Introduction
Estimating the sample size for a prospective study is one of the
first most important tasks in classical statistics. In clinical studies,
researchers need to determine the number of subjects to enroll in a
clinical trial to guarantee the reliability of the study results. If the
sample size is too small, it will not be able to achieve the power of
the analysis. If the size excessively larger than needed, it will waste
resources.
Estimating the optimal number of patients is necessary for developing
a Statistical Analysis Plan (SAP) in all prospective study. In
retrospective studies, we can determine how much power of the analysis
(for example, the power of detecting a difference if one existed).
This chapter focuses on how to
estimate sample size for a prospective study (e.g., randomized
controlled trial)
determine how much power we have to detect a difference if one
existed (post hoc analysis)
Sample size
estimation
Before enrolling patients in a clinical trial, we want to make sure
the we have the optimal number of patients for the study. Different
statistical procedures require different optimal sample sizes to attain
the target power. Next we discuss sample size determination for several
commonly used statistical procedures.
Before move forward, let recall two error probabilities associated
with a statistical test of hypothesis \(\text{H}_{\text{0}}\):
\(\alpha = \text{P[type I error]} =
\text{P[reject Ho | Ho is true]}\) = false positive rate
\(\beta = \text{P[type II error]} =
\text{P[fail to reject Ho | Ho is false]}\) = false negative.
\(\text{power of a test} = 1 - \beta
=\text{P[reject Ho | Ho is false]}\)
Several observations about \(\alpha\) and \(\beta\):
In general, if more than one test for testing a given hypothesis
\(Ho\) under the same \(\alpha\), the one that achieves the lowest
\(\beta\) is the best test. This tells
the relationship among estimated \(\alpha\), \(\beta\), power, and the sample size \(n\).
Sample size estimations for two proportions
This is a common sample size calculation when you have two groups and
the outcome is dichotomous (e.g., Yes / No) Assume that we have a study
that aims to estimate the efficacy of Treatment A versus Treatment B.
The main end point is a dichotomous variable: “Response” or “No
response.”
The null hypothesis is:
\(H_{0}\): There is no difference in
the proportion of responders between Treatment A and Treatment B
The alternative hypothesis is:
\(H_{a}\): There is a difference in
the proportion of responders between Treatment A and Treatment B
To determine the sample size needed to detect a meaningful difference
in the proportion of responders between Treatment A and Treatment B, we
need the following information:
\(\alpha\)
level (type I error) is the threshold where we make the
determination whether something is statistically significantly
different. We normally use an alpha level of 0.05 (type I
error).
Effect size is the standardized difference one
would expect to see between treatment groups. This is an estimate and
something that is usually based on past studies.
Power (1 - \(\beta\)) is the ability to
correctly reject the null hypothesis if the actual effect of the
population is equal to or greater than the specified effect
size.
We’ll set the two-tailed alpha level to 0.05 estimate size \(h\) using the following equation:
\[
h = \varphi_{1} - \varphi_{2}
\] where \(\varphi_{i} = 2 *
arcsine(\sqrt{p_{i}})\) and \(p_{i}\) denotes the proportion in treatment
\(i\) that were classified as
“responders.” In generally, the power is set to 80%.
With these pieces of information, we can estimate the sample size for
a study with two proportions as the outcome using the following
formula:
\[
\begin{aligned}
n_{i} = \frac{(Z_{\alpha/2} + Z_{1 - \beta})^2 + (p_{1}(1 - p_{1})) +
(p_{2}(1 - p_{2}))}{(p_{1} - p_{2})^2}
\end{aligned}
\]
where \(n_{i}\) is the sample size
for one group.
Use the pwr.2p.test()
function in
library("pwr")
to find out optimal sample size that meet the
requirements on the alpha level (alpha = 0.05
), effect size
\(h\), and power level
(power = 80%
).
Example 1: We consider Treatment A and Treatment B
in a survey study. Set Treatment B as the reference (e.g., control) with
50% response rate. Assume that Treatment A is slightly better with a
response rate of 60%. With these pieces of information, we can estimate
the sample size required to detect a difference in “response” rate
between Treatment A and Treatment B that is 10% (\(p_{1}\) - \(p_{2}\)) with an alpha of 5% and power of
80%.
### alpha = sig.level option and is equal to 0.05
### power = 0.80
### p1 = 0.60
### p2 = 0.50
power1 <-pwr.2p.test(h = ES.h(p1 = 0.60, p2 = 0.50), sig.level = 0.05, power = .80)
power1
Difference of proportion power calculation for binomial distribution (arcsine transformation)
h = 0.2013579
n = 387.1677
sig.level = 0.05
power = 0.8
alternative = two.sided
NOTE: same sample sizes
The effect size h
is 0.201, and the sample
n
is 387.2 or 388 rounded to the nearest whole number. This
n
is only for one group. Hence, based on the parameters of
our study, we need approximately 388 patients in Treatment A and 388
patients in Treatment B to detect a difference of 10% response or
greater with an alpha of 0.05 and power of 80%.
Power analysis for
two proportions
Power (1 - \(\beta\)) is the ability
to correctly reject the null hypothesis if the actual effect of the
population is equal to or greater than the specified effect size. In
other words, if you conclude that there is no difference in the sample,
then there is no true difference in the population conditioned on the
specified effect size
We can also use the plot feature to see how the power level changes
with varying sample sizes. As the sample size goes up, power increases.
As the sample size goes down, power decreases. This is important to
understand. As we increase our sample size, we reduce the uncertainty
around the estimates. By reducing this uncertainty, we gain greater
precision in our estimates, which results in greater confidence in our
ability to avoid making a type II error.
### We can plot the power relative to different levels of the sample size.
plot(power1)

Let’s change the \(p_{i}\) and see
how the power level change; we are fixing our sample size at 388 for
each group with an alpha of 0.05.
We create a sequence of values by varying the proportion of
“responders” for Treatment A. We will change these from 50% to 100% in
intervals of 5%.
p1 <- seq(0.5, 1.0, 0.05)
power1 <-pwr.2p.test(h = ES.h(p1 = p1, p2 = 0.50),
n = 388,
sig.level = 0.05)
powerchange <- data.frame(p1, power = power1$power * 100)
plot(powerchange$p1,
powerchange$power,
type = "b",
xlab = "Proportion of Responders in Treatment A",
ylab = "Power (%)")

We can also write a function for this:
iteration <- function(p_i, P_i, i_i, p2, n, alpha) {
p1 <- seq(p_i, P_i, i_i)
power1 <-pwr.2p.test(h = ES.h(p1 = p1, p2 = p2),
n = n,
sig.level = alpha)
powerchange <- data.frame(p1, power = power1$power * 100)
powerchange
}
iteration(0.5, 1.0, 0.05, 0.50, 388, 0.05)
p1 power
1 0.50 5.00000
2 0.55 28.65038
3 0.60 80.08415
4 0.65 98.88117
5 0.70 99.99190
6 0.75 100.00000
7 0.80 100.00000
8 0.85 100.00000
9 0.90 100.00000
10 0.95 100.00000
11 1.00 100.00000
Sample size estimations
for two averages
This is another common sample size estimation for two groups when the
outcome is a continuous variable.
Now let’s estimate the sample size for a study where we are comparing
the averages between two groups. Let’s suppose that we are working on a
randomized controlled trial that seeks to evaluate the difference in the
average change in hemogloblin A1c (HbA1c) from baseline between
Treatment A and Treatment B.
The null hypothesis is:
\(H_{0}\): There is no difference in
the average change in HbA1c from baseline between Treatment A and
Treatment B
The alternative hypothesis is:
\(H_{a}\): There is a difference in
the average change in HbA1c from baseline between Treatment A and
Treatment B
To determine the sample size needed to detect a meaningful difference
in the average HbA1c change from baseline between Treatment A and
Treatment B, we can use the following formula:
\[
\begin{aligned}
n_{i} = \frac{2 \sigma^2 * (Z_{\alpha/2} + Z_{1 - \beta})^2}{({\mu_{1} -
\mu_{2}})^2}
\end{aligned}
\]
where \(n_{i}\) is the sample size
for one of the groups, \(\mu_{1}\) and
\(\mu_{2}\) are the average changes in
HbA1c from baseline for Treatment A and Treatment B, respectively.
As usual, we’ll set the two-tailed alpha level to 0.05. The effect
size, also known as Cohen’s \(d\), is
estimated using the following equation:
\[
\begin{aligned}
d = \frac{\mu_{1} - \mu_{2}}{\sigma_{pooled}}
\end{aligned}
\]
The pooled standard deviation is estimated using the following
formula:
\[
\begin{aligned}
\sigma_{pooled} = \sqrt{\frac{sd_{1}^2 + sd_{2}^2}{2}}
\end{aligned}
\]
Once again, the R pwr
package can make this task easy
for us. However, we’ll need to estimate the Cohen’s \(d\).
Example 2: Since we haven’t started the study, we
have to make some assumptions of about each treatment strategy’s change
in HbA1c. Let’s assume that the expected average change in HbA1c from
baseline for Treatment A was 1.5% with a standard deviation of 0.25%.
Additionally, let’s assume that the expected average change in HbA1c
from baseline for Treatment B was 1.0% with a standard deviation of
0.20.
First, we’ll calculate the pooled standard deviation (\(\sigma_{pooled}\)):
sd1 = 0.25
sd2 = 0.30
sd.pooled = sqrt((sd1^2 +sd2^2) / 2)
sd.pooled
[1] 0.276134
Once we have the \(\sigma_{pooled}\), we can estimate the
Cohen’s \(d\):
mu1 = 1.5
mu2 = 1.0
d = (mu1 - mu2) / sd.pooled
d
[1] 1.810715
The Cohen’s \(d\) is 1.81, which is
considered a large effect size.
Now, we can take advantage of the pwr
package and
estimate the sample size needed to detect a difference of 0.5% (1.5% -
1.0%) in the average HbA1c change from baseline between Treatment A and
Treatment B with 80% power and a significance threshold of 5%.
### d = Cohen's d
### power = 0.80
### alpha = 0.05
n.i <- pwr.t.test(d = d, power = 0.80, sig.level = 0.05)
n.i
Two-sample t test power calculation
n = 5.921286
d = 1.810715
sig.level = 0.05
power = 0.8
alternative = two.sided
NOTE: n is number in *each* group
Based on our study parameters, we need 6 patients in each group to
detect a difference of 0.5% or greater with 80% power and a significance
threshold of 5%.
Power analysis for two
averages
Power (1 - \(\beta\)) is the ability to correctly reject
the null hypothesis if the actual effect of the population is equal to
or greater than the specified effect size.
We can plot how the power will change as the sample size changes. As
the sample size increases, power increases. This should make sense. Like
our previous example with two proportions, as we increase our sample
size, we reduce the uncertainty around the estimates. By reducing this
uncertainty, we gain greater precision in our estimates, which results
in greater confidence in our ability to avoid making a type II
error.
### We can plot the power relative to different levels of the sample size.
n <- seq(1, 10, 1)
nchange <- pwr.t.test(d = d, n = n, sig.level = 0.05)
nchange.df <- data.frame(n, power = nchange$power * 100)
nchange.df
n power
1 1 NaN
2 2 19.03307
3 3 39.61785
4 4 57.33850
5 5 70.87945
6 6 80.64997
7 7 87.42531
8 8 91.98145
9 9 94.96979
10 10 96.88938
plot(nchange.df$n,
nchange.df$power,
type = "b",
xlab = "Sample size, n",
ylab = "Power (%)")


