1 Introduction

We have discussed the relationship between two numerical variables using the linear correlation coefficient and linear regression. We now turn to the relationship between two categorical variables. The idea is to make an assumption (hypothesis) about the variable(s) and use this assumption to construct a frequency table, known as the expected table. At the same time, we tabulate the data to obtain an observed table. The discrepancy between the expected and observed tables can be used to make an inference about the relationship between the categorical variables.

This module introduces a new positive distribution—the chi-square (\(\chi^2\)) distribution—and its application in goodness-of-fit testing. Goodness-of-fit tests for categorical distribution assess the relationship between the observed frequency distribution and the hypothetical distribution under the null hypothesis (i.e., the expected distribution under \(H_0\)).


2 Chi-square (\(\chi^2\)) Distribution

As we learned from MAT121/125, the Chi-square (\(\chi^2\)) distribution is a continuous probability distribution commonly used in inferential statistics, especially for testing hypotheses about variances and categorical data (e.g., contingency tables). We will review this distribution and related problems.

2.1 Chi-Square Distribution

The key characteristics of \(\chi^2\) distribution are

  • Shape: Skewed right, but becomes more symmetric as degrees of freedom (df) increase.

  • Support: Defined only for non-negative values (\(x \ge 0\)).

  • Parameter: Degrees of freedom (df), typically a positive integer.

The following YouTube video gives a nice introduction to the \(\chi^2\) distribution.



2.2 Two Types of Questions

As we learned from normal and t-distributions, we need to calculate tail probabilities, in particular, the right-tail probabilities and quantiles for given probabilities. We used \(chi^2\) table in MAT121/125. You are encouraged to use R commands to find probabilities and quantiles.

Finding Probability (Area under the curve)

  • Goal: Calculate the probability that a \(\chi^2\) random variable falls below, above, or between certain values.

  • Typical Question: What is \(P(X \le x)\) or \(P(X \ge x)\) for a \(\chi^2\)-distributed variable with \(df = k\)?

  • R Command:

pchisq(x, df)                        # P(X <= x)
pchisq(x, df, lower.tail = FALSE)    # P(X >= x), x = chi-square test statistic

Note: All \(\chi^2\) tests are right-tailed since the test statistic measures the discrepancy between two distributions. The p-value of a \(\chi^2\) test is always the area of the tail region to the right-hand side of the test statistic, which can be found using pchisq(x, df, lower.tail = FALSE). The argument lower.tail = FALSE returns the upper-tail area and x = chi-square test statistic.

  • Example 1: Find \(P(X \le 5)\) for \(df = 10\).

pchisq(5, df = 10)
## [1] 0.108822
  • Example 2: Find \(P(X \ge 15)\) for \(df = 10\).

pchisq(15, df = 10, lower.tail = FALSE)
## [1] 0.1320619

  Finding Percentile (given the area under the curve)

  • Goal: Calculate the cut \(\chi^2\) value (percentile) that defines the tail region with given area (i.e., the tail probability).

  • Typical Question: What is the value \(x_0\) that satisfies \(P(X \le x_0) = p_0\) or \(P(X \ge x_0) = p_0\) for a \(\chi^2\)-tail area (probablity) \(p_0\)?

  • R Command:

qchisq(p, df, lower.tail = TRUE)
 # p: the probability (area under the curve)
 # df: degrees of freedom
 # lower.tail:
 #   TRUE (default) for left-tail area
 #   FALSE for right-tail area

Example 3: find the 95-th percentile of the \(\chi^2\) distribution with 12 degrees of freedom.

Answer: 95% percentile is the cut-off value that splits the region under the \(\chi^2_{12}\) density curve into two regions. The left region has an area of 0.95, and the right region has an area of 0.05. This means we use either qchi(0.95, df =12, lower.tail = TRUE) or qchi(0.05, df = 12, lower.tail = FALSE) to find the same percentile in R. The code is in the following.

qchisq(0.95, df =12, lower.tail = TRUE)
## [1] 21.02607
qchisq(0.05, df =12, lower.tail = FALSE)
## [1] 21.02607

2.3 Chisquare Table

We can also use a chi-square table to find the critical value based on a given significance level. When using a table, we always use the critical value method. The p-value method is used when using a software program.

The chi-square distribution is used to characterize a positive random variable. Unlike normal and t distributions that have symmetric density curves, the chi-square distributions (dependent on the degrees of freedom) have skewed density curves.

We can find the critical value of the chi-square distribution from the chi-square table that is available on the course web page. The structure of the chi-square table is similar to the t-table.

The possible degrees of freedom are listed in the first column, the possible right-tail areas are listed in the top row, and the critical values are listed in the main body of the table.

The steps for finding the critical values are the same as those we followed for finding the t-critical values.

Example 2. Find the critical value of the chi-square distribution with 5 degrees of freedom with a significance level of 0.05.

The above figure shows how to find the critical value, denoted by \(CV = \chi^2_{5, 0.05} = 11.071\). The first subscript denotes 5 degrees of freedom, and the second subscript is the significance level of 0.05.


3 Chi-square Test of Goodness-of-fit

A goodness-of-fit test of a distribution is a testing procedure that justifies whether the null hypothesis that the specified distribution is correct, based on sample information.

For a single categorical variable, the null hypothesis should specify the cell probabilities. In other words, if the category has k categories, then (\(p_1, p_2 \cdots, p_k\)) must be specified in the null hypothesis.

3.1 A Motivational Example

As a special case, we look at the following example of testing the proportion problem.

Example 1. We want to justify a claim that about 30% of WCU students are STEM majors. That is, we test the following hypotheses. \[ H_0: \ \ p = 0.3 \ \ \ \ v.s. \ \ \ \ H_a: \ \ p \ne 0.3. \] We took a random sample of 100 students and recorded their majors, and found that 33 of them claimed a major in STEM. This means 67 of them are non-STEM majors. We have introduced a procedure to test the above hypotheses with the test statistic. \[ TS = \frac{\hat{p}-p_0}{\sqrt{p_0(1-p_0)/n}} \]

That compares the claimed proportion with the sample proportion.

Note that the proportion of STEM majors contains the number of majors (frequencies) in both STEM and non-STEM disciplines. We can think about using (observed)sample frequencies and null (expected) frequencies to define the test statistic.

  • Under \(H_0\), we would expect to have 30 STEM majors and 70 non-STEM majors.

  • We observed 33 STEM majors and 67 STEM majors in the random sample.

The above observed and expected numbers of STEM and non-STEM majors are summarized in the following table.

In fact, a test statistic that measures the “distance” between the observed and expected frequency tables and has a \(\chi^2\) (chi-square) distribution is defined below \[ TS = \frac{(O_1 - E_1)^2}{E_1} + \frac{(O_2 - E_2)^2}{E_2} \to \chi_1^2. \]

The value of the test statistic in this example

\[TS = \frac{(33-30)^2}{30} + \frac{(67-70)^2}{70} = 9/30 + 49/70 = 3/10 + 7/10 = 1\]

With the above value of the test statistic, we can make a statistical decision on \(H_0\) based on a given significance level.

3.2 Formulation of Chi-square Test of Goodness-of-fit

Let \(k\) be the number of categories of categorical variable \(Y\). The category labels are \(C_1, C_2, \cdots, C_k\). Let \(P_1 = Pr(C_1), P_2 = Pr(C_2), \cdots, P_k = Pr(C_k)\). The null hypothesis claims that the categorical variable follows a specific distribution, and the alternative hypothesis claims that the categorical variable does NOT follow the distribution specified in the null hypothesis. That is,

\[ H_0:\ \ P_1 = p_1, P_2 = p_2, \cdots, P_k = p_k \ \ \ \ v.s. \ \ \ \ H_a: \ \ the \ distribution \ in \ H_0 \ is \ not \ correct. \]

The \(N\) is the sample size. We can then calculate the expected cell frequency of each category using formulas: \(E_1 = N\times p_1, E_2 = N \times p_2, \cdots, E_k = N \times p_k\). The observed cell frequency, denoted by \(O_i\) (for \(i=1,2, \cdots, k\)), of each category is obtained from the data set. The expected and observed frequencies are summarized in the following table.

The chi-square statistic is

\[ G^2 = \frac{(O_1-E_1)^2}{E_1} + \frac{(O_2-E_2)^2}{E_2} + \cdots + \frac{(O_k-E_k)^2}{E_k} \to \chi_{k-1}^2 \]

A small \(G^2\) indicates a lack of evidence for rejecting the null hypothesis. This implies that the Pearson chi-square test of goodness is always right-tailed. The degrees of freedom are always \((k-1)\) if the categorical factor variable has k levels.


IMPORTANT ASSUMPTION: The \(\chi^2\) goodness-of-fit test requires sufficiently large expected frequencies. The rule of thumb is that all expected frequencies should be at least 5. If any expected frequency is less than 5, the test may be unreliable.


In the subsequent examples, some expected frequencies may be less than 5. Please note that these examples are for illustrative purposes only. In practice, if too many expected frequencies are below 5, you should increase the sample size or combine categories (if meaningful) to ensure the validity of the \(\chi^2\) goodness-of-fit test.


Example 3. A gambler wants to test a die to determine whether it is fair. The gambler rolls a die that has six possible outcomes: 1, 2, 3, 4, 5, and 6; and the die is fair if each of these outcomes is equally likely. The gambler rolls the die 60 times and counts the number of times each number comes up. These counts, which are called the observed frequencies, are

