Introduction
We have briefly introduced the simple linear regression model earlier
with an explicit expression.
\[
y = \beta_0 + \beta_1 x + \epsilon,
\]
Where \(y\) is a continuous random
numerical variable, \(x\) is either a
numerical variable or a binary categorical variable, and \(\epsilon \rightarrow N(0, \sigma)\), the
basic applications of a simple linear regression model are twofold:
Assess the linear correlation between the
response variable (\(y\)) and the
predictor variable (\(x\)).
Predict the response for given new values of the
predictor variable \(x\).
In general, regression modeling is an iterative process in real-world
applications, as illustrated in the following chart.

In the course project and data analysis, we focus on the iterative
loop of model identification and reporting on the final model. To be
more specific, assuming we have an analytic data set that is ready for
modeling,
Select appropriate candidate models to address the
practical questions - This includes checking model assumptions
and ensuring the analytic dataset contains sufficient information for
the candidate models. We have highlighted all
assumptions when introducing new models in the previous
notes.
Fit candidate models to the data - This step
involves verifying the outputs to ensure the model parameters (e.g.,
coefficients) are appropriately estimated.
Note: the fitted models in
this step may not be valid or optimal, we should not interpret the model
at this point. We only report the final model obtained from
the iterative model identification process.
Model diagnostics - This is the most crucial
step in any regression analysis, where we assess whether all assumptions
of the candidate models are satisfied. For example, we apply residual
diagnostic methods (commonly used in linear regression) to evaluate
linearity, normality, homoscedasticity (constant variance), and other
key assumptions. If no violations are detected, we then use
application-specific performance measures to select the best model for
reporting and implementation.
Model remedy and refinement - If one or more
assumptions are violated, we need to use various methods to fix the
problems. We will not discuss this major topic in this class, but
will cover this critical topic in detail in subsequent
courses.
Enter the refined/modified model into the loop for the
next iteration - The refined or modified model will be
refitted, analyzed, and diagnosed to determine whether any violations
remain. This process continues iteratively until the final valid and
optimal model is identified.
Final model reporting - This topic will not be
emphasized in this class but will be highlighted in subsequent
statistical modeling classes.
In this note, we will extend simple linear regression to multiple
linear regression by incorporating two or more predictor variables into
the model. We begin by revisiting the simple linear regression model
discussed earlier this semester. Next, we will generalize the binary
categorical predictor to multi-category predictors through the use of
binary indicator variables – effectively creating a special case of
multiple linear regression with multiple binary categorical variables.
This approach integrates ANOVA analysis into the regression
framework.
Simple Linear
Regression Revisited
The term simple linear regression (SLR) simply means
that the regression equation has the form \(y
= \beta_0 + \beta_1 x + \epsilon\). The predictor variable is
either a continuous variable or a binary categorical variable that takes
only two possible distinct values, such as success vs
failure, disease vs disease-free, etc.
The response must be a continuous normal variable whose mean may
be influenced by the predictor \(x\)
but not the variance.
The key assumptions for SLR are
- linearity: linear relationship between \(y\) and \(x\);
- diagnostic check: scatter plot of \(x\) and \(y\)
- deterministic predictor \(x\): the predictor variable is not
a random variable.
- No direct information, check this assumption
- normality: the only random variable \(y\) is a normal random variable with
density function \(N(\beta+0 + \beta_1 x,
\sigma)\), or \(\epsilon \rightarrow
N(0, \sigma)\).
- diagnostic check: Q-Q plot
- constant variance: this assumption is contained in
the above normality assumption.
- diagnostic check: residual plot, studentized residual plot
- Influential observations: This is also related to
the normality assumption
- diagnostic check: leverage plot (Cook’s distance)
SLR with A Continuous
Predictor
When the predictor variable is continuous, the interpretation of the
slope \(\beta_1\) reflects the change
in \(y\) when \(x\) increases by one unit. The sign of
\(\beta_1\) reflects the direction of
linear association between \(x\) and
\(y\). Next, we use a numerical example
to illustrate the regression modeling process. The data set can be found
at https://pengdsci.github.io/STA200/dataset/EduWage.csv.
The R function lm()
will be used to perform regression
analysis.
The variables in the data set are defined as
- wage: average hourly earnings
- educ: years of education
- exper: years potential experience
- tenure: years with current employer
- lwage: log(wage) - in economics, it is called log
wage.
- region: the geographic region of the
respondent
- smsa: A Standard Metropolitan Statistical Area
(SMSA) is a geographical region defined by the U.S. Office of Management
and Budget that consists of a core urban area with a substantial
population, along with adjacent communities that have a high degree of
economic and social integration with that core. SMSAs are used for
statistical purposes to analyze urbanization, population density, and
economic activities in metropolitan areas, providing insights into urban
data trends.
Step 1: Load data and explore the dataset.
## Load the dataset
edu.wage <- read.csv("https://pengdsci.github.io/STA200/dataset/EduWage.csv")
## summary of variables in the dataset
summary(edu.wage)
| wage educ exper tenure
| Min. : 0.530 Min. : 0.00 Min. : 1.00 Min. : 0.000
| 1st Qu.: 3.330 1st Qu.:12.00 1st Qu.: 5.00 1st Qu.: 0.000
| Median : 4.650 Median :12.00 Median :13.50 Median : 2.000
| Mean : 5.896 Mean :12.56 Mean :17.02 Mean : 5.105
| 3rd Qu.: 6.880 3rd Qu.:14.00 3rd Qu.:26.00 3rd Qu.: 7.000
| Max. :24.980 Max. :18.00 Max. :51.00 Max. :44.000
| lwage region smsa
| Min. :-0.6349 Length:526 Min. :0.0000
| 1st Qu.: 1.2030 Class :character 1st Qu.:0.0000
| Median : 1.5369 Mode :character Median :1.0000
| Mean : 1.6233 Mean :0.7224
| 3rd Qu.: 1.9286 3rd Qu.:1.0000
| Max. : 3.2181 Max. :1.0000
The R function summary(dataset.name)
returns a
five-number summary of all numerical variables in the dataset. There is
a categorical variable region
in the dataset. To see the
distribution of categorical variables, we use the R
function table(variable.name)
to see the frequency
distribution of the categorical variables.
table(edu.wage$region)
|
| northcen other south west
| 132 118 187 89
Step 2: objective and candidate model - we examine
whether education affects the wage. The candidate model to address this
objective will be the simple linear regression model. We first make a
scatter plot of educ
(horizontal axis) and
wage
(vertical axis).
plot(edu.wage$educ, # horizontal axis
edu.wage$wage, # vertical axis
xlab = "Years of Education", # horizontal label
ylab = "Hourly Wage", # vertical label
main = "Scatter Plot of Edu vs Wage" # title of the plot
)

The above plot shows a linear relationship but also shows
non-constant variance. This violates the SLR assumption. Economic
studies show that logarithmic wage has less variation. We next try to
log wages in the SLR. Before building the model, we make a scatter plot
of log wage vs years of education.
plot((edu.wage$educ)[-1], # horizontal axis
(edu.wage$lwage)[-1], # vertical axis
xlab = "Years of Education", # horizontal label
ylab = "Hourly log(Wage)", # vertical label
main = "Scatter Plot of Edu vs log(Wage)" # title of the plot
)

The above scatter indicates that the log wage is a better response
for SLR.
Step 3: Fitting SLR: \(\text{log wage} = \beta_0 + \beta_1
\text{educ}\) and perform residual diagnostics.
## linear model
lgw.model <- lm(lwage ~ educ, data = edu.wage)
## residual plot
par(mfrow=c(2,2)) # create a graphic grid with 4 graphical cells
plot(lgw.model)

Interpretations of Residual Diagnostic Plots:
- Residual vs Fitted - shows a minor violation of the
assumption of constant variance (the variance increases as the fitted
value increases)
- Q_Q Residual Plot - There is no significant
violation of the normal distribution
- Scale-Location Plot - no serious violation except a
few outliers (not influential)
- Residuals-Leverage - shows no influential
points.
Overall, there is a minor violation of the constant variance
assumption. We will learn methods in subsequent courses to refine the
model. For illustration, we decided to report the above model.
Step 4 - summarize the log wage model
summary(lgw.model)
|
| Call:
| lm(formula = lwage ~ educ, data = edu.wage)
|
| Residuals:
| Min 1Q Median 3Q Max
| -2.21158 -0.36393 -0.07263 0.29712 1.52339
|
| Coefficients:
| Estimate Std. Error t value Pr(>|t|)
| (Intercept) 0.583773 0.097336 5.998 3.74e-09 ***
| educ 0.082744 0.007567 10.935 < 2e-16 ***
| ---
| Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
|
| Residual standard error: 0.4801 on 524 degrees of freedom
| Multiple R-squared: 0.1858, Adjusted R-squared: 0.1843
| F-statistic: 119.6 on 1 and 524 DF, p-value: < 2.2e-16
Brief Report:
The estimated slope coefficient \(\hat{\beta}_1 = 0.082744\) indicates that
log wage increases by 0.082744 for each additional year of education
(\(p \approx 0\)). The coefficient of
determination \(R^2 \approx 0.1858\)
shows that the log wage and years of education have a weak linear
correlation.
Remarks: Here are a few comments on the general
principles of regression analysis
In this example, we use only two variables in the data set with
more than 2 variables to illustrate how to implement an SLR. In
practice, if you have more information (more variables) available in the
data, we should use all relevant information - this is the
general principle of all data analysis. This means we need to
use multiple regression to include two or more predictor variables! We
will cover general MLR in the next note.
Implication of SLR: An implication of SLR is
that all other variables do not affect the response variable \(y\). This also implies that, in general, an
SLR can never be an optimal model if it is invalid.
Choose an optimal subset of predictors: This
means we always start with multiple candidate models in multiple linear
regression (MLR) models. For example, if we have two variables \(x_1\) and \(x_2\), we can fit three different
first order (in predictor variables) MLR based on the
combinations of \(x_1\), \(x_2\), and \(x_1
+ x_2\). More on different MLRs will be discussed in the next
note.
SLR with A Binary
Predictor
We have discussed the regression approach to the two-sample t-test at
the beginning of the semester. Here we use the sample wage dataset and a
binary categorical smsa
(Standard Metropolitan Statistical
Area) to see whether the average wage in rural and
urban areas is different.
Recall the assumption in the two-sample test:
- Wage distributions in both populations (rural and urban populations)
are normal, equivalent to the normality assumption on
SLR
- The variances of wages in both populations are unknown but equal,
equivalent to the constant variance assumption in
SLR.
When using a software program, we have to specify the predictor
variable \(x\) to be a factor
(categorical variable). In R, the function factor()
converts a categorical or discrete numerical variable (with finite
distinct values) to a factor variable.
We next implement the SLR with a binary factor variable
(smsa
) and use log wage lwage
as the
response.
# lm model
smsa.lm <- lm(lwage ~ factor(smsa), data = edu.wage)
# residual plots
par(mfrow=c(2,2))
plot(smsa.lm)

1. Interpretations of Residual
Diagnostic Plots
- Residual-fitted Values: does not reveal special
patterns. The variances of the two groups seem to be similar to each
other.
- Q-Q Plot: No serious violation of the normality
assumption was found from the Q-Q plot. Note that there is an outlier in
the plot.
- Scale-location Plot: does not reveal any special
pattern except for an outlier (obs N0. 24).
- Residuals vs Leverage: The Cook’s distance of
observation does not have a significant leverage (no influential).
Overall, there is no significant violation of model assumptions. We
report the current model in the following:
2. Interpretations of Regression
Coefficients
The binary variablesmsa
has two values: 0 = rural area,
1 = urban area. In general, a binary variable (taking values 0 and 1) is
also commonly called a dummy variable in statistics and
regression analysis.
summary(smsa.lm)
|
| Call:
| lm(formula = lwage ~ factor(smsa), data = edu.wage)
|
| Residuals:
| Min 1Q Median 3Q Max
| -2.3240 -0.3700 -0.0797 0.3422 1.5439
|
| Coefficients:
| Estimate Std. Error t value Pr(>|t|)
| (Intercept) 1.45182 0.04314 33.652 < 2e-16 ***
| factor(smsa)1 0.23732 0.05076 4.676 3.73e-06 ***
| ---
| Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
|
| Residual standard error: 0.5213 on 524 degrees of freedom
| Multiple R-squared: 0.04005, Adjusted R-squared: 0.03822
| F-statistic: 21.86 on 1 and 524 DF, p-value: 3.733e-06
- (Intercept): \(\hat{\beta}_0 = 1.41518\) is the average
log wage of rural area (
smsa = 0
is the
baseline of the categorical variable sasa
).
\[
\log(\text{wage}_{\text{rural}}) = 1.41518 \ \implies \
\text{wage}_{\text{rural}} = e^{ 1.41518} = 4.117228
\]
The above equations convert the log wage to the original wage. That
is, the mean wage in rural areas is 4.117228.
- slope parameter (
factor(sasa)1
= level
1 of factor variable smsa =1
: urban area): \(\hat{\beta}_1 = 0.23732\) is the difference
of the average log wage between the current category (urban area) and
the baseline category (rural area). A more practical interpretation of
the slope requires some algebra:
\[
\log(\text{wage}_{\text{urban}}) - \log(\text{wage}_{\text{rural}}) =
0.23732 \ \implies \log
\frac{\text{wage}_{\text{urban}}}{\text{wage}_{\text{rural}}} = 0.23732
\]
Expanding both sides of the last equation in the above, we have
\[
\frac{\text{wage}_{\text{urban}}}{\text{wage}_{\text{rural}}} =
e^{0.23732} = 1.267847 \implies \text{wage}_{\text{urban}}= 1.267847
\times \text{wage}_{\text{rural}},
\]
We re-express the last equation in the above to get
\[
\text{wage}_{\text{urban}} - \text{wage}_{\text{rural}}= 1.267847 \times
\text{wage}_{\text{rural}} - \text{wage}_{\text{rural}} =
0.267847\text{wage}_{\text{rural}}
\]
Which is equivalent to
\[
\frac{\text{wage}_{\text{urban}} -
\text{wage}_{\text{rural}}}{\text{wage}_{\text{rural}}} = 0.267847.
\]
This means that the wage in urban area is
26.7847% higher than the rural area..
3. Relationship between SLR and
One-way ANOVA
First of all, we can extract a one-way ANOVA table from a linear
regression model using the R function anova(lm.object)
anova(smsa.lm)
| Analysis of Variance Table
|
| Response: lwage
| Df Sum Sq Mean Sq F value Pr(>F)
| factor(smsa) 1 5.941 5.9406 21.862 3.733e-06 ***
| Residuals 524 142.389 0.2717
| ---
| Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The F statistic in the above ANOVA test (with 1 degree of freedom in
the numerator and 524 degrees of freedom in the denominator) is
\[
F = 21.862.
\]
The t-test statistic in the SLR is a t distribution with 524 degrees
of freedom, which is close to the standard normal distribution.
\[
Z \approx T = 4.676.
\]
It can be proven that \(t_{\text{d.f}}^2 =
F_{1, \ \text{d.f}}\). This means the result of the t-test in SLR
and the F-test in the ANOVA procedure are identical. Therefore,
the SLR with a binary predictor can
the one-way ANOVA is a special SLR!.
Linear Regression
Approach to One-Way ANOVA
We claimed that one-way ANOVA is a special linear regression model
when there is a binary categorical predictor is included in the model.
However, a general CRD allows multiple treatments. In this section, we
will illustrate how to use linear regression to perform a general
one-way ANOVA with multiple treatment groups.
For ease of presentation, we continue using the wage dataset with log
wage as the dependent variable and region as a categorical treatment
factor (consisting of four groups: South, West, North-Central, and
Other). When performing linear regression with a categorical variable
that has more than two categories, we must introduce a series of dummy
variables to properly represent the multi-category variable.
Why Use Dummy Variables?
Encode Categorical Data: They allow categorical
variables (nominal or ordinal) to be included in regression
models.
Avoid Arbitrary Numerical Assignments: Using
numbers like 1, 2, 3 for categories implies an order or magnitude, which
may not exist (e.g., Red = 1, Green = 2, Blue = 3
falsely
suggests that Green is “greater” than Red).
Interpretability: Each dummy variable represents
the presence (1) or absence (0) of a category, making coefficients easy
to interpret. To be more specific, the coefficient of a dummy variable
represents the discrepancy between the category associated with the
dummy variable and the baseline category.
Steps to Create Dummy Variables from a Multi-Category
Variable
choose a baseline category: The baseline
category serves as a reference, allowing other categories to be compared
against it.
- Most software programs automatically set the baseline as the
category with the smallest value (e.g., the first in alphabetical order
for categorical variables).
Create Dummy Variables: For each non-baseline
category, define a dummy variable labeling that category. For example,
region = (northcen, other, south, west)
, the three dummy
variables are defined as
- dummy.other = 1 if lived in
other
region, 0 if not in
other
region.
- dummy.south = 1 if lived in
south
and 0 if not in
south
region;
- dummy.west = 1 if lived in
west
and 0 if not in
west
.
In general, a categorical variable has \(k\) categories, and we need to define \(k-1\) dummy variables. For example,
south |
0 |
1 |
0 |
west |
0 |
0 |
1 |
northcen |
0 |
0 |
0 |
other |
1 |
0 |
0 |
south |
0 |
1 |
0 |
- Interpretation of Dummy Variables in
Regression
The coefficients for other
, south
, and
west
represent the difference from the reference category
(northcen
).
- Dummy variables in R
- Categorical variable with character values: In this
case, R will define dummy variables internally and use the default
reference category.
- Categorical variable with values in numerical form:
In this case, we must use R’s
factor()
function to convert
the categorical variable into a factor variable (numeric values will be
treated as category labels). R then internally defines dummy variables
and selects the baseline category as the one with the smallest numerical
label.
- If the default reference category is not preferred, you can use R’s
relevel()
function to manually specify a custom baseline
category for easier interpretation.
# Example data
data <- data.frame(color = c("Red", "Green", "Blue", "Green", "Red"))
# Set "Green" as the baseline (reference) category
data$color <- factor(data$color)
data$color <- relevel(data$color, ref = "Green")
# Check levels (first level is the baseline)
levels(data$color) # Output: "Green" "Red" "Blue"
| [1] "Green" "Blue" "Red"
On the Significance of the
Categorical Variable:
- If any of the dummy variables is statistically
significant (i.e., p-value < 0.05), the
original categorical variable is considered
significant.
- If all dummy variables are statistically
insignificant, the original categorical variable is
insignificant.
- If the original categorical variable is
insignificant, it should be excluded from the
regression model in real real-world application.
In the output of
lm()
, the F test in the bottom portion provides the
significance test of the categorical variable.
This F test is the same F
test in the one-way ANOVA!!!
An Numerical
Example
We use the plant growth dataset to build a
regression model with the multi-category predictor group
and compare it with a one-way ANOVA procedure. The data set is at
<>. We will follow several logical steps to conduct the
analysis.
Step 1: fit candidate model and perform
diagnostics
## Load the dataset
plant <- read.csv("https://pengdsci.github.io/STA200//dataset/oneWayPlantGrowth.csv")
##
plant.lm <- lm(weight ~ group, data = plant) # factor(group) will also work
## residual plots
par(mfrow=c(2,2))
plot(plant.lm)

