Required packages

# This is the R chunk for the required packages
library(readr)
library(tidyr) 
library(dplyr) 
library(ggplot2) 
library(outliers)
library(editrules)
library(MVN)

Executive Summary

In order to prepare the analysis of Competitive League of Legend Matches two data sets have been imported into R. The two data sets have various variables collected about the Legaue Matches. The Data section outlines what these variables are and what types of variables they are i.e. character, numerical. One of the data sets “gold_matches” is left joined onto “League_Matches” to create League_data which was joined through the variable “Address”. The new data set is then checked for any obvious errors.

In the Understand Section League_data is checked for any incorrectly categorized variables. Many of the variables were converted to from characters to factors as they were incorrectly read as characters.

League_data was then tidied and manipulated. Firstly the Season_Type column was separated as into two columns as it contained two variables. Secondly, a column was removed as it didn’t contain a variable and lastly, a new variable was created from 2 variables: “Golddiff_change_from_min10_min20” was created from the variable min_10 and min_20.

League_data was then scanned. Firstly, for missing values, special values and obvious errors/inconsistencies. It was found that there were 435 missing values, which were excluded as they made up a small percentage of the data set. No special values or obvious errors/inconsistencies were found.

Secondly, the data set was scanned for any outliers. the variable “Golddiff_change_from_min10_min20” was found to have outliers which were removed using the function z.scores().

Lastly, the variable “gamelength” was transformed to be normally distributed using logarithmic transformations as it is preferred for statistical inference.

Data

Two datasets “League_Matches” and “Gold_matches” both collected data from competitive League of Legends Matches from 2015 to 2018. League_Matches has both numeric and qualitative variables about the games played including, the result, game length, team names, the players, and champions picked. The data set "Gold_Matches also has both qualitative and numeric variables collected about the difference in gold from first minute to the 20th minute of the competitive League of Legend Matches.

League_Matches has 29 variables and 7620 observations. Example of the Definitions/details of these variables are given below:

League: The league in which the game was played. i.e. North American league (NALCS)

Year: Year the game was played

Season_Type: Which season and what type of game it was i.e. season match or final

blueTeamTag: Blue side team name

bResult: Result for Blue team

rResult: Result for Red team

RedTeamTag: Red Side team name

gamelength: How long the game lasted

BlueTop: Player who played top for Blue team

BlueTopChamp: Champion played top by the Blue team

BlueJungler: Player who played top for Blue team

BlueJunglerChamp Champion played jungle by the Blue team

BlueMiddle: Player who played mid for the Blue team

BlueMiddleChamp: Champion played mid by the Blue team

BlueADC: Player who played ADC for the Blue team

BlueADCChamp: Champion played ADC by the Blue team

BlueSupport: Player who played support for the Blue team

BlueSupportChampion: Champion played support by the Blue team

Position(i.e Support) and Champion variable repeated for the Red team. Website Url: https://www.kaggle.com/chuckephron/leagueoflegends

Gold_matches has 22 variables and 7620 observations. Examples of the Definitions/details of these variables are given below:

Address: the match URL the offical League of Legends match history site.

Type: The gold type

min_1: Gold difference at 1 minute

min_2: Gold difference at 2 minutes

min_3 Gold difference at 3 minutes

up to min_20: Gold Difference at 20 minutes

Website Url: https://www.kaggle.com/chuckephron/leagueoflegends

League_Matches and gold_matches csvs are imported, heads checked for any obvious issues. Gold_matches is left_joined onto League_Matches by “Address”.

# This is the R chunk for the Data Section
League_Matches <- read_csv("~/Pictures/Grad Cert/League Matches.csv")

── Column specification ──────────────────────────────────────────────────────────────
cols(
  .default = col_character(),
  Year = col_double(),
  bResult = col_double(),
  rResult = col_double(),
  gamelength = col_double()
)
ℹ Use `spec()` for the full column specifications.
gold_matches <- read_csv("~/Pictures/Grad Cert/gold matches.csv")

── Column specification ──────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  Address = col_character(),
  Type = col_character()
)
ℹ Use `spec()` for the full column specifications.
head(League_Matches)
head(gold_matches)

League_data <- League_Matches %>% left_join(gold_matches,by = "Address")
head(League_data)
NA

Understand

Checked the dimensions of the League_data data frame, 7620 observations, 50 variables. Of the 50 variables, 26 are currently read as characters and 24 as doubles/numeric. bResult and rResult should be converted into a factor variable and relabeled “Win” and “Loss” with Win ordered higher than loss. League, Year, Season Type, blueTeamTag and redTeamTag should also be converted to factors. This is done with the use of the as.factor function.

# This is the R chunk for the Understand Section

League_data$bResult <- as.factor(League_data$bResult)
League_data$bResult <- League_data$bResult %>% factor(levels = c("1","0"), order = TRUE, labels=c ("Win","Loss"))

League_data$rResult <- as.factor(League_data$rResult)
League_data$rResult <- League_data$rResult %>% factor(levels = c("1","0"), order = TRUE, labels= c("Win","Loss"))


League_data$League <- as.factor(League_data$League)
League_data$Year <- as.factor(League_data$Year)
League_data$Season_Type <- as.factor(League_data$Season_Type)
League_data$blueTeamTag <- as.factor(League_data$blueTeamTag)
League_data$redTeamTag <- as.factor(League_data$redTeamTag)

head(League_data)

Tidy & Manipulate Data I

Two variables were kept in the “Season_Type” column making the data frame untidy. Whether the game is played in the “Summer” or “Spring” was in the same column as whether the game was a “Season” game or a “Playoff” game. Therefore the separate function was used to tidy the data and have the variables separated into two different columns.

“Type” variable was also removed from the data set as it was not a variable as all observations contained the same observation “golddiff”.

# This is the R chunk for the Tidy & Manipulate Data I 
League_data <- League_data %>% separate(Season_Type, into = c("Season","Game_Type"),sep = " ")
League_data <- League_data %>% select (-Type)
League_data$Game_Type <- as.factor(League_data$Game_Type)
League_data$Season <- as.factor(League_data$Season)
head(League_data)
NA

Tidy & Manipulate Data II

Created a new variable from the min_10 and min_20 variable showing the change in the gold lead from 10 mins to 20 mins into the game. The mutate function was used to create this and will allow for easier analysis of how the gold lead changes from earlier in the game to later in the game.