As the sample size increases, our power increases. This makes sense
because we have more patients to detect differences that may be smaller.
But we fixed our effect size (Cohen’s \(d\)), so as we increase the sample size,
our power to detect that difference ultimately increases.
Let’s change the \(\mu_{i}\) and see
how the power level change; we are fixing our sample size at 6 for each
group with an alpha of 0.05.
We create a sequence of values by varying the average change in HbA1c
from baseline for Treatment A. We will change these from 0% to 2% in
intervals of 0.1%.
mu1 <- seq(0.0, 2.0, 0.1)
d <- (mu1 - mu2) / sd.pooled
power1 <- pwr.t.test(d = d, n = 6, sig.level = 0.05)
powerchange <- data.frame(d, power = power1$power * 100)
powerchange
d power
1 -3.621430 99.986261
2 -3.259287 99.898978
3 -2.897144 99.437136
4 -2.535001 97.615372
5 -2.172858 92.271971
6 -1.810715 80.649971
7 -1.448572 61.960800
8 -1.086429 39.817661
9 -0.724286 20.610368
10 -0.362143 8.785855
11 0.000000 5.000000
12 0.362143 8.785855
13 0.724286 20.610368
14 1.086429 39.817661
15 1.448572 61.960800
16 1.810715 80.649971
17 2.172858 92.271971
18 2.535001 97.615372
19 2.897144 99.437136
20 3.259287 99.898978
21 3.621430 99.986261
plot(powerchange$d,
powerchange$power,
type = "b",
xlab = "Cohen's d",
ylab = "Power (%)")

