# read in data
data = rbind.data.frame(5.2, 7.8, 9.1, 11.3, 12.5, 13.0, 14.2, 15.1, 15.9, 16.7, 17.2, 17.8, 18.4, 18.9,
19.3, 19.7, 20.2, 20.6, 21.0, 21.5, 21.9, 22.3, 22.7, 23.1, 23.5, 23.9, 24.3, 24.7,
25.1, 25.5, 25.9, 26.3, 26.7, 27.1, 27.5, 27.9, 28.3, 28.7, 29.1, 29.5, 29.9, 30.3,
30.7, 31.1, 31.5, 31.9, 32.3, 32.7, 33.1, 33.5, 33.9, 34.3, 34.7, 35.1, 35.5, 35.9,
36.3, 36.7, 37.1, 37.5, 37.9, 38.3, 38.7, 39.1, 39.5, 39.9, 40.3, 40.7, 41.1, 41.5,
41.9, 42.3, 42.7, 43.1, 43.5)
colnames(data) = "time"
# time is in months
Intro and Setup
The dataset at our disposal for this analyis is made up of 75
recorded failure times (measured in months) for wind turbine gearbox
components. Summary statistics as well as a histogram depiction of our
sample data can be seen below.
sum_stats_table = function(variable){
table = cbind(
round(min(variable),2),
round(quantile(variable, 0.25),2),
round(median(variable),2),
round(mean(variable),2),
round(quantile(variable, 0.75),2),
round(max(variable),2)
)
colnames(table) = c("Min", "Q1", "Med", "Mean", "Q3", "Max")
rownames(table) = NULL
return(table)
}
Summary_Table = sum_stats_table(variable = data$time)
kable(Summary_Table,align = "c",
caption = "<span style='color:##000000;'>
Summary Stats of Survival Times (Months)</span>") %>%
kable_styling(
bootstrap_options = c("striped", "bordered"),
full_width = FALSE,
position = "center")
Summary Stats of Survival Times
(Months)
|
Min
|
Q1
|
Med
|
Mean
|
Q3
|
Max
|
|
5.2
|
21.25
|
28.7
|
28.19
|
36.1
|
43.5
|
ggplot(data = data) +
geom_histogram(mapping = aes(x = time, y = after_stat(density)),
color = "black",
# argument color in geom_histogram is for color of bin lines
fill = "lightblue",
bins = 10,) +
labs(title = "Distribution of Survival Times",
x = "Time (Months)",
y = "Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3)
) # this is the equivalent of box(lwd = 3) in base R

The engineering team at a wind energy company is unsure whether to
label and treat the broader population distribution of fail times as
exponentially or Weibull distributed. The probability density of an
exponential distribution is simply a more simplified version of the
Weibull’s. It is the value of our shape parameter, \(\beta\), that determines which of these
distribution’s we will label as the framework for predictive analysis on
gearbox fail times moving forward.
For the purposes of today’s analysis, we will treat the null
hypothesis that said population is exponentially distributed (AKA \(\beta = 1\)), and the alternative
hypothesis that a Weibull distribution more accurately represents the
broader population of gearbox fail times (AKA \(\beta \neq 1\)).
\[\begin{align}
H_0&: \beta = 1 \quad \text{Takeaway: Exponential} \\
H_a&: \beta \neq 1 \quad \text{Takeaway: Weibull}
\end{align}\]
In order to assess the validity of these opposing hypotheses, we must
first quantify an estimate for our parameter \(\beta\) under the assumption of each
scenario (Weibull distribution vs exponential distribution). In the
following sections, I will use maximum likelihood estimation (MLE) to do
so.
a.) MLE of Weibull
Operating under the assumption that the population of gearbox fail
times is Weibull distributed, we can use MLE to
simultaneously generate estimates for the shape parameter, \(\beta\), and the the scale parameter, \(\lambda\). We’ll denote these estimates as
\(\hat{\beta}\) and \(\hat{\lambda}\) respectively.
Parameter calculations were performed with R’s built-in optim() function. For mathematical reference,
the log-likelihood function for the Weibull distribution as well as the
partial derivatives of that very function with respect to both \(\beta\) and \(\lambda\) are below.
\[\Large \ell(\beta,\lambda|t) =
[n \times \ln(\beta)] -
[n \times \beta \times \ln(\lambda)]
+ [(\beta - 1) \times \sum\ln(t_i)]
- \sum\left(\frac{(t_i)}{\lambda}\right)^\beta \]
\[\Large \frac{\partial f}{\partial \beta}
=
\frac{n}{\beta} -
n \times \ln(\lambda)
+ \sum\ln(t_i) -
\sum\left(\ln\frac{t_i}{\lambda}\right) \times
\left(\frac{t_i}{\lambda}\right)^\beta \]
\[\Large \frac{\partial f}{\partial
\lambda} = \frac{\beta}{\lambda} \times
\sum\left(\frac{t_i}{\lambda}\right)^\beta - n \]
## MLE Weibull Estimation
# code is largely copied from HW 9 assignment, which took formulas and procedure from following:
# Week 11, Section 5.2
# Week 7, Section 5
#### define likelihood function
## *negative* log likelihood function for Weibull distribution
# by negative log likelihood, this function....
log_likelihood = function(params, data) {
beta = params[1] # shape
lambda = params[2] # scale
# Ensure parameters are positive
if (beta <= 0 || lambda <= 0) {
return(1e10) # Return large value for invalid parameters
}
n = length(data)
log_lik = n * log(beta) - n * beta * log(lambda) +
(beta - 1) * sum(log(data)) - sum((data / lambda)^beta)
return(log_lik) # Return log-likelihood! NOT the negative log-likelihood
}
#### define score equations (partial derivatives)
log_likelihood_gradient = function(params, data) {
beta = params[1] # shape parameter
lambda = params[2] # scale parameter
n = length(data)
partial_deriv_beta = n/beta - n * log(lambda) + sum(log(data)) -
sum(log(data/lambda) * (data/lambda)^beta)
partial_deriv_lambda = (beta/lambda)*(sum((data/lambda)^beta) -n)
return(c(partial_deriv_beta,
partial_deriv_lambda)) # Gradient of log-likelihood, NOT the negative scores
}
#### use log likelihood and score equations in optim function
# need to have good initial guesses for beta and lambda for the optim function
beta_guess = (sd(data$time)/mean(data$time))^(-1.086)
lambda_guess = mean(data$time)/gamma(1 + 1/beta_guess)
weib_mle_estimates = optim(
par = c(beta_guess, lambda_guess), # par argument is initial "guesses"
data = data$time,
fn = log_likelihood,
gr = log_likelihood_gradient,
method = "L-BFGS-B",
hessian = TRUE,
# will use the Hessian matrix later on
control = list(maxit = 1000,
fnscale = -1,
trace = FALSE,
abstol = 1e-8)
)
#weib_mle_estimates
weib_mle_beta = weib_mle_estimates$par[1] # shape
weib_mle_lambda = weib_mle_estimates$par[2] # scale
Post-MLE, we have estimates of about 3.371 and 31.418 for \(\beta\) and \(\lambda\) respectively. To further ensure
these estimates seem reasonable, below I overlaid a Weibull distribution
with said parameter values atop our available sample data.
ggplot(data = data) +
geom_histogram(mapping = aes(x = time, y = after_stat(density)),
color = "black",
# argument color in geom_histogram is for color of bin lines
fill = "lightblue",
bins = 10,) +
# use stat_function in ggplot to show density curves of other distributions
stat_function(fun = dweibull,
args = list(shape = weib_mle_beta, scale = weib_mle_lambda),
color = "black",
linewidth = 1.5,
xlim = range(0:50))+
# xlim argument so curve doesn't awkardly cut out at edge points of data
labs(title = "Distribution of Gearbox Survival Times (Weibull)",
x = "Time (Months)",
y = "Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3),
legend.position = c(0.85, 0.85)
)