# This is the R chunk for the Tidy & Manipulate Data II 
League_data <- mutate(League_data, Golddiff_change_from_min10_min20 = min_20 - min_10)

Scan I

The data was scanned for missing values, special values and obvious errors and inconsistencies.

Scanning for missng variables showed that there 435 missing values. These values primarily occured in 38 rows of the data set and were sub 5% of the data set. So it was decided that it was the best stratergy to leave out the values with missing features in order not to bias the analysis.

The data was scanned for special values using is.infinite() and is.nan() no values were found.

The gold difference variables (i.e. min_1, min_2) and “gamelength” variable were also scanned for any obvious errors or inconsistencies. It was found that there were no errors or inconsistencies.

# This is the R chunk for the Scan I
sum(is.na(League_data))
[1] 435
colSums(is.na(League_data))
                          League                             Year 
                               0                                0 
                          Season                        Game_Type 
                               0                                0 
                     blueTeamTag                          bResult 
                              38                                0 
                         rResult                       redTeamTag 
                               0                               37 
                      gamelength                          blueTop 
                               0                               37 
                    blueTopChamp                       blueJungle 
                               0                               28 
                 blueJungleChamp                       blueMiddle 
                               0                               37 
                 blueMiddleChamp                          blueADC 
                               0                               37 
                    blueADCChamp                      blueSupport 
                               0                               37 
                blueSupportChamp                           redTop 
                               0                               37 
                     redTopChamp                        redJungle 
                               0                               24 
                  redJungleChamp                        redMiddle 
                               0                               37 
                  redMiddleChamp                           redADC 
                               0                               37 
                     redADCChamp                       redSupport 
                               0                               37 
                 redSupportChamp                          Address 
                               0                                0 
                           min_1                            min_2 
                               0                                0 
                           min_3                            min_4 
                               0                                0 
                           min_5                            min_6 
                               0                                0 
                           min_7                            min_8 
                               0                                0 
                           min_9                           min_10 
                               0                                0 
                          min_11                           min_12 
                               0                                0 
                          min_13                           min_14 
                               0                                0 
                          min_15                           min_16 
                               0                                0 
                          min_17                           min_18 
                               0                                1 
                          min_19                           min_20 
                               3                                4 
Golddiff_change_from_min10_min20 
                               4 
sapply(League_data,function(x) sum(is.infinite(x))) 
                          League                             Year 
                               0                                0 
                          Season                        Game_Type 
                               0                                0 
                     blueTeamTag                          bResult 
                               0                                0 
                         rResult                       redTeamTag 
                               0                                0 
                      gamelength                          blueTop 
                               0                                0 
                    blueTopChamp                       blueJungle 
                               0                                0 
                 blueJungleChamp                       blueMiddle 
                               0                                0 
                 blueMiddleChamp                          blueADC 
                               0                                0 
                    blueADCChamp                      blueSupport 
                               0                                0 
                blueSupportChamp                           redTop 
                               0                                0 
                     redTopChamp                        redJungle 
                               0                                0 
                  redJungleChamp                        redMiddle 
                               0                                0 
                  redMiddleChamp                           redADC 
                               0                                0 
                     redADCChamp                       redSupport 
                               0                                0 
                 redSupportChamp                          Address 
                               0                                0 
                           min_1                            min_2 
                               0                                0 
                           min_3                            min_4 
                               0                                0 
                           min_5                            min_6 
                               0                                0 
                           min_7                            min_8 
                               0                                0 
                           min_9                           min_10 
                               0                                0 
                          min_11                           min_12 
                               0                                0 
                          min_13                           min_14 
                               0                                0 
                          min_15                           min_16 
                               0                                0 
                          min_17                           min_18 
                               0                                0 
                          min_19                           min_20 
                               0                                0 
Golddiff_change_from_min10_min20 
                               0 
sapply(League_data,function(x) sum(is.nan(x)))
                          League                             Year 
                               0                                0 
                          Season                        Game_Type 
                               0                                0 
                     blueTeamTag                          bResult 
                               0                                0 
                         rResult                       redTeamTag 
                               0                                0 
                      gamelength                          blueTop 
                               0                                0 
                    blueTopChamp                       blueJungle 
                               0                                0 
                 blueJungleChamp                       blueMiddle 
                               0                                0 
                 blueMiddleChamp                          blueADC 
                               0                                0 
                    blueADCChamp                      blueSupport 
                               0                                0 
                blueSupportChamp                           redTop 
                               0                                0 
                     redTopChamp                        redJungle 
                               0                                0 
                  redJungleChamp                        redMiddle 
                               0                                0 
                  redMiddleChamp                           redADC 
                               0                                0 
                     redADCChamp                       redSupport 
                               0                                0 
                 redSupportChamp                          Address 
                               0                                0 
                           min_1                            min_2 
                               0                                0 
                           min_3                            min_4 
                               0                                0 
                           min_5                            min_6 
                               0                                0 
                           min_7                            min_8 
                               0                                0 
                           min_9                           min_10 
                               0                                0 
                          min_11                           min_12 
                               0                                0 
                          min_13                           min_14 
                               0                                0 
                          min_15                           min_16 
                               0                                0 
                          min_17                           min_18 
                               0                                0 
                          min_19                           min_20 
                               0                                0 
Golddiff_change_from_min10_min20 
                               0 
# This is the R chunk for the Scan I
League_data <- na.omit(League_data)
sum(is.na(League_data))
[1] 0
Rule1 <- editset(c("min_1 <= 2000", "min_2 <=4000","min_3 <= 6000","min_4 <= 8000","min_5 <=10000", "min_6 <= 10000", "min_7 <= 15000", "min_8 <=20000","min_9 <= 20000","min_10 <= 20000", "min_11 <=20000","min_12 <= 30000","min_13 <= 30000", "min_14 <=30000","min_15 <= 30000", "min_16 <= 40000", "min_17 <=50000","min_18 <= 50000", "min_19 <=50000","min_20 <= 50000"))
Rule2 <-editset(c("min_1 >= -3000", "min_2 >= -6000","min_3 >= -8000","min_4 >= -8000","min_5 >= -10000", "min_6 >= -10000", "min_7 >= -15000", "min_8 >= -20000","min_9 >= -20000","min_10 >= -20000", "min_11 >= -20000","min_12 >= -30000","min_13 >= -30000", "min_14 >= -30000","min_15 >= -30000", "min_16 >= -40000", "min_17 >=  -50000","min_18 >= -50000", "min_19 >= -50000","min_20 >= -50000"))
Rule3  <- editset(c("gamelength  <=100"))
violatedEdits(Rule1, League_data) %>% summary()
No violations detected, 0 checks evaluated to NA
NULL
violatedEdits(Rule2, League_data) %>% summary()
No violations detected, 0 checks evaluated to NA
NULL
violatedEdits(Rule3, League_data) %>% summary()
No violations detected, 0 checks evaluated to NA
NULL

