I. Multiple Predictor Linear Models

In the previous module we discussed bivariate regression models where one predictor or \(x\)-variable is used to create a model for one \(y\)-variable or dependent variable. If we use \(k\) predictors, say, \(x_1, x_2, \cdots, x_k\), then the parameters of our linear model will be \[y = \alpha + \beta_1x_1 + \beta_2x_2 + \cdots+ \beta_kx_k \] which will be estimated by the statistics calculated from our sample \[\hat y = a + b_1x_1 + b_2x_2 + \cdots+ b_kx_k\] In some stats apps, the coefficient \(a\) is referred to as \(b_0\). The analysis will be much the same as in the bivariate case, but multivariate linearity takes more than a scatter plot to decipher.

Initializing RStudio

The data set we will use primarily is Data3350 which was produced in 2015 during an undergraduate research project about personality and humor. The VarsData3350 PDF file has descriptions of each variable in the Data3350 file. Both are available for download in D2L. Be sure to put the Data3350 in your R folder in Documents, and make sure your working directory is set the same way (Session menu). The code block below uses the library function to ensure that the Mosaic package is loaded and will import the data frame used in this module: Data3350.

library(mosaic)
library(readxl)
Data3350 = read_excel("Data3350.xlsx")

II. Assumptions for Mutiple Regression

The assumptions for linear models are very much the same as before.

  1. Linearity. A linear relationship between the predictors and dependent variable exists.
  2. Normality. The errors or residuals are normally distributed.
  3. Homoscedasticity. The variance in the residuals will be the same regardless of position of predictors.
  4. Independence. The observations are independent of one another.

For the multivariate case, a scatter plot is insufficient. Instead, we will use a “fitted values” plot to assess linearity of the entire model including all predictors. We will still use the qq-plot to assess normality.

III. Mutiple Regression Modeling

We completed the Anxiety vs. Optimism example in the previous unit. Let’s rework it briefly and then create a multi-predictor model.

mod = lm(Anx ~ Opt, data = Data3350)
summary(mod)

Call:
lm(formula = Anx ~ Opt, data = Data3350)

Residuals:
     Min       1Q   Median       3Q      Max 
-16.8569  -5.5833  -0.3629   5.5158  20.6461 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  59.5964     2.9234  20.386  < 2e-16 ***
Opt          -1.1243     0.1452  -7.741 1.68e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.915 on 142 degrees of freedom
  (21 observations deleted due to missingness)
Multiple R-squared:  0.2968,    Adjusted R-squared:  0.2918 
F-statistic: 59.93 on 1 and 142 DF,  p-value: 1.68e-12

1. Verifying Assumptions

We will use Mosaic’s qqmath function to create the qq-plots, and the native R plot function to get the fitted values plots.

qqmath(~resid(mod))

This is imperfect because we cannot see the line we’re supposed to be comparing the plot against. We use the type parameter to specify that we want both points (“p”) and the line (“r”). Type “l” gives a connected-line scatter plot, which we don’t want. Here’s the correct code block.

qqmath(~resid(mod), type = c("p","r"))

Now we can see that entirity of the plot looks great except for couple of outliers on the far left. This should not worry us at all. The qq-plot gives good evidence the normality assumption is valid.

R’s standard plot function generates 4 plots, but we only need the first one which explains the “which” parameter below.

plot(mod , which = 1)

1.a) Fitted Values Plots and Linearity

For a fitted values plot, we are comparing the fitted values (using the model) to the residuals. If the linearity assumption is satisfied, a fitted values plot will have a roughly horizontal line of fit (e.g. randomly scattered around \(y=0\)). In the plot above, note the red line is quite close to the dotted line \(y = 0\). We have strong justification for the linearity assumption.

1.b) QQ-Plots and Normality

The qq-plot follows the 45-degree line quite closely, so the normality assumption appears to be satisfied as well. We begin to worry when the qq-plot deviates sharply from the 45-degree either showing a curve or S-shape or, sometimes, just a couple of outliers towards the endpoints that lie far away from the 45-degree line.

summary(mod)

Call:
lm(formula = Anx ~ Opt, data = Data3350)

Residuals:
     Min       1Q   Median       3Q      Max 
-16.8569  -5.5833  -0.3629   5.5158  20.6461 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  59.5964     2.9234  20.386  < 2e-16 ***
Opt          -1.1243     0.1452  -7.741 1.68e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.915 on 142 degrees of freedom
  (21 observations deleted due to missingness)
Multiple R-squared:  0.2968,    Adjusted R-squared:  0.2918 
F-statistic: 59.93 on 1 and 142 DF,  p-value: 1.68e-12

In the second row from the bottom of the output, consider “Multiple R-squared: 0.4433.” We only have one predictor in our model, so the correlation coefficient \(r\) is the square root of the R-squared value: \[r = \sqrt{0.4433}\approx 0.6658\]

2. Multiple Regression

We will extend the model to include a second and then a third predictor. The analysis for multiple regression is not that much more difficult except for swapping the scatter plot (bivariate) for the fitted values plot (multivariate).

We will use the Optimism vs. Anxiety model from above but add two more predictor variables: Neuroticism (Neuro) and Self-Esteem (SE), variables which are likely to have bivariate correlations with Anxiety. The statistics formula for this model is: \[\text{Anx}\sim \text{Opt}+\text{Neuro}+\text{SE}\] In statistical formulas, an asterisk (*) indicates a grouping or category variable while a plus sign (+) indicates a numeric variable.

3. Adding a 2nd Predictor: Neuroticism

Here’s the model when we add only one additional variable: Neuro.

mod2 = lm(Anx ~ Opt + Neuro, data = Data3350)
summary(mod2)

Call:
lm(formula = Anx ~ Opt + Neuro, data = Data3350)

Residuals:
     Min       1Q   Median       3Q      Max 
-16.2644  -4.9861  -0.1781   4.6335  15.8281 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 28.76274    4.67521   6.152 7.56e-09 ***
Opt         -0.42275    0.15506  -2.726  0.00722 ** 
Neuro        0.40004    0.04932   8.110 2.29e-13 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 6.519 on 140 degrees of freedom
  (22 observations deleted due to missingness)
Multiple R-squared:  0.5292,    Adjusted R-squared:  0.5225 
F-statistic:  78.7 on 2 and 140 DF,  p-value: < 2.2e-16

Checking for normality works like before, but RStudio calculates the residuals based upon the 2-predictor model. The qq-plot, despite including multiple predictors, is analyzed exactly as before. Here, our model residuals do not vary much from a linear pattern, so the normality assumption is justified. Note that the R native plot function can generate the qq-plot as well, if we ask it for it’s first two graphics. The result using plot is identical to the qqmath plot used earlier, which you can check for yourself. Here’s the quick way to get both:

plot(mod2, which = c(1,2))

3.a) Linearity Assumption

For the Anxiety model, the linearity assumption seems problematic, especially for values in the lowest quartile of the distribution. Should we stop analyzing? Recall the violations of the linearity assumption are a big problem. Regression statistics are only robust with respect the normality assumption. If we do proceed, it must be with an abundance of caution.

3.b) Regression Statistics and Analysis

The new model has a “Multiple R-squared: 0.5292” which has produced a huge uptick in variance accounted for. Recall that before, our model \(R^2\) indicated we were accounting for about 44% of the variance in Anxiety. Now, we’re accounting for almost 53% of the variance, an increase of about 9%. While the linearity assumption seems wobbly, the model is working better in terms of prediction. We can let the example develop for instructional purposes to see what happens noting that we do have legitimate concerns about linearity.

