Intro and Setup
For this exam, we will be examining and utilizing the
Kumaraswamy distribution. This distribution is
continuous, bounded between 0 and 1, and defined by two parameters
(\(a\) and \(b\)).
With \(X\) denoting a Kumaraswamy
random variable, the CDF of our distribution is the following.
\[\Large F(x; a,b) = 1 - (1-x^a)^b
\]
Two special cases of the Kumaraswamy distribution are the uniform and
power distributions. A distribution is uniform if \(a, b\) = 1, while such is power if \(a > 0, b = 1\).
Part A: Methodological Derivations
A1.)
Given the distribution’s cumulative function, we can use
calculus-based methods to derive the probability density function (PDF).
Said calculations were completed by hand and can be seen below.
knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A1.jpg")

Moving forward, we define our density function as the following.
\[\Large f(x; a, b) = ab \, x^{a-1} (1 -
x^a)^{b-1}\]
A2.)
Now having our distribution’s density function, we can denote our
log-likelihood, \(\ell(a,b)\), function
and subsequent gradient vector. The gradient vector is made up of the
partial derivatives of the log-likelihood function, first with respect
to \(a\) then with respect to \(b\). Below are calculations and ultimate
results.
knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A2_1.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A2_2.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A2_3.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A2_4.jpg")

\[\Large \ell(a,b) = n\ln(a) + n\ln(b) +
\left[ (a-1)\sum \ln(x_i) \right] + \left[ (b-1)\sum\ln(1-x_i^a)
\right]\]
\[\Large \ell_a^\prime(a,b) = \frac{n}{a}
+ \left[ \sum\ln(x_i) \right] - \left[(b-1)\sum\frac{x_i^a \times
\ln(x_i)}{1 - x_i^a} \right]\]
\[\Large \ell_b^\prime(a,b) = \frac{n}{b}
+ \sum\ln(1-x_i^a)\]
A3.)
Then taking the gradient vector components, I was able to calculate
the Fisher information matrix (\(I\)),
which is simply the negative of the Hessian matrix (composed of all
second-derivative extensions of that distribution’s log-likelihood). The
Fisher Information matrix for the Kumaraswamy distribution is below.
knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A3_1.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A3_2.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A3_3.jpg")

A4.)
We now consider the power distribution, a special
and more simplistic case of the Kumaraswamy distribution, which occurs
when the parameter \(b\) = 1. Given the
Kumaraswamy formula, a value of \(b\) =
1 means that the relative density function of the power distribution is
\(ax^{a-1}\). Knowing this, below are
formulas which can be used to estimate the parameter \(a\) via moment or maximum likelihood
estimation (MOM or MLE).
knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A4_1.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A4_2.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A4_3.jpg")

A5.)
Given an estimate of our parameter \(a\), (\(\hat{a}\)), we can setup a general
confidence interval (CI) formula for the value of \(a\). Assuming 95% confidence, therefore a
critical value of 1.96 predicated on the normal distribution, the makeup
of the CI would look like the following.
The variance and standard deviation of the interval were found from
the power distribution’s information matrix. The inverse of such matrix
serves as the variance when applied in single-parameter scenarios.
knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A5_1.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A5_2.jpg")

A6.)
The likelihood ratio test involves the subtraction of the log
likelihood estimate of a simpler model (the uniform distribution in this
case) from the log likelihood estimate of a more complex and more
parameterized model (the power distribution in this scenario). This test
is is meant to measure the improvement in fit that the more complex and
unrestricted model provides.
Below shows the formula for what our test statistic, \(\Lambda\) would equal in this instance.
Since \(\ell(1) = 0\), it is relatively
straightforward. When performing a likelihood ratio test, the
distribution of \(\Lambda\) follows a
chi-squared distribution. Again assuming a 95% confidence level, we
would consider any value of \(\Lambda\)
greater than about 3.841 sufficient evidence to suggest there is value
in using the more complex power distribution.
knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A6_1.jpg")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Final/A6_2.jpg")

Part B: Numerical Analysis
# read in data
data = rbind.data.frame(0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22,
0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32,
0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42,
0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52,
0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.78)
colnames(data) = "storage"
The dataset we will analyze consists of 50 recorded usable storage
proportions of a reservoir in a small town, with a value of 0
representing a basically empty reservoir and a value of 1 representing a
full body of water. Summary statistics and a histogram of the data 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$storage)
kable(Summary_Table,align = "c",
caption = "<span style='color:##000000;'>
Summary Stats of Storage Volumes </span>") %>%
kable_styling(
bootstrap_options = c("striped", "bordered"),
full_width = FALSE,
position = "center")
Summary Stats of Storage Volumes
|
Min
|
Q1
|
Med
|
Mean
|
Q3
|
Max
|
|
0.12
|
0.25
|
0.38
|
0.38
|
0.5
|
0.78
|
ggplot(data = data) +
geom_histogram(mapping = aes(x = storage, 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 Storage Volumes",
x = "Storage Volume",
y = "Probabiity Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3)
) # this is the equivalent of box(lwd = 3) in base R

B1.)
Now using the available sample data, and assuming a
Kumaraswamy distribution is applicable in this case, I
will perform MLE to estimate parameters \(a\) and \(b\). Key formulas for such calculation are
the log likelihood and gradient functions seen below.
\[\Large \ell(a,b) = n\ln(a) + n\ln(b) +
\left[ (a-1)\sum \ln(x_i) \right] + \left[ (b-1)\sum\ln(1-x_i^a)
\right]\]
\[\Large \ell_a^\prime(a,b) = \frac{n}{a}
+ \left[ \sum\ln(x_i) \right] - \left[(b-1)\sum\frac{x_i^a \times
\ln(x_i)}{1 - x_i^a} \right]\]
\[\Large \ell_b^\prime(a,b) = \frac{n}{b}
+ \sum\ln(1-x_i^a)\]
## first define log likelihood of Kumaraswamy distribution
log_like_kum = function(parameters, data){
a = parameters[1]
b = parameters[2]
n = length(data)
log_likelihood = n * log(a) +
n * log(b) +
(a-1) * sum(log(data)) +
(b-1) * sum(log(1-data^a))
return(log_likelihood)
}
## gradient functions
gradient_kum = function(parameters, data){
a = parameters[1]
b = parameters[2]
n = length(data)
## partial derivative with respect to a
partial_a = n/a +
sum(log(data)) -
(b-1)*sum((data^a*log(data))/(1-data^a))
## partial derivative with respect to b
partial_b = n/b + sum(log(1-data^a))
return(c(partial_a,
partial_b))
}
## now get an MLE estimate
mle_kum = optim(
par = c(a = 1.5, b = 5),
# tried MANY different starting estimates, continued to adjust based on histogram visual below.
fn = log_like_kum,
gr = gradient_kum,
data = data$storage,
method = "L-BFGS-B",
lower = c(1e-8, 1e-8), # using this method with lower restraints since a and b cannot be negative in a Kumaraswamy distribution
hessian = TRUE,
control = list(trace = FALSE,
fnscale = -1,
maxit = 500,
abstol = 1e-8)
)
mle_kum_a_estimate = mle_kum$par[1] # a
## controls behavior near 0
mle_kum_b_estimate = mle_kum$par[2] # b
## controls behavior approaching 1 / think right tail
Using R’s optim function, and
performing numerous iterations with different starting parameter
estimates of both \(a\) and \(b\), a reasonable estimate for the two
shape parameters are 2.53 and 7.883 respectively. Below is a visual of
our sample data with a Kumaraswamy distribution curve with said
parameter values additionally overlaid.
library(extraDistr) # needed to plot Kumaraswamy distribution curve
## visual confirmation
ggplot(data = data) +
geom_histogram(mapping = aes(x = storage, y = after_stat(density)),
color = "black",
fill = "lightblue",
bins = 10,) +
stat_function(fun = dkumar,
args = list(a = mle_kum_a_estimate, b = mle_kum_b_estimate),
color = "black",
linewidth = 1.5,
xlim = range(0:1))+
labs(title = "Distribution of Storage Volumes",
x = "Storage Volume",
y = "Probabiity Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3)
)

B2.)
Going back to the power distribution, I once again
performed MLE to approximate the value of the power distribution’s sole
parameter, \(a\).
## same procedure as B1, now use power distribution characteristics
log_like_power = function(a, data){
n = length(data)
log_likelihood = n * log(a) +
(a-1)*sum(log(data))
return(log_likelihood)
}
gradient_power = function(a, data){
n = length(data)
partial_a = n/a + sum(log(data))
return(partial_a)
}
mle_power = optim(
par = 2.6, ## maybe change this later
fn = log_like_power,
gr = gradient_power,
data = data$storage,
method = "L-BFGS-B",
lower = c(1e-8, 1e-8),
hessian = TRUE,
control = list(trace = FALSE,
fnscale = -1,
maxit = 500,
abstol = 1e-8)
)
mle_power_a_estimate = mle_power$par
# mean(data$storage) = 0.378 = x bar
# x bar = a / (a+1) [from question A4 MME formula]
# 0.94/1.94 = 0.4845361
After getting an estimate of roughly \(a
\approx 0.939\), I went ahead and once again overlaid what such a
power distribution would look like relative to our available sample
data.
## visual confirmation
# Since R does not have a built-in dpower function, need to manually create one
manual_d_power = function(x, a){
a * x^(a-1) # = pdf of power distribution
}
ggplot(data = data) +
geom_histogram(mapping = aes(x = storage, y = after_stat(density)),
color = "black",
fill = "lightblue",
bins = 10,) +
stat_function(fun = manual_d_power,
args = list(a = mle_power_a_estimate),
color = "black",
linewidth = 1.5,
xlim = range(0:1))+
labs(title = "Distribution of Storage Volumes",
x = "Storage Volume",
y = "Probabiity Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3)
)

