1 Introduction

Experimental design is a fundamental aspect of statistical analysis, allowing researchers to systematically investigate the effects of different treatments on a response variable. In CRD, experimental units are randomly assigned to different treatment groups.

In this note, we will explore how Classical Analysis of Variance (ANOVA) and Regression Analysis can be used to analyze data from a CRD. We will also illustrate these methods using some numerical examples. For

Working Data in Plant Physiology

Our example data are from an experiment in plant physiology, published by Sokal and Rohlf (1995). The lengths of pea sections (the dependent, or response, variable) grown in a tissue culture were recorded. The purpose of the experiment was to test the effects of various sugar media (the independent, or explanatory, variable) on mean pea section length. A balanced CRD was used with 10 replicates per treatment level.

The data are given in the table below:

The wide-format table is easy to use when performing manual calculations. Most of the software programs use long-format data tables. We will reshape this wide table when using the R program for various analyses.

2 Objective and Logic of Analyzing CRD Data

Before moving to data analysis, we first discuss the objective, logic, and methods for analyzing CRD data. The

2.1 The objective and Logic

The core goals when analyzing Completely Randomized Design (CRD) data are threefold:

  • Treatment Effect Detection - Determine if different treatments produce statistically significant differences in the response variable. For example, do fertilizers A, B, and C result in different crop yields?

  • Effect Size Quantification - Measure the magnitude of treatment differences. For example, Fertilizer C increases yield by 13 bushels/acre compared to Fertilizer A

  • Ranking/Comparison of Treatments Identify which treatments perform best/worst. This involves multiple comparisons among means across treatments. For example, we can order fertilizers by yield: A > B > A through multiple comparisons.

Statistically, treatment Effect Detection in CRD with \(k\) treatments can be achieved by testing a hypothesis.

\[ H_0: \mu_1 = \mu_2 = \cdots = \mu_k \ \ \text{vs} \ \ H_a: \ \text{at least one mean differs} \]

If \(H_0\) is rejected, we quantify the size of treatment effects and rank the treatment effects across the treatments in the CRD. There are different approaches to testing the above hypothesis

2.2 Measuring Discrepancy between \(H_0\) and \(H_a\)

Let’s use the following balanced CRD data table and related notations.

The three different errors defined above have the following relationship.

\[ (y_{ij} - \bar{y}_{\cdot\cdot}) = (y_{ij} - \bar{y}_{i\cdot}) + (\bar{y}_{i\cdot} - \bar{y}_{\cdot\cdot}) \]

The above expression simply means that we can decompose the overall residual (\(y_{ij} - \bar{y}_{\cdot\cdot}\)) into within treatment error (\((y_{ij} - \bar{y}_{i\cdot})\), also called within residual error) and between treatment error (\(\bar{y}_{i\cdot} - \bar{y}_{\cdot\cdot}\)). Since an error could be positive or negative. Similar to the definition of variance, we square all these errors to obtain squared errors.

After some tedous algebra (i.e., not straightforward at all!), we have the following equation

\[ \sum_{i=1}^t\sum_{j=1}^{n_i}(y_{ij} - \bar{y}_{\cdot\cdot})^2= \sum_{i=1}^t\sum_{j=1}^{n_i}(y_{ij} - \bar{y}_{i\cdot})^2 + \sum_{i=1}^t\sum_{j=1}^{n_i}(\bar{y}_{i\cdot} - \bar{y}_{\cdot\cdot})^2 \]

The last term in the above equation has no subscript \(j\); we simplify the last term to get the following equation.

\[ \underbrace{\sum_{i=1}^t\sum_{j=1}^{n_i}(y_{ij} - \bar{y}_{\cdot\cdot})^2}_{SS_T} =\underbrace{ \sum_{i=1}^t\sum_{j=1}^{n_i}(y_{ij} - \bar{y}_{i\cdot})^2}_{SS_W} + \underbrace{\sum_{i=1}^t n_i(\bar{y}_{i\cdot} - \bar{y}_{\cdot\cdot})^2}_{SS_B} \] where \(SS_T\) = Total Sum of Squared Residuals, \(SS_W\) = Sum of Squared Errors within treatments and \(SS_B\) = Sum of Squared Errors between treatments.

Recall the definition of sample variance

\[ s^2 = \frac{(x_1-\bar{x})^2 +(x_2-\bar{x})^2 + \cdots _ (x_n-\bar{x})^2}{n-1} = \frac{\sum_{i=1}^n (x_i-\bar{x})^2}{n-1}, \]

Which is average squared deviation (also called mean squared deviation MSD or mean squared error, MSE)! The denominator \(n -1\) in the above definition reflects the degrees of freedom - meaning that number of independent observations (\(n\)) minus one constratint (\(\bar{x} = \sum_{i=1}^n x_i/n\), each equation based on the \(n\) independent observatiob is considered as a contraint!).

Let’s look at \(SS_B\): There are \(t\) independent means (one for each treatment) \(\{\bar{y}_{1\cdot}, \bar{y}_{2\cdot}, \bar{y}_{3\cdot}, \cdots, \bar{y}_{t\cdot} \}\), the grand total \(\bar{y}_{\cdot\cdot}\) is consider a constraint. Therefore, there are $ t-1$ degrees of freedom associated with \(SS_B\). Therefore, the mean squared error of the between errors is defined by

\[ MS_B = \frac{SS_B}{t-1} \]

Similarly, in \(SS_W\), there \(n_T\) independent observations \(y_{ij}\) and \(t\) constraints \(\{\bar{y}_{1\cdot}, \bar{y}_{2\cdot}, \bar{y}_{3\cdot}, \cdots, \bar{y}_{t\cdot} \}\) (Yes! since each of them is the mean of observations within each treatment). Therefore, the degrees of freedom in \(SS_W\) is \(n_T-t\), Therefore, the mean square error of within errors is defined by

\[ MS_W = \frac{SS_W}{n_T - t}. \]

Remarks:

  • \(MS_B\) is the estimated sample variance of the sample means of individual treatments.

  • \(MS_W\) is the weighted average of the variances of each individual treatment.

Here is the logic for how to define a measure to assess the discrepancy between \(H_0\) and \(H_a\):

If there is no real difference between treatments (i.e., \(H_0\) is true), \(MS_B\) and \(MS_W\) both estimate the same underlying variance. Therefore \(MS_B \approx MS_W\)!


We can construct the test statistic based on \(MS_B\) and \(MSE_B\) under \(H_0\). Mathematically, both \(MS_B-MS_W\) (\(\approx 0\)) and \(MS_B/MS_W\) (\(\approx 1\)) are valid measures to assess the discepancy between \(H_0\) and \(H_a\). Since both quantities are random (since they are evaluated based on the random sample), we need to choose the one with a known probability distribution. The ratio expression \(MS_B/MS_W\) has a well-known distribution - F distribution!


2.3 Basics of F Distribution

We have discussed several distributions to characterize test statistics for the z-test, t-test, and chi-square test. One of the essential tools in hypothesis testing involving the comparison of variances (the case we introduced above) is the F-distribution. This subsection outlines the basics of the F-distribution and demonstrates how to use R to compute critical values and p-values associated with F-tests.

The F-distribution is a continuous probability distribution used for the comparison of two sample variances (such as \(SS_B\) and \(SS_W\)) and regression analysis (will discuss this later). Using the above quantities, we have

\[ F = \frac{SS_W/(n_T-t)}{SS_B/(t-1)} \rightarrow F_{n_T-t, \ t-1} \]

\(n_T-t\) is the degrees of freedom of the numerator and \(t-1\) is the degrees of the denominator. We can also flip the ratio to get another valid test statistic

\[ F^\prime = \frac{SS_B/(t-1)}{SS_W/(n_T-t)} \rightarrow F_{\ t-1, n_T-t} \]

Caution: the degrees of freedom in the subscript MUST be adjusted so that the first index is the degrees of freedom of the numerator and the second subscript represents the degrees of freedom of the denominator. This means \(F_{7,5}\) and \(F_{5, 7}\) are two different F distributions!

\(F_{df_N, df_D}\) is skewed to the right. The following figure shows the density curve of an F-distribution with degrees of freedom df1 = 7 (numerator) and df2 = 10 (denominator), together with the R commands to find the critical and p-values.

The syntax of the two R functions used to find the p-value and critical value is annotated in the following figure.

Most introductory statistics textbooks include an F table based on a few commonly used significance levels \(\alpha\). For example, the critical value of \(F_{7, 10}\) at \(\alpha = 0.05\) labeled in the left panel of the density curve of \(F_{7, 10}\) can also be found from the following F table

The F tables are constructed based on a few significance levels. It is not to use use F table to find p-values.

Next, we open a standalone section to formally introduce the one-way ANOVA for CRD data.


3 One-Way ANOVA and Implementation

We have discussed the logic and valid measures for assessing the discrepancy between \(H_0\) and \(H_a\). Next, we summarize the above results in a classical one-way ANOVA table and test the following null hypothesis based on the CRD.

\[ H_0: \mu_1 = \mu_2 = \cdots = \mu_t \ \ \text{vs} \ \ H_a: \text{at least one mean differs} \]

The test statistic and corresponding p-value are summarized in the following ANOVA table.