4. Adding a 3rd Predictor: Self-Esteem

Here’s the model when we add both Neuro and SE.

mod3 = lm(Anx ~ Opt + Neuro + SE, data = Data3350)
summary(mod3)

Call:
lm(formula = Anx ~ Opt + Neuro + SE, data = Data3350)

Residuals:
     Min       1Q   Median       3Q      Max 
-16.4391  -4.9244   0.2459   4.6683  15.6539 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 33.72105    5.80871   5.805 4.17e-08 ***
Opt         -0.36660    0.15941  -2.300   0.0229 *  
Neuro        0.36639    0.05449   6.723 4.24e-10 ***
SE          -0.08915    0.06240  -1.429   0.1553    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 6.495 on 139 degrees of freedom
  (22 observations deleted due to missingness)
Multiple R-squared:  0.5361,    Adjusted R-squared:  0.526 
F-statistic: 53.53 on 3 and 139 DF,  p-value: < 2.2e-16
plot(mod3, which = c(1,2))

The normality assumption seems fine as the qq-plot shows values that do not deviate much from the 45-degree line. The problem seems to be with linearity. Given that the SE variable did not contribute meaningfully to the model, one should not be surprised that the fitted values plot looks remarkably similar to the 2-variable model and still problematic.

III. Exploring Linear Models: Thrill-Seeking

While we don’t have time in this course to discuss exploratory modeling, we can give a sense of how hierarchical regression modeling works. Suppose we believe the following five variables might predict Thrill-seeking due to the fact each one has a significant bivariate correlation with the Thrill.

  1. Adult Playfulness (Play), \(r = .23\)
  2. Anxiety (Anx), $r = - 0.28 $
  3. Coping Humor (CHS), \(r = 0.22\)
  4. Narcissism (Narc), \(r = .34\)
  5. Optimism (Opt), \(r = 0.30\)

1. Five Predictor Model

Let’s create a linear model with all five variables: \[\text{Thrill} \sim \text{Anx} + \text{Narc} + \text{Play} + \text{CHS} + \text{Opt}\]

mod4 = lm(Thrill ~ Anx + Narc + Play + CHS + Opt, data = Data3350)
summary(mod4)

Call:
lm(formula = Thrill ~ Anx + Narc + Play + CHS + Opt, data = Data3350)

Residuals:
    Min      1Q  Median      3Q     Max 
-13.102  -3.569   0.480   3.569  12.091 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  9.78315    5.37263   1.821 0.071010 .  
Anx         -0.08378    0.05730  -1.462 0.146239    
Narc         0.61388    0.16302   3.766 0.000255 ***
Play         0.04295    0.02512   1.710 0.089782 .  
CHS          0.06594    0.10607   0.622 0.535311    
Opt          0.13931    0.11565   1.205 0.230650    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.908 on 125 degrees of freedom
  (34 observations deleted due to missingness)
Multiple R-squared:  0.2296,    Adjusted R-squared:  0.1988 
F-statistic: 7.451 on 5 and 125 DF,  p-value: 3.787e-06

Note that our multiple R-squared is 0.2296, so that our model is accounting for 23% of the variance in Thrill. This may not seem like much, but in the social sciences this indicates some significant relationships exist here. Before we check the diagnostics, notice the linear regression \(t\)-tests for the slope coefficients the \(p\)-values for which are listed in the last column of the “Coefficients” table. Only Narc is strongly significant. Notice the \(p-\)values for CHS and Opt show that they are the worst predictors in the model despite Opt having the 2nd highest bivariate correlation with Thrill.

The predictors are all correlated to some degree. Some of them are accounting for the same pieces of variance in the model. They’re fighting each other to predict roughly the same aspects of Thrill-seeking. Checking the diagnostics plots below, we see an issue on the left of the fitted values plot, but the qq-plot seems reasonable. Let’s remove the ill-fitting predictor CHS from the model.

plot(mod4, which = c(1,2))

2. Four Predictor Model

mod5 = lm(Thrill ~ Anx + Narc + Play + Opt, data = Data3350)
summary(mod5)

Call:
lm(formula = Thrill ~ Anx + Narc + Play + Opt, data = Data3350)

Residuals:
     Min       1Q   Median       3Q      Max 
-13.4020  -3.5840   0.3962   3.5528  12.0888 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 11.40509    4.68510   2.434 0.016321 *  
Anx         -0.09623    0.05355  -1.797 0.074748 .  
Narc         0.63071    0.16037   3.933 0.000138 ***
Play         0.04737    0.02403   1.971 0.050949 .  
Opt          0.13005    0.11441   1.137 0.257830    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.896 on 126 degrees of freedom
  (34 observations deleted due to missingness)
Multiple R-squared:  0.2272,    Adjusted R-squared:  0.2027 
F-statistic: 9.262 on 4 and 126 DF,  p-value: 1.358e-06

Notice that the R-squared value is 0.227, only slightly less than before, and while Narc is still the only strongly significant predictor, both Anx and Play have grown much more significant without the CHS predictor in the model. Apparently, those three predictors were all fighting over the same pieces of variance. Also, Opt is just not working out. After checking the diagonostics, we’ll remove it.

plot(mod5, which = c(1,2))

The diagnostics have changed very little. We still have the lack of linearity on the left side of the fitted values plot and a reasonable qq-plot. Let’s see what removing Opt does.

3. Three Predictor Model

mod6 = lm(Thrill ~ Anx + Narc + Play, data = Data3350)
summary(mod6)

Call:
lm(formula = Thrill ~ Anx + Narc + Play, data = Data3350)

Residuals:
     Min       1Q   Median       3Q      Max 
-13.4698  -3.7267   0.2912   3.6745  11.4900 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 14.30159    3.93603   3.634 0.000404 ***
Anx         -0.12766    0.04592  -2.780 0.006260 ** 
Narc         0.65882    0.15863   4.153 5.97e-05 ***
Play         0.05250    0.02363   2.221 0.028092 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.902 on 127 degrees of freedom
  (34 observations deleted due to missingness)
Multiple R-squared:  0.2193,    Adjusted R-squared:  0.2008 
F-statistic: 11.89 on 3 and 127 DF,  p-value: 6.479e-07

Notice that the R-squared value is 0.219, still just a tiny bit less than before. Interestingly, both Anx and Play are now significant predictors. Anx is strongly significant. Given the \(p\)-values from the table, we would say that Narc is the “most influential predictor” of Thrill. While Narc is the primary predictor, Anx is a secondary predictor and still strongly significant. Play is significant but of less importance to the model. Hopefully you have gotten a small taste of exploratory modeling. On assignments for this class, you will be asked only investigate and evaluate linear models, not design them yourself. In any case, this set of examples helps to show what “bad” predictors look like and how they affect the model.

plot(mod6, which = c(1,2))

Sadly, getting rid of two ineffective predictors hasn’t improved our model diagnostics. This makes sense, because most of the variance in our model was due to the three predictors we still have left. We do have a linearity issue which does call into question the validity of the model. Is it severe? No. 

What should we do? In a more advanced statistics class, we might try a transformation. If we can find the non-linearity, we might be able to take the square root or natural log of a predictor and remove it. For this class, since the lack of linearity was not too severe, we can report our analysis and discuss the potential non-linearity.

IV. Exercises

  1. Add the non-numeric variable biological Sex to the Thrill-seeking model above to test the stereotype of males being more adventurous than females. The stats notation for the model is \[\text{Thrill} \sim \text{Anx} + \text{Narc} + \text{Play} + \text{Sex}\] Is the variable Sex a significant predictor? Does it add anything to the model? Did the diagnostic plots change in any significant way?