Solution: The null hypothesis is that the six-sided die is fair. That is equivalent to \[ H_0: \ \ p_1 = p_2 = p_3 = p_4 = p_5 = p_6 = 1/6 \ \ \ \ v.s. \ \ \ \ H_a: \ \ The \ die \ is \ NOT \ fair. \] Based on the observed frequency table, the size of the sample is 60. Using the cell probabilities in \(H_0\), we have expected frequencies of the 6 categories to be equal to 10. We summarize the expected and observed frequencies in the following table.

The test statistic for testing \(H_0\) is defined by

\[ G^2 = \frac{(12-10)^2}{10}+\frac{(7-10)^2}{10}+\frac{(14-10)^2}{10}+\frac{(15-10)^2}{10} +\frac{(4-10)^2}{10}+\frac{(8-10)^2}{10} \\ =(4+9+16+25+36+4)/10=9.4 \] Since the categorical variable (number of dots on the faces of the 6-sided die) has 6 categories. The test statistic has 5 degrees of freedom. The critical value based on the significance level of 0.05 is given in the following figure.

The test statistic is NOT in the rejection region. We fail to reject the null hypothesis. The die is fair.

Example 4. Grade distribution: A statistics teacher claims that, on average, \(20\%\) of her students get a grade of A, \(35\%\) get a B, \(25\%\) get a C, \(10\%\) get a D, and \(10\%\) get an F. The grades of a random sample of 100 students were recorded. The following table presents the sample frequencies of each grade.

Solution: Based on the given information. \(N = 100\). The null hypothesis and the alternative hypothesis are \[ H_0: \ \ p_A = 0.2, p_B = 0.35, p_C = 0.25, p_D = 0.1, p_F = 0.1 \ \ \ \ v.s. H_a: \ \ The \ claimed \ distribution \ is \ wrong. \] Under the null hypothesis, the expected table is given by

The test statistic has 4 degrees of freedom, and the value is calculated as follows.

\[ G^2=\frac{(29-20)^2}{20}+\frac{(42-35)^2}{35}+\frac{(20-25)^2}{25}+\frac{(5-10)^2}{10}+\frac{(4-10)^2}{10}=12.56 \] The critical value with a significance level of 0.05 is given by

Since the test statistic is inside the rejection region, we reject the null hypothesis. That is, the sample does not support the claimed grade distribution in \(H_0\).

Remark: In the chi-square goodness-of-fit test, the crucial step is to find the *expected** frequency table under the null hypothesis.


The next YouTube video gives another example with detailed manual calculation.



4 Performing Goodness-of-fit Test in R

The two pieces of information required in the chi-square goodness-of-fit test are: observed frequency and the Hypothetical distribution under \(H_0\). Next, we will use the formulas introduced earlier and built-in R functions, respectively. For convenience, we use the following example to implement the \(\chi^2\) goodness-of-fit test.

Testing M&M Color Distribution: A company claims their M&Ms are distributed with these proportions:

Brown - 30%; Yellow - 20%; Red - 20%; Blue - 10%; Orange - 10%; Green - 10%

A random sample of 200 M&Ms was taken and observed:

Brown - 52; Yellow - 48; Red - 38; Blue - 22; Orange - 20; Green - 20

The null and alternative hypotheses are:

\[ H_0: p_1 = 0.3, \ \ p_2 = 0.2, \ \ p_3 = 0.2, \ \ p_4 = 0.1, \ \ p_5 = 0.1, \ \ p_6 = 0.1 \]

v.s.

\[ \text{at least one of the hypothetical probabilities is not true.} \]

Remark: In general, \(\chi^2\) tests are all right-tailed. This means that the critical value is on the right tail of the chi-square density curve, and the p-value is defined as the tail area to the right of the test statistic.

Define R Data:

observed <- c(52, 48, 38, 22, 20, 20)
expected.props <- c(0.30, 0.20, 0.20, 0.10, 0.10, 0.10)

4.1 Formula Approoach

Recall that the \(\chi^2\) test statistic is given by

\[ G^2 = \frac{(O_1-E_1)^2}{E_1} + \frac{(O_2-E_2)^2}{E_2} + \cdots + \frac{(O_k-E_k)^2}{E_k} \to \chi_{k-1}^2. \] To evaluate the test statistic \(G^2\), we need to find the expected number of colors based on the data defined earlier.

# observed and expected.props were defined earlier
# total count
tot <- sum(observed) 
expected.counts <- tot * expected.props   # this gives (52x0.30, 48x0.2, 38x0.2, ....)
                                               # and returns a vector of observed frequencies
## test statistics
G.sq <- sum ((observed - expected.counts)^2/expected.counts)  # sum() sum of resulting components
## degrees of freedom
df <- length(observed) - 1    # length() counts the number of cells in the vector
## all chi.sq test are right-tailed, using `lower.tail = FALSE`  to return the upper tail area.
p.value <- pchisq(G.sq, df =df, lower.tail = FALSE)   # 
## combine G.sq and p-value using cbind()
cbind(G.sq = G.sq, p.value = p.value)
##          G.sq  p.value
## [1,] 2.966667 0.705125

Since the p-value is greater than 0.05, the null hypothesis is not rejected. That is, the observed frequency distribution is not significantly different from the hypothetical probability distribution.

4.2 Built-in Function Approach

The package {stats} coming with base R has a function chisq.test() to perform the chi-square test. The following single line of code returns the results of the \(\chi^2\) test.

## CAUTION: the second argument must be in the form of: p = hypothetical probabilities!
##          when performing goodness-of-fit tests. OTHERWISE, R will perform independence tests.
chisq.test(observed, p = expected.props)
## 
##  Chi-squared test for given probabilities
## 
## data:  observed
## X-squared = 2.9667, df = 5, p-value = 0.7051


5 Practice Exercises

College Sports: A University conducted a survey of its recent graduates to collect demographic and health information for future planning purposes as well as to assess students’ satisfaction with their undergraduate experiences. The survey revealed that a substantial proportion of students were not engaging in regular exercise, many felt their nutrition was poor, and a substantial number were smoking. In response to a question on regular exercise, 60% of all graduates reported getting no regular exercise, 25% reported exercising sporadically, and 15% reported exercising regularly as undergraduates. The next year, the University launched a health promotion campaign on campus in an attempt to increase health behaviors among undergraduates. The program included modules on exercise, nutrition, and smoking cessation. To evaluate the impact of the program, the University again surveyed graduates and asked the same questions. The survey was completed by 470 graduates, and the following data were collected on the exercise question:

We specifically want to compare the distribution of responses in the sample to the distribution reported the previous year (i.e., 60%, 25%, 15% reporting no, sporadic, and regular exercise, respectively). Whether the data supports the above distribution at a significance level of 0.05.

