Parametric vs. Non-Parametric

  • Parametric tests: the tests we have studied so far (z, t, F) have been used to describe a populations distribution (parameters).
    • Require interval or ratio data
  • Non-Parametric tests: describe relationships about that exist in populations but make relaxed (or different) assumptions about populations distributions.
    • These tests can compare qualitative data (e.g., chi-squared)
    • Non-parametric tests are more likely to commit type II errors
    • Typically are used with ordinal or nominal data, but can also be used with interval or ratio data when parametric assumptions are not met (e.g., when variance or distribution presents a problem).
      • These tests do not use the mean and standard deviation since they are often meaningless in ordinal data.
      • These tests rank scores to see how different groups compare to each other.

One-Way Pearson’s Chi-Squared [Goodness of Fit]

Have you been told: “Stay with your first answer on a multiple-choice test.” So is changing answers more likely to be harmful?

Best (1979) studied the responses of 261 students in an introductory psychology course. He recorded the number of right-to-wrong (27), wrong-to-right (195), and wrong-to-wrong (39) answer changes for each student. Note: We will ignore wrong-to-wrong as he did in his first analysis.

Frequency Right-to-Wrong Wrong-to-Right
Observed 27 195

Total of 222 observations

We will use the One-Way Chi-Squared [Goodness of fit]. It asks whether the relative frequencies observed in the categories of a sample frequency distribution are in agreement with the relative frequencies hypothesized to be true in the population.

Hypothesis for Goodness of fit

There are two versions:

  • No preference: there will be no preference between different categories (e.g., do people prefer Coke or Pepsi)
  • No difference from a known population: This type hypothesis compares two populations (or representative samples)

If people were making chance guesses from a population of people who don’t have any knowledge about material on the test (version 2 of the hypothesis):

  • \(H_0: P_{right-to-wrong} = .5, P_{wrong-to-right} = .5\)
  • \(H_1: H_0\) is False

Note: The probability you set can be whatever you want, but across all cells, they must add to 1. When you do not know what probability should be from a theoretical standpoint, you can simply do 1/Number of cells.

Find Expected Frequencies

If we expect by chance people would have gotten p = .50 on wrong-to-right and right to wrong, \(f_e = pn\)

\(E_{right-to-wrong}= .5*222=111\) \(E_{wrong-to-right}= .5*222=111\)

Frequency Right-to-Wrong Wrong-to-Right
Observed 27 195
Expected 111 111

Note: These tables are often shown in papers (sometimes as proportions).

Goodness of Fit Calculation by Hand

\[\chi^2 = \sum \frac{(f_o-f_e)^2}{f_e}\]

\(\chi^2 = \frac{(27-111)^2}{111}+\frac{(195-111)^2}{111} = 127.14\)

Note: Never enter proportions into the chi-square. You must work with frequencies.

Test Against Distribution

The chi-square distribution is a non-parametric distribution [not normal] (see handout). Like the F-test, it has no tails. The distribution changes as a function of the degrees of freedom [\(df\) is the number of cells - 1]

Just like the F-test we ask where is our chi-square value relative to this chance distribution given our \(df = 1\). We calculated 127.14, and that is in the tail. We can use R or a table to get the critical values for alpha =.05

Crit.MCQ=qchisq(.05, df=1, lower.tail = FALSE)

We get the crit = 3.8414588 < 124.14, so we reject the null.

Impact of higher DF

Just like in F-tests the shape of chance distribution changes as we have more df.

As you can see the distribution gets more spread out. So with larger DF our critical value increases

ChiCrit<-qchisq(.05, 1:8, lower.tail = FALSE)
plot(ChiCrit, main="Chi-Square Critical Values: alpha = .05",
  xlab="df", ylab="Critical Value", xlim=c(1,8), ylim=c(0,25))

Goodness of Fit Calculation by Code

Step 1: Build your Table

MCQ.Study <- as.table(rbind(c(27, 195)))
dimnames(MCQ.Study) <- list(Freq = c("Observed"),
                           Action = c("RtoW", "WtoR"))
MCQ.Study
##           Action
## Freq       RtoW WtoR
##   Observed   27  195

Step 2: Calculate Chi-squared

(MCQ.chi <- chisq.test(MCQ.Study, p=c(.5, .5)))
## 
##  Chi-squared test for given probabilities
## 
## data:  MCQ.Study
## X-squared = 127.14, df = 1, p-value < 2.2e-16

Step 2a: Calculate chi-square via Monte Carlo simulation

In the goodness-of-fit simulation is done by random sampling from the discrete distribution specified by p, each sample being the total number of observations (see ?chisq.test for more details on the simulation process)

(MCQ.chi <- chisq.test(MCQ.Study, p=c(.5, .5), simulate.p.value = TRUE, B = 10000))
## 
##  Chi-squared test for given probabilities with simulated p-value (based
##  on 10000 replicates)
## 
## data:  MCQ.Study
## X-squared = 127.14, df = NA, p-value = 9.999e-05

Step 3: Report in APA

\(\chi^2(df,N) = X.XX, p < |= .XXX\)

Since our result was p-value < 2.2e-16

\(\chi^2(1,N = 222) = 124.14, p < .0001\)

There is a difference how people change their items, and we can see from the frequencies that should change their answers if they are unsure.

Two-Way Pearson’s Chi-Squared [Test of Independence]

“Maybe we should only change our answers on easy items, but on hard items, we should trust ourselves.”

Best (1979) also examined the 1670 total number of responses across the 261 students and divided the items into easy/difficult in an introductory psychology course. He recorded the number of right-to-wrong, wrong-to-right, and wrong-to-wrong (39) answer changes for each student. Again we will ignore wrong-to-wrong (17% of the responses) for simplicity.

Frequency Right to Wrong Wrong to Right
Easy 97 411
Difficult 251 620

We need to do a Two-Way Chi-Square [Test of Independence]. It asks whether observed frequencies reflect the independence of two qualitative variables. Compares the actual observed frequencies of some phenomenon (in our sample) with the frequencies we would expect if there were no relationship at all between the two variables in the larger (sampled) population. We ask if the two variables are independent: knowledge of the value of one variable provides no information about the value of another variable.

Hypothesis for Test of Independence

The null hypothesis is that for each, the value obtained for one variable is not related to or influenced by the second variable. This idea can be expressed in two versions:

  • Version 1: A single sample is measured on two separate variables. For example, knowing your personality will help predict your color preference (alternative). Knowing your personality will NOT help you predict your color preference (null) [Personality and color preference are measured per person]
    • Null: The variables are not related.
    • Alternative: The variables are related.
  • Version 2: Two (or more) samples are measured and compared to see if there are differences. For example, the same proportions of extroverts (group 1) and introverts (group 2) prefer the same color (null). If the proportions are different for the two groups, then you have the alternative hypothesis
    • Null: The samples are independent
    • Alternative: The samples are not independent

Here we are working with Version 1 (one group taking two types of items)

  • \(H_0:\) The item difficulty is not related to how a person changes their answer
  • \(H_1:\) The item difficulty is related to how a person changes their answer

Find Expected Frequencies

This is little more complex than the goodness of fit test

Step 1: Find row/col sums

Frequency Right to Wrong Wrong to Right Sum
Easy 97 411 508
Difficult 251 620 871
Sum 348 1031 1379

Step 2: Expected frequencies per cell

\[f_e = \frac{col\,total*row\,total}{overall\,total}\]

Frequency Right to Wrong Wrong to Right Sum
Easy 97 (128.1972) 411 (379.8028) 508
Difficult 251 (219.8028) 620 (651.1972) 871
Sum 348 1031 1379

Test of Independence Calculation by Hand

\[\chi^2 = \sum \frac{(f_o-f_e)^2}{f_e}\]

\(\chi^2 = \frac{(97-128.1972)^2}{128.1972} + \frac{(411-379.8028)^2}{379.8028} +\frac{(251-219.8028)^2}{219.8028}+\frac{(620-651.1972)^2}{651.1972}\)

\(\chi^2 = 16.08\)

Test Against Distribution

\(df = (Row-1)(Col-1)\) \(df = (2-1)(2-1) = 1\)

Given our \(df = 1\). We calculated 16.08 we can use R or a table to get the critical values for alpha = .05

Crit.MCQ=qchisq(.05, df=1, lower.tail = FALSE)

We get the crit = 3.8414588 < 16.08, so we reject the null.

Test of Independence Calculation by Code

Step 1: Build Your table

MCQ.Study.2 <- as.table(rbind(c(97, 411), c(251, 620)))
dimnames(MCQ.Study.2) <- list(Social = c("Easy","Diff"),
                              Change = c("RtoW", "WtoR"))
                             
MCQ.Study.2
##       Change
## Social RtoW WtoR
##   Easy   97  411
##   Diff  251  620

Step 2: Calculate chi-square

In tests of independence, it will calculate the expected frequencies for you. Also, you can apply a correction called the Yates’ continuity correction which reduced the error of when looking up discrete values on the continuous chi-square distribution. You should always use this version of the formula as it will be more conservative. You would simply write Yates corrected chi-square tests in your method section (no one uses the subscript as I wrote below).

\[\chi^2_{Yates} = \sum \frac{(|f_o-f_e| - .5)^2}{f_e}\]

Note: you can view observed and expected frequencies. Also, you can simulate the results as we did before.

(MCQ.chi.2 <- chisq.test(MCQ.Study.2,correct = TRUE))
MCQ.chi.2$observed   # observed counts (same as M)
MCQ.chi.2$expected   # expected counts under the null
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  MCQ.Study.2
## X-squared = 15.566, df = 1, p-value = 7.968e-05
## 
##       Change
## Social RtoW WtoR
##   Easy   97  411
##   Diff  251  620
##       Change
## Social     RtoW     WtoR
##   Easy 128.1972 379.8028
##   Diff 219.8028 651.1972

Step 3: Effect size

Biased calculation phi (\(\varphi\)) and cohen’s w can be estimated using this same formula (which is needed for power analysis). These are basically correlation coefficients when you have a 2x2 contingency table.

\[\varphi = \sqrt\frac{\chi^2}{N}\]

Cramer’s V, which is similar (\(\varphi\)), but used for when you have large than 2x2 tables.

\[V = \sqrt\frac{\chi^2}{N*min(C-1, R-1)}\]

\(V = \sqrt\frac{15.566}{1379*1} = 0.106283\)

df Small Medium Large
1 0.10 0.30 0.50
2 0.07 0.21 0.35
3 0.06 0.17 0.29
4 0.05 0.15 0.25
5 0.04 0.13 0.22

Odd-Ratio (OR) as Effect size

Some people (mostly in the clinical) prefer odds ratios, but they can only work when you have a r X 2 table

Odds Ratio (OR) is a measure of association between exposure and an outcome.

Frequency Right to Wrong Wrong to Right
Easy 97 (A) 411 (B)
Difficult 251 (C) 620 (D)

Conceptually:

\[OR = \frac{AD}{BC}\]

\(OR = \frac{97*620}{411*251} = 0.58\)