\[\text{Thrill} \sim \text{Anx} + \text{Narc} + \text{Play} + \text{Sex}\]

  1. Using the HSAG variable from the Data3350 data frame, build a linear model for Aggressive Humor using the predictors Narcissism and Self-Defeating Humor Style: \[\text{HSAG} \sim \text{Narc} + \text{HSSD}\] Evaluate and analyze your model including all diagnostic plots.

  2. Add the Eating Attitudes variable Eat as the third predictor in your model for HSAG:\[\text{HSAG} \sim \text{Narc} + \text{HSSD} + \text{Eat}\] Evaluate and analyze your model including all diagnostic plots, and compare your three-predictor model with your results from the two-predictor model. Is the correlation between Eat and HSAG positive or negative? How can you tell from the model summary statistics output? If higher scores on the Eat variable indicate higher levels of being calorie conscious, knowing the fat content of food items and thinking about burning calories when working out, does this relationship between Eat and HSAG make sense?

  3. Using the OCD variable from the Data3350 data frame, build a two-predictor linear model using Perf and TypeA as predictors: \[\text{OCD} \sim \text{Perf} + \text{TypeA}\] Evaluate and analyze your model including all diagnostic plots.

  4. Add Anx as the third predictor in your model for OCD: \[\text{OCD} \sim \text{Perf} + \text{TypeA}+ \text{Anx}\] Evaluate and analyze your model including all diagnostic plots, and compare your three-predictor model with your results from the two-predictor model.

