Introduction

  • Olympic Weightlifting has been a part of the Summer Olympic Games since 1896. Athletes perform Clean-and-Jerk and Snatch, and they have three attempts to aim for lifting the heaviest weight. Prizes are given for the heaviest weights lifted in each lift and in the overall. The overall is the maximum lifts of both added. Women and men compete separately, and they are split up into different weight classes. In the following report, we will use statistical methods to research correlation between Snatch and Clean-and-Jerk, improvements in Olympic Weightlifting over a 20-year span and if bodyweight affects the athletes’ maximum weight lifted.

The Data

  • The dataset that is used is collected from Kaggle and is from the 2000 to 2020 Summer Olympics in Olympic Weightlifting. It includes 10 different columns and 1233 data points and each row represents a different athlete.
Weightlifting.data = read.csv("weightlifting.csv") # reading the data from csv excel file
attach(Weightlifting.data)

Cleaning up the data

# Getting rid of all rows that have -1 as their value in the numerical columns. Also getting rid of the URL column.

Lifting.data <- Weightlifting.data[ , -8] %>% 
  filter(Total..kg. != -1) %>% 
  filter(Bodyweight..kg. > 10)
str(Lifting.data)
## 'data.frame':    1233 obs. of  10 variables:
##  $ X                : int  0 1 2 3 4 5 6 7 8 9 ...
##  $ Athlete          : chr  "Halil Mutlu (TUR)" "Wu Wenxiong (CHN)" "Zhang Xiangxiang (CHN)" "Wang Shin-yuan (TPE)" ...
##  $ Bodyweight..kg.  : num  55.6 55.5 55.9 55.4 55.7 ...
##  $ Snatch..kg.      : num  138 125 125 125 120 ...
##  $ Clean...Jerk..kg.: num  168 162 162 160 155 ...
##  $ Total..kg.       : num  305 288 288 285 275 ...
##  $ Ranking          : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Title            : chr  "Weightlifting at the 2000 Summer Olympics – Men's 56 kg" "Weightlifting at the 2000 Summer Olympics – Men's 56 kg" "Weightlifting at the 2000 Summer Olympics – Men's 56 kg" "Weightlifting at the 2000 Summer Olympics – Men's 56 kg" ...
##  $ Year             : int  2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 ...
##  $ Gender           : chr  "Men" "Men" "Men" "Men" ...
detach(Weightlifting.data)
attach(Lifting.data)
Lifting.data <- Lifting.data %>% mutate(Title = as.factor(Lifting.data$Title), Year = as.factor(Lifting.data$Year), Gender = as.factor(Lifting.data$Gender))
  • Lifting.data will be the data frame used for this project.
head(Lifting.data)
Des <- data.frame(
  Column = c("X","Athlete", "Bodyweight", "Snatch", "Clean & Jerk", "Total", "Ranking", "Title", "Year", "Gender"),
  Type = c("Int", "Chr", "Num", "Num", "Num", "Num", "Int", "Fct", "Fct", "Fct"),
  Description = c(
    "Athletes id",
    "Name",
    "Athletes' bodyweight",
    "Maximum weight of Snatch",
    "Maximum weight of Clean&Jerk",
    "Maximum lifts of both added",
    "Athletes' placement",
    "Athletes' bodyweight class/category",
    "Olympic Year",
    "Men or Women"))

datatable(Des, rownames = FALSE, caption = 'Lifting.data description')
# Separating genders into two different data frames for further research

LiftingWomen <- Lifting.data %>% 
  filter(Gender == "Women")

LiftingMen <- Lifting.data %>% 
  filter(Gender == "Men")

EDA of the data

  • Filter the table as you wish
datatable(Lifting.data, 
          colnames = c('Bodyweight' = 3, 'Snatch' = 4, 'Clean&Jerk' = 5, 'Total' = 6), 
          rownames = FALSE, 
          filter="top", 
          options = list(pageLength = 5, scrollX=T, autoWidth = TRUE) )
  • Summary table separated by genders
Lifting.data %>% 
  group_by(Gender) %>% 
  summarise(count = n(), min = min(Total..kg.), 
            mean = mean(Total..kg.), sd = sd(Total..kg.), median = median(Total..kg.),
            max = max(Total..kg.))
  • Summary table separated by years for men only
Lifting.data %>% 
  group_by(Year) %>% 
  filter(Gender == "Men") %>% 
  summarise(count = n(), min = min(Total..kg.), 
            mean = mean(Total..kg.), sd = sd(Total..kg.), median = median(Total..kg.),
            max = max(Total..kg.))
  • Summary table separated by years for women only
Lifting.data %>% 
  group_by(Year) %>% 
  filter(Gender == "Women") %>% 
  summarise(count = n(), min = min(Total..kg.), 
            mean = mean(Total..kg.), sd = sd(Total..kg.), median = median(Total..kg.),
            max = max(Total..kg.))

Methods

  1. Testing for correlation between two variables
  • Linear Regression

    • Predicts the value of unknown data.
  • Variance Inflation Factor (VIF)

    • It is a measure for a method to detect whether multicollinearity is a problem in a model. A VIF of 5 or higher indicates that multicollinearity could be a problem (Multicollinearity).
  1. Predicting total weight
  • Linear Regression

    • Predicts the coefficients for a linear combination.
  1. Comparing variables in different groups
  • T-test

    • One sided Hypothesis testing

    • Compares the mean in two groups

  1. Contrast and Linear Combination Comparison
  • Analysis of Variance and Anova

    • Compares factored statistics
  • Contrast

    • Computes and test arbitrary contrasts for regression objects

Section 1

Testing for correlation between two variables

  • Are Clean-and-Jerk and Snatch correlated with one another?

Graphical Analysis

poinpl.w.20 <- LiftingWomen %>% 
  ggplot(aes(x = Clean...Jerk..kg., y = Snatch..kg., color = Total..kg.)) +
  geom_point() + geom_smooth(method = "lm") +
  scale_color_gradient(low="blue", high="red") +
  labs(fill = "Total Weight") +
  xlab("Clean & Jerk") +
  ylab("Snatch") +
  labs(subtitle = "Women") +
  theme_ipsum()

poinpl.w.00 <- LiftingMen %>% 
  ggplot(aes(x = Clean...Jerk..kg., y = Snatch..kg., color = Total..kg.)) +
  geom_point() + geom_smooth(method = "lm") +
  scale_color_gradient(low="blue", high="red") +
  labs(color = "Total Weight") +
  xlab("Clean & Jerk") +
  ylab("Snatch") +
  labs(subtitle = "Men") +
  theme_ipsum()

plot <- ggarrange(poinpl.w.00, poinpl.w.20,
                  common.legend = TRUE,
                  ncol = 2, nrow = 1, legend = "bottom")
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
annotate_figure(plot, top = text_grob("Clean & Jerk and Snatch Relationship", 
               color = "black", face = "bold", size = 14))

  • The scatterplots show the relationship between Clean-and-Jerk and Snatch in the Olympics in 2000 and 2020. For both men and women, the scatterplots represent a positive relationship with barely any outliers and indicate that higher intensity in Clean-and-Jerk increases your intensity in your Snatch.

Testing – Linear Regression and Multicollinearity

corr.lm = lm(Clean...Jerk..kg. ~ Snatch..kg., data = Lifting.data)
summary(corr.lm)
## 
## Call:
## lm(formula = Clean...Jerk..kg. ~ Snatch..kg., data = Lifting.data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -23.4084  -4.5620  -0.1226   4.1845  31.1899 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 9.997528   0.724687    13.8   <2e-16 ***
## Snatch..kg. 1.153572   0.005326   216.6   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 6.792 on 1231 degrees of freedom
## Multiple R-squared:  0.9744, Adjusted R-squared:  0.9744 
## F-statistic: 4.691e+04 on 1 and 1231 DF,  p-value: < 2.2e-16
vif = 1/(1-0.9744)
vif
## [1] 39.0625

Analysis

  • With a VIF value of 15 and R-squared as 0.93, we can assume that clean-and-Jerk and Snatch are correlated with each other. If an athlete has a heavy Clean-and-Jerk, we can assume that he also has a heavy Snatch.

  • These results also indicate that if we want to do further testing, we do not want to have both variables together in a regression model.

Further Research

  • The two lifts are very different from one another, and weightlifters must get comfortable with both lifting techniques if they are aspiring to compete. Clean-and-Jerk is about pure power while Snatch is about finesse. One of the biggest differences is how you pull the bar off the ground. In Snatch, you have to elevate the bar way higher than you have to for the Jerk. That means that you should be able to load significantly more weight onto your Clean-and-Jerk than onto your Snatch. Even though they are very different, both lifts have the same goal. It is to lift a loaded barbell from the ground to overhead. The correlation between them is that they train similar muscle categories which could explain that if you lift heavy in one lift, you lift heavy in the other (Dickson, The snatch vs. the Clean & Jerk: Pros and cons of the two Olympic lifts 2023).

Section 2

Predicting total weight

  • What is the linear combination to predict the total weight from the athlete using bodyweight, Gender, and Clean-and-Jerk or Snatch?

    • In the final regression model, does Clean-and-Jerk or Snatch fit better.

    • The exploratory variable is Total Weight and the Responce variable is Bodyweight, Gender and Clean-and-Jerk or Snatch.

Graphical analysis

Lifting.data %>% ggpairs(columns = 3:6, aes(color = Gender, alpha = 0.5), upper = list(continuous = wrap("cor", size = 2.5)))

  • As proven in the first section, Clean-and-Jerk and Snatch have a high correlation. The total score also has a high correlation with the two variables because the it is the sum of the both.

Testing - Linear Regression

Model with clean-and-Jerk

  • Testing the model with Clean-and-Jerk variable
clean.lm = lm(Total..kg. ~ Clean...Jerk..kg. + Bodyweight..kg. + Gender, data = Lifting.data)
summary(clean.lm)
## 
## Call:
## lm(formula = Total..kg. ~ Clean...Jerk..kg. + Bodyweight..kg. + 
##     Gender, data = Lifting.data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -25.4820  -3.5256  -0.1228   3.8385  21.0726 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -2.4400377  1.3364284  -1.826   0.0681 .  
## Clean...Jerk..kg.  1.8313704  0.0099139 184.728   <2e-16 ***
## Bodyweight..kg.    0.0008984  0.0104507   0.086   0.9315    
## GenderWomen       -1.4104495  0.6402219  -2.203   0.0278 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.809 on 1229 degrees of freedom
## Multiple R-squared:  0.9945, Adjusted R-squared:  0.9945 
## F-statistic: 7.466e+04 on 3 and 1229 DF,  p-value: < 2.2e-16
plot(clean.lm, which = 1)

Model with Snatch

  • Testing the model with Snatch variable
snatch.lm = lm(Total..kg. ~ Snatch..kg. + Bodyweight..kg. + Gender, data = Lifting.data)
summary(snatch.lm)
## 
## Call:
## lm(formula = Total..kg. ~ Snatch..kg. + Bodyweight..kg. + Gender, 
##     data = Lifting.data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -22.0683  -4.2852   0.0374   4.3012  29.0767 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     20.13082    1.36685  14.728   <2e-16 ***
## Snatch..kg.      2.02465    0.01220 165.995   <2e-16 ***
## Bodyweight..kg.  0.11906    0.01107  10.752   <2e-16 ***
## GenderWomen     -6.45724    0.68654  -9.406   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 6.437 on 1229 degrees of freedom
## Multiple R-squared:  0.9933, Adjusted R-squared:  0.9933 
## F-statistic: 6.071e+04 on 3 and 1229 DF,  p-value: < 2.2e-16
plot(snatch.lm, which = 1)

Transformed model

  • Testing the snatch model with transformed variables
log.snatch.lm = lm(log(Total..kg.) ~ log(Snatch..kg.) + Bodyweight..kg. + Gender, data = Lifting.data)
summary(log.snatch.lm)
## 
## Call:
## lm(formula = log(Total..kg.) ~ log(Snatch..kg.) + Bodyweight..kg. + 
##     Gender, data = Lifting.data)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.090294 -0.014899  0.000236  0.015333  0.103899 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       1.1819436  0.0245252   48.19  < 2e-16 ***
## log(Snatch..kg.)  0.9181441  0.0052970  173.33  < 2e-16 ***
## Bodyweight..kg.   0.0003341  0.0000370    9.03  < 2e-16 ***
## GenderWomen      -0.0200015  0.0024662   -8.11 1.21e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.0229 on 1229 degrees of freedom
## Multiple R-squared:  0.9933, Adjusted R-squared:  0.9933 
## F-statistic: 6.086e+04 on 3 and 1229 DF,  p-value: < 2.2e-16
plot(log.snatch.lm, which = 1)

Analysis

  1. In the model with Clean-and-Jerk variable, the R-squared is .99 which is extremely good. However, the regression line in the plot has a lot of residual errors with the value of 5.8. One thing that is interesting about the model is that the p-value for the bodyweight coefficient is .93. A variable with that high of a p-value is irrelevant to the model.

  2. In the model with the Snatch, the R-squared and the regression line stay the same but all p-values for the variables are very low. That means that all variables are relevant to the exploratory variable and that makes this model better than the previous one. However, we want to make it even better and we do so by transforming some of the variables.

  3. By taking the logarithm of the exploratory variable and the logarithm of the snatch variable makes this model the ideal regression model. The R-squared stays at .99 but the residual standard error went down to .02. This is our final model.

  • The linear combination for Women is:
    • log(Total) = 1.16 + .92 log(Snatch) + .0003 Bodyweight
  • The linear combination for Men is:
    • log(Total) = 1.18 + .92 log(Snatch) + .0003 Bodyweight

Section 3

Comparing variables in different groups

  • Have Men and Women improved significantly in Olympic Weightlifting from the year 2000 to 2020?

  • To do this test we are going to compare men and women separately and only use the data from the 2000 Summer Olympics and the 2020 Summer Olympics.

Graphical Analysis

LiftingMen$Year <- as.character(LiftingMen$Year)
LiftingWomen$Year <- as.character(LiftingWomen$Year)

box.men <- LiftingMen %>% 
  group_by(Year) %>% 
  filter(Year == 2000 | Year == 2020) %>% 
  ggplot(aes(x = Year, y = Total..kg., fill = Year)) +
  geom_boxplot() +
  scale_fill_brewer(palette="Pastel2") +
  ylab("Total Weight in Kg") +
  labs(subtitle = "Men") +
  theme_ipsum()

box.women <- LiftingWomen %>% 
  group_by(Year) %>% 
  filter(Year == 2000 | Year == 2020) %>% 
  ggplot(aes(x = Year, y = Total..kg., fill = Year)) +
  geom_boxplot() +
  scale_fill_brewer(palette="Pastel2") +
  ylab("Total Weight in Kg") +
  labs(subtitle = "Women") +
  theme_ipsum()

