Introduction and
Background
The dataset I am using for my analysis is an extensive collection of
metrics for every NBA player’s game-by-game performance across the
2022-2023 playoff season. It was published on the open-source data
science platform Kaggle (link can be found in references section below).
The original source for the data’s accuracy can be confirmed at
Basketball-reference.com, a well-established database for enthusiasts of
the sport. All statistical analysis will be conducted via the
programming language R.
As for the dataset’s contents, it is composed of all 217 players who
played some amount of time in the 2022-2023 postseason. It contained 30
variables, however only 10 played a role in my analysis, so I created a
reduced dataset which only contained the information pertinent to my
research question. An explanation and breakdown of the names and data
types for the variables used in my analysis is below:
“Player” = player’s name = character
“Pos” = player’s position on the court or in starting lineup =
character
“Tm” = team player plays for = character
“Age” = player’s age = integer
“PTS” = player’s points per game average = double
“AST” = player’s assists per game average = double
“TRB” = player’s rebounds per game average = double
“STL” = player’s steals per game average = double
“BLK” = player’s blocks per game average = double
“MP” = player’s minutes per game average = double
I chose to confine my analysis to operating on these variables, and
not to include the remaining ones in the original dataset for a couple
of reasons.
First, when making linear models to predict or estimate
relationships, it is ideal to include the least amount of variables as
possible as long as no significant amount of accuracy is lost by
variable reduction. This is to prevent a phenomenon known as
“overfitting” in which the models we create work almost perfectly for
our given dataset, but not as well when applied to samples outside of
this particular dataset.
Also, I believed from a practical persepective, many of the
variables in this dataset served a redundant purpose. For example;
measurements such as total field goals attempted and made, two-point
field goals attempted and made, three-point field goals attempted and
made, as well as the respective shooting percentages, are all
representative of a player’s scoring output. I find it more logical to
simply retain the variable PTS for the analysis as that serves as a
summary of a player’s scoring output.
Previously, I have used the data at hand to perform both simple and
multiple linear regression. Via my simple linear regression model, I
found there to be a strong, positive and significant linear relationship
between a player’s average scoring output and his average playing time.
Through conducting multiple linear regression, I discovered that there
is strong evidence to suggest a positive and linear relationship between
a player’s given playing time and their per-game averages in points,
rebounds and steals, yet no such significant relationship exists between
his minutes per game and his averages in blocks or assists, nor his age,
position on the court or team he plays for. Both of my previous analyses
can be found under the References section below.
Today, I am going to expand upon my multiple linear regression model
which found a significant relationship between an NBA player’s playing
time and his points per game (ppg), rebounds per game (rpg) and steals
per game (spg). I will be using bootstrap sampling to create confidence
intervals for the coefficients of each of those three metrics. A benefit
of doing so is that bootstrap sampling is a non-parametric technique,
meaning we do not need to make as strong of assumptions about the
underlying population (in this case professional basketball players) in
order to ensure the validity of results.
Multiple Regression
Model
A summary of my final multiple regression model can be seen below.
After previously performing numerous rounds of stepwise regression,
residual analysis and a box-cox transformation, I came to the following
conclusion. Assuming all other elements of a player’s performance remain
unchanged; every increase of one point per game will lead to an extra
0.84 minutes per game, every extra rebound averaged per game will cause
an extra 1.2 minutes per game, and every additional steal a player
averages per game correlates with an extra 5.8 minutes of playing time
per game.
library(MASS)
Reduced_Playoff_Data2 = Reduced_Playoff_Data[Reduced_Playoff_Data$MP > 0, ]
Forward_Model2 = lm(MP ~ PTS + TRB + STL, data = Reduced_Playoff_Data2)
lambda = 1.05
# Modify MP variable in dataset with lamba transformation
Reduced_Playoff_Data2$MP_bc = if (lambda == 0) {
log(Reduced_Playoff_Data2$MP)
} else {
(Reduced_Playoff_Data2$MP^lambda - 1) / lambda
}
BoxCox_Model = lm(MP ~ PTS + TRB + STL, data = Reduced_Playoff_Data2)
invisible(summary(BoxCox_Model))
(kable(summary(BoxCox_Model)$coef, digits = 5, caption ="Coefficients for Final Multiple Linear Regression Model"))
Coefficients for Final Multiple Linear Regression
Model
(Intercept) |
5.01154 |
0.51694 |
9.69466 |
0 |
PTS |
0.83900 |
0.06582 |
12.74628 |
0 |
TRB |
1.19507 |
0.14462 |
8.26368 |
0 |
STL |
5.82980 |
0.88906 |
6.55724 |
0 |
Bootstrap
Regression
I employed two different bootstrap sampling methods (case and
residual) to estimate the coefficients of my regression model. With each
model, I created 95% confidence intervals for each coefficient of
interest (intercept, PTS, TRB and STL).
Bootstrap Approach 1
- Bootstrap Cases
The first method I used was called bootstrap case sampling. This
approach consists of taking an extremely high number of repeated samples
(with replacement), of the dataset at hand and then recalculating the
predictor variables’ regression coefficients each time to fit the
response variable’s value. These regression coefficients from each
sample then make up each coefficient’s bootstrap distribution.
Bootstrap_Model = lm (MP ~ PTS + TRB + STL, data = Reduced_Playoff_Data2)
##
B = 1000 # choose the number of bootstrap replicates.
##
num.p = dim(model.frame(Bootstrap_Model))[2] # returns number of parameters in the model
smpl.n = dim(model.frame(Bootstrap_Model))[1] # sample size
## zero matrix to store bootstrap coefficients
coef.mtrx = matrix(rep(0, B*num.p), ncol = num.p)
##
for (i in 1:B){
bootc.id = sample(1:smpl.n, smpl.n, replace = TRUE) # fit final model to the bootstrap sample
Bootstrap_Model.btc = lm (MP ~ PTS + TRB + STL, data = Reduced_Playoff_Data2[bootc.id,])
coef.mtrx[i,] = coef(Bootstrap_Model.btc) # extract coefs from bootstrap regression model
}
boot.hist = function(cmtrx, bt.coef.mtrx, var.id, var.nm){
## bt.coef.mtrx = matrix for storing bootstrap estimates of coefficients
## var.id = variable ID (1, 2, ..., k+1)
## var.nm = variable name on the hist title, must be the string in the double quotes
## coefficient matrix of the final model
## Bootstrap sampling distribution of the estimated coefficients
x1.1 = seq(min(bt.coef.mtrx[,var.id]), max(bt.coef.mtrx[,var.id]), length=300 )
y1.1 = dnorm(x1.1, mean(bt.coef.mtrx[,var.id]), sd(bt.coef.mtrx[,var.id]))
# height of the histogram - use it to make a nice-looking histogram.
highestbar = max(hist(bt.coef.mtrx[,var.id], plot = FALSE)$density)
ylimit = max(c(y1.1,highestbar))
hist(bt.coef.mtrx[,var.id], probability = TRUE, main = var.nm, xlab="",
col = "azure1",ylim=c(0,ylimit), border="lightseagreen")
lines(x = x1.1, y = y1.1, col = "red3")
lines(density(bt.coef.mtrx[,var.id], adjust=2), col="blue")
#legend("topright", c(""))
}
par(mfrow=c(2,2)) # histograms of bootstrap coefs
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=1, var.nm ="Slope Intercept" )
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=2, var.nm ="Points Per Game" )
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=3, var.nm ="Rebounds Per Game" )
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=4, var.nm ="Steals Per Game" )

num.p = dim(coef.mtrx)[2] # number of parameters
btc.ci = NULL
btc.wd = NULL
for (i in 1:num.p){
lci.025 = round(quantile(coef.mtrx[, i], 0.025, type = 2),8)
uci.975 = round(quantile(coef.mtrx[, i],0.975, type = 2 ),8)
btc.wd[i] = uci.975 - lci.025
btc.ci[i] = paste("[", round(lci.025,4),", ", round(uci.975,4),"]")
}
#as.data.frame(btc.ci)
Rounded_btc.wd = round(btc.wd,4)
cmtrx = summary(Bootstrap_Model)$coef
kable(as.data.frame(cbind(formatC(cmtrx,4,format="f"), btc.ci.95=btc.ci, Rounded_btc.wd)),
caption = "Bootstrap Cases Regression Coefficient Matrix, 95% CI")
Bootstrap Cases Regression Coefficient Matrix, 95% CI
(Intercept) |
5.0115 |
0.5169 |
9.6947 |
0.0000 |
[ 4.0371 , 6.0342 ] |
1.9971 |
PTS |
0.8390 |
0.0658 |
12.7463 |
0.0000 |
[ 0.6894 , 0.9928 ] |
0.3034 |
TRB |
1.1951 |
0.1446 |
8.2637 |
0.0000 |
[ 0.8464 , 1.5828 ] |
0.7364 |
STL |
5.8298 |
0.8891 |
6.5572 |
0.0000 |
[ 3.7215 , 8.0458 ] |
4.3244 |
Bootstrap Cases
Summary
After performing bootstrap case sampling (n = 1000), I created
histograms of each coefficient’s bootstrap sampling distribution. Each
histogram also contains two density curves. The red curve is
representative of estimated coefficients via the linear model that we
started today’s analysis with (the box-cox transformed model). While the
blue curve represents the bootstrap sampling distribution formed from
the cases method. We see tremendous overlap between the two curves in
all of our histograms, especially for the slope intercept and rebounds
per game. This indicates that there is not much difference between the
coefficient values originally calculated via the regression model, and
those found through the bootstrap sampling.
Next, we look at our 95% confidence intervals (btc.ci.95). We can see
that each interval captures the range of values that our original
regression coefficient plus or minus its given standard error would be
equal to. This means that there is no contradiction between our model
and its bootstrap sampling distribution.
Bootstrap Approach 2
- Bootstrap Residuals
The second bootstrap method I used is known as bootstrap residual
sampling. This approach works by fitting a regression model to our data
in an attempt to obtain predicted values and then creating new bootstrap
samples from so. These new samples consist of a new response variable by
which the model fits by adding randomly sampled residuals (with
replacement) to said response variables (PTS, TRB and STL).
hist(sort(Bootstrap_Model$residuals),n=40,
xlab="Residuals",
col = "lightblue",
border="navy",
main = "Histogram of Model Residuals")