Scan II

The created variable of “Golddiff_change_from_min10_min20” was scanned for outliers. The variable was plotted on in a box plot and a histogram. The box plot showed outliers at both the lower end and high end of the data. The histogram showed approximately normal distribution. Therefore z.scores can be used to exclude the outliers. This methodology was applied and 53 outliers were removed from the data set.

The “gamelength” variable was also scanned for outliers. The variable was plotted on a box plot and histogram. The box plot showed that there were outliers on the high end of the data. The histogram doesn’t show a normally distributed data set, rather it is right-skewed. Therefore z.scores are not appropriate for excluding outliers. Chi-square Q-Q plot method was attempted but the data set was greater than 5000 observations so was unable to run. Therefore outliers were not excluded.

# This is the R chunk for the Scan II

League_data$Golddiff_change_from_min10_min20 %>% boxplot(main= "Box Plot of Gold Diff Change from 10 mins to 20 mins", ylab= "Gold", col = "grey")

hist(League_data$Golddiff_change_from_min10_min20)

z.scores <- League_data$Golddiff_change_from_min10_min20 %>% scores(type = "z")
z.scores %>% summary()
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
-4.631499 -0.634183 -0.001472  0.000000  0.642287  4.534876 
length (which( abs(z.scores) >3 ))
[1] 52
Golddiff_change_from_min10_min20_clean <- League_data$Golddiff_change_from_min10_min20 [ - which( abs(z.scores) >3 )]
hist(Golddiff_change_from_min10_min20_clean)


League_data$gamelength %>% boxplot(main= "Box Plot of Game Length", ylab= "Game Length", col = "grey")

hist(League_data$gamelength)

Transform

From the previous step we know that the “gamelength” variable is right-skewed. We applied logarithmic transformations to the “gamelength” distribution to attempt to make it more symmetrical.

Applying log10(), log(), sqrt all improve the symmetry of “gamelength” making it more normally distributed. Normal distribution is preferred for statistical inference,therefore transforming the data is helpful for analysis.

# This is the R chunk for the Transform Section
hist(League_data$gamelength)


log_gamelength <- log10(League_data$gamelength)
hist(log_gamelength)


ln_gamelength <- log(League_data$gamelength)
hist(ln_gamelength)


sqrt_gamelength <- sqrt(League_data$gamelength)
hist(sqrt_gamelength)

