1 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.

2 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.

3 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.

4 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
Estimate Std. Error t value Pr(>|t|) btc.ci.95
(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.

5 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
Estimate Std. Error t value Pr(>|t|) btr.ci.95
(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 ]

6 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