Introduction
This report will compare standard multiple linear regression with
bootstrap resampled multiple linear regression
The data set used for this report has been uploaded for public access
to the GitHub repository: ncbrechbill/STA321: Repository for the class
STA321, Topics in Advanced Statistics. The web URL for this page is https://github.com/ncbrechbill/STA321.
The following continuous variables will be used for all further
analyses:
Arr_Delay \(Y\) : Arrival delay
to destination, in minutes.
Airport_Distance \(X_1\) : The
distance between the airports in miles.
Number_of_flights \(X_2\) :
Total number of flights in the departure airport.
Support_Crew_Available \(X_3\) :
Total number of support crew available.
Baggage_loading_time \(X_4\) :
Time to load all baggage in minutes.
Late_Arrival_o \(X_5\) :
Aircraft’s late arrival to airport in minutes.
Cleaning_o \(X_6\) : Time to
clean the aircraft in minutes.
Fueling_o \(X_7\) : Time to fuel
the aircraft in minutes.
Security_o \(X_8\) : Time to
complete security clearing in minutes.

Practical Question
We aim to model and predict a flight’s delay time given measurable
parameters. This can help an airport provide information to airlines,
aircraft crew, and passengers about the expected delay time. This can be
beneficial for several reasons, including attempts to reduce these
delays and increase airport efficiency and satisfaction.
Standard Multiple
Linear Regression
Let \(\{x_1, x_2, \cdots, x_k \}\)
be \(k\) explanatory variables and
\(y\) be the response variables. The
general form of the multiple linear regression model is defined as
\[
y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \cdots + \beta_k x_k +
\epsilon.
\]
We first start with a full model.




Step-wise selection will determine which variables are most important
to the model. We will perform stepwise selection in both directions to
ensure consistency, starting with both an “empty” model with no factors
and a “full” model with all factors.
## Start: AIC=24253.75
## Arr_Delay ~ 1
##
## Df Sum of Sq RSS AIC
## + Number_of_flights 1 2077915 989863 20192
## + Baggage_loading_time 1 1883866 1183911 20835
## + Late_Arrival_o 1 1364163 1703614 22142
## + Airport_Distance 1 713213 2354565 23305
## + Support_Crew_Available 1 401766 2666011 23751
## + Security_o 1 19673 3048105 24233
## + Fueling_o 1 4034 3063744 24251
## <none> 3067777 24254
## + Cleaning_o 1 37 3067740 24256
##
## Step: AIC=20191.55
## Arr_Delay ~ Number_of_flights
##
## Df Sum of Sq RSS AIC
## + Baggage_loading_time 1 297505 692358 18909
## + Late_Arrival_o 1 176896 812967 19486
## + Airport_Distance 1 80801 909062 19888
## + Support_Crew_Available 1 44206 945656 20029
## + Security_o 1 1072 988791 20190
## <none> 989863 20192
## + Cleaning_o 1 119 989744 20193
## + Fueling_o 1 3 989859 20194
## - Number_of_flights 1 2077915 3067777 24254
##
## Step: AIC=18909.19
## Arr_Delay ~ Number_of_flights + Baggage_loading_time
##
## Df Sum of Sq RSS AIC
## + Late_Arrival_o 1 80895 611462 18465
## + Airport_Distance 1 34139 658219 18730
## + Support_Crew_Available 1 18656 673702 18813
## <none> 692358 18909
## + Fueling_o 1 375 691982 18909
## + Security_o 1 230 692128 18910
## + Cleaning_o 1 185 692173 18910
## - Baggage_loading_time 1 297505 989863 20192
## - Number_of_flights 1 491553 1183911 20835
##
## Step: AIC=18464.76
## Arr_Delay ~ Number_of_flights + Baggage_loading_time + Late_Arrival_o
##
## Df Sum of Sq RSS AIC
## + Airport_Distance 1 27479 583984 18302
## + Support_Crew_Available 1 14610 596853 18380
## <none> 611462 18465
## + Fueling_o 1 327 611135 18465
## + Cleaning_o 1 282 611181 18465
## + Security_o 1 15 611447 18467
## - Late_Arrival_o 1 80895 692358 18909
## - Baggage_loading_time 1 201504 812967 19486
## - Number_of_flights 1 324014 935476 19991
##
## Step: AIC=18301.55
## Arr_Delay ~ Number_of_flights + Baggage_loading_time + Late_Arrival_o +
## Airport_Distance
##
## Df Sum of Sq RSS AIC
## + Support_Crew_Available 1 13580 570404 18219
## <none> 583984 18302
## + Cleaning_o 1 264 583720 18302
## + Fueling_o 1 180 583803 18302
## + Security_o 1 8 583976 18304
## - Airport_Distance 1 27479 611462 18465
## - Late_Arrival_o 1 74235 658219 18730
## - Baggage_loading_time 1 172621 756605 19230
## - Number_of_flights 1 283853 867836 19723
##
## Step: AIC=18219.02
## Arr_Delay ~ Number_of_flights + Baggage_loading_time + Late_Arrival_o +
## Airport_Distance + Support_Crew_Available
##
## Df Sum of Sq RSS AIC
## <none> 570404 18219
## + Cleaning_o 1 150 570254 18220
## + Fueling_o 1 98 570306 18220
## + Security_o 1 20 570384 18221
## - Support_Crew_Available 1 13580 583984 18302
## - Airport_Distance 1 26448 596853 18380
## - Late_Arrival_o 1 70633 641037 18637
## - Baggage_loading_time 1 159829 730234 19105
## - Number_of_flights 1 267074 837478 19597

Both directions determined that the best model is fitted as
follows:
\[
Y = -569 + 0.004497 X_2 + 13.97 X_4 + 7.093 X_5 + 0.1766 X_1 - 0.04974
X_3
\]
Based on residual analysis violations, bootstrap sampling will be
used to create a more appropriate and fitting model.
Bootstrap Cases
We will begin by using bootstrap cases to estimate the coefficients.
The distributions and confidence intervals will be found and
displayed.
delay <- lm(Arr_Delay ~ Number_of_flights + Baggage_loading_time + Late_Arrival_o + Airport_Distance + Support_Crew_Available, data = flight)
cmtrx <- summary(delay)$coef
##
B = 1000 # choose the number of bootstrap replicates.
##
num.p = dim(model.frame(delay))[2] # returns number of parameters in the model
smpl.n = dim(model.frame(delay))[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
delay.btc = lm(Arr_Delay ~ Number_of_flights + Baggage_loading_time + Late_Arrival_o + Airport_Distance + Support_Crew_Available, data = flight[bootc.id,])
coef.mtrx[i,] = coef(delay.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(""))
}
The following histograms represent the distribution of each of the
bootstrapped coefficients.
par(mfrow=c(2,3)) # histograms of bootstrap coefs
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=1, var.nm ="Intercept" )
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=2, var.nm ="Number of Flights" )
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=3, var.nm ="Baggage Loading Time" )
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=4, var.nm ="Late Arrival" )
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=5, var.nm ="Airport Distance" )
boot.hist(bt.coef.mtrx=coef.mtrx, var.id=6, var.nm ="Support Crew Available" )