This figure shows how the power changes with Cohen’s \(d\). It has a symmetrical patter because of
negative and positive range associated with Cohen’s \(d\). But the story is the same. As the
effect size increases (negative and positive signs do not matter; we
only care about the absolute values), the power increases. This makes
sense because we only have enough power to detect large differences with
the current sample size (which is fixed in this case). If the
differences are small, then we do not have enough power with the current
sample size of 6.
Sample size estimation
for paired data (before and after)
So far, we discussed how to perform sample size estimations for
“between-groups” comparisons. However, many studies investigate the
“within-group” changes. This are paired data, which means that the
observation for one data point is dependent on another observation. A
common study design where paired data is collected are longitudinal
studies. Theses types of studies involve repeated measure. For example a
pretest posttest study design will measure a data point for a patient at
baseline and then repeat that measurement at another point in time. In
the figure, Patient A has two measurements at \(t_{0}\) and \(t_{f}\). Since these measurements were made
in the same person, the change is “within” the patient. Alternatively,
we can think of this as a “repeated” measure since the patient had the
measurement performed twice.
When you have a study where you are performing a paired t test, you
can use the same pwr.t.test()
function for a two sample
test from the pwr
package.
Let’s assume that we want to conduct a prospective study measure the
weight change of a cohort of patients who started a diet. You want to
enroll enough patients to detect a 5 lb reduction in the weight 3 weeks
after the diet started. Let’s assume that at baseline the expected
average weight for the cohort was 130 lbs with a standard deviation of
11. After 3 weeks of diet, the expected average weight was 125 lbs with
a standard deviation of 12.
We can estimate the effect size (Cohen’s \(d_{z}\)) for a paired t test.
\[
\begin{aligned}
d_{z} = \frac{ | \mu_{z} |}{\sigma_{z}} = \frac{| \mu_{x} - \mu_{y} | }{
\sqrt{\sigma_{x}^{2} + \sigma_{y}^{2} - 2 \rho_{x, y} \sigma_{x}
\sigma_{y}}}
\end{aligned}
\]
where \(x\) denotes “before” (or
baseline), \(y\) denotes “after”, \(d_{z}\) denotes the Cohen’s \(d\) for paired analysis \(\rho\) denotes the correlation between the
measures before and after the diet. (For simplicity, I use 0.50 if I
don’t have prior information about this correlation.)
### Parameters for paired analysis or a pretest-posttest study design
mu_x <- 130 ### Average weight before the diet (baseline)
mu_y <- 125 ### Average weight after the diet
sd_x <- 11 ### Standard deviation before the diet
sd_y <- 12 ### Standard deviation after the diet
rho <- 0.5 ### Correlation between measures before and after the diet
sd_z <- sqrt(sd_x^2 + sd_y^2 - 2*rho*sd_x*sd_y)
d_z <- abs(mu_x - mu_y) / sd_z
d_z
[1] 0.433555
The Cohen’s \(d_{z}\) is 0.433. We
can input this into the pwr.t.test()
function.
n.paired <- pwr.t.test(d = d_z, power = 0.80, sig.level = 0.05, type = "paired")
n.paired
Paired t test power calculation
n = 43.71557
d = 0.433555
sig.level = 0.05
power = 0.8
alternative = two.sided
NOTE: n is number of *pairs*
We need 44 patients with two measurements (before and after) they
implement their diet to detect a difference of 5 lbs or greater with 80%
power and a significance level of 0.05.
Power analysis of
paired samples (paired t test)
We can plot how the power will change as the sample size changes for
the paired t test analysis. As the sample size increases, power
increases. This should make sense. Like our previous examples, as we
increase our sample size, we reduce the uncertainty around the
estimates. By reducing this uncertainty, we gain greater precision in
our estimates, which results in greater confidence in our ability to
avoid making a type II error.
### We can plot the power relative to different levels of the sample size for paired analysis.
n_z <- seq(1, 80, 5)
n_z.change <- pwr.t.test(d = d_z, n = n_z, sig.level = 0.05, type = "paired")
Warning in qt(sig.level/tside, nu, lower = FALSE): NaNs produced
n_z.change.df <- data.frame(n_z, power = n_z.change$power * 100)
n_z.change.df
n_z power
1 1 NaN
2 6 14.03624
3 11 25.58334
4 16 36.84309
5 21 47.26307
6 26 56.56985
7 31 64.66154
8 36 71.54769
9 41 77.30572
10 46 82.04980
11 51 85.90929
12 56 89.01478
13 61 91.48950
14 66 93.44465
15 71 94.97744
16 76 96.17076
plot(n_z.change.df$n,
n_z.change.df$power,
type = "b",
xlab = "Sample size, n",
ylab = "Power (%)")
As the sample size increases, we generate more power to detect a
difference of 5 lbs with a significance level of 0.05 and a fixed sample
size of 44 patients with two measurements (before and after) they
implement their diet.
Let’s see how power changes when we change the effect size. Let’s
change the average weight after the patients implement their diet.
Instead of an average of 125 lbs, let’s see how the power will change
when we reduce that to 100 lbs.
### Vary the mu_y from 50 lbs to 130 lbs in intervals of 5 lbs.
mu_y <- seq(50, 130, 5)
d_z <- abs(mu_x - mu_y) / sd_z
n_z.change <- pwr.t.test(d = d_z, n = 44, sig.level = 0.05)
n_z.change.df <- data.frame(d_z, power = n_z.change$power * 100)
n_z.change.df
d_z power
1 6.936880 100.00000
2 6.503325 100.00000
3 6.069770 100.00000
4 5.636215 100.00000
5 5.202660 100.00000
6 4.769105 100.00000
7 4.335550 100.00000
8 3.901995 100.00000
9 3.468440 100.00000
10 3.034885 100.00000
11 2.601330 100.00000
12 2.167775 100.00000
13 1.734220 100.00000
14 1.300665 99.99766
15 0.867110 98.03639
16 0.433555 52.03146
17 0.000000 5.00000
plot(n_z.change.df$d_z,
n_z.change.df$power,
type = "b",
xlab = "Cohen's d_z",
ylab = "Power (%)",
xlim = c(0, 2))
When we increase the effect size (Cohen’s \(d_{z}\)), our power goes up; recall that
the sample size is fixed at 44 and significance level is 0.05. But when
the effect size gets smaller (or when the average weight loss shrinks),
we lose power to detect a difference because our sample size is too
small. We’ll need to increase our sample size to have a reasonable power
to detect small differences.
We can also see how power changes when we vary \(\rho\). If we set \(\rho\) = 0, then the Cohen’s \(d_{z}\) = 0.307. If we set \(\rho\) = 1, then the Cohen’s \(d_{z}\) = 5.
mu_x <- 130 ### Average weight before the diet (baseline)
mu_y <- 125 ### Average weight after the diet
sd_x <- 11 ### Standard deviation before the diet
sd_y <- 12 ### Standard deviation after the diet
sd_z_1 <- sqrt(sd_x^2 + sd_y^2 - 2*1*sd_x*sd_y)
sd_z_0 <- sqrt(sd_x^2 + sd_y^2 - 2*0*sd_x*sd_y)
d_z_1 <- abs(mu_x - mu_y) / sd_z_1
d_z_0 <- abs(mu_x - mu_y) / sd_z_0
d_z_1
[1] 5
d_z_0
[1] 0.3071476
So, higher \(\rho\) results in large
\(d_{z}\) and smaller \(\rho\) results in small \(d_{z}\) values.
Let’s see how power changes when we change the \(\rho\) range from 0 to 1 in intervals of
0.1 units.
rho <- seq(0.0, 1.0, 0.1)
sd_z <- sqrt(sd_x^2 + sd_y^2 - 2*rho*sd_x*sd_y)
d_z <- abs(mu_x - mu_y) / sd_z
rho.change <- pwr.t.test(d = d_z, n = 44, sig.level = 0.05)
rho.change.df <- data.frame(d_z, power = rho.change$power * 100)
rho.change.df
d_z power
1 0.3071476 29.65480
2 0.3236941 32.35129
3 0.3432395 35.66281
4 0.3668151 39.80733
5 0.3960280 45.10546
6 0.4335550 52.03146
7 0.4842743 61.25990
8 0.5583195 73.54735
9 0.6816774 88.52181
10 0.9552009 99.32401
11 5.0000000 100.00000
plot(rho.change.df$d_z,
rho.change.df$power,
type = "b",
xlab = "Cohen's d_z",
ylab = "Power (%)",
xlim = c(0, 1.5))
As \(\rho\) increases, our power
increases. This makes sense because we are nearing “perfect”
correlation, which would require less sample to detect a difference if
one existed. As the correlation becomes less “perfect” our power drops
suggesting that we need to increase our sample size to make up for this
poor correlation.
Power analysis with
unequal sample sizes
It is common for the sample size to be different. The
pwr.t2n.test()
is a useful tool to help estimate the power
given the sample sizes of the study.
It is common to perform power analysis on a study where the sample
sizes between groups are different.
Suppose you have a retrospective study where the patients were
prescribed Treatment A and Treatment B. There were 130 patients in
Treatment A (\(n_{A}\) = 130) and 120
patients in Treatment B (\(n_{B}\) =
120). The average change in HbA1c was 1.5% with a standard deviation of
1.25% in Treatment A, and the average change in HbA1c was 1.4% with a
standard deviation of 1.01% in Treatment B.
First, we’ll calculate the pooled standard deviation (\(\sigma_{pooled}\)):
sd1 <- 1.25
sd2 <- 1.01
sd_pooled <- sqrt((sd1^2 +sd2^2) / 2)
sd_pooled
[1] 1.136354
Once we have the \(\sigma_{pooled}\), we can estimate the
Cohen’s \(d\):
mu1 <- 1.5
mu2 <- 1.4
d <- (mu1 - mu2) / sd_pooled
d
[1] 0.08800076
Now, we can estimate the power with the different sample sizes across
the groups (\(n_{A}\) = 130, \(n_{B}\) = 120).
n1 <- 130
n2 <- 120
power.diff_n <- pwr.t2n.test(d = d, n1 = n1, n2 = n2, sig.level = 0.05)
power.diff_n
t test power calculation
n1 = 130
n2 = 120
d = 0.08800076
sig.level = 0.05
power = 0.1064836
alternative = two.sided
Since the average HbA1c change from baseline for Treatment A is 1.5%
and 1.4% for Treatment B, the average difference in the HbA1c change
from baseline is 0.1%. This is a difference (difference between the
groups) of the differences (difference from baseline within the group)
calculation.
You only have 11% power to detect a difference of 0.10% or greater in
the HbA1c change from baseline. This means that you are underpowered to
detect a difference of 0.10% or greater in the HbA1c change from
baseline with \(n_{A}\) = 130, \(n_{B}\) = 120, and a significance level of
0.05. When studies are underpowered, there is a high potential for type
II error. The only way to address this problem is to enroll more
patients or expand the sample by relaxing inclusion criteria. But this
may increase the threats to the study’s internal validity.
Conclusions
Sample size estimations and power analysis are very useful tools to
determine how many patients you need in your study and how confident you
are that you didn’t make a type II error. Depending on the type of
study, you will need to use different functions from the
pwr
package. I highly encourage you to explore the other
functions of the pwr
package to see if those fit the study
design you have planned.
LS0tDQp0aXRsZTogJ1NhbXBsZSBTaXplIGFuZCBQb3dlciBDYWxjdWxhdGlvbicNCmF1dGhvcjogJ0NoZW5nIFBlbmcnDQpkYXRlOiAiV2VzdCBDaGVzdGVyIFVuaXZlcnNpdHkiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBmaWdfd2lkdGg6IDYNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICB0aGVtZTogcmVhZGFibGUNCiAgICBmaWdfaGVpZ2h0OiA0DQogIHdvcmRfZG9jdW1lbnQ6IA0KICAgIHRvYzogbm8NCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiBubw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogNQ0KICAgIGZpZ19oZWlnaHQ6IDQNCiAgZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCmgxLnRpdGxlIHsNCiAgZm9udC1zaXplOiAyMHB4Ow0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDEgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjJweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMiB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE1cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KPC9zdHlsZT4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgiSVN3UiIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJJU3dSIikNCiAgIGxpYnJhcnkoSVN3UikNCn0NCmlmICghcmVxdWlyZSgiTUFTUyIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJNQVNTIikNCiAgIGxpYnJhcnkoTUFTUykNCn0NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgiZm9yZWNhc3QiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiZm9yZWNhc3QiKQ0KICAgbGlicmFyeShmb3JlY2FzdCkNCn0NCmlmICghcmVxdWlyZSgidHVmdGUiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygidHVmdGUiKQ0KICAgbGlicmFyeSh0dWZ0ZSkNCn0NCmlmICghcmVxdWlyZSgicHdyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInB3ciIpDQogICBsaWJyYXJ5KHB3cikNCn0NCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5ncyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEpDQpgYGANCg0KDQojIEludHJvZHVjdGlvbg0KDQpFc3RpbWF0aW5nIHRoZSBzYW1wbGUgc2l6ZSBmb3IgYSBwcm9zcGVjdGl2ZSBzdHVkeSBpcyBvbmUgb2YgdGhlIGZpcnN0IG1vc3QgaW1wb3J0YW50IHRhc2tzIGluIGNsYXNzaWNhbCBzdGF0aXN0aWNzLiBJbiBjbGluaWNhbCBzdHVkaWVzLCByZXNlYXJjaGVycyBuZWVkIHRvIGRldGVybWluZSB0aGUgbnVtYmVyIG9mIHN1YmplY3RzIHRvIGVucm9sbCBpbiBhIGNsaW5pY2FsIHRyaWFsIHRvIGd1YXJhbnRlZSB0aGUgcmVsaWFiaWxpdHkgb2YgdGhlIHN0dWR5IHJlc3VsdHMuIElmIHRoZSBzYW1wbGUgc2l6ZSBpcyB0b28gc21hbGwsIGl0IHdpbGwgbm90IGJlIGFibGUgdG8gYWNoaWV2ZSB0aGUgcG93ZXIgb2YgdGhlIGFuYWx5c2lzLiBJZiB0aGUgc2l6ZSBleGNlc3NpdmVseSBsYXJnZXIgdGhhbiBuZWVkZWQsIGl0IHdpbGwgd2FzdGUgcmVzb3VyY2VzLg0KDQoNCkVzdGltYXRpbmcgdGhlIG9wdGltYWwgbnVtYmVyIG9mIHBhdGllbnRzIGlzIG5lY2Vzc2FyeSBmb3IgZGV2ZWxvcGluZyBhIFN0YXRpc3RpY2FsIEFuYWx5c2lzIFBsYW4gKFNBUCkgaW4gYWxsIHByb3NwZWN0aXZlIHN0dWR5LiBJbiByZXRyb3NwZWN0aXZlIHN0dWRpZXMsIHdlIGNhbiBkZXRlcm1pbmUgaG93IG11Y2ggcG93ZXIgb2YgdGhlIGFuYWx5c2lzIChmb3IgZXhhbXBsZSwgdGhlIHBvd2VyIG9mIGRldGVjdGluZyBhIGRpZmZlcmVuY2UgaWYgb25lIGV4aXN0ZWQpLiANCg0KDQpUaGlzIGNoYXB0ZXIgZm9jdXNlcyBvbiBob3cgdG8gDQoNCjEpIGVzdGltYXRlIHNhbXBsZSBzaXplIGZvciBhIHByb3NwZWN0aXZlIHN0dWR5IChlLmcuLCByYW5kb21pemVkIGNvbnRyb2xsZWQgdHJpYWwpIA0KDQoyKSBkZXRlcm1pbmUgaG93IG11Y2ggcG93ZXIgd2UgaGF2ZSB0byBkZXRlY3QgYSBkaWZmZXJlbmNlIGlmIG9uZSBleGlzdGVkIChwb3N0IGhvYyBhbmFseXNpcykNCg0KDQoNCg0KDQoNCg0KIyBTYW1wbGUgc2l6ZSBlc3RpbWF0aW9uDQoNCkJlZm9yZSBlbnJvbGxpbmcgcGF0aWVudHMgaW4gYSBjbGluaWNhbCB0cmlhbCwgd2Ugd2FudCB0byBtYWtlIHN1cmUgdGhlIHdlIGhhdmUgdGhlIG9wdGltYWwgbnVtYmVyIG9mIHBhdGllbnRzIGZvciB0aGUgc3R1ZHkuIERpZmZlcmVudCBzdGF0aXN0aWNhbCBwcm9jZWR1cmVzIHJlcXVpcmUgZGlmZmVyZW50IG9wdGltYWwgc2FtcGxlIHNpemVzIHRvIGF0dGFpbiB0aGUgdGFyZ2V0IHBvd2VyLiBOZXh0IHdlIGRpc2N1c3Mgc2FtcGxlIHNpemUgZGV0ZXJtaW5hdGlvbiBmb3Igc2V2ZXJhbCBjb21tb25seSB1c2VkIHN0YXRpc3RpY2FsIHByb2NlZHVyZXMuDQoNCkJlZm9yZSBtb3ZlIGZvcndhcmQsIGxldCByZWNhbGwgdHdvIGVycm9yIHByb2JhYmlsaXRpZXMgYXNzb2NpYXRlZCB3aXRoIGEgc3RhdGlzdGljYWwgdGVzdCBvZiBoeXBvdGhlc2lzICRcdGV4dHtIfV97XHRleHR7MH19JDoNCg0KJFxhbHBoYSA9IFx0ZXh0e1BbdHlwZSBJIGVycm9yXX0gPSBcdGV4dHtQW3JlamVjdCBIbyB8IEhvIGlzIHRydWVdfSQgPSAgZmFsc2UgcG9zaXRpdmUgcmF0ZQ0KDQokXGJldGEgPSBcdGV4dHtQW3R5cGUgSUkgZXJyb3JdfSA9IFx0ZXh0e1BbZmFpbCB0byByZWplY3QgSG8gfCBIbyBpcyBmYWxzZV19JCA9IGZhbHNlIG5lZ2F0aXZlLg0KDQokXHRleHR7cG93ZXIgb2YgYSB0ZXN0fSA9IDEgLSBcYmV0YSA9XHRleHR7UFtyZWplY3QgSG8gfCBIbyBpcyBmYWxzZV19JA0KDQpTZXZlcmFsIG9ic2VydmF0aW9ucyBhYm91dCAkXGFscGhhJCBhbmQgJFxiZXRhJDoNCg0KKiAkYWxwaGEkIGFuZCAkXGJldGEkIGFyZSBuZWdhdGl2ZWx5IGRlcGVuZGVudCBvbiBlYWNoIG90aGVyIChub3QgbGluZWFybHkgZGVwZW5kZW50KS4gDQoNCiogRXN0aW1hdGVkICRhbHBoYSQgYW5kICRcYmV0YSQgYXJlIGRlcGVuZGVudCBvbiB0aGUgc2FtcGxlIHNpemUuDQoNCg0KPiBJbiBnZW5lcmFsLCBpZiBtb3JlIHRoYW4gb25lIHRlc3QgZm9yIHRlc3RpbmcgYSBnaXZlbiBoeXBvdGhlc2lzICRIbyQgdW5kZXIgdGhlIHNhbWUgJFxhbHBoYSQsIHRoZSBvbmUgdGhhdCBhY2hpZXZlcyB0aGUgbG93ZXN0ICRcYmV0YSQgaXMgdGhlIGJlc3QgdGVzdC4gVGhpcyB0ZWxscyB0aGUgcmVsYXRpb25zaGlwIGFtb25nIGVzdGltYXRlZCAkXGFscGhhJCwgJFxiZXRhJCwgcG93ZXIsIGFuZCB0aGUgc2FtcGxlIHNpemUgJG4kLg0KDQoNClNhbXBsZSBzaXplIGVzdGltYXRpb25zIGZvciAqKnR3byBwcm9wb3J0aW9ucyoqDQoNClRoaXMgaXMgYSBjb21tb24gc2FtcGxlIHNpemUgY2FsY3VsYXRpb24gd2hlbiB5b3UgaGF2ZSB0d28gZ3JvdXBzIGFuZCB0aGUgb3V0Y29tZSBpcyBkaWNob3RvbW91cyAoZS5nLiwgWWVzIC8gTm8pDQpBc3N1bWUgdGhhdCB3ZSBoYXZlIGEgc3R1ZHkgdGhhdCBhaW1zIHRvIGVzdGltYXRlIHRoZSBlZmZpY2FjeSBvZiBUcmVhdG1lbnQgQSB2ZXJzdXMgVHJlYXRtZW50IEIuIFRoZSBtYWluIGVuZCBwb2ludCBpcyBhIGRpY2hvdG9tb3VzIHZhcmlhYmxlOiAiUmVzcG9uc2UiIG9yICJObyByZXNwb25zZS4iIA0KDQpUaGUgbnVsbCBoeXBvdGhlc2lzIGlzOg0KDQogJEhfezB9JDogVGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBpbiB0aGUgcHJvcG9ydGlvbiBvZiByZXNwb25kZXJzIGJldHdlZW4gVHJlYXRtZW50IEEgYW5kIFRyZWF0bWVudCBCDQoNClRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIGlzOg0KDQogJEhfe2F9JDogVGhlcmUgaXMgYSBkaWZmZXJlbmNlIGluIHRoZSBwcm9wb3J0aW9uIG9mIHJlc3BvbmRlcnMgYmV0d2VlbiBUcmVhdG1lbnQgQSBhbmQgVHJlYXRtZW50IEINCg0KXA0KDQpUbyBkZXRlcm1pbmUgdGhlIHNhbXBsZSBzaXplIG5lZWRlZCB0byBkZXRlY3QgYSBtZWFuaW5nZnVsIGRpZmZlcmVuY2UgaW4gdGhlIHByb3BvcnRpb24gb2YgcmVzcG9uZGVycyBiZXR3ZWVuIFRyZWF0bWVudCBBIGFuZCBUcmVhdG1lbnQgQiwgd2UgbmVlZCB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uOiANCg0KKiAqKiRcYWxwaGEkIGxldmVsKiogKHR5cGUgSSBlcnJvcikgaXMgdGhlIHRocmVzaG9sZCB3aGVyZSB3ZSBtYWtlIHRoZSBkZXRlcm1pbmF0aW9uIHdoZXRoZXIgc29tZXRoaW5nIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQuIFdlIG5vcm1hbGx5IHVzZSBhbiBhbHBoYSBsZXZlbCBvZiAwLjA1ICh0eXBlIEkgZXJyb3IpLiANCg0KKiAqKkVmZmVjdCBzaXplKiogaXMgdGhlIHN0YW5kYXJkaXplZCBkaWZmZXJlbmNlIG9uZSB3b3VsZCBleHBlY3QgdG8gc2VlIGJldHdlZW4gdHJlYXRtZW50IGdyb3Vwcy4gVGhpcyBpcyBhbiBlc3RpbWF0ZSBhbmQgc29tZXRoaW5nIHRoYXQgaXMgdXN1YWxseSBiYXNlZCBvbiBwYXN0IHN0dWRpZXMuIA0KDQoqICoqUG93ZXIgKDEgLSAkXGJldGEkKSoqIGlzIHRoZSBhYmlsaXR5IHRvIGNvcnJlY3RseSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBpZiB0aGUgYWN0dWFsIGVmZmVjdCBvZiB0aGUgcG9wdWxhdGlvbiBpcyBlcXVhbCB0byBvciBncmVhdGVyIHRoYW4gdGhlIHNwZWNpZmllZCBlZmZlY3Qgc2l6ZS4gDQoNCg0KV2UnbGwgc2V0IHRoZSB0d28tdGFpbGVkIGFscGhhIGxldmVsIHRvIDAuMDUgZXN0aW1hdGUgc2l6ZSAkaCQgdXNpbmcgdGhlIGZvbGxvd2luZyBlcXVhdGlvbjoNCg0KICQkDQogaCA9IFx2YXJwaGlfezF9IC0gXHZhcnBoaV97Mn0NCiAkJA0Kd2hlcmUgJFx2YXJwaGlfe2l9ID0gMiAqIGFyY3NpbmUoXHNxcnR7cF97aX19KSQgYW5kICRwX3tpfSQgZGVub3RlcyB0aGUgcHJvcG9ydGlvbiBpbiB0cmVhdG1lbnQgJGkkIHRoYXQgd2VyZSBjbGFzc2lmaWVkIGFzICJyZXNwb25kZXJzLiIgSW4gZ2VuZXJhbGx5LCAgdGhlIHBvd2VyIGlzIHNldCB0byA4MCUuIA0KDQoNCldpdGggdGhlc2UgcGllY2VzIG9mIGluZm9ybWF0aW9uLCB3ZSBjYW4gZXN0aW1hdGUgdGhlIHNhbXBsZSBzaXplIGZvciBhIHN0dWR5IHdpdGggdHdvIHByb3BvcnRpb25zIGFzIHRoZSBvdXRjb21lIHVzaW5nIHRoZSBmb2xsb3dpbmcgZm9ybXVsYToNCg0KDQokJA0KXGJlZ2lue2FsaWduZWR9DQpuX3tpfSA9IFxmcmFjeyhaX3tcYWxwaGEvMn0gKyBaX3sxIC0gXGJldGF9KV4yICsgKHBfezF9KDEgLSBwX3sxfSkpICsgKHBfezJ9KDEgLSBwX3syfSkpfXsocF97MX0gLSBwX3syfSleMn0NClxlbmR7YWxpZ25lZH0NCiQkDQoNCg0Kd2hlcmUgJG5fe2l9JCBpcyB0aGUgc2FtcGxlIHNpemUgZm9yIG9uZSBncm91cC4gDQoNCg0KVXNlIHRoZSBgcHdyLjJwLnRlc3QoKWAgZnVuY3Rpb24gaW4gYGxpYnJhcnkoInB3ciIpYHRvIGZpbmQgb3V0IG9wdGltYWwgc2FtcGxlIHNpemUgdGhhdCBtZWV0IHRoZSByZXF1aXJlbWVudHMgb24gdGhlIGFscGhhIGxldmVsIChgYWxwaGEgPSAwLjA1YCksIGVmZmVjdCBzaXplICRoJCwgYW5kIHBvd2VyIGxldmVsIChgcG93ZXIgPSA4MCVgKS4gDQoNCg0KKipFeGFtcGxlIDEqKjogV2UgY29uc2lkZXIgVHJlYXRtZW50IEEgYW5kIFRyZWF0bWVudCBCIGluIGEgc3VydmV5IHN0dWR5LiBTZXQgVHJlYXRtZW50IEIgYXMgdGhlIHJlZmVyZW5jZSAoZS5nLiwgY29udHJvbCkgd2l0aCA1MCUgcmVzcG9uc2UgcmF0ZS4gQXNzdW1lIHRoYXQgVHJlYXRtZW50IEEgaXMgc2xpZ2h0bHkgYmV0dGVyIHdpdGggYSByZXNwb25zZSByYXRlIG9mIDYwJS4gV2l0aCB0aGVzZSBwaWVjZXMgb2YgaW5mb3JtYXRpb24sIHdlIGNhbiBlc3RpbWF0ZSB0aGUgc2FtcGxlIHNpemUgcmVxdWlyZWQgdG8gZGV0ZWN0IGEgZGlmZmVyZW5jZSBpbiAicmVzcG9uc2UiIHJhdGUgYmV0d2VlbiBUcmVhdG1lbnQgQSBhbmQgVHJlYXRtZW50IEIgdGhhdCBpcyAxMCUgKCRwX3sxfSQgLSAkcF97Mn0kKSB3aXRoIGFuIGFscGhhIG9mIDUlIGFuZCBwb3dlciBvZiA4MCUuIA0KDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCiMjIyBhbHBoYSA9IHNpZy5sZXZlbCBvcHRpb24gYW5kIGlzIGVxdWFsIHRvIDAuMDUNCiMjIyBwb3dlciA9IDAuODANCiMjIyBwMSA9IDAuNjAgDQojIyMgcDIgPSAwLjUwDQpwb3dlcjEgPC1wd3IuMnAudGVzdChoID0gRVMuaChwMSA9IDAuNjAsIHAyID0gMC41MCksIHNpZy5sZXZlbCA9IDAuMDUsIHBvd2VyID0gLjgwKQ0KcG93ZXIxDQpgYGANCg0KVGhlIGVmZmVjdCBzaXplIGBoYCBpcyAwLjIwMSwgYW5kIHRoZSBzYW1wbGUgYG5gIGlzIDM4Ny4yIG9yIDM4OCByb3VuZGVkIHRvIHRoZSBuZWFyZXN0IHdob2xlIG51bWJlci4gVGhpcyBgbmAgaXMgb25seSBmb3Igb25lIGdyb3VwLiBIZW5jZSwgYmFzZWQgb24gdGhlIHBhcmFtZXRlcnMgb2Ygb3VyIHN0dWR5LCB3ZSBuZWVkIGFwcHJveGltYXRlbHkgMzg4IHBhdGllbnRzIGluIFRyZWF0bWVudCBBIGFuZCAzODggcGF0aWVudHMgaW4gVHJlYXRtZW50IEIgdG8gZGV0ZWN0IGEgZGlmZmVyZW5jZSBvZiAxMCUgcmVzcG9uc2Ugb3IgZ3JlYXRlciB3aXRoIGFuIGFscGhhIG9mIDAuMDUgYW5kIHBvd2VyIG9mIDgwJS4gDQoNCg0KIyBQb3dlciBhbmFseXNpcyBmb3IgKip0d28gcHJvcG9ydGlvbnMqKg0KDQoNClBvd2VyICgxIC0gJFxiZXRhJCkgaXMgdGhlIGFiaWxpdHkgdG8gY29ycmVjdGx5IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGlmIHRoZSBhY3R1YWwgZWZmZWN0IG9mIHRoZSBwb3B1bGF0aW9uIGlzIGVxdWFsIHRvIG9yIGdyZWF0ZXIgdGhhbiB0aGUgc3BlY2lmaWVkIGVmZmVjdCBzaXplLiBJbiBvdGhlciB3b3JkcywgaWYgeW91IGNvbmNsdWRlIHRoYXQgdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBpbiB0aGUgc2FtcGxlLCB0aGVuIHRoZXJlIGlzIG5vIHRydWUgZGlmZmVyZW5jZSBpbiB0aGUgcG9wdWxhdGlvbiBjb25kaXRpb25lZCBvbiB0aGUgc3BlY2lmaWVkIGVmZmVjdCBzaXplDQoNCg0KV2UgY2FuIGFsc28gdXNlIHRoZSBwbG90IGZlYXR1cmUgdG8gc2VlIGhvdyB0aGUgcG93ZXIgbGV2ZWwgY2hhbmdlcyB3aXRoIHZhcnlpbmcgc2FtcGxlIHNpemVzLiBBcyB0aGUgc2FtcGxlIHNpemUgZ29lcyB1cCwgcG93ZXIgaW5jcmVhc2VzLiBBcyB0aGUgc2FtcGxlIHNpemUgZ29lcyBkb3duLCBwb3dlciBkZWNyZWFzZXMuIFRoaXMgaXMgaW1wb3J0YW50IHRvIHVuZGVyc3RhbmQuIEFzIHdlIGluY3JlYXNlIG91ciBzYW1wbGUgc2l6ZSwgd2UgcmVkdWNlIHRoZSB1bmNlcnRhaW50eSBhcm91bmQgdGhlIGVzdGltYXRlcy4gQnkgcmVkdWNpbmcgdGhpcyB1bmNlcnRhaW50eSwgd2UgZ2FpbiBncmVhdGVyIHByZWNpc2lvbiBpbiBvdXIgZXN0aW1hdGVzLCB3aGljaCByZXN1bHRzIGluIGdyZWF0ZXIgY29uZmlkZW5jZSBpbiBvdXIgYWJpbGl0eSB0byBhdm9pZCBtYWtpbmcgYSB0eXBlIElJIGVycm9yLiANCg0KDQpgYGB7cn0NCiMjIyBXZSBjYW4gcGxvdCB0aGUgcG93ZXIgcmVsYXRpdmUgdG8gZGlmZmVyZW50IGxldmVscyBvZiB0aGUgc2FtcGxlIHNpemUuIA0KcGxvdChwb3dlcjEpDQpgYGANCg0KDQpMZXQncyBjaGFuZ2UgdGhlICRwX3tpfSQgYW5kIHNlZSBob3cgdGhlIHBvd2VyIGxldmVsIGNoYW5nZTsgd2UgYXJlIGZpeGluZyBvdXIgc2FtcGxlIHNpemUgYXQgMzg4IGZvciBlYWNoIGdyb3VwIHdpdGggYW4gYWxwaGEgb2YgMC4wNS4gDQoNCldlIGNyZWF0ZSBhIHNlcXVlbmNlIG9mIHZhbHVlcyBieSB2YXJ5aW5nIHRoZSBwcm9wb3J0aW9uIG9mICJyZXNwb25kZXJzIiBmb3IgVHJlYXRtZW50IEEuIFdlIHdpbGwgY2hhbmdlIHRoZXNlIGZyb20gNTAlIHRvIDEwMCUgaW4gaW50ZXJ2YWxzIG9mIDUlLiANCg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQpwMSA8LSBzZXEoMC41LCAxLjAsIDAuMDUpDQpwb3dlcjEgPC1wd3IuMnAudGVzdChoID0gRVMuaChwMSA9IHAxLCBwMiA9IDAuNTApLA0KICAgICAgICAgICAgICAgICAgICAgbiA9IDM4OCwNCiAgICAgICAgICAgICAgICAgICAgIHNpZy5sZXZlbCA9IDAuMDUpDQpwb3dlcmNoYW5nZSA8LSBkYXRhLmZyYW1lKHAxLCBwb3dlciA9IHBvd2VyMSRwb3dlciAqIDEwMCkNCnBsb3QocG93ZXJjaGFuZ2UkcDEsIA0KICAgICBwb3dlcmNoYW5nZSRwb3dlciwgDQogICAgIHR5cGUgPSAiYiIsIA0KICAgICB4bGFiID0gIlByb3BvcnRpb24gb2YgUmVzcG9uZGVycyBpbiBUcmVhdG1lbnQgQSIsIA0KICAgICB5bGFiID0gIlBvd2VyICglKSIpDQpgYGANCg0KV2UgY2FuIGFsc28gd3JpdGUgYSBmdW5jdGlvbiBmb3IgdGhpczoNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KaXRlcmF0aW9uIDwtIGZ1bmN0aW9uKHBfaSwgUF9pLCBpX2ksIHAyLCBuLCBhbHBoYSkgew0KICAgICAgICAgICAgICBwMSA8LSBzZXEocF9pLCBQX2ksIGlfaSkNCiAgICAgICAgICAgICAgcG93ZXIxIDwtcHdyLjJwLnRlc3QoaCA9IEVTLmgocDEgPSBwMSwgcDIgPSBwMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWcubGV2ZWwgPSBhbHBoYSkNCiAgICAgICAgICAgICAgcG93ZXJjaGFuZ2UgPC0gZGF0YS5mcmFtZShwMSwgcG93ZXIgPSBwb3dlcjEkcG93ZXIgKiAxMDApDQogICAgICAgICAgICAgIHBvd2VyY2hhbmdlDQp9DQoNCml0ZXJhdGlvbigwLjUsIDEuMCwgMC4wNSwgMC41MCwgMzg4LCAwLjA1KQ0KYGBgDQoNCiMgU2FtcGxlIHNpemUgZXN0aW1hdGlvbnMgZm9yICoqdHdvIGF2ZXJhZ2VzKioNCg0KDQpUaGlzIGlzIGFub3RoZXIgY29tbW9uIHNhbXBsZSBzaXplIGVzdGltYXRpb24gZm9yIHR3byBncm91cHMgd2hlbiB0aGUgb3V0Y29tZSBpcyBhIGNvbnRpbnVvdXMgdmFyaWFibGUuDQoNCk5vdyBsZXQncyBlc3RpbWF0ZSB0aGUgc2FtcGxlIHNpemUgZm9yIGEgc3R1ZHkgd2hlcmUgd2UgYXJlIGNvbXBhcmluZyB0aGUgYXZlcmFnZXMgYmV0d2VlbiB0d28gZ3JvdXBzLiBMZXQncyBzdXBwb3NlIHRoYXQgd2UgYXJlIHdvcmtpbmcgb24gYSByYW5kb21pemVkIGNvbnRyb2xsZWQgdHJpYWwgdGhhdCBzZWVrcyB0byBldmFsdWF0ZSB0aGUgZGlmZmVyZW5jZSBpbiB0aGUgYXZlcmFnZSBjaGFuZ2UgaW4gaGVtb2dsb2JsaW4gQTFjIChIYkExYykgZnJvbSBiYXNlbGluZSBiZXR3ZWVuIFRyZWF0bWVudCBBIGFuZCBUcmVhdG1lbnQgQi4gDQoNClwNCg0KVGhlIG51bGwgaHlwb3RoZXNpcyBpczoNCg0KICRIX3swfSQ6IFRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgaW4gdGhlIGF2ZXJhZ2UgY2hhbmdlIGluIEhiQTFjIGZyb20gYmFzZWxpbmUgYmV0d2VlbiBUcmVhdG1lbnQgQSBhbmQgVHJlYXRtZW50IEINCg0KVGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgaXM6DQoNCiAkSF97YX0kOiBUaGVyZSBpcyBhIGRpZmZlcmVuY2UgaW4gdGhlIGF2ZXJhZ2UgY2hhbmdlIGluIEhiQTFjIGZyb20gYmFzZWxpbmUgYmV0d2VlbiBUcmVhdG1lbnQgQSBhbmQgVHJlYXRtZW50IEINCg0KVG8gZGV0ZXJtaW5lIHRoZSBzYW1wbGUgc2l6ZSBuZWVkZWQgdG8gZGV0ZWN0IGEgbWVhbmluZ2Z1bCBkaWZmZXJlbmNlIGluIHRoZSBhdmVyYWdlIEhiQTFjIGNoYW5nZSBmcm9tIGJhc2VsaW5lIGJldHdlZW4gVHJlYXRtZW50IEEgYW5kIFRyZWF0bWVudCBCLCB3ZSBjYW4gdXNlIHRoZSBmb2xsb3dpbmcgZm9ybXVsYToNCg0KDQokJA0KXGJlZ2lue2FsaWduZWR9DQpuX3tpfSA9IFxmcmFjezIgXHNpZ21hXjIgKiAoWl97XGFscGhhLzJ9ICsgWl97MSAtIFxiZXRhfSleMn17KHtcbXVfezF9IC0gXG11X3syfX0pXjJ9DQpcZW5ke2FsaWduZWR9DQokJA0KDQp3aGVyZSAkbl97aX0kIGlzIHRoZSBzYW1wbGUgc2l6ZSBmb3Igb25lIG9mIHRoZSBncm91cHMsICRcbXVfezF9JCBhbmQgJFxtdV97Mn0kIGFyZSB0aGUgYXZlcmFnZSBjaGFuZ2VzIGluIEhiQTFjIGZyb20gYmFzZWxpbmUgZm9yIFRyZWF0bWVudCBBIGFuZCBUcmVhdG1lbnQgQiwgcmVzcGVjdGl2ZWx5Lg0KDQoNCkFzIHVzdWFsLCB3ZSdsbCBzZXQgdGhlIHR3by10YWlsZWQgYWxwaGEgbGV2ZWwgdG8gMC4wNS4gVGhlIGVmZmVjdCBzaXplLCBhbHNvIGtub3duIGFzIENvaGVuJ3MgJGQkLCBpcyBlc3RpbWF0ZWQgdXNpbmcgdGhlIGZvbGxvd2luZyBlcXVhdGlvbjoNCg0KJCQNClxiZWdpbnthbGlnbmVkfQ0KZCA9IFxmcmFje1xtdV97MX0gLSBcbXVfezJ9fXtcc2lnbWFfe3Bvb2xlZH19DQpcZW5ke2FsaWduZWR9DQokJA0KDQpUaGUgcG9vbGVkIHN0YW5kYXJkIGRldmlhdGlvbiBpcyBlc3RpbWF0ZWQgdXNpbmcgdGhlIGZvbGxvd2luZyBmb3JtdWxhOg0KDQoNCg0KJCQNClxiZWdpbnthbGlnbmVkfQ0KXHNpZ21hX3twb29sZWR9ID0gXHNxcnR7XGZyYWN7c2RfezF9XjIgKyBzZF97Mn1eMn17Mn19DQpcZW5ke2FsaWduZWR9DQokJA0KDQpPbmNlIGFnYWluLCB0aGUgUiBgcHdyYCBwYWNrYWdlIGNhbiBtYWtlIHRoaXMgdGFzayBlYXN5IGZvciB1cy4gSG93ZXZlciwgd2UnbGwgbmVlZCB0byBlc3RpbWF0ZSB0aGUgQ29oZW4ncyAkZCQuIA0KDQoqKkV4YW1wbGUgMioqOiBTaW5jZSB3ZSBoYXZlbid0IHN0YXJ0ZWQgdGhlIHN0dWR5LCB3ZSBoYXZlIHRvIG1ha2Ugc29tZSBhc3N1bXB0aW9ucyBvZiBhYm91dCBlYWNoIHRyZWF0bWVudCBzdHJhdGVneSdzIGNoYW5nZSBpbiBIYkExYy4gTGV0J3MgYXNzdW1lIHRoYXQgdGhlIGV4cGVjdGVkIGF2ZXJhZ2UgY2hhbmdlIGluIEhiQTFjIGZyb20gYmFzZWxpbmUgZm9yIFRyZWF0bWVudCBBIHdhcyAxLjUlIHdpdGggYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMC4yNSUuIEFkZGl0aW9uYWxseSwgbGV0J3MgYXNzdW1lIHRoYXQgdGhlIGV4cGVjdGVkIGF2ZXJhZ2UgY2hhbmdlIGluIEhiQTFjIGZyb20gYmFzZWxpbmUgZm9yIFRyZWF0bWVudCBCIHdhcyAxLjAlIHdpdGggYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMC4yMC4gDQoNCkZpcnN0LCB3ZSdsbCBjYWxjdWxhdGUgdGhlIHBvb2xlZCBzdGFuZGFyZCBkZXZpYXRpb24gKCRcc2lnbWFfe3Bvb2xlZH0kKToNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0Kc2QxID0gMC4yNQ0Kc2QyID0gMC4zMA0Kc2QucG9vbGVkID0gc3FydCgoc2QxXjIgK3NkMl4yKSAvIDIpDQpzZC5wb29sZWQNCmBgYA0KDQpPbmNlIHdlIGhhdmUgdGhlICRcc2lnbWFfe3Bvb2xlZH0kLCB3ZSBjYW4gZXN0aW1hdGUgdGhlIENvaGVuJ3MgJGQkOg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQptdTEgPSAxLjUNCm11MiA9IDEuMA0KZCA9IChtdTEgLSBtdTIpIC8gc2QucG9vbGVkDQpkDQpgYGANCg0KVGhlIENvaGVuJ3MgJGQkIGlzIDEuODEsIHdoaWNoIGlzIGNvbnNpZGVyZWQgYSBsYXJnZSBlZmZlY3Qgc2l6ZS4gDQoNCg0KTm93LCB3ZSBjYW4gdGFrZSBhZHZhbnRhZ2Ugb2YgdGhlIGBwd3JgIHBhY2thZ2UgYW5kIGVzdGltYXRlIHRoZSBzYW1wbGUgc2l6ZSBuZWVkZWQgdG8gZGV0ZWN0IGEgZGlmZmVyZW5jZSBvZiAwLjUlICgxLjUlIC0gMS4wJSkgaW4gdGhlIGF2ZXJhZ2UgSGJBMWMgY2hhbmdlIGZyb20gYmFzZWxpbmUgYmV0d2VlbiBUcmVhdG1lbnQgQSBhbmQgVHJlYXRtZW50IEIgd2l0aCA4MCUgcG93ZXIgYW5kIGEgc2lnbmlmaWNhbmNlIHRocmVzaG9sZCBvZiA1JS4gDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCiMjIyBkID0gQ29oZW4ncyBkDQojIyMgcG93ZXIgPSAwLjgwDQojIyMgYWxwaGEgPSAwLjA1DQpuLmkgPC0gcHdyLnQudGVzdChkID0gZCwgcG93ZXIgPSAwLjgwLCBzaWcubGV2ZWwgPSAwLjA1KQ0Kbi5pDQpgYGANCg0KQmFzZWQgb24gb3VyIHN0dWR5IHBhcmFtZXRlcnMsIHdlIG5lZWQgNiBwYXRpZW50cyBpbiBlYWNoIGdyb3VwIHRvIGRldGVjdCBhIGRpZmZlcmVuY2Ugb2YgMC41JSBvciBncmVhdGVyIHdpdGggODAlIHBvd2VyIGFuZCBhIHNpZ25pZmljYW5jZSB0aHJlc2hvbGQgb2YgNSUuIA0KDQoNCiMgUG93ZXIgYW5hbHlzaXMgZm9yIHR3byBhdmVyYWdlcw0KDQoNCioqUG93ZXIqKiAoMSAtICRcYmV0YSQpIGlzIHRoZSBhYmlsaXR5IHRvIGNvcnJlY3RseSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBpZiB0aGUgYWN0dWFsIGVmZmVjdCBvZiB0aGUgcG9wdWxhdGlvbiBpcyBlcXVhbCB0byBvciBncmVhdGVyIHRoYW4gdGhlIHNwZWNpZmllZCBlZmZlY3Qgc2l6ZS4gDQoNCldlIGNhbiBwbG90IGhvdyB0aGUgcG93ZXIgd2lsbCBjaGFuZ2UgYXMgdGhlIHNhbXBsZSBzaXplIGNoYW5nZXMuIEFzIHRoZSBzYW1wbGUgc2l6ZSBpbmNyZWFzZXMsIHBvd2VyIGluY3JlYXNlcy4gVGhpcyBzaG91bGQgbWFrZSBzZW5zZS4gTGlrZSBvdXIgcHJldmlvdXMgZXhhbXBsZSB3aXRoIHR3byBwcm9wb3J0aW9ucywgYXMgd2UgaW5jcmVhc2Ugb3VyIHNhbXBsZSBzaXplLCB3ZSByZWR1Y2UgdGhlIHVuY2VydGFpbnR5IGFyb3VuZCB0aGUgZXN0aW1hdGVzLiBCeSByZWR1Y2luZyB0aGlzIHVuY2VydGFpbnR5LCB3ZSBnYWluIGdyZWF0ZXIgcHJlY2lzaW9uIGluIG91ciBlc3RpbWF0ZXMsIHdoaWNoIHJlc3VsdHMgaW4gZ3JlYXRlciBjb25maWRlbmNlIGluIG91ciBhYmlsaXR5IHRvIGF2b2lkIG1ha2luZyBhIHR5cGUgSUkgZXJyb3IuIA0KDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFfQ0KIyMjIFdlIGNhbiBwbG90IHRoZSBwb3dlciByZWxhdGl2ZSB0byBkaWZmZXJlbnQgbGV2ZWxzIG9mIHRoZSBzYW1wbGUgc2l6ZS4gDQpuIDwtIHNlcSgxLCAxMCwgMSkNCm5jaGFuZ2UgPC0gcHdyLnQudGVzdChkID0gZCwgbiA9IG4sIHNpZy5sZXZlbCA9IDAuMDUpDQpuY2hhbmdlLmRmIDwtIGRhdGEuZnJhbWUobiwgcG93ZXIgPSBuY2hhbmdlJHBvd2VyICogMTAwKQ0KbmNoYW5nZS5kZg0KYGBgDQoNCmBgYHtyfQ0KcGxvdChuY2hhbmdlLmRmJG4sIA0KICAgICBuY2hhbmdlLmRmJHBvd2VyLCANCiAgICAgdHlwZSA9ICJiIiwgDQogICAgIHhsYWIgPSAiU2FtcGxlIHNpemUsIG4iLCANCiAgICAgeWxhYiA9ICJQb3dlciAoJSkiKQ0KYGBgDQoNCg0KYGBge3IsIGZpZy5tYXJnaW4gPSBUUlVFLCBlY2hvPSBGQUxTRX0NCnBsb3Qobi5pKQ0KYGBgDQoNCkFzIHRoZSBzYW1wbGUgc2l6ZSBpbmNyZWFzZXMsIG91ciBwb3dlciBpbmNyZWFzZXMuIFRoaXMgbWFrZXMgc2Vuc2UgYmVjYXVzZSB3ZSBoYXZlIG1vcmUgcGF0aWVudHMgdG8gZGV0ZWN0IGRpZmZlcmVuY2VzIHRoYXQgbWF5IGJlIHNtYWxsZXIuIEJ1dCB3ZSBmaXhlZCBvdXIgZWZmZWN0IHNpemUgKENvaGVuJ3MgJGQkKSwgc28gYXMgd2UgaW5jcmVhc2UgdGhlIHNhbXBsZSBzaXplLCBvdXIgcG93ZXIgdG8gZGV0ZWN0IHRoYXQgZGlmZmVyZW5jZSB1bHRpbWF0ZWx5IGluY3JlYXNlcy4gDQoNCkxldOKAmXMgY2hhbmdlIHRoZSAkXG11X3tpfSQgYW5kIHNlZSBob3cgdGhlIHBvd2VyIGxldmVsIGNoYW5nZTsgd2UgYXJlIGZpeGluZyBvdXIgc2FtcGxlIHNpemUgYXQgNiBmb3IgZWFjaCBncm91cCB3aXRoIGFuIGFscGhhIG9mIDAuMDUuDQoNCg0KV2UgY3JlYXRlIGEgc2VxdWVuY2Ugb2YgdmFsdWVzIGJ5IHZhcnlpbmcgdGhlIGF2ZXJhZ2UgY2hhbmdlIGluIEhiQTFjIGZyb20gYmFzZWxpbmUgZm9yIFRyZWF0bWVudCBBLiBXZSB3aWxsIGNoYW5nZSB0aGVzZSBmcm9tIDAlIHRvIDIlIGluIGludGVydmFscyBvZiAwLjElLiANCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KbXUxIDwtIHNlcSgwLjAsIDIuMCwgMC4xKQ0KDQpkIDwtIChtdTEgLSBtdTIpIC8gc2QucG9vbGVkDQoNCnBvd2VyMSA8LSBwd3IudC50ZXN0KGQgPSBkLCBuID0gNiwgc2lnLmxldmVsID0gMC4wNSkNCnBvd2VyY2hhbmdlIDwtIGRhdGEuZnJhbWUoZCwgcG93ZXIgPSBwb3dlcjEkcG93ZXIgKiAxMDApDQpwb3dlcmNoYW5nZQ0KYGBgDQoNCmBgYHtyfQ0KcGxvdChwb3dlcmNoYW5nZSRkLCANCiAgICAgcG93ZXJjaGFuZ2UkcG93ZXIsIA0KICAgICB0eXBlID0gImIiLCANCiAgICAgeGxhYiA9ICJDb2hlbidzIGQiLCANCiAgICAgeWxhYiA9ICJQb3dlciAoJSkiKQ0KYGBgDQoNClRoaXMgZmlndXJlIHNob3dzIGhvdyB0aGUgcG93ZXIgY2hhbmdlcyB3aXRoIENvaGVuJ3MgJGQkLiBJdCBoYXMgYSBzeW1tZXRyaWNhbCBwYXR0ZXIgYmVjYXVzZSBvZiBuZWdhdGl2ZSBhbmQgcG9zaXRpdmUgcmFuZ2UgYXNzb2NpYXRlZCB3aXRoIENvaGVuJ3MgJGQkLiBCdXQgdGhlIHN0b3J5IGlzIHRoZSBzYW1lLiBBcyB0aGUgZWZmZWN0IHNpemUgaW5jcmVhc2VzIChuZWdhdGl2ZSBhbmQgcG9zaXRpdmUgc2lnbnMgZG8gbm90IG1hdHRlcjsgd2Ugb25seSBjYXJlIGFib3V0IHRoZSBhYnNvbHV0ZSB2YWx1ZXMpLCB0aGUgcG93ZXIgaW5jcmVhc2VzLiBUaGlzIG1ha2VzIHNlbnNlIGJlY2F1c2Ugd2Ugb25seSBoYXZlIGVub3VnaCBwb3dlciB0byBkZXRlY3QgbGFyZ2UgZGlmZmVyZW5jZXMgd2l0aCB0aGUgY3VycmVudCBzYW1wbGUgc2l6ZSAod2hpY2ggaXMgZml4ZWQgaW4gdGhpcyBjYXNlKS4gSWYgdGhlIGRpZmZlcmVuY2VzIGFyZSBzbWFsbCwgdGhlbiB3ZSBkbyBub3QgaGF2ZSBlbm91Z2ggcG93ZXIgd2l0aCB0aGUgY3VycmVudCBzYW1wbGUgc2l6ZSBvZiA2LiANCg0KDQojIFNhbXBsZSBzaXplIGVzdGltYXRpb24gZm9yICoqcGFpcmVkIGRhdGEgKGJlZm9yZSBhbmQgYWZ0ZXIpKioNCg0KU28gZmFyLCB3ZSBkaXNjdXNzZWQgaG93IHRvIHBlcmZvcm0gc2FtcGxlIHNpemUgZXN0aW1hdGlvbnMgZm9yICJiZXR3ZWVuLWdyb3VwcyIgY29tcGFyaXNvbnMuIEhvd2V2ZXIsIG1hbnkgc3R1ZGllcyBpbnZlc3RpZ2F0ZSB0aGUgIndpdGhpbi1ncm91cCIgY2hhbmdlcy4gVGhpcyBhcmUgcGFpcmVkIGRhdGEsIHdoaWNoIG1lYW5zIHRoYXQgdGhlIG9ic2VydmF0aW9uIGZvciBvbmUgZGF0YSBwb2ludCBpcyBkZXBlbmRlbnQgb24gYW5vdGhlciBvYnNlcnZhdGlvbi4gQSBjb21tb24gc3R1ZHkgZGVzaWduIHdoZXJlIHBhaXJlZCBkYXRhIGlzIGNvbGxlY3RlZCBhcmUgbG9uZ2l0dWRpbmFsIHN0dWRpZXMuIFRoZXNlcyB0eXBlcyBvZiBzdHVkaWVzIGludm9sdmUgcmVwZWF0ZWQgbWVhc3VyZS4gRm9yIGV4YW1wbGUgYSBwcmV0ZXN0IHBvc3R0ZXN0IHN0dWR5IGRlc2lnbiB3aWxsIG1lYXN1cmUgYSBkYXRhIHBvaW50IGZvciBhIHBhdGllbnQgYXQgYmFzZWxpbmUgYW5kIHRoZW4gcmVwZWF0IHRoYXQgbWVhc3VyZW1lbnQgYXQgYW5vdGhlciBwb2ludCBpbiB0aW1lLiBJbiB0aGUgZmlndXJlLCBQYXRpZW50IEEgaGFzIHR3byBtZWFzdXJlbWVudHMgYXQgJHRfezB9JCBhbmQgJHRfe2Z9JC4gU2luY2UgdGhlc2UgbWVhc3VyZW1lbnRzIHdlcmUgbWFkZSBpbiB0aGUgc2FtZSBwZXJzb24sIHRoZSBjaGFuZ2UgaXMgIndpdGhpbiIgdGhlIHBhdGllbnQuIEFsdGVybmF0aXZlbHksIHdlIGNhbiB0aGluayBvZiB0aGlzIGFzIGEgInJlcGVhdGVkIiBtZWFzdXJlIHNpbmNlIHRoZSBwYXRpZW50IGhhZCB0aGUgbWVhc3VyZW1lbnQgcGVyZm9ybWVkIHR3aWNlLiANCg0KYGBge3IgLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSJGaWd1cmUgY2FwdGlvbjogUHJldGVzdC1Qb3N0dGVzdCAocmVwZWF0ZWQgbWVhc3VyZXMpIGZyYW1ld29yayIsIG91dC53aWR0aCA9ICcxMDAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJ3MDctQmVmb3JlQWZ0ZXIuanBnIikNCmBgYA0KDQpXaGVuIHlvdSBoYXZlIGEgc3R1ZHkgd2hlcmUgeW91IGFyZSBwZXJmb3JtaW5nIGEgcGFpcmVkIHQgdGVzdCwgeW91IGNhbiB1c2UgdGhlIHNhbWUgYHB3ci50LnRlc3QoKWAgZnVuY3Rpb24gZm9yIGEgdHdvIHNhbXBsZSB0ZXN0IGZyb20gdGhlIGBwd3JgIHBhY2thZ2UuIA0KDQpMZXQncyBhc3N1bWUgdGhhdCB3ZSB3YW50IHRvIGNvbmR1Y3QgYSBwcm9zcGVjdGl2ZSBzdHVkeSBtZWFzdXJlIHRoZSB3ZWlnaHQgY2hhbmdlIG9mIGEgY29ob3J0IG9mIHBhdGllbnRzIHdobyBzdGFydGVkIGEgZGlldC4gWW91IHdhbnQgdG8gZW5yb2xsIGVub3VnaCBwYXRpZW50cyB0byBkZXRlY3QgYSA1IGxiIHJlZHVjdGlvbiBpbiB0aGUgd2VpZ2h0IDMgd2Vla3MgYWZ0ZXIgdGhlIGRpZXQgc3RhcnRlZC4gTGV0J3MgYXNzdW1lIHRoYXQgYXQgYmFzZWxpbmUgdGhlIGV4cGVjdGVkIGF2ZXJhZ2Ugd2VpZ2h0IGZvciB0aGUgY29ob3J0IHdhcyAxMzAgbGJzIHdpdGggYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMTEuIEFmdGVyIDMgd2Vla3Mgb2YgZGlldCwgdGhlIGV4cGVjdGVkIGF2ZXJhZ2Ugd2VpZ2h0IHdhcyAxMjUgbGJzIHdpdGggYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMTIuIA0KDQpXZSBjYW4gZXN0aW1hdGUgdGhlIGVmZmVjdCBzaXplIChDb2hlbidzICRkX3t6fSQpIGZvciBhIHBhaXJlZCB0IHRlc3QuIA0KDQoNCiQkDQpcYmVnaW57YWxpZ25lZH0NCmRfe3p9ID0gXGZyYWN7IHwgXG11X3t6fSB8fXtcc2lnbWFfe3p9fSA9IFxmcmFje3wgXG11X3t4fSAtIFxtdV97eX0gfCB9eyBcc3FydHtcc2lnbWFfe3h9XnsyfSArIFxzaWdtYV97eX1eezJ9IC0gMiBccmhvX3t4LCB5fSBcc2lnbWFfe3h9IFxzaWdtYV97eX19fQ0KXGVuZHthbGlnbmVkfQ0KJCQNCg0Kd2hlcmUgJHgkIGRlbm90ZXMgImJlZm9yZSIgKG9yIGJhc2VsaW5lKSwgJHkkIGRlbm90ZXMgImFmdGVyIiwgJGRfe3p9JCBkZW5vdGVzIHRoZSBDb2hlbidzICRkJCBmb3IgcGFpcmVkIGFuYWx5c2lzICRccmhvJCBkZW5vdGVzIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBtZWFzdXJlcyBiZWZvcmUgYW5kIGFmdGVyIHRoZSBkaWV0LiAoRm9yIHNpbXBsaWNpdHksIEkgdXNlIDAuNTAgaWYgSSBkb24ndCBoYXZlIHByaW9yIGluZm9ybWF0aW9uIGFib3V0IHRoaXMgY29ycmVsYXRpb24uKSANCg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQojIyMgUGFyYW1ldGVycyBmb3IgcGFpcmVkIGFuYWx5c2lzIG9yIGEgcHJldGVzdC1wb3N0dGVzdCBzdHVkeSBkZXNpZ24NCg0KbXVfeCA8LSAxMzAgICAgICMjIyBBdmVyYWdlIHdlaWdodCBiZWZvcmUgdGhlIGRpZXQgKGJhc2VsaW5lKQ0KbXVfeSA8LSAxMjUgICAgICMjIyBBdmVyYWdlIHdlaWdodCBhZnRlciB0aGUgZGlldA0KDQpzZF94IDwtIDExICAgICAgIyMjIFN0YW5kYXJkIGRldmlhdGlvbiBiZWZvcmUgdGhlIGRpZXQNCnNkX3kgPC0gMTIgICAgICAjIyMgU3RhbmRhcmQgZGV2aWF0aW9uIGFmdGVyIHRoZSBkaWV0DQoNCnJobyA8LSAwLjUgICAgICAjIyMgQ29ycmVsYXRpb24gYmV0d2VlbiBtZWFzdXJlcyBiZWZvcmUgYW5kIGFmdGVyIHRoZSBkaWV0DQoNCnNkX3ogPC0gc3FydChzZF94XjIgKyBzZF95XjIgLSAyKnJobypzZF94KnNkX3kpDQogIA0KZF96IDwtIGFicyhtdV94IC0gbXVfeSkgLyBzZF96DQpkX3oNCmBgYA0KDQpUaGUgQ29oZW4ncyAkZF97en0kIGlzIDAuNDMzLiBXZSBjYW4gaW5wdXQgdGhpcyBpbnRvIHRoZSBgcHdyLnQudGVzdCgpYCBmdW5jdGlvbi4gDQoNCg0KYGBge3J9DQpuLnBhaXJlZCA8LSBwd3IudC50ZXN0KGQgPSBkX3osIHBvd2VyID0gMC44MCwgc2lnLmxldmVsID0gMC4wNSwgdHlwZSA9ICJwYWlyZWQiKQ0Kbi5wYWlyZWQNCmBgYA0KDQoNCldlIG5lZWQgNDQgcGF0aWVudHMgd2l0aCB0d28gbWVhc3VyZW1lbnRzIChiZWZvcmUgYW5kIGFmdGVyKSB0aGV5IGltcGxlbWVudCB0aGVpciBkaWV0IHRvIGRldGVjdCBhIGRpZmZlcmVuY2Ugb2YgNSBsYnMgb3IgZ3JlYXRlciB3aXRoIDgwJSBwb3dlciBhbmQgYSBzaWduaWZpY2FuY2UgbGV2ZWwgb2YgMC4wNS4gDQoNCg0KIyBQb3dlciBhbmFseXNpcyBvZiAqKnBhaXJlZCBzYW1wbGVzIChwYWlyZWQgdCB0ZXN0KSoqDQoNCldlIGNhbiBwbG90IGhvdyB0aGUgcG93ZXIgd2lsbCBjaGFuZ2UgYXMgdGhlIHNhbXBsZSBzaXplIGNoYW5nZXMgZm9yIHRoZSBwYWlyZWQgdCB0ZXN0IGFuYWx5c2lzLiBBcyB0aGUgc2FtcGxlIHNpemUgaW5jcmVhc2VzLCBwb3dlciBpbmNyZWFzZXMuIFRoaXMgc2hvdWxkIG1ha2Ugc2Vuc2UuIExpa2Ugb3VyIHByZXZpb3VzIGV4YW1wbGVzLCBhcyB3ZSBpbmNyZWFzZSBvdXIgc2FtcGxlIHNpemUsIHdlIHJlZHVjZSB0aGUgdW5jZXJ0YWludHkgYXJvdW5kIHRoZSBlc3RpbWF0ZXMuIEJ5IHJlZHVjaW5nIHRoaXMgdW5jZXJ0YWludHksIHdlIGdhaW4gZ3JlYXRlciBwcmVjaXNpb24gaW4gb3VyIGVzdGltYXRlcywgd2hpY2ggcmVzdWx0cyBpbiBncmVhdGVyIGNvbmZpZGVuY2UgaW4gb3VyIGFiaWxpdHkgdG8gYXZvaWQgbWFraW5nIGEgdHlwZSBJSSBlcnJvci4gDQoNCg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQojIyMgV2UgY2FuIHBsb3QgdGhlIHBvd2VyIHJlbGF0aXZlIHRvIGRpZmZlcmVudCBsZXZlbHMgb2YgdGhlIHNhbXBsZSBzaXplIGZvciBwYWlyZWQgYW5hbHlzaXMuIA0Kbl96IDwtIHNlcSgxLCA4MCwgNSkNCm5fei5jaGFuZ2UgPC0gcHdyLnQudGVzdChkID0gZF96LCBuID0gbl96LCBzaWcubGV2ZWwgPSAwLjA1LCB0eXBlID0gInBhaXJlZCIpDQoNCm5fei5jaGFuZ2UuZGYgPC0gZGF0YS5mcmFtZShuX3osIHBvd2VyID0gbl96LmNoYW5nZSRwb3dlciAqIDEwMCkNCm5fei5jaGFuZ2UuZGYNCmBgYA0KDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgZmlnLmNhcCA9ICJXZSBpbmNyZWFzZSB0aGUgc2FtcGxlIHNpemUgZnJvbSAxIHRvIDgwIGF0IDUtdW5pdCBpbnRlcnZhbHMuIn0NCnBsb3Qobl96LmNoYW5nZS5kZiRuLCANCiAgICAgbl96LmNoYW5nZS5kZiRwb3dlciwgDQogICAgIHR5cGUgPSAiYiIsIA0KICAgICB4bGFiID0gIlNhbXBsZSBzaXplLCBuIiwgDQogICAgIHlsYWIgPSAiUG93ZXIgKCUpIikNCg0KYGBgDQoNCg0KQXMgdGhlIHNhbXBsZSBzaXplIGluY3JlYXNlcywgd2UgZ2VuZXJhdGUgbW9yZSBwb3dlciB0byBkZXRlY3QgYSBkaWZmZXJlbmNlIG9mIDUgbGJzIHdpdGggYSBzaWduaWZpY2FuY2UgbGV2ZWwgb2YgMC4wNSBhbmQgYSBmaXhlZCBzYW1wbGUgc2l6ZSBvZiA0NCBwYXRpZW50cyB3aXRoIHR3byBtZWFzdXJlbWVudHMgKGJlZm9yZSBhbmQgYWZ0ZXIpIHRoZXkgaW1wbGVtZW50IHRoZWlyIGRpZXQuIA0KDQpMZXQncyBzZWUgaG93IHBvd2VyIGNoYW5nZXMgd2hlbiB3ZSBjaGFuZ2UgdGhlIGVmZmVjdCBzaXplLiBMZXQncyBjaGFuZ2UgdGhlIGF2ZXJhZ2Ugd2VpZ2h0IGFmdGVyIHRoZSBwYXRpZW50cyBpbXBsZW1lbnQgdGhlaXIgZGlldC4gSW5zdGVhZCBvZiBhbiBhdmVyYWdlIG9mIDEyNSBsYnMsIGxldCdzIHNlZSBob3cgdGhlIHBvd2VyIHdpbGwgY2hhbmdlIHdoZW4gd2UgcmVkdWNlIHRoYXQgdG8gMTAwIGxicy4gDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgZmlnLmNhcCA9ICJXZSB2YXJ5IHRoZSBhdmVyYWdlIHdlaWdodCAkXFxtdV97eX0kIGJldHdlZW4gNTAgbGJzIGFuZCAxMzAgbGJzIGluIGludGVydmFscyBvZiA1IGxicy4ifQ0KIyMjIFZhcnkgdGhlIG11X3kgZnJvbSA1MCBsYnMgdG8gMTMwIGxicyBpbiBpbnRlcnZhbHMgb2YgNSBsYnMuDQptdV95IDwtIHNlcSg1MCwgMTMwLCA1KQ0KDQpkX3ogPC0gYWJzKG11X3ggLSBtdV95KSAvIHNkX3oNCg0Kbl96LmNoYW5nZSA8LSBwd3IudC50ZXN0KGQgPSBkX3osIG4gPSA0NCwgc2lnLmxldmVsID0gMC4wNSkNCm5fei5jaGFuZ2UuZGYgPC0gZGF0YS5mcmFtZShkX3osIHBvd2VyID0gbl96LmNoYW5nZSRwb3dlciAqIDEwMCkNCm5fei5jaGFuZ2UuZGYNCg0KcGxvdChuX3ouY2hhbmdlLmRmJGRfeiwgDQogICAgIG5fei5jaGFuZ2UuZGYkcG93ZXIsIA0KICAgICB0eXBlID0gImIiLCANCiAgICAgeGxhYiA9ICJDb2hlbidzIGRfeiIsIA0KICAgICB5bGFiID0gIlBvd2VyICglKSIsDQogICAgIHhsaW0gPSBjKDAsIDIpKQ0KYGBgDQoNCldoZW4gd2UgaW5jcmVhc2UgdGhlIGVmZmVjdCBzaXplIChDb2hlbidzICRkX3t6fSQpLCBvdXIgcG93ZXIgZ29lcyB1cDsgcmVjYWxsIHRoYXQgdGhlIHNhbXBsZSBzaXplIGlzIGZpeGVkIGF0IDQ0IGFuZCBzaWduaWZpY2FuY2UgbGV2ZWwgaXMgMC4wNS4gQnV0IHdoZW4gdGhlIGVmZmVjdCBzaXplIGdldHMgc21hbGxlciAob3Igd2hlbiB0aGUgYXZlcmFnZSB3ZWlnaHQgbG9zcyBzaHJpbmtzKSwgd2UgbG9zZSBwb3dlciB0byBkZXRlY3QgYSBkaWZmZXJlbmNlIGJlY2F1c2Ugb3VyIHNhbXBsZSBzaXplIGlzIHRvbyBzbWFsbC4gV2UnbGwgbmVlZCB0byBpbmNyZWFzZSBvdXIgc2FtcGxlIHNpemUgdG8gaGF2ZSBhIHJlYXNvbmFibGUgcG93ZXIgdG8gZGV0ZWN0IHNtYWxsIGRpZmZlcmVuY2VzLiANCg0KV2UgY2FuIGFsc28gc2VlIGhvdyBwb3dlciBjaGFuZ2VzIHdoZW4gd2UgdmFyeSAkXHJobyQuIElmIHdlIHNldCAkXHJobyQgPSAwLCB0aGVuIHRoZSBDb2hlbidzICRkX3t6fSQgPSAwLjMwNy4gSWYgd2Ugc2V0ICRccmhvJCA9IDEsIHRoZW4gdGhlIENvaGVuJ3MgJGRfe3p9JCA9IDUuDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCm11X3ggPC0gMTMwICAgICAjIyMgQXZlcmFnZSB3ZWlnaHQgYmVmb3JlIHRoZSBkaWV0IChiYXNlbGluZSkNCm11X3kgPC0gMTI1ICAgICAjIyMgQXZlcmFnZSB3ZWlnaHQgYWZ0ZXIgdGhlIGRpZXQNCg0Kc2RfeCA8LSAxMSAgICAgICMjIyBTdGFuZGFyZCBkZXZpYXRpb24gYmVmb3JlIHRoZSBkaWV0DQpzZF95IDwtIDEyICAgICAgIyMjIFN0YW5kYXJkIGRldmlhdGlvbiBhZnRlciB0aGUgZGlldA0KDQpzZF96XzEgPC0gc3FydChzZF94XjIgKyBzZF95XjIgLSAyKjEqc2RfeCpzZF95KQ0Kc2Rfel8wIDwtIHNxcnQoc2RfeF4yICsgc2RfeV4yIC0gMiowKnNkX3gqc2RfeSkNCg0KZF96XzEgPC0gYWJzKG11X3ggLSBtdV95KSAvIHNkX3pfMQ0KZF96XzAgPC0gYWJzKG11X3ggLSBtdV95KSAvIHNkX3pfMA0KDQpkX3pfMQ0KZF96XzANCmBgYA0KDQpTbywgaGlnaGVyICRccmhvJCByZXN1bHRzIGluIGxhcmdlICRkX3t6fSQgYW5kIHNtYWxsZXIgJFxyaG8kIHJlc3VsdHMgaW4gc21hbGwgJGRfe3p9JCB2YWx1ZXMuIA0KDQpMZXQncyBzZWUgaG93IHBvd2VyIGNoYW5nZXMgd2hlbiB3ZSBjaGFuZ2UgdGhlICRccmhvJCByYW5nZSBmcm9tIDAgdG8gMSBpbiBpbnRlcnZhbHMgb2YgMC4xIHVuaXRzLiANCg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQpyaG8gPC0gc2VxKDAuMCwgMS4wLCAwLjEpDQoNCnNkX3ogPC0gc3FydChzZF94XjIgKyBzZF95XjIgLSAyKnJobypzZF94KnNkX3kpDQoNCmRfeiA8LSBhYnMobXVfeCAtIG11X3kpIC8gc2Rfeg0KDQpyaG8uY2hhbmdlIDwtIHB3ci50LnRlc3QoZCA9IGRfeiwgbiA9IDQ0LCBzaWcubGV2ZWwgPSAwLjA1KQ0KcmhvLmNoYW5nZS5kZiA8LSBkYXRhLmZyYW1lKGRfeiwgcG93ZXIgPSByaG8uY2hhbmdlJHBvd2VyICogMTAwKQ0KcmhvLmNoYW5nZS5kZg0KYGBgDQoNCg0KYGBge3IsIGVjaG8gPSBUUlVFLCBmaWcuY2FwID0gIldlIHZhcnkgJFxccmhvJCBmcm9tIDAgdG8gMSBhdCBpbnRlcnZhbHMgb2YgMC4xIHVuaXQuIn0NCnBsb3QocmhvLmNoYW5nZS5kZiRkX3osIA0KICAgICByaG8uY2hhbmdlLmRmJHBvd2VyLCANCiAgICAgdHlwZSA9ICJiIiwgDQogICAgIHhsYWIgPSAiQ29oZW4ncyBkX3oiLCANCiAgICAgeWxhYiA9ICJQb3dlciAoJSkiLA0KICAgICB4bGltID0gYygwLCAxLjUpKQ0KYGBgDQoNCkFzICRccmhvJCBpbmNyZWFzZXMsIG91ciBwb3dlciBpbmNyZWFzZXMuIFRoaXMgbWFrZXMgc2Vuc2UgYmVjYXVzZSB3ZSBhcmUgbmVhcmluZyAicGVyZmVjdCIgY29ycmVsYXRpb24sIHdoaWNoIHdvdWxkIHJlcXVpcmUgbGVzcyBzYW1wbGUgdG8gZGV0ZWN0IGEgZGlmZmVyZW5jZSBpZiBvbmUgZXhpc3RlZC4gQXMgdGhlIGNvcnJlbGF0aW9uIGJlY29tZXMgbGVzcyAicGVyZmVjdCIgb3VyIHBvd2VyIGRyb3BzIHN1Z2dlc3RpbmcgdGhhdCB3ZSBuZWVkIHRvIGluY3JlYXNlIG91ciBzYW1wbGUgc2l6ZSB0byBtYWtlIHVwIGZvciB0aGlzIHBvb3IgY29ycmVsYXRpb24uIA0KDQoNCiMgUG93ZXIgYW5hbHlzaXMgd2l0aCAqKnVuZXF1YWwgc2FtcGxlIHNpemVzKioNCg0KDQpJdCBpcyBjb21tb24gZm9yIHRoZSBzYW1wbGUgc2l6ZSB0byBiZSBkaWZmZXJlbnQuIFRoZSBgcHdyLnQybi50ZXN0KClgIGlzIGEgdXNlZnVsIHRvb2wgdG8gaGVscCBlc3RpbWF0ZSB0aGUgcG93ZXIgZ2l2ZW4gdGhlIHNhbXBsZSBzaXplcyBvZiB0aGUgc3R1ZHkuIA0KDQoNCkl0IGlzIGNvbW1vbiB0byBwZXJmb3JtIHBvd2VyIGFuYWx5c2lzIG9uIGEgc3R1ZHkgd2hlcmUgdGhlIHNhbXBsZSBzaXplcyBiZXR3ZWVuIGdyb3VwcyBhcmUgZGlmZmVyZW50LiANCg0KU3VwcG9zZSB5b3UgaGF2ZSBhIHJldHJvc3BlY3RpdmUgc3R1ZHkgd2hlcmUgdGhlIHBhdGllbnRzIHdlcmUgcHJlc2NyaWJlZCBUcmVhdG1lbnQgQSBhbmQgVHJlYXRtZW50IEIuIFRoZXJlIHdlcmUgMTMwIHBhdGllbnRzIGluIFRyZWF0bWVudCBBICgkbl97QX0kID0gMTMwKSBhbmQgMTIwIHBhdGllbnRzIGluIFRyZWF0bWVudCBCICgkbl97Qn0kID0gMTIwKS4gVGhlIGF2ZXJhZ2UgY2hhbmdlIGluIEhiQTFjIHdhcyAxLjUlIHdpdGggYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMS4yNSUgaW4gVHJlYXRtZW50IEEsIGFuZCB0aGUgYXZlcmFnZSBjaGFuZ2UgaW4gSGJBMWMgd2FzIDEuNCUgd2l0aCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAxLjAxJSBpbiBUcmVhdG1lbnQgQi4gDQoNCkZpcnN0LCB3ZSdsbCBjYWxjdWxhdGUgdGhlIHBvb2xlZCBzdGFuZGFyZCBkZXZpYXRpb24gKCRcc2lnbWFfe3Bvb2xlZH0kKToNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0Kc2QxIDwtIDEuMjUNCnNkMiA8LSAxLjAxDQpzZF9wb29sZWQgPC0gc3FydCgoc2QxXjIgK3NkMl4yKSAvIDIpDQpzZF9wb29sZWQNCmBgYA0KDQpPbmNlIHdlIGhhdmUgdGhlICRcc2lnbWFfe3Bvb2xlZH0kLCB3ZSBjYW4gZXN0aW1hdGUgdGhlIENvaGVuJ3MgJGQkOg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQptdTEgPC0gMS41DQptdTIgPC0gMS40DQpkIDwtIChtdTEgLSBtdTIpIC8gc2RfcG9vbGVkDQpkDQpgYGANCg0KTm93LCB3ZSBjYW4gZXN0aW1hdGUgdGhlIHBvd2VyIHdpdGggdGhlIGRpZmZlcmVudCBzYW1wbGUgc2l6ZXMgYWNyb3NzIHRoZSBncm91cHMgKCRuX3tBfSQgPSAxMzAsICRuX3tCfSQgPSAxMjApLg0KDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCm4xIDwtIDEzMA0KbjIgPC0gMTIwDQoNCnBvd2VyLmRpZmZfbiA8LSBwd3IudDJuLnRlc3QoZCA9IGQsIG4xID0gbjEsIG4yID0gbjIsIHNpZy5sZXZlbCA9IDAuMDUpDQpwb3dlci5kaWZmX24NCmBgYA0KDQoNCg0KU2luY2UgdGhlIGF2ZXJhZ2UgSGJBMWMgY2hhbmdlIGZyb20gYmFzZWxpbmUgZm9yIFRyZWF0bWVudCBBIGlzIDEuNSUgYW5kIDEuNCUgZm9yIFRyZWF0bWVudCBCLCB0aGUgYXZlcmFnZSBkaWZmZXJlbmNlIGluIHRoZSBIYkExYyBjaGFuZ2UgZnJvbSBiYXNlbGluZSBpcyAwLjElLiBUaGlzIGlzIGEgZGlmZmVyZW5jZSAoZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBncm91cHMpIG9mIHRoZSBkaWZmZXJlbmNlcyAoZGlmZmVyZW5jZSBmcm9tIGJhc2VsaW5lIHdpdGhpbiB0aGUgZ3JvdXApIGNhbGN1bGF0aW9uLiANCg0KDQpZb3Ugb25seSBoYXZlIDExJSBwb3dlciB0byBkZXRlY3QgYSBkaWZmZXJlbmNlIG9mIDAuMTAlIG9yIGdyZWF0ZXIgaW4gdGhlIEhiQTFjIGNoYW5nZSBmcm9tIGJhc2VsaW5lLiBUaGlzIG1lYW5zIHRoYXQgeW91IGFyZSB1bmRlcnBvd2VyZWQgdG8gZGV0ZWN0IGEgZGlmZmVyZW5jZSBvZiAwLjEwJSBvciBncmVhdGVyIGluIHRoZSBIYkExYyBjaGFuZ2UgZnJvbSBiYXNlbGluZSB3aXRoICRuX3tBfSQgPSAxMzAsICRuX3tCfSQgPSAxMjAsIGFuZCBhIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAwLjA1LiBXaGVuIHN0dWRpZXMgYXJlIHVuZGVycG93ZXJlZCwgdGhlcmUgaXMgYSBoaWdoIHBvdGVudGlhbCBmb3IgdHlwZSBJSSBlcnJvci4gVGhlIG9ubHkgd2F5IHRvIGFkZHJlc3MgdGhpcyBwcm9ibGVtIGlzIHRvIGVucm9sbCBtb3JlIHBhdGllbnRzIG9yIGV4cGFuZCB0aGUgc2FtcGxlIGJ5IHJlbGF4aW5nIGluY2x1c2lvbiBjcml0ZXJpYS4gQnV0IHRoaXMgbWF5IGluY3JlYXNlIHRoZSB0aHJlYXRzIHRvIHRoZSBzdHVkeSdzIGludGVybmFsIHZhbGlkaXR5Lg0KDQoNCiMgQ29uY2x1c2lvbnMNClNhbXBsZSBzaXplIGVzdGltYXRpb25zIGFuZCBwb3dlciBhbmFseXNpcyBhcmUgdmVyeSB1c2VmdWwgdG9vbHMgdG8gZGV0ZXJtaW5lIGhvdyBtYW55IHBhdGllbnRzIHlvdSBuZWVkIGluIHlvdXIgc3R1ZHkgYW5kIGhvdyBjb25maWRlbnQgeW91IGFyZSB0aGF0IHlvdSBkaWRuJ3QgbWFrZSBhIHR5cGUgSUkgZXJyb3IuIERlcGVuZGluZyBvbiB0aGUgdHlwZSBvZiBzdHVkeSwgeW91IHdpbGwgbmVlZCB0byB1c2UgZGlmZmVyZW50IGZ1bmN0aW9ucyBmcm9tIHRoZSBgcHdyYCBwYWNrYWdlLiBJIGhpZ2hseSBlbmNvdXJhZ2UgeW91IHRvIGV4cGxvcmUgdGhlIG90aGVyIGZ1bmN0aW9ucyBvZiB0aGUgYHB3cmAgcGFja2FnZSB0byBzZWUgaWYgdGhvc2UgZml0IHRoZSBzdHVkeSBkZXNpZ24geW91IGhhdmUgcGxhbm5lZC4gDQoNCg==