Introduction
Two-sample tests are statistical methods used to compare two groups
(samples) to determine whether they come from the same population or
have different characteristics. As you have learned in one-sample tests,
two-sample tests can be broadly classified into:
Parametric Tests: Assume data follows a specific
distribution (usually normal) and compare parameters like means or
variances.
Nonparametric Tests: Make fewer assumptions about
the data distribution and are used when parametric assumptions are
violated.
This module reviews parametric two-sample tests first and then
discusses non-parametric two-sample tests.
(Raw) Data
Structure
For convenience, we include the section on data structures from the
previous module. All procedures introduced in this module will use the
raw data table with the following layout:
\(y_1\) |
\(x_{11}\) |
\(x_{21}\) |
\(\cdots\) |
\(x_{k1}\) |
\(y_2\) |
\(x_{12}\) |
\(x_{22}\) |
\(\cdots\) |
\(x_{k2}\) |
\(y_3\) |
\(x_{13}\) |
\(x_{23}\) |
\(\cdots\) |
\(x_{k3}\) |
\(\vdots\) |
\(\vdots\) |
\(\vdots\) |
\(\vdots\) |
\(\vdots\) |
\(y_n\) |
\(x_{1n}\) |
\(x_{2n}\) |
\(\cdots\) |
\(x_{kn}\) |
For example, an employer wants to see whether their pay rate is fair
in terms of gender (i.e., assessing potential gaps in pay rate between
male and female employees in the same role under similar conditions).
The HR helped to create a dataset in the following form.
$56,230 |
F |
analyst |
12 |
4 |
$73,450 |
M |
manager |
16 |
8 |
$47,520 |
M |
analyst |
14 |
3 |
$111,190 |
F |
manager |
18 |
12 |
$66,800 |
F |
analyst |
14 |
7 |
$63,170 |
M |
analyst |
16 |
6 |
$77,430 |
M |
analyst |
16 |
9 |
$99,280 |
F |
analyst |
18 |
13 |
We also introduced R data frames earlier to store a dataset in R and
then use it for analysis. The next R code defines a dataframe in R based
on the above toy dataset.
my.toy.data <- data.frame(salary = c(56230, 73450, 47520, 111190, 66800, 63170, 77430, 99280), # numerical values
gender = c("F", "M", "M", "F", "F", "M", "M", "F"), # character (categorical) values
role = c("analyst", "manager", "analyst", "manager", "analyst", "analyst", "analyst", "analyst"),
Yr.edu = c(12, 16, 14, 18, 14, 16, 16, 18),
Yr.exp = c(4,8,3,12,7,6,9,13)
)
my.toy.data # print the data
| salary gender role Yr.edu Yr.exp
| 1 56230 F analyst 12 4
| 2 73450 M manager 16 8
| 3 47520 M analyst 14 3
| 4 111190 F manager 18 12
| 5 66800 F analyst 14 7
| 6 63170 M analyst 16 6
| 7 77430 M analyst 16 9
| 8 99280 F analyst 18 13
Since we will work with more
than one variable starting from this module, we introduce a few commands
you can use to select rows, columns, or individual cell values in a data
frame. The following figure shows the basics on how to
access an R data frame.

The following are a few examples
1. Explicit Access
# Select a single cell located at the intersection of row 2 and column 3
my.toy.data[2,3]
| [1] "manager"
# multiple cells involve multiple rows and columns. In this case, indices must be
# provided in the form of vector, e.g., c(2,5,6)
my.toy.data[c(3,6), c(1,3)]
| salary role
| 3 47520 analyst
| 6 63170 analyst
# select one column and ALL rows
my.toy.data[ , 4]
| [1] 12 16 14 18 14 16 16 18
# select multiple columns and ALL rows
my.toy.data[ , c(1,5)]
| salary Yr.exp
| 1 56230 4
| 2 73450 8
| 3 47520 3
| 4 111190 12
| 5 66800 7
| 6 63170 6
| 7 77430 9
| 8 99280 13
# select multiple columns and ALL rows using variable names
my.toy.data[ , c("salary", "gender", "role")] # vector with character values in quotes!
| salary gender role
| 1 56230 F analyst
| 2 73450 M manager
| 3 47520 M analyst
| 4 111190 F manager
| 5 66800 F analyst
| 6 63170 M analyst
| 7 77430 M analyst
| 8 99280 F analyst
# select one row (also called one record) and ALL columns
my.toy.data[4 , ]
| salary gender role Yr.edu Yr.exp
| 4 111190 F manager 18 12
# select multiple rows and ALL columns
my.toy.data[c(1,5) , ]
| salary gender role Yr.edu Yr.exp
| 1 56230 F analyst 12 4
| 5 66800 F analyst 14 7
2. Conditional Access
In application, sometimes we need to select a subset of the data
under certain conditions defined based on variables. For example, if we
want to compare the mean salary between male and female employees in a
company, we need to calculate the sample size, mean, and standard
deviation, respectively, from the male and female groups in introductory
statistics classes.
There are different R commands to achieve this goal. We use
which()
to identify salaries for male and female employees,
respectively. The following code shows how to separate the salaries of
the two groups.
# use my.toy.data$gender to identify male group
male.id <- which(my.toy.data$gender == "M") # CAUTION: double equal sign (==) MUST be used in conditional testing!!!
# This will return the row indexes of male employees
# Use the above returned row index to extract the two groups
male.salary <- my.toy.data[male.id, ] # male group
female.salary <- my.toy.data[ - male.id, ] # "- male.id": not male => female indexes
Print out the above subset.
##
male.salary
| salary gender role Yr.edu Yr.exp
| 2 73450 M manager 16 8
| 3 47520 M analyst 14 3
| 6 63170 M analyst 16 6
| 7 77430 M analyst 16 9
##
female.salary
| salary gender role Yr.edu Yr.exp
| 1 56230 F analyst 12 4
| 4 111190 F manager 18 12
| 5 66800 F analyst 14 7
| 8 99280 F analyst 18 13
Two-Sample t-Test
Revisited
Recall that, in introductory statistics (MAT121/125), the assumptions
of the two t-test are
- Both populations are normally distributed
- Both population variances are unknown but equal
Under the above assumptions, the two random samples were taken from
the two independent populations, respectively, with the following
statistics.
sample size |
\(n_1\) |
\(n_2\) |
sample mean |
\(\bar{x}_1\) |
\(\bar{x}_2\) |
sample standard deviation |
\(s_1\) |
\(s_2\) |
Under the second assumption, we need to estimate the common
standard deviation by pooling two samples using the following
formula.
\[
s_{\text{pool}} = \sqrt{\frac{(n_1-1)s_1^2 + (n_2-1)s_2^2}{n_1 + n_2 -
2}}
\]
The test statistic for testing \(H_0: \mu_1
- \mu_2 = 0 \ \ \text{vs} \ \ H_a: \mu_1 - \mu_2 \ne 0\) is
\[
TS = \frac{(\bar{x}_1 - \bar{x}_2) - 0}{s_{\text{pool}}\sqrt{1/n_1 +
1/n_2}} \rightarrow t_{n_1+n_2 -2}
\]
Remark: If the
equal variances assumption is not met, one can use an
approximate t-test using the Welch-Satterthwaite procedure. This
approximation will not be discussed in this note. We will address this
in the subsequent notes under more general settings.
Example: We will use the Pima Indian Diabetes data
to illustrate the above two sample tests to see whether the mean BMI
levels differ between diabetes and diabetes-free populations. We need to
load the data first before calculating the related statistics required
for the test. Note that diabetes status is reflected in the variable
diabetes
.
\[
H_0: \mu_1 - \mu_2 = 0 \ \ \text{vs} \ \ H_a: \mu_1 - \mu_2 \ne 0
\]
Since R is sensitive, we may want to use the
R command head()
to
check the exact names and first 6 observations in the data
frame
# read data into R
PimaIndiaDiabetes <- read.csv("https://pengdsci.github.io/STA200/dataset/PimaIndiaDiabetes.csv")
## checking variable names
head(PimaIndiaDiabetes)
| X pregnant glucose pressure triceps insulin mass pedigree age diabetes
| 1 4 1 89 66 23 94 28.1 0.167 21 neg
| 2 5 0 137 40 35 168 43.1 2.288 33 pos
| 3 7 3 78 50 32 88 31.0 0.248 26 pos
| 4 9 2 197 70 45 543 30.5 0.158 53 pos
| 5 14 1 189 60 23 846 30.1 0.398 59 pos
| 6 15 5 166 72 19 175 25.8 0.587 51 pos
Manual Calculation
Using R
Next, we show step-by-step manual calculation and translate the above
formulas directly into R code and report the test statistic, degrees of
freedom, and the p-value for statistical decision. To this end, we
define a subset with only two variables: BMI (mass
) and
diabetes
.
sub.diabetes <- PimaIndiaDiabetes[ , c("mass", "diabetes")] # values in the vector must be COMMA separated!
diabetes.id <- which(sub.diabetes$diabetes == "pos")
diabetes.pop <- sub.diabetes[diabetes.id, ]
no.diabetes.pop <- sub.diabetes[-diabetes.id, ]
##
## statistics for pop #1
n1 <- length(diabetes.pop$mass)
xbar.1 <- mean(diabetes.pop$mass)
s.1 <- sd(diabetes.pop$mass)
## statistics for pop #2
n2 <- length(no.diabetes.pop$mass)
xbar.2 <- mean(no.diabetes.pop$mass)
s.2 <- sd(no.diabetes.pop$mass)
## pooled standard deviation
s.pool <- sqrt(((n1-1)*s.1^2 + (n2-1)*s.2^2)/(n1+n2-2))
## evaluate test statistic
TS <- ((xbar.1-xbar.2)-0)/(s.pool*sqrt(1/n1 + 1/n2))
## absolute value of TS
abs.TS <- abs(TS)
##p-value: 2 times the right-tail area for a two-sample test
p.value <- 2*pt(abs.TS, df = n1+n2-2, lower.tail = FALSE) # lower.tail = FALSE specifies the right tail area
## print out statistic, df, and p-value in a combined vector
cbind(TS = TS, df = n1 +n2 - 2, p.value = p.value)
| TS df p.value
| [1,] 5.540362 390 5.563221e-08
There is clear strong evidence that the mean body
mass indices (BMI) in diabetes and diabetes-free populations are
different (p = 5.563221e-08 < 0.05).
This is consistent with clinical
findings.
Calling R Built-in
Function
We have used t.test()
in a previous note for a
one-sample t test. The same function can be used to perform a 2-sample t
test. We need to provide the independent sample vectors directly to the
function to produce the results.
# We use the two samples of BMI found previously:
t.test(diabetes.pop$mass, no.diabetes.pop$mass, alternative = "two.sided", var.equal = TRUE)
|
| Two Sample t-test
|
| data: diabetes.pop$mass and no.diabetes.pop$mass
| t = 5.5404, df = 390, p-value = 5.563e-08
| alternative hypothesis: true difference in means is not equal to 0
| 95 percent confidence interval:
| 2.597924 5.455934
| sample estimates:
| mean of x mean of y
| 35.77769 31.75076
The above output indicates that the built-in function produces the
same results.
As an exercise, you can explore
whether the mean of glucose
levels in diabetes and
diabetes-free populations are equal.
Regression Approach to
Two-sample t Test
The regression approach to the two-sample t-test is straightforward.
Special attention should be paid to the model formula in that the
group variable must be on the right-hand side and MUST
be a factor. R function factor()
turns a variable into a
factor variable. In other words, the model formula should be in the form
lm(y ~ factor(x), data = dataset.name)
The following three lines of code produce the results in the above
two-sample test using the regression method.
# read data into R
PimaIndiaDiabetes <- read.csv("https://pengdsci.github.io/STA200/dataset/PimaIndiaDiabetes.csv")
reg.2.sample.test <- lm(mass ~ factor(diabetes), data = PimaIndiaDiabetes)
summary(reg.2.sample.test)
|
| Call:
| lm(formula = mass ~ factor(diabetes), data = PimaIndiaDiabetes)
|
| Residuals:
| Min 1Q Median 3Q Max
| -13.5508 -4.9460 -0.8142 3.8242 31.3223
|
| Coefficients:
| Estimate Std. Error t value Pr(>|t|)
| (Intercept) 31.7508 0.4186 75.86 < 2e-16 ***
| factor(diabetes)pos 4.0269 0.7268 5.54 5.56e-08 ***
| ---
| Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
|
| Residual standard error: 6.775 on 390 degrees of freedom
| Multiple R-squared: 0.07296, Adjusted R-squared: 0.07059
| F-statistic: 30.7 on 1 and 390 DF, p-value: 5.563e-08
The following annotated output shows that the results are identical
to those obtained in the previous section.

