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:

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()
term estimate std.error statistic p.value
(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()
term estimate std.error statistic p.value
(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\)

  1. 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.

  2. 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.

  1. 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()
term estimate std.error statistic p.value
(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()
term estimate std.error statistic p.value
(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
unlabelled

Partial Regression Plot for MnJlyTemp against Sun, adjusting for Lat and Height.

coef(lm(e ~ f))
  (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.

cor.test(e, f)

    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

Variable Description
Cases The number of surgical cases
Eligible the eligible population per thousand
OpRooms the number of operating rooms

doctors at play

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

  1. Is ManHours related to at least one of the explanatory variables?

  2. Does Cases provide additional information about ManHours when the other explanatory variables are taken into account?

  3. Does Eligible provide additional information about ManHours when the other explanatory variables are taken into account?

  4. 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