So, people are .58 times more likely to switch from right-to-wrong/wrong-to-right based on the difficulty of the item. (OR < 1, so it’s less likely to happen). The item difficulty is significant as we already saw, but the difficulty has minimal impact.

In practice, we can use a package, which has other versions which can apply corrections and give us CIs around OR.

library(epitools)
# Regular
oddsratio.wald(MCQ.Study.2, correction=TRUE)$measure
# Small samples
oddsratio.small(MCQ.Study.2, correction=TRUE)$measure
##       odds ratio with 95% C.I.
## Social  estimate     lower     upper
##   Easy 1.0000000        NA        NA
##   Diff 0.5829722 0.4470703 0.7601862
##       odds ratio with 95% C.I.
## Social  estimate     lower     upper
##   Easy 1.0000000        NA        NA
##   Diff 0.5792495 0.4485089 0.7619142

Step 4: Report in APA

\(\chi^2(df,N) = X.XX, p < |= .XXX, V = .XX | OR = X.XX\)

Since our result was p-value < 7.968e-05

The item difficulty is related to how a person changes their answer, \(\chi^2(1,1379) = 15.57, p < .0001, V = .11\). [That is all we can say statistically. Normally people present a table in percentages to unpack this result, but You have to decide if you want to do row or column percentages. People do not present both]. I think the row percent make more sense in this case we want to compare across item difficulty.

Row Proportion Code

prop.table(MCQ.Study.2,1)
% Row Right to Wrong Wrong to Right %
Easy 19.1% 80.9% 100%
Difficult 28.8% 71.2% 100%
Col Total 25.2% 74.8% 100%

Col Proportion Code

prop.table(MCQ.Study.2,2)
% Col Right to Wrong Wrong to Right Row Total
Easy 27.9% 39.9% 36.8%
Difficult 72.1% 60.1% 63.2%
% 100% 100% 100%

Chi-Square Issues

  • We must have at least five responses per cell (it will calculate but its an assumption of the test)
  • Chi-squared cannot be negative because all discrepancies are squared.
  • Chi-squared can be zero, but only in the unusual event that each observed frequency exactly equals the corresponding expected frequency.
  • Other things being equal, the larger the discrepancy between the expected frequencies and their corresponding observed frequencies, the larger the observed value of chi-square.
  • It is not the size of the discrepancy alone that accounts for a contribution to the value of chi-square, but the size of the discrepancy relative to the magnitude of the expected frequency.
  • The value of chi-square depends on the number of discrepancies involved in its calculation.
  • There is no follow-up method, so we can remove conditions and re-test our chi-square (or one one-way chi-square), but you will need to Bonferroni correct the pvalues by hand (pvalue X number of tests conducted).
  • High rate of Type II error

Power in Chi-Squared

