Interesting R Posts
In this part, I will review and summarize 3 R posts.
1. Improving a Visualization
This is a summary of Improving a Visualization by Jonathan Carroll
Visualization is a crucial way to make sense of the trillions of rows of data generated every day. Data visualization helps to tell stories by curating data into a form easier to understand, highlighting the trends and outliers. As data scientists and analysts, we will often in our career face an issue that requires visualization, therefore, it is important to learn alternative ways to visualize. Exactly in this blog, the blogger demonstrates alternative visualization techniques for streaming services market share, comparing 2020 to 2021.
He found that the original visualization is built on PowerPoint but he was going to reproduce it in R. First he gathered the data then built a simple barplot using ggplot2. He continued to edit the barplot by changing the font, colors and adding the logos.
After achieving the original visualization with better colors and font, he proceeds to illustrate the same data on the pie chart. And then on the horizontal bar graph. Even though the prior visualizations does the job to show the current and previous market shares, in order to get a better idea about the one-year changes, loss and growth, he centered the 2020 percentages and demonstrated the differences with 2021. The blogger continues to explain the data on the dumbbell plot, aiming to show the separation between the two values. Even animates the changes between the two years. But the one that is interesting to me was the alluvial plot. Because it easily illustrated the transitions between service providers.
This blog helps us to understand how easy it is to code and to demonstrate the alternative ways of visualization in R.
2. 5 Ways to Subset a Data Frame in R
This is a review of 5 Ways to Subset a Data Frame in R by Douglas E. Rice
Subsetting a data frame is the process of selecting a set of rows and columns from the data frame. Subsetting is very useful because we often want to perform operations on subsets of our data, especially if it is big data. Also one of the important purposes of subsetting is to save bandwidth on the network and storage space on the computer.
1. The blogger at first explaining the most basic way of subsetting a data frame in R. This method is done by using square brackets.
Then, he continues with a hypothetical scenario. And retrieving the required data from the data frame by subsetting. With that subsetted data, he creates a new data frame.
2. In the second method, he mentions that in order to get the required data in the same data frame we can easily omit the unnecessary data. It is quite similar to the first method but instead, he uses “-” sign before vector function.
subtracting_data_frame <- education[-c(1:9,22:50),-c(1,3:5)]
3. Often we work on a large data set that it is not possible to count row and column numbers. In that case the blogger suggests to use the code below :
new_data_frame <- education[which(education$Region == 2),names(education) %in% c("State","Minor.Population","Education.Expenditures")]
In this method, by using the which() function we are able to get the returns the indices where the Region column of the education data from is 2. By using the %in% operator he retrieved the columns of the subset on the names of the education data frame.
4. In the next method, he explains an easier way by using subset() built-in function in R.
easier_data_frame <- subset(education, Region == 2, select = c("State","Minor.Population","Education.Expenditures"))
5. He states that the last method is the most useful in manipulating data once you get a grasp of it. This method is not initially included basic R, therefore, we need to download the dplyr package.
install.packages("dplyr")
library(dplyr)
dplyr_data_frame <- select(filter(education, Region == 2),c(State,Minor.Population:Education.Expenditures))
Once we’ve downloaded dplyr, we use filter and select functions in the package. Even though this method requires an external package we can see that, it is the easier and faster way to achieve the required output.
This blog helps us to understand multiple ways of subsetting in R in different situations.
3. How to Remove Outliers in R
This is a summary of How to Remove Outliers in R by Syed A. Hadi
An outlier is a data point that differs from other data points in a data set. Even though it sounds easy, determining what is or isn’t an outlier is pretty subjective, depending on the study. In this blog, the blogger goes into details about identifying, visualizing and removing outliers from a dataset. Removing an outlier is crucial for data analysis since it can dramatically affect the model, the plot or the data output.
1. Looking at Outliers in R
Statisticians use and prefer different ways to locate the outliers in a dataset. The most common methods include the Z-score method and the Interquartile Range (IQR) method. In this blog, the blogger uses the IQR method. In this method, outliers are considered points that are below [Q1 - (1.5)IQR] or above [Q3 + (1.5)IQR].
He is starting with loading warpbreaks
built-in dataset on R using the data function.
data("warpbreaks")
2. Visualizing Outliers in R
Secondly, he is creating the boxplot to identify the outliers.
boxplot(warpbreaks)$out
[1] 70 67
3. Finding Outliers – Statistical Methods
Generally, the visualization method is considered easy but it can become a real burden for the system, therefore, we will use statistical methods a lot in big data analytics. He is using the quantile() function to find the 25th and the 75th percentile of the dataset, and the IQR() function which gives him the difference of the 75th and 25th percentiles. Then, the cut-off ranges beyond which all data points are outliers.
Q <- quantile(warpbreaks$breaks, probs=c(.25, .75), na.rm = FALSE)
iqr <- IQR(warpbreaks$breaks)
up <- Q[2]+1.5*iqr # Upper Range
low<- Q[1]-1.5*iqr # Lower Range
3. Eliminating Outliers in R
Using the subset() function, he is extracting the data points that is not outliers. Then visualizing it on boxplot.
eliminated <- subset(warpbreaks, warpbreaks$breaks > (Q[1] - 1.5*iqr) & warpbreaks$breaks < (Q[2]+1.5*iqr))
R also has other ways of removing outliers, one of them done by using the boxplot() function to identify the outliers and the which() function to find and remove them from the dataset.
boxplot(warpbreaks$breaks, plot=FALSE)$out # identifying the outliers
outliers <- boxplot(warpbreaks$breaks, plot=FALSE)$out # saving the outliers in a vector
x <-warpbreaks
x <- x[-which(x$breaks %in% outliers),]
Even though, it requires a little bit more R knowledge, this is maybe the more efficient way to remove outliers in R.
This blog explains us why and how to remove outliers in R.
Thanks for reading…
LS0tDQp0aXRsZTogIioqQkRBLTUwMyBXZWVrIDEgLSBSTWFya2Rvd24gVGFzayoqIg0KYXV0aG9yOiAiX0VtaXJoYW4gxZ5haGluXyINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgICBodG1sX25vdGVib29rOg0KICAgICAgICB0b2M6IHRydWUNCiAgICAgICAgdG9jX2RlcHRoOiAyDQogICAgICAgIHRvY19mbG9hdDogdHJ1ZQ0KLS0tDQo8YnI+DQo8c3R5bGU+DQojVE9DIHsNCiAgICBjb2xvcjogIzQwNDA0MDsNCiAgICBmb250LXNpemU6IDEzcHg7DQogICAgYm9yZGVyLWNvbG9yOiAjMDAwMDAwOw0KICAgIGZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLCBzeXN0ZW0tdWksIEJsaW5rTWFjU3lzdGVtRm9udCwgIlNlZ29lIFVJIiwgUm9ib3RvLCBVYnVudHU7DQp9DQpoMS50aXRsZSB7DQogICAgY29sb3I6ICM0MDQwNDA7DQogICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCBSb2JvdG8sIFVidW50dTsNCn0NCmg0LmF1dGhvciB7DQogICAgY29sb3I6ICM0MDQwNDA7DQogICAgZm9udC1zaXplOiAxMnB4Ow0KICAgIGZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLCBzeXN0ZW0tdWksIEJsaW5rTWFjU3lzdGVtRm9udCwgIlNlZ29lIFVJIiwgUm9ib3RvLCBVYnVudHU7DQp9DQpoNC5kYXRlIHsNCiAgICBjb2xvcjogIzQwNDA0MDsNCiAgICBmb250LXNpemU6IDEycHg7DQogICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCBSb2JvdG8sIFVidW50dTsNCn0NCmJvZHkgew0KICAgIGNvbG9yOiAjNjk2OTY5Ow0KICAgIGZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLCBzeXN0ZW0tdWksIEJsaW5rTWFjU3lzdGVtRm9udCwgIlNlZ29lIFVJIiwgUm9ib3RvLCBVYnVudHU7DQogICAgYmFja2dyb3VuZC1jb2xvcjogI0Y1RjVGNTsNCiAgICBmb250LXNpemU6IDEzcHg7DQo8L3N0eWxlPg0KDQojICoqUGVyc29uYWwgSW5mb3JtYXRpb24qKg0KPGJyPg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7TXkgbmFtZSBpcyAqKkVtaXJoYW4gxZ5haGluKiouIEkgd2FzIGJvcm4gaW4gW0J1cnNhXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9CdXJzYSksIGluIDE5OTggYW5kIGxpdmVkIHRoZXJlIGZvciB0aGUgZmlyc3QgMTggeWVhcnMgb2YgbXkgbGlmZS4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7SSBncmFkdWF0ZWQgZnJvbSBbVGhlIEZhY3VsdHkgb2YgRWNvbm9taWNzIGluIEVuZ2xpc2hdKGh0dHBzOi8vaW5naWt0aXNhdC1pa3Rpc2F0LmlzdGFuYnVsLmVkdS50ci9lbikgYXQgW0lzdGFuYnVsIFVuaXZlcnNpdHldKGh0dHBzOi8vd3d3LmlzdGFuYnVsLmVkdS50ci9lbi9fKSBpbiBBdWd1c3QgMjAyMC4gRHVyaW5nIG15IGJhY2hlbG9yJ3MgZGVncmVlLCBJIHBhcnRpY2lwYXRlZCBpbiB0aGUgRXJhc211cyBwcm9ncmFtbWUgdG8gcHJvbW90ZSBteXNlbGYgaW4gdGVybXMgb2Ygc29jaWFiaWxpdHkgYW5kIGEgYmV0dGVyIHZpc2lvbiBmb3IgdGhlIHdvcmxkLiBJIHdlbnQgdG8gW0JhcmNlbG9uYV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQmFyY2Vsb25hKSwgb25lIG9mIG15IGZhdm9yaXRlIGNvdW50cmllcywgdGhlIG1vc3QgYmVhdXRpZnVsIGNpdHkgaW4gU3BhaW4uIEkgYWxzbyBzdGFydGVkIHRvIHdvcmsgYXMgYSBjYXNoaWVyIGluIFtaYXJhLCBJbmRpdGV4XShodHRwczovL3d3dy5pbmRpdGV4LmNvbS8pLiBKdXN0IGluIDMgbW9udGhzLCBJIGdvdCBwcm9tb3RlZCB0byBhY2NvdW50YW50IHBvc2l0aW9uIHRoZW4gdG8gdGhlIGFkbWluaXN0cmF0aXZlIHNlcnZpY2VzIHJlc3BvbnNpYmxlIHBvc2l0aW9uLiBBZnRlciB3b3JraW5nIHRoZXJlIGZvciBhbG1vc3QgMyB5ZWFycywgSSBxdWl0IG15IGpvYiB0byBjb21wbGV0ZSBteSBkZWdyZWUuDQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO1Vwb24gY29tcGxldGluZyBteSBiYWNoZWxvcuKAmXMgZGVncmVlLCBJIG1vdmVkIHRvIFtJem1pcl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvxLB6bWlyKSBpbiB0aGUgc3VtbWVyIG9mIDIwMjAgZm9yIGEgam9iLiBJbiB3aGljaCBJIHdhcyBhYmxlIHRvIGltcHJvdmUgbXlzZWxmIGluIHNvIG1hbnkgd2F5cy4gSSBhbHNvIGhhZCBhIGNoYW5jZSB0byBlYXJuIG1vbmV5IHdoaWxlIGRvaW5nIHNvbWV0aGluZyBJIGxvdmUsIHVzaW5nIGNvbXB1dGVycyBhbmQgb3RoZXIgdGVjaG5vbG9naWVzLiBUaGVyZWZvcmUsIEkgbGVhcm5lZCBhcHBsaWNhdGlvbnMgbGlrZSBbTWljcm9zb2Z0IE9mZmljZV0oaHR0cHM6Ly93d3cub2ZmaWNlLmNvbS8pLCBbTWljcm9zb2Z0IFBvd2VyUG9pbnRdKGh0dHBzOi8vd3d3Lm1pY3Jvc29mdC5jb20vZW4tdXMvbWljcm9zb2Z0LTM2NS9wb3dlcnBvaW50KSwgdmFyaW91cyBhY2NvdW50aW5nIGFuZCBtYW5hZ2VtZW50IHByb2dyYW1zLiBUaGF0IGlzIGFsc28gdGhlIHdheSB0aGF0IEkgbWV0ICoqZGF0YSBzY2llbmNlIGFuZCBtYWNoaW5lIGxlYXJuaW5nKiouIFNvIEkgc3RhcnRlZCB0byBsZWFybiBhYm91dCBwcm9ncmFtbWluZyBhbmQgZGF0YSBzY2llbmNlIG9uIG15IG93biwgYnV0IEkgaGF2ZSBkZWNpZGVkIHRoYXQgSSBuZWVkIHRvIHN0dWR5IHByb2Zlc3Npb25hbGx5LCB0aGVyZWZvcmUsIGFuZCBnZXQgYSBwb3N0Z3JhZHVhdGUgcHJvZ3JhbSBpbiBvcmRlciB0byBiZSByZWFkeSBmb3IgdGhlIGluZHVzdHJ5LiBGb3IgdGhpcyBwdXJwb3NlLCBJIGJlZ2FuIG15IG1hc3RlcidzIGRlZ3JlZSBpbiBbQmlnIERhdGEgQW5hbHl0aWNzXShodHRwczovL2JkYS5tZWYuZWR1LnRyL2VuI2dzYy50YWI9MCkgYXQgW01FRiBVbml2ZXJzaXR5XShodHRwczovL3d3dy5tZWYuZWR1LnRyL2VuI2dzYy50YWI9MCkgaW4gU2VwdGVtYmVyIDIwMjEuDQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO0kgYW0gZm9jdXNpbmcgb24gcHJvZmVzc2lvbmFsaXppbmcgdGhlIHRoZW9yZXRpY2FsIGtub3dsZWRnZSBJIHJlY2VpdmVkIGR1cmluZyBteSBhY2FkZW1pYyBjYXJlZXIuIEkgaG9wZSB0byBwcm92ZSBhbGwgdGhlIGtub3dsZWRnZSBJIGhhdmUgYXQgYSBjb21wYW55IHRoYXQgdXRpbGl6ZXMgbWFjaGluZSBsZWFybmluZyBhbmQgYmlnIGRhdGEuIEkgd291bGQgbG92ZSB0byB3b3JrIG9uIHJlYWwtbGlmZSBhcnRpZmljaWFsIGludGVsbGlnZW5jZSBhbmQgbWFjaGluZSBsZWFybmluZyBwcm9qZWN0cy4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Rm9yIGZ1cnRoZXIgaW5mb3JtYXRpb24sIHlvdSBjYW4gdGFrZSBhIGxvb2sgYXQgbXkgW0xpbmtlZEluXShodHRwczovL3d3dy5saW5rZWRpbi5jb20vaW4vZW1pcmhhbi1zYWhpbi8pIHBhZ2Ugb3IgYXNrIG1lIG9uIFtUd2l0dGVyXShodHRwczovL3R3aXR0ZXIuY29tL2xpb3BoaXJlKS4NCjxicj4NCjxicj4NCg0KIyAqKlRyZWUtQmFzZWQgTWFjaGluZSBMZWFybmluZyBmb3IgSW5zdXJhbmNlIFByaWNpbmcqKg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7X1RoaXMgcGFydCBpbmNsdWRlcyBhIHJldmlldyBhbmQgc3VtbWFyeSBvZiBhIFtSIENvbnNvcnRpdW0gdmlkZW8uXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PXoxQWxOR1hHejlBKV8NCjxicj4NCjxicj4NCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO0kgaGF2ZSBjaG9zZW4gdGhpcyB2aWRlbyB0byByZXZpZXcgYmVjYXVzZSB0aGUgdG9waWMgaXMgY2xvc2VseSByZWxhdGVkIHRvIHRoZSByZWFsIHdvcmxkIGFuZCB0aGUgbWFpbiBmb2N1cyBpcyBvbiBbYmlnIGRhdGFdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0JpZ19kYXRhKSBhbmQgW21hY2hpbmUgbGVhcm5pbmddKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01hY2hpbmVfbGVhcm5pbmcpLg0KPGJyPg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtUaGUgcHJlc2VudGVyIGZpcnN0IHN0YXJ0aW5nIHRvIHRhbGsgYWJvdXQgdGhlIG1ldGhvZHMgYW5kIGZvcm11bGFzIHRoZXkgdXNlIHRvIGFzc2VzcyB0aGUgW3ByaWNlIG9mIGEgcHJlbWl1bV0oaHR0cHM6Ly93d3cuaW52ZXN0b3BlZGlhLmNvbS90ZXJtcy9pL2luc3VyYW5jZS1wcmVtaXVtLmFzcCkuIFRoZW4gaGUgZXhwbGFpbnMgdGhlIGdvYWwgb2YgdGhlIHByZXNlbnRhdGlvbi4gSGUgc3RhdGVzIHRoYXQgdGhlIFtHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWxdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlbmVyYWxpemVkX2xpbmVhcl9tb2RlbCkgYnkgW0ouTmVsZGVyXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Kb2huX05lbGRlcikgYW5kIFtSLldlZGRlcmJ1cm5dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JvYmVydF9XZWRkZXJidXJuXyhzdGF0aXN0aWNpYW4pKSBpcyBhIHdpZGVseSB1c2VkIG1vZGVsIGluIGNsYXNzaWNhbCBwcmVtaXVtIGNhbGN1bGF0aW9ucy4gSGUgbGF0ZXIgY29udGludWVzIHRvIGV4cGxhaW4gdGhlIG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyBhbmQgcGFyYW1ldGVycyB0aGF0IGFyZSB1c2VkLiBIZSB0d2Vha3MgdGhlIHdheSBmcmVxdWVuY3kgYW5kIHNldmVyaXR5IGFyZSBjYWxjdWxhdGVkIGluIHRoZSBbR2VuZXJhbGl6ZWQgTGluZWFyIE1vZGVsXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HZW5lcmFsaXplZF9saW5lYXJfbW9kZWwpIGJ5IHJlcGxhY2luZyBbY291bnQgZGlzdHJpYnV0aW9uXShodHRwczovL29ubGluZWxpYnJhcnkud2lsZXkuY29tL2RvaS9wZGYvMTAuMTAwMi85NzgxMTE5MDk3MDEzLmFwcDEpIGluIGZyZXF1ZW5jeSB3aXRoIFtQb2lzc29uIGRldmlhbmNlXShodHRwczovL3BlaWppbi5tZWRpdW0uY29tL3RoZS1wb2lzc29uLWRldmlhbmNlLWZvci1yZWdyZXNzaW9uLWQ0NjliNTY5NTljZSkgYW5kIFtza2V3ZWQgZnVuY3Rpb25dKGh0dHBzOi8vd3d3LnN0YXRpc3RpY3Nob3d0by5jb20vcHJvYmFiaWxpdHktYW5kLXN0YXRpc3RpY3Mvc2tld2VkLWRpc3RyaWJ1dGlvbi8pIGluIHNldmVyaXR5IHdpdGggW0dhbW1hIGRldmlhbmNlXShodHRwczovL3NjaWtpdC1sZWFybi5vcmcvc3RhYmxlL21vZHVsZXMvZ2VuZXJhdGVkL3NrbGVhcm4ubWV0cmljcy5tZWFuX2dhbW1hX2RldmlhbmNlLmh0bWwjOn46dGV4dD1HYW1tYSUyMGRldmlhbmNlJTIwaXMlMjBlcXVpdmFsZW50JTIwdG8sdmFyaWFibGUlMkMlMjBhbmQlMjBtZWFzdXJlcyUyMHJlbGF0aXZlJTIwZXJyb3JzLiZ0ZXh0PUdyb3VuZCUyMHRydXRoJTIwKGNvcnJlY3QpJTIwdGFyZ2V0JTIwdmFsdWVzLFJlcXVpcmVzJTIweV90cnVlJTIwPiUyMDAuKSBhcyBsb3NzIGZ1bmN0aW9uLg0KPGJyPg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtJbiB0aGUgc2Vjb25kIGhhbGYgb2YgdGhlIHZpZGVvLCB0aGUgcHJlc2VudGVyIGlsbHVzdHJhdGVzIHRoZSByZXN1bHRzIG9mIHRoZSBuZXcgTUwgdGVjaG5pcXVlcyBhbmQgY29tcGFyZXMgdGhlbSB3aXRoIHRoZSBjbGFzc2ljYWwgbWV0aG9kcy4gSGUgc3RhdGVzIGV2ZW4gdGhvdWdoIGJvdGggb2YgdGhlIGNsYXNzaWNhbCBtZXRob2RzIGFyZSBiZXR0ZXIgdGhhbiAyIG9mIHRoZSBuZXcgTUwgdGVjaG5pcXVlLCBbR3JhZGllbnQgQm9vc3RpbmcgTWFjaGluZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR3JhZGllbnRfYm9vc3RpbmcpIHJldHVybnMgdGhlIG1vc3QgcHJlY2lzZSByZXN1bHRzIG91dCBvZiBhbGwgNSB0ZXN0cy4gTGF0ZXIgaGUgY29udGludWVzIHRvIGRlbW9uc3RyYXRlIHRoZSByZXN1bHRzIGFuZCBncmFwaHMgb2YgdGhlIHRlc3RzIGFuZCB0byBleHBsYWluIGhvdyBwcm9maXRhYmxlIGl0IGNhbiBiZSBvbmNlIHRoZSBjb21wYW55IGltcGxlbWVudHMgR0JNIHRlY2huaXF1ZS4NCjxicj4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7SW4gdGhlIGVuZCwgaGUgY29uY2x1ZGVzIGJ5IHN1bW1hcml6aW5nIHRoZSBwcm9zIGFuZCBjb25zIG9mIHVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgdGVjaG5pcXVlcy4NCjxicj4NCjxicj4NCg0KIyAqKkludGVyZXN0aW5nIFIgUG9zdHMqKg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7X0luIHRoaXMgcGFydCwgSSB3aWxsIHJldmlldyBhbmQgc3VtbWFyaXplIDMgUiBwb3N0cy5fDQo8YnI+DQoNCiMjICZuYnNwOyZuYnNwOyZuYnNwOyAqKjEuIEltcHJvdmluZyBhIFZpc3VhbGl6YXRpb24qKg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7X1RoaXMgaXMgYSBzdW1tYXJ5IG9mIFtJbXByb3ZpbmcgYSBWaXN1YWxpemF0aW9uXShodHRwczovL2pjYXJyb2xsLmNvbS5hdS8yMDIxLzA3LzAyL2ltcHJvdmluZy1hLXZpc3VhbGl6YXRpb24vKSBieSBbSm9uYXRoYW4gQ2Fycm9sbF0oaHR0cHM6Ly9naXRodWIuY29tL2pvbm9jYXJyb2xsKV8NCjxicj4NCjxicj4NCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyBWaXN1YWxpemF0aW9uIGlzIGEgY3J1Y2lhbCB3YXkgdG8gbWFrZSBzZW5zZSBvZiB0aGUgdHJpbGxpb25zIG9mIHJvd3Mgb2YgZGF0YSBnZW5lcmF0ZWQgZXZlcnkgZGF5LiBEYXRhIHZpc3VhbGl6YXRpb24gaGVscHMgdG8gdGVsbCBzdG9yaWVzIGJ5IGN1cmF0aW5nIGRhdGEgaW50byBhIGZvcm0gZWFzaWVyIHRvIHVuZGVyc3RhbmQsIGhpZ2hsaWdodGluZyB0aGUgdHJlbmRzIGFuZCBvdXRsaWVycy4gQXMgZGF0YSBzY2llbnRpc3RzIGFuZCBhbmFseXN0cywgd2UgIHdpbGwgb2Z0ZW4gaW4gb3VyIGNhcmVlciBmYWNlIGFuIGlzc3VlIHRoYXQgcmVxdWlyZXMgdmlzdWFsaXphdGlvbiwgdGhlcmVmb3JlLCBpdCBpcyBpbXBvcnRhbnQgdG8gbGVhcm4gYWx0ZXJuYXRpdmUgd2F5cyB0byB2aXN1YWxpemUuIEV4YWN0bHkgIGluIHRoaXMgYmxvZywgdGhlIGJsb2dnZXIgZGVtb25zdHJhdGVzIGFsdGVybmF0aXZlIHZpc3VhbGl6YXRpb24gdGVjaG5pcXVlcyBmb3IgW3N0cmVhbWluZyBzZXJ2aWNlcyBtYXJrZXQgc2hhcmUsIGNvbXBhcmluZyAyMDIwIHRvIDIwMjFdKGh0dHBzOi8vd3d3LnJlZGRpdC5jb20vci9kYXRhaXNiZWF1dGlmdWwvY29tbWVudHMvbXRsZDVmL29jX3VzX3N0cmVhbWluZ19zZXJ2aWNlc19tYXJrZXRfc2hhcmVfMjAyMF92c18yMDIxLykuDQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyBIZSBmb3VuZCB0aGF0IHRoZSBbb3JpZ2luYWwgdmlzdWFsaXphdGlvbl0oaHR0cHM6Ly93d3cucmVkZGl0LmNvbS9yL2RhdGFpc2JlYXV0aWZ1bC9jb21tZW50cy9tdGxkNWYvb2NfdXNfc3RyZWFtaW5nX3NlcnZpY2VzX21hcmtldF9zaGFyZV8yMDIwX3ZzXzIwMjEvZ3YwYnY0ai8/dXRtX3NvdXJjZT1zaGFyZSZ1dG1fbWVkaXVtPXdlYjJ4JmNvbnRleHQ9MykgaXMgYnVpbHQgb24gUG93ZXJQb2ludCBidXQgaGUgd2FzIGdvaW5nIHRvIHJlcHJvZHVjZSBpdCBpbiBSLiBGaXJzdCBoZSBnYXRoZXJlZCB0aGUgW2RhdGFdKGh0dHBzOi8vd3d3LnRoZXdyYXAuY29tL25ldGZsaXgtc3RyZWFtaW5nLXVzLW1hcmtldC1zaGFyZS1jaGFydC8pIHRoZW4gYnVpbHQgYSBzaW1wbGUgYmFycGxvdCB1c2luZyBfW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLylfLiBIZSBjb250aW51ZWQgdG8gZWRpdCB0aGUgYmFycGxvdCBieSBjaGFuZ2luZyB0aGUgZm9udCwgY29sb3JzIGFuZCBhZGRpbmcgdGhlIGxvZ29zLg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgQWZ0ZXIgYWNoaWV2aW5nIHRoZSBvcmlnaW5hbCB2aXN1YWxpemF0aW9uIHdpdGggYmV0dGVyIGNvbG9ycyBhbmQgZm9udCwgaGUgcHJvY2VlZHMgdG8gaWxsdXN0cmF0ZSB0aGUgc2FtZSBkYXRhIG9uIHRoZSBbcGllIGNoYXJ0XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QaWVfY2hhcnQpLiBBbmQgdGhlbiBvbiB0aGUgW2hvcml6b250YWwgYmFyIGdyYXBoXShodHRwczovL3d3dy5zcGxhc2hsZWFybi5jb20vbWF0aC12b2NhYnVsYXJ5L2dlb21ldHJ5L2hvcml6b250YWwtYmFyLWdyYXBoKS4gRXZlbiB0aG91Z2ggdGhlIHByaW9yIHZpc3VhbGl6YXRpb25zIGRvZXMgdGhlIGpvYiB0byBzaG93IHRoZSBjdXJyZW50IGFuZCBwcmV2aW91cyBtYXJrZXQgc2hhcmVzLCBpbiBvcmRlciB0byBnZXQgYSBiZXR0ZXIgaWRlYSBhYm91dCB0aGUgb25lLXllYXIgY2hhbmdlcywgbG9zcyBhbmQgZ3Jvd3RoLCBoZSBjZW50ZXJlZCB0aGUgMjAyMCBwZXJjZW50YWdlcyBhbmQgZGVtb25zdHJhdGVkIHRoZSBkaWZmZXJlbmNlcyB3aXRoIDIwMjEuIFRoZSBibG9nZ2VyIGNvbnRpbnVlcyB0byBleHBsYWluIHRoZSBkYXRhIG9uIHRoZSBbZHVtYmJlbGwgcGxvdF0oaHR0cHM6Ly93d3cuYnVzaW5lc3Mtc2NpZW5jZS5pby9yLzIwMjEvMDgvMTIvZ2dhbHQtZHVtYmJlbGwtcGxvdHMtZ2dwbG90Mi5odG1sIzp+OnRleHQ9V2hhdCUyMGlzJTIwYSUyMER1bWJiZWxsJTIwUGxvdCwodGhpbmslMjBzdGFydCUyMGFuZCUyMGZpbmlzaCkuKSwgYWltaW5nIHRvIHNob3cgdGhlIHNlcGFyYXRpb24gYmV0d2VlbiB0aGUgdHdvIHZhbHVlcy4gRXZlbiBhbmltYXRlcyB0aGUgY2hhbmdlcyBiZXR3ZWVuIHRoZSB0d28geWVhcnMuIEJ1dCB0aGUgb25lIHRoYXQgaXMgaW50ZXJlc3RpbmcgdG8gbWUgd2FzIHRoZSBbYWxsdXZpYWwgcGxvdF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQWxsdXZpYWxfZGlhZ3JhbSkuIEJlY2F1c2UgaXQgZWFzaWx5IGlsbHVzdHJhdGVkIHRoZSB0cmFuc2l0aW9ucyBiZXR3ZWVuIHNlcnZpY2UgcHJvdmlkZXJzLg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgVGhpcyBibG9nIGhlbHBzIHVzIHRvIHVuZGVyc3RhbmQgKipob3cgZWFzeSBpdCBpcyB0byBjb2RlIGFuZCB0byBkZW1vbnN0cmF0ZSB0aGUgYWx0ZXJuYXRpdmUgd2F5cyBvZiB2aXN1YWxpemF0aW9uIGluIFIqKi4NCjxicj4NCjxicj4NCg0KIyMgJm5ic3A7Jm5ic3A7Jm5ic3A7ICoqMi4gNSBXYXlzIHRvIFN1YnNldCBhIERhdGEgRnJhbWUgaW4gUioqDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtfVGhpcyBpcyBhIHJldmlldyBvZiBbNSBXYXlzIHRvIFN1YnNldCBhIERhdGEgRnJhbWUgaW4gUl0oaHR0cHM6Ly9ydmVyeWRheS53b3JkcHJlc3MuY29tLzIwMTYvMTEvMjkvNS13YXlzLXRvLXN1YnNldC1hLWRhdGEtZnJhbWUtaW4tci8pIGJ5IFtEb3VnbGFzIEUuIFJpY2VdKGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL2F1dGhvci9kb3VnbGFzLWUtcmljZS8pXw0KPGJyPg0KPGJyPg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IFtTdWJzZXR0aW5nIGEgZGF0YSBmcmFtZV0oaHR0cHM6Ly93d3cuc3RhdG1ldGhvZHMubmV0L21hbmFnZW1lbnQvc3Vic2V0Lmh0bWwpIGlzIHRoZSBwcm9jZXNzIG9mIHNlbGVjdGluZyBbYSBzZXQgb2Ygcm93cyBhbmQgY29sdW1ucyBmcm9tIHRoZSBkYXRhIGZyYW1lXShodHRwczovL2NzaGFycGNvcm5lci1taW5kY3JhY2tlcmluYy5uZXRkbmEtc3NsLmNvbS9hcnRpY2xlL3ItZGF0YS1mcmFtZS1vcGVyYXRpb25zLWFkZGluZy1yb3dzLXJlbW92aW5nLXJvd3MtYW5kLW1lcmdpbmctdHdvLWRhdGEtZnJhbWUvSW1hZ2VzL1VwZGF0ZWRJbWFnZS9BZGRlZCUyMEJ5JTIwYWRkX3Jvdy5KUEcpLiBTdWJzZXR0aW5nIGlzIHZlcnkgdXNlZnVsIGJlY2F1c2Ugd2Ugb2Z0ZW4gd2FudCB0byBwZXJmb3JtIG9wZXJhdGlvbnMgb24gc3Vic2V0cyBvZiBvdXIgZGF0YSwgZXNwZWNpYWxseSBpZiBpdCBpcyBbYmlnIGRhdGFdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0JpZ19kYXRhIzp+OnRleHQ9QmlnJTIwZGF0YSUyMGlzJTIwYSUyMGZpZWxkLHRyYWRpdGlvbmFsJTIwZGF0YS1wcm9jZXNzaW5nJTIwYXBwbGljYXRpb24lMjBzb2Z0d2FyZS4mdGV4dD1CaWclMjBkYXRhJTIwd2FzJTIwb3JpZ2luYWxseSUyMGFzc29jaWF0ZWQsdm9sdW1lJTJDJTIwdmFyaWV0eSUyQyUyMGFuZCUyMHZlbG9jaXR5LikuIEFsc28gb25lIG9mIHRoZSBpbXBvcnRhbnQgcHVycG9zZXMgb2Ygc3Vic2V0dGluZyBpcyB0byBzYXZlIFtiYW5kd2lkdGhdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0JhbmR3aWR0aF8oY29tcHV0aW5nKSkgb24gdGhlIG5ldHdvcmsgYW5kIFtzdG9yYWdlIHNwYWNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db21wdXRlcl9kYXRhX3N0b3JhZ2UpIG9uIHRoZSBjb21wdXRlci4NCg0KPGJyPg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ICoqMS4qKiAgVGhlIGJsb2dnZXIgYXQgZmlyc3QgZXhwbGFpbmluZyAqKnRoZSBtb3N0IGJhc2ljIHdheSBvZiBzdWJzZXR0aW5nIGEgZGF0YSBmcmFtZSBpbiBSKiouIFRoaXMgbWV0aG9kIGlzIGRvbmUgYnkgdXNpbmcgKipzcXVhcmUgYnJhY2tldHMqKi4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ICZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAhW1N1YnNldF0oaHR0cHM6Ly9jZG4uZ3VydTk5LmNvbS9pbWFnZXMvcl9wcm9ncmFtbWluZy8wMzI5MThfMTQ1Ml9SRGF0YUZyYW1lczEucG5nKVwNCg0KPGJyPg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IFRoZW4sIGhlIGNvbnRpbnVlcyB3aXRoIGEgaHlwb3RoZXRpY2FsIHNjZW5hcmlvLiBBbmQgcmV0cmlldmluZyB0aGUgcmVxdWlyZWQgZGF0YSBmcm9tIHRoZSBkYXRhIGZyYW1lIGJ5IHN1YnNldHRpbmcuIFdpdGggdGhhdCBzdWJzZXR0ZWQgZGF0YSwgaGUgY3JlYXRlcyBhIG5ldyBkYXRhIGZyYW1lLg0KDQo8YnI+DQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgKioyLioqICBJbiB0aGUgc2Vjb25kIG1ldGhvZCwgaGUgbWVudGlvbnMgdGhhdCBpbiBvcmRlciB0byBnZXQgdGhlIHJlcXVpcmVkIGRhdGEgaW4gdGhlIHNhbWUgZGF0YSBmcmFtZSB3ZSBjYW4gZWFzaWx5IG9taXQgdGhlIHVubmVjZXNzYXJ5IGRhdGEuIEl0IGlzIHF1aXRlIHNpbWlsYXIgdG8gdGhlIGZpcnN0IG1ldGhvZCBidXQgaW5zdGVhZCwgaGUgdXNlcyAqKiItIioqIHNpZ24gYmVmb3JlIFt2ZWN0b3JdKGh0dHBzOi8vd3d3LnR1dG9yaWFsc3BvaW50LmNvbS9yL3JfdmVjdG9ycy5odG0pIGZ1bmN0aW9uLg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NCnN1YnRyYWN0aW5nX2RhdGFfZnJhbWUgPC0gZWR1Y2F0aW9uWy1jKDE6OSwyMjo1MCksLWMoMSwzOjUpXQ0KYGBgDQoNCjxicj4NCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAqKjMuKiogIE9mdGVuIHdlIHdvcmsgb24gYSBsYXJnZSBkYXRhIHNldCB0aGF0IGl0IGlzIG5vdCBwb3NzaWJsZSB0byBjb3VudCByb3cgYW5kIGNvbHVtbiBudW1iZXJzLiBJbiB0aGF0IGNhc2UgdGhlIGJsb2dnZXIgc3VnZ2VzdHMgdG8gdXNlIHRoZSBjb2RlIGJlbG93IDoNCmBgYHtyLCBldmFsID0gRkFMU0V9DQpuZXdfZGF0YV9mcmFtZSA8LSBlZHVjYXRpb25bd2hpY2goZWR1Y2F0aW9uJFJlZ2lvbiA9PSAyKSxuYW1lcyhlZHVjYXRpb24pICVpbiUgYygiU3RhdGUiLCJNaW5vci5Qb3B1bGF0aW9uIiwiRWR1Y2F0aW9uLkV4cGVuZGl0dXJlcyIpXQ0KYGBgDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgSW4gdGhpcyBtZXRob2QsIGJ5IHVzaW5nIHRoZSBbd2hpY2goKV0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL2Jhc2UvdmVyc2lvbnMvMy42LjIvdG9waWNzL3doaWNoKSBmdW5jdGlvbiB3ZSBhcmUgYWJsZSB0byBnZXQgdGhlIHJldHVybnMgdGhlIGluZGljZXMgd2hlcmUgdGhlIFJlZ2lvbiBjb2x1bW4gb2YgdGhlIGVkdWNhdGlvbiBkYXRhIGZyb20gaXMgMi4gQnkgdXNpbmcgdGhlIFslaW4lXShodHRwczovL3d3dy5kYXRhc2NpZW5jZW1hZGVzaW1wbGUuY29tL2luLW9wZXJhdG9yLWluLXIvKSBvcGVyYXRvciBoZSByZXRyaWV2ZWQgdGhlIGNvbHVtbnMgb2YgdGhlIHN1YnNldCBvbiB0aGUgbmFtZXMgb2YgdGhlIGVkdWNhdGlvbiBkYXRhIGZyYW1lLg0KDQo8YnI+DQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgKio0LioqICBJbiB0aGUgbmV4dCBtZXRob2QsIGhlIGV4cGxhaW5zIGFuIGVhc2llciB3YXkgYnkgdXNpbmcgW3N1YnNldCgpXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvYmFzZS92ZXJzaW9ucy8zLjYuMi90b3BpY3Mvc3Vic2V0KSBidWlsdC1pbiBmdW5jdGlvbiBpbiBSLg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NCmVhc2llcl9kYXRhX2ZyYW1lIDwtIHN1YnNldChlZHVjYXRpb24sIFJlZ2lvbiA9PSAyLCBzZWxlY3QgPSBjKCJTdGF0ZSIsIk1pbm9yLlBvcHVsYXRpb24iLCJFZHVjYXRpb24uRXhwZW5kaXR1cmVzIikpDQpgYGANCg0KPGJyPg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ICoqNS4qKiAgSGUgc3RhdGVzIHRoYXQgdGhlIGxhc3QgbWV0aG9kIGlzICoqdGhlIG1vc3QgdXNlZnVsIGluIG1hbmlwdWxhdGluZyBkYXRhKiogb25jZSB5b3UgZ2V0IGEgZ3Jhc3Agb2YgaXQuIFRoaXMgbWV0aG9kIGlzIG5vdCBpbml0aWFsbHkgaW5jbHVkZWQgYmFzaWMgUiwgdGhlcmVmb3JlLCB3ZSBuZWVkIHRvIGRvd25sb2FkIHRoZSBfW2RwbHlyXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvKV8gcGFja2FnZS4NCmBgYHtyLCBldmFsID0gRkFMU0V9DQppbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQpsaWJyYXJ5KGRwbHlyKQ0KZHBseXJfZGF0YV9mcmFtZSA8LSBzZWxlY3QoZmlsdGVyKGVkdWNhdGlvbiwgUmVnaW9uID09IDIpLGMoU3RhdGUsTWlub3IuUG9wdWxhdGlvbjpFZHVjYXRpb24uRXhwZW5kaXR1cmVzKSkNCmBgYA0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IE9uY2Ugd2XigJl2ZSBkb3dubG9hZGVkIGRwbHlyLCB3ZSB1c2UgW2ZpbHRlcl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9maWx0ZXIuaHRtbCkgYW5kIFtzZWxlY3RdKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZmlsdGVyLmh0bWwpIGZ1bmN0aW9ucyBpbiB0aGUgcGFja2FnZS4gRXZlbiB0aG91Z2ggdGhpcyBtZXRob2QgcmVxdWlyZXMgYW4gZXh0ZXJuYWwgcGFja2FnZSB3ZSBjYW4gc2VlIHRoYXQsIGl0IGlzIHRoZSBlYXNpZXIgYW5kIGZhc3RlciB3YXkgdG8gYWNoaWV2ZSB0aGUgcmVxdWlyZWQgb3V0cHV0Lg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgVGhpcyBibG9nIGhlbHBzIHVzIHRvIHVuZGVyc3RhbmQgKiptdWx0aXBsZSB3YXlzIG9mIHN1YnNldHRpbmcgaW4gUiBpbiBkaWZmZXJlbnQgc2l0dWF0aW9ucyoqLg0KPGJyPg0KPGJyPg0KDQojIyAmbmJzcDsmbmJzcDsmbmJzcDsgKiozLiBIb3cgdG8gUmVtb3ZlIE91dGxpZXJzIGluIFIqKg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7X1RoaXMgaXMgYSBzdW1tYXJ5IG9mIFtIb3cgdG8gUmVtb3ZlIE91dGxpZXJzIGluIFJdKGh0dHBzOi8vd3d3LnByb2dyYW1taW5nci5jb20vY29udGVudC9yZW1vdmUtb3V0bGllcnMtaW4tci8/dXRtX3NvdXJjZT1mZWVkYnVybmVyJnV0bV9tZWRpdW09ZmVlZCZ1dG1fY2FtcGFpZ249RmVlZCUzQStQcm9ncmFtbWluZ1IrJTI4UHJvZ3JhbW1pbmcrUiUyOSkgYnkgW1N5ZWQgQS4gSGFkaV0oaHR0cHM6Ly93d3cucHJvZ3JhbW1pbmdyLmNvbS9jb250ZW50L2F1dGhvci9zeWVkLylfDQo8YnI+DQo8YnI+DQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgQW4gW291dGxpZXJdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL091dGxpZXIpIGlzIGEgZGF0YSBwb2ludCB0aGF0IGRpZmZlcnMgZnJvbSBvdGhlciBkYXRhIHBvaW50cyBpbiBhIGRhdGEgc2V0LiBFdmVuIHRob3VnaCBpdCBzb3VuZHMgZWFzeSwgZGV0ZXJtaW5pbmcgd2hhdCBpcyBvciBpc24ndCBhbiBvdXRsaWVyIGlzIHByZXR0eSBzdWJqZWN0aXZlLCBkZXBlbmRpbmcgb24gdGhlIHN0dWR5LiBJbiB0aGlzIGJsb2csIHRoZSBibG9nZ2VyIGdvZXMgaW50byBkZXRhaWxzIGFib3V0IGlkZW50aWZ5aW5nLCB2aXN1YWxpemluZyBhbmQgcmVtb3Zpbmcgb3V0bGllcnMgZnJvbSBhIGRhdGFzZXQuIFtSZW1vdmluZyBhbiBvdXRsaWVyXShodHRwczovL2h1bWFuc29mZGF0YS5hdGxhbi5jb20vMjAxOC8wMy93aGVuLWRlbGV0ZS1vdXRsaWVycy1kYXRhc2V0LykgaXMgY3J1Y2lhbCBmb3IgZGF0YSBhbmFseXNpcyBzaW5jZSBpdCBjYW4gZHJhbWF0aWNhbGx5IGFmZmVjdCB0aGUgbW9kZWwsIHRoZSBwbG90IG9yIHRoZSBkYXRhIG91dHB1dC4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ICoqMS4gIExvb2tpbmcgYXQgT3V0bGllcnMgaW4gUioqDQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyBTdGF0aXN0aWNpYW5zIHVzZSBhbmQgcHJlZmVyIGRpZmZlcmVudCB3YXlzIHRvIGxvY2F0ZSB0aGUgb3V0bGllcnMgaW4gYSBkYXRhc2V0LiBUaGUgbW9zdCBjb21tb24gbWV0aG9kcyBpbmNsdWRlIHRoZSBbWi1zY29yZV0oaHR0cHM6Ly93d3cuc3RhdGlzdGljc2hvd3RvLmNvbS9wcm9iYWJpbGl0eS1hbmQtc3RhdGlzdGljcy96LXNjb3JlLykgbWV0aG9kIGFuZCB0aGUgW0ludGVycXVhcnRpbGUgUmFuZ2UgKElRUildKGh0dHBzOi8vd3d3LnN0YXRpc3RpY3Nob3d0by5jb20vcHJvYmFiaWxpdHktYW5kLXN0YXRpc3RpY3MvaW50ZXJxdWFydGlsZS1yYW5nZS8pIG1ldGhvZC4gSW4gdGhpcyBibG9nLCB0aGUgYmxvZ2dlciB1c2VzIHRoZSBJUVIgbWV0aG9kLiBJbiB0aGlzIG1ldGhvZCwgb3V0bGllcnMgYXJlIGNvbnNpZGVyZWQgcG9pbnRzIHRoYXQgYXJlICoqYmVsb3cgW1ExIC0gKDEuNSlJUVJdKiogb3IgKiphYm92ZSBbUTMgKyAoMS41KUlRUl0qKi4NCg0KIVtpbnRlcnF1YXJ0aWxlXShodHRwczovL3d3dy5zdGF0b2xvZ3kub3JnL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDIxLzAxL2lxck91dGxpZXIxLnBuZylcDQoNCjxicj4NCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyBIZSBpcyBzdGFydGluZyB3aXRoIGxvYWRpbmcgX19fYHdhcnBicmVha3NgX19fIGJ1aWx0LWluIGRhdGFzZXQgb24gUiB1c2luZyBbdGhlIGRhdGEgZnVuY3Rpb25dKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy91dGlscy92ZXJzaW9ucy8zLjYuMi90b3BpY3MvZGF0YSkuDQpgYGB7cn0NCmRhdGEoIndhcnBicmVha3MiKQ0KYGBgDQoNCjxicj4NCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAqKjIuIFZpc3VhbGl6aW5nIE91dGxpZXJzIGluIFIqKg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgU2Vjb25kbHksIGhlIGlzIGNyZWF0aW5nIHRoZSBbYm94cGxvdF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQm94X3Bsb3QpIHRvIGlkZW50aWZ5IHRoZSBvdXRsaWVycy4NCmBgYHtyfQ0KYm94cGxvdCh3YXJwYnJlYWtzKSRvdXQNCmBgYA0KDQo8YnI+DQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgKiozLiBGaW5kaW5nIE91dGxpZXJzIOKAkyBTdGF0aXN0aWNhbCBNZXRob2RzKioNCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IEdlbmVyYWxseSwgdGhlIHZpc3VhbGl6YXRpb24gbWV0aG9kIGlzIGNvbnNpZGVyZWQgZWFzeSBidXQgaXQgY2FuIGJlY29tZSBhIHJlYWwgYnVyZGVuIGZvciB0aGUgc3lzdGVtLCB0aGVyZWZvcmUsICB3ZSB3aWxsIHVzZSBzdGF0aXN0aWNhbCBtZXRob2RzIGEgbG90IGluIGJpZyBkYXRhIGFuYWx5dGljcy4gSGUgaXMgdXNpbmcgdGhlIFtxdWFudGlsZSgpXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvc3RhdHMvdmVyc2lvbnMvMy42LjIvdG9waWNzL3F1YW50aWxlKSBmdW5jdGlvbiB0byBmaW5kIHRoZSAyNXRoIGFuZCB0aGUgNzV0aCBwZXJjZW50aWxlIG9mIHRoZSBkYXRhc2V0LCBhbmQgdGhlIFtJUVIoKV0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3N0YXRzL3ZlcnNpb25zLzMuNi4yL3RvcGljcy9JUVIpIGZ1bmN0aW9uIHdoaWNoIGdpdmVzIGhpbSB0aGUgZGlmZmVyZW5jZSBvZiB0aGUgNzV0aCBhbmQgMjV0aCBwZXJjZW50aWxlcy4gVGhlbiwgdGhlIGN1dC1vZmYgcmFuZ2VzIGJleW9uZCB3aGljaCBhbGwgZGF0YSBwb2ludHMgYXJlIG91dGxpZXJzLg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NClEgPC0gcXVhbnRpbGUod2FycGJyZWFrcyRicmVha3MsIHByb2JzPWMoLjI1LCAuNzUpLCBuYS5ybSA9IEZBTFNFKQ0KaXFyIDwtIElRUih3YXJwYnJlYWtzJGJyZWFrcykNCnVwIDwtICBRWzJdKzEuNSppcXIgIyBVcHBlciBSYW5nZQ0KbG93PC0gUVsxXS0xLjUqaXFyICMgTG93ZXIgUmFuZ2UNCmBgYA0KDQo8YnI+DQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgKiozLiBFbGltaW5hdGluZyBPdXRsaWVycyBpbiBSKioNCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IFVzaW5nIHRoZSBbc3Vic2V0KCldKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9iYXNlL3ZlcnNpb25zLzMuNi4yL3RvcGljcy9zdWJzZXQpIGZ1bmN0aW9uLCBoZSBpcyBleHRyYWN0aW5nIHRoZSBkYXRhIHBvaW50cyB0aGF0IGlzICoqbm90IG91dGxpZXJzKiouIFRoZW4gdmlzdWFsaXppbmcgaXQgb24gYm94cGxvdC4NCmBgYHtyLCBldmFsID0gRkFMU0V9DQplbGltaW5hdGVkIDwtIHN1YnNldCh3YXJwYnJlYWtzLCB3YXJwYnJlYWtzJGJyZWFrcyA+IChRWzFdIC0gMS41KmlxcikgJiB3YXJwYnJlYWtzJGJyZWFrcyA8IChRWzJdKzEuNSppcXIpKQ0KYGBgDQoNCjxicj4NCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyBSIGFsc28gaGFzIG90aGVyIHdheXMgb2YgcmVtb3Zpbmcgb3V0bGllcnMsIG9uZSBvZiB0aGVtIGRvbmUgYnkgdXNpbmcgdGhlIFtib3hwbG90KCldKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9ncmFwaGljcy92ZXJzaW9ucy8zLjYuMi90b3BpY3MvYm94cGxvdCkgZnVuY3Rpb24gdG8gaWRlbnRpZnkgdGhlIG91dGxpZXJzIGFuZCB0aGUgW3doaWNoKCldKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9iYXNlL3ZlcnNpb25zLzMuNi4yL3RvcGljcy93aGljaCkgZnVuY3Rpb24gdG8gZmluZCBhbmQgcmVtb3ZlIHRoZW0gZnJvbSB0aGUgZGF0YXNldC4NCmBgYHtyLCBldmFsID0gRkFMU0V9DQpib3hwbG90KHdhcnBicmVha3MkYnJlYWtzLCBwbG90PUZBTFNFKSRvdXQgIyBpZGVudGlmeWluZyB0aGUgb3V0bGllcnMNCm91dGxpZXJzIDwtIGJveHBsb3Qod2FycGJyZWFrcyRicmVha3MsIHBsb3Q9RkFMU0UpJG91dCAjIHNhdmluZyB0aGUgb3V0bGllcnMgaW4gYSB2ZWN0b3INCnggPC13YXJwYnJlYWtzDQp4IDwtIHhbLXdoaWNoKHgkYnJlYWtzICVpbiUgb3V0bGllcnMpLF0NCmBgYA0KDQo8YnI+DQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgRXZlbiB0aG91Z2gsIGl0IHJlcXVpcmVzIGEgbGl0dGxlIGJpdCBtb3JlIFIga25vd2xlZGdlLCB0aGlzIGlzIG1heWJlICoqdGhlIG1vcmUgZWZmaWNpZW50IHdheSB0byByZW1vdmUgb3V0bGllcnMgaW4gUioqLg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgVGhpcyBibG9nIGV4cGxhaW5zIHVzICoqd2h5IGFuZCBob3cgdG8gcmVtb3ZlIG91dGxpZXJzIGluIFIqKi4NCjxicj4NCjxicj4NCjxicj4NCg0KIyMjICZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO19fX1RoYW5rcyBmb3IgcmVhZGluZy4uLl9fXw0KPGJyPg0KPGJyPg0KIVtSTWFya2Rvd25dKGh0dHBzOi8vd3d3Lm1hcmF0aG9udXMuY29tL21lZGlhLzIzNjYvdXNpbmctci1tYXJrZG93bi10by1zaGFyZS1hbmFseXNpcy1zLmpwZz9xdWFsaXR5PTgwKVw=