Per these visuals, it appears that the Kumaraswamy distribution much
more accurately captures the reality of our broader distribution than
the power distribution does. To quantify this difference, we perform a
likelihood ratio test (LRT).
## if b = 1, then power distribution is applicable
## if b =/ 1, then Kumaraswamy distribution is applicable
# test stat for likelihood ratio test is uppercase Lambda
## evaluate at unrestricted (Kumaraswamy)
log_evaluation_kum = log_like_kum(parameters = c(mle_kum_a_estimate, mle_kum_b_estimate),
data = data$storage)
## evaluate at restricted/simpler (power)
log_evaluation_power = log_like_power(a = mle_power_a_estimate,
data = data$storage)
## the likelihood ratio test is just 2 *
# [log likelihood evaluated in unrestricted way] -
# [log likelihood evaluated in restricted or simple way]
Lambda = 2 * (log_evaluation_kum - log_evaluation_power)
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
The results of the LRT were overwhelmingly in support of the notion
that the paramater \(b\) is
not equal to 1, hence we should approach the broader
population of reservoir storage from the lens of a Kumaraswamy
distribution, rather than a power one. Our statistical results were a
\(\Lambda\) value of about 48.925 and a
p-value approximating 0.
Given the large visual discrepancies in the histograms overlaying the
Kumaraswamy and power distributions, these results are not
surprising.
B3.)
Now continuing with the assumption of a Kumaraswamy
distribution, i.e. both \(a,b\)
equaling any positive value other than exactly one, we return to the
likelihood estimates from section B1; \(a\) = 2.53 and \(b\) = 7.883 respectively.
1.)
To reduce the impact of sample variation, I performed bootstrapping
to obtain a sampling distribution - composed of 500 samples - of both a
and b.
# use the mle_kum function from earlier to obtain an estimate of a and b for each sample
bootstrap_kum_estimates = function(data, b){
n = length(data)
boots_a = numeric(b) # create a vector with b number of "slots" to fill throughout bootstrap process
boots_b = numeric(b)
# START FOR LOOP
for (i in 1:b){
boot_sample = sample(data, size = n, replace = TRUE) # replacement is necessary
# taken from mle_kum function from earlier
# we are getting estimates for the KUMARASWAMY distribution
boot_mle_kum = optim(
par = c(a = 1.5, b = 5),
fn = log_like_kum,
gr = gradient_kum,
data = boot_sample, ## critical change for bootstrap scenario
method = "L-BFGS-B",
lower = c(1e-8, 1e-8),
hessian = TRUE,
control = list(trace = FALSE,
fnscale = -1,
maxit = 500,
abstol = 1e-8)
)
## now store results for each parameter
boots_a[i] = boot_mle_kum$par[1]
boots_b[i] = boot_mle_kum$par[2]
} # END FOR LOOP
## now output our parameter estimates; will sort and put them as a dataframe for easier interpretation
boot_a_estimates = sort(boots_a)
boot_b_estimates = sort(boots_b)
boot_a_estimates = cbind.data.frame(boot_a_estimates)
boot_b_estimates = cbind.data.frame(boot_b_estimates)
return(list(boot_a_estimates,
boot_b_estimates))
} # END FUNCTION
set.seed(100)
# now run function, using 500 bootstrap samples
boot_sampling_dist = bootstrap_kum_estimates(data = data$storage, b = 500)
boot_a_estimates = boot_sampling_dist[[1]] # a hat distribution
colnames(boot_a_estimates) = "a"
boot_b_estimates = boot_sampling_dist[[2]] # b hat distribution
colnames(boot_b_estimates) = "b"
The results of this bootstrapping sequence resulted in average
estimates of parameters a and b of about 2.63 and 9.057 (not far from
our original estimate of 2.53 and 7.883).
Below are visuals of each parameter’s sampling distribution from the
bootstrapping sequence, with a Gaussian density
curve layered atop. Bandwidths for each density curve were chosen
in accordance with Silverman’s standard formula.
## use custom function to find Gaussian bandwidth values for each sampling distribution
gaussian_bw = function(data){
min_part = min(sd(data),(IQR(data)/1.34))
bw = 0.9 * min_part * (length(data)^(-0.2))
return(bw)
}
#gaussian_bw(boot_a_estimates$a) = 0.08314841
#gaussian_bw(boot_b_estimates$b) = 0.6875727
## plot a hat estimates first
ggplot(data = boot_a_estimates) +
geom_histogram(mapping = aes(x = a, y = after_stat(density)),
color = "black",
fill = "lightblue",
bins = 10,) +
## the geom_density function in ggplot by default uses Gaussian estimation
geom_density(
aes(x = a),
color = "red",
linewidth = 2,
bw = gaussian_bw(boot_a_estimates$a)
) +
labs(title = "Distribution of A Hat Estimates",
x = "A Hat",
y = "Probabiity Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3)
)

## now plot b hat estimates
ggplot(data = boot_b_estimates) +
geom_histogram(mapping = aes(x = b, y = after_stat(density)),
color = "black",
fill = "lightblue",
bins = 10,) +
geom_density(
aes(x = b),
color = "red",
linewidth = 2,
bw = gaussian_bw(boot_b_estimates$b)
) +
labs(title = "Distribution of B Hat Estimates",
x = "B Hat",
y = "Probabiity Density") +
theme(
panel.border = element_rect(color = "black", fill = NA, linewidth = 3)
)