Let’s use our use the V we got in the study above to substitute for Cohen’s W. Let’s use the power package to solve for N (total # of observations needed)

library(pwr)
pwr.chisq.test(w = 0.106283, N = NULL, df = 1, sig.level = 0.05, power = .80)
## 
##      Chi squared power calculation 
## 
##               w = 0.106283
##               N = 694.8307
##              df = 1
##       sig.level = 0.05
##           power = 0.8
## 
## NOTE: N is the number of observations

Other Classical Non-Parametric Tests

Nominal Data:

  • Chi-square test is the non-parametric equivalent to z, t, or F tests, but for nominal data only!
    • Binomial/sign test is a special case of the Chi-squared
    • Another older alternative is Fisher’s Exact test

Fisher’s Exact test

Fisher’s Exact test is like a chi-square, but its calculated differently and can be more conservative than Pearson’s chi-square. Its often used when you have small cell sizes.

fisher.test(MCQ.Study.2, simulate.p.value = TRUE, B = 1e5)
## 
##  Fisher's Exact Test for Count Data
## 
## data:  MCQ.Study.2
## p-value = 6.496e-05
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.4421001 0.7654197
## sample estimates:
## odds ratio 
##  0.5831962

Binominal Data

The binomial distribution approaches a normal distribution as you add more trials (for example, the more coin flips you have the more normal the distribution looks; where p=prob of head, and q=prob of tails, n = coin flips). Generally, when the values of pn and qn are both equal to 10, the distribution approaches normal. Note: \(\mu=pn\), \(\sigma = \sqrt{npq}\). Note this test is an old test useful when people tended to do stats by hand.

\[Z = \frac{X-\mu}{\sigma} = \frac{X-pn}{\sqrt{npq}}\]

We can use our Zcrit table again (remember \(\alpha=.05\) yields \(Z_{crit} = 1.96\))

Let’s use our goodness of fit data again:

Frequency Right to Wrong Wrong to Right
Observed 27 195

Binomial by hand

We just need to call one of the conditions a “success” (we will pick Wrong-to-Right; \(X = 195\)). So \(p = .5\), \(q = .5\), Our \(n = 195+27 = 222\)

\(Z = \frac{195-.5*222}{\sqrt{222*.5*.5}} = 11.27542\)

\(Z = 11.28, p < .05\)

Note: \(Z^2 = \chi^2\) = 11.27542^2 = 127.14 (the one-way \(\chi^2\) value we got above!)

Binomial by R function

binom.test(195, 222, p = 0.5,
           conf.level = 0.95)
## 
##  Exact binomial test
## 
## data:  195 and 222
## number of successes = 195, number of trials = 222, p-value < 2.2e-16
## alternative hypothesis: true probability of success is not equal to 0.5
## 95 percent confidence interval:
##  0.8279981 0.9182995
## sample estimates:
## probability of success 
##              0.8783784

Sign test

  • Sign test is a special case of the binomial test
  • A sign test compares the number of times a treatment results one direction over another.
    • Example, let’s say that you were a therapist charting several of your patient’s improvement to a new type of therapy you were using. You cannot measure the magnitude of the improvement, but you can record if you see if they improve or get worse.
      Sign tests:
  • Are used when you have the direction of change from an experiment
  • Can be used as a pilot test to see if you should move forward in an experiment
  • Can support a hypothesis when all other tests fail
  • Are not as sensitive as parametric tests
  • Use the same calculation as the binomial test; you just count the number of pluses and minuses

Ordinal Data

Wilcoxon rank sum test

Non-parametric equivalent to the t-test. This test compares ranks and not the means. It comes in two flavors (paired-sample and independent sample [also called the Mann-Whitney U-test])

Wilcoxon rank sum test for independent sample

\(H_0:\) There is no difference between the two treatments.

  • Therefore, there is no tendency for the ranks of one treatment condition to be systematically higher or lower than the ranks for the other treatment.

\(H_1:\) There is a difference between the two treatments.

  • Therefore, the ranks in one treatment condition are systematically higher or lower than the ranks in another treatment.
Group 1 Group 2
41 10
39 14
37 9
44 17
40 12
45 8
46 104

Data frame in R

data.W<-data.frame(IV=c(rep("G1",7),rep("G2",7)),
                        DV =c(41,39,37,44,40,45,46,10,14,9,13,12,8,104))

Independent t-test

library(dplyr)
data.W %>% group_by(IV) %>% summarise(Mean=mean(DV), SD=sd(DV))
t.test(DV~IV,data=data.W, paired=FALSE)
## # A tibble: 2 × 3
##   IV     Mean    SD
##   <chr> <dbl> <dbl>
## 1 G1     41.7  3.35
## 2 G2     24.3 35.2 
## 
##  Welch Two Sample t-test
## 
## data:  DV by IV
## t = 1.3035, df = 6.1087, p-value = 0.2394
## alternative hypothesis: true difference in means between group G1 and group G2 is not equal to 0
## 95 percent confidence interval:
##  -15.14833  50.00547
## sample estimates:
## mean in group G1 mean in group G2 
##         41.71429         24.28571

Independent W-test

wilcox.test(DV~IV,data=data.W, paired=FALSE)
## 
##  Wilcoxon rank sum exact test
## 
## data:  DV by IV
## W = 42, p-value = 0.02622
## alternative hypothesis: true location shift is not equal to 0

In this case, by comparing ranks and not raw scores, we can see the non-parametric test gives a significant result (as we are comparing ranks the variance difference between the groups goes away)

Note: If the data is paired sample, you simply have to say paired=TRUE

Paired W-test

t.test(DV~IV,data=data.W, paired=TRUE)
wilcox.test(DV~IV,data=data.W, paired=TRUE, alternative =("two.sided"))
## 
##  Paired t-test
## 
## data:  DV by IV
## t = 1.3777, df = 6, p-value = 0.2175
## alternative hypothesis: true mean difference is not equal to 0
## 95 percent confidence interval:
##  -13.52663  48.38378
## sample estimates:
## mean difference 
##        17.42857 
## 
## 
##  Wilcoxon signed rank test with continuity correction
## 
## data:  DV by IV
## V = 21, p-value = 0.2702
## alternative hypothesis: true location shift is not equal to 0

Kruskal-Wallis Test

The non-parametric equivalent to the independent measures one-way ANOVA. It compares three or more separate groups and is tested against the chi-square distribution.

Like the W test, you would convert the data into ranks and calculate the H value.

Group 1 Group 2 Group 3
14 2 26
3 14 8
2 9 14
5 12 19
8 5 20

Data frame in R

data.H<-data.frame(IV=c(rep("G1",5),rep("G2",5),rep("G3",5)),
                        DV =c(14,3,2,5,8,
                              2,14,9,12,5,
                              26,8,14,19,20))

Kruskal-Wallis Test in R

kruskal.test(DV~IV, data=data.H) 
## 
##  Kruskal-Wallis rank sum test
## 
## data:  DV by IV
## Kruskal-Wallis chi-squared = 6.0608, df = 2, p-value = 0.0483

You can follow up this analysis with the W test above

Friedman Test

Non-parametric one-way RM ANOVA. For this test you must have a “block”. You block will be your ID variable. You can follow up this test with Wilcoxon rank sum test (paired=TRUE).

ID Group 1 Group 2 Group 3
1 14 2 26
2 3 14 8
3 2 9 14
4 5 12 19
5 8 5 20

Data frame in R

data.F<-data.frame(ID=rep(1:5,3),
                   IV=c(rep("G1",5),rep("G2",5),rep("G3",5)),
                        DV =c(14,3,2,5,8,
                              2,14,9,12,5,
                              26,8,14,19,20))

Friedman Test in R

friedman.test(DV~IV|ID, data=data.F) 
## 
##  Friedman rank sum test
## 
## data:  DV and IV and ID
## Friedman chi-squared = 5.2, df = 2, p-value = 0.07427

You can follow up this analysis with the W test above

Pros and Cons

Classical non-parametrics are easy to run by hand and are often useful if parametric tests fail (especially if you have large variance or suspect your assumptions are not being met). However, they have a high rate of Type II Error.

References

Best, J, B. (1979). Item difficulty and answer changing. Teaching of Psychology, 6, 228-230

LS0tDQp0aXRsZTogIlBlYXJzb24ncyBDaGktU3F1YXJlIGFuZCBPdGhlciBVc2VmdWwgTm9uLVBhcmFtZXRyaWNzIg0KaGVhZGVyLWluY2x1ZGVzOg0KLSBcdXNlcGFja2FnZXthbXNtYXRofQ0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGZvbnRzaXplOiA4cHQNCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChjYWNoZT1UUlVFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gIEZBTFNFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy53aWR0aD00LjI1KQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5oZWlnaHQ9NC4wKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5hbGlnbj0nY2VudGVyJykgDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLnBvcyA9ICdIJykNCmtuaXRyOjpvcHRzX2NodW5rJHNldChyZXN1bHRzPSdob2xkJykgDQpgYGANCg0KXHBhZ2VicmVhaw0KDQojIFBhcmFtZXRyaWMgdnMuIE5vbi1QYXJhbWV0cmljDQotIFBhcmFtZXRyaWMgdGVzdHM6IHRoZSB0ZXN0cyB3ZSBoYXZlIHN0dWRpZWQgc28gZmFyICh6LCB0LCBGKSBoYXZlIGJlZW4gdXNlZCB0byBkZXNjcmliZSBhIHBvcHVsYXRpb25zIGRpc3RyaWJ1dGlvbiAocGFyYW1ldGVycykuIA0KICAgIC0gUmVxdWlyZSBpbnRlcnZhbCBvciByYXRpbyBkYXRhIA0KLSBOb24tUGFyYW1ldHJpYyB0ZXN0czogZGVzY3JpYmUgcmVsYXRpb25zaGlwcyBhYm91dCB0aGF0IGV4aXN0IGluIHBvcHVsYXRpb25zIGJ1dCBtYWtlIHJlbGF4ZWQgKG9yIGRpZmZlcmVudCkgYXNzdW1wdGlvbnMgYWJvdXQgcG9wdWxhdGlvbnMgZGlzdHJpYnV0aW9ucy4gIA0KICAgIC0gVGhlc2UgdGVzdHMgY2FuIGNvbXBhcmUgcXVhbGl0YXRpdmUgZGF0YSAoZS5nLiwgY2hpLXNxdWFyZWQpDQogICAgLSBOb24tcGFyYW1ldHJpYyB0ZXN0cyBhcmUgbW9yZSBsaWtlbHkgdG8gY29tbWl0IHR5cGUgSUkgZXJyb3JzDQogICAgLSBUeXBpY2FsbHkgYXJlIHVzZWQgd2l0aCBvcmRpbmFsIG9yIG5vbWluYWwgZGF0YSwgYnV0IGNhbiBhbHNvIGJlIHVzZWQgd2l0aCBpbnRlcnZhbCBvciByYXRpbyBkYXRhIHdoZW4gcGFyYW1ldHJpYyBhc3N1bXB0aW9ucyBhcmUgbm90IG1ldCAoZS5nLiwgd2hlbiB2YXJpYW5jZSBvciBkaXN0cmlidXRpb24gcHJlc2VudHMgYSBwcm9ibGVtKS4NCiAgICAgICAgLSBUaGVzZSB0ZXN0cyBkbyBub3QgdXNlIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gc2luY2UgdGhleSBhcmUgb2Z0ZW4gbWVhbmluZ2xlc3MgaW4gb3JkaW5hbCBkYXRhLiANCiAgICAgICAgLSAqKlRoZXNlIHRlc3RzIHJhbmsgc2NvcmVzIHRvIHNlZSBob3cgZGlmZmVyZW50IGdyb3VwcyBjb21wYXJlIHRvIGVhY2ggb3RoZXIuKioNCg0KIyBPbmUtV2F5IFBlYXJzb24ncyBDaGktU3F1YXJlZCBbR29vZG5lc3Mgb2YgRml0XQ0KSGF2ZSB5b3UgYmVlbiB0b2xkOiAiU3RheSB3aXRoIHlvdXIgZmlyc3QgYW5zd2VyIG9uIGEgbXVsdGlwbGUtY2hvaWNlIHRlc3QuIiAgKlNvIGlzIGNoYW5naW5nIGFuc3dlcnMgbW9yZSBsaWtlbHkgdG8gYmUgaGFybWZ1bD8qDQoNCj4gQmVzdCAoMTk3OSkgc3R1ZGllZCB0aGUgcmVzcG9uc2VzIG9mIDI2MSBzdHVkZW50cyBpbiBhbiBpbnRyb2R1Y3RvcnkgcHN5Y2hvbG9neSBjb3Vyc2UuICBIZSByZWNvcmRlZCB0aGUgbnVtYmVyIG9mIHJpZ2h0LXRvLXdyb25nICgyNyksIHdyb25nLXRvLXJpZ2h0ICgxOTUpLCBhbmQgd3JvbmctdG8td3JvbmcgKDM5KSBhbnN3ZXIgY2hhbmdlcyBmb3IgZWFjaCBzdHVkZW50LiBOb3RlOiBXZSB3aWxsIGlnbm9yZSB3cm9uZy10by13cm9uZyBhcyBoZSBkaWQgaW4gaGlzIGZpcnN0IGFuYWx5c2lzLiAgDQoNCkZyZXF1ZW5jeSB8IFJpZ2h0LXRvLVdyb25nIHwgV3JvbmctdG8tUmlnaHQNCjotLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLTogDQpPYnNlcnZlZCAgfCAgMjcgICAgICAgICAgICB8IDE5NQ0KDQpUb3RhbCBvZiAyMjIgb2JzZXJ2YXRpb25zDQoNCldlIHdpbGwgdXNlIHRoZSAqKk9uZS1XYXkgQ2hpLVNxdWFyZWQqKiBbR29vZG5lc3Mgb2YgZml0XS4gSXQgYXNrcyB3aGV0aGVyIHRoZSByZWxhdGl2ZSBmcmVxdWVuY2llcyBvYnNlcnZlZCBpbiB0aGUgY2F0ZWdvcmllcyBvZiBhIHNhbXBsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIGFyZSBpbiBhZ3JlZW1lbnQgd2l0aCB0aGUgcmVsYXRpdmUgZnJlcXVlbmNpZXMgaHlwb3RoZXNpemVkIHRvIGJlIHRydWUgaW4gdGhlIHBvcHVsYXRpb24uDQoNCiMjIEh5cG90aGVzaXMgZm9yIEdvb2RuZXNzIG9mIGZpdA0KVGhlcmUgYXJlIHR3byB2ZXJzaW9uczogDQoNCi0gTm8gcHJlZmVyZW5jZTogdGhlcmUgd2lsbCBiZSBubyBwcmVmZXJlbmNlIGJldHdlZW4gZGlmZmVyZW50IGNhdGVnb3JpZXMgKGUuZy4sIGRvIHBlb3BsZSBwcmVmZXIgQ29rZSBvciBQZXBzaSkNCi0JTm8gZGlmZmVyZW5jZSBmcm9tIGEga25vd24gcG9wdWxhdGlvbjogVGhpcyB0eXBlIGh5cG90aGVzaXMgY29tcGFyZXMgdHdvIHBvcHVsYXRpb25zIChvciByZXByZXNlbnRhdGl2ZSBzYW1wbGVzKQ0KDQpJZiBwZW9wbGUgd2VyZSBtYWtpbmcgY2hhbmNlIGd1ZXNzZXMgZnJvbSBhIHBvcHVsYXRpb24gb2YgcGVvcGxlIHdobyBkb24ndCBoYXZlIGFueSBrbm93bGVkZ2UgYWJvdXQgbWF0ZXJpYWwgb24gdGhlIHRlc3QgKHZlcnNpb24gMiBvZiB0aGUgaHlwb3RoZXNpcyk6DQoNCi0gJEhfMDogUF97cmlnaHQtdG8td3Jvbmd9ID0gLjUsIFBfe3dyb25nLXRvLXJpZ2h0fSA9IC41JCANCi0gJEhfMTogSF8wJCBpcyBGYWxzZSANCg0KKk5vdGU6KiBUaGUgcHJvYmFiaWxpdHkgeW91IHNldCBjYW4gYmUgd2hhdGV2ZXIgeW91IHdhbnQsIGJ1dCBhY3Jvc3MgYWxsIGNlbGxzLCB0aGV5IG11c3QgYWRkIHRvIDEuIFdoZW4geW91IGRvIG5vdCBrbm93IHdoYXQgcHJvYmFiaWxpdHkgc2hvdWxkIGJlIGZyb20gYSB0aGVvcmV0aWNhbCBzdGFuZHBvaW50LCB5b3UgY2FuIHNpbXBseSBkbyAxL051bWJlciBvZiBjZWxscy4gDQoNCiMjIyBGaW5kIEV4cGVjdGVkIEZyZXF1ZW5jaWVzDQoNCklmIHdlIGV4cGVjdCBieSBjaGFuY2UgcGVvcGxlIHdvdWxkIGhhdmUgZ290dGVuIHAgPSAuNTAgb24gd3JvbmctdG8tcmlnaHQgYW5kIHJpZ2h0IHRvIHdyb25nLCAkZl9lID0gcG4kICANCg0KJEVfe3JpZ2h0LXRvLXdyb25nfT0gLjUqMjIyPTExMSQNCiRFX3t3cm9uZy10by1yaWdodH09IC41KjIyMj0xMTEkDQoNCkZyZXF1ZW5jeSB8IFJpZ2h0LXRvLVdyb25nIHwgV3JvbmctdG8tUmlnaHQNCjotLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLTogDQpPYnNlcnZlZCAgfCAgMjcgICAgICAgICAgICB8IDE5NQ0KRXhwZWN0ZWQgIHwgIDExMSAgICAgICAgICAgfCAxMTENCg0KKk5vdGU6KiBUaGVzZSB0YWJsZXMgYXJlIG9mdGVuIHNob3duIGluIHBhcGVycyAoc29tZXRpbWVzIGFzIHByb3BvcnRpb25zKS4NCg0KIyMgR29vZG5lc3Mgb2YgRml0IENhbGN1bGF0aW9uIGJ5IEhhbmQNCg0KJCRcY2hpXjIgPSBcc3VtIFxmcmFjeyhmX28tZl9lKV4yfXtmX2V9JCQNCg0KJFxjaGleMiA9IFxmcmFjeygyNy0xMTEpXjJ9ezExMX0rXGZyYWN7KDE5NS0xMTEpXjJ9ezExMX0gPSAxMjcuMTQkDQoNCipOb3RlOiogTmV2ZXIgZW50ZXIgcHJvcG9ydGlvbnMgaW50byB0aGUgY2hpLXNxdWFyZS4gWW91IG11c3Qgd29yayB3aXRoIGZyZXF1ZW5jaWVzLg0KDQojIyMgVGVzdCBBZ2FpbnN0IERpc3RyaWJ1dGlvbg0KVGhlIGNoaS1zcXVhcmUgZGlzdHJpYnV0aW9uIGlzIGEgbm9uLXBhcmFtZXRyaWMgZGlzdHJpYnV0aW9uIFtub3Qgbm9ybWFsXSAoc2VlIGhhbmRvdXQpLiBMaWtlIHRoZSBGLXRlc3QsIGl0IGhhcyBubyB0YWlscy4gVGhlIGRpc3RyaWJ1dGlvbiBjaGFuZ2VzIGFzIGEgZnVuY3Rpb24gb2YgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBbJGRmJCBpcyB0aGUgbnVtYmVyIG9mIGNlbGxzIC0gMV0NCg0KYGBge3IsIGVjaG89RkFMU0V9DQp4IDwtIHJjaGlzcSgxZTYsIDEpDQpoaXN0KHgsIHByb2I9VFJVRSwgbWFpbj0iQ2hpLVNxdWFyZSBIaXN0b2dyYW0vRGVuc2l0eSBQbG90OiBkZiA9IDEiLA0KICB4bGFiPSJDaGktc3F1YXJlIHZhbHVlIiwgeWxhYj0iUHJvYmFiaWxpdHkgRGVuc2l0eSIsIHhsaW09YygwLDIwKSwgeWxpbT1jKDAsMS4xKSkNCmxpbmVzKGRlbnNpdHkoeCksIGNvbD0ncmVkJykNCmBgYA0KDQoNCkp1c3QgbGlrZSB0aGUgRi10ZXN0IHdlIGFzayB3aGVyZSBpcyBvdXIgY2hpLXNxdWFyZSB2YWx1ZSByZWxhdGl2ZSB0byB0aGlzIGNoYW5jZSBkaXN0cmlidXRpb24gZ2l2ZW4gb3VyICRkZiA9IDEkLiAgV2UgY2FsY3VsYXRlZCAxMjcuMTQsIGFuZCB0aGF0IGlzIGluIHRoZSB0YWlsLiBXZSBjYW4gdXNlIFIgb3IgYSB0YWJsZSB0byBnZXQgdGhlIGNyaXRpY2FsIHZhbHVlcyBmb3IgYWxwaGEgPS4wNSANCg0KYGBge3J9DQpDcml0Lk1DUT1xY2hpc3EoLjA1LCBkZj0xLCBsb3dlci50YWlsID0gRkFMU0UpDQpgYGANCg0KV2UgZ2V0IHRoZSBjcml0ID0gYHIgQ3JpdC5NQ1FgIDwgMTI0LjE0LCBzbyB3ZSByZWplY3QgdGhlIG51bGwuICAgDQoNCiMjIyMgSW1wYWN0IG9mIGhpZ2hlciBERg0KSnVzdCBsaWtlIGluIEYtdGVzdHMgdGhlIHNoYXBlIG9mIGNoYW5jZSBkaXN0cmlidXRpb24gY2hhbmdlcyBhcyB3ZSBoYXZlIG1vcmUgZGYuDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KeCA8LSByY2hpc3EoMWU2LCA0KQ0KaGlzdCh4LCBwcm9iPVRSVUUsIG1haW49IkNoaS1TcXVhcmUgSGlzdG9ncmFtL0RlbnNpdHkgUGxvdDogZGYgPSA0IiwNCiAgeGxhYj0iQ2hpLXNxdWFyZSB2YWx1ZSIsIHlsYWI9IlByb2JhYmlsaXR5IERlbnNpdHkiLCB4bGltPWMoMCwyMCksIHlsaW09YygwLC4yKSkNCmxpbmVzKGRlbnNpdHkoeCksIGNvbD0ncmVkJykNCmBgYA0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KeCA8LSByY2hpc3EoMWU2LCA4KQ0KaGlzdCh4LCBwcm9iPVRSVUUsIG1haW49IkNoaS1TcXVhcmUgSGlzdG9ncmFtL0RlbnNpdHkgUGxvdDogZGYgPSA4IiwNCiAgeGxhYj0iQ2hpLXNxdWFyZSB2YWx1ZSIsIHlsYWI9IlByb2JhYmlsaXR5IERlbnNpdHkiLCB4bGltPWMoMCwyMCksIHlsaW09YygwLC4yKSkNCmxpbmVzKGRlbnNpdHkoeCksIGNvbD0ncmVkJykNCmBgYA0KDQpBcyB5b3UgY2FuIHNlZSB0aGUgZGlzdHJpYnV0aW9uIGdldHMgbW9yZSBzcHJlYWQgb3V0LiBTbyB3aXRoIGxhcmdlciBERiBvdXIgY3JpdGljYWwgdmFsdWUgaW5jcmVhc2VzDQoNCmBgYHtyfQ0KQ2hpQ3JpdDwtcWNoaXNxKC4wNSwgMTo4LCBsb3dlci50YWlsID0gRkFMU0UpDQpwbG90KENoaUNyaXQsIG1haW49IkNoaS1TcXVhcmUgQ3JpdGljYWwgVmFsdWVzOiBhbHBoYSA9IC4wNSIsDQogIHhsYWI9ImRmIiwgeWxhYj0iQ3JpdGljYWwgVmFsdWUiLCB4bGltPWMoMSw4KSwgeWxpbT1jKDAsMjUpKQ0KYGBgDQoNCg0KDQojIyBHb29kbmVzcyBvZiBGaXQgQ2FsY3VsYXRpb24gYnkgQ29kZQ0KDQojIyMgU3RlcCAxOiBCdWlsZCB5b3VyIFRhYmxlDQoNCmBgYHtyfQ0KTUNRLlN0dWR5IDwtIGFzLnRhYmxlKHJiaW5kKGMoMjcsIDE5NSkpKQ0KZGltbmFtZXMoTUNRLlN0dWR5KSA8LSBsaXN0KEZyZXEgPSBjKCJPYnNlcnZlZCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgQWN0aW9uID0gYygiUnRvVyIsICJXdG9SIikpDQpNQ1EuU3R1ZHkNCmBgYA0KDQojIyMgU3RlcCAyOiBDYWxjdWxhdGUgQ2hpLXNxdWFyZWQNCg0KYGBge3J9DQooTUNRLmNoaSA8LSBjaGlzcS50ZXN0KE1DUS5TdHVkeSwgcD1jKC41LCAuNSkpKQ0KYGBgDQoNCiMjIyMgU3RlcCAyYTogQ2FsY3VsYXRlIGNoaS1zcXVhcmUgdmlhIE1vbnRlIENhcmxvIHNpbXVsYXRpb24NCkluIHRoZSBnb29kbmVzcy1vZi1maXQgc2ltdWxhdGlvbiBpcyBkb25lIGJ5IHJhbmRvbSBzYW1wbGluZyBmcm9tIHRoZSBkaXNjcmV0ZSBkaXN0cmlidXRpb24gc3BlY2lmaWVkIGJ5IHAsIGVhY2ggc2FtcGxlIGJlaW5nIHRoZSB0b3RhbCBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIChzZWUgP2NoaXNxLnRlc3QgZm9yIG1vcmUgZGV0YWlscyBvbiB0aGUgc2ltdWxhdGlvbiBwcm9jZXNzKQ0KDQpgYGB7cn0NCihNQ1EuY2hpIDwtIGNoaXNxLnRlc3QoTUNRLlN0dWR5LCBwPWMoLjUsIC41KSwgc2ltdWxhdGUucC52YWx1ZSA9IFRSVUUsIEIgPSAxMDAwMCkpDQpgYGANCg0KIyMjIFN0ZXAgMzogUmVwb3J0IGluIEFQQQ0KDQokXGNoaV4yKGRmLE4pID0gWC5YWCwgcCA8IHw9IC5YWFgkDQoNClNpbmNlIG91ciByZXN1bHQgd2FzIHAtdmFsdWUgPCAyLjJlLTE2DQoNCiRcY2hpXjIoMSxOID0gMjIyKSA9IDEyNC4xNCwgcCA8IC4wMDAxJA0KDQpUaGVyZSBpcyBhIGRpZmZlcmVuY2UgaG93IHBlb3BsZSBjaGFuZ2UgdGhlaXIgaXRlbXMsIGFuZCB3ZSBjYW4gc2VlIGZyb20gdGhlIGZyZXF1ZW5jaWVzIHRoYXQgc2hvdWxkIGNoYW5nZSB0aGVpciBhbnN3ZXJzIGlmIHRoZXkgYXJlIHVuc3VyZS4gDQoNClxwYWdlYnJlYWsNCg0KIyBUd28tV2F5IFBlYXJzb24ncyBDaGktU3F1YXJlZCBbVGVzdCBvZiBJbmRlcGVuZGVuY2VdIA0KIk1heWJlIHdlIHNob3VsZCBvbmx5IGNoYW5nZSBvdXIgYW5zd2VycyBvbiBlYXN5IGl0ZW1zLCBidXQgb24gaGFyZCBpdGVtcywgd2Ugc2hvdWxkIHRydXN0IG91cnNlbHZlcy4iDQoNCj4gQmVzdCAoMTk3OSkgYWxzbyBleGFtaW5lZCB0aGUgMTY3MCB0b3RhbCBudW1iZXIgb2YgcmVzcG9uc2VzIGFjcm9zcyB0aGUgMjYxIHN0dWRlbnRzIGFuZCBkaXZpZGVkIHRoZSBpdGVtcyBpbnRvIGVhc3kvZGlmZmljdWx0IGluIGFuIGludHJvZHVjdG9yeSBwc3ljaG9sb2d5IGNvdXJzZS4gIEhlIHJlY29yZGVkIHRoZSBudW1iZXIgb2YgcmlnaHQtdG8td3JvbmcsIHdyb25nLXRvLXJpZ2h0LCBhbmQgd3JvbmctdG8td3JvbmcgKDM5KSBhbnN3ZXIgY2hhbmdlcyBmb3IgZWFjaCBzdHVkZW50LiBBZ2FpbiB3ZSB3aWxsIGlnbm9yZSB3cm9uZy10by13cm9uZyAoMTclIG9mIHRoZSByZXNwb25zZXMpIGZvciBzaW1wbGljaXR5Lg0KDQpGcmVxdWVuY3kgfCBSaWdodCB0byBXcm9uZyB8IFdyb25nIHRvIFJpZ2h0IA0KLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLQ0KRWFzeSAgICAgfCAgOTcgICAgICAgICAgICB8IDQxMQ0KRGlmZmljdWx0fCAgMjUxICAgICAgICAgICB8IDYyMA0KDQpXZSBuZWVkIHRvIGRvIGEgVHdvLVdheSBDaGktU3F1YXJlIFtUZXN0IG9mIEluZGVwZW5kZW5jZV0uIEl0IGFza3Mgd2hldGhlciBvYnNlcnZlZCBmcmVxdWVuY2llcyByZWZsZWN0IHRoZSBpbmRlcGVuZGVuY2Ugb2YgdHdvIHF1YWxpdGF0aXZlIHZhcmlhYmxlcy4gQ29tcGFyZXMgdGhlIGFjdHVhbCBvYnNlcnZlZCBmcmVxdWVuY2llcyBvZiBzb21lIHBoZW5vbWVub24gKGluIG91ciBzYW1wbGUpIHdpdGggdGhlIGZyZXF1ZW5jaWVzIHdlIHdvdWxkIGV4cGVjdCBpZiB0aGVyZSB3ZXJlIG5vIHJlbGF0aW9uc2hpcCBhdCBhbGwgYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcyBpbiB0aGUgbGFyZ2VyIChzYW1wbGVkKSBwb3B1bGF0aW9uLiBXZSBhc2sgaWYgdGhlIHR3byB2YXJpYWJsZXMgYXJlIGluZGVwZW5kZW50OiBrbm93bGVkZ2Ugb2YgdGhlIHZhbHVlIG9mIG9uZSB2YXJpYWJsZSBwcm92aWRlcyBubyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdmFsdWUgb2YgYW5vdGhlciB2YXJpYWJsZS4NCg0KIyMgSHlwb3RoZXNpcyBmb3IgVGVzdCBvZiBJbmRlcGVuZGVuY2UNCg0KVGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0IGZvciBlYWNoLCB0aGUgdmFsdWUgb2J0YWluZWQgZm9yIG9uZSB2YXJpYWJsZSBpcyBub3QgcmVsYXRlZCB0byBvciBpbmZsdWVuY2VkIGJ5IHRoZSBzZWNvbmQgdmFyaWFibGUuICBUaGlzIGlkZWEgY2FuIGJlIGV4cHJlc3NlZCBpbiB0d28gdmVyc2lvbnM6DQoNCi0gVmVyc2lvbiAxOiBBIHNpbmdsZSBzYW1wbGUgaXMgbWVhc3VyZWQgb24gdHdvIHNlcGFyYXRlIHZhcmlhYmxlcy4gRm9yIGV4YW1wbGUsIGtub3dpbmcgeW91ciBwZXJzb25hbGl0eSB3aWxsIGhlbHAgcHJlZGljdCB5b3VyIGNvbG9yIHByZWZlcmVuY2UgKGFsdGVybmF0aXZlKS4gS25vd2luZyB5b3VyIHBlcnNvbmFsaXR5IHdpbGwgTk9UIGhlbHAgeW91IHByZWRpY3QgeW91ciBjb2xvciBwcmVmZXJlbmNlIChudWxsKSBbUGVyc29uYWxpdHkgYW5kIGNvbG9yIHByZWZlcmVuY2UgYXJlIG1lYXN1cmVkIHBlciBwZXJzb25dDQogICAgLQlOdWxsOiBUaGUgdmFyaWFibGVzIGFyZSBub3QgcmVsYXRlZC4gDQogICAgLQlBbHRlcm5hdGl2ZTogVGhlIHZhcmlhYmxlcyBhcmUgcmVsYXRlZC4gDQoNCi0gVmVyc2lvbiAyOiBUd28gKG9yIG1vcmUpIHNhbXBsZXMgYXJlIG1lYXN1cmVkIGFuZCBjb21wYXJlZCB0byBzZWUgaWYgdGhlcmUgYXJlIGRpZmZlcmVuY2VzLiBGb3IgZXhhbXBsZSwgdGhlIHNhbWUgcHJvcG9ydGlvbnMgb2YgZXh0cm92ZXJ0cyAoZ3JvdXAgMSkgYW5kIGludHJvdmVydHMgKGdyb3VwIDIpIHByZWZlciB0aGUgc2FtZSBjb2xvciAobnVsbCkuICBJZiB0aGUgcHJvcG9ydGlvbnMgYXJlIGRpZmZlcmVudCBmb3IgdGhlIHR3byBncm91cHMsIHRoZW4geW91IGhhdmUgdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMNCiAgICAtCU51bGw6IFRoZSBzYW1wbGVzIGFyZSBpbmRlcGVuZGVudCANCiAgICAtCUFsdGVybmF0aXZlOiBUaGUgc2FtcGxlcyBhcmUgbm90IGluZGVwZW5kZW50DQoNCkhlcmUgd2UgYXJlIHdvcmtpbmcgd2l0aCBWZXJzaW9uIDEgKG9uZSBncm91cCB0YWtpbmcgdHdvIHR5cGVzIG9mIGl0ZW1zKQ0KDQotICRIXzA6JCBUaGUgaXRlbSBkaWZmaWN1bHR5IGlzIG5vdCByZWxhdGVkIHRvIGhvdyBhIHBlcnNvbiBjaGFuZ2VzIHRoZWlyIGFuc3dlciANCi0gJEhfMTokIFRoZSBpdGVtIGRpZmZpY3VsdHkgaXMgcmVsYXRlZCB0byBob3cgYSBwZXJzb24gY2hhbmdlcyB0aGVpciBhbnN3ZXIgDQoNCiMjIEZpbmQgRXhwZWN0ZWQgRnJlcXVlbmNpZXMNClRoaXMgaXMgbGl0dGxlIG1vcmUgY29tcGxleCB0aGFuIHRoZSBnb29kbmVzcyBvZiBmaXQgdGVzdA0KDQojIyMgU3RlcCAxOiBGaW5kIHJvdy9jb2wgc3Vtcw0KDQpGcmVxdWVuY3kgfCBSaWdodCB0byBXcm9uZyB8IFdyb25nIHRvIFJpZ2h0IHwgU3VtDQotLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tfC0tLS0NCkVhc3kgICAgIHwgIDk3ICAgICAgICAgICAgfCA0MTEgICAgICAgICAgICB8ICoqNTA4KioNCkRpZmZpY3VsdHwgIDI1MSAgICAgICAgICAgfCA2MjAgICAgICAgICAgICB8ICoqODcxKioNClN1bSAgICAgIHwgICoqMzQ4KiogICAgICAgfCAqKjEwMzEqKiAgICAgICB8ICoqMTM3OSoqIA0KDQojIyMgU3RlcCAyOiBFeHBlY3RlZCBmcmVxdWVuY2llcyBwZXIgY2VsbA0KDQokJGZfZSA9IFxmcmFje2NvbFwsdG90YWwqcm93XCx0b3RhbH17b3ZlcmFsbFwsdG90YWx9JCQNCg0KDQpGcmVxdWVuY3kgfCBSaWdodCB0byBXcm9uZyB8IFdyb25nIHRvIFJpZ2h0IHwgU3VtDQotLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tfC0tLS0NCkVhc3kgICAgIHwgIDk3ICgxMjguMTk3MikgfCA0MTEgKDM3OS44MDI4KSB8ICoqNTA4KioNCkRpZmZpY3VsdHwgIDI1MSAoMjE5LjgwMjgpfCA2MjAgKDY1MS4xOTcyKSB8ICoqODcxKioNClN1bSAgICAgIHwgICoqMzQ4KiogICAgICAgfCAqKjEwMzEqKiAgICAgICB8ICoqMTM3OSoqIA0KDQoNCiMjIFRlc3Qgb2YgSW5kZXBlbmRlbmNlIENhbGN1bGF0aW9uIGJ5IEhhbmQNCg0KJCRcY2hpXjIgPSBcc3VtIFxmcmFjeyhmX28tZl9lKV4yfXtmX2V9JCQNCg0KJFxjaGleMiA9IFxmcmFjeyg5Ny0xMjguMTk3MileMn17MTI4LjE5NzJ9ICsgXGZyYWN7KDQxMS0zNzkuODAyOCleMn17Mzc5LjgwMjh9ICtcZnJhY3soMjUxLTIxOS44MDI4KV4yfXsyMTkuODAyOH0rXGZyYWN7KDYyMC02NTEuMTk3MileMn17NjUxLjE5NzJ9JA0KDQokXGNoaV4yID0gMTYuMDgkDQoNCiMjIyBUZXN0IEFnYWluc3QgRGlzdHJpYnV0aW9uDQokZGYgPSAoUm93LTEpKENvbC0xKSQNCiRkZiA9ICgyLTEpKDItMSkgPSAxJA0KDQpHaXZlbiBvdXIgJGRmID0gMSQuICBXZSBjYWxjdWxhdGVkIDE2LjA4IHdlIGNhbiB1c2UgUiBvciBhIHRhYmxlIHRvIGdldCB0aGUgY3JpdGljYWwgdmFsdWVzIGZvciBhbHBoYSA9IC4wNSANCg0KDQpgYGB7cn0NCkNyaXQuTUNRPXFjaGlzcSguMDUsIGRmPTEsIGxvd2VyLnRhaWwgPSBGQUxTRSkNCmBgYA0KDQpXZSBnZXQgdGhlIGNyaXQgPSBgciBDcml0Lk1DUWAgPCAxNi4wOCwgc28gd2UgcmVqZWN0IHRoZSBudWxsLiAgIA0KDQoNCiMjIFRlc3Qgb2YgSW5kZXBlbmRlbmNlIENhbGN1bGF0aW9uIGJ5IENvZGUNCg0KIyMjIFN0ZXAgMTogQnVpbGQgWW91ciB0YWJsZQ0KDQpgYGB7cn0NCk1DUS5TdHVkeS4yIDwtIGFzLnRhYmxlKHJiaW5kKGMoOTcsIDQxMSksIGMoMjUxLCA2MjApKSkNCmRpbW5hbWVzKE1DUS5TdHVkeS4yKSA8LSBsaXN0KFNvY2lhbCA9IGMoIkVhc3kiLCJEaWZmIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDaGFuZ2UgPSBjKCJSdG9XIiwgIld0b1IiKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpNQ1EuU3R1ZHkuMg0KYGBgDQoNCiMjIyBTdGVwIDI6IENhbGN1bGF0ZSBjaGktc3F1YXJlDQpJbiB0ZXN0cyBvZiBpbmRlcGVuZGVuY2UsIGl0IHdpbGwgY2FsY3VsYXRlIHRoZSBleHBlY3RlZCBmcmVxdWVuY2llcyBmb3IgeW91LiBBbHNvLCB5b3UgY2FuIGFwcGx5IGEgY29ycmVjdGlvbiBjYWxsZWQgdGhlIFlhdGVzJyBjb250aW51aXR5IGNvcnJlY3Rpb24gd2hpY2ggcmVkdWNlZCB0aGUgZXJyb3Igb2Ygd2hlbiBsb29raW5nIHVwIGRpc2NyZXRlIHZhbHVlcyBvbiB0aGUgY29udGludW91cyBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbi4gWW91IHNob3VsZCBhbHdheXMgdXNlIHRoaXMgdmVyc2lvbiBvZiB0aGUgZm9ybXVsYSBhcyBpdCB3aWxsIGJlIG1vcmUgY29uc2VydmF0aXZlLiBZb3Ugd291bGQgc2ltcGx5IHdyaXRlIFlhdGVzIGNvcnJlY3RlZCBjaGktc3F1YXJlIHRlc3RzIGluIHlvdXIgbWV0aG9kIHNlY3Rpb24gKG5vIG9uZSB1c2VzIHRoZSBzdWJzY3JpcHQgYXMgSSB3cm90ZSBiZWxvdykuDQoNCiQkXGNoaV4yX3tZYXRlc30gPSBcc3VtIFxmcmFjeyh8Zl9vLWZfZXwgLSAuNSleMn17Zl9lfSQkDQoNCipOb3RlKjogeW91IGNhbiB2aWV3IG9ic2VydmVkIGFuZCBleHBlY3RlZCBmcmVxdWVuY2llcy4gQWxzbywgeW91IGNhbiBzaW11bGF0ZSB0aGUgcmVzdWx0cyBhcyB3ZSBkaWQgYmVmb3JlLiANCg0KYGBge3J9DQooTUNRLmNoaS4yIDwtIGNoaXNxLnRlc3QoTUNRLlN0dWR5LjIsY29ycmVjdCA9IFRSVUUpKQ0KTUNRLmNoaS4yJG9ic2VydmVkICAgIyBvYnNlcnZlZCBjb3VudHMgKHNhbWUgYXMgTSkNCk1DUS5jaGkuMiRleHBlY3RlZCAgICMgZXhwZWN0ZWQgY291bnRzIHVuZGVyIHRoZSBudWxsDQpgYGANCg0KDQojIyMgU3RlcCAzOiBFZmZlY3Qgc2l6ZQ0KQmlhc2VkIGNhbGN1bGF0aW9uIHBoaSAoJFx2YXJwaGkkKSBhbmQgY29oZW4ncyB3IGNhbiBiZSBlc3RpbWF0ZWQgdXNpbmcgdGhpcyBzYW1lIGZvcm11bGEgKHdoaWNoIGlzIG5lZWRlZCBmb3IgcG93ZXIgYW5hbHlzaXMpLiBUaGVzZSBhcmUgYmFzaWNhbGx5IGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyB3aGVuIHlvdSBoYXZlIGEgMngyIGNvbnRpbmdlbmN5IHRhYmxlLiANCg0KJCRcdmFycGhpID0gXHNxcnRcZnJhY3tcY2hpXjJ9e059JCQNCg0KQ3JhbWVyJ3MgViwgd2hpY2ggaXMgc2ltaWxhciAoJFx2YXJwaGkkKSwgYnV0IHVzZWQgZm9yIHdoZW4geW91IGhhdmUgbGFyZ2UgdGhhbiAyeDIgdGFibGVzLg0KDQokJFYgPSBcc3FydFxmcmFje1xjaGleMn17TiptaW4oQy0xLCBSLTEpfSQkDQoNCiRWID0gXHNxcnRcZnJhY3sxNS41NjZ9ezEzNzkqMX0gPSAwLjEwNjI4MyQNCg0KDQp8IGRmICB8IFNtYWxsIHwgTWVkaXVtIHwgTGFyZ2UgfA0KfCA6LS0gfCA6LS0tLSB8IDotLS0tLSB8IDotLS0tIHwNCnwgMSAgIHwgMC4xMCAgfCAwLjMwICAgfCAwLjUwICB8DQp8IDIgICB8IDAuMDcgIHwgMC4yMSAgIHwgMC4zNSAgfA0KfCAzICAgfCAwLjA2ICB8IDAuMTcgICB8IDAuMjkgIHwNCnwgNCAgIHwgMC4wNSAgfCAwLjE1ICAgfCAwLjI1ICB8DQp8IDUgICB8IDAuMDQgIHwgMC4xMyAgIHwgMC4yMiAgfA0KDQojIyMjIE9kZC1SYXRpbyAoT1IpIGFzIEVmZmVjdCBzaXplDQpTb21lIHBlb3BsZSAobW9zdGx5IGluIHRoZSBjbGluaWNhbCkgcHJlZmVyIG9kZHMgcmF0aW9zLCBidXQgdGhleSBjYW4gb25seSB3b3JrIHdoZW4geW91IGhhdmUgYSByIFggMiB0YWJsZQ0KDQpPZGRzIFJhdGlvIChPUikgaXMgYSBtZWFzdXJlIG9mIGFzc29jaWF0aW9uIGJldHdlZW4gZXhwb3N1cmUgYW5kIGFuIG91dGNvbWUuIA0KDQpGcmVxdWVuY3kgfCBSaWdodCB0byBXcm9uZyB8IFdyb25nIHRvIFJpZ2h0IA0KLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLQ0KRWFzeSAgICAgfCAgOTcgIChBKSAgICAgICB8IDQxMSAoQikgICAgICAgICANCkRpZmZpY3VsdHwgIDI1MSAoQykgICAgICAgfCA2MjAgKEQpICAgICAgICAgDQoNCg0KQ29uY2VwdHVhbGx5OiANCg0KJCRPUiA9IFxmcmFje0FEfXtCQ30kJA0KDQokT1IgPSBcZnJhY3s5Nyo2MjB9ezQxMSoyNTF9ID0gMC41OCQNCg0KU28sIHBlb3BsZSBhcmUgLjU4IHRpbWVzIG1vcmUgbGlrZWx5IHRvIHN3aXRjaCBmcm9tIHJpZ2h0LXRvLXdyb25nL3dyb25nLXRvLXJpZ2h0IGJhc2VkIG9uIHRoZSBkaWZmaWN1bHR5IG9mIHRoZSBpdGVtLiAoT1IgPCAxLCBzbyBpdCdzIGxlc3MgbGlrZWx5IHRvIGhhcHBlbikuIFRoZSBpdGVtIGRpZmZpY3VsdHkgaXMgc2lnbmlmaWNhbnQgYXMgd2UgYWxyZWFkeSBzYXcsIGJ1dCB0aGUgZGlmZmljdWx0eSBoYXMgbWluaW1hbCBpbXBhY3QuIA0KDQpJbiBwcmFjdGljZSwgd2UgY2FuIHVzZSBhIHBhY2thZ2UsIHdoaWNoIGhhcyBvdGhlciB2ZXJzaW9ucyB3aGljaCBjYW4gYXBwbHkgY29ycmVjdGlvbnMgYW5kIGdpdmUgdXMgQ0lzIGFyb3VuZCBPUi4gDQoNCmBgYHtyfQ0KbGlicmFyeShlcGl0b29scykNCiMgUmVndWxhcg0Kb2Rkc3JhdGlvLndhbGQoTUNRLlN0dWR5LjIsIGNvcnJlY3Rpb249VFJVRSkkbWVhc3VyZQ0KIyBTbWFsbCBzYW1wbGVzDQpvZGRzcmF0aW8uc21hbGwoTUNRLlN0dWR5LjIsIGNvcnJlY3Rpb249VFJVRSkkbWVhc3VyZQ0KYGBgDQoNCg0KIyMjIFN0ZXAgNDogUmVwb3J0IGluIEFQQQ0KDQokXGNoaV4yKGRmLE4pID0gWC5YWCwgcCA8IHw9IC5YWFgsIFYgPSAuWFggfCBPUiA9IFguWFgkDQoNClNpbmNlIG91ciByZXN1bHQgd2FzIHAtdmFsdWUgPCA3Ljk2OGUtMDUNCg0KVGhlIGl0ZW0gZGlmZmljdWx0eSBpcyByZWxhdGVkIHRvIGhvdyBhIHBlcnNvbiBjaGFuZ2VzIHRoZWlyIGFuc3dlciwgJFxjaGleMigxLDEzNzkpID0gMTUuNTcsIHAgPCAuMDAwMSwgViA9IC4xMSQuIFtUaGF0IGlzIGFsbCB3ZSBjYW4gc2F5IHN0YXRpc3RpY2FsbHkuICBOb3JtYWxseSBwZW9wbGUgcHJlc2VudCBhIHRhYmxlIGluIHBlcmNlbnRhZ2VzIHRvIHVucGFjayB0aGlzIHJlc3VsdCwgKipidXQqKiBZb3UgaGF2ZSB0byBkZWNpZGUgaWYgeW91IHdhbnQgdG8gZG8gcm93IG9yIGNvbHVtbiBwZXJjZW50YWdlcy4gUGVvcGxlIGRvIG5vdCBwcmVzZW50IGJvdGhdLiBJIHRoaW5rIHRoZSByb3cgcGVyY2VudCBtYWtlIG1vcmUgc2Vuc2UgaW4gdGhpcyBjYXNlIHdlIHdhbnQgdG8gY29tcGFyZSBhY3Jvc3MgaXRlbSBkaWZmaWN1bHR5LiANCg0KIyMjIyBSb3cgUHJvcG9ydGlvbiBDb2RlDQpgYGB7ciwgZXZhbD1GQUxTRX0NCnByb3AudGFibGUoTUNRLlN0dWR5LjIsMSkNCmBgYA0KDQoNCiUgUm93ICAgIHwgUmlnaHQgdG8gV3JvbmcgfCBXcm9uZyB0byBSaWdodCB8ICUNCi0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS18LS0tLQ0KRWFzeSAgICAgfCAgMTkuMSUgICAgICAgICB8ICA4MC45JSAgICAgICAgIHwgMTAwJQ0KRGlmZmljdWx0fCAgMjguOCUgICAgICAgICB8ICA3MS4yJSAgICAgICAgIHwgMTAwJQ0KQ29sIFRvdGFsfCAgMjUuMiUgICAgICAgICB8ICA3NC44JSAgICAgICAgIHwgMTAwJSANCg0KDQojIyMjIENvbCBQcm9wb3J0aW9uIENvZGUNCmBgYHtyLCBldmFsPUZBTFNFfQ0KcHJvcC50YWJsZShNQ1EuU3R1ZHkuMiwyKQ0KYGBgDQoNCiUgQ29sICAgIHwgUmlnaHQgdG8gV3JvbmcgfCBXcm9uZyB0byBSaWdodCB8IFJvdyBUb3RhbA0KLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLXwtLS0tDQpFYXN5ICAgICB8ICAyNy45JSAgICAgICAgIHwgIDM5LjklICAgICAgICAgfCAzNi44JQ0KRGlmZmljdWx0fCAgNzIuMSUgICAgICAgICB8ICA2MC4xJSAgICAgICAgIHwgNjMuMiUNCiUgICAgICAgIHwgIDEwMCUgICAgICAgICAgfCAgMTAwJSAgICAgICAgICB8IDEwMCUgDQoNCiMjIENoaS1TcXVhcmUgSXNzdWVzDQotIFdlIG11c3QgaGF2ZSBhdCBsZWFzdCBmaXZlIHJlc3BvbnNlcyBwZXIgY2VsbCAoaXQgd2lsbCBjYWxjdWxhdGUgYnV0IGl0cyBhbiBhc3N1bXB0aW9uIG9mIHRoZSB0ZXN0KQ0KLSBDaGktc3F1YXJlZCBjYW5ub3QgYmUgbmVnYXRpdmUgYmVjYXVzZSBhbGwgZGlzY3JlcGFuY2llcyBhcmUgc3F1YXJlZC4NCi0gQ2hpLXNxdWFyZWQgY2FuIGJlIHplcm8sIGJ1dCBvbmx5IGluIHRoZSB1bnVzdWFsIGV2ZW50IHRoYXQgZWFjaCBvYnNlcnZlZCBmcmVxdWVuY3kgZXhhY3RseSBlcXVhbHMgdGhlIGNvcnJlc3BvbmRpbmcgZXhwZWN0ZWQgZnJlcXVlbmN5Lg0KLSBPdGhlciB0aGluZ3MgYmVpbmcgZXF1YWwsIHRoZSBsYXJnZXIgdGhlIGRpc2NyZXBhbmN5IGJldHdlZW4gdGhlIGV4cGVjdGVkIGZyZXF1ZW5jaWVzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIG9ic2VydmVkIGZyZXF1ZW5jaWVzLCB0aGUgbGFyZ2VyIHRoZSBvYnNlcnZlZCB2YWx1ZSBvZiBjaGktc3F1YXJlLg0KLSBJdCBpcyBub3QgdGhlIHNpemUgb2YgdGhlIGRpc2NyZXBhbmN5IGFsb25lIHRoYXQgYWNjb3VudHMgZm9yIGEgY29udHJpYnV0aW9uIHRvIHRoZSB2YWx1ZSBvZiBjaGktc3F1YXJlLCBidXQgdGhlIHNpemUgb2YgdGhlIGRpc2NyZXBhbmN5IHJlbGF0aXZlIHRvIHRoZSBtYWduaXR1ZGUgb2YgdGhlIGV4cGVjdGVkIGZyZXF1ZW5jeS4NCi0gVGhlIHZhbHVlIG9mIGNoaS1zcXVhcmUgZGVwZW5kcyBvbiB0aGUgbnVtYmVyIG9mIGRpc2NyZXBhbmNpZXMgaW52b2x2ZWQgaW4gaXRzIGNhbGN1bGF0aW9uLg0KLSAqKlRoZXJlIGlzIG5vIGZvbGxvdy11cCBtZXRob2QsIHNvIHdlIGNhbiByZW1vdmUgY29uZGl0aW9ucyBhbmQgcmUtdGVzdCBvdXIgY2hpLXNxdWFyZSAob3Igb25lIG9uZS13YXkgY2hpLXNxdWFyZSksIGJ1dCB5b3Ugd2lsbCBuZWVkIHRvIEJvbmZlcnJvbmkgY29ycmVjdCB0aGUgcHZhbHVlcyBieSBoYW5kIChwdmFsdWUgWCBudW1iZXIgb2YgdGVzdHMgY29uZHVjdGVkKS4qKg0KLSBIaWdoIHJhdGUgb2YgVHlwZSBJSSBlcnJvcg0KDQojIFBvd2VyIGluIENoaS1TcXVhcmVkDQoNCkxldCdzIHVzZSBvdXIgdXNlIHRoZSBWIHdlIGdvdCBpbiB0aGUgc3R1ZHkgYWJvdmUgdG8gc3Vic3RpdHV0ZSBmb3IgQ29oZW4ncyBXLiBMZXQncyB1c2UgdGhlIHBvd2VyIHBhY2thZ2UgdG8gc29sdmUgZm9yIE4gKHRvdGFsICMgb2Ygb2JzZXJ2YXRpb25zIG5lZWRlZCkNCg0KYGBge3J9DQpsaWJyYXJ5KHB3cikNCnB3ci5jaGlzcS50ZXN0KHcgPSAwLjEwNjI4MywgTiA9IE5VTEwsIGRmID0gMSwgc2lnLmxldmVsID0gMC4wNSwgcG93ZXIgPSAuODApDQpgYGANCg0KDQpccGFnZWJyZWFrDQoNCiMgT3RoZXIgQ2xhc3NpY2FsIE5vbi1QYXJhbWV0cmljIFRlc3RzDQoNCiMjIE5vbWluYWwgRGF0YToNCi0gQ2hpLXNxdWFyZSB0ZXN0IGlzIHRoZSBub24tcGFyYW1ldHJpYyBlcXVpdmFsZW50IHRvIHosIHQsIG9yIEYgdGVzdHMsIGJ1dCBmb3Igbm9taW5hbCBkYXRhIG9ubHkhIAkNCiAgICAtIEJpbm9taWFsL3NpZ24gdGVzdCBpcyBhIHNwZWNpYWwgY2FzZSBvZiB0aGUgQ2hpLXNxdWFyZWQNCiAgICAtIEFub3RoZXIgb2xkZXIgYWx0ZXJuYXRpdmUgaXMgRmlzaGVyJ3MgRXhhY3QgdGVzdA0KDQojIyMgRmlzaGVyJ3MgRXhhY3QgdGVzdCANCkZpc2hlcidzIEV4YWN0IHRlc3QgaXMgbGlrZSBhIGNoaS1zcXVhcmUsIGJ1dCBpdHMgY2FsY3VsYXRlZCBkaWZmZXJlbnRseSBhbmQgY2FuIGJlIG1vcmUgY29uc2VydmF0aXZlIHRoYW4gUGVhcnNvbidzIGNoaS1zcXVhcmUuIEl0cyBvZnRlbiB1c2VkIHdoZW4geW91IGhhdmUgc21hbGwgY2VsbCBzaXplcy4NCg0KYGBge3J9DQpmaXNoZXIudGVzdChNQ1EuU3R1ZHkuMiwgc2ltdWxhdGUucC52YWx1ZSA9IFRSVUUsIEIgPSAxZTUpDQpgYGANCg0KIyMjIEJpbm9taW5hbCBEYXRhDQpUaGUgYmlub21pYWwgZGlzdHJpYnV0aW9uIGFwcHJvYWNoZXMgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGFzIHlvdSBhZGQgbW9yZSB0cmlhbHMgKGZvciBleGFtcGxlLCB0aGUgbW9yZSBjb2luIGZsaXBzIHlvdSBoYXZlIHRoZSBtb3JlIG5vcm1hbCB0aGUgZGlzdHJpYnV0aW9uIGxvb2tzOyB3aGVyZSBwPXByb2Igb2YgaGVhZCwgYW5kIHE9cHJvYiBvZiB0YWlscywgbiA9IGNvaW4gZmxpcHMpLiAgR2VuZXJhbGx5LCB3aGVuIHRoZSB2YWx1ZXMgb2YgcG4gYW5kIHFuIGFyZSBib3RoIGVxdWFsIHRvIDEwLCB0aGUgZGlzdHJpYnV0aW9uIGFwcHJvYWNoZXMgbm9ybWFsLiAgTm90ZTogJFxtdT1wbiQsICRcc2lnbWEgPSBcc3FydHtucHF9JC4gTm90ZSB0aGlzIHRlc3QgaXMgYW4gb2xkIHRlc3QgdXNlZnVsIHdoZW4gcGVvcGxlIHRlbmRlZCB0byBkbyBzdGF0cyBieSBoYW5kLiAgDQoNCiQkWiA9IFxmcmFje1gtXG11fXtcc2lnbWF9ID0gXGZyYWN7WC1wbn17XHNxcnR7bnBxfX0kJA0KDQpXZSBjYW4gdXNlIG91ciBaY3JpdCB0YWJsZSBhZ2FpbiAocmVtZW1iZXIgJFxhbHBoYT0uMDUkIHlpZWxkcyAkWl97Y3JpdH0gPSAxLjk2JCkNCg0KTGV0J3MgdXNlIG91ciBnb29kbmVzcyBvZiBmaXQgZGF0YSBhZ2FpbjoNCg0KRnJlcXVlbmN5IHwgUmlnaHQgdG8gV3JvbmcgfCBXcm9uZyB0byBSaWdodA0KOi0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLToNCk9ic2VydmVkICB8ICAyNyAgICAgICAgICAgIHwgMTk1DQoNCiMjIyMgQmlub21pYWwgYnkgaGFuZA0KDQpXZSBqdXN0IG5lZWQgdG8gY2FsbCBvbmUgb2YgdGhlIGNvbmRpdGlvbnMgYSAic3VjY2VzcyIgKHdlIHdpbGwgcGljayBXcm9uZy10by1SaWdodDsgJFggPSAxOTUkKS4gU28gJHAgPSAuNSQsICRxID0gLjUkLCBPdXIgJG4gPSAxOTUrMjcgPSAyMjIkDQoNCiRaID0gXGZyYWN7MTk1LS41KjIyMn17XHNxcnR7MjIyKi41Ki41fX0gPSAxMS4yNzU0MiQNCg0KJFogPSAxMS4yOCwgcCA8IC4wNSQNCg0KTm90ZTogJFpeMiA9IFxjaGleMiQgPSAxMS4yNzU0Ml4yID0gMTI3LjE0ICh0aGUgb25lLXdheSAkXGNoaV4yJCB2YWx1ZSB3ZSBnb3QgYWJvdmUhKQ0KDQoNCiMjIyMgQmlub21pYWwgYnkgUiBmdW5jdGlvbg0KDQpgYGB7cn0NCmJpbm9tLnRlc3QoMTk1LCAyMjIsIHAgPSAwLjUsDQogICAgICAgICAgIGNvbmYubGV2ZWwgPSAwLjk1KQ0KYGBgDQoNCiMjIyBTaWduIHRlc3QNCi0gU2lnbiB0ZXN0IGlzIGEgc3BlY2lhbCBjYXNlIG9mIHRoZSBiaW5vbWlhbCB0ZXN0DQotIEEgc2lnbiB0ZXN0IGNvbXBhcmVzIHRoZSBudW1iZXIgb2YgdGltZXMgYSB0cmVhdG1lbnQgcmVzdWx0cyBvbmUgZGlyZWN0aW9uIG92ZXIgYW5vdGhlci4gDQogICAgLSBFeGFtcGxlLCBsZXQncyBzYXkgdGhhdCB5b3Ugd2VyZSBhIHRoZXJhcGlzdCBjaGFydGluZyBzZXZlcmFsIG9mIHlvdXIgcGF0aWVudCdzIGltcHJvdmVtZW50IHRvIGEgbmV3IHR5cGUgb2YgdGhlcmFweSB5b3Ugd2VyZSB1c2luZy4gIFlvdSBjYW5ub3QgbWVhc3VyZSB0aGUgbWFnbml0dWRlIG9mIHRoZSBpbXByb3ZlbWVudCwgYnV0IHlvdSBjYW4gcmVjb3JkIGlmIHlvdSBzZWUgaWYgdGhleSBpbXByb3ZlIG9yIGdldCB3b3JzZS4gICANClNpZ24gdGVzdHM6IA0KLSBBcmUgdXNlZCB3aGVuIHlvdSBoYXZlIHRoZSBkaXJlY3Rpb24gb2YgY2hhbmdlIGZyb20gYW4gZXhwZXJpbWVudA0KLSBDYW4gYmUgdXNlZCBhcyBhIHBpbG90IHRlc3QgdG8gc2VlIGlmIHlvdSBzaG91bGQgbW92ZSBmb3J3YXJkIGluIGFuIGV4cGVyaW1lbnQNCi0gQ2FuIHN1cHBvcnQgYSBoeXBvdGhlc2lzIHdoZW4gYWxsIG90aGVyIHRlc3RzIGZhaWwNCi0gQXJlIG5vdCBhcyBzZW5zaXRpdmUgYXMgcGFyYW1ldHJpYyB0ZXN0cw0KLSBVc2UgdGhlIHNhbWUgY2FsY3VsYXRpb24gYXMgdGhlIGJpbm9taWFsIHRlc3Q7IHlvdSBqdXN0IGNvdW50IHRoZSBudW1iZXIgb2YgcGx1c2VzIGFuZCBtaW51c2VzDQoNCg0KIyMgT3JkaW5hbCBEYXRhDQoNCiMjIyBXaWxjb3hvbiByYW5rIHN1bSB0ZXN0IA0KDQpOb24tcGFyYW1ldHJpYyBlcXVpdmFsZW50IHRvIHRoZSB0LXRlc3QuIFRoaXMgdGVzdCBjb21wYXJlcyByYW5rcyBhbmQgbm90IHRoZSBtZWFucy4gSXQgY29tZXMgaW4gdHdvIGZsYXZvcnMgKHBhaXJlZC1zYW1wbGUgYW5kIGluZGVwZW5kZW50IHNhbXBsZSBbYWxzbyBjYWxsZWQgdGhlIE1hbm4tV2hpdG5leSBVLXRlc3RdKQ0KDQojIyMjIFdpbGNveG9uIHJhbmsgc3VtIHRlc3QgZm9yIGluZGVwZW5kZW50IHNhbXBsZSANCg0KJEhfMDokICBUaGVyZSBpcyBubyBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byB0cmVhdG1lbnRzLg0KDQotIFRoZXJlZm9yZSwgdGhlcmUgaXMgbm8gdGVuZGVuY3kgZm9yIHRoZSByYW5rcyBvZiBvbmUgdHJlYXRtZW50IGNvbmRpdGlvbiB0byBiZSBzeXN0ZW1hdGljYWxseSBoaWdoZXIgb3IgbG93ZXIgdGhhbiB0aGUgcmFua3MgZm9yIHRoZSBvdGhlciB0cmVhdG1lbnQuIA0KDQokSF8xOiQgIFRoZXJlIGlzIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gdHJlYXRtZW50cy4gDQoNCi0gVGhlcmVmb3JlLCB0aGUgcmFua3MgaW4gb25lIHRyZWF0bWVudCBjb25kaXRpb24gYXJlIHN5c3RlbWF0aWNhbGx5IGhpZ2hlciBvciBsb3dlciB0aGFuIHRoZSByYW5rcyBpbiBhbm90aGVyIHRyZWF0bWVudC4gDQoNCnwgR3JvdXAgMSB8IEdyb3VwIDIgfA0KfCA6LS0gfCA6LS0gfA0KfCA0MSAgfCAxMCAgfA0KfCAzOSAgfCAxNCAgfA0KfCAzNyAgfCA5ICAgfA0KfCA0NCAgfCAxNyAgfA0KfCA0MCAgfCAxMiAgfA0KfCA0NSAgfCA4ICAgfA0KfCA0NiAgfCAxMDQgfA0KDQpEYXRhIGZyYW1lIGluIFINCmBgYHtyfQ0KZGF0YS5XPC1kYXRhLmZyYW1lKElWPWMocmVwKCJHMSIsNykscmVwKCJHMiIsNykpLA0KICAgICAgICAgICAgICAgICAgICAgICAgRFYgPWMoNDEsMzksMzcsNDQsNDAsNDUsNDYsMTAsMTQsOSwxMywxMiw4LDEwNCkpDQpgYGANCg0KDQojIyMjIEluZGVwZW5kZW50IHQtdGVzdCANCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmRhdGEuVyAlPiUgZ3JvdXBfYnkoSVYpICU+JSBzdW1tYXJpc2UoTWVhbj1tZWFuKERWKSwgU0Q9c2QoRFYpKQ0KdC50ZXN0KERWfklWLGRhdGE9ZGF0YS5XLCBwYWlyZWQ9RkFMU0UpDQpgYGANCg0KIyMjIyBJbmRlcGVuZGVudCBXLXRlc3QNCg0KYGBge3J9DQp3aWxjb3gudGVzdChEVn5JVixkYXRhPWRhdGEuVywgcGFpcmVkPUZBTFNFKQ0KYGBgDQoNCg0KSW4gdGhpcyBjYXNlLCBieSBjb21wYXJpbmcgcmFua3MgYW5kIG5vdCByYXcgc2NvcmVzLCB3ZSBjYW4gc2VlIHRoZSBub24tcGFyYW1ldHJpYyB0ZXN0IGdpdmVzIGEgc2lnbmlmaWNhbnQgcmVzdWx0IChhcyB3ZSBhcmUgY29tcGFyaW5nIHJhbmtzIHRoZSB2YXJpYW5jZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGdyb3VwcyBnb2VzIGF3YXkpIA0KDQoqTm90ZToqIElmIHRoZSBkYXRhIGlzIHBhaXJlZCBzYW1wbGUsIHlvdSBzaW1wbHkgaGF2ZSB0byBzYXkgcGFpcmVkPVRSVUUNCg0KIyMjIyBQYWlyZWQgVy10ZXN0DQoNCmBgYHtyfQ0KdC50ZXN0KERWfklWLGRhdGE9ZGF0YS5XLCBwYWlyZWQ9VFJVRSkNCndpbGNveC50ZXN0KERWfklWLGRhdGE9ZGF0YS5XLCBwYWlyZWQ9VFJVRSwgYWx0ZXJuYXRpdmUgPSgidHdvLnNpZGVkIikpDQpgYGANCg0KIyMjIEtydXNrYWwtV2FsbGlzIFRlc3QNClRoZSBub24tcGFyYW1ldHJpYyBlcXVpdmFsZW50IHRvIHRoZSBpbmRlcGVuZGVudCBtZWFzdXJlcyBvbmUtd2F5IEFOT1ZBLiAgSXQgY29tcGFyZXMgdGhyZWUgb3IgbW9yZSBzZXBhcmF0ZSBncm91cHMgYW5kIGlzIHRlc3RlZCBhZ2FpbnN0IHRoZSBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbi4gDQoNCg0KTGlrZSB0aGUgVyB0ZXN0LCB5b3Ugd291bGQgY29udmVydCB0aGUgZGF0YSBpbnRvIHJhbmtzIGFuZCBjYWxjdWxhdGUgdGhlIEggdmFsdWUuDQoNCg0KfCBHcm91cCAxIHwgR3JvdXAgMiB8IEdyb3VwIDMgfA0KfCA6LS0tLS0tIHwgOi0tLS0tLSB8IDotLS0tLS0gfA0KfCAxNCAgICAgIHwgMiAgICAgICB8IDI2ICAgICAgfA0KfCAzICAgICAgIHwgMTQgICAgICB8IDggICAgICAgfA0KfCAyICAgICAgIHwgOSAgICAgICB8IDE0ICAgICAgfA0KfCA1ICAgICAgIHwgMTIgICAgICB8IDE5ICAgICAgfA0KfCA4ICAgICAgIHwgNSAgICAgICB8IDIwICAgICAgfA0KDQoNCkRhdGEgZnJhbWUgaW4gUg0KYGBge3J9DQpkYXRhLkg8LWRhdGEuZnJhbWUoSVY9YyhyZXAoIkcxIiw1KSxyZXAoIkcyIiw1KSxyZXAoIkczIiw1KSksDQogICAgICAgICAgICAgICAgICAgICAgICBEViA9YygxNCwzLDIsNSw4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMiwxNCw5LDEyLDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyNiw4LDE0LDE5LDIwKSkNCmBgYA0KDQoNCiMjIyMgS3J1c2thbC1XYWxsaXMgVGVzdCBpbiBSDQoNCmBgYHtyfQ0Ka3J1c2thbC50ZXN0KERWfklWLCBkYXRhPWRhdGEuSCkgDQpgYGANCg0KWW91IGNhbiBmb2xsb3cgdXAgdGhpcyBhbmFseXNpcyB3aXRoIHRoZSBXIHRlc3QgYWJvdmUNCg0KDQojIyMgRnJpZWRtYW4gVGVzdA0KTm9uLXBhcmFtZXRyaWMgb25lLXdheSBSTSBBTk9WQS4gRm9yIHRoaXMgdGVzdCB5b3UgbXVzdCBoYXZlIGEgImJsb2NrIi4gWW91IGJsb2NrIHdpbGwgYmUgeW91ciBJRCB2YXJpYWJsZS4gWW91IGNhbiBmb2xsb3cgdXAgdGhpcyB0ZXN0IHdpdGggV2lsY294b24gcmFuayBzdW0gdGVzdCAocGFpcmVkPVRSVUUpLg0KDQoNCklEIHwgR3JvdXAgMSB8IEdyb3VwIDIgfCBHcm91cCAzIHwNCjotLXwgOi0tLS0tLSB8IDotLS0tLS0gfCA6LS0tLS0tIHwNCjEgIHwgMTQgICAgICB8IDIgICAgICAgfCAyNiAgICAgIHwNCjIgIHwgMyAgICAgICB8IDE0ICAgICAgfCA4ICAgICAgIHwNCjMgIHwgMiAgICAgICB8IDkgICAgICAgfCAxNCAgICAgIHwNCjQgIHwgNSAgICAgICB8IDEyICAgICAgfCAxOSAgICAgIHwNCjUgIHwgOCAgICAgICB8IDUgICAgICAgfCAyMCAgICAgIHwNCg0KRGF0YSBmcmFtZSBpbiBSDQpgYGB7cn0NCmRhdGEuRjwtZGF0YS5mcmFtZShJRD1yZXAoMTo1LDMpLA0KICAgICAgICAgICAgICAgICAgIElWPWMocmVwKCJHMSIsNSkscmVwKCJHMiIsNSkscmVwKCJHMyIsNSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgRFYgPWMoMTQsMywyLDUsOCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIsMTQsOSwxMiw1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMjYsOCwxNCwxOSwyMCkpDQpgYGANCg0KIyMjIyBGcmllZG1hbiBUZXN0IGluIFINCmBgYHtyfQ0KZnJpZWRtYW4udGVzdChEVn5JVnxJRCwgZGF0YT1kYXRhLkYpIA0KYGBgDQoNCllvdSBjYW4gZm9sbG93IHVwIHRoaXMgYW5hbHlzaXMgd2l0aCB0aGUgVyB0ZXN0IGFib3ZlDQoNCg0KIyBQcm9zIGFuZCBDb25zDQpDbGFzc2ljYWwgbm9uLXBhcmFtZXRyaWNzIGFyZSBlYXN5IHRvIHJ1biBieSBoYW5kIGFuZCBhcmUgb2Z0ZW4gdXNlZnVsIGlmIHBhcmFtZXRyaWMgdGVzdHMgZmFpbCAoZXNwZWNpYWxseSBpZiB5b3UgaGF2ZSBsYXJnZSB2YXJpYW5jZSBvciBzdXNwZWN0IHlvdXIgYXNzdW1wdGlvbnMgYXJlIG5vdCBiZWluZyBtZXQpLiBIb3dldmVyLCB0aGV5IGhhdmUgYSBoaWdoIHJhdGUgb2YgVHlwZSBJSSBFcnJvci4NCg0KDQoNCiMgUmVmZXJlbmNlcw0KQmVzdCwgSiwgQi4gKDE5NzkpLiBJdGVtIGRpZmZpY3VsdHkgYW5kIGFuc3dlciBjaGFuZ2luZy4gKlRlYWNoaW5nIG9mIFBzeWNob2xvZ3kqLCA2LCAyMjgtMjMwDQoNCg==