Two normal-density curves were placed on each of the histograms.
The red density curve uses the estimated
regression coefficients and their corresponding standard error in the
output of the regression procedure. The p-values reported in the output
are based on the red curve.
The blue curve is a non-parametric data-driven
estimate of the density of bootstrap sampling distribution. The
bootstrap confidence intervals of the regressions are based on these
non-parametric bootstrap sampling distributions.
We can see from the above histograms that the two density curves in
all histograms are close to each other. we would expect that
significance test results and the corresponding bootstrap confidence
intervals are consistent. Next, we find 95% bootstrap confidence
intervals of each regression coefficient and combined them with the
output of the final model.
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)
kable(as.data.frame(cbind(formatC(cmtrx,4,format="f"), btc.ci.95=btc.ci)),
caption = "Regression Coefficient Matrix")
Regression Coefficient Matrix
| (Intercept) |
-569.0375 |
7.3229 |
-77.7061 |
0.0000 |
[ -585.7031 , -551.5961 ] |
| Number_of_flights |
0.0045 |
0.0001 |
40.9817 |
0.0000 |
[ 0.0043 , 0.0047 ] |
| Baggage_loading_time |
13.9737 |
0.4408 |
31.7032 |
0.0000 |
[ 13.1707 , 14.8182 ] |
| Late_Arrival_o |
7.0929 |
0.3365 |
21.0755 |
0.0000 |
[ 6.4137 , 7.7148 ] |
| Airport_Distance |
0.1766 |
0.0137 |
12.8966 |
0.0000 |
[ 0.1495 , 0.2027 ] |
| Support_Crew_Available |
-0.0497 |
0.0054 |
-9.2410 |
0.0000 |
[ -0.0598 , -0.0397 ] |
All the coefficients are statistically significant, and the
confidence intervals are provided.
Bootstrap
Residuals
Assume that the fitted regression model is given by
\[
\begin{array}{ccc}
y_1 & = & \hat{\beta}_0 + \hat{\beta}_1 x_{11} + \hat{\beta}_2
x_{12} + \cdots + \hat{\beta}_k x_{1k} + e_1 \\
y_2 & = & \hat{\beta}_0 + \hat{\beta}_1 x_{21} + \hat{\beta}_2
x_{22} + \cdots + \hat{\beta}_k x_{2k} + e_2 \\
y_3 & = & \hat{\beta}_0 + \hat{\beta}_1 x_{31} + \hat{\beta}_2
x_{32} + \cdots + \hat{\beta}_k x_{3k} + e_3 \\
\vdots & \vdots & \vdots \\
y_n & = & \hat{\beta}_0 + \hat{\beta}_1 x_{n1} + \hat{\beta}_2
x_{n2} + \cdots + \hat{\beta}_k x_{nk} + e_n
\end{array}
\]
where \(\{e_1, e_2, \cdots, e_n \}\)
is the set of residuals obtained from the final model. \(\{x_{i1}, x_{i2}, \cdots, x_{ik} \}\) is
the i-th record from the data, and \(\{
\hat{\beta}_0, \hat{\beta}_1, \cdots, \hat{\beta}_k \}\) are the
estimated regression coefficients based on the original random
sample.
The distribution of the residuals is depicted in the following
histogram.
hist(sort(delay$residuals),n=40,
xlab="Residuals",
col = "lightblue",
border="navy",
main = "Histogram of Residuals")

