I. Correlation and Linear Models

When two numeric variables are related, we say they are correlated. If the correlation is reasonably strong, we can create a linear model. The modeling process is usually referred to as linear regression.

Like the hypothesis testing procedures, linear regression has a verification process based on the model assumptions.

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 frames used in this module: Data3350 and the U.S. wages data frames Med, Perc and PercB.

library(mosaic)
library(readxl)
Data3350 = read_excel("Data3350.xlsx")
Med = read_excel("Med.xlsx")
Perc = read_excel("Perc.xlsx")
PerB = read_excel("PercB.xlsx")

II. Assumptions for Linear Regression

Recall the assumptions for \(t\)-tests and ANOVA: normality, independence and homogeneity of the variances (e.g. “same variances”). Similar ideas are present for regression, plus a 4th assumption of a linear connection between the variables.

  1. Linearity. A linear relationship between the numeric variables exists.
  2. Normality. The errors or residuals are normally distributed.
  3. Homoscedasticity. Big word that simply means “same variance,” and the idea is that the variance in the residuals will be the same regardless of position along the \(x\)-axis.
  4. Independence. The observations are independent of one another.

The creators of SAS and JMP, two powerfuls statistical software tools, have provided a nicely illustrated overview of the assumptions for linear regression.

Residuals

A residual is the vertical distance between an actual data point and it’s \(y\)-value as predicted by the model. Suppose there is a data point \((4, 10)\), but when we plug that \(x\)-value into the linear model, we get a predicted value of \[\hat y = 12\].

The residual is defined as the vertical distance between the predicted \(y\)-value, \(\hat y\), and the actual \(y\)-value from the data point, \(y\). Residuals are referred to with the letter \(e\) because one can think of them as the “errors” in the model: \[\text{Residual} = \text{Predicted Value} - \text{Observed Value}\] or \[e = \hat y - y\]

III. Verification Process for Linear Regression Modeling

We will use a two part verification process for linear regression: check linearity with an xyplot (scatter plot), and check the normality and equal variances assumptions with a qqplot.

Example: Optimism vs. Anxiety

Let’s check the correlation of two variables in the Data3350 data frame. We can use the independent variable Opt, a measure of optimism, to predict levels of the dependent variable Anx, a measure of anxiety. Either variable could be the independent variable if a bivariate correlation were the only question, but a multiple regression prediction model for Anxiety is the ultimate goal of this unit. Using multiple predictors (independent variables) to predict the dependent variable is just as easy in RStudio as analyzing single-predictor models. The output from R is actually anticipating a multiple-predictor model, so it helps to think in terms of multiple predictors as we go through our example.

1. Verifiying Linearity Assumption

The xyplot function is included with the Mosaic package. Also remember to import the data frame Data3350. (See initialization block at top of document.) The statistical model \[\text{Anx} \sim \text{Opt}\] indicates that Anxiety is the dependent variable.

#library(mosaic)
xyplot(Anx ~ Opt, data = Data3350 , type = c("p","r"),
       main = "Optimism vs. Anxiety",
       xlab = "Optimism",
       ylab = "Anxiety")

In the code block above. the type parameter specifies the type of plotting we’re asking RStudio to do, and we’re asking for both points (“p”) and the regression line (“r”). A vector is created (c is R’s concatenate function) with two components, one for points and one for the regression line. If we ask only for type “p”, we get a standard scatter plot with no line of best fit superimposed.

The pattern in the scatter plot provides evidence of a linear pattern between the variables Opt and Anx. As the Optimism score increases, generally the Anxiety scores decrease.

2. Creating a Model

For our example, let’s create a linear model for Anxiety vs. Optimism.

lm(Anx ~ Opt, data = Data3350)

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

Coefficients:
(Intercept)          Opt  
     59.596       -1.124  

We only see the output for the coefficients of the line of best fit: the \(y\)-intercept and the slope. Yet, lots of information from the model has been generated by RStudio and is lurking in the background. Let’s create an object (or variable) called mod and ask RStudio to store the results there. Then we can access additional model information whenever we like.

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

Let’s request a model summary.

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

We will provide more details about the output later. For now, just realize that the function lm creates an object of class “linear model.” That object has many different outputs including details about the line of best fit, the residuals (as can be seen in the five number summary) and much, much more. That’s why we saved it as mod, short for “model.” We plan to call it later for diagnostic and analytic tasks.

3. Verifying Normality Assumption

Let’s consider what we’ve learned. We checked the linearity assumption by inspecting a scatter plot which showed a cloud of paired data points with a downward sloping trend (negative correlation). We next created a linear model and saved it as the RStudio object mod. Now, we wish to evaluate the normality assumption which says that the residuals should be normally distributed. In previous sections, we used histograms to investigate the shape of the data.

RStudio can plot a histogram of the residuals, too, but more typically we’ll use the qq-plot instead. Here’s the histogram.

histogram (~ resid (mod))

We can analyze the residuals histogram like any other: there is evidence the data were drawn from a bell-shaped distribution with skew to the right. The qq-plot does have advantages. Let’s create a qq-plot and then discuss what we’re seeing.

qqmath( ~ resid(mod))

The qq in qq-plot refers to quantiles, and quantile is just another word for percentile. A qq-plot compares the percentiles of one distribution to the percentiles of another. If the distributions have the same shape, the qq-plot will be a straight line. Our function qqmath is a normal qq-plot which compares the residuals in mod to the bell curve. If the residuals meet the model assumptions, we should see a straight line.

QQ-Plots

For details about what we’re
hoping not to find in a qq-plot,
see the QQ Plots module S11.

With real world data, we rarely see a perfectly straight line. What we hope to avoid is seeing something S-shaped or C-shaped where the last few points on the chart at either end jump far out of line.

Quick Example: \(\text{SE}\sim\text{Opt}\)

Using the Data3350 data frame, we can use a qq-plot to analyze the fit of the linear model for self-esteem (SE) with optimism (Opt).

mod1 = lm(SE ~ Opt, data = Data3350)
qqmath( ~ resid(mod1), type = c("p","r"))

The sharp drop-off at the bottom-left indicates that there is a more extreme value in the residuals than we would expect if the residuals were normally distributed. The top two points are also further from the 45-degree line than we would prefer.

Analyzing QQ-Plots

The University of Virginia has a nice article about understanding qq-plots which goes into more detail. Just beware they use slightly different R commands to achieve what we’re doing. (Remember, we always load the Mosaic package and use it’s simplified commands. The UVA article doesn’t use Mosaic.) I have linked to an image from the UVA article that shows an example of a qqplot showing a pattern we definitely don’t want to see. You should definitely click the link to understand the problematic shape we’re hoping to avoid.

Back to our original qq-plot: everything seems fine. While the tails of the qq-plot wiggle a bit, none of the plotted comparisons jump off the line very far. Our data appear to meet the normality assumptions.

4. Analysis Statements for Linear Regression

There are three analysis statements for regression models, two that describe the strength of the relationship, and one that describes how the relationship works. Let’s look at the model summary again:

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.2968.” 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.2968}\approx .5448\]

4.a) Analyzing the Correlation Coefficient \(r\)

The correlation coefficient \(r\) indicates the strength and direction of the bivariate association. The chart below relates to quantitative research involving human subjects in social sciences such as psychology, economics, and educational psychology. Regression methods are widely used across many disparate branches of research. No single chart like the one below could ever be general enough for every situation. A chemistry professor might have students check the correlation of measured outputs from a Boyle’s Law lab and decide that any \(r<0.98\) is too weak, that there must have been a measurement error.

\[\begin{array}{ll} \textbf{Correlation}&&\textbf{Strength}\\ \hline \hspace{1cm}|r|<.25&&\text{Little or None}\\ .25\leq|r|<.50&&\text{Weak}\\ .50\leq|r|<.75&&\text{Moderate}\\ .75\leq|r|&&\text{Strong} \end{array}\]

The analysis statement for the correlation must identify the strength and direction of the relationship. For this example, we find a moderate, negative correlation between Optimism and Anxiety.

4.b) Analyzing the Coefficient of Determination \(R^2\)

The output “Multiple R-squared: 0.2968” indicates the coefficient of determination. Because \(R^2=0.2968\), we know that 29.7% of the changes in Anxiety scores (the dependent variable) is accounted for by how the Optimism scores (the independent variable) are changing.

Why do we write \(R^2\) when it’s the square of the correlation coefficient which is always written in lower case? It’s important to understand the multivariate context. The coefficient of determination \(R^2\) is primarily used in multiple regression models to indicate the total variance accounted for by the model, not just one predictor. Correlations, on the other hand, only apply to bivariate scenarios. This concept will once more make better sense in the multiple predictor setting of the follow-on analysis.

For this example, we find that 30% of the variance in Anxiety is accounted for by Optimism. Note that \(R^2\) refers to the total variance accounted for by the model, so we will see this statistic again in the next section when we use multiple predictors.

Example 2: U.S. Median Wage Growth

Consider the scatter plot below showing median U.S. wages since 1980. All wage values are represented in current USD (e.g. corrected for inflation by the BLS). All data for this module were downloaded in September, 2002, from the Bureau of Labor Statistics using either Table 2 or Table 5. The data charts produced by the BLS are not data frames, so the wage data was coerced into single-column format with column headers and other formatting added so that it would work well in R. Period 0 is the 1st Quarter of 1980, the first quarter of Ronald Reagan’s first term.

U.S. Median Wage Growth

We can create scatter plots in Microsoft Excel by selecting the two columns of data and clicking on “Charts: Scatter” from the Insert menu. By right-clicking on a data point, we can “Add Trendline” and select options to include equation and \(R^2\) on the chart.

The equation displayed is the line of best fit \[ y = 4.09x + 260.57\] which can be used to estimate the median wage for any time period since 1981 Q1. Historically, the median weekly wage has increased by \(\$4.09\) each quarter (or $16.36 each year). The coefficient of determination \(R^2=.993\) shows that \(99.3\%\) of the variance in median wages is accounted for by the time period.

The pattern is clearly linear with an odd uptick in the final 1-2 periods which represent the first two quarters of 2020. What’s going on? Why would median income surge massively during the COVID lockdown?

IV. Outliers Affect Correlation and Predictions Based on Regression Models.

The two outliers at the far right correspond to the first two quarters of 2020 when the pandemic started. Think about which U.S. workers lost their jobs due to the COVID lockdowns. Most of them were members of the working poor who make much less than the median income: folks like waitresses, non-essential retail workers, and movie theater attendants. The total number of workers decreased.

Think about taking a data set of sample size 20. The median wage would be the average of the 10th and 11th individuals when the sample is ordered from least to greatest wage. Suppose the five individuals with the lowest wages were removed, the entire bottom quarter of the data set. The median of the new 15-person data set would be the 8th person when ordered from least to greatest, but in reality this is the the 13th person from the original data set. The median shifts upward even though 25% of this sample lost their jobs.

To display the chart below, we must first import the file Med.xlsx into RStudio (File menu: “Import Dataset”). The number of workers decreases sharply at the onset of recessions, and the job loss was particularly nasty in second quarter of 2020. Note the large discontinuity at the beginning of the recession of 2008-2009. The work force contracted by almost 5 million wage earners in the 1st quarter of 2009. The last data point on the right is the second quarter of 2020 when more than 11 million U.S. wage earners lost their jobs due to the COVID shutdown. In the previous quarter, more than 2 million lost their jobs.

xyplot(Earners ~ Period, data = Med, 
       xlab = "Quarters since 1981 Q1", 
       ylab = "Number of Wage Earners (in thousands)")

Apparently, for the COVID lockdown, the vast majority of those 13 million wage earners were at the lower end of the economic spectrum. Had they been evenly distributed throughout the economic spectrum, the median would not have jumped upward. These data show economic devastation was immense especially for those earning below median wages. To correct for these obvious outliers, we will compare only the pre-COVID quarters. If Med.xlsx has been imported into RStudio, the following code will subset it to only include quarters through the end of 2019.

newMed = subset( Med , Period <= 155 )

Let’s recreate the model in RStudio without the COVID outliers. We’re not ignoring them, we’re instead understanding that the outliers create a very rosy picture when something horrible is happening. In R, we use the xyplot function to create scatter plots. The “type” command asks R to show both the points (“p”) and regression line (“r”).

# library(mosaic)
xyplot( Median ~ Period, data = newMed , 
        type = c("p","r") ,
        xlab = "Quarters since 1981 Q1" , 
        ylab = "U.S. Median Wage")

The R commands \(\fbox{lm}\) and \(\fbox{cor}\) generate a linear model and the correlation respectively.

lm( Median ~ Period, data = newMed)

Call:
lm(formula = Median ~ Period, data = newMed)

Coefficients:
(Intercept)       Period  
    259.155        4.041  
cor(Median ~ Period, data = Med)
[1] 0.9963508
cor(Median ~ Period, data = newMed)
[1] 0.9975952

The correlation increased by 0.0011 and the rate of wage growth changed from \(\$4.09\) to \(\$4.04\). A nickel may not seem like much. However, consider the relative error of the slope of the regression line equates to more than \(1\%\) per quarter propagated over 150-plus quarters.

Example 2: Analysis Statements

Let’s return to the modified data set, build and save the model, and conduct our analysis without the outliers present.

mod = lm( Median ~ Period, data = newMed)
summary(mod)

Call:
lm(formula = Median ~ Period, data = newMed)

Residuals:
    Min      1Q  Median      3Q     Max 
-30.915  -9.027   1.179   8.671  33.461 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 259.1551     2.0411     127   <2e-16 ***
Period        4.0412     0.0227     178   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 12.64 on 153 degrees of freedom
Multiple R-squared:  0.9952,    Adjusted R-squared:  0.9952 
F-statistic: 3.17e+04 on 1 and 153 DF,  p-value: < 2.2e-16

The line of best fit is \[\text{Med} = 4.05\ *\ \text{Period} + 259.16 \] We find that \(R^2 = .995\) which means that \(r = \sqrt{R^2}=0.997\) (Beginning analysts should always use “Multiple R-squared” value, not adjusted.) Thus, the correlation between median wage and quarter since 1980 is very strong. \(R^2\) is the coefficient of determination and indicates that the Period accounts for \(99.5\%\) of the variance in median wages. Lastly, we can see that the slope of the line of best is \(\$4.04\) which means that U.S. wage growth over the past 40 years has averaged about \(4.04\) per week per quarter (in current U.S. dollars), or about \(\$16.32\) per week per year.

Example 3: Median Wages during Trump Administration

Trump campaigned in 2016 on tax cuts, tariffs on foreign imports, exiting global trade treaties (TPP) and renegotiating NAFTA. Trump claimed his approach would help the wage earners in the country by reversing the globalization that shipped middle class jobs overseas. To suggest that experts disagreed would be a marked understatement. The U.S. political climate for three decades has been increasingly globalist. Trump’s economic nationalism was pilloried by pundits, Republican party stalwarts and his political opponents alike.

Let’s investigate what transpired as detailed breifly in the YouTube video lecture, but this time work with the much more advanced tools in RStudio.

Using subset function in R to create data frame for Trump years only

We first need to subset our Med data set for just the years 2017 through 2109, or 12 quarters. These will be Periods 144 to 155.

TrumpMed = subset( Med , Period >=  144 & Period <= 155)

Scatter Plot: Trump Era Median Wage

xyplot(Median ~ Period, data = TrumpMed , 
        type = c("p","r") ,
        xlab = "All Quarters 2017 to 2019" ,
        ylab = "Trump Era Median Wage") 

Regression model for Trump era median wage

We use the lm function in R to create the linear model, and we store the results in the variable modT (Trump model) so we can access it later. The summary statistics match the YouTube lecture video which were created using the TI graphing calculator.

modT = lm(Median ~ Period, data = TrumpMed)
summary(modT)

Call:
lm(formula = Median ~ Period, data = TrumpMed)

Residuals:
    Min      1Q  Median      3Q     Max 
-14.139  -3.509   1.417   3.787  12.417 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -44.288     90.176  -0.491    0.634    
Period         6.185      0.603  10.257 1.26e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.211 on 10 degrees of freedom
Multiple R-squared:  0.9132,    Adjusted R-squared:  0.9045 
F-statistic: 105.2 on 1 and 10 DF,  p-value: 1.259e-06

QQ-Plot for Trump era median wage model

There is certainly some deviation in the qq-plot, but the overall pattern is roughly along the 45-degree line.

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

Example 3b: Median Wages during Obama Administration

We can subset the data frame for the whole Obama era or just the last three years.

ObamaMedTotal = subset( Med , Period >= 112 & Period <= 143 )
ObamaMedL3 = subset( Med , Period >= 132 & Period <= 143 )

Scatter plots for wage growth during Obama era

xyplot(Median ~ Period, data = ObamaMedTotal , 
        type = c("p","r") ,
        xlab = "All Quarters 2009 to 2016" ,
        ylab = "Obama Era Median Wage") 

A marked increase can be seen in the final few quarters above. Let’s display the last 3 years only.

xyplot(Median ~ Period, data = ObamaMedL3 , 
        type = c("p","r") ,
        xlab = "All Quarters 2014 to 2016" ,
        ylab = "Obama Era Median Wage") 

