View the
latest recording of this lecture
In the previous lecture we looked at tests for a relationship between
the response and at least one of the predictors in a multiple linear
regression model.
In this lecture we will examine another testing method about
predictors.
We will begin by looking at tests about a single predictor
variable.
What Precisely Are We Testing?
Consider the following question regarding the NZ Climate example:
Is the mean July temperature related to the number of sunshine
hours?
This question is essentially the same as asking, “Does
Sun
provide useful information about
MnJlyTemp
”
The answer to this depends on the context in which the question is
asked.
For example:
Sun
may be helpful in understanding
MnJlyTemp
in the absence of other information;
Sun
may not provide significant additional information
once other explanatory variables are taken into account.
For example, suppose we are modelling a measure of reading ability
(response variable) for children at primary school.
We would find that reading ability is related to height.
However, height probably does not provide additional useful
information once age is taken into account.
T Tests for Single Parameters
The summary()
command in R (and standard output from
other statistical packages) provides information for testing the
importance of a covariate “taking into account all other variables in
the model”.
When we saw this in the case of simple regression, we were making an
adjustment for only the average of responses, not for any other
predictors that affect the response.
Specifically, given the model \(Y_i =
\beta_0 + \beta_1 x_{i1} + \ldots + \beta_p x_{ip}
+ \varepsilon_i~~~(i=1,2,\ldots,n)\) the output provides
statistics for performing a t test of \[H_0: \beta_j = 0~~\mbox{versus}~~H_1: \beta_j \ne
0\] for any given variable xj, making no
assumptions about the other regression parameters.
T Tests for the Climate Regression Model
Download climate.csv
## Climate <- read.csv(file = "https://r-resources.massey.ac.nz/data/161251/Climate.csv",
## header = TRUE, row.names = 1)
Consider testing whether MnJlyTemp
is related to
Sun
, and then again having accounted for the other
variables Lat
and Height
.
Climate.lm5 = lm(MnJlyTemp ~ Sun, data = Climate)
Climate.lm5 |>
tidy() |>
kable()
(Intercept) |
-1.151124 |
4.1371927 |
-0.278238 |
0.7825148 |
Sun |
0.004295 |
0.0020775 |
2.067359 |
0.0463798 |
So, if we take a naive look at whether the sunshine hours affect the
July temperature, we probably conclude that there is evidence that there
is a relationship. This sort of naive investigation is conducted rather
too often for my liking.
The correct analysis is to include the variables we know affect the
response variable. For example let’s include Lat
and
Height
. (We could include other variables but these are
enough to make the point.)
Climate.lm6 = lm(MnJlyTemp ~ Lat + Height + Sun, data = Climate)
Climate.lm6 |>
tidy() |>
kable()
(Intercept) |
34.7991844 |
3.7668565 |
9.2382559 |
0.0000000 |
Lat |
-0.6154963 |
0.0641705 |
-9.5915784 |
0.0000000 |
Height |
-0.0073314 |
0.0009824 |
-7.4628382 |
0.0000000 |
Sun |
-0.0006514 |
0.0009694 |
-0.6719237 |
0.5064548 |
This test shows that sunchine hours do not provide useful additional
information about the July temperature having taken account of (or
adjusted for) the other variables.
This does not mean that
MnJlyTemp
is unrelated to Sun
. We saw that it
was.
Consider though that this data includes cities and towns. The
latitude and altitude of towns and cities is rather unlikely to change.
(OK, let’s not debate sea level rises courtesy of climate change just
now!)
The number of sunshine hours is likely to change from year to year
though.
While the temptation is to suggest that we ought to worry about the
amount of sunshine having a realistic impact on temperature, the
evidence is that in this context, the differences in latitude and
altitude are more important.
What this shows is that (for this data) the amount of
Sun
is related to the Lat
and
Height
variables somehow.
Added-Variable Plot (Partial Regression Plot)
Recall that for a simple linear model we can interpret the
relationship between Y and \(x\) by drawing a graph - indeed you should
always look at a fitted line plot, and possibly a scatterplot with a
lowess line as well. The slope that shows up on the fitted line plot
exactly matches that which is given in the Regression output.
However for a multiple regression, as we have seen, the regression
parameters are usually different to what you get with a simple
regression, and so the fitted line plot is no help with visualising the
relationship between Y and \(x_1\) or between Y and \(x_2\) (etc.). This is where the
Added-variable plot (or “Partial Regression Plot”) comes in.
This plot is based on the idea that if we want to visualise \(\hat{\beta}_{Sun}\) we subtract out all the
information provided by the other variable/variables in the model from
Lat
and Height
in this case). Then we plot the
residual information in Y against the residual information in
Sun
.
This gives what can be thought of as a “pure” Sun
effect’, i.e. a contribution coming only from Sun
and not
expressed by the other two variables.
Specifically (using a more general notation) let the explanatory
variables be written as \(X_1,…., X_i,
...,X_p\) and we suppose we want to visualise the graph
corresponding to regression coefficient \(\hat\beta_i\)
We regress Y against all the predictors except \(X_i\) i.e. regress Y vs \(x_1,...x_{i-1},x_{i+1},...X_p\). Save the
residuals e
. These residuals represent the information in
Y which is not explained by any of the other
variables.
Now also regress \(X_i\) against
\(x_1,...x_{i-1},x_{x+1},...x_p\). Save
the residuals f
.
These residuals represent the information in \(x_i\) not contained in any other
variable.
- Now plot
e
against f
. Any trend in the
plot can be thought of as a “pure” Y vs \(x_i\) relationship. In particular, a fitted
line plot of e
against f
will produce a graph
with exactly the same slope as in the full regression
model. (i.e. with Y predicted by all the
regression variables at once.)
A frequent benefit of doing this plot is that it may show that a
‘significant’ predictor is in fact only significant because of an
outlier in \(X_i\) or Y. The
outlier may not show up as being unusual when the raw \(X_i\) value was plotted against Y.
However in relation to other variables it does show up as an outlier. In
this circumstance you may decide to delete the outlier and refit the
model, in order to see whether the ‘added variable’ \(X_i\) is really needed.
Example
We fitted a model with just Lat
and Height
a couple of lectures back. It was:
Climate.lm3 = lm(MnJlyTemp ~ Lat + Height, data = Climate)
Climate.lm3 |>
tidy() |>
kable()
(Intercept) |
32.8788366 |
2.4333203 |
13.511923 |
0 |
Lat |
-0.6005121 |
0.0596687 |
-10.064098 |
0 |
Height |
-0.0071984 |
0.0009542 |
-7.543891 |
0 |
We will need the residuals from this model and the model using
Sun
as the response variable.
Climate.lm4 = lm(Sun ~ Lat + Height, data = Climate)
Climate.lm4 |>
tidy() |>
kable()
(Intercept) |
2948.1923582 |
440.6338786 |
6.690798 |
0.0000001 |
Lat |
-23.0044035 |
10.8050185 |
-2.129048 |
0.0408019 |
Height |
-0.2042485 |
0.1727897 |
-1.182064 |
0.2456282 |
e = resid(Climate.lm3)
f = resid(Climate.lm4)
plot(e ~ f)
lines(lowess(f, e)) # note the ordering there
(Intercept) f
2.101067e-17 -6.513645e-04
Interpreting the Correlation and \(R^2\) from an Added Variable Plot.
Usefully, if we calculate a correlation R, or the \(R^2\) from the regression of e
on f
, then these are also interpretable.
Partial correlation
The correlation of the two sets of residuals e and
f represent how closely related Y and \(X_i\) are once one adjusts both variables
for the effect of the other covariates \(X_1,...,X_{i-1},X_{i+1},...,X_p\). This is
called the Partial correlation.
Pearson's product-moment correlation
data: e and f
t = -0.6926, df = 34, p-value = 0.4933
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
-0.4298306 0.2190738
sample estimates:
cor
-0.1179513
Partial \(R^2\)
Since e is the residuals after regressing Y on
\(x_1,...x_{i-1},x_{x+1},...X_p\) then
it represents the variation in Y not explained by the rest of
the predictors. Therefore, when we regress the residuals e on
f we get an \(R^2\) which is
the proportion of previously unexplained variation which is now
explained (i.e. it shows the additional benefit of the extra
variable).
names(summary(lm(e ~ f)))
[1] "call" "terms" "residuals" "coefficients"
[5] "aliased" "sigma" "df" "r.squared"
[9] "adj.r.squared" "fstatistic" "cov.unscaled"
summary(lm(e ~ f))$r.squared
[1] 0.01391251
summary(Climate.lm3)$r.squared
[1] 0.8467109
For the regression of mean July temperature on Lat
and
Height
, the \(R^2\) was
84.7%.
Given we saw that Sun
was not significant once added to
the model with Lat
and Height`, we ought to expect only a
small increase in \(R^2\). It was
84.9%, found using:
summary(Climate.lm6)$r.squared
[1] 0.8488436
Important things that changed
The adjustment for other variables caused the coefficient for
Sun
to change, but equally importantly, the standard error
for Sun
also changed. It is the combination of these
changes that will show the impact of the adjustment for other
predictors.
Adding variables can make a variable either more important or less
important. The t test and p-value are only going to
remain unchanged in an extremely specific scenario which is almost
impossible for observational study data.
Optional Task: Hospital Maintenance Data
Data are from 12 naval hospitals in the USA. Response variable,
ManHours
, is monthly man-hours associated with maintaining
the anaesthesiology service. Explanatory variables are
Cases |
The number of surgical cases |
Eligible |
the eligible population per thousand |
OpRooms |
the number of operating rooms |
Source: A Handbook of Small Data Sets by Hand, Daly, Lunn,
McConway and Ostrowski.
R output
Download hospital.csv
## Hospital <- read.csv(file = "https://r-resources.massey.ac.nz/161221/data/hospital.csv",
## header = TRUE)
Hospital.lm <- lm(ManHours ~ ., data = Hospital)
summary(Hospital.lm)
Call:
lm(formula = ManHours ~ ., data = Hospital)
Residuals:
Min 1Q Median 3Q Max
-218.669 -98.962 -3.585 112.429 195.408
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -114.5895 130.3392 -0.879 0.4049
Cases 2.0315 0.6778 2.997 0.0171 *
Eligible 2.2714 1.6820 1.350 0.2138
OpRooms 99.7254 42.2158 2.362 0.0458 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 165.5 on 8 degrees of freedom
Multiple R-squared: 0.9855, Adjusted R-squared: 0.98
F-statistic: 181 on 3 and 8 DF, p-value: 1.087e-07
Questions
Is ManHours
related to at least one of the
explanatory variables?
Does Cases
provide additional information about
ManHours
when the other explanatory variables are taken
into account?
Does Eligible
provide additional information about
ManHours
when the other explanatory variables are taken
into account?
Is ManHours
related to
Eligible
?
To understand more about these data, look at scatter plots of the
response against each of the explanatory variables.
Summary for Tests for a Single Predictor
T-tests can be used to test single parameters, and hence
assess the importance of single variables in a multiple linear
regression model.
The interpretation of these tests depends on what other variables are
included in the model.
To test the importance of groups of multiple covariates requires
F tests, using the type of technology that was introduced in
the previous lecture.
LS0tDQp0aXRsZTogIkxlY3R1cmUgMTE6IFRlc3RpbmcgaW4gTXVsdGlwbGUgUmVncmVzc2lvbiBNb2RlbHMgKDIpIg0Kc3VidGl0bGU6IDE2MS4yNTEgUmVncmVzc2lvbiBNb2RlbGxpbmcNCmF1dGhvcjogIlByZXNlbnRlZCBieSBKb25hdGhhbiBHb2RmcmV5IDxhLmouZ29kZnJleUBtYXNzZXkuYWMubno+IiAgDQpkYXRlOiAiV2VlayA0IG9mIFNlbWVzdGVyIDIsIGByIGx1YnJpZGF0ZTo6eWVhcihsdWJyaWRhdGU6Om5vdygpKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiB5ZXRpDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0aGVtZTogeWV0aQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgaW9zbGlkZXNfcHJlc2VudGF0aW9uOg0KICAgIHdpZGVzY3JlZW46IHRydWUNCiAgICBzbWFsbGVyOiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgc2xpZHlfcHJlc2VudGF0aW9uOiANCiAgICB0aGVtZTogeWV0aQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQoNCg0KDQpbVmlldyB0aGUgbGF0ZXN0IHJlY29yZGluZyBvZiB0aGlzIGxlY3R1cmVdKGh0dHBzOi8vUi1SZXNvdXJjZXMubWFzc2V5LmFjLm56L3ZpZGVvcy8yNTFMMTEubXA0KQ0KPCEtLS0gRGF0YSBpcyBvbg0KaHR0cHM6Ly9yLXJlc291cmNlcy5tYXNzZXkuYWMubnovZGF0YS8xNjEyNTEvDQotLS0+DQoNCmBgYHtyIHNldHVwLCBwdXJsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCm9wdHNfY2h1bmskc2V0KGRldj1jKCJwbmciLCAicGRmIikpDQpvcHRzX2NodW5rJHNldChmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD03LCBmaWcucGF0aD0iRmlndXJlcy8iLCBmaWcuYWx0PSJ1bmxhYmVsbGVkIikNCm9wdHNfY2h1bmskc2V0KGNvbW1lbnQ9IiIsIGZpZy5hbGlnbj0iY2VudGVyIiwgdGlkeT1UUlVFKQ0Kb3B0aW9ucyhrbml0ci5rYWJsZS5OQSA9ICcnKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGJyb29tKQ0KYGBgDQoNCg0KPCEtLS0gRG8gbm90IGVkaXQgYW55dGhpbmcgYWJvdmUgdGhpcyBsaW5lLiAtLS0+DQoNCjwhLS0tIGhvc3BpdGFsIGlzIEdMTXNEYXRhOjpuaG9zcGl0YWwgLS0tPg0KDQoNCg0KSW4gdGhlIHByZXZpb3VzIGxlY3R1cmUgd2UgbG9va2VkIGF0IHRlc3RzIGZvciBhIHJlbGF0aW9uc2hpcA0KICAgIGJldHdlZW4gdGhlIHJlc3BvbnNlIGFuZCBhdCBsZWFzdCBvbmUgb2YgdGhlIHByZWRpY3RvcnMgaW4gYQ0KICAgIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLg0KDQpJbiB0aGlzIGxlY3R1cmUgd2Ugd2lsbCBleGFtaW5lIGFub3RoZXIgdGVzdGluZyBtZXRob2QgYWJvdXQgcHJlZGljdG9ycy4NCg0KV2Ugd2lsbCBiZWdpbiBieSBsb29raW5nIGF0IHRlc3RzIGFib3V0IGEgc2luZ2xlIHByZWRpY3RvciB2YXJpYWJsZS4NCg0KIyMgV2hhdCBQcmVjaXNlbHkgQXJlIFdlIFRlc3Rpbmc/DQoNCkNvbnNpZGVyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb24gcmVnYXJkaW5nIHRoZSBOWiBDbGltYXRlIGV4YW1wbGU6ICANCg0KSXMgdGhlIG1lYW4gSnVseSB0ZW1wZXJhdHVyZSByZWxhdGVkIHRvIHRoZSBudW1iZXIgb2Ygc3Vuc2hpbmUgaG91cnM/DQoNCg0KVGhpcyBxdWVzdGlvbiBpcyBlc3NlbnRpYWxseSB0aGUgc2FtZSBhcyBhc2tpbmcsICJEb2VzIGBTdW5gIHByb3ZpZGUgdXNlZnVsIGluZm9ybWF0aW9uIGFib3V0IGBNbkpseVRlbXBgIg0KDQpUaGUgYW5zd2VyIHRvIHRoaXMgZGVwZW5kcyBvbiB0aGUgY29udGV4dCBpbiB3aGljaCB0aGUgcXVlc3Rpb24gaXMgYXNrZWQuDQoNCkZvciBleGFtcGxlOg0KDQotIGBTdW5gIG1heSBiZSBoZWxwZnVsIGluIHVuZGVyc3RhbmRpbmcgYE1uSmx5VGVtcGAgaW4gdGhlIGFic2VuY2Ugb2Ygb3RoZXIgaW5mb3JtYXRpb247DQotIGBTdW5gIG1heSBub3QgcHJvdmlkZSBzaWduaWZpY2FudCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIG9uY2Ugb3RoZXIgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGFyZSB0YWtlbiBpbnRvIGFjY291bnQuDQoNCg0KRm9yIGV4YW1wbGUsIHN1cHBvc2Ugd2UgYXJlIG1vZGVsbGluZyBhIG1lYXN1cmUgb2YgcmVhZGluZyBhYmlsaXR5DQogICAgKHJlc3BvbnNlIHZhcmlhYmxlKSBmb3IgY2hpbGRyZW4gYXQgcHJpbWFyeSBzY2hvb2wuDQoNCldlIHdvdWxkIGZpbmQgdGhhdCByZWFkaW5nIGFiaWxpdHkgaXMgcmVsYXRlZCB0byBoZWlnaHQuDQoNCkhvd2V2ZXIsIGhlaWdodCBwcm9iYWJseSBkb2VzIG5vdCBwcm92aWRlIGFkZGl0aW9uYWwgdXNlZnVsIGluZm9ybWF0aW9uIG9uY2UgYWdlIGlzIHRha2VuIGludG8gYWNjb3VudC4NCg0KIyMgVCBUZXN0cyBmb3IgU2luZ2xlIFBhcmFtZXRlcnMNCg0KVGhlIGBzdW1tYXJ5KClgIGNvbW1hbmQgaW4gUiAoYW5kIHN0YW5kYXJkIG91dHB1dCBmcm9tIG90aGVyIHN0YXRpc3RpY2FsIHBhY2thZ2VzKSBwcm92aWRlcyBpbmZvcm1hdGlvbiBmb3IgdGVzdGluZyB0aGUgaW1wb3J0YW5jZSBvZiBhIGNvdmFyaWF0ZSAidGFraW5nIGludG8gYWNjb3VudCBhbGwgb3RoZXIgdmFyaWFibGVzIGluIHRoZSBtb2RlbCIuDQoNCldoZW4gd2Ugc2F3IHRoaXMgaW4gdGhlIGNhc2Ugb2Ygc2ltcGxlIHJlZ3Jlc3Npb24sIHdlIHdlcmUgbWFraW5nIGFuIGFkanVzdG1lbnQgZm9yIG9ubHkgdGhlIGF2ZXJhZ2Ugb2YgcmVzcG9uc2VzLCBub3QgZm9yIGFueSBvdGhlciBwcmVkaWN0b3JzIHRoYXQgYWZmZWN0IHRoZSByZXNwb25zZS4NCg0KU3BlY2lmaWNhbGx5LCBnaXZlbiB0aGUgbW9kZWwgJFlfaSA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfe2kxfSArIFxsZG90cyArIFxiZXRhX3AgeF97aXB9ICsgICAgICBcdmFyZXBzaWxvbl9pfn5+KGk9MSwyLFxsZG90cyxuKSQgdGhlIG91dHB1dCBwcm92aWRlcw0KICAgIHN0YXRpc3RpY3MgZm9yIHBlcmZvcm1pbmcgYSAqdCogdGVzdCBvZiAkJEhfMDogXGJldGFfaiA9IDB+flxtYm94e3ZlcnN1c31+fkhfMTogXGJldGFfaiBcbmUgMCQkDQogICAgZm9yIGFueSBnaXZlbiB2YXJpYWJsZSAqeH5qfiosIG1ha2luZyBubyBhc3N1bXB0aW9ucyBhYm91dCB0aGUgICAgb3RoZXIgcmVncmVzc2lvbg0KcGFyYW1ldGVycy4NCg0KIyMgVCBUZXN0cyBmb3IgdGhlIENsaW1hdGUgUmVncmVzc2lvbiBNb2RlbA0KDQoNCmByIHhmdW46OmVtYmVkX2ZpbGUoIi4uLy4uL2RhdGEvY2xpbWF0ZS5jc3YiKWAgDQoNCmBgYHtyIGdldENsaW1hdGUsIGVjaG89LTEsIGV2YWw9LTJ9DQpDbGltYXRlIDwtIHJlYWQuY3N2KGZpbGU9Ii4uLy4uL2RhdGEvQ2xpbWF0ZS5jc3YiLCBoZWFkZXI9VFJVRSwgcm93Lm5hbWVzPTEpIA0KQ2xpbWF0ZSA8LSByZWFkLmNzdihmaWxlPSJodHRwczovL3ItcmVzb3VyY2VzLm1hc3NleS5hYy5uei9kYXRhLzE2MTI1MS9DbGltYXRlLmNzdiIsIGhlYWRlcj1UUlVFLCByb3cubmFtZXM9MSkgDQpgYGANCg0KQ29uc2lkZXIgdGVzdGluZyB3aGV0aGVyIGBNbkpseVRlbXBgIGlzIHJlbGF0ZWQgdG8gYFN1bmAsIGFuZCB0aGVuIGFnYWluICBoYXZpbmcgYWNjb3VudGVkIGZvciB0aGUgb3RoZXIgdmFyaWFibGVzIGBMYXRgIGFuZCBgSGVpZ2h0YC4NCg0KYGBge3IgQ2xpbWF0ZS5sbTV9DQpDbGltYXRlLmxtNSA9IGxtKE1uSmx5VGVtcH5TdW4sIGRhdGE9Q2xpbWF0ZSkNCkNsaW1hdGUubG01IHw+IHRpZHkoKSB8PiBrYWJsZSgpDQpgYGANCg0KDQpTbywgaWYgd2UgdGFrZSBhIG5haXZlIGxvb2sgYXQgd2hldGhlciB0aGUgc3Vuc2hpbmUgaG91cnMgYWZmZWN0IHRoZSBKdWx5IHRlbXBlcmF0dXJlLCB3ZSBwcm9iYWJseSBjb25jbHVkZSB0aGF0IHRoZXJlIGlzIGV2aWRlbmNlIHRoYXQgdGhlcmUgaXMgYSByZWxhdGlvbnNoaXAuIFRoaXMgc29ydCBvZiBuYWl2ZSBpbnZlc3RpZ2F0aW9uIGlzIGNvbmR1Y3RlZCByYXRoZXIgdG9vIG9mdGVuIGZvciBteSBsaWtpbmcuDQoNClRoZSBjb3JyZWN0IGFuYWx5c2lzIGlzIHRvIGluY2x1ZGUgdGhlIHZhcmlhYmxlcyB3ZSBrbm93IGFmZmVjdCB0aGUgcmVzcG9uc2UgdmFyaWFibGUuIEZvciBleGFtcGxlIGxldCdzIGluY2x1ZGUgYExhdGAgYW5kIGBIZWlnaHQJYC4gKFdlIGNvdWxkIGluY2x1ZGUgb3RoZXIgdmFyaWFibGVzIGJ1dCB0aGVzZSBhcmUgZW5vdWdoIHRvIG1ha2UgdGhlIHBvaW50LikNCg0KYGBge3IgQ2xpbWF0ZS5sbTZ9DQpDbGltYXRlLmxtNiA9IGxtKE1uSmx5VGVtcH5MYXQrSGVpZ2h0K1N1biwgZGF0YT1DbGltYXRlKQ0KQ2xpbWF0ZS5sbTYgfD4gdGlkeSgpIHw+IGthYmxlKCkNCmBgYA0KDQoNCg0KVGhpcyB0ZXN0IHNob3dzIHRoYXQgc3VuY2hpbmUgaG91cnMgZG8gbm90IHByb3ZpZGUgdXNlZnVsIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgdGhlIEp1bHkgdGVtcGVyYXR1cmUgaGF2aW5nIHRha2VuIGFjY291bnQgb2YgKG9yICoqYWRqdXN0ZWQgZm9yKiopIHRoZSBvdGhlciB2YXJpYWJsZXMuDQoNClRoaXMgZG9lcyAqKipub3QqKiogbWVhbiB0aGF0IGBNbkpseVRlbXBgIGlzIHVucmVsYXRlZCB0byBgU3VuYC4gV2Ugc2F3IHRoYXQgaXQgd2FzLg0KDQpDb25zaWRlciB0aG91Z2ggdGhhdCB0aGlzIGRhdGEgaW5jbHVkZXMgY2l0aWVzIGFuZCB0b3ducy4gVGhlIGxhdGl0dWRlIGFuZCBhbHRpdHVkZSBvZiB0b3ducyBhbmQgY2l0aWVzIGlzIHJhdGhlciB1bmxpa2VseSB0byBjaGFuZ2UuIChPSywgbGV0J3Mgbm90IGRlYmF0ZSBzZWEgbGV2ZWwgcmlzZXMgY291cnRlc3kgb2YgY2xpbWF0ZSBjaGFuZ2UganVzdCBub3chKQ0KDQpUaGUgbnVtYmVyIG9mIHN1bnNoaW5lIGhvdXJzIGlzIGxpa2VseSB0byBjaGFuZ2UgZnJvbSB5ZWFyIHRvIHllYXIgdGhvdWdoLg0KDQpXaGlsZSB0aGUgdGVtcHRhdGlvbiBpcyB0byBzdWdnZXN0IHRoYXQgd2Ugb3VnaHQgdG8gd29ycnkgYWJvdXQgdGhlIGFtb3VudCBvZiBzdW5zaGluZSBoYXZpbmcgYSByZWFsaXN0aWMgaW1wYWN0IG9uIHRlbXBlcmF0dXJlLCB0aGUgZXZpZGVuY2UgaXMgdGhhdCBpbiB0aGlzIGNvbnRleHQsIHRoZSBkaWZmZXJlbmNlcyBpbiBsYXRpdHVkZSBhbmQgYWx0aXR1ZGUgYXJlIG1vcmUgaW1wb3J0YW50Lg0KDQpXaGF0IHRoaXMgc2hvd3MgaXMgdGhhdCAoZm9yIHRoaXMgZGF0YSkgdGhlIGFtb3VudCBvZiBgU3VuYCBpcyByZWxhdGVkIHRvIHRoZSBgTGF0YCBhbmQgYEhlaWdodGAgdmFyaWFibGVzIHNvbWVob3cuIA0KDQojIyBBZGRlZC1WYXJpYWJsZSBQbG90ICAgICAoUGFydGlhbCBSZWdyZXNzaW9uIFBsb3QpDQoNClJlY2FsbCB0aGF0IGZvciBhIHNpbXBsZSBsaW5lYXIgbW9kZWwgd2UgY2FuIGludGVycHJldCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKlkqIGFuZCAkeCQgIGJ5IGRyYXdpbmcgYSBncmFwaCAgLSAgaW5kZWVkIHlvdSBzaG91bGQgYWx3YXlzIGxvb2sgYXQgYSBmaXR0ZWQgbGluZSBwbG90LCBhbmQgcG9zc2libHkgYSBzY2F0dGVycGxvdCB3aXRoIGEgbG93ZXNzDQpsaW5lICBhcyB3ZWxsLiAgIFRoZSBzbG9wZSB0aGF0IHNob3dzIHVwIG9uIHRoZSBmaXR0ZWQgbGluZSBwbG90IGV4YWN0bHkgbWF0Y2hlcyB0aGF0IHdoaWNoIGlzIGdpdmVuIGluIHRoZSBSZWdyZXNzaW9uIG91dHB1dC4NCg0KSG93ZXZlciBmb3IgYSBtdWx0aXBsZSByZWdyZXNzaW9uLCBhcyB3ZSBoYXZlIHNlZW4sIHRoZSByZWdyZXNzaW9uIHBhcmFtZXRlcnMgYXJlIHVzdWFsbHkgZGlmZmVyZW50IHRvIHdoYXQgeW91IGdldCB3aXRoIGEgc2ltcGxlIHJlZ3Jlc3Npb24sIGFuZCBzbyB0aGUgZml0dGVkIGxpbmUgcGxvdCBpcyBubyBoZWxwIHdpdGggdmlzdWFsaXNpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICpZKiBhbmQgJHhfMSQgb3IgYmV0d2VlbiAqWSogYW5kICR4XzIkIChldGMuKS4gDQogVGhpcyBpcyB3aGVyZSB0aGUgQWRkZWQtdmFyaWFibGUgcGxvdCAob3Ig4oCcUGFydGlhbCBSZWdyZXNzaW9uIFBsb3TigJ0pICBjb21lcyBpbi4gIA0KDQpUaGlzIHBsb3QgaXMgYmFzZWQgb24gdGhlIGlkZWEgdGhhdCBpZiB3ZSB3YW50IHRvIHZpc3VhbGlzZSAkXGhhdHtcYmV0YX1fe1N1bn0kDQp3ZSBzdWJ0cmFjdCBvdXQgYWxsIHRoZSBpbmZvcm1hdGlvbiBwcm92aWRlZCBieSB0aGUgb3RoZXIgdmFyaWFibGUvdmFyaWFibGVzICBpbiB0aGUgbW9kZWwgZnJvbSBgTGF0YCBhbmQgYEhlaWdodGAgaW4gdGhpcyBjYXNlKS4gVGhlbiB3ZSBwbG90IHRoZSByZXNpZHVhbCBpbmZvcm1hdGlvbiBpbiAqWSogDQphZ2FpbnN0IHRoZSByZXNpZHVhbCBpbmZvcm1hdGlvbiBpbiBgU3VuYC4NCg0KVGhpcyBnaXZlcyB3aGF0IGNhbiBiZSB0aG91Z2h0IG9mIGFzIGEgInB1cmUiICBgU3VuYCBlZmZlY3TigJksIGkuZS4gYSBjb250cmlidXRpb24gY29taW5nIG9ubHkgZnJvbSAgYFN1bmAgYW5kIG5vdCBleHByZXNzZWQgYnkgdGhlIG90aGVyIHR3byB2YXJpYWJsZXMuDQoNClNwZWNpZmljYWxseSAgKHVzaW5nIGEgbW9yZSBnZW5lcmFsIG5vdGF0aW9uKSAgbGV0IHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYmUgd3JpdHRlbiBhcyAgJFhfMSzigKYuLCBYX2ksIC4uLixYX3AkDQphbmQgd2Ugc3VwcG9zZSB3ZSB3YW50IHRvIHZpc3VhbGlzZSB0aGUgZ3JhcGggY29ycmVzcG9uZGluZyB0byByZWdyZXNzaW9uIGNvZWZmaWNpZW50ICRcaGF0XGJldGFfaSQNCg0KKDEpICBXZSByZWdyZXNzICpZKiBhZ2FpbnN0IGFsbCB0aGUgcHJlZGljdG9ycyBleGNlcHQgJFhfaSQNCmkuZS4gcmVncmVzcyAqWSogdnMgJHhfMSwuLi54X3tpLTF9LHhfe2krMX0sLi4uWF9wJC4gDQpTYXZlIHRoZSByZXNpZHVhbHMgIGBlYC4gVGhlc2UgcmVzaWR1YWxzIHJlcHJlc2VudCB0aGUgaW5mb3JtYXRpb24gaW4gKlkqIHdoaWNoIGlzIG5vdCBleHBsYWluZWQgYnkgYW55IG9mIHRoZSBvdGhlciB2YXJpYWJsZXMuDQoNCigyKSAgIE5vdyBhbHNvIHJlZ3Jlc3MgJFhfaSQgYWdhaW5zdCAgICR4XzEsLi4ueF97aS0xfSx4X3t4KzF9LC4uLnhfcCQuIFNhdmUgdGhlIHJlc2lkdWFscyBgZmAuIA0KIA0KVGhlc2UgcmVzaWR1YWxzICByZXByZXNlbnQgdGhlIGluZm9ybWF0aW9uIGluICR4X2kkIG5vdCBjb250YWluZWQgaW4gYW55IG90aGVyIHZhcmlhYmxlLg0KDQooMykgIE5vdyBwbG90ICBgZWAgYWdhaW5zdCAgYGZgLiBBbnkgdHJlbmQgaW4gdGhlIHBsb3QgY2FuIGJlIHRob3VnaHQgb2YgYXMgYSAicHVyZSIgKlkqIHZzICR4X2kkICByZWxhdGlvbnNoaXAuICBJbiBwYXJ0aWN1bGFyLCBhIGZpdHRlZCBsaW5lIHBsb3Qgb2YgYGVgICBhZ2FpbnN0IGBmYCAgd2lsbCBwcm9kdWNlIGEgZ3JhcGggd2l0aCAqKipleGFjdGx5IHRoZSBzYW1lICBzbG9wZSBhcyBpbiB0aGUgIGZ1bGwgcmVncmVzc2lvbiBtb2RlbC4qKiogICAoaS5lLiB3aXRoICpZKg0KcHJlZGljdGVkIGJ5IGFsbCB0aGUgcmVncmVzc2lvbiB2YXJpYWJsZXMgYXQgb25jZS4pICANCg0KQSBmcmVxdWVudCBiZW5lZml0IG9mIGRvaW5nIHRoaXMgcGxvdCBpcyB0aGF0IGl0IG1heSBzaG93IHRoYXQgYSDigJhzaWduaWZpY2FudOKAmSBwcmVkaWN0b3IgaXMgaW4gZmFjdCBvbmx5IHNpZ25pZmljYW50IGJlY2F1c2Ugb2YgYW4gb3V0bGllciBpbiAkWF9pJCBvciAqWSouICAgICBUaGUgb3V0bGllciBtYXkgbm90IHNob3cgdXAgYXMgYmVpbmcgdW51c3VhbCB3aGVuIHRoZSByYXcgJFhfaSQgdmFsdWUgd2FzIHBsb3R0ZWQgYWdhaW5zdCAqWSouICAgSG93ZXZlciBpbiByZWxhdGlvbiB0byBvdGhlciB2YXJpYWJsZXMgaXQgZG9lcyBzaG93IHVwIGFzIGFuIG91dGxpZXIuICAgSW4gdGhpcyBjaXJjdW1zdGFuY2UgeW91IG1heSBkZWNpZGUgdG8gZGVsZXRlIHRoZSBvdXRsaWVyICAgYW5kIHJlZml0IHRoZSBtb2RlbCwgaW4gb3JkZXIgdG8gc2VlIHdoZXRoZXIgdGhlIOKAmGFkZGVkIHZhcmlhYmxl4oCZICRYX2kkIGlzIHJlYWxseSBuZWVkZWQuDQoNCg0KIyMjIEV4YW1wbGUNCg0KV2UgZml0dGVkIGEgbW9kZWwgd2l0aCBqdXN0IGBMYXRgIGFuZCBgSGVpZ2h0YCBhIGNvdXBsZSBvZiBsZWN0dXJlcyBiYWNrLiBJdCB3YXM6DQoNCmBgYHtyICBDbGltYXRlLmxtM30NCiBDbGltYXRlLmxtMyA9IGxtKE1uSmx5VGVtcCB+IExhdCArIEhlaWdodCwgZGF0YT1DbGltYXRlKQ0KQ2xpbWF0ZS5sbTMgfD4gdGlkeSgpIHw+IGthYmxlKCkNCmBgYA0KDQpXZSB3aWxsIG5lZWQgdGhlIHJlc2lkdWFscyBmcm9tIHRoaXMgbW9kZWwgYW5kIHRoZSBtb2RlbCB1c2luZyBgU3VuYCBhcyB0aGUgcmVzcG9uc2UgdmFyaWFibGUuDQoNCmBgYHtyICBDbGltYXRlLmxtNH0NCiBDbGltYXRlLmxtNCA9IGxtKFN1biB+IExhdCArIEhlaWdodCwgZGF0YT1DbGltYXRlKQ0KQ2xpbWF0ZS5sbTQgfD4gdGlkeSgpIHw+IGthYmxlKCkNCmBgYA0KDQoNCg0KDQpgYGB7ciBhZGRlZFZhcmlhYmxlUGxvdCwgZmlnLmNhcD0iUGFydGlhbCBSZWdyZXNzaW9uIFBsb3QgZm9yIGBNbkpseVRlbXBgIGFnYWluc3QgYFN1bmAsIGFkanVzdGluZyBmb3IgYExhdGAgYW5kIGBIZWlnaHRgLiJ9DQplPXJlc2lkKENsaW1hdGUubG0zKQ0KZj1yZXNpZChDbGltYXRlLmxtNCkNCnBsb3QoZX5mKQ0KbGluZXMobG93ZXNzKGYsZSkpICMgbm90ZSB0aGUgb3JkZXJpbmcgdGhlcmUNCmNvZWYobG0oZX5mKSkNCmBgYA0KDQojIyMgSW50ZXJwcmV0aW5nIHRoZSBDb3JyZWxhdGlvbiBhbmQgJFJeMiQgZnJvbSBhbiBBZGRlZCBWYXJpYWJsZSBQbG90Lg0KDQpVc2VmdWxseSwgaWYgd2UgY2FsY3VsYXRlIGEgY29ycmVsYXRpb24gKlIqLCAgb3IgdGhlICRSXjIkIGZyb20gdGhlIHJlZ3Jlc3Npb24gb2YgYGVgIG9uIGBmYCwgdGhlbiB0aGVzZSBhcmUgYWxzbyBpbnRlcnByZXRhYmxlLiANCg0KIyMjIFBhcnRpYWwgY29ycmVsYXRpb24gDQoNClRoZSBjb3JyZWxhdGlvbiBvZiB0aGUgdHdvIHNldHMgb2YgcmVzaWR1YWxzICplKiBhbmQgKmYqIHJlcHJlc2VudCBob3cgY2xvc2VseSByZWxhdGVkICpZKiBhbmQgJFhfaSQgYXJlIG9uY2Ugb25lIGFkanVzdHMgYm90aCB2YXJpYWJsZXMgZm9yIHRoZSBlZmZlY3Qgb2YgdGhlIG90aGVyIGNvdmFyaWF0ZXMgJFhfMSwuLi4sWF97aS0xfSxYX3tpKzF9LC4uLixYX3AkLiBUaGlzIGlzIGNhbGxlZCB0aGUgUGFydGlhbCBjb3JyZWxhdGlvbi4NCg0KYGBge3IgcGFydGlhbCBjb3JyZWxhdGlvbn0NCmNvci50ZXN0KGUsZikNCmBgYA0KDQojIyMgUGFydGlhbCAkUl4yJA0KDQpTaW5jZSAqZSogaXMgdGhlIHJlc2lkdWFscyBhZnRlciByZWdyZXNzaW5nICpZKiBvbiAgJHhfMSwuLi54X3tpLTF9LHhfe3grMX0sLi4uWF9wJCB0aGVuIGl0IHJlcHJlc2VudHMgdGhlIHZhcmlhdGlvbiBpbiAqWSogbm90IGV4cGxhaW5lZCBieSB0aGUgcmVzdCBvZiB0aGUgcHJlZGljdG9ycy4gDQpUaGVyZWZvcmUsIHdoZW4gd2UgcmVncmVzcyB0aGUgcmVzaWR1YWxzICplKiBvbiAqZiogDQp3ZSBnZXQgYW4gJFJeMiQgDQp3aGljaCBpcyB0aGUgcHJvcG9ydGlvbiBvZiAqKnByZXZpb3VzbHkgdW5leHBsYWluZWQgdmFyaWF0aW9uIHdoaWNoIGlzIG5vdyBleHBsYWluZWQqKiAoaS5lLiBpdCBzaG93cyB0aGUgYWRkaXRpb25hbCBiZW5lZml0IG9mIHRoZSBleHRyYSB2YXJpYWJsZSkuDQoNCmBgYHtyIHBlcmNlbnQgbm93IGV4cGxhaW5lZH0NCm5hbWVzKHN1bW1hcnkobG0oZSB+IGYpKSkNCnN1bW1hcnkobG0oZSB+IGYpKSRyLnNxdWFyZWQNCnN1bW1hcnkoQ2xpbWF0ZS5sbTMpJHIuc3F1YXJlZA0KYGBgDQoNCkZvciB0aGUgcmVncmVzc2lvbiBvZiBtZWFuIEp1bHkgdGVtcGVyYXR1cmUgIG9uIGBMYXRgIGFuZCBgSGVpZ2h0YCwgdGhlICRSXjIkICB3YXMgYHIgcm91bmQoMTAwKnN1bW1hcnkoQ2xpbWF0ZS5sbTMpJHIuc3F1YXJlZCwgMSlgJS4NCg0KR2l2ZW4gd2Ugc2F3IHRoYXQgYFN1bmAgd2FzIG5vdCBzaWduaWZpY2FudCBvbmNlIGFkZGVkIHRvIHRoZSBtb2RlbCB3aXRoIGBMYXRgIGFuZCBIZWlnaHRgLCB3ZSBvdWdodCB0byBleHBlY3Qgb25seSBhIHNtYWxsIGluY3JlYXNlIGluICRSXjIkLiBJdCAgd2FzIGByIHJvdW5kKDEwMCpzdW1tYXJ5KENsaW1hdGUubG02KSRyLnNxdWFyZWQsIDEpYCUsIGZvdW5kIHVzaW5nOg0KDQpgYGB7ciBSMkNsaW1hdGUubG02fQ0Kc3VtbWFyeShDbGltYXRlLmxtNikkci5zcXVhcmVkDQpgYGANCg0KDQoNCg0KDQojIyMgSW1wb3J0YW50IHRoaW5ncyB0aGF0IGNoYW5nZWQNCg0KVGhlIGFkanVzdG1lbnQgZm9yIG90aGVyIHZhcmlhYmxlcyBjYXVzZWQgdGhlIGNvZWZmaWNpZW50IGZvciBgU3VuYCB0byBjaGFuZ2UsIGJ1dCBlcXVhbGx5IGltcG9ydGFudGx5LCB0aGUgc3RhbmRhcmQgZXJyb3IgZm9yIGBTdW5gIGFsc28gY2hhbmdlZC4gSXQgaXMgdGhlIGNvbWJpbmF0aW9uIG9mIHRoZXNlIGNoYW5nZXMgdGhhdCB3aWxsIHNob3cgdGhlIGltcGFjdCBvZiB0aGUgYWRqdXN0bWVudCBmb3Igb3RoZXIgcHJlZGljdG9ycy4NCg0KQWRkaW5nIHZhcmlhYmxlcyBjYW4gbWFrZSBhIHZhcmlhYmxlIGVpdGhlciBtb3JlIGltcG9ydGFudCBvciBsZXNzIGltcG9ydGFudC4gVGhlICp0KiB0ZXN0IGFuZCAqcCotdmFsdWUgYXJlIG9ubHkgZ29pbmcgdG8gcmVtYWluIHVuY2hhbmdlZCBpbiBhbiBleHRyZW1lbHkgc3BlY2lmaWMgc2NlbmFyaW8gd2hpY2ggaXMgYWxtb3N0IGltcG9zc2libGUgZm9yIG9ic2VydmF0aW9uYWwgc3R1ZHkgZGF0YS4NCg0KDQoNCg0KDQoNCiMjIE9wdGlvbmFsIFRhc2s6IEhvc3BpdGFsIE1haW50ZW5hbmNlIERhdGENCg0KDQpEYXRhIGFyZSBmcm9tIDEyIG5hdmFsIGhvc3BpdGFscyBpbiB0aGUgVVNBLg0KUmVzcG9uc2UgdmFyaWFibGUsICBgTWFuSG91cnNgICwgaXMgbW9udGhseSBtYW4taG91cnMgYXNzb2NpYXRlZCB3aXRoIG1haW50YWluaW5nIHRoZSBhbmFlc3RoZXNpb2xvZ3kgc2VydmljZS4NCkV4cGxhbmF0b3J5IHZhcmlhYmxlcyBhcmUNCg0KVmFyaWFibGUgfCBEZXNjcmlwdGlvbg0KLS0tIHwgLS0tDQpgQ2FzZXNgIHwgVGhlIG51bWJlciBvZiBzdXJnaWNhbCBjYXNlcw0KYEVsaWdpYmxlYCB8IHRoZSBlbGlnaWJsZSBwb3B1bGF0aW9uIHBlciB0aG91c2FuZA0KYE9wUm9vbXNgIHwgdGhlIG51bWJlciBvZiBvcGVyYXRpbmcgcm9vbXMNCg0KDQohW2RvY3RvcnMgYXQgcGxheV0oLi4vZ3JhcGhpY3MvaG9zcGl0YWwuanBnKSBbXSgpDQoNCg0KDQoNClNvdXJjZTogKkEgSGFuZGJvb2sgb2YgU21hbGwgRGF0YSBTZXRzKiBieSBIYW5kLCBEYWx5LA0KTHVubiwgTWNDb253YXkgYW5kIE9zdHJvd3NraS4NCg0KIyMjICBSIG91dHB1dA0KDQpgciB4ZnVuOjplbWJlZF9maWxlKCIuLi8uLi9kYXRhL2hvc3BpdGFsLmNzdiIpYCANCg0KYGBge3IgZ2V0SG9zcGl0YWxEYXRhLCBlY2hvPS0xLCBldmFsPS0yfQ0KSG9zcGl0YWwgPC0gcmVhZC5jc3YoZmlsZT0iLi4vLi4vZGF0YS9ob3NwaXRhbC5jc3YiLCBoZWFkZXI9VFJVRSkNCkhvc3BpdGFsICA8LSByZWFkLmNzdihmaWxlPSJodHRwczovL3ItcmVzb3VyY2VzLm1hc3NleS5hYy5uei8xNjEyMjEvZGF0YS9ob3NwaXRhbC5jc3YiLCBoZWFkZXI9VFJVRSkNCkhvc3BpdGFsLmxtIDwtIGxtKE1hbkhvdXJzIH4gLiwgZGF0YT1Ib3NwaXRhbCkNCnN1bW1hcnkoSG9zcGl0YWwubG0pDQpgYGANCg0KIyMjIFF1ZXN0aW9ucw0KDQoxLiAgSXMgYE1hbkhvdXJzYCByZWxhdGVkIHRvIGF0IGxlYXN0IG9uZSBvZiB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzPw0KDQoyLiAgRG9lcyBgQ2FzZXNgIHByb3ZpZGUgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBhYm91dCBgTWFuSG91cnNgIHdoZW4NCiAgICB0aGUgb3RoZXIgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGFyZSB0YWtlbiBpbnRvIGFjY291bnQ/DQoNCjMuICBEb2VzIGBFbGlnaWJsZWAgcHJvdmlkZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IGBNYW5Ib3Vyc2Agd2hlbg0KICAgIHRoZSBvdGhlciBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYXJlIHRha2VuIGludG8gYWNjb3VudD8NCg0KNC4gIElzIGBNYW5Ib3Vyc2AgcmVsYXRlZCB0byBgRWxpZ2libGVgPw0KDQpUbyB1bmRlcnN0YW5kIG1vcmUgYWJvdXQgdGhlc2UgZGF0YSwgbG9vayBhdCBzY2F0dGVyIHBsb3RzIG9mIHRoZSByZXNwb25zZSBhZ2FpbnN0IGVhY2ggb2YgdGhlDQpleHBsYW5hdG9yeSB2YXJpYWJsZXMuDQoNCiMjIFN1bW1hcnkgZm9yIFRlc3RzIGZvciBhIFNpbmdsZSBQcmVkaWN0b3INCg0KKlQqLXRlc3RzIGNhbiBiZSB1c2VkIHRvIHRlc3Qgc2luZ2xlIHBhcmFtZXRlcnMsIGFuZCBoZW5jZSBhc3Nlc3MgdGhlDQogICAgaW1wb3J0YW5jZSBvZiBzaW5nbGUgdmFyaWFibGVzIGluIGEgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24NCiAgICBtb2RlbC4NCg0KVGhlIGludGVycHJldGF0aW9uIG9mIHRoZXNlIHRlc3RzIGRlcGVuZHMgb24gd2hhdCBvdGhlciB2YXJpYWJsZXMNCiAgICBhcmUgaW5jbHVkZWQgaW4gdGhlIG1vZGVsLg0KDQpUbyB0ZXN0IHRoZSBpbXBvcnRhbmNlIG9mIGdyb3VwcyBvZiBtdWx0aXBsZSBjb3ZhcmlhdGVzIHJlcXVpcmVzICpGKiB0ZXN0cywgdXNpbmcgdGhlIHR5cGUgb2YgdGVjaG5vbG9neSB0aGF0IHdhcyBpbnRyb2R1Y2VkIGluIHRoZSBwcmV2aW91cyBsZWN0dXJlLg0K