delay.resid <- delay$residuals
B=1000
num.p = dim(model.matrix(delay))[2] # number of parameters
samp.n = dim(model.matrix(delay))[1] # sample size
btr.mtrx = matrix(rep(0,6*B), ncol=num.p) # zero matrix to store boot coefs
for (i in 1:B){
## Bootstrap response values
bt.delay = delay$fitted.values +
sample(delay.resid, samp.n, replace = TRUE) # bootstrap residuals
# replace PriceUnitArea with bootstrap log price
flight$bt.delay = bt.delay # send the boot response to the data
btr.model = lm(bt.delay ~ Number_of_flights + Baggage_loading_time + Late_Arrival_o + Airport_Distance + Support_Crew_Available, data = flight) # b
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,3)) # histograms of bootstrap coefs
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=1, var.nm ="Intercept" )
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=2, var.nm ="Number of Flights" )
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=3, var.nm ="Baggage Loading Time" )
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=4, var.nm ="Late Arrival" )
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=5, var.nm ="Distance to Airport" )
boot.hist(bt.coef.mtrx=btr.mtrx, var.id=6, var.nm ="Support Crew Available" )

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),"]")
}
#as.data.frame(btc.ci)
kable(as.data.frame(cbind(formatC(cmtrx,4,format="f"), btr.ci.95=btr.ci)),
caption = "Regression Coefficient Matrix with 95% Residual Bootstrap CI")
Regression Coefficient Matrix with 95% Residual Bootstrap
CI
| (Intercept) |
-569.0375 |
7.3229 |
-77.7061 |
0.0000 |
[ -583.3537 , -554.4205 ] |
| Number_of_flights |
0.0045 |
0.0001 |
40.9817 |
0.0000 |
[ 0.0043 , 0.0047 ] |
| Baggage_loading_time |
13.9737 |
0.4408 |
31.7032 |
0.0000 |
[ 13.0799 , 14.8642 ] |
| Late_Arrival_o |
7.0929 |
0.3365 |
21.0755 |
0.0000 |
[ 6.4633 , 7.7799 ] |
| Airport_Distance |
0.1766 |
0.0137 |
12.8966 |
0.0000 |
[ 0.15 , 0.2015 ] |
| Support_Crew_Available |
-0.0497 |
0.0054 |
-9.2410 |
0.0000 |
[ -0.0598 , -0.0393 ] |
Analysis
The results of the standard and the bootstrapped models were very
similar. The first model was computationally the easiest to create, but
the bootstrapped models helped keep the assumptions of linear regression
under control, particularly the violations we observed in residual
analysis. The bootstrap model should thus be used for building
predictions.
Some of the variables that were excluded from the model were routine
airport activities. This indicates that the time to complete these are
not contributing factors to delays. Some of the factors that were
important to the model were based around general airport traffic and
business (total flights, baggage loading time, support crew available).
These factors seem to indicate that having more staff available to
handle the amount of flights may reduce the amount and magnitude of
delays. Some factors are almost impossible to account for (airport
distance, late arrival) and will likely always account for some amount
of delays.
LS0tDQp0aXRsZTogIlJlZ3Jlc3Npb24gQW5hbHlzaXMgb2YgQWlycG9ydCBEZWxheSBUaW1lcyINCmF1dGhvcjogIk5vYWggQnJlY2hiaWxsIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfd2lkdGg6IDYNCiAgICBmaWdfaGVpZ2h0OiA2DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgdGhlbWU6IGx1bWVuDQotLS0NCg0KYGBgez1odG1sfQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCmgxLnRpdGxlIHsNCiAgZm9udC1zaXplOiAyMHB4Ow0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDEgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjJweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMiB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE1cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KPC9zdHlsZT4NCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsIGVycm9yPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KaWYgKCFyZXF1aXJlKCJHR2FsbHkiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiR0dhbGx5IikNCiAgIGxpYnJhcnkoR0dhbGx5KQ0KfQ0KaWYgKCFyZXF1aXJlKCJwYW5kZXIiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwYW5kZXIiKQ0KICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmICghcmVxdWlyZSgiTUFTUyIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoIk1BU1MiKQ0KICBsaWJyYXJ5KE1BU1MpDQp9DQppZiAoIXJlcXVpcmUoImJvb3QiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJib290IikNCiAgbGlicmFyeShib290KQ0KfQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KdXJsIDwtICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vbmNicmVjaGJpbGwvU1RBMzIxL21haW4vU1RBMzIxL0ZsaWdodF9kZWxheS1kYXRhLmNzdiINCmZsaWdodCA8LSByZWFkLmNzdih1cmwpDQpmbGlnaHQgPC0gZHBseXI6OnNlbGVjdChmbGlnaHQsIEFpcnBvcnRfRGlzdGFuY2UsIE51bWJlcl9vZl9mbGlnaHRzLCBTdXBwb3J0X0NyZXdfQXZhaWxhYmxlLCBCYWdnYWdlX2xvYWRpbmdfdGltZSwgTGF0ZV9BcnJpdmFsX28sIENsZWFuaW5nX28sIEZ1ZWxpbmdfbywgU2VjdXJpdHlfbywgQXJyX0RlbGF5KQ0KYGBgDQoNClRoaXMgcmVwb3J0IHdpbGwgY29tcGFyZSBzdGFuZGFyZCBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiB3aXRoIGJvb3RzdHJhcCByZXNhbXBsZWQgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24NCg0KVGhlIGRhdGEgc2V0IHVzZWQgZm9yIHRoaXMgcmVwb3J0IGhhcyBiZWVuIHVwbG9hZGVkIGZvciBwdWJsaWMgYWNjZXNzIHRvIHRoZSBHaXRIdWIgcmVwb3NpdG9yeTogbmNicmVjaGJpbGwvU1RBMzIxOiBSZXBvc2l0b3J5IGZvciB0aGUgY2xhc3MgU1RBMzIxLCBUb3BpY3MgaW4gQWR2YW5jZWQgU3RhdGlzdGljcy4gVGhlIHdlYiBVUkwgZm9yIHRoaXMgcGFnZSBpcyA8aHR0cHM6Ly9naXRodWIuY29tL25jYnJlY2hiaWxsL1NUQTMyMT4uDQoNClRoZSBmb2xsb3dpbmcgY29udGludW91cyB2YXJpYWJsZXMgd2lsbCBiZSB1c2VkIGZvciBhbGwgZnVydGhlciBhbmFseXNlczoNCg0KLSAgIEFycl9EZWxheSAkWSQgOiBBcnJpdmFsIGRlbGF5IHRvIGRlc3RpbmF0aW9uLCBpbiBtaW51dGVzLg0KDQotICAgQWlycG9ydF9EaXN0YW5jZSAkWF8xJCA6IFRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBhaXJwb3J0cyBpbiBtaWxlcy4NCg0KLSAgIE51bWJlcl9vZl9mbGlnaHRzICRYXzIkIDogVG90YWwgbnVtYmVyIG9mIGZsaWdodHMgaW4gdGhlIGRlcGFydHVyZSBhaXJwb3J0Lg0KDQotICAgU3VwcG9ydF9DcmV3X0F2YWlsYWJsZSAkWF8zJCA6IFRvdGFsIG51bWJlciBvZiBzdXBwb3J0IGNyZXcgYXZhaWxhYmxlLg0KDQotICAgQmFnZ2FnZV9sb2FkaW5nX3RpbWUgJFhfNCQgOiBUaW1lIHRvIGxvYWQgYWxsIGJhZ2dhZ2UgaW4gbWludXRlcy4NCg0KLSAgIExhdGVfQXJyaXZhbF9vICRYXzUkIDogQWlyY3JhZnQncyBsYXRlIGFycml2YWwgdG8gYWlycG9ydCBpbiBtaW51dGVzLg0KDQotICAgQ2xlYW5pbmdfbyAkWF82JCA6IFRpbWUgdG8gY2xlYW4gdGhlIGFpcmNyYWZ0IGluIG1pbnV0ZXMuDQoNCi0gICBGdWVsaW5nX28gJFhfNyQgOiBUaW1lIHRvIGZ1ZWwgdGhlIGFpcmNyYWZ0IGluIG1pbnV0ZXMuDQoNCi0gICBTZWN1cml0eV9vICRYXzgkIDogVGltZSB0byBjb21wbGV0ZSBzZWN1cml0eSBjbGVhcmluZyBpbiBtaW51dGVzLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmdncGFpcnMoZmxpZ2h0KQ0KYGBgDQoNCiMgUHJhY3RpY2FsIFF1ZXN0aW9uDQoNCldlIGFpbSB0byBtb2RlbCBhbmQgcHJlZGljdCBhIGZsaWdodCdzIGRlbGF5IHRpbWUgZ2l2ZW4gbWVhc3VyYWJsZSBwYXJhbWV0ZXJzLiBUaGlzIGNhbiBoZWxwIGFuIGFpcnBvcnQgcHJvdmlkZSBpbmZvcm1hdGlvbiB0byBhaXJsaW5lcywgYWlyY3JhZnQgY3JldywgYW5kIHBhc3NlbmdlcnMgYWJvdXQgdGhlIGV4cGVjdGVkIGRlbGF5IHRpbWUuIFRoaXMgY2FuIGJlIGJlbmVmaWNpYWwgZm9yIHNldmVyYWwgcmVhc29ucywgaW5jbHVkaW5nIGF0dGVtcHRzIHRvIHJlZHVjZSB0aGVzZSBkZWxheXMgYW5kIGluY3JlYXNlIGFpcnBvcnQgZWZmaWNpZW5jeSBhbmQgc2F0aXNmYWN0aW9uLg0KDQojIFN0YW5kYXJkIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uDQoNCkxldCAkXHt4XzEsIHhfMiwgXGNkb3RzLCB4X2sgXH0kIGJlICRrJCBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYW5kICR5JCBiZSB0aGUgcmVzcG9uc2UgdmFyaWFibGVzLiBUaGUgZ2VuZXJhbCBmb3JtIG9mIHRoZSBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBpcyBkZWZpbmVkIGFzDQoNCiQkDQp5ID0gXGJldGFfMCArIFxiZXRhXzEgeF8xICsgXGJldGFfMiB4XzIgKyBcY2RvdHMgKyBcYmV0YV9rIHhfayArIFxlcHNpbG9uLg0KJCQNCg0KV2UgZmlyc3Qgc3RhcnQgd2l0aCBhIGZ1bGwgbW9kZWwuDQoNCmBgYHtyLCBmaWcuc2hvdz0naG9sZCcsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmZ1bGwubW9kZWwgPC0gbG0oQXJyX0RlbGF5IH4gLiwgZGF0YSA9IGZsaWdodCkNCnBsb3QoZnVsbC5tb2RlbCkNCmBgYA0KDQpTdGVwLXdpc2Ugc2VsZWN0aW9uIHdpbGwgZGV0ZXJtaW5lIHdoaWNoIHZhcmlhYmxlcyBhcmUgbW9zdCBpbXBvcnRhbnQgdG8gdGhlIG1vZGVsLiBXZSB3aWxsIHBlcmZvcm0gc3RlcHdpc2Ugc2VsZWN0aW9uIGluIGJvdGggZGlyZWN0aW9ucyB0byBlbnN1cmUgY29uc2lzdGVuY3ksIHN0YXJ0aW5nIHdpdGggYm90aCBhbiAiZW1wdHkiIG1vZGVsIHdpdGggbm8gZmFjdG9ycyBhbmQgYSAiZnVsbCIgbW9kZWwgd2l0aCBhbGwgZmFjdG9ycy4NCg0KYGBge3IsIGZpZy5zaG93PSdob2xkJywgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NiwgZmlnLmFsaWduPSdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KbnVsbC5tb2RlbCA8LSBsbShBcnJfRGVsYXkgfiAxLCBkYXRhID0gZmxpZ2h0KQ0Kc3RlcCA8LSBzdGVwKG51bGwubW9kZWwsDQogICAgICAgICAgICAgc2NvcGUgPSBsaXN0KGxvd2VyID0gbnVsbC5tb2RlbCwgdXBwZXIgPSBmdWxsLm1vZGVsKSwNCiAgICAgICAgICAgICBkaXJlY3Rpb24gPSAiYm90aCIpDQpwYXIobWZyb3cgPSBjKDIsMikpDQpwbG90KHN0ZXApDQpgYGANCg0KQm90aCBkaXJlY3Rpb25zIGRldGVybWluZWQgdGhhdCB0aGUgYmVzdCBtb2RlbCBpcyBmaXR0ZWQgYXMgZm9sbG93czoNCg0KJCQNClkgPSAtNTY5ICsgMC4wMDQ0OTcgWF8yICsgMTMuOTcgWF80ICsgNy4wOTMgWF81ICsgMC4xNzY2IFhfMSAtIDAuMDQ5NzQgWF8zDQokJA0KDQpCYXNlZCBvbiByZXNpZHVhbCBhbmFseXNpcyB2aW9sYXRpb25zLCBib290c3RyYXAgc2FtcGxpbmcgd2lsbCBiZSB1c2VkIHRvIGNyZWF0ZSBhIG1vcmUgYXBwcm9wcmlhdGUgYW5kIGZpdHRpbmcgbW9kZWwuDQoNCiMgQm9vdHN0cmFwIENhc2VzDQoNCldlIHdpbGwgYmVnaW4gYnkgdXNpbmcgYm9vdHN0cmFwIGNhc2VzIHRvIGVzdGltYXRlIHRoZSBjb2VmZmljaWVudHMuIFRoZSBkaXN0cmlidXRpb25zIGFuZCBjb25maWRlbmNlIGludGVydmFscyB3aWxsIGJlIGZvdW5kIGFuZCBkaXNwbGF5ZWQuDQoNCmBgYHtyfQ0KZGVsYXkgPC0gbG0oQXJyX0RlbGF5IH4gTnVtYmVyX29mX2ZsaWdodHMgKyBCYWdnYWdlX2xvYWRpbmdfdGltZSArIExhdGVfQXJyaXZhbF9vICsgQWlycG9ydF9EaXN0YW5jZSArIFN1cHBvcnRfQ3Jld19BdmFpbGFibGUsIGRhdGEgPSBmbGlnaHQpDQpjbXRyeCA8LSBzdW1tYXJ5KGRlbGF5KSRjb2VmDQojIw0KQiA9IDEwMDAgICAgICAgIyBjaG9vc2UgdGhlIG51bWJlciBvZiBib290c3RyYXAgcmVwbGljYXRlcy4NCiMjIA0KbnVtLnAgPSBkaW0obW9kZWwuZnJhbWUoZGVsYXkpKVsyXSAgIyByZXR1cm5zIG51bWJlciBvZiBwYXJhbWV0ZXJzIGluIHRoZSBtb2RlbA0Kc21wbC5uID0gZGltKG1vZGVsLmZyYW1lKGRlbGF5KSlbMV0gIyBzYW1wbGUgc2l6ZQ0KIyMgemVybyBtYXRyaXggdG8gc3RvcmUgYm9vdHN0cmFwIGNvZWZmaWNpZW50cyANCmNvZWYubXRyeCA9IG1hdHJpeChyZXAoMCwgQipudW0ucCksIG5jb2wgPSBudW0ucCkgICAgICAgDQojIyANCmZvciAoaSBpbiAxOkIpew0KICBib290Yy5pZCA9IHNhbXBsZSgxOnNtcGwubiwgc21wbC5uLCByZXBsYWNlID0gVFJVRSkgIyBmaXQgZmluYWwgbW9kZWwgdG8gdGhlIGJvb3RzdHJhcCBzYW1wbGUNCiAgZGVsYXkuYnRjID0gbG0oQXJyX0RlbGF5IH4gTnVtYmVyX29mX2ZsaWdodHMgKyBCYWdnYWdlX2xvYWRpbmdfdGltZSArIExhdGVfQXJyaXZhbF9vICsgQWlycG9ydF9EaXN0YW5jZSArIFN1cHBvcnRfQ3Jld19BdmFpbGFibGUsIGRhdGEgPSBmbGlnaHRbYm9vdGMuaWQsXSkgICAgIA0KICBjb2VmLm10cnhbaSxdID0gY29lZihkZWxheS5idGMpICAgICMgZXh0cmFjdCBjb2VmcyBmcm9tIGJvb3RzdHJhcCByZWdyZXNzaW9uIG1vZGVsICAgIA0KfQ0KYGBgDQoNCmBgYHtyfQ0KYm9vdC5oaXN0ID0gZnVuY3Rpb24oY210cngsIGJ0LmNvZWYubXRyeCwgdmFyLmlkLCB2YXIubm0pew0KICAjIyBidC5jb2VmLm10cnggPSBtYXRyaXggZm9yIHN0b3JpbmcgYm9vdHN0cmFwIGVzdGltYXRlcyBvZiBjb2VmZmljaWVudHMNCiAgIyMgdmFyLmlkID0gdmFyaWFibGUgSUQgKDEsIDIsIC4uLiwgaysxKQ0KICAjIyB2YXIubm0gPSB2YXJpYWJsZSBuYW1lIG9uIHRoZSBoaXN0IHRpdGxlLCBtdXN0IGJlIHRoZSBzdHJpbmcgaW4gdGhlIGRvdWJsZSBxdW90ZXMNCiAgIyMgY29lZmZpY2llbnQgbWF0cml4IG9mIHRoZSBmaW5hbCBtb2RlbA0KICAjIyBCb290c3RyYXAgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mIHRoZSBlc3RpbWF0ZWQgY29lZmZpY2llbnRzDQogIHgxLjEgPC0gc2VxKG1pbihidC5jb2VmLm10cnhbLHZhci5pZF0pLCBtYXgoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdKSwgbGVuZ3RoPTMwMCApDQogIHkxLjEgPC0gZG5vcm0oeDEuMSwgbWVhbihidC5jb2VmLm10cnhbLHZhci5pZF0pLCBzZChidC5jb2VmLm10cnhbLHZhci5pZF0pKQ0KICAjIGhlaWdodCBvZiB0aGUgaGlzdG9ncmFtIC0gdXNlIGl0IHRvIG1ha2UgYSBuaWNlLWxvb2tpbmcgaGlzdG9ncmFtLg0KICBoaWdoZXN0YmFyID0gbWF4KGhpc3QoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdLCBwbG90ID0gRkFMU0UpJGRlbnNpdHkpIA0KICB5bGltaXQgPC0gbWF4KGMoeTEuMSxoaWdoZXN0YmFyKSkNCiAgaGlzdChidC5jb2VmLm10cnhbLHZhci5pZF0sIHByb2JhYmlsaXR5ID0gVFJVRSwgbWFpbiA9IHZhci5ubSwgeGxhYj0iIiwgDQogICAgICAgY29sID0gImF6dXJlMSIseWxpbT1jKDAseWxpbWl0KSwgYm9yZGVyPSJsaWdodHNlYWdyZWVuIikNCiAgbGluZXMoeCA9IHgxLjEsIHkgPSB5MS4xLCBjb2wgPSAicmVkMyIpDQogIGxpbmVzKGRlbnNpdHkoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdLCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpIA0KICAjbGVnZW5kKCJ0b3ByaWdodCIsIGMoIiIpKQ0KfQ0KYGBgDQoNClRoZSBmb2xsb3dpbmcgaGlzdG9ncmFtcyByZXByZXNlbnQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBlYWNoIG9mIHRoZSBib290c3RyYXBwZWQgY29lZmZpY2llbnRzLg0KDQpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQ0KcGFyKG1mcm93PWMoMiwzKSkgICMgaGlzdG9ncmFtcyBvZiBib290c3RyYXAgY29lZnMNCmJvb3QuaGlzdChidC5jb2VmLm10cng9Y29lZi5tdHJ4LCB2YXIuaWQ9MSwgdmFyLm5tID0iSW50ZXJjZXB0IiApDQpib290Lmhpc3QoYnQuY29lZi5tdHJ4PWNvZWYubXRyeCwgdmFyLmlkPTIsIHZhci5ubSA9Ik51bWJlciBvZiBGbGlnaHRzIiApDQpib290Lmhpc3QoYnQuY29lZi5tdHJ4PWNvZWYubXRyeCwgdmFyLmlkPTMsIHZhci5ubSA9IkJhZ2dhZ2UgTG9hZGluZyBUaW1lIiApDQpib290Lmhpc3QoYnQuY29lZi5tdHJ4PWNvZWYubXRyeCwgdmFyLmlkPTQsIHZhci5ubSA9IkxhdGUgQXJyaXZhbCIgKQ0KYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1jb2VmLm10cngsIHZhci5pZD01LCB2YXIubm0gPSJBaXJwb3J0IERpc3RhbmNlIiApDQpib290Lmhpc3QoYnQuY29lZi5tdHJ4PWNvZWYubXRyeCwgdmFyLmlkPTYsIHZhci5ubSA9IlN1cHBvcnQgQ3JldyBBdmFpbGFibGUiICkNCmBgYA0KDQpUd28gbm9ybWFsLWRlbnNpdHkgY3VydmVzIHdlcmUgcGxhY2VkIG9uIGVhY2ggb2YgdGhlIGhpc3RvZ3JhbXMuDQoNCi0gICBUaGUgcmVkICoqZGVuc2l0eSBjdXJ2ZSoqIHVzZXMgdGhlIGVzdGltYXRlZCByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBzdGFuZGFyZCBlcnJvciBpbiB0aGUgb3V0cHV0IG9mIHRoZSByZWdyZXNzaW9uIHByb2NlZHVyZS4gVGhlIHAtdmFsdWVzIHJlcG9ydGVkIGluIHRoZSBvdXRwdXQgYXJlIGJhc2VkIG9uIHRoZSByZWQgY3VydmUuDQoNCi0gICBUaGUgKipibHVlIGN1cnZlKiogaXMgYSBub24tcGFyYW1ldHJpYyBkYXRhLWRyaXZlbiBlc3RpbWF0ZSBvZiB0aGUgZGVuc2l0eSBvZiBib290c3RyYXAgc2FtcGxpbmcgZGlzdHJpYnV0aW9uLiBUaGUgYm9vdHN0cmFwIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9mIHRoZSByZWdyZXNzaW9ucyBhcmUgYmFzZWQgb24gdGhlc2Ugbm9uLXBhcmFtZXRyaWMgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMuDQoNCldlIGNhbiBzZWUgZnJvbSB0aGUgYWJvdmUgaGlzdG9ncmFtcyB0aGF0IHRoZSB0d28gZGVuc2l0eSBjdXJ2ZXMgaW4gYWxsIGhpc3RvZ3JhbXMgYXJlIGNsb3NlIHRvIGVhY2ggb3RoZXIuIHdlIHdvdWxkIGV4cGVjdCB0aGF0IHNpZ25pZmljYW5jZSB0ZXN0IHJlc3VsdHMgYW5kIHRoZSBjb3JyZXNwb25kaW5nIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFscyBhcmUgY29uc2lzdGVudC4gTmV4dCwgd2UgZmluZCA5NSUgYm9vdHN0cmFwIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9mIGVhY2ggcmVncmVzc2lvbiBjb2VmZmljaWVudCBhbmQgY29tYmluZWQgdGhlbSB3aXRoIHRoZSBvdXRwdXQgb2YgdGhlIGZpbmFsIG1vZGVsLg0KDQpgYGB7cn0NCm51bS5wID0gZGltKGNvZWYubXRyeClbMl0gICMgbnVtYmVyIG9mIHBhcmFtZXRlcnMNCmJ0Yy5jaSA9IE5VTEwNCmJ0Yy53ZCA9IE5VTEwNCmZvciAoaSBpbiAxOm51bS5wKXsNCiAgbGNpLjAyNSA9IHJvdW5kKHF1YW50aWxlKGNvZWYubXRyeFssIGldLCAwLjAyNSwgdHlwZSA9IDIpLDgpDQogIHVjaS45NzUgPSByb3VuZChxdWFudGlsZShjb2VmLm10cnhbLCBpXSwwLjk3NSwgdHlwZSA9IDIgKSw4KQ0KICBidGMud2RbaV0gPSAgdWNpLjk3NSAtIGxjaS4wMjUNCiAgYnRjLmNpW2ldID0gcGFzdGUoIlsiLCByb3VuZChsY2kuMDI1LDQpLCIsICIsIHJvdW5kKHVjaS45NzUsNCksIl0iKQ0KIH0NCiNhcy5kYXRhLmZyYW1lKGJ0Yy5jaSkNCmthYmxlKGFzLmRhdGEuZnJhbWUoY2JpbmQoZm9ybWF0QyhjbXRyeCw0LGZvcm1hdD0iZiIpLCBidGMuY2kuOTU9YnRjLmNpKSksIA0KICAgICAgY2FwdGlvbiA9ICJSZWdyZXNzaW9uIENvZWZmaWNpZW50IE1hdHJpeCIpDQpgYGANCg0KQWxsIHRoZSBjb2VmZmljaWVudHMgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIGFuZCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgYXJlIHByb3ZpZGVkLg0KDQojIEJvb3RzdHJhcCBSZXNpZHVhbHMNCg0KQXNzdW1lIHRoYXQgdGhlIGZpdHRlZCByZWdyZXNzaW9uIG1vZGVsIGlzIGdpdmVuIGJ5DQoNCiQkDQpcYmVnaW57YXJyYXl9e2NjY30gDQp5XzEgJiA9ICYgIFxoYXR7XGJldGF9XzAgKyBcaGF0e1xiZXRhfV8xIHhfezExfSArIFxoYXR7XGJldGF9XzIgeF97MTJ9ICsgXGNkb3RzICsgXGhhdHtcYmV0YX1fayB4X3sxa30gKyBlXzEgIFxcDQp5XzIgJiA9ICYgIFxoYXR7XGJldGF9XzAgKyBcaGF0e1xiZXRhfV8xIHhfezIxfSArIFxoYXR7XGJldGF9XzIgeF97MjJ9ICsgXGNkb3RzICsgXGhhdHtcYmV0YX1fayB4X3sya30gKyBlXzIgIFxcDQp5XzMgJiA9ICYgIFxoYXR7XGJldGF9XzAgKyBcaGF0e1xiZXRhfV8xIHhfezMxfSArIFxoYXR7XGJldGF9XzIgeF97MzJ9ICsgXGNkb3RzICsgXGhhdHtcYmV0YX1fayB4X3sza30gKyBlXzMgIFxcDQpcdmRvdHMgJiBcdmRvdHMgJiBcdmRvdHMgXFwNCnlfbiAmID0gJiAgXGhhdHtcYmV0YX1fMCArIFxoYXR7XGJldGF9XzEgeF97bjF9ICsgXGhhdHtcYmV0YX1fMiB4X3tuMn0gKyBcY2RvdHMgKyBcaGF0e1xiZXRhfV9rIHhfe25rfSArIGVfbg0KXGVuZHthcnJheX0NCiQkDQoNCndoZXJlICRce2VfMSwgZV8yLCBcY2RvdHMsIGVfbiBcfSQgaXMgdGhlIHNldCBvZiByZXNpZHVhbHMgb2J0YWluZWQgZnJvbSB0aGUgZmluYWwgbW9kZWwuICRce3hfe2kxfSwgeF97aTJ9LCBcY2RvdHMsIHhfe2lrfSBcfSQgaXMgdGhlIGktdGggcmVjb3JkIGZyb20gdGhlIGRhdGEsIGFuZCAkXHsgXGhhdHtcYmV0YX1fMCwgXGhhdHtcYmV0YX1fMSwgIFxjZG90cywgXGhhdHtcYmV0YX1fayBcfSQgYXJlIHRoZSBlc3RpbWF0ZWQgcmVncmVzc2lvbiBjb2VmZmljaWVudHMgYmFzZWQgb24gdGhlIG9yaWdpbmFsIHJhbmRvbSBzYW1wbGUuDQoNClRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHJlc2lkdWFscyBpcyBkZXBpY3RlZCBpbiB0aGUgZm9sbG93aW5nIGhpc3RvZ3JhbS4NCg0KYGBge3J9DQpoaXN0KHNvcnQoZGVsYXkkcmVzaWR1YWxzKSxuPTQwLA0KICAgICB4bGFiPSJSZXNpZHVhbHMiLA0KICAgICBjb2wgPSAibGlnaHRibHVlIiwNCiAgICAgYm9yZGVyPSJuYXZ5IiwNCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gb2YgUmVzaWR1YWxzIikNCmBgYA0KDQpgYGB7cn0NCmRlbGF5LnJlc2lkIDwtIGRlbGF5JHJlc2lkdWFscw0KDQpCPTEwMDANCm51bS5wID0gZGltKG1vZGVsLm1hdHJpeChkZWxheSkpWzJdICAgIyBudW1iZXIgb2YgcGFyYW1ldGVycw0Kc2FtcC5uID0gZGltKG1vZGVsLm1hdHJpeChkZWxheSkpWzFdICAjIHNhbXBsZSBzaXplDQpidHIubXRyeCA9IG1hdHJpeChyZXAoMCw2KkIpLCBuY29sPW51bS5wKSAjIHplcm8gbWF0cml4IHRvIHN0b3JlIGJvb3QgY29lZnMNCmZvciAoaSBpbiAxOkIpew0KICAjIyBCb290c3RyYXAgcmVzcG9uc2UgdmFsdWVzDQogIGJ0LmRlbGF5ID0gZGVsYXkkZml0dGVkLnZhbHVlcyArIA0KICAgICAgICBzYW1wbGUoZGVsYXkucmVzaWQsIHNhbXAubiwgcmVwbGFjZSA9IFRSVUUpICAjIGJvb3RzdHJhcCByZXNpZHVhbHMNCiAgIyByZXBsYWNlIFByaWNlVW5pdEFyZWEgd2l0aCBib290c3RyYXAgbG9nIHByaWNlDQogIGZsaWdodCRidC5kZWxheSA9ICBidC5kZWxheSAgICMgIHNlbmQgdGhlIGJvb3QgcmVzcG9uc2UgdG8gdGhlIGRhdGENCiAgYnRyLm1vZGVsID0gbG0oYnQuZGVsYXkgfiBOdW1iZXJfb2ZfZmxpZ2h0cyArIEJhZ2dhZ2VfbG9hZGluZ190aW1lICsgTGF0ZV9BcnJpdmFsX28gKyBBaXJwb3J0X0Rpc3RhbmNlICsgU3VwcG9ydF9DcmV3X0F2YWlsYWJsZSwgZGF0YSA9IGZsaWdodCkgICAjIGINCiAgYnRyLm10cnhbaSxdPWJ0ci5tb2RlbCRjb2VmZmljaWVudHMNCn0NCmBgYA0KDQpgYGB7cn0NCmJvb3QuaGlzdCA9IGZ1bmN0aW9uKGJ0LmNvZWYubXRyeCwgdmFyLmlkLCB2YXIubm0pew0KICAjIyBidC5jb2VmLm10cnggPSBtYXRyaXggZm9yIHN0b3JpbmcgYm9vdHN0cmFwIGVzdGltYXRlcyBvZiBjb2VmZmljaWVudHMNCiAgIyMgdmFyLmlkID0gdmFyaWFibGUgSUQgKDEsIDIsIC4uLiwgaysxKQ0KICAjIyB2YXIubm0gPSB2YXJpYWJsZSBuYW1lIG9uIHRoZSBoaXN0IHRpdGxlLCBtdXN0IGJlIHRoZSBzdHJpbmcgaW4gdGhlIGRvdWJsZSBxdW90ZXMNCiAgIyMgQm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50cw0KICB4MS4xIDwtIHNlcShtaW4oYnQuY29lZi5tdHJ4Wyx2YXIuaWRdKSwgbWF4KGJ0LmNvZWYubXRyeFssdmFyLmlkXSksIGxlbmd0aD0zMDAgKQ0KICB5MS4xIDwtIGRub3JtKHgxLjEsIG1lYW4oYnQuY29lZi5tdHJ4Wyx2YXIuaWRdKSwgc2QoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdKSkNCiAgIyBoZWlnaHQgb2YgdGhlIGhpc3RvZ3JhbSAtIHVzZSBpdCB0byBtYWtlIGEgbmljZS1sb29raW5nIGhpc3RvZ3JhbS4NCiAgaGlnaGVzdGJhciA9IG1heChoaXN0KGJ0LmNvZWYubXRyeFssdmFyLmlkXSwgcGxvdCA9IEZBTFNFKSRkZW5zaXR5KSANCiAgeWxpbWl0IDwtIG1heChjKHkxLjEsaGlnaGVzdGJhcikpDQogIGhpc3QoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdLCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSB2YXIubm0sIHhsYWI9IiIsIA0KICAgICAgIGNvbCA9ICJhenVyZTEiLHlsaW09YygwLHlsaW1pdCksIGJvcmRlcj0ibGlnaHRzZWFncmVlbiIpDQogIGxpbmVzKHggPSB4MS4xLCB5ID0geTEuMSwgY29sID0gInJlZDMiKSAgICAgICAjIG5vcm1hbCBkZW5zaXR5IGN1cnZlICAgICAgICAgDQogIGxpbmVzKGRlbnNpdHkoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdLCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpICAgICMgbG9lc3MgY3VydmUNCn0gDQpgYGANCg0KYGBge3J9DQpwYXIobWZyb3c9YygyLDMpKSAgIyBoaXN0b2dyYW1zIG9mIGJvb3RzdHJhcCBjb2Vmcw0KYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1idHIubXRyeCwgdmFyLmlkPTEsIHZhci5ubSA9IkludGVyY2VwdCIgKQ0KYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1idHIubXRyeCwgdmFyLmlkPTIsIHZhci5ubSA9Ik51bWJlciBvZiBGbGlnaHRzIiApDQpib290Lmhpc3QoYnQuY29lZi5tdHJ4PWJ0ci5tdHJ4LCB2YXIuaWQ9MywgdmFyLm5tID0iQmFnZ2FnZSBMb2FkaW5nIFRpbWUiICkNCmJvb3QuaGlzdChidC5jb2VmLm10cng9YnRyLm10cngsIHZhci5pZD00LCB2YXIubm0gPSJMYXRlIEFycml2YWwiICkNCmJvb3QuaGlzdChidC5jb2VmLm10cng9YnRyLm10cngsIHZhci5pZD01LCB2YXIubm0gPSJEaXN0YW5jZSB0byBBaXJwb3J0IiApDQpib290Lmhpc3QoYnQuY29lZi5tdHJ4PWJ0ci5tdHJ4LCB2YXIuaWQ9NiwgdmFyLm5tID0iU3VwcG9ydCBDcmV3IEF2YWlsYWJsZSIgKQ0KYGBgDQoNCmBgYHtyfQ0KbnVtLnAgPSBkaW0oY29lZi5tdHJ4KVsyXSAgIyBudW1iZXIgb2YgcGFyYW1ldGVycw0KYnRyLmNpID0gTlVMTA0KYnRyLndkID0gTlVMTA0KZm9yIChpIGluIDE6bnVtLnApew0KICBsY2kuMDI1ID0gcm91bmQocXVhbnRpbGUoYnRyLm10cnhbLCBpXSwgMC4wMjUsIHR5cGUgPSAyKSw4KQ0KICB1Y2kuOTc1ID0gcm91bmQocXVhbnRpbGUoYnRyLm10cnhbLCBpXSwwLjk3NSwgdHlwZSA9IDIgKSw4KQ0KICBidHIud2RbaV0gPSB1Y2kuOTc1IC0gbGNpLjAyNQ0KICBidHIuY2lbaV0gPSBwYXN0ZSgiWyIsIHJvdW5kKGxjaS4wMjUsNCksIiwgIiwgcm91bmQodWNpLjk3NSw0KSwiXSIpDQp9DQojYXMuZGF0YS5mcmFtZShidGMuY2kpDQprYWJsZShhcy5kYXRhLmZyYW1lKGNiaW5kKGZvcm1hdEMoY210cngsNCxmb3JtYXQ9ImYiKSwgYnRyLmNpLjk1PWJ0ci5jaSkpLCANCiAgICAgIGNhcHRpb24gPSAiUmVncmVzc2lvbiBDb2VmZmljaWVudCBNYXRyaXggd2l0aCA5NSUgUmVzaWR1YWwgQm9vdHN0cmFwIENJIikNCmBgYA0KDQojIEFuYWx5c2lzDQoNClRoZSByZXN1bHRzIG9mIHRoZSBzdGFuZGFyZCBhbmQgdGhlIGJvb3RzdHJhcHBlZCBtb2RlbHMgd2VyZSB2ZXJ5IHNpbWlsYXIuIFRoZSBmaXJzdCBtb2RlbCB3YXMgY29tcHV0YXRpb25hbGx5IHRoZSBlYXNpZXN0IHRvIGNyZWF0ZSwgYnV0IHRoZSBib290c3RyYXBwZWQgbW9kZWxzIGhlbHBlZCBrZWVwIHRoZSBhc3N1bXB0aW9ucyBvZiBsaW5lYXIgcmVncmVzc2lvbiB1bmRlciBjb250cm9sLCBwYXJ0aWN1bGFybHkgdGhlIHZpb2xhdGlvbnMgd2Ugb2JzZXJ2ZWQgaW4gcmVzaWR1YWwgYW5hbHlzaXMuIFRoZSBib290c3RyYXAgbW9kZWwgc2hvdWxkIHRodXMgYmUgdXNlZCBmb3IgYnVpbGRpbmcgcHJlZGljdGlvbnMuDQoNClNvbWUgb2YgdGhlIHZhcmlhYmxlcyB0aGF0IHdlcmUgZXhjbHVkZWQgZnJvbSB0aGUgbW9kZWwgd2VyZSByb3V0aW5lIGFpcnBvcnQgYWN0aXZpdGllcy4gVGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGUgdGltZSB0byBjb21wbGV0ZSB0aGVzZSBhcmUgbm90IGNvbnRyaWJ1dGluZyBmYWN0b3JzIHRvIGRlbGF5cy4gU29tZSBvZiB0aGUgZmFjdG9ycyB0aGF0IHdlcmUgaW1wb3J0YW50IHRvIHRoZSBtb2RlbCB3ZXJlIGJhc2VkIGFyb3VuZCBnZW5lcmFsIGFpcnBvcnQgdHJhZmZpYyBhbmQgYnVzaW5lc3MgKHRvdGFsIGZsaWdodHMsIGJhZ2dhZ2UgbG9hZGluZyB0aW1lLCBzdXBwb3J0IGNyZXcgYXZhaWxhYmxlKS4gVGhlc2UgZmFjdG9ycyBzZWVtIHRvIGluZGljYXRlIHRoYXQgaGF2aW5nIG1vcmUgc3RhZmYgYXZhaWxhYmxlIHRvIGhhbmRsZSB0aGUgYW1vdW50IG9mIGZsaWdodHMgbWF5IHJlZHVjZSB0aGUgYW1vdW50IGFuZCBtYWduaXR1ZGUgb2YgZGVsYXlzLiBTb21lIGZhY3RvcnMgYXJlIGFsbW9zdCBpbXBvc3NpYmxlIHRvIGFjY291bnQgZm9yIChhaXJwb3J0IGRpc3RhbmNlLCBsYXRlIGFycml2YWwpIGFuZCB3aWxsIGxpa2VseSBhbHdheXMgYWNjb3VudCBmb3Igc29tZSBhbW91bnQgb2YgZGVsYXlzLg0K