Non-parametric
Two-sample Test
We have discussed the comparison of two normal population means under
the assumption that the two populations have equal variances, using the
two-sample t-test. However, if either of the two assumptions—normality
and equal variances—is not satisfied, the two-sample t-test may not be
appropriate.
In statistics, there are alternative procedures for comparing numeric
characteristics between populations without assuming normality or equal
variances. This section introduces one such test: the Wilcoxon
Rank Sum Test (also called the Mann-Whitney U
test), which assesses whether the
two population distributions are equal.
This is a much stronger test because the assumption of equal means
does not require the two populations to have identical distributions
(see the following figure).

The Wilcoxon Rank Sum Test assesses whether two
sampled groups are likely to derive from the same population. A common
misconception is that it compares medians, but this is only true
if the distributions are symmetric and differ only in location.
In other words, if the distributions have different shapes (e.g.,
skewness or variance differences), the test may still reject (\(H_0\)) even if medians are equal (see the
above figure).
The hypotheses in a two-tailed Wilcoxon Rank Sum
Test are:
Remark:
one-tailed Wilcoxon Rank Sum Tests
compare stochastic dominance between the two distributions. This is out
of the scope of this class. We will not discuss this topic in this
class.
Manual
Implementation
Next, we discuss the development of the Wilcoxon Rank
Sum test. To help you understand the steps, we use the
following toy data set.

Step 1: Ranking the
Data
Combine the data from both groups into a single dataset and sort
them in ascending order:
10, 12, 14, 15, 16, 18, 20, 22
Assign ranks to all observations from smallest to largest
(tied values receive the average
rank): 1, 2, 3, 4, 5, 6, 7, 8
.
Step 2: Ranking the
Data
- Sum the ranks for each group
separately.
- $R_1 = $ Sum of ranks for Group 1: \(R_A =
1+2+3+5=11\)
- $R_2 = $ Sum of ranks for Group 2: \(R_B =
4+6+7+8=25\)
Step 3 Compute the Test
Statistic (U)
- The test statistic \(U\) can be
calculated for either group (\(n_1\)
and \(n_2\) are group sizes):
\[
U_1 = n_1n_2 + \frac{n_1(n_1+1)}{2} - R_1
\] \[
U_2 = n_1n_2 + \frac{n_2(n_2+1)}{2} - R_2
\]
The test statistic (commonly denoted by U) is defined to be
\[
U = \min \{U_1, U_2 \},
\]
That is, U is equal to the smaller of \(U_1\) and \(U_2\).
In the above toy example,
\[
U_A = 4\times 4 + \frac{4(4+1)}{2} - 11 = 15
\] \[
U_A = 4\times 4 + \frac{4(4+1)}{2} - 25 = 1
\] \[
U = \min\{15, 1\} = 1.
\]
Step 4 Statistical
Decision
To make a statistical decision, we need to find the critical value or
the p-value. The key question is: What is the distribution of the test
statistic? Similar to the sign test, there is an exact distribution and
an approximate distribution.
Exact Distribution
The exact probability distribution is symmetric and can be computed
using recursive methods or lookup tables for small \(n_1, n_2\) (typically \(n_1 ,n_2 \le 20\)). The following table
given critical values for (\(n_1 \le
20\) and \(n_2 \le 20\))
based on the significant level of
0.05.