As we can see in our histogram above, there is certainly a
respectable amount of overlap between the distributions of our sample
data and a theoretical Weibull density curve with parameters of \(\beta \approx 3.371\) and \(\lambda \approx 31.418\). This leads us to
believe that if we are to label the broader population of
gearbox survival times as Weibull distributed, then the \(\beta\) and \(\lambda\) estimates prescribed via MLE are
quality starting population estimators.
Now for comparison’s sake, I will repeat the MLE and visualization
procedure, but this time operating under the assumption that the gearbox
survival times are generally exponentially
distributed.
b.) MLE of Exponential
As alluded to before, the exponential distribution can be
simplistically described as a less complicated “version” of the Weibull
distribution. Instead of employing two active parameters, the
exponential distribution’s only parameter is \(\lambda\), which we will now estimate via
MLE. Log-likelihood functions and partial derivatives are written
below.
\[\Large \ell(\lambda|t) = -[n \times
\ln(\lambda)] - \frac{\sum(t_i)}{\lambda} \]
\[\Large \frac{\partial f}{\partial
\lambda} = \frac{n}{\lambda} +
\frac{\sum(t_i)}{\lambda^2} \]
## Exponential MLE Distribution
# once again code largely brought over from HW 9 assignment
# exponential log likelihood follows same pattern as Weibull log likelihood but a MUCH simpler distribution
exp_log_likelihood = function(lambda, data) {
if (lambda <= 0) return (1e10)
n = length(data)
log_lik = -n * log(lambda) - sum(data)/lambda
return(log_lik)
}
### now define partial derivative w/ respect to lambda (the score function or gradient)
# performed via quick hand calculation
exp_gradient = function(lambda, data) {
if (lambda <= 0) return (NA)
n = length(data)
partial_deriv_lambda = (n/lambda) + (sum(data)/(lambda^2))
return(partial_deriv_lambda)
}
exp_mle_estimates = optim(
par = 1/mean(data$time),
# the initial guess can simply be 1/(mean of the data) since we are performing this analysis under the theoretical that it is an EXPONENTIAL distribution. The mean of an exponential distribution is 1 divided by the the rate parameter lambda
data = data$time,
fn = exp_log_likelihood,
gr = exp_gradient,
method = "L-BFGS-B",
hessian = TRUE,
# will use the Hessian matrix later on
control = list(maxit = 1000,
fnscale = -1,
trace = FALSE,
abstol = 1e-8)
)
#exp_mle_estimates$par
exp_mle_lambda = exp_mle_estimates$par
Per MLE calculations, we can assert that the \(\lambda\) parameter of the distribution of
gearbox survival times, if said distribution was truly exponential, is
estimated to be roughly 28.377. An exponential
distribution with \(\lambda =
28.377\) is overlaid atop the sample data and available
below.
ggplot(data = data) +
geom_histogram(mapping = aes(x = time, y = after_stat(density)),
color = "black",
# argument color in geom_histogram is for color of bin lines
fill = "lightblue",
bins = 10,) +
# use stat_function in ggplot to show density curves of other distributions
stat_function(fun = dexp,
args = list(rate = 1/exp_mle_lambda),
color = "red",
linewidth = 1.5,
xlim = range(0:50)
)+
# xlim argument so curve doesn't awkardly cut out at edge points of data
labs(title = "Distribution of Survival Times (Exp)",
x = "Time (Months)",
y = "Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3),
legend.position = c(0.85, 0.85)
)