Model summaries for Obama era

modB = lm(Median ~ Period, data = ObamaMedTotal)
modBL3 = lm(Median ~ Period, data = ObamaMedL3)
summary(modB)

Call:
lm(formula = Median ~ Period, data = ObamaMedTotal)

Residuals:
    Min      1Q  Median      3Q     Max 
-14.193  -5.309   1.039   5.343  15.086 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 384.6521    18.6409   20.64   <2e-16 ***
Period        3.0515     0.1458   20.93   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.616 on 30 degrees of freedom
Multiple R-squared:  0.9359,    Adjusted R-squared:  0.9337 
F-statistic: 437.9 on 1 and 30 DF,  p-value: < 2.2e-16
summary(modBL3)

Call:
lm(formula = Median ~ Period, data = ObamaMedL3)

Residuals:
     Min       1Q   Median       3Q      Max 
-10.6608  -5.4554  -0.7168   5.4222   9.6503 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 212.9615    86.2571   2.469   0.0332 *  
Period        4.3112     0.6271   6.875 4.33e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.499 on 10 degrees of freedom
Multiple R-squared:  0.8254,    Adjusted R-squared:  0.8079 
F-statistic: 47.26 on 1 and 10 DF,  p-value: 4.327e-05

Note that the median wage growth for the entire 8 years of the Obama administration is lower than the historic trend of \(\$4.05\), but in the final three years was \(\$5.08\) as discussed in the YouTube lecture video.

V. Testing Sigificance of Slope: Randomized Confidence Intervals

The hypothesis we wish to test is if the slope of the model from the Trump era is significantly different (higher) than the historic trend.

\[H_0 : \beta = 4.04\\H_a : \beta > 4.04\]

One reason we save the models is that it makes grabbing them later quite easy. Let’s generate the 95% confidence intervals for the slope of the regression line in each model.

Confidence interval: Trump era

confint.lm(modT)
                  2.5 %    97.5 %
(Intercept) -245.213481 156.63772
Period         4.841689   7.52894

Because the 95% confidence interval \((4.84,7.52)\) does not include \(\$4.04\), we reject the null and have evidence for a significantly higher Trump era median wage growth at the \(\alpha = 0.025\) level. With confidence intervals, we don’t have the luxury of a one-tailed hypothesis evaluation. When testing a two-tailed hypothesis with a confidence interval, then \[\alpha = 1 - \text{confidence level}\] For one-tailed tests, we have to match the area in the tails, so

\[\alpha = \frac{1 - \text{confidence level}}{2}\]

To produce the exact equivalent of testing at the \(\alpha = 0.05\) level, we would use the following 90% confidence interval estimate.

confint.lm(modT, level = 0.90)
                    5 %       95 %
(Intercept) -207.729148 119.153390
Period         5.092353   7.278276

Now we have exactly 5% of the area under the curve to the left which matches the rejection region for a one-tailed \(t\)-test.

Confidence intervals: Obama era

We can test the hypothesis that the Obama era median wage growth was different that historic value at the 0.05 level. \[H_0 : \beta = 4.04\\H_a : \beta \neq 4.04\]

confint.lm(modB)
                 2.5 %    97.5 %
(Intercept) 346.582336 422.72192
Period        2.753696   3.34931

The historic trend for median wage growth of $4.04 is not included in the interval which suggests (based on the endpoints of the confidence interval above) that we reject the null hypothesis that the Obama era median wage growth is $4.05. When all 32 quarters of the Obama era are included, evidence suggests that the overall growth of the U.S. median wage was significantly lower than the historic trend (at the 0.025 level of significance).

Confidence interval: Last 3 years of Obama era

Note that a model restricted to the final three years of the Obama era dramatically shifts the analysis in favor of Obama. While the effect is certainly a cherry-picking of the best Obama years, we were analyzing the argument that the Trump economy rode on the coattails of the Obama economy in 2016. The argument is plausible on its face, so let’s take a look at the data.

We’re testing the null hypothesis that the last three years of the Obama era growth in median wages is similar to the Trump era growth of $6.90.

\[H_0 : \beta = 6.19\\H_a : \beta \neq 6.19\]

We need the 95% confidence interval for the last three years of Obama.

confint.lm(modBL3, level = 0.95)
                2.5 %     97.5 %
(Intercept) 20.768690 405.154386
Period       2.913863   5.708515

The upper endpoint of the confidence is close to but not greater than $6.19. Thus, we reject the null. We have evidence the median wage growth was significantly different in the pre-COVID Trump era than during the last three years of Obama. Remember that removing the median wage outliers from the COVID recession actually makes Trump’s growth rate lower.

QQ-Plots for Obama era median wage growth models

As with the Trump era, both Obama era qq-plots line up approximately with the 45-degree line, but they do have some odd variations.

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

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

VI. Robustness of estimates of regression statistics

Due to the Gauss-Markov theorem, we know that the Ordinary Least Squares model is the best linear unbiased estimator (BlUE) for the model provided the relationship between the variables is actually linear. Better, we know that the regression statistics are generally robust even if the normality assumption is violated, so long as evidence of linearity is present.

We do have a problem, however, because the linear regression \(t\)-tests and \(t\)-intervals are not robust. Their intervals and \(p\)-values can be skewed by a lack of normality. When the qq-plot shows the residuals may not be normally distributed, we should use randomization techniques to generate p-values and confidence intervals instead traditional statistical procedures.

Mosaic’s Randomization Options

  1. Shuffle. Permutes the values in the sample data.
  2. Sample. Draws a sub-sample from the sample data
    without replacement.
  3. Resample. Draws a sub-sample from the sample data
    with replacement.

For examples of permutation tests and bootstrapping, see
the Randomization Tutorial.

VII. Randomization approach for Trump vs. Obama

We have two randomization options:

  1. Permutation Method
  2. Bootstrapping Method

The permutation method simply shuffles the \(y\)-values, pairing them with random \(x\)-values. The random association of \(y\)-values will generate, on average, a correlation and slope of zero. This allows us to test the null hypothesis \[H_0 : \rho = 0\] but not null hypotheses like \[H_0 : \rho = 5.08\]

As usual, the Rossman-Chance applet is both a great visualization and easily implements the randomization.

Rossman Chance Regression Shuffle App

Randomized Confidence Intervals

See the Statistical Estimation (module 6) for details
on using bootstrapping to create randomized confidence
intervals.

However, we knew that the correlation of median wage during the Trump era was significantly different than zero. Given the historic trend of $4.05, the correlation would be remarkable only if it were zero.

Bootstrapping

The bootstrapping method takes samples with replacement from the sample data to generate an estimate of the sampling distribution. Let’s create one of the resamples.

coef(lm(Median ~ Period, data=resample(TrumpMed, size = 10)))
(Intercept)      Period 
-112.674672    6.641921 

The resample function has produced 10 data points drawn with replacement from the TrumpMed data frame. Note that the same data point may be drawn more than once. The linear model created by using those resampled data points has a slope of 6.64.

For bootstrapping, we are going to allow the resample function to choose its own size parameter. If we resample a data set with 155 observations, the resample functions will make 155 draws with replacment each time it runs.

bootstrap = do(500) * coef(lm(Median ~ Period, data=resample(TrumpMed)))
densityplot(~Period, data=bootstrap)

There are a couple of methods to generate a confidence interval based on the bootstrap distribution. The best method - most often appropriate in most common situations - requires only that the bootstrap distribution be symmetric. The density plot above suggests the symmetry assumption is reasonable.

To create the confidence interval, we just find the relevant percentiles from within the bootstrap distribution. In our bootstrap distribution we have two values, “Intercept” and “Period.” The “Period” column contains the slope estimates.

qdata(~Period, p=c(0.025, 0.975), data=bootstrap)
    2.5%    97.5% 
5.026753 7.544513 

Thus, the 95% confidence interval using randomization is \[(5.03, 7.54)\] which is a bit different than the \(t\)-interval of \[(4.84, 7.53)\] calculated above.

You can rerun the bootstrapping resampling several times to see how the confidence interval changes. It remains somewhat close to the \(t\)-interval values, but does vary a bit. In any case, we still appear to reject the null hypothesis that the Trump era was no different than the Obama era, at least with regard to median wage growth.

Caveats and Takeaways

In political discussions, folks often choose teams to support and get frustrated when their team seems diminished. A word or two of caution.

  1. Agenda-driven geeks can lie with statistics. Politics is rife with deception. Media reports are increasingly agenda-driven. Question the motivation and factual integrity of every voice. Rely on good science.
  2. Multiple ways of assessing the economy are viable. If you felt the economic discussion was slanted right, remember there are lots of measures of economic health. Perhaps other measures tilt left. Wages are not the only way to earn money (investing, commisions, real estate, etc.). Median wages also don’t measure the lowest end of the economic spectrum. What about the 10th percentile or 25th percentile? Studying an issue like this is multifaceted and may require lots of research. Keep an open mind and dig through the most scientific results you can find.

Key Takeaways

  1. Savvy geeks detect others’ attempted lies with statistics. One major benefit of this class should be learning to apply your analytic skills to real world issues where it’s incredibly important not to naively fall for deceptions like cherry-picking cases that support one’s position. The counter-intuitive COVID outliers in the median wage data are a perfect example that would have sharply increased the median wage growth during the Trump era. People disagree about politics, but I hope we can agree that learning the art and science of applied statistics makes us more knowledgeable citizens and better potential employees and entrepreneurs.
  2. The median wage discussion contained great data sets. The major reason the economic data was chosen was for pedagogy. Several of the qq-plots looked quite wobbly which motivated a discussion about violations of the normality assumption. The media report statistics that were generated by analyses exactly like the ones shown above. We don’t get to check for crazy COVID outliers. We don’t get to scan the qq-plots to assess model fit. We don’t get to verify any of the assumptions or, in fact, check for bias on the part of the scientist who did the analysis. The median wage data sets allowed for an important discussion, and hopefully an interesting one as well.
  3. Regression model statistics are robust with respect violations of the normality assumption for residuals, but linear regression \(t\)-tests and \(t\)-intervals are not. We always use scatter plots to verify that a linear relationship is a reasonable. With qq-plots, we are trying to decide how reliable the resulting model will be. If the qq-plot detects issues, use a randomization method for tests of significant correlation or confidence interval estimates.
  4. Bootstrapping. We presented two randomization methods to tests of significant correlation. The permutation method is visually demonstrated by the Rossman-Chance applet. The bootstrap method allowed us to construct a confidence interval estimate of the slope parameter, yet the only the assumption was that bootstrap distribution was symmetric. When the qq-plot indicates potential violations of the normality assumption, use bootstrapping instead of \(t\)-procedures.

VIII. Exercises

  1. Use the Data3350 data frame to build and evaluate a linear model for narcissism (dependent variabele) vs. thrill-seeking (independent variable) using the Thrill and Narc variables. Be sure to check the linearity and normality assumptions and analyze all regression statistics. Construct a confidence interval for the slope of the regression line using an appropriate method.

  2. Use the Data3350 data frame to build and evaluate a linear model for neuroticism (dependent variabele) vs. optimism (independent variable) using the Neuro and Opt variables. Be sure to check the linearity and normality assumptions and analyze all regression statistics. Construct a confidence interval for the slope of the regression line using an appropriate method.

  3. Using the built-in Mosaic data set Dimes, test the significance of the correlation between mass and year. Would it be appropriate to build a linear model in this case? Why or why not?

  4. Use the Perc data frame to create linear models for the 25th percentile wage earners from 2000 Q1 through 2019 Q4. Be sure to look carefully at all diagnostic plots. Create models for the Trump era and the last 3 years of the Obmama era and conduct hypothesis tests that the Trump era growth was significantly greater than the historic trend as well as greater than the Obama era.

  5. Use the Perc data frame to create linear models for the 75th and 90th percentile wage earners from 2000 Q1 through 2019 Q4. Be sure to look carefully at all diagnostic plots. Create models for the Trump era and the last 3 years of the Obmama era and conduct hypothesis tests that the Trump era growth was significantly greater than the historic trend as well as greater than the Obama era.

  6. The PercB data is similar to Perc in that it includes the 10th, 25th, 50th, 75th and 90th percentile wages, but PerB includes Black wage earners only. Use the PercB data frame to create a linear model for the median wage growth (50th percentile) from 2000 Q1 through 2019 Q4. Be sure to look carefully at all diagnostic plots. Create models for the Trump era and the last 3 years of the Obmama era and conduct hypothesis tests that the Trump era growth was significantly greater than the historic trend as well as greater than the Obama era.

