1 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.


2 (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 \(X_1\) \(X_2\) \(\cdots\) \(X_k\)
\(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.

salary (\(Y\)) gender (\(X_1\)) role (\(X_2\)) Yr_edu (\(X_3\)) Yr_exp (\(X_4\))
$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


3 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.

Type of Statistics sample 1 sample 2
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

3.1 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.


3.2 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.


4 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.


5 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:

  • The null hypothesis (\(H_0\)) is that the two population distributions are equal.

  • The alternative hypothesis (\(H_1\)) is that the two population distributions are not equal.


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.


5.1 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\).



5.2 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.

5.3 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.


6 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.

6.1 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.


6.2 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 functionwilcox.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==