invisible(mean(Bootstrap_Model$residuals))
Bootstrap_Model = lm (MP ~ PTS + TRB + STL, data = Reduced_Playoff_Data2)
model.resid = Bootstrap_Model$residuals
##
C=1500
num.p = dim(model.matrix(Bootstrap_Model))[2] # number of parameters
samp.n = dim(model.matrix(Bootstrap_Model))[1] # sample size
btr.mtrx = matrix(rep(0,6*B), ncol=num.p) # zero matrix to store boot coefs
for (i in 1:C){
## Bootstrap response values
bt.Bootstrap_Model = Bootstrap_Model$fitted.values +
sample(Bootstrap_Model$residuals, samp.n, replace = TRUE) # bootstrap residuals
# replace PriceUnitArea with bootstrap log price
Reduced_Playoff_Data2$bt.Bootstrap_Model = bt.Bootstrap_Model # send the boot response to the data
btr.model = lm(bt.Bootstrap_Model ~ PTS + TRB + STL, data = Reduced_Playoff_Data2)
btr.mtrx[i,]=btr.model$coefficients
}
boot.hist = function(bt.coef.mtrx, var.id, var.nm){
## bt.coef.mtrx = matrix for storing bootstrap estimates of coefficients
## var.id = variable ID (1, 2, ..., k+1)
## var.nm = variable name on the hist title, must be the string in the double quotes
## Bootstrap sampling distribution of the estimated coefficients
x1.1 <- seq(min(bt.coef.mtrx[,var.id]), max(bt.coef.mtrx[,var.id]), length=300 )
y1.1 <- dnorm(x1.1, mean(bt.coef.mtrx[,var.id]), sd(bt.coef.mtrx[,var.id]))
# height of the histogram - use it to make a nice-looking histogram.
highestbar = max(hist(bt.coef.mtrx[,var.id], plot = FALSE)$density)
ylimit <- max(c(y1.1,highestbar))
hist(bt.coef.mtrx[,var.id], probability = TRUE, main = var.nm, xlab="",
col = "azure1",ylim=c(0,ylimit), border="lightseagreen")
lines(x = x1.1, y = y1.1, col = "red3") # normal density curve
lines(density(bt.coef.mtrx[,var.id], adjust=2), col="blue") # loess curve
}
par(mfrow=c(2,2)) # histograms of bootstrap coefs
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=1, var.nm ="Slope Intercept" )
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=2, var.nm ="Points Per Game" )
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=3, var.nm ="Rebounds Per Game" )
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=4, var.nm ="Steals Per Game" )