box.plot <- ggarrange(box.men, box.women,
                  common.legend = TRUE,
                  ncol = 2, nrow = 1, legend = "bottom")
annotate_figure(box.plot, top = text_grob("Total Weight difference between 2000 and 2020 Summer Olympics", 
               color = "black", face = "bold", size = 14))

  • The box plots presented show different things for the women’s category and the men’s category. Our research question asks if the total weight is higher in 2020 than in 2000. In the men’s category it looks like on average the athletes lifted heavier in 2000. The spread is longer in 2000 but it has a higher median. In the women’s category it seems like the women got stronger in the twenty-year span. The spread is bigger in 2000 but you can see that the median line and the third quarter are higher in 2020. However, there is one outlier in 2020 that seems to represent one athlete that lifted significantly heavier than the rest. If we would be interested in doing further research, we could take the outlier in 2020 out of the data and see if the results are different.

Men

Additional graphical analysis

density.men <- LiftingMen %>% 
  filter(Year == 2000 | Year == 2020) %>% 
  ggplot(aes(x = Total..kg., y = Year, fill = stat(x), alpha = 0.7)) +
  geom_density_ridges_gradient(scale = 3, rel_min_height = 0.01, alpha = 0.5) +
  scale_fill_viridis(name = "Total Weight", option = "C") +
  labs(title = 'Difference in Mens total weight') +
  xlab("Total Weight in Kg") +
  theme_ipsum()
density.men
## Picking joint bandwidth of 19.9

  • By the look of the density plot, it looks like that in 2000 the lightest weight is lower than in 2020 but there are more density on the right side of the plot. It is the opposite for the year 2020. The heaviest weight lifted looks like it was a little heavier than in 2000 but most of the density is on the left side of the plot.

Hypothesis:

  • H0: µ2000 = µ2020

  • Hα: µ2000 < µ2020

One-Sided T-Test

# Seperating Mens Summer Olympics 2000 and 2020

Men2000 <- LiftingMen %>% 
  filter(Year == 2000)

Men2020 <- LiftingMen %>% 
  filter(Year == 2020)
t.test(Men2020$Total..kg., Men2000$Total..kg., paired = FALSE, alternative = "greater")
## 
##  Welch Two Sample t-test
## 
## data:  Men2020$Total..kg. and Men2000$Total..kg.
## t = -0.15364, df = 159.46, p-value = 0.561
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  -14.33783       Inf
## sample estimates:
## mean of x mean of y 
##  344.3803  345.5986

Analysis

  • With a p-value of 0.5 we are not able to reject the H0 on a 5% significance level. The t value is negative and that indicates that the relationship between the groups has a negative slope. However, if you look at the mean for both groups, they are almost equal. Like the graphical analysis showed, the men in 2020 did not lift heavier than the men in 2000.

Women

Additional graphical analysis

density.women <- LiftingWomen %>% 
  filter(Year == 2000 | Year == 2020) %>% 
  ggplot(aes(x = Total..kg., y = Year, fill = stat(x), alpha = 0.7)) +
  geom_density_ridges_gradient(scale = 3, rel_min_height = 0.01, alpha = 0.5) +
  scale_fill_viridis(name = "Total Weight", option = "C") +
  labs(title = 'Difference in Womens total weight') +
  xlab("Total Weight in Kg") +
  theme_ipsum()
density.women
## Picking joint bandwidth of 11.3

  • The density plot for the year 2020 is way more on the right than the one for 2000. The lightest and the heaviest weight lifted in 2020 were way higher than in 2000. The data from 2020 has a very normal distribution where the highest density is in the middle. For the year 2000, the density is high in two places. That could point out that about half of the athletes lifted lightly while the other half lifted a lot heavier and not as much balance as there was in 2020.

Hypothesis

  • H0: µ2000 = µ2020

  • Hα: µ2000 < µ2020

One-Sided T-Test

# Seperating Womens Summer Olympics 2000 and 2020

Women2000 <- LiftingWomen %>% 
  filter(Year == 2000)

Women2020 <- LiftingWomen %>% 
  filter(Year == 2020)
t.test(Women2020$Total..kg., Women2000$Total..kg., paired = FALSE, alternative = "greater")
## 
##  Welch Two Sample t-test
## 
## data:  Women2020$Total..kg. and Women2000$Total..kg.
## t = 2.0306, df = 152.79, p-value = 0.02201
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  1.926703      Inf
## sample estimates:
## mean of x mean of y 
##  217.5595  207.1474

Analysis

  • With a p-value of 0.022 we can reject the p-value on a 5% significance level. The t value is positive which represents a positive slope between the groups. The means are significantly different as well. The women in 2020 lifted significantly heavier than the women in 2000.

Section 4

Contrast and Linear Combination Comparisons

  • Does a higher bodyweight increase your total weight in Olympic Weightlifting?

  • We will be testing men and women separately and using data from the 2000 and 2020 Summer Olympics. We have a total of 14 bodyweight categories for both men and women.

Graphical Analysis

# Separating light bodyweight and heavy bodyweight into mens and womens data frames from the Years 2000 and 2020

Men.low.bodyweight <- Lifting.data %>% 
  group_by(Title) %>% 
  filter(Gender == "Men" && 
           Year == 2000 && 
           Title == "Weightlifting at the 2000 Summer Olympics – Men's 56 kg" | 
           Title == "Weightlifting at the 2000 Summer Olympics – Men's 62 kg" | 
           Title == "Weightlifting at the 2000 Summer Olympics – Men's 69 kg" | 
           Title == "Weightlifting at the 2000 Summer Olympics – Men's 77 kg" | 
           Year == 2020 &&
           Title ==  "Weightlifting at the 2020 Summer Olympics – Men's 61 kg" | 
           Title ==  "Weightlifting at the 2020 Summer Olympics – Men's 67 kg" | 
           Title == "Weightlifting at the 2020 Summer Olympics – Men's 73 kg")

Men.high.bodyweight <- Lifting.data %>% 
  group_by(Title) %>% 
  filter(Gender == "Men" && 
           Year == 2000 && 
           Title == "Weightlifting at the 2000 Summer Olympics – Men's 85 kg" | 
           Title == "Weightlifting at the 2000 Summer Olympics – Men's 94 kg" | 
           Title == "Weightlifting at the 2000 Summer Olympics – Men's 105 kg" | 
           Title == "Weightlifting at the 2000 Summer Olympics – Men's +105 kg" | 
           Year == 2020 &&
           Title ==  "Weightlifting at the 2020 Summer Olympics – Men's +109 kg" | 
           Title ==  "Weightlifting at the 2020 Summer Olympics – Men's 109 kg" | 
           Title == "Weightlifting at the 2020 Summer Olympics – Men's 81 kg")