None of the above residual plots shows significant violations of
model assumptions except for a few outliers that are not influential. We
report the model.
Step 2: Reporting the linear model
summary(plant.lm)
|
| Call:
| lm(formula = weight ~ group, data = plant)
|
| Residuals:
| Min 1Q Median 3Q Max
| -1.0710 -0.4180 -0.0060 0.2627 1.3690
|
| Coefficients:
| Estimate Std. Error t value Pr(>|t|)
| (Intercept) 5.0320 0.1971 25.527 <2e-16 ***
| grouptrt1 -0.3710 0.2788 -1.331 0.1944
| grouptrt2 0.4940 0.2788 1.772 0.0877 .
| ---
| Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
|
| Residual standard error: 0.6234 on 27 degrees of freedom
| Multiple R-squared: 0.2641, Adjusted R-squared: 0.2096
| F-statistic: 4.846 on 2 and 27 DF, p-value: 0.01591
Interpretation of the output
The explicit model formula has only the original group
categorical variable with three categories. In fact, the implicit model
formula uses dummy variables. In other words, the actual model formula
used in the model is \(\text{weight} = \beta_0
+ \beta_1 \text{grouptrt1} + \beta_2 \text{grouptrt2}\),
where \(\beta_0 = \mu_{\text{ctr}}\), \(\beta_1 = \mu_{\text{trt1}} -
\mu_{\text{ctr}}\) and \(\beta_2 =
\mu_{\text{trt2}} - \mu_{\text{ctr}}\)
The F test in the bottom portion yields a p-value of 0.01591. At
a significance level of 0.05, we reject the null hypothesis that
region is significant. In
other words, this F-test tests the
null hypothesis: \(H_0: \beta_1 = \beta_2 =
0\). This equivalent to
\(H_0:
\mu_{\text{ctr}} = \mu_{\text{trt1}} =
\mu_{\text{trt2}}\).
This is exactly the F test in the
one-way ANOVA! We will extract the one-way ANOVA from
the linear model shortly.
Interpretation of Regression coefficients: At
the significance level of 0.05, neither of the two dummy variables is
statistically significant.
- \(\beta_0 = \mu_{\text{ctr}}\),
This represents the mean of the baseline category. The p-value tests the
hypothesis \(H_0: \beta_0 = 0\).
- \(\hat{\beta}_1 = \hat{\mu}_{\text{trt1}}
- \hat{\mu}_{\text{ctr}} = -0.3710\): The p-value of
0.1944 corresponds to testing the hypothesis \(H_0: \beta_1 = 0\) (or equivalently, \(H_0: \mu_{\text{trt1}} - \mu_{\text{ctr}} =
0\)). The p-value indicates no statistically significant
difference between
trt1
and ctr
. The
negative sign of the estimate suggests that the sample mean of
ctr
is higher than that of trt1
.
- \(\hat{\beta}_2 = \hat{\mu}_{\text{trt2}}
- \hat{\mu}_{\text{ctr}} =0.4940\), The p-value of
0.0877 corresponds to testing the hypothesis \(H_0: \beta_2 = 0\) (or equivalently, \(H_0: \mu_{\text{trt2}} - \mu_{\text{ctr}} =
0\)). The p-value indicates no statistically significant
difference between
trt2
and ctr
. The
positive sign of the estimate suggests that the sample mean of
trt2
is higher than that of ctr
.
Next, we extract the one-way ANOVA table directly from the above
linear regression model.
# extract ANOVA table directly from linear regression model
anova(plant.lm)
| Analysis of Variance Table
|
| Response: weight
| Df Sum Sq Mean Sq F value Pr(>F)
| group 2 3.7663 1.8832 4.8461 0.01591 *
| Residuals 27 10.4921 0.3886
| ---
| Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The F-test from the one-way ANOVA table above is identical to the one
reported in the previous regression model. We can also generate the same
one-way ANOVA table using R’s built-in functionaov()
The coefficients associated with dummy variables in the regression
output represent the difference between the mean of the underlying
category and that of the baseline category. That is, \(\hat{\beta}_1 = \hat{\mu}_{\text{trt1}} -
\hat{\mu}_{\text{ctr}} = -0.3710\) and \(\hat{\beta}_2 = \hat{\mu}_{\text{trt2}} -
\hat{\mu}_{\text{ctr}} =0.4940\). This information is given in
Tukey’s HSD (see the output of TukeyHSD()
)
plant.aov <- aov(weight ~ group, data = plant)
TukeyHSD(plant.aov)
| Tukey multiple comparisons of means
| 95% family-wise confidence level
|
| Fit: aov(formula = weight ~ group, data = plant)
|
| $group
| diff lwr upr p adj
| trt1-ctrl -0.371 -1.0622161 0.3202161 0.3908711
| trt2-ctrl 0.494 -0.1972161 1.1852161 0.1979960
| trt2-trt1 0.865 0.1737839 1.5562161 0.0120064
The first two estimated differences (trt1 - ctr
and
trt2 - ctr
) correspond to the regression coefficients of
the dummy variables in the previous model. The p-values reported in the
regression model are unadjusted (based on individual tests), whereas
Tukey’s HSD is a group test, and its corresponding p-values are adjusted
to control the overall Type I error rate (i.e., to prevent inflation of
the false positive rate).
Remarks:
The linear regression model used to perform one-way ANOVA has
multiple dummy predictor variables in the model formula
(although implicitly expressed). In other words, the regression model
for the one-way ANOVA is a special multiple linear
Regression (MLR) model.
Multiple Linear Regression (MLR) maintains the same assumptions
as simple linear regression: independent and identically distributed
(i.i.d.) observations, deterministic predictors, linearity between
response and predictor, normality of residuals, and homoscedasticity
(constant variance). Since MLR involves multiple predictor variables, an
additional assumption is the absence of high correlations between
predictors. Violation of this assumption is referred to as
multicollinearity in regression modeling.
The reason we encode a categorical variable with k categories
into (k-1) dummy variables (rather than k) is to avoid multicollinearity
issues. For example, suppose we have a categorical variable
Education with 3 levels: High School
(baseline/reference), Bachelor’s, and Master’s. If we create 3 dummy
variables:
- D1 = 1 if High School, 0 otherwise
- D2 = 1 if Bachelor’s, 0 otherwise
- D3 = 1 if Master’s, 0 otherwise
This creates perfect
multicollinearity because for every observation: D1 +
D2 + D3 = 1 (always)!!!
To conclude this section, watch the YouTube video (https://www.youtube.com/watch?v=CMAwKuCw5CM&list=PLfQppi3mzF5nQzSm-RWQnvHFg46GQVK_4&index=4)
that focuses on the ANOVA table extracted from the linear
regression.
Multiple Linear
Regression Approach to Two-way ANOVA
This section focuses on linear regression with two
categorical variables, each with multiple levels. We have
previously learned about two-way ANOVA based on a replicated Randomized
Block Design (RBD), which allows for inference on interaction effects.
The linear regression model to be discussed will also include an
interaction term.
Since the underlying concept is similar to the one-way ANOVA covered
in the previous section, the explicit model formula remains relatively
simple. However, the implicit model formula for linear regression with
two categorical variables (including an interaction effect) is more
complex than that of one-way ANOVA. We will use an example to illustrate
some key features of multiple linear regression (MLR) involving only
categorical variables with an interaction term.
The dataset recorded the yield of different crops under different
fertilizers. The two-way data table is given below.

We have used various R commands earlier to convert a two-way data
table to an R dataframe for regression modeling. We next use similar
code to convert the above table to a dataframe.
## To avoid typing errors, we input the table cell by cell from the data table
crop.data <- data.frame(
Fertilizer = rep(c("Blend X", "Blend Y", "Blend Z"), each = 20),
Crop = rep(rep(c("Wheat", "Corn", "Soy", "Rice"), each = 5), times = 3),
Yield = c(123, 156, 112, 100, 168, # Blend X - Wheat
128, 150, 174, 116, 109, # Blend X - Corn
166, 178, 187, 133, 195, # Blend X - Soy
151, 125, 117, 155, 138, # Blend X - Rice
##
135, 130, 176, 120, 155, # Blend Y - Wheat
175, 132, 120, 187, 184, # Blend Y - Corn
140, 145, 159, 131, 126, # Blend Y - Soy
167, 188, 142, 167, 168, # Blend Y - Rice
##
156, 180, 147, 146, 193, # Blend Z - Wheat
186, 138, 178, 176, 190, # Blend Z - Corn
185, 206, 188, 165, 188, # Blend Z - Soy
175, 173, 154, 191, 169) # Blend Z - Rice
)
# Convert factors to factors (important for modeling)
crop.data$Fertilizer <- as.factor(crop.data$Fertilizer)
crop.data$Crop <- as.factor(crop.data$Crop)
Next, we fit a linear regression model with an interaction term and
list the terms (dummy variables) in the implicit internal model formula
by using two R functions model.matrix(model.name)
and
colnames(model.matrix.name)
. See how these R functions are
called in the following code chunk.
## Explicit form is still a simple
crop.lm <- lm(Yield ~ Crop * Fertilizer, data = crop.data)
## model matrix provides all dummy variables implicitly defined in the R
model.mtx <- model.matrix(crop.lm)
## extract the column names of the model matrix ==> list of dummy variables in the
## implicit internal model formula
colnames(model.mtx)
| [1] "(Intercept)" "CropRice"
| [3] "CropSoy" "CropWheat"
| [5] "FertilizerBlend Y" "FertilizerBlend Z"
| [7] "CropRice:FertilizerBlend Y" "CropSoy:FertilizerBlend Y"
| [9] "CropWheat:FertilizerBlend Y" "CropRice:FertilizerBlend Z"
| [11] "CropSoy:FertilizerBlend Z" "CropWheat:FertilizerBlend Z"
These dummy variables will appear in the output of the regression
model in the subsequent model output. Before summarizing the model, we
check the model assumptions to see whether significant violations exist
using residual diagnostic plots.
par(mfrow = c(2,2)) # define the layout with 2x2 graphical panels
plot(crop.lm)

The residual plots look fine except for a pattern in the Q-Q plot,
which indicates the distribution of the residuals is slightly skewed to
the left. We will not explore methods of remedies in this class, but
they will be discussed in the subsequent classes. Next, we report the
results of the models.
summary(crop.lm)
|
| Call:
| lm(formula = Yield ~ Crop * Fertilizer, data = crop.data)
|
| Residuals:
| Min 1Q Median 3Q Max
| -39.60 -15.00 0.70 15.45 38.60
|
| Coefficients:
| Estimate Std. Error t value Pr(>|t|)
| (Intercept) 135.400 9.639 14.048 < 2e-16 ***
| CropRice 1.800 13.631 0.132 0.89549
| CropSoy 36.400 13.631 2.670 0.01031 *
| CropWheat -3.600 13.631 -0.264 0.79283
| FertilizerBlend Y 24.200 13.631 1.775 0.08218 .
| FertilizerBlend Z 38.200 13.631 2.802 0.00729 **
| CropRice:FertilizerBlend Y 5.000 19.277 0.259 0.79646
| CropSoy:FertilizerBlend Y -55.800 19.277 -2.895 0.00570 **
| CropWheat:FertilizerBlend Y -12.800 19.277 -0.664 0.50987
| CropRice:FertilizerBlend Z -3.000 19.277 -0.156 0.87698
| CropSoy:FertilizerBlend Z -23.600 19.277 -1.224 0.22683
| CropWheat:FertilizerBlend Z -5.600 19.277 -0.291 0.77269
| ---
| Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
|
| Residual standard error: 21.55 on 48 degrees of freedom
| Multiple R-squared: 0.4543, Adjusted R-squared: 0.3292
| F-statistic: 3.632 on 11 and 48 DF, p-value: 0.0008828
Output
Interpretations
The F-test in the bottom portion of the output indicates that at
least one factor (crop
or fertilizer
or both)
is significant ()
Intercept - the mean of yields of corn using
fertilizer X. i.e., (128 + 150 + 174 + 116 +
109)/5 = 135.4. This is the baseline category, defined
by Corn
and Blend X
. All other categories will
be compared to this baseline either directly or indirectly.
- The coefficients for
CropRice
, CropSoy
,
and CropWheat
represent the difference in mean
yield between these crops and Corn
when using
Blend X
fertilizer.
- The coefficients for
FertilizerBlend Y
and
FertilizerBlend Z
represent the difference in mean
yield for Corn
when comparing Blend Y
and Blend Z
to the baseline (Blend X
).
- The coefficients for the interaction terms are not straightforward
to interpret because they represent combined effects. Refer to the
annotated output and original data table below to understand how these
interaction term coefficients were calculated.

As we did with the one-way ANOVA, we can also extract the two-way
ANOVA table directly from the linear regression model above.
anova(crop.lm)
| Analysis of Variance Table
|
| Response: Yield
| Df Sum Sq Mean Sq F value Pr(>F)
| Crop 3 2965.7 988.6 2.1282 0.1089382
| Fertilizer 2 9702.2 4851.1 10.4436 0.0001716 ***
| Crop:Fertilizer 6 5892.6 982.1 2.1143 0.0687635 .
| Residuals 48 22296.4 464.5
| ---
| Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The two-way ANOVA table provides three F-tests for assessing the two
individual factors and their interaction effect, whereas the F-test in
the regression output only tests whether all factors are jointly
insignificant—a global goodness-of-fit measure. From this perspective,
the two-way ANOVA F-tests offer more granular insights. However,
regression coefficient inference allows for more detailed testing at
individual factor levels, as well as for interaction effects between
factor levels. Although Tukey’s HSD procedure provides confidence
intervals (and family-wise tests for simultaneous comparisons), it does
not explicitly account for interaction effects in the multiple
comparisons.
## fit an anova model since TukeyHSD() requires the aov() object
crop.aov <- aov(Yield ~ Crop * Fertilizer, data = crop.data)
## HSD calls
TukeyHSD(crop.aov)
| Tukey multiple comparisons of means
| 95% family-wise confidence level
|
| Fit: aov(formula = Yield ~ Crop * Fertilizer, data = crop.data)
|
| $Crop
| diff lwr upr p adj
| Rice-Corn 2.466667 -18.47792 23.411252 0.9891976
| Soy-Corn 9.933333 -11.01125 30.877918 0.5910428
| Wheat-Corn -9.733333 -30.67792 11.211252 0.6069146
| Soy-Rice 7.466667 -13.47792 28.411252 0.7787573
| Wheat-Rice -12.200000 -33.14459 8.744585 0.4163283
| Wheat-Soy -19.666667 -40.61125 1.277918 0.0728352
|
| $Fertilizer
| diff lwr upr p adj
| Blend Y-Blend X 8.30 -8.183166 24.78317 0.4486138
| Blend Z-Blend X 30.15 13.666834 46.63317 0.0001620
| Blend Z-Blend Y 21.85 5.366834 38.33317 0.0066534
|
| $`Crop:Fertilizer`
| diff lwr upr p adj
| Rice:Blend X-Corn:Blend X 1.8 -45.0050873 48.605087 1.0000000
| Soy:Blend X-Corn:Blend X 36.4 -10.4050873 83.205087 0.2718890
| Wheat:Blend X-Corn:Blend X -3.6 -50.4050873 43.205087 1.0000000
| Corn:Blend Y-Corn:Blend X 24.2 -22.6050873 71.005087 0.8228174
| Rice:Blend Y-Corn:Blend X 31.0 -15.8050873 77.805087 0.5076482
| Soy:Blend Y-Corn:Blend X 4.8 -42.0050873 51.605087 0.9999999
| Wheat:Blend Y-Corn:Blend X 7.8 -39.0050873 54.605087 0.9999854
| Corn:Blend Z-Corn:Blend X 38.2 -8.6050873 85.005087 0.2115608
| Rice:Blend Z-Corn:Blend X 37.0 -9.8050873 83.805087 0.2506320
| Soy:Blend Z-Corn:Blend X 51.0 4.1949127 97.805087 0.0219849
| Wheat:Blend Z-Corn:Blend X 29.0 -17.8050873 75.805087 0.6066374
| Soy:Blend X-Rice:Blend X 34.6 -12.2050873 81.405087 0.3423125
| Wheat:Blend X-Rice:Blend X -5.4 -52.2050873 41.405087 0.9999997
| Corn:Blend Y-Rice:Blend X 22.4 -24.4050873 69.205087 0.8838055
| Rice:Blend Y-Rice:Blend X 29.2 -17.6050873 76.005087 0.5967325
| Soy:Blend Y-Rice:Blend X 3.0 -43.8050873 49.805087 1.0000000
| Wheat:Blend Y-Rice:Blend X 6.0 -40.8050873 52.805087 0.9999990
| Corn:Blend Z-Rice:Blend X 36.4 -10.4050873 83.205087 0.2718890
| Rice:Blend Z-Rice:Blend X 35.2 -11.6050873 82.005087 0.3177646
| Soy:Blend Z-Rice:Blend X 49.2 2.3949127 96.005087 0.0315296
| Wheat:Blend Z-Rice:Blend X 27.2 -19.6050873 74.005087 0.6939901
| Wheat:Blend X-Soy:Blend X -40.0 -86.8050873 6.805087 0.1614830
| Corn:Blend Y-Soy:Blend X -12.2 -59.0050873 34.605087 0.9988789
| Rice:Blend Y-Soy:Blend X -5.4 -52.2050873 41.405087 0.9999997
| Soy:Blend Y-Soy:Blend X -31.6 -78.4050873 15.205087 0.4784497
| Wheat:Blend Y-Soy:Blend X -28.6 -75.4050873 18.205087 0.6263743
| Corn:Blend Z-Soy:Blend X 1.8 -45.0050873 48.605087 1.0000000
| Rice:Blend Z-Soy:Blend X 0.6 -46.2050873 47.405087 1.0000000
| Soy:Blend Z-Soy:Blend X 14.6 -32.2050873 61.405087 0.9946081
| Wheat:Blend Z-Soy:Blend X -7.4 -54.2050873 39.405087 0.9999915
| Corn:Blend Y-Wheat:Blend X 27.8 -19.0050873 74.605087 0.6653705
| Rice:Blend Y-Wheat:Blend X 34.6 -12.2050873 81.405087 0.3423125
| Soy:Blend Y-Wheat:Blend X 8.4 -38.4050873 55.205087 0.9999691
| Wheat:Blend Y-Wheat:Blend X 11.4 -35.4050873 58.205087 0.9993994
| Corn:Blend Z-Wheat:Blend X 41.8 -5.0050873 88.605087 0.1210713
| Rice:Blend Z-Wheat:Blend X 40.6 -6.2050873 87.405087 0.1469832
| Soy:Blend Z-Wheat:Blend X 54.6 7.7949127 101.405087 0.0103529
| Wheat:Blend Z-Wheat:Blend X 32.6 -14.2050873 79.405087 0.4309559
| Rice:Blend Y-Corn:Blend Y 6.8 -40.0050873 53.605087 0.9999964
| Soy:Blend Y-Corn:Blend Y -19.4 -66.2050873 27.405087 0.9529104
| Wheat:Blend Y-Corn:Blend Y -16.4 -63.2050873 30.405087 0.9861932
| Corn:Blend Z-Corn:Blend Y 14.0 -32.8050873 60.805087 0.9962200
| Rice:Blend Z-Corn:Blend Y 12.8 -34.0050873 59.605087 0.9982727
| Soy:Blend Z-Corn:Blend Y 26.8 -20.0050873 73.605087 0.7126723
| Wheat:Blend Z-Corn:Blend Y 4.8 -42.0050873 51.605087 0.9999999
| Soy:Blend Y-Rice:Blend Y -26.2 -73.0050873 20.605087 0.7399717
| Wheat:Blend Y-Rice:Blend Y -23.2 -70.0050873 23.605087 0.8584571
| Corn:Blend Z-Rice:Blend Y 7.2 -39.6050873 54.005087 0.9999936
| Rice:Blend Z-Rice:Blend Y 6.0 -40.8050873 52.805087 0.9999990
| Soy:Blend Z-Rice:Blend Y 20.0 -26.8050873 66.805087 0.9422853
| Wheat:Blend Z-Rice:Blend Y -2.0 -48.8050873 44.805087 1.0000000
| Wheat:Blend Y-Soy:Blend Y 3.0 -43.8050873 49.805087 1.0000000
| Corn:Blend Z-Soy:Blend Y 33.4 -13.4050873 80.205087 0.3943466
| Rice:Blend Z-Soy:Blend Y 32.2 -14.6050873 79.005087 0.4497486
| Soy:Blend Z-Soy:Blend Y 46.2 -0.6050873 93.005087 0.0559743
| Wheat:Blend Z-Soy:Blend Y 24.2 -22.6050873 71.005087 0.8228174
| Corn:Blend Z-Wheat:Blend Y 30.4 -16.4050873 77.205087 0.5372002
| Rice:Blend Z-Wheat:Blend Y 29.2 -17.6050873 76.005087 0.5967325
| Soy:Blend Z-Wheat:Blend Y 43.2 -3.6050873 90.005087 0.0956612
| Wheat:Blend Z-Wheat:Blend Y 21.2 -25.6050873 68.005087 0.9163288
| Rice:Blend Z-Corn:Blend Z -1.2 -48.0050873 45.605087 1.0000000
| Soy:Blend Z-Corn:Blend Z 12.8 -34.0050873 59.605087 0.9982727
| Wheat:Blend Z-Corn:Blend Z -9.2 -56.0050873 37.605087 0.9999234
| Soy:Blend Z-Rice:Blend Z 14.0 -32.8050873 60.805087 0.9962200
| Wheat:Blend Z-Rice:Blend Z -8.0 -54.8050873 38.805087 0.9999811
| Wheat:Blend Z-Soy:Blend Z -22.0 -68.8050873 24.805087 0.8953849
The following annotated output illustrates how to calculate various
differences in the results of Tukey’s HSD procedure.

We can see that Tukey’s HSD.
The following YouTube video (28 minutes) is one of the very few that
uses a linear regression approach to perform ANOVA analysis (https://www.youtube.com/watch?v=CS5ogBL-MHo). Please pay
close attention to the explanation of the linear regression output,
particularly the explanation of the two-way ANOVA with interaction
term.
Finally, practice two-way ANOVA using regression approaches based on
the following data table with two binary factors. Because both factors
are binary, the interpretation of the output should be
straightforward.

LS0tDQp0aXRsZTogIkxpbmVhciBSZWdyZXNzaW9uIE1vZGVscyB3aXRoIENhdGVnb3JpY2FsIFByZWRpY3RvcnMiDQphdXRob3I6ICJDaGVuZyBQZW5nIg0KZGF0ZTogIlNUQTIwMCBTdGF0aXN0aWNzIElJICINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgdGhlbWU6IGx1bWVuDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBmaWdfd2lkdGg6IDUNCiAgICBmaWdfaGVpZ2h0OiA0DQotLS0NCg0KYGBgez1odG1sfQ0KDQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpkaXYjVE9DIGxpIHsNCiAgICBsaXN0LXN0eWxlOm5vbmU7DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDI0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgxIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIwcHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgyIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCjwvc3R5bGU+DQpgYGANCg0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQoNCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCiMga25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSAiQzovVXNlcnMvNzVDUEVORy9PbmVEcml2ZSAtIFdlc3QgQ2hlc3RlciBVbml2ZXJzaXR5IG9mIFBBL0RvY3VtZW50cyIpDQojIGtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gIkM6XFxTVEE0OTBcXHcwNSIpDQoNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFRSVUUsICAgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSAifCIpDQpgYGANCg0KXA0KDQoNCiMgSW50cm9kdWN0aW9uDQoNCldlIGhhdmUgYnJpZWZseSBpbnRyb2R1Y2VkIHRoZSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgZWFybGllciB3aXRoIGFuIGV4cGxpY2l0IGV4cHJlc3Npb24uDQoNCiQkDQp5ID0gXGJldGFfMCArIFxiZXRhXzEgeCArIFxlcHNpbG9uLA0KJCQNCg0KV2hlcmUgJHkkIGlzIGEgY29udGludW91cyByYW5kb20gbnVtZXJpY2FsIHZhcmlhYmxlLCAkeCQgaXMgZWl0aGVyIGEgbnVtZXJpY2FsIHZhcmlhYmxlIG9yIGEgYmluYXJ5IGNhdGVnb3JpY2FsIHZhcmlhYmxlLCBhbmQgJFxlcHNpbG9uIFxyaWdodGFycm93IE4oMCwgXHNpZ21hKSQsIHRoZSBiYXNpYyBhcHBsaWNhdGlvbnMgb2YgYSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgYXJlIHR3b2ZvbGQ6DQoNCigxKSAqKkFzc2VzcyoqIHRoZSBsaW5lYXIgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgcmVzcG9uc2UgdmFyaWFibGUgKCR5JCkgYW5kIHRoZSBwcmVkaWN0b3IgdmFyaWFibGUgKCR4JCkuDQoNCigyKSAqKlByZWRpY3QqKiB0aGUgcmVzcG9uc2UgZm9yIGdpdmVuIG5ldyB2YWx1ZXMgb2YgdGhlIHByZWRpY3RvciB2YXJpYWJsZSAkeCQuDQoNCkluIGdlbmVyYWwsIHJlZ3Jlc3Npb24gbW9kZWxpbmcgaXMgYW4gaXRlcmF0aXZlIHByb2Nlc3MgaW4gcmVhbC13b3JsZCBhcHBsaWNhdGlvbnMsIGFzIGlsbHVzdHJhdGVkIGluIHRoZSBmb2xsb3dpbmcgY2hhcnQuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjcwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDUvcmVnLXByb2Nlc3MucG5nIikNCmBgYA0KDQpJbiB0aGUgY291cnNlIHByb2plY3QgYW5kIGRhdGEgYW5hbHlzaXMsIHdlIGZvY3VzIG9uIHRoZSBpdGVyYXRpdmUgbG9vcCBvZiBtb2RlbCBpZGVudGlmaWNhdGlvbiBhbmQgcmVwb3J0aW5nIG9uIHRoZSBmaW5hbCBtb2RlbC4gVG8gYmUgbW9yZSBzcGVjaWZpYywgYXNzdW1pbmcgd2UgaGF2ZSBhbiBhbmFseXRpYyBkYXRhIHNldCB0aGF0IGlzIHJlYWR5IGZvciBtb2RlbGluZywNCg0KKiAqKlNlbGVjdCBhcHByb3ByaWF0ZSBjYW5kaWRhdGUgbW9kZWxzIHRvIGFkZHJlc3MgdGhlIHByYWN0aWNhbCBxdWVzdGlvbnMqKiAtIFRoaXMgaW5jbHVkZXMgY2hlY2tpbmcgbW9kZWwgYXNzdW1wdGlvbnMgYW5kIGVuc3VyaW5nIHRoZSBhbmFseXRpYyBkYXRhc2V0IGNvbnRhaW5zIHN1ZmZpY2llbnQgaW5mb3JtYXRpb24gZm9yIHRoZSBjYW5kaWRhdGUgbW9kZWxzLiA8Zm9udCBjb2xvciA9ICJibHVlIj4qXGNvbG9ye2JsdWV9V2UgaGF2ZSBoaWdobGlnaHRlZCBhbGwgYXNzdW1wdGlvbnMgd2hlbiBpbnRyb2R1Y2luZyBuZXcgbW9kZWxzIGluIHRoZSBwcmV2aW91cyBub3Rlcy4qPC9mb250Pg0KDQoqICoqRml0IGNhbmRpZGF0ZSBtb2RlbHMgdG8gdGhlIGRhdGEqKiAtIFRoaXMgc3RlcCBpbnZvbHZlcyB2ZXJpZnlpbmcgdGhlIG91dHB1dHMgdG8gZW5zdXJlIHRoZSBtb2RlbCBwYXJhbWV0ZXJzIChlLmcuLCBjb2VmZmljaWVudHMpIGFyZSBhcHByb3ByaWF0ZWx5IGVzdGltYXRlZC4NCg0KPiA8Zm9udCBjb2xvciA9ICJyZWQiPioqXGNvbG9ye3JlZH1Ob3RlOioqICp0aGUgZml0dGVkIG1vZGVscyBpbiB0aGlzIHN0ZXAgbWF5IG5vdCBiZSB2YWxpZCBvciBvcHRpbWFsLCB3ZSBzaG91bGQgbm90IGludGVycHJldCB0aGUgbW9kZWwgYXQgdGhpcyBwb2ludC4qICoqV2Ugb25seSByZXBvcnQgdGhlIGZpbmFsIG1vZGVsIG9idGFpbmVkIGZyb20gdGhlIGl0ZXJhdGl2ZSBtb2RlbCBpZGVudGlmaWNhdGlvbiBwcm9jZXNzLioqIDwvZm9udD4NCg0KKiAqKk1vZGVsIGRpYWdub3N0aWNzKiogLSBUaGlzIGlzIHRoZSBtb3N0IGNydWNpYWwgc3RlcCBpbiBhbnkgcmVncmVzc2lvbiBhbmFseXNpcywgd2hlcmUgd2UgYXNzZXNzIHdoZXRoZXIgYWxsIGFzc3VtcHRpb25zIG9mIHRoZSBjYW5kaWRhdGUgbW9kZWxzIGFyZSBzYXRpc2ZpZWQuIEZvciBleGFtcGxlLCB3ZSBhcHBseSByZXNpZHVhbCBkaWFnbm9zdGljIG1ldGhvZHMgKGNvbW1vbmx5IHVzZWQgaW4gbGluZWFyIHJlZ3Jlc3Npb24pIHRvIGV2YWx1YXRlIGxpbmVhcml0eSwgbm9ybWFsaXR5LCBob21vc2NlZGFzdGljaXR5IChjb25zdGFudCB2YXJpYW5jZSksIGFuZCBvdGhlciBrZXkgYXNzdW1wdGlvbnMuIElmIG5vIHZpb2xhdGlvbnMgYXJlIGRldGVjdGVkLCB3ZSB0aGVuIHVzZSBhcHBsaWNhdGlvbi1zcGVjaWZpYyBwZXJmb3JtYW5jZSBtZWFzdXJlcyB0byBzZWxlY3QgdGhlIGJlc3QgbW9kZWwgZm9yIHJlcG9ydGluZyBhbmQgaW1wbGVtZW50YXRpb24uDQoNCiogKipNb2RlbCByZW1lZHkgYW5kIHJlZmluZW1lbnQqKiAtIElmIG9uZSBvciBtb3JlIGFzc3VtcHRpb25zIGFyZSB2aW9sYXRlZCwgd2UgbmVlZCB0byB1c2UgdmFyaW91cyBtZXRob2RzIHRvIGZpeCB0aGUgcHJvYmxlbXMuICpXZSB3aWxsIG5vdCBkaXNjdXNzIHRoaXMgbWFqb3IgdG9waWMgaW4gdGhpcyBjbGFzcywgYnV0IHdpbGwgY292ZXIgdGhpcyBjcml0aWNhbCB0b3BpYyBpbiBkZXRhaWwgaW4gc3Vic2VxdWVudCBjb3Vyc2VzKi4gIA0KDQoqICoqRW50ZXIgdGhlIHJlZmluZWQvbW9kaWZpZWQgbW9kZWwgaW50byB0aGUgbG9vcCBmb3IgdGhlIG5leHQgaXRlcmF0aW9uKiogLSBUaGUgcmVmaW5lZCBvciBtb2RpZmllZCBtb2RlbCB3aWxsIGJlIHJlZml0dGVkLCBhbmFseXplZCwgYW5kIGRpYWdub3NlZCB0byBkZXRlcm1pbmUgd2hldGhlciBhbnkgdmlvbGF0aW9ucyByZW1haW4uIFRoaXMgcHJvY2VzcyBjb250aW51ZXMgaXRlcmF0aXZlbHkgdW50aWwgdGhlIGZpbmFsIHZhbGlkIGFuZCBvcHRpbWFsIG1vZGVsIGlzIGlkZW50aWZpZWQuDQoNCiogKipGaW5hbCBtb2RlbCByZXBvcnRpbmcqKiAtIFRoaXMgdG9waWMgd2lsbCBub3QgYmUgZW1waGFzaXplZCBpbiB0aGlzIGNsYXNzIGJ1dCB3aWxsIGJlIGhpZ2hsaWdodGVkIGluIHN1YnNlcXVlbnQgc3RhdGlzdGljYWwgbW9kZWxpbmcgY2xhc3Nlcy4NCg0KDQpJbiB0aGlzIG5vdGUsIHdlIHdpbGwgZXh0ZW5kIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiB0byBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBieSBpbmNvcnBvcmF0aW5nIHR3byBvciBtb3JlIHByZWRpY3RvciB2YXJpYWJsZXMgaW50byB0aGUgbW9kZWwuIFdlIGJlZ2luIGJ5IHJldmlzaXRpbmcgdGhlIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBkaXNjdXNzZWQgZWFybGllciB0aGlzIHNlbWVzdGVyLiBOZXh0LCB3ZSB3aWxsIGdlbmVyYWxpemUgdGhlIGJpbmFyeSBjYXRlZ29yaWNhbCBwcmVkaWN0b3IgdG8gbXVsdGktY2F0ZWdvcnkgcHJlZGljdG9ycyB0aHJvdWdoIHRoZSB1c2Ugb2YgYmluYXJ5IGluZGljYXRvciB2YXJpYWJsZXMg4oCTIGVmZmVjdGl2ZWx5IGNyZWF0aW5nIGEgc3BlY2lhbCBjYXNlIG9mIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIHdpdGggbXVsdGlwbGUgYmluYXJ5IGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gVGhpcyBhcHByb2FjaCBpbnRlZ3JhdGVzIEFOT1ZBIGFuYWx5c2lzIGludG8gdGhlIHJlZ3Jlc3Npb24gZnJhbWV3b3JrLg0KDQpcDQoNCiMgU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uIFJldmlzaXRlZA0KDQpUaGUgdGVybSAqKnNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbioqIChTTFIpIHNpbXBseSBtZWFucyB0aGF0IHRoZSByZWdyZXNzaW9uIGVxdWF0aW9uIGhhcyB0aGUgZm9ybSAkeSA9IFxiZXRhXzAgKyBcYmV0YV8xIHggKyBcZXBzaWxvbiQuIFRoZSBwcmVkaWN0b3IgdmFyaWFibGUgaXMgZWl0aGVyIGEgY29udGludW91cyB2YXJpYWJsZSBvciBhIGJpbmFyeSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB0aGF0IHRha2VzIG9ubHkgdHdvIHBvc3NpYmxlIGRpc3RpbmN0IHZhbHVlcywgc3VjaCBhcyAqc3VjY2VzcyogdnMgKmZhaWx1cmUqLCAqZGlzZWFzZSogdnMgKmRpc2Vhc2UtZnJlZSosIGV0Yy4gKipUaGUgcmVzcG9uc2UgbXVzdCBiZSBhIGNvbnRpbnVvdXMgbm9ybWFsIHZhcmlhYmxlIHdob3NlIG1lYW4gbWF5IGJlIGluZmx1ZW5jZWQgYnkgdGhlIHByZWRpY3RvciAkeCQgYnV0IG5vdCB0aGUgdmFyaWFuY2UuKioNCg0KVGhlIGtleSBhc3N1bXB0aW9ucyBmb3IgU0xSIGFyZQ0KDQoqICoqbGluZWFyaXR5Kio6IGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiAkeSQgYW5kICR4JDsgDQogICsgZGlhZ25vc3RpYyBjaGVjazogc2NhdHRlciBwbG90IG9mICR4JCBhbmQgJHkkDQoqICoqZGV0ZXJtaW5pc3RpYyBwcmVkaWN0b3IgJHgkKio6IHRoZSBwcmVkaWN0b3IgdmFyaWFibGUgaXMgbm90IGEgcmFuZG9tIHZhcmlhYmxlLg0KICArIE5vIGRpcmVjdCBpbmZvcm1hdGlvbiwgY2hlY2sgdGhpcyBhc3N1bXB0aW9uDQoqICoqbm9ybWFsaXR5Kio6IHRoZSBvbmx5IHJhbmRvbSB2YXJpYWJsZSAkeSQgaXMgYSBub3JtYWwgcmFuZG9tIHZhcmlhYmxlIHdpdGggZGVuc2l0eSBmdW5jdGlvbiAkTihcYmV0YSswICsgXGJldGFfMSB4LCBcc2lnbWEpJCwgb3IgJFxlcHNpbG9uIFxyaWdodGFycm93IE4oMCwgXHNpZ21hKSQuDQogICsgZGlhZ25vc3RpYyBjaGVjazogUS1RIHBsb3QNCiogKipjb25zdGFudCB2YXJpYW5jZSoqOiB0aGlzIGFzc3VtcHRpb24gaXMgY29udGFpbmVkIGluIHRoZSBhYm92ZSAqKm5vcm1hbGl0eSoqIGFzc3VtcHRpb24uIA0KICArIGRpYWdub3N0aWMgY2hlY2s6IHJlc2lkdWFsIHBsb3QsIHN0dWRlbnRpemVkIHJlc2lkdWFsIHBsb3QNCiogKipJbmZsdWVudGlhbCBvYnNlcnZhdGlvbnMqKjogVGhpcyBpcyBhbHNvIHJlbGF0ZWQgdG8gdGhlICoqbm9ybWFsaXR5IGFzc3VtcHRpb24qKiANCiAgKyBkaWFnbm9zdGljIGNoZWNrOiBsZXZlcmFnZSBwbG90IChDb29rJ3MgZGlzdGFuY2UpDQoNCg0KDQoNCiMjIFNMUiB3aXRoIEEgQ29udGludW91cyBQcmVkaWN0b3INCg0KV2hlbiB0aGUgcHJlZGljdG9yIHZhcmlhYmxlIGlzIGNvbnRpbnVvdXMsIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgc2xvcGUgJFxiZXRhXzEkIHJlZmxlY3RzIHRoZSBjaGFuZ2UgaW4gJHkkIHdoZW4gJHgkIGluY3JlYXNlcyBieSBvbmUgdW5pdC4gVGhlIHNpZ24gb2YgJFxiZXRhXzEkIHJlZmxlY3RzIHRoZSBkaXJlY3Rpb24gb2YgbGluZWFyIGFzc29jaWF0aW9uIGJldHdlZW4gJHgkIGFuZCAkeSQuIE5leHQsIHdlIHVzZSBhIG51bWVyaWNhbCBleGFtcGxlIHRvIGlsbHVzdHJhdGUgdGhlIHJlZ3Jlc3Npb24gbW9kZWxpbmcgcHJvY2Vzcy4gVGhlIGRhdGEgc2V0IGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vU1RBMjAwL2RhdGFzZXQvRWR1V2FnZS5jc3Y+LiBUaGUgUiBmdW5jdGlvbiBgbG0oKWAgd2lsbCBiZSB1c2VkIHRvIHBlcmZvcm0gcmVncmVzc2lvbiBhbmFseXNpcy4NCg0KVGhlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBzZXQgYXJlIGRlZmluZWQgYXMNCg0KKiAqKndhZ2UqKjogYXZlcmFnZSBob3VybHkgZWFybmluZ3MNCiogKiplZHVjKio6IHllYXJzIG9mIGVkdWNhdGlvbg0KKiAqKmV4cGVyKio6IHllYXJzIHBvdGVudGlhbCBleHBlcmllbmNlDQoqICoqdGVudXJlKio6ICB5ZWFycyB3aXRoIGN1cnJlbnQgZW1wbG95ZXINCiogKipsd2FnZSoqOiAgbG9nKHdhZ2UpIC0gaW4gZWNvbm9taWNzLCBpdCBpcyBjYWxsZWQgbG9nIHdhZ2UuDQoqICoqcmVnaW9uKio6IHRoZSBnZW9ncmFwaGljIHJlZ2lvbiBvZiB0aGUgcmVzcG9uZGVudA0KKiAqKnNtc2EqKjogQSBTdGFuZGFyZCBNZXRyb3BvbGl0YW4gU3RhdGlzdGljYWwgQXJlYSAoU01TQSkgaXMgYSBnZW9ncmFwaGljYWwgcmVnaW9uIGRlZmluZWQgYnkgdGhlIFUuUy4gT2ZmaWNlIG9mIE1hbmFnZW1lbnQgYW5kIEJ1ZGdldCB0aGF0IGNvbnNpc3RzIG9mIGEgY29yZSB1cmJhbiBhcmVhIHdpdGggYSBzdWJzdGFudGlhbCBwb3B1bGF0aW9uLCBhbG9uZyB3aXRoIGFkamFjZW50IGNvbW11bml0aWVzIHRoYXQgaGF2ZSBhIGhpZ2ggZGVncmVlIG9mIGVjb25vbWljIGFuZCBzb2NpYWwgaW50ZWdyYXRpb24gd2l0aCB0aGF0IGNvcmUuIFNNU0FzIGFyZSB1c2VkIGZvciBzdGF0aXN0aWNhbCBwdXJwb3NlcyB0byBhbmFseXplIHVyYmFuaXphdGlvbiwgcG9wdWxhdGlvbiBkZW5zaXR5LCBhbmQgZWNvbm9taWMgYWN0aXZpdGllcyBpbiBtZXRyb3BvbGl0YW4gYXJlYXMsIHByb3ZpZGluZyBpbnNpZ2h0cyBpbnRvIHVyYmFuIGRhdGEgdHJlbmRzLg0KDQoNCg0KKipTdGVwIDEqKjogTG9hZCBkYXRhIGFuZCBleHBsb3JlIHRoZSBkYXRhc2V0Lg0KDQpgYGB7cn0NCiMjIExvYWQgdGhlIGRhdGFzZXQNCmVkdS53YWdlIDwtIHJlYWQuY3N2KCJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9TVEEyMDAvZGF0YXNldC9FZHVXYWdlLmNzdiIpDQojIyBzdW1tYXJ5IG9mIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldA0Kc3VtbWFyeShlZHUud2FnZSkNCmBgYA0KDQpUaGUgUiBmdW5jdGlvbiBgc3VtbWFyeShkYXRhc2V0Lm5hbWUpYCByZXR1cm5zIGEgZml2ZS1udW1iZXIgc3VtbWFyeSBvZiBhbGwgbnVtZXJpY2FsIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldC4gVGhlcmUgaXMgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBgcmVnaW9uYCBpbiB0aGUgZGF0YXNldC4gVG8gc2VlIHRoZSBkaXN0cmlidXRpb24gb2YgKipjYXRlZ29yaWNhbCB2YXJpYWJsZXMqKiwgd2UgdXNlIHRoZSBSIGZ1bmN0aW9uIGB0YWJsZSh2YXJpYWJsZS5uYW1lKWAgdG8gc2VlIHRoZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIG9mIHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0KdGFibGUoZWR1LndhZ2UkcmVnaW9uKQ0KYGBgDQoNCioqU3RlcCAyKio6IG9iamVjdGl2ZSBhbmQgY2FuZGlkYXRlIG1vZGVsIC0gd2UgZXhhbWluZSB3aGV0aGVyIGVkdWNhdGlvbiBhZmZlY3RzIHRoZSB3YWdlLiBUaGUgY2FuZGlkYXRlIG1vZGVsIHRvIGFkZHJlc3MgdGhpcyBvYmplY3RpdmUgd2lsbCBiZSB0aGUgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLiBXZSBmaXJzdCBtYWtlIGEgc2NhdHRlciBwbG90IG9mIGBlZHVjYCAoaG9yaXpvbnRhbCBheGlzKSBhbmQgYHdhZ2VgICh2ZXJ0aWNhbCBheGlzKS4NCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01fQ0KcGxvdChlZHUud2FnZSRlZHVjLCAgICAgICAgICAgICAgICAgIyBob3Jpem9udGFsIGF4aXMNCiAgICAgZWR1LndhZ2Ukd2FnZSwgICAgICAgICAgICAgICAgICMgdmVydGljYWwgYXhpcw0KICAgICB4bGFiID0gIlllYXJzIG9mIEVkdWNhdGlvbiIsICAgIyBob3Jpem9udGFsIGxhYmVsDQogICAgIHlsYWIgPSAiSG91cmx5IFdhZ2UiLCAgICAgICAgICAjIHZlcnRpY2FsIGxhYmVsDQogICAgIG1haW4gPSAiU2NhdHRlciBQbG90IG9mIEVkdSB2cyBXYWdlIiAgICAjIHRpdGxlIG9mIHRoZSBwbG90DQogICAgICkNCmBgYA0KDQpUaGUgYWJvdmUgcGxvdCBzaG93cyBhIGxpbmVhciByZWxhdGlvbnNoaXAgYnV0IGFsc28gc2hvd3Mgbm9uLWNvbnN0YW50IHZhcmlhbmNlLiBUaGlzIHZpb2xhdGVzIHRoZSBTTFIgYXNzdW1wdGlvbi4gRWNvbm9taWMgc3R1ZGllcyBzaG93IHRoYXQgbG9nYXJpdGhtaWMgd2FnZSBoYXMgbGVzcyB2YXJpYXRpb24uICBXZSBuZXh0IHRyeSB0byBsb2cgd2FnZXMgaW4gdGhlIFNMUi4gQmVmb3JlIGJ1aWxkaW5nIHRoZSBtb2RlbCwgd2UgbWFrZSBhIHNjYXR0ZXIgcGxvdCBvZiBsb2cgd2FnZSB2cyB5ZWFycyBvZiBlZHVjYXRpb24uDQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NX0NCnBsb3QoKGVkdS53YWdlJGVkdWMpWy0xXSwgICAgICAgICAgICAgICAgICMgaG9yaXpvbnRhbCBheGlzDQogICAgIChlZHUud2FnZSRsd2FnZSlbLTFdLCAgICAgICAgICAgICAgICAgIyB2ZXJ0aWNhbCBheGlzDQogICAgIHhsYWIgPSAiWWVhcnMgb2YgRWR1Y2F0aW9uIiwgICAjIGhvcml6b250YWwgbGFiZWwNCiAgICAgeWxhYiA9ICJIb3VybHkgbG9nKFdhZ2UpIiwgICAgICAgICAgIyB2ZXJ0aWNhbCBsYWJlbA0KICAgICBtYWluID0gIlNjYXR0ZXIgUGxvdCBvZiBFZHUgdnMgbG9nKFdhZ2UpIiAgICAjIHRpdGxlIG9mIHRoZSBwbG90DQogICAgICkNCmBgYA0KDQpUaGUgYWJvdmUgc2NhdHRlciBpbmRpY2F0ZXMgdGhhdCB0aGUgbG9nIHdhZ2UgaXMgYSBiZXR0ZXIgcmVzcG9uc2UgZm9yIFNMUi4NCg0KKipTdGVwIDMqKjogRml0dGluZyBTTFI6ICAkXHRleHR7bG9nIHdhZ2V9ID0gXGJldGFfMCArIFxiZXRhXzEgXHRleHR7ZWR1Y30kIGFuZCBwZXJmb3JtIHJlc2lkdWFsIGRpYWdub3N0aWNzLg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTZ9DQojIyBsaW5lYXIgbW9kZWwNCmxndy5tb2RlbCA8LSBsbShsd2FnZSB+IGVkdWMsIGRhdGEgPSBlZHUud2FnZSkNCiMjIHJlc2lkdWFsIHBsb3QNCnBhcihtZnJvdz1jKDIsMikpICAgICMgY3JlYXRlIGEgZ3JhcGhpYyBncmlkIHdpdGggNCBncmFwaGljYWwgY2VsbHMgDQpwbG90KGxndy5tb2RlbCkNCmBgYA0KDQpJbnRlcnByZXRhdGlvbnMgb2YgUmVzaWR1YWwgRGlhZ25vc3RpYyBQbG90czoNCg0KKiAqKlJlc2lkdWFsIHZzIEZpdHRlZCoqIC0gc2hvd3MgYSBtaW5vciB2aW9sYXRpb24gb2YgdGhlIGFzc3VtcHRpb24gb2YgY29uc3RhbnQgdmFyaWFuY2UgKHRoZSB2YXJpYW5jZSBpbmNyZWFzZXMgYXMgdGhlIGZpdHRlZCB2YWx1ZSBpbmNyZWFzZXMpDQoqICoqUV9RIFJlc2lkdWFsIFBsb3QqKiAtIFRoZXJlIGlzIG5vIHNpZ25pZmljYW50IHZpb2xhdGlvbiBvZiB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbg0KKiAqKlNjYWxlLUxvY2F0aW9uIFBsb3QqKiAtIG5vIHNlcmlvdXMgdmlvbGF0aW9uIGV4Y2VwdCBhIGZldyBvdXRsaWVycyAobm90IGluZmx1ZW50aWFsKQ0KKiAqKlJlc2lkdWFscy1MZXZlcmFnZSoqIC0gc2hvd3Mgbm8gaW5mbHVlbnRpYWwgcG9pbnRzLg0KDQpPdmVyYWxsLCB0aGVyZSBpcyBhIG1pbm9yIHZpb2xhdGlvbiBvZiB0aGUgY29uc3RhbnQgdmFyaWFuY2UgYXNzdW1wdGlvbi4gV2Ugd2lsbCBsZWFybiBtZXRob2RzIGluIHN1YnNlcXVlbnQgY291cnNlcyB0byByZWZpbmUgdGhlIG1vZGVsLiBGb3IgaWxsdXN0cmF0aW9uLCB3ZSBkZWNpZGVkIHRvIHJlcG9ydCB0aGUgYWJvdmUgbW9kZWwuDQoNCioqU3RlcCA0KiogLSBzdW1tYXJpemUgdGhlIGxvZyB3YWdlIG1vZGVsDQoNCmBgYHtyfQ0Kc3VtbWFyeShsZ3cubW9kZWwpDQpgYGANCg0KKipCcmllZiBSZXBvcnQqKjoNCg0KVGhlIGVzdGltYXRlZCBzbG9wZSBjb2VmZmljaWVudCAkXGhhdHtcYmV0YX1fMSA9IDAuMDgyNzQ0JCBpbmRpY2F0ZXMgdGhhdCBsb2cgd2FnZSBpbmNyZWFzZXMgYnkgMC4wODI3NDQgZm9yIGVhY2ggYWRkaXRpb25hbCB5ZWFyIG9mIGVkdWNhdGlvbiAoJHAgXGFwcHJveCAwJCkuIFRoZSBjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uICRSXjIgXGFwcHJveCAwLjE4NTgkIHNob3dzIHRoYXQgdGhlIGxvZyB3YWdlIGFuZCB5ZWFycyBvZiBlZHVjYXRpb24gaGF2ZSBhIHdlYWsgbGluZWFyIGNvcnJlbGF0aW9uLg0KDQoqKlJlbWFya3MqKjogSGVyZSBhcmUgYSBmZXcgY29tbWVudHMgb24gdGhlIGdlbmVyYWwgcHJpbmNpcGxlcyBvZiByZWdyZXNzaW9uIGFuYWx5c2lzDQoNCiogSW4gdGhpcyBleGFtcGxlLCB3ZSB1c2Ugb25seSB0d28gdmFyaWFibGVzIGluIHRoZSBkYXRhIHNldCB3aXRoIG1vcmUgdGhhbiAyIHZhcmlhYmxlcyB0byBpbGx1c3RyYXRlIGhvdyB0byBpbXBsZW1lbnQgYW4gU0xSLiBJbiBwcmFjdGljZSwgaWYgeW91IGhhdmUgbW9yZSBpbmZvcm1hdGlvbiAobW9yZSB2YXJpYWJsZXMpIGF2YWlsYWJsZSBpbiB0aGUgZGF0YSwgd2Ugc2hvdWxkIHVzZSBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gLSAqKnRoaXMgaXMgdGhlIGdlbmVyYWwgcHJpbmNpcGxlIG9mIGFsbCBkYXRhIGFuYWx5c2lzKiouIFRoaXMgbWVhbnMgd2UgbmVlZCB0byB1c2UgbXVsdGlwbGUgcmVncmVzc2lvbiB0byBpbmNsdWRlIHR3byBvciBtb3JlIHByZWRpY3RvciB2YXJpYWJsZXMhIFdlIHdpbGwgY292ZXIgZ2VuZXJhbCBNTFIgaW4gdGhlIG5leHQgbm90ZS4NCg0KKiAqKkltcGxpY2F0aW9uIG9mIFNMUioqOiBBbiBpbXBsaWNhdGlvbiBvZiBTTFIgaXMgdGhhdCBhbGwgb3RoZXIgdmFyaWFibGVzIGRvIG5vdCBhZmZlY3QgdGhlIHJlc3BvbnNlIHZhcmlhYmxlICR5JC4gVGhpcyBhbHNvIGltcGxpZXMgdGhhdCwgaW4gZ2VuZXJhbCwgYW4gU0xSIGNhbiBuZXZlciBiZSBhbiBvcHRpbWFsIG1vZGVsIGlmIGl0IGlzIGludmFsaWQuDQoNCiogKipDaG9vc2UgYW4gb3B0aW1hbCBzdWJzZXQgb2YgcHJlZGljdG9ycyoqOiBUaGlzIG1lYW5zIHdlIGFsd2F5cyBzdGFydCB3aXRoIG11bHRpcGxlIGNhbmRpZGF0ZSBtb2RlbHMgaW4gbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gKE1MUikgbW9kZWxzLiBGb3IgZXhhbXBsZSwgaWYgd2UgaGF2ZSB0d28gdmFyaWFibGVzICR4XzEkIGFuZCAkeF8yJCwgd2UgY2FuIGZpdCB0aHJlZSBkaWZmZXJlbnQgKipmaXJzdCBvcmRlcioqIChpbiBwcmVkaWN0b3IgdmFyaWFibGVzKSBNTFIgYmFzZWQgb24gdGhlIGNvbWJpbmF0aW9ucyBvZiAkeF8xJCwgJHhfMiQsIGFuZCAkeF8xICsgeF8yJC4gTW9yZSBvbiBkaWZmZXJlbnQgTUxScyB3aWxsIGJlIGRpc2N1c3NlZCBpbiB0aGUgbmV4dCBub3RlLg0KDQoNCg0KXA0KDQoNCiMjIFNMUiB3aXRoIEEgQmluYXJ5IFByZWRpY3Rvcg0KDQpXZSBoYXZlIGRpc2N1c3NlZCB0aGUgcmVncmVzc2lvbiBhcHByb2FjaCB0byB0aGUgdHdvLXNhbXBsZSB0LXRlc3QgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgc2VtZXN0ZXIuIEhlcmUgd2UgdXNlIHRoZSBzYW1wbGUgd2FnZSBkYXRhc2V0IGFuZCBhIGJpbmFyeSBjYXRlZ29yaWNhbCBgc21zYWAoU3RhbmRhcmQgTWV0cm9wb2xpdGFuIFN0YXRpc3RpY2FsIEFyZWEpIHRvIHNlZSB3aGV0aGVyIHRoZSBhdmVyYWdlIHdhZ2UgaW4gKipydXJhbCoqIGFuZCAqKnVyYmFuKiogYXJlYXMgaXMgZGlmZmVyZW50LiANCg0KUmVjYWxsIHRoZSBhc3N1bXB0aW9uIGluIHRoZSB0d28tc2FtcGxlIHRlc3Q6DQoNCiogV2FnZSBkaXN0cmlidXRpb25zIGluIGJvdGggcG9wdWxhdGlvbnMgKHJ1cmFsIGFuZCB1cmJhbiBwb3B1bGF0aW9ucykgYXJlIG5vcm1hbCwgZXF1aXZhbGVudCB0byB0aGUgKipub3JtYWxpdHkgYXNzdW1wdGlvbioqIG9uIFNMUg0KKiBUaGUgdmFyaWFuY2VzIG9mIHdhZ2VzIGluIGJvdGggcG9wdWxhdGlvbnMgYXJlIHVua25vd24gYnV0IGVxdWFsLCBlcXVpdmFsZW50IHRvIHRoZSAqKmNvbnN0YW50IHZhcmlhbmNlIGFzc3VtcHRpb24qKiBpbiBTTFIuIA0KDQpXaGVuIHVzaW5nIGEgc29mdHdhcmUgcHJvZ3JhbSwgd2UgaGF2ZSB0byBzcGVjaWZ5IHRoZSBwcmVkaWN0b3IgdmFyaWFibGUgJHgkIHRvIGJlIGEgZmFjdG9yIChjYXRlZ29yaWNhbCB2YXJpYWJsZSkuIEluIFIsIHRoZSBmdW5jdGlvbiBgZmFjdG9yKClgIGNvbnZlcnRzIGEgY2F0ZWdvcmljYWwgb3IgZGlzY3JldGUgbnVtZXJpY2FsIHZhcmlhYmxlICh3aXRoIGZpbml0ZSBkaXN0aW5jdCB2YWx1ZXMpIHRvIGEgZmFjdG9yIHZhcmlhYmxlLg0KDQpXZSBuZXh0IGltcGxlbWVudCB0aGUgU0xSIHdpdGggYSBiaW5hcnkgZmFjdG9yIHZhcmlhYmxlIChgc21zYWApIGFuZCB1c2UgbG9nIHdhZ2UgYGx3YWdlYCBhcyB0aGUgcmVzcG9uc2UuDQoNCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD03fQ0KIyBsbSBtb2RlbA0Kc21zYS5sbSA8LSBsbShsd2FnZSB+IGZhY3RvcihzbXNhKSwgZGF0YSA9IGVkdS53YWdlKQ0KIyByZXNpZHVhbCBwbG90cw0KcGFyKG1mcm93PWMoMiwyKSkNCnBsb3Qoc21zYS5sbSkNCmBgYA0KDQo8Zm9udCBjb2xvciA9ICJibHVlIiBzaXplID00PioqMS4gSW50ZXJwcmV0YXRpb25zIG9mIFJlc2lkdWFsIERpYWdub3N0aWMgUGxvdHMqKjwvZm9udD4NCg0KDQoqICoqUmVzaWR1YWwtZml0dGVkIFZhbHVlcyoqOiBkb2VzIG5vdCByZXZlYWwgc3BlY2lhbCBwYXR0ZXJucy4gVGhlIHZhcmlhbmNlcyBvZiB0aGUgdHdvIGdyb3VwcyBzZWVtIHRvIGJlIHNpbWlsYXIgdG8gZWFjaCBvdGhlci4NCiogKipRLVEgUGxvdCoqOiBObyBzZXJpb3VzIHZpb2xhdGlvbiBvZiB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gd2FzIGZvdW5kIGZyb20gdGhlIFEtUSBwbG90LiBOb3RlIHRoYXQgdGhlcmUgaXMgYW4gb3V0bGllciBpbiB0aGUgcGxvdC4NCiogKipTY2FsZS1sb2NhdGlvbiBQbG90Kio6IGRvZXMgbm90IHJldmVhbCBhbnkgc3BlY2lhbCBwYXR0ZXJuIGV4Y2VwdCBmb3IgYW4gb3V0bGllciAob2JzIE4wLiAyNCkuDQoqICoqUmVzaWR1YWxzIHZzIExldmVyYWdlKio6IFRoZSBDb29rJ3MgZGlzdGFuY2Ugb2Ygb2JzZXJ2YXRpb24gZG9lcyBub3QgaGF2ZSBhIHNpZ25pZmljYW50IGxldmVyYWdlIChubyBpbmZsdWVudGlhbCkuDQoNCk92ZXJhbGwsIHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IHZpb2xhdGlvbiBvZiBtb2RlbCBhc3N1bXB0aW9ucy4gV2UgcmVwb3J0IHRoZSBjdXJyZW50IG1vZGVsIGluIHRoZSBmb2xsb3dpbmc6DQoNClwNCg0KPGZvbnQgY29sb3IgPSAiYmx1ZSIgc2l6ZSA9ND4qKjIuIEludGVycHJldGF0aW9ucyBvZiBSZWdyZXNzaW9uIENvZWZmaWNpZW50cyoqPC9mb250Pg0KDQpUaGUgYmluYXJ5IHZhcmlhYmxlYHNtc2FgIGhhcyB0d28gdmFsdWVzOiAwID0gcnVyYWwgYXJlYSwgMSA9IHVyYmFuIGFyZWEuICBJbiBnZW5lcmFsLCBhIGJpbmFyeSB2YXJpYWJsZSAodGFraW5nIHZhbHVlcyAwIGFuZCAxKSBpcyBhbHNvIGNvbW1vbmx5IGNhbGxlZCBhICoqZHVtbXkgdmFyaWFibGUqKiBpbiBzdGF0aXN0aWNzIGFuZCByZWdyZXNzaW9uIGFuYWx5c2lzLg0KDQpgYGB7cn0NCnN1bW1hcnkoc21zYS5sbSkNCmBgYA0KDQoqICoqKEludGVyY2VwdCkqKjogJFxoYXR7XGJldGF9XzAgPSAgMS40MTUxOCQgaXMgdGhlIGF2ZXJhZ2UgbG9nIHdhZ2Ugb2YgKipydXJhbCBhcmVhKiogKGBzbXNhID0gMGAgaXMgdGhlIGJhc2VsaW5lIG9mIHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBgc2FzYWApLg0KDQokJA0KXGxvZyhcdGV4dHt3YWdlfV97XHRleHR7cnVyYWx9fSkgPSAgMS40MTUxOCBcIFxpbXBsaWVzIFwgXHRleHR7d2FnZX1fe1x0ZXh0e3J1cmFsfX0gPSBlXnsgMS40MTUxOH0gPSA0LjExNzIyOA0KJCQNCg0KVGhlIGFib3ZlIGVxdWF0aW9ucyBjb252ZXJ0IHRoZSBsb2cgd2FnZSB0byB0aGUgb3JpZ2luYWwgd2FnZS4gVGhhdCBpcywgdGhlIG1lYW4gd2FnZSBpbiBydXJhbCBhcmVhcyBpcyA0LjExNzIyOC4NCg0KDQoqICoqc2xvcGUgcGFyYW1ldGVyKiogKGBmYWN0b3Ioc2FzYSkxYCA9IGxldmVsIDEgb2YgZmFjdG9yIHZhcmlhYmxlIGBzbXNhID0xYDogdXJiYW4gYXJlYSk6ICRcaGF0e1xiZXRhfV8xID0gMC4yMzczMiQgaXMgdGhlIGRpZmZlcmVuY2Ugb2YgdGhlIGF2ZXJhZ2UgbG9nIHdhZ2UgYmV0d2VlbiB0aGUgY3VycmVudCBjYXRlZ29yeSAodXJiYW4gYXJlYSkgYW5kIHRoZSBiYXNlbGluZSBjYXRlZ29yeSAocnVyYWwgYXJlYSkuIEEgbW9yZSBwcmFjdGljYWwgaW50ZXJwcmV0YXRpb24gb2YgdGhlIHNsb3BlIHJlcXVpcmVzIHNvbWUgYWxnZWJyYToNCg0KJCQNClxsb2coXHRleHR7d2FnZX1fe1x0ZXh0e3VyYmFufX0pIC0gXGxvZyhcdGV4dHt3YWdlfV97XHRleHR7cnVyYWx9fSkgPSAwLjIzNzMyIFwgXGltcGxpZXMgXGxvZyBcZnJhY3tcdGV4dHt3YWdlfV97XHRleHR7dXJiYW59fX17XHRleHR7d2FnZX1fe1x0ZXh0e3J1cmFsfX19ID0gMC4yMzczMg0KJCQNCg0KRXhwYW5kaW5nIGJvdGggc2lkZXMgb2YgdGhlIGxhc3QgZXF1YXRpb24gaW4gdGhlIGFib3ZlLCB3ZSBoYXZlDQoNCiQkDQogXGZyYWN7XHRleHR7d2FnZX1fe1x0ZXh0e3VyYmFufX19e1x0ZXh0e3dhZ2V9X3tcdGV4dHtydXJhbH19fSA9IGVeezAuMjM3MzJ9ID0gMS4yNjc4NDcgXGltcGxpZXMgXHRleHR7d2FnZX1fe1x0ZXh0e3VyYmFufX09IDEuMjY3ODQ3IFx0aW1lcyBcdGV4dHt3YWdlfV97XHRleHR7cnVyYWx9fSwNCiQkDQoNCldlIHJlLWV4cHJlc3MgdGhlIGxhc3QgZXF1YXRpb24gaW4gdGhlIGFib3ZlIHRvIGdldA0KDQokJA0KXHRleHR7d2FnZX1fe1x0ZXh0e3VyYmFufX0gLSBcdGV4dHt3YWdlfV97XHRleHR7cnVyYWx9fT0gMS4yNjc4NDcgXHRpbWVzIFx0ZXh0e3dhZ2V9X3tcdGV4dHtydXJhbH19IC0gXHRleHR7d2FnZX1fe1x0ZXh0e3J1cmFsfX0gPSAwLjI2Nzg0N1x0ZXh0e3dhZ2V9X3tcdGV4dHtydXJhbH19DQokJA0KDQpXaGljaCBpcyBlcXVpdmFsZW50IHRvDQoNCiQkDQpcZnJhY3tcdGV4dHt3YWdlfV97XHRleHR7dXJiYW59fSAtIFx0ZXh0e3dhZ2V9X3tcdGV4dHtydXJhbH19fXtcdGV4dHt3YWdlfV97XHRleHR7cnVyYWx9fX0gPSAwLjI2Nzg0Ny4NCiQkDQoNCg0KVGhpcyBtZWFucyB0aGF0IDxmb250IGNvbG9yID0gInJlZCI+KipcY29sb3J7cmVkfXRoZSB3YWdlIGluIHVyYmFuIGFyZWEgaXMgMjYuNzg0NyUgaGlnaGVyIHRoYW4gdGhlIHJ1cmFsIGFyZWEqKi48L2ZvbnQ+Lg0KDQpcDQoNCjxmb250IGNvbG9yID0gImJsdWUiIHNpemUgPTQ+KiozLiBSZWxhdGlvbnNoaXAgYmV0d2VlbiBTTFIgYW5kIE9uZS13YXkgQU5PVkEqKjwvZm9udD4NCg0KRmlyc3Qgb2YgYWxsLCB3ZSBjYW4gZXh0cmFjdCBhIG9uZS13YXkgQU5PVkEgdGFibGUgZnJvbSBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHVzaW5nIHRoZSBSIGZ1bmN0aW9uIGBhbm92YShsbS5vYmplY3QpYA0KDQpgYGB7cn0NCmFub3ZhKHNtc2EubG0pDQpgYGANCg0KVGhlIEYgc3RhdGlzdGljIGluIHRoZSBhYm92ZSBBTk9WQSB0ZXN0ICh3aXRoIDEgZGVncmVlIG9mIGZyZWVkb20gaW4gdGhlIG51bWVyYXRvciBhbmQgNTI0IGRlZ3JlZXMgb2YgZnJlZWRvbSBpbiB0aGUgZGVub21pbmF0b3IpIGlzIA0KDQokJA0KRiA9IDIxLjg2Mi4NCiQkDQoNClRoZSB0LXRlc3Qgc3RhdGlzdGljIGluIHRoZSBTTFIgaXMgYSB0IGRpc3RyaWJ1dGlvbiB3aXRoIDUyNCBkZWdyZWVzIG9mIGZyZWVkb20sIHdoaWNoIGlzIGNsb3NlIHRvIHRoZSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uLiANCg0KJCQNClogXGFwcHJveCBUID0gNC42NzYuDQokJA0KDQpJdCBjYW4gYmUgcHJvdmVuIHRoYXQgJHRfe1x0ZXh0e2QuZn19XjIgPSBGX3sxLCBcIFx0ZXh0e2QuZn19JC4gVGhpcyBtZWFucyB0aGUgcmVzdWx0IG9mIHRoZSB0LXRlc3QgaW4gU0xSIGFuZCB0aGUgRi10ZXN0IGluIHRoZSBBTk9WQSBwcm9jZWR1cmUgYXJlIGlkZW50aWNhbC4gVGhlcmVmb3JlLCA8Zm9udCBjb2xvciA9ICJyZWQiIHNpemUgPSA0PioqdGhlIFNMUiB3aXRoIGEgYmluYXJ5IHByZWRpY3RvciBjYW4gdGhlIG9uZS13YXkgQU5PVkEgaXMgYSBzcGVjaWFsIFNMUiEqKjwvZm9udD4uICAgDQoNCg0KDQoNClwNCg0KIyBMaW5lYXIgUmVncmVzc2lvbiBBcHByb2FjaCB0byBPbmUtV2F5IEFOT1ZBDQoNCldlIGNsYWltZWQgdGhhdCBvbmUtd2F5IEFOT1ZBIGlzIGEgc3BlY2lhbCBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB3aGVuIHRoZXJlIGlzIGEgYmluYXJ5IGNhdGVnb3JpY2FsIHByZWRpY3RvciBpcyBpbmNsdWRlZCBpbiB0aGUgbW9kZWwuIEhvd2V2ZXIsIGEgZ2VuZXJhbCBDUkQgYWxsb3dzIG11bHRpcGxlIHRyZWF0bWVudHMuICBJbiB0aGlzIHNlY3Rpb24sIHdlIHdpbGwgaWxsdXN0cmF0ZSBob3cgdG8gdXNlIGxpbmVhciByZWdyZXNzaW9uIHRvIHBlcmZvcm0gYSBnZW5lcmFsIG9uZS13YXkgQU5PVkEgd2l0aCBtdWx0aXBsZSB0cmVhdG1lbnQgZ3JvdXBzLg0KDQpGb3IgZWFzZSBvZiBwcmVzZW50YXRpb24sIHdlIGNvbnRpbnVlIHVzaW5nIHRoZSB3YWdlIGRhdGFzZXQgd2l0aCBsb2cgd2FnZSBhcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCByZWdpb24gYXMgYSBjYXRlZ29yaWNhbCB0cmVhdG1lbnQgZmFjdG9yIChjb25zaXN0aW5nIG9mIGZvdXIgZ3JvdXBzOiBTb3V0aCwgV2VzdCwgTm9ydGgtQ2VudHJhbCwgYW5kIE90aGVyKS4gV2hlbiBwZXJmb3JtaW5nIGxpbmVhciByZWdyZXNzaW9uIHdpdGggYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB0aGF0IGhhcyBtb3JlIHRoYW4gdHdvIGNhdGVnb3JpZXMsIHdlIG11c3QgaW50cm9kdWNlIGEgc2VyaWVzIG9mIGR1bW15IHZhcmlhYmxlcyB0byBwcm9wZXJseSByZXByZXNlbnQgdGhlIG11bHRpLWNhdGVnb3J5IHZhcmlhYmxlLg0KDQoqKldoeSBVc2UgRHVtbXkgVmFyaWFibGVzPyoqDQoNCiogKipFbmNvZGUgQ2F0ZWdvcmljYWwgRGF0YSoqOiBUaGV5IGFsbG93IGNhdGVnb3JpY2FsIHZhcmlhYmxlcyAobm9taW5hbCBvciBvcmRpbmFsKSB0byBiZSBpbmNsdWRlZCBpbiByZWdyZXNzaW9uIG1vZGVscy4NCg0KKiAqKkF2b2lkIEFyYml0cmFyeSBOdW1lcmljYWwgQXNzaWdubWVudHMqKjogVXNpbmcgbnVtYmVycyBsaWtlIDEsIDIsIDMgZm9yIGNhdGVnb3JpZXMgaW1wbGllcyBhbiBvcmRlciBvciBtYWduaXR1ZGUsIHdoaWNoIG1heSBub3QgZXhpc3QgKGUuZy4sIGBSZWQgPSAxLCBHcmVlbiA9IDIsIEJsdWUgPSAzYCBmYWxzZWx5IHN1Z2dlc3RzIHRoYXQgR3JlZW4gaXMgImdyZWF0ZXIiIHRoYW4gUmVkKS4NCg0KKiAqKkludGVycHJldGFiaWxpdHkqKjogRWFjaCBkdW1teSB2YXJpYWJsZSByZXByZXNlbnRzIHRoZSBwcmVzZW5jZSAoMSkgb3IgYWJzZW5jZSAoMCkgb2YgYSBjYXRlZ29yeSwgbWFraW5nIGNvZWZmaWNpZW50cyBlYXN5IHRvIGludGVycHJldC4gVG8gYmUgbW9yZSBzcGVjaWZpYywgdGhlIGNvZWZmaWNpZW50IG9mIGEgZHVtbXkgdmFyaWFibGUgcmVwcmVzZW50cyB0aGUgZGlzY3JlcGFuY3kgYmV0d2VlbiB0aGUgY2F0ZWdvcnkgYXNzb2NpYXRlZCB3aXRoIHRoZSBkdW1teSB2YXJpYWJsZSBhbmQgdGhlIGJhc2VsaW5lIGNhdGVnb3J5Lg0KDQpcDQoNCioqU3RlcHMgdG8gQ3JlYXRlIER1bW15IFZhcmlhYmxlcyBmcm9tIGEgTXVsdGktQ2F0ZWdvcnkgVmFyaWFibGUqKg0KDQoqICoqY2hvb3NlIGEgYmFzZWxpbmUgY2F0ZWdvcnkqKjogIFRoZSBiYXNlbGluZSBjYXRlZ29yeSBzZXJ2ZXMgYXMgYSByZWZlcmVuY2UsIGFsbG93aW5nIG90aGVyIGNhdGVnb3JpZXMgdG8gYmUgY29tcGFyZWQgYWdhaW5zdCBpdC4NCiAgKyBNb3N0IHNvZnR3YXJlIHByb2dyYW1zIGF1dG9tYXRpY2FsbHkgc2V0IHRoZSBiYXNlbGluZSBhcyB0aGUgY2F0ZWdvcnkgd2l0aCB0aGUgc21hbGxlc3QgdmFsdWUgKGUuZy4sIHRoZSBmaXJzdCBpbiBhbHBoYWJldGljYWwgb3JkZXIgZm9yIGNhdGVnb3JpY2FsIHZhcmlhYmxlcykuDQoNCiogKipDcmVhdGUgRHVtbXkgVmFyaWFibGVzKio6IEZvciBlYWNoIG5vbi1iYXNlbGluZSBjYXRlZ29yeSwgZGVmaW5lIGEgZHVtbXkgdmFyaWFibGUgbGFiZWxpbmcgdGhhdCBjYXRlZ29yeS4gRm9yIGV4YW1wbGUsIGByZWdpb24gPSAobm9ydGhjZW4sIG90aGVyLCBzb3V0aCwgd2VzdClgLCB0aGUgdGhyZWUgZHVtbXkgdmFyaWFibGVzIGFyZSBkZWZpbmVkIGFzIA0KDQogICsgZHVtbXkub3RoZXIgPSAxIGlmIGxpdmVkIGluIGBvdGhlcmAgcmVnaW9uLCAwIGlmIG5vdCBpbiBgb3RoZXJgIHJlZ2lvbi4NCiAgKyBkdW1teS5zb3V0aCA9IDEgaWYgbGl2ZWQgaW4gYHNvdXRoYCBhbmQgMCBpZiBub3QgaW4gYHNvdXRoYCByZWdpb247DQogICsgZHVtbXkud2VzdCA9IDEgaWYgbGl2ZWQgaW4gYHdlc3RgIGFuZCAwIGlmIG5vdCBpbiBgd2VzdGAuDQoNCkluIGdlbmVyYWwsIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgaGFzICRrJCBjYXRlZ29yaWVzLCBhbmQgd2UgbmVlZCB0byBkZWZpbmUgJGstMSQgZHVtbXkgdmFyaWFibGVzLiBGb3IgZXhhbXBsZSwgDQoNCnwgKipyZWdpb24qKiAgfCAqKmR1bW15Lm90aGVyKiogfCAqKmR1bW15LnNvdXRoKiogIHwgKipkdW1teS53ZXN0KiogIHwNCnw6LS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLXwNCnwgIHNvdXRoICAgICB8ICAgICAgMCAgICAgICAgICB8ICAgICAgIDEgICAgICAgICAgIHwgICAgMCAgICAgICAgICAgICB8DQp8ICB3ZXN0ICAgICAgfCAgICAgIDAgICAgICAgICAgfCAgICAgICAwICAgICAgICAgICB8ICAgIDEgICAgICAgICAgICAgfA0KfG5vcnRoY2VuICAgIHwgICAgICAwICAgICAgICAgIHwgICAgICAgMCAgICAgICAgICAgfCAgICAwICAgICAgICAgICAgIHwNCnxvdGhlciAgICAgICB8ICAgICAgMSAgICAgICAgICB8ICAgICAgIDAgICAgICAgICAgIHwgICAgMCAgICAgICAgICAgICB8DQp8ICBzb3V0aCAgICAgfCAgICAgIDAgICAgICAgICAgfCAgICAgICAxICAgICAgICAgICB8ICAgIDAgICAgICAgICAgICAgfA0KIA0KDQoqICoqSW50ZXJwcmV0YXRpb24gb2YgRHVtbXkgVmFyaWFibGVzIGluIFJlZ3Jlc3Npb24qKg0KDQpUaGUgY29lZmZpY2llbnRzIGZvciBgb3RoZXJgLCBgc291dGhgLCBhbmQgYHdlc3RgIHJlcHJlc2VudCB0aGUgZGlmZmVyZW5jZSBmcm9tIHRoZSByZWZlcmVuY2UgY2F0ZWdvcnkgKGBub3J0aGNlbmApLg0KDQoqICoqRHVtbXkgdmFyaWFibGVzIGluIFIqKg0KICArICoqQ2F0ZWdvcmljYWwgdmFyaWFibGUgd2l0aCBjaGFyYWN0ZXIgdmFsdWVzKio6IEluIHRoaXMgY2FzZSwgUiB3aWxsIGRlZmluZSBkdW1teSB2YXJpYWJsZXMgaW50ZXJuYWxseSBhbmQgdXNlIHRoZSBkZWZhdWx0IHJlZmVyZW5jZSBjYXRlZ29yeS4NCiAgKyAqKkNhdGVnb3JpY2FsIHZhcmlhYmxlIHdpdGggdmFsdWVzIGluIG51bWVyaWNhbCBmb3JtKio6IEluIHRoaXMgY2FzZSwgd2UgbXVzdCB1c2UgUuKAmXMgYGZhY3RvcigpYCBmdW5jdGlvbiB0byBjb252ZXJ0IHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBpbnRvIGEgZmFjdG9yIHZhcmlhYmxlIChudW1lcmljIHZhbHVlcyB3aWxsIGJlIHRyZWF0ZWQgYXMgY2F0ZWdvcnkgbGFiZWxzKS4gUiB0aGVuIGludGVybmFsbHkgZGVmaW5lcyBkdW1teSB2YXJpYWJsZXMgYW5kIHNlbGVjdHMgdGhlIGJhc2VsaW5lIGNhdGVnb3J5IGFzIHRoZSBvbmUgd2l0aCB0aGUgc21hbGxlc3QgbnVtZXJpY2FsIGxhYmVsLg0KICArIElmIHRoZSBkZWZhdWx0IHJlZmVyZW5jZSBjYXRlZ29yeSBpcyBub3QgcHJlZmVycmVkLCB5b3UgY2FuIHVzZSBSJ3MgYHJlbGV2ZWwoKWAgZnVuY3Rpb24gdG8gbWFudWFsbHkgc3BlY2lmeSBhIGN1c3RvbSBiYXNlbGluZSBjYXRlZ29yeSBmb3IgZWFzaWVyIGludGVycHJldGF0aW9uLiANCiAgDQogIA0KYGBge3J9DQojIEV4YW1wbGUgZGF0YQ0KZGF0YSA8LSBkYXRhLmZyYW1lKGNvbG9yID0gYygiUmVkIiwgIkdyZWVuIiwgIkJsdWUiLCAiR3JlZW4iLCAiUmVkIikpDQoNCiMgU2V0ICJHcmVlbiIgYXMgdGhlIGJhc2VsaW5lIChyZWZlcmVuY2UpIGNhdGVnb3J5DQpkYXRhJGNvbG9yIDwtIGZhY3RvcihkYXRhJGNvbG9yKSAgDQpkYXRhJGNvbG9yIDwtIHJlbGV2ZWwoZGF0YSRjb2xvciwgcmVmID0gIkdyZWVuIikgIA0KDQojIENoZWNrIGxldmVscyAoZmlyc3QgbGV2ZWwgaXMgdGhlIGJhc2VsaW5lKQ0KbGV2ZWxzKGRhdGEkY29sb3IpICAjIE91dHB1dDogIkdyZWVuIiAiUmVkIiAiQmx1ZSINCmBgYA0KDQoNClwNCg0KPGZvbnQgY29sb3IgPSAicmVkIiBzaXplID0gND4qKlxjb2xvcntyZWR9T24gdGhlIFNpZ25pZmljYW5jZSBvZiB0aGUgQ2F0ZWdvcmljYWwgVmFyaWFibGUqKjogDQoNCiogSWYgKiphbnkqKiBvZiB0aGUgZHVtbXkgdmFyaWFibGVzIGlzIHN0YXRpc3RpY2FsbHkgKipzaWduaWZpY2FudCoqIChpLmUuLCAqcCotdmFsdWUgPCAwLjA1KSwgdGhlIG9yaWdpbmFsIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGlzIGNvbnNpZGVyZWQgKipzaWduaWZpY2FudCoqLg0KKiBJZiAqKmFsbCoqIGR1bW15IHZhcmlhYmxlcyBhcmUgc3RhdGlzdGljYWxseSAqKmluc2lnbmlmaWNhbnQqKiwgdGhlIG9yaWdpbmFsIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGlzICoqaW5zaWduaWZpY2FudCoqLiA8L2ZvbnQ+ICANCiogSWYgdGhlIG9yaWdpbmFsIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGlzICoqaW5zaWduaWZpY2FudCoqLCBpdCBzaG91bGQgYmUgZXhjbHVkZWQgZnJvbSB0aGUgcmVncmVzc2lvbiBtb2RlbCBpbiByZWFsIHJlYWwtd29ybGQgYXBwbGljYXRpb24uIA0KDQoNClwNCiAgDQo8Zm9udCBjb2xvciA9ICJibHVlIiBzaXplID0gND4qKlxjb2xvcntibHVlfUluIHRoZSBvdXRwdXQgb2YgYGxtKClgLCB0aGUgRiB0ZXN0IGluIHRoZSBib3R0b20gcG9ydGlvbiBwcm92aWRlcyB0aGUgc2lnbmlmaWNhbmNlIHRlc3Qgb2YgdGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlLioqIDwvZm9udD48Zm9udCBjb2xvciA9ICJyZWQiIHNpemUgPSA0PioqXGNvbG9ye3JlZH1UaGlzIEYgdGVzdCBpcyB0aGUgc2FtZSBGIHRlc3QgaW4gdGhlIG9uZS13YXkgQU5PVkEhISEqKjwvZm9udD4gIA0KICANCiANCiAgDQpcDQoNCjxmb250IGNvbG9yID0gInJlZCIgc2l6ZSA9IDQ+KipcY29sb3J7cmVkfUFuIE51bWVyaWNhbCBFeGFtcGxlKio8L2ZvbnQ+IA0KDQpXZSB1c2UgdGhlICoqcGxhbnQgZ3Jvd3RoKiogZGF0YXNldCB0byBidWlsZCBhIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCB0aGUgbXVsdGktY2F0ZWdvcnkgcHJlZGljdG9yIGBncm91cGAgYW5kIGNvbXBhcmUgaXQgd2l0aCBhIG9uZS13YXkgQU5PVkEgcHJvY2VkdXJlLiBUaGUgZGF0YSBzZXQgaXMgYXQgPD4uICBXZSB3aWxsIGZvbGxvdyBzZXZlcmFsIGxvZ2ljYWwgc3RlcHMgdG8gY29uZHVjdCB0aGUgYW5hbHlzaXMuDQoNCg0KKipTdGVwIDEqKjogZml0IGNhbmRpZGF0ZSBtb2RlbCBhbmQgcGVyZm9ybSBkaWFnbm9zdGljcw0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQojIyBMb2FkIHRoZSBkYXRhc2V0DQpwbGFudCA8LSByZWFkLmNzdigiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vU1RBMjAwLy9kYXRhc2V0L29uZVdheVBsYW50R3Jvd3RoLmNzdiIpDQojIw0KcGxhbnQubG0gPC0gbG0od2VpZ2h0IH4gZ3JvdXAsIGRhdGEgPSBwbGFudCkgICMgZmFjdG9yKGdyb3VwKSB3aWxsIGFsc28gd29yaw0KIyMgcmVzaWR1YWwgcGxvdHMNCnBhcihtZnJvdz1jKDIsMikpDQpwbG90KHBsYW50LmxtKQ0KYGBgDQoNCg0KTm9uZSBvZiB0aGUgYWJvdmUgcmVzaWR1YWwgcGxvdHMgc2hvd3Mgc2lnbmlmaWNhbnQgdmlvbGF0aW9ucyBvZiBtb2RlbCBhc3N1bXB0aW9ucyBleGNlcHQgZm9yIGEgZmV3IG91dGxpZXJzIHRoYXQgYXJlIG5vdCBpbmZsdWVudGlhbC4gV2UgcmVwb3J0IHRoZSBtb2RlbC4gDQoNCioqU3RlcCAyKio6IFJlcG9ydGluZyB0aGUgbGluZWFyIG1vZGVsDQoNCmBgYHtyfQ0Kc3VtbWFyeShwbGFudC5sbSkNCmBgYA0KDQoqKkludGVycHJldGF0aW9uIG9mIHRoZSBvdXRwdXQqKg0KDQoqIFRoZSBleHBsaWNpdCBtb2RlbCBmb3JtdWxhIGhhcyBvbmx5IHRoZSBvcmlnaW5hbCBncm91cCBjYXRlZ29yaWNhbCB2YXJpYWJsZSB3aXRoIHRocmVlIGNhdGVnb3JpZXMuIEluIGZhY3QsIHRoZSBpbXBsaWNpdCBtb2RlbCBmb3JtdWxhIHVzZXMgZHVtbXkgdmFyaWFibGVzLiBJbiBvdGhlciB3b3JkcywgdGhlIGFjdHVhbCBtb2RlbCBmb3JtdWxhIHVzZWQgaW4gdGhlIG1vZGVsIGlzICRcdGV4dHt3ZWlnaHR9ID0gXGJldGFfMCArIFxiZXRhXzEgXHRleHR7Z3JvdXB0cnQxfSArIFxiZXRhXzIgXHRleHR7Z3JvdXB0cnQyfSQsIDxmb250IGNvbG9yID0gInJlZCIgc2l6ZSA9IDQ+KipcY29sb3J7cmVkfSB3aGVyZSAkXGJldGFfMCA9IFxtdV97XHRleHR7Y3RyfX0kLCAgJFxiZXRhXzEgPSBcbXVfe1x0ZXh0e3RydDF9fSAtIFxtdV97XHRleHR7Y3RyfX0kIGFuZCAkXGJldGFfMiA9IFxtdV97XHRleHR7dHJ0Mn19IC0gXG11X3tcdGV4dHtjdHJ9fSQqKjwvZm9udD4gDQoNCiogVGhlIEYgdGVzdCBpbiB0aGUgYm90dG9tIHBvcnRpb24geWllbGRzIGEgcC12YWx1ZSBvZiAwLjAxNTkxLiBBdCBhIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAwLjA1LCB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IDxmb250IGNvbG9yID0gInJlZCI+KipcY29sb3J7cmVkfXJlZ2lvbiBpcyBzaWduaWZpY2FudCoqLjwvZm9udD4gSW4gb3RoZXIgd29yZHMsIHRoaXMgRi10ZXN0IHRlc3RzIHRoZSA8Zm9udCBjb2xvciA9ICJyZWQiIHNpemUgPSA0PioqXGNvbG9ye3JlZH1udWxsIGh5cG90aGVzaXM6ICRIXzA6IFxiZXRhXzEgPSBcYmV0YV8yID0gMCQuKio8L2ZvbnQ+IFRoaXMgZXF1aXZhbGVudCB0byA8Zm9udCBjb2xvciA9ICJyZWQiIHNpemUgPSA0PioqXGNvbG9ye3JlZH0kSF8wOiBcbXVfe1x0ZXh0e2N0cn19ID0gXG11X3tcdGV4dHt0cnQxfX0gPSBcbXVfe1x0ZXh0e3RydDJ9fSQqKi48L2ZvbnQ+IDxmb250IGNvbG9yPSJibHVlIiBzaXplID0gND4qKlxjb2xvcntibHVlfVRoaXMgaXMgZXhhY3RseSB0aGUgRiB0ZXN0IGluIHRoZSBvbmUtd2F5IEFOT1ZBISoqPC9mb250PiBXZSB3aWxsIGV4dHJhY3QgdGhlIG9uZS13YXkgQU5PVkEgZnJvbSB0aGUgbGluZWFyIG1vZGVsIHNob3J0bHkuDQoNCiogKipJbnRlcnByZXRhdGlvbiBvZiBSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyoqOiBBdCB0aGUgc2lnbmlmaWNhbmNlIGxldmVsIG9mIDAuMDUsIG5laXRoZXIgb2YgdGhlIHR3byBkdW1teSB2YXJpYWJsZXMgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4NCiAgKyAkXGJldGFfMCAgPSBcbXVfe1x0ZXh0e2N0cn19JCwgVGhpcyByZXByZXNlbnRzIHRoZSBtZWFuIG9mIHRoZSBiYXNlbGluZSBjYXRlZ29yeS4gVGhlIHAtdmFsdWUgdGVzdHMgdGhlIGh5cG90aGVzaXMgJEhfMDogXGJldGFfMCA9IDAkLg0KICArICRcaGF0e1xiZXRhfV8xID0gXGhhdHtcbXV9X3tcdGV4dHt0cnQxfX0gLSBcaGF0e1xtdX1fe1x0ZXh0e2N0cn19ID0gLTAuMzcxMCQ6IFRoZSBwLXZhbHVlIG9mICoqMC4xOTQ0KiogY29ycmVzcG9uZHMgdG8gdGVzdGluZyB0aGUgaHlwb3RoZXNpcyAkSF8wOiBcYmV0YV8xID0gMCQgKG9yIGVxdWl2YWxlbnRseSwgJEhfMDogXG11X3tcdGV4dHt0cnQxfX0gLSBcbXVfe1x0ZXh0e2N0cn19ID0gMCQpLiBUaGUgcC12YWx1ZSBpbmRpY2F0ZXMgKipubyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2UqKiBiZXR3ZWVuIGB0cnQxYCBhbmQgYGN0cmAuIFRoZSBuZWdhdGl2ZSBzaWduIG9mIHRoZSBlc3RpbWF0ZSBzdWdnZXN0cyB0aGF0IHRoZSBzYW1wbGUgbWVhbiBvZiBgY3RyYCBpcyBoaWdoZXIgdGhhbiB0aGF0IG9mIGB0cnQxYC4NCiAgKyAkXGhhdHtcYmV0YX1fMiA9IFxoYXR7XG11fV97XHRleHR7dHJ0Mn19IC0gXGhhdHtcbXV9X3tcdGV4dHtjdHJ9fSA9MC40OTQwJCwgVGhlIHAtdmFsdWUgb2YgKiowLjA4NzcqKiBjb3JyZXNwb25kcyB0byB0ZXN0aW5nIHRoZSBoeXBvdGhlc2lzICRIXzA6IFxiZXRhXzIgPSAwJCAob3IgZXF1aXZhbGVudGx5LCAkSF8wOiBcbXVfe1x0ZXh0e3RydDJ9fSAtIFxtdV97XHRleHR7Y3RyfX0gPSAwJCkuIFRoZSBwLXZhbHVlIGluZGljYXRlcyAqKm5vIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSoqIGJldHdlZW4gYHRydDJgIGFuZCBgY3RyYC4gVGhlIHBvc2l0aXZlIHNpZ24gb2YgdGhlIGVzdGltYXRlIHN1Z2dlc3RzIHRoYXQgdGhlIHNhbXBsZSBtZWFuIG9mIGB0cnQyYCBpcyBoaWdoZXIgdGhhbiB0aGF0IG9mIGBjdHJgLg0KICANClwNCg0KTmV4dCwgd2UgZXh0cmFjdCB0aGUgb25lLXdheSBBTk9WQSB0YWJsZSBkaXJlY3RseSBmcm9tIHRoZSBhYm92ZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbC4NCg0KDQpgYGB7cn0NCiMgZXh0cmFjdCBBTk9WQSB0YWJsZSBkaXJlY3RseSBmcm9tIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsDQphbm92YShwbGFudC5sbSkNCmBgYA0KDQpUaGUgRi10ZXN0IGZyb20gdGhlIG9uZS13YXkgQU5PVkEgdGFibGUgYWJvdmUgaXMgaWRlbnRpY2FsIHRvIHRoZSBvbmUgcmVwb3J0ZWQgaW4gdGhlIHByZXZpb3VzIHJlZ3Jlc3Npb24gbW9kZWwuIFdlIGNhbiBhbHNvIGdlbmVyYXRlIHRoZSBzYW1lIG9uZS13YXkgQU5PVkEgdGFibGUgdXNpbmcgUuKAmXMgYnVpbHQtaW4gZnVuY3Rpb25gYW92KClgIA0KDQoNClRoZSBjb2VmZmljaWVudHMgYXNzb2NpYXRlZCB3aXRoIGR1bW15IHZhcmlhYmxlcyBpbiB0aGUgcmVncmVzc2lvbiBvdXRwdXQgcmVwcmVzZW50IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW4gb2YgdGhlIHVuZGVybHlpbmcgY2F0ZWdvcnkgYW5kIHRoYXQgb2YgdGhlIGJhc2VsaW5lIGNhdGVnb3J5LiBUaGF0IGlzLCAkXGhhdHtcYmV0YX1fMSA9IFxoYXR7XG11fV97XHRleHR7dHJ0MX19IC0gXGhhdHtcbXV9X3tcdGV4dHtjdHJ9fSA9IC0wLjM3MTAkIGFuZCAkXGhhdHtcYmV0YX1fMiA9IFxoYXR7XG11fV97XHRleHR7dHJ0Mn19IC0gXGhhdHtcbXV9X3tcdGV4dHtjdHJ9fSA9MC40OTQwJC4gVGhpcyBpbmZvcm1hdGlvbiBpcyBnaXZlbiBpbiBUdWtleSdzIEhTRCAoc2VlIHRoZSBvdXRwdXQgb2YgYFR1a2V5SFNEKClgKQ0KDQoNCmBgYHtyfQ0KcGxhbnQuYW92IDwtIGFvdih3ZWlnaHQgfiBncm91cCwgZGF0YSA9IHBsYW50KQ0KVHVrZXlIU0QocGxhbnQuYW92KQ0KYGBgDQoNClRoZSBmaXJzdCB0d28gZXN0aW1hdGVkIGRpZmZlcmVuY2VzIChgdHJ0MSAtIGN0cmAgYW5kIGB0cnQyIC0gY3RyYCkgY29ycmVzcG9uZCB0byB0aGUgcmVncmVzc2lvbiBjb2VmZmljaWVudHMgb2YgdGhlIGR1bW15IHZhcmlhYmxlcyBpbiB0aGUgcHJldmlvdXMgbW9kZWwuIFRoZSBwLXZhbHVlcyByZXBvcnRlZCBpbiB0aGUgcmVncmVzc2lvbiBtb2RlbCBhcmUgdW5hZGp1c3RlZCAoYmFzZWQgb24gaW5kaXZpZHVhbCB0ZXN0cyksIHdoZXJlYXMgVHVrZXkncyBIU0QgaXMgYSBncm91cCB0ZXN0LCBhbmQgaXRzIGNvcnJlc3BvbmRpbmcgcC12YWx1ZXMgYXJlIGFkanVzdGVkIHRvIGNvbnRyb2wgdGhlIG92ZXJhbGwgVHlwZSBJIGVycm9yIHJhdGUgKGkuZS4sIHRvIHByZXZlbnQgaW5mbGF0aW9uIG9mIHRoZSBmYWxzZSBwb3NpdGl2ZSByYXRlKS4NCg0KDQpcDQoNCjxmb250IGNvbG9yID0gInJlZCIgc2l6ZSA9IDQ+KipcY29sb3J7cmVkfVJlbWFya3M6Kio8L2ZvbnQ+DQoNCiogVGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHVzZWQgdG8gcGVyZm9ybSBvbmUtd2F5IEFOT1ZBIGhhcyAqKm11bHRpcGxlIGR1bW15IHByZWRpY3RvciB2YXJpYWJsZXMqKiBpbiB0aGUgbW9kZWwgZm9ybXVsYSAoYWx0aG91Z2ggaW1wbGljaXRseSBleHByZXNzZWQpLiBJbiBvdGhlciB3b3JkcywgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIHRoZSBvbmUtd2F5IEFOT1ZBIGlzIGEgc3BlY2lhbCAqKm11bHRpcGxlIGxpbmVhciBSZWdyZXNzaW9uKiogKE1MUikgbW9kZWwuDQoNCiogTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24gKE1MUikgbWFpbnRhaW5zIHRoZSBzYW1lIGFzc3VtcHRpb25zIGFzIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbjogaW5kZXBlbmRlbnQgYW5kIGlkZW50aWNhbGx5IGRpc3RyaWJ1dGVkIChpLmkuZC4pIG9ic2VydmF0aW9ucywgZGV0ZXJtaW5pc3RpYyBwcmVkaWN0b3JzLCBsaW5lYXJpdHkgYmV0d2VlbiByZXNwb25zZSBhbmQgcHJlZGljdG9yLCBub3JtYWxpdHkgb2YgcmVzaWR1YWxzLCBhbmQgaG9tb3NjZWRhc3RpY2l0eSAoY29uc3RhbnQgdmFyaWFuY2UpLiBTaW5jZSBNTFIgaW52b2x2ZXMgbXVsdGlwbGUgcHJlZGljdG9yIHZhcmlhYmxlcywgYW4gYWRkaXRpb25hbCBhc3N1bXB0aW9uIGlzIHRoZSBhYnNlbmNlIG9mIGhpZ2ggY29ycmVsYXRpb25zIGJldHdlZW4gcHJlZGljdG9ycy4gVmlvbGF0aW9uIG9mIHRoaXMgYXNzdW1wdGlvbiBpcyByZWZlcnJlZCB0byBhcyAqKm11bHRpY29sbGluZWFyaXR5KiogaW4gcmVncmVzc2lvbiBtb2RlbGluZy4NCg0KKiBUaGUgcmVhc29uIHdlIGVuY29kZSBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlIHdpdGggayBjYXRlZ29yaWVzIGludG8gKGstMSkgZHVtbXkgdmFyaWFibGVzIChyYXRoZXIgdGhhbiBrKSBpcyB0byBhdm9pZCBtdWx0aWNvbGxpbmVhcml0eSBpc3N1ZXMuIEZvciBleGFtcGxlLCBzdXBwb3NlIHdlIGhhdmUgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSAqKkVkdWNhdGlvbioqIHdpdGggMyBsZXZlbHM6IEhpZ2ggU2Nob29sIChiYXNlbGluZS9yZWZlcmVuY2UpLCBCYWNoZWxvcidzLCBhbmQgTWFzdGVyJ3MuIElmIHdlIGNyZWF0ZSAzIGR1bW15IHZhcmlhYmxlczoNCiAgKyBEMSA9IDEgaWYgSGlnaCBTY2hvb2wsIDAgb3RoZXJ3aXNlDQogICsgRDIgPSAxIGlmIEJhY2hlbG9yJ3MsIDAgb3RoZXJ3aXNlDQogICsgRDMgPSAxIGlmIE1hc3RlcidzLCAwIG90aGVyd2lzZQ0KDQogIDxmb250IGNvbG9yID0gInJlZCI+VGhpcyBjcmVhdGVzIHBlcmZlY3QgKiptdWx0aWNvbGxpbmVhcml0eSoqIGJlY2F1c2UgZm9yIGV2ZXJ5IG9ic2VydmF0aW9uOiBEMSArIEQyICsgRDMgPSAxIChhbHdheXMpISEhPC9mb250Pg0KDQoNClRvIGNvbmNsdWRlIHRoaXMgc2VjdGlvbiwgd2F0Y2ggdGhlIFlvdVR1YmUgdmlkZW8gKDxodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUNNQXdLdUN3NUNNJmxpc3Q9UExmUXBwaTNtekY1blF6U20tUldRbnZIRmc0NkdRVktfNCZpbmRleD00PikgdGhhdCBmb2N1c2VzIG9uIHRoZSBBTk9WQSB0YWJsZSBleHRyYWN0ZWQgZnJvbSB0aGUgbGluZWFyIHJlZ3Jlc3Npb24uICANCg0KDQpcDQoNCjxjZW50ZXI+PGEgaHJlZj0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1DTUF3S3VDdzVDTSZsaXN0PVBMZlFwcGkzbXpGNW5RelNtLVJXUW52SEZnNDZHUVZLXzQmaW5kZXg9NCIgdGFyZ2V0PSJwb3B1cCIgDQogICAgICAgICAgICAgICAgICAgb25jbGljaz0id2luZG93Lm9wZW4oJ2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9Q01Bd0t1Q3c1Q00mbGlzdD1QTGZRcHBpM216RjVuUXpTbS1SV1FudkhGZzQ2R1FWS180JmluZGV4PTQnLA0KICAgICAgICAgICAgICAgICAgICAgICduYW1lJywnd2lkdGg9ODUwLGhlaWdodD01MDAnKSI+PGltZyBzcmMgPSAiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vTUFUMTIxVzUvaW1nL1ZpZGVvSWNvbi5wbmciIHdpZHRoPSIyMDAiIGhlaWdodD0iMTIwIj48L2E+DQo8L2NlbnRlcj4NCg0KDQoNClwNCg0KDQojIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIEFwcHJvYWNoIHRvIFR3by13YXkgQU5PVkENCg0KKipUaGlzIHNlY3Rpb24gZm9jdXNlcyBvbiBsaW5lYXIgcmVncmVzc2lvbiB3aXRoIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIGVhY2ggd2l0aCBtdWx0aXBsZSBsZXZlbHMuKiogV2UgaGF2ZSBwcmV2aW91c2x5IGxlYXJuZWQgYWJvdXQgdHdvLXdheSBBTk9WQSBiYXNlZCBvbiBhIHJlcGxpY2F0ZWQgUmFuZG9taXplZCBCbG9jayBEZXNpZ24gKFJCRCksIHdoaWNoIGFsbG93cyBmb3IgaW5mZXJlbmNlIG9uIGludGVyYWN0aW9uIGVmZmVjdHMuIFRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB0byBiZSBkaXNjdXNzZWQgd2lsbCBhbHNvIGluY2x1ZGUgYW4gaW50ZXJhY3Rpb24gdGVybS4NCg0KU2luY2UgdGhlIHVuZGVybHlpbmcgY29uY2VwdCBpcyBzaW1pbGFyIHRvIHRoZSBvbmUtd2F5IEFOT1ZBIGNvdmVyZWQgaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24sIHRoZSBleHBsaWNpdCBtb2RlbCBmb3JtdWxhIHJlbWFpbnMgcmVsYXRpdmVseSBzaW1wbGUuIEhvd2V2ZXIsIHRoZSBpbXBsaWNpdCBtb2RlbCBmb3JtdWxhIGZvciBsaW5lYXIgcmVncmVzc2lvbiB3aXRoIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgKGluY2x1ZGluZyBhbiBpbnRlcmFjdGlvbiBlZmZlY3QpIGlzIG1vcmUgY29tcGxleCB0aGFuIHRoYXQgb2Ygb25lLXdheSBBTk9WQS4gV2Ugd2lsbCB1c2UgYW4gZXhhbXBsZSB0byBpbGx1c3RyYXRlIHNvbWUga2V5IGZlYXR1cmVzIG9mIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIChNTFIpIGludm9sdmluZyBvbmx5IGNhdGVnb3JpY2FsIHZhcmlhYmxlcyB3aXRoIGFuIGludGVyYWN0aW9uIHRlcm0uDQoNCg0KVGhlIGRhdGFzZXQgcmVjb3JkZWQgdGhlIHlpZWxkIG9mIGRpZmZlcmVudCBjcm9wcyB1bmRlciBkaWZmZXJlbnQgZmVydGlsaXplcnMuIFRoZSB0d28td2F5IGRhdGEgdGFibGUgaXMgZ2l2ZW4gYmVsb3cuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjQwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDUvVHdvLXdheS1EYXRhLnBuZyIpDQpgYGANCg0KV2UgaGF2ZSB1c2VkIHZhcmlvdXMgUiBjb21tYW5kcyBlYXJsaWVyIHRvIGNvbnZlcnQgYSB0d28td2F5IGRhdGEgdGFibGUgdG8gYW4gUiBkYXRhZnJhbWUgZm9yIHJlZ3Jlc3Npb24gbW9kZWxpbmcuIFdlIG5leHQgdXNlIHNpbWlsYXIgY29kZSB0byBjb252ZXJ0IHRoZSBhYm92ZSB0YWJsZSB0byBhIGRhdGFmcmFtZS4NCg0KYGBge3J9DQojIyBUbyBhdm9pZCB0eXBpbmcgZXJyb3JzLCB3ZSBpbnB1dCB0aGUgdGFibGUgY2VsbCBieSBjZWxsIGZyb20gdGhlIGRhdGEgdGFibGUNCmNyb3AuZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBGZXJ0aWxpemVyID0gcmVwKGMoIkJsZW5kIFgiLCAiQmxlbmQgWSIsICJCbGVuZCBaIiksIGVhY2ggPSAyMCksDQogIENyb3AgPSByZXAocmVwKGMoIldoZWF0IiwgIkNvcm4iLCAiU295IiwgIlJpY2UiKSwgZWFjaCA9IDUpLCB0aW1lcyA9IDMpLA0KICBZaWVsZCA9IGMoMTIzLCAxNTYsIDExMiwgMTAwLCAxNjgsICAgIyBCbGVuZCBYIC0gV2hlYXQNCiAgICAgICAgICAgIDEyOCwgMTUwLCAxNzQsIDExNiwgMTA5LCAgICMgQmxlbmQgWCAtIENvcm4NCiAgICAgICAgICAgIDE2NiwgMTc4LCAxODcsIDEzMywgMTk1LCAgICMgQmxlbmQgWCAtIFNveQ0KICAgICAgICAgICAgMTUxLCAxMjUsIDExNywgMTU1LCAxMzgsICAgIyBCbGVuZCBYIC0gUmljZQ0KICAgICAgICAgICAgIyMNCiAgICAgICAgICAgIDEzNSwgMTMwLCAxNzYsIDEyMCwgMTU1LCAgICMgQmxlbmQgWSAtIFdoZWF0DQogICAgICAgICAgICAxNzUsIDEzMiwgMTIwLCAxODcsIDE4NCwgICAjIEJsZW5kIFkgLSBDb3JuDQogICAgICAgICAgICAxNDAsIDE0NSwgMTU5LCAxMzEsIDEyNiwgICAjIEJsZW5kIFkgLSBTb3kNCiAgICAgICAgICAgIDE2NywgMTg4LCAxNDIsIDE2NywgMTY4LCAgICMgQmxlbmQgWSAtIFJpY2UNCiAgICAgICAgICAgICMjDQogICAgICAgICAgICAxNTYsIDE4MCwgMTQ3LCAxNDYsIDE5MywgICAjIEJsZW5kIFogLSBXaGVhdA0KICAgICAgICAgICAgMTg2LCAxMzgsIDE3OCwgMTc2LCAxOTAsICAgIyBCbGVuZCBaIC0gQ29ybg0KICAgICAgICAgICAgMTg1LCAyMDYsIDE4OCwgMTY1LCAxODgsICAgIyBCbGVuZCBaIC0gU295DQogICAgICAgICAgICAxNzUsIDE3MywgMTU0LCAxOTEsIDE2OSkgICAjIEJsZW5kIFogLSBSaWNlDQopDQoNCiMgQ29udmVydCBmYWN0b3JzIHRvIGZhY3RvcnMgKGltcG9ydGFudCBmb3IgbW9kZWxpbmcpDQpjcm9wLmRhdGEkRmVydGlsaXplciA8LSBhcy5mYWN0b3IoY3JvcC5kYXRhJEZlcnRpbGl6ZXIpDQpjcm9wLmRhdGEkQ3JvcCA8LSBhcy5mYWN0b3IoY3JvcC5kYXRhJENyb3ApDQpgYGANCg0KTmV4dCwgd2UgZml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBhbiBpbnRlcmFjdGlvbiB0ZXJtIGFuZCBsaXN0IHRoZSB0ZXJtcyAoZHVtbXkgdmFyaWFibGVzKSBpbiB0aGUgaW1wbGljaXQgaW50ZXJuYWwgbW9kZWwgZm9ybXVsYSBieSB1c2luZyB0d28gUiBmdW5jdGlvbnMgYG1vZGVsLm1hdHJpeChtb2RlbC5uYW1lKWAgYW5kIGBjb2xuYW1lcyhtb2RlbC5tYXRyaXgubmFtZSlgLiBTZWUgaG93IHRoZXNlIFIgZnVuY3Rpb25zIGFyZSBjYWxsZWQgaW4gdGhlIGZvbGxvd2luZyBjb2RlIGNodW5rLg0KDQpgYGB7cn0NCiMjIEV4cGxpY2l0IGZvcm0gaXMgc3RpbGwgYSBzaW1wbGUNCmNyb3AubG0gPC0gbG0oWWllbGQgfiBDcm9wICogRmVydGlsaXplciwgZGF0YSA9IGNyb3AuZGF0YSkNCiMjIG1vZGVsIG1hdHJpeCBwcm92aWRlcyBhbGwgZHVtbXkgdmFyaWFibGVzIGltcGxpY2l0bHkgZGVmaW5lZCBpbiB0aGUgUg0KbW9kZWwubXR4IDwtIG1vZGVsLm1hdHJpeChjcm9wLmxtKQ0KIyMgZXh0cmFjdCB0aGUgY29sdW1uIG5hbWVzIG9mIHRoZSBtb2RlbCBtYXRyaXggPT0+IGxpc3Qgb2YgZHVtbXkgdmFyaWFibGVzIGluIHRoZQ0KIyMgaW1wbGljaXQgaW50ZXJuYWwgbW9kZWwgZm9ybXVsYQ0KY29sbmFtZXMobW9kZWwubXR4KQ0KYGBgDQoNClRoZXNlIGR1bW15IHZhcmlhYmxlcyB3aWxsIGFwcGVhciBpbiB0aGUgb3V0cHV0IG9mIHRoZSByZWdyZXNzaW9uIG1vZGVsIGluIHRoZSBzdWJzZXF1ZW50IG1vZGVsIG91dHB1dC4gQmVmb3JlIHN1bW1hcml6aW5nIHRoZSBtb2RlbCwgd2UgY2hlY2sgdGhlIG1vZGVsIGFzc3VtcHRpb25zIHRvIHNlZSB3aGV0aGVyIHNpZ25pZmljYW50IHZpb2xhdGlvbnMgZXhpc3QgdXNpbmcgcmVzaWR1YWwgZGlhZ25vc3RpYyBwbG90cy4NCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD03fQ0KcGFyKG1mcm93ID0gYygyLDIpKSAgIyBkZWZpbmUgdGhlIGxheW91dCB3aXRoIDJ4MiBncmFwaGljYWwgcGFuZWxzDQpwbG90KGNyb3AubG0pDQpgYGANCg0KDQpUaGUgcmVzaWR1YWwgcGxvdHMgbG9vayBmaW5lIGV4Y2VwdCBmb3IgYSBwYXR0ZXJuIGluIHRoZSBRLVEgcGxvdCwgd2hpY2ggaW5kaWNhdGVzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHJlc2lkdWFscyBpcyBzbGlnaHRseSBza2V3ZWQgdG8gdGhlIGxlZnQuIFdlIHdpbGwgbm90IGV4cGxvcmUgbWV0aG9kcyBvZiByZW1lZGllcyBpbiB0aGlzIGNsYXNzLCBidXQgdGhleSB3aWxsIGJlIGRpc2N1c3NlZCBpbiB0aGUgc3Vic2VxdWVudCBjbGFzc2VzLiBOZXh0LCB3ZSByZXBvcnQgdGhlIHJlc3VsdHMgb2YgdGhlIG1vZGVscy4NCg0KYGBge3J9DQpzdW1tYXJ5KGNyb3AubG0pDQpgYGANCg0KPGZvbnQgY29sb3IgPSAiYmx1ZSIgc2l6ZSA9IDQ+KipcY29sb3J7Ymx1ZX1PdXRwdXQgSW50ZXJwcmV0YXRpb25zKio8L2ZvbnQ+DQoNCiogVGhlIEYtdGVzdCBpbiB0aGUgYm90dG9tIHBvcnRpb24gb2YgdGhlIG91dHB1dCBpbmRpY2F0ZXMgdGhhdCBhdCBsZWFzdCBvbmUgZmFjdG9yIChgY3JvcGAgb3IgYGZlcnRpbGl6ZXJgIG9yIGJvdGgpIGlzIHNpZ25pZmljYW50ICgpDQoNCiogKipJbnRlcmNlcHQqKiAtIHRoZSBtZWFuIG9mIHlpZWxkcyBvZiBjb3JuIHVzaW5nIGZlcnRpbGl6ZXIgWC4gaS5lLiwgPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9KDEyOCArIDE1MCArIDE3NCArIDExNiArIDEwOSkvNSA9IDEzNS40LioqPC9mb250PiBUaGlzIGlzIHRoZSBiYXNlbGluZSBjYXRlZ29yeSwgZGVmaW5lZCBieSBgQ29ybmAgYW5kIGBCbGVuZCBYYC4gQWxsIG90aGVyIGNhdGVnb3JpZXMgd2lsbCBiZSBjb21wYXJlZCB0byB0aGlzIGJhc2VsaW5lIGVpdGhlciBkaXJlY3RseSBvciBpbmRpcmVjdGx5Lg0KDQogICsgVGhlIGNvZWZmaWNpZW50cyBmb3IgYENyb3BSaWNlYCwgYENyb3BTb3lgLCBhbmQgYENyb3BXaGVhdGAgcmVwcmVzZW50IHRoZSBkaWZmZXJlbmNlIGluICoqbWVhbiB5aWVsZCoqIGJldHdlZW4gdGhlc2UgY3JvcHMgYW5kIGBDb3JuYCB3aGVuIHVzaW5nIGBCbGVuZCBYYCBmZXJ0aWxpemVyLg0KICArIFRoZSBjb2VmZmljaWVudHMgZm9yIGBGZXJ0aWxpemVyQmxlbmQgWWAgYW5kIGBGZXJ0aWxpemVyQmxlbmQgWmAgcmVwcmVzZW50IHRoZSBkaWZmZXJlbmNlIGluICoqbWVhbiB5aWVsZCoqIGZvciBgQ29ybmAgd2hlbiBjb21wYXJpbmcgYEJsZW5kIFlgIGFuZCBgQmxlbmQgWmAgdG8gdGhlIGJhc2VsaW5lIChgQmxlbmQgWGApLg0KICArIFRoZSBjb2VmZmljaWVudHMgZm9yIHRoZSBpbnRlcmFjdGlvbiB0ZXJtcyBhcmUgbm90IHN0cmFpZ2h0Zm9yd2FyZCB0byBpbnRlcnByZXQgYmVjYXVzZSB0aGV5IHJlcHJlc2VudCBjb21iaW5lZCBlZmZlY3RzLiBSZWZlciB0byB0aGUgYW5ub3RhdGVkIG91dHB1dCBhbmQgb3JpZ2luYWwgZGF0YSB0YWJsZSBiZWxvdyB0byB1bmRlcnN0YW5kIGhvdyB0aGVzZSBpbnRlcmFjdGlvbiB0ZXJtIGNvZWZmaWNpZW50cyB3ZXJlIGNhbGN1bGF0ZWQuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9Ijk5JSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDUvQW5ub2F0ZWQyd2F5QU5PVkEucG5nIikNCmBgYA0KDQpBcyB3ZSBkaWQgd2l0aCB0aGUgb25lLXdheSBBTk9WQSwgd2UgY2FuIGFsc28gZXh0cmFjdCB0aGUgdHdvLXdheSBBTk9WQSB0YWJsZSBkaXJlY3RseSBmcm9tIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBhYm92ZS4NCg0KYGBge3J9DQphbm92YShjcm9wLmxtKQ0KYGBgDQoNClRoZSB0d28td2F5IEFOT1ZBIHRhYmxlIHByb3ZpZGVzIHRocmVlIEYtdGVzdHMgZm9yIGFzc2Vzc2luZyB0aGUgdHdvIGluZGl2aWR1YWwgZmFjdG9ycyBhbmQgdGhlaXIgaW50ZXJhY3Rpb24gZWZmZWN0LCB3aGVyZWFzIHRoZSBGLXRlc3QgaW4gdGhlIHJlZ3Jlc3Npb24gb3V0cHV0IG9ubHkgdGVzdHMgd2hldGhlciBhbGwgZmFjdG9ycyBhcmUgam9pbnRseSBpbnNpZ25pZmljYW504oCUYSBnbG9iYWwgZ29vZG5lc3Mtb2YtZml0IG1lYXN1cmUuIEZyb20gdGhpcyBwZXJzcGVjdGl2ZSwgdGhlIHR3by13YXkgQU5PVkEgRi10ZXN0cyBvZmZlciBtb3JlIGdyYW51bGFyIGluc2lnaHRzLiBIb3dldmVyLCByZWdyZXNzaW9uIGNvZWZmaWNpZW50IGluZmVyZW5jZSBhbGxvd3MgZm9yIG1vcmUgZGV0YWlsZWQgdGVzdGluZyBhdCBpbmRpdmlkdWFsIGZhY3RvciBsZXZlbHMsIGFzIHdlbGwgYXMgZm9yIGludGVyYWN0aW9uIGVmZmVjdHMgYmV0d2VlbiBmYWN0b3IgbGV2ZWxzLiBBbHRob3VnaCBUdWtleeKAmXMgSFNEIHByb2NlZHVyZSBwcm92aWRlcyBjb25maWRlbmNlIGludGVydmFscyAoYW5kIGZhbWlseS13aXNlIHRlc3RzIGZvciBzaW11bHRhbmVvdXMgY29tcGFyaXNvbnMpLCBpdCBkb2VzIG5vdCBleHBsaWNpdGx5IGFjY291bnQgZm9yIGludGVyYWN0aW9uIGVmZmVjdHMgaW4gdGhlIG11bHRpcGxlIGNvbXBhcmlzb25zLg0KDQoNCmBgYHtyfQ0KIyMgZml0IGFuIGFub3ZhIG1vZGVsIHNpbmNlIFR1a2V5SFNEKCkgcmVxdWlyZXMgdGhlIGFvdigpIG9iamVjdA0KY3JvcC5hb3YgPC0gYW92KFlpZWxkIH4gQ3JvcCAqIEZlcnRpbGl6ZXIsIGRhdGEgPSBjcm9wLmRhdGEpDQojIyBIU0QgY2FsbHMNClR1a2V5SFNEKGNyb3AuYW92KQ0KYGBgDQoNClRoZSBmb2xsb3dpbmcgYW5ub3RhdGVkIG91dHB1dCBpbGx1c3RyYXRlcyBob3cgdG8gY2FsY3VsYXRlIHZhcmlvdXMgZGlmZmVyZW5jZXMgaW4gdGhlIHJlc3VsdHMgb2YgVHVrZXnigJlzIEhTRCBwcm9jZWR1cmUuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9Ijk5JSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDUvSFNELUFubm90YXRpb24ucG5nIikNCmBgYA0KDQoNCldlIGNhbiBzZWUgdGhhdCBUdWtleSdzIEhTRC4gDQoNCg0KVGhlIGZvbGxvd2luZyBZb3VUdWJlIHZpZGVvICgyOCBtaW51dGVzKSBpcyBvbmUgb2YgdGhlIHZlcnkgZmV3IHRoYXQgdXNlcyBhIGxpbmVhciByZWdyZXNzaW9uIGFwcHJvYWNoIHRvIHBlcmZvcm0gQU5PVkEgYW5hbHlzaXMgKDxodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUNTNW9nQkwtTUhvPikuIFBsZWFzZSBwYXkgY2xvc2UgYXR0ZW50aW9uIHRvIHRoZSBleHBsYW5hdGlvbiBvZiB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gb3V0cHV0LCBwYXJ0aWN1bGFybHkgdGhlIGV4cGxhbmF0aW9uIG9mIHRoZSB0d28td2F5IEFOT1ZBIHdpdGggaW50ZXJhY3Rpb24gdGVybS4NClwNCg0KPGNlbnRlcj48YSBocmVmPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUNTNW9nQkwtTUhvIiB0YXJnZXQ9InBvcHVwIiANCiAgICAgICAgICAgICAgICAgICBvbmNsaWNrPSJ3aW5kb3cub3BlbignaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1DUzVvZ0JMLU1IbycsDQogICAgICAgICAgICAgICAgICAgICAgJ25hbWUnLCd3aWR0aD04NTAsaGVpZ2h0PTUwMCcpIj48aW1nIHNyYyA9ICJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9NQVQxMjFXNS9pbWcvVmlkZW9JY29uLnBuZyIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMjAiPjwvYT4NCjwvY2VudGVyPg0KDQpcDQoNCkZpbmFsbHksIHByYWN0aWNlIHR3by13YXkgQU5PVkEgdXNpbmcgcmVncmVzc2lvbiBhcHByb2FjaGVzIGJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgZGF0YSB0YWJsZSB3aXRoIHR3byBiaW5hcnkgZmFjdG9ycy4gQmVjYXVzZSBib3RoIGZhY3RvcnMgYXJlIGJpbmFyeSwgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBvdXRwdXQgc2hvdWxkIGJlIHN0cmFpZ2h0Zm9yd2FyZC4gDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjcwJSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJ3ZWVrMDQvUmVwbGljYXRlUkJELXdvcmtpbmdEYXRhLnBuZyIpDQpgYGANCg0KDQo=