data = rbind.data.frame(12.4, 18.7, 25.3, 30.1, 33.5, 35.2, 38.9, 40.3, 42.7, 45.1, 47.6, 49.8, 52.4, 55.0,
57.3, 60.2, 62.8, 65.1, 67.9, 70.5, 72.3, 75.6, 78.2, 80.9, 83.4, 85.7, 88.1, 90.6,
93.2, 95.8, 98.4, 101.0, 104.5, 107.3, 110.6, 113.2, 116.8, 120.1, 123.7, 127.4,
130.9, 134.5, 138.2, 142.0, 146.3, 150.7, 155.2, 160.8, 168.4, 175.9)
colnames(data) = "time"
Intro and Setup
For this analysis we are examining a dataset composed of 50 survival
times (the recorded times from start until failure) of identically
manufactured ball bearings. Over previous months, associates have
recognized what they believe to be an increase in the unreliability of
these bearings. A summary and visualization of the 50 recorded survival
times are 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 </span>") %>%
kable_styling(
bootstrap_options = c("striped", "bordered"),
full_width = FALSE,
position = "center")
Summary Stats of Survival Times
|
Min
|
Q1
|
Med
|
Mean
|
Q3
|
Max
|
|
12.4
|
53.05
|
84.55
|
87.61
|
119.27
|
175.9
|
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",
y = "Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3)
) # this is the equivalent of box(lwd = 3) in base R

For the purposes of this analysis, our default assumption (null
hypothesis) is that the \(\beta\) term
of the broader population of ball bearings at hand is equal to 1. If
this is truly the case, then our population is exponentially
distributed. However, given the makeup of the density formulas for both
exponential and Weibull distributions, if \(\beta \ne\) 1, that means our population is
Weibull distributed. Knowing a population’s true distribution
is valuable for future predictive analysis, making this a worthwhile
exercise.
\[\begin{align}
H_0&: \beta = 1 \quad \text{Takeaway: Exponential} \\
H_a&: \beta \neq 1 \quad \text{Takeaway: Weibull}
\end{align}\]
a.) MLE of Weibull Distribution
The first way that we will attempt to estimate \(\beta\) (the shape parameter) is via
maximum likelihood estimation (MLE). We will also simultaneously use MLE
to estimate the scale parameter, \(\lambda\). We will denote these estimates
as \(\hat{\beta}\) and \(\hat{\lambda}\) respectively.
In the process of performing likelihood estimation, 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 *
ln(\beta)] - [n*\beta *ln(\lambda)] + [(\beta - 1) * \sum(ln(t_i))] -
\sum(\frac{(t_i)}{\lambda})^\beta \]
\[\Large \frac{\partial f}{\partial \beta}
= \frac{n}{\beta} - n * ln(\lambda) + \sum(ln(t_i) -
\sum(ln\frac{t_i}{\lambda}) * (\frac{t_i}{\lambda})^\beta \]
\[\Large \frac{\partial f}{\partial
\lambda} = \frac{\beta}{\lambda} * \sum(\frac{t_i}{\lambda})^\beta -
n \]
## the log likelihood function simply runs a logarithm through all the terms and accounts for the summation of all data points, as opposed to one value of our variable t
##### Overall process is from section 5.2 of this week's notes
## reference week 7 section 5 notes for distribution-specific functions and formulas below
#### 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)
## gradient (partial derivatives) of *negative* log likelihood function for Weibull distribution
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
# reference section 5.2 of week 7 "Asymptotic Sampling" notes
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
Utilizing R’s optim() function,
along with the log likelihood and partial derivatives of the Weibull
distribution, this round of MLE-based estimates yielded a value for
\(\beta\) of roughly 2.206 and an
approximation of 99.021 for \(\lambda\).
As a means of further investigation, I overlaid the density curve of
a Weibull distribution with those exact shape (\(\beta\)) and scale (\(\lambda\)) characteristics atop the
histogram of our available sample data. The results below show that our
sample data certainly does not seem to strongly reject the potential
accuracy of our maximum likelihood estimation.
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:200))+
# xlim argument so curve doesn't awkardly cut out at edge points of data
labs(title = "Distribution of Survival Times",
x = "Time",
y = "Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3),
legend.position = c(0.85, 0.85)
)

If the population of ball bearing survival times truly is distributed
in a Weibull manner, then it seems very likely that \(\beta\) and \(\lambda\) are about equal to 2.206 and
99.021 respectively. I will now perform the MLE process again, this time
operating under the assertion that the population is
exponentially distributed.
b.) MLE of Exponential Distribution
\[\Large \ell(\lambda|t) = -[n *
ln(\lambda)] - \frac{\sum(t_i)}{\lambda} \]
\[\Large \frac{\partial f}{\partial
\lambda} = \frac{n}{\lambda} +
\frac{\sum(t_i)}{\lambda^2} \]
# 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
Once again using Utilizing R’s optim() along with the principles of maximum
likelihood estimation, I calculated an estimation of \(\lambda\). Under the assumption that the
ball bearing survival time population is exponentially
distributed, we would estimate \(\lambda\) to be roughly 88.132.
Below is the sample data with an exponential
curve with said lambda (scale) parameter overlaid. While this
does curve not appear to match the data to as close an extent as the
previous Weibull curve did, it is still reasonably similar in pattern
and scale.
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:200)
)+
# xlim argument so curve doesn't awkardly cut out at edge points of data
labs(title = "Distribution of Survival Times",
x = "Time",
y = "Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3),
legend.position = c(0.85, 0.85)
)

c.) Likelihood Ratio Test
Now having two different estimates of \(\lambda\), formulated via two differing
distribution assumptions, I went ahead and performed a likelihood ratio
test to help determine which presumed value of \(\lambda\) is more effective as per our
sample data serving as evidence.
The likelihood ratio test, which involves the subtraction of the log
likelihood estimate of a simpler model (the exponential performed in
part b) from the log likelihood estimate of a more complex and more
parameterized model (the Weibull performed in part a), is meant to
measure the improvement in fit that the more complex and unrestricted
model provides. The null hypothesis of this test is that, outside of
sampling variation, there is no sufficient difference in fit between the
simpler and more complex models. The test statistic for this hypothesis
test, \(\Lambda\), follows a chi-square
distribution with degrees of freedom equaling the number of parameters
actively being tested for.
###### handle Weibull distribution first
# 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(which is what we did in part a)] -
# [log likelihood evaluated in restricted or simple way(which we did in part b)]
# test stat for likelihood ratio test is uppercase Lambda
Lambda = 2 * (weib_mle_lambda - exp_mle_lambda)
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
Performing the likelihood ratio test, the resulting value of \(\Lambda\) was roughly 21.779, which yielded
a p value of roughly 3^{-6}. This of course leads us to reject the null
hypothesis, as there seems to be a large enough amount of evidence that
significant amount of fit is lost by operating under the assumption of
an exponential distribution. The findings of this test are rather
unsurprising, given the histogram visuals we looked at earlier.
d.) Wald Test
For further confirmation that the greater complexity which the
Weibull carries in comparison to the exponential distribution is a
worthwhile tradeoff for increased accuracy, I also performed the Wald
test. Like the likelihood ratio test, the Wald test also follows a
chi-square distribution, with the degrees of freedom acting as the
number of parameters being estimated at that time.
The null hypothesis of the Wald test is that the parameter of
interest (\(\beta\) in our case) is
close enough or equal to whatever previously hypothesized value. In this
instance, we will compare the unconstrained MLE-based estimate of \(\beta\) found in part a to the value of
\(\beta\) (1) that would make this
distribution of ball bearing survival times truly exponential.
invisible(
weib_mle_estimates$hessian
)
## the inverse of the Hessian matrix is the covariance
# in R, the solve function returns the inverse of a matrix object
covar_matrix = solve(-weib_mle_estimates$hessian)
# already have weib_mle_beta as our estiamte based on the unrestricted likelihood estimation method
var_beta = covar_matrix[1,1]
wald_stat = (weib_mle_beta - 1)^2 / var_beta
## once again, wald_stat is chi square just like likelihood ratio
p_value_wald = 1 - pchisq(wald_stat, df = 1)
Per the results of the Wald test, there is sufficient statistical
evidence that we cannot simply operate under the
assumption that the true shape parameter \(\beta\) of our distribution is 1. The Wald
test yielded a test statistic and p value of approximately 23.111 and
2^{-6} respectively.
e.) Summary and Conclusions
Given the results of the two performed hypothesis tests, we
cannot justify treating the distribution of ball
bearing survival times as exponential. Doing so would result in a
significant amount of predictive accuracy lost per the results of the
likelihood ratio test. And per the Wald test, there is not sufficient
evidence that the \(\beta\) parameter
is “flexible” enough to be assumed at a value of one, given our
available data.
Knowing this, we should move forward with the assumptions that the
broader population of bearing survival times is Weibull
distributed, with a shape parameter of approximately 2.206 and
a scale parameter of about 99.021. The visual for this distribution is
below once again.
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:200))+
# xlim argument so curve doesn't awkardly cut out at edge points of data
labs(title = "Distribution of Survival Times",
x = "Time",
y = "Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3),
legend.position = c(0.85, 0.85)
)