Source DF SS MS F-Value P-Value
Between \(t-1\) \(SS_B\) \(MS_B=SS_B/(t-1)\) \(MS_W/MS_B\)
Within \(n_T - t\) \(SS_W\) \(MS_W = SS_W/(n_T-t)\)
Total \(n_T-`\) \(SS_T\)

Decision Rule: If the p-value in the above table is less than the significance level \(\alpha\), we reject the null hypothesis; otherwise, we conclude the null hypothesis.

Next, we use the plant physiology data to demonstrate to to construct the above ANOVA table and use R as a calculator to find \(SS\) and \(MS\) and related quantities in the ANOVA table. The following code loads the data into R in the same format (i.e., wide table format)

# Create the data vectors
Control <- c(75, 67, 70, 75, 65, 71, 67, 67, 76, 68)     # Control
Glucose <- c(57, 58, 59, 59, 62, 60, 60, 57, 59, 61)     # Glucose
Fructose <- c(58, 61, 56, 58, 57, 56, 58, 60, 57, 58)     # Fructose
GlucFruc <- c(58, 59, 58, 61, 57, 56, 58, 57, 57, 59)     # GlucFruc
Sucrose <- c(62, 66, 65, 63, 64, 62, 65, 65, 62, 67)     # Sucrose
## using cbind() to display the data
cbind(Control, Glucose, Fructose, GlucFruc, Sucrose)
|       Control Glucose Fructose GlucFruc Sucrose
|  [1,]      75      57       58       58      62
|  [2,]      67      58       61       59      66
|  [3,]      70      59       56       58      65
|  [4,]      75      59       58       61      63
|  [5,]      65      62       57       57      64
|  [6,]      71      60       56       56      62
|  [7,]      67      60       58       58      65
|  [8,]      67      57       60       57      65
|  [9,]      76      59       57       57      62
| [10,]      68      61       58       59      67
#colnames(wide.table) <- c("Control", "Glucose", "Fructose", "GlucFruc", "Sucrose")

The next code chunk calculates different quantities in the ANOVA table. I will make comments in the code to show detailed steps. The primary R commands are sum(), mean(), and related R functions of the F-distribution.

## degrees of freedom
t = 5
n.T = 10*5
dfN = t - 1
dfD = n.T - t
ybar.. = mean(c(Control, Glucose, Fructose, GlucFruc, Sucrose))
## Sum of squares
SS.B = 10*sum(c((mean(Control)-ybar..)^2, (mean(Glucose)-ybar..)^2, (mean(Fructose)-ybar..)^2, (mean(GlucFruc)-ybar..)^2, (mean(Sucrose)-ybar..)))
SS.W = sum(c(sum((Control-mean(Control))^2), sum((Glucose-mean(Glucose))^2), sum((Fructose-mean(Fructose))^2), sum((GlucFruc-mean(GlucFruc))^2), sum((Sucrose-mean(Sucrose))^2)))
SS.T = sum((c(Control, Glucose, Fructose, GlucFruc, Sucrose) - ybar..)^2)
## MS
MS.B = SS.B/dfN
MS.W = SS.W/dfD
## F value
F.value = MS.B/MS.W
p.val = pf(F.value, dfN, dfD, lower.tail = FALSE)
anova.out <- data.frame(
  DF = c(dfN, dfD),
  SS = c(SS.B, SS.W),
  MS = c(MS.B, MS.W),
  F.value = c(F.value, NA),
  p.value = c(p.val, NA)
)
rownames(anova.out)=c("Between", "Within")
print(anova.out, na.print = "")
|         DF       SS         MS  F.value      p.value
| Between  4 1077.944 269.486000 51.31981 3.324636e-16
| Within  45  236.300   5.251111       NA           NA

Conclusion: The p-value is approximately 0. We reject the null hypothesis that all means are equal. In other words, the mean pea section length is affected by various sugar media.


The second part of the following YouTube video (after 15 Minutes, https://www.youtube.com/watch?v=KJ5G2KjcXcA) discussed in the next note on One-way ANOVA.



4 ANOVA with R Function aov()

We still use plant physiology data to illustrate one-way ANOVA analysis using aov(). Since aov() requires a long table structure. That is, all measurements of the response must be stored in a column and a standalone column to label the treatment of each value in the measurement column. The following code creates a long table.

# Create the data vectors
lengths <- c(
  75, 67, 70, 75, 65, 71, 67, 67, 76, 68,     # Control
  57, 58, 59, 59, 62, 60, 60, 57, 59, 61,     # Glucose
  58, 61, 56, 58, 57, 56, 58, 60, 57, 58,     # Fructose
  58, 59, 58, 61, 57, 56, 58, 57, 57, 59,     # GlucFruc
  62, 66, 65, 63, 64, 62, 65, 65, 62, 67      # Sucrose
)

# Create the treatment factor
treatment <- rep(c("Control", "Glucose", "Fructose", "GlucFruc", "Sucrose"), each = 10)

# Combine into a data frame
pea.long <- data.frame(
  Length = lengths,
  Treatment = factor(treatment, levels = c("Control", "Glucose", "Fructose", "GlucFruc", "Sucrose"))
)

# View the first 20 rows to make sure the data structure is correct
head(pea.long, n=20)
|    Length Treatment
| 1      75   Control
| 2      67   Control
| 3      70   Control
| 4      75   Control
| 5      65   Control
| 6      71   Control
| 7      67   Control
| 8      67   Control
| 9      76   Control
| 10     68   Control
| 11     57   Glucose
| 12     58   Glucose
| 13     59   Glucose
| 14     59   Glucose
| 15     62   Glucose
| 16     60   Glucose
| 17     60   Glucose
| 18     57   Glucose
| 19     59   Glucose
| 20     61   Glucose

We next call aov() to perform ANOVA analysis.

## create an anova model object 
aov.model <- aov(Length ~ Treatment, data = pea.long)
## create the classical ANOVA table
anova(aov.model)
| Analysis of Variance Table
| 
| Response: Length
|           Df Sum Sq Mean Sq F value    Pr(>F)    
| Treatment  4 1105.7 276.430  52.642 < 2.2e-16 ***
| Residuals 45  236.3   5.251                      
| ---
| Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## or alternatively, you can simply use summary(aov.model) to produce the same results!

The annotated output is given by

Conclusion: Since the p-value is approximately 0, the null hypothesis is rejected. That is, the various sugar media (the independent, or explanatory, variable) significantly affect the mean pea section length.


The following YouTube video ( https://www.youtube.com/watch?v=IkR3Rzrgiv4) gives another example of using the R function aov(). The video also uses some graphical functions to create some visualizations. We did not discuss visualizations in this class, but we will cover more visualizations in subsequent statistics courses.



5 Multiple Comparisons

When analyzing variance (ANOVA), a significant F-test (i.e., p-value is less than the given significance level \(\alpha\)) indicates that at least one group mean differs from the others. However, ANOVA does not specify which pairs of groups are significantly different. Post-hoc tests, also known as multiple comparison tests, are used to identify these specific differences while controlling for the increased risk of Type I errors (false positives) that arise from performing multiple comparisons.

There are different Post-hoc tests. We only introduce two commonly used post-hoc methods using R built-in functions:

  • Tukey’s Honest Significant Difference (HSD) -Controls family-wise error rate (FWER) for all pairwise comparisons.

  • Bonferroni Correction - Adjusts p-values by multiplying them by the number of comparisons

6 Visual Comparison

We have learned different graphical summaries of data. Box-plot is a geometric representation of the 5-number-summary of a numerical variable. Since treatment variable has multiple categories, we can create a back-to-back box-plot to visualize the different in the distributions.

The R function boxplot() can draw multiple boxplots of a numerical variable according the categories of the group variable. Since package {graphics} comes with the base R, installation and loading the package is unnecessary.

boxplot(Length ~ Treatment, data = pea.long)

The above box-plots clearly show that the pea lengths using sugar media Fructose, Glucose, and GlucFruc are similar to each other.

6.1 Tukey’s Honest Significant Difference (HSD)

Tukey’s Honest Significant Difference (HSD) is a post-hoc test used after a statistically significant ANOVA to determine which specific group means differ from each other. Unlike multiple t-tests, which inflate the Type I error rate, Tukey’s HSD adjusts for multiple comparisons, maintaining the family-wise error rate (FWER) at the desired level (e.g., 0.05).

Next, we perform a multiple comparison of pea length across different sugar media using the plant physiology data. For convenience, we use the long-format data frame defined earlier and an anova object in the following R code.

## refit the ANOVA model
aov.model <- aov(Length ~ Treatment, data = pea.long)
## multiple comparison
tukey.comp <- TukeyHSD(aov.model)
print(tukey.comp)
|   Tukey multiple comparisons of means
|     95% family-wise confidence level
| 
| Fit: aov(formula = Length ~ Treatment, data = pea.long)
| 
| $Treatment
|                    diff        lwr       upr     p adj
| Glucose-Control   -10.9 -13.811928 -7.988072 0.0000000
| Fructose-Control  -12.2 -15.111928 -9.288072 0.0000000
| GlucFruc-Control  -12.1 -15.011928 -9.188072 0.0000000
| Sucrose-Control    -6.0  -8.911928 -3.088072 0.0000050
| Fructose-Glucose   -1.3  -4.211928  1.611928 0.7114379
| GlucFruc-Glucose   -1.2  -4.111928  1.711928 0.7676225
| Sucrose-Glucose     4.9   1.988072  7.811928 0.0001778
| GlucFruc-Fructose   0.1  -2.811928  3.011928 0.9999786
| Sucrose-Fructose    6.2   3.288072  9.111928 0.0000026
| Sucrose-GlucFruc    6.1   3.188072  9.011928 0.0000036

The results indicate that there is no significant difference in pairs Fructose-Glucose, GlucFruc-Glucose, and GlucFruc-Fructose.

par(mai=c(1.5,2,1,1)) # Makes room on the plot for the group names
plot(tukey.comp,      # name of the TukeyHSD() object
     cex.lab = 0.6,   # adjust the font size of the labels of the vertical axis
     las = 1)         # orientation of the labels

6.2 Bonferroni Comparison

The Bonferroni correction is a conservative method for adjusting significance levels when performing multiple comparisons to reduce the risk of Type I errors (false positives). It is one of the simplest and most widely used approaches for controlling the family-wise error rate.

The R function pairwise.t.test() performs pairwise comparison. It requires inputting individual variables (response and treatment group). The following is code for the Bonferroni procedure.

Bonfeeroni.result <- pairwise.t.test(
  x = pea.long$Length, 
  g = pea.long$Treatment,
  p.adjust.method = "bonferroni"
)
print(Bonfeeroni.result)
| 
|   Pairwise comparisons using t tests with pooled SD 
| 
| data:  pea.long$Length and pea.long$Treatment 
| 
|          Control Glucose Fructose GlucFruc
| Glucose  7.3e-13 -       -        -       
| Fructose 1.7e-14 1.00000 -        -       
| GlucFruc 2.2e-14 1.00000 1.00000  -       
| Sucrose  5.1e-06 0.00019 2.6e-06  3.7e-06 
| 
| P value adjustment method: bonferroni

Using the p-value adjusted Bonferroni procedure, three pairs of treatment groups are significantly different: Fructose-Glucose, GlucFruc-Glucose, and GlucFruc-Fructose. This result is consistent with Tukeu’s HSD method.


Before conclude this section, we recommend a YouTube video (https://www.youtube.com/watch?v=hPUvqtmCu7Q) with an example one multiple comparison among group means using R,



7 Concluding Remarks

One-Way ANOVA (Analysis of Variance) is a statistical method used to compare the means of three or more independent groups to determine if at least one group mean is significantly different from the others. It extends the t-test (which compares only two groups) to multiple groups.

Hypotheses

  • Null Hypothesis (\(H_0\)): All group means are equal(\(\mu_1 = \mu_2 = \cdots = \mu_k\)).

  • Alternative Hypothesis (\(H_a\)): At least one group mean is different.

The fundamental assumptions of One-Way ANOVA include:

  • Independence: Observations must be independent (e.g., random sampling).

  • Normality: Data in each group should be approximately normally distributed (checked via Q-Q plots or Shapiro-Wilk test).

  • Homogeneity of Variance (Homoscedasticity): Groups should have equal variances (tested using Levene’s test or Bartlett’s test).

If any of theses assumptions are violated, the classical ANOVA results will be invalid. There some alternatives of the classic ANOVA that will be covered in the subsequent related courses. The key information in the ANOVA analysis is summarized in the following one-way ANOVA table.

If ANOVA rejects the null hypotheis, post-hoc tests identify which specific groups differ. We introduced two prcedures for this purpose.

  • Tukey’s HSD (controls family-wise error rate).

  • Bonferroni Correction (conservative adjustment).

LS0tDQp0aXRsZTogIkFuYWx5c2lzIG9mIFZhcmlhbmNlIGZvciBDb21wbGV0ZWx5IFJhbmRvbWl6ZWQgRGVzaWduIg0KYXV0aG9yOiAiQ2hlbmcgUGVuZyINCmRhdGU6ICJTVEEyMDAgU3RhdGlzdGljcyBJSSAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIHRoZW1lOiBsdW1lbg0KICBwZGZfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiA1DQogICAgZmlnX2hlaWdodDogNA0KLS0tDQoNCmBgYHs9aHRtbH0NCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KZGl2I1RPQyBsaSB7DQogICAgbGlzdC1zdHlsZTpub25lOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCmgxLnRpdGxlIHsNCiAgZm9udC1zaXplOiAyNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMiB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQo8L3N0eWxlPg0KYGBgDQoNCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQojIGtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gIkM6L1VzZXJzLzc1Q1BFTkcvT25lRHJpdmUgLSBXZXN0IENoZXN0ZXIgVW5pdmVyc2l0eSBvZiBQQS9Eb2N1bWVudHMiKQ0KIyBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICJDOlxcU1RBNDkwXFx3MDUiKQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gInwiKQ0KYGBgDQoNCg0KDQpcDQoNCg0KIyBJbnRyb2R1Y3Rpb24NCg0KRXhwZXJpbWVudGFsIGRlc2lnbiBpcyBhIGZ1bmRhbWVudGFsIGFzcGVjdCBvZiBzdGF0aXN0aWNhbCBhbmFseXNpcywgYWxsb3dpbmcgcmVzZWFyY2hlcnMgdG8gc3lzdGVtYXRpY2FsbHkgaW52ZXN0aWdhdGUgdGhlIGVmZmVjdHMgb2YgZGlmZmVyZW50IHRyZWF0bWVudHMgb24gYSByZXNwb25zZSB2YXJpYWJsZS4gSW4gQ1JELCBleHBlcmltZW50YWwgdW5pdHMgYXJlIHJhbmRvbWx5IGFzc2lnbmVkIHRvIGRpZmZlcmVudCB0cmVhdG1lbnQgZ3JvdXBzLg0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjcwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDQvQ1JELnBuZyIpDQpgYGANCg0KSW4gdGhpcyBub3RlLCB3ZSB3aWxsIGV4cGxvcmUgaG93IENsYXNzaWNhbCBBbmFseXNpcyBvZiBWYXJpYW5jZSAoQU5PVkEpIGFuZCBSZWdyZXNzaW9uIEFuYWx5c2lzIGNhbiBiZSB1c2VkIHRvIGFuYWx5emUgZGF0YSBmcm9tIGEgQ1JELiBXZSB3aWxsIGFsc28gaWxsdXN0cmF0ZSB0aGVzZSBtZXRob2RzIHVzaW5nIHNvbWUgbnVtZXJpY2FsIGV4YW1wbGVzLiBGb3INCg0KDQoqKldvcmtpbmcgRGF0YSBpbiBQbGFudCBQaHlzaW9sb2d5KioNCg0KT3VyIGV4YW1wbGUgZGF0YSBhcmUgZnJvbSBhbiBleHBlcmltZW50IGluIHBsYW50IHBoeXNpb2xvZ3ksIHB1Ymxpc2hlZCBieSBTb2thbCBhbmQgUm9obGYgKDE5OTUpLiBUaGUgbGVuZ3RocyBvZiBwZWEgc2VjdGlvbnMgKHRoZSBkZXBlbmRlbnQsIG9yIHJlc3BvbnNlLCB2YXJpYWJsZSkgZ3Jvd24gaW4gYSB0aXNzdWUgY3VsdHVyZSB3ZXJlIHJlY29yZGVkLiBUaGUgcHVycG9zZSBvZiB0aGUgZXhwZXJpbWVudCB3YXMgdG8gdGVzdCB0aGUgZWZmZWN0cyBvZiB2YXJpb3VzIHN1Z2FyIG1lZGlhICh0aGUgaW5kZXBlbmRlbnQsIG9yIGV4cGxhbmF0b3J5LCB2YXJpYWJsZSkgb24gbWVhbiBwZWEgc2VjdGlvbiBsZW5ndGguIEEgKipiYWxhbmNlZCBDUkQqKiB3YXMgdXNlZCB3aXRoIDEwIHJlcGxpY2F0ZXMgcGVyIHRyZWF0bWVudCBsZXZlbC4NCg0KVGhlIGRhdGEgYXJlIGdpdmVuIGluIHRoZSB0YWJsZSBiZWxvdzoNCg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI3MCUifQ0KaW5jbHVkZV9ncmFwaGljcygid2VlazA0L0FOT1ZBLUV4YW1wbGVEYXRhLnBuZyIpDQpgYGANCg0KDQoNClRoZSB3aWRlLWZvcm1hdCB0YWJsZSBpcyBlYXN5IHRvIHVzZSB3aGVuIHBlcmZvcm1pbmcgbWFudWFsIGNhbGN1bGF0aW9ucy4gTW9zdCBvZiB0aGUgc29mdHdhcmUgcHJvZ3JhbXMgdXNlIGxvbmctZm9ybWF0IGRhdGEgdGFibGVzLiBXZSB3aWxsIHJlc2hhcGUgdGhpcyB3aWRlIHRhYmxlIHdoZW4gdXNpbmcgdGhlIFIgcHJvZ3JhbSBmb3IgdmFyaW91cyBhbmFseXNlcy4NCg0KDQoNCg0KIyBPYmplY3RpdmUgYW5kIExvZ2ljIG9mIEFuYWx5emluZyBDUkQgRGF0YQ0KDQpCZWZvcmUgbW92aW5nIHRvIGRhdGEgYW5hbHlzaXMsIHdlIGZpcnN0IGRpc2N1c3MgdGhlIG9iamVjdGl2ZSwgbG9naWMsIGFuZCBtZXRob2RzIGZvciBhbmFseXppbmcgQ1JEIGRhdGEuIFRoZSANCg0KIyMgVGhlIG9iamVjdGl2ZSBhbmQgTG9naWMNCg0KVGhlIGNvcmUgZ29hbHMgd2hlbiBhbmFseXppbmcgQ29tcGxldGVseSBSYW5kb21pemVkIERlc2lnbiAoQ1JEKSBkYXRhIGFyZSB0aHJlZWZvbGQ6DQoNCiogKipUcmVhdG1lbnQgRWZmZWN0IERldGVjdGlvbioqIC0gRGV0ZXJtaW5lIGlmIGRpZmZlcmVudCB0cmVhdG1lbnRzIHByb2R1Y2Ugc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBpbiB0aGUgcmVzcG9uc2UgdmFyaWFibGUuIEZvciBleGFtcGxlLCBkbyBmZXJ0aWxpemVycyBBLCBCLCBhbmQgQyByZXN1bHQgaW4gZGlmZmVyZW50IGNyb3AgeWllbGRzPw0KDQoqICoqRWZmZWN0IFNpemUgUXVhbnRpZmljYXRpb24qKiAtIE1lYXN1cmUgdGhlIG1hZ25pdHVkZSBvZiB0cmVhdG1lbnQgZGlmZmVyZW5jZXMuIEZvciBleGFtcGxlLCBGZXJ0aWxpemVyIEMgaW5jcmVhc2VzIHlpZWxkIGJ5IDEzIGJ1c2hlbHMvYWNyZSBjb21wYXJlZCB0byBGZXJ0aWxpemVyIEENCg0KKiAqKlJhbmtpbmcvQ29tcGFyaXNvbiBvZiBUcmVhdG1lbnRzKiogSWRlbnRpZnkgd2hpY2ggdHJlYXRtZW50cyBwZXJmb3JtIGJlc3Qvd29yc3QuIFRoaXMgaW52b2x2ZXMgbXVsdGlwbGUgY29tcGFyaXNvbnMgYW1vbmcgbWVhbnMgYWNyb3NzIHRyZWF0bWVudHMuIEZvciBleGFtcGxlLCB3ZSBjYW4gb3JkZXIgZmVydGlsaXplcnMgYnkgeWllbGQ6IEEgPiBCID4gQSB0aHJvdWdoIG11bHRpcGxlIGNvbXBhcmlzb25zLg0KDQoNClN0YXRpc3RpY2FsbHksICoqdHJlYXRtZW50IEVmZmVjdCBEZXRlY3Rpb24qKiBpbiBDUkQgd2l0aCAkayQgdHJlYXRtZW50cyBjYW4gYmUgYWNoaWV2ZWQgYnkgdGVzdGluZyBhIGh5cG90aGVzaXMuDQoNCiQkDQpIXzA6IFxtdV8xID0gXG11XzIgPSBcY2RvdHMgPSBcbXVfayBcIFwgXHRleHR7dnN9IFwgXCAgSF9hOiBcIFx0ZXh0e2F0IGxlYXN0IG9uZSBtZWFuIGRpZmZlcnN9DQokJA0KDQpJZiAkSF8wJCBpcyAqKnJlamVjdGVkKiosIHdlIHF1YW50aWZ5IHRoZSBzaXplIG9mIHRyZWF0bWVudCBlZmZlY3RzIGFuZCByYW5rIHRoZSB0cmVhdG1lbnQgZWZmZWN0cyBhY3Jvc3MgdGhlIHRyZWF0bWVudHMgaW4gdGhlIENSRC4gVGhlcmUgYXJlIGRpZmZlcmVudCBhcHByb2FjaGVzIHRvIHRlc3RpbmcgdGhlIGFib3ZlIGh5cG90aGVzaXMNCg0KDQojIyBNZWFzdXJpbmcgRGlzY3JlcGFuY3kgYmV0d2VlbiAkSF8wJCBhbmQgJEhfYSQNCg0KTGV0J3MgdXNlIHRoZSBmb2xsb3dpbmcgYmFsYW5jZWQgQ1JEIGRhdGEgdGFibGUgYW5kIHJlbGF0ZWQgbm90YXRpb25zLg0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjkwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDQvR2VuZXJpY0NSRC1EYXRhVGFibGUucG5nIikNCmBgYA0KDQpUaGUgdGhyZWUgZGlmZmVyZW50IGVycm9ycyBkZWZpbmVkIGFib3ZlIGhhdmUgdGhlIGZvbGxvd2luZyByZWxhdGlvbnNoaXAuDQoNCiQkDQooeV97aWp9IC0gXGJhcnt5fV97XGNkb3RcY2RvdH0pID0gKHlfe2lqfSAtIFxiYXJ7eX1fe2lcY2RvdH0pICsgKFxiYXJ7eX1fe2lcY2RvdH0gLSBcYmFye3l9X3tcY2RvdFxjZG90fSkgDQokJA0KDQpUaGUgYWJvdmUgZXhwcmVzc2lvbiBzaW1wbHkgbWVhbnMgdGhhdCB3ZSBjYW4gKipkZWNvbXBvc2UqKiB0aGUgb3ZlcmFsbCByZXNpZHVhbCAoJHlfe2lqfSAtIFxiYXJ7eX1fe1xjZG90XGNkb3R9JCkgaW50byB3aXRoaW4gdHJlYXRtZW50IGVycm9yICgkKHlfe2lqfSAtIFxiYXJ7eX1fe2lcY2RvdH0pJCwgYWxzbyBjYWxsZWQgd2l0aGluIHJlc2lkdWFsIGVycm9yKSBhbmQgYmV0d2VlbiB0cmVhdG1lbnQgZXJyb3IgKCRcYmFye3l9X3tpXGNkb3R9IC0gXGJhcnt5fV97XGNkb3RcY2RvdH0kKS4gU2luY2UgYW4gZXJyb3IgY291bGQgYmUgcG9zaXRpdmUgb3IgbmVnYXRpdmUuIFNpbWlsYXIgdG8gdGhlIGRlZmluaXRpb24gb2YgdmFyaWFuY2UsIHdlIHNxdWFyZSBhbGwgdGhlc2UgZXJyb3JzIHRvIG9idGFpbiBzcXVhcmVkIGVycm9ycy4gDQoNCjxmb250IGNvbG9yID0gInJlZCIgc2l6ZSA9IDQ+KipcY29sb3J7cmVkfUFmdGVyIHNvbWUgdGVkb3VzIGFsZ2VicmEqKiAoaS5lLiwgbm90IHN0cmFpZ2h0Zm9yd2FyZCBhdCBhbGwhKTwvZm9udD4sIHdlIGhhdmUgdGhlIGZvbGxvd2luZyBlcXVhdGlvbg0KDQokJA0KXHN1bV97aT0xfV50XHN1bV97aj0xfV57bl9pfSh5X3tpan0gLSBcYmFye3l9X3tcY2RvdFxjZG90fSleMj0gXHN1bV97aT0xfV50XHN1bV97aj0xfV57bl9pfSh5X3tpan0gLSBcYmFye3l9X3tpXGNkb3R9KV4yICsgXHN1bV97aT0xfV50XHN1bV97aj0xfV57bl9pfShcYmFye3l9X3tpXGNkb3R9IC0gXGJhcnt5fV97XGNkb3RcY2RvdH0pXjIgDQokJA0KDQpUaGUgbGFzdCB0ZXJtIGluIHRoZSBhYm92ZSBlcXVhdGlvbiBoYXMgbm8gc3Vic2NyaXB0ICRqJDsgd2Ugc2ltcGxpZnkgdGhlIGxhc3QgdGVybSB0byBnZXQgdGhlIGZvbGxvd2luZyBlcXVhdGlvbi4NCg0KJCQNClx1bmRlcmJyYWNle1xzdW1fe2k9MX1edFxzdW1fe2o9MX1ee25faX0oeV97aWp9IC0gXGJhcnt5fV97XGNkb3RcY2RvdH0pXjJ9X3tTU19UfSAgPVx1bmRlcmJyYWNleyBcc3VtX3tpPTF9XnRcc3VtX3tqPTF9XntuX2l9KHlfe2lqfSAtIFxiYXJ7eX1fe2lcY2RvdH0pXjJ9X3tTU19XfSAgKyBcdW5kZXJicmFjZXtcc3VtX3tpPTF9XnQgbl9pKFxiYXJ7eX1fe2lcY2RvdH0gLSBcYmFye3l9X3tcY2RvdFxjZG90fSleMn1fe1NTX0J9ICANCiQkDQp3aGVyZSAkU1NfVCQgPSAqKlRvdGFsIFN1bSBvZiBTcXVhcmVkIFJlc2lkdWFscyoqLCAkU1NfVyQgPSAqKlN1bSBvZiBTcXVhcmVkIEVycm9ycyB3aXRoaW4gdHJlYXRtZW50cyoqIGFuZCAkU1NfQiQgPSAqKlN1bSBvZiBTcXVhcmVkIEVycm9ycyBiZXR3ZWVuIHRyZWF0bWVudHMqKi4NCg0KDQo8Zm9udCBjb2xvciA9ICJyZWQiIHNpemUgPSA1PioqXGNvbG9ye3JlZH0gUmVjYWxsIHRoZSBkZWZpbml0aW9uIG9mIHNhbXBsZSB2YXJpYW5jZSoqPC9mb250Pg0KDQokJA0Kc14yID0gXGZyYWN7KHhfMS1cYmFye3h9KV4yICsoeF8yLVxiYXJ7eH0pXjIgKyBcY2RvdHMgXyAoeF9uLVxiYXJ7eH0pXjJ9e24tMX0gPSBcZnJhY3tcc3VtX3tpPTF9Xm4gKHhfaS1cYmFye3h9KV4yfXtuLTF9LA0KJCQNCg0KV2hpY2ggaXMgPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9YXZlcmFnZSBzcXVhcmVkIGRldmlhdGlvbioqPC9mb250PiAoYWxzbyBjYWxsZWQgKiptZWFuIHNxdWFyZWQgZGV2aWF0aW9uIE1TRCBvciBtZWFuIHNxdWFyZWQgZXJyb3IsIE1TRSoqKSEgVGhlIGRlbm9taW5hdG9yICRuIC0xJCBpbiB0aGUgYWJvdmUgZGVmaW5pdGlvbiByZWZsZWN0cyB0aGUgKipkZWdyZWVzIG9mIGZyZWVkb20qKiAtIG1lYW5pbmcgdGhhdCBudW1iZXIgb2YgaW5kZXBlbmRlbnQgb2JzZXJ2YXRpb25zICgkbiQpIG1pbnVzICoqb25lKiogY29uc3RyYXRpbnQgKCRcYmFye3h9ID0gXHN1bV97aT0xfV5uIHhfaS9uJCwgZWFjaCBlcXVhdGlvbiBiYXNlZCBvbiB0aGUgJG4kIGluZGVwZW5kZW50IG9ic2VydmF0aW9iIGlzIGNvbnNpZGVyZWQgYXMgYSBjb250cmFpbnQhKS4NCg0KTGV0J3MgbG9vayBhdCAkU1NfQiQ6IFRoZXJlIGFyZSAkdCQgaW5kZXBlbmRlbnQgbWVhbnMgKG9uZSBmb3IgZWFjaCB0cmVhdG1lbnQpICRce1xiYXJ7eX1fezFcY2RvdH0sIFxiYXJ7eX1fezJcY2RvdH0sIFxiYXJ7eX1fezNcY2RvdH0sIFxjZG90cywgXGJhcnt5fV97dFxjZG90fSBcfSQsIHRoZSBncmFuZCB0b3RhbCAkXGJhcnt5fV97XGNkb3RcY2RvdH0kIGlzIGNvbnNpZGVyIGEgY29uc3RyYWludC4gVGhlcmVmb3JlLCB0aGVyZSBhcmUgJCB0LTEkIGRlZ3JlZXMgb2YgZnJlZWRvbSBhc3NvY2lhdGVkIHdpdGggJFNTX0IkLiBUaGVyZWZvcmUsIHRoZSBtZWFuIHNxdWFyZWQgZXJyb3Igb2YgdGhlIGJldHdlZW4gZXJyb3JzIGlzIGRlZmluZWQgYnkNCg0KJCQNCk1TX0IgPSBcZnJhY3tTU19CfXt0LTF9DQokJA0KDQoNCg0KDQoNClNpbWlsYXJseSwgaW4gJFNTX1ckLCB0aGVyZSAkbl9UJCBpbmRlcGVuZGVudCBvYnNlcnZhdGlvbnMgJHlfe2lqfSQgYW5kICR0JCBjb25zdHJhaW50cyAkXHtcYmFye3l9X3sxXGNkb3R9LCBcYmFye3l9X3syXGNkb3R9LCBcYmFye3l9X3szXGNkb3R9LCBcY2RvdHMsIFxiYXJ7eX1fe3RcY2RvdH0gXH0kICg8Zm9udCBjb2xvciA9ICJyZWQiPioqWWVzISBzaW5jZSBlYWNoIG9mIHRoZW0gaXMgdGhlIG1lYW4gb2Ygb2JzZXJ2YXRpb25zIHdpdGhpbiBlYWNoIHRyZWF0bWVudCoqKTwvZm9udD4uIFRoZXJlZm9yZSwgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBpbiAkU1NfVyQgaXMgJG5fVC10JCwgVGhlcmVmb3JlLCB0aGUgbWVhbiBzcXVhcmUgZXJyb3Igb2Ygd2l0aGluIGVycm9ycyBpcyBkZWZpbmVkIGJ5DQoNCiQkDQpNU19XID0gXGZyYWN7U1NfV317bl9UIC0gdH0uDQokJA0KDQo8Zm9udCBjb2xvciA9ICJyZWQiPioqXGNvbG9ye3JlZH1SZW1hcmtzKio8L2ZvbnQ+Og0KDQoqICRNU19CJCBpcyB0aGUgZXN0aW1hdGVkIHNhbXBsZSB2YXJpYW5jZSBvZiB0aGUgKipzYW1wbGUgbWVhbnMqKiBvZiBpbmRpdmlkdWFsIHRyZWF0bWVudHMuDQoNCiogJE1TX1ckIGlzIHRoZSB3ZWlnaHRlZCBhdmVyYWdlIG9mIHRoZSB2YXJpYW5jZXMgb2YgZWFjaCBpbmRpdmlkdWFsIHRyZWF0bWVudC4NCg0KDQoNCg0KPGZvbnQgY29sb3IgPSAicmVkIiBzaXplID0gND4qKlxjb2xvcntyZWR9SGVyZSBpcyB0aGUgbG9naWMgZm9yIGhvdyB0byBkZWZpbmUgYSBtZWFzdXJlIHRvIGFzc2VzcyB0aGUgZGlzY3JlcGFuY3kgYmV0d2VlbiAkSF8wJCBhbmQgJEhfYSQ6Kio8L2ZvbnQ+DQoNCjxmb250IGNvbG9yID0gImJsdWUiIHNpemUgPSA1PioqXGNvbG9ye2JsdWV9SWYgdGhlcmUgaXMgbm8gcmVhbCBkaWZmZXJlbmNlIGJldHdlZW4gdHJlYXRtZW50cyAoaS5lLiwgJEhfMCQgaXMgdHJ1ZSksICRNU19CJCBhbmQgJE1TX1ckIGJvdGggZXN0aW1hdGUgdGhlIHNhbWUgdW5kZXJseWluZyB2YXJpYW5jZS4gVGhlcmVmb3JlICRNU19CIFxhcHByb3ggTVNfVyQhKio8L2ZvbnQ+DQoNClwNCg0KV2UgY2FuIGNvbnN0cnVjdCB0aGUgdGVzdCBzdGF0aXN0aWMgYmFzZWQgb24gJE1TX0IkIGFuZCAkTVNFX0IkIHVuZGVyICRIXzAkLiBNYXRoZW1hdGljYWxseSwgYm90aCAkTVNfQi1NU19XJCAoJFxhcHByb3ggMCQpIGFuZCAkTVNfQi9NU19XJCAoJFxhcHByb3ggMSQpIGFyZSB2YWxpZCBtZWFzdXJlcyB0byBhc3Nlc3MgdGhlIGRpc2NlcGFuY3kgYmV0d2VlbiAkSF8wJCBhbmQgJEhfYSQuIFNpbmNlIGJvdGggcXVhbnRpdGllcyBhcmUgcmFuZG9tIChzaW5jZSB0aGV5IGFyZSBldmFsdWF0ZWQgYmFzZWQgb24gdGhlIHJhbmRvbSBzYW1wbGUpLCB3ZSBuZWVkIHRvIGNob29zZSB0aGUgb25lIHdpdGggYSBrbm93biAqKnByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbioqLiBUaGUgcmF0aW8gZXhwcmVzc2lvbiAkTVNfQi9NU19XJCBoYXMgYSB3ZWxsLWtub3duIGRpc3RyaWJ1dGlvbiAtICoqRiBkaXN0cmlidXRpb24qKiENCg0KXA0KDQojIyBCYXNpY3Mgb2YgRiBEaXN0cmlidXRpb24NCg0KV2UgaGF2ZSBkaXNjdXNzZWQgc2V2ZXJhbCBkaXN0cmlidXRpb25zIHRvIGNoYXJhY3Rlcml6ZSB0ZXN0IHN0YXRpc3RpY3MgZm9yIHRoZSB6LXRlc3QsIHQtdGVzdCwgYW5kIGNoaS1zcXVhcmUgdGVzdC4gT25lIG9mIHRoZSBlc3NlbnRpYWwgdG9vbHMgaW4gaHlwb3RoZXNpcyB0ZXN0aW5nIGludm9sdmluZyB0aGUgY29tcGFyaXNvbiBvZiB2YXJpYW5jZXMgKHRoZSBjYXNlIHdlIGludHJvZHVjZWQgYWJvdmUpIGlzIHRoZSBGLWRpc3RyaWJ1dGlvbi4gVGhpcyBzdWJzZWN0aW9uIG91dGxpbmVzIHRoZSBiYXNpY3Mgb2YgdGhlIEYtZGlzdHJpYnV0aW9uIGFuZCBkZW1vbnN0cmF0ZXMgaG93IHRvIHVzZSBSIHRvIGNvbXB1dGUgY3JpdGljYWwgdmFsdWVzIGFuZCBwLXZhbHVlcyBhc3NvY2lhdGVkIHdpdGggRi10ZXN0cy4NCg0KVGhlIEYtZGlzdHJpYnV0aW9uIGlzIGEgY29udGludW91cyBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gdXNlZCBmb3IgdGhlIGNvbXBhcmlzb24gb2YgdHdvIHNhbXBsZSB2YXJpYW5jZXMgKHN1Y2ggYXMgJFNTX0IkIGFuZCAkU1NfVyQpIGFuZCByZWdyZXNzaW9uIGFuYWx5c2lzICh3aWxsIGRpc2N1c3MgdGhpcyBsYXRlcikuIFVzaW5nIHRoZSBhYm92ZSBxdWFudGl0aWVzLCB3ZSBoYXZlDQoNCiQkDQpGID0gXGZyYWN7U1NfVy8obl9ULXQpfXtTU19CLyh0LTEpfSBccmlnaHRhcnJvdyBGX3tuX1QtdCwgXCB0LTF9DQokJA0KDQokbl9ULXQkIGlzIHRoZSBkZWdyZWVzIG9mIGZyZWVkb20gb2YgdGhlICoqbnVtZXJhdG9yKiogYW5kICR0LTEkIGlzIHRoZSBkZWdyZWVzIG9mIHRoZSAqKmRlbm9taW5hdG9yKiouIFdlIGNhbiBhbHNvIGZsaXAgdGhlIHJhdGlvIHRvIGdldCBhbm90aGVyIHZhbGlkIHRlc3Qgc3RhdGlzdGljDQoNCg0KJCQNCkZeXHByaW1lID0gXGZyYWN7U1NfQi8odC0xKX17U1NfVy8obl9ULXQpfSBccmlnaHRhcnJvdyBGX3tcIHQtMSwgbl9ULXR9DQokJA0KDQo8Zm9udCBjb2xvciA9ICJyZWQiPioqXGNvbG9ye3JlZH0gQ2F1dGlvbjoqKiB0aGUgZGVncmVlcyBvZiBmcmVlZG9tIGluIHRoZSBzdWJzY3JpcHQgTVVTVCBiZSBhZGp1c3RlZCBzbyB0aGF0IHRoZSBmaXJzdCBpbmRleCBpcyB0aGUgZGVncmVlcyBvZiBmcmVlZG9tIG9mIHRoZSBudW1lcmF0b3IgYW5kIHRoZSBzZWNvbmQgc3Vic2NyaXB0IHJlcHJlc2VudHMgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBvZiB0aGUgZGVub21pbmF0b3IuIDwvZm9udD4gPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9IFRoaXMgbWVhbnMgJEZfezcsNX0kIGFuZCAkRl97NSwgN30kIGFyZSB0d28gZGlmZmVyZW50IEYgZGlzdHJpYnV0aW9ucyEqKjwvZm9udD4NCg0KDQokRl97ZGZfTiwgZGZfRH0kIGlzIHNrZXdlZCB0byB0aGUgcmlnaHQuIFRoZSBmb2xsb3dpbmcgZmlndXJlIHNob3dzIHRoZSBkZW5zaXR5IGN1cnZlIG9mIGFuIEYtZGlzdHJpYnV0aW9uIHdpdGggZGVncmVlcyBvZiBmcmVlZG9tIGRmMSA9IDcgKG51bWVyYXRvcikgYW5kIGRmMiA9IDEwIChkZW5vbWluYXRvciksIHRvZ2V0aGVyIHdpdGggdGhlIFIgY29tbWFuZHMgdG8gZmluZCB0aGUgY3JpdGljYWwgYW5kIHAtdmFsdWVzLg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI5OSUifQ0KaW5jbHVkZV9ncmFwaGljcygid2VlazA0L0YtZGVuc2l0eUN1cnZlLnBuZyIpDQpgYGANCg0KVGhlIHN5bnRheCBvZiB0aGUgdHdvIFIgZnVuY3Rpb25zIHVzZWQgdG8gZmluZCB0aGUgcC12YWx1ZSBhbmQgY3JpdGljYWwgdmFsdWUgaXMgYW5ub3RhdGVkIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlLg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI5MCUifQ0KaW5jbHVkZV9ncmFwaGljcygid2VlazA0L0YtRGlzUlN5bnRheC5wbmciKQ0KYGBgDQoNCk1vc3QgaW50cm9kdWN0b3J5IHN0YXRpc3RpY3MgdGV4dGJvb2tzIGluY2x1ZGUgYW4gRiB0YWJsZSBiYXNlZCBvbiBhIGZldyBjb21tb25seSB1c2VkIHNpZ25pZmljYW5jZSBsZXZlbHMgJFxhbHBoYSQuIEZvciBleGFtcGxlLCB0aGUgY3JpdGljYWwgdmFsdWUgb2YgJEZfezcsIDEwfSQgYXQgJFxhbHBoYSA9IDAuMDUkIGxhYmVsZWQgaW4gdGhlIGxlZnQgcGFuZWwgb2YgdGhlIGRlbnNpdHkgY3VydmUgb2YgJEZfezcsIDEwfSQgY2FuIGFsc28gYmUgZm91bmQgZnJvbSB0aGUgZm9sbG93aW5nIEYgdGFibGUNCg0KYGBge3IgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iOTAlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoIndlZWswNC9GLXRhYmxlLnBuZyIpDQpgYGANCg0KVGhlIEYgdGFibGVzIGFyZSBjb25zdHJ1Y3RlZCBiYXNlZCBvbiBhIGZldyBzaWduaWZpY2FuY2UgbGV2ZWxzLiBJdCBpcyBub3QgdG8gdXNlIHVzZSBGIHRhYmxlIHRvIGZpbmQgcC12YWx1ZXMuIA0KDQpOZXh0LCB3ZSBvcGVuIGEgc3RhbmRhbG9uZSBzZWN0aW9uIHRvIGZvcm1hbGx5IGludHJvZHVjZSB0aGUgb25lLXdheSBBTk9WQSBmb3IgQ1JEIGRhdGEuDQoNClwNCg0KIyBPbmUtV2F5IEFOT1ZBIGFuZCBJbXBsZW1lbnRhdGlvbg0KDQpXZSBoYXZlIGRpc2N1c3NlZCB0aGUgbG9naWMgYW5kIHZhbGlkIG1lYXN1cmVzIGZvciBhc3Nlc3NpbmcgdGhlIGRpc2NyZXBhbmN5IGJldHdlZW4gJEhfMCQgYW5kICRIX2EkLiBOZXh0LCB3ZSBzdW1tYXJpemUgdGhlIGFib3ZlIHJlc3VsdHMgaW4gYSBjbGFzc2ljYWwgb25lLXdheSBBTk9WQSB0YWJsZSBhbmQgdGVzdCB0aGUgZm9sbG93aW5nIG51bGwgaHlwb3RoZXNpcyBiYXNlZCBvbiB0aGUgQ1JELg0KDQokJA0KSF8wOiBcbXVfMSA9IFxtdV8yID0gXGNkb3RzID0gXG11X3QgXCBcIFx0ZXh0e3ZzfSBcIFwgSF9hOiBcdGV4dHthdCBsZWFzdCBvbmUgbWVhbiBkaWZmZXJzfQ0KJCQNCg0KVGhlIHRlc3Qgc3RhdGlzdGljIGFuZCBjb3JyZXNwb25kaW5nIHAtdmFsdWUgYXJlIHN1bW1hcml6ZWQgaW4gdGhlIGZvbGxvd2luZyBBTk9WQSB0YWJsZS4NCg0KfCAgKipTb3VyY2UqKiAgICB8ICoqREYqKiB8ICAgKipTUyoqICAgICB8ICAgKipNUyoqICB8ICoqRi1WYWx1ZSoqIHwgKipQLVZhbHVlKiogICAgfA0KfDotLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS18Oi0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tfA0KfCAqKkJldHdlZW4qKiAgfCAkdC0xJCAgICB8ICRTU19CJCAgICAgICB8ICRNU19CPVNTX0IvKHQtMSkkICAgICAgICB8ICRNU19XL01TX0IkIHwgfA0KfCAqKldpdGhpbioqICAgfCAkbl9UIC0gdCR8ICRTU19XJCAgICAgICB8ICRNU19XID0gU1NfVy8obl9ULXQpJCAgICB8ICAgICAgICAgICAgIHwgfA0KfCAqKlRvdGFsKiogICAgfCAkbl9ULWAkICB8ICRTU19UJCAgICAgICB8DQoNCioqRGVjaXNpb24gUnVsZSoqOiBJZiB0aGUgcC12YWx1ZSBpbiB0aGUgYWJvdmUgdGFibGUgaXMgbGVzcyB0aGFuIHRoZSBzaWduaWZpY2FuY2UgbGV2ZWwgJFxhbHBoYSQsIHdlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzOyBvdGhlcndpc2UsIHdlIGNvbmNsdWRlIHRoZSBudWxsIGh5cG90aGVzaXMuDQoNCg0KTmV4dCwgd2UgdXNlIHRoZSAqKnBsYW50IHBoeXNpb2xvZ3kgZGF0YSoqIHRvIGRlbW9uc3RyYXRlIHRvIHRvIGNvbnN0cnVjdCB0aGUgYWJvdmUgQU5PVkEgdGFibGUgYW5kIHVzZSBSIGFzIGEgY2FsY3VsYXRvciB0byBmaW5kICRTUyQgYW5kICRNUyQgYW5kIHJlbGF0ZWQgcXVhbnRpdGllcyBpbiB0aGUgQU5PVkEgdGFibGUuIFRoZSBmb2xsb3dpbmcgY29kZSBsb2FkcyB0aGUgZGF0YSBpbnRvIFIgaW4gdGhlIHNhbWUgZm9ybWF0IChpLmUuLCB3aWRlIHRhYmxlIGZvcm1hdCkNCg0KYGBge3J9DQojIENyZWF0ZSB0aGUgZGF0YSB2ZWN0b3JzDQpDb250cm9sIDwtIGMoNzUsIDY3LCA3MCwgNzUsIDY1LCA3MSwgNjcsIDY3LCA3NiwgNjgpICAgICAjIENvbnRyb2wNCkdsdWNvc2UgPC0gYyg1NywgNTgsIDU5LCA1OSwgNjIsIDYwLCA2MCwgNTcsIDU5LCA2MSkgICAgICMgR2x1Y29zZQ0KRnJ1Y3Rvc2UgPC0gYyg1OCwgNjEsIDU2LCA1OCwgNTcsIDU2LCA1OCwgNjAsIDU3LCA1OCkgICAgICMgRnJ1Y3Rvc2UNCkdsdWNGcnVjIDwtIGMoNTgsIDU5LCA1OCwgNjEsIDU3LCA1NiwgNTgsIDU3LCA1NywgNTkpICAgICAjIEdsdWNGcnVjDQpTdWNyb3NlIDwtIGMoNjIsIDY2LCA2NSwgNjMsIDY0LCA2MiwgNjUsIDY1LCA2MiwgNjcpICAgICAjIFN1Y3Jvc2UNCiMjIHVzaW5nIGNiaW5kKCkgdG8gZGlzcGxheSB0aGUgZGF0YQ0KY2JpbmQoQ29udHJvbCwgR2x1Y29zZSwgRnJ1Y3Rvc2UsIEdsdWNGcnVjLCBTdWNyb3NlKQ0KI2NvbG5hbWVzKHdpZGUudGFibGUpIDwtIGMoIkNvbnRyb2wiLCAiR2x1Y29zZSIsICJGcnVjdG9zZSIsICJHbHVjRnJ1YyIsICJTdWNyb3NlIikNCmBgYA0KDQoNClRoZSBuZXh0IGNvZGUgY2h1bmsgY2FsY3VsYXRlcyBkaWZmZXJlbnQgcXVhbnRpdGllcyBpbiB0aGUgQU5PVkEgdGFibGUuIEkgd2lsbCBtYWtlIGNvbW1lbnRzIGluIHRoZSBjb2RlIHRvIHNob3cgZGV0YWlsZWQgc3RlcHMuIFRoZSBwcmltYXJ5IFIgY29tbWFuZHMgYXJlIGBzdW0oKWAsIGBtZWFuKClgLCBhbmQgcmVsYXRlZCBSIGZ1bmN0aW9ucyBvZiB0aGUgRi1kaXN0cmlidXRpb24uDQoNCmBgYHtyfQ0KIyMgZGVncmVlcyBvZiBmcmVlZG9tDQp0ID0gNQ0Kbi5UID0gMTAqNQ0KZGZOID0gdCAtIDENCmRmRCA9IG4uVCAtIHQNCnliYXIuLiA9IG1lYW4oYyhDb250cm9sLCBHbHVjb3NlLCBGcnVjdG9zZSwgR2x1Y0ZydWMsIFN1Y3Jvc2UpKQ0KIyMgU3VtIG9mIHNxdWFyZXMNClNTLkIgPSAxMCpzdW0oYygobWVhbihDb250cm9sKS15YmFyLi4pXjIsIChtZWFuKEdsdWNvc2UpLXliYXIuLileMiwgKG1lYW4oRnJ1Y3Rvc2UpLXliYXIuLileMiwgKG1lYW4oR2x1Y0ZydWMpLXliYXIuLileMiwgKG1lYW4oU3Vjcm9zZSkteWJhci4uKSkpDQpTUy5XID0gc3VtKGMoc3VtKChDb250cm9sLW1lYW4oQ29udHJvbCkpXjIpLCBzdW0oKEdsdWNvc2UtbWVhbihHbHVjb3NlKSleMiksIHN1bSgoRnJ1Y3Rvc2UtbWVhbihGcnVjdG9zZSkpXjIpLCBzdW0oKEdsdWNGcnVjLW1lYW4oR2x1Y0ZydWMpKV4yKSwgc3VtKChTdWNyb3NlLW1lYW4oU3Vjcm9zZSkpXjIpKSkNClNTLlQgPSBzdW0oKGMoQ29udHJvbCwgR2x1Y29zZSwgRnJ1Y3Rvc2UsIEdsdWNGcnVjLCBTdWNyb3NlKSAtIHliYXIuLileMikNCiMjIE1TDQpNUy5CID0gU1MuQi9kZk4NCk1TLlcgPSBTUy5XL2RmRA0KIyMgRiB2YWx1ZQ0KRi52YWx1ZSA9IE1TLkIvTVMuVw0KcC52YWwgPSBwZihGLnZhbHVlLCBkZk4sIGRmRCwgbG93ZXIudGFpbCA9IEZBTFNFKQ0KYW5vdmEub3V0IDwtIGRhdGEuZnJhbWUoDQogIERGID0gYyhkZk4sIGRmRCksDQogIFNTID0gYyhTUy5CLCBTUy5XKSwNCiAgTVMgPSBjKE1TLkIsIE1TLlcpLA0KICBGLnZhbHVlID0gYyhGLnZhbHVlLCBOQSksDQogIHAudmFsdWUgPSBjKHAudmFsLCBOQSkNCikNCnJvd25hbWVzKGFub3ZhLm91dCk9YygiQmV0d2VlbiIsICJXaXRoaW4iKQ0KcHJpbnQoYW5vdmEub3V0LCBuYS5wcmludCA9ICIiKQ0KDQpgYGANCg0KKipDb25jbHVzaW9uKio6IFRoZSBwLXZhbHVlIGlzIGFwcHJveGltYXRlbHkgMC4gV2UgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCBhbGwgbWVhbnMgYXJlIGVxdWFsLiBJbiBvdGhlciB3b3JkcywgIHRoZSBtZWFuIHBlYSBzZWN0aW9uIGxlbmd0aCBpcyBhZmZlY3RlZCBieSB2YXJpb3VzIHN1Z2FyIG1lZGlhLg0KDQpcDQoNCg0KVGhlIHNlY29uZCBwYXJ0IG9mIHRoZSBmb2xsb3dpbmcgWW91VHViZSB2aWRlbyAgKGFmdGVyIDE1IE1pbnV0ZXMsIDxodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUtKNUcyS2pjWGNBPikgZGlzY3Vzc2VkIGluIHRoZSBuZXh0IG5vdGUgb24gT25lLXdheSBBTk9WQS4gDQoNClwNCg0KPGNlbnRlcj48YSBocmVmPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUtKNUcyS2pjWGNBIiB0YXJnZXQ9InBvcHVwIiANCiAgICAgICAgICAgICAgICAgICBvbmNsaWNrPSJ3aW5kb3cub3BlbignaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1LSjVHMktqY1hjQScsDQogICAgICAgICAgICAgICAgICAgICAgJ25hbWUnLCd3aWR0aD04NTAsaGVpZ2h0PTUwMCcpIj48aW1nIHNyYyA9ICJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9NQVQxMjFXNS9pbWcvVmlkZW9JY29uLnBuZyIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMjAiPjwvYT4NCjwvY2VudGVyPg0KDQpcDQoNCg0KDQoNCg0KDQoNCg0KDQoNCiMgQU5PVkEgd2l0aCBSIEZ1bmN0aW9uIGBhb3YoKWANCg0KV2Ugc3RpbGwgdXNlICoqcGxhbnQgcGh5c2lvbG9neSBkYXRhKiogdG8gaWxsdXN0cmF0ZSBvbmUtd2F5IEFOT1ZBIGFuYWx5c2lzIHVzaW5nIGBhb3YoKWAuIFNpbmNlIGBhb3YoKWAgcmVxdWlyZXMgYSBsb25nIHRhYmxlIHN0cnVjdHVyZS4gVGhhdCBpcywgYWxsIG1lYXN1cmVtZW50cyBvZiB0aGUgcmVzcG9uc2UgbXVzdCBiZSBzdG9yZWQgaW4gYSBjb2x1bW4gYW5kIGEgc3RhbmRhbG9uZSBjb2x1bW4gdG8gbGFiZWwgdGhlIHRyZWF0bWVudCBvZiBlYWNoIHZhbHVlIGluIHRoZSBtZWFzdXJlbWVudCBjb2x1bW4uIFRoZSBmb2xsb3dpbmcgY29kZSBjcmVhdGVzIGEgbG9uZyB0YWJsZS4gDQoNCmBgYHtyfQ0KIyBDcmVhdGUgdGhlIGRhdGEgdmVjdG9ycw0KbGVuZ3RocyA8LSBjKA0KICA3NSwgNjcsIDcwLCA3NSwgNjUsIDcxLCA2NywgNjcsIDc2LCA2OCwgICAgICMgQ29udHJvbA0KICA1NywgNTgsIDU5LCA1OSwgNjIsIDYwLCA2MCwgNTcsIDU5LCA2MSwgICAgICMgR2x1Y29zZQ0KICA1OCwgNjEsIDU2LCA1OCwgNTcsIDU2LCA1OCwgNjAsIDU3LCA1OCwgICAgICMgRnJ1Y3Rvc2UNCiAgNTgsIDU5LCA1OCwgNjEsIDU3LCA1NiwgNTgsIDU3LCA1NywgNTksICAgICAjIEdsdWNGcnVjDQogIDYyLCA2NiwgNjUsIDYzLCA2NCwgNjIsIDY1LCA2NSwgNjIsIDY3ICAgICAgIyBTdWNyb3NlDQopDQoNCiMgQ3JlYXRlIHRoZSB0cmVhdG1lbnQgZmFjdG9yDQp0cmVhdG1lbnQgPC0gcmVwKGMoIkNvbnRyb2wiLCAiR2x1Y29zZSIsICJGcnVjdG9zZSIsICJHbHVjRnJ1YyIsICJTdWNyb3NlIiksIGVhY2ggPSAxMCkNCg0KIyBDb21iaW5lIGludG8gYSBkYXRhIGZyYW1lDQpwZWEubG9uZyA8LSBkYXRhLmZyYW1lKA0KICBMZW5ndGggPSBsZW5ndGhzLA0KICBUcmVhdG1lbnQgPSBmYWN0b3IodHJlYXRtZW50LCBsZXZlbHMgPSBjKCJDb250cm9sIiwgIkdsdWNvc2UiLCAiRnJ1Y3Rvc2UiLCAiR2x1Y0ZydWMiLCAiU3Vjcm9zZSIpKQ0KKQ0KDQojIFZpZXcgdGhlIGZpcnN0IDIwIHJvd3MgdG8gbWFrZSBzdXJlIHRoZSBkYXRhIHN0cnVjdHVyZSBpcyBjb3JyZWN0DQpoZWFkKHBlYS5sb25nLCBuPTIwKQ0KYGBgDQoNCldlIG5leHQgY2FsbCBgYW92KClgIHRvIHBlcmZvcm0gQU5PVkEgYW5hbHlzaXMuDQoNCmBgYHtyfQ0KIyMgY3JlYXRlIGFuIGFub3ZhIG1vZGVsIG9iamVjdCANCmFvdi5tb2RlbCA8LSBhb3YoTGVuZ3RoIH4gVHJlYXRtZW50LCBkYXRhID0gcGVhLmxvbmcpDQojIyBjcmVhdGUgdGhlIGNsYXNzaWNhbCBBTk9WQSB0YWJsZQ0KYW5vdmEoYW92Lm1vZGVsKQ0KIyMgb3IgYWx0ZXJuYXRpdmVseSwgeW91IGNhbiBzaW1wbHkgdXNlIHN1bW1hcnkoYW92Lm1vZGVsKSB0byBwcm9kdWNlIHRoZSBzYW1lIHJlc3VsdHMhDQpgYGANCg0KVGhlIGFubm90YXRlZCBvdXRwdXQgaXMgZ2l2ZW4gYnkNCg0KYGBge3IgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNjAlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoIndlZWswNC9Bbm5vdGF0ZWQtQU5PVkEtT3V0cHV0LnBuZyIpDQpgYGANCg0KKipDb25jbHVzaW9uKio6ICBTaW5jZSB0aGUgcC12YWx1ZSBpcyBhcHByb3hpbWF0ZWx5IDAsIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgcmVqZWN0ZWQuIFRoYXQgaXMsIHRoZSB2YXJpb3VzIHN1Z2FyIG1lZGlhICh0aGUgaW5kZXBlbmRlbnQsIG9yIGV4cGxhbmF0b3J5LCB2YXJpYWJsZSkgc2lnbmlmaWNhbnRseSBhZmZlY3QgdGhlIG1lYW4gcGVhIHNlY3Rpb24gbGVuZ3RoLg0KDQpcDQoNClRoZSBmb2xsb3dpbmcgWW91VHViZSB2aWRlbyAoIDxodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUlrUjNSenJnaXY0PikgZ2l2ZXMgYW5vdGhlciBleGFtcGxlIG9mIHVzaW5nIHRoZSBSIGZ1bmN0aW9uIGBhb3YoKWAuIFRoZSB2aWRlbyBhbHNvIHVzZXMgc29tZSBncmFwaGljYWwgZnVuY3Rpb25zIHRvIGNyZWF0ZSBzb21lIHZpc3VhbGl6YXRpb25zLiBXZSBkaWQgbm90IGRpc2N1c3MgdmlzdWFsaXphdGlvbnMgaW4gdGhpcyBjbGFzcywgYnV0IHdlIHdpbGwgY292ZXIgbW9yZSB2aXN1YWxpemF0aW9ucyBpbiBzdWJzZXF1ZW50IHN0YXRpc3RpY3MgY291cnNlcy4NCg0KXA0KDQo8Y2VudGVyPjxhIGhyZWY9Imh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9SWtSM1J6cmdpdjQiIHRhcmdldD0icG9wdXAiIA0KICAgICAgICAgICAgICAgICAgIG9uY2xpY2s9IndpbmRvdy5vcGVuKCdodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUlrUjNSenJnaXY0JywNCiAgICAgICAgICAgICAgICAgICAgICAnbmFtZScsJ3dpZHRoPTg1MCxoZWlnaHQ9NTAwJykiPjxpbWcgc3JjID0gImh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL01BVDEyMVc1L2ltZy9WaWRlb0ljb24ucG5nIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjEyMCI+PC9hPg0KPC9jZW50ZXI+DQoNClwNCg0KDQojIE11bHRpcGxlIENvbXBhcmlzb25zDQoNCldoZW4gYW5hbHl6aW5nIHZhcmlhbmNlIChBTk9WQSksIGEgc2lnbmlmaWNhbnQgRi10ZXN0IChpLmUuLCBwLXZhbHVlIGlzIGxlc3MgdGhhbiB0aGUgZ2l2ZW4gc2lnbmlmaWNhbmNlIGxldmVsICRcYWxwaGEkKSBpbmRpY2F0ZXMgdGhhdCBhdCBsZWFzdCBvbmUgZ3JvdXAgbWVhbiBkaWZmZXJzIGZyb20gdGhlIG90aGVycy4gSG93ZXZlciwgQU5PVkEgZG9lcyBub3Qgc3BlY2lmeSB3aGljaCBwYWlycyBvZiBncm91cHMgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50LiAqKlBvc3QtaG9jIHRlc3RzKiosIGFsc28ga25vd24gYXMgKiptdWx0aXBsZSBjb21wYXJpc29uIHRlc3RzKiosIGFyZSB1c2VkIHRvIGlkZW50aWZ5IHRoZXNlIHNwZWNpZmljIGRpZmZlcmVuY2VzIHdoaWxlIGNvbnRyb2xsaW5nIGZvciB0aGUgaW5jcmVhc2VkIHJpc2sgb2YgVHlwZSBJIGVycm9ycyAoZmFsc2UgcG9zaXRpdmVzKSB0aGF0IGFyaXNlIGZyb20gcGVyZm9ybWluZyBtdWx0aXBsZSBjb21wYXJpc29ucy4gDQoNClRoZXJlIGFyZSBkaWZmZXJlbnQgKipQb3N0LWhvYyB0ZXN0cyoqLiBXZSBvbmx5IGludHJvZHVjZSB0d28gY29tbW9ubHkgdXNlZCBwb3N0LWhvYyBtZXRob2RzIHVzaW5nIFIgYnVpbHQtaW4gZnVuY3Rpb25zOg0KDQoqICoqVHVrZXnigJlzIEhvbmVzdCBTaWduaWZpY2FudCBEaWZmZXJlbmNlIChIU0QpKiogLUNvbnRyb2xzICoqZmFtaWx5LXdpc2UgZXJyb3IgcmF0ZSoqIChGV0VSKSBmb3IgYWxsIHBhaXJ3aXNlIGNvbXBhcmlzb25zLg0KDQoqICoqQm9uZmVycm9uaSBDb3JyZWN0aW9uKiogLSBBZGp1c3RzIHAtdmFsdWVzIGJ5IG11bHRpcGx5aW5nIHRoZW0gYnkgdGhlIG51bWJlciBvZiBjb21wYXJpc29ucw0KDQoNCiMgVmlzdWFsIENvbXBhcmlzb24NCg0KV2UgaGF2ZSBsZWFybmVkIGRpZmZlcmVudCBncmFwaGljYWwgc3VtbWFyaWVzIG9mIGRhdGEuIEJveC1wbG90IGlzIGEgZ2VvbWV0cmljIHJlcHJlc2VudGF0aW9uIG9mIHRoZSA1LW51bWJlci1zdW1tYXJ5IG9mIGEgbnVtZXJpY2FsIHZhcmlhYmxlLiBTaW5jZSB0cmVhdG1lbnQgdmFyaWFibGUgaGFzIG11bHRpcGxlIGNhdGVnb3JpZXMsIHdlIGNhbiBjcmVhdGUgYSBiYWNrLXRvLWJhY2sgYm94LXBsb3QgdG8gdmlzdWFsaXplIHRoZSBkaWZmZXJlbnQgaW4gdGhlIGRpc3RyaWJ1dGlvbnMuIA0KDQpUaGUgUiBmdW5jdGlvbiBgYm94cGxvdCgpYCBjYW4gZHJhdyBtdWx0aXBsZSBib3hwbG90cyBvZiBhIG51bWVyaWNhbCB2YXJpYWJsZSBhY2NvcmRpbmcgdGhlIGNhdGVnb3JpZXMgb2YgdGhlIGdyb3VwIHZhcmlhYmxlLiBTaW5jZSBwYWNrYWdlICoqe2dyYXBoaWNzfSoqIGNvbWVzIHdpdGggdGhlIGJhc2UgUiwgaW5zdGFsbGF0aW9uIGFuZCBsb2FkaW5nIHRoZSBwYWNrYWdlIGlzIHVubmVjZXNzYXJ5Lg0KDQpgYGB7cn0NCmJveHBsb3QoTGVuZ3RoIH4gVHJlYXRtZW50LCBkYXRhID0gcGVhLmxvbmcpDQpgYGANCg0KVGhlIGFib3ZlIGJveC1wbG90cyBjbGVhcmx5IHNob3cgdGhhdCB0aGUgcGVhIGxlbmd0aHMgdXNpbmcgc3VnYXIgbWVkaWEgRnJ1Y3Rvc2UsIEdsdWNvc2UsIGFuZCBHbHVjRnJ1YyBhcmUgc2ltaWxhciB0byBlYWNoIG90aGVyLg0KDQoNCg0KIyMgVHVrZXnigJlzIEhvbmVzdCBTaWduaWZpY2FudCBEaWZmZXJlbmNlIChIU0QpDQoNClR1a2V54oCZcyBIb25lc3QgU2lnbmlmaWNhbnQgRGlmZmVyZW5jZSAoSFNEKSBpcyBhIHBvc3QtaG9jIHRlc3QgdXNlZCBhZnRlciBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgQU5PVkEgdG8gZGV0ZXJtaW5lIHdoaWNoIHNwZWNpZmljIGdyb3VwIG1lYW5zIGRpZmZlciBmcm9tIGVhY2ggb3RoZXIuIFVubGlrZSBtdWx0aXBsZSB0LXRlc3RzLCB3aGljaCBpbmZsYXRlIHRoZSBUeXBlIEkgZXJyb3IgcmF0ZSwgVHVrZXnigJlzIEhTRCBhZGp1c3RzIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucywgbWFpbnRhaW5pbmcgdGhlIGZhbWlseS13aXNlIGVycm9yIHJhdGUgKEZXRVIpIGF0IHRoZSBkZXNpcmVkIGxldmVsIChlLmcuLCAwLjA1KS4NCg0KTmV4dCwgd2UgcGVyZm9ybSBhIG11bHRpcGxlIGNvbXBhcmlzb24gb2YgcGVhIGxlbmd0aCBhY3Jvc3MgZGlmZmVyZW50IHN1Z2FyIG1lZGlhIHVzaW5nIHRoZSAqKnBsYW50IHBoeXNpb2xvZ3kgZGF0YSoqLiBGb3IgY29udmVuaWVuY2UsIHdlIHVzZSB0aGUgbG9uZy1mb3JtYXQgZGF0YSBmcmFtZSBkZWZpbmVkIGVhcmxpZXIgYW5kIGFuIGFub3ZhIG9iamVjdCBpbiB0aGUgZm9sbG93aW5nIFIgY29kZS4NCg0KYGBge3J9DQojIyByZWZpdCB0aGUgQU5PVkEgbW9kZWwNCmFvdi5tb2RlbCA8LSBhb3YoTGVuZ3RoIH4gVHJlYXRtZW50LCBkYXRhID0gcGVhLmxvbmcpDQojIyBtdWx0aXBsZSBjb21wYXJpc29uDQp0dWtleS5jb21wIDwtIFR1a2V5SFNEKGFvdi5tb2RlbCkNCnByaW50KHR1a2V5LmNvbXApDQoNCmBgYA0KDQpUaGUgcmVzdWx0cyBpbmRpY2F0ZSB0aGF0IHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gcGFpcnMgRnJ1Y3Rvc2UtR2x1Y29zZSwgR2x1Y0ZydWMtR2x1Y29zZSwgYW5kIEdsdWNGcnVjLUZydWN0b3NlLiANCg0KYGBge3J9DQpwYXIobWFpPWMoMS41LDIsMSwxKSkgIyBNYWtlcyByb29tIG9uIHRoZSBwbG90IGZvciB0aGUgZ3JvdXAgbmFtZXMNCnBsb3QodHVrZXkuY29tcCwgICAgICAjIG5hbWUgb2YgdGhlIFR1a2V5SFNEKCkgb2JqZWN0DQogICAgIGNleC5sYWIgPSAwLjYsICAgIyBhZGp1c3QgdGhlIGZvbnQgc2l6ZSBvZiB0aGUgbGFiZWxzIG9mIHRoZSB2ZXJ0aWNhbCBheGlzDQogICAgIGxhcyA9IDEpICAgICAgICAgIyBvcmllbnRhdGlvbiBvZiB0aGUgbGFiZWxzDQpgYGANCg0KDQoNCiMjIEJvbmZlcnJvbmkgQ29tcGFyaXNvbiANCg0KVGhlIEJvbmZlcnJvbmkgY29ycmVjdGlvbiBpcyBhIGNvbnNlcnZhdGl2ZSBtZXRob2QgZm9yIGFkanVzdGluZyBzaWduaWZpY2FuY2UgbGV2ZWxzIHdoZW4gcGVyZm9ybWluZyBtdWx0aXBsZSBjb21wYXJpc29ucyB0byByZWR1Y2UgdGhlIHJpc2sgb2YgVHlwZSBJIGVycm9ycyAoZmFsc2UgcG9zaXRpdmVzKS4gSXQgaXMgb25lIG9mIHRoZSBzaW1wbGVzdCBhbmQgbW9zdCB3aWRlbHkgdXNlZCBhcHByb2FjaGVzIGZvciBjb250cm9sbGluZyB0aGUgZmFtaWx5LXdpc2UgZXJyb3IgcmF0ZS4NCg0KVGhlIFIgZnVuY3Rpb24gYHBhaXJ3aXNlLnQudGVzdCgpYCBwZXJmb3JtcyBwYWlyd2lzZSBjb21wYXJpc29uLiBJdCByZXF1aXJlcyBpbnB1dHRpbmcgaW5kaXZpZHVhbCB2YXJpYWJsZXMgKHJlc3BvbnNlIGFuZCB0cmVhdG1lbnQgZ3JvdXApLiBUaGUgZm9sbG93aW5nIGlzIGNvZGUgZm9yIHRoZSBCb25mZXJyb25pIHByb2NlZHVyZS4NCg0KYGBge3J9DQpCb25mZWVyb25pLnJlc3VsdCA8LSBwYWlyd2lzZS50LnRlc3QoDQogIHggPSBwZWEubG9uZyRMZW5ndGgsIA0KICBnID0gcGVhLmxvbmckVHJlYXRtZW50LA0KICBwLmFkanVzdC5tZXRob2QgPSAiYm9uZmVycm9uaSINCikNCnByaW50KEJvbmZlZXJvbmkucmVzdWx0KQ0KYGBgDQoNClVzaW5nIHRoZSBwLXZhbHVlIGFkanVzdGVkIEJvbmZlcnJvbmkgcHJvY2VkdXJlLCB0aHJlZSBwYWlycyBvZiB0cmVhdG1lbnQgZ3JvdXBzIGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudDogRnJ1Y3Rvc2UtR2x1Y29zZSwgR2x1Y0ZydWMtR2x1Y29zZSwgYW5kIEdsdWNGcnVjLUZydWN0b3NlLiBUaGlzIHJlc3VsdCBpcyBjb25zaXN0ZW50IHdpdGggVHVrZXUncyBIU0QgbWV0aG9kLg0KDQpcDQoNCkJlZm9yZSBjb25jbHVkZSB0aGlzIHNlY3Rpb24sIHdlIHJlY29tbWVuZCBhIFlvdVR1YmUgdmlkZW8gKDxodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PWhQVXZxdG1DdTdRPikgd2l0aCBhbiBleGFtcGxlIG9uZSBtdWx0aXBsZSBjb21wYXJpc29uIGFtb25nIGdyb3VwIG1lYW5zIHVzaW5nIFIsDQoNClwNCg0KPGNlbnRlcj48YSBocmVmPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PWhQVXZxdG1DdTdRIiB0YXJnZXQ9InBvcHVwIiANCiAgICAgICAgICAgICAgICAgICBvbmNsaWNrPSJ3aW5kb3cub3BlbignaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1oUFV2cXRtQ3U3UScsDQogICAgICAgICAgICAgICAgICAgICAgJ25hbWUnLCd3aWR0aD04NTAsaGVpZ2h0PTUwMCcpIj48aW1nIHNyYyA9ICJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9NQVQxMjFXNS9pbWcvVmlkZW9JY29uLnBuZyIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMjAiPjwvYT4NCjwvY2VudGVyPg0KDQpcDQoNCg0KIyBDb25jbHVkaW5nIFJlbWFya3MNCg0KKipPbmUtV2F5IEFOT1ZBKiogKEFuYWx5c2lzIG9mIFZhcmlhbmNlKSBpcyBhIHN0YXRpc3RpY2FsIG1ldGhvZCB1c2VkIHRvIGNvbXBhcmUgdGhlIG1lYW5zIG9mIHRocmVlIG9yIG1vcmUgaW5kZXBlbmRlbnQgZ3JvdXBzIHRvIGRldGVybWluZSBpZiBhdCBsZWFzdCBvbmUgZ3JvdXAgbWVhbiBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHRoZSBvdGhlcnMuIEl0IGV4dGVuZHMgdGhlIHQtdGVzdCAod2hpY2ggY29tcGFyZXMgb25seSB0d28gZ3JvdXBzKSB0byBtdWx0aXBsZSBncm91cHMuDQoNCkh5cG90aGVzZXMNCg0KKiAqKk51bGwgSHlwb3RoZXNpcyAoJEhfMCQpKio6IEFsbCBncm91cCBtZWFucyBhcmUgZXF1YWwoJFxtdV8xID0gXG11XzIgPSBcY2RvdHMgPSBcbXVfayQpLg0KDQoqICoqQWx0ZXJuYXRpdmUgSHlwb3RoZXNpcyAoJEhfYSQpKio6IEF0IGxlYXN0IG9uZSBncm91cCBtZWFuIGlzIGRpZmZlcmVudC4NCg0KDQpUaGUgZnVuZGFtZW50YWwgYXNzdW1wdGlvbnMgb2YgT25lLVdheSBBTk9WQSBpbmNsdWRlOg0KDQoqICoqSW5kZXBlbmRlbmNlKio6IE9ic2VydmF0aW9ucyBtdXN0IGJlIGluZGVwZW5kZW50IChlLmcuLCByYW5kb20gc2FtcGxpbmcpLg0KDQoqICoqTm9ybWFsaXR5Kio6IERhdGEgaW4gZWFjaCBncm91cCBzaG91bGQgYmUgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZCAoY2hlY2tlZCB2aWEgUS1RIHBsb3RzIG9yIFNoYXBpcm8tV2lsayB0ZXN0KS4NCg0KKiAqKkhvbW9nZW5laXR5IG9mIFZhcmlhbmNlKiogKEhvbW9zY2VkYXN0aWNpdHkpOiBHcm91cHMgc2hvdWxkIGhhdmUgZXF1YWwgdmFyaWFuY2VzICh0ZXN0ZWQgdXNpbmcgTGV2ZW5l4oCZcyB0ZXN0IG9yIEJhcnRsZXR04oCZcyB0ZXN0KS4NCg0KSWYgYW55IG9mIHRoZXNlcyBhc3N1bXB0aW9ucyBhcmUgdmlvbGF0ZWQsIHRoZSBjbGFzc2ljYWwgQU5PVkEgcmVzdWx0cyB3aWxsIGJlIGludmFsaWQuIFRoZXJlIHNvbWUgYWx0ZXJuYXRpdmVzIG9mIHRoZSBjbGFzc2ljIEFOT1ZBIHRoYXQgd2lsbCBiZSBjb3ZlcmVkIGluIHRoZSBzdWJzZXF1ZW50IHJlbGF0ZWQgY291cnNlcy4gVGhlIGtleSBpbmZvcm1hdGlvbiBpbiB0aGUgQU5PVkEgYW5hbHlzaXMgaXMgc3VtbWFyaXplZCBpbiB0aGUgZm9sbG93aW5nIG9uZS13YXkgQU5PVkEgdGFibGUuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjkwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDQvU3VtbWFyaXplZEFOT1ZBdGFibGUucG5nIikNCmBgYA0KDQpJZiBBTk9WQSByZWplY3RzIHRoZSBudWxsIGh5cG90aGVpcywgcG9zdC1ob2MgdGVzdHMgaWRlbnRpZnkgd2hpY2ggc3BlY2lmaWMgZ3JvdXBzIGRpZmZlci4gV2UgaW50cm9kdWNlZCB0d28gcHJjZWR1cmVzIGZvciB0aGlzIHB1cnBvc2UuDQoNCiogKipUdWtleeKAmXMgSFNEKiogKGNvbnRyb2xzIGZhbWlseS13aXNlIGVycm9yIHJhdGUpLg0KDQoqICoqQm9uZmVycm9uaSBDb3JyZWN0aW9uKiogKGNvbnNlcnZhdGl2ZSBhZGp1c3RtZW50KS4NCg0KDQoNCg0KDQoNCg0KDQo=