The Decision Rule based on the critical value from
the above table:
- Reject \(H_0\) if \(U < CV_{\alpha}\) or \(U > n_1n_2 - CV_{\alpha}\)
- Fail to reject \(H_0\) if \(CV_{\alpha} < U < n_1n_2 -
CV_{\alpha}\)
From the above table, for \(n_1 = n_2 =
4\) and \(\alpha = 0.05\)
(one-tailed), the critical value from the Wilcoxon Rank Sum test is 0.
Recall that \(U = 1\). We see that
\(0 = CV_{0.05} < U < 16\), we
fail to reject the null hypothesis \(H_0\). That is, the two distributions are
not significantly different.
Normal Approximation
If \(n_1 > 20 \ \ \text{and} \ \ n_2
> 20\),
\[
Z = \frac{U - \mu_U}{\sigma_U} \rightarrow N(0,1),
\]
where
\[
\mu_U = \frac{n_1n_2}{2} \ \ \text{and} \ \ \sigma_U =
\sqrt{\frac{n_1n_2(n_1+n_2+1)}{12}}.
\]
We can either normal table or software to find the critical value and
p-value.
The following short video (https://pengdsci.github.io/STA200/week03/Nonparametrics-WilcoxonTest.mp4)
explains the Wilcoxon Rank Sum test with manually worked examples.
Table 9 in Appendix B in the video refers to the
U-table with significance level of \(\alpha =
0.05\).
Implementation Using
R
The R function wilcox.test()
in the base package
{stats} implements the rank sum test.
The key arguments are
- Define two vectors to store the group values.
alternative = "two.sided"
(default, tests for any
difference).
exact = TRUE
(for small samples, computes exact
p-value). If FALSE
, uses normal approximation (recommended
for large samples).
paired = FALSE
(default, ensures it’s an
independent-samples test).
# Define vectors to store values from Group A and Group B, respectively
group.A <- c(10, 12, 14, 16)
group.B <- c(15, 18, 20, 22)
# Perform Wilcoxon Rank Sum Test (Mann-Whitney U)
result <- wilcox.test(group.A, group.B, alternative = "two.sided", exact = TRUE)
result
|
| Wilcoxon rank sum exact test
|
| data: group.A and group.B
| W = 1, p-value = 0.05714
| alternative hypothesis: true location shift is not equal to 0
The above results show that the test statistic W = 1 and p-value =
0.0574. At the significance level of 0.05, the null hypothesis was not
rejected. This is consistent with the result obtained previously based
on the critical value method.
Case study - Pima
Indian Diabetes
To conclude this section, we implement the Wilcoxon Rank Sum test to
assess whether the distribution of BMIs is the same between diabetes and
diabetes-free populations. We will reload the data and define vectors to
store BMI for the two populations. Since both sample sizes are larger
than 20, we will use the approximation approach for the p-value.
# read data into R
PimaIndiaDiabetes <- read.csv("https://pengdsci.github.io/STA200/dataset/PimaIndiaDiabetes.csv")
# define BMI for diabetes and diabetes-free population
sub.diabetes <- PimaIndiaDiabetes[ , c("mass", "diabetes")] # values in the vector must be COMMA separated!
diabetes.id <- which(sub.diabetes$diabetes == "pos")
diabetes.pop <- sub.diabetes[diabetes.id, ]
no.diabetes.pop <- sub.diabetes[-diabetes.id, ]
##
diabetes.BMI <- diabetes.pop$mass
no.diabetes.BMI <- no.diabetes.pop$mass
## Wilcoxon test
wilcox.test(diabetes.BMI, no.diabetes.BMI, alternative = "two.sided", exact = FALSE)
|
| Wilcoxon rank sum test with continuity correction
|
| data: diabetes.BMI and no.diabetes.BMI
| W = 22608, p-value = 1.287e-07
| alternative hypothesis: true location shift is not equal to 0
The above test result shows that the null hypothesis is rejected
(\(p \approx 0\)). This means the
distributions of BMIs in the two groups are different.

The above overlaid density curves also showed the difference between
the two distributions.
Two-Paired-Sample
Tests
The two-sample tests discussed in the previous section are based on
two independent samples drawn from two independent
populations. For example, we may take two sets of new CS graduates
(subjects
) from two different universities and compare
their starting salaries (measurements
). In practical
applications, however, there are situations in which only one set of
subjects
is drawn from a single population, but
measurements
are taken twice from each subject at two
different time points. The two sets of sample measurements
in this case are called paired samples. For example, a
clinical trial investigates whether a new blood pressure (BP) medication
reduces systolic BP in hypertensive patients.
- Measurements: Systolic BP (mmHg) recorded before
and after 4 weeks of treatment.
- Sample Size: 10 patients (small sample
implies normality check crucial).

Because each pair of measurements is taken from the same patient and
therefore correlated (i.e., dependent), we cannot use the two-sample
tests introduced in previous sections to assess the treatment effect. It
is reasonable to take the difference between each pair of measurements
so that each subject has a single resulting value. This transforms the
two-correlated-sample problem into a one-sample situation.
Paired Sample t
Test
We have covered this topic in MAT121/125. The basic assumptions
are
- The differences are normally distributed
- The standard deviation of the population of
differences is unknown.
We will not repeat the details of the one-sample t test. Next, we use
the R function t.test()
to assess the treatment effect
based on the above data table.
before <- c(150, 160, 145, 155, 140, 165, 152, 158, 148, 162)
after <- c(140, 155, 142, 150, 138, 160, 148, 152, 145, 156)
differences <- after - before
##
t.test(differences)
|
| One Sample t-test
|
| data: differences
| t = -6.9374, df = 9, p-value = 6.779e-05
| alternative hypothesis: true mean is not equal to 0
| 95 percent confidence interval:
| -6.497808 -3.302192
| sample estimates:
| mean of x
| -4.9
That the p-value is approximately equal to 0 implies a significant
treatment effect.
Wilcoxon Signed Rank
Test
The Wilcoxon Signed-Rank Test is a nonparametric
alternative to the paired t-test, used when comparing
two related (paired) samples where data is not
normally distributed. It assesses whether the median
difference between pairs is zero.
The following Illustrative Example Data will be used
to explain the procedure of the Wilcoxon Signed Rank
Test
A study investigates whether a new pain relief medication reduces
pain scores (on a 0-10 scale) in patients with chronic back pain. Pain
scores are measured before and after 1 week of treatment.

Steps for Wilcoxon Signed Rank Test
- Exclude zero differences (Patient 2 is removed,
remaining n=9).
- Rank absolute differences (ignoring sign):
- Differences: -2, -1, -4, -1, +1, -3, +1, -2, -1
- Absolute: 2, 1, 4, 1, 1, 3, 1, 2, 1
- Sorted: 1, 1, 1, 1, 1, 2, 2, 3, 4
- Ranks: 1s → avg rank = 3, 2s → 6.5, 3 → 8, 4 → 9.
- Sum ranks for positive and negative differences:
- Positive differences (+1, +1): Ranks = 3, 3 → Sum = 6.
- Negative differences: Sum = 3 + 6.5 + 6.5 + 8 + 9 + 3 = 36.
- Test statistic (W) = smaller sum = 6.
- Compare to critical value (from the following
Wilcoxon crtical value table) at \(\alpha =
0.05\) for \(n = 9\) which is
5.

Since the \(TS = 6 > 5 =
CV_{0.05}\), the null hypothesis is rejected. That means the
treatment is effective.
Next, we use R function
wilcox.test()` to perform the signed
rank test:
# Pain scores (0-10 scale)
before <- c(7, 6, 8, 9, 5, 7, 6, 8, 4, 7)
after <- c(5, 6, 7, 5, 4, 8, 3, 9, 2, 6)
# Compute differences (After - Before)
differences <- after - before
# Perform the test (paired=TRUE)
wilcox.test(before, after, paired = TRUE, exact = FALSE, correct = FALSE)
|
| Wilcoxon signed rank test
|
| data: before and after
| V = 39, p-value = 0.04639
| alternative hypothesis: true location shift is not equal to 0
The p-value (0.046) is less than 0.05, which means we reject the null
hypothesis. Both the p-value and critical value methods lead to the same
conclusion.
LS0tDQp0aXRsZTogIlR3by1zYW1wbGUgVGVzdHMgZm9yIExvY2F0aW9ucyINCmF1dGhvcjogIkNoZW5nIFBlbmciDQpkYXRlOiAiU1RBMjAwIFN0YXRpc3RpY3MgSUkgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogNQ0KICAgIGZpZ19oZWlnaHQ6IDQNCi0tLQ0KDQpgYGB7PWh0bWx9DQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoNCmRpdiNUT0MgbGkgew0KICAgIGxpc3Qtc3R5bGU6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDIgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KPC9zdHlsZT4NCmBgYA0KDQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCg0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KIyBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICJDOi9Vc2Vycy83NUNQRU5HL09uZURyaXZlIC0gV2VzdCBDaGVzdGVyIFVuaXZlcnNpdHkgb2YgUEEvRG9jdW1lbnRzIikNCiMga25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSAiQzpcXFNUQTQ5MFxcdzA1IikNCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gVFJVRSwgICANCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9ICJ8IikNCmBgYA0KDQoNCg0KXA0KDQoNCiMgSW50cm9kdWN0aW9uDQoNClR3by1zYW1wbGUgdGVzdHMgYXJlIHN0YXRpc3RpY2FsIG1ldGhvZHMgdXNlZCB0byBjb21wYXJlIHR3byBncm91cHMgKHNhbXBsZXMpIHRvIGRldGVybWluZSB3aGV0aGVyIHRoZXkgY29tZSBmcm9tIHRoZSBzYW1lIHBvcHVsYXRpb24gb3IgaGF2ZSBkaWZmZXJlbnQgY2hhcmFjdGVyaXN0aWNzLiBBcyB5b3UgaGF2ZSBsZWFybmVkIGluIG9uZS1zYW1wbGUgdGVzdHMsIHR3by1zYW1wbGUgdGVzdHMgY2FuIGJlIGJyb2FkbHkgY2xhc3NpZmllZCBpbnRvOg0KDQoqKlBhcmFtZXRyaWMgVGVzdHMqKjogIEFzc3VtZSBkYXRhIGZvbGxvd3MgYSBzcGVjaWZpYyBkaXN0cmlidXRpb24gKHVzdWFsbHkgbm9ybWFsKSBhbmQgY29tcGFyZSBwYXJhbWV0ZXJzIGxpa2UgbWVhbnMgb3IgdmFyaWFuY2VzLg0KDQoqKk5vbnBhcmFtZXRyaWMgVGVzdHMqKjogIE1ha2UgZmV3ZXIgYXNzdW1wdGlvbnMgYWJvdXQgdGhlIGRhdGEgZGlzdHJpYnV0aW9uIGFuZCBhcmUgdXNlZCB3aGVuIHBhcmFtZXRyaWMgYXNzdW1wdGlvbnMgYXJlIHZpb2xhdGVkLg0KDQpUaGlzIG1vZHVsZSByZXZpZXdzIHBhcmFtZXRyaWMgdHdvLXNhbXBsZSB0ZXN0cyBmaXJzdCBhbmQgdGhlbiBkaXNjdXNzZXMgbm9uLXBhcmFtZXRyaWMgdHdvLXNhbXBsZSB0ZXN0cy4gDQoNClwNCg0KIyAoUmF3KSBEYXRhIFN0cnVjdHVyZSANCg0KRm9yIGNvbnZlbmllbmNlLCB3ZSBpbmNsdWRlIHRoZSBzZWN0aW9uIG9uIGRhdGEgc3RydWN0dXJlcyBmcm9tIHRoZSBwcmV2aW91cyBtb2R1bGUuIEFsbCBwcm9jZWR1cmVzIGludHJvZHVjZWQgaW4gdGhpcyBtb2R1bGUgd2lsbCB1c2UgdGhlIHJhdyBkYXRhIHRhYmxlIHdpdGggdGhlIGZvbGxvd2luZyBsYXlvdXQ6DQoNCnwgWSAgIHwgICRYXzEkICB8ICAkWF8yJCAgfCAkXGNkb3RzJCAgIHwgICAkWF9rJCAgfA0KfDotLS0tfDotLS0tLS0tLS0tfDotLS0tLS0tLXw6LS0tLS0tLS0tLS18Oi0tLS0tLS0tLXwNCnwgJHlfMSR8ICR4X3sxMX0kIHwgJHhfezIxfSR8ICRcY2RvdHMkIHwgJHhfe2sxfSQgICB8DQp8ICR5XzIkfCAkeF97MTJ9JCB8ICR4X3syMn0kfCAkXGNkb3RzJCB8ICR4X3trMn0kICAgfA0KfCAkeV8zJHwgJHhfezEzfSQgfCAkeF97MjN9JHwgJFxjZG90cyQgfCAkeF97azN9JCAgIHwNCnwgJFx2ZG90cyR8ICRcdmRvdHMkfCAkXHZkb3RzJHwgJFx2ZG90cyQgfCAkXHZkb3RzJCB8DQp8ICR5X24kfCAkeF97MW59JCB8ICR4X3sybn0kfCAkXGNkb3RzJCB8ICR4X3trbn0kICAgfA0KDQpGb3IgZXhhbXBsZSwgYW4gZW1wbG95ZXIgd2FudHMgdG8gc2VlIHdoZXRoZXIgdGhlaXIgcGF5IHJhdGUgaXMgZmFpciBpbiB0ZXJtcyBvZiBnZW5kZXIgKGkuZS4sIGFzc2Vzc2luZyBwb3RlbnRpYWwgZ2FwcyBpbiBwYXkgcmF0ZSBiZXR3ZWVuIG1hbGUgYW5kIGZlbWFsZSBlbXBsb3llZXMgaW4gdGhlIHNhbWUgcm9sZSB1bmRlciBzaW1pbGFyIGNvbmRpdGlvbnMpLiBUaGUgSFIgaGVscGVkIHRvIGNyZWF0ZSBhIGRhdGFzZXQgaW4gdGhlIGZvbGxvd2luZyBmb3JtLg0KDQoNCnwgc2FsYXJ5ICgkWSQpICAgfCBnZW5kZXIgKCRYXzEkKSB8ICByb2xlICgkWF8yJCkgfCBZcl9lZHUgKCRYXzMkKSB8IFlyX2V4cCAoJFhfNCQpfA0KfC0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS18DQp8JDU2LDIzMCAgICAgICAgfCBGICAgICAgICAgICAgfCBhbmFseXN0ICAgICAgICAgfCAxMiAgICAgICAgICAgIHwgNCAgICAgICAgICAgICAgIHwNCnwkNzMsNDUwICAgICAgICB8IE0gICAgICAgICAgICB8IG1hbmFnZXIgICAgICAgICB8IDE2ICAgICAgICAgICAgfCA4ICAgICAgICAgICAgICAgfA0KfCQ0Nyw1MjAgICAgICAgIHwgTSAgICAgICAgICAgIHwgYW5hbHlzdCAgICAgICAgIHwgMTQgICAgICAgICAgICB8IDMgICAgICAgICAgICAgICB8DQp8JDExMSwxOTAgICAgICAgfCBGICAgICAgICAgICAgfCBtYW5hZ2VyICAgICAgICAgfCAxOCAgICAgICAgICAgIHwgMTIgICAgICAgICAgICAgIHwgDQp8JDY2LDgwMCAgICAgICAgfCBGICAgICAgICAgICAgfCBhbmFseXN0ICAgICAgICAgfCAxNCAgICAgICAgICAgIHwgNyAgICAgICAgICAgICAgIHwNCnwkNjMsMTcwICAgICAgICB8IE0gICAgICAgICAgICB8IGFuYWx5c3QgICAgICAgICB8IDE2ICAgICAgICAgICAgfCA2ICAgICAgICAgICAgICAgfA0KfCQ3Nyw0MzAgICAgICAgIHwgTSAgICAgICAgICAgIHwgYW5hbHlzdCAgICAgICAgIHwgMTYgICAgICAgICAgICB8IDkgICAgICAgICAgICAgICB8DQp8JDk5LDI4MCAgICAgICAgfCBGICAgICAgICAgICAgfCBhbmFseXN0ICAgICAgICAgfCAxOCAgICAgICAgICAgIHwgMTMgICAgICAgICAgICAgIHwgDQoNCldlIGFsc28gaW50cm9kdWNlZCBSIGRhdGEgZnJhbWVzIGVhcmxpZXIgdG8gc3RvcmUgYSBkYXRhc2V0IGluIFIgYW5kIHRoZW4gdXNlIGl0IGZvciBhbmFseXNpcy4gVGhlIG5leHQgUiBjb2RlIGRlZmluZXMgYSBkYXRhZnJhbWUgaW4gUiBiYXNlZCBvbiB0aGUgYWJvdmUgdG95IGRhdGFzZXQuDQoNCmBgYHtyfQ0KbXkudG95LmRhdGEgPC0gZGF0YS5mcmFtZShzYWxhcnkgPSBjKDU2MjMwLCA3MzQ1MCwgNDc1MjAsIDExMTE5MCwgNjY4MDAsIDYzMTcwLCA3NzQzMCwgOTkyODApLCAgICMgbnVtZXJpY2FsIHZhbHVlcw0KICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5kZXIgPSBjKCJGIiwgIk0iLCAiTSIsICJGIiwgIkYiLCAiTSIsICJNIiwgIkYiKSwgICAgICAgICAgICAjIGNoYXJhY3RlciAoY2F0ZWdvcmljYWwpIHZhbHVlcw0KICAgICAgICAgICAgICAgICAgICAgICAgICByb2xlID0gYygiYW5hbHlzdCIsICJtYW5hZ2VyIiwgImFuYWx5c3QiLCAibWFuYWdlciIsICJhbmFseXN0IiwgImFuYWx5c3QiLCAiYW5hbHlzdCIsICJhbmFseXN0IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgIFlyLmVkdSA9IGMoMTIsIDE2LCAxNCwgMTgsIDE0LCAxNiwgMTYsIDE4KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgWXIuZXhwID0gYyg0LDgsMywxMiw3LDYsOSwxMykNCiAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KbXkudG95LmRhdGEgICAgICMgcHJpbnQgdGhlIGRhdGENCmBgYA0KDQo8Zm9udCBjb2xvciA9ICJyZWQiIHNpemUgPSA0PioqXGNvbG9ye3JlZH1TaW5jZSB3ZSB3aWxsIHdvcmsgd2l0aCBtb3JlIHRoYW4gb25lIHZhcmlhYmxlIHN0YXJ0aW5nIGZyb20gdGhpcyBtb2R1bGUsIHdlIGludHJvZHVjZSBhIGZldyBjb21tYW5kcyB5b3UgY2FuIHVzZSB0byBzZWxlY3Qgcm93cywgY29sdW1ucywgb3IgaW5kaXZpZHVhbCBjZWxsIHZhbHVlcyBpbiBhIGRhdGEgZnJhbWUuKio8L2ZvbnQ+ICBUaGUgZm9sbG93aW5nIGZpZ3VyZSBzaG93cyB0aGUgYmFzaWNzIG9uIGhvdyB0byBhY2Nlc3MgYW4gUiBkYXRhIGZyYW1lLg0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjcwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDMvQWNjZXNzaW5nRGF0YUZyYW1lLnBuZyIpDQpgYGANCg0KKipUaGUgZm9sbG93aW5nIGFyZSBhIGZldyBleGFtcGxlcyoqDQoNCg0KKioxLiBFeHBsaWNpdCBBY2Nlc3MqKg0KDQpgYGB7cn0NCiMgU2VsZWN0IGEgc2luZ2xlIGNlbGwgbG9jYXRlZCBhdCB0aGUgaW50ZXJzZWN0aW9uIG9mIHJvdyAyIGFuZCBjb2x1bW4gMw0KbXkudG95LmRhdGFbMiwzXQ0KDQojIG11bHRpcGxlIGNlbGxzIGludm9sdmUgbXVsdGlwbGUgcm93cyBhbmQgY29sdW1ucy4gSW4gdGhpcyBjYXNlLCBpbmRpY2VzIG11c3QgYmUgDQojIHByb3ZpZGVkIGluIHRoZSBmb3JtIG9mIHZlY3RvciwgZS5nLiwgYygyLDUsNikNCm15LnRveS5kYXRhW2MoMyw2KSwgYygxLDMpXQ0KDQojIHNlbGVjdCBvbmUgY29sdW1uIGFuZCBBTEwgcm93cw0KbXkudG95LmRhdGFbICwgNF0NCg0KIyBzZWxlY3QgbXVsdGlwbGUgY29sdW1ucyBhbmQgQUxMIHJvd3MNCm15LnRveS5kYXRhWyAsIGMoMSw1KV0NCg0KIyBzZWxlY3QgbXVsdGlwbGUgY29sdW1ucyBhbmQgQUxMIHJvd3MgdXNpbmcgdmFyaWFibGUgbmFtZXMNCm15LnRveS5kYXRhWyAsIGMoInNhbGFyeSIsICJnZW5kZXIiLCAicm9sZSIpXSAgICMgdmVjdG9yIHdpdGggY2hhcmFjdGVyIHZhbHVlcyBpbiBxdW90ZXMhDQoNCiMgc2VsZWN0IG9uZSByb3cgKGFsc28gY2FsbGVkIG9uZSByZWNvcmQpIGFuZCBBTEwgY29sdW1ucw0KbXkudG95LmRhdGFbNCAsIF0NCg0KIyBzZWxlY3QgbXVsdGlwbGUgcm93cyBhbmQgQUxMIGNvbHVtbnMNCm15LnRveS5kYXRhW2MoMSw1KSAsIF0NCmBgYA0KDQoNCioqMi4gQ29uZGl0aW9uYWwgQWNjZXNzKioNCg0KSW4gYXBwbGljYXRpb24sIHNvbWV0aW1lcyB3ZSBuZWVkIHRvIHNlbGVjdCBhIHN1YnNldCBvZiB0aGUgZGF0YSB1bmRlciBjZXJ0YWluIGNvbmRpdGlvbnMgZGVmaW5lZCBiYXNlZCBvbiB2YXJpYWJsZXMuIEZvciBleGFtcGxlLCBpZiB3ZSB3YW50IHRvIGNvbXBhcmUgdGhlIG1lYW4gc2FsYXJ5IGJldHdlZW4gbWFsZSBhbmQgZmVtYWxlIGVtcGxveWVlcyBpbiBhIGNvbXBhbnksIHdlIG5lZWQgdG8gY2FsY3VsYXRlIHRoZSBzYW1wbGUgc2l6ZSwgbWVhbiwgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiwgcmVzcGVjdGl2ZWx5LCBmcm9tIHRoZSBtYWxlIGFuZCBmZW1hbGUgZ3JvdXBzIGluIGludHJvZHVjdG9yeSBzdGF0aXN0aWNzIGNsYXNzZXMuDQoNClRoZXJlIGFyZSBkaWZmZXJlbnQgUiBjb21tYW5kcyB0byBhY2hpZXZlIHRoaXMgZ29hbC4gV2UgdXNlIGB3aGljaCgpYCB0byBpZGVudGlmeSBzYWxhcmllcyBmb3IgbWFsZSBhbmQgZmVtYWxlIGVtcGxveWVlcywgcmVzcGVjdGl2ZWx5LiBUaGUgZm9sbG93aW5nIGNvZGUgc2hvd3MgaG93IHRvIHNlcGFyYXRlIHRoZSBzYWxhcmllcyBvZiB0aGUgdHdvIGdyb3Vwcy4NCg0KYGBge3J9DQojIHVzZSBteS50b3kuZGF0YSRnZW5kZXIgdG8gaWRlbnRpZnkgbWFsZSBncm91cA0KbWFsZS5pZCA8LSB3aGljaChteS50b3kuZGF0YSRnZW5kZXIgPT0gIk0iKSAgICAjIENBVVRJT046IGRvdWJsZSBlcXVhbCBzaWduICg9PSkgTVVTVCBiZSB1c2VkIGluIGNvbmRpdGlvbmFsIHRlc3RpbmchISENCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBUaGlzIHdpbGwgcmV0dXJuIHRoZSByb3cgaW5kZXhlcyBvZiBtYWxlIGVtcGxveWVlcw0KIyBVc2UgdGhlIGFib3ZlIHJldHVybmVkIHJvdyBpbmRleCB0byBleHRyYWN0IHRoZSB0d28gZ3JvdXBzDQptYWxlLnNhbGFyeSA8LSBteS50b3kuZGF0YVttYWxlLmlkLCBdICAgICAgICAgICMgbWFsZSBncm91cA0KZmVtYWxlLnNhbGFyeSA8LSBteS50b3kuZGF0YVsgLSBtYWxlLmlkLCBdICAgICAjICItIG1hbGUuaWQiOiBub3QgbWFsZSA9PiBmZW1hbGUgaW5kZXhlcyANCmBgYA0KDQpQcmludCBvdXQgdGhlIGFib3ZlIHN1YnNldC4NCg0KYGBge3J9DQojIw0KbWFsZS5zYWxhcnkNCiMjDQpmZW1hbGUuc2FsYXJ5DQpgYGANCg0KXA0KDQojIFR3by1TYW1wbGUgdC1UZXN0IFJldmlzaXRlZA0KDQpSZWNhbGwgdGhhdCwgaW4gaW50cm9kdWN0b3J5IHN0YXRpc3RpY3MgKE1BVDEyMS8xMjUpLCB0aGUgYXNzdW1wdGlvbnMgb2YgdGhlIHR3byB0LXRlc3QgYXJlDQoNCiogQm90aCBwb3B1bGF0aW9ucyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQNCiogQm90aCBwb3B1bGF0aW9uIHZhcmlhbmNlcyBhcmUgdW5rbm93biBidXQgZXF1YWwNCg0KVW5kZXIgdGhlIGFib3ZlIGFzc3VtcHRpb25zLCB0aGUgdHdvIHJhbmRvbSBzYW1wbGVzIHdlcmUgdGFrZW4gZnJvbSB0aGUgdHdvIGluZGVwZW5kZW50IHBvcHVsYXRpb25zLCByZXNwZWN0aXZlbHksIHdpdGggdGhlIGZvbGxvd2luZyBzdGF0aXN0aWNzLg0KDQp8ICoqVHlwZSBvZiBTdGF0aXN0aWNzKiogfCAgKipzYW1wbGUgMSoqICB8ICoqc2FtcGxlIDIqKiB8DQp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS18DQp8IHNhbXBsZSBzaXplICAgICAgICAgICAgfCAgICRuXzEkICAgICAgICB8ICAkbl8yJCAgICAgICB8DQp8IHNhbXBsZSBtZWFuICAgICAgICAgICAgfCAgICRcYmFye3h9XzEkICB8ICAkXGJhcnt4fV8yJCB8DQp8c2FtcGxlIHN0YW5kYXJkIGRldmlhdGlvbnwgICRzXzEkICAgICAgICB8ICAkc18yJA0KDQoNClVuZGVyIHRoZSBzZWNvbmQgYXNzdW1wdGlvbiwgd2UgbmVlZCB0byBlc3RpbWF0ZSB0aGUgKipjb21tb24gc3RhbmRhcmQgZGV2aWF0aW9uKiogYnkgcG9vbGluZyB0d28gc2FtcGxlcyB1c2luZyB0aGUgZm9sbG93aW5nIGZvcm11bGEuDQoNCiQkDQpzX3tcdGV4dHtwb29sfX0gPSBcc3FydHtcZnJhY3sobl8xLTEpc18xXjIgKyAobl8yLTEpc18yXjJ9e25fMSArIG5fMiAtIDJ9fQ0KJCQNCg0KVGhlIHRlc3Qgc3RhdGlzdGljIGZvciB0ZXN0aW5nICRIXzA6IFxtdV8xIC0gXG11XzIgPSAwIFwgXCBcdGV4dHt2c30gXCBcIEhfYTogXG11XzEgLSBcbXVfMiBcbmUgMCQgaXMgDQoNCiQkDQpUUyA9IFxmcmFjeyhcYmFye3h9XzEgLSBcYmFye3h9XzIpIC0gMH17c197XHRleHR7cG9vbH19XHNxcnR7MS9uXzEgKyAxL25fMn19IFxyaWdodGFycm93IHRfe25fMStuXzIgLTJ9DQokJA0KDQo8Zm9udCBjb2xvciA9ICJyZWQiPioqUmVtYXJrKio8L2ZvbnQ+OiBJZiB0aGUgKiplcXVhbCB2YXJpYW5jZXMqKiBhc3N1bXB0aW9uIGlzIG5vdCBtZXQsIG9uZSBjYW4gdXNlIGFuIGFwcHJveGltYXRlIHQtdGVzdCB1c2luZyB0aGUgV2VsY2gtU2F0dGVydGh3YWl0ZSBwcm9jZWR1cmUuIFRoaXMgYXBwcm94aW1hdGlvbiB3aWxsIG5vdCBiZSBkaXNjdXNzZWQgaW4gdGhpcyBub3RlLiBXZSB3aWxsIGFkZHJlc3MgdGhpcyBpbiB0aGUgc3Vic2VxdWVudCBub3RlcyB1bmRlciBtb3JlIGdlbmVyYWwgc2V0dGluZ3MuDQoNClwNCg0KKipFeGFtcGxlKio6IFdlIHdpbGwgdXNlIHRoZSBQaW1hIEluZGlhbiBEaWFiZXRlcyBkYXRhIHRvIGlsbHVzdHJhdGUgdGhlIGFib3ZlIHR3byBzYW1wbGUgdGVzdHMgdG8gc2VlIHdoZXRoZXIgdGhlIG1lYW4gQk1JIGxldmVscyBkaWZmZXIgYmV0d2VlbiBkaWFiZXRlcyBhbmQgZGlhYmV0ZXMtZnJlZSBwb3B1bGF0aW9ucy4gV2UgbmVlZCB0byBsb2FkIHRoZSBkYXRhIGZpcnN0IGJlZm9yZSBjYWxjdWxhdGluZyB0aGUgcmVsYXRlZCBzdGF0aXN0aWNzIHJlcXVpcmVkIGZvciB0aGUgdGVzdC4gTm90ZSB0aGF0IGRpYWJldGVzIHN0YXR1cyBpcyByZWZsZWN0ZWQgaW4gdGhlIHZhcmlhYmxlIGBkaWFiZXRlc2AuDQoNClwNCg0KJCQNCkhfMDogXG11XzEgLSBcbXVfMiA9IDAgXCBcIFx0ZXh0e3ZzfSBcIFwgSF9hOiBcbXVfMSAtIFxtdV8yIFxuZSAwIA0KJCQNClwNCg0KPGZvbnQgY29sb3IgPSAicmVkIj4qU2luY2UgUiBpcyBzZW5zaXRpdmUsIHdlIG1heSB3YW50IHRvIHVzZSB0aGUgUiBjb21tYW5kKjwvZm9udD4gYGhlYWQoKWAgPGZvbnQgY29sb3IgPSAicmVkIj4qdG8gY2hlY2sgdGhlIGV4YWN0IG5hbWVzIGFuZCBmaXJzdCA2IG9ic2VydmF0aW9ucyBpbiB0aGUgZGF0YSBmcmFtZSo8L2ZvbnQ+IA0KDQpcDQoNCmBgYHtyfQ0KIyByZWFkIGRhdGEgaW50byBSDQpQaW1hSW5kaWFEaWFiZXRlcyA8LSByZWFkLmNzdigiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vU1RBMjAwL2RhdGFzZXQvUGltYUluZGlhRGlhYmV0ZXMuY3N2IikNCiMjIGNoZWNraW5nIHZhcmlhYmxlIG5hbWVzDQpoZWFkKFBpbWFJbmRpYURpYWJldGVzKQ0KYGBgDQoNCiMjIE1hbnVhbCBDYWxjdWxhdGlvbiBVc2luZyBSDQoNCk5leHQsIHdlIHNob3cgc3RlcC1ieS1zdGVwIG1hbnVhbCBjYWxjdWxhdGlvbiBhbmQgdHJhbnNsYXRlIHRoZSBhYm92ZSBmb3JtdWxhcyBkaXJlY3RseSBpbnRvIFIgY29kZSBhbmQgcmVwb3J0IHRoZSB0ZXN0IHN0YXRpc3RpYywgZGVncmVlcyBvZiBmcmVlZG9tLCBhbmQgdGhlIHAtdmFsdWUgZm9yIHN0YXRpc3RpY2FsIGRlY2lzaW9uLiBUbyB0aGlzIGVuZCwgd2UgZGVmaW5lIGEgc3Vic2V0IHdpdGggb25seSB0d28gdmFyaWFibGVzOiBCTUkgKGBtYXNzYCkgYW5kIGBkaWFiZXRlc2AuDQoNCg0KYGBge3J9DQpzdWIuZGlhYmV0ZXMgPC0gUGltYUluZGlhRGlhYmV0ZXNbICwgYygibWFzcyIsICJkaWFiZXRlcyIpXSAgICMgdmFsdWVzIGluIHRoZSB2ZWN0b3IgbXVzdCBiZSBDT01NQSBzZXBhcmF0ZWQhDQpkaWFiZXRlcy5pZCA8LSB3aGljaChzdWIuZGlhYmV0ZXMkZGlhYmV0ZXMgPT0gInBvcyIpDQpkaWFiZXRlcy5wb3AgPC0gc3ViLmRpYWJldGVzW2RpYWJldGVzLmlkLCBdDQpuby5kaWFiZXRlcy5wb3AgPC0gc3ViLmRpYWJldGVzWy1kaWFiZXRlcy5pZCwgXQ0KIyMNCiMjIHN0YXRpc3RpY3MgZm9yIHBvcCAjMQ0KbjEgPC0gbGVuZ3RoKGRpYWJldGVzLnBvcCRtYXNzKQ0KeGJhci4xIDwtIG1lYW4oZGlhYmV0ZXMucG9wJG1hc3MpDQpzLjEgPC0gc2QoZGlhYmV0ZXMucG9wJG1hc3MpDQojIyBzdGF0aXN0aWNzIGZvciBwb3AgIzINCm4yIDwtIGxlbmd0aChuby5kaWFiZXRlcy5wb3AkbWFzcykNCnhiYXIuMiA8LSBtZWFuKG5vLmRpYWJldGVzLnBvcCRtYXNzKQ0Kcy4yIDwtIHNkKG5vLmRpYWJldGVzLnBvcCRtYXNzKQ0KIyMgcG9vbGVkIHN0YW5kYXJkIGRldmlhdGlvbg0Kcy5wb29sIDwtIHNxcnQoKChuMS0xKSpzLjFeMiArIChuMi0xKSpzLjJeMikvKG4xK24yLTIpKQ0KIyMgZXZhbHVhdGUgdGVzdCBzdGF0aXN0aWMNClRTIDwtICgoeGJhci4xLXhiYXIuMiktMCkvKHMucG9vbCpzcXJ0KDEvbjEgKyAxL24yKSkNCiMjIGFic29sdXRlIHZhbHVlIG9mIFRTICAgICANCmFicy5UUyA8LSBhYnMoVFMpDQojI3AtdmFsdWU6IDIgdGltZXMgdGhlIHJpZ2h0LXRhaWwgYXJlYSBmb3IgYSB0d28tc2FtcGxlIHRlc3QNCnAudmFsdWUgPC0gMipwdChhYnMuVFMsIGRmID0gbjErbjItMiwgbG93ZXIudGFpbCA9IEZBTFNFKSAgIyBsb3dlci50YWlsID0gRkFMU0Ugc3BlY2lmaWVzIHRoZSByaWdodCB0YWlsIGFyZWENCiMjIHByaW50IG91dCBzdGF0aXN0aWMsIGRmLCBhbmQgcC12YWx1ZSBpbiBhIGNvbWJpbmVkIHZlY3Rvcg0KY2JpbmQoVFMgPSBUUywgZGYgPSBuMSArbjIgLSAyLCBwLnZhbHVlID0gcC52YWx1ZSkNCmBgYA0KDQpUaGVyZSBpcyBjbGVhciAqKnN0cm9uZyoqIGV2aWRlbmNlIHRoYXQgdGhlIG1lYW4gYm9keSBtYXNzIGluZGljZXMgKEJNSSkgaW4gZGlhYmV0ZXMgYW5kIGRpYWJldGVzLWZyZWUgcG9wdWxhdGlvbnMgYXJlICoqZGlmZmVyZW50KiogKHAgPSA1LjU2MzIyMWUtMDggPCAwLjA1KS4gPGZvbnQgY29sb3IgPSAicmVkIj4qKlRoaXMgaXMgY29uc2lzdGVudCB3aXRoIGNsaW5pY2FsIGZpbmRpbmdzLioqPC9mb250Pg0KDQpcDQoNCg0KIyMgQ2FsbGluZyBSIEJ1aWx0LWluIEZ1bmN0aW9uDQoNCldlIGhhdmUgdXNlZCBgdC50ZXN0KClgIGluIGEgcHJldmlvdXMgbm90ZSBmb3IgYSBvbmUtc2FtcGxlIHQgdGVzdC4gVGhlIHNhbWUgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gcGVyZm9ybSBhIDItc2FtcGxlIHQgdGVzdC4gV2UgbmVlZCB0byBwcm92aWRlIHRoZSBpbmRlcGVuZGVudCBzYW1wbGUgdmVjdG9ycyBkaXJlY3RseSB0byB0aGUgZnVuY3Rpb24gdG8gcHJvZHVjZSB0aGUgcmVzdWx0cy4NCg0KYGBge3J9DQojIFdlIHVzZSB0aGUgdHdvIHNhbXBsZXMgb2YgQk1JIGZvdW5kIHByZXZpb3VzbHk6IA0KdC50ZXN0KGRpYWJldGVzLnBvcCRtYXNzLCBuby5kaWFiZXRlcy5wb3AkbWFzcywgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgdmFyLmVxdWFsID0gVFJVRSkNCmBgYA0KDQpUaGUgYWJvdmUgb3V0cHV0IGluZGljYXRlcyB0aGF0IHRoZSBidWlsdC1pbiBmdW5jdGlvbiBwcm9kdWNlcyB0aGUgc2FtZSByZXN1bHRzLg0KDQpcDQoNCjxmb250IGNvbG9yID0gInJlZCIgc2l6ZSA9IDQ+KipcY29sb3J7cmVkfUFzIGFuIGV4ZXJjaXNlLCB5b3UgY2FuIGV4cGxvcmUgd2hldGhlciB0aGUgbWVhbiBvZiBgZ2x1Y29zZWAgbGV2ZWxzIGluIGRpYWJldGVzIGFuZCBkaWFiZXRlcy1mcmVlIHBvcHVsYXRpb25zIGFyZSBlcXVhbC4qKjwvZm9udD4NCg0KDQpcDQoNCg0KIyBSZWdyZXNzaW9uIEFwcHJvYWNoIHRvIFR3by1zYW1wbGUgdCBUZXN0DQoNClRoZSByZWdyZXNzaW9uIGFwcHJvYWNoIHRvIHRoZSB0d28tc2FtcGxlIHQtdGVzdCBpcyBzdHJhaWdodGZvcndhcmQuIFNwZWNpYWwgYXR0ZW50aW9uIHNob3VsZCBiZSBwYWlkIHRvIHRoZSBtb2RlbCBmb3JtdWxhIGluIHRoYXQgdGhlICoqZ3JvdXAqKiB2YXJpYWJsZSBtdXN0IGJlIG9uIHRoZSByaWdodC1oYW5kIHNpZGUgYW5kIE1VU1QgYmUgYSBmYWN0b3IuIFIgZnVuY3Rpb24gYGZhY3RvcigpYCB0dXJucyBhIHZhcmlhYmxlIGludG8gYSBmYWN0b3IgdmFyaWFibGUuIEluIG90aGVyIHdvcmRzLCB0aGUgbW9kZWwgZm9ybXVsYSBzaG91bGQgYmUgaW4gdGhlIGZvcm0gYGxtKHkgfiBmYWN0b3IoeCksIGRhdGEgPSBkYXRhc2V0Lm5hbWUpYCANCg0KVGhlIGZvbGxvd2luZyB0aHJlZSBsaW5lcyBvZiBjb2RlIHByb2R1Y2UgdGhlIHJlc3VsdHMgaW4gdGhlIGFib3ZlIHR3by1zYW1wbGUgdGVzdCB1c2luZyB0aGUgcmVncmVzc2lvbiBtZXRob2QuDQoNCmBgYHtyfQ0KIyByZWFkIGRhdGEgaW50byBSDQpQaW1hSW5kaWFEaWFiZXRlcyA8LSByZWFkLmNzdigiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vU1RBMjAwL2RhdGFzZXQvUGltYUluZGlhRGlhYmV0ZXMuY3N2IikNCnJlZy4yLnNhbXBsZS50ZXN0IDwtIGxtKG1hc3MgfiBmYWN0b3IoZGlhYmV0ZXMpLCBkYXRhID0gUGltYUluZGlhRGlhYmV0ZXMpDQpzdW1tYXJ5KHJlZy4yLnNhbXBsZS50ZXN0KQ0KYGBgDQoNClRoZSBmb2xsb3dpbmcgYW5ub3RhdGVkIG91dHB1dCBzaG93cyB0aGF0IHRoZSByZXN1bHRzIGFyZSBpZGVudGljYWwgdG8gdGhvc2Ugb2J0YWluZWQgaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24uDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjgwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDMvUmVncmVzc29uLW91dHB1dC5wbmciKQ0KYGBgDQoNClwNCg0KIyBOb24tcGFyYW1ldHJpYyBUd28tc2FtcGxlIFRlc3QNCg0KV2UgaGF2ZSBkaXNjdXNzZWQgdGhlIGNvbXBhcmlzb24gb2YgdHdvIG5vcm1hbCBwb3B1bGF0aW9uIG1lYW5zIHVuZGVyIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIHR3byBwb3B1bGF0aW9ucyBoYXZlIGVxdWFsIHZhcmlhbmNlcywgdXNpbmcgdGhlIHR3by1zYW1wbGUgdC10ZXN0LiBIb3dldmVyLCBpZiBlaXRoZXIgb2YgdGhlIHR3byBhc3N1bXB0aW9uc+KAlG5vcm1hbGl0eSBhbmQgZXF1YWwgdmFyaWFuY2Vz4oCUaXMgbm90IHNhdGlzZmllZCwgdGhlIHR3by1zYW1wbGUgdC10ZXN0IG1heSBub3QgYmUgYXBwcm9wcmlhdGUuDQoNCkluIHN0YXRpc3RpY3MsIHRoZXJlIGFyZSBhbHRlcm5hdGl2ZSBwcm9jZWR1cmVzIGZvciBjb21wYXJpbmcgbnVtZXJpYyBjaGFyYWN0ZXJpc3RpY3MgYmV0d2VlbiBwb3B1bGF0aW9ucyB3aXRob3V0IGFzc3VtaW5nIG5vcm1hbGl0eSBvciBlcXVhbCB2YXJpYW5jZXMuIFRoaXMgc2VjdGlvbiBpbnRyb2R1Y2VzIG9uZSBzdWNoIHRlc3Q6IHRoZSAqKldpbGNveG9uIFJhbmsgU3VtIFRlc3QqKiAoYWxzbyBjYWxsZWQgdGhlICoqTWFubi1XaGl0bmV5IFUgdGVzdCoqKSwgd2hpY2ggYXNzZXNzZXMgPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9d2hldGhlciB0aGUgdHdvIHBvcHVsYXRpb24gZGlzdHJpYnV0aW9ucyBhcmUgZXF1YWwqKjwvZm9udD4uDQoNClRoaXMgaXMgYSBtdWNoIHN0cm9uZ2VyIHRlc3QgYmVjYXVzZSB0aGUgYXNzdW1wdGlvbiBvZiBlcXVhbCBtZWFucyBkb2VzIG5vdCByZXF1aXJlIHRoZSB0d28gcG9wdWxhdGlvbnMgdG8gaGF2ZSBpZGVudGljYWwgZGlzdHJpYnV0aW9ucyAoc2VlIHRoZSBmb2xsb3dpbmcgZmlndXJlKS4NCg0KYGBge3IgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iODAlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoIndlZWswMy9FcXVhbE1lYW5EaWZmRGlzdHJpYnV0aW9uLnBuZyIpDQpgYGANCg0KVGhlICoqV2lsY294b24gUmFuayBTdW0gVGVzdCoqIGFzc2Vzc2VzIHdoZXRoZXIgdHdvIHNhbXBsZWQgZ3JvdXBzIGFyZSBsaWtlbHkgdG8gZGVyaXZlIGZyb20gdGhlIHNhbWUgcG9wdWxhdGlvbi4gQSBjb21tb24gbWlzY29uY2VwdGlvbiBpcyB0aGF0IGl0IGNvbXBhcmVzIG1lZGlhbnMsIGJ1dCB0aGlzIGlzICoqb25seSB0cnVlIGlmIHRoZSBkaXN0cmlidXRpb25zIGFyZSBzeW1tZXRyaWMgYW5kIGRpZmZlciBvbmx5IGluIGxvY2F0aW9uKiouIEluIG90aGVyIHdvcmRzLCBpZiB0aGUgZGlzdHJpYnV0aW9ucyBoYXZlIGRpZmZlcmVudCBzaGFwZXMgKGUuZy4sIHNrZXduZXNzIG9yIHZhcmlhbmNlIGRpZmZlcmVuY2VzKSwgdGhlIHRlc3QgbWF5IHN0aWxsIHJlamVjdCAoJEhfMCQpIGV2ZW4gaWYgbWVkaWFucyBhcmUgZXF1YWwgKHNlZSB0aGUgYWJvdmUgZmlndXJlKS4NCg0KDQoNClRoZSBoeXBvdGhlc2VzIGluIGEgKip0d28tdGFpbGVkIFdpbGNveG9uIFJhbmsgU3VtIFRlc3QqKiBhcmU6DQoNCg0KKiBUaGUgPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9bnVsbCBoeXBvdGhlc2lzICgkSF8wJCkqKjwvZm9udD4gaXMgdGhhdCB0aGUgKip0d28gcG9wdWxhdGlvbiBkaXN0cmlidXRpb25zIGFyZSBlcXVhbCoqLg0KDQoqIFRoZSA8Zm9udCBjb2xvciA9ICJyZWQiPioqXGNvbG9ye3JlZH1hbHRlcm5hdGl2ZSBoeXBvdGhlc2lzICgkSF8xJCkqKjwvZm9udD4gaXMgdGhhdCB0aGUgKip0d28gcG9wdWxhdGlvbiBkaXN0cmlidXRpb25zIGFyZSBub3QgZXF1YWwqKi4NCg0KXA0KDQo8Zm9udCBjb2xvciA9ICJyZWQiIHNpemUgPTQ+KipcY29sb3J7cmVkfVJlbWFyayoqPC9mb250PjogPGZvbnQgY29sb3IgPSAiYmx1ZSIgc2l6ZSA9IDQ+Klxjb2xvcntibHVlfSBvbmUtdGFpbGVkIFdpbGNveG9uIFJhbmsgU3VtIFRlc3RzIGNvbXBhcmUgc3RvY2hhc3RpYyBkb21pbmFuY2UgYmV0d2VlbiB0aGUgdHdvIGRpc3RyaWJ1dGlvbnMuIFRoaXMgaXMgb3V0IG9mIHRoZSBzY29wZSBvZiB0aGlzIGNsYXNzLiBXZSB3aWxsIG5vdCBkaXNjdXNzIHRoaXMgdG9waWMgaW4gdGhpcyBjbGFzcy4qPC9mb250Pg0KDQpcDQoNCiMjIE1hbnVhbCBJbXBsZW1lbnRhdGlvbg0KDQpOZXh0LCB3ZSBkaXNjdXNzIHRoZSBkZXZlbG9wbWVudCBvZiB0aGUgKipXaWxjb3hvbiBSYW5rIFN1bSoqIHRlc3QuIFRvIGhlbHAgeW91IHVuZGVyc3RhbmQgdGhlIHN0ZXBzLCB3ZSB1c2UgdGhlIGZvbGxvd2luZyB0b3kgZGF0YSBzZXQuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjMwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDMvV2lsY294LVRveS1EYXRhLnBuZyIpDQpgYGANCg0KXA0KDQo8Zm9udCBjb2xvciA9ICJkYXJrcmVkIj4qKlN0ZXAgMSoqOiBSYW5raW5nIHRoZSBEYXRhPC9mb250Pg0KDQoqIENvbWJpbmUgdGhlIGRhdGEgZnJvbSBib3RoIGdyb3VwcyBpbnRvIGEgc2luZ2xlIGRhdGFzZXQgYW5kIHNvcnQgdGhlbSBpbiA8Zm9udCBjb2xvciA9ICJyZWQiPioqXGNvbG9ye3JlZH0gYXNjZW5kaW5nIG9yZGVyKio8L2ZvbnQ+OiBgMTAsIDEyLCAxNCwgMTUsIDE2LCAxOCwgMjAsIDIyYA0KDQoqIEFzc2lnbiByYW5rcyB0byBhbGwgb2JzZXJ2YXRpb25zIGZyb20gc21hbGxlc3QgdG8gbGFyZ2VzdCAoPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9dGllZCB2YWx1ZXMgcmVjZWl2ZSB0aGUgYXZlcmFnZSByYW5rKio8L2ZvbnQ+KTogYDEsIDIsIDMsIDQsIDUsIDYsIDcsIDhgLiANCg0KDQo8Zm9udCBjb2xvciA9ICJkYXJrcmVkIj4qKlN0ZXAgMioqOiBSYW5raW5nIHRoZSBEYXRhPC9mb250Pg0KDQoqIFN1bSB0aGUgcmFua3MgZm9yIGVhY2ggZ3JvdXAgPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9c2VwYXJhdGVseSoqPC9mb250Pi4NCiAgKyAkUl8xID0gJCBTdW0gb2YgcmFua3MgZm9yIEdyb3VwIDE6ICRSX0EgPSAxKzIrMys1PTExJA0KICArICRSXzIgPSAkIFN1bSBvZiByYW5rcyBmb3IgR3JvdXAgMjogJFJfQiA9IDQrNis3Kzg9MjUkDQoNCg0KPGZvbnQgY29sb3IgPSAiZGFya3JlZCI+KipTdGVwIDMqKiBDb21wdXRlIHRoZSBUZXN0IFN0YXRpc3RpYyAoVSk8L2ZvbnQ+DQoNCiogVGhlIHRlc3Qgc3RhdGlzdGljICRVJCBjYW4gYmUgY2FsY3VsYXRlZCBmb3IgZWl0aGVyIGdyb3VwICgkbl8xJCBhbmQgJG5fMiQgYXJlIGdyb3VwIHNpemVzKToNCg0KJCQNClVfMSA9IG5fMW5fMiArIFxmcmFje25fMShuXzErMSl9ezJ9IC0gUl8xDQokJA0KJCQNClVfMiA9IG5fMW5fMiArIFxmcmFje25fMihuXzIrMSl9ezJ9IC0gUl8yDQokJA0KDQpUaGUgdGVzdCBzdGF0aXN0aWMgKGNvbW1vbmx5IGRlbm90ZWQgYnkgVSkgaXMgZGVmaW5lZCB0byBiZQ0KDQokJA0KVSA9IFxtaW4gXHtVXzEsIFVfMiBcfSwNCiQkDQoNClRoYXQgaXMsIFUgaXMgZXF1YWwgdG8gdGhlIHNtYWxsZXIgb2YgJFVfMSQgYW5kICRVXzIkLiANCg0KSW4gdGhlIGFib3ZlIHRveSBleGFtcGxlLA0KDQokJA0KVV9BID0gNFx0aW1lcyA0ICsgXGZyYWN7NCg0KzEpfXsyfSAtIDExID0gMTUNCiQkDQokJA0KVV9BID0gNFx0aW1lcyA0ICsgXGZyYWN7NCg0KzEpfXsyfSAtIDI1ID0gMQ0KJCQNCiQkDQpVID0gXG1pblx7MTUsIDFcfSA9IDEuDQokJA0KDQo8Zm9udCBjb2xvciA9ICJkYXJrcmVkIj4qKlN0ZXAgNCoqIFN0YXRpc3RpY2FsIERlY2lzaW9uPC9mb250Pg0KDQpUbyBtYWtlIGEgc3RhdGlzdGljYWwgZGVjaXNpb24sIHdlIG5lZWQgdG8gZmluZCB0aGUgY3JpdGljYWwgdmFsdWUgb3IgdGhlIHAtdmFsdWUuIFRoZSBrZXkgcXVlc3Rpb24gaXM6IFdoYXQgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgdGVzdCBzdGF0aXN0aWM/IFNpbWlsYXIgdG8gdGhlIHNpZ24gdGVzdCwgdGhlcmUgaXMgYW4gZXhhY3QgZGlzdHJpYnV0aW9uIGFuZCBhbiBhcHByb3hpbWF0ZSBkaXN0cmlidXRpb24uDQoNCioqRXhhY3QgRGlzdHJpYnV0aW9uKioNCg0KVGhlIGV4YWN0IHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbiBpcyBzeW1tZXRyaWMgYW5kIGNhbiBiZSBjb21wdXRlZCB1c2luZyByZWN1cnNpdmUgbWV0aG9kcyBvciBsb29rdXAgdGFibGVzIGZvciBzbWFsbCAkbl8xLCBuXzIkICh0eXBpY2FsbHkgJG5fMSAsbl8yICBcbGUgMjAkKS4gVGhlIGZvbGxvd2luZyB0YWJsZSBnaXZlbiBjcml0aWNhbCB2YWx1ZXMgZm9yICgkbl8xIFxsZSAyMCQgYW5kICRuXzIgXGxlIDIwJCkgPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9YmFzZWQgb24gdGhlIHNpZ25pZmljYW50IGxldmVsIG9mIDAuMDUqKjwvZm9udD4uDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjgwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDMvTWFubi1XaGl0bmV5LVRlc3QtQ1YtVGFibGUucG5nIikNCmBgYA0KDQpUaGUgKipEZWNpc2lvbiBSdWxlKiogYmFzZWQgb24gdGhlIGNyaXRpY2FsIHZhbHVlIGZyb20gdGhlIGFib3ZlIHRhYmxlOg0KDQoqIFJlamVjdCAkSF8wJCBpZiAkVSA8IENWX3tcYWxwaGF9JCBvciAkVSA+IG5fMW5fMiAtIENWX3tcYWxwaGF9JA0KKiBGYWlsIHRvIHJlamVjdCAkSF8wJCBpZiAkQ1Zfe1xhbHBoYX0gPCBVIDwgbl8xbl8yIC0gQ1Zfe1xhbHBoYX0kDQoNCkZyb20gdGhlIGFib3ZlIHRhYmxlLCBmb3IgJG5fMSA9IG5fMiA9IDQkIGFuZCAkXGFscGhhID0gMC4wNSQgKG9uZS10YWlsZWQpLCB0aGUgY3JpdGljYWwgdmFsdWUgZnJvbSB0aGUgV2lsY294b24gUmFuayBTdW0gdGVzdCBpcyAwLiBSZWNhbGwgdGhhdCAkVSA9IDEkLiBXZSBzZWUgdGhhdCAkMCA9IENWX3swLjA1fSA8IFUgPCAxNiQsIHdlIGZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMCQuIFRoYXQgaXMsIHRoZSB0d28gZGlzdHJpYnV0aW9ucyBhcmUgKipub3Qgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQqKi4NCg0KXA0KDQoqKk5vcm1hbCBBcHByb3hpbWF0aW9uKioNCg0KSWYgJG5fMSA+IDIwIFwgXCBcdGV4dHthbmR9IFwgXCAgbl8yID4gMjAkLCANCg0KJCQNClogPSBcZnJhY3tVIC0gXG11X1V9e1xzaWdtYV9VfSBccmlnaHRhcnJvdyBOKDAsMSksDQokJA0KDQp3aGVyZQ0KDQokJA0KXG11X1UgPSBcZnJhY3tuXzFuXzJ9ezJ9IFwgXCBcdGV4dHthbmR9IFwgXCBcc2lnbWFfVSA9IFxzcXJ0e1xmcmFje25fMW5fMihuXzErbl8yKzEpfXsxMn19Lg0KJCQNCg0KV2UgY2FuIGVpdGhlciBub3JtYWwgdGFibGUgb3Igc29mdHdhcmUgdG8gZmluZCB0aGUgY3JpdGljYWwgdmFsdWUgYW5kIHAtdmFsdWUuDQoNClwNCg0KVGhlIGZvbGxvd2luZyBzaG9ydCB2aWRlbyAoPGh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL1NUQTIwMC93ZWVrMDMvTm9ucGFyYW1ldHJpY3MtV2lsY294b25UZXN0Lm1wND4pIGV4cGxhaW5zIHRoZSBXaWxjb3hvbiBSYW5rIFN1bSB0ZXN0IHdpdGggbWFudWFsbHkgd29ya2VkIGV4YW1wbGVzLiAqKlRhYmxlIDkgaW4gQXBwZW5kaXggQioqIGluIHRoZSB2aWRlbyByZWZlcnMgdG8gdGhlIFUtdGFibGUgd2l0aCBzaWduaWZpY2FuY2UgbGV2ZWwgb2YgJFxhbHBoYSA9IDAuMDUkLiANCg0KDQpcDQo8Y2VudGVyPjxhIGhyZWY9Imh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL1NUQTIwMC93ZWVrMDMvTm9ucGFyYW1ldHJpY3MtV2lsY294b25UZXN0Lm1wNCIgdGFyZ2V0PSJwb3B1cCIgDQogICAgICAgICAgICAgICAgICAgb25jbGljaz0id2luZG93Lm9wZW4oJ2h0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL1NUQTIwMC93ZWVrMDMvTm9ucGFyYW1ldHJpY3MtV2lsY294b25UZXN0Lm1wNCcsDQogICAgICAgICAgICAgICAgICAgICAgJ25hbWUnLCd3aWR0aD04NTAsaGVpZ2h0PTUwMCcpIj48aW1nIHNyYyA9ICJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9NQVQxMjFXNS9pbWcvVmlkZW9JY29uLnBuZyIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMjAiPjwvYT4NCjwvY2VudGVyPg0KDQpcDQoNCg0KIyMgSW1wbGVtZW50YXRpb24gVXNpbmcgUg0KDQpUaGUgUiBmdW5jdGlvbiBgd2lsY294LnRlc3QoKWAgaW4gdGhlIGJhc2UgcGFja2FnZSAqKntzdGF0c30qKiBpbXBsZW1lbnRzIHRoZSAqKnJhbmsgc3VtIHRlc3QqKi4gVGhlIGtleSBhcmd1bWVudHMgYXJlDQoNCiogRGVmaW5lIHR3byB2ZWN0b3JzIHRvIHN0b3JlIHRoZSBncm91cCB2YWx1ZXMuDQoqIGBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiYChkZWZhdWx0LCB0ZXN0cyBmb3IgYW55IGRpZmZlcmVuY2UpLg0KKiBgZXhhY3QgPSBUUlVFYCAoZm9yIHNtYWxsIHNhbXBsZXMsIGNvbXB1dGVzIGV4YWN0IHAtdmFsdWUpLiBJZiBgRkFMU0VgLCB1c2VzIG5vcm1hbCBhcHByb3hpbWF0aW9uIChyZWNvbW1lbmRlZCBmb3IgbGFyZ2Ugc2FtcGxlcykuDQoqIGBwYWlyZWQgPSBGQUxTRWAgKGRlZmF1bHQsIGVuc3VyZXMgaXTigJlzIGFuIGluZGVwZW5kZW50LXNhbXBsZXMgdGVzdCkuDQoNCg0KYGBge3J9DQojIERlZmluZSB2ZWN0b3JzIHRvIHN0b3JlIHZhbHVlcyBmcm9tIEdyb3VwIEEgYW5kIEdyb3VwIEIsIHJlc3BlY3RpdmVseQ0KZ3JvdXAuQSA8LSBjKDEwLCAxMiwgMTQsIDE2KQ0KZ3JvdXAuQiA8LSBjKDE1LCAxOCwgMjAsIDIyKQ0KIyBQZXJmb3JtIFdpbGNveG9uIFJhbmsgU3VtIFRlc3QgKE1hbm4tV2hpdG5leSBVKQ0KcmVzdWx0IDwtIHdpbGNveC50ZXN0KGdyb3VwLkEsIGdyb3VwLkIsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIGV4YWN0ID0gVFJVRSkNCnJlc3VsdCAgDQpgYGANCg0KVGhlIGFib3ZlIHJlc3VsdHMgc2hvdyB0aGF0IHRoZSB0ZXN0IHN0YXRpc3RpYyBXID0gMSBhbmQgcC12YWx1ZSA9IDAuMDU3NC4gQXQgdGhlIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAwLjA1LCB0aGUgbnVsbCBoeXBvdGhlc2lzIHdhcyBub3QgcmVqZWN0ZWQuIFRoaXMgaXMgY29uc2lzdGVudCB3aXRoIHRoZSByZXN1bHQgb2J0YWluZWQgcHJldmlvdXNseSBiYXNlZCBvbiB0aGUgY3JpdGljYWwgdmFsdWUgbWV0aG9kLiANCg0KIyMgQ2FzZSBzdHVkeSAtIFBpbWEgSW5kaWFuIERpYWJldGVzDQoNClRvIGNvbmNsdWRlIHRoaXMgc2VjdGlvbiwgd2UgaW1wbGVtZW50IHRoZSBXaWxjb3hvbiBSYW5rIFN1bSB0ZXN0IHRvIGFzc2VzcyB3aGV0aGVyIHRoZSBkaXN0cmlidXRpb24gb2YgQk1JcyBpcyB0aGUgc2FtZSBiZXR3ZWVuIGRpYWJldGVzIGFuZCBkaWFiZXRlcy1mcmVlIHBvcHVsYXRpb25zLiBXZSB3aWxsIHJlbG9hZCB0aGUgZGF0YSBhbmQgZGVmaW5lIHZlY3RvcnMgdG8gc3RvcmUgQk1JIGZvciB0aGUgdHdvIHBvcHVsYXRpb25zLiBTaW5jZSBib3RoIHNhbXBsZSBzaXplcyBhcmUgbGFyZ2VyIHRoYW4gMjAsIHdlIHdpbGwgdXNlIHRoZSBhcHByb3hpbWF0aW9uIGFwcHJvYWNoIGZvciB0aGUgcC12YWx1ZS4NCg0KYGBge3J9DQojIHJlYWQgZGF0YSBpbnRvIFINClBpbWFJbmRpYURpYWJldGVzIDwtIHJlYWQuY3N2KCJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9TVEEyMDAvZGF0YXNldC9QaW1hSW5kaWFEaWFiZXRlcy5jc3YiKQ0KIyBkZWZpbmUgQk1JIGZvciBkaWFiZXRlcyBhbmQgZGlhYmV0ZXMtZnJlZSBwb3B1bGF0aW9uDQpzdWIuZGlhYmV0ZXMgPC0gUGltYUluZGlhRGlhYmV0ZXNbICwgYygibWFzcyIsICJkaWFiZXRlcyIpXSAgICMgdmFsdWVzIGluIHRoZSB2ZWN0b3IgbXVzdCBiZSBDT01NQSBzZXBhcmF0ZWQhDQpkaWFiZXRlcy5pZCA8LSB3aGljaChzdWIuZGlhYmV0ZXMkZGlhYmV0ZXMgPT0gInBvcyIpDQpkaWFiZXRlcy5wb3AgPC0gc3ViLmRpYWJldGVzW2RpYWJldGVzLmlkLCBdDQpuby5kaWFiZXRlcy5wb3AgPC0gc3ViLmRpYWJldGVzWy1kaWFiZXRlcy5pZCwgXQ0KIyMNCmRpYWJldGVzLkJNSSA8LSBkaWFiZXRlcy5wb3AkbWFzcw0Kbm8uZGlhYmV0ZXMuQk1JIDwtIG5vLmRpYWJldGVzLnBvcCRtYXNzDQojIyBXaWxjb3hvbiB0ZXN0DQp3aWxjb3gudGVzdChkaWFiZXRlcy5CTUksIG5vLmRpYWJldGVzLkJNSSwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgZXhhY3QgPSBGQUxTRSkNCmBgYA0KDQpUaGUgYWJvdmUgdGVzdCByZXN1bHQgc2hvd3MgdGhhdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHJlamVjdGVkICgkcCBcYXBwcm94IDAkKS4gVGhpcyBtZWFucyB0aGUgZGlzdHJpYnV0aW9ucyBvZiBCTUlzIGluIHRoZSB0d28gZ3JvdXBzIGFyZSBkaWZmZXJlbnQuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NX0NCmxpYnJhcnkoZ2dwbG90MikNCiNjcmVhdGUgb3ZlcmxheWluZyBkZW5zaXR5IHBsb3RzDQpnZ3Bsb3QoUGltYUluZGlhRGlhYmV0ZXMsIGFlcyh4PW1hc3MsIGZpbGw9ZGlhYmV0ZXMpKSArDQogIGdlb21fZGVuc2l0eShhbHBoYT0uNzUpDQpgYGANCg0KVGhlIGFib3ZlIG92ZXJsYWlkIGRlbnNpdHkgY3VydmVzIGFsc28gc2hvd2VkIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBkaXN0cmlidXRpb25zLg0KDQoNClwNCg0KIyBUd28tUGFpcmVkLVNhbXBsZSBUZXN0cw0KDQpUaGUgdHdvLXNhbXBsZSB0ZXN0cyBkaXNjdXNzZWQgaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24gYXJlIGJhc2VkIG9uIHR3byAqKmluZGVwZW5kZW50IHNhbXBsZXMqKiBkcmF3biBmcm9tIHR3byBpbmRlcGVuZGVudCBwb3B1bGF0aW9ucy4gRm9yIGV4YW1wbGUsIHdlIG1heSB0YWtlIHR3byBzZXRzIG9mIG5ldyBDUyBncmFkdWF0ZXMgKGBzdWJqZWN0c2ApIGZyb20gdHdvIGRpZmZlcmVudCB1bml2ZXJzaXRpZXMgYW5kIGNvbXBhcmUgdGhlaXIgc3RhcnRpbmcgc2FsYXJpZXMgKGBtZWFzdXJlbWVudHNgKS4gSW4gcHJhY3RpY2FsIGFwcGxpY2F0aW9ucywgaG93ZXZlciwgdGhlcmUgYXJlIHNpdHVhdGlvbnMgaW4gd2hpY2ggb25seSBvbmUgc2V0IG9mIGBzdWJqZWN0c2AgaXMgZHJhd24gZnJvbSBhIHNpbmdsZSBwb3B1bGF0aW9uLCBidXQgYG1lYXN1cmVtZW50c2AgYXJlIHRha2VuIHR3aWNlIGZyb20gZWFjaCBzdWJqZWN0IGF0IHR3byBkaWZmZXJlbnQgdGltZSBwb2ludHMuIFRoZSB0d28gc2V0cyBvZiBzYW1wbGUgYG1lYXN1cmVtZW50c2AgaW4gdGhpcyBjYXNlIGFyZSBjYWxsZWQgKipwYWlyZWQgc2FtcGxlcyoqLiBGb3IgZXhhbXBsZSwgYSBjbGluaWNhbCB0cmlhbCBpbnZlc3RpZ2F0ZXMgd2hldGhlciBhIG5ldyBibG9vZCBwcmVzc3VyZSAoQlApIG1lZGljYXRpb24gcmVkdWNlcyBzeXN0b2xpYyBCUCBpbiBoeXBlcnRlbnNpdmUgcGF0aWVudHMuDQoNCiogKipNZWFzdXJlbWVudHMqKjogU3lzdG9saWMgQlAgKG1tSGcpIHJlY29yZGVkIGJlZm9yZSBhbmQgYWZ0ZXIgNCB3ZWVrcyBvZiB0cmVhdG1lbnQuDQoqICoqU2FtcGxlIFNpemUqKjogMTAgcGF0aWVudHMgKHNtYWxsIHNhbXBsZSAqaW1wbGllcyogbm9ybWFsaXR5IGNoZWNrIGNydWNpYWwpLg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI0MCUifQ0KaW5jbHVkZV9ncmFwaGljcygid2VlazAzL1BhaXJlZFNhbXBsZS5wbmciKQ0KYGBgDQoNCkJlY2F1c2UgZWFjaCBwYWlyIG9mIG1lYXN1cmVtZW50cyBpcyB0YWtlbiBmcm9tIHRoZSBzYW1lIHBhdGllbnQgYW5kIHRoZXJlZm9yZSBjb3JyZWxhdGVkIChpLmUuLCBkZXBlbmRlbnQpLCB3ZSBjYW5ub3QgdXNlIHRoZSB0d28tc2FtcGxlIHRlc3RzIGludHJvZHVjZWQgaW4gcHJldmlvdXMgc2VjdGlvbnMgdG8gYXNzZXNzIHRoZSB0cmVhdG1lbnQgZWZmZWN0LiBJdCBpcyByZWFzb25hYmxlIHRvIHRha2UgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBlYWNoIHBhaXIgb2YgbWVhc3VyZW1lbnRzIHNvIHRoYXQgZWFjaCBzdWJqZWN0IGhhcyBhIHNpbmdsZSByZXN1bHRpbmcgdmFsdWUuIFRoaXMgdHJhbnNmb3JtcyB0aGUgdHdvLWNvcnJlbGF0ZWQtc2FtcGxlIHByb2JsZW0gaW50byBhIG9uZS1zYW1wbGUgc2l0dWF0aW9uLg0KDQojIyBQYWlyZWQgU2FtcGxlIHQgVGVzdA0KDQpXZSBoYXZlIGNvdmVyZWQgdGhpcyB0b3BpYyBpbiBNQVQxMjEvMTI1LiBUaGUgYmFzaWMgYXNzdW1wdGlvbnMgYXJlDQoNCiogVGhlIGRpZmZlcmVuY2VzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZA0KKiBUaGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBwb3B1bGF0aW9uIG9mICoqZGlmZmVyZW5jZXMqKiBpcyB1bmtub3duLg0KDQpXZSB3aWxsIG5vdCByZXBlYXQgdGhlIGRldGFpbHMgb2YgdGhlIG9uZS1zYW1wbGUgdCB0ZXN0LiBOZXh0LCB3ZSB1c2UgdGhlIFIgZnVuY3Rpb24gYHQudGVzdCgpYCB0byBhc3Nlc3MgdGhlIHRyZWF0bWVudCBlZmZlY3QgYmFzZWQgb24gdGhlIGFib3ZlIGRhdGEgdGFibGUuDQoNCmBgYHtyfQ0KYmVmb3JlIDwtIGMoMTUwLCAxNjAsIDE0NSwgMTU1LCAxNDAsIDE2NSwgMTUyLCAxNTgsIDE0OCwgMTYyKQ0KYWZ0ZXIgPC0gYygxNDAsIDE1NSwgMTQyLCAxNTAsIDEzOCwgMTYwLCAxNDgsIDE1MiwgMTQ1LCAxNTYpDQpkaWZmZXJlbmNlcyA8LSBhZnRlciAtIGJlZm9yZQ0KIyMNCnQudGVzdChkaWZmZXJlbmNlcykNCmBgYA0KDQpUaGF0IHRoZSBwLXZhbHVlIGlzIGFwcHJveGltYXRlbHkgZXF1YWwgdG8gMCBpbXBsaWVzIGEgc2lnbmlmaWNhbnQgdHJlYXRtZW50IGVmZmVjdC4NCg0KXA0KDQojIyBXaWxjb3hvbiBTaWduZWQgUmFuayBUZXN0DQoNClRoZSAqKldpbGNveG9uIFNpZ25lZC1SYW5rIFRlc3QqKiBpcyBhIG5vbnBhcmFtZXRyaWMgYWx0ZXJuYXRpdmUgdG8gdGhlICoqcGFpcmVkIHQtdGVzdCoqLCB1c2VkIHdoZW4gY29tcGFyaW5nICoqdHdvIHJlbGF0ZWQgKHBhaXJlZCkgc2FtcGxlcyoqIHdoZXJlIGRhdGEgaXMgKipub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQqKi4gSXQgYXNzZXNzZXMgd2hldGhlciB0aGUgKiptZWRpYW4gZGlmZmVyZW5jZSoqIGJldHdlZW4gcGFpcnMgaXMgemVyby4NCg0KVGhlIGZvbGxvd2luZyAqKklsbHVzdHJhdGl2ZSBFeGFtcGxlIERhdGEqKiB3aWxsIGJlIHVzZWQgdG8gZXhwbGFpbiB0aGUgcHJvY2VkdXJlIG9mIHRoZSAqKldpbGNveG9uIFNpZ25lZCBSYW5rIFRlc3QqKg0KDQpBIHN0dWR5IGludmVzdGlnYXRlcyB3aGV0aGVyIGEgbmV3IHBhaW4gcmVsaWVmIG1lZGljYXRpb24gcmVkdWNlcyBwYWluIHNjb3JlcyAob24gYSAwLTEwIHNjYWxlKSBpbiBwYXRpZW50cyB3aXRoIGNocm9uaWMgYmFjayBwYWluLiBQYWluIHNjb3JlcyBhcmUgbWVhc3VyZWQgYmVmb3JlIGFuZCBhZnRlciAxIHdlZWsgb2YgdHJlYXRtZW50Lg0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjgwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDMvU2lnbmVkUmFua1Rlc3REYXRhLnBuZyIpDQpgYGANCg0KDQoqKlN0ZXBzIGZvciBXaWxjb3hvbiBTaWduZWQgUmFuayBUZXN0KioNCg0KKiAqKkV4Y2x1ZGUgemVybyBkaWZmZXJlbmNlcyoqIChQYXRpZW50IDIgaXMgcmVtb3ZlZCwgcmVtYWluaW5nIG49OSkuDQoqICoqUmFuayBhYnNvbHV0ZSBkaWZmZXJlbmNlcyoqIChpZ25vcmluZyBzaWduKToNCiAgKyBEaWZmZXJlbmNlczogLTIsIC0xLCAtNCwgLTEsICsxLCAtMywgKzEsIC0yLCAtMQ0KICArIEFic29sdXRlOiAyLCAxLCA0LCAxLCAxLCAzLCAxLCAyLCAxDQogICsgU29ydGVkOiAxLCAxLCAxLCAxLCAxLCAyLCAyLCAzLCA0DQogICsgUmFua3M6IDFzIOKGkiBhdmcgcmFuayA9IDMsIDJzIOKGkiA2LjUsIDMg4oaSIDgsIDQg4oaSIDkuDQoNCiogKipTdW0gcmFua3MgZm9yIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBkaWZmZXJlbmNlcyoqOg0KICArIFBvc2l0aXZlIGRpZmZlcmVuY2VzICgrMSwgKzEpOiBSYW5rcyA9IDMsIDMg4oaSIFN1bSA9IDYuDQogICsgTmVnYXRpdmUgZGlmZmVyZW5jZXM6IFN1bSA9IDMgKyA2LjUgKyA2LjUgKyA4ICsgOSArIDMgPSAzNi4NCg0KKiAqKlRlc3Qgc3RhdGlzdGljIChXKSoqID0gc21hbGxlciBzdW0gPSA2Lg0KKiAqKkNvbXBhcmUgdG8gY3JpdGljYWwgdmFsdWUqKiAoZnJvbSB0aGUgZm9sbG93aW5nIFdpbGNveG9uIGNydGljYWwgdmFsdWUgdGFibGUpIGF0ICRcYWxwaGEgPSAwLjA1JCBmb3IgJG4gPSA5JCB3aGljaCBpcyA1Lg0KDQpcDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjYwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDMvV2lsY294b25TaWduZWRSYW5rLUNyaXRpY2FsVmFsdWUucG5nIikNCmBgYA0KDQpTaW5jZSB0aGUgJFRTID0gNiA+IDUgPSBDVl97MC4wNX0kLCB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHJlamVjdGVkLiBUaGF0IG1lYW5zIHRoZSB0cmVhdG1lbnQgaXMgZWZmZWN0aXZlLg0KYA0KTmV4dCwgd2UgdXNlIFIgZnVuY3Rpb25gd2lsY294LnRlc3QoKWAgdG8gcGVyZm9ybSB0aGUgc2lnbmVkIHJhbmsgdGVzdDoNCg0KYGBge3J9DQojIFBhaW4gc2NvcmVzICgwLTEwIHNjYWxlKQ0KYmVmb3JlIDwtIGMoNywgNiwgOCwgOSwgNSwgNywgNiwgOCwgNCwgNykNCmFmdGVyIDwtIGMoNSwgNiwgNywgNSwgNCwgOCwgMywgOSwgMiwgNikNCg0KIyBDb21wdXRlIGRpZmZlcmVuY2VzIChBZnRlciAtIEJlZm9yZSkNCmRpZmZlcmVuY2VzIDwtIGFmdGVyIC0gYmVmb3JlDQoNCiMgUGVyZm9ybSB0aGUgdGVzdCAocGFpcmVkPVRSVUUpDQp3aWxjb3gudGVzdChiZWZvcmUsIGFmdGVyLCBwYWlyZWQgPSBUUlVFLCBleGFjdCA9IEZBTFNFLCBjb3JyZWN0ID0gRkFMU0UpDQpgYGANClRoZSBwLXZhbHVlICgwLjA0NikgaXMgbGVzcyB0aGFuIDAuMDUsIHdoaWNoIG1lYW5zIHdlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBCb3RoIHRoZSBwLXZhbHVlIGFuZCBjcml0aWNhbCB2YWx1ZSBtZXRob2RzIGxlYWQgdG8gdGhlIHNhbWUgY29uY2x1c2lvbi4NCg0KDQoNCg0KDQoNCg==