2.)
Looking deeper into the \(b\)
parameter for the Kumaraswamy distribution, I constructed a bootstrap
confidence interval for its value.
## bootstrap CI
ci_percentile = function(data, b, alpha){
n = length(data)
boots_a = numeric(b) # create a vector with b number of "slots" to fill throughout bootstrap process
boots_b = numeric(b)
### code taken from B3 Question 1
# START FOR LOOP
for (i in 1:b){
boot_sample = sample(data, size = n, replace = TRUE) # replacement is necessary
# taken from mle_kum function from earlier
# we are getting estimates for the KUMARASWAMY distribution
boot_mle_kum = optim(
par = c(a = 1.5, b = 5),
fn = log_like_kum,
gr = gradient_kum,
data = boot_sample, ## critical change for bootstrap scenario
method = "L-BFGS-B",
lower = c(1e-8, 1e-8),
hessian = TRUE,
control = list(trace = FALSE,
fnscale = -1,
maxit = 500,
abstol = 1e-8)
)
## now store results for each parameter
boots_a[i] = boot_mle_kum$par[1] # not necessary for output in this scenario but will keep for now
boots_b[i] = boot_mle_kum$par[2]
} # END FOR LOOP
## now do CI calculation
boots_b = sort(boots_b)
lower_quant = (alpha/2)
higher_quant = (1-(alpha/2))
lower_estimate = quantile(boots_b, lower_quant)
higher_estimate = quantile(boots_b, higher_quant)
# now put together in a table for output
results = rbind(lower_estimate,
higher_estimate)
colnames(results) = "b_hat"
rownames(results) = c("Lower Estimate", "Higher Estimate")
return(results)
}
set.seed(100)
boot_ci = ci_percentile(data = data$storage, b = 500, alpha = 0.05)
With a 500-iteration bootstrap sequence and confidence level of about
95%, we can assert that the true value of the parameter \(b\) is approximately somewhere between
5.191 and 16.676. Knowing our initial, MLE-based, estimate for the
parameter was roughly 7.883, and the Kumaraswamy distribution is
right-skewed, these results seem plausible.
After performing the bootstrap sequence, I then constructed a Wald
confidence interval, which is predicated on a parameter’s point
estimate, critical value and standard error.
## Wald CI
# Wald formula = estimate +- z score * standard error
# estimate = mle_kum_b_estimate ~ 7.88
wald_z = 1.96
# let I denote Fisher matrix
I = -mle_kum$hessian
wald_se = sqrt(diag(solve(I))) # b ~ 2.245
# if we invert and solve the Fisher matrix, then square root the diagonals, we will get estimates of each parameter's standard error
wald_se_b = wald_se[2] # what we need right now
wald_lower_est = mle_kum_b_estimate - wald_z * wald_se_b
wald_higher_est = mle_kum_b_estimate + wald_z * wald_se_b
Our standard error for the estimate of \(b\) was derived from the Fisher matrix of
\(a\) and \(b\) which was created in R’s optim function previously.
As per Wald’s interval, we can say with about 95% certainty that the
true value of b resides between 3.484 and 12.283.
3.)
Although the Wald interval provides a more conservative estimate for
\(b\) than the bootstrap interval does,
it is still reasonably close enough to not rule out and keep in
consideration for population estimation purposes. With an original point
estimate for \(b\) of 7.883, that
estimate falls roughly in the middle of our Wald interval.
Alternatively, our bootstrap confidence interval (as we can see in our
histogram in section B3 Q1) more accurately recognizes the rightward
skew that the Kumaraswamy distribution typically carries.
B4.)
Finally, I complete another LRT to determine if there is significant
loss in accuracy when examining our broader population via a uniform
distribution lens rather than a Kumaraswamy one, using the available
sample data as a “benchmark” of such.
# if (a,b) = 1, then uniform distribution is applicable
# if at least one of a or b =/ 1, then distribution is not uniform
log_evaluation_uniform = log_like_kum(parameters = c(1,1), # a and b = 1 of a Kum distribution, that is same as uniform distribution
data = data$storage)
Lambda_B4 = 2 * (log_evaluation_kum - log_evaluation_uniform)
p_value_B4 = 1 - pchisq(Lambda_B4, df = 2)
# now estimating 2 parameters so df = 2
Unsurprisingly, the LRT results found that there is sufficient reason
to believe that the broader population of reservoir storage is
not uniformly distributed, sporting a test statistic of
about 49.125 and a p-value approaching zero. Given the estimates for
\(a\) and \(b\) throughout this analysis as well as
visualizations of the data, these findings align with what we have
observed so far.
LS0tCnRpdGxlOiAiU1RBIDUwNiBGaW5hbCBFeGFtOiBFc3RpbWF0aW9uIHcvIEt1bWFyYXN3YW15IERpc3RyaWJ1dGlvbiIKYXV0aG9yOiAiQ2hyaXMgQmFobSIKZGF0ZTogIk1heSA1LCAyMDI2IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfd2lkdGg6IDYKICAgIGZpZ19oZWlnaHQ6IDQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgc2VsZl9jb250YWluZWQ6IGZhbHNlCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKLS0tCgpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9CmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47CiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7CiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOwogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOwp9CgpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLwogIGZvbnQtc2l6ZTogMjRweDsKICBmb250LXdlaWdodDogYm9sZDsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogIGNvbG9yOiBEYXJrUmVkOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogIGNvbG9yOiBEYXJrQmx1ZTsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgxIHsgLyogSGVhZGVyIDEgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMjBweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogZGFya3JlZDsKICAgIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogICAgZm9udC1zaXplOiAxOHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogICAgZm9udC1zaXplOiAxNnB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogICAgZm9udC1zaXplOiAxNHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogZGFya3JlZDsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgewogIGNvbnRlbnQ6ICIuIjsKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLgoKaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7ICAgICAgICAgICAgICAgICAgICAgICMgdXNlIGNvbmRpdGlvbmFsIHN0YXRlbWVudCB0byBkZXRlY3QKICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKSAgICAgICAgICAgICAgICAgICMgd2hldGhlciBhIHBhY2thZ2Ugd2FzIGluc3RhbGxlZCBpbgogICBsaWJyYXJ5KGtuaXRyKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3VyIG1hY2hpbmUuIElmIG5vdCwgaW5zdGFsbCBpdCBhbmQKfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbG9hZCBpdCB0byB0aGUgd29ya2luZyBkaXJlY3RvcnkuCgppZiAoIXJlcXVpcmUodGlkeXZlcnNlKSkge2xpYnJhcnkodGlkeXZzZXJzZSl9IAoKaWYgKCFyZXF1aXJlKEdHYWxseSkpIHtsaWJyYXJ5KEdHYWxseSl9IAoKaWYgKCFyZXF1aXJlKGthYmxlRXh0cmEpKSB7bGlicmFyeShrYWJsZUV4dHJhKX0gCgppZiAoIXJlcXVpcmUoZ2dwbG90MikpIHtsaWJyYXJ5KGdncGxvdDIpfSAKCmlmICghcmVxdWlyZShjYXIpKSB7bGlicmFyeShjYXIpfSAKCmlmICghcmVxdWlyZShkcGx5cikpIHtsaWJyYXJ5KGRwbHlyKX0gCgppZiAoIXJlcXVpcmUocGFuZGVyKSkge2xpYnJhcnkocGFuZGVyKX0gCgppZiAoIXJlcXVpcmUoZm9yZWNhc3QpKSB7bGlicmFyeShmb3JlY2FzdCl9IAoKaWYgKCFyZXF1aXJlKGx1YnJpZGF0ZSkpIHtsaWJyYXJ5KGx1YnJpZGF0ZSl9IAoKaWYgKCFyZXF1aXJlKCJzY2FsZXMiKSkgewppbnN0YWxsLnBhY2thZ2VzKCJzY2FsZXMiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKbGlicmFyeSgic2NhbGVzIikgCn0KCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFLAoJY29tbWVudCA9IE5BLAoJcmVzdWx0cyA9IFRSVUUsCglmaWcuYWxpZ24gPSAiY2VudGVyIgopCmBgYAoKIyBJbnRybyBhbmQgU2V0dXAKRm9yIHRoaXMgZXhhbSwgd2Ugd2lsbCBiZSBleGFtaW5pbmcgYW5kIHV0aWxpemluZyB0aGUgKipLdW1hcmFzd2FteSBkaXN0cmlidXRpb24qKi4gVGhpcyBkaXN0cmlidXRpb24gaXMgY29udGludW91cywgYm91bmRlZCBiZXR3ZWVuIDAgYW5kIDEsIGFuZCBkZWZpbmVkIGJ5IHR3byBwYXJhbWV0ZXJzICgkYSQgYW5kICRiJCkuCgpXaXRoICRYJCBkZW5vdGluZyBhIEt1bWFyYXN3YW15IHJhbmRvbSB2YXJpYWJsZSwgdGhlIENERiBvZiBvdXIgZGlzdHJpYnV0aW9uIGlzIHRoZSBmb2xsb3dpbmcuCgokJFxMYXJnZSBGKHg7IGEsYikgPSAxIC0gKDEteF5hKV5iICQkCgpUd28gc3BlY2lhbCBjYXNlcyBvZiB0aGUgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIGFyZSB0aGUgdW5pZm9ybSBhbmQgcG93ZXIgZGlzdHJpYnV0aW9ucy4gQSBkaXN0cmlidXRpb24gaXMgdW5pZm9ybSBpZiAkYSwgYiQgPSAxLCB3aGlsZSBzdWNoIGlzIHBvd2VyIGlmICRhID4gMCwgYiA9IDEkLgoKPGJyPgoKIyBQYXJ0IEE6IE1ldGhvZG9sb2dpY2FsIERlcml2YXRpb25zCgojIyBBMS4pCkdpdmVuIHRoZSBkaXN0cmlidXRpb24ncyBjdW11bGF0aXZlIGZ1bmN0aW9uLCB3ZSBjYW4gdXNlIGNhbGN1bHVzLWJhc2VkIG1ldGhvZHMgdG8gZGVyaXZlIHRoZSBwcm9iYWJpbGl0eSBkZW5zaXR5IGZ1bmN0aW9uIChQREYpLiBTYWlkIGNhbGN1bGF0aW9ucyB3ZXJlIGNvbXBsZXRlZCBieSBoYW5kIGFuZCBjYW4gYmUgc2VlbiBiZWxvdy4KCmBgYHtyLCBvdXQud2lkdGg9IjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvY2hyaXNiYWhtL0xpYnJhcnkvTW9iaWxlIERvY3VtZW50cy9jb21+YXBwbGV+Q2xvdWREb2NzL1dlc3QgQ2hlc3Rlci9TcHJpbmcgMjAyNi9TVEEgNTA2IC0gR3JhZCBNYXRoIFN0YXQgMiAvU1RBIDUwNiBSIEZvbGRlci9GaW5hbC9BMS5qcGciKQpgYGAKCk1vdmluZyBmb3J3YXJkLCB3ZSBkZWZpbmUgb3VyIGRlbnNpdHkgZnVuY3Rpb24gYXMgdGhlIGZvbGxvd2luZy4KJCRcTGFyZ2UgIGYoeDsgYSwgYikgPSBhYiBcLCB4XnthLTF9ICgxIC0geF5hKV57Yi0xfSQkCgojIyBBMi4pIApOb3cgaGF2aW5nIG91ciBkaXN0cmlidXRpb24ncyBkZW5zaXR5IGZ1bmN0aW9uLCB3ZSBjYW4gZGVub3RlIG91ciBsb2ctbGlrZWxpaG9vZCwgJFxlbGwoYSxiKSQsIGZ1bmN0aW9uIGFuZCBzdWJzZXF1ZW50IGdyYWRpZW50IHZlY3Rvci4gVGhlIGdyYWRpZW50IHZlY3RvciBpcyBtYWRlIHVwIG9mIHRoZSBwYXJ0aWFsIGRlcml2YXRpdmVzIG9mIHRoZSBsb2ctbGlrZWxpaG9vZCBmdW5jdGlvbiwgZmlyc3Qgd2l0aCByZXNwZWN0IHRvICRhJCB0aGVuIHdpdGggcmVzcGVjdCB0byAkYiQuIEJlbG93IGFyZSBjYWxjdWxhdGlvbnMgYW5kIHVsdGltYXRlIHJlc3VsdHMuCgpgYGB7ciwgb3V0LndpZHRoPSI1MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL2NocmlzYmFobS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9XZXN0IENoZXN0ZXIvU3ByaW5nIDIwMjYvU1RBIDUwNiAtIEdyYWQgTWF0aCBTdGF0IDIgL1NUQSA1MDYgUiBGb2xkZXIvRmluYWwvQTJfMS5qcGciKQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9jaHJpc2JhaG0vTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvV2VzdCBDaGVzdGVyL1NwcmluZyAyMDI2L1NUQSA1MDYgLSBHcmFkIE1hdGggU3RhdCAyIC9TVEEgNTA2IFIgRm9sZGVyL0ZpbmFsL0EyXzIuanBnIikKCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvY2hyaXNiYWhtL0xpYnJhcnkvTW9iaWxlIERvY3VtZW50cy9jb21+YXBwbGV+Q2xvdWREb2NzL1dlc3QgQ2hlc3Rlci9TcHJpbmcgMjAyNi9TVEEgNTA2IC0gR3JhZCBNYXRoIFN0YXQgMiAvU1RBIDUwNiBSIEZvbGRlci9GaW5hbC9BMl8zLmpwZyIpCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL2NocmlzYmFobS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9XZXN0IENoZXN0ZXIvU3ByaW5nIDIwMjYvU1RBIDUwNiAtIEdyYWQgTWF0aCBTdGF0IDIgL1NUQSA1MDYgUiBGb2xkZXIvRmluYWwvQTJfNC5qcGciKQpgYGAKCgokJFxMYXJnZSBcZWxsKGEsYikgPSBuXGxuKGEpICsgblxsbihiKSArIFxsZWZ0WyAoYS0xKVxzdW0gXGxuKHhfaSkgXHJpZ2h0XSArIFxsZWZ0WyAoYi0xKVxzdW1cbG4oMS14X2leYSkgXHJpZ2h0XSQkCgokJFxMYXJnZSBcZWxsX2FeXHByaW1lKGEsYikgPSBcZnJhY3tufXthfSArIFxsZWZ0WyBcc3VtXGxuKHhfaSkgXHJpZ2h0XSAtIFxsZWZ0WyhiLTEpXHN1bVxmcmFje3hfaV5hIFx0aW1lcyBcbG4oeF9pKX17MSAtIHhfaV5hfSBccmlnaHRdJCQKCiQkXExhcmdlIFxlbGxfYl5ccHJpbWUoYSxiKSA9IFxmcmFje259e2J9ICsgXHN1bVxsbigxLXhfaV5hKSQkCgoKIyMgQTMuKSAKVGhlbiB0YWtpbmcgdGhlIGdyYWRpZW50IHZlY3RvciBjb21wb25lbnRzLCBJIHdhcyBhYmxlIHRvIGNhbGN1bGF0ZSB0aGUgRmlzaGVyIGluZm9ybWF0aW9uIG1hdHJpeCAoJEkkKSwgd2hpY2ggaXMgc2ltcGx5IHRoZSBuZWdhdGl2ZSBvZiB0aGUgSGVzc2lhbiBtYXRyaXggKGNvbXBvc2VkIG9mIGFsbCBzZWNvbmQtZGVyaXZhdGl2ZSBleHRlbnNpb25zIG9mIHRoYXQgZGlzdHJpYnV0aW9uJ3MgbG9nLWxpa2VsaWhvb2QpLiBUaGUgRmlzaGVyIEluZm9ybWF0aW9uIG1hdHJpeCBmb3IgdGhlIEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiBpcyBiZWxvdy4KCmBgYHtyLCBvdXQud2lkdGg9IjUwJSIsIG91dC5oZWlnaHQ9IjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvY2hyaXNiYWhtL0xpYnJhcnkvTW9iaWxlIERvY3VtZW50cy9jb21+YXBwbGV+Q2xvdWREb2NzL1dlc3QgQ2hlc3Rlci9TcHJpbmcgMjAyNi9TVEEgNTA2IC0gR3JhZCBNYXRoIFN0YXQgMiAvU1RBIDUwNiBSIEZvbGRlci9GaW5hbC9BM18xLmpwZyIpCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL2NocmlzYmFobS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9XZXN0IENoZXN0ZXIvU3ByaW5nIDIwMjYvU1RBIDUwNiAtIEdyYWQgTWF0aCBTdGF0IDIgL1NUQSA1MDYgUiBGb2xkZXIvRmluYWwvQTNfMi5qcGciKQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9jaHJpc2JhaG0vTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvV2VzdCBDaGVzdGVyL1NwcmluZyAyMDI2L1NUQSA1MDYgLSBHcmFkIE1hdGggU3RhdCAyIC9TVEEgNTA2IFIgRm9sZGVyL0ZpbmFsL0EzXzMuanBnIikKYGBgCgojIyBBNC4pCldlIG5vdyBjb25zaWRlciB0aGUgKipwb3dlcioqIGRpc3RyaWJ1dGlvbiwgYSBzcGVjaWFsIGFuZCBtb3JlIHNpbXBsaXN0aWMgY2FzZSBvZiB0aGUgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uLCB3aGljaCBvY2N1cnMgd2hlbiB0aGUgcGFyYW1ldGVyICRiJCA9IDEuIEdpdmVuIHRoZSBLdW1hcmFzd2FteSBmb3JtdWxhLCBhIHZhbHVlIG9mICRiJCA9IDEgbWVhbnMgdGhhdCB0aGUgcmVsYXRpdmUgZGVuc2l0eSBmdW5jdGlvbiBvZiB0aGUgcG93ZXIgZGlzdHJpYnV0aW9uIGlzICRheF57YS0xfSQuIEtub3dpbmcgdGhpcywgYmVsb3cgYXJlIGZvcm11bGFzIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGVzdGltYXRlIHRoZSBwYXJhbWV0ZXIgJGEkIHZpYSBtb21lbnQgb3IgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRpb24gKE1PTSBvciBNTEUpLgoKYGBge3IsIG91dC53aWR0aD0iNTAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9jaHJpc2JhaG0vTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvV2VzdCBDaGVzdGVyL1NwcmluZyAyMDI2L1NUQSA1MDYgLSBHcmFkIE1hdGggU3RhdCAyIC9TVEEgNTA2IFIgRm9sZGVyL0ZpbmFsL0E0XzEuanBnIikKCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvY2hyaXNiYWhtL0xpYnJhcnkvTW9iaWxlIERvY3VtZW50cy9jb21+YXBwbGV+Q2xvdWREb2NzL1dlc3QgQ2hlc3Rlci9TcHJpbmcgMjAyNi9TVEEgNTA2IC0gR3JhZCBNYXRoIFN0YXQgMiAvU1RBIDUwNiBSIEZvbGRlci9GaW5hbC9BNF8yLmpwZyIpCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL2NocmlzYmFobS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9XZXN0IENoZXN0ZXIvU3ByaW5nIDIwMjYvU1RBIDUwNiAtIEdyYWQgTWF0aCBTdGF0IDIgL1NUQSA1MDYgUiBGb2xkZXIvRmluYWwvQTRfMy5qcGciKQpgYGAKCgojIyBBNS4pCkdpdmVuIGFuIGVzdGltYXRlIG9mIG91ciBwYXJhbWV0ZXIgJGEkLCAoJFxoYXR7YX0kKSwgd2UgY2FuIHNldHVwIGEgZ2VuZXJhbCBjb25maWRlbmNlIGludGVydmFsIChDSSkgZm9ybXVsYSBmb3IgdGhlIHZhbHVlIG9mICRhJC4gQXNzdW1pbmcgOTUlIGNvbmZpZGVuY2UsIHRoZXJlZm9yZSBhIGNyaXRpY2FsIHZhbHVlIG9mIDEuOTYgcHJlZGljYXRlZCBvbiB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgdGhlIG1ha2V1cCBvZiB0aGUgQ0kgd291bGQgbG9vayBsaWtlIHRoZSBmb2xsb3dpbmcuIAoKVGhlIHZhcmlhbmNlIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGludGVydmFsIHdlcmUgZm91bmQgZnJvbSB0aGUgcG93ZXIgZGlzdHJpYnV0aW9uJ3MgaW5mb3JtYXRpb24gbWF0cml4LiBUaGUgaW52ZXJzZSBvZiBzdWNoIG1hdHJpeCBzZXJ2ZXMgYXMgdGhlIHZhcmlhbmNlIHdoZW4gYXBwbGllZCBpbiBzaW5nbGUtcGFyYW1ldGVyIHNjZW5hcmlvcy4KCmBgYHtyLCBvdXQud2lkdGg9IjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvY2hyaXNiYWhtL0xpYnJhcnkvTW9iaWxlIERvY3VtZW50cy9jb21+YXBwbGV+Q2xvdWREb2NzL1dlc3QgQ2hlc3Rlci9TcHJpbmcgMjAyNi9TVEEgNTA2IC0gR3JhZCBNYXRoIFN0YXQgMiAvU1RBIDUwNiBSIEZvbGRlci9GaW5hbC9BNV8xLmpwZyIpCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL2NocmlzYmFobS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9XZXN0IENoZXN0ZXIvU3ByaW5nIDIwMjYvU1RBIDUwNiAtIEdyYWQgTWF0aCBTdGF0IDIgL1NUQSA1MDYgUiBGb2xkZXIvRmluYWwvQTVfMi5qcGciKQpgYGAKCiMjIEE2LikKVGhlIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBpbnZvbHZlcyB0aGUgc3VidHJhY3Rpb24gb2YgdGhlIGxvZyBsaWtlbGlob29kIGVzdGltYXRlIG9mIGEgc2ltcGxlciBtb2RlbCAodGhlIHVuaWZvcm0gZGlzdHJpYnV0aW9uIGluIHRoaXMgY2FzZSkgZnJvbSB0aGUgbG9nIGxpa2VsaWhvb2QgZXN0aW1hdGUgb2YgYSBtb3JlIGNvbXBsZXggYW5kIG1vcmUgcGFyYW1ldGVyaXplZCBtb2RlbCAodGhlIHBvd2VyIGRpc3RyaWJ1dGlvbiBpbiB0aGlzIHNjZW5hcmlvKS4gVGhpcyB0ZXN0IGlzIGlzIG1lYW50IHRvIG1lYXN1cmUgdGhlIGltcHJvdmVtZW50IGluIGZpdCB0aGF0IHRoZSBtb3JlIGNvbXBsZXggYW5kIHVucmVzdHJpY3RlZCBtb2RlbCBwcm92aWRlcy4gCgpCZWxvdyBzaG93cyB0aGUgZm9ybXVsYSBmb3Igd2hhdCBvdXIgdGVzdCBzdGF0aXN0aWMsICRcTGFtYmRhJCB3b3VsZCBlcXVhbCBpbiB0aGlzIGluc3RhbmNlLiBTaW5jZSAkXGVsbCgxKSA9IDAkLCBpdCBpcyByZWxhdGl2ZWx5IHN0cmFpZ2h0Zm9yd2FyZC4gV2hlbiBwZXJmb3JtaW5nIGEgbGlrZWxpaG9vZCByYXRpbyB0ZXN0LCB0aGUgZGlzdHJpYnV0aW9uIG9mICRcTGFtYmRhJCBmb2xsb3dzIGEgY2hpLXNxdWFyZWQgZGlzdHJpYnV0aW9uLiBBZ2FpbiBhc3N1bWluZyBhIDk1JSBjb25maWRlbmNlIGxldmVsLCB3ZSB3b3VsZCBjb25zaWRlciBhbnkgdmFsdWUgb2YgJFxMYW1iZGEkIGdyZWF0ZXIgdGhhbiBhYm91dCAzLjg0MSBzdWZmaWNpZW50IGV2aWRlbmNlIHRvIHN1Z2dlc3QgdGhlcmUgaXMgdmFsdWUgaW4gdXNpbmcgdGhlIG1vcmUgY29tcGxleCBwb3dlciBkaXN0cmlidXRpb24uCgpgYGB7ciwgb3V0LndpZHRoPSI1MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL2NocmlzYmFobS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9XZXN0IENoZXN0ZXIvU3ByaW5nIDIwMjYvU1RBIDUwNiAtIEdyYWQgTWF0aCBTdGF0IDIgL1NUQSA1MDYgUiBGb2xkZXIvRmluYWwvQTZfMS5qcGciKQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9jaHJpc2JhaG0vTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvV2VzdCBDaGVzdGVyL1NwcmluZyAyMDI2L1NUQSA1MDYgLSBHcmFkIE1hdGggU3RhdCAyIC9TVEEgNTA2IFIgRm9sZGVyL0ZpbmFsL0E2XzIuanBnIikKYGBgCgo8YnI+CgojIFBhcnQgQjogTnVtZXJpY2FsIEFuYWx5c2lzCgpgYGB7cn0KIyByZWFkIGluIGRhdGEKZGF0YSA9IHJiaW5kLmRhdGEuZnJhbWUoMC4xMiwgMC4xNCwgMC4xNSwgMC4xNiwgMC4xNywgMC4xOCwgMC4xOSwgMC4yMCwgMC4yMSwgMC4yMiwKMC4yMywgMC4yNCwgMC4yNSwgMC4yNiwgMC4yNywgMC4yOCwgMC4yOSwgMC4zMCwgMC4zMSwgMC4zMiwKMC4zMywgMC4zNCwgMC4zNSwgMC4zNiwgMC4zNywgMC4zOCwgMC4zOSwgMC40MCwgMC40MSwgMC40MiwKMC40MywgMC40NCwgMC40NSwgMC40NiwgMC40NywgMC40OCwgMC40OSwgMC41MCwgMC41MSwgMC41MiwKMC41MywgMC41NCwgMC41NSwgMC41NiwgMC41NywgMC41OCwgMC41OSwgMC42MCwgMC42MSwgMC43OCkKY29sbmFtZXMoZGF0YSkgPSAic3RvcmFnZSIKYGBgClRoZSBkYXRhc2V0IHdlIHdpbGwgYW5hbHl6ZSBjb25zaXN0cyBvZiBgciBucm93KGRhdGEpYCByZWNvcmRlZCB1c2FibGUgc3RvcmFnZSBwcm9wb3J0aW9ucyBvZiBhIHJlc2Vydm9pciBpbiBhIHNtYWxsIHRvd24sIHdpdGggYSB2YWx1ZSBvZiAwIHJlcHJlc2VudGluZyBhIGJhc2ljYWxseSBlbXB0eSByZXNlcnZvaXIgYW5kIGEgdmFsdWUgb2YgMSByZXByZXNlbnRpbmcgYSBmdWxsIGJvZHkgb2Ygd2F0ZXIuIFN1bW1hcnkgc3RhdGlzdGljcyBhbmQgYSBoaXN0b2dyYW0gb2YgdGhlIGRhdGEgYXJlIGJlbG93LgoKYGBge3J9CnN1bV9zdGF0c190YWJsZSA9IGZ1bmN0aW9uKHZhcmlhYmxlKXsKICB0YWJsZSA9IGNiaW5kKAogICAgcm91bmQobWluKHZhcmlhYmxlKSwyKSwKICAgIHJvdW5kKHF1YW50aWxlKHZhcmlhYmxlLCAwLjI1KSwyKSwKICAgIHJvdW5kKG1lZGlhbih2YXJpYWJsZSksMiksCiAgICByb3VuZChtZWFuKHZhcmlhYmxlKSwyKSwKICAgIHJvdW5kKHF1YW50aWxlKHZhcmlhYmxlLCAwLjc1KSwyKSwKICAgIHJvdW5kKG1heCh2YXJpYWJsZSksMikKICApCiAgY29sbmFtZXModGFibGUpID0gYygiTWluIiwgIlExIiwgIk1lZCIsICJNZWFuIiwgIlEzIiwgIk1heCIpCiAgcm93bmFtZXModGFibGUpID0gTlVMTAogIHJldHVybih0YWJsZSkKfQoKU3VtbWFyeV9UYWJsZSA9IHN1bV9zdGF0c190YWJsZSh2YXJpYWJsZSA9IGRhdGEkc3RvcmFnZSkKa2FibGUoU3VtbWFyeV9UYWJsZSxhbGlnbiA9ICJjIiwKICAgICAgY2FwdGlvbiA9ICI8c3BhbiBzdHlsZT0nY29sb3I6IyMwMDAwMDA7Jz4KICAgICAgU3VtbWFyeSBTdGF0cyBvZiBTdG9yYWdlIFZvbHVtZXMgPC9zcGFuPiIpICU+JQogIGthYmxlX3N0eWxpbmcoCiAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiYm9yZGVyZWQiKSwKICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwKICAgIHBvc2l0aW9uID0gImNlbnRlciIpCgpnZ3Bsb3QoZGF0YSA9IGRhdGEpICsKICBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKHggPSBzdG9yYWdlLCB5ID0gYWZ0ZXJfc3RhdChkZW5zaXR5KSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgICAjIGFyZ3VtZW50IGNvbG9yIGluIGdlb21faGlzdG9ncmFtIGlzIGZvciBjb2xvciBvZiBiaW4gbGluZXMKICAgICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Ymx1ZSIsCiAgICAgICAgICAgICAgICAgYmlucyA9IDEwLCkgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFN0b3JhZ2UgVm9sdW1lcyIsCiAgICAgICB4ID0gIlN0b3JhZ2UgVm9sdW1lIiwKICAgICAgIHkgPSAiUHJvYmFiaWl0eSBEZW5zaXR5IikgKyAKICB0aGVtZSgKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgbGluZXdpZHRoID0gMykKICApICMgdGhpcyBpcyB0aGUgZXF1aXZhbGVudCBvZiBib3gobHdkID0gMykgaW4gYmFzZSBSCmBgYAoKIyMgQjEuKQpOb3cgdXNpbmcgdGhlIGF2YWlsYWJsZSBzYW1wbGUgZGF0YSwgYW5kIGFzc3VtaW5nIGEgKipLdW1hcmFzd2FteSBkaXN0cmlidXRpb24qKiBpcyBhcHBsaWNhYmxlIGluIHRoaXMgY2FzZSwgSSB3aWxsIHBlcmZvcm0gTUxFIHRvIGVzdGltYXRlIHBhcmFtZXRlcnMgJGEkIGFuZCAkYiQuIEtleSBmb3JtdWxhcyBmb3Igc3VjaCBjYWxjdWxhdGlvbiBhcmUgdGhlIGxvZyBsaWtlbGlob29kIGFuZCBncmFkaWVudCBmdW5jdGlvbnMgc2VlbiBiZWxvdy4KCiQkXExhcmdlIFxlbGwoYSxiKSA9IG5cbG4oYSkgKyBuXGxuKGIpICsgXGxlZnRbIChhLTEpXHN1bSBcbG4oeF9pKSBccmlnaHRdICsgXGxlZnRbIChiLTEpXHN1bVxsbigxLXhfaV5hKSBccmlnaHRdJCQKCiQkXExhcmdlIFxlbGxfYV5ccHJpbWUoYSxiKSA9IFxmcmFje259e2F9ICsgXGxlZnRbIFxzdW1cbG4oeF9pKSBccmlnaHRdIC0gXGxlZnRbKGItMSlcc3VtXGZyYWN7eF9pXmEgXHRpbWVzIFxsbih4X2kpfXsxIC0geF9pXmF9IFxyaWdodF0kJAoKJCRcTGFyZ2UgXGVsbF9iXlxwcmltZShhLGIpID0gXGZyYWN7bn17Yn0gKyBcc3VtXGxuKDEteF9pXmEpJCQKCmBgYHtyfQojIyBmaXJzdCBkZWZpbmUgbG9nIGxpa2VsaWhvb2Qgb2YgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uCmxvZ19saWtlX2t1bSA9IGZ1bmN0aW9uKHBhcmFtZXRlcnMsIGRhdGEpewogICAgYSA9IHBhcmFtZXRlcnNbMV0KICAgIGIgPSBwYXJhbWV0ZXJzWzJdCiAgICBuID0gbGVuZ3RoKGRhdGEpCiAgICAKICAgIGxvZ19saWtlbGlob29kID0gbiAqIGxvZyhhKSArIAogICAgICAgIG4gKiBsb2coYikgKyAKICAgICAgICAoYS0xKSAqIHN1bShsb2coZGF0YSkpICsgCiAgICAgICAgKGItMSkgKiBzdW0obG9nKDEtZGF0YV5hKSkKICAgIHJldHVybihsb2dfbGlrZWxpaG9vZCkKICAgIH0KCiMjIGdyYWRpZW50IGZ1bmN0aW9ucwpncmFkaWVudF9rdW0gPSBmdW5jdGlvbihwYXJhbWV0ZXJzLCBkYXRhKXsKICAgIGEgPSBwYXJhbWV0ZXJzWzFdCiAgICBiID0gcGFyYW1ldGVyc1syXQogICAgbiA9IGxlbmd0aChkYXRhKQogICAgCiAgICAjIyBwYXJ0aWFsIGRlcml2YXRpdmUgd2l0aCByZXNwZWN0IHRvIGEKICAgIHBhcnRpYWxfYSA9IG4vYSArCiAgICAgIHN1bShsb2coZGF0YSkpIC0KICAgICAgKGItMSkqc3VtKChkYXRhXmEqbG9nKGRhdGEpKS8oMS1kYXRhXmEpKQogICAgCiAgICAjIyBwYXJ0aWFsIGRlcml2YXRpdmUgd2l0aCByZXNwZWN0IHRvIGIgCiAgICBwYXJ0aWFsX2IgPSBuL2IgKyBzdW0obG9nKDEtZGF0YV5hKSkKICAgIAogICAgcmV0dXJuKGMocGFydGlhbF9hLAogICAgICAgICAgICAgcGFydGlhbF9iKSkKICAKICAgIH0KCiMjIG5vdyBnZXQgYW4gTUxFIGVzdGltYXRlCm1sZV9rdW0gPSBvcHRpbSgKICAgIHBhciA9IGMoYSA9IDEuNSwgYiA9IDUpLAogICAgICAjIHRyaWVkIE1BTlkgZGlmZmVyZW50IHN0YXJ0aW5nIGVzdGltYXRlcywgY29udGludWVkIHRvIGFkanVzdCBiYXNlZCBvbiBoaXN0b2dyYW0gdmlzdWFsIGJlbG93LgogICAgZm4gPSBsb2dfbGlrZV9rdW0sCiAgICBnciA9IGdyYWRpZW50X2t1bSwKICAgIGRhdGEgPSBkYXRhJHN0b3JhZ2UsCiAgICBtZXRob2QgPSAiTC1CRkdTLUIiLAogICAgICBsb3dlciA9IGMoMWUtOCwgMWUtOCksICMgdXNpbmcgdGhpcyBtZXRob2Qgd2l0aCBsb3dlciByZXN0cmFpbnRzIHNpbmNlIGEgYW5kIGIgY2Fubm90IGJlIG5lZ2F0aXZlIGluIGEgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uCiAgICBoZXNzaWFuID0gVFJVRSwKICAgIGNvbnRyb2wgPSBsaXN0KHRyYWNlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICBmbnNjYWxlID0gLTEsCiAgICAgICAgICAgICAgICAgICBtYXhpdCA9IDUwMCwKICAgICAgICAgICAgICAgICAgIGFic3RvbCA9IDFlLTgpCiAgICApCgptbGVfa3VtX2FfZXN0aW1hdGUgPSBtbGVfa3VtJHBhclsxXSAjIGEKICAjIyBjb250cm9scyBiZWhhdmlvciBuZWFyIDAKbWxlX2t1bV9iX2VzdGltYXRlID0gbWxlX2t1bSRwYXJbMl0gIyBiCiAgIyMgY29udHJvbHMgYmVoYXZpb3IgYXBwcm9hY2hpbmcgMSAvIHRoaW5rIHJpZ2h0IHRhaWwKYGBgCgpVc2luZyBSJ3MgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij5vcHRpbTwvc3Bhbj4gZnVuY3Rpb24sIGFuZCBwZXJmb3JtaW5nIG51bWVyb3VzIGl0ZXJhdGlvbnMgd2l0aCBkaWZmZXJlbnQgc3RhcnRpbmcgcGFyYW1ldGVyIGVzdGltYXRlcyBvZiBib3RoICRhJCBhbmQgJGIkLCBhIHJlYXNvbmFibGUgZXN0aW1hdGUgZm9yIHRoZSB0d28gc2hhcGUgcGFyYW1ldGVycyBhcmUgYHIgcm91bmQobWxlX2t1bV9hX2VzdGltYXRlLDMpYCBhbmQgYHIgcm91bmQobWxlX2t1bV9iX2VzdGltYXRlLDMpYCByZXNwZWN0aXZlbHkuIEJlbG93IGlzIGEgdmlzdWFsIG9mIG91ciBzYW1wbGUgZGF0YSB3aXRoIGEgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIGN1cnZlIHdpdGggc2FpZCBwYXJhbWV0ZXIgdmFsdWVzIGFkZGl0aW9uYWxseSBvdmVybGFpZC4KCmBgYHtyfQpsaWJyYXJ5KGV4dHJhRGlzdHIpICMgbmVlZGVkIHRvIHBsb3QgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIGN1cnZlCgojIyB2aXN1YWwgY29uZmlybWF0aW9uCmdncGxvdChkYXRhID0gZGF0YSkgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHN0b3JhZ2UsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgZmlsbCA9ICJsaWdodGJsdWUiLAogICAgICAgICAgICAgICAgIGJpbnMgPSAxMCwpICsKICAgICAgc3RhdF9mdW5jdGlvbihmdW4gPSBka3VtYXIsIAogICAgICAgICAgICAgICAgYXJncyA9IGxpc3QoYSA9IG1sZV9rdW1fYV9lc3RpbWF0ZSwgYiA9IG1sZV9rdW1fYl9lc3RpbWF0ZSksCiAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLjUsCiAgICAgICAgICAgICAgICB4bGltID0gcmFuZ2UoMDoxKSkrCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU3RvcmFnZSBWb2x1bWVzIiwKICAgICAgIHggPSAiU3RvcmFnZSBWb2x1bWUiLAogICAgICAgeSA9ICJQcm9iYWJpaXR5IERlbnNpdHkiKSArIAogIHRoZW1lKAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9IE5BLCBsaW5ld2lkdGggPSAzKQogICkgCmBgYAoKIyMgQjIuKSAKR29pbmcgYmFjayB0byB0aGUgKipwb3dlcioqIGRpc3RyaWJ1dGlvbiwgSSBvbmNlIGFnYWluIHBlcmZvcm1lZCBNTEUgdG8gYXBwcm94aW1hdGUgdGhlIHZhbHVlIG9mIHRoZSBwb3dlciBkaXN0cmlidXRpb24ncyBzb2xlIHBhcmFtZXRlciwgJGEkLgoKYGBge3J9CiMjIHNhbWUgcHJvY2VkdXJlIGFzIEIxLCBub3cgdXNlIHBvd2VyIGRpc3RyaWJ1dGlvbiBjaGFyYWN0ZXJpc3RpY3MKbG9nX2xpa2VfcG93ZXIgPSBmdW5jdGlvbihhLCBkYXRhKXsKICAgICAgbiA9IGxlbmd0aChkYXRhKQogICAgICBsb2dfbGlrZWxpaG9vZCA9IG4gKiBsb2coYSkgKwogICAgICAgIChhLTEpKnN1bShsb2coZGF0YSkpCiAgICByZXR1cm4obG9nX2xpa2VsaWhvb2QpCiAgICB9CgpncmFkaWVudF9wb3dlciA9IGZ1bmN0aW9uKGEsIGRhdGEpewogICAgbiA9IGxlbmd0aChkYXRhKQogICAgcGFydGlhbF9hID0gbi9hICsgc3VtKGxvZyhkYXRhKSkKICAgIHJldHVybihwYXJ0aWFsX2EpCiAgICB9CgptbGVfcG93ZXIgPSBvcHRpbSgKICAgIHBhciA9IDIuNiwgIyMgbWF5YmUgY2hhbmdlIHRoaXMgbGF0ZXIKICAgIGZuID0gbG9nX2xpa2VfcG93ZXIsCiAgICBnciA9IGdyYWRpZW50X3Bvd2VyLAogICAgZGF0YSA9IGRhdGEkc3RvcmFnZSwKICAgIG1ldGhvZCA9ICJMLUJGR1MtQiIsCiAgICAgIGxvd2VyID0gYygxZS04LCAxZS04KSwKICAgIGhlc3NpYW4gPSBUUlVFLAogICAgY29udHJvbCA9IGxpc3QodHJhY2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgIGZuc2NhbGUgPSAtMSwKICAgICAgICAgICAgICAgICAgIG1heGl0ID0gNTAwLAogICAgICAgICAgICAgICAgICAgYWJzdG9sID0gMWUtOCkKICAgICkKCm1sZV9wb3dlcl9hX2VzdGltYXRlID0gbWxlX3Bvd2VyJHBhciAKCiMgbWVhbihkYXRhJHN0b3JhZ2UpID0gMC4zNzggPSB4IGJhcgoKIyB4IGJhciA9IGEgLyAoYSsxKSBbZnJvbSBxdWVzdGlvbiBBNCBNTUUgZm9ybXVsYV0KICAjIDAuOTQvMS45NCA9IDAuNDg0NTM2MQpgYGAKQWZ0ZXIgZ2V0dGluZyBhbiBlc3RpbWF0ZSBvZiByb3VnaGx5ICRhIFxhcHByb3ggYHIgcm91bmQobWxlX3Bvd2VyX2FfZXN0aW1hdGUsMylgJCwgSSB3ZW50IGFoZWFkIGFuZCBvbmNlIGFnYWluIG92ZXJsYWlkIHdoYXQgc3VjaCBhIHBvd2VyIGRpc3RyaWJ1dGlvbiB3b3VsZCBsb29rIGxpa2UgcmVsYXRpdmUgdG8gb3VyIGF2YWlsYWJsZSBzYW1wbGUgZGF0YS4KCmBgYHtyfQojIyB2aXN1YWwgY29uZmlybWF0aW9uCgojIFNpbmNlIFIgZG9lcyBub3QgaGF2ZSBhIGJ1aWx0LWluIGRwb3dlciBmdW5jdGlvbiwgbmVlZCB0byBtYW51YWxseSBjcmVhdGUgb25lCm1hbnVhbF9kX3Bvd2VyID0gZnVuY3Rpb24oeCwgYSl7CiAgYSAqIHheKGEtMSkgIyA9IHBkZiBvZiBwb3dlciBkaXN0cmlidXRpb24KfQoKZ2dwbG90KGRhdGEgPSBkYXRhKSArCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4ID0gc3RvcmFnZSwgeSA9IGFmdGVyX3N0YXQoZGVuc2l0eSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Ymx1ZSIsCiAgICAgICAgICAgICAgICAgYmlucyA9IDEwLCkgKwogICAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IG1hbnVhbF9kX3Bvd2VyLCAKICAgICAgICAgICAgICAgIGFyZ3MgPSBsaXN0KGEgPSBtbGVfcG93ZXJfYV9lc3RpbWF0ZSksCiAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLjUsCiAgICAgICAgICAgICAgICB4bGltID0gcmFuZ2UoMDoxKSkrCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU3RvcmFnZSBWb2x1bWVzIiwKICAgICAgIHggPSAiU3RvcmFnZSBWb2x1bWUiLAogICAgICAgeSA9ICJQcm9iYWJpaXR5IERlbnNpdHkiKSArIAogIHRoZW1lKAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9IE5BLCBsaW5ld2lkdGggPSAzKQogICkgCmBgYAoKUGVyIHRoZXNlIHZpc3VhbHMsIGl0IGFwcGVhcnMgdGhhdCB0aGUgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIG11Y2ggbW9yZSBhY2N1cmF0ZWx5IGNhcHR1cmVzIHRoZSByZWFsaXR5IG9mIG91ciBicm9hZGVyIGRpc3RyaWJ1dGlvbiB0aGFuIHRoZSBwb3dlciBkaXN0cmlidXRpb24gZG9lcy4gVG8gcXVhbnRpZnkgdGhpcyBkaWZmZXJlbmNlLCB3ZSBwZXJmb3JtIGEgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IChMUlQpLgoKYGBge3J9CiMjIGlmIGIgPSAxLCB0aGVuIHBvd2VyIGRpc3RyaWJ1dGlvbiBpcyBhcHBsaWNhYmxlCiMjIGlmIGIgPS8gMSwgdGhlbiBLdW1hcmFzd2FteSBkaXN0cmlidXRpb24gaXMgYXBwbGljYWJsZQoKIyB0ZXN0IHN0YXQgZm9yIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBpcyB1cHBlcmNhc2UgTGFtYmRhCgojIyBldmFsdWF0ZSBhdCB1bnJlc3RyaWN0ZWQgKEt1bWFyYXN3YW15KQpsb2dfZXZhbHVhdGlvbl9rdW0gPSBsb2dfbGlrZV9rdW0ocGFyYW1ldGVycyA9IGMobWxlX2t1bV9hX2VzdGltYXRlLCBtbGVfa3VtX2JfZXN0aW1hdGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEkc3RvcmFnZSkKCiMjIGV2YWx1YXRlIGF0IHJlc3RyaWN0ZWQvc2ltcGxlciAocG93ZXIpCmxvZ19ldmFsdWF0aW9uX3Bvd2VyID0gbG9nX2xpa2VfcG93ZXIoYSA9IG1sZV9wb3dlcl9hX2VzdGltYXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhJHN0b3JhZ2UpCgoKIyMgdGhlIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBpcyBqdXN0IDIgKiAKICAjIFtsb2cgbGlrZWxpaG9vZCBldmFsdWF0ZWQgaW4gdW5yZXN0cmljdGVkIHdheV0gLQogICMgW2xvZyBsaWtlbGlob29kIGV2YWx1YXRlZCBpbiByZXN0cmljdGVkIG9yIHNpbXBsZSB3YXldCgpMYW1iZGEgPSAyICogKGxvZ19ldmFsdWF0aW9uX2t1bSAtIGxvZ19ldmFsdWF0aW9uX3Bvd2VyKQoKcF92YWx1ZV9saWtlbGlob29kcmF0aW8gPSAxIC0gcGNoaXNxKExhbWJkYSwgZGYgPSAxKQogICMgdGVzdCBzdGF0IGRpc3RyaWJ1dGlvbiBmb3IgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IGlzIGNoaS1zcXVhcmUgZGlzdHJpYnV0ZWQKICAjIGRmID0gbnVtYmVyIG9mIHBhcmFtZXRlcnMgd2UgYXJlIGVzdGltYXRpbmcgaW4gZnVuY3Rpb24KCmBgYApUaGUgcmVzdWx0cyBvZiB0aGUgTFJUIHdlcmUgb3ZlcndoZWxtaW5nbHkgaW4gc3VwcG9ydCBvZiB0aGUgbm90aW9uIHRoYXQgdGhlIHBhcmFtYXRlciAkYiQgaXMgKipub3QqKiBlcXVhbCB0byAxLCBoZW5jZSB3ZSBzaG91bGQgYXBwcm9hY2ggdGhlIGJyb2FkZXIgcG9wdWxhdGlvbiBvZiByZXNlcnZvaXIgc3RvcmFnZSBmcm9tIHRoZSBsZW5zIG9mIGEgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uLCByYXRoZXIgdGhhbiBhIHBvd2VyIG9uZS4gT3VyIHN0YXRpc3RpY2FsIHJlc3VsdHMgd2VyZSBhICRcTGFtYmRhJCB2YWx1ZSBvZiBhYm91dCBgciByb3VuZChMYW1iZGEsMylgIGFuZCBhIHAtdmFsdWUgYXBwcm94aW1hdGluZyBgciByb3VuZChwX3ZhbHVlX2xpa2VsaWhvb2RyYXRpbyw2KWAuCgpHaXZlbiB0aGUgbGFyZ2UgdmlzdWFsIGRpc2NyZXBhbmNpZXMgaW4gdGhlIGhpc3RvZ3JhbXMgb3ZlcmxheWluZyB0aGUgS3VtYXJhc3dhbXkgYW5kIHBvd2VyIGRpc3RyaWJ1dGlvbnMsIHRoZXNlIHJlc3VsdHMgYXJlIG5vdCBzdXJwcmlzaW5nLgoKIyMgQjMuKQpOb3cgY29udGludWluZyB3aXRoIHRoZSBhc3N1bXB0aW9uIG9mIGEgKipLdW1hcmFzd2FteSoqIGRpc3RyaWJ1dGlvbiwgaS5lLiBib3RoICRhLGIkIGVxdWFsaW5nIGFueSBwb3NpdGl2ZSB2YWx1ZSBvdGhlciB0aGFuIGV4YWN0bHkgb25lLCB3ZSByZXR1cm4gdG8gdGhlIGxpa2VsaWhvb2QgZXN0aW1hdGVzIGZyb20gc2VjdGlvbiBCMTsgJGEkID0gYHIgcm91bmQobWxlX2t1bV9hX2VzdGltYXRlLDMpYCBhbmQgJGIkID0gYHIgcm91bmQobWxlX2t1bV9iX2VzdGltYXRlLDMpYCByZXNwZWN0aXZlbHkuCgojIyMgMS4pClRvIHJlZHVjZSB0aGUgaW1wYWN0IG9mIHNhbXBsZSB2YXJpYXRpb24sIEkgcGVyZm9ybWVkIGJvb3RzdHJhcHBpbmcgdG8gb2J0YWluIGEgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIC0gY29tcG9zZWQgb2YgNTAwIHNhbXBsZXMgLSBvZiBib3RoIGEgYW5kIGIuCgpgYGB7cn0KIyB1c2UgdGhlIG1sZV9rdW0gZnVuY3Rpb24gZnJvbSBlYXJsaWVyIHRvIG9idGFpbiBhbiBlc3RpbWF0ZSBvZiBhIGFuZCBiIGZvciBlYWNoIHNhbXBsZQoKYm9vdHN0cmFwX2t1bV9lc3RpbWF0ZXMgPSBmdW5jdGlvbihkYXRhLCBiKXsKICBuID0gbGVuZ3RoKGRhdGEpCiAgYm9vdHNfYSA9IG51bWVyaWMoYikgIyBjcmVhdGUgYSB2ZWN0b3Igd2l0aCBiIG51bWJlciBvZiAic2xvdHMiIHRvIGZpbGwgdGhyb3VnaG91dCBib290c3RyYXAgcHJvY2VzcwogIGJvb3RzX2IgPSBudW1lcmljKGIpCiAgCiAgIyBTVEFSVCBGT1IgTE9PUAogICAgZm9yIChpIGluIDE6Yil7CiAgICAgICAgYm9vdF9zYW1wbGUgPSBzYW1wbGUoZGF0YSwgc2l6ZSA9IG4sIHJlcGxhY2UgPSBUUlVFKSAjIHJlcGxhY2VtZW50IGlzIG5lY2Vzc2FyeSAKICAgICAgICAKICAgICAgICAjIHRha2VuIGZyb20gbWxlX2t1bSBmdW5jdGlvbiBmcm9tIGVhcmxpZXIgCiAgICAgICAgIyB3ZSBhcmUgZ2V0dGluZyBlc3RpbWF0ZXMgZm9yIHRoZSBLVU1BUkFTV0FNWSBkaXN0cmlidXRpb24KICAgICAgICBib290X21sZV9rdW0gPSBvcHRpbSgKICAgICAgICBwYXIgPSBjKGEgPSAxLjUsIGIgPSA1KSwKICAgICAgICBmbiA9IGxvZ19saWtlX2t1bSwKICAgICAgICBnciA9IGdyYWRpZW50X2t1bSwKICAgICAgICBkYXRhID0gYm9vdF9zYW1wbGUsICMjIGNyaXRpY2FsIGNoYW5nZSBmb3IgYm9vdHN0cmFwIHNjZW5hcmlvCiAgICAgICAgbWV0aG9kID0gIkwtQkZHUy1CIiwKICAgICAgICAgIGxvd2VyID0gYygxZS04LCAxZS04KSwKICAgICAgICBoZXNzaWFuID0gVFJVRSwKICAgICAgICBjb250cm9sID0gbGlzdCh0cmFjZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGZuc2NhbGUgPSAtMSwKICAgICAgICAgICAgICAgICAgICAgICBtYXhpdCA9IDUwMCwKICAgICAgICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQogICAgICApCiAgICAgICAKICAgICAgICMjIG5vdyBzdG9yZSByZXN1bHRzIGZvciBlYWNoIHBhcmFtZXRlcgogICAgICAgIGJvb3RzX2FbaV0gPSBib290X21sZV9rdW0kcGFyWzFdCiAgICAgICAgYm9vdHNfYltpXSA9IGJvb3RfbWxlX2t1bSRwYXJbMl0KICAgICAgIAogICAgfSAjIEVORCBGT1IgTE9PUAogIAogICMjIG5vdyBvdXRwdXQgb3VyIHBhcmFtZXRlciBlc3RpbWF0ZXM7IHdpbGwgc29ydCBhbmQgcHV0IHRoZW0gYXMgYSBkYXRhZnJhbWUgZm9yIGVhc2llciBpbnRlcnByZXRhdGlvbgogIGJvb3RfYV9lc3RpbWF0ZXMgPSBzb3J0KGJvb3RzX2EpCiAgYm9vdF9iX2VzdGltYXRlcyA9IHNvcnQoYm9vdHNfYikKICAKICBib290X2FfZXN0aW1hdGVzID0gY2JpbmQuZGF0YS5mcmFtZShib290X2FfZXN0aW1hdGVzKQogIGJvb3RfYl9lc3RpbWF0ZXMgPSBjYmluZC5kYXRhLmZyYW1lKGJvb3RfYl9lc3RpbWF0ZXMpCiAgCiAgCiAgcmV0dXJuKGxpc3QoYm9vdF9hX2VzdGltYXRlcywKICAgICAgICAgICAgICBib290X2JfZXN0aW1hdGVzKSkKICAKfSAjIEVORCBGVU5DVElPTgoKc2V0LnNlZWQoMTAwKQojIG5vdyBydW4gZnVuY3Rpb24sIHVzaW5nIDUwMCBib290c3RyYXAgc2FtcGxlcwpib290X3NhbXBsaW5nX2Rpc3QgPSBib290c3RyYXBfa3VtX2VzdGltYXRlcyhkYXRhID0gZGF0YSRzdG9yYWdlLCBiID0gNTAwKQoKYm9vdF9hX2VzdGltYXRlcyA9IGJvb3Rfc2FtcGxpbmdfZGlzdFtbMV1dICMgYSBoYXQgZGlzdHJpYnV0aW9uCiAgY29sbmFtZXMoYm9vdF9hX2VzdGltYXRlcykgPSAiYSIKYm9vdF9iX2VzdGltYXRlcyA9IGJvb3Rfc2FtcGxpbmdfZGlzdFtbMl1dICMgYiBoYXQgZGlzdHJpYnV0aW9uCiAgY29sbmFtZXMoYm9vdF9iX2VzdGltYXRlcykgPSAiYiIKYGBgClRoZSByZXN1bHRzIG9mIHRoaXMgYm9vdHN0cmFwcGluZyBzZXF1ZW5jZSByZXN1bHRlZCBpbiBhdmVyYWdlIGVzdGltYXRlcyBvZiBwYXJhbWV0ZXJzIGEgYW5kIGIgb2YgYWJvdXQgYHIgcm91bmQobWVhbihib290X2FfZXN0aW1hdGVzJGEpLDMpYCBhbmQgYHIgcm91bmQobWVhbihib290X2JfZXN0aW1hdGVzJGIpLDMpYCAobm90IGZhciBmcm9tIG91ciBvcmlnaW5hbCBlc3RpbWF0ZSBvZiBgciByb3VuZChtbGVfa3VtX2FfZXN0aW1hdGUsMylgIGFuZCBgciByb3VuZChtbGVfa3VtX2JfZXN0aW1hdGUsMylgKS4KCkJlbG93IGFyZSB2aXN1YWxzIG9mIGVhY2ggcGFyYW1ldGVyJ3Mgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIGZyb20gdGhlIGJvb3RzdHJhcHBpbmcgc2VxdWVuY2UsIHdpdGggYSA8c3BhbiBzdHlsZT0iY29sb3I6cmVkOyI+R2F1c3NpYW4gZGVuc2l0eSBjdXJ2ZTwvc3Bhbj4gbGF5ZXJlZCBhdG9wLiBCYW5kd2lkdGhzIGZvciBlYWNoIGRlbnNpdHkgY3VydmUgd2VyZSBjaG9zZW4gaW4gYWNjb3JkYW5jZSB3aXRoIFNpbHZlcm1hbuKAmXMgc3RhbmRhcmQgZm9ybXVsYS4KYGBge3J9CiMjIHVzZSBjdXN0b20gZnVuY3Rpb24gdG8gZmluZCBHYXVzc2lhbiBiYW5kd2lkdGggdmFsdWVzIGZvciBlYWNoIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbgpnYXVzc2lhbl9idyA9IGZ1bmN0aW9uKGRhdGEpewogIG1pbl9wYXJ0ID0gbWluKHNkKGRhdGEpLChJUVIoZGF0YSkvMS4zNCkpCiAgYncgPSAwLjkgKiBtaW5fcGFydCAqIChsZW5ndGgoZGF0YSleKC0wLjIpKQogIHJldHVybihidykKfQoKI2dhdXNzaWFuX2J3KGJvb3RfYV9lc3RpbWF0ZXMkYSkgID0gMC4wODMxNDg0MQojZ2F1c3NpYW5fYncoYm9vdF9iX2VzdGltYXRlcyRiKSAgPSAwLjY4NzU3MjcKYGBgCgpgYGB7cn0KIyMgcGxvdCBhIGhhdCBlc3RpbWF0ZXMgZmlyc3QKZ2dwbG90KGRhdGEgPSBib290X2FfZXN0aW1hdGVzKSArCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4ID0gYSwgeSA9IGFmdGVyX3N0YXQoZGVuc2l0eSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Ymx1ZSIsCiAgICAgICAgICAgICAgICAgYmlucyA9IDEwLCkgKwogICMjIHRoZSBnZW9tX2RlbnNpdHkgZnVuY3Rpb24gaW4gZ2dwbG90IGJ5IGRlZmF1bHQgdXNlcyBHYXVzc2lhbiBlc3RpbWF0aW9uCiAgZ2VvbV9kZW5zaXR5KAogICAgYWVzKHggPSBhKSwKICAgIGNvbG9yID0gInJlZCIsCiAgICBsaW5ld2lkdGggPSAyLAogICAgYncgPSBnYXVzc2lhbl9idyhib290X2FfZXN0aW1hdGVzJGEpCiAgKSArIAogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEEgSGF0IEVzdGltYXRlcyIsCiAgICAgICB4ID0gIkEgSGF0IiwKICAgICAgIHkgPSAiUHJvYmFiaWl0eSBEZW5zaXR5IikgKyAKICB0aGVtZSgKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgbGluZXdpZHRoID0gMykKICApIApgYGAKCmBgYHtyfQojIyBub3cgcGxvdCBiIGhhdCBlc3RpbWF0ZXMgCmdncGxvdChkYXRhID0gYm9vdF9iX2VzdGltYXRlcykgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IGIsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgZmlsbCA9ICJsaWdodGJsdWUiLAogICAgICAgICAgICAgICAgIGJpbnMgPSAxMCwpICsKICBnZW9tX2RlbnNpdHkoCiAgICBhZXMoeCA9IGIpLAogICAgY29sb3IgPSAicmVkIiwKICAgIGxpbmV3aWR0aCA9IDIsCiAgICBidyA9IGdhdXNzaWFuX2J3KGJvb3RfYl9lc3RpbWF0ZXMkYikKICApICsgCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgQiBIYXQgRXN0aW1hdGVzIiwKICAgICAgIHggPSAiQiBIYXQiLAogICAgICAgeSA9ICJQcm9iYWJpaXR5IERlbnNpdHkiKSArIAogIHRoZW1lKAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9IE5BLCBsaW5ld2lkdGggPSAzKQogICkgCmBgYAoKCiMjIyAyLikKTG9va2luZyBkZWVwZXIgaW50byB0aGUgJGIkIHBhcmFtZXRlciBmb3IgdGhlIEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiwgSSBjb25zdHJ1Y3RlZCBhIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFsIGZvciBpdHMgdmFsdWUuCgpgYGB7cn0KIyMgYm9vdHN0cmFwIENJCmNpX3BlcmNlbnRpbGUgPSBmdW5jdGlvbihkYXRhLCBiLCBhbHBoYSl7CiAgbiA9IGxlbmd0aChkYXRhKQogIGJvb3RzX2EgPSBudW1lcmljKGIpICMgY3JlYXRlIGEgdmVjdG9yIHdpdGggYiBudW1iZXIgb2YgInNsb3RzIiB0byBmaWxsIHRocm91Z2hvdXQgYm9vdHN0cmFwIHByb2Nlc3MKICBib290c19iID0gbnVtZXJpYyhiKQogIAogIAogICMjIyBjb2RlIHRha2VuIGZyb20gQjMgUXVlc3Rpb24gMQogICMgU1RBUlQgRk9SIExPT1AKICAgIGZvciAoaSBpbiAxOmIpewogICAgICAgIGJvb3Rfc2FtcGxlID0gc2FtcGxlKGRhdGEsIHNpemUgPSBuLCByZXBsYWNlID0gVFJVRSkgIyByZXBsYWNlbWVudCBpcyBuZWNlc3NhcnkgCiAgICAgICAgCiAgICAgICAgIyB0YWtlbiBmcm9tIG1sZV9rdW0gZnVuY3Rpb24gZnJvbSBlYXJsaWVyIAogICAgICAgICMgd2UgYXJlIGdldHRpbmcgZXN0aW1hdGVzIGZvciB0aGUgS1VNQVJBU1dBTVkgZGlzdHJpYnV0aW9uCiAgICAgICAgYm9vdF9tbGVfa3VtID0gb3B0aW0oCiAgICAgICAgcGFyID0gYyhhID0gMS41LCBiID0gNSksCiAgICAgICAgZm4gPSBsb2dfbGlrZV9rdW0sCiAgICAgICAgZ3IgPSBncmFkaWVudF9rdW0sCiAgICAgICAgZGF0YSA9IGJvb3Rfc2FtcGxlLCAjIyBjcml0aWNhbCBjaGFuZ2UgZm9yIGJvb3RzdHJhcCBzY2VuYXJpbwogICAgICAgIG1ldGhvZCA9ICJMLUJGR1MtQiIsCiAgICAgICAgICBsb3dlciA9IGMoMWUtOCwgMWUtOCksCiAgICAgICAgaGVzc2lhbiA9IFRSVUUsCiAgICAgICAgY29udHJvbCA9IGxpc3QodHJhY2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBmbnNjYWxlID0gLTEsCiAgICAgICAgICAgICAgICAgICAgICAgbWF4aXQgPSA1MDAsCiAgICAgICAgICAgICAgICAgICAgICAgYWJzdG9sID0gMWUtOCkKICAgICAgKQogICAgICAgCiAgICAgICAjIyBub3cgc3RvcmUgcmVzdWx0cyBmb3IgZWFjaCBwYXJhbWV0ZXIKICAgICAgICBib290c19hW2ldID0gYm9vdF9tbGVfa3VtJHBhclsxXSAjIG5vdCBuZWNlc3NhcnkgZm9yIG91dHB1dCBpbiB0aGlzIHNjZW5hcmlvIGJ1dCB3aWxsIGtlZXAgZm9yIG5vdwogICAgICAgIGJvb3RzX2JbaV0gPSBib290X21sZV9rdW0kcGFyWzJdCiAgICAgICAKICAgIH0gIyBFTkQgRk9SIExPT1AKICAKICAjIyBub3cgZG8gQ0kgY2FsY3VsYXRpb24KICBib290c19iID0gc29ydChib290c19iKQogIGxvd2VyX3F1YW50ID0gKGFscGhhLzIpCiAgaGlnaGVyX3F1YW50ID0gKDEtKGFscGhhLzIpKQogIGxvd2VyX2VzdGltYXRlID0gcXVhbnRpbGUoYm9vdHNfYiwgbG93ZXJfcXVhbnQpCiAgaGlnaGVyX2VzdGltYXRlID0gcXVhbnRpbGUoYm9vdHNfYiwgaGlnaGVyX3F1YW50KQogIAogICMgbm93IHB1dCB0b2dldGhlciBpbiBhIHRhYmxlIGZvciBvdXRwdXQKICByZXN1bHRzID0gcmJpbmQobG93ZXJfZXN0aW1hdGUsCiAgICAgICAgICAgICAgICAgIGhpZ2hlcl9lc3RpbWF0ZSkKICBjb2xuYW1lcyhyZXN1bHRzKSA9ICJiX2hhdCIKICByb3duYW1lcyhyZXN1bHRzKSA9IGMoIkxvd2VyIEVzdGltYXRlIiwgIkhpZ2hlciBFc3RpbWF0ZSIpCiAgCiAgcmV0dXJuKHJlc3VsdHMpCn0KCnNldC5zZWVkKDEwMCkKYm9vdF9jaSA9IGNpX3BlcmNlbnRpbGUoZGF0YSA9IGRhdGEkc3RvcmFnZSwgYiA9IDUwMCwgYWxwaGEgPSAwLjA1KQpgYGAKV2l0aCBhIDUwMC1pdGVyYXRpb24gYm9vdHN0cmFwIHNlcXVlbmNlIGFuZCBjb25maWRlbmNlIGxldmVsIG9mIGFib3V0IDk1JSwgd2UgY2FuIGFzc2VydCB0aGF0IHRoZSB0cnVlIHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIgJGIkIGlzIGFwcHJveGltYXRlbHkgc29tZXdoZXJlIGJldHdlZW4gYHIgcm91bmQoYm9vdF9jaVsxXSwzKWAgYW5kIGByIHJvdW5kKGJvb3RfY2lbMl0sMylgLiBLbm93aW5nIG91ciBpbml0aWFsLCBNTEUtYmFzZWQsIGVzdGltYXRlIGZvciB0aGUgcGFyYW1ldGVyIHdhcyByb3VnaGx5IGByIHJvdW5kKG1sZV9rdW1fYl9lc3RpbWF0ZSwzKWAsIGFuZCB0aGUgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIGlzIHJpZ2h0LXNrZXdlZCwgdGhlc2UgcmVzdWx0cyBzZWVtIHBsYXVzaWJsZS4KCkFmdGVyIHBlcmZvcm1pbmcgdGhlIGJvb3RzdHJhcCBzZXF1ZW5jZSwgSSB0aGVuIGNvbnN0cnVjdGVkIGEgV2FsZCBjb25maWRlbmNlIGludGVydmFsLCB3aGljaCBpcyBwcmVkaWNhdGVkIG9uIGEgcGFyYW1ldGVyJ3MgcG9pbnQgZXN0aW1hdGUsIGNyaXRpY2FsIHZhbHVlIGFuZCBzdGFuZGFyZCBlcnJvci4gCgpgYGB7cn0KIyMgV2FsZCBDSQoKIyBXYWxkIGZvcm11bGEgPSBlc3RpbWF0ZSArLSB6IHNjb3JlICogc3RhbmRhcmQgZXJyb3IKICAjIGVzdGltYXRlID0gbWxlX2t1bV9iX2VzdGltYXRlIH4gNy44OAoKd2FsZF96ID0gMS45NgojIGxldCBJIGRlbm90ZSBGaXNoZXIgbWF0cml4CkkgPSAtbWxlX2t1bSRoZXNzaWFuCgp3YWxkX3NlID0gc3FydChkaWFnKHNvbHZlKEkpKSkgIyBiIH4gMi4yNDUKICAjIGlmIHdlIGludmVydCBhbmQgc29sdmUgdGhlIEZpc2hlciBtYXRyaXgsIHRoZW4gc3F1YXJlIHJvb3QgdGhlIGRpYWdvbmFscywgd2Ugd2lsbCBnZXQgZXN0aW1hdGVzIG9mIGVhY2ggcGFyYW1ldGVyJ3Mgc3RhbmRhcmQgZXJyb3IKCndhbGRfc2VfYiA9IHdhbGRfc2VbMl0gIyB3aGF0IHdlIG5lZWQgcmlnaHQgbm93Cgp3YWxkX2xvd2VyX2VzdCA9IG1sZV9rdW1fYl9lc3RpbWF0ZSAtIHdhbGRfeiAqIHdhbGRfc2VfYgp3YWxkX2hpZ2hlcl9lc3QgPSBtbGVfa3VtX2JfZXN0aW1hdGUgKyB3YWxkX3ogKiB3YWxkX3NlX2IKYGBgCgpPdXIgc3RhbmRhcmQgZXJyb3IgZm9yIHRoZSBlc3RpbWF0ZSBvZiAkYiQgd2FzIGRlcml2ZWQgZnJvbSB0aGUgRmlzaGVyIG1hdHJpeCBvZiAkYSQgYW5kICRiJCB3aGljaCB3YXMgY3JlYXRlZCBpbiBSJ3MgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij5vcHRpbTwvc3Bhbj4gZnVuY3Rpb24gcHJldmlvdXNseS4KCkFzIHBlciBXYWxkJ3MgaW50ZXJ2YWwsIHdlIGNhbiBzYXkgd2l0aCBhYm91dCA5NSUgY2VydGFpbnR5IHRoYXQgdGhlIHRydWUgdmFsdWUgb2YgYiByZXNpZGVzIGJldHdlZW4gYHIgcm91bmQod2FsZF9sb3dlcl9lc3QsMylgIGFuZCBgciByb3VuZCh3YWxkX2hpZ2hlcl9lc3QsMylgLgoKIyMjIDMuKQpBbHRob3VnaCB0aGUgV2FsZCBpbnRlcnZhbCBwcm92aWRlcyBhIG1vcmUgY29uc2VydmF0aXZlIGVzdGltYXRlIGZvciAkYiQgdGhhbiB0aGUgYm9vdHN0cmFwIGludGVydmFsIGRvZXMsIGl0IGlzIHN0aWxsIHJlYXNvbmFibHkgY2xvc2UgZW5vdWdoIHRvIG5vdCBydWxlIG91dCBhbmQga2VlcCBpbiBjb25zaWRlcmF0aW9uIGZvciBwb3B1bGF0aW9uIGVzdGltYXRpb24gcHVycG9zZXMuIFdpdGggYW4gb3JpZ2luYWwgcG9pbnQgZXN0aW1hdGUgZm9yICRiJCBvZiBgciByb3VuZChtbGVfa3VtX2JfZXN0aW1hdGUsMylgLCB0aGF0IGVzdGltYXRlIGZhbGxzIHJvdWdobHkgaW4gdGhlIG1pZGRsZSBvZiBvdXIgV2FsZCBpbnRlcnZhbC4gQWx0ZXJuYXRpdmVseSwgb3VyIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFsIChhcyB3ZSBjYW4gc2VlIGluIG91ciBoaXN0b2dyYW0gaW4gc2VjdGlvbiBCMyBRMSkgbW9yZSBhY2N1cmF0ZWx5IHJlY29nbml6ZXMgdGhlIHJpZ2h0d2FyZCBza2V3IHRoYXQgdGhlIEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiB0eXBpY2FsbHkgY2Fycmllcy4KCiMjIEI0LikKRmluYWxseSwgSSBjb21wbGV0ZSBhbm90aGVyIExSVCB0byBkZXRlcm1pbmUgaWYgdGhlcmUgaXMgc2lnbmlmaWNhbnQgbG9zcyBpbiBhY2N1cmFjeSB3aGVuIGV4YW1pbmluZyBvdXIgYnJvYWRlciBwb3B1bGF0aW9uIHZpYSBhIHVuaWZvcm0gZGlzdHJpYnV0aW9uIGxlbnMgcmF0aGVyIHRoYW4gYSBLdW1hcmFzd2FteSBvbmUsIHVzaW5nIHRoZSBhdmFpbGFibGUgc2FtcGxlIGRhdGEgYXMgYSAiYmVuY2htYXJrIiBvZiBzdWNoLgpgYGB7cn0KIyBpZiAoYSxiKSA9IDEsIHRoZW4gdW5pZm9ybSBkaXN0cmlidXRpb24gaXMgYXBwbGljYWJsZQojIGlmIGF0IGxlYXN0IG9uZSBvZiBhIG9yIGIgPS8gMSwgdGhlbiBkaXN0cmlidXRpb24gaXMgbm90IHVuaWZvcm0KCmxvZ19ldmFsdWF0aW9uX3VuaWZvcm0gPSBsb2dfbGlrZV9rdW0ocGFyYW1ldGVycyA9IGMoMSwxKSwgIyBhIGFuZCBiID0gMSBvZiBhIEt1bSBkaXN0cmlidXRpb24sIHRoYXQgaXMgc2FtZSBhcyB1bmlmb3JtIGRpc3RyaWJ1dGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEkc3RvcmFnZSkKCkxhbWJkYV9CNCA9IDIgKiAobG9nX2V2YWx1YXRpb25fa3VtIC0gbG9nX2V2YWx1YXRpb25fdW5pZm9ybSkgCgpwX3ZhbHVlX0I0ID0gMSAtIHBjaGlzcShMYW1iZGFfQjQsIGRmID0gMikKICAjIG5vdyBlc3RpbWF0aW5nIDIgcGFyYW1ldGVycyBzbyBkZiA9IDIKYGBgCgpVbnN1cnByaXNpbmdseSwgdGhlIExSVCByZXN1bHRzIGZvdW5kIHRoYXQgdGhlcmUgaXMgc3VmZmljaWVudCByZWFzb24gdG8gYmVsaWV2ZSB0aGF0IHRoZSBicm9hZGVyIHBvcHVsYXRpb24gb2YgcmVzZXJ2b2lyIHN0b3JhZ2UgaXMgKipub3QqKiB1bmlmb3JtbHkgZGlzdHJpYnV0ZWQsIHNwb3J0aW5nIGEgdGVzdCBzdGF0aXN0aWMgb2YgYWJvdXQgYHIgcm91bmQoTGFtYmRhX0I0LDMpYCBhbmQgYSBwLXZhbHVlIGFwcHJvYWNoaW5nIHplcm8uIEdpdmVuIHRoZSBlc3RpbWF0ZXMgZm9yICRhJCBhbmQgJGIkIHRocm91Z2hvdXQgdGhpcyBhbmFseXNpcyBhcyB3ZWxsIGFzIHZpc3VhbGl6YXRpb25zIG9mIHRoZSBkYXRhLCB0aGVzZSBmaW5kaW5ncyBhbGlnbiB3aXRoIHdoYXQgd2UgaGF2ZSBvYnNlcnZlZCBzbyBmYXIuCg==