num.p = dim(coef.mtrx)[2] # number of parameters
btr.ci = NULL
btr.wd = NULL
for (i in 1:num.p){
lci.025 = round(quantile(btr.mtrx[, i], 0.025, type = 2),8)
uci.975 = round(quantile(btr.mtrx[, i],0.975, type = 2 ),8)
btr.wd[i] = uci.975 - lci.025
btr.ci[i] = paste("[", round(lci.025,4),", ", round(uci.975,4),"]")
}
Rounded_btr.wd = round(btr.wd,4)
kable(as.data.frame(cbind(formatC(cmtrx,4,format="f"), btr.ci.95=btr.ci, Rounded_btr.wd)),
caption = "Bootstrap Residual Regression Coefficient Matrix, 95% CI")
Bootstrap Residual Regression Coefficient Matrix, 95%
CI
(Intercept) |
5.0115 |
0.5169 |
9.6947 |
0.0000 |
[ 4.0389 , 6.0412 ] |
2.0023 |
PTS |
0.8390 |
0.0658 |
12.7463 |
0.0000 |
[ 0.7148 , 0.975 ] |
0.2602 |
TRB |
1.1951 |
0.1446 |
8.2637 |
0.0000 |
[ 0.9104 , 1.4664 ] |
0.556 |
STL |
5.8298 |
0.8891 |
6.5572 |
0.0000 |
[ 4.1143 , 7.5571 ] |
3.4429 |
Bootstrap Residuals
Summary
We can see from our model residual histogram that our residuals are
not quite normally distributed, as there is a visible slight rightward
skew, yet the calculated mean of the residuals is extremely close to
zero (~7.4-17), so we proceed with caution.
Like in the residual bootstrap histograms produced from the bootstrap
cases method, our histograms here show a close proximity between the
traditional regression density curve (red line) and the bootstrap-based
density curve (blue line). This indicates a high degree of shared values
from the two estimations. Note that in this instance, the blue line is
representative of bootstrap residuals’ sampling distribution.
Lastly, we take a look at the 95% confidence intervals (btr.ci.95)
created for our regression coefficients. Once again, all of our
confidence intervals via the bootstrap method are within the range of
our original regression-calculated coefficients, plus or minus their
given standard error. Hence the results from performing the bootstrap
residuals method are in alignment with the takeaways from our simplified
model that we started today’s analysis with.
Conclusion
Below we can see a summary of our model, its original regression
coefficients, as well as the confidence interval metrics for its
bootstrap cases and bootstrap residual distributions. Given that all
three methods yielded results practically in alignment with each other,
we can safely say that an NBA player’s average playing time has a strong
linear relationship with his averages in points, rebounds and steals per
game, with the exact degree of correlation slightly differing via the
widths of said confidence intervals.
Rounded_Interval_Widths = cbind(Rounded_btc.wd, Rounded_btr.wd)
kable(as.data.frame(cbind(formatC(cmtrx[,-3],4,format="f"), btc.ci.95=btc.ci,btr.ci.95=btr.ci, Rounded_Interval_Widths)),
caption="Final Regression Coefficient Estimates: P-Values and Bootstrap CIs")
Final Regression Coefficient Estimates: P-Values and Bootstrap
CIs
(Intercept) |
5.0115 |
0.5169 |
0.0000 |
[ 4.0371 , 6.0342 ] |
[ 4.0389 , 6.0412 ] |
1.9971 |
2.0023 |
PTS |
0.8390 |
0.0658 |
0.0000 |
[ 0.6894 , 0.9928 ] |
[ 0.7148 , 0.975 ] |
0.3034 |
0.2602 |
TRB |
1.1951 |
0.1446 |
0.0000 |
[ 0.8464 , 1.5828 ] |
[ 0.9104 , 1.4664 ] |
0.7364 |
0.556 |
STL |
5.8298 |
0.8891 |
0.0000 |
[ 3.7215 , 8.0458 ] |
[ 4.1143 , 7.5571 ] |
4.3244 |
3.4429 |
Summary/Discussion
The findings from my analysis over the past few weeks could be
valuable to NBA players as well as those deeply vested in their on-court
performance such as agents and advertisers. If a player desires more
playing time, it is helpful to know exactly what metrics (PTS, TRB and
STL in this case) having an increase in will traditionally correlate
with more playing time across the league.
For my analysis, the most recent dataset I could find was one from
the 2022-2023 NBA season. Moving forward, if there was a way I could
perform similar exploration on data from the most recent NBA season,
that would potentially bring even more credibility to whatever
findings resulted.
LS0tCnRpdGxlOiAiQm9vdHN0cmFwIFNhbXBsaW5nIHRvIEV4cGxvcmUgUmVsYXRpb25zaGlwIEJldHdlZW4gYW4gTkJBIFBsYXllcidzIFNjb3JpbmcsIFJlYm91bmRpbmcgYW5kIFN0ZWFsaW5nIHdpdGggUGxheWluZyBUaW1lIgphdXRob3I6ICJDaHJpcyBCYWhtIgpkYXRlOiAiMjAyNS0wOS0yOSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIHRvY19kZXB0aDogNAogICAgZmlnX3dpZHRoOiA2CiAgICBmaWdfaGVpZ2h0OiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKYGBge2NzcywgZWNobyA9IEZBTFNFfQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IAojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4KCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgYSBwYWNrYWdlIHdhcyBpbnN0YWxsZWQgaW4KICAgbGlicmFyeShrbml0cikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91ciBtYWNoaW5lLiBJZiBub3QsIGluc3RhbGwgaXQgYW5kCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIHtsaWJyYXJ5KHRpZHl2c2Vyc2UpfSAKCmlmICghcmVxdWlyZShHR2FsbHkpKSB7bGlicmFyeShHR2FsbHkpfSAKCmlmICghcmVxdWlyZShrYWJsZUV4dHJhKSkge2xpYnJhcnkoa2FibGVFeHRyYSl9IAoKaWYgKCFyZXF1aXJlKGdncGxvdDIpKSB7bGlicmFyeShnZ3Bsb3QyKX0gCgppZiAoIXJlcXVpcmUoY2FyKSkge2xpYnJhcnkoY2FyKX0gCgppZiAoIXJlcXVpcmUoZHBseXIpKSB7bGlicmFyeShkcGx5cil9IAoKaWYgKCFyZXF1aXJlKCJzY2FsZXMiKSkgewppbnN0YWxsLnBhY2thZ2VzKCJzY2FsZXMiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKbGlicmFyeSgic2NhbGVzIikgCn0KCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFLAoJY29tbWVudCA9IE5BLAoJcmVzdWx0cyA9IFRSVUUKKQogICAKYGBgCgojIEludHJvZHVjdGlvbiBhbmQgQmFja2dyb3VuZApUaGUgZGF0YXNldCBJIGFtIHVzaW5nIGZvciBteSBhbmFseXNpcyBpcyBhbiBleHRlbnNpdmUgY29sbGVjdGlvbiBvZiBtZXRyaWNzIGZvciBldmVyeSBOQkEgcGxheWVyJ3MgZ2FtZS1ieS1nYW1lIHBlcmZvcm1hbmNlIGFjcm9zcyB0aGUgMjAyMi0yMDIzIHBsYXlvZmYgc2Vhc29uLiBJdCB3YXMgcHVibGlzaGVkIG9uIHRoZSBvcGVuLXNvdXJjZSBkYXRhIHNjaWVuY2UgcGxhdGZvcm0gS2FnZ2xlIChsaW5rIGNhbiBiZSBmb3VuZCBpbiByZWZlcmVuY2VzIHNlY3Rpb24gYmVsb3cpLiBUaGUgb3JpZ2luYWwgc291cmNlIGZvciB0aGUgZGF0YSdzIGFjY3VyYWN5IGNhbiBiZSBjb25maXJtZWQgYXQgQmFza2V0YmFsbC1yZWZlcmVuY2UuY29tLCBhIHdlbGwtZXN0YWJsaXNoZWQgZGF0YWJhc2UgZm9yIGVudGh1c2lhc3RzIG9mIHRoZSBzcG9ydC4gQWxsIHN0YXRpc3RpY2FsIGFuYWx5c2lzIHdpbGwgYmUgY29uZHVjdGVkIHZpYSB0aGUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UgUi4KCkFzIGZvciB0aGUgZGF0YXNldCdzIGNvbnRlbnRzLCBpdCBpcyBjb21wb3NlZCBvZiBhbGwgMjE3IHBsYXllcnMgd2hvIHBsYXllZCBzb21lIGFtb3VudCBvZiB0aW1lIGluIHRoZSAyMDIyLTIwMjMgcG9zdHNlYXNvbi4gSXQgY29udGFpbmVkIDMwIHZhcmlhYmxlcywgaG93ZXZlciBvbmx5IDEwIHBsYXllZCBhIHJvbGUgaW4gbXkgYW5hbHlzaXMsIHNvIEkgY3JlYXRlZCBhIHJlZHVjZWQgZGF0YXNldCB3aGljaCBvbmx5IGNvbnRhaW5lZCB0aGUgaW5mb3JtYXRpb24gcGVydGluZW50IHRvIG15IHJlc2VhcmNoIHF1ZXN0aW9uLiBBbiBleHBsYW5hdGlvbiBhbmQgYnJlYWtkb3duIG9mIHRoZSBuYW1lcyBhbmQgZGF0YSB0eXBlcyBmb3IgdGhlIHZhcmlhYmxlcyB1c2VkIGluIG15IGFuYWx5c2lzIGlzIGJlbG93OgoKLSAgICJQbGF5ZXIiID0gcGxheWVyJ3MgbmFtZSA9IGNoYXJhY3RlcgoKLSAgICJQb3MiID0gcGxheWVyJ3MgcG9zaXRpb24gb24gdGhlIGNvdXJ0IG9yIGluIHN0YXJ0aW5nIGxpbmV1cCA9IGNoYXJhY3RlcgoKLSAgICJUbSIgPSB0ZWFtIHBsYXllciBwbGF5cyBmb3IgPSBjaGFyYWN0ZXIKCi0gICAiQWdlIiA9IHBsYXllcidzIGFnZSA9IGludGVnZXIKCi0gICAiUFRTIiA9IHBsYXllcidzIHBvaW50cyBwZXIgZ2FtZSBhdmVyYWdlID0gZG91YmxlCgotICAgIkFTVCIgPSBwbGF5ZXIncyBhc3Npc3RzIHBlciBnYW1lIGF2ZXJhZ2UgPSBkb3VibGUKCi0gICAiVFJCIiA9IHBsYXllcidzIHJlYm91bmRzIHBlciBnYW1lIGF2ZXJhZ2UgPSBkb3VibGUKCi0gICAiU1RMIiA9IHBsYXllcidzIHN0ZWFscyBwZXIgZ2FtZSBhdmVyYWdlID0gZG91YmxlCgotICAgIkJMSyIgPSBwbGF5ZXIncyBibG9ja3MgcGVyIGdhbWUgYXZlcmFnZSA9IGRvdWJsZQoKLSAgICJNUCIgPSBwbGF5ZXIncyBtaW51dGVzIHBlciBnYW1lIGF2ZXJhZ2UgPSBkb3VibGUKCkkgY2hvc2UgdG8gY29uZmluZSBteSBhbmFseXNpcyB0byBvcGVyYXRpbmcgb24gdGhlc2UgdmFyaWFibGVzLCBhbmQgbm90IHRvIGluY2x1ZGUgdGhlIHJlbWFpbmluZyBvbmVzIGluIHRoZSBvcmlnaW5hbCBkYXRhc2V0IGZvciBhIGNvdXBsZSBvZiByZWFzb25zLgoKLSBGaXJzdCwgd2hlbiBtYWtpbmcgbGluZWFyIG1vZGVscyB0byBwcmVkaWN0IG9yIGVzdGltYXRlIHJlbGF0aW9uc2hpcHMsIGl0IGlzIGlkZWFsIHRvIGluY2x1ZGUgdGhlIGxlYXN0IGFtb3VudCBvZiB2YXJpYWJsZXMgYXMgcG9zc2libGUgYXMgbG9uZyBhcyBubyBzaWduaWZpY2FudCBhbW91bnQgb2YgYWNjdXJhY3kgaXMgbG9zdCBieSB2YXJpYWJsZSByZWR1Y3Rpb24uIFRoaXMgaXMgdG8gcHJldmVudCBhIHBoZW5vbWVub24ga25vd24gYXMgIm92ZXJmaXR0aW5nIiBpbiB3aGljaCB0aGUgbW9kZWxzIHdlIGNyZWF0ZSB3b3JrIGFsbW9zdCBwZXJmZWN0bHkgZm9yIG91ciBnaXZlbiBkYXRhc2V0LCBidXQgbm90IGFzIHdlbGwgd2hlbiBhcHBsaWVkIHRvIHNhbXBsZXMgb3V0c2lkZSBvZiB0aGlzIHBhcnRpY3VsYXIgZGF0YXNldC4KCi0gQWxzbywgSSBiZWxpZXZlZCBmcm9tIGEgcHJhY3RpY2FsIHBlcnNlcGVjdGl2ZSwgbWFueSBvZiB0aGUgdmFyaWFibGVzIGluIHRoaXMgZGF0YXNldCBzZXJ2ZWQgYSByZWR1bmRhbnQgcHVycG9zZS4gRm9yIGV4YW1wbGU7IG1lYXN1cmVtZW50cyBzdWNoIGFzIHRvdGFsIGZpZWxkIGdvYWxzIGF0dGVtcHRlZCBhbmQgbWFkZSwgdHdvLXBvaW50IGZpZWxkIGdvYWxzIGF0dGVtcHRlZCBhbmQgbWFkZSwgdGhyZWUtcG9pbnQgZmllbGQgZ29hbHMgYXR0ZW1wdGVkIGFuZCBtYWRlLCBhcyB3ZWxsIGFzIHRoZSByZXNwZWN0aXZlIHNob290aW5nIHBlcmNlbnRhZ2VzLCBhcmUgYWxsIHJlcHJlc2VudGF0aXZlIG9mIGEgcGxheWVyJ3Mgc2NvcmluZyBvdXRwdXQuIEkgZmluZCBpdCBtb3JlIGxvZ2ljYWwgdG8gc2ltcGx5IHJldGFpbiB0aGUgdmFyaWFibGUgUFRTIGZvciB0aGUgYW5hbHlzaXMgYXMgdGhhdCBzZXJ2ZXMgYXMgYSBzdW1tYXJ5IG9mIGEgcGxheWVyJ3Mgc2NvcmluZyBvdXRwdXQuCgpQcmV2aW91c2x5LCBJIGhhdmUgdXNlZCB0aGUgZGF0YSBhdCBoYW5kIHRvIHBlcmZvcm0gYm90aCBzaW1wbGUgYW5kIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uLiBWaWEgbXkgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLCBJIGZvdW5kIHRoZXJlIHRvIGJlIGEgc3Ryb25nLCBwb3NpdGl2ZSBhbmQgc2lnbmlmaWNhbnQgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGEgcGxheWVyJ3MgYXZlcmFnZSBzY29yaW5nIG91dHB1dCBhbmQgaGlzIGF2ZXJhZ2UgcGxheWluZyB0aW1lLiBUaHJvdWdoIGNvbmR1Y3RpbmcgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24sIEkgZGlzY292ZXJlZCB0aGF0IHRoZXJlIGlzIHN0cm9uZyBldmlkZW5jZSB0byBzdWdnZXN0IGEgcG9zaXRpdmUgYW5kIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIHBsYXllcidzIGdpdmVuIHBsYXlpbmcgdGltZSBhbmQgdGhlaXIgcGVyLWdhbWUgYXZlcmFnZXMgaW4gcG9pbnRzLCByZWJvdW5kcyBhbmQgc3RlYWxzLCB5ZXQgbm8gc3VjaCBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAgZXhpc3RzIGJldHdlZW4gaGlzIG1pbnV0ZXMgcGVyIGdhbWUgYW5kIGhpcyBhdmVyYWdlcyBpbiBibG9ja3Mgb3IgYXNzaXN0cywgbm9yIGhpcyBhZ2UsIHBvc2l0aW9uIG9uIHRoZSBjb3VydCBvciB0ZWFtIGhlIHBsYXlzIGZvci4gQm90aCBvZiBteSBwcmV2aW91cyBhbmFseXNlcyBjYW4gYmUgZm91bmQgdW5kZXIgdGhlIFJlZmVyZW5jZXMgc2VjdGlvbiBiZWxvdy4KClRvZGF5LCBJIGFtIGdvaW5nIHRvIGV4cGFuZCB1cG9uIG15IG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHdoaWNoIGZvdW5kIGEgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIGJldHdlZW4gYW4gTkJBIHBsYXllcidzIHBsYXlpbmcgdGltZSBhbmQgaGlzIHBvaW50cyBwZXIgZ2FtZSAocHBnKSwgcmVib3VuZHMgcGVyIGdhbWUgKHJwZykgYW5kIHN0ZWFscyBwZXIgZ2FtZSAoc3BnKS4gSSB3aWxsIGJlIHVzaW5nIGJvb3RzdHJhcCBzYW1wbGluZyB0byBjcmVhdGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIHRoZSBjb2VmZmljaWVudHMgb2YgZWFjaCBvZiB0aG9zZSB0aHJlZSBtZXRyaWNzLiBBIGJlbmVmaXQgb2YgZG9pbmcgc28gaXMgdGhhdCBib290c3RyYXAgc2FtcGxpbmcgaXMgYSBub24tcGFyYW1ldHJpYyB0ZWNobmlxdWUsIG1lYW5pbmcgd2UgZG8gbm90IG5lZWQgdG8gbWFrZSBhcyBzdHJvbmcgb2YgYXNzdW1wdGlvbnMgYWJvdXQgdGhlIHVuZGVybHlpbmcgcG9wdWxhdGlvbiAoaW4gdGhpcyBjYXNlIHByb2Zlc3Npb25hbCBiYXNrZXRiYWxsIHBsYXllcnMpIGluIG9yZGVyIHRvIGVuc3VyZSB0aGUgdmFsaWRpdHkgb2YgcmVzdWx0cy4KCmBgYHtyIERhdGFfUmVhZF9pbl9hbmRfQ2xlYW5pbmcsIGluY2x1ZGU9RkFMU0V9CgpEYXRhX1VybCA9ICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQ2hyaXNCMjMyMy9TVEEzMjEvbWFpbi9QbGF5b2ZmX0RhdGEuY3N2IgpGdWxsX1BsYXlvZmZfRGF0YSA9IHJlYWRfZGVsaW0oRGF0YV9VcmwsIGRlbGltID0gIjsiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQpnbGltcHNlKEZ1bGxfUGxheW9mZl9EYXRhKQoKUmVkdWNlZF9QbGF5b2ZmX0RhdGEgPSBGdWxsX1BsYXlvZmZfRGF0YSAlPiUgZHBseXI6OnNlbGVjdChQbGF5ZXIsIFBvcywgVG0sIEFnZSwgUFRTLCBBU1QsIFRSQiwgU1RMLCBCTEssIE1QKQpnbGltcHNlKFJlZHVjZWRfUGxheW9mZl9EYXRhKQoKUGxheWVyID0gUmVkdWNlZF9QbGF5b2ZmX0RhdGEkUGxheWVyClBvcyA9IFJlZHVjZWRfUGxheW9mZl9EYXRhJFBvcwpUbSA9IFJlZHVjZWRfUGxheW9mZl9EYXRhJFRtCkFnZSA9IFJlZHVjZWRfUGxheW9mZl9EYXRhJEFnZQpQVFMgPSBSZWR1Y2VkX1BsYXlvZmZfRGF0YSRQVFMKQVNUID0gUmVkdWNlZF9QbGF5b2ZmX0RhdGEkQVNUClRSQiA9IFJlZHVjZWRfUGxheW9mZl9EYXRhJFRSQgpTVEwgPSBSZWR1Y2VkX1BsYXlvZmZfRGF0YSRTVEwKQkxLID0gUmVkdWNlZF9QbGF5b2ZmX0RhdGEkQkxLCk1QID0gUmVkdWNlZF9QbGF5b2ZmX0RhdGEkTVAKClF1YW50aXRhdGl2ZV9QcmVkaWN0b3JfVmFyaWFibGVzID0gUmVkdWNlZF9QbGF5b2ZmX0RhdGFbYygiQWdlIiwgIlBUUyIsICJBU1QiLCAiVFJCIiwgIlNUTCIsICJCTEsiKV0KCkNhdGVnb3JpY2FsX1ByZWRpY3Rvcl9WYXJpYWJsZXMgPSBSZWR1Y2VkX1BsYXlvZmZfRGF0YVtjKCJQb3MiLCAiVG0iKV0KCiMgUXVhbnRpdGF0aXZlIFByZWRpY3RvcjogQWdlLCBQVFMsIEFTVCwgVFJCLCBTVEwsIEJMSwojIENhdGVnb3JpY2FsIFByZWRpY3RvcjogUG9zLCBUbQoKQWxsX1ByZWRpY3Rvcl9WYXJpYWJsZXMgPSBjYmluZChRdWFudGl0YXRpdmVfUHJlZGljdG9yX1ZhcmlhYmxlcywgQ2F0ZWdvcmljYWxfUHJlZGljdG9yX1ZhcmlhYmxlcykKYGBgCgojIE11bHRpcGxlIFJlZ3Jlc3Npb24gTW9kZWwKQSBzdW1tYXJ5IG9mIG15IGZpbmFsIG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWwgY2FuIGJlIHNlZW4gYmVsb3cuIEFmdGVyIHByZXZpb3VzbHkgcGVyZm9ybWluZyBudW1lcm91cyByb3VuZHMgb2Ygc3RlcHdpc2UgcmVncmVzc2lvbiwgcmVzaWR1YWwgYW5hbHlzaXMgYW5kIGEgYm94LWNveCB0cmFuc2Zvcm1hdGlvbiwgSSBjYW1lIHRvIHRoZSBmb2xsb3dpbmcgY29uY2x1c2lvbi4gQXNzdW1pbmcgYWxsIG90aGVyIGVsZW1lbnRzIG9mIGEgcGxheWVyJ3MgcGVyZm9ybWFuY2UgcmVtYWluIHVuY2hhbmdlZDsgZXZlcnkgaW5jcmVhc2Ugb2Ygb25lIHBvaW50IHBlciBnYW1lIHdpbGwgbGVhZCB0byBhbiBleHRyYSAwLjg0IG1pbnV0ZXMgcGVyIGdhbWUsIGV2ZXJ5IGV4dHJhIHJlYm91bmQgYXZlcmFnZWQgcGVyIGdhbWUgd2lsbCBjYXVzZSBhbiBleHRyYSAxLjIgbWludXRlcyBwZXIgZ2FtZSwgYW5kIGV2ZXJ5IGFkZGl0aW9uYWwgc3RlYWwgYSBwbGF5ZXIgYXZlcmFnZXMgcGVyIGdhbWUgY29ycmVsYXRlcyB3aXRoIGFuIGV4dHJhIDUuOCBtaW51dGVzIG9mIHBsYXlpbmcgdGltZSBwZXIgZ2FtZS4KYGBge3IgcmVzdWx0cz0naGlkZSd9CmxpYnJhcnkoTUFTUykKClJlZHVjZWRfUGxheW9mZl9EYXRhMiA9IFJlZHVjZWRfUGxheW9mZl9EYXRhW1JlZHVjZWRfUGxheW9mZl9EYXRhJE1QID4gMCwgXQoKRm9yd2FyZF9Nb2RlbDIgPSBsbShNUCB+IFBUUyArIFRSQiArIFNUTCwgZGF0YSA9IFJlZHVjZWRfUGxheW9mZl9EYXRhMikKYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KQm94Y294ID0gYm94Y294KEZvcndhcmRfTW9kZWwyLCBsYW1iZGEgPSBzZXEoLTIsIDIsIDAuMSkpCmBgYAoKYGBge3J9CmxhbWJkYSA9IDEuMDUKCiMgTW9kaWZ5IE1QIHZhcmlhYmxlIGluIGRhdGFzZXQgd2l0aCBsYW1iYSB0cmFuc2Zvcm1hdGlvbgpSZWR1Y2VkX1BsYXlvZmZfRGF0YTIkTVBfYmMgPSBpZiAobGFtYmRhID09IDApIHsKICBsb2coUmVkdWNlZF9QbGF5b2ZmX0RhdGEyJE1QKQp9IGVsc2UgewogIChSZWR1Y2VkX1BsYXlvZmZfRGF0YTIkTVBebGFtYmRhIC0gMSkgLyBsYW1iZGEKfQpCb3hDb3hfTW9kZWwgPSBsbShNUCB+IFBUUyArIFRSQiArIFNUTCwgZGF0YSA9IFJlZHVjZWRfUGxheW9mZl9EYXRhMikKaW52aXNpYmxlKHN1bW1hcnkoQm94Q294X01vZGVsKSkKCihrYWJsZShzdW1tYXJ5KEJveENveF9Nb2RlbCkkY29lZiwgZGlnaXRzID0gNSwgY2FwdGlvbiA9IkNvZWZmaWNpZW50cyBmb3IgRmluYWwgTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24gTW9kZWwiKSkKYGBgCgojIEJvb3RzdHJhcCBSZWdyZXNzaW9uCkkgZW1wbG95ZWQgdHdvIGRpZmZlcmVudCBib290c3RyYXAgc2FtcGxpbmcgbWV0aG9kcyAoY2FzZSBhbmQgcmVzaWR1YWwpIHRvIGVzdGltYXRlIHRoZSBjb2VmZmljaWVudHMgb2YgbXkgcmVncmVzc2lvbiBtb2RlbC4gV2l0aCBlYWNoIG1vZGVsLCBJIGNyZWF0ZWQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciBlYWNoIGNvZWZmaWNpZW50IG9mIGludGVyZXN0IChpbnRlcmNlcHQsIFBUUywgVFJCIGFuZCBTVEwpLiAKCiMjIEJvb3RzdHJhcCBBcHByb2FjaCAxIC0gQm9vdHN0cmFwIENhc2VzClRoZSBmaXJzdCBtZXRob2QgSSB1c2VkIHdhcyBjYWxsZWQgYm9vdHN0cmFwIGNhc2Ugc2FtcGxpbmcuIFRoaXMgYXBwcm9hY2ggY29uc2lzdHMgb2YgdGFraW5nIGFuIGV4dHJlbWVseSBoaWdoIG51bWJlciBvZiByZXBlYXRlZCBzYW1wbGVzICh3aXRoIHJlcGxhY2VtZW50KSwgb2YgdGhlIGRhdGFzZXQgYXQgaGFuZCBhbmQgdGhlbiByZWNhbGN1bGF0aW5nIHRoZSBwcmVkaWN0b3IgdmFyaWFibGVzJyByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyBlYWNoIHRpbWUgdG8gZml0IHRoZSByZXNwb25zZSB2YXJpYWJsZSdzIHZhbHVlLiBUaGVzZSByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyBmcm9tIGVhY2ggc2FtcGxlIHRoZW4gbWFrZSB1cCBlYWNoIGNvZWZmaWNpZW50J3MgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbi4KCmBgYHtyIE9yaWdpbmFsIENvZGluZyBvZiBCb290c3RyYXAgTWV0aG9kIDEsIGluY2x1ZGU9RkFMU0V9CnNldC5zZWVkKDEyMykgICAgICAgICAgICAgICAgICMgZm9yIHJlcHJvZHVjaWJpbGl0eQpCID0gMTAwMCAgICAgICAgICAgICAgICAgICAgICMgbnVtYmVyIG9mIGJvb3RzdHJhcCByZXNhbXBsZXMKCm4gPSBucm93KFJlZHVjZWRfUGxheW9mZl9EYXRhMikKdmVjX2lkID1zZXFfbGVuKG4pCgojIHN0b3JhZ2UKQm9vdC5iZXRhMCA9IG51bWVyaWMoQikgIyBpbnRlcmNlcHQKQm9vdC5iZXRhMSA9IG51bWVyaWMoQikgIyBzbG9wZQpCb290LmJldGEyID0gbnVtZXJpYyhCKSAjIHNsb3BlCkJvb3QuYmV0YTMgPSBudW1lcmljKEIpICMgc2xvcGUKCmZvciAoaSBpbiBzZXFfbGVuKEIpKSB7CiAgYm9vdF9pZCA9IHNhbXBsZSh2ZWNfaWQsIG4sIHJlcGxhY2UgPSBUUlVFKSAjIHJlc2FtcGxlIHJvd3MKICBib290X3JlZyA9IGxtKE1QIH4gUFRTICsgVFJCICsgU1RMLCBkYXRhID0gUmVkdWNlZF9QbGF5b2ZmX0RhdGEyW2Jvb3RfaWQsICwgZHJvcCA9IEZBTFNFXSkgCiAgY28gPSBjb2VmKGJvb3RfcmVnKQogIEJvb3QuYmV0YTBbaV0gPSBjb1sxXSAgICAjIGludGVyY2VwdAogIEJvb3QuYmV0YTFbaV0gPSBjb1syXSAgICAjIHNsb3BlIGZvciBQVFMKICBCb290LmJldGEyW2ldID0gY29bM10gICAgIyBzbG9wZSBmb3IgVFJCCiAgQm9vdC5iZXRhM1tpXSA9IGNvWzRdICAgICMgc2xvcGUgZm9yIFNUTAp9CgojIDk1JSBwZXJjZW50aWxlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCmNpX2JldGEwID0gcXVhbnRpbGUoQm9vdC5iZXRhMCwgYygwLjAyNSwgMC45NzUpKQpjaV9iZXRhMSA9IHF1YW50aWxlKEJvb3QuYmV0YTEsIGMoMC4wMjUsIDAuOTc1KSkKY2lfYmV0YTIgPSBxdWFudGlsZShCb290LmJldGEyLCBjKDAuMDI1LCAwLjk3NSkpCmNpX2JldGEzID0gcXVhbnRpbGUoQm9vdC5iZXRhMywgYygwLjAyNSwgMC45NzUpKQoKY2lfYmV0YTAgCmNpX2JldGExCmNpX2JldGEyCmNpX2JldGEzCgpwYXIobWZyb3c9YygyLDIpKQpoaXN0KEJvb3QuYmV0YTAsIG1haW4gPSAiU2xvcGUgSW50ZXJjZXB0IE1vZGVsIENvZWZmaWNpZW50IiwgeGxhYiA9ICJTbG9wZSBJbnRlcmNlcHQgVmFsdWUiLCB5bGFiID0gIkJvb3RzdHJhcCBTYW1wbGUgRnJlcXVlbmN5IikKaGlzdChCb290LmJldGExLCBtYWluID0gIlBvaW50cyBQZXIgR2FtZSBNb2RlbCBDb2VmZmljaWVudCIsIHhsYWIgPSAiUG9pbnRzIFBlciBHYW1lIFZhbHVlIiwgeWxhYiA9ICJCb290c3RyYXAgU2FtcGxlIEZyZXF1ZW5jeSIpCmhpc3QoQm9vdC5iZXRhMiwgbWFpbiA9ICJSZWJvdW5kcyBQZXIgR2FtZSBNb2RlbCBDb2VmZmljaWVudCIsIHhsYWIgPSAiUmVib3VuZHMgUGVyIEdhbWUgVmFsdWUiLCB5bGFiID0gIkJvb3RzdHJhcCBTYW1wbGUgRnJlcXVlbmN5IikKaGlzdChCb290LmJldGEzLCBtYWluID0gIlN0ZWFscyBQZXIgR2FtZSBNb2RlbCBDb2VmZmljaWVudCIsIHhsYWIgPSAiU3RlYWxzIFBlciBHYW1lIFZhbHVlIiwgeWxhYiA9ICJCb290c3RyYXAgU2FtcGxlIEZyZXF1ZW5jeSIpCmBgYAoKYGBge3IgTmV3IENvZGluZyBvZiBCb290c3RyYXAgTWV0aG9kIDF9CkJvb3RzdHJhcF9Nb2RlbCA9IGxtIChNUCB+IFBUUyArIFRSQiArIFNUTCwgZGF0YSA9IFJlZHVjZWRfUGxheW9mZl9EYXRhMikKIyMKQiA9IDEwMDAgICAgICAgIyBjaG9vc2UgdGhlIG51bWJlciBvZiBib290c3RyYXAgcmVwbGljYXRlcy4KIyMgCm51bS5wID0gZGltKG1vZGVsLmZyYW1lKEJvb3RzdHJhcF9Nb2RlbCkpWzJdICAjIHJldHVybnMgbnVtYmVyIG9mIHBhcmFtZXRlcnMgaW4gdGhlIG1vZGVsCnNtcGwubiA9IGRpbShtb2RlbC5mcmFtZShCb290c3RyYXBfTW9kZWwpKVsxXSAjIHNhbXBsZSBzaXplCiMjIHplcm8gbWF0cml4IHRvIHN0b3JlIGJvb3RzdHJhcCBjb2VmZmljaWVudHMgCmNvZWYubXRyeCA9IG1hdHJpeChyZXAoMCwgQipudW0ucCksIG5jb2wgPSBudW0ucCkgICAgICAgCiMjIApmb3IgKGkgaW4gMTpCKXsKICBib290Yy5pZCA9IHNhbXBsZSgxOnNtcGwubiwgc21wbC5uLCByZXBsYWNlID0gVFJVRSkgIyBmaXQgZmluYWwgbW9kZWwgdG8gdGhlIGJvb3RzdHJhcCBzYW1wbGUKICBCb290c3RyYXBfTW9kZWwuYnRjID0gbG0gKE1QIH4gUFRTICsgVFJCICsgU1RMLCBkYXRhID0gUmVkdWNlZF9QbGF5b2ZmX0RhdGEyW2Jvb3RjLmlkLF0pICAgICAKICBjb2VmLm10cnhbaSxdID0gY29lZihCb290c3RyYXBfTW9kZWwuYnRjKSAgICAjIGV4dHJhY3QgY29lZnMgZnJvbSBib290c3RyYXAgcmVncmVzc2lvbiBtb2RlbCAgICAKfQoKYm9vdC5oaXN0ID0gZnVuY3Rpb24oY210cngsIGJ0LmNvZWYubXRyeCwgdmFyLmlkLCB2YXIubm0pewogICMjIGJ0LmNvZWYubXRyeCA9IG1hdHJpeCBmb3Igc3RvcmluZyBib290c3RyYXAgZXN0aW1hdGVzIG9mIGNvZWZmaWNpZW50cwogICMjIHZhci5pZCA9IHZhcmlhYmxlIElEICgxLCAyLCAuLi4sIGsrMSkKICAjIyB2YXIubm0gPSB2YXJpYWJsZSBuYW1lIG9uIHRoZSBoaXN0IHRpdGxlLCBtdXN0IGJlIHRoZSBzdHJpbmcgaW4gdGhlIGRvdWJsZSBxdW90ZXMKICAjIyBjb2VmZmljaWVudCBtYXRyaXggb2YgdGhlIGZpbmFsIG1vZGVsCiAgIyMgQm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50cwogIHgxLjEgPSBzZXEobWluKGJ0LmNvZWYubXRyeFssdmFyLmlkXSksIG1heChidC5jb2VmLm10cnhbLHZhci5pZF0pLCBsZW5ndGg9MzAwICkKICB5MS4xID0gZG5vcm0oeDEuMSwgbWVhbihidC5jb2VmLm10cnhbLHZhci5pZF0pLCBzZChidC5jb2VmLm10cnhbLHZhci5pZF0pKQogICMgaGVpZ2h0IG9mIHRoZSBoaXN0b2dyYW0gLSB1c2UgaXQgdG8gbWFrZSBhIG5pY2UtbG9va2luZyBoaXN0b2dyYW0uCiAgaGlnaGVzdGJhciA9IG1heChoaXN0KGJ0LmNvZWYubXRyeFssdmFyLmlkXSwgcGxvdCA9IEZBTFNFKSRkZW5zaXR5KSAKICB5bGltaXQgPSBtYXgoYyh5MS4xLGhpZ2hlc3RiYXIpKQogIGhpc3QoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdLCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSB2YXIubm0sIHhsYWI9IiIsIAogICAgICAgY29sID0gImF6dXJlMSIseWxpbT1jKDAseWxpbWl0KSwgYm9yZGVyPSJsaWdodHNlYWdyZWVuIikKICBsaW5lcyh4ID0geDEuMSwgeSA9IHkxLjEsIGNvbCA9ICJyZWQzIikKICBsaW5lcyhkZW5zaXR5KGJ0LmNvZWYubXRyeFssdmFyLmlkXSwgYWRqdXN0PTIpLCBjb2w9ImJsdWUiKSAKICAjbGVnZW5kKCJ0b3ByaWdodCIsIGMoIiIpKQp9IAogIHBhcihtZnJvdz1jKDIsMikpICAjIGhpc3RvZ3JhbXMgb2YgYm9vdHN0cmFwIGNvZWZzCmJvb3QuaGlzdChidC5jb2VmLm10cng9Y29lZi5tdHJ4LCB2YXIuaWQ9MSwgdmFyLm5tID0iU2xvcGUgSW50ZXJjZXB0IiApCmJvb3QuaGlzdChidC5jb2VmLm10cng9Y29lZi5tdHJ4LCB2YXIuaWQ9MiwgdmFyLm5tID0iUG9pbnRzIFBlciBHYW1lIiApCmJvb3QuaGlzdChidC5jb2VmLm10cng9Y29lZi5tdHJ4LCB2YXIuaWQ9MywgdmFyLm5tID0iUmVib3VuZHMgUGVyIEdhbWUiICkKYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1jb2VmLm10cngsIHZhci5pZD00LCB2YXIubm0gPSJTdGVhbHMgUGVyIEdhbWUiICkKCm51bS5wID0gZGltKGNvZWYubXRyeClbMl0gICMgbnVtYmVyIG9mIHBhcmFtZXRlcnMKYnRjLmNpID0gTlVMTApidGMud2QgPSBOVUxMCmZvciAoaSBpbiAxOm51bS5wKXsKICBsY2kuMDI1ID0gcm91bmQocXVhbnRpbGUoY29lZi5tdHJ4WywgaV0sIDAuMDI1LCB0eXBlID0gMiksOCkKICB1Y2kuOTc1ID0gcm91bmQocXVhbnRpbGUoY29lZi5tdHJ4WywgaV0sMC45NzUsIHR5cGUgPSAyICksOCkKICBidGMud2RbaV0gPSAgdWNpLjk3NSAtIGxjaS4wMjUKICBidGMuY2lbaV0gPSBwYXN0ZSgiWyIsIHJvdW5kKGxjaS4wMjUsNCksIiwgIiwgcm91bmQodWNpLjk3NSw0KSwiXSIpCiB9CiNhcy5kYXRhLmZyYW1lKGJ0Yy5jaSkKUm91bmRlZF9idGMud2QgPSByb3VuZChidGMud2QsNCkKCmNtdHJ4ID0gc3VtbWFyeShCb290c3RyYXBfTW9kZWwpJGNvZWYKCmthYmxlKGFzLmRhdGEuZnJhbWUoY2JpbmQoZm9ybWF0QyhjbXRyeCw0LGZvcm1hdD0iZiIpLCBidGMuY2kuOTU9YnRjLmNpLCBSb3VuZGVkX2J0Yy53ZCkpLCAKICAgICAgY2FwdGlvbiA9ICJCb290c3RyYXAgQ2FzZXMgUmVncmVzc2lvbiBDb2VmZmljaWVudCBNYXRyaXgsIDk1JSBDSSIpCmBgYAojIyMgQm9vdHN0cmFwIENhc2VzIFN1bW1hcnkKQWZ0ZXIgcGVyZm9ybWluZyBib290c3RyYXAgY2FzZSBzYW1wbGluZyAobiA9IDEwMDApLCBJIGNyZWF0ZWQgaGlzdG9ncmFtcyBvZiBlYWNoIGNvZWZmaWNpZW50J3MgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbi4gRWFjaCBoaXN0b2dyYW0gYWxzbyBjb250YWlucyB0d28gZGVuc2l0eSBjdXJ2ZXMuIFRoZSByZWQgY3VydmUgaXMgcmVwcmVzZW50YXRpdmUgb2YgZXN0aW1hdGVkIGNvZWZmaWNpZW50cyB2aWEgdGhlIGxpbmVhciBtb2RlbCB0aGF0IHdlIHN0YXJ0ZWQgdG9kYXkncyBhbmFseXNpcyB3aXRoICh0aGUgYm94LWNveCB0cmFuc2Zvcm1lZCBtb2RlbCkuIFdoaWxlIHRoZSBibHVlIGN1cnZlIHJlcHJlc2VudHMgdGhlIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gZm9ybWVkIGZyb20gdGhlIGNhc2VzIG1ldGhvZC4gV2Ugc2VlIHRyZW1lbmRvdXMgb3ZlcmxhcCBiZXR3ZWVuIHRoZSB0d28gY3VydmVzIGluIGFsbCBvZiBvdXIgaGlzdG9ncmFtcywgZXNwZWNpYWxseSBmb3IgdGhlIHNsb3BlIGludGVyY2VwdCBhbmQgcmVib3VuZHMgcGVyIGdhbWUuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlcmUgaXMgbm90IG11Y2ggZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBjb2VmZmljaWVudCB2YWx1ZXMgb3JpZ2luYWxseSBjYWxjdWxhdGVkIHZpYSB0aGUgcmVncmVzc2lvbiBtb2RlbCwgYW5kIHRob3NlIGZvdW5kIHRocm91Z2ggdGhlIGJvb3RzdHJhcCBzYW1wbGluZy4KCk5leHQsIHdlIGxvb2sgYXQgb3VyIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoYnRjLmNpLjk1KS4gV2UgY2FuIHNlZSB0aGF0IGVhY2ggaW50ZXJ2YWwgY2FwdHVyZXMgdGhlIHJhbmdlIG9mIHZhbHVlcyB0aGF0IG91ciBvcmlnaW5hbCByZWdyZXNzaW9uIGNvZWZmaWNpZW50IHBsdXMgb3IgbWludXMgaXRzIGdpdmVuIHN0YW5kYXJkIGVycm9yIHdvdWxkIGJlIGVxdWFsIHRvLiBUaGlzIG1lYW5zIHRoYXQgdGhlcmUgaXMgbm8gY29udHJhZGljdGlvbiBiZXR3ZWVuIG91ciBtb2RlbCBhbmQgaXRzIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24uCgojIyBCb290c3RyYXAgQXBwcm9hY2ggMiAtIEJvb3RzdHJhcCBSZXNpZHVhbHMKVGhlIHNlY29uZCBib290c3RyYXAgbWV0aG9kIEkgdXNlZCBpcyBrbm93biBhcyBib290c3RyYXAgcmVzaWR1YWwgc2FtcGxpbmcuIFRoaXMgYXBwcm9hY2ggd29ya3MgYnkgZml0dGluZyBhIHJlZ3Jlc3Npb24gbW9kZWwgdG8gb3VyIGRhdGEgaW4gYW4gYXR0ZW1wdCB0byBvYnRhaW4gcHJlZGljdGVkIHZhbHVlcyBhbmQgdGhlbiBjcmVhdGluZyBuZXcgYm9vdHN0cmFwIHNhbXBsZXMgZnJvbSBzby4gVGhlc2UgbmV3IHNhbXBsZXMgY29uc2lzdCBvZiBhIG5ldyByZXNwb25zZSB2YXJpYWJsZSBieSB3aGljaCB0aGUgbW9kZWwgZml0cyBieSBhZGRpbmcgcmFuZG9tbHkgc2FtcGxlZCByZXNpZHVhbHMgKHdpdGggcmVwbGFjZW1lbnQpIHRvIHNhaWQgcmVzcG9uc2UgdmFyaWFibGVzIChQVFMsIFRSQiBhbmQgU1RMKS4KCmBgYHtyfQpoaXN0KHNvcnQoQm9vdHN0cmFwX01vZGVsJHJlc2lkdWFscyksbj00MCwKICAgICB4bGFiPSJSZXNpZHVhbHMiLAogICAgIGNvbCA9ICJsaWdodGJsdWUiLAogICAgIGJvcmRlcj0ibmF2eSIsCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gb2YgTW9kZWwgUmVzaWR1YWxzIikKCmludmlzaWJsZShtZWFuKEJvb3RzdHJhcF9Nb2RlbCRyZXNpZHVhbHMpKQoKQm9vdHN0cmFwX01vZGVsID0gbG0gKE1QIH4gUFRTICsgVFJCICsgU1RMLCBkYXRhID0gUmVkdWNlZF9QbGF5b2ZmX0RhdGEyKQptb2RlbC5yZXNpZCA9IEJvb3RzdHJhcF9Nb2RlbCRyZXNpZHVhbHMKIyMKQz0xNTAwCm51bS5wID0gZGltKG1vZGVsLm1hdHJpeChCb290c3RyYXBfTW9kZWwpKVsyXSAgICMgbnVtYmVyIG9mIHBhcmFtZXRlcnMKc2FtcC5uID0gZGltKG1vZGVsLm1hdHJpeChCb290c3RyYXBfTW9kZWwpKVsxXSAgIyBzYW1wbGUgc2l6ZQpidHIubXRyeCA9IG1hdHJpeChyZXAoMCw2KkIpLCBuY29sPW51bS5wKSAjIHplcm8gbWF0cml4IHRvIHN0b3JlIGJvb3QgY29lZnMKZm9yIChpIGluIDE6Qyl7CiAgIyMgQm9vdHN0cmFwIHJlc3BvbnNlIHZhbHVlcwogIGJ0LkJvb3RzdHJhcF9Nb2RlbCA9IEJvb3RzdHJhcF9Nb2RlbCRmaXR0ZWQudmFsdWVzICsgCiAgICAgICAgc2FtcGxlKEJvb3RzdHJhcF9Nb2RlbCRyZXNpZHVhbHMsIHNhbXAubiwgcmVwbGFjZSA9IFRSVUUpICAjIGJvb3RzdHJhcCByZXNpZHVhbHMKICAjIHJlcGxhY2UgUHJpY2VVbml0QXJlYSB3aXRoIGJvb3RzdHJhcCBsb2cgcHJpY2UKICBSZWR1Y2VkX1BsYXlvZmZfRGF0YTIkYnQuQm9vdHN0cmFwX01vZGVsID0gIGJ0LkJvb3RzdHJhcF9Nb2RlbCAgICMgIHNlbmQgdGhlIGJvb3QgcmVzcG9uc2UgdG8gdGhlIGRhdGEKICBidHIubW9kZWwgPSBsbShidC5Cb290c3RyYXBfTW9kZWwgfiBQVFMgKyBUUkIgKyBTVEwsIGRhdGEgPSBSZWR1Y2VkX1BsYXlvZmZfRGF0YTIpICAgCiAgYnRyLm10cnhbaSxdPWJ0ci5tb2RlbCRjb2VmZmljaWVudHMKfQoKYm9vdC5oaXN0ID0gZnVuY3Rpb24oYnQuY29lZi5tdHJ4LCB2YXIuaWQsIHZhci5ubSl7CiAgIyMgYnQuY29lZi5tdHJ4ID0gbWF0cml4IGZvciBzdG9yaW5nIGJvb3RzdHJhcCBlc3RpbWF0ZXMgb2YgY29lZmZpY2llbnRzCiAgIyMgdmFyLmlkID0gdmFyaWFibGUgSUQgKDEsIDIsIC4uLiwgaysxKQogICMjIHZhci5ubSA9IHZhcmlhYmxlIG5hbWUgb24gdGhlIGhpc3QgdGl0bGUsIG11c3QgYmUgdGhlIHN0cmluZyBpbiB0aGUgZG91YmxlIHF1b3RlcwogICMjIEJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgdGhlIGVzdGltYXRlZCBjb2VmZmljaWVudHMKICB4MS4xIDwtIHNlcShtaW4oYnQuY29lZi5tdHJ4Wyx2YXIuaWRdKSwgbWF4KGJ0LmNvZWYubXRyeFssdmFyLmlkXSksIGxlbmd0aD0zMDAgKQogIHkxLjEgPC0gZG5vcm0oeDEuMSwgbWVhbihidC5jb2VmLm10cnhbLHZhci5pZF0pLCBzZChidC5jb2VmLm10cnhbLHZhci5pZF0pKQogICMgaGVpZ2h0IG9mIHRoZSBoaXN0b2dyYW0gLSB1c2UgaXQgdG8gbWFrZSBhIG5pY2UtbG9va2luZyBoaXN0b2dyYW0uCiAgaGlnaGVzdGJhciA9IG1heChoaXN0KGJ0LmNvZWYubXRyeFssdmFyLmlkXSwgcGxvdCA9IEZBTFNFKSRkZW5zaXR5KSAKICB5bGltaXQgPC0gbWF4KGMoeTEuMSxoaWdoZXN0YmFyKSkKICBoaXN0KGJ0LmNvZWYubXRyeFssdmFyLmlkXSwgcHJvYmFiaWxpdHkgPSBUUlVFLCBtYWluID0gdmFyLm5tLCB4bGFiPSIiLCAKICAgICAgIGNvbCA9ICJhenVyZTEiLHlsaW09YygwLHlsaW1pdCksIGJvcmRlcj0ibGlnaHRzZWFncmVlbiIpCiAgbGluZXMoeCA9IHgxLjEsIHkgPSB5MS4xLCBjb2wgPSAicmVkMyIpICAgICAgICMgbm9ybWFsIGRlbnNpdHkgY3VydmUgICAgICAgICAKICBsaW5lcyhkZW5zaXR5KGJ0LmNvZWYubXRyeFssdmFyLmlkXSwgYWRqdXN0PTIpLCBjb2w9ImJsdWUiKSAgICAjIGxvZXNzIGN1cnZlCn0gCnBhcihtZnJvdz1jKDIsMikpICAjIGhpc3RvZ3JhbXMgb2YgYm9vdHN0cmFwIGNvZWZzCmJvb3QuaGlzdChidC5jb2VmLm10cng9YnRyLm10cngsIHZhci5pZD0xLCB2YXIubm0gPSJTbG9wZSBJbnRlcmNlcHQiICkKYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1idHIubXRyeCwgdmFyLmlkPTIsIHZhci5ubSA9IlBvaW50cyBQZXIgR2FtZSIgKQpib290Lmhpc3QoYnQuY29lZi5tdHJ4PWJ0ci5tdHJ4LCB2YXIuaWQ9MywgdmFyLm5tID0iUmVib3VuZHMgUGVyIEdhbWUiICkKYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1idHIubXRyeCwgdmFyLmlkPTQsIHZhci5ubSA9IlN0ZWFscyBQZXIgR2FtZSIgKQoKbnVtLnAgPSBkaW0oY29lZi5tdHJ4KVsyXSAgIyBudW1iZXIgb2YgcGFyYW1ldGVycwpidHIuY2kgPSBOVUxMCmJ0ci53ZCA9IE5VTEwKZm9yIChpIGluIDE6bnVtLnApewogIGxjaS4wMjUgPSByb3VuZChxdWFudGlsZShidHIubXRyeFssIGldLCAwLjAyNSwgdHlwZSA9IDIpLDgpCiAgdWNpLjk3NSA9IHJvdW5kKHF1YW50aWxlKGJ0ci5tdHJ4WywgaV0sMC45NzUsIHR5cGUgPSAyICksOCkKICBidHIud2RbaV0gPSB1Y2kuOTc1IC0gbGNpLjAyNQogIGJ0ci5jaVtpXSA9IHBhc3RlKCJbIiwgcm91bmQobGNpLjAyNSw0KSwiLCAiLCByb3VuZCh1Y2kuOTc1LDQpLCJdIikKfQoKUm91bmRlZF9idHIud2QgPSByb3VuZChidHIud2QsNCkKa2FibGUoYXMuZGF0YS5mcmFtZShjYmluZChmb3JtYXRDKGNtdHJ4LDQsZm9ybWF0PSJmIiksIGJ0ci5jaS45NT1idHIuY2ksIFJvdW5kZWRfYnRyLndkKSksIAogICAgICBjYXB0aW9uID0gIkJvb3RzdHJhcCBSZXNpZHVhbCBSZWdyZXNzaW9uIENvZWZmaWNpZW50IE1hdHJpeCwgOTUlIENJIikKCmBgYAojIyMgQm9vdHN0cmFwIFJlc2lkdWFscyBTdW1tYXJ5CldlIGNhbiBzZWUgZnJvbSBvdXIgbW9kZWwgcmVzaWR1YWwgaGlzdG9ncmFtIHRoYXQgb3VyIHJlc2lkdWFscyBhcmUgbm90IHF1aXRlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCBhcyB0aGVyZSBpcyBhIHZpc2libGUgc2xpZ2h0IHJpZ2h0d2FyZCBza2V3LCB5ZXQgdGhlIGNhbGN1bGF0ZWQgbWVhbiBvZiB0aGUgcmVzaWR1YWxzIGlzIGV4dHJlbWVseSBjbG9zZSB0byB6ZXJvICh+Ny40Xi0xN14pLCBzbyB3ZSBwcm9jZWVkIHdpdGggY2F1dGlvbi4KCkxpa2UgaW4gdGhlIHJlc2lkdWFsIGJvb3RzdHJhcCBoaXN0b2dyYW1zIHByb2R1Y2VkIGZyb20gdGhlIGJvb3RzdHJhcCBjYXNlcyBtZXRob2QsIG91ciBoaXN0b2dyYW1zIGhlcmUgc2hvdyBhIGNsb3NlIHByb3hpbWl0eSBiZXR3ZWVuIHRoZSB0cmFkaXRpb25hbCByZWdyZXNzaW9uIGRlbnNpdHkgY3VydmUgKHJlZCBsaW5lKSBhbmQgdGhlIGJvb3RzdHJhcC1iYXNlZCBkZW5zaXR5IGN1cnZlIChibHVlIGxpbmUpLiBUaGlzIGluZGljYXRlcyBhIGhpZ2ggZGVncmVlIG9mIHNoYXJlZCB2YWx1ZXMgZnJvbSB0aGUgdHdvIGVzdGltYXRpb25zLiBOb3RlIHRoYXQgaW4gdGhpcyBpbnN0YW5jZSwgdGhlIGJsdWUgbGluZSBpcyByZXByZXNlbnRhdGl2ZSBvZiBib290c3RyYXAgcmVzaWR1YWxzJyBzYW1wbGluZyBkaXN0cmlidXRpb24uCgpMYXN0bHksIHdlIHRha2UgYSBsb29rIGF0IHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKGJ0ci5jaS45NSkgY3JlYXRlZCBmb3Igb3VyIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLiBPbmNlIGFnYWluLCBhbGwgb2Ygb3VyIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHZpYSB0aGUgYm9vdHN0cmFwIG1ldGhvZCBhcmUgd2l0aGluIHRoZSByYW5nZSBvZiBvdXIgb3JpZ2luYWwgcmVncmVzc2lvbi1jYWxjdWxhdGVkIGNvZWZmaWNpZW50cywgcGx1cyBvciBtaW51cyB0aGVpciBnaXZlbiBzdGFuZGFyZCBlcnJvci4gSGVuY2UgdGhlIHJlc3VsdHMgZnJvbSBwZXJmb3JtaW5nIHRoZSBib290c3RyYXAgcmVzaWR1YWxzIG1ldGhvZCBhcmUgaW4gYWxpZ25tZW50IHdpdGggdGhlIHRha2Vhd2F5cyBmcm9tIG91ciBzaW1wbGlmaWVkIG1vZGVsIHRoYXQgd2Ugc3RhcnRlZCB0b2RheSdzIGFuYWx5c2lzIHdpdGguIAoKCiMgQ29uY2x1c2lvbgpCZWxvdyB3ZSBjYW4gc2VlIGEgc3VtbWFyeSBvZiBvdXIgbW9kZWwsIGl0cyBvcmlnaW5hbCByZWdyZXNzaW9uIGNvZWZmaWNpZW50cywgYXMgd2VsbCBhcyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBtZXRyaWNzIGZvciBpdHMgYm9vdHN0cmFwIGNhc2VzIGFuZCBib290c3RyYXAgcmVzaWR1YWwgZGlzdHJpYnV0aW9ucy4gR2l2ZW4gdGhhdCBhbGwgdGhyZWUgbWV0aG9kcyB5aWVsZGVkIHJlc3VsdHMgcHJhY3RpY2FsbHkgaW4gYWxpZ25tZW50IHdpdGggZWFjaCBvdGhlciwgd2UgY2FuIHNhZmVseSBzYXkgdGhhdCBhbiBOQkEgcGxheWVyJ3MgYXZlcmFnZSBwbGF5aW5nIHRpbWUgaGFzIGEgc3Ryb25nIGxpbmVhciByZWxhdGlvbnNoaXAgd2l0aCBoaXMgYXZlcmFnZXMgaW4gcG9pbnRzLCByZWJvdW5kcyBhbmQgc3RlYWxzIHBlciBnYW1lLCB3aXRoIHRoZSBleGFjdCBkZWdyZWUgb2YgY29ycmVsYXRpb24gc2xpZ2h0bHkgZGlmZmVyaW5nIHZpYSB0aGUgd2lkdGhzIG9mIHNhaWQgY29uZmlkZW5jZSBpbnRlcnZhbHMuCgpgYGB7cn0KUm91bmRlZF9JbnRlcnZhbF9XaWR0aHMgPSBjYmluZChSb3VuZGVkX2J0Yy53ZCwgUm91bmRlZF9idHIud2QpCgprYWJsZShhcy5kYXRhLmZyYW1lKGNiaW5kKGZvcm1hdEMoY210cnhbLC0zXSw0LGZvcm1hdD0iZiIpLCBidGMuY2kuOTU9YnRjLmNpLGJ0ci5jaS45NT1idHIuY2ksIFJvdW5kZWRfSW50ZXJ2YWxfV2lkdGhzKSksIAogICAgICBjYXB0aW9uPSJGaW5hbCBSZWdyZXNzaW9uIENvZWZmaWNpZW50IEVzdGltYXRlczogUC1WYWx1ZXMgYW5kIEJvb3RzdHJhcCBDSXMiKQoKYGBgCgojIFN1bW1hcnkvRGlzY3Vzc2lvbgpUaGUgZmluZGluZ3MgZnJvbSBteSBhbmFseXNpcyBvdmVyIHRoZSBwYXN0IGZldyB3ZWVrcyBjb3VsZCBiZSB2YWx1YWJsZSB0byBOQkEgcGxheWVycyBhcyB3ZWxsIGFzIHRob3NlIGRlZXBseSB2ZXN0ZWQgaW4gdGhlaXIgb24tY291cnQgcGVyZm9ybWFuY2Ugc3VjaCBhcyBhZ2VudHMgYW5kIGFkdmVydGlzZXJzLiBJZiBhIHBsYXllciBkZXNpcmVzIG1vcmUgcGxheWluZyB0aW1lLCBpdCBpcyBoZWxwZnVsIHRvIGtub3cgZXhhY3RseSB3aGF0IG1ldHJpY3MgKFBUUywgVFJCIGFuZCBTVEwgaW4gdGhpcyBjYXNlKSBoYXZpbmcgYW4gaW5jcmVhc2UgaW4gd2lsbCB0cmFkaXRpb25hbGx5IGNvcnJlbGF0ZSB3aXRoIG1vcmUgcGxheWluZyB0aW1lIGFjcm9zcyB0aGUgbGVhZ3VlLgoKRm9yIG15IGFuYWx5c2lzLCB0aGUgbW9zdCByZWNlbnQgZGF0YXNldCBJIGNvdWxkIGZpbmQgd2FzIG9uZSBmcm9tIHRoZSAyMDIyLTIwMjMgTkJBIHNlYXNvbi4gTW92aW5nIGZvcndhcmQsIGlmIHRoZXJlIHdhcyBhIHdheSBJIGNvdWxkIHBlcmZvcm0gc2ltaWxhciBleHBsb3JhdGlvbiBvbiBkYXRhIGZyb20gdGhlIG1vc3QgcmVjZW50IE5CQSBzZWFzb24sIHRoYXQgd291bGQgcG90ZW50aWFsbHkgYnJpbmcgZXZlbiBfbW9yZV8gY3JlZGliaWxpdHkgdG8gd2hhdGV2ZXIgZmluZGluZ3MgcmVzdWx0ZWQuCgojIFJlZmVyZW5jZXM6Ck9yaWdpbmFsIERhdGFzZXQgU291cmNlOiA8aHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy92aXZvdmluY28vMjAyMjIwMjMtbmJhLXBsYXllci1zdGF0cy1yZWd1bGFyPgoKRGF0YXNldCBEb3dubG9hZCBMaW5rIHZpYSBHaXRodWI6Cmh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DaHJpc0IyMzIzL1NUQTMyMS9tYWluL1BsYXlvZmZfRGF0YS5jc3YgCgpNeSBQcmV2aW91cyBBbmFseXNlczoKCi0gUmVsYXRpb25zaGlwIEJldHdlZW4gQWxsIDUgU3RhbmRhcmQgU3RhdGlzdGljcyBhbmQgQ2lyY3Vtc3RhbmNlIHdpdGggUGxheWluZyBUaW1lIGh0dHBzOi8vcnB1YnMuY29tL0NocmlzX0JhaG0vMTM0NzQzNgoKLSBSZWxhdGlvbnNoaXAgQmV0d2VlbiBTY29yaW5nIE91dHB1dCBhbmQgUGxheWluZyBUaW1lOiBodHRwczovL3JwdWJzLmNvbS9DaHJpc19CYWhtLzEzNDQ0Njg=