men.2000.plot <- Men2000 %>% 
  group_by(Title) %>% 
  ggplot(aes(x = Title, y = Total..kg., fill = Title)) +
  geom_boxplot() + 
  ylim(150, 500) +
  ylab("Total Weight in Kg") +
  labs(subtitle = "2000 Summer Olympics") +
  scale_x_discrete(
    name = "Category",
    limits = c("Weightlifting at the 2000 Summer Olympics – Men's 56 kg", 
               "Weightlifting at the 2000 Summer Olympics – Men's 62 kg", 
               "Weightlifting at the 2000 Summer Olympics – Men's 69 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's 77 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's 85 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's 94 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's 105 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's +105 kg"),
    labels=c(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ')) +
  scale_fill_discrete(
    breaks = c("Weightlifting at the 2000 Summer Olympics – Men's 56 kg", 
               "Weightlifting at the 2000 Summer Olympics – Men's 62 kg", 
               "Weightlifting at the 2000 Summer Olympics – Men's 69 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's 77 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's 85 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's 94 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's 105 kg",
               "Weightlifting at the 2000 Summer Olympics – Men's +105 kg"),
    labels = c("56 kg", 
               "62 kg", 
               "69 kg", 
               "77 kg", 
               "85 kg",
               "94 kg",
               "105 kg",
               "+105 kg"),
    name = " ") + 
  theme_ipsum()

men.2020.plot <- Men2020 %>% 
  group_by(Title) %>% 
  ggplot(aes(x = Title, y = Total..kg., fill = Title)) +
  geom_boxplot() + 
  ylim(150, 500) +
  ylab("Total Weight in Kg") +
  labs(subtitle = "2020 Summer Olympics") +
  scale_x_discrete(
    name = "Category",
    limits = c("Weightlifting at the 2020 Summer Olympics – Men's 61 kg", 
               "Weightlifting at the 2020 Summer Olympics – Men's 67 kg", 
               "Weightlifting at the 2020 Summer Olympics – Men's 73 kg",
               "Weightlifting at the 2020 Summer Olympics – Men's 81 kg",
               "Weightlifting at the 2020 Summer Olympics – Men's 109 kg",
               "Weightlifting at the 2020 Summer Olympics – Men's +109 kg"),
    labels=c(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ')) +
  scale_fill_discrete(
    breaks = c("Weightlifting at the 2020 Summer Olympics – Men's 61 kg", 
               "Weightlifting at the 2020 Summer Olympics – Men's 67 kg", 
               "Weightlifting at the 2020 Summer Olympics – Men's 73 kg",
               "Weightlifting at the 2020 Summer Olympics – Men's 81 kg",
               "Weightlifting at the 2020 Summer Olympics – Men's 109 kg",
               "Weightlifting at the 2020 Summer Olympics – Men's +109 kg"),
    labels = c("61 kg", 
               "67 kg", 
               "73 kg", 
               "81 kg", 
               "109 kg",
               "+109 kg"),
    name = " ") + 
  theme_ipsum()

ggarrange(men.2000.plot, men.2020.plot, 
          labels = c("Total Weight between Men's Categories"),
          ncol = 2, nrow = 1, legend = "bottom")

women.2000.plot <- Women2000 %>% 
  group_by(Title) %>% 
  ggplot(aes(x = Title, y = Total..kg., fill = Title)) +
  geom_boxplot() + 
  ylim(110, 325) +
  ylab("Total Weight in Kg") +
  labs(subtitle = "2000 Summer Olympics") +
  scale_x_discrete(
    name = "Category",
    limits = c("Weightlifting at the 2000 Summer Olympics – Women's 48 kg", 
               "Weightlifting at the 2000 Summer Olympics – Women's 53 kg", 
               "Weightlifting at the 2000 Summer Olympics – Women's 58 kg",
               "Weightlifting at the 2000 Summer Olympics – Women's 63 kg",
               "Weightlifting at the 2000 Summer Olympics – Women's 69 kg",
               "Weightlifting at the 2000 Summer Olympics – Women's 75 kg",
               "Weightlifting at the 2000 Summer Olympics – Women's +75 kg"),
    labels=c(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ')) +
  scale_fill_discrete(
    breaks = c("Weightlifting at the 2000 Summer Olympics – Women's 48 kg", 
               "Weightlifting at the 2000 Summer Olympics – Women's 53 kg", 
               "Weightlifting at the 2000 Summer Olympics – Women's 58 kg",
               "Weightlifting at the 2000 Summer Olympics – Women's 63 kg",
               "Weightlifting at the 2000 Summer Olympics – Women's 69 kg",
               "Weightlifting at the 2000 Summer Olympics – Women's 75 kg",
               "Weightlifting at the 2000 Summer Olympics – Women's +75 kg"),
    labels = c("48 kg", 
               "53 kg", 
               "58 kg", 
               "63 kg", 
               "69 kg",
               "75 kg",
               "+75 kg"),
    name = " ") + 
  theme_ipsum(base_family = "Arial Narrow")


women.2020.plot <- Women2020 %>% 
  group_by(Title) %>% 
  ggplot(aes(x = Title, y = Total..kg., fill = Title)) +
  geom_boxplot() + 
  ylim(110, 325) +
  ylab("Total Weight in Kg") +
  labs(subtitle = "2020 Summer Olympics") +
  scale_x_discrete(
    name = "Category",
    limits = c("Weightlifting at the 2020 Summer Olympics – Women's 49 kg", 
               "Weightlifting at the 2020 Summer Olympics – Women's 55 kg", 
               "Weightlifting at the 2020 Summer Olympics – Women's 59 kg",
               "Weightlifting at the 2020 Summer Olympics – Women's 64 kg",
               "Weightlifting at the 2020 Summer Olympics – Women's 76 kg",
               "Weightlifting at the 2020 Summer Olympics – Women's 87 kg",
               "Weightlifting at the 2020 Summer Olympics – Women's +87 kg"),
    labels=c(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ')) +
  scale_fill_discrete(
    breaks = c("Weightlifting at the 2020 Summer Olympics – Women's 49 kg", 
               "Weightlifting at the 2020 Summer Olympics – Women's 55 kg", 
               "Weightlifting at the 2020 Summer Olympics – Women's 59 kg",
               "Weightlifting at the 2020 Summer Olympics – Women's 64 kg",
               "Weightlifting at the 2020 Summer Olympics – Women's 76 kg",
               "Weightlifting at the 2020 Summer Olympics – Women's 87 kg",
               "Weightlifting at the 2020 Summer Olympics – Women's +87 kg"),
    labels = c("49 kg", 
               "55 kg", 
               "59 kg", 
               "64 kg", 
               "76 kg",
               "87 kg",
               "+87 kg"),
    name = " ") + 
  theme_ipsum(base_family = "Arial Narrow")

ggarrange(women.2000.plot, women.2020.plot,
          labels = c("Total Weight between Women's Categories"),
          ncol = 2, nrow = 1, legend = "bottom")

  • In all four box plots presented, they all have the same trend of showing a positive relationship between each group. There is significant difference between each weight category with both genders in both Olympics. By looking at the values of the legends for both genders, the 2020 Olympics increased their weight in the bodyweight categories. For women that did not change the trend of the box plot. For men however, in the 2020 box plot there is not a big difference in the total weight in the top two categories. Does that mean that it was unnecessary for the change in categories? For men, the interquartile ranges in 2000 are way larger than the ones in 2020 and if we focus on the median line, it is higher in 2020. So, the change of bodyweight categories was successful in the men’s category. For the women however, it is the opposite. For the heaviest category, the interquartile ranges are larger in 2020 and the median is higher in 2000. That implies that it could have been unnecessary for the category change. Some could argue and say that maybe the women were stronger in 2000 but we have already done statistical testing and proven that that is incorrect.

Methods & Testing

  • Step 1, we test if all bodyweight categories have the same mean in total weight. The best way for that is to do hypothesis testing by fitting an Analysis of Variance Model into an Anova test.

  • Step 2, we are interested in comparing the average total weight of the heaviest bodyweight categories vs. lightest bodyweight categories. The best way of testing is to Compute and test arbitrary contrasts for regression objects.

Step 1

Hypothesis

  • Men

    • H0: µ56kg = µ61kg = µ62kg = µ67kg = µ69kg = µ73kg = µ77kg = µ81kg = µ85kg = µ94kg = µ105kg = µ105+kg = µ109kg = µ109+kg

    • Hα: At least one mean is different

  • Women

    • H0: µ48kg = µ49kg = µ53kg = µ55kg = µ58kg = µ59kg = µ63kg = µ64kg = µ69kg = µ75kg = µ75+kg = µ76kg = µ87kg = µ87+kg

    • Hα: At least one mean is different

Analysis of Variance

  • Men
# Data frame with only males athletes from 2000 and 2020
men.2000.2020 <- LiftingMen %>% filter(Year == 2000 | Year == 2020) %>% mutate(Title = as.factor(Title))
men.aov <- aov(men.2000.2020$Total..kg. ~ men.2000.2020$Title)
anova(men.aov)
  • Women
# Data frame with only female athletes from 2000 and 2020
women.2000.2020 <- LiftingWomen %>% filter(Year == 2000 | Year == 2020) %>% mutate(Title = as.factor(Title))
women.aov <- aov(women.2000.2020$Total..kg. ~ women.2000.2020$Title)
anova(women.aov)

Analysis and conclusion

  • Both genders have a p-value of 2.2e-16 so we reject both null hypothesis on a 5% significance level. There is at least one bodyweight category for both genders that does not have the same mean as another.

  • The p-value is less than 0.05 so we can reject the null hypothesis on a 5% significance level.

Step 2

Linear Combination

  • Men

    • (µ56kg + µ61kg + µ62kg + µ67kg + µ69kg + µ73kg + µ77kg)/7 - (µ81kg + µ85kg + µ94kg + µ105kg + µ+105kg + µ109kg + µ+109kg)/7 = 0
  • Women

    • (µ48kg + µ49kg + µ53kg + µ55kg + µ58kg + µ59kg + µ63kg)/7 - (µ64kg+ µ69kg + µ75kg + µ+75kg + µ76kg + µ87kg + µ+87kg)/7 = 0

Hypothesis (both genders)

  • H0: µlower = µhigher

  • Hα: µ2lower < µhigher

Testing

  • Men:
fit.contrast(men.aov, men.2000.2020$Title, c(-(1/7), -(1/7), (1/7), (1/7), (1/7), (1/7), -(1/7), -(1/7), -(1/7), -(1/7), (1/7), (1/7), (1/7), -(1/7)), conf.int = 0.95)
##                                                                                                                                                                                                                                                                                               Estimate
## men.2000.2020$Title c=( -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 ) -82.96056
##                                                                                                                                                                                                                                                                                              Std. Error
## men.2000.2020$Title c=( -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 )    4.18016
##                                                                                                                                                                                                                                                                                                t value
## men.2000.2020$Title c=( -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 ) -19.84626
##                                                                                                                                                                                                                                                                                                  Pr(>|t|)
## men.2000.2020$Title c=( -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 ) 4.632297e-49
##                                                                                                                                                                                                                                                                                               lower CI
## men.2000.2020$Title c=( -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 ) -91.20366
##                                                                                                                                                                                                                                                                                               upper CI
## men.2000.2020$Title c=( -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 ) -74.71747
## attr(,"class")
## [1] "fit_contrast"
  • Women
fit.contrast(women.aov, women.2000.2020$Title, c(-(1/7), (1/7), (1/7), (1/7), (1/7), -(1/7), -(1/7), -(1/7), (1/7), (1/7), (1/7), -(1/7), -(1/7), -(1/7)), conf.int = 0.95)
##                                                                                                                                                                                                                                                                                                 Estimate
## women.2000.2020$Title c=( -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 ) -44.56471
##                                                                                                                                                                                                                                                                                                Std. Error
## women.2000.2020$Title c=( -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 )   3.434913
##                                                                                                                                                                                                                                                                                                  t value
## women.2000.2020$Title c=( -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 ) -12.97404
##                                                                                                                                                                                                                                                                                                    Pr(>|t|)
## women.2000.2020$Title c=( -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 ) 3.467122e-26
##                                                                                                                                                                                                                                                                                                 lower CI
## women.2000.2020$Title c=( -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 ) -51.35251
##                                                                                                                                                                                                                                                                                                upper CI
## women.2000.2020$Title c=( -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 0.142857142857143 0.142857142857143 0.142857142857143 -0.142857142857143 -0.142857142857143 -0.142857142857143 ) -37.7769
## attr(,"class")
## [1] "fit_contrast"

Analysis

Step 1

  • Both genders have a p-value of 2.2e-16 so we reject both null hypothesis on a 5% significance level. There is at least one bodyweight category for both genders that does not have the same mean as another.

Step 2

  • For both genders the p-value is so low that we can reject both null hypothesis on a 5% significance level. The heavier the athlete is, the heavier his total weight score is.

Further Research and Analysis

  • As you can tell by the data presented in the research, the weight categories for men and women change between Olympics. The adjustment is made to improve the sport and make it fair between the athletes (Why change weightlifting’s bodyweight categories … again?).

  • The bodyweight categories will change for the Olympics in 2024. To reach full gender equality, there will be 5 weight categories for each gender. Men will compete in 61kg, 73kg, 89kg, 102kg and +102kg. Women will compete in 49kg, 59kg, 71kg, 81kg and +81kg (Paris 2024: Weight categories for the Olympic Weightlifting Competition).

  • Those categories are very different from the ones in our data. There is a bigger range between each men’s category and the heaviest one will be 7kg lighter than the heaviest one from our data. The women’s future plus category is between the plus categories from 2000 and 2020. In our graphical analysis we concluded that the women in the plus category in 2000 were stronger than the one in the plus category from 2020. Since the plus category in 2024 will be in between them, it is exciting to see if the results will improve from previous Olympic Games.

Conclusion

  • The statistical results from these observational studies can be applied to Olympic Weightlifting in general with 95 percent confidence. If an athlete is good at one Olympic lift, he is most likely good at the other one as well. That is about the athlete’s general strength.
  • The results presented in section 2 is an equation to predict an athletes sum of Clean-and-Jerk and Snatch from bodyweight and Snatch information. You can also calculate the prediction of your Clean-and-Jerk from those results by detucting your Snatch variable from your total weight prediction.
  • The evidence collected in section 3 cannot be applied to a broader audience than the elite athletes because that was only tested with data from Olympic Games. Male elite athletes have not improved over the 21st century, while female elite athletes have.
  • We also statistically proved that athletes with heavy bodyweight lift heavier weights than athletes with light bodyweight.

References

LS0tCnRpdGxlOiBBbmFseXNpcyBvbiBTdW1tZXIgT2x5bXBpY3MgaW4gT2x5bXBpYyBXZWlnaHRsaWZ0aW5nIDIwMDAgdG8gMjAyMCAKYXV0aG9yOiBCcnluaGlsZHVyIFRyYXVzdGFkw7N0dGlyCmRhdGU6ICIyIE1heSAyMDIzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCiAKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFKQpsaWJyYXJ5KFNsZXV0aDMpCmxpYnJhcnkoc3RhdHMpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodmlyaWRpcykKbGlicmFyeShocmJydGhlbWVzKQpsaWJyYXJ5KG1vc2FpYykKbGlicmFyeShHR2FsbHkpICMgZ2dwYWlycwpsaWJyYXJ5KElTTFIpCmxpYnJhcnkoRFQpCmxpYnJhcnkoZ21vZGVscykKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShtdWx0Y29tcCkKbGlicmFyeShkZXZ0b29scykKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkoTUFTUykKbGlicmFyeShsZWFwcykKbGlicmFyeShvbHNycikKbGlicmFyeShjYXIpCmxpYnJhcnkocGF0Y2h3b3JrKSAjTWFrZXMgbXVsdGlibGUgZ3JhcGhzIGJlIGluIG9uZSBieSBhL2IKbGlicmFyeShwbG90bHkpICMgTWFrZXMgaXQgcG9zc2libGUgdG8gaW50ZXJhY3Qgd2l0aCAzRCBncmFwaHMKYGBgCgojICoqSW50cm9kdWN0aW9uKioKCiogT2x5bXBpYyBXZWlnaHRsaWZ0aW5nIGhhcyBiZWVuIGEgcGFydCBvZiB0aGUgU3VtbWVyIE9seW1waWMgR2FtZXMgc2luY2UgMTg5Ni4gQXRobGV0ZXMgcGVyZm9ybSBDbGVhbi1hbmQtSmVyayBhbmQgU25hdGNoLCBhbmQgdGhleSBoYXZlIHRocmVlIGF0dGVtcHRzIHRvIGFpbSBmb3IgbGlmdGluZyB0aGUgaGVhdmllc3Qgd2VpZ2h0LiBQcml6ZXMgYXJlIGdpdmVuIGZvciB0aGUgaGVhdmllc3Qgd2VpZ2h0cyBsaWZ0ZWQgaW4gZWFjaCBsaWZ0IGFuZCBpbiB0aGUgb3ZlcmFsbC4gVGhlIG92ZXJhbGwgaXMgdGhlIG1heGltdW0gbGlmdHMgb2YgYm90aCBhZGRlZC4gV29tZW4gYW5kIG1lbiBjb21wZXRlIHNlcGFyYXRlbHksIGFuZCB0aGV5IGFyZSBzcGxpdCB1cCBpbnRvIGRpZmZlcmVudCB3ZWlnaHQgY2xhc3Nlcy4gSW4gdGhlIGZvbGxvd2luZyByZXBvcnQsIHdlIHdpbGwgdXNlIHN0YXRpc3RpY2FsIG1ldGhvZHMgdG8gcmVzZWFyY2ggY29ycmVsYXRpb24gYmV0d2VlbiBTbmF0Y2ggYW5kIENsZWFuLWFuZC1KZXJrLCBpbXByb3ZlbWVudHMgaW4gT2x5bXBpYyBXZWlnaHRsaWZ0aW5nIG92ZXIgYSAyMC15ZWFyIHNwYW4gYW5kIGlmIGJvZHl3ZWlnaHQgYWZmZWN0cyB0aGUgYXRobGV0ZXPigJkgbWF4aW11bSB3ZWlnaHQgbGlmdGVkLiAKCgojICoqVGhlIERhdGEqKgoKKiBUaGUgZGF0YXNldCB0aGF0IGlzIHVzZWQgaXMgY29sbGVjdGVkIGZyb20gS2FnZ2xlIGFuZCBpcyBmcm9tIHRoZSAyMDAwIHRvIDIwMjAgU3VtbWVyIE9seW1waWNzIGluIE9seW1waWMgV2VpZ2h0bGlmdGluZy4gSXQgaW5jbHVkZXMgMTAgZGlmZmVyZW50IGNvbHVtbnMgYW5kIDEyMzMgZGF0YSBwb2ludHMgYW5kIGVhY2ggcm93IHJlcHJlc2VudHMgYSBkaWZmZXJlbnQgYXRobGV0ZS4KCmBgYHtyfQpXZWlnaHRsaWZ0aW5nLmRhdGEgPSByZWFkLmNzdigid2VpZ2h0bGlmdGluZy5jc3YiKSAjIHJlYWRpbmcgdGhlIGRhdGEgZnJvbSBjc3YgZXhjZWwgZmlsZQphdHRhY2goV2VpZ2h0bGlmdGluZy5kYXRhKQpgYGAKCiMjIENsZWFuaW5nIHVwIHRoZSBkYXRhCgpgYGB7cn0KIyBHZXR0aW5nIHJpZCBvZiBhbGwgcm93cyB0aGF0IGhhdmUgLTEgYXMgdGhlaXIgdmFsdWUgaW4gdGhlIG51bWVyaWNhbCBjb2x1bW5zLiBBbHNvIGdldHRpbmcgcmlkIG9mIHRoZSBVUkwgY29sdW1uLgoKTGlmdGluZy5kYXRhIDwtIFdlaWdodGxpZnRpbmcuZGF0YVsgLCAtOF0gJT4lIAogIGZpbHRlcihUb3RhbC4ua2cuICE9IC0xKSAlPiUgCiAgZmlsdGVyKEJvZHl3ZWlnaHQuLmtnLiA+IDEwKQpzdHIoTGlmdGluZy5kYXRhKQpgYGAKCmBgYHtyfQpkZXRhY2goV2VpZ2h0bGlmdGluZy5kYXRhKQphdHRhY2goTGlmdGluZy5kYXRhKQpMaWZ0aW5nLmRhdGEgPC0gTGlmdGluZy5kYXRhICU+JSBtdXRhdGUoVGl0bGUgPSBhcy5mYWN0b3IoTGlmdGluZy5kYXRhJFRpdGxlKSwgWWVhciA9IGFzLmZhY3RvcihMaWZ0aW5nLmRhdGEkWWVhciksIEdlbmRlciA9IGFzLmZhY3RvcihMaWZ0aW5nLmRhdGEkR2VuZGVyKSkKYGBgCgoqIExpZnRpbmcuZGF0YSB3aWxsIGJlIHRoZSBkYXRhIGZyYW1lIHVzZWQgZm9yIHRoaXMgcHJvamVjdC4KICAgIApgYGB7cn0KaGVhZChMaWZ0aW5nLmRhdGEpCmBgYAoKYGBge3J9CkRlcyA8LSBkYXRhLmZyYW1lKAogIENvbHVtbiA9IGMoIlgiLCJBdGhsZXRlIiwgIkJvZHl3ZWlnaHQiLCAiU25hdGNoIiwgIkNsZWFuICYgSmVyayIsICJUb3RhbCIsICJSYW5raW5nIiwgIlRpdGxlIiwgIlllYXIiLCAiR2VuZGVyIiksCiAgVHlwZSA9IGMoIkludCIsICJDaHIiLCAiTnVtIiwgIk51bSIsICJOdW0iLCAiTnVtIiwgIkludCIsICJGY3QiLCAiRmN0IiwgIkZjdCIpLAogIERlc2NyaXB0aW9uID0gYygKICAgICJBdGhsZXRlcyBpZCIsCiAgICAiTmFtZSIsCiAgICAiQXRobGV0ZXMnIGJvZHl3ZWlnaHQiLAogICAgIk1heGltdW0gd2VpZ2h0IG9mIFNuYXRjaCIsCiAgICAiTWF4aW11bSB3ZWlnaHQgb2YgQ2xlYW4mSmVyayIsCiAgICAiTWF4aW11bSBsaWZ0cyBvZiBib3RoIGFkZGVkIiwKICAgICJBdGhsZXRlcycgcGxhY2VtZW50IiwKICAgICJBdGhsZXRlcycgYm9keXdlaWdodCBjbGFzcy9jYXRlZ29yeSIsCiAgICAiT2x5bXBpYyBZZWFyIiwKICAgICJNZW4gb3IgV29tZW4iKSkKCmRhdGF0YWJsZShEZXMsIHJvd25hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAnTGlmdGluZy5kYXRhIGRlc2NyaXB0aW9uJykKYGBgCgpgYGB7cn0KIyBTZXBhcmF0aW5nIGdlbmRlcnMgaW50byB0d28gZGlmZmVyZW50IGRhdGEgZnJhbWVzIGZvciBmdXJ0aGVyIHJlc2VhcmNoCgpMaWZ0aW5nV29tZW4gPC0gTGlmdGluZy5kYXRhICU+JSAKICBmaWx0ZXIoR2VuZGVyID09ICJXb21lbiIpCgpMaWZ0aW5nTWVuIDwtIExpZnRpbmcuZGF0YSAlPiUgCiAgZmlsdGVyKEdlbmRlciA9PSAiTWVuIikKYGBgCgojIyBFREEgb2YgdGhlIGRhdGEKCiogRmlsdGVyIHRoZSB0YWJsZSBhcyB5b3Ugd2lzaAoKYGBge3J9CmRhdGF0YWJsZShMaWZ0aW5nLmRhdGEsIAogICAgICAgICAgY29sbmFtZXMgPSBjKCdCb2R5d2VpZ2h0JyA9IDMsICdTbmF0Y2gnID0gNCwgJ0NsZWFuJkplcmsnID0gNSwgJ1RvdGFsJyA9IDYpLCAKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsIAogICAgICAgICAgZmlsdGVyPSJ0b3AiLCAKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSA1LCBzY3JvbGxYPVQsIGF1dG9XaWR0aCA9IFRSVUUpICkKYGBgCgoqIFN1bW1hcnkgdGFibGUgc2VwYXJhdGVkIGJ5IGdlbmRlcnMKCmBgYHtyfQpMaWZ0aW5nLmRhdGEgJT4lIAogIGdyb3VwX2J5KEdlbmRlcikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgbWluID0gbWluKFRvdGFsLi5rZy4pLCAKICAgICAgICAgICAgbWVhbiA9IG1lYW4oVG90YWwuLmtnLiksIHNkID0gc2QoVG90YWwuLmtnLiksIG1lZGlhbiA9IG1lZGlhbihUb3RhbC4ua2cuKSwKICAgICAgICAgICAgbWF4ID0gbWF4KFRvdGFsLi5rZy4pKQpgYGAKCiogU3VtbWFyeSB0YWJsZSBzZXBhcmF0ZWQgYnkgeWVhcnMgZm9yIG1lbiBvbmx5CgpgYGB7cn0KTGlmdGluZy5kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgZmlsdGVyKEdlbmRlciA9PSAiTWVuIikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgbWluID0gbWluKFRvdGFsLi5rZy4pLCAKICAgICAgICAgICAgbWVhbiA9IG1lYW4oVG90YWwuLmtnLiksIHNkID0gc2QoVG90YWwuLmtnLiksIG1lZGlhbiA9IG1lZGlhbihUb3RhbC4ua2cuKSwKICAgICAgICAgICAgbWF4ID0gbWF4KFRvdGFsLi5rZy4pKQpgYGAKCiogU3VtbWFyeSB0YWJsZSBzZXBhcmF0ZWQgYnkgeWVhcnMgZm9yIHdvbWVuIG9ubHkKCmBgYHtyfQpMaWZ0aW5nLmRhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBmaWx0ZXIoR2VuZGVyID09ICJXb21lbiIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIG1pbiA9IG1pbihUb3RhbC4ua2cuKSwgCiAgICAgICAgICAgIG1lYW4gPSBtZWFuKFRvdGFsLi5rZy4pLCBzZCA9IHNkKFRvdGFsLi5rZy4pLCBtZWRpYW4gPSBtZWRpYW4oVG90YWwuLmtnLiksCiAgICAgICAgICAgIG1heCA9IG1heChUb3RhbC4ua2cuKSkKYGBgCgoKCiMgKipNZXRob2RzKioKCjEuICoqVGVzdGluZyBmb3IgY29ycmVsYXRpb24gYmV0d2VlbiB0d28gdmFyaWFibGVzICoqCgogICogTGluZWFyIFJlZ3Jlc3Npb24gCiAgCiAgICArIFByZWRpY3RzIHRoZSB2YWx1ZSBvZiB1bmtub3duIGRhdGEuIAoKICAqIFZhcmlhbmNlIEluZmxhdGlvbiBGYWN0b3IgKFZJRikgCgogICAgKyBJdCBpcyBhIG1lYXN1cmUgZm9yIGEgbWV0aG9kIHRvIGRldGVjdCB3aGV0aGVyIG11bHRpY29sbGluZWFyaXR5IGlzIGEgcHJvYmxlbSBpbiBhIG1vZGVsLiBBIFZJRiBvZiA1IG9yIGhpZ2hlciBpbmRpY2F0ZXMgdGhhdCBtdWx0aWNvbGxpbmVhcml0eSBjb3VsZCBiZSBhIHByb2JsZW0gKE11bHRpY29sbGluZWFyaXR5KS4gCiAgICAKMi4gKipQcmVkaWN0aW5nIHRvdGFsIHdlaWdodCoqCiAgCiAgKiBMaW5lYXIgUmVncmVzc2lvbgogICAgCiAgICArIFByZWRpY3RzIHRoZSBjb2VmZmljaWVudHMgZm9yIGEgbGluZWFyIGNvbWJpbmF0aW9uLgoKMy4gKipDb21wYXJpbmcgdmFyaWFibGVzIGluIGRpZmZlcmVudCBncm91cHMgKioKCiAgKiBULXRlc3QgCgogICAgKyBPbmUgc2lkZWQgSHlwb3RoZXNpcyB0ZXN0aW5nIAoKICAgICsgQ29tcGFyZXMgdGhlIG1lYW4gaW4gdHdvIGdyb3VwcyAKCjQuICoqQ29udHJhc3QgYW5kIExpbmVhciBDb21iaW5hdGlvbiBDb21wYXJpc29uICoqCgogICogQW5hbHlzaXMgb2YgVmFyaWFuY2UgYW5kIEFub3ZhIAoKICAgICsgQ29tcGFyZXMgZmFjdG9yZWQgc3RhdGlzdGljcyAKCiAgKiBDb250cmFzdCAKCiAgICArIENvbXB1dGVzIGFuZCB0ZXN0IGFyYml0cmFyeSBjb250cmFzdHMgZm9yIHJlZ3Jlc3Npb24gb2JqZWN0cyAKCgoKIyAqKlNlY3Rpb24gMSoqCgojIyBUZXN0aW5nIGZvciBjb3JyZWxhdGlvbiBiZXR3ZWVuIHR3byB2YXJpYWJsZXMgCgoqIEFyZSBDbGVhbi1hbmQtSmVyayBhbmQgU25hdGNoIGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlcj8gCiAgICAKIyMgR3JhcGhpY2FsIEFuYWx5c2lzCgpgYGB7cn0KcG9pbnBsLncuMjAgPC0gTGlmdGluZ1dvbWVuICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBDbGVhbi4uLkplcmsuLmtnLiwgeSA9IFNuYXRjaC4ua2cuLCBjb2xvciA9IFRvdGFsLi5rZy4pKSArCiAgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdz0iYmx1ZSIsIGhpZ2g9InJlZCIpICsKICBsYWJzKGZpbGwgPSAiVG90YWwgV2VpZ2h0IikgKwogIHhsYWIoIkNsZWFuICYgSmVyayIpICsKICB5bGFiKCJTbmF0Y2giKSArCiAgbGFicyhzdWJ0aXRsZSA9ICJXb21lbiIpICsKICB0aGVtZV9pcHN1bSgpCgpwb2lucGwudy4wMCA8LSBMaWZ0aW5nTWVuICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBDbGVhbi4uLkplcmsuLmtnLiwgeSA9IFNuYXRjaC4ua2cuLCBjb2xvciA9IFRvdGFsLi5rZy4pKSArCiAgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdz0iYmx1ZSIsIGhpZ2g9InJlZCIpICsKICBsYWJzKGNvbG9yID0gIlRvdGFsIFdlaWdodCIpICsKICB4bGFiKCJDbGVhbiAmIEplcmsiKSArCiAgeWxhYigiU25hdGNoIikgKwogIGxhYnMoc3VidGl0bGUgPSAiTWVuIikgKwogIHRoZW1lX2lwc3VtKCkKCnBsb3QgPC0gZ2dhcnJhbmdlKHBvaW5wbC53LjAwLCBwb2lucGwudy4yMCwKICAgICAgICAgICAgICAgICAgY29tbW9uLmxlZ2VuZCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIG5jb2wgPSAyLCBucm93ID0gMSwgbGVnZW5kID0gImJvdHRvbSIpCmFubm90YXRlX2ZpZ3VyZShwbG90LCB0b3AgPSB0ZXh0X2dyb2IoIkNsZWFuICYgSmVyayBhbmQgU25hdGNoIFJlbGF0aW9uc2hpcCIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCkpCmBgYAoKKiBUaGUgc2NhdHRlcnBsb3RzIHNob3cgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIENsZWFuLWFuZC1KZXJrIGFuZCBTbmF0Y2ggaW4gdGhlIE9seW1waWNzIGluIDIwMDAgYW5kIDIwMjAuIEZvciBib3RoIG1lbiBhbmQgd29tZW4sIHRoZSBzY2F0dGVycGxvdHMgcmVwcmVzZW50IGEgcG9zaXRpdmUgcmVsYXRpb25zaGlwIHdpdGggYmFyZWx5IGFueSBvdXRsaWVycyBhbmQgaW5kaWNhdGUgdGhhdCBoaWdoZXIgaW50ZW5zaXR5IGluIENsZWFuLWFuZC1KZXJrIGluY3JlYXNlcyB5b3VyIGludGVuc2l0eSBpbiB5b3VyIFNuYXRjaC4gCgojIyBUZXN0aW5nIOKAkyBMaW5lYXIgUmVncmVzc2lvbiBhbmQgTXVsdGljb2xsaW5lYXJpdHkgCgpgYGB7cn0KY29yci5sbSA9IGxtKENsZWFuLi4uSmVyay4ua2cuIH4gU25hdGNoLi5rZy4sIGRhdGEgPSBMaWZ0aW5nLmRhdGEpCnN1bW1hcnkoY29yci5sbSkKCnZpZiA9IDEvKDEtMC45NzQ0KQp2aWYKYGBgCgojIyBBbmFseXNpcwoKKiBXaXRoIGEgVklGIHZhbHVlIG9mIDE1IGFuZCBSLXNxdWFyZWQgYXMgMC45Mywgd2UgY2FuIGFzc3VtZSB0aGF0IGNsZWFuLWFuZC1KZXJrIGFuZCBTbmF0Y2ggYXJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLiBJZiBhbiBhdGhsZXRlIGhhcyBhIGhlYXZ5IENsZWFuLWFuZC1KZXJrLCB3ZSBjYW4gYXNzdW1lIHRoYXQgaGUgYWxzbyBoYXMgYSBoZWF2eSBTbmF0Y2guIAoKKiBUaGVzZSByZXN1bHRzIGFsc28gaW5kaWNhdGUgdGhhdCBpZiB3ZSB3YW50IHRvIGRvIGZ1cnRoZXIgdGVzdGluZywgd2UgZG8gbm90IHdhbnQgdG8gaGF2ZSBib3RoIHZhcmlhYmxlcyB0b2dldGhlciBpbiBhIHJlZ3Jlc3Npb24gbW9kZWwuICAKICAgIAojIyBGdXJ0aGVyIFJlc2VhcmNoIAoKKiBUaGUgdHdvIGxpZnRzIGFyZSB2ZXJ5IGRpZmZlcmVudCBmcm9tIG9uZSBhbm90aGVyLCBhbmQgd2VpZ2h0bGlmdGVycyBtdXN0IGdldCBjb21mb3J0YWJsZSB3aXRoIGJvdGggbGlmdGluZyB0ZWNobmlxdWVzIGlmIHRoZXkgYXJlIGFzcGlyaW5nIHRvIGNvbXBldGUuIENsZWFuLWFuZC1KZXJrIGlzIGFib3V0IHB1cmUgcG93ZXIgd2hpbGUgU25hdGNoIGlzIGFib3V0IGZpbmVzc2UuIE9uZSBvZiB0aGUgYmlnZ2VzdCBkaWZmZXJlbmNlcyBpcyBob3cgeW91IHB1bGwgdGhlIGJhciBvZmYgdGhlIGdyb3VuZC4gSW4gU25hdGNoLCB5b3UgaGF2ZSB0byBlbGV2YXRlIHRoZSBiYXIgd2F5IGhpZ2hlciB0aGFuIHlvdSBoYXZlIHRvIGZvciB0aGUgSmVyay4gVGhhdCBtZWFucyB0aGF0IHlvdSBzaG91bGQgYmUgYWJsZSB0byBsb2FkIHNpZ25pZmljYW50bHkgbW9yZSB3ZWlnaHQgb250byB5b3VyIENsZWFuLWFuZC1KZXJrIHRoYW4gb250byB5b3VyIFNuYXRjaC4gRXZlbiB0aG91Z2ggdGhleSBhcmUgdmVyeSBkaWZmZXJlbnQsIGJvdGggbGlmdHMgaGF2ZSB0aGUgc2FtZSBnb2FsLiBJdCBpcyB0byBsaWZ0IGEgbG9hZGVkIGJhcmJlbGwgZnJvbSB0aGUgZ3JvdW5kIHRvIG92ZXJoZWFkLiBUaGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGVtIGlzIHRoYXQgdGhleSB0cmFpbiBzaW1pbGFyIG11c2NsZSBjYXRlZ29yaWVzIHdoaWNoIGNvdWxkIGV4cGxhaW4gdGhhdCBpZiB5b3UgbGlmdCBoZWF2eSBpbiBvbmUgbGlmdCwgeW91IGxpZnQgaGVhdnkgaW4gdGhlIG90aGVyIChEaWNrc29uLCBUaGUgc25hdGNoIHZzLiB0aGUgQ2xlYW4gJiBKZXJrOiBQcm9zIGFuZCBjb25zIG9mIHRoZSB0d28gT2x5bXBpYyBsaWZ0cyAyMDIzKS4gCgoKCiMgKipTZWN0aW9uIDIqKgoKIyMgUHJlZGljdGluZyB0b3RhbCB3ZWlnaHQKCiogV2hhdCBpcyB0aGUgbGluZWFyIGNvbWJpbmF0aW9uIHRvIHByZWRpY3QgdGhlIHRvdGFsIHdlaWdodCBmcm9tIHRoZSBhdGhsZXRlIHVzaW5nIGJvZHl3ZWlnaHQsIEdlbmRlciwgYW5kIENsZWFuLWFuZC1KZXJrIG9yIFNuYXRjaD8KCiAgKyBJbiB0aGUgZmluYWwgcmVncmVzc2lvbiBtb2RlbCwgZG9lcyBDbGVhbi1hbmQtSmVyayBvciBTbmF0Y2ggZml0IGJldHRlci4KICAKICArIFRoZSBleHBsb3JhdG9yeSB2YXJpYWJsZSBpcyBUb3RhbCBXZWlnaHQgYW5kIHRoZSBSZXNwb25jZSB2YXJpYWJsZSBpcyBCb2R5d2VpZ2h0LCBHZW5kZXIgYW5kIENsZWFuLWFuZC1KZXJrIG9yIFNuYXRjaC4KICAKIyMgR3JhcGhpY2FsIGFuYWx5c2lzCgpgYGB7cn0KTGlmdGluZy5kYXRhICU+JSBnZ3BhaXJzKGNvbHVtbnMgPSAzOjYsIGFlcyhjb2xvciA9IEdlbmRlciwgYWxwaGEgPSAwLjUpLCB1cHBlciA9IGxpc3QoY29udGludW91cyA9IHdyYXAoImNvciIsIHNpemUgPSAyLjUpKSkKYGBgCgoqIEFzIHByb3ZlbiBpbiB0aGUgZmlyc3Qgc2VjdGlvbiwgQ2xlYW4tYW5kLUplcmsgYW5kIFNuYXRjaCBoYXZlIGEgaGlnaCBjb3JyZWxhdGlvbi4gVGhlIHRvdGFsIHNjb3JlIGFsc28gaGFzIGEgaGlnaCBjb3JyZWxhdGlvbiB3aXRoIHRoZSB0d28gdmFyaWFibGVzIGJlY2F1c2UgdGhlIGl0IGlzIHRoZSBzdW0gb2YgdGhlIGJvdGguCgojIyBUZXN0aW5nIC0gTGluZWFyIFJlZ3Jlc3Npb24KCiMjIyBNb2RlbCB3aXRoIGNsZWFuLWFuZC1KZXJrCgoqIFRlc3RpbmcgdGhlIG1vZGVsIHdpdGggQ2xlYW4tYW5kLUplcmsgdmFyaWFibGUKCmBgYHtyfQpjbGVhbi5sbSA9IGxtKFRvdGFsLi5rZy4gfiBDbGVhbi4uLkplcmsuLmtnLiArIEJvZHl3ZWlnaHQuLmtnLiArIEdlbmRlciwgZGF0YSA9IExpZnRpbmcuZGF0YSkKc3VtbWFyeShjbGVhbi5sbSkKcGxvdChjbGVhbi5sbSwgd2hpY2ggPSAxKQpgYGAKCiMjIyBNb2RlbCB3aXRoIFNuYXRjaAoKKiBUZXN0aW5nIHRoZSBtb2RlbCB3aXRoIFNuYXRjaCB2YXJpYWJsZQogICAgCmBgYHtyfQpzbmF0Y2gubG0gPSBsbShUb3RhbC4ua2cuIH4gU25hdGNoLi5rZy4gKyBCb2R5d2VpZ2h0Li5rZy4gKyBHZW5kZXIsIGRhdGEgPSBMaWZ0aW5nLmRhdGEpCnN1bW1hcnkoc25hdGNoLmxtKQpwbG90KHNuYXRjaC5sbSwgd2hpY2ggPSAxKQpgYGAKCiMjIyBUcmFuc2Zvcm1lZCBtb2RlbAoKKiBUZXN0aW5nIHRoZSBzbmF0Y2ggbW9kZWwgd2l0aCB0cmFuc2Zvcm1lZCB2YXJpYWJsZXMKICAgIApgYGB7cn0KbG9nLnNuYXRjaC5sbSA9IGxtKGxvZyhUb3RhbC4ua2cuKSB+IGxvZyhTbmF0Y2guLmtnLikgKyBCb2R5d2VpZ2h0Li5rZy4gKyBHZW5kZXIsIGRhdGEgPSBMaWZ0aW5nLmRhdGEpCnN1bW1hcnkobG9nLnNuYXRjaC5sbSkKcGxvdChsb2cuc25hdGNoLmxtLCB3aGljaCA9IDEpCmBgYAoKIyMgQW5hbHlzaXMKCjEuIEluIHRoZSBtb2RlbCB3aXRoIENsZWFuLWFuZC1KZXJrIHZhcmlhYmxlLCB0aGUgUi1zcXVhcmVkIGlzIC45OSB3aGljaCBpcyBleHRyZW1lbHkgZ29vZC4gSG93ZXZlciwgdGhlIHJlZ3Jlc3Npb24gbGluZSBpbiB0aGUgcGxvdCBoYXMgYSBsb3Qgb2YgcmVzaWR1YWwgZXJyb3JzIHdpdGggdGhlIHZhbHVlIG9mIDUuOC4gT25lIHRoaW5nIHRoYXQgaXMgaW50ZXJlc3RpbmcgYWJvdXQgdGhlIG1vZGVsIGlzIHRoYXQgdGhlIHAtdmFsdWUgZm9yIHRoZSBib2R5d2VpZ2h0IGNvZWZmaWNpZW50IGlzIC45My4gQSB2YXJpYWJsZSB3aXRoIHRoYXQgaGlnaCBvZiBhIHAtdmFsdWUgaXMgaXJyZWxldmFudCB0byB0aGUgbW9kZWwuIAoKMi4gSW4gdGhlIG1vZGVsIHdpdGggdGhlIFNuYXRjaCwgdGhlIFItc3F1YXJlZCBhbmQgdGhlIHJlZ3Jlc3Npb24gbGluZSBzdGF5IHRoZSBzYW1lIGJ1dCBhbGwgcC12YWx1ZXMgZm9yIHRoZSB2YXJpYWJsZXMgYXJlIHZlcnkgbG93LiBUaGF0IG1lYW5zIHRoYXQgYWxsIHZhcmlhYmxlcyBhcmUgcmVsZXZhbnQgdG8gdGhlIGV4cGxvcmF0b3J5IHZhcmlhYmxlIGFuZCB0aGF0IG1ha2VzIHRoaXMgbW9kZWwgYmV0dGVyIHRoYW4gdGhlIHByZXZpb3VzIG9uZS4gSG93ZXZlciwgd2Ugd2FudCB0byBtYWtlIGl0IGV2ZW4gYmV0dGVyIGFuZCB3ZSBkbyBzbyBieSB0cmFuc2Zvcm1pbmcgc29tZSBvZiB0aGUgdmFyaWFibGVzLgoKMy4gQnkgdGFraW5nIHRoZSBsb2dhcml0aG0gb2YgdGhlIGV4cGxvcmF0b3J5IHZhcmlhYmxlIGFuZCB0aGUgbG9nYXJpdGhtIG9mIHRoZSBzbmF0Y2ggdmFyaWFibGUgbWFrZXMgdGhpcyBtb2RlbCB0aGUgaWRlYWwgcmVncmVzc2lvbiBtb2RlbC4gVGhlIFItc3F1YXJlZCBzdGF5cyBhdCAuOTkgYnV0IHRoZSByZXNpZHVhbCBzdGFuZGFyZCBlcnJvciB3ZW50IGRvd24gdG8gLjAyLiBUaGlzIGlzIG91ciBmaW5hbCBtb2RlbC4KCiAgKiBUaGUgbGluZWFyIGNvbWJpbmF0aW9uIGZvciBXb21lbiBpczogCiAgICArIGxvZyhUb3RhbCkgPSAxLjE2ICsgLjkyIGxvZyhTbmF0Y2gpICsgLjAwMDMgQm9keXdlaWdodAoKICAqIFRoZSBsaW5lYXIgY29tYmluYXRpb24gZm9yIE1lbiBpczoKICAgICsgbG9nKFRvdGFsKSA9IDEuMTggKyAuOTIgbG9nKFNuYXRjaCkgKyAuMDAwMyBCb2R5d2VpZ2h0CgoKCiMgKipTZWN0aW9uIDMqKgoKIyMgQ29tcGFyaW5nIHZhcmlhYmxlcyBpbiBkaWZmZXJlbnQgZ3JvdXBzIAoKKiBIYXZlIE1lbiBhbmQgV29tZW4gaW1wcm92ZWQgc2lnbmlmaWNhbnRseSBpbiBPbHltcGljIFdlaWdodGxpZnRpbmcgZnJvbSB0aGUgeWVhciAyMDAwIHRvIDIwMjA/IAoKKiBUbyBkbyB0aGlzIHRlc3Qgd2UgYXJlIGdvaW5nIHRvIGNvbXBhcmUgbWVuIGFuZCB3b21lbiBzZXBhcmF0ZWx5IGFuZCBvbmx5IHVzZSB0aGUgZGF0YSBmcm9tIHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyBhbmQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzLiAKICAgIAojIyBHcmFwaGljYWwgQW5hbHlzaXMgCgpgYGB7cn0KTGlmdGluZ01lbiRZZWFyIDwtIGFzLmNoYXJhY3RlcihMaWZ0aW5nTWVuJFllYXIpCkxpZnRpbmdXb21lbiRZZWFyIDwtIGFzLmNoYXJhY3RlcihMaWZ0aW5nV29tZW4kWWVhcikKCmJveC5tZW4gPC0gTGlmdGluZ01lbiAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIGZpbHRlcihZZWFyID09IDIwMDAgfCBZZWFyID09IDIwMjApICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gVG90YWwuLmtnLiwgZmlsbCA9IFllYXIpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IlBhc3RlbDIiKSArCiAgeWxhYigiVG90YWwgV2VpZ2h0IGluIEtnIikgKwogIGxhYnMoc3VidGl0bGUgPSAiTWVuIikgKwogIHRoZW1lX2lwc3VtKCkKCmJveC53b21lbiA8LSBMaWZ0aW5nV29tZW4gJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBmaWx0ZXIoWWVhciA9PSAyMDAwIHwgWWVhciA9PSAyMDIwKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFRvdGFsLi5rZy4sIGZpbGwgPSBZZWFyKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJQYXN0ZWwyIikgKwogIHlsYWIoIlRvdGFsIFdlaWdodCBpbiBLZyIpICsKICBsYWJzKHN1YnRpdGxlID0gIldvbWVuIikgKwogIHRoZW1lX2lwc3VtKCkKCmJveC5wbG90IDwtIGdnYXJyYW5nZShib3gubWVuLCBib3gud29tZW4sCiAgICAgICAgICAgICAgICAgIGNvbW1vbi5sZWdlbmQgPSBUUlVFLAogICAgICAgICAgICAgICAgICBuY29sID0gMiwgbnJvdyA9IDEsIGxlZ2VuZCA9ICJib3R0b20iKQphbm5vdGF0ZV9maWd1cmUoYm94LnBsb3QsIHRvcCA9IHRleHRfZ3JvYigiVG90YWwgV2VpZ2h0IGRpZmZlcmVuY2UgYmV0d2VlbiAyMDAwIGFuZCAyMDIwIFN1bW1lciBPbHltcGljcyIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCkpCmBgYAoKKiBUaGUgYm94IHBsb3RzIHByZXNlbnRlZCBzaG93IGRpZmZlcmVudCB0aGluZ3MgZm9yIHRoZSB3b21lbidzIGNhdGVnb3J5IGFuZCB0aGUgbWVuJ3MgY2F0ZWdvcnkuIE91ciByZXNlYXJjaCBxdWVzdGlvbiBhc2tzIGlmIHRoZSB0b3RhbCB3ZWlnaHQgaXMgaGlnaGVyIGluIDIwMjAgdGhhbiBpbiAyMDAwLiBJbiB0aGUgbWVu4oCZcyBjYXRlZ29yeSBpdCBsb29rcyBsaWtlIG9uIGF2ZXJhZ2UgdGhlIGF0aGxldGVzIGxpZnRlZCBoZWF2aWVyIGluIDIwMDAuIFRoZSBzcHJlYWQgaXMgbG9uZ2VyIGluIDIwMDAgYnV0IGl0IGhhcyBhIGhpZ2hlciBtZWRpYW4uIEluIHRoZSB3b21lbuKAmXMgY2F0ZWdvcnkgaXQgc2VlbXMgbGlrZSB0aGUgd29tZW4gZ290IHN0cm9uZ2VyIGluIHRoZSB0d2VudHkteWVhciBzcGFuLiBUaGUgc3ByZWFkIGlzIGJpZ2dlciBpbiAyMDAwIGJ1dCB5b3UgY2FuIHNlZSB0aGF0IHRoZSBtZWRpYW4gbGluZSBhbmQgdGhlIHRoaXJkIHF1YXJ0ZXIgYXJlIGhpZ2hlciBpbiAyMDIwLiBIb3dldmVyLCB0aGVyZSBpcyBvbmUgb3V0bGllciBpbiAyMDIwIHRoYXQgc2VlbXMgdG8gcmVwcmVzZW50IG9uZSBhdGhsZXRlIHRoYXQgbGlmdGVkIHNpZ25pZmljYW50bHkgaGVhdmllciB0aGFuIHRoZSByZXN0LiBJZiB3ZSB3b3VsZCBiZSBpbnRlcmVzdGVkIGluIGRvaW5nIGZ1cnRoZXIgcmVzZWFyY2gsIHdlIGNvdWxkIHRha2UgdGhlIG91dGxpZXIgaW4gMjAyMCBvdXQgb2YgdGhlIGRhdGEgYW5kIHNlZSBpZiB0aGUgcmVzdWx0cyBhcmUgZGlmZmVyZW50LiAKCiMjIE1lbgoKIyMjIEFkZGl0aW9uYWwgZ3JhcGhpY2FsIGFuYWx5c2lzCgpgYGB7cn0KZGVuc2l0eS5tZW4gPC0gTGlmdGluZ01lbiAlPiUgCiAgZmlsdGVyKFllYXIgPT0gMjAwMCB8IFllYXIgPT0gMjAyMCkgJT4lIAogIGdncGxvdChhZXMoeCA9IFRvdGFsLi5rZy4sIHkgPSBZZWFyLCBmaWxsID0gc3RhdCh4KSwgYWxwaGEgPSAwLjcpKSArCiAgZ2VvbV9kZW5zaXR5X3JpZGdlc19ncmFkaWVudChzY2FsZSA9IDMsIHJlbF9taW5faGVpZ2h0ID0gMC4wMSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV9maWxsX3ZpcmlkaXMobmFtZSA9ICJUb3RhbCBXZWlnaHQiLCBvcHRpb24gPSAiQyIpICsKICBsYWJzKHRpdGxlID0gJ0RpZmZlcmVuY2UgaW4gTWVucyB0b3RhbCB3ZWlnaHQnKSArCiAgeGxhYigiVG90YWwgV2VpZ2h0IGluIEtnIikgKwogIHRoZW1lX2lwc3VtKCkKZGVuc2l0eS5tZW4KYGBgCgoqIEJ5IHRoZSBsb29rIG9mIHRoZSBkZW5zaXR5IHBsb3QsIGl0IGxvb2tzIGxpa2UgdGhhdCBpbiAyMDAwIHRoZSBsaWdodGVzdCB3ZWlnaHQgaXMgbG93ZXIgdGhhbiBpbiAyMDIwIGJ1dCB0aGVyZSBhcmUgbW9yZSBkZW5zaXR5IG9uIHRoZSByaWdodCBzaWRlIG9mIHRoZSBwbG90LiBJdCBpcyB0aGUgb3Bwb3NpdGUgZm9yIHRoZSB5ZWFyIDIwMjAuIFRoZSBoZWF2aWVzdCB3ZWlnaHQgbGlmdGVkIGxvb2tzIGxpa2UgaXQgd2FzIGEgbGl0dGxlIGhlYXZpZXIgdGhhbiBpbiAyMDAwIGJ1dCBtb3N0IG9mIHRoZSBkZW5zaXR5IGlzIG9uIHRoZSBsZWZ0IHNpZGUgb2YgdGhlIHBsb3QuCgojIyMgSHlwb3RoZXNpczoKCiogSDA6IMK1MjAwMCA9IMK1MjAyMCAgCgoqIEjOsTogwrUyMDAwIDwgwrUyMDIwIAoKIyMjIE9uZS1TaWRlZCBULVRlc3QKCmBgYHtyfQojIFNlcGVyYXRpbmcgTWVucyBTdW1tZXIgT2x5bXBpY3MgMjAwMCBhbmQgMjAyMAoKTWVuMjAwMCA8LSBMaWZ0aW5nTWVuICU+JSAKICBmaWx0ZXIoWWVhciA9PSAyMDAwKQoKTWVuMjAyMCA8LSBMaWZ0aW5nTWVuICU+JSAKICBmaWx0ZXIoWWVhciA9PSAyMDIwKQpgYGAKCmBgYHtyfQp0LnRlc3QoTWVuMjAyMCRUb3RhbC4ua2cuLCBNZW4yMDAwJFRvdGFsLi5rZy4sIHBhaXJlZCA9IEZBTFNFLCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikKYGBgCgojIyMgQW5hbHlzaXMKCiogV2l0aCBhIHAtdmFsdWUgb2YgMC41IHdlIGFyZSBub3QgYWJsZSB0byByZWplY3QgdGhlIEgwIG9uIGEgNSUgc2lnbmlmaWNhbmNlIGxldmVsLiBUaGUgdCB2YWx1ZSBpcyBuZWdhdGl2ZSBhbmQgdGhhdCBpbmRpY2F0ZXMgdGhhdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGdyb3VwcyBoYXMgYSBuZWdhdGl2ZSBzbG9wZS4gSG93ZXZlciwgaWYgeW91IGxvb2sgYXQgdGhlIG1lYW4gZm9yIGJvdGggZ3JvdXBzLCB0aGV5IGFyZSBhbG1vc3QgZXF1YWwuIExpa2UgdGhlIGdyYXBoaWNhbCBhbmFseXNpcyBzaG93ZWQsIHRoZSBtZW4gaW4gMjAyMCBkaWQgbm90IGxpZnQgaGVhdmllciB0aGFuIHRoZSBtZW4gaW4gMjAwMC4gCgojIyBXb21lbgoKIyMjIEFkZGl0aW9uYWwgZ3JhcGhpY2FsIGFuYWx5c2lzCgpgYGB7cn0KZGVuc2l0eS53b21lbiA8LSBMaWZ0aW5nV29tZW4gJT4lIAogIGZpbHRlcihZZWFyID09IDIwMDAgfCBZZWFyID09IDIwMjApICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBUb3RhbC4ua2cuLCB5ID0gWWVhciwgZmlsbCA9IHN0YXQoeCksIGFscGhhID0gMC43KSkgKwogIGdlb21fZGVuc2l0eV9yaWRnZXNfZ3JhZGllbnQoc2NhbGUgPSAzLCByZWxfbWluX2hlaWdodCA9IDAuMDEsIGFscGhhID0gMC41KSArCiAgc2NhbGVfZmlsbF92aXJpZGlzKG5hbWUgPSAiVG90YWwgV2VpZ2h0Iiwgb3B0aW9uID0gIkMiKSArCiAgbGFicyh0aXRsZSA9ICdEaWZmZXJlbmNlIGluIFdvbWVucyB0b3RhbCB3ZWlnaHQnKSArCiAgeGxhYigiVG90YWwgV2VpZ2h0IGluIEtnIikgKwogIHRoZW1lX2lwc3VtKCkKZGVuc2l0eS53b21lbgpgYGAKCiogVGhlIGRlbnNpdHkgcGxvdCBmb3IgdGhlIHllYXIgMjAyMCBpcyB3YXkgbW9yZSBvbiB0aGUgcmlnaHQgdGhhbiB0aGUgb25lIGZvciAyMDAwLiBUaGUgbGlnaHRlc3QgYW5kIHRoZSBoZWF2aWVzdCB3ZWlnaHQgbGlmdGVkIGluIDIwMjAgd2VyZSB3YXkgaGlnaGVyIHRoYW4gaW4gMjAwMC4gVGhlIGRhdGEgZnJvbSAyMDIwIGhhcyBhIHZlcnkgbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aGVyZSB0aGUgaGlnaGVzdCBkZW5zaXR5IGlzIGluIHRoZSBtaWRkbGUuIEZvciB0aGUgeWVhciAyMDAwLCB0aGUgZGVuc2l0eSBpcyBoaWdoIGluIHR3byBwbGFjZXMuIFRoYXQgY291bGQgcG9pbnQgb3V0IHRoYXQgYWJvdXQgaGFsZiBvZiB0aGUgYXRobGV0ZXMgbGlmdGVkIGxpZ2h0bHkgd2hpbGUgdGhlIG90aGVyIGhhbGYgbGlmdGVkIGEgbG90IGhlYXZpZXIgYW5kIG5vdCBhcyBtdWNoIGJhbGFuY2UgYXMgdGhlcmUgd2FzIGluIDIwMjAuCgojIyMgSHlwb3RoZXNpcwoKKiBIMDogwrUyMDAwID0gwrUyMDIwICAKCiogSM6xOiDCtTIwMDAgPCDCtTIwMjAgCiAgICAgIAojIyMgT25lLVNpZGVkIFQtVGVzdCAgCgpgYGB7cn0KIyBTZXBlcmF0aW5nIFdvbWVucyBTdW1tZXIgT2x5bXBpY3MgMjAwMCBhbmQgMjAyMAoKV29tZW4yMDAwIDwtIExpZnRpbmdXb21lbiAlPiUgCiAgZmlsdGVyKFllYXIgPT0gMjAwMCkKCldvbWVuMjAyMCA8LSBMaWZ0aW5nV29tZW4gJT4lIAogIGZpbHRlcihZZWFyID09IDIwMjApCmBgYAoKYGBge3J9CnQudGVzdChXb21lbjIwMjAkVG90YWwuLmtnLiwgV29tZW4yMDAwJFRvdGFsLi5rZy4sIHBhaXJlZCA9IEZBTFNFLCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikKYGBgCgojIyMgQW5hbHlzaXMKCiogV2l0aCBhIHAtdmFsdWUgb2YgMC4wMjIgd2UgY2FuIHJlamVjdCB0aGUgcC12YWx1ZSBvbiBhIDUlIHNpZ25pZmljYW5jZSBsZXZlbC4gVGhlIHQgdmFsdWUgaXMgcG9zaXRpdmUgd2hpY2ggcmVwcmVzZW50cyBhIHBvc2l0aXZlIHNsb3BlIGJldHdlZW4gdGhlIGdyb3Vwcy4gVGhlIG1lYW5zIGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBhcyB3ZWxsLiBUaGUgd29tZW4gaW4gMjAyMCBsaWZ0ZWQgc2lnbmlmaWNhbnRseSBoZWF2aWVyIHRoYW4gdGhlIHdvbWVuIGluIDIwMDAuIAoKCgojICoqU2VjdGlvbiA0KioKCiMjIENvbnRyYXN0IGFuZCBMaW5lYXIgQ29tYmluYXRpb24gQ29tcGFyaXNvbnMgCgoqIERvZXMgYSBoaWdoZXIgYm9keXdlaWdodCBpbmNyZWFzZSB5b3VyIHRvdGFsIHdlaWdodCBpbiBPbHltcGljIFdlaWdodGxpZnRpbmc/IAoKKiBXZSB3aWxsIGJlIHRlc3RpbmcgbWVuIGFuZCB3b21lbiBzZXBhcmF0ZWx5IGFuZCB1c2luZyBkYXRhIGZyb20gdGhlIDIwMDAgYW5kIDIwMjAgU3VtbWVyIE9seW1waWNzLiBXZSBoYXZlIGEgdG90YWwgb2YgMTQgYm9keXdlaWdodCBjYXRlZ29yaWVzIGZvciBib3RoIG1lbiBhbmQgd29tZW4uICAKICAgIAojIyBHcmFwaGljYWwgQW5hbHlzaXMKCmBgYHtyfQojIFNlcGFyYXRpbmcgbGlnaHQgYm9keXdlaWdodCBhbmQgaGVhdnkgYm9keXdlaWdodCBpbnRvIG1lbnMgYW5kIHdvbWVucyBkYXRhIGZyYW1lcyBmcm9tIHRoZSBZZWFycyAyMDAwIGFuZCAyMDIwCgpNZW4ubG93LmJvZHl3ZWlnaHQgPC0gTGlmdGluZy5kYXRhICU+JSAKICBncm91cF9ieShUaXRsZSkgJT4lIAogIGZpbHRlcihHZW5kZXIgPT0gIk1lbiIgJiYgCiAgICAgICAgICAgWWVhciA9PSAyMDAwICYmIAogICAgICAgICAgIFRpdGxlID09ICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNTYga2ciIHwgCiAgICAgICAgICAgVGl0bGUgPT0gIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyA2MiBrZyIgfCAKICAgICAgICAgICBUaXRsZSA9PSAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDY5IGtnIiB8IAogICAgICAgICAgIFRpdGxlID09ICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNzcga2ciIHwgCiAgICAgICAgICAgWWVhciA9PSAyMDIwICYmCiAgICAgICAgICAgVGl0bGUgPT0gICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNjEga2ciIHwgCiAgICAgICAgICAgVGl0bGUgPT0gICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNjcga2ciIHwgCiAgICAgICAgICAgVGl0bGUgPT0gIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyA3MyBrZyIpCgpNZW4uaGlnaC5ib2R5d2VpZ2h0IDwtIExpZnRpbmcuZGF0YSAlPiUgCiAgZ3JvdXBfYnkoVGl0bGUpICU+JSAKICBmaWx0ZXIoR2VuZGVyID09ICJNZW4iICYmIAogICAgICAgICAgIFllYXIgPT0gMjAwMCAmJiAKICAgICAgICAgICBUaXRsZSA9PSAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDg1IGtnIiB8IAogICAgICAgICAgIFRpdGxlID09ICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgOTQga2ciIHwgCiAgICAgICAgICAgVGl0bGUgPT0gIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyAxMDUga2ciIHwgCiAgICAgICAgICAgVGl0bGUgPT0gIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyArMTA1IGtnIiB8IAogICAgICAgICAgIFllYXIgPT0gMjAyMCAmJgogICAgICAgICAgIFRpdGxlID09ICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAyMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzICsxMDkga2ciIHwgCiAgICAgICAgICAgVGl0bGUgPT0gICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgMTA5IGtnIiB8IAogICAgICAgICAgIFRpdGxlID09ICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgODEga2ciKQpgYGAKCmBgYHtyfQptZW4uMjAwMC5wbG90IDwtIE1lbjIwMDAgJT4lIAogIGdyb3VwX2J5KFRpdGxlKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gVGl0bGUsIHkgPSBUb3RhbC4ua2cuLCBmaWxsID0gVGl0bGUpKSArCiAgZ2VvbV9ib3hwbG90KCkgKyAKICB5bGltKDE1MCwgNTAwKSArCiAgeWxhYigiVG90YWwgV2VpZ2h0IGluIEtnIikgKwogIGxhYnMoc3VidGl0bGUgPSAiMjAwMCBTdW1tZXIgT2x5bXBpY3MiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgKICAgIG5hbWUgPSAiQ2F0ZWdvcnkiLAogICAgbGltaXRzID0gYygiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDU2IGtnIiwgCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNjIga2ciLCAKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyA2OSBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNzcga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDg1IGtnIiwKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyA5NCBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgMTA1IGtnIiwKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyArMTA1IGtnIiksCiAgICBsYWJlbHM9YygnICcsICcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcsICcgJywgJyAnKSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUoCiAgICBicmVha3MgPSBjKCJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNTYga2ciLCAKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyA2MiBrZyIsIAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDY5IGtnIiwKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyA3NyBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgODUga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDk0IGtnIiwKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyAxMDUga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzICsxMDUga2ciKSwKICAgIGxhYmVscyA9IGMoIjU2IGtnIiwgCiAgICAgICAgICAgICAgICI2MiBrZyIsIAogICAgICAgICAgICAgICAiNjkga2ciLCAKICAgICAgICAgICAgICAgIjc3IGtnIiwgCiAgICAgICAgICAgICAgICI4NSBrZyIsCiAgICAgICAgICAgICAgICI5NCBrZyIsCiAgICAgICAgICAgICAgICIxMDUga2ciLAogICAgICAgICAgICAgICAiKzEwNSBrZyIpLAogICAgbmFtZSA9ICIgIikgKyAKICB0aGVtZV9pcHN1bSgpCgptZW4uMjAyMC5wbG90IDwtIE1lbjIwMjAgJT4lIAogIGdyb3VwX2J5KFRpdGxlKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gVGl0bGUsIHkgPSBUb3RhbC4ua2cuLCBmaWxsID0gVGl0bGUpKSArCiAgZ2VvbV9ib3hwbG90KCkgKyAKICB5bGltKDE1MCwgNTAwKSArCiAgeWxhYigiVG90YWwgV2VpZ2h0IGluIEtnIikgKwogIGxhYnMoc3VidGl0bGUgPSAiMjAyMCBTdW1tZXIgT2x5bXBpY3MiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgKICAgIG5hbWUgPSAiQ2F0ZWdvcnkiLAogICAgbGltaXRzID0gYygiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAyMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDYxIGtnIiwgCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNjcga2ciLCAKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyA3MyBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgODEga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAyMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDEwOSBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgKzEwOSBrZyIpLAogICAgbGFiZWxzPWMoJyAnLCAnICcsICcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcsICcgJykpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKAogICAgYnJlYWtzID0gYygiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAyMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDYxIGtnIiwgCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgNjcga2ciLCAKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBNZW4ncyA3MyBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgODEga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAyMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIE1lbidzIDEwOSBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgTWVuJ3MgKzEwOSBrZyIpLAogICAgbGFiZWxzID0gYygiNjEga2ciLCAKICAgICAgICAgICAgICAgIjY3IGtnIiwgCiAgICAgICAgICAgICAgICI3MyBrZyIsIAogICAgICAgICAgICAgICAiODEga2ciLCAKICAgICAgICAgICAgICAgIjEwOSBrZyIsCiAgICAgICAgICAgICAgICIrMTA5IGtnIiksCiAgICBuYW1lID0gIiAiKSArIAogIHRoZW1lX2lwc3VtKCkKCmdnYXJyYW5nZShtZW4uMjAwMC5wbG90LCBtZW4uMjAyMC5wbG90LCAKICAgICAgICAgIGxhYmVscyA9IGMoIlRvdGFsIFdlaWdodCBiZXR3ZWVuIE1lbidzIENhdGVnb3JpZXMiKSwKICAgICAgICAgIG5jb2wgPSAyLCBucm93ID0gMSwgbGVnZW5kID0gImJvdHRvbSIpCmBgYAoKYGBge3J9CndvbWVuLjIwMDAucGxvdCA8LSBXb21lbjIwMDAgJT4lIAogIGdyb3VwX2J5KFRpdGxlKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gVGl0bGUsIHkgPSBUb3RhbC4ua2cuLCBmaWxsID0gVGl0bGUpKSArCiAgZ2VvbV9ib3hwbG90KCkgKyAKICB5bGltKDExMCwgMzI1KSArCiAgeWxhYigiVG90YWwgV2VpZ2h0IGluIEtnIikgKwogIGxhYnMoc3VidGl0bGUgPSAiMjAwMCBTdW1tZXIgT2x5bXBpY3MiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgKICAgIG5hbWUgPSAiQ2F0ZWdvcnkiLAogICAgbGltaXRzID0gYygiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIFdvbWVuJ3MgNDgga2ciLCAKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBXb21lbidzIDUzIGtnIiwgCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA1OCBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA2MyBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA2OSBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA3NSBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyArNzUga2ciKSwKICAgIGxhYmVscz1jKCcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcpKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZSgKICAgIGJyZWFrcyA9IGMoIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMDAgU3VtbWVyIE9seW1waWNzIOKAkyBXb21lbidzIDQ4IGtnIiwgCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDAwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA1MyBrZyIsIAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIFdvbWVuJ3MgNTgga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIFdvbWVuJ3MgNjMga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIFdvbWVuJ3MgNjkga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIFdvbWVuJ3MgNzUga2ciLAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAwMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIFdvbWVuJ3MgKzc1IGtnIiksCiAgICBsYWJlbHMgPSBjKCI0OCBrZyIsIAogICAgICAgICAgICAgICAiNTMga2ciLCAKICAgICAgICAgICAgICAgIjU4IGtnIiwgCiAgICAgICAgICAgICAgICI2MyBrZyIsIAogICAgICAgICAgICAgICAiNjkga2ciLAogICAgICAgICAgICAgICAiNzUga2ciLAogICAgICAgICAgICAgICAiKzc1IGtnIiksCiAgICBuYW1lID0gIiAiKSArIAogIHRoZW1lX2lwc3VtKGJhc2VfZmFtaWx5ID0gIkFyaWFsIE5hcnJvdyIpCgoKd29tZW4uMjAyMC5wbG90IDwtIFdvbWVuMjAyMCAlPiUgCiAgZ3JvdXBfYnkoVGl0bGUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBUaXRsZSwgeSA9IFRvdGFsLi5rZy4sIGZpbGwgPSBUaXRsZSkpICsKICBnZW9tX2JveHBsb3QoKSArIAogIHlsaW0oMTEwLCAzMjUpICsKICB5bGFiKCJUb3RhbCBXZWlnaHQgaW4gS2ciKSArCiAgbGFicyhzdWJ0aXRsZSA9ICIyMDIwIFN1bW1lciBPbHltcGljcyIpICsKICBzY2FsZV94X2Rpc2NyZXRlKAogICAgbmFtZSA9ICJDYXRlZ29yeSIsCiAgICBsaW1pdHMgPSBjKCJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA0OSBrZyIsIAogICAgICAgICAgICAgICAiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAyMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIFdvbWVuJ3MgNTUga2ciLCAKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBXb21lbidzIDU5IGtnIiwKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBXb21lbidzIDY0IGtnIiwKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBXb21lbidzIDc2IGtnIiwKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBXb21lbidzIDg3IGtnIiwKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBXb21lbidzICs4NyBrZyIpLAogICAgbGFiZWxzPWMoJyAnLCAnICcsICcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcsICcgJykpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKAogICAgYnJlYWtzID0gYygiV2VpZ2h0bGlmdGluZyBhdCB0aGUgMjAyMCBTdW1tZXIgT2x5bXBpY3Mg4oCTIFdvbWVuJ3MgNDkga2ciLCAKICAgICAgICAgICAgICAgIldlaWdodGxpZnRpbmcgYXQgdGhlIDIwMjAgU3VtbWVyIE9seW1waWNzIOKAkyBXb21lbidzIDU1IGtnIiwgCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA1OSBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA2NCBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA3NiBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyA4NyBrZyIsCiAgICAgICAgICAgICAgICJXZWlnaHRsaWZ0aW5nIGF0IHRoZSAyMDIwIFN1bW1lciBPbHltcGljcyDigJMgV29tZW4ncyArODcga2ciKSwKICAgIGxhYmVscyA9IGMoIjQ5IGtnIiwgCiAgICAgICAgICAgICAgICI1NSBrZyIsIAogICAgICAgICAgICAgICAiNTkga2ciLCAKICAgICAgICAgICAgICAgIjY0IGtnIiwgCiAgICAgICAgICAgICAgICI3NiBrZyIsCiAgICAgICAgICAgICAgICI4NyBrZyIsCiAgICAgICAgICAgICAgICIrODcga2ciKSwKICAgIG5hbWUgPSAiICIpICsgCiAgdGhlbWVfaXBzdW0oYmFzZV9mYW1pbHkgPSAiQXJpYWwgTmFycm93IikKCmdnYXJyYW5nZSh3b21lbi4yMDAwLnBsb3QsIHdvbWVuLjIwMjAucGxvdCwKICAgICAgICAgIGxhYmVscyA9IGMoIlRvdGFsIFdlaWdodCBiZXR3ZWVuIFdvbWVuJ3MgQ2F0ZWdvcmllcyIpLAogICAgICAgICAgbmNvbCA9IDIsIG5yb3cgPSAxLCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgoqIEluIGFsbCBmb3VyIGJveCBwbG90cyBwcmVzZW50ZWQsIHRoZXkgYWxsIGhhdmUgdGhlIHNhbWUgdHJlbmQgb2Ygc2hvd2luZyBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGVhY2ggZ3JvdXAuIFRoZXJlIGlzIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiBlYWNoIHdlaWdodCBjYXRlZ29yeSB3aXRoIGJvdGggZ2VuZGVycyBpbiBib3RoIE9seW1waWNzLiBCeSBsb29raW5nIGF0IHRoZSB2YWx1ZXMgb2YgdGhlIGxlZ2VuZHMgZm9yIGJvdGggZ2VuZGVycywgdGhlIDIwMjAgT2x5bXBpY3MgaW5jcmVhc2VkIHRoZWlyIHdlaWdodCBpbiB0aGUgYm9keXdlaWdodCBjYXRlZ29yaWVzLiBGb3Igd29tZW4gdGhhdCBkaWQgbm90IGNoYW5nZSB0aGUgdHJlbmQgb2YgdGhlIGJveCBwbG90LiBGb3IgbWVuIGhvd2V2ZXIsIGluIHRoZSAyMDIwIGJveCBwbG90IHRoZXJlIGlzIG5vdCBhIGJpZyBkaWZmZXJlbmNlIGluIHRoZSB0b3RhbCB3ZWlnaHQgaW4gdGhlIHRvcCB0d28gY2F0ZWdvcmllcy4gRG9lcyB0aGF0IG1lYW4gdGhhdCBpdCB3YXMgdW5uZWNlc3NhcnkgZm9yIHRoZSBjaGFuZ2UgaW4gY2F0ZWdvcmllcz8gRm9yIG1lbiwgdGhlIGludGVycXVhcnRpbGUgcmFuZ2VzIGluIDIwMDAgYXJlIHdheSBsYXJnZXIgdGhhbiB0aGUgb25lcyBpbiAyMDIwIGFuZCBpZiB3ZSBmb2N1cyBvbiB0aGUgbWVkaWFuIGxpbmUsIGl0IGlzIGhpZ2hlciBpbiAyMDIwLiBTbywgdGhlIGNoYW5nZSBvZiBib2R5d2VpZ2h0IGNhdGVnb3JpZXMgd2FzIHN1Y2Nlc3NmdWwgaW4gdGhlIG1lbuKAmXMgY2F0ZWdvcnkuIEZvciB0aGUgd29tZW4gaG93ZXZlciwgaXQgaXMgdGhlIG9wcG9zaXRlLiBGb3IgdGhlIGhlYXZpZXN0IGNhdGVnb3J5LCB0aGUgaW50ZXJxdWFydGlsZSByYW5nZXMgYXJlIGxhcmdlciBpbiAyMDIwIGFuZCB0aGUgbWVkaWFuIGlzIGhpZ2hlciBpbiAyMDAwLiBUaGF0IGltcGxpZXMgdGhhdCBpdCBjb3VsZCBoYXZlIGJlZW4gdW5uZWNlc3NhcnkgZm9yIHRoZSBjYXRlZ29yeSBjaGFuZ2UuIFNvbWUgY291bGQgYXJndWUgYW5kIHNheSB0aGF0IG1heWJlIHRoZSB3b21lbiB3ZXJlIHN0cm9uZ2VyIGluIDIwMDAgYnV0IHdlIGhhdmUgYWxyZWFkeSBkb25lIHN0YXRpc3RpY2FsIHRlc3RpbmcgYW5kIHByb3ZlbiB0aGF0IHRoYXQgaXMgaW5jb3JyZWN0LiAKCiMjIE1ldGhvZHMgJiBUZXN0aW5nIAoKKiBTdGVwIDEsIHdlIHRlc3QgaWYgYWxsIGJvZHl3ZWlnaHQgY2F0ZWdvcmllcyBoYXZlIHRoZSBzYW1lIG1lYW4gaW4gdG90YWwgd2VpZ2h0LiBUaGUgYmVzdCB3YXkgZm9yIHRoYXQgaXMgdG8gZG8gaHlwb3RoZXNpcyB0ZXN0aW5nIGJ5IGZpdHRpbmcgYW4gQW5hbHlzaXMgb2YgVmFyaWFuY2UgTW9kZWwgaW50byBhbiBBbm92YSB0ZXN0LiAKCiogU3RlcCAyLCB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBjb21wYXJpbmcgdGhlIGF2ZXJhZ2UgdG90YWwgd2VpZ2h0IG9mIHRoZSBoZWF2aWVzdCBib2R5d2VpZ2h0IGNhdGVnb3JpZXMgdnMuIGxpZ2h0ZXN0IGJvZHl3ZWlnaHQgY2F0ZWdvcmllcy4gVGhlIGJlc3Qgd2F5IG9mIHRlc3RpbmcgaXMgdG8gQ29tcHV0ZSBhbmQgdGVzdCBhcmJpdHJhcnkgY29udHJhc3RzIGZvciByZWdyZXNzaW9uIG9iamVjdHMuICAKICAgIAojIyBTdGVwIDEKCiMjIyBIeXBvdGhlc2lzCgoqIE1lbiAKCiAgKyBIMDogwrU1NmtnID0gwrU2MWtnID0gwrU2MmtnID0gwrU2N2tnID0gwrU2OWtnID0gwrU3M2tnID0gwrU3N2tnID0gwrU4MWtnID0gwrU4NWtnID0gwrU5NGtnID0gwrUxMDVrZyA9IMK1MTA1K2tnID0gwrUxMDlrZyA9IMK1MTA5K2tnIAoKICArIEjOsTogQXQgbGVhc3Qgb25lIG1lYW4gaXMgZGlmZmVyZW50IAogICAgICAKKiBXb21lbiAKCiAgKyBIMDogwrU0OGtnID0gwrU0OWtnID0gwrU1M2tnID0gwrU1NWtnID0gwrU1OGtnID0gwrU1OWtnID0gwrU2M2tnID0gwrU2NGtnID0gwrU2OWtnID0gwrU3NWtnID0gwrU3NStrZyA9IMK1NzZrZyA9IMK1ODdrZyA9IMK1ODcra2cgCgogICsgSM6xOiBBdCBsZWFzdCBvbmUgbWVhbiBpcyBkaWZmZXJlbnQgCiAgICAgIAojIyMgQW5hbHlzaXMgb2YgVmFyaWFuY2UKCiogTWVuCiAgICAgIApgYGB7cn0KIyBEYXRhIGZyYW1lIHdpdGggb25seSBtYWxlcyBhdGhsZXRlcyBmcm9tIDIwMDAgYW5kIDIwMjAKbWVuLjIwMDAuMjAyMCA8LSBMaWZ0aW5nTWVuICU+JSBmaWx0ZXIoWWVhciA9PSAyMDAwIHwgWWVhciA9PSAyMDIwKSAlPiUgbXV0YXRlKFRpdGxlID0gYXMuZmFjdG9yKFRpdGxlKSkKYGBgCgpgYGB7cn0KbWVuLmFvdiA8LSBhb3YobWVuLjIwMDAuMjAyMCRUb3RhbC4ua2cuIH4gbWVuLjIwMDAuMjAyMCRUaXRsZSkKYW5vdmEobWVuLmFvdikKYGBgCgoqIFdvbWVuCiAgICAKYGBge3J9CiMgRGF0YSBmcmFtZSB3aXRoIG9ubHkgZmVtYWxlIGF0aGxldGVzIGZyb20gMjAwMCBhbmQgMjAyMAp3b21lbi4yMDAwLjIwMjAgPC0gTGlmdGluZ1dvbWVuICU+JSBmaWx0ZXIoWWVhciA9PSAyMDAwIHwgWWVhciA9PSAyMDIwKSAlPiUgbXV0YXRlKFRpdGxlID0gYXMuZmFjdG9yKFRpdGxlKSkKYGBgCgpgYGB7cn0Kd29tZW4uYW92IDwtIGFvdih3b21lbi4yMDAwLjIwMjAkVG90YWwuLmtnLiB+IHdvbWVuLjIwMDAuMjAyMCRUaXRsZSkKYW5vdmEod29tZW4uYW92KQpgYGAKCiMjIyBBbmFseXNpcyBhbmQgY29uY2x1c2lvbgoKKiBCb3RoIGdlbmRlcnMgaGF2ZSBhIHAtdmFsdWUgb2YgMi4yZS0xNiBzbyB3ZSByZWplY3QgYm90aCBudWxsIGh5cG90aGVzaXMgb24gYSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwuIFRoZXJlIGlzIGF0IGxlYXN0IG9uZSBib2R5d2VpZ2h0IGNhdGVnb3J5IGZvciBib3RoIGdlbmRlcnMgdGhhdCBkb2VzIG5vdCBoYXZlIHRoZSBzYW1lIG1lYW4gYXMgYW5vdGhlci4gCiAgICAKKiBUaGUgcC12YWx1ZSBpcyBsZXNzIHRoYW4gMC4wNSBzbyB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgb24gYSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwuCgojIyBTdGVwIDIKCiMjIyBMaW5lYXIgQ29tYmluYXRpb24gIAoKKiBNZW4KICAgIAogICsgKMK1NTZrZyArIMK1NjFrZyArIMK1NjJrZyArIMK1NjdrZyArIMK1NjlrZyArIMK1NzNrZyArIMK1NzdrZykvNyAtICjCtTgxa2cgKyDCtTg1a2cgKyDCtTk0a2cgKyDCtTEwNWtnICsgwrUrMTA1a2cgKyDCtTEwOWtnICsgwrUrMTA5a2cpLzcgPSAwCiAgICAgIAoqIFdvbWVuCiAgICAKICArICjCtTQ4a2cgKyDCtTQ5a2cgKyDCtTUza2cgKyDCtTU1a2cgKyDCtTU4a2cgKyDCtTU5a2cgKyDCtTYza2cpLzcgLSAowrU2NGtnKyDCtTY5a2cgKyDCtTc1a2cgKyDCtSs3NWtnICsgwrU3NmtnICsgwrU4N2tnICsgwrUrODdrZykvNyA9IDAgIAoKIyMjIEh5cG90aGVzaXMgKGJvdGggZ2VuZGVycykgCgoqIEgwOiDCtWxvd2VyID0gwrVoaWdoZXIgIAoKKiBIzrE6IMK1Mmxvd2VyIDwgwrVoaWdoZXIgCgojIyMgVGVzdGluZyAKCiogTWVuOgoKYGBge3J9CmZpdC5jb250cmFzdChtZW4uYW92LCBtZW4uMjAwMC4yMDIwJFRpdGxlLCBjKC0oMS83KSwgLSgxLzcpLCAoMS83KSwgKDEvNyksICgxLzcpLCAoMS83KSwgLSgxLzcpLCAtKDEvNyksIC0oMS83KSwgLSgxLzcpLCAoMS83KSwgKDEvNyksICgxLzcpLCAtKDEvNykpLCBjb25mLmludCA9IDAuOTUpCmBgYAoKKiBXb21lbgoKYGBge3J9CmZpdC5jb250cmFzdCh3b21lbi5hb3YsIHdvbWVuLjIwMDAuMjAyMCRUaXRsZSwgYygtKDEvNyksICgxLzcpLCAoMS83KSwgKDEvNyksICgxLzcpLCAtKDEvNyksIC0oMS83KSwgLSgxLzcpLCAoMS83KSwgKDEvNyksICgxLzcpLCAtKDEvNyksIC0oMS83KSwgLSgxLzcpKSwgY29uZi5pbnQgPSAwLjk1KQpgYGAKCiMjIEFuYWx5c2lzCgojIyMgU3RlcCAxCgoqIEJvdGggZ2VuZGVycyBoYXZlIGEgcC12YWx1ZSBvZiAyLjJlLTE2IHNvIHdlIHJlamVjdCBib3RoIG51bGwgaHlwb3RoZXNpcyBvbiBhIDUlIHNpZ25pZmljYW5jZSBsZXZlbC4gVGhlcmUgaXMgYXQgbGVhc3Qgb25lIGJvZHl3ZWlnaHQgY2F0ZWdvcnkgZm9yIGJvdGggZ2VuZGVycyB0aGF0IGRvZXMgbm90IGhhdmUgdGhlIHNhbWUgbWVhbiBhcyBhbm90aGVyLiAKCiMjIyBTdGVwIDIKCiogRm9yIGJvdGggZ2VuZGVycyB0aGUgcC12YWx1ZSBpcyBzbyBsb3cgdGhhdCB3ZSBjYW4gcmVqZWN0IGJvdGggbnVsbCBoeXBvdGhlc2lzIG9uIGEgNSUgc2lnbmlmaWNhbmNlIGxldmVsLiBUaGUgaGVhdmllciB0aGUgYXRobGV0ZSBpcywgdGhlIGhlYXZpZXIgaGlzIHRvdGFsIHdlaWdodCBzY29yZSBpcy4gCiAgICAKIyMgRnVydGhlciBSZXNlYXJjaCBhbmQgQW5hbHlzaXMgCgoqIEFzIHlvdSBjYW4gdGVsbCBieSB0aGUgZGF0YSBwcmVzZW50ZWQgaW4gdGhlIHJlc2VhcmNoLCB0aGUgd2VpZ2h0IGNhdGVnb3JpZXMgZm9yIG1lbiBhbmQgd29tZW4gY2hhbmdlIGJldHdlZW4gT2x5bXBpY3MuIFRoZSBhZGp1c3RtZW50IGlzIG1hZGUgdG8gaW1wcm92ZSB0aGUgc3BvcnQgYW5kIG1ha2UgaXQgZmFpciBiZXR3ZWVuIHRoZSBhdGhsZXRlcyAoV2h5IGNoYW5nZSB3ZWlnaHRsaWZ0aW5nJ3MgYm9keXdlaWdodCBjYXRlZ29yaWVzIC4uLiBhZ2Fpbj8pLiAKCiogVGhlIGJvZHl3ZWlnaHQgY2F0ZWdvcmllcyB3aWxsIGNoYW5nZSBmb3IgdGhlIE9seW1waWNzIGluIDIwMjQuIFRvIHJlYWNoIGZ1bGwgZ2VuZGVyIGVxdWFsaXR5LCB0aGVyZSB3aWxsIGJlIDUgd2VpZ2h0IGNhdGVnb3JpZXMgZm9yIGVhY2ggZ2VuZGVyLiBNZW4gd2lsbCBjb21wZXRlIGluIDYxa2csIDcza2csIDg5a2csIDEwMmtnIGFuZCArMTAya2cuIFdvbWVuIHdpbGwgY29tcGV0ZSBpbiA0OWtnLCA1OWtnLCA3MWtnLCA4MWtnIGFuZCArODFrZyAoUGFyaXMgMjAyNDogV2VpZ2h0IGNhdGVnb3JpZXMgZm9yIHRoZSBPbHltcGljIFdlaWdodGxpZnRpbmcgQ29tcGV0aXRpb24pLiAKCiogVGhvc2UgY2F0ZWdvcmllcyBhcmUgdmVyeSBkaWZmZXJlbnQgZnJvbSB0aGUgb25lcyBpbiBvdXIgZGF0YS4gVGhlcmUgaXMgYSBiaWdnZXIgcmFuZ2UgYmV0d2VlbiBlYWNoIG1lbidzIGNhdGVnb3J5IGFuZCB0aGUgaGVhdmllc3Qgb25lIHdpbGwgYmUgN2tnIGxpZ2h0ZXIgdGhhbiB0aGUgaGVhdmllc3Qgb25lIGZyb20gb3VyIGRhdGEuIFRoZSB3b21lbidzIGZ1dHVyZSBwbHVzIGNhdGVnb3J5IGlzIGJldHdlZW4gdGhlIHBsdXMgY2F0ZWdvcmllcyBmcm9tIDIwMDAgYW5kIDIwMjAuIEluIG91ciBncmFwaGljYWwgYW5hbHlzaXMgd2UgY29uY2x1ZGVkIHRoYXQgdGhlIHdvbWVuIGluIHRoZSBwbHVzIGNhdGVnb3J5IGluIDIwMDAgd2VyZSBzdHJvbmdlciB0aGFuIHRoZSBvbmUgaW4gdGhlIHBsdXMgY2F0ZWdvcnkgZnJvbSAyMDIwLiBTaW5jZSB0aGUgcGx1cyBjYXRlZ29yeSBpbiAyMDI0IHdpbGwgYmUgaW4gYmV0d2VlbiB0aGVtLCBpdCBpcyBleGNpdGluZyB0byBzZWUgaWYgdGhlIHJlc3VsdHMgd2lsbCBpbXByb3ZlIGZyb20gcHJldmlvdXMgT2x5bXBpYyBHYW1lcy4gCgoKCiMgKipDb25jbHVzaW9uKioKCiogVGhlIHN0YXRpc3RpY2FsIHJlc3VsdHMgZnJvbSB0aGVzZSBvYnNlcnZhdGlvbmFsIHN0dWRpZXMgY2FuIGJlIGFwcGxpZWQgdG8gT2x5bXBpYyBXZWlnaHRsaWZ0aW5nIGluIGdlbmVyYWwgd2l0aCA5NSBwZXJjZW50IGNvbmZpZGVuY2UuIElmIGFuIGF0aGxldGUgaXMgZ29vZCBhdCBvbmUgT2x5bXBpYyBsaWZ0LCBoZSBpcyBtb3N0IGxpa2VseSBnb29kIGF0IHRoZSBvdGhlciBvbmUgYXMgd2VsbC4gVGhhdCBpcyBhYm91dCB0aGUgYXRobGV0ZSdzIGdlbmVyYWwgc3RyZW5ndGguIAoqIFRoZSByZXN1bHRzIHByZXNlbnRlZCBpbiBzZWN0aW9uIDIgaXMgYW4gZXF1YXRpb24gdG8gcHJlZGljdCBhbiBhdGhsZXRlcyBzdW0gb2YgQ2xlYW4tYW5kLUplcmsgYW5kIFNuYXRjaCBmcm9tIGJvZHl3ZWlnaHQgYW5kIFNuYXRjaCBpbmZvcm1hdGlvbi4gWW91IGNhbiBhbHNvIGNhbGN1bGF0ZSB0aGUgcHJlZGljdGlvbiBvZiB5b3VyIENsZWFuLWFuZC1KZXJrIGZyb20gdGhvc2UgcmVzdWx0cyBieSBkZXR1Y3RpbmcgeW91ciBTbmF0Y2ggdmFyaWFibGUgZnJvbSB5b3VyIHRvdGFsIHdlaWdodCBwcmVkaWN0aW9uLgoqIFRoZSBldmlkZW5jZSBjb2xsZWN0ZWQgaW4gc2VjdGlvbiAzIGNhbm5vdCBiZSBhcHBsaWVkIHRvIGEgYnJvYWRlciBhdWRpZW5jZSB0aGFuIHRoZSBlbGl0ZSBhdGhsZXRlcyBiZWNhdXNlIHRoYXQgd2FzIG9ubHkgdGVzdGVkIHdpdGggZGF0YSBmcm9tIE9seW1waWMgR2FtZXMuIE1hbGUgZWxpdGUgYXRobGV0ZXMgaGF2ZSBub3QgaW1wcm92ZWQgb3ZlciB0aGUgMjFzdCBjZW50dXJ5LCB3aGlsZSBmZW1hbGUgZWxpdGUgYXRobGV0ZXMgaGF2ZS4gCiogV2UgYWxzbyBzdGF0aXN0aWNhbGx5IHByb3ZlZCB0aGF0IGF0aGxldGVzIHdpdGggaGVhdnkgYm9keXdlaWdodCBsaWZ0IGhlYXZpZXIgd2VpZ2h0cyB0aGFuIGF0aGxldGVzIHdpdGggbGlnaHQgYm9keXdlaWdodC4gCiAgICAKICAgIAogICAgCiMgKipSZWZlcmVuY2VzKioKCiogRGlja3NvbiwgSi4gKDIwMjNiLCBGZWJydWFyeSAxMCkuIFRoZSBzbmF0Y2ggdnMuIHRoZSBDbGVhbiAmIEplcms6IFByb3MgYW5kIGNvbnMgb2YgdGhlIHR3byBvbHltcGljIGxpZnRzLiBCYXJCZW5kLiBodHRwczovL2JhcmJlbmQuY29tL3NuYXRjaC12cy1jbGVhbi1hbmQtamVyay8gCgoqIE11bHRpY29sbGluZWFyaXR5LiBKTVAuIChuLmQuKS4gaHR0cHM6Ly93d3cuam1wLmNvbS9lbl91cy9zdGF0aXN0aWNzLWtub3dsZWRnZS1wb3J0YWwvd2hhdC1pcy1tdWx0aXBsZS1yZWdyZXNzaW9uL211bHRpY29sbGluZWFyaXR5Lmh0bWwgCgoqIFBhcmlzIDIwMjQ6IFdlaWdodCBjYXRlZ29yaWVzIGZvciB0aGUgT2x5bXBpYyBXZWlnaHRsaWZ0aW5nIENvbXBldGl0aW9uLiAobi5kLikuIGh0dHBzOi8vb2x5bXBpY3MuY29tL2VuL25ld3MvcGFyaXMtMjAyNC13ZWlnaHQtY2F0ZWdvcmllcy1vbHltcGljLXdlaWdodGxpZnRpbmctY29tcGV0aXRpb24gCgoqIFdoeSBjaGFuZ2Ugd2VpZ2h0bGlmdGluZ+KAmXMgYm9keXdlaWdodCBjYXRlZ29yaWVzIC4uLiBhZ2Fpbj8gU3BvcnRzRWRUVi4gKG4uZC4pLiBodHRwczovL3Nwb3J0c2VkdHYuY29tL2Jsb2cvd2h5LWNoYW5nZS13ZWlnaHRsaWZ0aW5ncy1ib2R5d2VpZ2h0LWNhdGVnb3JpZXMtYWdhaW4gCgoK