Comparing this histogram to the one from part a, we see a drastic
decline in distribution resemblance between the sample data and the
theoretical density curve, when working under the assumption that the
population of gearbox survival times is exponentially distributed. We
will keep this in mind moving forward, as we run hypothesis tests to
quantify the differences between the two distribution assumptions.
c.) Likelihood Ratio Test
To further investigate the difference in each distribution’s fit with
regards to our population of interest (gearbox survival times), we will
perform a likelihood ratio test (LRT). The LRT takes into account the
log-likelihood function evaluated with parameter values estimated from a
simpler model (the exponential in this case) and the log-likelihood
function evaluated with parameter values estimated from a more
complicated model (the Weibull in this scenario). The null hypothesis of
such a test is that, per our sample data, there is no
significant difference between the two model fits.
# weib_mle_beta and weib_mle_lambda are UNRESTRICTED MLE VALUES, but now we must find
# null hypothesis is that beta = 1
# if null hypothesis is true, then distribution is really just exponential
## the likelihood ratio test is just 2 *
# [log likelihood evaluated in unrestricted way] -
# [log likelihood evaluated in restricted or simple way]
# need to evaluate each distribution's likelihood function at the previously estimated parameters of beta and/or lambda
log_evaluation_weib = log_likelihood(params = c(weib_mle_beta, weib_mle_lambda),
data = data)
log_evaluation_exp = exp_log_likelihood(lambda = exp_mle_lambda,
data = data)
# test stat for likelihood ratio test is uppercase Lambda
Lambda = 2 * abs(log_evaluation_weib - log_evaluation_exp)
p_value_likelihoodratio = 1 - pchisq(Lambda, df = 1)
# test stat distribution for likelihood ratio test is chi-square distributed
# df = number of parameters we are estimating in function
Our LRT returned an extremely high test value (\(\Lambda\)) of about 1145.444. Considering
\(\Lambda\) follows a chi-square
distribution, this test stat coincides with a p value of approximately
zero. With these findings, we must reject the null
hypothesis as there is very convincing evidence that the Weibull
distribution more accurately represents the fit of our population of
interest than the exponential distribution does. After examining the
histograms in parts a and b, this finding is not surprising.
d.) Bootstrap Likelihood Ratio Test
Lastly, I repeated this same type of procedure, likelihood ratio
testing, and applied it to a bootstrapped scenario. Under the guise of
the bootstrap LRT, we take repeated samples of a theoretical
distribution, in this case an exponential distribution with \(\lambda \approx\) 28.377. Then, for each
sample, a test statistic of \(\Lambda\)
is found using that particular bootstrap sample’s log-likelihood
evaluation along with the log-likelihood evaluation of our original and
more complex/unrestricted model (the Weibull in this scenario).
### Bootstrap Likelihood Ratio Test (BLRT) for short
# reference code section 4.3 from Week 12 notes, need to change formulas since we are applying to exponential distribution, not normal
bootstrap_lrt_test = function(data, b, rate_null, obs_lr_stat){
# obs_lr_stat will = Lambda = likelihood ratio test stat taken from observed data calculations
n = length(data)
boot_lr_stat = numeric(b)
# Log-likelihood functions are found in earlier code chunks and will be called to within the optim functions of the for loop process
# START FOR LOOP
for (i in 1:b){
# Generating artificial data meant to replicate the characteristics of our NULL hypothesis
# In this case, our null hypothesis is that the data fits an exponential distribution with rate parameter lambda
boot_exp_sample = rexp(n = n, rate = rate_null)
####### Weibull likelihood per boot sample
boot_beta_guess = (sd(boot_exp_sample)/mean(boot_exp_sample))^(-1.086)
boot_lambda_guess = mean(boot_exp_sample)/gamma(1 + 1/boot_beta_guess)
boot_log_weib = optim(
par = c(boot_beta_guess, boot_lambda_guess), # par argument is initial "guesses"
data = boot_exp_sample,
fn = log_likelihood,
gr = log_likelihood_gradient,
method = "L-BFGS-B",
lower = c(1e-8, 1e-8), ## this limiting lower argument is NECESSARY, before I added it I was getting an error line for "non-finite value supplied by optim"
hessian = TRUE,
control = list(maxit = 1000,
fnscale = -1,
trace = FALSE,
abstol = 1e-8)
)
boot_log_weib = boot_log_weib$value # store log likelihood evaluation
####### End Weibull likelihood per boot sample
####### Exponential likelihood per boot sample
boot_log_exp = optim(
par = 1/mean(boot_exp_sample),
data = boot_exp_sample,
fn = exp_log_likelihood,
gr = exp_gradient,
method = "L-BFGS-B",
hessian = TRUE,
control = list(maxit = 1000,
fnscale = -1,
trace = FALSE,
abstol = 1e-8)
)
boot_log_exp = boot_log_exp$value # store log likelihood evaluation
####### End Exponential likelihood per boot sample
# the likelihood ratio for EACH instance of the bootstrap is 2 times the difference between the likelihood ratio evaluated under unrestricted (Weibull) circumstances and evaluated under simpler (exponential) circumstances
boot_lr_stat[i] = 2 * abs(boot_log_weib - boot_log_exp)
} # END FOR LOOP
# calculate and output final p value
p = (sum(boot_lr_stat >= obs_lr_stat) + 1)/ (b + 1)
### FINAL p value of bootstrap exercise is equal to..
# number of bootstrap sample LR test stats greater than or equal to the original LR test stat found in section c
return(list(p_value_bootstrap = p,
bootstrap_lr_stats = boot_lr_stat))
} #### END BOOTSTRAP FUNCTION
## now running the function
set.seed(123)
BLRT_test = bootstrap_lrt_test(data = data$time,
b = 1000,
rate_null = exp_mle_lambda,
obs_lr_stat = Lambda)
# BLRT_test$p_value_bootstrap = 0.000999001
Using a repeated sample size of 1,000, there once again appears to be
significant evidence that an assumption of exponential distribution
would result in a much less accurate resemblance of our population of
gearbox survival times than an assumption of Weibull distribution would.
Our bootstrap LRT yielded a p-value of only 0.001.
e.) Summary and Conclusions
To summarize, all of the analysis up to this point supports the
notion of moving forward under the assumption that the broader
population of gearbox survival times is Weibull
distributed with a shape parameter (\(\beta\)) of about 3.371 and scale parameter
(\(\lambda\)) of roughly 31.418. Both
the standard and bootstrap iterations of the LRT show a significant
decline in distribution resemblance when assuming an exponential
distribution. Furthermore, we could see in preliminary visual analysis
via the histograms in sections a and b, that a Weibull distribution
density curve with said paremeters was much more aligned with
our sample distribution than that of the exponential curve with \(\beta\) value of approximately 28.377.
LS0tCnRpdGxlOiAiQm9vdHN0cmFwIExpa2VsaWhvb2QgUmF0aW8gVGVzdCIKYXV0aG9yOiAiQ2hyaXMgQmFobSIKZGF0ZTogIkFwcmlsIDE4LCAyMDI2IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfd2lkdGg6IDYKICAgIGZpZ19oZWlnaHQ6IDQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKYGBge2NzcywgZWNobyA9IEZBTFNFfQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IAojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4KCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgYSBwYWNrYWdlIHdhcyBpbnN0YWxsZWQgaW4KICAgbGlicmFyeShrbml0cikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91ciBtYWNoaW5lLiBJZiBub3QsIGluc3RhbGwgaXQgYW5kCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIHtsaWJyYXJ5KHRpZHl2c2Vyc2UpfSAKCmlmICghcmVxdWlyZShHR2FsbHkpKSB7bGlicmFyeShHR2FsbHkpfSAKCmlmICghcmVxdWlyZShrYWJsZUV4dHJhKSkge2xpYnJhcnkoa2FibGVFeHRyYSl9IAoKaWYgKCFyZXF1aXJlKGdncGxvdDIpKSB7bGlicmFyeShnZ3Bsb3QyKX0gCgppZiAoIXJlcXVpcmUoY2FyKSkge2xpYnJhcnkoY2FyKX0gCgppZiAoIXJlcXVpcmUoZHBseXIpKSB7bGlicmFyeShkcGx5cil9IAoKaWYgKCFyZXF1aXJlKHBhbmRlcikpIHtsaWJyYXJ5KHBhbmRlcil9IAoKaWYgKCFyZXF1aXJlKGZvcmVjYXN0KSkge2xpYnJhcnkoZm9yZWNhc3QpfSAKCmlmICghcmVxdWlyZShsdWJyaWRhdGUpKSB7bGlicmFyeShsdWJyaWRhdGUpfSAKCmlmICghcmVxdWlyZSgic2NhbGVzIikpIHsKaW5zdGFsbC5wYWNrYWdlcygic2NhbGVzIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCmxpYnJhcnkoInNjYWxlcyIpIAp9Cgprbml0cjo6b3B0c19jaHVuayRzZXQoCgllY2hvID0gVFJVRSwKCW1lc3NhZ2UgPSBGQUxTRSwKCXdhcm5pbmcgPSBGQUxTRSwKCWNvbW1lbnQgPSBOQSwKCXJlc3VsdHMgPSBUUlVFLAoJZmlnLmFsaWduID0gImNlbnRlciIKKQpgYGAKCmBgYHtyfQojIHJlYWQgaW4gZGF0YQpkYXRhID0gcmJpbmQuZGF0YS5mcmFtZSg1LjIsICA3LjgsICA5LjEsIDExLjMsIDEyLjUsIDEzLjAsIDE0LjIsIDE1LjEsIDE1LjksIDE2LjcsIDE3LjIsIDE3LjgsIDE4LjQsIDE4LjksIAogIDE5LjMsIDE5LjcsIDIwLjIsIDIwLjYsIDIxLjAsIDIxLjUsIDIxLjksIDIyLjMsIDIyLjcsIDIzLjEsIDIzLjUsIDIzLjksIDI0LjMsIDI0LjcsIAogIDI1LjEsIDI1LjUsIDI1LjksIDI2LjMsIDI2LjcsIDI3LjEsIDI3LjUsIDI3LjksIDI4LjMsIDI4LjcsIDI5LjEsIDI5LjUsIDI5LjksIDMwLjMsIAogIDMwLjcsIDMxLjEsIDMxLjUsIDMxLjksIDMyLjMsIDMyLjcsIDMzLjEsIDMzLjUsIDMzLjksIDM0LjMsIDM0LjcsIDM1LjEsIDM1LjUsIDM1LjksIAogIDM2LjMsIDM2LjcsIDM3LjEsIDM3LjUsIDM3LjksIDM4LjMsIDM4LjcsIDM5LjEsIDM5LjUsIDM5LjksIDQwLjMsIDQwLjcsIDQxLjEsIDQxLjUsCiAgNDEuOSwgNDIuMywgNDIuNywgNDMuMSwgNDMuNSkKY29sbmFtZXMoZGF0YSkgPSAidGltZSIKICAjIHRpbWUgaXMgaW4gbW9udGhzCmBgYAoKIyBJbnRybyBhbmQgU2V0dXAKClRoZSBkYXRhc2V0IGF0IG91ciBkaXNwb3NhbCBmb3IgdGhpcyBhbmFseWlzIGlzIG1hZGUgdXAgb2YgYHIgbnJvdyhkYXRhKWAgcmVjb3JkZWQgZmFpbHVyZSB0aW1lcyAobWVhc3VyZWQgaW4gbW9udGhzKSBmb3Igd2luZCB0dXJiaW5lIGdlYXJib3ggY29tcG9uZW50cy4gU3VtbWFyeSBzdGF0aXN0aWNzIGFzIHdlbGwgYXMgYSBoaXN0b2dyYW0gZGVwaWN0aW9uIG9mIG91ciBzYW1wbGUgZGF0YSBjYW4gYmUgc2VlbiBiZWxvdy4KCmBgYHtyfQpzdW1fc3RhdHNfdGFibGUgPSBmdW5jdGlvbih2YXJpYWJsZSl7CiAgdGFibGUgPSBjYmluZCgKICAgIHJvdW5kKG1pbih2YXJpYWJsZSksMiksCiAgICByb3VuZChxdWFudGlsZSh2YXJpYWJsZSwgMC4yNSksMiksCiAgICByb3VuZChtZWRpYW4odmFyaWFibGUpLDIpLAogICAgcm91bmQobWVhbih2YXJpYWJsZSksMiksCiAgICByb3VuZChxdWFudGlsZSh2YXJpYWJsZSwgMC43NSksMiksCiAgICByb3VuZChtYXgodmFyaWFibGUpLDIpCiAgKQogIGNvbG5hbWVzKHRhYmxlKSA9IGMoIk1pbiIsICJRMSIsICJNZWQiLCAiTWVhbiIsICJRMyIsICJNYXgiKQogIHJvd25hbWVzKHRhYmxlKSA9IE5VTEwKICByZXR1cm4odGFibGUpCn0KClN1bW1hcnlfVGFibGUgPSBzdW1fc3RhdHNfdGFibGUodmFyaWFibGUgPSBkYXRhJHRpbWUpCmthYmxlKFN1bW1hcnlfVGFibGUsYWxpZ24gPSAiYyIsCiAgICAgIGNhcHRpb24gPSAiPHNwYW4gc3R5bGU9J2NvbG9yOiMjMDAwMDAwOyc+CiAgICAgIFN1bW1hcnkgU3RhdHMgb2YgU3Vydml2YWwgVGltZXMgKE1vbnRocyk8L3NwYW4+IikgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIpLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAiY2VudGVyIikKCmdncGxvdChkYXRhID0gZGF0YSkgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHRpbWUsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICMgYXJndW1lbnQgY29sb3IgaW4gZ2VvbV9oaXN0b2dyYW0gaXMgZm9yIGNvbG9yIG9mIGJpbiBsaW5lcwogICAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRibHVlIiwKICAgICAgICAgICAgICAgICBiaW5zID0gMTAsKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU3Vydml2YWwgVGltZXMiLAogICAgICAgeCA9ICJUaW1lIChNb250aHMpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIpICsgCiAgdGhlbWUoCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIGxpbmV3aWR0aCA9IDMpCiAgKSAjIHRoaXMgaXMgdGhlIGVxdWl2YWxlbnQgb2YgYm94KGx3ZCA9IDMpIGluIGJhc2UgUgpgYGAKCgpUaGUgZW5naW5lZXJpbmcgdGVhbSBhdCBhIHdpbmQgZW5lcmd5IGNvbXBhbnkgaXMgdW5zdXJlIHdoZXRoZXIgdG8gbGFiZWwgYW5kIHRyZWF0IHRoZSBicm9hZGVyIHBvcHVsYXRpb24gZGlzdHJpYnV0aW9uIG9mIGZhaWwgdGltZXMgYXMgZXhwb25lbnRpYWxseSBvciBXZWlidWxsIGRpc3RyaWJ1dGVkLiBUaGUgcHJvYmFiaWxpdHkgZGVuc2l0eSBvZiBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gaXMgc2ltcGx5IGEgbW9yZSBzaW1wbGlmaWVkIHZlcnNpb24gb2YgdGhlIFdlaWJ1bGwncy4gSXQgaXMgdGhlIHZhbHVlIG9mIG91ciBzaGFwZSBwYXJhbWV0ZXIsICRcYmV0YSQsIHRoYXQgZGV0ZXJtaW5lcyB3aGljaCBvZiB0aGVzZSBkaXN0cmlidXRpb24ncyB3ZSB3aWxsIGxhYmVsIGFzIHRoZSBmcmFtZXdvcmsgZm9yIHByZWRpY3RpdmUgYW5hbHlzaXMgb24gZ2VhcmJveCBmYWlsIHRpbWVzIG1vdmluZyBmb3J3YXJkLgoKRm9yIHRoZSBwdXJwb3NlcyBvZiB0b2RheSdzIGFuYWx5c2lzLCB3ZSB3aWxsIHRyZWF0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCBzYWlkIHBvcHVsYXRpb24gaXMgZXhwb25lbnRpYWxseSBkaXN0cmlidXRlZCAoQUtBICRcYmV0YSA9IDEkKSwgYW5kIHRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIHRoYXQgYSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBtb3JlIGFjY3VyYXRlbHkgcmVwcmVzZW50cyB0aGUgYnJvYWRlciBwb3B1bGF0aW9uIG9mIGdlYXJib3ggZmFpbCB0aW1lcyAoQUtBICRcYmV0YSBcbmVxIDEkKS4KCgpcYmVnaW57YWxpZ259CkhfMCY6IFxiZXRhID0gMSBccXVhZCBcdGV4dHtUYWtlYXdheTogRXhwb25lbnRpYWx9IFxcCkhfYSY6IFxiZXRhIFxuZXEgMSBccXVhZCBcdGV4dHtUYWtlYXdheTogV2VpYnVsbH0KXGVuZHthbGlnbn0KCkluIG9yZGVyIHRvIGFzc2VzcyB0aGUgdmFsaWRpdHkgb2YgdGhlc2Ugb3Bwb3NpbmcgaHlwb3RoZXNlcywgd2UgbXVzdCBmaXJzdCBxdWFudGlmeSBhbiBlc3RpbWF0ZSBmb3Igb3VyIHBhcmFtZXRlciAkXGJldGEkIHVuZGVyIHRoZSBhc3N1bXB0aW9uIG9mIGVhY2ggc2NlbmFyaW8gKFdlaWJ1bGwgZGlzdHJpYnV0aW9uIHZzIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbikuIEluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMsIEkgd2lsbCB1c2UgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRpb24gKE1MRSkgdG8gZG8gc28uCgoKIyBhLikgTUxFIG9mIFdlaWJ1bGwKT3BlcmF0aW5nIHVuZGVyIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIHBvcHVsYXRpb24gb2YgZ2VhcmJveCBmYWlsIHRpbWVzIGlzICoqV2VpYnVsbCBkaXN0cmlidXRlZCoqLCB3ZSBjYW4gdXNlIE1MRSB0byBzaW11bHRhbmVvdXNseSBnZW5lcmF0ZSBlc3RpbWF0ZXMgZm9yIHRoZSBzaGFwZSBwYXJhbWV0ZXIsICRcYmV0YSQsIGFuZCB0aGUgdGhlIHNjYWxlIHBhcmFtZXRlciwgJFxsYW1iZGEkLiBXZSdsbCBkZW5vdGUgdGhlc2UgZXN0aW1hdGVzIGFzICRcaGF0e1xiZXRhfSQgYW5kICRcaGF0e1xsYW1iZGF9JCByZXNwZWN0aXZlbHkuCgpQYXJhbWV0ZXIgY2FsY3VsYXRpb25zIHdlcmUgcGVyZm9ybWVkIHdpdGggUidzIGJ1aWx0LWluIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+b3B0aW0oKTwvc3Bhbj4gZnVuY3Rpb24uIEZvciBtYXRoZW1hdGljYWwgcmVmZXJlbmNlLCB0aGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24gZm9yIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBhcyB3ZWxsIGFzIHRoZSBwYXJ0aWFsIGRlcml2YXRpdmVzIG9mIHRoYXQgdmVyeSBmdW5jdGlvbiB3aXRoIHJlc3BlY3QgdG8gYm90aCAkXGJldGEkIGFuZCAkXGxhbWJkYSQgYXJlIGJlbG93LgoKJCRcTGFyZ2UgXGVsbChcYmV0YSxcbGFtYmRhfHQpID0KW24gXHRpbWVzIFxsbihcYmV0YSldIC0gCltuIFx0aW1lcyBcYmV0YSBcdGltZXMgXGxuKFxsYW1iZGEpXQorIFsoXGJldGEgLSAxKSBcdGltZXMgXHN1bVxsbih0X2kpXQotIFxzdW1cbGVmdChcZnJhY3sodF9pKX17XGxhbWJkYX1ccmlnaHQpXlxiZXRhICQkCgo8YnI+CgokJFxMYXJnZSBcZnJhY3tccGFydGlhbCBmfXtccGFydGlhbCBcYmV0YX0gPQpcZnJhY3tufXtcYmV0YX0gLQpuIFx0aW1lcyBcbG4oXGxhbWJkYSkKKyBcc3VtXGxuKHRfaSkgLQpcc3VtXGxlZnQoXGxuXGZyYWN7dF9pfXtcbGFtYmRhfVxyaWdodCkgXHRpbWVzIFxsZWZ0KFxmcmFje3RfaX17XGxhbWJkYX1ccmlnaHQpXlxiZXRhICAgICQkCgo8YnI+CgokJFxMYXJnZSBcZnJhY3tccGFydGlhbCBmfXtccGFydGlhbCBcbGFtYmRhfSA9ICBcZnJhY3tcYmV0YX17XGxhbWJkYX0gXHRpbWVzIFxzdW1cbGVmdChcZnJhY3t0X2l9e1xsYW1iZGF9XHJpZ2h0KV5cYmV0YSAtIG4gICAgJCQKPGJyPgoKYGBge3J9CiMjIE1MRSBXZWlidWxsIEVzdGltYXRpb24KICAjIGNvZGUgaXMgbGFyZ2VseSBjb3BpZWQgZnJvbSBIVyA5IGFzc2lnbm1lbnQsIHdoaWNoIHRvb2sgZm9ybXVsYXMgYW5kIHByb2NlZHVyZSBmcm9tIGZvbGxvd2luZzoKICAgICMgV2VlayAxMSwgU2VjdGlvbiA1LjIgCiAgICAjIFdlZWsgNywgU2VjdGlvbiA1CgojIyMjIGRlZmluZSBsaWtlbGlob29kIGZ1bmN0aW9uCiMjICpuZWdhdGl2ZSogbG9nIGxpa2VsaWhvb2QgZnVuY3Rpb24gZm9yIFdlaWJ1bGwgZGlzdHJpYnV0aW9uCiAgIyBieSBuZWdhdGl2ZSBsb2cgbGlrZWxpaG9vZCwgdGhpcyBmdW5jdGlvbi4uLi4KbG9nX2xpa2VsaWhvb2QgPSBmdW5jdGlvbihwYXJhbXMsIGRhdGEpIHsKICBiZXRhID0gcGFyYW1zWzFdICAjIHNoYXBlCiAgbGFtYmRhID0gcGFyYW1zWzJdICAjIHNjYWxlIAogIAogICMgRW5zdXJlIHBhcmFtZXRlcnMgYXJlIHBvc2l0aXZlCiAgaWYgKGJldGEgPD0gMCB8fCBsYW1iZGEgPD0gMCkgewogICAgcmV0dXJuKDFlMTApICAjIFJldHVybiBsYXJnZSB2YWx1ZSBmb3IgaW52YWxpZCBwYXJhbWV0ZXJzCiAgfQogIAogIG4gPSBsZW5ndGgoZGF0YSkKICBsb2dfbGlrID0gbiAqIGxvZyhiZXRhKSAtIG4gKiBiZXRhICogbG9nKGxhbWJkYSkgKyAKICAgIChiZXRhIC0gMSkgKiBzdW0obG9nKGRhdGEpKSAtIHN1bSgoZGF0YSAvIGxhbWJkYSleYmV0YSkKICAKICByZXR1cm4obG9nX2xpaykgICMgUmV0dXJuIGxvZy1saWtlbGlob29kISBOT1QgdGhlIG5lZ2F0aXZlIGxvZy1saWtlbGlob29kCn0KCiMjIyMgZGVmaW5lIHNjb3JlIGVxdWF0aW9ucyAocGFydGlhbCBkZXJpdmF0aXZlcykKbG9nX2xpa2VsaWhvb2RfZ3JhZGllbnQgPSBmdW5jdGlvbihwYXJhbXMsIGRhdGEpIHsKICBiZXRhID0gcGFyYW1zWzFdICAgICAgICMgc2hhcGUgcGFyYW1ldGVyCiAgbGFtYmRhID0gcGFyYW1zWzJdICAjIHNjYWxlIHBhcmFtZXRlcgogIAogIG4gPSBsZW5ndGgoZGF0YSkKICAKICBwYXJ0aWFsX2Rlcml2X2JldGEgPSBuL2JldGEgLSBuICogbG9nKGxhbWJkYSkgKyBzdW0obG9nKGRhdGEpKSAtIAogICAgICAgIHN1bShsb2coZGF0YS9sYW1iZGEpICogKGRhdGEvbGFtYmRhKV5iZXRhKQogIAogIHBhcnRpYWxfZGVyaXZfbGFtYmRhID0gIChiZXRhL2xhbWJkYSkqKHN1bSgoZGF0YS9sYW1iZGEpXmJldGEpIC1uKQogIAogIHJldHVybihjKHBhcnRpYWxfZGVyaXZfYmV0YSwKICAgICAgICAgICBwYXJ0aWFsX2Rlcml2X2xhbWJkYSkpICAjIEdyYWRpZW50IG9mIGxvZy1saWtlbGlob29kLCBOT1QgdGhlIG5lZ2F0aXZlIHNjb3Jlcwp9CgojIyMjIHVzZSBsb2cgbGlrZWxpaG9vZCBhbmQgc2NvcmUgZXF1YXRpb25zIGluIG9wdGltIGZ1bmN0aW9uCgojIG5lZWQgdG8gaGF2ZSBnb29kIGluaXRpYWwgZ3Vlc3NlcyBmb3IgYmV0YSBhbmQgbGFtYmRhIGZvciB0aGUgb3B0aW0gZnVuY3Rpb24KYmV0YV9ndWVzcyA9IChzZChkYXRhJHRpbWUpL21lYW4oZGF0YSR0aW1lKSleKC0xLjA4NikKCmxhbWJkYV9ndWVzcyA9IG1lYW4oZGF0YSR0aW1lKS9nYW1tYSgxICsgMS9iZXRhX2d1ZXNzKQoKCndlaWJfbWxlX2VzdGltYXRlcyA9IG9wdGltKAogIHBhciA9IGMoYmV0YV9ndWVzcywgbGFtYmRhX2d1ZXNzKSwgIyBwYXIgYXJndW1lbnQgaXMgaW5pdGlhbCAiZ3Vlc3NlcyIKICBkYXRhID0gZGF0YSR0aW1lLAogIGZuID0gbG9nX2xpa2VsaWhvb2QsCiAgZ3IgPSBsb2dfbGlrZWxpaG9vZF9ncmFkaWVudCwKICBtZXRob2QgPSAiTC1CRkdTLUIiLAogIGhlc3NpYW4gPSBUUlVFLAogICAgIyB3aWxsIHVzZSB0aGUgSGVzc2lhbiBtYXRyaXggbGF0ZXIgb24KICBjb250cm9sID0gbGlzdChtYXhpdCA9IDEwMDAsIAogICAgICAgICAgICAgICAgIGZuc2NhbGUgID0gLTEsCiAgICAgICAgICAgICAgICAgdHJhY2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQopCiN3ZWliX21sZV9lc3RpbWF0ZXMKICAKd2VpYl9tbGVfYmV0YSA9IHdlaWJfbWxlX2VzdGltYXRlcyRwYXJbMV0gIyBzaGFwZQp3ZWliX21sZV9sYW1iZGEgPSB3ZWliX21sZV9lc3RpbWF0ZXMkcGFyWzJdICMgc2NhbGUKYGBgCgpQb3N0LU1MRSwgd2UgaGF2ZSBlc3RpbWF0ZXMgb2YgYWJvdXQgYHIgcm91bmQod2VpYl9tbGVfYmV0YSwzKWAgYW5kIGByIHJvdW5kKHdlaWJfbWxlX2xhbWJkYSwzKWAgZm9yICRcYmV0YSQgYW5kICRcbGFtYmRhJCByZXNwZWN0aXZlbHkuIFRvIGZ1cnRoZXIgZW5zdXJlIHRoZXNlIGVzdGltYXRlcyBzZWVtIHJlYXNvbmFibGUsIGJlbG93IEkgb3ZlcmxhaWQgYSBXZWlidWxsIGRpc3RyaWJ1dGlvbiB3aXRoIHNhaWQgcGFyYW1ldGVyIHZhbHVlcyBhdG9wIG91ciBhdmFpbGFibGUgc2FtcGxlIGRhdGEuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBkYXRhKSArCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4ID0gdGltZSwgeSA9IGFmdGVyX3N0YXQoZGVuc2l0eSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgICAgICAgIyBhcmd1bWVudCBjb2xvciBpbiBnZW9tX2hpc3RvZ3JhbSBpcyBmb3IgY29sb3Igb2YgYmluIGxpbmVzCiAgICAgICAgICAgICAgICAgZmlsbCA9ICJsaWdodGJsdWUiLAogICAgICAgICAgICAgICAgIGJpbnMgPSAxMCwpICsKICAjIHVzZSBzdGF0X2Z1bmN0aW9uIGluIGdncGxvdCB0byBzaG93IGRlbnNpdHkgY3VydmVzIG9mIG90aGVyIGRpc3RyaWJ1dGlvbnMKICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZHdlaWJ1bGwsIAogICAgICAgICAgICAgICAgYXJncyA9IGxpc3Qoc2hhcGUgPSB3ZWliX21sZV9iZXRhLCBzY2FsZSA9IHdlaWJfbWxlX2xhbWJkYSksCiAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLjUsCiAgICAgICAgICAgICAgICB4bGltID0gcmFuZ2UoMDo1MCkpKwogICAgICAgICAgICAjIHhsaW0gYXJndW1lbnQgc28gY3VydmUgZG9lc24ndCBhd2thcmRseSBjdXQgb3V0IGF0IGVkZ2UgcG9pbnRzIG9mIGRhdGEKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBHZWFyYm94IFN1cnZpdmFsIFRpbWVzIChXZWlidWxsKSIsCiAgICAgICB4ID0gIlRpbWUgKE1vbnRocykiLAogICAgICAgeSA9ICJEZW5zaXR5IikgKyAKICB0aGVtZSgKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgbGluZXdpZHRoID0gMyksCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuODUsIDAuODUpCiAgKQpgYGAKCkFzIHdlIGNhbiBzZWUgaW4gb3VyIGhpc3RvZ3JhbSBhYm92ZSwgdGhlcmUgaXMgY2VydGFpbmx5IGEgcmVzcGVjdGFibGUgYW1vdW50IG9mIG92ZXJsYXAgYmV0d2VlbiB0aGUgZGlzdHJpYnV0aW9ucyBvZiBvdXIgc2FtcGxlIGRhdGEgYW5kIGEgdGhlb3JldGljYWwgV2VpYnVsbCBkZW5zaXR5IGN1cnZlIHdpdGggcGFyYW1ldGVycyBvZiAkXGJldGEgXGFwcHJveCBgciByb3VuZCh3ZWliX21sZV9iZXRhLDMpYCQgYW5kICRcbGFtYmRhIFxhcHByb3ggYHIgcm91bmQod2VpYl9tbGVfbGFtYmRhLDMpYCQuIFRoaXMgbGVhZHMgdXMgdG8gYmVsaWV2ZSB0aGF0ICppZiogd2UgYXJlIHRvIGxhYmVsIHRoZSBicm9hZGVyIHBvcHVsYXRpb24gb2YgZ2VhcmJveCBzdXJ2aXZhbCB0aW1lcyBhcyBXZWlidWxsIGRpc3RyaWJ1dGVkLCB0aGVuIHRoZSAkXGJldGEkIGFuZCAkXGxhbWJkYSQgZXN0aW1hdGVzIHByZXNjcmliZWQgdmlhIE1MRSBhcmUgcXVhbGl0eSBzdGFydGluZyBwb3B1bGF0aW9uIGVzdGltYXRvcnMuCgpOb3cgZm9yIGNvbXBhcmlzb24ncyBzYWtlLCBJIHdpbGwgcmVwZWF0IHRoZSBNTEUgYW5kIHZpc3VhbGl6YXRpb24gcHJvY2VkdXJlLCBidXQgdGhpcyB0aW1lIG9wZXJhdGluZyB1bmRlciB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSBnZWFyYm94IHN1cnZpdmFsIHRpbWVzIGFyZSBnZW5lcmFsbHkgKipleHBvbmVudGlhbGx5KiogZGlzdHJpYnV0ZWQuCgojIGIuKSBNTEUgb2YgRXhwb25lbnRpYWwKQXMgYWxsdWRlZCB0byBiZWZvcmUsIHRoZSBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gY2FuIGJlIHNpbXBsaXN0aWNhbGx5IGRlc2NyaWJlZCBhcyBhIGxlc3MgY29tcGxpY2F0ZWQgInZlcnNpb24iIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbi4gSW5zdGVhZCBvZiBlbXBsb3lpbmcgdHdvIGFjdGl2ZSBwYXJhbWV0ZXJzLCB0aGUgZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uJ3Mgb25seSBwYXJhbWV0ZXIgaXMgJFxsYW1iZGEkLCB3aGljaCB3ZSB3aWxsIG5vdyBlc3RpbWF0ZSB2aWEgTUxFLiBMb2ctbGlrZWxpaG9vZCBmdW5jdGlvbnMgYW5kIHBhcnRpYWwgZGVyaXZhdGl2ZXMgYXJlIHdyaXR0ZW4gYmVsb3cuCgokJFxMYXJnZSBcZWxsKFxsYW1iZGF8dCkgPSAtW24gXHRpbWVzIFxsbihcbGFtYmRhKV0gLSBcZnJhY3tcc3VtKHRfaSl9e1xsYW1iZGF9ICAkJAoKPGJyPgoKJCRcTGFyZ2UgXGZyYWN7XHBhcnRpYWwgZn17XHBhcnRpYWwgXGxhbWJkYX0gPSBcZnJhY3tufXtcbGFtYmRhfSArIFxmcmFje1xzdW0odF9pKX17XGxhbWJkYV4yfSAgICQkCgo8YnI+CmBgYHtyfQojIyBFeHBvbmVudGlhbCBNTEUgRGlzdHJpYnV0aW9uCiAgIyBvbmNlIGFnYWluIGNvZGUgbGFyZ2VseSBicm91Z2h0IG92ZXIgZnJvbSBIVyA5IGFzc2lnbm1lbnQKCiMgZXhwb25lbnRpYWwgbG9nIGxpa2VsaWhvb2QgZm9sbG93cyBzYW1lIHBhdHRlcm4gYXMgV2VpYnVsbCBsb2cgbGlrZWxpaG9vZCBidXQgYSBNVUNIIHNpbXBsZXIgZGlzdHJpYnV0aW9uCmV4cF9sb2dfbGlrZWxpaG9vZCA9IGZ1bmN0aW9uKGxhbWJkYSwgZGF0YSkgewogaWYgKGxhbWJkYSA8PSAwKSByZXR1cm4gKDFlMTApCiBuID0gbGVuZ3RoKGRhdGEpCiBsb2dfbGlrID0gLW4gKiBsb2cobGFtYmRhKSAtIHN1bShkYXRhKS9sYW1iZGEKIHJldHVybihsb2dfbGlrKQp9CgojIyMgbm93IGRlZmluZSBwYXJ0aWFsIGRlcml2YXRpdmUgdy8gcmVzcGVjdCB0byBsYW1iZGEgKHRoZSBzY29yZSBmdW5jdGlvbiBvciBncmFkaWVudCkKICAjIHBlcmZvcm1lZCB2aWEgcXVpY2sgaGFuZCBjYWxjdWxhdGlvbgoKZXhwX2dyYWRpZW50ID0gZnVuY3Rpb24obGFtYmRhLCBkYXRhKSB7CiAgaWYgKGxhbWJkYSA8PSAwKSByZXR1cm4gKE5BKQogIG4gPSBsZW5ndGgoZGF0YSkKICBwYXJ0aWFsX2Rlcml2X2xhbWJkYSA9IChuL2xhbWJkYSkgKyAoc3VtKGRhdGEpLyhsYW1iZGFeMikpCiAgcmV0dXJuKHBhcnRpYWxfZGVyaXZfbGFtYmRhKQp9CgpleHBfbWxlX2VzdGltYXRlcyA9IG9wdGltKAogIHBhciA9IDEvbWVhbihkYXRhJHRpbWUpLAogICAgIyB0aGUgaW5pdGlhbCBndWVzcyBjYW4gc2ltcGx5IGJlIDEvKG1lYW4gb2YgdGhlIGRhdGEpIHNpbmNlIHdlIGFyZSBwZXJmb3JtaW5nIHRoaXMgYW5hbHlzaXMgdW5kZXIgdGhlIHRoZW9yZXRpY2FsIHRoYXQgaXQgaXMgYW4gRVhQT05FTlRJQUwgZGlzdHJpYnV0aW9uLiBUaGUgbWVhbiBvZiBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gaXMgMSBkaXZpZGVkIGJ5IHRoZSB0aGUgcmF0ZSBwYXJhbWV0ZXIgbGFtYmRhCiAgZGF0YSA9IGRhdGEkdGltZSwKICBmbiA9IGV4cF9sb2dfbGlrZWxpaG9vZCwKICBnciA9IGV4cF9ncmFkaWVudCwKICBtZXRob2QgPSAiTC1CRkdTLUIiLAogIGhlc3NpYW4gPSBUUlVFLAogICAgIyB3aWxsIHVzZSB0aGUgSGVzc2lhbiBtYXRyaXggbGF0ZXIgb24KICBjb250cm9sID0gbGlzdChtYXhpdCA9IDEwMDAsIAogICAgICAgICAgICAgICAgIGZuc2NhbGUgID0gLTEsCiAgICAgICAgICAgICAgICAgdHJhY2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQopCiAgCiNleHBfbWxlX2VzdGltYXRlcyRwYXIKCmV4cF9tbGVfbGFtYmRhID0gZXhwX21sZV9lc3RpbWF0ZXMkcGFyCmBgYAoKUGVyIE1MRSBjYWxjdWxhdGlvbnMsIHdlIGNhbiBhc3NlcnQgdGhhdCB0aGUgJFxsYW1iZGEkIHBhcmFtZXRlciBvZiB0aGUgZGlzdHJpYnV0aW9uIG9mIGdlYXJib3ggc3Vydml2YWwgdGltZXMsIGlmIHNhaWQgZGlzdHJpYnV0aW9uIHdhcyB0cnVseSBleHBvbmVudGlhbCwgaXMgZXN0aW1hdGVkIHRvIGJlIHJvdWdobHkgYHIgcm91bmQoZXhwX21sZV9sYW1iZGEsMylgLiBBbiA8c3BhbiBzdHlsZT0iY29sb3I6cmVkOyI+ZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uPC9zcGFuPiB3aXRoICRcbGFtYmRhID0gYHIgcm91bmQoZXhwX21sZV9sYW1iZGEsMylgJCBpcyBvdmVybGFpZCBhdG9wIHRoZSBzYW1wbGUgZGF0YSBhbmQgYXZhaWxhYmxlIGJlbG93LgoKYGBge3J9CmdncGxvdChkYXRhID0gZGF0YSkgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHRpbWUsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICMgYXJndW1lbnQgY29sb3IgaW4gZ2VvbV9oaXN0b2dyYW0gaXMgZm9yIGNvbG9yIG9mIGJpbiBsaW5lcwogICAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRibHVlIiwKICAgICAgICAgICAgICAgICBiaW5zID0gMTAsKSArCiAgIyB1c2Ugc3RhdF9mdW5jdGlvbiBpbiBnZ3Bsb3QgdG8gc2hvdyBkZW5zaXR5IGN1cnZlcyBvZiBvdGhlciBkaXN0cmlidXRpb25zCiAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRleHAsIAogICAgICAgICAgICAgICAgYXJncyA9IGxpc3QocmF0ZSA9IDEvZXhwX21sZV9sYW1iZGEpLAogICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwKICAgICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEuNSwKICAgICAgICAgICAgICAgIHhsaW0gPSByYW5nZSgwOjUwKQogICAgICAgICAgICAgICAgKSsKICAgICAgICAgICAgIyB4bGltIGFyZ3VtZW50IHNvIGN1cnZlIGRvZXNuJ3QgYXdrYXJkbHkgY3V0IG91dCBhdCBlZGdlIHBvaW50cyBvZiBkYXRhCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU3Vydml2YWwgVGltZXMgKEV4cCkiLAogICAgICAgeCA9ICJUaW1lIChNb250aHMpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIpICsgCiAgdGhlbWUoCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIGxpbmV3aWR0aCA9IDMpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjg1LCAwLjg1KQogICkKCmBgYAoKQ29tcGFyaW5nIHRoaXMgaGlzdG9ncmFtIHRvIHRoZSBvbmUgZnJvbSBwYXJ0IGEsIHdlIHNlZSBhIGRyYXN0aWMgZGVjbGluZSBpbiBkaXN0cmlidXRpb24gcmVzZW1ibGFuY2UgYmV0d2VlbiB0aGUgc2FtcGxlIGRhdGEgYW5kIHRoZSB0aGVvcmV0aWNhbCBkZW5zaXR5IGN1cnZlLCB3aGVuIHdvcmtpbmcgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgcG9wdWxhdGlvbiBvZiBnZWFyYm94IHN1cnZpdmFsIHRpbWVzIGlzIGV4cG9uZW50aWFsbHkgZGlzdHJpYnV0ZWQuIFdlIHdpbGwga2VlcCB0aGlzIGluIG1pbmQgbW92aW5nIGZvcndhcmQsIGFzIHdlIHJ1biBoeXBvdGhlc2lzIHRlc3RzIHRvIHF1YW50aWZ5IHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSB0d28gZGlzdHJpYnV0aW9uIGFzc3VtcHRpb25zLgoKIyBjLikgTGlrZWxpaG9vZCBSYXRpbyBUZXN0CgpUbyBmdXJ0aGVyIGludmVzdGlnYXRlIHRoZSBkaWZmZXJlbmNlIGluIGVhY2ggZGlzdHJpYnV0aW9uJ3MgZml0IHdpdGggcmVnYXJkcyB0byBvdXIgcG9wdWxhdGlvbiBvZiBpbnRlcmVzdCAoZ2VhcmJveCBzdXJ2aXZhbCB0aW1lcyksIHdlIHdpbGwgcGVyZm9ybSBhIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCAoTFJUKS4gVGhlIExSVCB0YWtlcyBpbnRvIGFjY291bnQgdGhlIGxvZy1saWtlbGlob29kIGZ1bmN0aW9uIGV2YWx1YXRlZCB3aXRoIHBhcmFtZXRlciB2YWx1ZXMgZXN0aW1hdGVkIGZyb20gYSBzaW1wbGVyIG1vZGVsICh0aGUgZXhwb25lbnRpYWwgaW4gdGhpcyBjYXNlKSBhbmQgdGhlIGxvZy1saWtlbGlob29kIGZ1bmN0aW9uIGV2YWx1YXRlZCB3aXRoIHBhcmFtZXRlciB2YWx1ZXMgZXN0aW1hdGVkIGZyb20gYSBtb3JlIGNvbXBsaWNhdGVkIG1vZGVsICh0aGUgV2VpYnVsbCBpbiB0aGlzIHNjZW5hcmlvKS4gVGhlIG51bGwgaHlwb3RoZXNpcyBvZiBzdWNoIGEgdGVzdCBpcyB0aGF0LCBwZXIgb3VyIHNhbXBsZSBkYXRhLCB0aGVyZSBpcyAqKm5vKiogc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gbW9kZWwgZml0cy4KCmBgYHtyfQojIHdlaWJfbWxlX2JldGEgYW5kIHdlaWJfbWxlX2xhbWJkYSBhcmUgVU5SRVNUUklDVEVEIE1MRSBWQUxVRVMsIGJ1dCBub3cgd2UgbXVzdCBmaW5kCgojIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0IGJldGEgPSAxCiMgaWYgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUsIHRoZW4gZGlzdHJpYnV0aW9uIGlzIHJlYWxseSBqdXN0IGV4cG9uZW50aWFsCgojIyB0aGUgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IGlzIGp1c3QgMiAqIAogICMgW2xvZyBsaWtlbGlob29kIGV2YWx1YXRlZCBpbiB1bnJlc3RyaWN0ZWQgd2F5XSAtCiAgIyBbbG9nIGxpa2VsaWhvb2QgZXZhbHVhdGVkIGluIHJlc3RyaWN0ZWQgb3Igc2ltcGxlIHdheV0KCiMgbmVlZCB0byBldmFsdWF0ZSBlYWNoIGRpc3RyaWJ1dGlvbidzIGxpa2VsaWhvb2QgZnVuY3Rpb24gYXQgdGhlIHByZXZpb3VzbHkgZXN0aW1hdGVkIHBhcmFtZXRlcnMgb2YgYmV0YSBhbmQvb3IgbGFtYmRhCmxvZ19ldmFsdWF0aW9uX3dlaWIgPSBsb2dfbGlrZWxpaG9vZChwYXJhbXMgPSBjKHdlaWJfbWxlX2JldGEsIHdlaWJfbWxlX2xhbWJkYSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSkKbG9nX2V2YWx1YXRpb25fZXhwID0gZXhwX2xvZ19saWtlbGlob29kKGxhbWJkYSA9IGV4cF9tbGVfbGFtYmRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEpCgojIHRlc3Qgc3RhdCBmb3IgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IGlzIHVwcGVyY2FzZSBMYW1iZGEKCkxhbWJkYSA9IDIgKiBhYnMobG9nX2V2YWx1YXRpb25fd2VpYiAtIGxvZ19ldmFsdWF0aW9uX2V4cCkKCnBfdmFsdWVfbGlrZWxpaG9vZHJhdGlvID0gMSAtIHBjaGlzcShMYW1iZGEsIGRmID0gMSkKICAjIHRlc3Qgc3RhdCBkaXN0cmlidXRpb24gZm9yIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBpcyBjaGktc3F1YXJlIGRpc3RyaWJ1dGVkCiAgIyBkZiA9IG51bWJlciBvZiBwYXJhbWV0ZXJzIHdlIGFyZSBlc3RpbWF0aW5nIGluIGZ1bmN0aW9uCmBgYAoKT3VyIExSVCByZXR1cm5lZCBhbiBleHRyZW1lbHkgaGlnaCB0ZXN0IHZhbHVlICgkXExhbWJkYSQpIG9mIGFib3V0IGByIHJvdW5kKExhbWJkYSwzKWAuIENvbnNpZGVyaW5nICRcTGFtYmRhJCBmb2xsb3dzIGEgY2hpLXNxdWFyZSBkaXN0cmlidXRpb24sIHRoaXMgdGVzdCBzdGF0IGNvaW5jaWRlcyB3aXRoIGEgcCB2YWx1ZSBvZiBhcHByb3hpbWF0ZWx5IHplcm8uIFdpdGggdGhlc2UgZmluZGluZ3MsIHdlIG11c3QgKipyZWplY3QqKiB0aGUgbnVsbCBoeXBvdGhlc2lzIGFzIHRoZXJlIGlzIHZlcnkgY29udmluY2luZyBldmlkZW5jZSB0aGF0IHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBtb3JlIGFjY3VyYXRlbHkgcmVwcmVzZW50cyB0aGUgZml0IG9mIG91ciBwb3B1bGF0aW9uIG9mIGludGVyZXN0IHRoYW4gdGhlIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiBkb2VzLiBBZnRlciBleGFtaW5pbmcgdGhlIGhpc3RvZ3JhbXMgaW4gcGFydHMgYSBhbmQgYiwgdGhpcyBmaW5kaW5nIGlzIG5vdCBzdXJwcmlzaW5nLgoKIyBkLikgQm9vdHN0cmFwIExpa2VsaWhvb2QgUmF0aW8gVGVzdCAKTGFzdGx5LCBJIHJlcGVhdGVkIHRoaXMgc2FtZSB0eXBlIG9mIHByb2NlZHVyZSwgbGlrZWxpaG9vZCByYXRpbyB0ZXN0aW5nLCBhbmQgYXBwbGllZCBpdCB0byBhIGJvb3RzdHJhcHBlZCBzY2VuYXJpby4gVW5kZXIgdGhlIGd1aXNlIG9mIHRoZSBib290c3RyYXAgTFJULCB3ZSB0YWtlIHJlcGVhdGVkIHNhbXBsZXMgb2YgYSB0aGVvcmV0aWNhbCBkaXN0cmlidXRpb24sIGluIHRoaXMgY2FzZSBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gd2l0aCAkXGxhbWJkYSBcYXBwcm94JCBgciByb3VuZChleHBfbWxlX2xhbWJkYSwzKWAuIFRoZW4sIGZvciBlYWNoIHNhbXBsZSwgYSB0ZXN0IHN0YXRpc3RpYyBvZiAkXExhbWJkYSQgaXMgZm91bmQgdXNpbmcgdGhhdCBwYXJ0aWN1bGFyIGJvb3RzdHJhcCBzYW1wbGUncyBsb2ctbGlrZWxpaG9vZCBldmFsdWF0aW9uIGFsb25nIHdpdGggdGhlIGxvZy1saWtlbGlob29kIGV2YWx1YXRpb24gb2Ygb3VyIG9yaWdpbmFsIGFuZCBtb3JlIGNvbXBsZXgvdW5yZXN0cmljdGVkIG1vZGVsICh0aGUgV2VpYnVsbCBpbiB0aGlzIHNjZW5hcmlvKS4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojIyMgQm9vdHN0cmFwIExpa2VsaWhvb2QgUmF0aW8gVGVzdCAoQkxSVCkgZm9yIHNob3J0CiMgcmVmZXJlbmNlIGNvZGUgc2VjdGlvbiA0LjMgZnJvbSBXZWVrIDEyIG5vdGVzLCBuZWVkIHRvIGNoYW5nZSBmb3JtdWxhcyBzaW5jZSB3ZSBhcmUgYXBwbHlpbmcgdG8gZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uLCBub3Qgbm9ybWFsCgpib290c3RyYXBfbHJ0X3Rlc3QgPSBmdW5jdGlvbihkYXRhLCBiLCByYXRlX251bGwsIG9ic19scl9zdGF0KXsKICAgICMgb2JzX2xyX3N0YXQgd2lsbCA9IExhbWJkYSA9IGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBzdGF0IHRha2VuIGZyb20gb2JzZXJ2ZWQgZGF0YSBjYWxjdWxhdGlvbnMKICBuID0gbGVuZ3RoKGRhdGEpCiAgYm9vdF9scl9zdGF0ID0gbnVtZXJpYyhiKQogICAgCiAgIyBMb2ctbGlrZWxpaG9vZCBmdW5jdGlvbnMgYXJlIGZvdW5kIGluIGVhcmxpZXIgY29kZSBjaHVua3MgYW5kIHdpbGwgYmUgY2FsbGVkIHRvIHdpdGhpbiB0aGUgb3B0aW0gZnVuY3Rpb25zIG9mIHRoZSBmb3IgbG9vcCBwcm9jZXNzCiAgICAKICAjIFNUQVJUIEZPUiBMT09QCiAgICBmb3IgKGkgaW4gMTpiKXsKICAgICAgCiAgICAgICMgR2VuZXJhdGluZyBhcnRpZmljaWFsIGRhdGEgbWVhbnQgdG8gcmVwbGljYXRlIHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2Ygb3VyIE5VTEwgaHlwb3RoZXNpcwogICAgICAjIEluIHRoaXMgY2FzZSwgb3VyIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0IHRoZSBkYXRhIGZpdHMgYW4gZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIHdpdGggcmF0ZSBwYXJhbWV0ZXIgbGFtYmRhCiAgICAgIGJvb3RfZXhwX3NhbXBsZSA9IHJleHAobiA9IG4sIHJhdGUgPSByYXRlX251bGwpIAogIAogICAgICAjIyMjIyMjIFdlaWJ1bGwgbGlrZWxpaG9vZCBwZXIgYm9vdCBzYW1wbGUgICAgCiAgICAgIGJvb3RfYmV0YV9ndWVzcyA9IChzZChib290X2V4cF9zYW1wbGUpL21lYW4oYm9vdF9leHBfc2FtcGxlKSleKC0xLjA4NikKCiAgICAgIGJvb3RfbGFtYmRhX2d1ZXNzID0gbWVhbihib290X2V4cF9zYW1wbGUpL2dhbW1hKDEgKyAxL2Jvb3RfYmV0YV9ndWVzcykKICAgICAgCiAgICAgIGJvb3RfbG9nX3dlaWIgPSBvcHRpbSgKICAgICAgICAgIHBhciA9IGMoYm9vdF9iZXRhX2d1ZXNzLCBib290X2xhbWJkYV9ndWVzcyksICMgcGFyIGFyZ3VtZW50IGlzIGluaXRpYWwgImd1ZXNzZXMiCiAgICAgICAgICBkYXRhID0gYm9vdF9leHBfc2FtcGxlLAogICAgICAgICAgZm4gPSBsb2dfbGlrZWxpaG9vZCwKICAgICAgICAgIGdyID0gbG9nX2xpa2VsaWhvb2RfZ3JhZGllbnQsCiAgICAgICAgICBtZXRob2QgPSAiTC1CRkdTLUIiLAogICAgICAgICAgbG93ZXIgPSBjKDFlLTgsIDFlLTgpLCAjIyB0aGlzIGxpbWl0aW5nIGxvd2VyIGFyZ3VtZW50IGlzIE5FQ0VTU0FSWSwgYmVmb3JlIEkgYWRkZWQgaXQgSSB3YXMgZ2V0dGluZyBhbiBlcnJvciBsaW5lIGZvciAibm9uLWZpbml0ZSB2YWx1ZSBzdXBwbGllZCBieSBvcHRpbSIKICAgICAgICAgIGhlc3NpYW4gPSBUUlVFLAogICAgICAgICAgY29udHJvbCA9IGxpc3QobWF4aXQgPSAxMDAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGZuc2NhbGUgID0gLTEsCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgYWJzdG9sID0gMWUtOCkKICAgICAgICAgICkKICAgICAgYm9vdF9sb2dfd2VpYiA9IGJvb3RfbG9nX3dlaWIkdmFsdWUgIyBzdG9yZSBsb2cgbGlrZWxpaG9vZCBldmFsdWF0aW9uCiAgICAgICMjIyMjIyMgRW5kIFdlaWJ1bGwgbGlrZWxpaG9vZCBwZXIgYm9vdCBzYW1wbGUgCiAgCgogICAgICAjIyMjIyMjIEV4cG9uZW50aWFsIGxpa2VsaWhvb2QgcGVyIGJvb3Qgc2FtcGxlICAgIAogICAgICBib290X2xvZ19leHAgPSBvcHRpbSgKICAgICAgICAgIHBhciA9IDEvbWVhbihib290X2V4cF9zYW1wbGUpLAogICAgICAgICAgZGF0YSA9IGJvb3RfZXhwX3NhbXBsZSwKICAgICAgICAgIGZuID0gZXhwX2xvZ19saWtlbGlob29kLAogICAgICAgICAgZ3IgPSBleHBfZ3JhZGllbnQsCiAgICAgICAgICBtZXRob2QgPSAiTC1CRkdTLUIiLAogICAgICAgICAgaGVzc2lhbiA9IFRSVUUsCiAgICAgICAgICBjb250cm9sID0gbGlzdChtYXhpdCA9IDEwMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgZm5zY2FsZSAgPSAtMSwKICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQogICAgICAgICAgKQogICAgICBib290X2xvZ19leHAgPSBib290X2xvZ19leHAkdmFsdWUgICMgc3RvcmUgbG9nIGxpa2VsaWhvb2QgZXZhbHVhdGlvbgogICAgICAjIyMjIyMjIEVuZCBFeHBvbmVudGlhbCBsaWtlbGlob29kIHBlciBib290IHNhbXBsZSAgCiAgICAgIAogICAgICAKICAgICAgIyB0aGUgbGlrZWxpaG9vZCByYXRpbyBmb3IgRUFDSCBpbnN0YW5jZSBvZiB0aGUgYm9vdHN0cmFwIGlzIDIgdGltZXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbGlrZWxpaG9vZCByYXRpbyBldmFsdWF0ZWQgdW5kZXIgdW5yZXN0cmljdGVkIChXZWlidWxsKSBjaXJjdW1zdGFuY2VzIGFuZCBldmFsdWF0ZWQgdW5kZXIgc2ltcGxlciAoZXhwb25lbnRpYWwpIGNpcmN1bXN0YW5jZXMKICAgICAgYm9vdF9scl9zdGF0W2ldID0gMiAqIGFicyhib290X2xvZ193ZWliIC0gYm9vdF9sb2dfZXhwKQogICAgICAKCiAgICB9ICMgRU5EIEZPUiBMT09QCiAgICAKICAjIGNhbGN1bGF0ZSBhbmQgb3V0cHV0IGZpbmFsIHAgdmFsdWUKICBwID0gKHN1bShib290X2xyX3N0YXQgPj0gb2JzX2xyX3N0YXQpICsgMSkvIChiICsgMSkKICAKICAjIyMgRklOQUwgcCB2YWx1ZSBvZiBib290c3RyYXAgZXhlcmNpc2UgaXMgZXF1YWwgdG8uLiAKICAjIG51bWJlciBvZiBib290c3RyYXAgc2FtcGxlIExSIHRlc3Qgc3RhdHMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBvcmlnaW5hbCBMUiB0ZXN0IHN0YXQgZm91bmQgaW4gc2VjdGlvbiBjCiAgCiAgcmV0dXJuKGxpc3QocF92YWx1ZV9ib290c3RyYXAgPSBwLAogICAgICAgICAgICAgIGJvb3RzdHJhcF9scl9zdGF0cyA9IGJvb3RfbHJfc3RhdCkpCiAgCn0gIyMjIyBFTkQgQk9PVFNUUkFQIEZVTkNUSU9OCgoKIyMgbm93IHJ1bm5pbmcgdGhlIGZ1bmN0aW9uCnNldC5zZWVkKDEyMykKQkxSVF90ZXN0ID0gYm9vdHN0cmFwX2xydF90ZXN0KGRhdGEgPSBkYXRhJHRpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiID0gMTAwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXRlX251bGwgPSBleHBfbWxlX2xhbWJkYSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic19scl9zdGF0ID0gTGFtYmRhKQoKIyBCTFJUX3Rlc3QkcF92YWx1ZV9ib290c3RyYXAgPSAwLjAwMDk5OTAwMQpgYGAKClVzaW5nIGEgcmVwZWF0ZWQgc2FtcGxlIHNpemUgb2YgMSwwMDAsIHRoZXJlIG9uY2UgYWdhaW4gYXBwZWFycyB0byBiZSBzaWduaWZpY2FudCBldmlkZW5jZSB0aGF0IGFuIGFzc3VtcHRpb24gb2YgZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIHdvdWxkIHJlc3VsdCBpbiBhIG11Y2ggbGVzcyBhY2N1cmF0ZSByZXNlbWJsYW5jZSBvZiBvdXIgcG9wdWxhdGlvbiBvZiBnZWFyYm94IHN1cnZpdmFsIHRpbWVzIHRoYW4gYW4gYXNzdW1wdGlvbiBvZiBXZWlidWxsIGRpc3RyaWJ1dGlvbiB3b3VsZC4gT3VyIGJvb3RzdHJhcCBMUlQgeWllbGRlZCBhIHAtdmFsdWUgb2Ygb25seSBgciByb3VuZChCTFJUX3Rlc3QkcF92YWx1ZV9ib290c3RyYXAsIDQpYC4KCiMgZS4pIFN1bW1hcnkgYW5kIENvbmNsdXNpb25zClRvIHN1bW1hcml6ZSwgYWxsIG9mIHRoZSBhbmFseXNpcyB1cCB0byB0aGlzIHBvaW50IHN1cHBvcnRzIHRoZSBub3Rpb24gb2YgbW92aW5nIGZvcndhcmQgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgYnJvYWRlciBwb3B1bGF0aW9uIG9mIGdlYXJib3ggc3Vydml2YWwgdGltZXMgaXMgKipXZWlidWxsIGRpc3RyaWJ1dGVkKiogd2l0aCBhIHNoYXBlIHBhcmFtZXRlciAoJFxiZXRhJCkgb2YgYWJvdXQgYHIgcm91bmQod2VpYl9tbGVfYmV0YSwzKWAgYW5kIHNjYWxlIHBhcmFtZXRlciAoJFxsYW1iZGEkKSBvZiByb3VnaGx5IGByIHJvdW5kKHdlaWJfbWxlX2xhbWJkYSwzKWAuIEJvdGggdGhlIHN0YW5kYXJkIGFuZCBib290c3RyYXAgaXRlcmF0aW9ucyBvZiB0aGUgTFJUIHNob3cgYSBzaWduaWZpY2FudCBkZWNsaW5lIGluIGRpc3RyaWJ1dGlvbiByZXNlbWJsYW5jZSB3aGVuIGFzc3VtaW5nIGFuIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbi4gRnVydGhlcm1vcmUsIHdlIGNvdWxkIHNlZSBpbiBwcmVsaW1pbmFyeSB2aXN1YWwgYW5hbHlzaXMgdmlhIHRoZSBoaXN0b2dyYW1zIGluIHNlY3Rpb25zIGEgYW5kIGIsIHRoYXQgYSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBkZW5zaXR5IGN1cnZlIHdpdGggc2FpZCBwYXJlbWV0ZXJzIHdhcyAqbXVjaCogbW9yZSBhbGlnbmVkIHdpdGggb3VyIHNhbXBsZSBkaXN0cmlidXRpb24gdGhhbiB0aGF0IG9mIHRoZSBleHBvbmVudGlhbCBjdXJ2ZSB3aXRoICRcYmV0YSQgdmFsdWUgb2YgYXBwcm94aW1hdGVseSBgciByb3VuZChleHBfbWxlX2xhbWJkYSwzKWAuCgoK