LS0tCnRpdGxlOiAiTUFUSDIzNDkgRGF0YSBXcmFuZ2xpbmciCmF1dGhvcjogIkJhcnQgTGV3aXMgKHMzODcyNTQ5KSIKc3VidGl0bGU6IEFzc2lnbm1lbnQgMgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgojIyBSZXF1aXJlZCBwYWNrYWdlcyAKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSByZXF1aXJlZCBwYWNrYWdlcwpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHRpZHlyKSAKbGlicmFyeShkcGx5cikgCmxpYnJhcnkoZ2dwbG90MikgCmxpYnJhcnkob3V0bGllcnMpCmxpYnJhcnkoZWRpdHJ1bGVzKQpsaWJyYXJ5KE1WTikKYGBgCiMjIEV4ZWN1dGl2ZSBTdW1tYXJ5IAoKSW4gb3JkZXIgdG8gcHJlcGFyZSB0aGUgYW5hbHlzaXMgb2YgQ29tcGV0aXRpdmUgTGVhZ3VlIG9mIExlZ2VuZCBNYXRjaGVzIHR3byBkYXRhIHNldHMgaGF2ZSBiZWVuIGltcG9ydGVkIGludG8gUi4gVGhlIHR3byBkYXRhIHNldHMgaGF2ZSB2YXJpb3VzIHZhcmlhYmxlcyBjb2xsZWN0ZWQgYWJvdXQgdGhlIExlZ2F1ZSBNYXRjaGVzLiBUaGUgRGF0YSBzZWN0aW9uIG91dGxpbmVzIHdoYXQgdGhlc2UgdmFyaWFibGVzIGFyZSBhbmQgd2hhdCB0eXBlcyBvZiB2YXJpYWJsZXMgdGhleSBhcmUgaS5lLiBjaGFyYWN0ZXIsIG51bWVyaWNhbC4gT25lIG9mIHRoZSBkYXRhIHNldHMgImdvbGRfbWF0Y2hlcyIgaXMgbGVmdCBqb2luZWQgb250byAiTGVhZ3VlX01hdGNoZXMiIHRvIGNyZWF0ZSBMZWFndWVfZGF0YSB3aGljaCB3YXMgam9pbmVkIHRocm91Z2ggdGhlIHZhcmlhYmxlICJBZGRyZXNzIi4gVGhlIG5ldyBkYXRhIHNldCBpcyB0aGVuIGNoZWNrZWQgZm9yIGFueSBvYnZpb3VzICBlcnJvcnMuICAKCkluIHRoZSBVbmRlcnN0YW5kIFNlY3Rpb24gTGVhZ3VlX2RhdGEgaXMgY2hlY2tlZCBmb3IgYW55IGluY29ycmVjdGx5IGNhdGVnb3JpemVkIHZhcmlhYmxlcy4gTWFueSBvZiB0aGUgdmFyaWFibGVzIHdlcmUgY29udmVydGVkIHRvIGZyb20gY2hhcmFjdGVycyB0byBmYWN0b3JzIGFzIHRoZXkgd2VyZSBpbmNvcnJlY3RseSByZWFkIGFzIGNoYXJhY3RlcnMuCgpMZWFndWVfZGF0YSB3YXMgdGhlbiB0aWRpZWQgYW5kIG1hbmlwdWxhdGVkLiBGaXJzdGx5IHRoZSBTZWFzb25fVHlwZSBjb2x1bW4gd2FzIHNlcGFyYXRlZCBhcyBpbnRvIHR3byBjb2x1bW5zIGFzIGl0IGNvbnRhaW5lZCB0d28gdmFyaWFibGVzLiBTZWNvbmRseSwgYSBjb2x1bW4gd2FzIHJlbW92ZWQgYXMgaXQgZGlkbid0IGNvbnRhaW4gYSB2YXJpYWJsZSBhbmQgbGFzdGx5LCBhIG5ldyB2YXJpYWJsZSB3YXMgY3JlYXRlZCBmcm9tIDIgdmFyaWFibGVzOiAiR29sZGRpZmZfY2hhbmdlX2Zyb21fbWluMTBfbWluMjAiIHdhcyBjcmVhdGVkIGZyb20gdGhlIHZhcmlhYmxlIG1pbl8xMCBhbmQgbWluXzIwLiAKCkxlYWd1ZV9kYXRhIHdhcyB0aGVuIHNjYW5uZWQuIEZpcnN0bHksIGZvciBtaXNzaW5nIHZhbHVlcywgc3BlY2lhbCB2YWx1ZXMgYW5kIG9idmlvdXMgZXJyb3JzL2luY29uc2lzdGVuY2llcy4gSXQgd2FzIGZvdW5kIHRoYXQgdGhlcmUgd2VyZSA0MzUgbWlzc2luZyB2YWx1ZXMsIHdoaWNoIHdlcmUgZXhjbHVkZWQgYXMgdGhleSBtYWRlIHVwIGEgc21hbGwgcGVyY2VudGFnZSBvZiB0aGUgZGF0YSBzZXQuIE5vIHNwZWNpYWwgdmFsdWVzIG9yIG9idmlvdXMgZXJyb3JzL2luY29uc2lzdGVuY2llcyB3ZXJlIGZvdW5kLiAKClNlY29uZGx5LCB0aGUgZGF0YSBzZXQgd2FzIHNjYW5uZWQgZm9yIGFueSBvdXRsaWVycy4gdGhlIHZhcmlhYmxlICAiR29sZGRpZmZfY2hhbmdlX2Zyb21fbWluMTBfbWluMjAiIHdhcyBmb3VuZCB0byBoYXZlIG91dGxpZXJzIHdoaWNoIHdlcmUgcmVtb3ZlZCB1c2luZyB0aGUgZnVuY3Rpb24gei5zY29yZXMoKS4gCgpMYXN0bHksIHRoZSB2YXJpYWJsZSAiZ2FtZWxlbmd0aCIgd2FzICB0cmFuc2Zvcm1lZCB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZCB1c2luZyBsb2dhcml0aG1pYyB0cmFuc2Zvcm1hdGlvbnMgYXMgaXQgaXMgcHJlZmVycmVkIGZvciBzdGF0aXN0aWNhbCBpbmZlcmVuY2UuIAoKCiMjIERhdGEgCgpUd28gZGF0YXNldHMgIkxlYWd1ZV9NYXRjaGVzIiBhbmQg4oCcR29sZF9tYXRjaGVz4oCdIGJvdGggY29sbGVjdGVkIGRhdGEgZnJvbSBjb21wZXRpdGl2ZSBMZWFndWUgb2YgTGVnZW5kcyBNYXRjaGVzIGZyb20gMjAxNSB0byAyMDE4LiBMZWFndWVfTWF0Y2hlcyBoYXMgYm90aCBudW1lcmljIGFuZCBxdWFsaXRhdGl2ZSB2YXJpYWJsZXMgYWJvdXQgdGhlIGdhbWVzIHBsYXllZCBpbmNsdWRpbmcsIHRoZSByZXN1bHQsIGdhbWUgbGVuZ3RoLCB0ZWFtIG5hbWVzLCB0aGUgcGxheWVycywgYW5kIGNoYW1waW9ucyBwaWNrZWQuIFRoZSBkYXRhIHNldCAiR29sZF9NYXRjaGVzIGFsc28gaGFzIGJvdGggcXVhbGl0YXRpdmUgYW5kIG51bWVyaWMgdmFyaWFibGVzIGNvbGxlY3RlZCBhYm91dCB0aGUgZGlmZmVyZW5jZSBpbiBnb2xkIGZyb20gZmlyc3QgbWludXRlIHRvIHRoZSAyMHRoIG1pbnV0ZSBvZiB0aGUgY29tcGV0aXRpdmUgTGVhZ3VlIG9mIExlZ2VuZCBNYXRjaGVzLiAKCkxlYWd1ZV9NYXRjaGVzIGhhcyAyOSB2YXJpYWJsZXMgYW5kIDc2MjAgb2JzZXJ2YXRpb25zLiAgRXhhbXBsZSBvZiB0aGUgRGVmaW5pdGlvbnMvZGV0YWlscwpvZiB0aGVzZSB2YXJpYWJsZXMgYXJlIGdpdmVuIGJlbG93OgoKTGVhZ3VlOiBUaGUgbGVhZ3VlIGluIHdoaWNoIHRoZSBnYW1lIHdhcyBwbGF5ZWQuIGkuZS4gTm9ydGggQW1lcmljYW4gbGVhZ3VlIChOQUxDUykgCgpZZWFyOiBZZWFyIHRoZSBnYW1lIHdhcyBwbGF5ZWQKClNlYXNvbl9UeXBlOiBXaGljaCBzZWFzb24gYW5kIHdoYXQgdHlwZSBvZiBnYW1lIGl0IHdhcyBpLmUuIHNlYXNvbiBtYXRjaCBvciBmaW5hbCAKCmJsdWVUZWFtVGFnOiBCbHVlIHNpZGUgdGVhbSBuYW1lCgpiUmVzdWx0OiBSZXN1bHQgZm9yIEJsdWUgdGVhbSAKCnJSZXN1bHQ6IFJlc3VsdCBmb3IgUmVkIHRlYW0KClJlZFRlYW1UYWc6IFJlZCBTaWRlIHRlYW0gbmFtZSAKCmdhbWVsZW5ndGg6IEhvdyBsb25nIHRoZSBnYW1lIGxhc3RlZCAKCkJsdWVUb3A6IFBsYXllciB3aG8gcGxheWVkIHRvcCBmb3IgQmx1ZSB0ZWFtIAoKQmx1ZVRvcENoYW1wOiBDaGFtcGlvbiBwbGF5ZWQgdG9wIGJ5IHRoZSBCbHVlIHRlYW0gCgpCbHVlSnVuZ2xlcjogUGxheWVyIHdobyBwbGF5ZWQgdG9wIGZvciBCbHVlIHRlYW0gCgpCbHVlSnVuZ2xlckNoYW1wIENoYW1waW9uIHBsYXllZCBqdW5nbGUgYnkgdGhlIEJsdWUgdGVhbSAKCkJsdWVNaWRkbGU6IFBsYXllciB3aG8gcGxheWVkIG1pZCBmb3IgdGhlIEJsdWUgdGVhbQoKQmx1ZU1pZGRsZUNoYW1wOiBDaGFtcGlvbiBwbGF5ZWQgbWlkIGJ5IHRoZSBCbHVlIHRlYW0gCgpCbHVlQURDOiBQbGF5ZXIgd2hvIHBsYXllZCBBREMgZm9yIHRoZSBCbHVlIHRlYW0gCgpCbHVlQURDQ2hhbXA6IENoYW1waW9uIHBsYXllZCBBREMgYnkgdGhlIEJsdWUgdGVhbQoKQmx1ZVN1cHBvcnQ6IFBsYXllciB3aG8gcGxheWVkIHN1cHBvcnQgZm9yIHRoZSBCbHVlIHRlYW0gCgpCbHVlU3VwcG9ydENoYW1waW9uOiBDaGFtcGlvbiBwbGF5ZWQgc3VwcG9ydCBieSB0aGUgQmx1ZSB0ZWFtIAoKUG9zaXRpb24oaS5lIFN1cHBvcnQpIGFuZCBDaGFtcGlvbiB2YXJpYWJsZSByZXBlYXRlZCBmb3IgdGhlIFJlZCB0ZWFtLiAKV2Vic2l0ZSBVcmw6IGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vY2h1Y2tlcGhyb24vbGVhZ3Vlb2ZsZWdlbmRzCgpHb2xkX21hdGNoZXMgaGFzIDIyIHZhcmlhYmxlcyBhbmQgNzYyMCBvYnNlcnZhdGlvbnMuICBFeGFtcGxlcyBvZiB0aGUgRGVmaW5pdGlvbnMvZGV0YWlscwpvZiB0aGVzZSB2YXJpYWJsZXMgYXJlIGdpdmVuIGJlbG93OgoKQWRkcmVzczogdGhlIG1hdGNoIFVSTCB0aGUgb2ZmaWNhbCBMZWFndWUgb2YgTGVnZW5kcyBtYXRjaCBoaXN0b3J5IHNpdGUuIAoKVHlwZTogVGhlIGdvbGQgdHlwZQoKbWluXzE6IEdvbGQgZGlmZmVyZW5jZSBhdCAxIG1pbnV0ZQoKbWluXzI6IEdvbGQgZGlmZmVyZW5jZSBhdCAyIG1pbnV0ZXMKCm1pbl8zIEdvbGQgZGlmZmVyZW5jZSBhdCAzIG1pbnV0ZXMgCgp1cCB0byBtaW5fMjA6IEdvbGQgRGlmZmVyZW5jZSBhdCAyMCBtaW51dGVzCgpXZWJzaXRlIFVybDogaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9jaHVja2VwaHJvbi9sZWFndWVvZmxlZ2VuZHMKCkxlYWd1ZV9NYXRjaGVzIGFuZCBnb2xkX21hdGNoZXMgY3N2cyBhcmUgaW1wb3J0ZWQsIGhlYWRzIGNoZWNrZWQgZm9yIGFueSBvYnZpb3VzIGlzc3Vlcy4gR29sZF9tYXRjaGVzIGlzIGxlZnRfam9pbmVkIG9udG8gTGVhZ3VlX01hdGNoZXMgYnkgIkFkZHJlc3MiLiAKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBEYXRhIFNlY3Rpb24KTGVhZ3VlX01hdGNoZXMgPC0gcmVhZF9jc3YoIn4vUGljdHVyZXMvR3JhZCBDZXJ0L0xlYWd1ZSBNYXRjaGVzLmNzdiIpCmdvbGRfbWF0Y2hlcyA8LSByZWFkX2Nzdigifi9QaWN0dXJlcy9HcmFkIENlcnQvZ29sZCBtYXRjaGVzLmNzdiIpCmhlYWQoTGVhZ3VlX01hdGNoZXMpCmhlYWQoZ29sZF9tYXRjaGVzKQoKTGVhZ3VlX2RhdGEgPC0gTGVhZ3VlX01hdGNoZXMgJT4lIGxlZnRfam9pbihnb2xkX21hdGNoZXMsYnkgPSAiQWRkcmVzcyIpCmhlYWQoTGVhZ3VlX2RhdGEpCmBgYAojIyBVbmRlcnN0YW5kIAoKQ2hlY2tlZCB0aGUgZGltZW5zaW9ucyBvZiB0aGUgTGVhZ3VlX2RhdGEgZGF0YSBmcmFtZSwgNzYyMCBvYnNlcnZhdGlvbnMsIDUwIHZhcmlhYmxlcy4gT2YgdGhlIDUwIHZhcmlhYmxlcywgMjYgYXJlIGN1cnJlbnRseSByZWFkIGFzIGNoYXJhY3RlcnMgYW5kIDI0IGFzIGRvdWJsZXMvbnVtZXJpYy4gYlJlc3VsdCBhbmQgclJlc3VsdCBzaG91bGQgYmUgY29udmVydGVkIGludG8gYSBmYWN0b3IgdmFyaWFibGUgYW5kIHJlbGFiZWxlZCAiV2luIiBhbmQgIkxvc3MiIHdpdGggV2luIG9yZGVyZWQgaGlnaGVyIHRoYW4gbG9zcy4gTGVhZ3VlLCBZZWFyLCBTZWFzb24gVHlwZSwgYmx1ZVRlYW1UYWcgYW5kIHJlZFRlYW1UYWcgc2hvdWxkIGFsc28gYmUgY29udmVydGVkIHRvIGZhY3RvcnMuIFRoaXMgaXMgZG9uZSB3aXRoIHRoZSB1c2Ugb2YgdGhlIGFzLmZhY3RvciBmdW5jdGlvbi4KCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBVbmRlcnN0YW5kIFNlY3Rpb24KCkxlYWd1ZV9kYXRhJGJSZXN1bHQgPC0gYXMuZmFjdG9yKExlYWd1ZV9kYXRhJGJSZXN1bHQpCkxlYWd1ZV9kYXRhJGJSZXN1bHQgPC0gTGVhZ3VlX2RhdGEkYlJlc3VsdCAlPiUgZmFjdG9yKGxldmVscyA9IGMoIjEiLCIwIiksIG9yZGVyID0gVFJVRSwgbGFiZWxzPWMgKCJXaW4iLCJMb3NzIikpCgpMZWFndWVfZGF0YSRyUmVzdWx0IDwtIGFzLmZhY3RvcihMZWFndWVfZGF0YSRyUmVzdWx0KQpMZWFndWVfZGF0YSRyUmVzdWx0IDwtIExlYWd1ZV9kYXRhJHJSZXN1bHQgJT4lIGZhY3RvcihsZXZlbHMgPSBjKCIxIiwiMCIpLCBvcmRlciA9IFRSVUUsIGxhYmVscz0gYygiV2luIiwiTG9zcyIpKQoKCkxlYWd1ZV9kYXRhJExlYWd1ZSA8LSBhcy5mYWN0b3IoTGVhZ3VlX2RhdGEkTGVhZ3VlKQpMZWFndWVfZGF0YSRZZWFyIDwtIGFzLmZhY3RvcihMZWFndWVfZGF0YSRZZWFyKQpMZWFndWVfZGF0YSRTZWFzb25fVHlwZSA8LSBhcy5mYWN0b3IoTGVhZ3VlX2RhdGEkU2Vhc29uX1R5cGUpCkxlYWd1ZV9kYXRhJGJsdWVUZWFtVGFnIDwtIGFzLmZhY3RvcihMZWFndWVfZGF0YSRibHVlVGVhbVRhZykKTGVhZ3VlX2RhdGEkcmVkVGVhbVRhZyA8LSBhcy5mYWN0b3IoTGVhZ3VlX2RhdGEkcmVkVGVhbVRhZykKCmhlYWQoTGVhZ3VlX2RhdGEpCmBgYAojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgCgpUd28gdmFyaWFibGVzIHdlcmUga2VwdCBpbiB0aGUgIlNlYXNvbl9UeXBlIiBjb2x1bW4gbWFraW5nIHRoZSBkYXRhIGZyYW1lIHVudGlkeS4gV2hldGhlciB0aGUgZ2FtZSBpcyBwbGF5ZWQgaW4gdGhlICJTdW1tZXIiIG9yICJTcHJpbmciICB3YXMgaW4gdGhlIHNhbWUgY29sdW1uIGFzIHdoZXRoZXIgdGhlIGdhbWUgd2FzIGEgIlNlYXNvbiIgZ2FtZSBvciBhICJQbGF5b2ZmIiBnYW1lLiBUaGVyZWZvcmUgdGhlIHNlcGFyYXRlIGZ1bmN0aW9uIHdhcyB1c2VkIHRvIHRpZHkgdGhlIGRhdGEgYW5kIGhhdmUgdGhlIHZhcmlhYmxlcyBzZXBhcmF0ZWQgaW50byB0d28gZGlmZmVyZW50IGNvbHVtbnMuIAoKIlR5cGUiIHZhcmlhYmxlIHdhcyBhbHNvIHJlbW92ZWQgZnJvbSB0aGUgZGF0YSBzZXQgYXMgaXQgd2FzIG5vdCBhIHZhcmlhYmxlIGFzIGFsbCBvYnNlcnZhdGlvbnMgY29udGFpbmVkIHRoZSBzYW1lIG9ic2VydmF0aW9uICJnb2xkZGlmZiIuICAKCgpgYGB7cn0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJIApMZWFndWVfZGF0YSA8LSBMZWFndWVfZGF0YSAlPiUgc2VwYXJhdGUoU2Vhc29uX1R5cGUsIGludG8gPSBjKCJTZWFzb24iLCJHYW1lX1R5cGUiKSxzZXAgPSAiICIpCkxlYWd1ZV9kYXRhIDwtIExlYWd1ZV9kYXRhICU+JSBzZWxlY3QgKC1UeXBlKQpMZWFndWVfZGF0YSRHYW1lX1R5cGUgPC0gYXMuZmFjdG9yKExlYWd1ZV9kYXRhJEdhbWVfVHlwZSkKTGVhZ3VlX2RhdGEkU2Vhc29uIDwtIGFzLmZhY3RvcihMZWFndWVfZGF0YSRTZWFzb24pCmhlYWQoTGVhZ3VlX2RhdGEpCmBgYAojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJIAoKQ3JlYXRlZCBhIG5ldyB2YXJpYWJsZSBmcm9tIHRoZSBtaW5fMTAgYW5kIG1pbl8yMCB2YXJpYWJsZSBzaG93aW5nIHRoZSBjaGFuZ2UgaW4gdGhlIGdvbGQgbGVhZCBmcm9tIDEwIG1pbnMgdG8gMjAgbWlucyBpbnRvIHRoZSBnYW1lLiBUaGUgbXV0YXRlIGZ1bmN0aW9uIHdhcyB1c2VkIHRvIGNyZWF0ZSB0aGlzIGFuZCB3aWxsIGFsbG93IGZvciBlYXNpZXIgYW5hbHlzaXMgb2YgaG93IHRoZSBnb2xkIGxlYWQgY2hhbmdlcyBmcm9tIGVhcmxpZXIgaW4gdGhlIGdhbWUgdG8gbGF0ZXIgaW4gdGhlIGdhbWUuIAoKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJIApMZWFndWVfZGF0YSA8LSBtdXRhdGUoTGVhZ3VlX2RhdGEsIEdvbGRkaWZmX2NoYW5nZV9mcm9tX21pbjEwX21pbjIwID0gbWluXzIwIC0gbWluXzEwKQpgYGAKCiMjCVNjYW4gSSAKClRoZSBkYXRhIHdhcyBzY2FubmVkIGZvciBtaXNzaW5nIHZhbHVlcywgc3BlY2lhbCB2YWx1ZXMgYW5kIG9idmlvdXMgZXJyb3JzIGFuZCBpbmNvbnNpc3RlbmNpZXMuIAoKU2Nhbm5pbmcgIGZvciBtaXNzbmcgdmFyaWFibGVzIHNob3dlZCB0aGF0IHRoZXJlIDQzNSBtaXNzaW5nIHZhbHVlcy4gVGhlc2UgdmFsdWVzICBwcmltYXJpbHkgIG9jY3VyZWQgaW4gIDM4IHJvd3MgIG9mIHRoZSAgZGF0YSBzZXQgYW5kIHdlcmUgc3ViIDUlIG9mIHRoZSBkYXRhIHNldC4gU28gaXQgd2FzIGRlY2lkZWQgdGhhdCBpdCB3YXMgdGhlIGJlc3Qgc3RyYXRlcmd5IHRvIGxlYXZlIG91dCB0aGUgdmFsdWVzIHdpdGggbWlzc2luZyBmZWF0dXJlcyBpbiBvcmRlciBub3QgdG8gYmlhcyB0aGUgYW5hbHlzaXMuCgpUaGUgZGF0YSB3YXMgc2Nhbm5lZCBmb3Igc3BlY2lhbCB2YWx1ZXMgdXNpbmcgaXMuaW5maW5pdGUoKSBhbmQgaXMubmFuKCkgbm8gdmFsdWVzIHdlcmUgZm91bmQuCgpUaGUgZ29sZCBkaWZmZXJlbmNlIHZhcmlhYmxlcyAoaS5lLiBtaW5fMSwgbWluXzIpIGFuZCAiZ2FtZWxlbmd0aCIgdmFyaWFibGUgIHdlcmUgYWxzbyBzY2FubmVkIGZvciBhbnkgb2J2aW91cyBlcnJvcnMgb3IgaW5jb25zaXN0ZW5jaWVzLiBJdCAgd2FzICBmb3VuZCAgdGhhdCB0aGVyZSAgd2VyZSBubyBlcnJvcnMgb3IgaW5jb25zaXN0ZW5jaWVzLiAgIAoKCgpgYGB7cn0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgU2NhbiBJCnN1bShpcy5uYShMZWFndWVfZGF0YSkpCmNvbFN1bXMoaXMubmEoTGVhZ3VlX2RhdGEpKQpzYXBwbHkoTGVhZ3VlX2RhdGEsZnVuY3Rpb24oeCkgc3VtKGlzLmluZmluaXRlKHgpKSkgCnNhcHBseShMZWFndWVfZGF0YSxmdW5jdGlvbih4KSBzdW0oaXMubmFuKHgpKSkKYGBgCgpgYGB7cn0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgU2NhbiBJCkxlYWd1ZV9kYXRhIDwtIG5hLm9taXQoTGVhZ3VlX2RhdGEpCnN1bShpcy5uYShMZWFndWVfZGF0YSkpClJ1bGUxIDwtIGVkaXRzZXQoYygibWluXzEgPD0gMjAwMCIsICJtaW5fMiA8PTQwMDAiLCJtaW5fMyA8PSA2MDAwIiwibWluXzQgPD0gODAwMCIsIm1pbl81IDw9MTAwMDAiLCAibWluXzYgPD0gMTAwMDAiLCAibWluXzcgPD0gMTUwMDAiLCAibWluXzggPD0yMDAwMCIsIm1pbl85IDw9IDIwMDAwIiwibWluXzEwIDw9IDIwMDAwIiwgIm1pbl8xMSA8PTIwMDAwIiwibWluXzEyIDw9IDMwMDAwIiwibWluXzEzIDw9IDMwMDAwIiwgIm1pbl8xNCA8PTMwMDAwIiwibWluXzE1IDw9IDMwMDAwIiwgIm1pbl8xNiA8PSA0MDAwMCIsICJtaW5fMTcgPD01MDAwMCIsIm1pbl8xOCA8PSA1MDAwMCIsICJtaW5fMTkgPD01MDAwMCIsIm1pbl8yMCA8PSA1MDAwMCIpKQpSdWxlMiA8LWVkaXRzZXQoYygibWluXzEgPj0gLTMwMDAiLCAibWluXzIgPj0gLTYwMDAiLCJtaW5fMyA+PSAtODAwMCIsIm1pbl80ID49IC04MDAwIiwibWluXzUgPj0gLTEwMDAwIiwgIm1pbl82ID49IC0xMDAwMCIsICJtaW5fNyA+PSAtMTUwMDAiLCAibWluXzggPj0gLTIwMDAwIiwibWluXzkgPj0gLTIwMDAwIiwibWluXzEwID49IC0yMDAwMCIsICJtaW5fMTEgPj0gLTIwMDAwIiwibWluXzEyID49IC0zMDAwMCIsIm1pbl8xMyA+PSAtMzAwMDAiLCAibWluXzE0ID49IC0zMDAwMCIsIm1pbl8xNSA+PSAtMzAwMDAiLCAibWluXzE2ID49IC00MDAwMCIsICJtaW5fMTcgPj0gIC01MDAwMCIsIm1pbl8xOCA+PSAtNTAwMDAiLCAibWluXzE5ID49IC01MDAwMCIsIm1pbl8yMCA+PSAtNTAwMDAiKSkKUnVsZTMgIDwtIGVkaXRzZXQoYygiZ2FtZWxlbmd0aCAgPD0xMDAiKSkKdmlvbGF0ZWRFZGl0cyhSdWxlMSwgTGVhZ3VlX2RhdGEpICU+JSBzdW1tYXJ5KCkKdmlvbGF0ZWRFZGl0cyhSdWxlMiwgTGVhZ3VlX2RhdGEpICU+JSBzdW1tYXJ5KCkKdmlvbGF0ZWRFZGl0cyhSdWxlMywgTGVhZ3VlX2RhdGEpICU+JSBzdW1tYXJ5KCkKYGBgCgojIwlTY2FuIElJCgpUaGUgY3JlYXRlZCB2YXJpYWJsZSBvZiAiR29sZGRpZmZfY2hhbmdlX2Zyb21fbWluMTBfbWluMjAiIHdhcyAgc2Nhbm5lZCBmb3Igb3V0bGllcnMuIFRoZSB2YXJpYWJsZSB3YXMgcGxvdHRlZCBvbiBpbiBhICBib3ggcGxvdCBhbmQgYSBoaXN0b2dyYW0uIFRoZSBib3ggcGxvdCBzaG93ZWQgb3V0bGllcnMgYXQgYm90aCB0aGUgbG93ZXIgZW5kIGFuZCBoaWdoIGVuZCBvZiB0aGUgZGF0YS4gVGhlIGhpc3RvZ3JhbSBzaG93ZWQgYXBwcm94aW1hdGVseSBub3JtYWwgZGlzdHJpYnV0aW9uLiBUaGVyZWZvcmUgei5zY29yZXMgY2FuIGJlIHVzZWQgdG8gZXhjbHVkZSB0aGUgb3V0bGllcnMuIFRoaXMgbWV0aG9kb2xvZ3kgd2FzIGFwcGxpZWQgYW5kIDUzIG91dGxpZXJzIHdlcmUgcmVtb3ZlZCBmcm9tIHRoZSBkYXRhIHNldC4gCgpUaGUgImdhbWVsZW5ndGgiIHZhcmlhYmxlICB3YXMgYWxzbyBzY2FubmVkIGZvciBvdXRsaWVycy4gVGhlIHZhcmlhYmxlIHdhcyBwbG90dGVkIG9uIGEgYm94IHBsb3QgYW5kIGhpc3RvZ3JhbS4gVGhlIGJveCBwbG90IHNob3dlZCB0aGF0IHRoZXJlIHdlcmUgb3V0bGllcnMgb24gdGhlIGhpZ2ggZW5kIG9mIHRoZSBkYXRhLiBUaGUgaGlzdG9ncmFtIGRvZXNuJ3Qgc2hvdyBhIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGRhdGEgc2V0LCByYXRoZXIgaXQgaXMgcmlnaHQtc2tld2VkLiBUaGVyZWZvcmUgei5zY29yZXMgYXJlIG5vdCBhcHByb3ByaWF0ZSBmb3IgZXhjbHVkaW5nICBvdXRsaWVycy4gQ2hpLXNxdWFyZSBRLVEgcGxvdCBtZXRob2Qgd2FzIGF0dGVtcHRlZCAgYnV0IHRoZSBkYXRhIHNldCB3YXMgZ3JlYXRlciB0aGFuIDUwMDAgb2JzZXJ2YXRpb25zIHNvIHdhcyB1bmFibGUgdG8gcnVuLiBUaGVyZWZvcmUgb3V0bGllcnMgd2VyZSBub3QgZXhjbHVkZWQuICAKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBTY2FuIElJCgpMZWFndWVfZGF0YSRHb2xkZGlmZl9jaGFuZ2VfZnJvbV9taW4xMF9taW4yMCAlPiUgYm94cGxvdChtYWluPSAiQm94IFBsb3Qgb2YgR29sZCBEaWZmIENoYW5nZSBmcm9tIDEwIG1pbnMgdG8gMjAgbWlucyIsIHlsYWI9ICJHb2xkIiwgY29sID0gImdyZXkiKQpoaXN0KExlYWd1ZV9kYXRhJEdvbGRkaWZmX2NoYW5nZV9mcm9tX21pbjEwX21pbjIwKQp6LnNjb3JlcyA8LSBMZWFndWVfZGF0YSRHb2xkZGlmZl9jaGFuZ2VfZnJvbV9taW4xMF9taW4yMCAlPiUgc2NvcmVzKHR5cGUgPSAieiIpCnouc2NvcmVzICU+JSBzdW1tYXJ5KCkKbGVuZ3RoICh3aGljaCggYWJzKHouc2NvcmVzKSA+MyApKQpHb2xkZGlmZl9jaGFuZ2VfZnJvbV9taW4xMF9taW4yMF9jbGVhbiA8LSBMZWFndWVfZGF0YSRHb2xkZGlmZl9jaGFuZ2VfZnJvbV9taW4xMF9taW4yMCBbIC0gd2hpY2goIGFicyh6LnNjb3JlcykgPjMgKV0KaGlzdChHb2xkZGlmZl9jaGFuZ2VfZnJvbV9taW4xMF9taW4yMF9jbGVhbikKCkxlYWd1ZV9kYXRhJGdhbWVsZW5ndGggJT4lIGJveHBsb3QobWFpbj0gIkJveCBQbG90IG9mIEdhbWUgTGVuZ3RoIiwgeWxhYj0gIkdhbWUgTGVuZ3RoIiwgY29sID0gImdyZXkiKQpoaXN0KExlYWd1ZV9kYXRhJGdhbWVsZW5ndGgpCmBgYAojIwlUcmFuc2Zvcm0gCgoKRnJvbSB0aGUgcHJldmlvdXMgc3RlcCB3ZSBrbm93IHRoYXQgdGhlICJnYW1lbGVuZ3RoIiB2YXJpYWJsZSBpcyByaWdodC1za2V3ZWQuIFdlIGFwcGxpZWQgIGxvZ2FyaXRobWljIHRyYW5zZm9ybWF0aW9ucyB0byB0aGUgImdhbWVsZW5ndGgiIGRpc3RyaWJ1dGlvbiB0byBhdHRlbXB0IHRvIG1ha2UgaXQgbW9yZSAgc3ltbWV0cmljYWwuCgpBcHBseWluZyBsb2cxMCgpLCBsb2coKSwgc3FydCBhbGwgaW1wcm92ZSB0aGUgc3ltbWV0cnkgb2YgImdhbWVsZW5ndGgiIG1ha2luZyBpdCBtb3JlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBOb3JtYWwgZGlzdHJpYnV0aW9uIGlzIHByZWZlcnJlZCBmb3Igc3RhdGlzdGljYWwgaW5mZXJlbmNlLHRoZXJlZm9yZSB0cmFuc2Zvcm1pbmcgdGhlIGRhdGEgaXMgaGVscGZ1bCBmb3IgYW5hbHlzaXMuICAKCgpgYGB7cn0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgVHJhbnNmb3JtIFNlY3Rpb24KaGlzdChMZWFndWVfZGF0YSRnYW1lbGVuZ3RoKQoKbG9nX2dhbWVsZW5ndGggPC0gbG9nMTAoTGVhZ3VlX2RhdGEkZ2FtZWxlbmd0aCkKaGlzdChsb2dfZ2FtZWxlbmd0aCkKCmxuX2dhbWVsZW5ndGggPC0gbG9nKExlYWd1ZV9kYXRhJGdhbWVsZW5ndGgpCmhpc3QobG5fZ2FtZWxlbmd0aCkKCnNxcnRfZ2FtZWxlbmd0aCA8LSBzcXJ0KExlYWd1ZV9kYXRhJGdhbWVsZW5ndGgpCmhpc3Qoc3FydF9nYW1lbGVuZ3RoKQpgYGAK