Packages Required
library(readr);library(tidyr);library(dplyr)
library(validate);library(lubridate);library(deductive)
library(outliers);library(Hmisc);library(stringr)
library(knitr);library(ggplot2)
Abstract
The assignment is based on pre-processing the data. The dataset used for this purpose is exported from Kaggle. The dataset contains two files with descriptions of olympic events and players demographics. The two data files are mergered together using the function left_join. The dataset is analysed to understand the variable types.
The variable NOC were renamed as country code in both the datasets.Some variables such as Country code and height of players were converted into factor and numeric variables respectively. The date variable was analysed and converted based the seasons. The variable medals eas ordered and assigned labels based on Gld, Silver and Bronze and N/A’s as Not_Awarded. The variable games contained year and seasons which was spilt and assigned them into two columns. The variable column notes was dropped as it wasn’t useful and it mostly contained N/A’s.
The Body mass Index column was created using the variables weight and height by converting height variable and using function mutate to create a new column Bosy Mass Index. Next, the dataset was scanned to check for N/A’s. The N/A’s in the weight, height and bosy_mass columns were replaced based on gender. The age variable was replaced with the mean ages of players. The N/A’s in the medals variable was replaced using Not_awarded.
Then the height and body mass index variables were transformed and ploted using boxplot. They happened to have many outliers, tose outliers were treated by capping them. The height and body mass variables were transformed using log and log10 transformations. Then those transformed variables were plotted using histograms.
Data
The data of olympic events and their regional information is taken from Kaggle. The dataset source:
https://www.kaggle.com/heesoo37/120-years-of-olympic-history-athletes-and-results#athlete_events.csv
The dataset contains information of all events and players from 1896 to 2016. the data contains 2,71,116 observations containing 15 columns in the athletics dataset. The dataset nationality contains 230 observation and 3 variables. They are merged together based on the Country code of the olympics being played.
The datset athletics contains variables such as ID, Names, Sex, Age, Weight, Height, Teams, counry code, games, year,seasons, sport played, city, events and medals won. The other dataset nationality contains 3 variables such as country code, countries and notes.
Reading the dataset into R
The datsets both athletics and nationality were read to R Studio using function read_csv and the NOC cariable was renamed as countrycode. Then the nationality dataset was read into R and both the columns NOC and Regions were renamed as country code and country respectively. Both the dataset was then merged together and using the head() function the first few rows of the datset is displayed.
athletics <- read_csv("C:/Users/Varshini/Desktop/Data Pre-Processing/athletics.csv")
head(athletics)
nationality <- read.csv("C:/Users/Varshini/Desktop/Data Pre-Processing/nationality.csv")
colnames(nationality)
[1] "NOC" "region" "notes"
names(nationality)[names(nationality) == "NOC"] <- "Country_code"
names(nationality)[names(nationality) == "region"] <- "Country"
head(nationality)
sports <- left_join(athletics, nationality)
head(sports)
Understand
The data is scanned using the str() function to understad the variable types. The variable types were read in correctly. Country code variable is converted into factor variable. Changing the height variable to be numeric. The year variable is converted to date format using the ifelse statement to determine summer and winter olympics. The medal variable contained silver, silve and bronze levels. These levels were ordered from gold to bronze.
sports$Height <- as.numeric(sports$Height)
sports$Country_code <- as.factor(sports$Country_code)
year_season <- ifelse(sports$Season == "Winter", paste(sports$Year, 7, 20, sep = "-"), paste(sports$Year, 1, 20, sep = "-"))
year_season <- ymd(year_season)
sports$season_year <- year_season
sports$Medal <- ordered(sports$Medal, levels = c("Gold", "Silver", "Bronze"), labels=c("Gold_Medal", "Silver_Medal", "Bronze_Medal"))
str(sports)
Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame': 271116 obs. of 18 variables:
$ ID : num 1 2 3 4 5 5 5 5 5 5 ...
$ Name : chr "A Dijiang" "A Lamusi" "Gunnar Nielsen Aaby" "Edgar Lindenau Aabye" ...
$ Gender : Factor w/ 2 levels "Male","Female": 1 1 1 1 2 2 2 2 2 2 ...
$ Age : num 24 23 24 34 21 21 25 25 27 27 ...
$ Height : num 180 170 NA NA 185 185 185 185 185 185 ...
$ Weight : num 80 60 NA NA 82 82 82 82 82 82 ...
$ Team : chr "China" "China" "Denmark" "Denmark/Sweden" ...
$ Country_code: Factor w/ 230 levels "AFG","AHO","ALB",..: 42 42 56 56 146 146 146 146 146 146 ...
$ Games : chr "1992 Summer" "2012 Summer" "1920 Summer" "1900 Summer" ...
$ Year : num 1992 2012 1920 1900 1988 ...
$ Season : chr "Summer" "Summer" "Summer" "Summer" ...
$ City : chr "Barcelona" "London" "Antwerpen" "Paris" ...
$ Sport : chr "Basketball" "Judo" "Football" "Tug-Of-War" ...
$ Event : chr "Basketball Men's Basketball" "Judo Men's Extra-Lightweight" "Football Men's Football" "Tug-Of-War Men's Tug-Of-War" ...
$ Medal : Ord.factor w/ 3 levels "Gold_Medal"<"Silver_Medal"<..: NA NA NA 1 NA NA NA NA NA NA ...
$ Country : Factor w/ 206 levels "Afghanistan",..: 40 40 51 51 130 130 130 130 130 130 ...
$ notes : Factor w/ 22 levels "","Antigua and Barbuda",..: 1 1 1 1 1 1 1 1 1 1 ...
$ season_year : Date, format: "1992-01-20" "2012-01-20" ...
Tidy & Manipulate Data I
The dataset is cleaned but the games played variable contains year and season information which needed to be spilt by the use of the seperate() to create new column season and year from the spilt information of the games variable. Then the column games and notes was dropped as they were not useful for the analysis.
sports_mod <- sports %>% separate(Games, into = c("Date_Year", "Seasons"), sep = " ")
head(sports_mod)
Tidy & Manipulate Data II
The height variable is converted into metric using the formula height/100
A new column body mass was created utilizing the weight and height variabl by converting height variable into metrics and using the formula Body_mass_Index = weight/height^2
var_height <- format(as.numeric(sports_mod$Height) / 100)
var_height <- as.numeric(var_height)
body_mass <- mutate(sports_mod, body_mass = sports_mod$Weight/sports_mod$Height^2)
sports_mod <- cbind(body_mass)
head(sports_mod)
Scan I
The dataset is scanned to check N/A’s in the column variables. The N/A’s in the variable age is replaced by uing the mean age of players based on the gender of the players. The variable height, weight, and body mass N/A’s were replaced using their mean by grouping them by gender. The medals variable contained N/A’s which was replaced by using Not_awarded in place of N/A’s as only maximum 3 possible players in every game will wins one of the medal and all others are not awarded medals for securing other positions in the games.
The remaing N/A’s were removed and using the colsums(is.na()) we check for colunms with N/A’s and omit them.
colSums(is.na(sports_mod))
ID Name Gender Age Height Weight
0 0 0 9474 60171 62875
Team Country_code Date_Year Seasons Year Season
0 0 0 0 0 0
City Sport Event Medal Country notes
0 0 0 231333 370 349
season_year body_mass
0 64263
sports_mod$Age[is.na(sports_mod$Age)] <- mean(sports_mod$Age, na.rm = TRUE)
sports_mod$Height[is.na(sports_mod$Height)] <- mean(sports_mod$Height, na.rm = TRUE)
sports_mod$Weight[is.na(sports_mod$Weight)] <- mean(sports_mod$Weight, na.rm = TRUE)
sports_mod$body_mass[is.na(sports_mod$body_mass)] <- mean(sports_mod$body_mass, na.rm = TRUE)
sports_mod$Medal<- as.character(sports_mod$Medal)
sports_mod$Medal[is.na(sports_mod$Medal)] <- "not_awarded"
sports_mod$Medal <- ordered(sports_mod$Medal, c("Gold", "Silver", "Bronze", "not_awarded"))
sports_mod <- na.omit(sports_mod)
head(sports_mod)
colSums(is.na(sports_mod))
ID Name Gender Age Height Weight
0 0 0 0 0 0
Team Country_code Date_Year Seasons Year Season
0 0 0 0 0 0
City Sport Event Medal Country notes
0 0 0 0 0 0
season_year body_mass
0 0
Scan II
The data is scanned again using boxplot function to check for outliers. All the numeric variables had outliers in them. To treat the outliers in the variables, the outliers were capped. These variables were again plotted to check for outliers and there were no signs of outliers.
par(mfrow = c(1,2))
boxplot(var_height, main = "Athletes Weight", col="orange")
boxplot(sports_mod$Weight, main= " Athletes Weight", col="blue")