LS0tDQp0aXRsZTogIkJhc2ljcyBvZiBDb3JyZWxhdGlvbiBhbmQgUmVncmVzc2lvbiINCnN1YnRpdGxlOiBVTkcgTUFUSCAzMzUwIChvbmxpbmUpDQphdXRob3I6IFJvYmIgU2lubg0KZGF0ZTogU2VwdGVtYmVyIDIwMjANCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+SS4gQ29ycmVsYXRpb24gYW5kIExpbmVhciBNb2RlbHM8L3NwYW4+DQoNCldoZW4gdHdvIG51bWVyaWMgdmFyaWFibGVzIGFyZSByZWxhdGVkLCB3ZSBzYXkgdGhleSBhcmUgY29ycmVsYXRlZC4gSWYgdGhlIGNvcnJlbGF0aW9uIGlzIHJlYXNvbmFibHkgc3Ryb25nLCB3ZSBjYW4gY3JlYXRlIGEgbGluZWFyIG1vZGVsLiBUaGUgbW9kZWxpbmcgcHJvY2VzcyBpcyB1c3VhbGx5IHJlZmVycmVkIHRvIGFzIGxpbmVhciByZWdyZXNzaW9uLg0KDQpMaWtlIHRoZSBoeXBvdGhlc2lzIHRlc3RpbmcgcHJvY2VkdXJlcywgbGluZWFyIHJlZ3Jlc3Npb24gaGFzIGEgdmVyaWZpY2F0aW9uIHByb2Nlc3MgYmFzZWQgb24gdGhlIG1vZGVsIGFzc3VtcHRpb25zLg0KDQo8ZGl2IHN0eWxlPSJmbG9hdDpyaWdodDsgbWFyZ2luOiA4cHg7IGJvcmRlcjoycHggYmxhY2sgc29saWQ7IHBhZGRpbmc6IDBweCAxMHB4IDVweCI+DQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5Jbml0aWFsaXppbmcgUlN0dWRpbzwvc3Bhbj4NClRoZSBkYXRhIHNldCB3ZSB3aWxsIHVzZSBwcmltYXJpbHkgaXMgKipEYXRhMzM1MCoqIHdoaWNoIHdhcyBwcm9kdWNlZCBpbiAyMDE1IGR1cmluZyBhbiB1bmRlcmdyYWR1YXRlIHJlc2VhcmNoIHByb2plY3QgYWJvdXQgcGVyc29uYWxpdHkgYW5kIGh1bW9yLiBUaGUgKipWYXJzRGF0YTMzNTAqKiBQREYgZmlsZSBoYXMgZGVzY3JpcHRpb25zIG9mIGVhY2ggdmFyaWFibGUgaW4gdGhlIERhdGEzMzUwIGZpbGUuIEJvdGggYXJlIGF2YWlsYWJsZSBmb3IgZG93bmxvYWQgaW4gRDJMLiBCZSBzdXJlIHRvIHB1dCB0aGUgRGF0YTMzNTAgaW4geW91ciBSIGZvbGRlciBpbiBEb2N1bWVudHMsIGFuZCBtYWtlIHN1cmUgeW91ciB3b3JraW5nIGRpcmVjdG9yeSBpcyBzZXQgdGhlIHNhbWUgd2F5IChTZXNzaW9uIG1lbnUpLiBUaGUgY29kZSBibG9jayBiZWxvdyB1c2VzIHRoZSAqKmxpYnJhcnkqKiBmdW5jdGlvbiB0byBlbnN1cmUgdGhhdCB0aGUgKipNb3NhaWMqKiBwYWNrYWdlIGlzIGxvYWRlZCBhbmQgd2lsbCBpbXBvcnQgdGhlIGRhdGEgZnJhbWVzIHVzZWQgaW4gdGhpcyBtb2R1bGU6ICoqRGF0YTMzNTAqKiBhbmQgdGhlIFUuUy4gd2FnZXMgZGF0YSBmcmFtZXMgKipNZWQqKiwgKipQZXJjKiogYW5kICoqUGVyY0IqKi4NCg0KYGBge3J9DQpsaWJyYXJ5KG1vc2FpYykNCmxpYnJhcnkocmVhZHhsKQ0KRGF0YTMzNTAgPSByZWFkX2V4Y2VsKCJEYXRhMzM1MC54bHN4IikNCk1lZCA9IHJlYWRfZXhjZWwoIk1lZC54bHN4IikNClBlcmMgPSByZWFkX2V4Y2VsKCJQZXJjLnhsc3giKQ0KUGVyQiA9IHJlYWRfZXhjZWwoIlBlcmNCLnhsc3giKQ0KYGBgDQo8L2Rpdj4NCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5JSS4gQXNzdW1wdGlvbnMgZm9yIExpbmVhciBSZWdyZXNzaW9uPC9zcGFuPg0KDQpSZWNhbGwgdGhlIGFzc3VtcHRpb25zIGZvciAkdCQtdGVzdHMgYW5kIEFOT1ZBOiBub3JtYWxpdHksIGluZGVwZW5kZW5jZSBhbmQgaG9tb2dlbmVpdHkgb2YgdGhlIHZhcmlhbmNlcyAoZS5nLiAic2FtZSB2YXJpYW5jZXMiKS4gU2ltaWxhciBpZGVhcyBhcmUgcHJlc2VudCBmb3IgcmVncmVzc2lvbiwgcGx1cyBhIDR0aCBhc3N1bXB0aW9uIG9mIGEgbGluZWFyIGNvbm5lY3Rpb24gYmV0d2VlbiB0aGUgdmFyaWFibGVzLiANCg0KMS4gKipMaW5lYXJpdHkuKiogQSAqbGluZWFyKiByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgbnVtZXJpYyB2YXJpYWJsZXMgZXhpc3RzLg0KMi4gKipOb3JtYWxpdHkuKiogVGhlIGVycm9ycyBvciAqcmVzaWR1YWxzKiBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQozLiAqKkhvbW9zY2VkYXN0aWNpdHkuKiogQmlnIHdvcmQgdGhhdCBzaW1wbHkgbWVhbnMgInNhbWUgdmFyaWFuY2UsIiBhbmQgdGhlIGlkZWEgaXMgdGhhdCB0aGUgdmFyaWFuY2UgaW4gdGhlIHJlc2lkdWFscyB3aWxsIGJlIHRoZSBzYW1lIHJlZ2FyZGxlc3Mgb2YgcG9zaXRpb24gYWxvbmcgdGhlICR4JC1heGlzLg0KNC4gKipJbmRlcGVuZGVuY2UuKiogVGhlIG9ic2VydmF0aW9ucyBhcmUgaW5kZXBlbmRlbnQgb2Ygb25lIGFub3RoZXIuDQoNClRoZSBjcmVhdG9ycyBvZiBTQVMgYW5kIEpNUCwgdHdvIHBvd2VyZnVscyBzdGF0aXN0aWNhbCBzb2Z0d2FyZSB0b29scywgaGF2ZSBwcm92aWRlZCBhIDxhIGhyZWYgPSBodHRwczovL3d3dy5qbXAuY29tL2VuX3VzL3N0YXRpc3RpY3Mta25vd2xlZGdlLXBvcnRhbC93aGF0LWlzLXJlZ3Jlc3Npb24vc2ltcGxlLWxpbmVhci1yZWdyZXNzaW9uLWFzc3VtcHRpb25zLmh0bWw+bmljZWx5IGlsbHVzdHJhdGVkIG92ZXJ2aWV3IG9mIHRoZSBhc3N1bXB0aW9ucyBmb3IgbGluZWFyIHJlZ3Jlc3Npb248L2E+LiANCg0KIyMgUmVzaWR1YWxzDQoNCkEgcmVzaWR1YWwgaXMgdGhlIHZlcnRpY2FsIGRpc3RhbmNlIGJldHdlZW4gYW4gYWN0dWFsIGRhdGEgcG9pbnQgYW5kIGl0J3MgJHkkLXZhbHVlIGFzIHByZWRpY3RlZCBieSB0aGUgbW9kZWwuIFN1cHBvc2UgdGhlcmUgaXMgYSBkYXRhIHBvaW50ICQoNCwgMTApJCwgYnV0IHdoZW4gd2UgcGx1ZyB0aGF0ICR4JC12YWx1ZSBpbnRvIHRoZSBsaW5lYXIgbW9kZWwsIHdlIGdldCBhIHByZWRpY3RlZCB2YWx1ZSBvZiAkJFxoYXQgeSA9IDEyJCQuDQoNClRoZSByZXNpZHVhbCBpcyBkZWZpbmVkIGFzIHRoZSB2ZXJ0aWNhbCBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBwcmVkaWN0ZWQgJHkkLXZhbHVlLCAkXGhhdCB5JCwgYW5kIHRoZSBhY3R1YWwgJHkkLXZhbHVlIGZyb20gdGhlIGRhdGEgcG9pbnQsICR5JC4gUmVzaWR1YWxzIGFyZSByZWZlcnJlZCB0byB3aXRoIHRoZSBsZXR0ZXIgJGUkIGJlY2F1c2Ugb25lIGNhbiB0aGluayBvZiB0aGVtIGFzIHRoZSAiZXJyb3JzIiBpbiB0aGUgbW9kZWw6DQokJFx0ZXh0e1Jlc2lkdWFsfSA9IFx0ZXh0e1ByZWRpY3RlZCBWYWx1ZX0gLSBcdGV4dHtPYnNlcnZlZCBWYWx1ZX0kJA0Kb3INCiQkZSA9IFxoYXQgeSAtIHkkJA0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPklJSS4gVmVyaWZpY2F0aW9uIFByb2Nlc3MgZm9yIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsaW5nPC9zcGFuPg0KDQpXZSB3aWxsIHVzZSBhIHR3byBwYXJ0IHZlcmlmaWNhdGlvbiBwcm9jZXNzIGZvciBsaW5lYXIgcmVncmVzc2lvbjogY2hlY2sgbGluZWFyaXR5IHdpdGggYW4gKip4eXBsb3QqKiAoc2NhdHRlciBwbG90KSwgYW5kIGNoZWNrIHRoZSBub3JtYWxpdHkgYW5kIGVxdWFsIHZhcmlhbmNlcyBhc3N1bXB0aW9ucyB3aXRoIGEgKipxcXBsb3QqKi4NCg0KIyMgRXhhbXBsZTogT3B0aW1pc20gdnMuIEFueGlldHkNCg0KTGV0J3MgY2hlY2sgdGhlIGNvcnJlbGF0aW9uIG9mIHR3byB2YXJpYWJsZXMgaW4gdGhlIERhdGEzMzUwIGRhdGEgZnJhbWUuIFdlIGNhbiB1c2UgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlICoqT3B0KiosIGEgbWVhc3VyZSBvZiBvcHRpbWlzbSwgdG8gcHJlZGljdCBsZXZlbHMgb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAqKkFueCoqLCBhIG1lYXN1cmUgb2YgYW54aWV0eS4gRWl0aGVyIHZhcmlhYmxlIGNvdWxkIGJlIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSBpZiBhIGJpdmFyaWF0ZSBjb3JyZWxhdGlvbiB3ZXJlIHRoZSBvbmx5IHF1ZXN0aW9uLCBidXQgYSBtdWx0aXBsZSByZWdyZXNzaW9uIHByZWRpY3Rpb24gbW9kZWwgZm9yICoqQW54aWV0eSoqIGlzIHRoZSB1bHRpbWF0ZSBnb2FsIG9mIHRoaXMgdW5pdC4gVXNpbmcgbXVsdGlwbGUgcHJlZGljdG9ycyAoaW5kZXBlbmRlbnQgdmFyaWFibGVzKSB0byBwcmVkaWN0IHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgaXMganVzdCBhcyBlYXN5IGluIFJTdHVkaW8gYXMgYW5hbHl6aW5nIHNpbmdsZS1wcmVkaWN0b3IgbW9kZWxzLiBUaGUgb3V0cHV0IGZyb20gUiBpcyBhY3R1YWxseSBhbnRpY2lwYXRpbmcgYSBtdWx0aXBsZS1wcmVkaWN0b3IgbW9kZWwsIHNvIGl0IGhlbHBzIHRvIHRoaW5rIGluIHRlcm1zIG9mIG11bHRpcGxlIHByZWRpY3RvcnMgYXMgd2UgZ28gdGhyb3VnaCBvdXIgZXhhbXBsZS4NCg0KIyMjIDEuIFZlcmlmaXlpbmcgTGluZWFyaXR5IEFzc3VtcHRpb24NCg0KVGhlICoqeHlwbG90KiogZnVuY3Rpb24gaXMgaW5jbHVkZWQgd2l0aCB0aGUgTW9zYWljIHBhY2thZ2UuIEFsc28gcmVtZW1iZXIgdG8gaW1wb3J0IHRoZSBkYXRhIGZyYW1lIERhdGEzMzUwLiAoU2VlIGluaXRpYWxpemF0aW9uIGJsb2NrIGF0IHRvcCBvZiBkb2N1bWVudC4pIFRoZSBzdGF0aXN0aWNhbCBtb2RlbCAkJFx0ZXh0e0FueH0gXHNpbSBcdGV4dHtPcHR9JCQgaW5kaWNhdGVzIHRoYXQgQW54aWV0eSBpcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLg0KDQpgYGB7cn0NCnh5cGxvdChBbnggfiBPcHQsIGRhdGEgPSBEYXRhMzM1MCAsIHR5cGUgPSBjKCJwIiwiciIpLA0KICAgICAgIG1haW4gPSAiT3B0aW1pc20gdnMuIEFueGlldHkiLA0KICAgICAgIHhsYWIgPSAiT3B0aW1pc20iLA0KICAgICAgIHlsYWIgPSAiQW54aWV0eSIpDQpgYGANCg0KSW4gdGhlIGNvZGUgYmxvY2sgYWJvdmUuIHRoZSAqKnR5cGUqKiBwYXJhbWV0ZXIgc3BlY2lmaWVzIHRoZSB0eXBlIG9mIHBsb3R0aW5nIHdlJ3JlIGFza2luZyBSU3R1ZGlvIHRvIGRvLCBhbmQgd2UncmUgYXNraW5nIGZvciBib3RoIHBvaW50cyAoInAiKSBhbmQgdGhlIHJlZ3Jlc3Npb24gbGluZSAoInIiKS4gQSB2ZWN0b3IgaXMgY3JlYXRlZCAoKipjKiogaXMgUidzICoqY29uY2F0ZW5hdGUqKiBmdW5jdGlvbikgd2l0aCB0d28gY29tcG9uZW50cywgb25lIGZvciBwb2ludHMgYW5kIG9uZSBmb3IgdGhlIHJlZ3Jlc3Npb24gbGluZS4gSWYgd2UgYXNrIG9ubHkgZm9yIHR5cGUgInAiLCB3ZSBnZXQgYSBzdGFuZGFyZCBzY2F0dGVyIHBsb3Qgd2l0aCBubyBsaW5lIG9mIGJlc3QgZml0IHN1cGVyaW1wb3NlZC4NCg0KVGhlIHBhdHRlcm4gaW4gdGhlIHNjYXR0ZXIgcGxvdCBwcm92aWRlcyBldmlkZW5jZSBvZiBhIGxpbmVhciBwYXR0ZXJuIGJldHdlZW4gdGhlIHZhcmlhYmxlcyAqKk9wdCoqIGFuZCAqKkFueCoqLiBBcyB0aGUgKipPcHRpbWlzbSoqIHNjb3JlIGluY3JlYXNlcywgZ2VuZXJhbGx5IHRoZSAqKkFueGlldHkqKiBzY29yZXMgZGVjcmVhc2UuDQoNCiMjIyAyLiBDcmVhdGluZyBhIE1vZGVsDQoNCkZvciBvdXIgZXhhbXBsZSwgbGV0J3MgY3JlYXRlIGEgbGluZWFyIG1vZGVsIGZvciAqKkFueGlldHkgdnMuIE9wdGltaXNtKiouDQoNCmBgYHtyfQ0KbG0oQW54IH4gT3B0LCBkYXRhID0gRGF0YTMzNTApDQpgYGANCg0KV2Ugb25seSBzZWUgdGhlIG91dHB1dCBmb3IgdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgbGluZSBvZiBiZXN0IGZpdDogdGhlICR5JC1pbnRlcmNlcHQgYW5kIHRoZSBzbG9wZS4gWWV0LCBsb3RzIG9mIGluZm9ybWF0aW9uIGZyb20gdGhlIG1vZGVsIGhhcyBiZWVuIGdlbmVyYXRlZCBieSBSU3R1ZGlvIGFuZCBpcyBsdXJraW5nIGluIHRoZSBiYWNrZ3JvdW5kLiBMZXQncyBjcmVhdGUgYW4gb2JqZWN0IChvciB2YXJpYWJsZSkgY2FsbGVkICoqbW9kKiogYW5kIGFzayBSU3R1ZGlvIHRvIHN0b3JlIHRoZSByZXN1bHRzIHRoZXJlLiBUaGVuIHdlIGNhbiBhY2Nlc3MgYWRkaXRpb25hbCBtb2RlbCBpbmZvcm1hdGlvbiB3aGVuZXZlciB3ZSBsaWtlLiANCg0KYGBge3J9DQptb2QgPSBsbShBbnggfiBPcHQsIGRhdGEgPSBEYXRhMzM1MCkNCmBgYA0KDQpMZXQncyByZXF1ZXN0IGEgbW9kZWwgc3VtbWFyeS4NCg0KYGBge3J9DQpzdW1tYXJ5KG1vZCkNCmBgYA0KDQpXZSB3aWxsIHByb3ZpZGUgbW9yZSBkZXRhaWxzIGFib3V0IHRoZSBvdXRwdXQgbGF0ZXIuIEZvciBub3csIGp1c3QgcmVhbGl6ZSB0aGF0IHRoZSBmdW5jdGlvbiAqKmxtKiogY3JlYXRlcyBhbiBvYmplY3Qgb2YgY2xhc3MgImxpbmVhciBtb2RlbC4iIFRoYXQgb2JqZWN0IGhhcyBtYW55IGRpZmZlcmVudCBvdXRwdXRzIGluY2x1ZGluZyBkZXRhaWxzIGFib3V0IHRoZSBsaW5lIG9mIGJlc3QgZml0LCB0aGUgcmVzaWR1YWxzIChhcyBjYW4gYmUgc2VlbiBpbiB0aGUgZml2ZSBudW1iZXIgc3VtbWFyeSkgYW5kIG11Y2gsIG11Y2ggbW9yZS4gVGhhdCdzIHdoeSB3ZSBzYXZlZCBpdCBhcyAqKm1vZCoqLCBzaG9ydCBmb3IgIm1vZGVsLiIgV2UgcGxhbiB0byBjYWxsIGl0IGxhdGVyIGZvciBkaWFnbm9zdGljIGFuZCBhbmFseXRpYyB0YXNrcy4NCg0KIyMjIDMuIFZlcmlmeWluZyBOb3JtYWxpdHkgQXNzdW1wdGlvbg0KDQpMZXQncyBjb25zaWRlciB3aGF0IHdlJ3ZlIGxlYXJuZWQuIFdlIGNoZWNrZWQgdGhlIGxpbmVhcml0eSBhc3N1bXB0aW9uIGJ5IGluc3BlY3RpbmcgYSBzY2F0dGVyIHBsb3Qgd2hpY2ggc2hvd2VkIGEgY2xvdWQgb2YgcGFpcmVkIGRhdGEgcG9pbnRzIHdpdGggYSBkb3dud2FyZCBzbG9waW5nIHRyZW5kIChuZWdhdGl2ZSBjb3JyZWxhdGlvbikuIFdlIG5leHQgY3JlYXRlZCBhIGxpbmVhciBtb2RlbCBhbmQgc2F2ZWQgaXQgYXMgdGhlIFJTdHVkaW8gb2JqZWN0ICoqbW9kKiouIE5vdywgd2Ugd2lzaCB0byBldmFsdWF0ZSB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gd2hpY2ggc2F5cyB0aGF0IHRoZSByZXNpZHVhbHMgc2hvdWxkIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBJbiBwcmV2aW91cyBzZWN0aW9ucywgd2UgdXNlZCBoaXN0b2dyYW1zIHRvIGludmVzdGlnYXRlIHRoZSBzaGFwZSBvZiB0aGUgZGF0YS4NCg0KUlN0dWRpbyBjYW4gcGxvdCBhIGhpc3RvZ3JhbSBvZiB0aGUgcmVzaWR1YWxzLCB0b28sIGJ1dCBtb3JlIHR5cGljYWxseSB3ZSdsbCB1c2UgdGhlICpxcS1wbG90KiBpbnN0ZWFkLiBIZXJlJ3MgdGhlIGhpc3RvZ3JhbS4NCg0KYGBge3J9DQpoaXN0b2dyYW0gKH4gcmVzaWQgKG1vZCkpDQpgYGANCg0KV2UgY2FuIGFuYWx5emUgdGhlIHJlc2lkdWFscyBoaXN0b2dyYW0gbGlrZSBhbnkgb3RoZXI6IHRoZXJlIGlzIGV2aWRlbmNlIHRoZSBkYXRhIHdlcmUgZHJhd24gZnJvbSBhIGJlbGwtc2hhcGVkIGRpc3RyaWJ1dGlvbiB3aXRoIHNrZXcgdG8gdGhlIHJpZ2h0LiBUaGUgKipxcS1wbG90KiogZG9lcyBoYXZlIGFkdmFudGFnZXMuIExldCdzIGNyZWF0ZSBhIHFxLXBsb3QgYW5kIHRoZW4gZGlzY3VzcyB3aGF0IHdlJ3JlIHNlZWluZy4NCg0KYGBge3J9DQpxcW1hdGgoIH4gcmVzaWQobW9kKSkNCmBgYA0KDQpUaGUgKnFxKiBpbiBxcS1wbG90IHJlZmVycyB0byBxdWFudGlsZXMsIGFuZCBxdWFudGlsZSBpcyBqdXN0IGFub3RoZXIgd29yZCBmb3IgcGVyY2VudGlsZS4gQSBxcS1wbG90IGNvbXBhcmVzIHRoZSBwZXJjZW50aWxlcyBvZiBvbmUgZGlzdHJpYnV0aW9uIHRvIHRoZSBwZXJjZW50aWxlcyBvZiBhbm90aGVyLiBJZiB0aGUgZGlzdHJpYnV0aW9ucyBoYXZlIHRoZSBzYW1lIHNoYXBlLCB0aGUgcXEtcGxvdCB3aWxsIGJlIGEgc3RyYWlnaHQgbGluZS4gT3VyIGZ1bmN0aW9uICoqcXFtYXRoKiogaXMgYSAqKm5vcm1hbCoqIHFxLXBsb3Qgd2hpY2ggY29tcGFyZXMgdGhlIHJlc2lkdWFscyBpbiAqKm1vZCoqIHRvIHRoZSBiZWxsIGN1cnZlLiA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPklmIHRoZSByZXNpZHVhbHMgbWVldCB0aGUgbW9kZWwgYXNzdW1wdGlvbnMsIHdlIHNob3VsZCBzZWUgYSBzdHJhaWdodCBsaW5lLjwvc3Bhbj4NCg0KPGRpdiBzdHlsZT0iZmxvYXQ6cmlnaHQ7IG1hcmdpbjogOHB4OyBib3JkZXI6MnB4IGJsYWNrIHNvbGlkOyBwYWRkaW5nOiAxMHB4IDE1cHggMTBweCI+DQojIyMjIFFRLVBsb3RzDQpGb3IgZGV0YWlscyBhYm91dCB3aGF0IHdlJ3JlPC9icj4NCmhvcGluZyAqbm90KiB0byBmaW5kIGluIGEgcXEtcGxvdCw8L2JyPiBzZWUgdGhlIDxhIGhyZWYgPSBodHRwczovL3JwdWJzLmNvbS9yb2Jic2lubi9zMTE+UVEgUGxvdHMgbW9kdWxlIFMxMTwvYT4uDQo8L2Rpdj4NCg0KV2l0aCByZWFsIHdvcmxkIGRhdGEsIHdlIHJhcmVseSBzZWUgYSBwZXJmZWN0bHkgc3RyYWlnaHQgbGluZS4gV2hhdCB3ZSBob3BlIHRvIGF2b2lkIGlzIHNlZWluZyBzb21ldGhpbmcgUy1zaGFwZWQgb3IgQy1zaGFwZWQgd2hlcmUgdGhlIGxhc3QgZmV3IHBvaW50cyBvbiB0aGUgY2hhcnQgYXQgZWl0aGVyIGVuZCBqdW1wIGZhciBvdXQgb2YgbGluZS4gDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcmVkOyI+UXVpY2sgRXhhbXBsZTogJFx0ZXh0e1NFfVxzaW1cdGV4dHtPcHR9JDwvc3Bhbj4NCg0KVXNpbmcgdGhlIERhdGEzMzUwIGRhdGEgZnJhbWUsIHdlIGNhbiB1c2UgYSBxcS1wbG90IHRvIGFuYWx5emUgdGhlIGZpdCBvZiB0aGUgbGluZWFyIG1vZGVsIGZvciBzZWxmLWVzdGVlbSAoU0UpIHdpdGggb3B0aW1pc20gKE9wdCkuDQoNCmBgYHtyfQ0KbW9kMSA9IGxtKFNFIH4gT3B0LCBkYXRhID0gRGF0YTMzNTApDQpxcW1hdGgoIH4gcmVzaWQobW9kMSksIHR5cGUgPSBjKCJwIiwiciIpKQ0KYGBgDQoNClRoZSBzaGFycCBkcm9wLW9mZiBhdCB0aGUgYm90dG9tLWxlZnQgaW5kaWNhdGVzIHRoYXQgdGhlcmUgaXMgYSBtb3JlIGV4dHJlbWUgdmFsdWUgaW4gdGhlIHJlc2lkdWFscyB0aGFuIHdlIHdvdWxkIGV4cGVjdCBpZiB0aGUgcmVzaWR1YWxzIHdlcmUgbm9ybWFsbHkNCmRpc3RyaWJ1dGVkLiBUaGUgdG9wIHR3byBwb2ludHMgYXJlIGFsc28gZnVydGhlciBmcm9tIHRoZSA0NS1kZWdyZWUgbGluZSB0aGFuIHdlIHdvdWxkIHByZWZlci4NCg0KPGRpdiBzdHlsZT0iZmxvYXQ6cmlnaHQ7IG1hcmdpbjogOHB4OyBib3JkZXI6MnB4IGJsYWNrIHNvbGlkOyBwYWRkaW5nOiAxMHB4IDE1cHggMTBweCI+DQojIyMgQW5hbHl6aW5nIFFRLVBsb3RzDQpUaGUgVW5pdmVyc2l0eSBvZiBWaXJnaW5pYSBoYXMgYSBuaWNlIGFydGljbGUgYWJvdXQgPGEgaHJlZiA9IGh0dHBzOi8vZGF0YS5saWJyYXJ5LnZpcmdpbmlhLmVkdS91bmRlcnN0YW5kaW5nLXEtcS1wbG90cy8+dW5kZXJzdGFuZGluZyBxcS1wbG90czwvYT4gd2hpY2ggZ29lcyBpbnRvIG1vcmUgZGV0YWlsLiBKdXN0IGJld2FyZSB0aGV5IHVzZSBzbGlnaHRseSBkaWZmZXJlbnQgUiBjb21tYW5kcyB0byBhY2hpZXZlIHdoYXQgd2UncmUgZG9pbmcuIChSZW1lbWJlciwgd2UgYWx3YXlzIGxvYWQgdGhlIE1vc2FpYyBwYWNrYWdlIGFuZCB1c2UgaXQncyBzaW1wbGlmaWVkIGNvbW1hbmRzLiBUaGUgVVZBIGFydGljbGUgZG9lc24ndCB1c2UgTW9zYWljLikgSSBoYXZlIGxpbmtlZCB0byBhbiBpbWFnZSBmcm9tIHRoZSBVVkEgYXJ0aWNsZSB0aGF0IHNob3dzIGFuIDxhIGhyZWYgPSBodHRwczovL2RhdGEubGlicmFyeS52aXJnaW5pYS5lZHUvZmlsZXMvaGVhdnlfdGFpbHMuanBlZz5leGFtcGxlIG9mIGEgcXFwbG90IHNob3dpbmcgYSBwYXR0ZXJuIHdlIGRlZmluaXRlbHkgZG9uJ3Qgd2FudCB0byBzZWU8L2E+LiBZb3Ugc2hvdWxkIGRlZmluaXRlbHkgY2xpY2sgdGhlIGxpbmsgdG8gdW5kZXJzdGFuZCB0aGUgcHJvYmxlbWF0aWMgc2hhcGUgd2UncmUgaG9waW5nIHRvIGF2b2lkLg0KPC9kaXY+DQoNCkJhY2sgdG8gb3VyIG9yaWdpbmFsIHFxLXBsb3Q6IGV2ZXJ5dGhpbmcgc2VlbXMgZmluZS4gV2hpbGUgdGhlIHRhaWxzIG9mIHRoZSBxcS1wbG90IHdpZ2dsZSBhIGJpdCwgbm9uZSBvZiB0aGUgcGxvdHRlZCBjb21wYXJpc29ucyBqdW1wIG9mZiB0aGUgbGluZSB2ZXJ5IGZhci4gT3VyIGRhdGEgYXBwZWFyIHRvIG1lZXQgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9ucy4NCg0KIyMjIDQuIEFuYWx5c2lzIFN0YXRlbWVudHMgZm9yIExpbmVhciBSZWdyZXNzaW9uDQoNClRoZXJlIGFyZSB0aHJlZSBhbmFseXNpcyBzdGF0ZW1lbnRzIGZvciByZWdyZXNzaW9uIG1vZGVscywgdHdvIHRoYXQgZGVzY3JpYmUgdGhlIHN0cmVuZ3RoIG9mIHRoZSByZWxhdGlvbnNoaXAsIGFuZCBvbmUgdGhhdCBkZXNjcmliZXMgaG93IHRoZSByZWxhdGlvbnNoaXAgd29ya3MuIExldCdzIGxvb2sgYXQgdGhlIG1vZGVsIHN1bW1hcnkgYWdhaW46DQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2QpDQpgYGANCg0KSW4gdGhlIHNlY29uZCByb3cgZnJvbSB0aGUgYm90dG9tIG9mIHRoZSBvdXRwdXQsIGNvbnNpZGVyICJNdWx0aXBsZSBSLXNxdWFyZWQ6IDAuMjk2OC4iIFdlIG9ubHkgaGF2ZSBvbmUgcHJlZGljdG9yIGluIG91ciBtb2RlbCwgc28gdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50ICRyJCBpcyB0aGUgc3F1YXJlIHJvb3Qgb2YgdGhlIFItc3F1YXJlZCB2YWx1ZToNCiQkciA9IFxzcXJ0ezAuMjk2OH1cYXBwcm94IC41NDQ4JCQNCg0KIyMjIyA0LmEpIEFuYWx5emluZyB0aGUgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQgJHIkDQpUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgJHIkIGluZGljYXRlcyB0aGUgc3RyZW5ndGggYW5kIGRpcmVjdGlvbiBvZiB0aGUgYml2YXJpYXRlIGFzc29jaWF0aW9uLiBUaGUgY2hhcnQgYmVsb3cgcmVsYXRlcyB0byBxdWFudGl0YXRpdmUgcmVzZWFyY2ggaW52b2x2aW5nIGh1bWFuIHN1YmplY3RzIGluIHNvY2lhbCBzY2llbmNlcyBzdWNoIGFzIHBzeWNob2xvZ3ksIGVjb25vbWljcywgYW5kIGVkdWNhdGlvbmFsIHBzeWNob2xvZ3kuIFJlZ3Jlc3Npb24gbWV0aG9kcyBhcmUgd2lkZWx5IHVzZWQgYWNyb3NzIG1hbnkgZGlzcGFyYXRlIGJyYW5jaGVzIG9mIHJlc2VhcmNoLiBObyBzaW5nbGUgY2hhcnQgbGlrZSB0aGUgb25lIGJlbG93IGNvdWxkIGV2ZXIgYmUgZ2VuZXJhbCBlbm91Z2ggZm9yIGV2ZXJ5IHNpdHVhdGlvbi4gQSBjaGVtaXN0cnkgcHJvZmVzc29yIG1pZ2h0IGhhdmUgc3R1ZGVudHMgY2hlY2sgdGhlIGNvcnJlbGF0aW9uIG9mIG1lYXN1cmVkIG91dHB1dHMgZnJvbSBhIEJveWxlJ3MgTGF3IGxhYiBhbmQgZGVjaWRlIHRoYXQgYW55ICRyPDAuOTgkIGlzIHRvbyB3ZWFrLCB0aGF0IHRoZXJlIG11c3QgaGF2ZSBiZWVuIGEgbWVhc3VyZW1lbnQgZXJyb3IuDQoNCiQkXGJlZ2lue2FycmF5fXtsbH0NClx0ZXh0YmZ7Q29ycmVsYXRpb259JiZcdGV4dGJme1N0cmVuZ3RofVxcIFxobGluZQ0KXGhzcGFjZXsxY219fHJ8PC4yNSYmXHRleHR7TGl0dGxlIG9yIE5vbmV9XFwNCi4yNVxsZXF8cnw8LjUwJiZcdGV4dHtXZWFrfVxcDQouNTBcbGVxfHJ8PC43NSYmXHRleHR7TW9kZXJhdGV9XFwNCi43NVxsZXF8cnwmJlx0ZXh0e1N0cm9uZ30NClxlbmR7YXJyYXl9JCQNCg0KVGhlIGFuYWx5c2lzIHN0YXRlbWVudCBmb3IgdGhlIGNvcnJlbGF0aW9uIG11c3QgaWRlbnRpZnkgdGhlIHN0cmVuZ3RoIGFuZCBkaXJlY3Rpb24gb2YgdGhlIHJlbGF0aW9uc2hpcC4gRm9yIHRoaXMgZXhhbXBsZSwgd2UgZmluZCBhIG1vZGVyYXRlLCBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIE9wdGltaXNtIGFuZCBBbnhpZXR5Lg0KDQojIyMjIDQuYikgQW5hbHl6aW5nIHRoZSBDb2VmZmljaWVudCBvZiBEZXRlcm1pbmF0aW9uICRSXjIkDQpUaGUgb3V0cHV0ICJNdWx0aXBsZSBSLXNxdWFyZWQ6IDAuMjk2OCIgaW5kaWNhdGVzIHRoZSBjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uLiBCZWNhdXNlICRSXjI9MC4yOTY4JCwgd2Uga25vdyB0aGF0IDI5LjclIG9mIHRoZSBjaGFuZ2VzIGluIEFueGlldHkgc2NvcmVzICh0aGUgZGVwZW5kZW50IHZhcmlhYmxlKSBpcyBhY2NvdW50ZWQgZm9yIGJ5IGhvdyB0aGUgT3B0aW1pc20gc2NvcmVzICh0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUpIGFyZSBjaGFuZ2luZy4gDQoNCldoeSBkbyB3ZSB3cml0ZSAkUl4yJCB3aGVuIGl0J3MgdGhlIHNxdWFyZSBvZiB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgd2hpY2ggaXMgYWx3YXlzIHdyaXR0ZW4gaW4gbG93ZXIgY2FzZT8gSXQncyBpbXBvcnRhbnQgdG8gdW5kZXJzdGFuZCB0aGUgbXVsdGl2YXJpYXRlIGNvbnRleHQuIFRoZSBjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uICRSXjIkIGlzIHByaW1hcmlseSB1c2VkIGluIG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWxzIHRvIGluZGljYXRlIHRoZSB0b3RhbCB2YXJpYW5jZSBhY2NvdW50ZWQgZm9yIGJ5IHRoZSBtb2RlbCwgbm90IGp1c3Qgb25lIHByZWRpY3Rvci4gQ29ycmVsYXRpb25zLCBvbiB0aGUgb3RoZXIgaGFuZCwgb25seSBhcHBseSB0byBiaXZhcmlhdGUgc2NlbmFyaW9zLiBUaGlzIGNvbmNlcHQgd2lsbCBvbmNlIG1vcmUgbWFrZSBiZXR0ZXIgc2Vuc2UgaW4gdGhlIG11bHRpcGxlIHByZWRpY3RvciBzZXR0aW5nIG9mIHRoZSBmb2xsb3ctb24gYW5hbHlzaXMuDQoNCkZvciB0aGlzIGV4YW1wbGUsIHdlIGZpbmQgdGhhdCAzMCUgb2YgdGhlIHZhcmlhbmNlIGluIEFueGlldHkgaXMgYWNjb3VudGVkIGZvciBieSBPcHRpbWlzbS4gTm90ZSB0aGF0ICRSXjIkIHJlZmVycyB0byB0aGUgdG90YWwgdmFyaWFuY2UgYWNjb3VudGVkIGZvciBieSB0aGUgbW9kZWwsIHNvIHdlIHdpbGwgc2VlIHRoaXMgc3RhdGlzdGljIGFnYWluIGluIHRoZSBuZXh0IHNlY3Rpb24gd2hlbiB3ZSB1c2UgbXVsdGlwbGUgcHJlZGljdG9ycy4NCg0KIyMgRXhhbXBsZSAyOiBVLlMuIE1lZGlhbiBXYWdlIEdyb3d0aA0KDQpDb25zaWRlciB0aGUgc2NhdHRlciBwbG90IGJlbG93IHNob3dpbmcgbWVkaWFuIFUuUy4gd2FnZXMgc2luY2UgMTk4MC4gQWxsIHdhZ2UgdmFsdWVzIGFyZSByZXByZXNlbnRlZCBpbiBjdXJyZW50IFVTRCAoZS5nLiBjb3JyZWN0ZWQgZm9yIGluZmxhdGlvbiBieSB0aGUgQkxTKS4gQWxsIGRhdGEgZm9yIHRoaXMgbW9kdWxlIHdlcmUgZG93bmxvYWRlZCBpbiBTZXB0ZW1iZXIsIDIwMDIsIGZyb20gdGhlIDxhIGhyZWYgPSBodHRwczovL3d3dy5ibHMuZ292Lz5CdXJlYXUgb2YgTGFib3IgU3RhdGlzdGljczwvYT4gdXNpbmcgZWl0aGVyIDxhIGhyZWYgPSBodHRwczovL3d3dy5ibHMuZ292L3dlYmFwcHMvbGVnYWN5L2Nwc3drdGFiMi5odG0+VGFibGUgMjwvYT4gb3IgPGEgaHJlZiA9IGh0dHBzOi8vd3d3LmJscy5nb3Yvd2ViYXBwcy9sZWdhY3kvY3Bzd2t0YWI1Lmh0bT5UYWJsZSA1PC9hPi4gVGhlIGRhdGEgY2hhcnRzIHByb2R1Y2VkIGJ5IHRoZSBCTFMgYXJlIG5vdCBkYXRhIGZyYW1lcywgc28gdGhlIHdhZ2UgZGF0YSB3YXMgY29lcmNlZCBpbnRvIHNpbmdsZS1jb2x1bW4gZm9ybWF0IHdpdGggY29sdW1uIGhlYWRlcnMgYW5kIG90aGVyIGZvcm1hdHRpbmcgYWRkZWQgc28gdGhhdCBpdCB3b3VsZCB3b3JrIHdlbGwgaW4gUi4gUGVyaW9kIDAgaXMgdGhlIDFzdCBRdWFydGVyIG9mIDE5ODAsIHRoZSBmaXJzdCBxdWFydGVyIG9mIFJvbmFsZCBSZWFnYW4ncyBmaXJzdCB0ZXJtLg0KDQohW1UuUy4gTWVkaWFuIFdhZ2UgR3Jvd3RoXShpbWFnZXNcTWVkV2FnZXMuUE5HKQ0KDQpXZSBjYW4gY3JlYXRlIHNjYXR0ZXIgcGxvdHMgaW4gTWljcm9zb2Z0IEV4Y2VsIGJ5IHNlbGVjdGluZyB0aGUgdHdvIGNvbHVtbnMgb2YgZGF0YSBhbmQgY2xpY2tpbmcgb24gIkNoYXJ0czogU2NhdHRlciIgZnJvbSB0aGUgSW5zZXJ0IG1lbnUuIEJ5IHJpZ2h0LWNsaWNraW5nIG9uIGEgZGF0YSBwb2ludCwgd2UgY2FuICJBZGQgVHJlbmRsaW5lIiBhbmQgc2VsZWN0IG9wdGlvbnMgdG8gaW5jbHVkZSBlcXVhdGlvbiBhbmQgJFJeMiQgb24gdGhlIGNoYXJ0Lg0KDQpUaGUgZXF1YXRpb24gZGlzcGxheWVkIGlzIHRoZSBsaW5lIG9mIGJlc3QgZml0ICQkIHkgPSA0LjA5eCArIDI2MC41NyQkIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGVzdGltYXRlIHRoZSBtZWRpYW4gd2FnZSBmb3IgYW55IHRpbWUgcGVyaW9kIHNpbmNlIDE5ODEgUTEuIEhpc3RvcmljYWxseSwgdGhlIG1lZGlhbiB3ZWVrbHkgd2FnZSBoYXMgaW5jcmVhc2VkIGJ5ICRcJDQuMDkkIGVhY2ggcXVhcnRlciAob3IgXCQxNi4zNiBlYWNoIHllYXIpLiBUaGUgY29lZmZpY2llbnQgb2YgZGV0ZXJtaW5hdGlvbiAkUl4yPS45OTMkIHNob3dzIHRoYXQgJDk5LjNcJSQgb2YgdGhlIHZhcmlhbmNlIGluIG1lZGlhbiB3YWdlcyBpcyBhY2NvdW50ZWQgZm9yIGJ5IHRoZSB0aW1lIHBlcmlvZC4NCg0KVGhlIHBhdHRlcm4gaXMgY2xlYXJseSBsaW5lYXIgd2l0aCBhbiBvZGQgdXB0aWNrIGluIHRoZSBmaW5hbCAxLTIgcGVyaW9kcyB3aGljaCByZXByZXNlbnQgdGhlIGZpcnN0IHR3byBxdWFydGVycyBvZiAyMDIwLiBXaGF0J3MgZ29pbmcgb24/IFdoeSB3b3VsZCBtZWRpYW4gaW5jb21lIHN1cmdlIG1hc3NpdmVseSBkdXJpbmcgdGhlIENPVklEIGxvY2tkb3duPw0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPklWLiBPdXRsaWVycyBBZmZlY3QgQ29ycmVsYXRpb24gYW5kIFByZWRpY3Rpb25zIEJhc2VkIG9uIFJlZ3Jlc3Npb24gTW9kZWxzLjwvc3Bhbj4NCg0KVGhlIHR3byBvdXRsaWVycyBhdCB0aGUgZmFyIHJpZ2h0IGNvcnJlc3BvbmQgdG8gdGhlIGZpcnN0IHR3byBxdWFydGVycyBvZiAyMDIwIHdoZW4gdGhlIHBhbmRlbWljIHN0YXJ0ZWQuIFRoaW5rIGFib3V0IHdoaWNoIFUuUy4gd29ya2VycyBsb3N0IHRoZWlyIGpvYnMgZHVlIHRvIHRoZSBDT1ZJRCBsb2NrZG93bnMuIE1vc3Qgb2YgdGhlbSB3ZXJlIG1lbWJlcnMgb2YgdGhlIHdvcmtpbmcgcG9vciB3aG8gbWFrZSBtdWNoIGxlc3MgdGhhbiB0aGUgbWVkaWFuIGluY29tZTogZm9sa3MgbGlrZSB3YWl0cmVzc2VzLCBub24tZXNzZW50aWFsIHJldGFpbCB3b3JrZXJzLCBhbmQgbW92aWUgdGhlYXRlciBhdHRlbmRhbnRzLiBUaGUgdG90YWwgbnVtYmVyIG9mIHdvcmtlcnMgZGVjcmVhc2VkLiANCg0KVGhpbmsgYWJvdXQgdGFraW5nIGEgZGF0YSBzZXQgb2Ygc2FtcGxlIHNpemUgMjAuIFRoZSBtZWRpYW4gd2FnZSB3b3VsZCBiZSB0aGUgYXZlcmFnZSBvZiB0aGUgMTB0aCBhbmQgMTF0aCBpbmRpdmlkdWFscyB3aGVuIHRoZSBzYW1wbGUgaXMgb3JkZXJlZCBmcm9tIGxlYXN0IHRvIGdyZWF0ZXN0IHdhZ2UuIFN1cHBvc2UgdGhlIGZpdmUgaW5kaXZpZHVhbHMgd2l0aCB0aGUgbG93ZXN0IHdhZ2VzIHdlcmUgcmVtb3ZlZCwgdGhlIGVudGlyZSBib3R0b20gcXVhcnRlciBvZiB0aGUgZGF0YSBzZXQuIFRoZSBtZWRpYW4gb2YgdGhlIG5ldyAxNS1wZXJzb24gZGF0YSBzZXQgd291bGQgYmUgdGhlIDh0aCBwZXJzb24gd2hlbiBvcmRlcmVkIGZyb20gbGVhc3QgdG8gZ3JlYXRlc3QsIGJ1dCBpbiByZWFsaXR5IHRoaXMgaXMgdGhlIHRoZSAxM3RoIHBlcnNvbiBmcm9tIHRoZSBvcmlnaW5hbCBkYXRhIHNldC4gVGhlIG1lZGlhbiBzaGlmdHMgdXB3YXJkIGV2ZW4gdGhvdWdoIDI1JSBvZiB0aGlzIHNhbXBsZSBsb3N0IHRoZWlyIGpvYnMuDQoNClRvIGRpc3BsYXkgdGhlIGNoYXJ0IGJlbG93LCB3ZSBtdXN0IGZpcnN0IGltcG9ydCB0aGUgZmlsZSAqTWVkLnhsc3gqIGludG8gUlN0dWRpbyAoRmlsZSBtZW51OiAiSW1wb3J0IERhdGFzZXQiKS4gVGhlIG51bWJlciBvZiB3b3JrZXJzIGRlY3JlYXNlcyBzaGFycGx5IGF0IHRoZSBvbnNldCBvZiByZWNlc3Npb25zLCBhbmQgdGhlIGpvYiBsb3NzIHdhcyBwYXJ0aWN1bGFybHkgbmFzdHkgaW4gc2Vjb25kIHF1YXJ0ZXIgb2YgMjAyMC4gTm90ZSB0aGUgbGFyZ2UgZGlzY29udGludWl0eSBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSByZWNlc3Npb24gb2YgMjAwOC0yMDA5LiBUaGUgd29yayBmb3JjZSBjb250cmFjdGVkIGJ5IGFsbW9zdCA1IG1pbGxpb24gd2FnZSBlYXJuZXJzIGluIHRoZSAxc3QgcXVhcnRlciBvZiAyMDA5LiBUaGUgbGFzdCBkYXRhIHBvaW50IG9uIHRoZSByaWdodCBpcyB0aGUgc2Vjb25kIHF1YXJ0ZXIgb2YgMjAyMCB3aGVuIG1vcmUgdGhhbiAxMSBtaWxsaW9uIFUuUy4gd2FnZSBlYXJuZXJzIGxvc3QgdGhlaXIgam9icyBkdWUgdG8gdGhlIENPVklEIHNodXRkb3duLiBJbiB0aGUgcHJldmlvdXMgcXVhcnRlciwgbW9yZSB0aGFuIDIgbWlsbGlvbiBsb3N0IHRoZWlyIGpvYnMuDQoNCmBgYHtyfQ0KeHlwbG90KEVhcm5lcnMgfiBQZXJpb2QsIGRhdGEgPSBNZWQsIA0KICAgICAgIHhsYWIgPSAiUXVhcnRlcnMgc2luY2UgMTk4MSBRMSIsIA0KICAgICAgIHlsYWIgPSAiTnVtYmVyIG9mIFdhZ2UgRWFybmVycyAoaW4gdGhvdXNhbmRzKSIpDQpgYGANCg0KQXBwYXJlbnRseSwgZm9yIHRoZSBDT1ZJRCBsb2NrZG93biwgdGhlIHZhc3QgbWFqb3JpdHkgb2YgdGhvc2UgMTMgbWlsbGlvbiB3YWdlIGVhcm5lcnMgd2VyZSBhdCB0aGUgbG93ZXIgZW5kIG9mIHRoZSBlY29ub21pYyBzcGVjdHJ1bS4gSGFkIHRoZXkgYmVlbiBldmVubHkgZGlzdHJpYnV0ZWQgdGhyb3VnaG91dCB0aGUgZWNvbm9taWMgc3BlY3RydW0sIHRoZSBtZWRpYW4gd291bGQgbm90IGhhdmUganVtcGVkIHVwd2FyZC4gVGhlc2UgZGF0YSBzaG93IGVjb25vbWljIGRldmFzdGF0aW9uIHdhcyBpbW1lbnNlIGVzcGVjaWFsbHkgZm9yIHRob3NlIGVhcm5pbmcgYmVsb3cgbWVkaWFuIHdhZ2VzLiBUbyBjb3JyZWN0IGZvciB0aGVzZSBvYnZpb3VzIG91dGxpZXJzLCB3ZSB3aWxsIGNvbXBhcmUgb25seSB0aGUgcHJlLUNPVklEIHF1YXJ0ZXJzLiBJZiAqKk1lZC54bHN4KiogaGFzIGJlZW4gaW1wb3J0ZWQgaW50byBSU3R1ZGlvLCB0aGUgZm9sbG93aW5nIGNvZGUgd2lsbCBzdWJzZXQgaXQgdG8gb25seSBpbmNsdWRlIHF1YXJ0ZXJzIHRocm91Z2ggdGhlIGVuZCBvZiAyMDE5LiANCg0KYGBge3J9DQpuZXdNZWQgPSBzdWJzZXQoIE1lZCAsIFBlcmlvZCA8PSAxNTUgKQ0KYGBgDQoNCkxldCdzIHJlY3JlYXRlIHRoZSBtb2RlbCBpbiBSU3R1ZGlvIHdpdGhvdXQgdGhlIENPVklEIG91dGxpZXJzLiBXZSdyZSBub3QgaWdub3JpbmcgdGhlbSwgd2UncmUgaW5zdGVhZCB1bmRlcnN0YW5kaW5nIHRoYXQgdGhlIG91dGxpZXJzIGNyZWF0ZSBhIHZlcnkgcm9zeSBwaWN0dXJlIHdoZW4gc29tZXRoaW5nIGhvcnJpYmxlIGlzIGhhcHBlbmluZy4gSW4gUiwgd2UgdXNlIHRoZSAqKnh5cGxvdCoqIGZ1bmN0aW9uIHRvIGNyZWF0ZSBzY2F0dGVyIHBsb3RzLiBUaGUgInR5cGUiIGNvbW1hbmQgYXNrcyBSIHRvIHNob3cgYm90aCB0aGUgKnBvaW50cyogKCJwIikgYW5kICpyZWdyZXNzaW9uIGxpbmUqICgiciIpLg0KDQpgYGB7cn0NCnh5cGxvdCggTWVkaWFuIH4gUGVyaW9kLCBkYXRhID0gbmV3TWVkICwgDQogICAgICAgIHR5cGUgPSBjKCJwIiwiciIpICwNCiAgICAgICAgeGxhYiA9ICJRdWFydGVycyBzaW5jZSAxOTgxIFExIiAsIA0KICAgICAgICB5bGFiID0gIlUuUy4gTWVkaWFuIFdhZ2UiKQ0KYGBgDQoNClRoZSBSIGNvbW1hbmRzICRcZmJveHtsbX0kIGFuZCAkXGZib3h7Y29yfSQgZ2VuZXJhdGUgYSBsaW5lYXIgbW9kZWwgYW5kIHRoZSBjb3JyZWxhdGlvbiByZXNwZWN0aXZlbHkuDQoNCmBgYHtyfQ0KbG0oIE1lZGlhbiB+IFBlcmlvZCwgZGF0YSA9IG5ld01lZCkNCmNvcihNZWRpYW4gfiBQZXJpb2QsIGRhdGEgPSBNZWQpDQpjb3IoTWVkaWFuIH4gUGVyaW9kLCBkYXRhID0gbmV3TWVkKQ0KYGBgDQoNClRoZSBjb3JyZWxhdGlvbiBpbmNyZWFzZWQgYnkgMC4wMDExIGFuZCB0aGUgcmF0ZSBvZiB3YWdlIGdyb3d0aCBjaGFuZ2VkIGZyb20gJFwkNC4wOSQgdG8gJFwkNC4wNCQuIEEgbmlja2VsIG1heSBub3Qgc2VlbSBsaWtlIG11Y2guIEhvd2V2ZXIsIGNvbnNpZGVyIHRoZSByZWxhdGl2ZSBlcnJvciBvZiB0aGUgc2xvcGUgb2YgdGhlIHJlZ3Jlc3Npb24gbGluZSBlcXVhdGVzIHRvIG1vcmUgdGhhbiAkMVwlJCBwZXIgcXVhcnRlciBwcm9wYWdhdGVkIG92ZXIgMTUwLXBsdXMgcXVhcnRlcnMuDQoNCiMjIyBFeGFtcGxlIDI6IEFuYWx5c2lzIFN0YXRlbWVudHMNCg0KTGV0J3MgcmV0dXJuIHRvIHRoZSBtb2RpZmllZCBkYXRhIHNldCwgYnVpbGQgYW5kIHNhdmUgdGhlIG1vZGVsLCBhbmQgY29uZHVjdCBvdXIgYW5hbHlzaXMgd2l0aG91dCB0aGUgb3V0bGllcnMgcHJlc2VudC4NCg0KYGBge3J9DQptb2QgPSBsbSggTWVkaWFuIH4gUGVyaW9kLCBkYXRhID0gbmV3TWVkKQ0Kc3VtbWFyeShtb2QpDQpgYGANCg0KVGhlIGxpbmUgb2YgYmVzdCBmaXQgaXMgJCRcdGV4dHtNZWR9ID0gNC4wNVwgKlwgXHRleHR7UGVyaW9kfSArIDI1OS4xNiAkJA0KV2UgZmluZCB0aGF0ICRSXjIgPSAuOTk1JCB3aGljaCBtZWFucyB0aGF0ICRyID0gXHNxcnR7Ul4yfT0wLjk5NyQgKEJlZ2lubmluZyBhbmFseXN0cyBzaG91bGQgYWx3YXlzIHVzZSAiTXVsdGlwbGUgUi1zcXVhcmVkIiB2YWx1ZSwgbm90IGFkanVzdGVkLikgVGh1cywgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gbWVkaWFuIHdhZ2UgYW5kIHF1YXJ0ZXIgc2luY2UgMTk4MCBpcyB2ZXJ5IHN0cm9uZy4gJFJeMiQgaXMgdGhlIGNvZWZmaWNpZW50IG9mIGRldGVybWluYXRpb24gYW5kIGluZGljYXRlcyB0aGF0IHRoZSBQZXJpb2QgYWNjb3VudHMgZm9yICQ5OS41XCUkIG9mIHRoZSB2YXJpYW5jZSBpbiBtZWRpYW4gd2FnZXMuIExhc3RseSwgd2UgY2FuIHNlZSB0aGF0IHRoZSBzbG9wZSBvZiB0aGUgbGluZSBvZiBiZXN0IGlzICRcJDQuMDQkIHdoaWNoIG1lYW5zIHRoYXQgVS5TLiB3YWdlIGdyb3d0aCBvdmVyIHRoZSBwYXN0IDQwIHllYXJzIGhhcyBhdmVyYWdlZCBhYm91dCAkNC4wNCQgcGVyIHdlZWsgcGVyIHF1YXJ0ZXIgKGluIGN1cnJlbnQgVS5TLiBkb2xsYXJzKSwgb3IgYWJvdXQgJFwkMTYuMzIkIHBlciB3ZWVrIHBlciB5ZWFyLg0KDQojIyBFeGFtcGxlIDM6IE1lZGlhbiBXYWdlcyBkdXJpbmcgVHJ1bXAgQWRtaW5pc3RyYXRpb24NCg0KVHJ1bXAgY2FtcGFpZ25lZCBpbiAyMDE2IG9uIHRheCBjdXRzLCB0YXJpZmZzIG9uIGZvcmVpZ24gaW1wb3J0cywgZXhpdGluZyBnbG9iYWwgdHJhZGUgdHJlYXRpZXMgKFRQUCkgYW5kIHJlbmVnb3RpYXRpbmcgTkFGVEEuIFRydW1wIGNsYWltZWQgaGlzIGFwcHJvYWNoIHdvdWxkIGhlbHAgdGhlIHdhZ2UgZWFybmVycyBpbiB0aGUgY291bnRyeSBieSByZXZlcnNpbmcgdGhlIGdsb2JhbGl6YXRpb24gdGhhdCBzaGlwcGVkIG1pZGRsZSBjbGFzcyBqb2JzIG92ZXJzZWFzLiBUbyBzdWdnZXN0IHRoYXQgZXhwZXJ0cyBkaXNhZ3JlZWQgd291bGQgYmUgYSBtYXJrZWQgdW5kZXJzdGF0ZW1lbnQuIFRoZSBVLlMuIHBvbGl0aWNhbCBjbGltYXRlIGZvciB0aHJlZSBkZWNhZGVzIGhhcyBiZWVuIGluY3JlYXNpbmdseSBnbG9iYWxpc3QuIFRydW1wJ3MgZWNvbm9taWMgbmF0aW9uYWxpc20gd2FzIDxhIGhyZWYgPSBodHRwczovL3d3dy53YXNoaW5ndG9ucG9zdC5jb20vb3BpbmlvbnMvYS1wcmVzaWRlbnQtdHJ1bXAtY291bGQtZGVzdHJveS10aGUtd29ybGQtZWNvbm9teS8yMDE2LzEwLzA1L2Y3MDAxOWMwLTg0ZGYtMTFlNi05MmMyLTE0YjY0ZjNkNDUzZl9zdG9yeS5odG1sPnBpbGxvcmllZCBieSBwdW5kaXRzPC9hPiwgUmVwdWJsaWNhbiBwYXJ0eSBzdGFsd2FydHMgYW5kIGhpcyBwb2xpdGljYWwgb3Bwb25lbnRzIGFsaWtlLg0KDQpMZXQncyBpbnZlc3RpZ2F0ZSB3aGF0IHRyYW5zcGlyZWQgYXMgZGV0YWlsZWQgYnJlaWZseSBpbiB0aGUgWW91VHViZSB2aWRlbyBsZWN0dXJlLCBidXQgdGhpcyB0aW1lIHdvcmsgd2l0aCB0aGUgbXVjaCBtb3JlIGFkdmFuY2VkIHRvb2xzIGluIFJTdHVkaW8uIA0KDQojIyMgVXNpbmcgKnN1YnNldCogZnVuY3Rpb24gaW4gUiB0byBjcmVhdGUgZGF0YSBmcmFtZSBmb3IgVHJ1bXAgeWVhcnMgb25seQ0KDQpXZSBmaXJzdCBuZWVkIHRvIHN1YnNldCBvdXIgKk1lZCogZGF0YSBzZXQgZm9yIGp1c3QgdGhlIHllYXJzIDIwMTcgdGhyb3VnaCAyMTA5LCBvciAxMiBxdWFydGVycy4gVGhlc2Ugd2lsbCBiZSBQZXJpb2RzIDE0NCB0byAxNTUuDQoNCmBgYHtyfQ0KVHJ1bXBNZWQgPSBzdWJzZXQoIE1lZCAsIFBlcmlvZCA+PSAgMTQ0ICYgUGVyaW9kIDw9IDE1NSkNCmBgYA0KDQojIyMgU2NhdHRlciBQbG90OiBUcnVtcCBFcmEgTWVkaWFuIFdhZ2UNCg0KYGBge3J9DQp4eXBsb3QoTWVkaWFuIH4gUGVyaW9kLCBkYXRhID0gVHJ1bXBNZWQgLCANCiAgICAgICAgdHlwZSA9IGMoInAiLCJyIikgLA0KICAgICAgICB4bGFiID0gIkFsbCBRdWFydGVycyAyMDE3IHRvIDIwMTkiICwNCiAgICAgICAgeWxhYiA9ICJUcnVtcCBFcmEgTWVkaWFuIFdhZ2UiKSANCmBgYA0KDQojIyMgUmVncmVzc2lvbiBtb2RlbCBmb3IgVHJ1bXAgZXJhIG1lZGlhbiB3YWdlDQoNCldlIHVzZSB0aGUgKipsbSoqIGZ1bmN0aW9uIGluIFIgdG8gY3JlYXRlIHRoZSBsaW5lYXIgbW9kZWwsIGFuZCB3ZSBzdG9yZSB0aGUgcmVzdWx0cyBpbiB0aGUgdmFyaWFibGUgKm1vZFQqIChUcnVtcCBtb2RlbCkgc28gd2UgY2FuIGFjY2VzcyBpdCBsYXRlci4gVGhlIHN1bW1hcnkgc3RhdGlzdGljcyBtYXRjaCB0aGUgWW91VHViZSBsZWN0dXJlIHZpZGVvIHdoaWNoIHdlcmUgY3JlYXRlZCB1c2luZyB0aGUgVEkgZ3JhcGhpbmcgY2FsY3VsYXRvci4NCg0KYGBge3J9DQptb2RUID0gbG0oTWVkaWFuIH4gUGVyaW9kLCBkYXRhID0gVHJ1bXBNZWQpDQpzdW1tYXJ5KG1vZFQpDQpgYGANCg0KIyMjIFFRLVBsb3QgZm9yIFRydW1wIGVyYSBtZWRpYW4gd2FnZSBtb2RlbA0KDQpUaGVyZSBpcyBjZXJ0YWlubHkgc29tZSBkZXZpYXRpb24gaW4gdGhlIHFxLXBsb3QsIGJ1dCB0aGUgb3ZlcmFsbCBwYXR0ZXJuIGlzIHJvdWdobHkgYWxvbmcgdGhlIDQ1LWRlZ3JlZSBsaW5lLg0KDQpgYGB7cn0NCnFxbWF0aCggfiByZXNpZChtb2RUKSwgdHlwZSA9IGMoInAiLCJyIikpDQpgYGANCg0KIyMgRXhhbXBsZSAzYjogTWVkaWFuIFdhZ2VzIGR1cmluZyBPYmFtYSBBZG1pbmlzdHJhdGlvbg0KDQpXZSBjYW4gc3Vic2V0IHRoZSBkYXRhIGZyYW1lIGZvciB0aGUgd2hvbGUgT2JhbWEgZXJhIG9yIGp1c3QgdGhlIGxhc3QgdGhyZWUgeWVhcnMuDQoNCmBgYHtyfQ0KT2JhbWFNZWRUb3RhbCA9IHN1YnNldCggTWVkICwgUGVyaW9kID49IDExMiAmIFBlcmlvZCA8PSAxNDMgKQ0KT2JhbWFNZWRMMyA9IHN1YnNldCggTWVkICwgUGVyaW9kID49IDEzMiAmIFBlcmlvZCA8PSAxNDMgKQ0KYGBgDQoNCiMjIyBTY2F0dGVyIHBsb3RzIGZvciB3YWdlIGdyb3d0aCBkdXJpbmcgT2JhbWEgZXJhDQoNCmBgYHtyfQ0KeHlwbG90KE1lZGlhbiB+IFBlcmlvZCwgZGF0YSA9IE9iYW1hTWVkVG90YWwgLCANCiAgICAgICAgdHlwZSA9IGMoInAiLCJyIikgLA0KICAgICAgICB4bGFiID0gIkFsbCBRdWFydGVycyAyMDA5IHRvIDIwMTYiICwNCiAgICAgICAgeWxhYiA9ICJPYmFtYSBFcmEgTWVkaWFuIFdhZ2UiKSANCmBgYA0KDQpBIG1hcmtlZCBpbmNyZWFzZSBjYW4gYmUgc2VlbiBpbiB0aGUgZmluYWwgZmV3IHF1YXJ0ZXJzIGFib3ZlLiBMZXQncyBkaXNwbGF5IHRoZSBsYXN0IDMgeWVhcnMgb25seS4NCg0KYGBge3J9DQp4eXBsb3QoTWVkaWFuIH4gUGVyaW9kLCBkYXRhID0gT2JhbWFNZWRMMyAsIA0KICAgICAgICB0eXBlID0gYygicCIsInIiKSAsDQogICAgICAgIHhsYWIgPSAiQWxsIFF1YXJ0ZXJzIDIwMTQgdG8gMjAxNiIgLA0KICAgICAgICB5bGFiID0gIk9iYW1hIEVyYSBNZWRpYW4gV2FnZSIpIA0KYGBgDQoNCiMjIyBNb2RlbCBzdW1tYXJpZXMgZm9yIE9iYW1hIGVyYQ0KDQpgYGB7cn0NCm1vZEIgPSBsbShNZWRpYW4gfiBQZXJpb2QsIGRhdGEgPSBPYmFtYU1lZFRvdGFsKQ0KbW9kQkwzID0gbG0oTWVkaWFuIH4gUGVyaW9kLCBkYXRhID0gT2JhbWFNZWRMMykNCnN1bW1hcnkobW9kQikNCnN1bW1hcnkobW9kQkwzKQ0KYGBgDQpOb3RlIHRoYXQgdGhlIG1lZGlhbiB3YWdlIGdyb3d0aCBmb3IgdGhlIGVudGlyZSA4IHllYXJzIG9mIHRoZSBPYmFtYSBhZG1pbmlzdHJhdGlvbiBpcyBsb3dlciB0aGFuIHRoZSBoaXN0b3JpYyB0cmVuZCBvZiAkXCQ0LjA1JCwgYnV0IGluIHRoZSBmaW5hbCB0aHJlZSB5ZWFycyB3YXMgJFwkNS4wOCQgYXMgZGlzY3Vzc2VkIGluIHRoZSBZb3VUdWJlIGxlY3R1cmUgdmlkZW8uIA0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPlYuIFRlc3RpbmcgU2lnaWZpY2FuY2Ugb2YgU2xvcGU6IFJhbmRvbWl6ZWQgQ29uZmlkZW5jZSBJbnRlcnZhbHM8L3NwYW4+DQoNClRoZSBoeXBvdGhlc2lzIHdlIHdpc2ggdG8gdGVzdCBpcyBpZiB0aGUgc2xvcGUgb2YgdGhlIG1vZGVsIGZyb20gdGhlIFRydW1wIGVyYSBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCAoaGlnaGVyKSB0aGFuIHRoZSBoaXN0b3JpYyB0cmVuZC4NCg0KJCRIXzAgOiBcYmV0YSA9IDQuMDRcXEhfYSA6IFxiZXRhID4gNC4wNCQkDQoNCk9uZSByZWFzb24gd2Ugc2F2ZSB0aGUgbW9kZWxzIGlzIHRoYXQgaXQgbWFrZXMgZ3JhYmJpbmcgdGhlbSBsYXRlciBxdWl0ZSBlYXN5LiBMZXQncyBnZW5lcmF0ZSB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciB0aGUgc2xvcGUgb2YgdGhlIHJlZ3Jlc3Npb24gbGluZSBpbiBlYWNoIG1vZGVsLg0KDQojIyMgQ29uZmlkZW5jZSBpbnRlcnZhbDogVHJ1bXAgZXJhDQoNCmBgYHtyfQ0KY29uZmludC5sbShtb2RUKQ0KYGBgDQpCZWNhdXNlIHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCAkKDQuODQsNy41MikkIGRvZXMgbm90IGluY2x1ZGUgJFwkNC4wNCQsIHdlIHJlamVjdCB0aGUgbnVsbCBhbmQgaGF2ZSBldmlkZW5jZSBmb3IgYSBzaWduaWZpY2FudGx5IGhpZ2hlciBUcnVtcCBlcmEgbWVkaWFuIHdhZ2UgZ3Jvd3RoIGF0IHRoZSAkXGFscGhhID0gMC4wMjUkIGxldmVsLiBXaXRoIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCB3ZSBkb24ndCBoYXZlIHRoZSBsdXh1cnkgb2YgYSBvbmUtdGFpbGVkIGh5cG90aGVzaXMgZXZhbHVhdGlvbi4gV2hlbiB0ZXN0aW5nIGEgdHdvLXRhaWxlZCBoeXBvdGhlc2lzIHdpdGggYSBjb25maWRlbmNlIGludGVydmFsLCB0aGVuDQokJFxhbHBoYSA9IDEgLSBcdGV4dHtjb25maWRlbmNlIGxldmVsfSQkDQpGb3Igb25lLXRhaWxlZCB0ZXN0cywgd2UgaGF2ZSB0byBtYXRjaCB0aGUgYXJlYSBpbiB0aGUgdGFpbHMsIHNvDQoNCiQkXGFscGhhID0gXGZyYWN7MSAtIFx0ZXh0e2NvbmZpZGVuY2UgbGV2ZWx9fXsyfSQkDQoNClRvIHByb2R1Y2UgdGhlIGV4YWN0IGVxdWl2YWxlbnQgb2YgdGVzdGluZyBhdCB0aGUgJFxhbHBoYSA9IDAuMDUkIGxldmVsLCB3ZSB3b3VsZCB1c2UgdGhlIGZvbGxvd2luZyA5MCUgY29uZmlkZW5jZSBpbnRlcnZhbCBlc3RpbWF0ZS4NCg0KYGBge3J9DQpjb25maW50LmxtKG1vZFQsIGxldmVsID0gMC45MCkNCmBgYA0KDQpOb3cgd2UgaGF2ZSBleGFjdGx5IDUlIG9mIHRoZSBhcmVhIHVuZGVyIHRoZSBjdXJ2ZSB0byB0aGUgbGVmdCB3aGljaCBtYXRjaGVzIHRoZSByZWplY3Rpb24gcmVnaW9uIGZvciBhIG9uZS10YWlsZWQgJHQkLXRlc3QuDQoNCg0KIyMjIENvbmZpZGVuY2UgaW50ZXJ2YWxzOiBPYmFtYSBlcmENCg0KV2UgY2FuIHRlc3QgdGhlIGh5cG90aGVzaXMgdGhhdCB0aGUgT2JhbWEgZXJhIG1lZGlhbiB3YWdlIGdyb3d0aCB3YXMgZGlmZmVyZW50IHRoYXQgaGlzdG9yaWMgdmFsdWUgYXQgdGhlIDAuMDUgbGV2ZWwuDQokJEhfMCA6IFxiZXRhID0gNC4wNFxcSF9hIDogXGJldGEgXG5lcSA0LjA0JCQNCg0KYGBge3J9DQpjb25maW50LmxtKG1vZEIpDQpgYGANCg0KVGhlIGhpc3RvcmljIHRyZW5kIGZvciBtZWRpYW4gd2FnZSBncm93dGggb2YgJDQuMDQgaXMgbm90IGluY2x1ZGVkIGluIHRoZSBpbnRlcnZhbCB3aGljaCBzdWdnZXN0cyAoYmFzZWQgb24gdGhlIGVuZHBvaW50cyBvZiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBhYm92ZSkgdGhhdCB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBPYmFtYSBlcmEgbWVkaWFuIHdhZ2UgZ3Jvd3RoIGlzIFwkNC4wNS4gV2hlbiBhbGwgMzIgcXVhcnRlcnMgb2YgdGhlIE9iYW1hIGVyYSBhcmUgaW5jbHVkZWQsIGV2aWRlbmNlIHN1Z2dlc3RzIHRoYXQgdGhlIG92ZXJhbGwgZ3Jvd3RoIG9mIHRoZSBVLlMuIG1lZGlhbiB3YWdlIHdhcyBzaWduaWZpY2FudGx5IGxvd2VyIHRoYW4gdGhlIGhpc3RvcmljIHRyZW5kIChhdCB0aGUgMC4wMjUgbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlKS4NCg0KIyMjIENvbmZpZGVuY2UgaW50ZXJ2YWw6IExhc3QgMyB5ZWFycyBvZiBPYmFtYSBlcmENCg0KTm90ZSB0aGF0IGEgbW9kZWwgcmVzdHJpY3RlZCB0byB0aGUgZmluYWwgdGhyZWUgeWVhcnMgb2YgdGhlIE9iYW1hIGVyYSBkcmFtYXRpY2FsbHkgc2hpZnRzIHRoZSBhbmFseXNpcyBpbiBmYXZvciBvZiBPYmFtYS4gV2hpbGUgdGhlIGVmZmVjdCBpcyBjZXJ0YWlubHkgYSBjaGVycnktcGlja2luZyBvZiB0aGUgYmVzdCBPYmFtYSB5ZWFycywgd2Ugd2VyZSBhbmFseXppbmcgdGhlIGFyZ3VtZW50IHRoYXQgdGhlIFRydW1wIGVjb25vbXkgcm9kZSBvbiB0aGUgY29hdHRhaWxzIG9mIHRoZSBPYmFtYSBlY29ub215IGluIDIwMTYuIFRoZSBhcmd1bWVudCBpcyBwbGF1c2libGUgb24gaXRzIGZhY2UsIHNvIGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhLg0KDQpXZSdyZSB0ZXN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgbGFzdCB0aHJlZSB5ZWFycyBvZiB0aGUgT2JhbWEgZXJhIGdyb3d0aCBpbiBtZWRpYW4gd2FnZXMgaXMgc2ltaWxhciB0byB0aGUgVHJ1bXAgZXJhIGdyb3d0aCBvZiAkNi45MC4NCg0KJCRIXzAgOiBcYmV0YSA9IDYuMTlcXEhfYSA6IFxiZXRhIFxuZXEgNi4xOSQkDQoNCldlIG5lZWQgdGhlIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgbGFzdCB0aHJlZSB5ZWFycyBvZiBPYmFtYS4NCg0KYGBge3J9DQpjb25maW50LmxtKG1vZEJMMywgbGV2ZWwgPSAwLjk1KQ0KYGBgDQoNClRoZSB1cHBlciBlbmRwb2ludCBvZiB0aGUgY29uZmlkZW5jZSBpcyBjbG9zZSB0byBidXQgbm90IGdyZWF0ZXIgdGhhbiAkNi4xOS4gVGh1cywgd2UgcmVqZWN0IHRoZSBudWxsLiBXZSBoYXZlIGV2aWRlbmNlIHRoZSBtZWRpYW4gd2FnZSBncm93dGggd2FzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGluIHRoZSBwcmUtQ09WSUQgVHJ1bXAgZXJhIHRoYW4gZHVyaW5nIHRoZSBsYXN0IHRocmVlIHllYXJzIG9mIE9iYW1hLiBSZW1lbWJlciB0aGF0IHJlbW92aW5nIHRoZSBtZWRpYW4gd2FnZSBvdXRsaWVycyBmcm9tIHRoZSBDT1ZJRCByZWNlc3Npb24gYWN0dWFsbHkgbWFrZXMgVHJ1bXAncyBncm93dGggcmF0ZSBsb3dlci4NCg0KIyMgUVEtUGxvdHMgZm9yIE9iYW1hIGVyYSBtZWRpYW4gd2FnZSBncm93dGggbW9kZWxzDQoNCkFzIHdpdGggdGhlIFRydW1wIGVyYSwgYm90aCBPYmFtYSBlcmEgcXEtcGxvdHMgbGluZSB1cCBhcHByb3hpbWF0ZWx5IHdpdGggdGhlIDQ1LWRlZ3JlZSBsaW5lLCBidXQgdGhleSBkbyBoYXZlIHNvbWUgb2RkIHZhcmlhdGlvbnMuDQoNCmBgYHtyfQ0KcXFtYXRoKCB+IHJlc2lkKG1vZEIpLCB0eXBlID0gYygicCIsInIiKSkNCmBgYA0KDQpgYGB7cn0NCnFxbWF0aCggfiByZXNpZChtb2RCTDMpLCB0eXBlID0gYygicCIsInIiKSkNCmBgYA0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPlZJLiBSb2J1c3RuZXNzIG9mIGVzdGltYXRlcyBvZiByZWdyZXNzaW9uIHN0YXRpc3RpY3M8L3NwYW4+DQoNCkR1ZSB0byB0aGUgPGEgaHJlZiA9IGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9vbHMtbGluZWFyLXJlZ3Jlc3Npb24tZ2F1c3MtbWFya292LWJsdWUtYW5kLXVuZGVyc3RhbmRpbmctdGhlLW1hdGgtNDUzZDdjYzYzMGE1PkdhdXNzLU1hcmtvdiB0aGVvcmVtPC9hPiwgd2Uga25vdyB0aGF0IHRoZSBPcmRpbmFyeSBMZWFzdCBTcXVhcmVzIG1vZGVsIGlzIHRoZSAqYmVzdCBsaW5lYXIgdW5iaWFzZWQgZXN0aW1hdG9yKiAoQmxVRSkgZm9yIHRoZSBtb2RlbCBwcm92aWRlZCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHZhcmlhYmxlcyBpcyAqKmFjdHVhbGx5IGxpbmVhcioqLiBCZXR0ZXIsIHdlIGtub3cgdGhhdCB0aGUgcmVncmVzc2lvbiBzdGF0aXN0aWNzIGFyZSBnZW5lcmFsbHkgcm9idXN0IGV2ZW4gaWYgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIGlzIHZpb2xhdGVkLCBzbyBsb25nIGFzIGV2aWRlbmNlIG9mIGxpbmVhcml0eSBpcyBwcmVzZW50Lg0KDQpXZSBkbyBoYXZlIGEgcHJvYmxlbSwgaG93ZXZlciwgYmVjYXVzZSB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gJHQkLXRlc3RzIGFuZCAkdCQtaW50ZXJ2YWxzIGFyZSBub3Qgcm9idXN0LiBUaGVpciBpbnRlcnZhbHMgYW5kICRwJC12YWx1ZXMgY2FuIGJlIHNrZXdlZCBieSBhIGxhY2sgb2Ygbm9ybWFsaXR5LiBXaGVuIHRoZSBxcS1wbG90IHNob3dzIHRoZSByZXNpZHVhbHMgbWF5IG5vdCBiZSBub3JtYWxseSBkaXN0cmlidXRlZCwgd2Ugc2hvdWxkIHVzZSByYW5kb21pemF0aW9uIHRlY2huaXF1ZXMgdG8gZ2VuZXJhdGUgcC12YWx1ZXMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGluc3RlYWQgdHJhZGl0aW9uYWwgc3RhdGlzdGljYWwgcHJvY2VkdXJlcy4NCg0KPGRpdiBzdHlsZT0iZmxvYXQ6cmlnaHQ7IG1hcmdpbjogOHB4OyBib3JkZXI6MnB4IGJsYWNrIHNvbGlkOyBwYWRkaW5nOiAxMHB4IDE1cHggMTBweCI+DQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5Nb3NhaWMncyBSYW5kb21pemF0aW9uIE9wdGlvbnM8L3NwYW4+DQoxLiAqKlNodWZmbGUuKiogUGVybXV0ZXMgdGhlIHZhbHVlcyBpbiB0aGUgc2FtcGxlIGRhdGEuDQoyLiAqKlNhbXBsZS4qKiBEcmF3cyBhIHN1Yi1zYW1wbGUgZnJvbSB0aGUgc2FtcGxlIGRhdGE8L2JyPip3aXRob3V0IHJlcGxhY2VtZW50Ki4NCjMuICoqUmVzYW1wbGUuKiogRHJhd3MgYSBzdWItc2FtcGxlIGZyb20gdGhlIHNhbXBsZSBkYXRhPC9icj4qd2l0aCByZXBsYWNlbWVudCouPC9icj4NCg0KRm9yIGV4YW1wbGVzIG9mIHBlcm11dGF0aW9uIHRlc3RzIGFuZCBib290c3RyYXBwaW5nLCBzZWU8L2JyPg0KdGhlIDxhIGhyZWYgPSBodHRwczovL3JwdWJzLmNvbS9yb2Jic2lubi9zMTE+UmFuZG9taXphdGlvbiBUdXRvcmlhbDwvYT4uDQo8L2Rpdj4NCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5WSUkuIFJhbmRvbWl6YXRpb24gYXBwcm9hY2ggZm9yIFRydW1wIHZzLiBPYmFtYQ0KDQpXZSBoYXZlIHR3byByYW5kb21pemF0aW9uIG9wdGlvbnM6DQoNCjEuIFBlcm11dGF0aW9uIE1ldGhvZA0KMi4gQm9vdHN0cmFwcGluZyBNZXRob2QNCg0KVGhlICoqcGVybXV0YXRpb24qKiBtZXRob2Qgc2ltcGx5IHNodWZmbGVzIHRoZSAkeSQtdmFsdWVzLCBwYWlyaW5nIHRoZW0gd2l0aCByYW5kb20gJHgkLXZhbHVlcy4gVGhlIHJhbmRvbSBhc3NvY2lhdGlvbiBvZiAkeSQtdmFsdWVzIHdpbGwgZ2VuZXJhdGUsIG9uIGF2ZXJhZ2UsIGEgY29ycmVsYXRpb24gYW5kIHNsb3BlIG9mIHplcm8uIFRoaXMgYWxsb3dzIHVzIHRvIHRlc3QgdGhlIG51bGwgaHlwb3RoZXNpcyAkJEhfMCA6IFxyaG8gPSAwJCQgYnV0IG5vdCBudWxsIGh5cG90aGVzZXMgbGlrZSAkJEhfMCA6IFxyaG8gPSA1LjA4JCQNCg0KQXMgdXN1YWwsIHRoZSBSb3NzbWFuLUNoYW5jZSBhcHBsZXQgaXMgYm90aCBhIGdyZWF0IHZpc3VhbGl6YXRpb24gYW5kIGVhc2lseSBpbXBsZW1lbnRzIHRoZSByYW5kb21pemF0aW9uLg0KDQohW1Jvc3NtYW4gQ2hhbmNlIFJlZ3Jlc3Npb24gU2h1ZmZsZSBBcHBdKGltYWdlc1xSZWcyLlBORykNCg0KPGRpdiBzdHlsZT0iZmxvYXQ6cmlnaHQ7IG1hcmdpbjogOHB4OyBib3JkZXI6MnB4IGJsYWNrIHNvbGlkOyBwYWRkaW5nOiAxMHB4IDE1cHggMTBweCI+DQojIyMgUmFuZG9taXplZCBDb25maWRlbmNlIEludGVydmFscw0KU2VlIHRoZSA8YSBocmVmID0gaHR0cHM6Ly9ycHVicy5jb20vcm9iYnNpbm4vczY+U3RhdGlzdGljYWwgRXN0aW1hdGlvbjwvYT4gKG1vZHVsZSA2KSBmb3IgZGV0YWlsczwvYnI+DQpvbiB1c2luZyBib290c3RyYXBwaW5nIHRvIGNyZWF0ZSByYW5kb21pemVkIGNvbmZpZGVuY2U8L2JyPg0KaW50ZXJ2YWxzLg0KPC9kaXY+DQoNCkhvd2V2ZXIsIHdlIGtuZXcgdGhhdCB0aGUgY29ycmVsYXRpb24gb2YgbWVkaWFuIHdhZ2UgZHVyaW5nIHRoZSBUcnVtcCBlcmEgd2FzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHRoYW4gemVyby4gR2l2ZW4gdGhlIGhpc3RvcmljIHRyZW5kIG9mICQ0LjA1LCB0aGUgY29ycmVsYXRpb24gd291bGQgYmUgcmVtYXJrYWJsZSBvbmx5IGlmIGl0IHdlcmUgemVyby4NCg0KIyMjIEJvb3RzdHJhcHBpbmcNCg0KVGhlIGJvb3RzdHJhcHBpbmcgbWV0aG9kIHRha2VzIHNhbXBsZXMgd2l0aCByZXBsYWNlbWVudCBmcm9tIHRoZSBzYW1wbGUgZGF0YSB0byBnZW5lcmF0ZSBhbiBlc3RpbWF0ZSBvZiB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uLiBMZXQncyBjcmVhdGUgb25lIG9mIHRoZSByZXNhbXBsZXMuDQoNCmBgYHtyfQ0KY29lZihsbShNZWRpYW4gfiBQZXJpb2QsIGRhdGE9cmVzYW1wbGUoVHJ1bXBNZWQsIHNpemUgPSAxMCkpKQ0KYGBgDQoNClRoZSByZXNhbXBsZSBmdW5jdGlvbiBoYXMgcHJvZHVjZWQgMTAgZGF0YSBwb2ludHMgZHJhd24gd2l0aCByZXBsYWNlbWVudCBmcm9tIHRoZSBUcnVtcE1lZCBkYXRhIGZyYW1lLiBOb3RlIHRoYXQgdGhlIHNhbWUgZGF0YSBwb2ludCBtYXkgYmUgZHJhd24gbW9yZSB0aGFuIG9uY2UuIFRoZSBsaW5lYXIgbW9kZWwgY3JlYXRlZCBieSB1c2luZyB0aG9zZSByZXNhbXBsZWQgZGF0YSBwb2ludHMgaGFzIGEgc2xvcGUgb2YgNi42NC4NCg0KRm9yIGJvb3RzdHJhcHBpbmcsIHdlIGFyZSBnb2luZyB0byBhbGxvdyB0aGUgKipyZXNhbXBsZSoqIGZ1bmN0aW9uIHRvIGNob29zZSBpdHMgb3duICoqc2l6ZSoqIHBhcmFtZXRlci4gSWYgd2UgcmVzYW1wbGUgYSBkYXRhIHNldCB3aXRoIDE1NSBvYnNlcnZhdGlvbnMsIHRoZSAqKnJlc2FtcGxlKiogZnVuY3Rpb25zIHdpbGwgbWFrZSAxNTUgZHJhd3Mgd2l0aCByZXBsYWNtZW50IGVhY2ggdGltZSBpdCBydW5zLg0KDQpgYGB7cn0NCmJvb3RzdHJhcCA9IGRvKDUwMCkgKiBjb2VmKGxtKE1lZGlhbiB+IFBlcmlvZCwgZGF0YT1yZXNhbXBsZShUcnVtcE1lZCkpKQ0KZGVuc2l0eXBsb3QoflBlcmlvZCwgZGF0YT1ib290c3RyYXApDQpgYGANCg0KVGhlcmUgYXJlIGEgY291cGxlIG9mIG1ldGhvZHMgdG8gZ2VuZXJhdGUgYSBjb25maWRlbmNlIGludGVydmFsIGJhc2VkIG9uIHRoZSBib290c3RyYXAgZGlzdHJpYnV0aW9uLiBUaGUgYmVzdCBtZXRob2QgLSBtb3N0IG9mdGVuIGFwcHJvcHJpYXRlIGluIG1vc3QgY29tbW9uIHNpdHVhdGlvbnMgLSByZXF1aXJlcyBvbmx5IHRoYXQgdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gYmUgc3ltbWV0cmljLiBUaGUgZGVuc2l0eSBwbG90IGFib3ZlIHN1Z2dlc3RzIHRoZSBzeW1tZXRyeSBhc3N1bXB0aW9uIGlzIHJlYXNvbmFibGUuDQoNClRvIGNyZWF0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCwgd2UganVzdCBmaW5kIHRoZSByZWxldmFudCBwZXJjZW50aWxlcyBmcm9tIHdpdGhpbiB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbi4gSW4gb3VyIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gd2UgaGF2ZSB0d28gdmFsdWVzLCAiSW50ZXJjZXB0IiBhbmQgIlBlcmlvZC4iIFRoZSAiUGVyaW9kIiBjb2x1bW4gY29udGFpbnMgdGhlIHNsb3BlIGVzdGltYXRlcy4NCg0KYGBge3J9DQpxZGF0YSh+UGVyaW9kLCBwPWMoMC4wMjUsIDAuOTc1KSwgZGF0YT1ib290c3RyYXApDQpgYGANCg0KVGh1cywgdGhlIDk1JSBjb25maWRlbmNlIGludGVydmFsIHVzaW5nIHJhbmRvbWl6YXRpb24gaXMgJCQoNS4wMywgNy41NCkkJA0Kd2hpY2ggaXMgYSBiaXQgZGlmZmVyZW50IHRoYW4gdGhlICR0JC1pbnRlcnZhbCBvZiAkJCg0Ljg0LCA3LjUzKSQkIGNhbGN1bGF0ZWQgYWJvdmUuDQoNCg0KWW91IGNhbiByZXJ1biB0aGUgYm9vdHN0cmFwcGluZyByZXNhbXBsaW5nIHNldmVyYWwgdGltZXMgdG8gc2VlIGhvdyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBjaGFuZ2VzLiBJdCByZW1haW5zIHNvbWV3aGF0IGNsb3NlIHRvIHRoZSAkdCQtaW50ZXJ2YWwgdmFsdWVzLCBidXQgZG9lcyB2YXJ5IGEgYml0LiBJbiBhbnkgY2FzZSwgd2Ugc3RpbGwgYXBwZWFyIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIFRydW1wIGVyYSB3YXMgbm8gZGlmZmVyZW50IHRoYW4gdGhlIE9iYW1hIGVyYSwgYXQgbGVhc3Qgd2l0aCByZWdhcmQgdG8gbWVkaWFuIHdhZ2UgZ3Jvd3RoLg0KDQojIENhdmVhdHMgYW5kIFRha2Vhd2F5cw0KDQpJbiBwb2xpdGljYWwgZGlzY3Vzc2lvbnMsIGZvbGtzIG9mdGVuIGNob29zZSB0ZWFtcyB0byBzdXBwb3J0IGFuZCBnZXQgZnJ1c3RyYXRlZCB3aGVuIHRoZWlyIHRlYW0gc2VlbXMgZGltaW5pc2hlZC4gQSB3b3JkIG9yIHR3byBvZiBjYXV0aW9uLg0KDQoxLiAgKkFnZW5kYS1kcml2ZW4gZ2Vla3MgY2FuIGxpZSB3aXRoIHN0YXRpc3RpY3MuKiBQb2xpdGljcyBpcyByaWZlIHdpdGggZGVjZXB0aW9uLiBNZWRpYSByZXBvcnRzIGFyZSBpbmNyZWFzaW5nbHkgYWdlbmRhLWRyaXZlbi4gUXVlc3Rpb24gdGhlIG1vdGl2YXRpb24gYW5kIGZhY3R1YWwgaW50ZWdyaXR5IG9mIGV2ZXJ5IHZvaWNlLiBSZWx5IG9uIGdvb2Qgc2NpZW5jZS4NCjIuICAqTXVsdGlwbGUgd2F5cyBvZiBhc3Nlc3NpbmcgdGhlIGVjb25vbXkgYXJlIHZpYWJsZS4qIElmIHlvdSBmZWx0IHRoZSBlY29ub21pYyBkaXNjdXNzaW9uIHdhcyBzbGFudGVkIHJpZ2h0LCByZW1lbWJlciB0aGVyZSBhcmUgbG90cyBvZiBtZWFzdXJlcyBvZiBlY29ub21pYyBoZWFsdGguIFBlcmhhcHMgb3RoZXIgbWVhc3VyZXMgdGlsdCBsZWZ0LiBXYWdlcyBhcmUgbm90IHRoZSBvbmx5IHdheSB0byBlYXJuIG1vbmV5IChpbnZlc3RpbmcsIGNvbW1pc2lvbnMsIHJlYWwgZXN0YXRlLCBldGMuKS4gTWVkaWFuIHdhZ2VzIGFsc28gZG9uJ3QgbWVhc3VyZSB0aGUgbG93ZXN0IGVuZCBvZiB0aGUgZWNvbm9taWMgc3BlY3RydW0uIFdoYXQgYWJvdXQgdGhlIDEwdGggcGVyY2VudGlsZSBvciAyNXRoIHBlcmNlbnRpbGU/IFN0dWR5aW5nIGFuIGlzc3VlIGxpa2UgdGhpcyBpcyBtdWx0aWZhY2V0ZWQgYW5kIG1heSByZXF1aXJlIGxvdHMgb2YgcmVzZWFyY2guIEtlZXAgYW4gb3BlbiBtaW5kIGFuZCBkaWcgdGhyb3VnaCB0aGUgbW9zdCBzY2llbnRpZmljIHJlc3VsdHMgeW91IGNhbiBmaW5kLg0KDQojIyBLZXkgVGFrZWF3YXlzDQoNCjEuICpTYXZ2eSBnZWVrcyBkZXRlY3Qgb3RoZXJzJyBhdHRlbXB0ZWQgbGllcyB3aXRoIHN0YXRpc3RpY3MuKiBPbmUgbWFqb3IgYmVuZWZpdCBvZiB0aGlzIGNsYXNzIHNob3VsZCBiZSBsZWFybmluZyB0byBhcHBseSB5b3VyIGFuYWx5dGljIHNraWxscyB0byByZWFsIHdvcmxkIGlzc3VlcyB3aGVyZSBpdCdzIGluY3JlZGlibHkgaW1wb3J0YW50IG5vdCB0byBuYWl2ZWx5IGZhbGwgZm9yIGRlY2VwdGlvbnMgbGlrZSBjaGVycnktcGlja2luZyBjYXNlcyB0aGF0IHN1cHBvcnQgb25lJ3MgcG9zaXRpb24uIFRoZSBjb3VudGVyLWludHVpdGl2ZSBDT1ZJRCBvdXRsaWVycyBpbiB0aGUgbWVkaWFuIHdhZ2UgZGF0YSBhcmUgYSBwZXJmZWN0IGV4YW1wbGUgdGhhdCB3b3VsZCBoYXZlIHNoYXJwbHkgaW5jcmVhc2VkIHRoZSBtZWRpYW4gd2FnZSBncm93dGggZHVyaW5nIHRoZSBUcnVtcCBlcmEuIFBlb3BsZSBkaXNhZ3JlZSBhYm91dCBwb2xpdGljcywgYnV0IEkgaG9wZSB3ZSBjYW4gYWdyZWUgdGhhdCBsZWFybmluZyB0aGUgYXJ0IGFuZCBzY2llbmNlIG9mIGFwcGxpZWQgc3RhdGlzdGljcyBtYWtlcyB1cyBtb3JlIGtub3dsZWRnZWFibGUgY2l0aXplbnMgYW5kIGJldHRlciBwb3RlbnRpYWwgZW1wbG95ZWVzIGFuZCBlbnRyZXByZW5ldXJzLg0KMi4gKlRoZSBtZWRpYW4gd2FnZSBkaXNjdXNzaW9uIGNvbnRhaW5lZCBncmVhdCBkYXRhIHNldHMuKiBUaGUgbWFqb3IgcmVhc29uIHRoZSBlY29ub21pYyBkYXRhIHdhcyBjaG9zZW4gd2FzIGZvciBwZWRhZ29neS4gU2V2ZXJhbCBvZiB0aGUgcXEtcGxvdHMgbG9va2VkIHF1aXRlIHdvYmJseSB3aGljaCBtb3RpdmF0ZWQgYSBkaXNjdXNzaW9uIGFib3V0IHZpb2xhdGlvbnMgb2YgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uLiBUaGUgbWVkaWEgcmVwb3J0IHN0YXRpc3RpY3MgdGhhdCB3ZXJlIGdlbmVyYXRlZCBieSBhbmFseXNlcyBleGFjdGx5IGxpa2UgdGhlIG9uZXMgc2hvd24gYWJvdmUuIFdlIGRvbid0IGdldCB0byBjaGVjayBmb3IgY3JhenkgQ09WSUQgb3V0bGllcnMuIFdlIGRvbid0IGdldCB0byBzY2FuIHRoZSBxcS1wbG90cyB0byBhc3Nlc3MgbW9kZWwgZml0LiBXZSBkb24ndCBnZXQgdG8gdmVyaWZ5IGFueSBvZiB0aGUgYXNzdW1wdGlvbnMgb3IsIGluIGZhY3QsIGNoZWNrIGZvciBiaWFzIG9uIHRoZSBwYXJ0IG9mIHRoZSBzY2llbnRpc3Qgd2hvIGRpZCB0aGUgYW5hbHlzaXMuIFRoZSBtZWRpYW4gd2FnZSBkYXRhIHNldHMgYWxsb3dlZCBmb3IgYW4gaW1wb3J0YW50IGRpc2N1c3Npb24sIGFuZCBob3BlZnVsbHkgYW4gaW50ZXJlc3Rpbmcgb25lIGFzIHdlbGwuDQozLiAqUmVncmVzc2lvbiBtb2RlbCBzdGF0aXN0aWNzIGFyZSByb2J1c3Qgd2l0aCByZXNwZWN0IHZpb2xhdGlvbnMgb2YgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uKiBmb3IgcmVzaWR1YWxzLCBidXQgbGluZWFyIHJlZ3Jlc3Npb24gJHQkLXRlc3RzIGFuZCAkdCQtaW50ZXJ2YWxzIGFyZSBub3QuIFdlIGFsd2F5cyB1c2Ugc2NhdHRlciBwbG90cyB0byB2ZXJpZnkgdGhhdCBhIGxpbmVhciByZWxhdGlvbnNoaXAgaXMgYSByZWFzb25hYmxlLiBXaXRoIHFxLXBsb3RzLCB3ZSBhcmUgdHJ5aW5nIHRvIGRlY2lkZSBob3cgcmVsaWFibGUgdGhlIHJlc3VsdGluZyBtb2RlbCB3aWxsIGJlLiBJZiB0aGUgcXEtcGxvdCBkZXRlY3RzIGlzc3VlcywgdXNlIGEgcmFuZG9taXphdGlvbiBtZXRob2QgZm9yIHRlc3RzIG9mIHNpZ25pZmljYW50IGNvcnJlbGF0aW9uIG9yIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZXN0aW1hdGVzLg0KNC4gKkJvb3RzdHJhcHBpbmcuKiBXZSBwcmVzZW50ZWQgdHdvIHJhbmRvbWl6YXRpb24gbWV0aG9kcyB0byB0ZXN0cyBvZiBzaWduaWZpY2FudCBjb3JyZWxhdGlvbi4gVGhlIHBlcm11dGF0aW9uIG1ldGhvZCBpcyB2aXN1YWxseSBkZW1vbnN0cmF0ZWQgYnkgdGhlIFJvc3NtYW4tQ2hhbmNlIGFwcGxldC4gVGhlIGJvb3RzdHJhcCBtZXRob2QgYWxsb3dlZCB1cyB0byBjb25zdHJ1Y3QgYSBjb25maWRlbmNlIGludGVydmFsIGVzdGltYXRlIG9mIHRoZSBzbG9wZSBwYXJhbWV0ZXIsIHlldCB0aGUgb25seSB0aGUgYXNzdW1wdGlvbiB3YXMgdGhhdCBib290c3RyYXAgZGlzdHJpYnV0aW9uIHdhcyBzeW1tZXRyaWMuIFdoZW4gdGhlIHFxLXBsb3QgaW5kaWNhdGVzIHBvdGVudGlhbCB2aW9sYXRpb25zIG9mIHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbiwgdXNlIGJvb3RzdHJhcHBpbmcgaW5zdGVhZCBvZiAkdCQtcHJvY2VkdXJlcy4NCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5WSUlJLiBFeGVyY2lzZXM8L3NwYW4+DQoNCjEuIFVzZSB0aGUgRGF0YTMzNTAgZGF0YSBmcmFtZSB0byBidWlsZCBhbmQgZXZhbHVhdGUgYSBsaW5lYXIgbW9kZWwgZm9yIG5hcmNpc3Npc20gKGRlcGVuZGVudCB2YXJpYWJlbGUpIHZzLiB0aHJpbGwtc2Vla2luZyAoaW5kZXBlbmRlbnQgdmFyaWFibGUpIHVzaW5nIHRoZSAqKlRocmlsbCoqIGFuZCAqKk5hcmMqKiB2YXJpYWJsZXMuIEJlIHN1cmUgdG8gY2hlY2sgdGhlIGxpbmVhcml0eSBhbmQgbm9ybWFsaXR5IGFzc3VtcHRpb25zIGFuZCBhbmFseXplIGFsbCByZWdyZXNzaW9uIHN0YXRpc3RpY3MuIENvbnN0cnVjdCBhIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoZSBzbG9wZSBvZiB0aGUgcmVncmVzc2lvbiBsaW5lIHVzaW5nIGFuIGFwcHJvcHJpYXRlIG1ldGhvZC4NCg0KMi4gVXNlIHRoZSBEYXRhMzM1MCBkYXRhIGZyYW1lIHRvIGJ1aWxkIGFuZCBldmFsdWF0ZSBhIGxpbmVhciBtb2RlbCBmb3IgbmV1cm90aWNpc20gKGRlcGVuZGVudCB2YXJpYWJlbGUpIHZzLiBvcHRpbWlzbSAoaW5kZXBlbmRlbnQgdmFyaWFibGUpIHVzaW5nIHRoZSAqKk5ldXJvKiogYW5kICoqT3B0KiogdmFyaWFibGVzLiBCZSBzdXJlIHRvIGNoZWNrIHRoZSBsaW5lYXJpdHkgYW5kIG5vcm1hbGl0eSBhc3N1bXB0aW9ucyBhbmQgYW5hbHl6ZSBhbGwgcmVncmVzc2lvbiBzdGF0aXN0aWNzLiBDb25zdHJ1Y3QgYSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgc2xvcGUgb2YgdGhlIHJlZ3Jlc3Npb24gbGluZSB1c2luZyBhbiBhcHByb3ByaWF0ZSBtZXRob2QuDQoNCjMuIFVzaW5nIHRoZSBidWlsdC1pbiBNb3NhaWMgZGF0YSBzZXQgKipEaW1lcyoqLCB0ZXN0IHRoZSBzaWduaWZpY2FuY2Ugb2YgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gKiptYXNzKiogYW5kICoqeWVhcioqLiBXb3VsZCBpdCBiZSBhcHByb3ByaWF0ZSB0byBidWlsZCBhIGxpbmVhciBtb2RlbCBpbiB0aGlzIGNhc2U/IFdoeSBvciB3aHkgbm90Pw0KDQo0LiBVc2UgdGhlICoqUGVyYyoqIGRhdGEgZnJhbWUgdG8gY3JlYXRlIGxpbmVhciBtb2RlbHMgZm9yIHRoZSAyNXRoIHBlcmNlbnRpbGUgd2FnZSBlYXJuZXJzIGZyb20gMjAwMCBRMSB0aHJvdWdoICAyMDE5IFE0LiBCZSBzdXJlIHRvIGxvb2sgY2FyZWZ1bGx5IGF0IGFsbCBkaWFnbm9zdGljIHBsb3RzLiBDcmVhdGUgbW9kZWxzIGZvciB0aGUgVHJ1bXAgZXJhIGFuZCB0aGUgbGFzdCAzIHllYXJzIG9mIHRoZSBPYm1hbWEgZXJhIGFuZCBjb25kdWN0IGh5cG90aGVzaXMgdGVzdHMgdGhhdCB0aGUgVHJ1bXAgZXJhIGdyb3d0aCB3YXMgc2lnbmlmaWNhbnRseSBncmVhdGVyIHRoYW4gdGhlIGhpc3RvcmljIHRyZW5kIGFzIHdlbGwgYXMgZ3JlYXRlciB0aGFuIHRoZSBPYmFtYSBlcmEuDQoNCjUuIFVzZSB0aGUgKipQZXJjKiogZGF0YSBmcmFtZSB0byBjcmVhdGUgbGluZWFyIG1vZGVscyBmb3IgdGhlIDc1dGggYW5kIDkwdGggcGVyY2VudGlsZSB3YWdlIGVhcm5lcnMgZnJvbSAyMDAwIFExIHRocm91Z2ggIDIwMTkgUTQuIEJlIHN1cmUgdG8gbG9vayBjYXJlZnVsbHkgYXQgYWxsIGRpYWdub3N0aWMgcGxvdHMuIENyZWF0ZSBtb2RlbHMgZm9yIHRoZSBUcnVtcCBlcmEgYW5kIHRoZSBsYXN0IDMgeWVhcnMgb2YgdGhlIE9ibWFtYSBlcmEgYW5kIGNvbmR1Y3QgaHlwb3RoZXNpcyB0ZXN0cyB0aGF0IHRoZSBUcnVtcCBlcmEgZ3Jvd3RoIHdhcyBzaWduaWZpY2FudGx5IGdyZWF0ZXIgdGhhbiB0aGUgaGlzdG9yaWMgdHJlbmQgYXMgd2VsbCBhcyBncmVhdGVyIHRoYW4gdGhlIE9iYW1hIGVyYS4NCg0KNi4gVGhlICoqUGVyY0IqKiBkYXRhIGlzIHNpbWlsYXIgdG8gKipQZXJjKiogaW4gdGhhdCBpdCBpbmNsdWRlcyB0aGUgMTB0aCwgMjV0aCwgNTB0aCwgNzV0aCBhbmQgOTB0aCBwZXJjZW50aWxlIHdhZ2VzLCBidXQgKipQZXJCKiogaW5jbHVkZXMgQmxhY2sgd2FnZSBlYXJuZXJzIG9ubHkuIFVzZSB0aGUgKipQZXJjQioqIGRhdGEgZnJhbWUgdG8gY3JlYXRlIGEgbGluZWFyIG1vZGVsIGZvciB0aGUgbWVkaWFuIHdhZ2UgZ3Jvd3RoICg1MHRoIHBlcmNlbnRpbGUpIGZyb20gMjAwMCBRMSB0aHJvdWdoIDIwMTkgUTQuIEJlIHN1cmUgdG8gbG9vayBjYXJlZnVsbHkgYXQgYWxsIGRpYWdub3N0aWMgcGxvdHMuIENyZWF0ZSBtb2RlbHMgZm9yIHRoZSBUcnVtcCBlcmEgYW5kIHRoZSBsYXN0IDMgeWVhcnMgb2YgdGhlIE9ibWFtYSBlcmEgYW5kIGNvbmR1Y3QgaHlwb3RoZXNpcyB0ZXN0cyB0aGF0IHRoZSBUcnVtcCBlcmEgZ3Jvd3RoIHdhcyBzaWduaWZpY2FudGx5IGdyZWF0ZXIgdGhhbiB0aGUgaGlzdG9yaWMgdHJlbmQgYXMgd2VsbCBhcyBncmVhdGVyIHRoYW4gdGhlIE9iYW1hIGVyYS4NCg==