Our visual shows a rather immediate uptick in values, and then a
noticeable rightward skew. This is a standard pattern for a Weibull
distribution, making it a powerful modeling framework for areas like
engineering and life expectancies.
LS0tCnRpdGxlOiAiSHlwb3RoZXNpcyBUZXN0aW5nIHRvIERldGVybWluZSBQb3RlbnRpYWwgT3ZlcmZpdHRpbmcgb2YgRGlzdHJpYnV0aW9uIgphdXRob3I6ICJDaHJpcyBCYWhtIgpkYXRlOiAiQXByaWwgMTMsIDIwMjYiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogdHJ1ZQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ193aWR0aDogNgogICAgZmlnX2hlaWdodDogNAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IGx1bWVuCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKLS0tCgpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9CmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47CiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7CiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOwogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOwp9CgpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLwogIGZvbnQtc2l6ZTogMjRweDsKICBmb250LXdlaWdodDogYm9sZDsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogIGNvbG9yOiBEYXJrUmVkOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogIGNvbG9yOiBEYXJrQmx1ZTsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgxIHsgLyogSGVhZGVyIDEgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMjBweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogZGFya3JlZDsKICAgIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogICAgZm9udC1zaXplOiAxOHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogICAgZm9udC1zaXplOiAxNnB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogICAgZm9udC1zaXplOiAxNHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogZGFya3JlZDsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgewogIGNvbnRlbnQ6ICIuIjsKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLgoKaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7ICAgICAgICAgICAgICAgICAgICAgICMgdXNlIGNvbmRpdGlvbmFsIHN0YXRlbWVudCB0byBkZXRlY3QKICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKSAgICAgICAgICAgICAgICAgICMgd2hldGhlciBhIHBhY2thZ2Ugd2FzIGluc3RhbGxlZCBpbgogICBsaWJyYXJ5KGtuaXRyKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3VyIG1hY2hpbmUuIElmIG5vdCwgaW5zdGFsbCBpdCBhbmQKfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbG9hZCBpdCB0byB0aGUgd29ya2luZyBkaXJlY3RvcnkuCgppZiAoIXJlcXVpcmUodGlkeXZlcnNlKSkge2xpYnJhcnkodGlkeXZzZXJzZSl9IAoKaWYgKCFyZXF1aXJlKEdHYWxseSkpIHtsaWJyYXJ5KEdHYWxseSl9IAoKaWYgKCFyZXF1aXJlKGthYmxlRXh0cmEpKSB7bGlicmFyeShrYWJsZUV4dHJhKX0gCgppZiAoIXJlcXVpcmUoZ2dwbG90MikpIHtsaWJyYXJ5KGdncGxvdDIpfSAKCmlmICghcmVxdWlyZShjYXIpKSB7bGlicmFyeShjYXIpfSAKCmlmICghcmVxdWlyZShkcGx5cikpIHtsaWJyYXJ5KGRwbHlyKX0gCgppZiAoIXJlcXVpcmUocGFuZGVyKSkge2xpYnJhcnkocGFuZGVyKX0gCgppZiAoIXJlcXVpcmUoZm9yZWNhc3QpKSB7bGlicmFyeShmb3JlY2FzdCl9IAoKaWYgKCFyZXF1aXJlKGx1YnJpZGF0ZSkpIHtsaWJyYXJ5KGx1YnJpZGF0ZSl9IAoKaWYgKCFyZXF1aXJlKCJzY2FsZXMiKSkgewppbnN0YWxsLnBhY2thZ2VzKCJzY2FsZXMiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKbGlicmFyeSgic2NhbGVzIikgCn0KCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFLAoJY29tbWVudCA9IE5BLAoJcmVzdWx0cyA9IFRSVUUsCglmaWcuYWxpZ24gPSAiY2VudGVyIgopCmBgYAoKYGBge3J9CmRhdGEgPSByYmluZC5kYXRhLmZyYW1lKDEyLjQsIDE4LjcsIDI1LjMsIDMwLjEsIDMzLjUsIDM1LjIsIDM4LjksIDQwLjMsIDQyLjcsIDQ1LjEsIDQ3LjYsIDQ5LjgsIDUyLjQsIDU1LjAsIAo1Ny4zLCA2MC4yLCA2Mi44LCA2NS4xLCA2Ny45LCA3MC41LCA3Mi4zLCA3NS42LCA3OC4yLCA4MC45LCA4My40LCA4NS43LCA4OC4xLCA5MC42LCAKOTMuMiwgOTUuOCwgOTguNCwgMTAxLjAsIDEwNC41LCAxMDcuMywgMTEwLjYsIDExMy4yLCAxMTYuOCwgMTIwLjEsIDEyMy43LCAxMjcuNCwKMTMwLjksIDEzNC41LCAxMzguMiwgMTQyLjAsIDE0Ni4zLCAxNTAuNywgMTU1LjIsIDE2MC44LCAxNjguNCwgMTc1LjkpCmNvbG5hbWVzKGRhdGEpID0gInRpbWUiCmBgYAoKIyBJbnRybyBhbmQgU2V0dXAKRm9yIHRoaXMgYW5hbHlzaXMgd2UgYXJlIGV4YW1pbmluZyBhIGRhdGFzZXQgY29tcG9zZWQgb2YgYHIgbnJvdyhkYXRhKWAgc3Vydml2YWwgdGltZXMgKHRoZSByZWNvcmRlZCB0aW1lcyBmcm9tIHN0YXJ0IHVudGlsIGZhaWx1cmUpIG9mIGlkZW50aWNhbGx5IG1hbnVmYWN0dXJlZCBiYWxsIGJlYXJpbmdzLiBPdmVyIHByZXZpb3VzIG1vbnRocywgYXNzb2NpYXRlcyBoYXZlIHJlY29nbml6ZWQgd2hhdCB0aGV5IGJlbGlldmUgdG8gYmUgYW4gaW5jcmVhc2UgaW4gdGhlIHVucmVsaWFiaWxpdHkgb2YgdGhlc2UgYmVhcmluZ3MuIEEgc3VtbWFyeSBhbmQgdmlzdWFsaXphdGlvbiBvZiB0aGUgYHIgbnJvdyhkYXRhKWAgcmVjb3JkZWQgc3Vydml2YWwgdGltZXMgYXJlIGJlbG93LgpgYGB7cn0Kc3VtX3N0YXRzX3RhYmxlID0gZnVuY3Rpb24odmFyaWFibGUpewogIHRhYmxlID0gY2JpbmQoCiAgICByb3VuZChtaW4odmFyaWFibGUpLDIpLAogICAgcm91bmQocXVhbnRpbGUodmFyaWFibGUsIDAuMjUpLDIpLAogICAgcm91bmQobWVkaWFuKHZhcmlhYmxlKSwyKSwKICAgIHJvdW5kKG1lYW4odmFyaWFibGUpLDIpLAogICAgcm91bmQocXVhbnRpbGUodmFyaWFibGUsIDAuNzUpLDIpLAogICAgcm91bmQobWF4KHZhcmlhYmxlKSwyKQogICkKICBjb2xuYW1lcyh0YWJsZSkgPSBjKCJNaW4iLCAiUTEiLCAiTWVkIiwgIk1lYW4iLCAiUTMiLCAiTWF4IikKICByb3duYW1lcyh0YWJsZSkgPSBOVUxMCiAgcmV0dXJuKHRhYmxlKQp9CgpTdW1tYXJ5X1RhYmxlID0gc3VtX3N0YXRzX3RhYmxlKHZhcmlhYmxlID0gZGF0YSR0aW1lKQprYWJsZShTdW1tYXJ5X1RhYmxlLGFsaWduID0gImMiLAogICAgICBjYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojIzAwMDAwMDsnPgogICAgICBTdW1tYXJ5IFN0YXRzIG9mIFN1cnZpdmFsIFRpbWVzIDwvc3Bhbj4iKSAlPiUKICBrYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiksCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiKQoKCmdncGxvdChkYXRhID0gZGF0YSkgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHRpbWUsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICMgYXJndW1lbnQgY29sb3IgaW4gZ2VvbV9oaXN0b2dyYW0gaXMgZm9yIGNvbG9yIG9mIGJpbiBsaW5lcwogICAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRibHVlIiwKICAgICAgICAgICAgICAgICBiaW5zID0gMTAsKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU3Vydml2YWwgVGltZXMiLAogICAgICAgeCA9ICJUaW1lIiwKICAgICAgIHkgPSAiRGVuc2l0eSIpICsgCiAgdGhlbWUoCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIGxpbmV3aWR0aCA9IDMpCiAgKSAjIHRoaXMgaXMgdGhlIGVxdWl2YWxlbnQgb2YgYm94KGx3ZCA9IDMpIGluIGJhc2UgUgoKCmBgYAoKRm9yIHRoZSBwdXJwb3NlcyBvZiB0aGlzIGFuYWx5c2lzLCBvdXIgZGVmYXVsdCBhc3N1bXB0aW9uIChudWxsIGh5cG90aGVzaXMpIGlzIHRoYXQgdGhlICRcYmV0YSQgdGVybSBvZiB0aGUgYnJvYWRlciBwb3B1bGF0aW9uIG9mIGJhbGwgYmVhcmluZ3MgYXQgaGFuZCBpcyBlcXVhbCB0byAxLiBJZiB0aGlzIGlzIHRydWx5IHRoZSBjYXNlLCB0aGVuIG91ciBwb3B1bGF0aW9uIGlzICpleHBvbmVudGlhbGx5KiBkaXN0cmlidXRlZC4gSG93ZXZlciwgZ2l2ZW4gdGhlIG1ha2V1cCBvZiB0aGUgZGVuc2l0eSBmb3JtdWxhcyBmb3IgYm90aCBleHBvbmVudGlhbCBhbmQgV2VpYnVsbCBkaXN0cmlidXRpb25zLCBpZiAkXGJldGEgXG5lJCAxLCB0aGF0IG1lYW5zIG91ciBwb3B1bGF0aW9uIGlzICpXZWlidWxsKiBkaXN0cmlidXRlZC4gS25vd2luZyBhIHBvcHVsYXRpb24ncyB0cnVlIGRpc3RyaWJ1dGlvbiBpcyB2YWx1YWJsZSBmb3IgZnV0dXJlIHByZWRpY3RpdmUgYW5hbHlzaXMsIG1ha2luZyB0aGlzIGEgd29ydGh3aGlsZSBleGVyY2lzZS4KClxiZWdpbnthbGlnbn0KSF8wJjogXGJldGEgPSAxIFxxdWFkIFx0ZXh0e1Rha2Vhd2F5OiBFeHBvbmVudGlhbH0gXFwKSF9hJjogXGJldGEgXG5lcSAxIFxxdWFkIFx0ZXh0e1Rha2Vhd2F5OiBXZWlidWxsfQpcZW5ke2FsaWdufQoKCiMgYS4pIE1MRSBvZiBXZWlidWxsIERpc3RyaWJ1dGlvbgpUaGUgZmlyc3Qgd2F5IHRoYXQgd2Ugd2lsbCBhdHRlbXB0IHRvIGVzdGltYXRlICRcYmV0YSQgKHRoZSBzaGFwZSBwYXJhbWV0ZXIpIGlzIHZpYSBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGlvbiAoTUxFKS4gV2Ugd2lsbCBhbHNvIHNpbXVsdGFuZW91c2x5IHVzZSBNTEUgdG8gZXN0aW1hdGUgdGhlIHNjYWxlIHBhcmFtZXRlciwgJFxsYW1iZGEkLiBXZSB3aWxsIGRlbm90ZSB0aGVzZSBlc3RpbWF0ZXMgYXMgJFxoYXR7XGJldGF9JCBhbmQgJFxoYXR7XGxhbWJkYX0kIHJlc3BlY3RpdmVseS4KCkluIHRoZSBwcm9jZXNzIG9mIHBlcmZvcm1pbmcgbGlrZWxpaG9vZCBlc3RpbWF0aW9uLCB0aGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24gZm9yIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBhcyB3ZWxsIGFzIHRoZSBwYXJ0aWFsIGRlcml2YXRpdmVzIG9mIHRoYXQgdmVyeSBmdW5jdGlvbiB3aXRoIHJlc3BlY3QgdG8gYm90aCAkXGJldGEkIGFuZCAkXGxhbWJkYSQgYXJlIGJlbG93LgoKJCRcTGFyZ2UgXGVsbChcYmV0YSxcbGFtYmRhfHQpID0gW24gKiBsbihcYmV0YSldIC0gW24qXGJldGEgKmxuKFxsYW1iZGEpXSArIFsoXGJldGEgLSAxKSAqIFxzdW0obG4odF9pKSldIC0gXHN1bShcZnJhY3sodF9pKX17XGxhbWJkYX0pXlxiZXRhICQkCjxicj4KCiQkXExhcmdlIFxmcmFje1xwYXJ0aWFsIGZ9e1xwYXJ0aWFsIFxiZXRhfSA9IFxmcmFje259e1xiZXRhfSAtIG4gKiBsbihcbGFtYmRhKSArIFxzdW0obG4odF9pKSAtIFxzdW0obG5cZnJhY3t0X2l9e1xsYW1iZGF9KSAqIChcZnJhY3t0X2l9e1xsYW1iZGF9KV5cYmV0YSAgICAkJAo8YnI+CiQkXExhcmdlIFxmcmFje1xwYXJ0aWFsIGZ9e1xwYXJ0aWFsIFxsYW1iZGF9ID0gIFxmcmFje1xiZXRhfXtcbGFtYmRhfSAqIFxzdW0oXGZyYWN7dF9pfXtcbGFtYmRhfSleXGJldGEgLSBuICAgICQkCjxicj4KCmBgYHtyfQojIyB0aGUgbG9nIGxpa2VsaWhvb2QgZnVuY3Rpb24gc2ltcGx5IHJ1bnMgYSBsb2dhcml0aG0gdGhyb3VnaCBhbGwgdGhlIHRlcm1zIGFuZCBhY2NvdW50cyBmb3IgdGhlIHN1bW1hdGlvbiBvZiBhbGwgZGF0YSBwb2ludHMsIGFzIG9wcG9zZWQgdG8gb25lIHZhbHVlIG9mIG91ciB2YXJpYWJsZSB0CgoKIyMjIyMgT3ZlcmFsbCBwcm9jZXNzIGlzIGZyb20gc2VjdGlvbiA1LjIgb2YgdGhpcyB3ZWVrJ3Mgbm90ZXMKCiMjIHJlZmVyZW5jZSB3ZWVrIDcgc2VjdGlvbiA1IG5vdGVzIGZvciBkaXN0cmlidXRpb24tc3BlY2lmaWMgZnVuY3Rpb25zIGFuZCBmb3JtdWxhcyBiZWxvdwoKIyMjIyBkZWZpbmUgbGlrZWxpaG9vZCBmdW5jdGlvbgojIyAqbmVnYXRpdmUqIGxvZyBsaWtlbGlob29kIGZ1bmN0aW9uIGZvciBXZWlidWxsIGRpc3RyaWJ1dGlvbgogICMgYnkgbmVnYXRpdmUgbG9nIGxpa2VsaWhvb2QsIHRoaXMgZnVuY3Rpb24uLi4uCmxvZ19saWtlbGlob29kID0gZnVuY3Rpb24ocGFyYW1zLCBkYXRhKSB7CiAgYmV0YSA9IHBhcmFtc1sxXSAgIyBzaGFwZQogIGxhbWJkYSA9IHBhcmFtc1syXSAgIyBzY2FsZSAKICAKICAjIEVuc3VyZSBwYXJhbWV0ZXJzIGFyZSBwb3NpdGl2ZQogIGlmIChiZXRhIDw9IDAgfHwgbGFtYmRhIDw9IDApIHsKICAgIHJldHVybigxZTEwKSAgIyBSZXR1cm4gbGFyZ2UgdmFsdWUgZm9yIGludmFsaWQgcGFyYW1ldGVycwogIH0KICAKICBuID0gbGVuZ3RoKGRhdGEpCiAgbG9nX2xpayA9IG4gKiBsb2coYmV0YSkgLSBuICogYmV0YSAqIGxvZyhsYW1iZGEpICsgCiAgICAoYmV0YSAtIDEpICogc3VtKGxvZyhkYXRhKSkgLSBzdW0oKGRhdGEgLyBsYW1iZGEpXmJldGEpCiAgCiAgcmV0dXJuKGxvZ19saWspICAjIFJldHVybiBsb2ctbGlrZWxpaG9vZCEgTk9UIHRoZSBuZWdhdGl2ZSBsb2ctbGlrZWxpaG9vZAp9CgoKIyMjIyBkZWZpbmUgc2NvcmUgZXF1YXRpb25zIChwYXJ0aWFsIGRlcml2YXRpdmVzKQojIyBncmFkaWVudCAocGFydGlhbCBkZXJpdmF0aXZlcykgb2YgKm5lZ2F0aXZlKiBsb2cgbGlrZWxpaG9vZCBmdW5jdGlvbiAgZm9yIFdlaWJ1bGwgZGlzdHJpYnV0aW9uCmxvZ19saWtlbGlob29kX2dyYWRpZW50ID0gZnVuY3Rpb24ocGFyYW1zLCBkYXRhKSB7CiAgYmV0YSA9IHBhcmFtc1sxXSAgICAgICAjIHNoYXBlIHBhcmFtZXRlcgogIGxhbWJkYSA9IHBhcmFtc1syXSAgIyBzY2FsZSBwYXJhbWV0ZXIKICAKICBuID0gbGVuZ3RoKGRhdGEpCiAgCiAgcGFydGlhbF9kZXJpdl9iZXRhID0gbi9iZXRhIC0gbiAqIGxvZyhsYW1iZGEpICsgc3VtKGxvZyhkYXRhKSkgLSAKICAgICAgICBzdW0obG9nKGRhdGEvbGFtYmRhKSAqIChkYXRhL2xhbWJkYSleYmV0YSkKICAKICBwYXJ0aWFsX2Rlcml2X2xhbWJkYSA9ICAoYmV0YS9sYW1iZGEpKihzdW0oKGRhdGEvbGFtYmRhKV5iZXRhKSAtbikKICAKICByZXR1cm4oYyhwYXJ0aWFsX2Rlcml2X2JldGEsCiAgICAgICAgICAgcGFydGlhbF9kZXJpdl9sYW1iZGEpKSAgIyBHcmFkaWVudCBvZiBsb2ctbGlrZWxpaG9vZCwgTk9UIHRoZSBuZWdhdGl2ZSBzY29yZXMKfQoKCiMjIyMgdXNlIGxvZyBsaWtlbGlob29kIGFuZCBzY29yZSBlcXVhdGlvbnMgaW4gb3B0aW0gZnVuY3Rpb24KCiMgbmVlZCB0byBoYXZlIGdvb2QgaW5pdGlhbCBndWVzc2VzIGZvciBiZXRhIGFuZCBsYW1iZGEgZm9yIHRoZSBvcHRpbSBmdW5jdGlvbgogICMgcmVmZXJlbmNlIHNlY3Rpb24gNS4yIG9mIHdlZWsgNyAiQXN5bXB0b3RpYyBTYW1wbGluZyIgbm90ZXMKYmV0YV9ndWVzcyA9IChzZChkYXRhJHRpbWUpL21lYW4oZGF0YSR0aW1lKSleKC0xLjA4NikKCmxhbWJkYV9ndWVzcyA9IG1lYW4oZGF0YSR0aW1lKS9nYW1tYSgxICsgMS9iZXRhX2d1ZXNzKQoKCndlaWJfbWxlX2VzdGltYXRlcyA9IG9wdGltKAogIHBhciA9IGMoYmV0YV9ndWVzcywgbGFtYmRhX2d1ZXNzKSwgIyBwYXIgYXJndW1lbnQgaXMgaW5pdGlhbCAiZ3Vlc3NlcyIKICBkYXRhID0gZGF0YSR0aW1lLAogIGZuID0gbG9nX2xpa2VsaWhvb2QsCiAgZ3IgPSBsb2dfbGlrZWxpaG9vZF9ncmFkaWVudCwKICBtZXRob2QgPSAiTC1CRkdTLUIiLAogIGhlc3NpYW4gPSBUUlVFLAogICAgIyB3aWxsIHVzZSB0aGUgSGVzc2lhbiBtYXRyaXggbGF0ZXIgb24KICBjb250cm9sID0gbGlzdChtYXhpdCA9IDEwMDAsIAogICAgICAgICAgICAgICAgIGZuc2NhbGUgID0gLTEsCiAgICAgICAgICAgICAgICAgdHJhY2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQopCiN3ZWliX21sZV9lc3RpbWF0ZXMKICAKd2VpYl9tbGVfYmV0YSA9IHdlaWJfbWxlX2VzdGltYXRlcyRwYXJbMV0gIyBzaGFwZQp3ZWliX21sZV9sYW1iZGEgPSB3ZWliX21sZV9lc3RpbWF0ZXMkcGFyWzJdICMgc2NhbGUKCmBgYApVdGlsaXppbmcgUidzIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+b3B0aW0oKTwvc3Bhbj4gZnVuY3Rpb24sIGFsb25nIHdpdGggdGhlIGxvZyBsaWtlbGlob29kIGFuZCBwYXJ0aWFsIGRlcml2YXRpdmVzIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiwgdGhpcyByb3VuZCBvZiBNTEUtYmFzZWQgZXN0aW1hdGVzIHlpZWxkZWQgYSB2YWx1ZSBmb3IgJFxiZXRhJCBvZiByb3VnaGx5IGByIHJvdW5kKHdlaWJfbWxlX2JldGEsMylgIGFuZCBhbiBhcHByb3hpbWF0aW9uIG9mIGByIHJvdW5kKHdlaWJfbWxlX2xhbWJkYSwzKWAgZm9yICRcbGFtYmRhJC4gCgpBcyBhIG1lYW5zIG9mIGZ1cnRoZXIgaW52ZXN0aWdhdGlvbiwgSSBvdmVybGFpZCB0aGUgZGVuc2l0eSBjdXJ2ZSBvZiBhICoqV2VpYnVsbCBkaXN0cmlidXRpb24qKiB3aXRoIHRob3NlIGV4YWN0IHNoYXBlICgkXGJldGEkKSBhbmQgc2NhbGUgKCRcbGFtYmRhJCkgY2hhcmFjdGVyaXN0aWNzIGF0b3AgdGhlIGhpc3RvZ3JhbSBvZiBvdXIgYXZhaWxhYmxlIHNhbXBsZSBkYXRhLiBUaGUgcmVzdWx0cyBiZWxvdyBzaG93IHRoYXQgb3VyIHNhbXBsZSBkYXRhIGNlcnRhaW5seSBkb2VzIG5vdCBzZWVtIHRvIHN0cm9uZ2x5IHJlamVjdCB0aGUgcG90ZW50aWFsIGFjY3VyYWN5IG9mIG91ciBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGlvbi4KYGBge3J9CmdncGxvdChkYXRhID0gZGF0YSkgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHRpbWUsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICMgYXJndW1lbnQgY29sb3IgaW4gZ2VvbV9oaXN0b2dyYW0gaXMgZm9yIGNvbG9yIG9mIGJpbiBsaW5lcwogICAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRibHVlIiwKICAgICAgICAgICAgICAgICBiaW5zID0gMTAsKSArCiAgIyB1c2Ugc3RhdF9mdW5jdGlvbiBpbiBnZ3Bsb3QgdG8gc2hvdyBkZW5zaXR5IGN1cnZlcyBvZiBvdGhlciBkaXN0cmlidXRpb25zCiAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGR3ZWlidWxsLCAKICAgICAgICAgICAgICAgIGFyZ3MgPSBsaXN0KHNoYXBlID0gd2VpYl9tbGVfYmV0YSwgc2NhbGUgPSB3ZWliX21sZV9sYW1iZGEpLAogICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgbGluZXdpZHRoID0gMS41LAogICAgICAgICAgICAgICAgeGxpbSA9IHJhbmdlKDA6MjAwKSkrCiAgICAgICAgICAgICMgeGxpbSBhcmd1bWVudCBzbyBjdXJ2ZSBkb2Vzbid0IGF3a2FyZGx5IGN1dCBvdXQgYXQgZWRnZSBwb2ludHMgb2YgZGF0YQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFN1cnZpdmFsIFRpbWVzIiwKICAgICAgIHggPSAiVGltZSIsCiAgICAgICB5ID0gIkRlbnNpdHkiKSArIAogIHRoZW1lKAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9IE5BLCBsaW5ld2lkdGggPSAzKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44NSwgMC44NSkKICApCgpgYGAKCklmIHRoZSBwb3B1bGF0aW9uIG9mIGJhbGwgYmVhcmluZyBzdXJ2aXZhbCB0aW1lcyB0cnVseSBpcyBkaXN0cmlidXRlZCBpbiBhIFdlaWJ1bGwgbWFubmVyLCB0aGVuIGl0IHNlZW1zIHZlcnkgbGlrZWx5IHRoYXQgJFxiZXRhJCBhbmQgJFxsYW1iZGEkIGFyZSBhYm91dCBlcXVhbCB0byBgciByb3VuZCh3ZWliX21sZV9iZXRhLDMpYCBhbmQgIGByIHJvdW5kKHdlaWJfbWxlX2xhbWJkYSwzKWAgcmVzcGVjdGl2ZWx5LiBJIHdpbGwgbm93IHBlcmZvcm0gdGhlIE1MRSBwcm9jZXNzIGFnYWluLCB0aGlzIHRpbWUgb3BlcmF0aW5nIHVuZGVyIHRoZSBhc3NlcnRpb24gdGhhdCB0aGUgcG9wdWxhdGlvbiBpcyAqZXhwb25lbnRpYWxseSogZGlzdHJpYnV0ZWQuCgoKIyBiLikgTUxFIG9mIEV4cG9uZW50aWFsIERpc3RyaWJ1dGlvbgoKJCRcTGFyZ2UgXGVsbChcbGFtYmRhfHQpID0gLVtuICogbG4oXGxhbWJkYSldIC0gXGZyYWN7XHN1bSh0X2kpfXtcbGFtYmRhfSAgJCQKPGJyPgoKJCRcTGFyZ2UgXGZyYWN7XHBhcnRpYWwgZn17XHBhcnRpYWwgXGxhbWJkYX0gPSBcZnJhY3tufXtcbGFtYmRhfSArIFxmcmFje1xzdW0odF9pKX17XGxhbWJkYV4yfSAgICQkCgo8YnI+CgpgYGB7cn0KIyBleHBvbmVudGlhbCBsb2cgbGlrZWxpaG9vZCBmb2xsb3dzIHNhbWUgcGF0dGVybiBhcyBXZWlidWxsIGxvZyBsaWtlbGlob29kIGJ1dCBhIE1VQ0ggc2ltcGxlciBkaXN0cmlidXRpb24KZXhwX2xvZ19saWtlbGlob29kID0gZnVuY3Rpb24obGFtYmRhLCBkYXRhKSB7CiBpZiAobGFtYmRhIDw9IDApIHJldHVybiAoMWUxMCkKIG4gPSBsZW5ndGgoZGF0YSkKIGxvZ19saWsgPSAtbiAqIGxvZyhsYW1iZGEpIC0gc3VtKGRhdGEpL2xhbWJkYQogcmV0dXJuKGxvZ19saWspCn0KCiMjIyBub3cgZGVmaW5lIHBhcnRpYWwgZGVyaXZhdGl2ZSB3LyByZXNwZWN0IHRvIGxhbWJkYSAodGhlIHNjb3JlIGZ1bmN0aW9uIG9yIGdyYWRpZW50KQogICMgcGVyZm9ybWVkIHZpYSBxdWljayBoYW5kIGNhbGN1bGF0aW9uCgpleHBfZ3JhZGllbnQgPSBmdW5jdGlvbihsYW1iZGEsIGRhdGEpIHsKICBpZiAobGFtYmRhIDw9IDApIHJldHVybiAoTkEpCiAgbiA9IGxlbmd0aChkYXRhKQogIHBhcnRpYWxfZGVyaXZfbGFtYmRhID0gKG4vbGFtYmRhKSArIChzdW0oZGF0YSkvKGxhbWJkYV4yKSkKICByZXR1cm4ocGFydGlhbF9kZXJpdl9sYW1iZGEpCn0KCgpleHBfbWxlX2VzdGltYXRlcyA9IG9wdGltKAogIHBhciA9IDEvbWVhbihkYXRhJHRpbWUpLAogICAgIyB0aGUgaW5pdGlhbCBndWVzcyBjYW4gc2ltcGx5IGJlIDEvKG1lYW4gb2YgdGhlIGRhdGEpIHNpbmNlIHdlIGFyZSBwZXJmb3JtaW5nIHRoaXMgYW5hbHlzaXMgdW5kZXIgdGhlIHRoZW9yZXRpY2FsIHRoYXQgaXQgaXMgYW4gRVhQT05FTlRJQUwgZGlzdHJpYnV0aW9uLiBUaGUgbWVhbiBvZiBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gaXMgMSBkaXZpZGVkIGJ5IHRoZSB0aGUgcmF0ZSBwYXJhbWV0ZXIgbGFtYmRhCiAgZGF0YSA9IGRhdGEkdGltZSwKICBmbiA9IGV4cF9sb2dfbGlrZWxpaG9vZCwKICBnciA9IGV4cF9ncmFkaWVudCwKICBtZXRob2QgPSAiTC1CRkdTLUIiLAogIGhlc3NpYW4gPSBUUlVFLAogICAgIyB3aWxsIHVzZSB0aGUgSGVzc2lhbiBtYXRyaXggbGF0ZXIgb24KICBjb250cm9sID0gbGlzdChtYXhpdCA9IDEwMDAsIAogICAgICAgICAgICAgICAgIGZuc2NhbGUgID0gLTEsCiAgICAgICAgICAgICAgICAgdHJhY2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQopCiAgCiNleHBfbWxlX2VzdGltYXRlcyRwYXIKCmV4cF9tbGVfbGFtYmRhID0gZXhwX21sZV9lc3RpbWF0ZXMkcGFyCmBgYApPbmNlIGFnYWluIHVzaW5nIFV0aWxpemluZyBSJ3MgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij5vcHRpbSgpPC9zcGFuPiBhbG9uZyB3aXRoIHRoZSBwcmluY2lwbGVzIG9mIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0aW9uLCBJIGNhbGN1bGF0ZWQgYW4gZXN0aW1hdGlvbiBvZiAkXGxhbWJkYSQuIFVuZGVyIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIGJhbGwgYmVhcmluZyBzdXJ2aXZhbCB0aW1lIHBvcHVsYXRpb24gaXMgKmV4cG9uZW50aWFsbHkqIGRpc3RyaWJ1dGVkLCB3ZSB3b3VsZCBlc3RpbWF0ZSAkXGxhbWJkYSQgdG8gYmUgcm91Z2hseSBgciByb3VuZChleHBfbWxlX2xhbWJkYSwzKWAuIAoKQmVsb3cgaXMgdGhlIHNhbXBsZSBkYXRhIHdpdGggYW4gPHNwYW4gc3R5bGU9ImNvbG9yOnJlZDsiPmV4cG9uZW50aWFsIGN1cnZlPC9zcGFuPiB3aXRoIHNhaWQgbGFtYmRhIChzY2FsZSkgcGFyYW1ldGVyIG92ZXJsYWlkLiBXaGlsZSB0aGlzIGRvZXMgY3VydmUgbm90IGFwcGVhciB0byBtYXRjaCB0aGUgZGF0YSB0byBhcyBjbG9zZSBhbiBleHRlbnQgYXMgdGhlIHByZXZpb3VzIFdlaWJ1bGwgY3VydmUgZGlkLCBpdCBpcyBzdGlsbCByZWFzb25hYmx5IHNpbWlsYXIgaW4gcGF0dGVybiBhbmQgc2NhbGUuCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGRhdGEpICsKICBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKHggPSB0aW1lLCB5ID0gYWZ0ZXJfc3RhdChkZW5zaXR5KSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgICAjIGFyZ3VtZW50IGNvbG9yIGluIGdlb21faGlzdG9ncmFtIGlzIGZvciBjb2xvciBvZiBiaW4gbGluZXMKICAgICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Ymx1ZSIsCiAgICAgICAgICAgICAgICAgYmlucyA9IDEwLCkgKwogICMgdXNlIHN0YXRfZnVuY3Rpb24gaW4gZ2dwbG90IHRvIHNob3cgZGVuc2l0eSBjdXJ2ZXMgb2Ygb3RoZXIgZGlzdHJpYnV0aW9ucwogICAgc3RhdF9mdW5jdGlvbihmdW4gPSBkZXhwLCAKICAgICAgICAgICAgICAgIGFyZ3MgPSBsaXN0KHJhdGUgPSAxL2V4cF9tbGVfbGFtYmRhKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsCiAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLjUsCiAgICAgICAgICAgICAgICB4bGltID0gcmFuZ2UoMDoyMDApCiAgICAgICAgICAgICAgICApKwogICAgICAgICAgICAjIHhsaW0gYXJndW1lbnQgc28gY3VydmUgZG9lc24ndCBhd2thcmRseSBjdXQgb3V0IGF0IGVkZ2UgcG9pbnRzIG9mIGRhdGEKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBTdXJ2aXZhbCBUaW1lcyIsCiAgICAgICB4ID0gIlRpbWUiLAogICAgICAgeSA9ICJEZW5zaXR5IikgKyAKICB0aGVtZSgKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgbGluZXdpZHRoID0gMyksCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuODUsIDAuODUpCiAgKQoKYGBgCgoKIyBjLikgTGlrZWxpaG9vZCBSYXRpbyBUZXN0Ck5vdyBoYXZpbmcgdHdvIGRpZmZlcmVudCBlc3RpbWF0ZXMgb2YgJFxsYW1iZGEkLCBmb3JtdWxhdGVkIHZpYSB0d28gZGlmZmVyaW5nIGRpc3RyaWJ1dGlvbiBhc3N1bXB0aW9ucywgSSB3ZW50IGFoZWFkIGFuZCBwZXJmb3JtZWQgYSBsaWtlbGlob29kIHJhdGlvIHRlc3QgdG8gaGVscCBkZXRlcm1pbmUgd2hpY2ggcHJlc3VtZWQgdmFsdWUgb2YgJFxsYW1iZGEkIGlzIG1vcmUgZWZmZWN0aXZlIGFzIHBlciBvdXIgc2FtcGxlIGRhdGEgc2VydmluZyBhcyBldmlkZW5jZS4gCgpUaGUgbGlrZWxpaG9vZCByYXRpbyB0ZXN0LCB3aGljaCBpbnZvbHZlcyB0aGUgc3VidHJhY3Rpb24gb2YgdGhlIGxvZyBsaWtlbGlob29kIGVzdGltYXRlIG9mIGEgc2ltcGxlciBtb2RlbCAodGhlIGV4cG9uZW50aWFsIHBlcmZvcm1lZCBpbiBwYXJ0IGIpIGZyb20gdGhlIGxvZyBsaWtlbGlob29kIGVzdGltYXRlIG9mIGEgbW9yZSBjb21wbGV4IGFuZCBtb3JlIHBhcmFtZXRlcml6ZWQgbW9kZWwgKHRoZSBXZWlidWxsIHBlcmZvcm1lZCBpbiBwYXJ0IGEpLCBpcyBtZWFudCB0byBtZWFzdXJlIHRoZSBpbXByb3ZlbWVudCBpbiBmaXQgdGhhdCB0aGUgbW9yZSBjb21wbGV4IGFuZCB1bnJlc3RyaWN0ZWQgbW9kZWwgcHJvdmlkZXMuIFRoZSBudWxsIGh5cG90aGVzaXMgb2YgdGhpcyB0ZXN0IGlzIHRoYXQsIG91dHNpZGUgb2Ygc2FtcGxpbmcgdmFyaWF0aW9uLCB0aGVyZSBpcyBubyBzdWZmaWNpZW50IGRpZmZlcmVuY2UgaW4gZml0IGJldHdlZW4gdGhlIHNpbXBsZXIgYW5kIG1vcmUgY29tcGxleCBtb2RlbHMuIFRoZSB0ZXN0IHN0YXRpc3RpYyBmb3IgdGhpcyBoeXBvdGhlc2lzIHRlc3QsICRcTGFtYmRhJCwgZm9sbG93cyBhIGNoaS1zcXVhcmUgZGlzdHJpYnV0aW9uIHdpdGggZGVncmVlcyBvZiBmcmVlZG9tIGVxdWFsaW5nIHRoZSBudW1iZXIgb2YgcGFyYW1ldGVycyBhY3RpdmVseSBiZWluZyB0ZXN0ZWQgZm9yLgoKYGBge3J9CiMjIyMjIyBoYW5kbGUgV2VpYnVsbCBkaXN0cmlidXRpb24gZmlyc3QKIyB3ZWliX21sZV9iZXRhIGFuZCB3ZWliX21sZV9sYW1iZGEgYXJlIFVOUkVTVFJJQ1RFRCBNTEUgVkFMVUVTLCBidXQgbm93IHdlIG11c3QgZmluZAoKIyBudWxsIGh5cG90aGVzaXMgaXMgdGhhdCBiZXRhID0gMQojIGlmIG51bGwgaHlwb3RoZXNpcyBpcyB0cnVlLCB0aGVuIGRpc3RyaWJ1dGlvbiBpcyByZWFsbHkganVzdCBleHBvbmVudGlhbAoKIyMgdGhlIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBpcyBqdXN0IDIgKiAKICAjIFtsb2cgbGlrZWxpaG9vZCBldmFsdWF0ZWQgaW4gdW5yZXN0cmljdGVkIHdheSh3aGljaCBpcyB3aGF0IHdlIGRpZCBpbiBwYXJ0IGEpXSAtCiAgIyBbbG9nIGxpa2VsaWhvb2QgZXZhbHVhdGVkIGluIHJlc3RyaWN0ZWQgb3Igc2ltcGxlIHdheSh3aGljaCB3ZSBkaWQgaW4gcGFydCBiKV0KCiMgdGVzdCBzdGF0IGZvciBsaWtlbGlob29kIHJhdGlvIHRlc3QgaXMgdXBwZXJjYXNlIExhbWJkYQoKTGFtYmRhID0gMiAqICh3ZWliX21sZV9sYW1iZGEgLSBleHBfbWxlX2xhbWJkYSkKCnBfdmFsdWVfbGlrZWxpaG9vZHJhdGlvID0gMSAtIHBjaGlzcShMYW1iZGEsIGRmID0gMSkKICAjIHRlc3Qgc3RhdCBkaXN0cmlidXRpb24gZm9yIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBpcyBjaGktc3F1YXJlIGRpc3RyaWJ1dGVkCiAgIyBkZiA9IG51bWJlciBvZiBwYXJhbWV0ZXJzIHdlIGFyZSBlc3RpbWF0aW5nIGluIGZ1bmN0aW9uCgpgYGAKClBlcmZvcm1pbmcgdGhlIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCwgdGhlIHJlc3VsdGluZyB2YWx1ZSBvZiAkXExhbWJkYSQgd2FzIHJvdWdobHkgYHIgcm91bmQoTGFtYmRhLDMpYCwgd2hpY2ggeWllbGRlZCBhIHAgdmFsdWUgb2Ygcm91Z2hseSBgciByb3VuZChwX3ZhbHVlX2xpa2VsaWhvb2RyYXRpbywgNilgLiBUaGlzIG9mIGNvdXJzZSBsZWFkcyB1cyB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcywgYXMgdGhlcmUgc2VlbXMgdG8gYmUgYSBsYXJnZSBlbm91Z2ggYW1vdW50IG9mIGV2aWRlbmNlIHRoYXQgc2lnbmlmaWNhbnQgYW1vdW50IG9mIGZpdCBpcyBsb3N0IGJ5IG9wZXJhdGluZyB1bmRlciB0aGUgYXNzdW1wdGlvbiBvZiBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24uIFRoZSBmaW5kaW5ncyBvZiB0aGlzIHRlc3QgYXJlIHJhdGhlciB1bnN1cnByaXNpbmcsIGdpdmVuIHRoZSBoaXN0b2dyYW0gdmlzdWFscyB3ZSBsb29rZWQgYXQgZWFybGllci4KCiMgZC4pIFdhbGQgVGVzdAoKRm9yIGZ1cnRoZXIgY29uZmlybWF0aW9uIHRoYXQgdGhlIGdyZWF0ZXIgY29tcGxleGl0eSB3aGljaCB0aGUgV2VpYnVsbCBjYXJyaWVzIGluIGNvbXBhcmlzb24gdG8gdGhlIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiBpcyBhIHdvcnRod2hpbGUgdHJhZGVvZmYgZm9yIGluY3JlYXNlZCBhY2N1cmFjeSwgSSBhbHNvIHBlcmZvcm1lZCB0aGUgV2FsZCB0ZXN0LiBMaWtlIHRoZSBsaWtlbGlob29kIHJhdGlvIHRlc3QsIHRoZSBXYWxkIHRlc3QgYWxzbyBmb2xsb3dzIGEgY2hpLXNxdWFyZSBkaXN0cmlidXRpb24sIHdpdGggdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBhY3RpbmcgYXMgdGhlIG51bWJlciBvZiBwYXJhbWV0ZXJzIGJlaW5nIGVzdGltYXRlZCBhdCB0aGF0IHRpbWUuIAoKVGhlIG51bGwgaHlwb3RoZXNpcyBvZiB0aGUgV2FsZCB0ZXN0IGlzIHRoYXQgdGhlIHBhcmFtZXRlciBvZiBpbnRlcmVzdCAoJFxiZXRhJCBpbiBvdXIgY2FzZSkgaXMgY2xvc2UgZW5vdWdoIG9yIGVxdWFsIHRvIHdoYXRldmVyIHByZXZpb3VzbHkgaHlwb3RoZXNpemVkIHZhbHVlLiBJbiB0aGlzIGluc3RhbmNlLCB3ZSB3aWxsIGNvbXBhcmUgdGhlIHVuY29uc3RyYWluZWQgTUxFLWJhc2VkIGVzdGltYXRlIG9mICRcYmV0YSQgZm91bmQgaW4gcGFydCBhIHRvIHRoZSB2YWx1ZSBvZiAkXGJldGEkICgxKSB0aGF0IHdvdWxkIG1ha2UgdGhpcyBkaXN0cmlidXRpb24gb2YgYmFsbCBiZWFyaW5nIHN1cnZpdmFsIHRpbWVzIHRydWx5IGV4cG9uZW50aWFsLgpgYGB7cn0KaW52aXNpYmxlKAogIHdlaWJfbWxlX2VzdGltYXRlcyRoZXNzaWFuCikKIyMgdGhlIGludmVyc2Ugb2YgdGhlIEhlc3NpYW4gbWF0cml4IGlzIHRoZSBjb3ZhcmlhbmNlCiAjIGluIFIsIHRoZSBzb2x2ZSBmdW5jdGlvbiByZXR1cm5zIHRoZSBpbnZlcnNlIG9mIGEgbWF0cml4IG9iamVjdApjb3Zhcl9tYXRyaXggPSBzb2x2ZSgtd2VpYl9tbGVfZXN0aW1hdGVzJGhlc3NpYW4pCgojIGFscmVhZHkgaGF2ZSB3ZWliX21sZV9iZXRhIGFzIG91ciBlc3RpYW10ZSBiYXNlZCBvbiB0aGUgdW5yZXN0cmljdGVkIGxpa2VsaWhvb2QgZXN0aW1hdGlvbiBtZXRob2QKCnZhcl9iZXRhID0gY292YXJfbWF0cml4WzEsMV0KCndhbGRfc3RhdCA9ICh3ZWliX21sZV9iZXRhIC0gMSleMiAvIHZhcl9iZXRhCgojIyBvbmNlIGFnYWluLCB3YWxkX3N0YXQgaXMgY2hpIHNxdWFyZSBqdXN0IGxpa2UgbGlrZWxpaG9vZCByYXRpbwpwX3ZhbHVlX3dhbGQgPSAxIC0gcGNoaXNxKHdhbGRfc3RhdCwgZGYgPSAxKQoKYGBgCgpQZXIgdGhlIHJlc3VsdHMgb2YgdGhlIFdhbGQgdGVzdCwgdGhlcmUgaXMgc3VmZmljaWVudCBzdGF0aXN0aWNhbCBldmlkZW5jZSB0aGF0IHdlICoqY2Fubm90Kiogc2ltcGx5IG9wZXJhdGUgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgdHJ1ZSBzaGFwZSBwYXJhbWV0ZXIgJFxiZXRhJCBvZiBvdXIgZGlzdHJpYnV0aW9uIGlzIDEuIFRoZSBXYWxkIHRlc3QgeWllbGRlZCBhIHRlc3Qgc3RhdGlzdGljIGFuZCBwIHZhbHVlIG9mIGFwcHJveGltYXRlbHkgYHIgcm91bmQod2FsZF9zdGF0LCAzKWAgYW5kIGByIHJvdW5kKHBfdmFsdWVfd2FsZCw2KWAgcmVzcGVjdGl2ZWx5LgoKIyBlLikgU3VtbWFyeSBhbmQgQ29uY2x1c2lvbnMKR2l2ZW4gdGhlIHJlc3VsdHMgb2YgdGhlIHR3byBwZXJmb3JtZWQgaHlwb3RoZXNpcyB0ZXN0cywgd2UgKipjYW5ub3QqKiBqdXN0aWZ5IHRyZWF0aW5nIHRoZSBkaXN0cmlidXRpb24gb2YgYmFsbCBiZWFyaW5nIHN1cnZpdmFsIHRpbWVzIGFzIGV4cG9uZW50aWFsLiBEb2luZyBzbyB3b3VsZCByZXN1bHQgaW4gYSBzaWduaWZpY2FudCBhbW91bnQgb2YgcHJlZGljdGl2ZSBhY2N1cmFjeSBsb3N0IHBlciB0aGUgcmVzdWx0cyBvZiB0aGUgbGlrZWxpaG9vZCByYXRpbyB0ZXN0LiBBbmQgcGVyIHRoZSBXYWxkIHRlc3QsIHRoZXJlIGlzIG5vdCBzdWZmaWNpZW50IGV2aWRlbmNlIHRoYXQgdGhlICRcYmV0YSQgcGFyYW1ldGVyIGlzICJmbGV4aWJsZSIgZW5vdWdoIHRvIGJlIGFzc3VtZWQgYXQgYSB2YWx1ZSBvZiBvbmUsIGdpdmVuIG91ciBhdmFpbGFibGUgZGF0YS4KCktub3dpbmcgdGhpcywgd2Ugc2hvdWxkIG1vdmUgZm9yd2FyZCB3aXRoIHRoZSBhc3N1bXB0aW9ucyB0aGF0IHRoZSBicm9hZGVyIHBvcHVsYXRpb24gb2YgYmVhcmluZyBzdXJ2aXZhbCB0aW1lcyBpcyAqKldlaWJ1bGwgZGlzdHJpYnV0ZWQqKiwgd2l0aCBhIHNoYXBlIHBhcmFtZXRlciBvZiBhcHByb3hpbWF0ZWx5IGByIHJvdW5kKHdlaWJfbWxlX2JldGEsMylgIGFuZCBhIHNjYWxlIHBhcmFtZXRlciBvZiBhYm91dCBgciByb3VuZCh3ZWliX21sZV9sYW1iZGEsMylgLiBUaGUgdmlzdWFsIGZvciB0aGlzIGRpc3RyaWJ1dGlvbiBpcyBiZWxvdyBvbmNlIGFnYWluLgoKYGBge3J9CmdncGxvdChkYXRhID0gZGF0YSkgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHRpbWUsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICMgYXJndW1lbnQgY29sb3IgaW4gZ2VvbV9oaXN0b2dyYW0gaXMgZm9yIGNvbG9yIG9mIGJpbiBsaW5lcwogICAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRibHVlIiwKICAgICAgICAgICAgICAgICBiaW5zID0gMTAsKSArCiAgIyB1c2Ugc3RhdF9mdW5jdGlvbiBpbiBnZ3Bsb3QgdG8gc2hvdyBkZW5zaXR5IGN1cnZlcyBvZiBvdGhlciBkaXN0cmlidXRpb25zCiAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGR3ZWlidWxsLCAKICAgICAgICAgICAgICAgIGFyZ3MgPSBsaXN0KHNoYXBlID0gd2VpYl9tbGVfYmV0YSwgc2NhbGUgPSB3ZWliX21sZV9sYW1iZGEpLAogICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgbGluZXdpZHRoID0gMS41LAogICAgICAgICAgICAgICAgeGxpbSA9IHJhbmdlKDA6MjAwKSkrCiAgICAgICAgICAgICMgeGxpbSBhcmd1bWVudCBzbyBjdXJ2ZSBkb2Vzbid0IGF3a2FyZGx5IGN1dCBvdXQgYXQgZWRnZSBwb2ludHMgb2YgZGF0YQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFN1cnZpdmFsIFRpbWVzIiwKICAgICAgIHggPSAiVGltZSIsCiAgICAgICB5ID0gIkRlbnNpdHkiKSArIAogIHRoZW1lKAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9IE5BLCBsaW5ld2lkdGggPSAzKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44NSwgMC44NSkKICApCgpgYGAKCk91ciB2aXN1YWwgc2hvd3MgYSByYXRoZXIgaW1tZWRpYXRlIHVwdGljayBpbiB2YWx1ZXMsIGFuZCB0aGVuIGEgbm90aWNlYWJsZSByaWdodHdhcmQgc2tldy4gVGhpcyBpcyBhIHN0YW5kYXJkIHBhdHRlcm4gZm9yIGEgV2VpYnVsbCBkaXN0cmlidXRpb24sIG1ha2luZyBpdCBhIHBvd2VyZnVsIG1vZGVsaW5nIGZyYW1ld29yayBmb3IgYXJlYXMgbGlrZSBlbmdpbmVlcmluZyBhbmQgbGlmZSBleHBlY3RhbmNpZXMuCg==