par(mfrow = c(1,2))
boxplot(sports_mod$body_mass, main = "Body Mass Index of Athletes", col="green")
boxplot(sports_mod$Age, main = "Athletes Age", col="red")

cap <- function(x){
quantiles <- quantile( x, c(.05, 0.25, 0.75, .95 ) )
x[ x < quantiles[2] - 1.5*IQR(x) ] <- quantiles[1]
x[ x > quantiles[3] + 1.5*IQR(x) ] <- quantiles[4]
x
}
height_var <- sports_mod$Height %>% cap()
weight_var <- sports_mod$Weight %>% cap()
bosy_mass <- sports_mod$body_mass %>% cap()
age_var <- sports_mod$Age %>% cap()
par(mfrow = c(1,2))
boxplot(var_height, main = "Athletes Height", col="orange")
boxplot(sports_mod$Weight, main= "Athletes Weight", col="blue")

par(mfrow = c(1,2))
boxplot(sports_mod$body_mass, main = "Body Mass Index of Athletes", col="green")
boxplot(sports_mod$Age, main = "Age of Athletes", col="red")

Conclusion
The olympic games dataset was mostly tidy but had some untidy variables and needed new variables to be created to analyse the events more accurately. Various functions from the tidyr, dplyr,lubricate, outliers etc were used to tidy the dataset. The data set numeric variables were transfored and plotted to understand and analyse the olympic dataset.
LS0tDQp0aXRsZTogIlNlbWVzdGVyIDEsIDIwMTkgLSBNQVRIMjM0OShEYXRhIFByZXByb2Nlc3NpbmcpIg0KYXV0aG9yOiAiVmFyc2hpbmkgUmF2aShzMzY1NDI3MikgIg0Kc3VidGl0bGU6IEFzc2lnbm1lbnQgMw0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQotLS0NCg0KIyMgUGFja2FnZXMgUmVxdWlyZWQNCg0KYGBge3J9DQpsaWJyYXJ5KHJlYWRyKTtsaWJyYXJ5KHRpZHlyKTtsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh2YWxpZGF0ZSk7bGlicmFyeShsdWJyaWRhdGUpO2xpYnJhcnkoZGVkdWN0aXZlKQ0KbGlicmFyeShvdXRsaWVycyk7bGlicmFyeShIbWlzYyk7bGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShrbml0cik7bGlicmFyeShnZ3Bsb3QyKQ0KDQpgYGANCg0KDQojIyAgQWJzdHJhY3QgIA0KDQpUaGUgYXNzaWdubWVudCBpcyBiYXNlZCBvbiBwcmUtcHJvY2Vzc2luZyB0aGUgZGF0YS4gVGhlIGRhdGFzZXQgdXNlZCBmb3IgdGhpcyBwdXJwb3NlIGlzIGV4cG9ydGVkIGZyb20gS2FnZ2xlLiBUaGUgZGF0YXNldCBjb250YWlucyB0d28gZmlsZXMgd2l0aCBkZXNjcmlwdGlvbnMgb2YgIG9seW1waWMgZXZlbnRzIGFuZCBwbGF5ZXJzIGRlbW9ncmFwaGljcy4gVGhlIHR3byBkYXRhIGZpbGVzIGFyZSBtZXJnZXJlZCB0b2dldGhlciB1c2luZyB0aGUgZnVuY3Rpb24gbGVmdF9qb2luLiBUaGUgZGF0YXNldCBpcyBhbmFseXNlZCB0byB1bmRlcnN0YW5kIHRoZSB2YXJpYWJsZSB0eXBlcy4NCg0KVGhlIHZhcmlhYmxlIE5PQyB3ZXJlIHJlbmFtZWQgYXMgY291bnRyeSBjb2RlIGluIGJvdGggdGhlIGRhdGFzZXRzLlNvbWUgdmFyaWFibGVzIHN1Y2ggYXMgQ291bnRyeSBjb2RlIGFuZCBoZWlnaHQgb2YgcGxheWVycyB3ZXJlIGNvbnZlcnRlZCBpbnRvIGZhY3RvciBhbmQgbnVtZXJpYyB2YXJpYWJsZXMgcmVzcGVjdGl2ZWx5LiBUaGUgZGF0ZSB2YXJpYWJsZSB3YXMgYW5hbHlzZWQgYW5kIGNvbnZlcnRlZCBiYXNlZCB0aGUgc2Vhc29ucy4gVGhlIHZhcmlhYmxlIG1lZGFscyBlYXMgb3JkZXJlZCBhbmQgYXNzaWduZWQgbGFiZWxzIGJhc2VkIG9uIEdsZCwgU2lsdmVyIGFuZCBCcm9uemUgYW5kIE4vQSdzIGFzIE5vdF9Bd2FyZGVkLiBUaGUgdmFyaWFibGUgZ2FtZXMgY29udGFpbmVkIHllYXIgYW5kIHNlYXNvbnMgd2hpY2ggd2FzIHNwaWx0IGFuZCBhc3NpZ25lZCB0aGVtIGludG8gdHdvIGNvbHVtbnMuIFRoZSB2YXJpYWJsZSBjb2x1bW4gbm90ZXMgd2FzIGRyb3BwZWQgYXMgaXQgd2Fzbid0IHVzZWZ1bCBhbmQgaXQgbW9zdGx5IGNvbnRhaW5lZCBOL0Ency4NCg0KVGhlIEJvZHkgbWFzcyBJbmRleCBjb2x1bW4gd2FzIGNyZWF0ZWQgdXNpbmcgdGhlIHZhcmlhYmxlcyB3ZWlnaHQgYW5kIGhlaWdodCBieSBjb252ZXJ0aW5nIGhlaWdodCB2YXJpYWJsZSBhbmQgdXNpbmcgZnVuY3Rpb24gbXV0YXRlIHRvIGNyZWF0ZSBhIG5ldyBjb2x1bW4gQm9zeSBNYXNzIEluZGV4LiBOZXh0LCB0aGUgZGF0YXNldCB3YXMgc2Nhbm5lZCB0byBjaGVjayBmb3IgTi9BJ3MuIFRoZSBOL0EncyBpbiB0aGUgd2VpZ2h0LCBoZWlnaHQgYW5kIGJvc3lfbWFzcyBjb2x1bW5zIHdlcmUgcmVwbGFjZWQgYmFzZWQgb24gZ2VuZGVyLiBUaGUgYWdlIHZhcmlhYmxlIHdhcyByZXBsYWNlZCB3aXRoIHRoZSBtZWFuIGFnZXMgb2YgcGxheWVycy4gVGhlIE4vQSdzIGluIHRoZSBtZWRhbHMgdmFyaWFibGUgd2FzIHJlcGxhY2VkIHVzaW5nIE5vdF9hd2FyZGVkLg0KDQpUaGVuIHRoZSBoZWlnaHQgYW5kIGJvZHkgbWFzcyBpbmRleCB2YXJpYWJsZXMgd2VyZSB0cmFuc2Zvcm1lZCBhbmQgcGxvdGVkIHVzaW5nIGJveHBsb3QuIFRoZXkgaGFwcGVuZWQgdG8gaGF2ZSBtYW55IG91dGxpZXJzLCB0b3NlIG91dGxpZXJzIHdlcmUgdHJlYXRlZCBieSBjYXBwaW5nIHRoZW0uIFRoZSBoZWlnaHQgYW5kIGJvZHkgbWFzcyB2YXJpYWJsZXMgd2VyZSB0cmFuc2Zvcm1lZCB1c2luZyBsb2cgYW5kIGxvZzEwIHRyYW5zZm9ybWF0aW9ucy4gVGhlbiB0aG9zZSB0cmFuc2Zvcm1lZCB2YXJpYWJsZXMgd2VyZSBwbG90dGVkIHVzaW5nIGhpc3RvZ3JhbXMuDQoNCiMjIERhdGEgDQoNClRoZSBkYXRhIG9mIG9seW1waWMgZXZlbnRzIGFuZCB0aGVpciByZWdpb25hbCBpbmZvcm1hdGlvbiBpcyB0YWtlbiBmcm9tIEthZ2dsZS4gIFRoZSBkYXRhc2V0IHNvdXJjZTogDQoNCmh0dHBzOi8vd3d3LmthZ2dsZS5jb20vaGVlc29vMzcvMTIwLXllYXJzLW9mLW9seW1waWMtaGlzdG9yeS1hdGhsZXRlcy1hbmQtcmVzdWx0cyNhdGhsZXRlX2V2ZW50cy5jc3YNCg0KVGhlIGRhdGFzZXQgY29udGFpbnMgaW5mb3JtYXRpb24gb2YgYWxsIGV2ZW50cyBhbmQgcGxheWVycyBmcm9tIDE4OTYgdG8gMjAxNi4gdGhlIGRhdGEgY29udGFpbnMgMiw3MSwxMTYgb2JzZXJ2YXRpb25zIGNvbnRhaW5pbmcgMTUgY29sdW1ucyBpbiB0aGUgYXRobGV0aWNzIGRhdGFzZXQuIFRoZSBkYXRhc2V0IG5hdGlvbmFsaXR5IGNvbnRhaW5zIDIzMCBvYnNlcnZhdGlvbiBhbmQgMyB2YXJpYWJsZXMuIFRoZXkgYXJlIG1lcmdlZCB0b2dldGhlciBiYXNlZCBvbiB0aGUgQ291bnRyeSBjb2RlIG9mIHRoZSBvbHltcGljcyBiZWluZyBwbGF5ZWQuDQoNClRoZSBkYXRzZXQgYXRobGV0aWNzIGNvbnRhaW5zIHZhcmlhYmxlcyBzdWNoIGFzIElELCBOYW1lcywgU2V4LCBBZ2UsIFdlaWdodCwgSGVpZ2h0LCBUZWFtcywgY291bnJ5IGNvZGUsIGdhbWVzLCB5ZWFyLHNlYXNvbnMsIHNwb3J0IHBsYXllZCwgY2l0eSwgZXZlbnRzIGFuZCBtZWRhbHMgd29uLiBUaGUgb3RoZXIgZGF0YXNldCBuYXRpb25hbGl0eSBjb250YWlucyAzIHZhcmlhYmxlcyBzdWNoIGFzIGNvdW50cnkgY29kZSwgY291bnRyaWVzIGFuZCBub3Rlcy4NCg0KDQoNCiMjIFJlYWRpbmcgdGhlIGRhdGFzZXQgaW50byBSIA0KIFRoZSBkYXRzZXRzIGJvdGggYXRobGV0aWNzIGFuZCBuYXRpb25hbGl0eSB3ZXJlIHJlYWQgdG8gUiBTdHVkaW8gdXNpbmcgZnVuY3Rpb24gcmVhZF9jc3YgYW5kIHRoZSBOT0MgY2FyaWFibGUgd2FzIHJlbmFtZWQgYXMgY291bnRyeWNvZGUuIFRoZW4gdGhlIG5hdGlvbmFsaXR5IGRhdGFzZXQgd2FzIHJlYWQgaW50byBSIGFuZCBib3RoIHRoZSBjb2x1bW5zIE5PQyBhbmQgUmVnaW9ucyB3ZXJlIHJlbmFtZWQgYXMgY291bnRyeSBjb2RlIGFuZCBjb3VudHJ5IHJlc3BlY3RpdmVseS4gQm90aCB0aGUgZGF0YXNldCB3YXMgdGhlbiBtZXJnZWQgdG9nZXRoZXIgYW5kIHVzaW5nIHRoZSBoZWFkKCkNCmZ1bmN0aW9uIHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZGF0c2V0IGlzIGRpc3BsYXllZC4NCg0KYGBge3IsIGV2YWw9RkFMU0V9DQphdGhsZXRpY3MgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL1ZhcnNoaW5pL0Rlc2t0b3AvRGF0YSBQcmUtUHJvY2Vzc2luZy9hdGhsZXRpY3MuY3N2IikNCmBgYA0KDQpgYGB7ciwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCm5hbWVzKGF0aGxldGljcylbbmFtZXMoYXRobGV0aWNzKSA9PSAiTk9DIl0gPC0gIkNvdW50cnlfY29kZSINCm5hbWVzKGF0aGxldGljcylbbmFtZXMoYXRobGV0aWNzKT09IlNleCJdIDwtICJHZW5kZXIiDQoNCmF0aGxldGljcyRHZW5kZXIgPC0gZmFjdG9yKGF0aGxldGljcyRHZW5kZXIsIGxldmVscz1jKCdNJywnRicpLA0KICBsYWJlbHM9YygnTWFsZScsJ0ZlbWFsZScpKQ0KYGBgDQoNCmBgYHtyfQ0KaGVhZChhdGhsZXRpY3MpDQpgYGANCg0KYGBge3J9DQpuYXRpb25hbGl0eSA8LSByZWFkLmNzdigiQzovVXNlcnMvVmFyc2hpbmkvRGVza3RvcC9EYXRhIFByZS1Qcm9jZXNzaW5nL25hdGlvbmFsaXR5LmNzdiIpDQpjb2xuYW1lcyhuYXRpb25hbGl0eSkNCm5hbWVzKG5hdGlvbmFsaXR5KVtuYW1lcyhuYXRpb25hbGl0eSkgPT0gIk5PQyJdIDwtICJDb3VudHJ5X2NvZGUiDQpuYW1lcyhuYXRpb25hbGl0eSlbbmFtZXMobmF0aW9uYWxpdHkpID09ICJyZWdpb24iXSA8LSAiQ291bnRyeSINCmhlYWQobmF0aW9uYWxpdHkpDQpgYGANCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpzcG9ydHMgPC0gbGVmdF9qb2luKGF0aGxldGljcywgbmF0aW9uYWxpdHkpDQpgYGANCg0KYGBge3J9DQpoZWFkKHNwb3J0cykNCmBgYA0KDQojIyBVbmRlcnN0YW5kIA0KDQpUaGUgZGF0YSBpcyBzY2FubmVkIHVzaW5nIHRoZSBzdHIoKSBmdW5jdGlvbiB0byB1bmRlcnN0YWQgdGhlIHZhcmlhYmxlIHR5cGVzLiBUaGUgdmFyaWFibGUgdHlwZXMgd2VyZSByZWFkIGluIGNvcnJlY3RseS4gQ291bnRyeSBjb2RlIHZhcmlhYmxlIGlzIGNvbnZlcnRlZCBpbnRvIGZhY3RvciB2YXJpYWJsZS4gQ2hhbmdpbmcgdGhlIGhlaWdodCB2YXJpYWJsZSB0byBiZSBudW1lcmljLiBUaGUgeWVhciB2YXJpYWJsZSBpcyBjb252ZXJ0ZWQgdG8gZGF0ZSBmb3JtYXQgdXNpbmcgdGhlIGlmZWxzZSBzdGF0ZW1lbnQgdG8gZGV0ZXJtaW5lIHN1bW1lciBhbmQgd2ludGVyIG9seW1waWNzLg0KVGhlIG1lZGFsIHZhcmlhYmxlIGNvbnRhaW5lZCBzaWx2ZXIsIHNpbHZlIGFuZCBicm9uemUgbGV2ZWxzLiBUaGVzZSBsZXZlbHMgd2VyZSBvcmRlcmVkIGZyb20gZ29sZCB0byBicm9uemUuDQoNCg0KYGBge3J9DQpzcG9ydHMkSGVpZ2h0IDwtIGFzLm51bWVyaWMoc3BvcnRzJEhlaWdodCkNCnNwb3J0cyRDb3VudHJ5X2NvZGUgPC0gYXMuZmFjdG9yKHNwb3J0cyRDb3VudHJ5X2NvZGUpDQoNCnllYXJfc2Vhc29uIDwtIGlmZWxzZShzcG9ydHMkU2Vhc29uID09ICJXaW50ZXIiLCBwYXN0ZShzcG9ydHMkWWVhciwgNywgMjAsIHNlcCA9ICItIiksIHBhc3RlKHNwb3J0cyRZZWFyLCAxLCAyMCwgc2VwID0gIi0iKSkNCnllYXJfc2Vhc29uIDwtIHltZCh5ZWFyX3NlYXNvbikNCnNwb3J0cyRzZWFzb25feWVhciA8LSB5ZWFyX3NlYXNvbg0KDQpzcG9ydHMkTWVkYWwgPC0gb3JkZXJlZChzcG9ydHMkTWVkYWwsIGxldmVscyA9IGMoIkdvbGQiLCAiU2lsdmVyIiwgIkJyb256ZSIpLCBsYWJlbHM9YygiR29sZF9NZWRhbCIsICJTaWx2ZXJfTWVkYWwiLCAiQnJvbnplX01lZGFsIikpDQoNCmBgYA0KDQpgYGB7cn0NCnN0cihzcG9ydHMpDQpgYGANCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSANCg0KVGhlIGRhdGFzZXQgaXMgY2xlYW5lZCBidXQgdGhlIGdhbWVzIHBsYXllZCB2YXJpYWJsZSBjb250YWlucyB5ZWFyIGFuZCBzZWFzb24gaW5mb3JtYXRpb24gd2hpY2ggbmVlZGVkIHRvIGJlIHNwaWx0IGJ5IHRoZSB1c2Ugb2YgdGhlIHNlcGVyYXRlKCkgIHRvIGNyZWF0ZSBuZXcgY29sdW1uIHNlYXNvbiBhbmQgeWVhciBmcm9tIHRoZSBzcGlsdCBpbmZvcm1hdGlvbiBvZiB0aGUgZ2FtZXMgdmFyaWFibGUuDQpUaGVuIHRoZSBjb2x1bW4gZ2FtZXMgYW5kIG5vdGVzIHdhcyBkcm9wcGVkIGFzIHRoZXkgd2VyZSBub3QgdXNlZnVsIGZvciB0aGUgYW5hbHlzaXMuDQoNCmBgYHtyfQ0Kc3BvcnRzX21vZCA8LSBzcG9ydHMgJT4lIHNlcGFyYXRlKEdhbWVzLCBpbnRvID0gYygiRGF0ZV9ZZWFyIiwgIlNlYXNvbnMiKSwgc2VwID0gIiAiKQ0KaGVhZChzcG9ydHNfbW9kKQ0KYGBgDQoNCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSUkgDQoNClRoZSBoZWlnaHQgdmFyaWFibGUgaXMgY29udmVydGVkIGludG8gbWV0cmljIHVzaW5nIHRoZSBmb3JtdWxhDQogICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodC8xMDAgICAgICANCkEgbmV3IGNvbHVtbiBib2R5IG1hc3Mgd2FzIGNyZWF0ZWQgdXRpbGl6aW5nIHRoZSB3ZWlnaHQgYW5kIGhlaWdodCB2YXJpYWJsIGJ5IGNvbnZlcnRpbmcgaGVpZ2h0IHZhcmlhYmxlIGludG8gbWV0cmljcyBhbmQgdXNpbmcgdGhlIGZvcm11bGEgDQogICAgICAgICAgICAgICAgICAgIEJvZHlfbWFzc19JbmRleCA9IHdlaWdodC9oZWlnaHReMg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCnZhcl9oZWlnaHQgPC0gZm9ybWF0KGFzLm51bWVyaWMoc3BvcnRzX21vZCRIZWlnaHQpIC8gMTAwKQ0KdmFyX2hlaWdodCA8LSBhcy5udW1lcmljKHZhcl9oZWlnaHQpDQoNCmBgYA0KDQpgYGB7cn0NCmJvZHlfbWFzcyA8LSBtdXRhdGUoc3BvcnRzX21vZCwgYm9keV9tYXNzID0gc3BvcnRzX21vZCRXZWlnaHQvc3BvcnRzX21vZCRIZWlnaHReMikNCnNwb3J0c19tb2QgPC0gY2JpbmQoYm9keV9tYXNzKQ0KDQpoZWFkKHNwb3J0c19tb2QpDQpgYGANCg0KIyMJU2NhbiBJIA0KDQpUaGUgZGF0YXNldCBpcyBzY2FubmVkIHRvIGNoZWNrIE4vQSdzIGluIHRoZSBjb2x1bW4gdmFyaWFibGVzLiBUaGUgTi9BJ3MgaW4gdGhlIHZhcmlhYmxlIGFnZSBpcyByZXBsYWNlZCBieSB1aW5nIHRoZSBtZWFuIGFnZSBvZiBwbGF5ZXJzIGJhc2VkIG9uIHRoZSBnZW5kZXIgb2YgdGhlIHBsYXllcnMuIFRoZSB2YXJpYWJsZSBoZWlnaHQsIHdlaWdodCwgYW5kIGJvZHkgbWFzcyBOL0EncyB3ZXJlIHJlcGxhY2VkIHVzaW5nIHRoZWlyIG1lYW4gYnkgZ3JvdXBpbmcgdGhlbSBieSBnZW5kZXIuIFRoZSBtZWRhbHMgdmFyaWFibGUgY29udGFpbmVkIE4vQSdzIHdoaWNoIHdhcyByZXBsYWNlZCBieSB1c2luZyBOb3RfYXdhcmRlZCBpbiBwbGFjZSBvZiBOL0EncyBhcyBvbmx5IG1heGltdW0gMyBwb3NzaWJsZSBwbGF5ZXJzIGluIGV2ZXJ5IGdhbWUgd2lsbCB3aW5zIG9uZSBvZiB0aGUgbWVkYWwgYW5kIGFsbCBvdGhlcnMgYXJlIG5vdCBhd2FyZGVkIG1lZGFscyBmb3Igc2VjdXJpbmcgb3RoZXIgcG9zaXRpb25zIGluIHRoZSBnYW1lcy4NCg0KVGhlIHJlbWFpbmcgTi9BJ3Mgd2VyZSByZW1vdmVkIGFuZCB1c2luZyB0aGUgY29sc3Vtcyhpcy5uYSgpKSB3ZSBjaGVjayBmb3IgY29sdW5tcyB3aXRoIE4vQSdzIGFuZCBvbWl0IHRoZW0uDQoNCg0KYGBge3J9DQpjb2xTdW1zKGlzLm5hKHNwb3J0c19tb2QpKQ0KDQpgYGANCmBgYHtyLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbmFtZXMoc3BvcnRzX21vZClbbmFtZXMoc3BvcnRzX21vZCkgPT0gIlNleCJdIDwtICJHZW5kZXIiDQpgYGANCg0KYGBge3J9DQpzcG9ydHNfbW9kJEFnZVtpcy5uYShzcG9ydHNfbW9kJEFnZSldIDwtIG1lYW4oc3BvcnRzX21vZCRBZ2UsIG5hLnJtID0gVFJVRSkNCg0Kc3BvcnRzX21vZCRIZWlnaHRbaXMubmEoc3BvcnRzX21vZCRIZWlnaHQpXSA8LSBtZWFuKHNwb3J0c19tb2QkSGVpZ2h0LCBuYS5ybSA9IFRSVUUpDQoNCnNwb3J0c19tb2QkV2VpZ2h0W2lzLm5hKHNwb3J0c19tb2QkV2VpZ2h0KV0gPC0gbWVhbihzcG9ydHNfbW9kJFdlaWdodCwgbmEucm0gPSBUUlVFKQ0KDQpzcG9ydHNfbW9kJGJvZHlfbWFzc1tpcy5uYShzcG9ydHNfbW9kJGJvZHlfbWFzcyldIDwtIG1lYW4oc3BvcnRzX21vZCRib2R5X21hc3MsIG5hLnJtID0gVFJVRSkNCg0KYGBgDQoNCmBgYHtyfQ0Kc3BvcnRzX21vZCRNZWRhbDwtIGFzLmNoYXJhY3RlcihzcG9ydHNfbW9kJE1lZGFsKQ0Kc3BvcnRzX21vZCRNZWRhbFtpcy5uYShzcG9ydHNfbW9kJE1lZGFsKV0gPC0gIm5vdF9hd2FyZGVkIg0Kc3BvcnRzX21vZCRNZWRhbCA8LSBvcmRlcmVkKHNwb3J0c19tb2QkTWVkYWwsIGMoIkdvbGQiLCAiU2lsdmVyIiwgIkJyb256ZSIsICJub3RfYXdhcmRlZCIpKQ0KYGBgDQoNCmBgYHtyfQ0Kc3BvcnRzX21vZCA8LSBuYS5vbWl0KHNwb3J0c19tb2QpDQpoZWFkKHNwb3J0c19tb2QpDQpgYGANCg0KYGBge3J9DQpjb2xTdW1zKGlzLm5hKHNwb3J0c19tb2QpKQ0KYGBgDQoNCiMjCVNjYW4gSUkNCg0KVGhlIGRhdGEgaXMgc2Nhbm5lZCBhZ2FpbiB1c2luZyBib3hwbG90IGZ1bmN0aW9uIHRvIGNoZWNrIGZvciBvdXRsaWVycy4gQWxsIHRoZSBudW1lcmljIHZhcmlhYmxlcyBoYWQgb3V0bGllcnMgaW4gdGhlbS4gVG8gdHJlYXQgdGhlIG91dGxpZXJzIGluIHRoZSB2YXJpYWJsZXMsIHRoZSBvdXRsaWVycyB3ZXJlIGNhcHBlZC4gVGhlc2UgdmFyaWFibGVzIHdlcmUgYWdhaW4gcGxvdHRlZCB0byBjaGVjayBmb3Igb3V0bGllcnMgYW5kIHRoZXJlIHdlcmUgbm8gc2lnbnMgb2Ygb3V0bGllcnMuDQoNCmBgYHtyfQ0KcGFyKG1mcm93ID0gYygxLDIpKQ0KYm94cGxvdCh2YXJfaGVpZ2h0LCBtYWluID0gIkF0aGxldGVzIFdlaWdodCIsIGNvbD0ib3JhbmdlIikNCmJveHBsb3Qoc3BvcnRzX21vZCRXZWlnaHQsIG1haW49ICIgQXRobGV0ZXMgV2VpZ2h0IiwgY29sPSJibHVlIikNCmBgYA0KDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMoMSwyKSkNCmJveHBsb3Qoc3BvcnRzX21vZCRib2R5X21hc3MsIG1haW4gPSAiQm9keSBNYXNzIEluZGV4IG9mIEF0aGxldGVzIiwgY29sPSJncmVlbiIpDQpib3hwbG90KHNwb3J0c19tb2QkQWdlLCBtYWluID0gIkF0aGxldGVzIEFnZSIsIGNvbD0icmVkIikNCmBgYA0KDQpgYGB7cn0NCmNhcCA8LSBmdW5jdGlvbih4KXsNCiAgICBxdWFudGlsZXMgPC0gcXVhbnRpbGUoIHgsIGMoLjA1LCAwLjI1LCAwLjc1LCAuOTUgKSApDQogICAgeFsgeCA8IHF1YW50aWxlc1syXSAtIDEuNSpJUVIoeCkgXSA8LSBxdWFudGlsZXNbMV0NCiAgICB4WyB4ID4gcXVhbnRpbGVzWzNdICsgMS41KklRUih4KSBdIDwtIHF1YW50aWxlc1s0XQ0KICAgIHgNCn0NCg0KaGVpZ2h0X3ZhciA8LSBzcG9ydHNfbW9kJEhlaWdodCAlPiUgY2FwKCkNCndlaWdodF92YXIgPC0gc3BvcnRzX21vZCRXZWlnaHQgJT4lIGNhcCgpDQpib3N5X21hc3MgPC0gc3BvcnRzX21vZCRib2R5X21hc3MgJT4lIGNhcCgpDQphZ2VfdmFyIDwtIHNwb3J0c19tb2QkQWdlICU+JSBjYXAoKQ0KDQpgYGANCg0KYGBge3J9DQpwYXIobWZyb3cgPSBjKDEsMikpDQpib3hwbG90KHZhcl9oZWlnaHQsIG1haW4gPSAiQXRobGV0ZXMgSGVpZ2h0IiwgY29sPSJvcmFuZ2UiKQ0KYm94cGxvdChzcG9ydHNfbW9kJFdlaWdodCwgbWFpbj0gIkF0aGxldGVzIFdlaWdodCIsIGNvbD0iYmx1ZSIpDQpgYGANCg0KYGBge3J9DQpwYXIobWZyb3cgPSBjKDEsMikpDQpib3hwbG90KHNwb3J0c19tb2QkYm9keV9tYXNzLCBtYWluID0gIkJvZHkgTWFzcyBJbmRleCBvZiBBdGhsZXRlcyIsIGNvbD0iZ3JlZW4iKQ0KYm94cGxvdChzcG9ydHNfbW9kJEFnZSwgbWFpbiA9ICJBZ2Ugb2YgQXRobGV0ZXMiLCBjb2w9InJlZCIpDQoNCmBgYA0KDQojIwlUcmFuc2Zvcm0gDQoNClRoZSBkYXRhc2V0IGNvbnRhaW5pbmcgbnVtZXJpYyB2YXJpYWJsZXMgc3VjaCBhcyBib2R5IG1hc3MgaW5kZXggYW5kIGhlaWdodCB3ZXJlIHRyYW5zZm9ybWVkIHVzaW5nIGxvZzEwIGFuZCBsb2cgbmF0dXJhbCBmdW5jdGlvbiBpbiBSLiBUaGlzIHRyYW5zZm9ybWF0aW9uIGlzIGRvbmUgdG8gdGhlc2UgdmFyaWFibGUgdG8gbWFrZSB0aGUgZGF0YSBsb29rIG1vcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFVzaW5nIHRoZSBwbG90IGZ1bmN0aW9uIGluIGdncGxvdF8yIHdlIHBsb3QgdGhlIGhpc3RvZ3JhbSBvZiB0aGUgdHJhbnNmb3JtZWQgdmFyaWFibGVzLg0KDQoNCg0KYGBge3J9DQpib2R5X21hc3NfbG9nIDwtbG9nMTAoc3BvcnRzX21vZCRib2R5X21hc3MpDQpnZ3Bsb3QoZGF0YSA9IHNwb3J0c19tb2QsIG1hcHBpbmcgPSBhZXMoYm9keV9tYXNzX2xvZykpICsgDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wNSwgY29sb3I9ImJsYWNrIiwgZmlsbD1yZ2IoMC4yLDAuNywwLjEsMC44KSkNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBzcG9ydHNfbW9kLCBtYXBwaW5nID0gYWVzKHNwb3J0c19tb2QkSGVpZ2h0KSkgKyANCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBjb2xvcj0iYmxhY2siLCBmaWxsPXJnYigwLjcsMC40LDAuNywwLjkpKQ0KDQpgYGANCg0KYGBge3J9DQpsb2cgPC0gbG9nMTAoc3BvcnRzX21vZCRIZWlnaHQpDQpnZ3Bsb3QoZGF0YSA9IHNwb3J0c19tb2QsIG1hcHBpbmcgPSBhZXMobG9nKSkgKyANCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLGNvbG9yPSJibGFjayIsIGZpbGw9cmdiKDAuOCwwLjMsMC4zLDAuOCkgKQ0KDQpgYGANCg0KIyMgQ29uY2x1c2lvbg0KDQpUaGUgb2x5bXBpYyBnYW1lcyBkYXRhc2V0IHdhcyBtb3N0bHkgdGlkeSBidXQgaGFkIHNvbWUgdW50aWR5IHZhcmlhYmxlcyBhbmQgbmVlZGVkIG5ldyB2YXJpYWJsZXMgdG8gYmUgY3JlYXRlZCB0byBhbmFseXNlIHRoZSBldmVudHMgbW9yZSBhY2N1cmF0ZWx5LiBWYXJpb3VzICBmdW5jdGlvbnMgZnJvbSB0aGUgdGlkeXIsIGRwbHlyLGx1YnJpY2F0ZSwgb3V0bGllcnMgZXRjIHdlcmUgdXNlZCB0byB0aWR5IHRoZSBkYXRhc2V0LiBUaGUgZGF0YSBzZXQgbnVtZXJpYyB2YXJpYWJsZXMgd2VyZSB0cmFuc2ZvcmVkIGFuZCBwbG90dGVkIHRvIHVuZGVyc3RhbmQgYW5kIGFuYWx5c2UgdGhlIG9seW1waWMgZGF0YXNldC4NCg0KPGJyPg0KPGJyPg0K