LS0tDQp0aXRsZTogIkNoaXNxdWFyZSBHb29kbmVzcy1vZi1maXQgVGVzdCINCmF1dGhvcjogIkNoZW5nIFBlbmciDQpkYXRlOiAiU1RBMjAwIFN0YXRpc3RpY3MgSUkgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogNQ0KICAgIGZpZ19oZWlnaHQ6IDQNCi0tLQ0KDQpgYGB7PWh0bWx9DQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoNCmRpdiNUT0MgbGkgew0KICAgIGxpc3Qtc3R5bGU6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDIgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KPC9zdHlsZT4NCmBgYA0KDQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCg0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KIyBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICJDOi9Vc2Vycy83NUNQRU5HL09uZURyaXZlIC0gV2VzdCBDaGVzdGVyIFVuaXZlcnNpdHkgb2YgUEEvRG9jdW1lbnRzIikNCiMga25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSAiQzpcXFNUQTQ5MFxcdzA1IikNCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gVFJVRSwgICANCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UpDQpgYGANCg0KXA0KDQpcDQoNCiMgSW50cm9kdWN0aW9uDQoNCldlIGhhdmUgZGlzY3Vzc2VkIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0d28gbnVtZXJpY2FsIHZhcmlhYmxlcyB1c2luZyB0aGUgbGluZWFyIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGFuZCBsaW5lYXIgcmVncmVzc2lvbi4gV2Ugbm93IHR1cm4gdG8gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuIFRoZSBpZGVhIGlzIHRvIG1ha2UgYW4gYXNzdW1wdGlvbiAoaHlwb3RoZXNpcykgYWJvdXQgdGhlIHZhcmlhYmxlKHMpIGFuZCB1c2UgdGhpcyBhc3N1bXB0aW9uIHRvIGNvbnN0cnVjdCBhIGZyZXF1ZW5jeSB0YWJsZSwga25vd24gYXMgdGhlIGV4cGVjdGVkIHRhYmxlLiBBdCB0aGUgc2FtZSB0aW1lLCB3ZSB0YWJ1bGF0ZSB0aGUgZGF0YSB0byBvYnRhaW4gYW4gb2JzZXJ2ZWQgdGFibGUuIFRoZSBkaXNjcmVwYW5jeSBiZXR3ZWVuIHRoZSBleHBlY3RlZCBhbmQgb2JzZXJ2ZWQgdGFibGVzIGNhbiBiZSB1c2VkIHRvIG1ha2UgYW4gaW5mZXJlbmNlIGFib3V0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGVzLg0KDQpUaGlzIG1vZHVsZSBpbnRyb2R1Y2VzIGEgbmV3IHBvc2l0aXZlIGRpc3RyaWJ1dGlvbuKAlHRoZSBjaGktc3F1YXJlICgkXGNoaV4yJCkgZGlzdHJpYnV0aW9u4oCUYW5kIGl0cyBhcHBsaWNhdGlvbiBpbiAqKmdvb2RuZXNzLW9mLWZpdCoqIHRlc3RpbmcuICoqR29vZG5lc3Mtb2YtZml0IHRlc3RzIGZvciBjYXRlZ29yaWNhbCBkaXN0cmlidXRpb24qKiBhc3Nlc3MgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSAqKm9ic2VydmVkIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24qKiBhbmQgdGhlICoqaHlwb3RoZXRpY2FsIGRpc3RyaWJ1dGlvbioqIHVuZGVyIHRoZSBudWxsIGh5cG90aGVzaXMgKGkuZS4sIHRoZSBleHBlY3RlZCBkaXN0cmlidXRpb24gdW5kZXIgJEhfMCQpLg0KDQpcDQoNCiMgQ2hpLXNxdWFyZSAoJFxjaGleMiQpIERpc3RyaWJ1dGlvbg0KDQpBcyB3ZSBsZWFybmVkIGZyb20gTUFUMTIxLzEyNSwgdGhlICoqQ2hpLXNxdWFyZSAoJFxjaGleMiQpIGRpc3RyaWJ1dGlvbioqIGlzIGEgY29udGludW91cyBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gY29tbW9ubHkgdXNlZCBpbiBpbmZlcmVudGlhbCBzdGF0aXN0aWNzLCBlc3BlY2lhbGx5IGZvciB0ZXN0aW5nIGh5cG90aGVzZXMgYWJvdXQgdmFyaWFuY2VzIGFuZCBjYXRlZ29yaWNhbCBkYXRhIChlLmcuLCBjb250aW5nZW5jeSB0YWJsZXMpLiBXZSB3aWxsIHJldmlldyB0aGlzIGRpc3RyaWJ1dGlvbiBhbmQgcmVsYXRlZCBwcm9ibGVtcy4NCg0KIyMgQ2hpLVNxdWFyZSBEaXN0cmlidXRpb24NCg0KVGhlIGtleSBjaGFyYWN0ZXJpc3RpY3Mgb2YgJFxjaGleMiQgZGlzdHJpYnV0aW9uIGFyZQ0KDQoqICoqU2hhcGUqKjogU2tld2VkIHJpZ2h0LCBidXQgYmVjb21lcyBtb3JlIHN5bW1ldHJpYyBhcyBkZWdyZWVzIG9mIGZyZWVkb20gKGRmKSBpbmNyZWFzZS4NCg0KKiAqKlN1cHBvcnQqKjogRGVmaW5lZCBvbmx5IGZvciBub24tbmVnYXRpdmUgdmFsdWVzICgkeCBcZ2UgMCQpLg0KDQoqICoqUGFyYW1ldGVyKio6IERlZ3JlZXMgb2YgZnJlZWRvbSAoZGYpLCB0eXBpY2FsbHkgYSBwb3NpdGl2ZSBpbnRlZ2VyLg0KDQoNClRoZSBmb2xsb3dpbmcgWW91VHViZSB2aWRlbyBnaXZlcyBhIG5pY2UgaW50cm9kdWN0aW9uIHRvIHRoZSAkXGNoaV4yJCBkaXN0cmlidXRpb24uIA0KDQoNClwNCjxjZW50ZXI+PGEgaHJlZj0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1oY0RiMTJmc2JCVSIgdGFyZ2V0PSJwb3B1cCIgDQogICAgICAgICAgICAgICAgICAgb25jbGljaz0id2luZG93Lm9wZW4oJ2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9aGNEYjEyZnNiQlUnLA0KICAgICAgICAgICAgICAgICAgICAgICduYW1lJywnd2lkdGg9ODUwLGhlaWdodD01MDAnKSI+PGltZyBzcmMgPSAiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vTUFUMTIxVzUvaW1nL1ZpZGVvSWNvbi5wbmciIHdpZHRoPSIyMDAiIGhlaWdodD0iMTIwIj48L2E+DQo8L2NlbnRlcj4NClwNCg0KIyMgVHdvIFR5cGVzIG9mIFF1ZXN0aW9ucw0KDQpBcyB3ZSBsZWFybmVkIGZyb20gbm9ybWFsIGFuZCB0LWRpc3RyaWJ1dGlvbnMsIHdlIG5lZWQgdG8gY2FsY3VsYXRlIHRhaWwgcHJvYmFiaWxpdGllcywgaW4gcGFydGljdWxhciwgdGhlIHJpZ2h0LXRhaWwgcHJvYmFiaWxpdGllcyBhbmQgcXVhbnRpbGVzIGZvciBnaXZlbiBwcm9iYWJpbGl0aWVzLiBXZSB1c2VkICRjaGleMiQgdGFibGUgaW4gTUFUMTIxLzEyNS4gWW91IGFyZSBlbmNvdXJhZ2VkIHRvIHVzZSBSIGNvbW1hbmRzIHRvIGZpbmQgcHJvYmFiaWxpdGllcyBhbmQgcXVhbnRpbGVzLg0KDQoqKkZpbmRpbmcgUHJvYmFiaWxpdHkgKEFyZWEgdW5kZXIgdGhlIGN1cnZlKSoqDQoNCiogKipHb2FsKio6IENhbGN1bGF0ZSB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhICRcY2hpXjIkIHJhbmRvbSB2YXJpYWJsZSBmYWxscyBiZWxvdywgYWJvdmUsIG9yIGJldHdlZW4gY2VydGFpbiB2YWx1ZXMuDQoNCiogKipUeXBpY2FsIFF1ZXN0aW9uKio6IFdoYXQgaXMgJFAoWCBcbGUgeCkkIG9yICRQKFggXGdlIHgpJCBmb3IgYSAkXGNoaV4yJC1kaXN0cmlidXRlZCB2YXJpYWJsZSB3aXRoICRkZiA9IGskPw0KDQoqICoqUiBDb21tYW5kKio6DQoNCmBgYHt9DQpwY2hpc3EoeCwgZGYpICAgICAgICAgICAgICAgICAgICAgICAgIyBQKFggPD0geCkNCnBjaGlzcSh4LCBkZiwgbG93ZXIudGFpbCA9IEZBTFNFKSAgICAjIFAoWCA+PSB4KSwgeCA9IGNoaS1zcXVhcmUgdGVzdCBzdGF0aXN0aWMNCmBgYA0KDQo8Zm9udCBjb2xvciA9ICJyZWQiPioqXGNvbG9ye3JlZH1Ob3RlKio8L2ZvbnQ+OiA8Zm9udCBjb2xvciA9ICJibHVlIj4qKlxjb2xvcntibHVlfSBBbGwgJFxjaGleMiQgdGVzdHMgYXJlIHJpZ2h0LXRhaWxlZCBzaW5jZSB0aGUgdGVzdCBzdGF0aXN0aWMgbWVhc3VyZXMgdGhlIGRpc2NyZXBhbmN5IGJldHdlZW4gdHdvIGRpc3RyaWJ1dGlvbnMuKio8L2ZvbnQ+IFRoZSBwLXZhbHVlIG9mIGEgJFxjaGleMiQgdGVzdCBpcyBhbHdheXMgdGhlIGFyZWEgb2YgdGhlIHRhaWwgcmVnaW9uIHRvIHRoZSByaWdodC1oYW5kIHNpZGUgb2YgdGhlIHRlc3Qgc3RhdGlzdGljLCB3aGljaCBjYW4gYmUgZm91bmQgdXNpbmcgYHBjaGlzcSh4LCBkZiwgbG93ZXIudGFpbCA9IEZBTFNFKSBgLiBUaGUgYXJndW1lbnQgYGxvd2VyLnRhaWwgPSBGQUxTRWAgcmV0dXJucyB0aGUgKip1cHBlci10YWlsIGFyZWEqKiBhbmQgYHhgID0gY2hpLXNxdWFyZSB0ZXN0IHN0YXRpc3RpYy4NCg0KDQoNCg0KKiAqKkV4YW1wbGUgMSoqOiBGaW5kICRQKFggXGxlIDUpJCBmb3IgJGRmID0gMTAkLg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsICBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNzUlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoIndlZWswMi9NMDMtY2hpc3FQcm9iLnBuZyIpDQpgYGANCg0KDQpgYGB7cn0NCnBjaGlzcSg1LCBkZiA9IDEwKQ0KYGBgDQoNCiogKipFeGFtcGxlIDIqKjogRmluZCAkUChYIFxnZSAxNSkkIGZvciAkZGYgPSAxMCQuDQoNCg0KYGBge3IgZWNobyA9IEZBTFNFLCAgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9Ijc1JSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDIvTTAzLWNoaXNxUHJvYjAyLnBuZyIpDQpgYGANCg0KDQpgYGB7cn0NCnBjaGlzcSgxNSwgZGYgPSAxMCwgbG93ZXIudGFpbCA9IEZBTFNFKQ0KYGBgDQpcIA0KKipGaW5kaW5nIFBlcmNlbnRpbGUgKGdpdmVuIHRoZSBhcmVhIHVuZGVyIHRoZSBjdXJ2ZSkqKg0KDQoqICoqR29hbCoqOiBDYWxjdWxhdGUgdGhlIGN1dCAkXGNoaV4yJCB2YWx1ZSAocGVyY2VudGlsZSkgdGhhdCBkZWZpbmVzIHRoZSB0YWlsIHJlZ2lvbiB3aXRoIGdpdmVuIGFyZWEgKGkuZS4sIHRoZSB0YWlsIHByb2JhYmlsaXR5KS4gDQoNCiogKipUeXBpY2FsIFF1ZXN0aW9uKio6IFdoYXQgaXMgIHRoZSB2YWx1ZSAkeF8wJCB0aGF0IHNhdGlzZmllcyAkUChYIFxsZSB4XzApID0gcF8wJCBvciAkUChYIFxnZSB4XzApID0gcF8wJCBmb3IgYSAkXGNoaV4yJC10YWlsIGFyZWEgKHByb2JhYmxpdHkpICRwXzAkPw0KDQoqICoqUiBDb21tYW5kKio6DQoNCg0KYGBge30NCnFjaGlzcShwLCBkZiwgbG93ZXIudGFpbCA9IFRSVUUpDQogIyBwOiB0aGUgcHJvYmFiaWxpdHkgKGFyZWEgdW5kZXIgdGhlIGN1cnZlKQ0KICMgZGY6IGRlZ3JlZXMgb2YgZnJlZWRvbQ0KICMgbG93ZXIudGFpbDoNCiAjICAgVFJVRSAoZGVmYXVsdCkgZm9yIGxlZnQtdGFpbCBhcmVhDQogIyAgIEZBTFNFIGZvciByaWdodC10YWlsIGFyZWENCmBgYA0KDQoNCioqRXhhbXBsZSAzKio6IGZpbmQgdGhlIDk1LXRoIHBlcmNlbnRpbGUgb2YgdGhlICRcY2hpXjIkIGRpc3RyaWJ1dGlvbiB3aXRoIDEyIGRlZ3JlZXMgb2YgZnJlZWRvbS4NCg0KKipBbnN3ZXIqKjogOTUlIHBlcmNlbnRpbGUgaXMgdGhlIGN1dC1vZmYgdmFsdWUgdGhhdCBzcGxpdHMgdGhlIHJlZ2lvbiB1bmRlciB0aGUgJFxjaGleMl97MTJ9JCBkZW5zaXR5IGN1cnZlIGludG8gdHdvIHJlZ2lvbnMuIFRoZSBsZWZ0IHJlZ2lvbiBoYXMgYW4gYXJlYSBvZiAwLjk1LCBhbmQgdGhlIHJpZ2h0IHJlZ2lvbiBoYXMgYW4gYXJlYSBvZiAwLjA1LiBUaGlzIG1lYW5zIHdlIHVzZSBlaXRoZXIgYHFjaGkoMC45NSwgZGYgPTEyLCBsb3dlci50YWlsID0gVFJVRSlgIG9yIGBxY2hpKDAuMDUsIGRmID0gMTIsIGxvd2VyLnRhaWwgPSBGQUxTRSlgIHRvIGZpbmQgdGhlIHNhbWUgcGVyY2VudGlsZSBpbiBSLiBUaGUgY29kZSBpcyBpbiB0aGUgZm9sbG93aW5nLg0KDQoNCmBgYHtyfQ0KcWNoaXNxKDAuOTUsIGRmID0xMiwgbG93ZXIudGFpbCA9IFRSVUUpDQpxY2hpc3EoMC4wNSwgZGYgPTEyLCBsb3dlci50YWlsID0gRkFMU0UpDQpgYGANCg0KYGBge3IgZWNobyA9IEZBTFNFLCAgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9Ijc1JSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDIvTTAzLWNoaXNxUHJvYjAzLnBuZyIpDQpgYGANCg0KDQoNCg0KDQoNCg0KIyMgQ2hpc3F1YXJlIFRhYmxlDQoNCldlIGNhbiBhbHNvIHVzZSBhIGNoaS1zcXVhcmUgdGFibGUgdG8gZmluZCB0aGUgY3JpdGljYWwgdmFsdWUgYmFzZWQgb24gYSBnaXZlbiBzaWduaWZpY2FuY2UgbGV2ZWwuIFdoZW4gdXNpbmcgYSB0YWJsZSwgd2UgYWx3YXlzIHVzZSB0aGUgY3JpdGljYWwgdmFsdWUgbWV0aG9kLiBUaGUgcC12YWx1ZSBtZXRob2QgaXMgdXNlZCB3aGVuIHVzaW5nIGEgc29mdHdhcmUgcHJvZ3JhbS4NCg0KVGhlIGNoaS1zcXVhcmUgZGlzdHJpYnV0aW9uIGlzIHVzZWQgdG8gY2hhcmFjdGVyaXplIGEgcG9zaXRpdmUgcmFuZG9tIHZhcmlhYmxlLiBVbmxpa2Ugbm9ybWFsIGFuZCB0IGRpc3RyaWJ1dGlvbnMgdGhhdCBoYXZlIHN5bW1ldHJpYyBkZW5zaXR5IGN1cnZlcywgdGhlIGNoaS1zcXVhcmUgZGlzdHJpYnV0aW9ucyAoZGVwZW5kZW50IG9uIHRoZSBkZWdyZWVzIG9mIGZyZWVkb20pIGhhdmUgc2tld2VkIGRlbnNpdHkgY3VydmVzLg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsICBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICc2MCUnfQ0KaW5jbHVkZV9ncmFwaGljcygid2VlazAyL2NoaXNxRGVuc2l0eS5wbmciKQ0KYGBgICANCg0KV2UgY2FuIGZpbmQgdGhlIGNyaXRpY2FsIHZhbHVlIG9mIHRoZSBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbiBmcm9tIHRoZSBjaGktc3F1YXJlIHRhYmxlIHRoYXQgaXMgYXZhaWxhYmxlIG9uIHRoZSBjb3Vyc2Ugd2ViIHBhZ2UuIFRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGNoaS1zcXVhcmUgdGFibGUgaXMgc2ltaWxhciB0byB0aGUgdC10YWJsZS4gDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzgwJSd9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDIvY2hpc3FUYWJsZS5wbmciKQ0KYGBgIA0KDQpUaGUgcG9zc2libGUgZGVncmVlcyBvZiBmcmVlZG9tIGFyZSBsaXN0ZWQgaW4gdGhlIGZpcnN0IGNvbHVtbiwgdGhlIHBvc3NpYmxlIHJpZ2h0LXRhaWwgYXJlYXMgYXJlIGxpc3RlZCBpbiB0aGUgdG9wIHJvdywgYW5kIHRoZSBjcml0aWNhbCB2YWx1ZXMgYXJlIGxpc3RlZCBpbiB0aGUgbWFpbiBib2R5IG9mIHRoZSB0YWJsZS4NCg0KDQpUaGUgc3RlcHMgZm9yIGZpbmRpbmcgdGhlIGNyaXRpY2FsIHZhbHVlcyBhcmUgdGhlIHNhbWUgYXMgdGhvc2Ugd2UgZm9sbG93ZWQgZm9yIGZpbmRpbmcgdGhlIHQtY3JpdGljYWwgdmFsdWVzLg0KDQo8Zm9udCBjb2xvciA9ICJkYXJrcmVkIj4gKipFeGFtcGxlIDIqKi48L2ZvbnQ+IEZpbmQgdGhlIGNyaXRpY2FsIHZhbHVlIG9mIHRoZSBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbiB3aXRoIDUgZGVncmVlcyBvZiBmcmVlZG9tIHdpdGggYSBzaWduaWZpY2FuY2UgbGV2ZWwgb2YgMC4wNS4NCg0KYGBge3IgZWNobyA9IEZBTFNFLCAgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnODAlJ30NCmluY2x1ZGVfZ3JhcGhpY3MoIndlZWswMi9leGFtcGxlMDJDaGlzcUNWLnBuZyIpDQpgYGAgDQoNClRoZSBhYm92ZSBmaWd1cmUgc2hvd3MgaG93IHRvIGZpbmQgdGhlIGNyaXRpY2FsIHZhbHVlLCBkZW5vdGVkIGJ5ICRDViA9IFxjaGleMl97NSwgMC4wNX0gPSAxMS4wNzEkLiBUaGUgZmlyc3Qgc3Vic2NyaXB0IGRlbm90ZXMgNSBkZWdyZWVzIG9mIGZyZWVkb20sIGFuZCB0aGUgc2Vjb25kIHN1YnNjcmlwdCBpcyB0aGUgc2lnbmlmaWNhbmNlIGxldmVsIG9mIDAuMDUuDQoNCg0KPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9Kio8L2ZvbnQ+DQoNClwNCg0KDQojIENoaS1zcXVhcmUgVGVzdCBvZiBHb29kbmVzcy1vZi1maXQgDQoNCioqQSBnb29kbmVzcy1vZi1maXQgdGVzdCoqIG9mIGEgZGlzdHJpYnV0aW9uIGlzIGEgdGVzdGluZyBwcm9jZWR1cmUgdGhhdCBqdXN0aWZpZXMgd2hldGhlciB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIHNwZWNpZmllZCBkaXN0cmlidXRpb24gaXMgY29ycmVjdCwgYmFzZWQgb24gc2FtcGxlIGluZm9ybWF0aW9uLiANCg0KRm9yIGEgc2luZ2xlIGNhdGVnb3JpY2FsIHZhcmlhYmxlLCB0aGUgbnVsbCBoeXBvdGhlc2lzIHNob3VsZCBzcGVjaWZ5IHRoZSBjZWxsIHByb2JhYmlsaXRpZXMuIEluIG90aGVyIHdvcmRzLCBpZiB0aGUgY2F0ZWdvcnkgaGFzIGsgY2F0ZWdvcmllcywgdGhlbiAoJHBfMSwgcF8yIFxjZG90cywgcF9rJCkgbXVzdCBiZSBzcGVjaWZpZWQgaW4gdGhlIG51bGwgaHlwb3RoZXNpcy4NCg0KIyMgQSBNb3RpdmF0aW9uYWwgRXhhbXBsZQ0KDQpBcyBhIHNwZWNpYWwgY2FzZSwgd2UgbG9vayBhdCB0aGUgZm9sbG93aW5nIGV4YW1wbGUgb2YgdGVzdGluZyB0aGUgcHJvcG9ydGlvbiBwcm9ibGVtLiANCg0KPGZvbnQgY29sb3IgPSAiZGFya3JlZCI+ICoqRXhhbXBsZSAxKiouPC9mb250PiBXZSB3YW50IHRvIGp1c3RpZnkgYSBjbGFpbSB0aGF0IGFib3V0IDMwJSBvZiBXQ1Ugc3R1ZGVudHMgYXJlIFNURU0gbWFqb3JzLiBUaGF0IGlzLCB3ZSB0ZXN0IHRoZSBmb2xsb3dpbmcgaHlwb3RoZXNlcy4NCiQkDQpIXzA6IFwgIFwgcCA9IDAuMyBcIFwgXCBcIHYucy4gXCBcIFwgXCBIX2E6IFwgXCBwIFxuZSAwLjMuDQokJA0KV2UgdG9vayBhIHJhbmRvbSBzYW1wbGUgb2YgMTAwIHN0dWRlbnRzIGFuZCByZWNvcmRlZCB0aGVpciBtYWpvcnMsIGFuZCBmb3VuZCB0aGF0IDMzIG9mIHRoZW0gY2xhaW1lZCBhIG1ham9yIGluIFNURU0uIFRoaXMgbWVhbnMgNjcgb2YgdGhlbSBhcmUgbm9uLVNURU0gbWFqb3JzLiBXZSBoYXZlIGludHJvZHVjZWQgYSBwcm9jZWR1cmUgdG8gdGVzdCB0aGUgYWJvdmUgaHlwb3RoZXNlcyB3aXRoIHRoZSB0ZXN0IHN0YXRpc3RpYy4NCiQkDQpUUyA9IFxmcmFje1xoYXR7cH0tcF8wfXtcc3FydHtwXzAoMS1wXzApL259fQ0KJCQNCg0KVGhhdCBjb21wYXJlcyB0aGUgY2xhaW1lZCBwcm9wb3J0aW9uIHdpdGggdGhlIHNhbXBsZSBwcm9wb3J0aW9uLiANCg0KDQpOb3RlIHRoYXQgdGhlIHByb3BvcnRpb24gb2YgU1RFTSBtYWpvcnMgY29udGFpbnMgdGhlIG51bWJlciBvZiBtYWpvcnMgKGZyZXF1ZW5jaWVzKSBpbiBib3RoIFNURU0gYW5kIG5vbi1TVEVNIGRpc2NpcGxpbmVzLiBXZSBjYW4gdGhpbmsgYWJvdXQgdXNpbmcgKG9ic2VydmVkKXNhbXBsZSBmcmVxdWVuY2llcyBhbmQgbnVsbCAoZXhwZWN0ZWQpIGZyZXF1ZW5jaWVzIHRvIGRlZmluZSB0aGUgdGVzdCBzdGF0aXN0aWMuIA0KDQoqICoqVW5kZXIgJEhfMCQqKiwgd2Ugd291bGQgKipleHBlY3QqKiB0byBoYXZlIDMwIFNURU0gbWFqb3JzIGFuZCA3MCBub24tU1RFTSBtYWpvcnMuDQoNCiogV2UgKipvYnNlcnZlZCoqIDMzIFNURU0gbWFqb3JzIGFuZCA2NyBTVEVNIG1ham9ycyBpbiB0aGUgcmFuZG9tIHNhbXBsZS4NCg0KVGhlIGFib3ZlIG9ic2VydmVkIGFuZCBleHBlY3RlZCBudW1iZXJzIG9mIFNURU0gYW5kIG5vbi1TVEVNIG1ham9ycyBhcmUgc3VtbWFyaXplZCBpbiB0aGUgZm9sbG93aW5nIHRhYmxlLg0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzUwJSd9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDIvZXhhbXBsZTAxLUV4cE9ic1RhYmxlLnBuZyIpDQpgYGAgIA0KDQpJbiBmYWN0LCBhIHRlc3Qgc3RhdGlzdGljIHRoYXQgbWVhc3VyZXMgdGhlICJkaXN0YW5jZSIgYmV0d2VlbiB0aGUgb2JzZXJ2ZWQgYW5kIGV4cGVjdGVkIGZyZXF1ZW5jeSB0YWJsZXMgYW5kIGhhcyBhICRcY2hpXjIkIChjaGktc3F1YXJlKSBkaXN0cmlidXRpb24gaXMgZGVmaW5lZCBiZWxvdw0KJCQNClRTID0gXGZyYWN7KE9fMSAtIEVfMSleMn17RV8xfSArIFxmcmFjeyhPXzIgLSBFXzIpXjJ9e0VfMn0gXHRvIFxjaGlfMV4yLg0KJCQNCg0KVGhlIHZhbHVlIG9mIHRoZSB0ZXN0IHN0YXRpc3RpYyBpbiB0aGlzIGV4YW1wbGUgDQoNCiQkVFMgPSBcZnJhY3soMzMtMzApXjJ9ezMwfSArIFxmcmFjeyg2Ny03MCleMn17NzB9ID0gOS8zMCArIDQ5LzcwID0gMy8xMCArIDcvMTAgPSAxJCQNCg0KV2l0aCB0aGUgYWJvdmUgdmFsdWUgb2YgdGhlIHRlc3Qgc3RhdGlzdGljLCB3ZSBjYW4gbWFrZSBhIHN0YXRpc3RpY2FsIGRlY2lzaW9uIG9uICRIXzAkIGJhc2VkIG9uIGEgZ2l2ZW4gc2lnbmlmaWNhbmNlIGxldmVsLg0KDQoNCg0KDQojIyBGb3JtdWxhdGlvbiBvZiBDaGktc3F1YXJlIFRlc3Qgb2YgR29vZG5lc3Mtb2YtZml0DQoNCg0KTGV0ICRrJCBiZSB0aGUgbnVtYmVyIG9mIGNhdGVnb3JpZXMgb2YgY2F0ZWdvcmljYWwgdmFyaWFibGUgJFkkLiBUaGUgY2F0ZWdvcnkgbGFiZWxzIGFyZSAkQ18xLCBDXzIsIFxjZG90cywgQ19rJC4gTGV0ICRQXzEgPSBQcihDXzEpLCBQXzIgPSBQcihDXzIpLCBcY2RvdHMsIFBfayA9IFByKENfaykkLiBUaGUgbnVsbCBoeXBvdGhlc2lzIGNsYWltcyB0aGF0IHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBmb2xsb3dzIGEgc3BlY2lmaWMgZGlzdHJpYnV0aW9uLCBhbmQgdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgY2xhaW1zIHRoYXQgdGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGRvZXMgTk9UIGZvbGxvdyB0aGUgZGlzdHJpYnV0aW9uIHNwZWNpZmllZCBpbiB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGF0IGlzLA0KDQokJA0KSF8wOlwgXCBQXzEgPSBwXzEsIFBfMiA9IHBfMiwgXGNkb3RzLCBQX2sgPSBwX2sgXCBcIFwgXCB2LnMuIFwgIFwgIFwgIFwgIEhfYTogXCBcIHRoZSBcIGRpc3RyaWJ1dGlvbiBcIGluIFwgSF8wIFwgaXMgXCBub3QgXCBjb3JyZWN0Lg0KJCQNCg0KVGhlICROJCBpcyB0aGUgc2FtcGxlIHNpemUuIFdlIGNhbiB0aGVuIGNhbGN1bGF0ZSB0aGUgKipleHBlY3RlZCBjZWxsIGZyZXF1ZW5jeSoqIG9mIGVhY2ggY2F0ZWdvcnkgdXNpbmcgZm9ybXVsYXM6ICRFXzEgPSBOXHRpbWVzIHBfMSwgRV8yID0gTiBcdGltZXMgcF8yLCBcY2RvdHMsIEVfayA9IE4gXHRpbWVzIHBfayQuIFRoZSAqKm9ic2VydmVkIGNlbGwgZnJlcXVlbmN5KiosIGRlbm90ZWQgYnkgJE9faSQgKGZvciAkaT0xLDIsIFxjZG90cywgayQpLCBvZiBlYWNoIGNhdGVnb3J5IGlzIG9idGFpbmVkIGZyb20gdGhlIGRhdGEgc2V0LiBUaGUgKipleHBlY3RlZCoqIGFuZCAqKm9ic2VydmVkKiogZnJlcXVlbmNpZXMgYXJlIHN1bW1hcml6ZWQgaW4gdGhlIGZvbGxvd2luZyB0YWJsZS4NCg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsICBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICc2MCUnfQ0KaW5jbHVkZV9ncmFwaGljcygid2VlazAyL29ic0V4cFRhYmxlLnBuZyIpDQpgYGAgDQoNClRoZSBjaGktc3F1YXJlIHN0YXRpc3RpYyBpcw0KDQokJA0KR14yID0gXGZyYWN7KE9fMS1FXzEpXjJ9e0VfMX0gKyBcZnJhY3soT18yLUVfMileMn17RV8yfSArIFxjZG90cyArIFxmcmFjeyhPX2stRV9rKV4yfXtFX2t9IFx0byBcY2hpX3trLTF9XjINCiQkDQoNCkEgc21hbGwgJEdeMiQgaW5kaWNhdGVzIGEgbGFjayBvZiBldmlkZW5jZSBmb3IgcmVqZWN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMuIFRoaXMgaW1wbGllcyB0aGF0ICoqdGhlIFBlYXJzb24gY2hpLXNxdWFyZSB0ZXN0IG9mIGdvb2RuZXNzIGlzIGFsd2F5cyByaWdodC10YWlsZWQqKi4gIFRoZSBkZWdyZWVzIG9mIGZyZWVkb20gYXJlIGFsd2F5cyAkKGstMSkkIGlmIHRoZSBjYXRlZ29yaWNhbCBmYWN0b3IgdmFyaWFibGUgaGFzIGsgbGV2ZWxzLg0KDQpcDQoNCjxmb250IGNvbG9yPSJyZWQiIHNpemU9IjUiPioqXGNvbG9ye3JlZH1JTVBPUlRBTlQgQVNTVU1QVElPTioqPC9mb250PjogVGhlICRcY2hpXjIkIGdvb2RuZXNzLW9mLWZpdCB0ZXN0IHJlcXVpcmVzIDxmb250IGNvbG9yPSJibHVlIiBzaXplPSI1Ij4qKlxjb2xvcntibHVlfXN1ZmZpY2llbnRseSBsYXJnZSBleHBlY3RlZCBmcmVxdWVuY2llcyoqPC9mb250Pi4gVGhlICoqcnVsZSBvZiB0aHVtYioqIGlzIHRoYXQgYWxsIGV4cGVjdGVkIGZyZXF1ZW5jaWVzIHNob3VsZCBiZSAqKmF0IGxlYXN0IDUqKi4gPGZvbnQgY29sb3I9InJlZCIgc2l6ZT0iNSI+Klxjb2xvcntyZWR9SWYgYW55IGV4cGVjdGVkIGZyZXF1ZW5jeSBpcyBsZXNzIHRoYW4gNSwgdGhlIHRlc3QgbWF5IGJlIHVucmVsaWFibGUuKjwvZm9udD4NCg0KXA0KDQpJbiB0aGUgc3Vic2VxdWVudCBleGFtcGxlcywgc29tZSAqKmV4cGVjdGVkIGZyZXF1ZW5jaWVzKiogbWF5IGJlIGxlc3MgdGhhbiA1LiBQbGVhc2Ugbm90ZSB0aGF0IHRoZXNlIGV4YW1wbGVzIGFyZSBmb3IgaWxsdXN0cmF0aXZlIHB1cnBvc2VzIG9ubHkuIEluIHByYWN0aWNlLCBpZiB0b28gbWFueSBleHBlY3RlZCBmcmVxdWVuY2llcyBhcmUgYmVsb3cgNSwgeW91IHNob3VsZCAqKmluY3JlYXNlIHRoZSBzYW1wbGUgc2l6ZSoqICBvciAqKmNvbWJpbmUgY2F0ZWdvcmllcyoqIChpZiBtZWFuaW5nZnVsKSB0byBlbnN1cmUgdGhlIHZhbGlkaXR5IG9mIHRoZSAkXGNoaV4yJCBnb29kbmVzcy1vZi1maXQgdGVzdC4NCg0KXA0KDQoNCg0KDQo8Zm9udCBjb2xvciA9ICJkYXJrcmVkIj4gKipFeGFtcGxlIDMqKi48L2ZvbnQ+IEEgZ2FtYmxlciB3YW50cyB0byB0ZXN0IGEgZGllIHRvIGRldGVybWluZSB3aGV0aGVyIGl0IGlzIGZhaXIuIFRoZSBnYW1ibGVyIHJvbGxzIGEgZGllIHRoYXQgaGFzIHNpeCBwb3NzaWJsZSBvdXRjb21lczogMSwgMiwgMywgNCwgNSwgYW5kIDY7IGFuZCB0aGUgZGllIGlzIGZhaXIgaWYgZWFjaCBvZiB0aGVzZSBvdXRjb21lcyBpcyBlcXVhbGx5IGxpa2VseS4gVGhlIGdhbWJsZXIgcm9sbHMgdGhlIGRpZSA2MCB0aW1lcyBhbmQgY291bnRzIHRoZSBudW1iZXIgb2YgdGltZXMgZWFjaCBudW1iZXIgY29tZXMgdXAuIFRoZXNlIGNvdW50cywgd2hpY2ggYXJlIGNhbGxlZCB0aGUgb2JzZXJ2ZWQgZnJlcXVlbmNpZXMsIGFyZQ0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzM1JSd9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDIvZXhhbXBsZTAzRGF0YS5wbmciKQ0KYGBgIA0KDQoqKlNvbHV0aW9uKio6IFRoZSBudWxsIGh5cG90aGVzaXMgaXMgdGhhdCB0aGUgc2l4LXNpZGVkIGRpZSBpcyBmYWlyLiBUaGF0IGlzIGVxdWl2YWxlbnQgdG8NCiQkDQpIXzA6IFwgXCAgcF8xID0gcF8yID0gcF8zID0gcF80ID0gcF81ID0gcF82ID0gMS82IFwgXCBcIFwgdi5zLiBcIFwgXCBcIEhfYTogXCBcIFRoZSBcIGRpZSBcIGlzIFwgTk9UIFwgZmFpci4NCiQkDQpCYXNlZCBvbiB0aGUgb2JzZXJ2ZWQgZnJlcXVlbmN5IHRhYmxlLCB0aGUgc2l6ZSBvZiB0aGUgc2FtcGxlIGlzIDYwLiBVc2luZyB0aGUgKmNlbGwgcHJvYmFiaWxpdGllcyogaW4gJEhfMCQsIHdlIGhhdmUgKipleHBlY3RlZCBmcmVxdWVuY2llcyoqIG9mIHRoZSA2IGNhdGVnb3JpZXMgdG8gYmUgZXF1YWwgdG8gMTAuIFdlIHN1bW1hcml6ZSB0aGUgKipleHBlY3RlZCoqIGFuZCAqKm9ic2VydmVkKiogZnJlcXVlbmNpZXMgaW4gdGhlIGZvbGxvd2luZyB0YWJsZS4NCg0KYGBge3IgZWNobyA9IEZBTFNFLCAgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnNDUlJ30NCmluY2x1ZGVfZ3JhcGhpY3MoIndlZWswMi9leGFtcGxlMDMucG5nIikNCmBgYCANCg0KVGhlIHRlc3Qgc3RhdGlzdGljIGZvciB0ZXN0aW5nICRIXzAkIGlzIGRlZmluZWQgYnkNCg0KJCQNCkdeMiA9IFxmcmFjeygxMi0xMCleMn17MTB9K1xmcmFjeyg3LTEwKV4yfXsxMH0rXGZyYWN7KDE0LTEwKV4yfXsxMH0rXGZyYWN7KDE1LTEwKV4yfXsxMH0NCitcZnJhY3soNC0xMCleMn17MTB9K1xmcmFjeyg4LTEwKV4yfXsxMH0gXFwgPSg0KzkrMTYrMjUrMzYrNCkvMTA9OS40DQokJA0KU2luY2UgdGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlIChudW1iZXIgb2YgZG90cyBvbiB0aGUgZmFjZXMgb2YgdGhlIDYtc2lkZWQgZGllKSBoYXMgNiBjYXRlZ29yaWVzLiBUaGUgdGVzdCBzdGF0aXN0aWMgaGFzIDUgZGVncmVlcyBvZiBmcmVlZG9tLiAgVGhlIGNyaXRpY2FsIHZhbHVlIGJhc2VkIG9uIHRoZSBzaWduaWZpY2FuY2UgbGV2ZWwgb2YgMC4wNSBpcyBnaXZlbiBpbiB0aGUgZm9sbG93aW5nIGZpZ3VyZS4NCg0KYGBge3IgZWNobyA9IEZBTFNFLCAgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnODUlJ30NCmluY2x1ZGVfZ3JhcGhpY3MoIndlZWswMi9leGFtcGxlMDNDVi5wbmciKQ0KYGBgIA0KDQpUaGUgdGVzdCBzdGF0aXN0aWMgaXMgTk9UIGluIHRoZSByZWplY3Rpb24gcmVnaW9uLiBXZSBmYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGUgZGllIGlzIGZhaXIuDQoNCg0KPGZvbnQgY29sb3IgPSAiZGFya3JlZCI+ICoqRXhhbXBsZSA0KiouPC9mb250PiAgR3JhZGUgZGlzdHJpYnV0aW9uOiBBIHN0YXRpc3RpY3MgdGVhY2hlciBjbGFpbXMgdGhhdCwgb24gYXZlcmFnZSwgJDIwXCUkIG9mIGhlciBzdHVkZW50cyBnZXQgYSBncmFkZSBvZiBBLCAkMzVcJSQgZ2V0IGEgQiwgJDI1XCUkIGdldCBhIEMsICQxMFwlJCBnZXQgYSBELCBhbmQgJDEwXCUkIGdldCBhbiBGLiBUaGUgZ3JhZGVzIG9mIGEgcmFuZG9tIHNhbXBsZSBvZiAxMDAgc3R1ZGVudHMgd2VyZSByZWNvcmRlZC4gVGhlIGZvbGxvd2luZyB0YWJsZSBwcmVzZW50cyB0aGUgc2FtcGxlIGZyZXF1ZW5jaWVzIG9mIGVhY2ggZ3JhZGUuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzI1JSd9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDIvZXhhbXBsZTA0RGF0YS5wbmciKQ0KYGBgIA0KDQoNCg0KKipTb2x1dGlvbioqOiBCYXNlZCBvbiB0aGUgZ2l2ZW4gaW5mb3JtYXRpb24uICROID0gMTAwJC4gVGhlIG51bGwgaHlwb3RoZXNpcyBhbmQgdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgYXJlDQokJA0KSF8wOiBcIFwgcF9BID0gMC4yLCBwX0IgPSAwLjM1LCBwX0MgPSAwLjI1LCBwX0QgPSAwLjEsIHBfRiA9IDAuMSBcIFwgXCBcIHYucy4gSF9hOiBcIFwgVGhlIFwgY2xhaW1lZCBcIGRpc3RyaWJ1dGlvbiBcIGlzIFwgd3JvbmcuDQokJA0KVW5kZXIgdGhlIG51bGwgaHlwb3RoZXNpcywgdGhlIGV4cGVjdGVkIHRhYmxlIGlzIGdpdmVuIGJ5DQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzI1JSd9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDIvZXhhbXBsZTA0RXhwVGFibGUucG5nIikNCmBgYA0KDQpUaGUgdGVzdCBzdGF0aXN0aWMgaGFzIDQgZGVncmVlcyBvZiBmcmVlZG9tLCBhbmQgdGhlIHZhbHVlIGlzIGNhbGN1bGF0ZWQgYXMgZm9sbG93cy4NCg0KJCQNCkdeMj1cZnJhY3soMjktMjApXjJ9ezIwfStcZnJhY3soNDItMzUpXjJ9ezM1fStcZnJhY3soMjAtMjUpXjJ9ezI1fStcZnJhY3soNS0xMCleMn17MTB9K1xmcmFjeyg0LTEwKV4yfXsxMH09MTIuNTYNCiQkDQpUaGUgY3JpdGljYWwgdmFsdWUgd2l0aCBhIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAwLjA1IGlzIGdpdmVuIGJ5DQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzc1JSd9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDIvZXhhbXBsZTA0Q1YucG5nIikNCmBgYA0KDQpTaW5jZSB0aGUgdGVzdCBzdGF0aXN0aWMgaXMgaW5zaWRlIHRoZSByZWplY3Rpb24gcmVnaW9uLCB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gVGhhdCBpcywgdGhlIHNhbXBsZSBkb2VzIG5vdCBzdXBwb3J0IHRoZSBjbGFpbWVkIGdyYWRlIGRpc3RyaWJ1dGlvbiBpbiAkSF8wJC4NCg0KDQoNCioqUmVtYXJrKio6IEluIHRoZSBjaGktc3F1YXJlIGdvb2RuZXNzLW9mLWZpdCB0ZXN0LCB0aGUgY3J1Y2lhbCBzdGVwIGlzIHRvIGZpbmQgdGhlICpleHBlY3RlZCoqIGZyZXF1ZW5jeSB0YWJsZSB1bmRlciB0aGUgbnVsbCBoeXBvdGhlc2lzLg0KDQpcDQoNClRoZSBuZXh0IFlvdVR1YmUgdmlkZW8gZ2l2ZXMgYW5vdGhlciBleGFtcGxlIHdpdGggZGV0YWlsZWQgbWFudWFsIGNhbGN1bGF0aW9uLg0KDQoNClwNCg0KPGNlbnRlcj48YSBocmVmPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PTJRZURSc3hTRjlNIiB0YXJnZXQ9InBvcHVwIiANCiAgICAgICAgICAgICAgICAgICBvbmNsaWNrPSJ3aW5kb3cub3BlbignaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj0yUWVEUnN4U0Y5TScsDQogICAgICAgICAgICAgICAgICAgICAgJ25hbWUnLCd3aWR0aD04NTAsaGVpZ2h0PTUwMCcpIj48aW1nIHNyYyA9ICJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9NQVQxMjFXNS9pbWcvVmlkZW9JY29uLnBuZyIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMjAiPjwvYT4NCjwvY2VudGVyPg0KDQpcDQoNCg0KDQoNCg0KDQojIFBlcmZvcm1pbmcgR29vZG5lc3Mtb2YtZml0IFRlc3QgaW4gUg0KDQpUaGUgdHdvIHBpZWNlcyBvZiBpbmZvcm1hdGlvbiByZXF1aXJlZCBpbiB0aGUgY2hpLXNxdWFyZSBnb29kbmVzcy1vZi1maXQgdGVzdCBhcmU6IG9ic2VydmVkIGZyZXF1ZW5jeSBhbmQgdGhlIEh5cG90aGV0aWNhbCBkaXN0cmlidXRpb24gdW5kZXIgJEhfMCQuIE5leHQsIHdlIHdpbGwgdXNlIHRoZSBmb3JtdWxhcyBpbnRyb2R1Y2VkIGVhcmxpZXIgYW5kIGJ1aWx0LWluIFIgZnVuY3Rpb25zLCByZXNwZWN0aXZlbHkuIEZvciBjb252ZW5pZW5jZSwgd2UgdXNlIHRoZSBmb2xsb3dpbmcgZXhhbXBsZSB0byBpbXBsZW1lbnQgdGhlICRcY2hpXjIkIGdvb2RuZXNzLW9mLWZpdCB0ZXN0Lg0KDQoqKlRlc3RpbmcgTSZNIENvbG9yIERpc3RyaWJ1dGlvbioqOiBBIGNvbXBhbnkgY2xhaW1zIHRoZWlyIE0mTXMgYXJlIGRpc3RyaWJ1dGVkIHdpdGggdGhlc2UgcHJvcG9ydGlvbnM6DQoNCkJyb3duIC0gMzAlOyBZZWxsb3cgLSAyMCU7IFJlZCAtIDIwJTsgQmx1ZSAtIDEwJTsgT3JhbmdlIC0gMTAlOyBHcmVlbiAtIDEwJQ0KDQpBIHJhbmRvbSBzYW1wbGUgb2YgMjAwIE0mTXMgd2FzIHRha2VuIGFuZCBvYnNlcnZlZDoNCg0KQnJvd24gLSA1MjsgWWVsbG93IC0gNDg7IFJlZCAtIDM4OyBCbHVlIC0gMjI7IE9yYW5nZSAtIDIwOyBHcmVlbiAtIDIwDQoNClRoZSBudWxsIGFuZCBhbHRlcm5hdGl2ZSBoeXBvdGhlc2VzIGFyZToNCg0KJCQNCkhfMDogcF8xID0gMC4zLCBcIFwgcF8yID0gMC4yLCBcIFwgcF8zID0gMC4yLCBcIFwgcF80ID0gMC4xLCBcIFwgcF81ID0gMC4xLCBcIFwgcF82ID0gMC4xIA0KJCQNCg0Kdi5zLg0KDQokJA0KXHRleHR7YXQgbGVhc3QgIG9uZSAgb2YgIHRoZSAgaHlwb3RoZXRpY2FsICBwcm9iYWJpbGl0aWVzICBpcyAgbm90ICB0cnVlLn0NCiQkDQoNCjxmb250IGNvbG9yID0gInJlZCI+KipcY29sb3J7cmVkfVJlbWFyayoqOjwvZm9udD4gPGZvbnQgY29sb3IgPSAiYmx1ZSI+IEluIGdlbmVyYWwsICRcY2hpXjIkIHRlc3RzIGFyZSBhbGwgcmlnaHQtdGFpbGVkLiBUaGlzIG1lYW5zIHRoYXQgdGhlIGNyaXRpY2FsIHZhbHVlIGlzIG9uIHRoZSByaWdodCB0YWlsIG9mIHRoZSBjaGktc3F1YXJlIGRlbnNpdHkgY3VydmUsIGFuZCB0aGUgcC12YWx1ZSBpcyBkZWZpbmVkIGFzIHRoZSB0YWlsIGFyZWEgdG8gdGhlIHJpZ2h0IG9mIHRoZSB0ZXN0IHN0YXRpc3RpYy4gPC9mb250Pg0KDQoNCg0KKipEZWZpbmUgUiBEYXRhKio6DQoNCmBgYHtyIGVjaG8gPSBUUlVFfQ0Kb2JzZXJ2ZWQgPC0gYyg1MiwgNDgsIDM4LCAyMiwgMjAsIDIwKQ0KZXhwZWN0ZWQucHJvcHMgPC0gYygwLjMwLCAwLjIwLCAwLjIwLCAwLjEwLCAwLjEwLCAwLjEwKQ0KYGBgDQoNCg0KIyMgRm9ybXVsYSBBcHByb29hY2gNCg0KUmVjYWxsIHRoYXQgdGhlICRcY2hpXjIkIHRlc3Qgc3RhdGlzdGljIGlzIGdpdmVuIGJ5DQoNCiQkDQpHXjIgPSBcZnJhY3soT18xLUVfMSleMn17RV8xfSArIFxmcmFjeyhPXzItRV8yKV4yfXtFXzJ9ICsgXGNkb3RzICsgXGZyYWN7KE9fay1FX2spXjJ9e0Vfa30gXHRvIFxjaGlfe2stMX1eMi4NCiQkDQpUbyBldmFsdWF0ZSB0aGUgdGVzdCBzdGF0aXN0aWMgJEdeMiQsIHdlIG5lZWQgdG8gZmluZCB0aGUgZXhwZWN0ZWQgbnVtYmVyIG9mIGNvbG9ycyBiYXNlZCBvbiB0aGUgZGF0YSBkZWZpbmVkIGVhcmxpZXIuDQoNCmBgYHtyIGVjaG8gPSBUUlVFfQ0KIyBvYnNlcnZlZCBhbmQgZXhwZWN0ZWQucHJvcHMgd2VyZSBkZWZpbmVkIGVhcmxpZXINCiMgdG90YWwgY291bnQNCnRvdCA8LSBzdW0ob2JzZXJ2ZWQpIA0KZXhwZWN0ZWQuY291bnRzIDwtIHRvdCAqIGV4cGVjdGVkLnByb3BzICAgIyB0aGlzIGdpdmVzICg1MngwLjMwLCA0OHgwLjIsIDM4eDAuMiwgLi4uLikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhbmQgcmV0dXJucyBhIHZlY3RvciBvZiBvYnNlcnZlZCBmcmVxdWVuY2llcw0KIyMgdGVzdCBzdGF0aXN0aWNzDQpHLnNxIDwtIHN1bSAoKG9ic2VydmVkIC0gZXhwZWN0ZWQuY291bnRzKV4yL2V4cGVjdGVkLmNvdW50cykgICMgc3VtKCkgc3VtIG9mIHJlc3VsdGluZyBjb21wb25lbnRzDQojIyBkZWdyZWVzIG9mIGZyZWVkb20NCmRmIDwtIGxlbmd0aChvYnNlcnZlZCkgLSAxICAgICMgbGVuZ3RoKCkgY291bnRzIHRoZSBudW1iZXIgb2YgY2VsbHMgaW4gdGhlIHZlY3Rvcg0KIyMgYWxsIGNoaS5zcSB0ZXN0IGFyZSByaWdodC10YWlsZWQsIHVzaW5nIGBsb3dlci50YWlsID0gRkFMU0VgICB0byByZXR1cm4gdGhlIHVwcGVyIHRhaWwgYXJlYS4NCnAudmFsdWUgPC0gcGNoaXNxKEcuc3EsIGRmID1kZiwgbG93ZXIudGFpbCA9IEZBTFNFKSAgICMgDQojIyBjb21iaW5lIEcuc3EgYW5kIHAtdmFsdWUgdXNpbmcgY2JpbmQoKQ0KY2JpbmQoRy5zcSA9IEcuc3EsIHAudmFsdWUgPSBwLnZhbHVlKQ0KYGBgDQoNClNpbmNlIHRoZSBwLXZhbHVlIGlzIGdyZWF0ZXIgdGhhbiAwLjA1LCB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzICoqbm90KiogcmVqZWN0ZWQuIFRoYXQgaXMsIHRoZSBvYnNlcnZlZCBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIGlzICoqbm90Kiogc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB0aGUgaHlwb3RoZXRpY2FsIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbi4NCg0KDQojIyBCdWlsdC1pbiBGdW5jdGlvbiBBcHByb2FjaA0KDQpUaGUgcGFja2FnZSBge3N0YXRzfWAgY29taW5nIHdpdGggYmFzZSBSIGhhcyBhIGZ1bmN0aW9uIGBjaGlzcS50ZXN0KClgIHRvIHBlcmZvcm0gdGhlIGNoaS1zcXVhcmUgdGVzdC4gVGhlIGZvbGxvd2luZyBzaW5nbGUgbGluZSBvZiBjb2RlIHJldHVybnMgdGhlIHJlc3VsdHMgb2YgdGhlICRcY2hpXjIkIHRlc3QuDQoNCg0KYGBge3J9DQojIyBDQVVUSU9OOiB0aGUgc2Vjb25kIGFyZ3VtZW50IG11c3QgYmUgaW4gdGhlIGZvcm0gb2Y6IHAgPSBoeXBvdGhldGljYWwgcHJvYmFiaWxpdGllcyENCiMjICAgICAgICAgIHdoZW4gcGVyZm9ybWluZyBnb29kbmVzcy1vZi1maXQgdGVzdHMuIE9USEVSV0lTRSwgUiB3aWxsIHBlcmZvcm0gaW5kZXBlbmRlbmNlIHRlc3RzLg0KY2hpc3EudGVzdChvYnNlcnZlZCwgcCA9IGV4cGVjdGVkLnByb3BzKQ0KYGBgDQoNClwNCg0KIyBQcmFjdGljZSBFeGVyY2lzZXMNCg0KKipDb2xsZWdlIFNwb3J0cyoqOiBBIFVuaXZlcnNpdHkgY29uZHVjdGVkIGEgc3VydmV5IG9mIGl0cyByZWNlbnQgZ3JhZHVhdGVzIHRvIGNvbGxlY3QgZGVtb2dyYXBoaWMgYW5kIGhlYWx0aCBpbmZvcm1hdGlvbiBmb3IgZnV0dXJlIHBsYW5uaW5nIHB1cnBvc2VzIGFzIHdlbGwgYXMgdG8gYXNzZXNzIHN0dWRlbnRzJyBzYXRpc2ZhY3Rpb24gd2l0aCB0aGVpciB1bmRlcmdyYWR1YXRlIGV4cGVyaWVuY2VzLiBUaGUgc3VydmV5IHJldmVhbGVkIHRoYXQgYSBzdWJzdGFudGlhbCBwcm9wb3J0aW9uIG9mIHN0dWRlbnRzIHdlcmUgbm90IGVuZ2FnaW5nIGluIHJlZ3VsYXIgZXhlcmNpc2UsIG1hbnkgZmVsdCB0aGVpciBudXRyaXRpb24gd2FzIHBvb3IsIGFuZCBhIHN1YnN0YW50aWFsIG51bWJlciB3ZXJlIHNtb2tpbmcuIEluIHJlc3BvbnNlIHRvIGEgcXVlc3Rpb24gb24gcmVndWxhciBleGVyY2lzZSwgNjAlIG9mIGFsbCBncmFkdWF0ZXMgcmVwb3J0ZWQgZ2V0dGluZyBubyByZWd1bGFyIGV4ZXJjaXNlLCAyNSUgcmVwb3J0ZWQgZXhlcmNpc2luZyBzcG9yYWRpY2FsbHksIGFuZCAxNSUgcmVwb3J0ZWQgZXhlcmNpc2luZyByZWd1bGFybHkgYXMgdW5kZXJncmFkdWF0ZXMuIFRoZSBuZXh0IHllYXIsIHRoZSBVbml2ZXJzaXR5IGxhdW5jaGVkIGEgaGVhbHRoIHByb21vdGlvbiBjYW1wYWlnbiBvbiBjYW1wdXMgaW4gYW4gYXR0ZW1wdCB0byBpbmNyZWFzZSBoZWFsdGggYmVoYXZpb3JzIGFtb25nIHVuZGVyZ3JhZHVhdGVzLiBUaGUgcHJvZ3JhbSBpbmNsdWRlZCBtb2R1bGVzIG9uIGV4ZXJjaXNlLCBudXRyaXRpb24sIGFuZCBzbW9raW5nIGNlc3NhdGlvbi4gVG8gZXZhbHVhdGUgdGhlIGltcGFjdCBvZiB0aGUgcHJvZ3JhbSwgdGhlIFVuaXZlcnNpdHkgYWdhaW4gc3VydmV5ZWQgZ3JhZHVhdGVzIGFuZCBhc2tlZCB0aGUgc2FtZSBxdWVzdGlvbnMuIFRoZSBzdXJ2ZXkgd2FzIGNvbXBsZXRlZCBieSA0NzAgZ3JhZHVhdGVzLCBhbmQgdGhlIGZvbGxvd2luZyBkYXRhIHdlcmUgY29sbGVjdGVkIG9uIHRoZSBleGVyY2lzZSBxdWVzdGlvbjoNCg0KYGBge3IgZWNobyA9IEZBTFNFLCAgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnNzUlJ30NCmluY2x1ZGVfZ3JhcGhpY3MoIndlZWswMi9wcmFjdGljZUV4MDFEYXRhLnBuZyIpDQpgYGANCg0KV2Ugc3BlY2lmaWNhbGx5IHdhbnQgdG8gY29tcGFyZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHJlc3BvbnNlcyBpbiB0aGUgc2FtcGxlIHRvIHRoZSBkaXN0cmlidXRpb24gcmVwb3J0ZWQgdGhlIHByZXZpb3VzIHllYXIgKGkuZS4sIDYwJSwgMjUlLCAxNSUgcmVwb3J0aW5nIG5vLCBzcG9yYWRpYywgYW5kIHJlZ3VsYXIgZXhlcmNpc2UsIHJlc3BlY3RpdmVseSkuIFdoZXRoZXIgdGhlIGRhdGEgc3VwcG9ydHMgdGhlIGFib3ZlIGRpc3RyaWJ1dGlvbiBhdCBhIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAwLjA1LiAgDQoNCg0KDQoNCg0K