LS0tDQp0aXRsZTogIkxpbmVhciBNb2RlbHMgYW5kIE11bHRpcGxlIFJlZ3Jlc3Npb24iDQpzdWJ0aXRsZTogVU5HIE1BVEggMzM1MCAob25saW5lKQ0KYXV0aG9yOiBSb2JiIFNpbm4NCmRhdGU6IEp1bHkgMjAyMA0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5JLiBNdWx0aXBsZSBQcmVkaWN0b3IgTGluZWFyIE1vZGVsczwvc3Bhbj4NCg0KSW4gdGhlIHByZXZpb3VzIG1vZHVsZSB3ZSBkaXNjdXNzZWQgYml2YXJpYXRlIHJlZ3Jlc3Npb24gbW9kZWxzIHdoZXJlIG9uZSBwcmVkaWN0b3Igb3IgJHgkLXZhcmlhYmxlIGlzIHVzZWQgdG8gY3JlYXRlIGEgbW9kZWwgZm9yIG9uZSAkeSQtdmFyaWFibGUgb3IgZGVwZW5kZW50IHZhcmlhYmxlLiBJZiB3ZSB1c2UgJGskIHByZWRpY3RvcnMsIHNheSwgJHhfMSwgeF8yLCBcY2RvdHMsIHhfayQsIHRoZW4gdGhlIHBhcmFtZXRlcnMgb2Ygb3VyIGxpbmVhciBtb2RlbCB3aWxsIGJlDQokJHkgPSBcYWxwaGEgKyBcYmV0YV8xeF8xICsgXGJldGFfMnhfMiArIFxjZG90cysgXGJldGFfa3hfayAkJA0Kd2hpY2ggd2lsbCBiZSBlc3RpbWF0ZWQgYnkgdGhlIHN0YXRpc3RpY3MgY2FsY3VsYXRlZCBmcm9tIG91ciBzYW1wbGUNCiQkXGhhdCB5ID0gYSArIGJfMXhfMSArIGJfMnhfMiArIFxjZG90cysgYl9reF9rJCQNCkluIHNvbWUgc3RhdHMgYXBwcywgdGhlIGNvZWZmaWNpZW50ICRhJCBpcyByZWZlcnJlZCB0byBhcyAkYl8wJC4gVGhlIGFuYWx5c2lzIHdpbGwgYmUgbXVjaCB0aGUgc2FtZSBhcyBpbiB0aGUgYml2YXJpYXRlIGNhc2UsIGJ1dCBtdWx0aXZhcmlhdGUgbGluZWFyaXR5IHRha2VzIG1vcmUgdGhhbiBhIHNjYXR0ZXIgcGxvdCB0byBkZWNpcGhlci4NCg0KPGRpdiBzdHlsZT0iZmxvYXQ6cmlnaHQ7IG1hcmdpbjogOHB4OyBib3JkZXI6MnB4IGJsYWNrIHNvbGlkOyBwYWRkaW5nOiAwcHggMTBweCA1cHgiPg0KIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcmVkOyI+SW5pdGlhbGl6aW5nIFJTdHVkaW88L3NwYW4+DQpUaGUgZGF0YSBzZXQgd2Ugd2lsbCB1c2UgcHJpbWFyaWx5IGlzICoqRGF0YTMzNTAqKiB3aGljaCB3YXMgcHJvZHVjZWQgaW4gMjAxNSBkdXJpbmcgYW4gdW5kZXJncmFkdWF0ZSByZXNlYXJjaCBwcm9qZWN0IGFib3V0IHBlcnNvbmFsaXR5IGFuZCBodW1vci4gVGhlICoqVmFyc0RhdGEzMzUwKiogUERGIGZpbGUgaGFzIGRlc2NyaXB0aW9ucyBvZiBlYWNoIHZhcmlhYmxlIGluIHRoZSBEYXRhMzM1MCBmaWxlLiBCb3RoIGFyZSBhdmFpbGFibGUgZm9yIGRvd25sb2FkIGluIEQyTC4gQmUgc3VyZSB0byBwdXQgdGhlIERhdGEzMzUwIGluIHlvdXIgUiBmb2xkZXIgaW4gRG9jdW1lbnRzLCBhbmQgbWFrZSBzdXJlIHlvdXIgd29ya2luZyBkaXJlY3RvcnkgaXMgc2V0IHRoZSBzYW1lIHdheSAoU2Vzc2lvbiBtZW51KS4gVGhlIGNvZGUgYmxvY2sgYmVsb3cgdXNlcyB0aGUgKipsaWJyYXJ5KiogZnVuY3Rpb24gdG8gZW5zdXJlIHRoYXQgdGhlICoqTW9zYWljKiogcGFja2FnZSBpcyBsb2FkZWQgYW5kIHdpbGwgaW1wb3J0IHRoZSBkYXRhIGZyYW1lIHVzZWQgaW4gdGhpcyBtb2R1bGU6ICoqRGF0YTMzNTAqKi4NCmBgYHtyfQ0KbGlicmFyeShtb3NhaWMpDQpsaWJyYXJ5KHJlYWR4bCkNCkRhdGEzMzUwID0gcmVhZF9leGNlbCgiRGF0YTMzNTAueGxzeCIpDQpgYGANCjwvZGl2Pg0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPklJLiBBc3N1bXB0aW9ucyBmb3IgTXV0aXBsZSBSZWdyZXNzaW9uPC9zcGFuPg0KDQpUaGUgYXNzdW1wdGlvbnMgZm9yIGxpbmVhciBtb2RlbHMgYXJlIHZlcnkgbXVjaCB0aGUgc2FtZSBhcyBiZWZvcmUuDQoNCjEuICoqTGluZWFyaXR5LioqIEEgKmxpbmVhciogcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHByZWRpY3RvcnMgYW5kIGRlcGVuZGVudCB2YXJpYWJsZSBleGlzdHMuDQoyLiAqKk5vcm1hbGl0eS4qKiBUaGUgZXJyb3JzIG9yICpyZXNpZHVhbHMqIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZC4NCjMuICoqSG9tb3NjZWRhc3RpY2l0eS4qKiBUaGUgdmFyaWFuY2UgaW4gdGhlIHJlc2lkdWFscyB3aWxsIGJlIHRoZSBzYW1lIHJlZ2FyZGxlc3Mgb2YgcG9zaXRpb24gb2YgcHJlZGljdG9ycy4NCjQuICoqSW5kZXBlbmRlbmNlLioqIFRoZSBvYnNlcnZhdGlvbnMgYXJlIGluZGVwZW5kZW50IG9mIG9uZSBhbm90aGVyLg0KDQpGb3IgdGhlIG11bHRpdmFyaWF0ZSBjYXNlLCBhIHNjYXR0ZXIgcGxvdCBpcyBpbnN1ZmZpY2llbnQuIEluc3RlYWQsIHdlIHdpbGwgdXNlIGEgImZpdHRlZCB2YWx1ZXMiIHBsb3QgdG8gYXNzZXNzIGxpbmVhcml0eSBvZiB0aGUgZW50aXJlIG1vZGVsIGluY2x1ZGluZyBhbGwgcHJlZGljdG9ycy4gV2Ugd2lsbCBzdGlsbCB1c2UgdGhlICoqcXEtcGxvdCoqIHRvIGFzc2VzcyBub3JtYWxpdHkuDQoNCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+SUlJLiBNdXRpcGxlIFJlZ3Jlc3Npb24gTW9kZWxpbmc8L3NwYW4+DQoNCldlIGNvbXBsZXRlZCB0aGUgQW54aWV0eSB2cy4gT3B0aW1pc20gZXhhbXBsZSBpbiB0aGUgcHJldmlvdXMgdW5pdC4gTGV0J3MgcmV3b3JrIGl0IGJyaWVmbHkgYW5kIHRoZW4gY3JlYXRlIGEgbXVsdGktcHJlZGljdG9yIG1vZGVsLg0KDQpgYGB7cn0NCm1vZCA9IGxtKEFueCB+IE9wdCwgZGF0YSA9IERhdGEzMzUwKQ0Kc3VtbWFyeShtb2QpDQpgYGANCg0KIyMgMS4gVmVyaWZ5aW5nIEFzc3VtcHRpb25zDQoNCldlIHdpbGwgdXNlIE1vc2FpYydzICoqcXFtYXRoKiogZnVuY3Rpb24gdG8gY3JlYXRlIHRoZSBxcS1wbG90cywgYW5kIHRoZSBuYXRpdmUgUiAqKnBsb3QqKiBmdW5jdGlvbiB0byBnZXQgdGhlIGZpdHRlZCB2YWx1ZXMgcGxvdHMuDQoNCmBgYHtyfQ0KcXFtYXRoKH5yZXNpZChtb2QpKQ0KYGBgDQpUaGlzIGlzIGltcGVyZmVjdCBiZWNhdXNlIHdlIGNhbm5vdCBzZWUgdGhlIGxpbmUgd2UncmUgc3VwcG9zZWQgdG8gYmUgY29tcGFyaW5nIHRoZSBwbG90IGFnYWluc3QuIFdlIHVzZSB0aGUgKip0eXBlKiogcGFyYW1ldGVyIHRvIHNwZWNpZnkgdGhhdCB3ZSB3YW50IGJvdGggcG9pbnRzICgicCIpIGFuZCB0aGUgbGluZSAoInIiKS4gVHlwZSAibCIgZ2l2ZXMgYSBjb25uZWN0ZWQtbGluZSBzY2F0dGVyIHBsb3QsIHdoaWNoIHdlIGRvbid0IHdhbnQuIEhlcmUncyB0aGUgY29ycmVjdCBjb2RlIGJsb2NrLg0KDQpgYGB7cn0NCnFxbWF0aCh+cmVzaWQobW9kKSwgdHlwZSA9IGMoInAiLCJyIikpDQpgYGANCk5vdyB3ZSBjYW4gc2VlIHRoYXQgZW50aXJpdHkgb2YgdGhlIHBsb3QgbG9va3MgZ3JlYXQgZXhjZXB0IGZvciBjb3VwbGUgb2Ygb3V0bGllcnMgb24gdGhlIGZhciBsZWZ0LiBUaGlzIHNob3VsZCBub3Qgd29ycnkgdXMgYXQgYWxsLiBUaGUgcXEtcGxvdCBnaXZlcyBnb29kIGV2aWRlbmNlIHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbiBpcyB2YWxpZC4NCg0KUidzIHN0YW5kYXJkICoqcGxvdCoqIGZ1bmN0aW9uIGdlbmVyYXRlcyA0IHBsb3RzLCBidXQgd2Ugb25seSBuZWVkIHRoZSBmaXJzdCBvbmUgd2hpY2ggZXhwbGFpbnMgdGhlICJ3aGljaCIgcGFyYW1ldGVyIGJlbG93Lg0KDQoNCmBgYHtyfQ0KcGxvdChtb2QgLCB3aGljaCA9IDEpDQpgYGANCg0KDQojIyAxLmEpIEZpdHRlZCBWYWx1ZXMgUGxvdHMgYW5kIExpbmVhcml0eQ0KDQpGb3IgYSBmaXR0ZWQgdmFsdWVzIHBsb3QsIHdlIGFyZSBjb21wYXJpbmcgdGhlIGZpdHRlZCB2YWx1ZXMgKHVzaW5nIHRoZSBtb2RlbCkgdG8gdGhlIHJlc2lkdWFscy4gSWYgdGhlIGxpbmVhcml0eSBhc3N1bXB0aW9uIGlzIHNhdGlzZmllZCwgYSBmaXR0ZWQgdmFsdWVzIHBsb3Qgd2lsbCBoYXZlIGEgcm91Z2hseSBob3Jpem9udGFsIGxpbmUgb2YgZml0IChlLmcuIHJhbmRvbWx5IHNjYXR0ZXJlZCBhcm91bmQgJHk9MCQpLiBJbiB0aGUgcGxvdCBhYm92ZSwgbm90ZSB0aGUgcmVkIGxpbmUgaXMgcXVpdGUgY2xvc2UgdG8gdGhlIGRvdHRlZCBsaW5lICR5ID0gMCQuIFdlIGhhdmUgc3Ryb25nIGp1c3RpZmljYXRpb24gZm9yIHRoZSBsaW5lYXJpdHkgYXNzdW1wdGlvbi4NCg0KIyMgMS5iKSBRUS1QbG90cyBhbmQgTm9ybWFsaXR5DQoNClRoZSBxcS1wbG90IGZvbGxvd3MgdGhlIDQ1LWRlZ3JlZSBsaW5lIHF1aXRlIGNsb3NlbHksIHNvIHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbiBhcHBlYXJzIHRvIGJlIHNhdGlzZmllZCBhcyB3ZWxsLiBXZSBiZWdpbiB0byB3b3JyeSB3aGVuIHRoZSBxcS1wbG90IGRldmlhdGVzIHNoYXJwbHkgZnJvbSB0aGUgNDUtZGVncmVlIGVpdGhlciBzaG93aW5nIGEgY3VydmUgb3IgUy1zaGFwZSBvciwgc29tZXRpbWVzLCBqdXN0IGEgY291cGxlIG9mIG91dGxpZXJzIHRvd2FyZHMgdGhlIGVuZHBvaW50cyB0aGF0IGxpZSBmYXIgYXdheSBmcm9tIHRoZSA0NS1kZWdyZWUgbGluZS4NCg0KDQpgYGB7cn0NCnN1bW1hcnkobW9kKQ0KYGBgDQoNCkluIHRoZSBzZWNvbmQgcm93IGZyb20gdGhlIGJvdHRvbSBvZiB0aGUgb3V0cHV0LCBjb25zaWRlciAiTXVsdGlwbGUgUi1zcXVhcmVkOiAgMC40NDMzLiIgV2Ugb25seSBoYXZlIG9uZSBwcmVkaWN0b3IgaW4gb3VyIG1vZGVsLCBzbyB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgJHIkIGlzIHRoZSBzcXVhcmUgcm9vdCBvZiB0aGUgUi1zcXVhcmVkIHZhbHVlOg0KJCRyID0gXHNxcnR7MC40NDMzfVxhcHByb3ggMC42NjU4JCQNCg0KIyMgMi4gTXVsdGlwbGUgUmVncmVzc2lvbg0KDQpXZSB3aWxsIGV4dGVuZCB0aGUgbW9kZWwgdG8gaW5jbHVkZSBhIHNlY29uZCBhbmQgdGhlbiBhIHRoaXJkIHByZWRpY3Rvci4gVGhlIGFuYWx5c2lzIGZvciBtdWx0aXBsZSByZWdyZXNzaW9uIGlzIG5vdCB0aGF0IG11Y2ggbW9yZSBkaWZmaWN1bHQgZXhjZXB0IGZvciBzd2FwcGluZyB0aGUgc2NhdHRlciBwbG90IChiaXZhcmlhdGUpIGZvciB0aGUgZml0dGVkIHZhbHVlcyBwbG90IChtdWx0aXZhcmlhdGUpLg0KDQpXZSB3aWxsIHVzZSB0aGUgT3B0aW1pc20gdnMuIEFueGlldHkgbW9kZWwgZnJvbSBhYm92ZSBidXQgYWRkIHR3byBtb3JlIHByZWRpY3RvciB2YXJpYWJsZXM6IE5ldXJvdGljaXNtIChOZXVybykgYW5kIFNlbGYtRXN0ZWVtIChTRSksIHZhcmlhYmxlcyB3aGljaCBhcmUgbGlrZWx5IHRvIGhhdmUgYml2YXJpYXRlIGNvcnJlbGF0aW9ucyB3aXRoIEFueGlldHkuIFRoZSBzdGF0aXN0aWNzIGZvcm11bGEgZm9yIHRoaXMgbW9kZWwgaXM6ICQkXHRleHR7QW54fVxzaW0gXHRleHR7T3B0fStcdGV4dHtOZXVyb30rXHRleHR7U0V9JCQNCkluIHN0YXRpc3RpY2FsIGZvcm11bGFzLCBhbiBhc3RlcmlzayAoKikgaW5kaWNhdGVzIGEgZ3JvdXBpbmcgb3IgY2F0ZWdvcnkgdmFyaWFibGUgd2hpbGUgYSBwbHVzIHNpZ24gKCspIGluZGljYXRlcyBhIG51bWVyaWMgdmFyaWFibGUuDQoNCiMjIDMuIEFkZGluZyBhIDJuZCBQcmVkaWN0b3I6IE5ldXJvdGljaXNtDQoNCkhlcmUncyB0aGUgbW9kZWwgd2hlbiB3ZSBhZGQgb25seSBvbmUgYWRkaXRpb25hbCB2YXJpYWJsZTogKipOZXVybyoqLg0KDQpgYGB7cn0NCm1vZDIgPSBsbShBbnggfiBPcHQgKyBOZXVybywgZGF0YSA9IERhdGEzMzUwKQ0Kc3VtbWFyeShtb2QyKQ0KYGBgDQoNCkNoZWNraW5nIGZvciBub3JtYWxpdHkgd29ya3MgbGlrZSBiZWZvcmUsIGJ1dCBSU3R1ZGlvIGNhbGN1bGF0ZXMgdGhlIHJlc2lkdWFscyBiYXNlZCB1cG9uIHRoZSAyLXByZWRpY3RvciBtb2RlbC4gVGhlIHFxLXBsb3QsIGRlc3BpdGUgaW5jbHVkaW5nIG11bHRpcGxlIHByZWRpY3RvcnMsIGlzIGFuYWx5emVkIGV4YWN0bHkgYXMgYmVmb3JlLiBIZXJlLCBvdXIgbW9kZWwgcmVzaWR1YWxzIGRvIG5vdCB2YXJ5IG11Y2ggZnJvbSBhIGxpbmVhciBwYXR0ZXJuLCBzbyB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gaXMganVzdGlmaWVkLiBOb3RlIHRoYXQgdGhlIFIgbmF0aXZlICoqcGxvdCoqIGZ1bmN0aW9uIGNhbiBnZW5lcmF0ZSB0aGUgcXEtcGxvdCBhcyB3ZWxsLCBpZiB3ZSBhc2sgaXQgZm9yIGl0J3MgZmlyc3QgdHdvIGdyYXBoaWNzLiBUaGUgcmVzdWx0IHVzaW5nICoqcGxvdCoqIGlzIGlkZW50aWNhbCB0byB0aGUgKipxcW1hdGgqKiBwbG90IHVzZWQgZWFybGllciwgd2hpY2ggeW91IGNhbiBjaGVjayBmb3IgeW91cnNlbGYuIEhlcmUncyB0aGUgcXVpY2sgd2F5IHRvIGdldCBib3RoOg0KDQpgYGB7cn0NCnBsb3QobW9kMiwgd2hpY2ggPSBjKDEsMikpDQpgYGANCg0KDQojIyAzLmEpIExpbmVhcml0eSBBc3N1bXB0aW9uDQoNCkZvciB0aGUgQW54aWV0eSBtb2RlbCwgdGhlIGxpbmVhcml0eSBhc3N1bXB0aW9uIHNlZW1zIHByb2JsZW1hdGljLCBlc3BlY2lhbGx5IGZvciB2YWx1ZXMgaW4gdGhlIGxvd2VzdCBxdWFydGlsZSBvZiB0aGUgZGlzdHJpYnV0aW9uLiBTaG91bGQgd2Ugc3RvcCBhbmFseXppbmc/IFJlY2FsbCB0aGUgdmlvbGF0aW9ucyBvZiB0aGUgbGluZWFyaXR5IGFzc3VtcHRpb24gYXJlIGEgYmlnIHByb2JsZW0uIFJlZ3Jlc3Npb24gc3RhdGlzdGljcyBhcmUgb25seSByb2J1c3Qgd2l0aCByZXNwZWN0IHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbi4gSWYgd2UgZG8gcHJvY2VlZCwgaXQgbXVzdCBiZSB3aXRoIGFuIGFidW5kYW5jZSBvZiBjYXV0aW9uLg0KDQojIyAzLmIpIFJlZ3Jlc3Npb24gU3RhdGlzdGljcyBhbmQgQW5hbHlzaXMNCg0KVGhlIG5ldyBtb2RlbCBoYXMgYSAiTXVsdGlwbGUgUi1zcXVhcmVkOiAgMC41MjkyIiB3aGljaCBoYXMgcHJvZHVjZWQgYSBodWdlIHVwdGljayBpbiB2YXJpYW5jZSBhY2NvdW50ZWQgZm9yLiBSZWNhbGwgdGhhdCBiZWZvcmUsIG91ciBtb2RlbCAkUl4yJCBpbmRpY2F0ZWQgd2Ugd2VyZSBhY2NvdW50aW5nIGZvciBhYm91dCA0NCUgb2YgdGhlIHZhcmlhbmNlIGluIEFueGlldHkuIE5vdywgd2UncmUgYWNjb3VudGluZyBmb3IgYWxtb3N0IDUzJSBvZiB0aGUgdmFyaWFuY2UsIGFuIGluY3JlYXNlIG9mIGFib3V0IDklLiBXaGlsZSB0aGUgbGluZWFyaXR5IGFzc3VtcHRpb24gc2VlbXMgd29iYmx5LCB0aGUgbW9kZWwgaXMgd29ya2luZyBiZXR0ZXIgaW4gdGVybXMgb2YgcHJlZGljdGlvbi4gV2UgY2FuIGxldCB0aGUgZXhhbXBsZSBkZXZlbG9wIGZvciBpbnN0cnVjdGlvbmFsIHB1cnBvc2VzIHRvIHNlZSB3aGF0IGhhcHBlbnMgbm90aW5nIHRoYXQgd2UgZG8gaGF2ZSBsZWdpdGltYXRlIGNvbmNlcm5zIGFib3V0IGxpbmVhcml0eS4NCg0KIyMgNC4gQWRkaW5nIGEgM3JkIFByZWRpY3RvcjogU2VsZi1Fc3RlZW0NCg0KSGVyZSdzIHRoZSBtb2RlbCB3aGVuIHdlIGFkZCBib3RoICpOZXVybyogYW5kICpTRSouDQoNCmBgYHtyfQ0KbW9kMyA9IGxtKEFueCB+IE9wdCArIE5ldXJvICsgU0UsIGRhdGEgPSBEYXRhMzM1MCkNCnN1bW1hcnkobW9kMykNCmBgYA0KDQoNCmBgYHtyfQ0KcGxvdChtb2QzLCB3aGljaCA9IGMoMSwyKSkNCmBgYA0KDQpUaGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gc2VlbXMgZmluZSBhcyB0aGUgcXEtcGxvdCBzaG93cyB2YWx1ZXMgdGhhdCBkbyBub3QgZGV2aWF0ZSBtdWNoIGZyb20gdGhlIDQ1LWRlZ3JlZSBsaW5lLiBUaGUgcHJvYmxlbSBzZWVtcyB0byBiZSB3aXRoIGxpbmVhcml0eS4gR2l2ZW4gdGhhdCB0aGUgU0UgdmFyaWFibGUgZGlkIG5vdCBjb250cmlidXRlIG1lYW5pbmdmdWxseSB0byB0aGUgbW9kZWwsIG9uZSBzaG91bGQgbm90IGJlIHN1cnByaXNlZCB0aGF0IHRoZSBmaXR0ZWQgdmFsdWVzIHBsb3QgbG9va3MgcmVtYXJrYWJseSBzaW1pbGFyIHRvIHRoZSAyLXZhcmlhYmxlIG1vZGVsIGFuZCBzdGlsbCBwcm9ibGVtYXRpYy4NCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5JSUkuIEV4cGxvcmluZyBMaW5lYXIgTW9kZWxzOiBUaHJpbGwtU2Vla2luZw0KDQpXaGlsZSB3ZSBkb24ndCBoYXZlIHRpbWUgaW4gdGhpcyBjb3Vyc2UgdG8gZGlzY3VzcyBleHBsb3JhdG9yeSBtb2RlbGluZywgd2UgY2FuIGdpdmUgYSBzZW5zZSBvZiBob3cgaGllcmFyY2hpY2FsIHJlZ3Jlc3Npb24gbW9kZWxpbmcgd29ya3MuIFN1cHBvc2Ugd2UgYmVsaWV2ZSB0aGUgZm9sbG93aW5nIGZpdmUgdmFyaWFibGVzIG1pZ2h0IHByZWRpY3QgVGhyaWxsLXNlZWtpbmcgZHVlIHRvIHRoZSBmYWN0IGVhY2ggb25lIGhhcyBhIHNpZ25pZmljYW50IGJpdmFyaWF0ZSBjb3JyZWxhdGlvbiB3aXRoIHRoZSAqKlRocmlsbCoqLg0KDQoxLiBBZHVsdCBQbGF5ZnVsbmVzcyAoUGxheSksICRyID0gLjIzJA0KMi4gQW54aWV0eSAoQW54KSwgJHIgPSAtIDAuMjggJA0KMy4gQ29waW5nIEh1bW9yIChDSFMpLCAkciA9IDAuMjIkDQo0LiBOYXJjaXNzaXNtIChOYXJjKSwgJHIgPSAuMzQkDQo1LiBPcHRpbWlzbSAoT3B0KSwgJHIgPSAwLjMwJA0KDQojIyAxLiBGaXZlIFByZWRpY3RvciBNb2RlbA0KDQpMZXQncyBjcmVhdGUgYSBsaW5lYXIgbW9kZWwgd2l0aCBhbGwgZml2ZSB2YXJpYWJsZXM6ICQkXHRleHR7VGhyaWxsfSBcc2ltIFx0ZXh0e0FueH0gKyBcdGV4dHtOYXJjfSArIFx0ZXh0e1BsYXl9ICsgXHRleHR7Q0hTfSArIFx0ZXh0e09wdH0kJA0KDQpgYGB7cn0NCm1vZDQgPSBsbShUaHJpbGwgfiBBbnggKyBOYXJjICsgUGxheSArIENIUyArIE9wdCwgZGF0YSA9IERhdGEzMzUwKQ0Kc3VtbWFyeShtb2Q0KQ0KYGBgDQoNCk5vdGUgdGhhdCBvdXIgbXVsdGlwbGUgUi1zcXVhcmVkIGlzIDAuMjI5Niwgc28gdGhhdCBvdXIgbW9kZWwgaXMgYWNjb3VudGluZyBmb3IgMjMlIG9mIHRoZSB2YXJpYW5jZSBpbiAqKlRocmlsbCoqLiBUaGlzIG1heSBub3Qgc2VlbSBsaWtlIG11Y2gsIGJ1dCBpbiB0aGUgc29jaWFsIHNjaWVuY2VzIHRoaXMgaW5kaWNhdGVzIHNvbWUgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwcyBleGlzdCBoZXJlLiBCZWZvcmUgd2UgY2hlY2sgdGhlIGRpYWdub3N0aWNzLCBub3RpY2UgdGhlIGxpbmVhciByZWdyZXNzaW9uICR0JC10ZXN0cyBmb3IgdGhlIHNsb3BlIGNvZWZmaWNpZW50cyB0aGUgJHAkLXZhbHVlcyBmb3Igd2hpY2ggYXJlIGxpc3RlZCBpbiB0aGUgbGFzdCBjb2x1bW4gb2YgdGhlICJDb2VmZmljaWVudHMiIHRhYmxlLiBPbmx5ICoqTmFyYyoqIGlzIHN0cm9uZ2x5IHNpZ25pZmljYW50LiBOb3RpY2UgdGhlICRwLSR2YWx1ZXMgZm9yICoqQ0hTKiogYW5kICoqT3B0Kiogc2hvdyB0aGF0IHRoZXkgYXJlIHRoZSB3b3JzdCBwcmVkaWN0b3JzIGluIHRoZSBtb2RlbCBkZXNwaXRlICoqT3B0KiogaGF2aW5nIHRoZSAybmQgaGlnaGVzdCBiaXZhcmlhdGUgY29ycmVsYXRpb24gd2l0aCAqKlRocmlsbCoqLg0KDQpUaGUgcHJlZGljdG9ycyBhcmUgYWxsIGNvcnJlbGF0ZWQgdG8gc29tZSBkZWdyZWUuIFNvbWUgb2YgdGhlbSBhcmUgYWNjb3VudGluZyBmb3IgdGhlIHNhbWUgcGllY2VzIG9mIHZhcmlhbmNlIGluIHRoZSBtb2RlbC4gVGhleSdyZSBmaWdodGluZyBlYWNoIG90aGVyIHRvIHByZWRpY3Qgcm91Z2hseSB0aGUgc2FtZSBhc3BlY3RzIG9mIFRocmlsbC1zZWVraW5nLiBDaGVja2luZyB0aGUgZGlhZ25vc3RpY3MgcGxvdHMgYmVsb3csIHdlIHNlZSBhbiBpc3N1ZSBvbiB0aGUgbGVmdCBvZiB0aGUgZml0dGVkIHZhbHVlcyBwbG90LCBidXQgdGhlIHFxLXBsb3Qgc2VlbXMgcmVhc29uYWJsZS4gTGV0J3MgcmVtb3ZlIHRoZSBpbGwtZml0dGluZyBwcmVkaWN0b3IgKipDSFMqKiBmcm9tIHRoZSBtb2RlbC4NCg0KYGBge3J9DQpwbG90KG1vZDQsIHdoaWNoID0gYygxLDIpKQ0KYGBgDQoNCiMjIDIuIEZvdXIgUHJlZGljdG9yIE1vZGVsDQoNCmBgYHtyfQ0KbW9kNSA9IGxtKFRocmlsbCB+IEFueCArIE5hcmMgKyBQbGF5ICsgT3B0LCBkYXRhID0gRGF0YTMzNTApDQpzdW1tYXJ5KG1vZDUpDQpgYGANCg0KTm90aWNlIHRoYXQgdGhlIFItc3F1YXJlZCB2YWx1ZSBpcyAwLjIyNywgb25seSBzbGlnaHRseSBsZXNzIHRoYW4gYmVmb3JlLCBhbmQgd2hpbGUgKipOYXJjKiogaXMgc3RpbGwgdGhlIG9ubHkgc3Ryb25nbHkgc2lnbmlmaWNhbnQgcHJlZGljdG9yLCBib3RoICoqQW54KiogYW5kICoqUGxheSoqIGhhdmUgZ3Jvd24gbXVjaCBtb3JlIHNpZ25pZmljYW50IHdpdGhvdXQgdGhlICoqQ0hTKiogcHJlZGljdG9yIGluIHRoZSBtb2RlbC4gQXBwYXJlbnRseSwgdGhvc2UgdGhyZWUgcHJlZGljdG9ycyB3ZXJlIGFsbCBmaWdodGluZyBvdmVyIHRoZSBzYW1lIHBpZWNlcyBvZiB2YXJpYW5jZS4gQWxzbywgKipPcHQqKiBpcyBqdXN0IG5vdCB3b3JraW5nIG91dC4gQWZ0ZXIgY2hlY2tpbmcgdGhlIGRpYWdvbm9zdGljcywgd2UnbGwgcmVtb3ZlIGl0Lg0KDQpgYGB7cn0NCnBsb3QobW9kNSwgd2hpY2ggPSBjKDEsMikpDQpgYGANCg0KVGhlIGRpYWdub3N0aWNzIGhhdmUgY2hhbmdlZCB2ZXJ5IGxpdHRsZS4gV2Ugc3RpbGwgaGF2ZSB0aGUgbGFjayBvZiBsaW5lYXJpdHkgb24gdGhlIGxlZnQgc2lkZSBvZiB0aGUgZml0dGVkIHZhbHVlcyBwbG90IGFuZCBhIHJlYXNvbmFibGUgcXEtcGxvdC4gTGV0J3Mgc2VlIHdoYXQgcmVtb3ZpbmcgKipPcHQqKiBkb2VzLg0KDQojIyAzLiBUaHJlZSBQcmVkaWN0b3IgTW9kZWwNCg0KYGBge3J9DQptb2Q2ID0gbG0oVGhyaWxsIH4gQW54ICsgTmFyYyArIFBsYXksIGRhdGEgPSBEYXRhMzM1MCkNCnN1bW1hcnkobW9kNikNCmBgYA0KDQpOb3RpY2UgdGhhdCB0aGUgUi1zcXVhcmVkIHZhbHVlIGlzIDAuMjE5LCBzdGlsbCBqdXN0IGEgdGlueSBiaXQgbGVzcyB0aGFuIGJlZm9yZS4gSW50ZXJlc3RpbmdseSwgYm90aCAqKkFueCoqIGFuZCAqKlBsYXkqKiBhcmUgbm93IHNpZ25pZmljYW50IHByZWRpY3RvcnMuICoqQW54KiogaXMgc3Ryb25nbHkgc2lnbmlmaWNhbnQuIEdpdmVuIHRoZSAkcCQtdmFsdWVzIGZyb20gdGhlIHRhYmxlLCB3ZSB3b3VsZCBzYXkgdGhhdCAqKk5hcmMqKiBpcyB0aGUgIm1vc3QgaW5mbHVlbnRpYWwgcHJlZGljdG9yIiBvZiAqKlRocmlsbC4qKiBXaGlsZSAqKk5hcmMqKiBpcyB0aGUgcHJpbWFyeSBwcmVkaWN0b3IsICoqQW54KiogaXMgYSBzZWNvbmRhcnkgcHJlZGljdG9yIGFuZCBzdGlsbCBzdHJvbmdseSBzaWduaWZpY2FudC4gKipQbGF5KiogaXMgc2lnbmlmaWNhbnQgYnV0IG9mIGxlc3MgaW1wb3J0YW5jZSB0byB0aGUgbW9kZWwuIEhvcGVmdWxseSB5b3UgaGF2ZSBnb3R0ZW4gYSBzbWFsbCB0YXN0ZSBvZiBleHBsb3JhdG9yeSBtb2RlbGluZy4gT24gYXNzaWdubWVudHMgZm9yIHRoaXMgY2xhc3MsIHlvdSB3aWxsIGJlIGFza2VkIG9ubHkgaW52ZXN0aWdhdGUgYW5kIGV2YWx1YXRlIGxpbmVhciBtb2RlbHMsIG5vdCBkZXNpZ24gdGhlbSB5b3Vyc2VsZi4gSW4gYW55IGNhc2UsIHRoaXMgc2V0IG9mIGV4YW1wbGVzIGhlbHBzIHRvIHNob3cgd2hhdCAiYmFkIiBwcmVkaWN0b3JzIGxvb2sgbGlrZSBhbmQgaG93IHRoZXkgYWZmZWN0IHRoZSBtb2RlbC4NCg0KYGBge3J9DQpwbG90KG1vZDYsIHdoaWNoID0gYygxLDIpKQ0KYGBgDQoNClNhZGx5LCBnZXR0aW5nIHJpZCBvZiB0d28gaW5lZmZlY3RpdmUgcHJlZGljdG9ycyBoYXNuJ3QgaW1wcm92ZWQgb3VyIG1vZGVsIGRpYWdub3N0aWNzLiBUaGlzIG1ha2VzIHNlbnNlLCBiZWNhdXNlIG1vc3Qgb2YgdGhlIHZhcmlhbmNlIGluIG91ciBtb2RlbCB3YXMgZHVlIHRvIHRoZSB0aHJlZSBwcmVkaWN0b3JzIHdlIHN0aWxsIGhhdmUgbGVmdC4gV2UgZG8gaGF2ZSBhIGxpbmVhcml0eSBpc3N1ZSB3aGljaCBkb2VzIGNhbGwgaW50byBxdWVzdGlvbiB0aGUgdmFsaWRpdHkgb2YgdGhlIG1vZGVsLiBJcyBpdCBzZXZlcmU/IE5vLiANCg0KV2hhdCBzaG91bGQgd2UgZG8/IEluIGEgbW9yZSBhZHZhbmNlZCBzdGF0aXN0aWNzIGNsYXNzLCB3ZSBtaWdodCB0cnkgYSB0cmFuc2Zvcm1hdGlvbi4gSWYgd2UgY2FuIGZpbmQgdGhlIG5vbi1saW5lYXJpdHksIHdlIG1pZ2h0IGJlIGFibGUgdG8gdGFrZSB0aGUgc3F1YXJlIHJvb3Qgb3IgbmF0dXJhbCBsb2cgb2YgYSBwcmVkaWN0b3IgYW5kIHJlbW92ZSBpdC4gRm9yIHRoaXMgY2xhc3MsIHNpbmNlIHRoZSBsYWNrIG9mIGxpbmVhcml0eSB3YXMgbm90IHRvbyBzZXZlcmUsIHdlIGNhbiByZXBvcnQgb3VyIGFuYWx5c2lzIGFuZCBkaXNjdXNzIHRoZSBwb3RlbnRpYWwgbm9uLWxpbmVhcml0eS4NCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5JVi4gRXhlcmNpc2VzPC9zcGFuPg0KDQoxLiBBZGQgdGhlIG5vbi1udW1lcmljIHZhcmlhYmxlIGJpb2xvZ2ljYWwgKipTZXgqKiB0byB0aGUgVGhyaWxsLXNlZWtpbmcgbW9kZWwgYWJvdmUgdG8gdGVzdCB0aGUgc3RlcmVvdHlwZSBvZiBtYWxlcyBiZWluZyBtb3JlIGFkdmVudHVyb3VzIHRoYW4gZmVtYWxlcy4gVGhlIHN0YXRzIG5vdGF0aW9uIGZvciB0aGUgbW9kZWwgaXMgJCRcdGV4dHtUaHJpbGx9IFxzaW0gXHRleHR7QW54fSArIFx0ZXh0e05hcmN9ICsgXHRleHR7UGxheX0gKyBcdGV4dHtTZXh9JCQgSXMgdGhlIHZhcmlhYmxlICoqU2V4KiogYSBzaWduaWZpY2FudCBwcmVkaWN0b3I/IERvZXMgaXQgYWRkIGFueXRoaW5nIHRvIHRoZSBtb2RlbD8gRGlkIHRoZSBkaWFnbm9zdGljIHBsb3RzIGNoYW5nZSBpbiBhbnkgc2lnbmlmaWNhbnQgd2F5Pw0KDQokJFx0ZXh0e1RocmlsbH0gXHNpbSBcdGV4dHtBbnh9ICsgXHRleHR7TmFyY30gKyBcdGV4dHtQbGF5fSArIFx0ZXh0e1NleH0kJA0KDQoyLiBVc2luZyB0aGUgKipIU0FHKiogdmFyaWFibGUgZnJvbSB0aGUgRGF0YTMzNTAgZGF0YSBmcmFtZSwgYnVpbGQgYSBsaW5lYXIgbW9kZWwgZm9yIEFnZ3Jlc3NpdmUgSHVtb3IgdXNpbmcgdGhlIHByZWRpY3RvcnMgTmFyY2lzc2lzbSAgYW5kIFNlbGYtRGVmZWF0aW5nIEh1bW9yIFN0eWxlOiAkJFx0ZXh0e0hTQUd9IFxzaW0gXHRleHR7TmFyY30gKyBcdGV4dHtIU1NEfSQkIEV2YWx1YXRlIGFuZCBhbmFseXplIHlvdXIgbW9kZWwgaW5jbHVkaW5nIGFsbCBkaWFnbm9zdGljIHBsb3RzLg0KDQozLiBBZGQgdGhlIEVhdGluZyBBdHRpdHVkZXMgdmFyaWFibGUgKipFYXQqKiBhcyB0aGUgdGhpcmQgcHJlZGljdG9yIGluIHlvdXIgbW9kZWwgZm9yICoqSFNBRyoqOiQkXHRleHR7SFNBR30gXHNpbSBcdGV4dHtOYXJjfSArIFx0ZXh0e0hTU0R9ICsgXHRleHR7RWF0fSQkIEV2YWx1YXRlIGFuZCBhbmFseXplIHlvdXIgbW9kZWwgaW5jbHVkaW5nIGFsbCBkaWFnbm9zdGljIHBsb3RzLCBhbmQgY29tcGFyZSB5b3VyIHRocmVlLXByZWRpY3RvciBtb2RlbCB3aXRoIHlvdXIgcmVzdWx0cyBmcm9tIHRoZSB0d28tcHJlZGljdG9yIG1vZGVsLiBJcyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiAqKkVhdCoqIGFuZCAqKkhTQUcqKiBwb3NpdGl2ZSBvciBuZWdhdGl2ZT8gSG93IGNhbiB5b3UgdGVsbCBmcm9tIHRoZSBtb2RlbCBzdW1tYXJ5IHN0YXRpc3RpY3Mgb3V0cHV0PyBJZiBoaWdoZXIgc2NvcmVzIG9uIHRoZSAqKkVhdCoqIHZhcmlhYmxlIGluZGljYXRlIGhpZ2hlciBsZXZlbHMgb2YgYmVpbmcgY2Fsb3JpZSBjb25zY2lvdXMsIGtub3dpbmcgdGhlIGZhdCBjb250ZW50IG9mIGZvb2QgaXRlbXMgYW5kIHRoaW5raW5nIGFib3V0IGJ1cm5pbmcgY2Fsb3JpZXMgd2hlbiB3b3JraW5nIG91dCwgZG9lcyB0aGlzIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICoqRWF0KiogYW5kICoqSFNBRyoqIG1ha2Ugc2Vuc2U/DQoNCjQuIFVzaW5nIHRoZSAqKk9DRCoqIHZhcmlhYmxlIGZyb20gdGhlIERhdGEzMzUwIGRhdGEgZnJhbWUsIGJ1aWxkIGEgdHdvLXByZWRpY3RvciBsaW5lYXIgbW9kZWwgdXNpbmcgKipQZXJmKiogYW5kICoqVHlwZUEqKiBhcyBwcmVkaWN0b3JzOiAkJFx0ZXh0e09DRH0gXHNpbSBcdGV4dHtQZXJmfSArIFx0ZXh0e1R5cGVBfSQkICBFdmFsdWF0ZSBhbmQgYW5hbHl6ZSB5b3VyIG1vZGVsIGluY2x1ZGluZyBhbGwgZGlhZ25vc3RpYyBwbG90cy4NCg0KNS4gQWRkICoqQW54KiogYXMgdGhlIHRoaXJkIHByZWRpY3RvciBpbiB5b3VyIG1vZGVsIGZvciAqKk9DRCoqOiAgJCRcdGV4dHtPQ0R9IFxzaW0gXHRleHR7UGVyZn0gKyBcdGV4dHtUeXBlQX0rIFx0ZXh0e0FueH0kJCBFdmFsdWF0ZSBhbmQgYW5hbHl6ZSB5b3VyIG1vZGVsIGluY2x1ZGluZyBhbGwgZGlhZ25vc3RpYyBwbG90cywgYW5kIGNvbXBhcmUgeW91ciB0aHJlZS1wcmVkaWN0b3IgbW9kZWwgd2l0aCB5b3VyIHJlc3VsdHMgZnJvbSB0aGUgdHdvLXByZWRpY3RvciBtb2RlbC4=