1 Introduction

Simple Linear Regression (SLR) is a statistical method used to model the relationship between a single independent (predictor) variable (\(X\)) and a dependent (response) variable (\(Y\)). It assumes a linear relationship between the two variables and is widely used for prediction and inference.

Purpose of Simple Linear Regression

  • To quantify the relationship between \(X\) and \(Y\). For example, price vs. demand in economics, drug dosage vs. effect in medicine, stress vs. material strain in engineering, etc..

  • To predict the value of \(Y\) for a given value of \(X\). For example, we may want to use house footage to predict the house price.

  • To test hypotheses about the relationship between \(X\) and \(Y\). For example, we may want to test whether hours of study influence the course grade.

2 Structure of the Simple Linear Regression Model

The simple linear regression (SLR) model is represented as

\[ Y=\beta_0 + \beta_1 X + \epsilon \]

Where \(Y\) is a dependent variable (response), \(X\) is an independent variable (predictor) which is assumed to be non-random. \(\beta_0\) is the intercept (value of \(Y\) when \(X = 0\)), \(\beta_1\) is the slope (the change in \(Y\) per unit change in \(X\)). \(\epsilon\) = ““residual** random error term (assumed \(\epsilon \rightarrow N(0,\sigma^2)\), see the assumptions of the linear regression model in the subsequent section).

For example, the practical regression between price and demand is expressed in the following.

\[ \text{price} = \beta_0 + \beta_1\times \text{demand} + \epsilon. \]

With a given dataset, we can estimate \(\beta_0\) and \(\beta_1\) using the least squares method, denoted respectively by \(b_0\) and \(b_1\). The estimated regression line (fitted model) is:

\[ \hat{Y} = b_0 + b_1 X. \]

The estimated residuals are defined to be the estimated value \(\hat{Y}\) and the observed \(Y\) from the data set. In R, we can extract estimated \(\hat{Y}\) and residuals using R commands fitted(model.name) and `resid(model.name``

Example 1: Simple linear regression to assess the relationship between study hours and course grade. We us simulated data in the following R code

## 
## Call:
## lm(formula = course_grade ~ study_hours, data = example.data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.38182 -0.58182  0.02727  0.45909  1.43636 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  54.7636     0.7155   76.54 9.46e-13 ***
## study_hours   2.4364     0.1007   24.20 9.07e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.9145 on 8 degrees of freedom
## Multiple R-squared:  0.9865, Adjusted R-squared:  0.9848 
## F-statistic: 585.5 on 1 and 8 DF,  p-value: 9.075e-09

The annotation of the output is depicted in the following.

The estimated Y, denoted by \(\hat{Y}\) (commonly called fitted Y) and estimated residual \(e = Y - \hat{Y}\) can be extracted from the above model in the following R code.

##     Y    Y.hat      e.hat
## 1  60 59.63636  0.3636364
## 2  63 62.07273  0.9272727
## 3  65 64.50909  0.4909091
## 4  66 66.94545 -0.9454545
## 5  68 69.38182 -1.3818182
## 6  72 71.81818  0.1818182
## 7  74 74.25455 -0.2545455
## 8  76 76.69091 -0.6909091
## 9  79 79.12727 -0.1272727
## 10 83 81.56364  1.4363636

You see from the above output that Y - Y.hat = e.hat.

3 Assumptions of Simple Linear Regression

For valid inference and predictions, SLR relies on the following assumptions:

  • Linearity: The relationship between \(X\) and \(Y\) is linear. This can be visually checked by a simple scatter plot for SLR (i.e., with only one predictor variable). We can check the linearity of the above example using the following R code.

  • Independence: Errors (\(\epsilon\)) are independent (no autocorrelation). This is hard to check in this level of statistics course.

  • Homoscedasticity: Constant variance of errors across \(X\). Since \(X\) is assumed to be non-random, the variance of \(Y\) is the same as the residual \(\epsilon\). In practice, we check whether the variance of the estimated residual errors \(e = Y - \hat{Y}\).

In the above grade-study example, we can plot the residual in the following.

It turns out that the residuals does not have a constant variance across the fitted values.

  • Normality: Errors are normally distributed. There are testing hypothesis procedures for normality. In practice, we only use visual checks for normality. QQ-plot (quantile-quantile plot) is a commonly used visual tool. It compares the distribution of the estimated residuals with a set of true normally distributed values. The following QQ-plot was generated from R code.

The R functions qqnorm() and qqline() in package {stats} can draw the qq-plot and the reference line. The following code shows how to draw the QQ-plot and reference line based on the above example.

4 Model Diagnostics

In practice, it is quite often to have different methods under different assumptions to solve the same problem. The goals of an analyst are to validate each individual model based on the related assumption and then choose the best model to implement (report). The process of validating a model is called model diagnosis.

As discussed in the previous section, most of the assumptions are related to the residual errors. This section will focus on residual analysis by analyzing the patterns in various residual plots.

  • Residual Plots - Residuals vs Fitted: Checking for non-linearity & heteroscedasticity.

  • Q-Q Plot: Check normality of residuals.

  • Influence Measures - Cook’s Distance: Detects influential observations that impact the regression model (line) significantly. To read the plot of Cook’s distance, you need to have a clear understanding of three definitions:

1. Outlier - an observation that lies an abnormal distance from other values in the dataset.

2. Leverage - a measure of how far an independent variable (X) deviates from its mean.

3. Influential Point - an observation that significantly alters the regression coefficients if removed.

The following YouTube video explains these concepts clearly.



The following table explains the three concepts and diagnostic measures.

Concept Detects… Depends on… Diagnostic Measure
Outlier Atypical Y value Residual magnitude Standardized residuals
Leverage Extreme X value X position only leverage measure
Influence Impact on model Both X and Y Cook’s Distance
  • Relationship Between Outliers, Leverage, and Influential Points

The following table explains the relationship.

Scenario Leverage Residual Influence
Normal point Low Small No
Vertical outlier Low Large Minimal
Good leverage point High Small No
Bad leverage point High Large Yes
  • Graphical Illustration of These Concepts

5 Inference About Regression Coefficients

We perform hypothesis tests to determine if the relationship is statistically significant. Recall that the equation of the simple linear regression model is

\[ Y = \beta_0 + \beta_1 X + \epsilon. \] \(X\) is a numeric or binary (has two possible distinct values, such as STEM-major and non-STEM-major, yes and no, disease and disease-free, etc.).

If the slope \(\beta_1 = 0\), the above regression model is reduced to \(Y = \beta_0 + \epsilon\), In this case, any changes in \(X\) will not influence \(Y\). We call \(X\) and \(Y\) uncorrelated.

In practice, we only need to test whether \(\beta_1 = 0\) to assess the linear relationship between \(Y\) and \(X\). As shown earlier, the output in R provides hypothesis testing on both \(beta_0 = 0\) and \(\beta_1 = 0\) respectively. The following screenshot from R linear regression provides all the information for inference of regression coefficients.

NOTE: The degrees of freedom of the t-test in linear regression is defined to be: df = n - # coefficients!

5.1 t-test for Slope (\(\beta_1\))

\[ H_0: \ \ \beta_1 = 0 \ \ \text{v.s.} \ \ \beta_1 \ne 0 \]

In the Course-grade and Study-time example, the sample size = 10. The test Statistic for testing the above hypothesis is defined as

\[ TS = \frac{b_1 - 0}{\text{SE}(b_1)} \rightarrow t_{10-2} \]

We use the information in the output to evaluate the above test statistic and obtain

\[ TS = \frac{2.4364 - 0}{0.1007} = 24.02. \]

The p-value of the two-tailed test based on the distribution with 8 degrees of freedom is \(\text{p-value} = P(TS>24.02) = 9.618379e-09 \approx 0\). We can use the following R code to calculate the p-value.

## [1] 9.618379e-09

Using significance level \(\alpha = 0.05\), we fail to reject the null hypothesis \(H_0: \beta = 0\). This implies that study-hours influence the course grade significantly since p-value \(\approx 0\) < the significance level 0.05.

Remarks:

(1). pt(24.02, 8) gives the left-tail area. The right-tail area is (1-pt(24.02, 8)).

  1. We have learned from the previous introductory statistics that the p-value of a two-tailed test is equal to two times the smaller tail area.

5.2 Confidence Interval for Slope

Using the information in the output, we can also construct the 95% confidence interval of the slope. Recall that the confidence of the population mean has the following general form.

\[ \bar{x} \pm CV\times \frac{s}{\sqrt{n}} \]

The confidence interval of the slope (\(\beta_1\)) has a similar form given below.

\[ b_1 \pm CV\times \text{SE}(b_1), \]

Where \(b_1\) and \(\text{SE}(b_1)\) are given in the R output (see the above screenshot). CV (critical value) is based on the t-distribution with n - # coefficients (in this study-time and grade example, 10 -2 = 8). Let’s use a confidence level of 95%, the critical value can be found using the R command qt(0.975,8), which gives 2.306. The confidence level and critical value are labeled on the following t-density curve.

Based on the above explanation, the 95% confidence interval of \(\beta_1\) is given by

\[ b_1 \pm CV\times \text{SE}(b_1) = 2.4364 \pm 2.306\times 0.1007 = (2.204186, 2.668614). \]

6 Summary

1. Structure

Models the relationship between one predictor (X) and one response (Y).

Equation: \(Y = \beta_0 + \beta_1 X + \epsilon\). Two regresson coefficients are intercept \((\beta_0)\) and slope \((\beta_1)\). \(\epsilon\) is the random error.

2. Assumptions

  • Linearity: The Relationship between X and Y is linear.

  • Independence: Residuals are uncorrelated (no autocorrelation).

  • Homoscedasticity: Constant variance of residuals across X.

  • Normality: Residuals are normally distributed (important for inference).

3. Diagnostics

Residual plots: Check for patterns (non-linearity, heteroscedasticity).

Q-Q plot: Assess normality of residuals.

Leverage/Cook’s distance: Identify influential points.

R-squared: Proportion of variance explained by X.

4. Interpretation

  • Slope (\(\beta_1\)): Change in Y per unit increase in X.

  • Intercept (\(\beta_0\): Expected Y when X = 0 (may not always be meaningful).

  • R-squared: between 0 and 1; higher = better fit (but doesn’t imply causation).

5. Inference

  • Hypothesis test on \(\beta_1\): \(H_0: \beta_1 = 0 \ \ \text{v.s} \ \ H_a: \beta_1 \ne 0\). Use a t-test for significance.

  • Confidence interval of \(\beta_1\): Range for \(\beta_1\). \(b_1 \pm t_{\text{df}, \ \ 1-\alpha/2}\)

  • p-value: Probability of observing the slope under \(H_0: \beta_1 = 0\).

6. Key R Functions

  • Fit model: lm(Y ~ X, data)

  • Summarize: summary(model). need to understand estimated regression coefficients, R-squared, p-values, etc.

  • Diagnostics:

    • plot(model) (residual plots).
    • qqnorm(resid(model)) (normality check).
  • Predictions: predict(model, newdata)

LS0tDQp0aXRsZTogIkxpbmVhciBSZWdyZXNzaW9uOiBSZXZpZXcsIEV4dGVuc2lvbiBhbmQgRGlhZ25vc2lzIg0KYXV0aG9yOiAiQ2hlbmcgUGVuZyINCmRhdGU6ICIgU1RBMjAwOiBTdGF0aXN0aWNzIElJIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogNQ0KICAgIGZpZ19oZWlnaHQ6IDQNCi0tLQ0KDQpgYGB7Y3NzIGVjaG8gPSBGQUxTRX0NCg0KZGl2I1RPQyBsaSB7DQogICAgbGlzdC1zdHlsZTpub25lOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCmgxLnRpdGxlIHsNCiAgZm9udC1zaXplOiAyNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDIwcHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IGRhcmtyZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgyIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTZweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCmBgYA0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSwgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFRSVUUsICAgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uDQoNClNpbXBsZSBMaW5lYXIgUmVncmVzc2lvbiAoU0xSKSBpcyBhIHN0YXRpc3RpY2FsIG1ldGhvZCB1c2VkIHRvIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIHNpbmdsZSBpbmRlcGVuZGVudCAocHJlZGljdG9yKSB2YXJpYWJsZSAoJFgkKSBhbmQgYSBkZXBlbmRlbnQgKHJlc3BvbnNlKSB2YXJpYWJsZSAoJFkkKS4gSXQgYXNzdW1lcyBhIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcyBhbmQgaXMgd2lkZWx5IHVzZWQgZm9yIHByZWRpY3Rpb24gYW5kIGluZmVyZW5jZS4NCg0KKipQdXJwb3NlIG9mIFNpbXBsZSBMaW5lYXIgUmVncmVzc2lvbioqDQoNCiogVG8gcXVhbnRpZnkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICRYJCBhbmQgJFkkLiAqRm9yIGV4YW1wbGUsIHByaWNlIHZzLiBkZW1hbmQgaW4gZWNvbm9taWNzLCBkcnVnIGRvc2FnZSB2cy4gZWZmZWN0IGluIG1lZGljaW5lLCBzdHJlc3MgdnMuIG1hdGVyaWFsIHN0cmFpbiBpbiBlbmdpbmVlcmluZywgZXRjLi4qDQoNCg0KKiBUbyBwcmVkaWN0IHRoZSB2YWx1ZSBvZiAkWSQgZm9yIGEgZ2l2ZW4gdmFsdWUgb2YgJFgkLiAqRm9yIGV4YW1wbGUsIHdlIG1heSB3YW50IHRvIHVzZSBob3VzZSBmb290YWdlIHRvIHByZWRpY3QgdGhlIGhvdXNlIHByaWNlLioNCg0KKiBUbyB0ZXN0IGh5cG90aGVzZXMgYWJvdXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICRYJCBhbmQgJFkkLiAqRm9yIGV4YW1wbGUsIHdlIG1heSB3YW50IHRvIHRlc3Qgd2hldGhlciBob3VycyBvZiBzdHVkeSBpbmZsdWVuY2UgdGhlIGNvdXJzZSBncmFkZS4qDQoNCg0KDQojIFN0cnVjdHVyZSBvZiB0aGUgU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsDQoNClRoZSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gKFNMUikgbW9kZWwgaXMgcmVwcmVzZW50ZWQgYXMNCg0KJCQNClk9XGJldGFfMCArIFxiZXRhXzEgWCArIFxlcHNpbG9uDQokJA0KIA0KV2hlcmUgJFkkIGlzIGEgZGVwZW5kZW50IHZhcmlhYmxlIChyZXNwb25zZSksICRYJCBpcyBhbiBpbmRlcGVuZGVudCB2YXJpYWJsZSAocHJlZGljdG9yKSA8Zm9udCBjb2xvciA9ICJyZWQiPioqd2hpY2ggaXMgYXNzdW1lZCB0byBiZSBub24tcmFuZG9tKio8L2ZvbnQ+LiAkXGJldGFfMCQgaXMgdGhlIGludGVyY2VwdCAodmFsdWUgb2YgJFkkIHdoZW4gJFggPSAwJCksICRcYmV0YV8xJCBpcyB0aGUgc2xvcGUgKHRoZSBjaGFuZ2UgaW4gJFkkIHBlciB1bml0IGNoYW5nZSBpbiAkWCQpLiAkXGVwc2lsb24kID0gIiJyZXNpZHVhbCoqIHJhbmRvbSBlcnJvciB0ZXJtIChhc3N1bWVkICRcZXBzaWxvbiBccmlnaHRhcnJvdyBOKDAsXHNpZ21hXjIpJCwgc2VlIHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaW4gdGhlIHN1YnNlcXVlbnQgc2VjdGlvbikuDQoNCkZvciBleGFtcGxlLCB0aGUgcHJhY3RpY2FsIHJlZ3Jlc3Npb24gYmV0d2VlbiBwcmljZSBhbmQgZGVtYW5kIGlzIGV4cHJlc3NlZCBpbiB0aGUgZm9sbG93aW5nLg0KDQokJA0KXHRleHR7cHJpY2V9ID0gXGJldGFfMCArIFxiZXRhXzFcdGltZXMgXHRleHR7ZGVtYW5kfSArIFxlcHNpbG9uLg0KJCQNCg0KV2l0aCBhIGdpdmVuIGRhdGFzZXQsIHdlIGNhbiBlc3RpbWF0ZSAkXGJldGFfMCQgYW5kICRcYmV0YV8xJCB1c2luZyB0aGUgbGVhc3Qgc3F1YXJlcyBtZXRob2QsIGRlbm90ZWQgcmVzcGVjdGl2ZWx5IGJ5ICRiXzAkIGFuZCAkYl8xJC4gVGhlIGVzdGltYXRlZCByZWdyZXNzaW9uIGxpbmUgKGZpdHRlZCBtb2RlbCkgaXM6DQoNCiQkDQpcaGF0e1l9ID0gYl8wICsgYl8xIFguDQokJA0KDQpUaGUgKiplc3RpbWF0ZWQqKiByZXNpZHVhbHMgYXJlIGRlZmluZWQgdG8gYmUgdGhlIGVzdGltYXRlZCB2YWx1ZSAkXGhhdHtZfSQgYW5kIHRoZSBvYnNlcnZlZCAkWSQgZnJvbSB0aGUgZGF0YSBzZXQuIEluIFIsIHdlIGNhbiBleHRyYWN0IGVzdGltYXRlZCAkXGhhdHtZfSQgYW5kIHJlc2lkdWFscyB1c2luZyBSIGNvbW1hbmRzIGBmaXR0ZWQobW9kZWwubmFtZSlgIGFuZCBgcmVzaWQobW9kZWwubmFtZWBgDQoNCg0KDQoqKkV4YW1wbGUgMSoqOiAgU2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIHRvIGFzc2VzcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKnN0dWR5IGhvdXJzKiBhbmQgKmNvdXJzZSBncmFkZSouIFdlIHVzIHNpbXVsYXRlZCBkYXRhIGluIHRoZSBmb2xsb3dpbmcgUiBjb2RlDQoNCmBgYHtyfQ0KIyBkZWZpbmUgU2FtcGxlIGRhdGENCnN0dWR5X2hvdXJzIDwtIGMoMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExKQ0KY291cnNlX2dyYWRlIDwtIGMoNjAsIDYzLCA2NSwgNjYsIDY4LCA3MiwgNzQsIDc2LCA3OSwgODMpDQoNCiMgQ29tYmluZSBpbnRvIGEgZGF0YSBmcmFtZSB3aXRoIG5hbWU6IGV4YW1wbGUuZGF0YQ0KZXhhbXBsZS5kYXRhIDwtIGRhdGEuZnJhbWUoc3R1ZHlfaG91cnMsIGNvdXJzZV9ncmFkZSkNCg0KIyBGaXQgdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLiBXZSBuYW1lIHRoZSBtb2RlbDogZXhhbXBsZS5tb2RlbA0KZXhhbXBsZS5tb2RlbCA8LSBsbShjb3Vyc2VfZ3JhZGUgfiBzdHVkeV9ob3VycywgZGF0YSA9IGV4YW1wbGUuZGF0YSkgDQoNCiMgVmlldyB0aGUgbW9kZWwgc3VtbWFyeQ0Kc3VtbWFyeShleGFtcGxlLm1vZGVsKQ0KYGBgDQpUaGUgYW5ub3RhdGlvbiBvZiB0aGUgb3V0cHV0IGlzIGRlcGljdGVkIGluIHRoZSBmb2xsb3dpbmcuDQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI5MCUifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2UvTTAyLVNMUi1vdXRwdXQucG5nIikNCmBgYA0KDQoNClRoZSBlc3RpbWF0ZWQgWSwgZGVub3RlZCBieSAkXGhhdHtZfSQgKGNvbW1vbmx5IGNhbGxlZCBmaXR0ZWQgWSkgYW5kIGVzdGltYXRlZCByZXNpZHVhbCAkZSA9IFkgLSBcaGF0e1l9JCBjYW4gYmUgZXh0cmFjdGVkIGZyb20gdGhlIGFib3ZlIG1vZGVsIGluIHRoZSBmb2xsb3dpbmcgUiBjb2RlLg0KDQpgYGB7cn0NCmZpdHRlZC5ZIDwtIGZpdHRlZChleGFtcGxlLm1vZGVsKSAgICAgICAgICAgIyBlc3RpbWF0ZWQgWQ0KZXN0aW1hdGVkLnJlc2lkIDwtIHJlc2lkKGV4YW1wbGUubW9kZWwpICAgICAjIGVzdGltYXRlZCByZXNpZHVhbCBlcnJvcg0KY2JpbmQoWSA9IGNvdXJzZV9ncmFkZSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgY29tYmluZSB0aHJlZSB2YXJpYWJsZXMgZm9yIGJhY2stdG8tYmFjayBjb21wYXJpc29uDQogICAgICBZLmhhdCA9IGZpdHRlZC5ZLA0KICAgICAgZS5oYXQgPSBlc3RpbWF0ZWQucmVzaWQpDQpgYGANCg0KWW91IHNlZSBmcm9tIHRoZSBhYm92ZSBvdXRwdXQgdGhhdCBgWSAtIFkuaGF0ID0gZS5oYXRgLg0KDQoNCiMgQXNzdW1wdGlvbnMgb2YgU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uDQoNCkZvciB2YWxpZCBpbmZlcmVuY2UgYW5kIHByZWRpY3Rpb25zLCBTTFIgcmVsaWVzIG9uIHRoZSBmb2xsb3dpbmcgYXNzdW1wdGlvbnM6DQoNCiogKipMaW5lYXJpdHkqKjogVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICRYJCBhbmQgJFkkIGlzIGxpbmVhci4gVGhpcyBjYW4gYmUgdmlzdWFsbHkgY2hlY2tlZCBieSBhIHNpbXBsZSBzY2F0dGVyIHBsb3QgZm9yIFNMUiAoaS5lLiwgd2l0aCBvbmx5IG9uZSBwcmVkaWN0b3IgdmFyaWFibGUpLiBXZSBjYW4gY2hlY2sgdGhlIGxpbmVhcml0eSBvZiB0aGUgYWJvdmUgZXhhbXBsZSB1c2luZyB0aGUgZm9sbG93aW5nIFIgY29kZS4NCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01fQ0KcGxvdChzdHVkeV9ob3VycywgY291cnNlX2dyYWRlLCBtYWluPSJDb3Vyc2UgR3JhZGUgdi5zLiBTdHVkeSBIb3VycyIpDQpgYGANCg0KDQoqICoqSW5kZXBlbmRlbmNlKio6IEVycm9ycyAoJFxlcHNpbG9uJCkgYXJlIGluZGVwZW5kZW50IChubyBhdXRvY29ycmVsYXRpb24pLiBUaGlzIGlzIGhhcmQgdG8gY2hlY2sgaW4gdGhpcyBsZXZlbCBvZiBzdGF0aXN0aWNzIGNvdXJzZS4gDQoNCiogSG9tb3NjZWRhc3RpY2l0eTogQ29uc3RhbnQgdmFyaWFuY2Ugb2YgZXJyb3JzIGFjcm9zcyAkWCQuIFNpbmNlICRYJCBpcyBhc3N1bWVkIHRvIGJlIG5vbi1yYW5kb20sIHRoZSB2YXJpYW5jZSBvZiAkWSQgaXMgdGhlIHNhbWUgYXMgdGhlIHJlc2lkdWFsICRcZXBzaWxvbiQuIEluIHByYWN0aWNlLCB3ZSBjaGVjayB3aGV0aGVyIHRoZSB2YXJpYW5jZSBvZiB0aGUgZXN0aW1hdGVkIHJlc2lkdWFsIGVycm9ycyAkZSA9IFkgLSBcaGF0e1l9JC4NCg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iODAlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlL00wMi1yZXNpZHVhbC1wYXR0ZXJucy5wbmciKQ0KYGBgDQoNCkluIHRoZSBhYm92ZSBncmFkZS1zdHVkeSBleGFtcGxlLCB3ZSBjYW4gcGxvdCB0aGUgcmVzaWR1YWwgaW4gdGhlIGZvbGxvd2luZy4NCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01fQ0KIyBmaXR0ZWQuWSBhbmQgZXN0aW1hdGVkLnJlc2lkIHdlcmUgZGVmaW5lZCBlYXJsaWVyDQojIENhdXRpb246IFdoZW4geW91IHVzZSBhIHZhcmlhYmxlIGluIGFuYWx5c2lzIGFuZCBwbG90dGluZywgbWFrZSBzdXJlIGl0IGlzIGRlZmluZWQgZWFybGllci4NCiMgSW4gYW55IGZ1bmN0aW9uIGNhbGxzLCBhcmd1bWVudHMgbXVzdCBiZSBzZXBhcmF0ZWQgYnkgYSBjb21tYSENCnBsb3QoZml0dGVkLlksICAgICAgICAgICAgICAgICMgZml0dGVkIG9yIHByZWRpY3RlZCB2YWx1ZXMNCiAgICAgZXN0aW1hdGVkLnJlc2lkLCAgICAgICAgICMgZXN0aW1hdGVkIHJlc2lkdWFscw0KICAgICB4bGFiID0gIkZpdHRlZCBWYWx1ZXMiLCAgIyB0aGUgbGFiZWwgb2YgeC1heGlzDQogICAgIHlsYWIgPSAiUmVzaWR1YWxzIiwgICAgICAjIHRoZSBsYWJlbCBvZiB5LWxhYmVsDQogICAgIG1haW4gPSAiUmVzaWR1YWwgUGxvdCBFeGFtcGxlIExpbmVhciBNb2RlbCINCiAgICAgKQ0KYGBgDQoNCkl0IHR1cm5zIG91dCB0aGF0IHRoZSByZXNpZHVhbHMgKipkb2VzIG5vdCoqIGhhdmUgYSBjb25zdGFudCB2YXJpYW5jZSBhY3Jvc3MgdGhlIGZpdHRlZCB2YWx1ZXMuDQoNCg0KDQoqICoqTm9ybWFsaXR5Kio6IEVycm9ycyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFRoZXJlIGFyZSB0ZXN0aW5nIGh5cG90aGVzaXMgcHJvY2VkdXJlcyBmb3Igbm9ybWFsaXR5LiBJbiBwcmFjdGljZSwgd2Ugb25seSB1c2UgdmlzdWFsIGNoZWNrcyBmb3Igbm9ybWFsaXR5LiAqKlFRLXBsb3QqKiAocXVhbnRpbGUtcXVhbnRpbGUgcGxvdCkgaXMgYSBjb21tb25seSB1c2VkIHZpc3VhbCB0b29sLiBJdCBjb21wYXJlcyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBlc3RpbWF0ZWQgcmVzaWR1YWxzIHdpdGggYSBzZXQgb2YgdHJ1ZSBub3JtYWxseSBkaXN0cmlidXRlZCB2YWx1ZXMuIFRoZSBmb2xsb3dpbmcgKipRUS1wbG90Kiogd2FzIGdlbmVyYXRlZCBmcm9tIFIgY29kZS4gDQoNClRoZSBSIGZ1bmN0aW9ucyBgcXFub3JtKClgIGFuZCBgcXFsaW5lKClgIGluIHBhY2thZ2UgKip7c3RhdHN9KiogY2FuIGRyYXcgdGhlIHFxLXBsb3QgYW5kIHRoZSByZWZlcmVuY2UgbGluZS4gVGhlIGZvbGxvd2luZyBjb2RlIHNob3dzIGhvdyB0byBkcmF3IHRoZSBRUS1wbG90IGFuZCByZWZlcmVuY2UgbGluZSBiYXNlZCBvbiB0aGUgYWJvdmUgZXhhbXBsZS4gDQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NX0NCiMgbmVlZCB0byBpbnN0YWxsIGFuZCBsb2FkIHRoZSBwYWNrYWdlIHtnZ3Bsb3QyfQ0KIyBTaW5jZSBwYWNrYWdlIHtzdGF0c30gY29tZXMgd2l0aCBiYXNlIFIsIHdlIGRvbid0IG5lZWQgdG8gaW5zdGFsbCBpdC4NCiMjDQpxcW5vcm0oZXN0aW1hdGVkLnJlc2lkKSAgICMgdGhlIHNldCBvZiBlc3RpbWF0ZWQgcmVzaWR1YWxzDQpxcWxpbmUoZXN0aW1hdGVkLnJlc2lkKSAgICMgZHJhdyB0aGUgcmVmZXJlbmNlIGxpbmUNCmBgYA0KDQojIE1vZGVsIERpYWdub3N0aWNzDQoNCkluIHByYWN0aWNlLCBpdCBpcyBxdWl0ZSBvZnRlbiB0byBoYXZlIGRpZmZlcmVudCBtZXRob2RzIHVuZGVyIGRpZmZlcmVudCBhc3N1bXB0aW9ucyB0byBzb2x2ZSB0aGUgc2FtZSBwcm9ibGVtLiBUaGUgZ29hbHMgb2YgYW4gYW5hbHlzdCBhcmUgdG8gdmFsaWRhdGUgZWFjaCBpbmRpdmlkdWFsIG1vZGVsIGJhc2VkIG9uIHRoZSByZWxhdGVkIGFzc3VtcHRpb24gYW5kIHRoZW4gY2hvb3NlIHRoZSBiZXN0IG1vZGVsIHRvIGltcGxlbWVudCAocmVwb3J0KS4gVGhlIHByb2Nlc3Mgb2YgdmFsaWRhdGluZyBhIG1vZGVsIGlzIGNhbGxlZCAqKm1vZGVsIGRpYWdub3NpcyoqLg0KDQpBcyBkaXNjdXNzZWQgaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24sIG1vc3Qgb2YgdGhlIGFzc3VtcHRpb25zIGFyZSByZWxhdGVkIHRvIHRoZSByZXNpZHVhbCBlcnJvcnMuIFRoaXMgc2VjdGlvbiB3aWxsIGZvY3VzIG9uICoqcmVzaWR1YWwgYW5hbHlzaXMqKiBieSBhbmFseXppbmcgdGhlIHBhdHRlcm5zIGluIHZhcmlvdXMgcmVzaWR1YWwgcGxvdHMuDQoNCiogKipSZXNpZHVhbCBQbG90cyoqIC0gUmVzaWR1YWxzIHZzIEZpdHRlZDogQ2hlY2tpbmcgZm9yIG5vbi1saW5lYXJpdHkgJiBoZXRlcm9zY2VkYXN0aWNpdHkuDQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI4MCUifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2UvTTAyLVJlc2lkdWFsUGxvdFBhdHRlcm5zLnBuZyIpDQpgYGANCg0KKiAqKlEtUSBQbG90Kio6IENoZWNrIG5vcm1hbGl0eSBvZiByZXNpZHVhbHMuIA0KDQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI4MCUifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2UvTTAyLVFRUGxvdFBhdHRlcm5zLnBuZyIpDQpgYGANCg0KDQoqICoqSW5mbHVlbmNlIE1lYXN1cmVzIC0gQ29va+KAmXMgRGlzdGFuY2UqKjogRGV0ZWN0cyBpbmZsdWVudGlhbCBvYnNlcnZhdGlvbnMgdGhhdCBpbXBhY3QgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgKGxpbmUpIHNpZ25pZmljYW50bHkuIFRvIHJlYWQgdGhlIHBsb3Qgb2YgQ29vaydzIGRpc3RhbmNlLCB5b3UgbmVlZCB0byBoYXZlIGEgY2xlYXIgdW5kZXJzdGFuZGluZyBvZiB0aHJlZSBkZWZpbml0aW9uczoNCg0KKioxLiBPdXRsaWVyKiogLSBhbiBvYnNlcnZhdGlvbiB0aGF0IGxpZXMgYW4gKiphYm5vcm1hbCBkaXN0YW5jZSoqIGZyb20gb3RoZXIgdmFsdWVzIGluIHRoZSBkYXRhc2V0LiANCg0KKioyLiBMZXZlcmFnZSoqIC0gYSBtZWFzdXJlIG9mIGhvdyBmYXIgYW4gKippbmRlcGVuZGVudCB2YXJpYWJsZSAoWCkqKiBkZXZpYXRlcyBmcm9tIGl0cyBtZWFuLg0KDQoqKjMuIEluZmx1ZW50aWFsIFBvaW50KiogLSBhbiBvYnNlcnZhdGlvbiB0aGF0IHNpZ25pZmljYW50bHkgYWx0ZXJzIHRoZSByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyBpZiByZW1vdmVkLiANCg0KVGhlIGZvbGxvd2luZyBZb3VUdWJlIHZpZGVvIGV4cGxhaW5zIHRoZXNlIGNvbmNlcHRzIGNsZWFybHkuDQoNClwNCg0KPGNlbnRlcj48YSBocmVmPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PXhjX1g5R0ZWdVZVIiB0YXJnZXQ9InBvcHVwIiANCiAgICAgICAgICAgICAgICAgICBvbmNsaWNrPSJ3aW5kb3cub3BlbignaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj14Y19YOUdGVnVWVScsDQogICAgICAgICAgICAgICAgICAgICAgJ25hbWUnLCd3aWR0aD04NTAsaGVpZ2h0PTUwMCcpIj48aW1nIHNyYyA9ICJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9NQVQxMjFXNS9pbWcvVmlkZW9JY29uLnBuZyIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMjAiPjwvYT4NCjwvY2VudGVyPg0KDQpcDQoNClRoZSBmb2xsb3dpbmcgdGFibGUgZXhwbGFpbnMgdGhlIHRocmVlIGNvbmNlcHRzIGFuZCBkaWFnbm9zdGljIG1lYXN1cmVzLiANCg0KfCBDb25jZXB0ICAgICAgIHwgRGV0ZWN0cy4uLiAgICAgICAgICB8IERlcGVuZHMgb24uLi4gICAgICAgfCBEaWFnbm9zdGljIE1lYXN1cmUgICAgICAgICAgfA0KfDotLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCAqKk91dGxpZXIqKiAgIHwgQXR5cGljYWwgWSB2YWx1ZSAgICB8IFJlc2lkdWFsIG1hZ25pdHVkZSAgfCBTdGFuZGFyZGl6ZWQgcmVzaWR1YWxzICAgICAgfA0KfCAqKkxldmVyYWdlKiogIHwgRXh0cmVtZSBYIHZhbHVlICAgICB8IFggcG9zaXRpb24gb25seSAgICAgfCBsZXZlcmFnZSBtZWFzdXJlICAgICAgICAgICAgfA0KfCAqKkluZmx1ZW5jZSoqIHwgSW1wYWN0IG9uIG1vZGVsICAgICB8IEJvdGggWCBhbmQgWSAgICAgICAgfCBDb29r4oCZcyBEaXN0YW5jZSAgICAgICAgICAgICB8DQoNCg0KKiAqKlJlbGF0aW9uc2hpcCBCZXR3ZWVuIE91dGxpZXJzLCBMZXZlcmFnZSwgYW5kIEluZmx1ZW50aWFsIFBvaW50cyoqDQoNClRoZSBmb2xsb3dpbmcgdGFibGUgZXhwbGFpbnMgdGhlIHJlbGF0aW9uc2hpcC4NCg0KfCBTY2VuYXJpbyAgICAgICAgICAgICAgICB8IExldmVyYWdlIHwgUmVzaWR1YWwgfCBJbmZsdWVuY2UgfA0KfDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLXw6LS0tLS0tLS0tfDotLS0tLS0tLS0tfA0KfCBOb3JtYWwgcG9pbnQgICAgICAgICAgICB8IExvdyAgICAgIHwgU21hbGwgICAgfCBObyAgICAgICAgfA0KfCBWZXJ0aWNhbCBvdXRsaWVyICAgICAgICB8IExvdyAgICAgIHwgTGFyZ2UgICAgfCBNaW5pbWFsICAgfA0KfCBHb29kIGxldmVyYWdlIHBvaW50ICAgICB8IEhpZ2ggICAgIHwgU21hbGwgICAgfCBObyAgICAgICAgfA0KfCBCYWQgbGV2ZXJhZ2UgcG9pbnQgICAgICB8IEhpZ2ggICAgIHwgTGFyZ2UgICAgfCBZZXMgICAgICAgfA0KDQoNCiogKipHcmFwaGljYWwgSWxsdXN0cmF0aW9uIG9mIFRoZXNlIENvbmNlcHRzKioNCg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iOTUlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlL00wMi1JbmZsdWVudGlhbExldmVyYWdlT3V0bGllci5wbmciKQ0KYGBgDQoNCg0KDQojIEluZmVyZW5jZSBBYm91dCBSZWdyZXNzaW9uIENvZWZmaWNpZW50cw0KDQpXZSBwZXJmb3JtIGh5cG90aGVzaXMgdGVzdHMgdG8gZGV0ZXJtaW5lIGlmIHRoZSByZWxhdGlvbnNoaXAgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4gUmVjYWxsIHRoYXQgdGhlIGVxdWF0aW9uIG9mIHRoZSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaXMNCg0KJCQNClkgPSBcYmV0YV8wICsgXGJldGFfMSBYICsgXGVwc2lsb24uDQokJA0KJFgkIGlzIGEgbnVtZXJpYyBvciBiaW5hcnkgKGhhcyB0d28gcG9zc2libGUgZGlzdGluY3QgdmFsdWVzLCBzdWNoIGFzIGBTVEVNLW1ham9yYCBhbmQgYG5vbi1TVEVNLW1ham9yYCwgYHllc2AgYW5kIGBub2AsIGBkaXNlYXNlYCBhbmQgYGRpc2Vhc2UtZnJlZWAsIGV0Yy4pLiANCg0KSWYgdGhlIHNsb3BlICRcYmV0YV8xID0gMCQsIHRoZSBhYm92ZSByZWdyZXNzaW9uIG1vZGVsIGlzIHJlZHVjZWQgdG8gJFkgPSBcYmV0YV8wICsgXGVwc2lsb24kLCBJbiB0aGlzIGNhc2UsIGFueSBjaGFuZ2VzIGluICRYJCB3aWxsICoqbm90KiogaW5mbHVlbmNlICRZJC4gV2UgY2FsbCAkWCQgYW5kICRZJCB1bmNvcnJlbGF0ZWQuDQoNCkluIHByYWN0aWNlLCB3ZSBvbmx5IG5lZWQgdG8gdGVzdCB3aGV0aGVyICRcYmV0YV8xID0gMCQgdG8gYXNzZXNzIHRoZSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gJFkkIGFuZCAkWCQuIEFzIHNob3duIGVhcmxpZXIsIHRoZSBvdXRwdXQgaW4gUiBwcm92aWRlcyBoeXBvdGhlc2lzIHRlc3Rpbmcgb24gYm90aCAkYmV0YV8wID0gMCQgYW5kICRcYmV0YV8xID0gMCQgcmVzcGVjdGl2ZWx5LiBUaGUgZm9sbG93aW5nIHNjcmVlbnNob3QgZnJvbSBSIGxpbmVhciByZWdyZXNzaW9uIHByb3ZpZGVzIGFsbCB0aGUgaW5mb3JtYXRpb24gZm9yIGluZmVyZW5jZSBvZiByZWdyZXNzaW9uIGNvZWZmaWNpZW50cy4gIA0KDQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI4NSUifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2UvTTAyLVItbG0tT3V0cHV0LnBuZyIpDQpgYGANCg0KPGZvbnQgY29sb3IgPSAicmVkIj4qKlxjb2xvcntyZWR9Tk9URTogVGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBvZiB0aGUgdC10ZXN0IGluIGxpbmVhciByZWdyZXNzaW9uIGlzIGRlZmluZWQgdG8gYmU6IGRmID0gbiAtICMgY29lZmZpY2llbnRzISoqPC9mb250Pg0KDQojIyB0LXRlc3QgZm9yIFNsb3BlICgkXGJldGFfMSQpDQoNCiQkIA0KSF8wOiBcIFwgXGJldGFfMSA9IDAgXCBcIFx0ZXh0e3Yucy59IFwgXCBcYmV0YV8xIFxuZSAwIA0KJCQNCg0KSW4gdGhlICoqQ291cnNlLWdyYWRlIGFuZCBTdHVkeS10aW1lKiogZXhhbXBsZSwgdGhlIHNhbXBsZSBzaXplID0gMTAuIFRoZSB0ZXN0IFN0YXRpc3RpYyBmb3IgdGVzdGluZyB0aGUgYWJvdmUgaHlwb3RoZXNpcyBpcyBkZWZpbmVkIGFzDQoNCiQkDQpUUyA9IFxmcmFje2JfMSAtIDB9e1x0ZXh0e1NFfShiXzEpfSBccmlnaHRhcnJvdyB0X3sxMC0yfQ0KJCQNCg0KV2UgdXNlIHRoZSBpbmZvcm1hdGlvbiBpbiB0aGUgb3V0cHV0IHRvIGV2YWx1YXRlIHRoZSBhYm92ZSB0ZXN0IHN0YXRpc3RpYyBhbmQgb2J0YWluDQoNCiQkDQpUUyA9IFxmcmFjezIuNDM2NCAtIDB9ezAuMTAwN30gPSAyNC4wMi4NCiQkDQogDQogVGhlIHAtdmFsdWUgb2YgdGhlIHR3by10YWlsZWQgdGVzdCBiYXNlZCBvbiB0aGUgZGlzdHJpYnV0aW9uIHdpdGggOCBkZWdyZWVzIG9mIGZyZWVkb20gaXMgJFx0ZXh0e3AtdmFsdWV9ID0gUChUUz4yNC4wMikgPSA5LjYxODM3OWUtMDkgXGFwcHJveCAwJC4gV2UgY2FuIHVzZSB0aGUgZm9sbG93aW5nIFIgY29kZSB0byBjYWxjdWxhdGUgdGhlIHAtdmFsdWUuDQogDQogDQpgYGB7cn0NCiBwLnZhbHVlIDwtIDIqKDEtcHQoIDI0LjAyLCA4KSkNCiBwLnZhbHVlDQpgYGANCiANClVzaW5nIHNpZ25pZmljYW5jZSBsZXZlbCAkXGFscGhhID0gMC4wNSQsIHdlIGZhaWwgdG8gKipyZWplY3QqKiB0aGUgbnVsbCBoeXBvdGhlc2lzICRIXzA6ICBcYmV0YSA9IDAkLiBUaGlzIGltcGxpZXMgdGhhdCBzdHVkeS1ob3VycyBpbmZsdWVuY2UgdGhlIGNvdXJzZSBncmFkZSAqKnNpZ25pZmljYW50bHkqKiBzaW5jZSBwLXZhbHVlICRcYXBwcm94IDAkIDwgdGhlIHNpZ25pZmljYW5jZSBsZXZlbCAwLjA1Lg0KIA0KIA0KICoqUmVtYXJrcyoqOiANCiANCiAoMSkuIGBwdCgyNC4wMiwgOClgIGdpdmVzIHRoZSAqKmxlZnQtdGFpbCBhcmVhKiouIFRoZSAqKnJpZ2h0LXRhaWwgYXJlYSoqIGlzIGAoMS1wdCgyNC4wMiwgOCkpYC4gDQogDQogDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNzUlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlL00wMi10LWRlbnNpdHlDdXJ2ZS5wbmciKQ0KYGBgDQogDQogKDIpIFdlIGhhdmUgbGVhcm5lZCBmcm9tIHRoZSBwcmV2aW91cyBpbnRyb2R1Y3Rvcnkgc3RhdGlzdGljcyB0aGF0IHRoZSBwLXZhbHVlIG9mIGEgdHdvLXRhaWxlZCB0ZXN0IGlzIGVxdWFsIHRvIHR3byB0aW1lcyB0aGUgc21hbGxlciB0YWlsIGFyZWEuDQogDQoNCg0KIyMgQ29uZmlkZW5jZSBJbnRlcnZhbCBmb3IgU2xvcGUNCg0KVXNpbmcgdGhlIGluZm9ybWF0aW9uIGluIHRoZSBvdXRwdXQsIHdlIGNhbiBhbHNvIGNvbnN0cnVjdCB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIHNsb3BlLiBSZWNhbGwgdGhhdCB0aGUgY29uZmlkZW5jZSBvZiB0aGUgcG9wdWxhdGlvbiBtZWFuIGhhcyB0aGUgZm9sbG93aW5nIGdlbmVyYWwgZm9ybS4NCg0KJCQNClxiYXJ7eH0gXHBtIENWXHRpbWVzIFxmcmFje3N9e1xzcXJ0e259fQ0KJCQNCg0KVGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIHNsb3BlICgkXGJldGFfMSQpIGhhcyBhIHNpbWlsYXIgZm9ybSBnaXZlbiBiZWxvdy4NCg0KJCQNCmJfMSBccG0gQ1ZcdGltZXMgXHRleHR7U0V9KGJfMSksDQokJA0KDQpXaGVyZSAkYl8xJCBhbmQgJFx0ZXh0e1NFfShiXzEpJCBhcmUgZ2l2ZW4gaW4gdGhlIFIgb3V0cHV0IChzZWUgdGhlIGFib3ZlIHNjcmVlbnNob3QpLiBDViAoY3JpdGljYWwgdmFsdWUpIGlzIGJhc2VkIG9uIHRoZSB0LWRpc3RyaWJ1dGlvbiB3aXRoIGBuIC0gIyBjb2VmZmljaWVudHNgIChpbiB0aGlzIHN0dWR5LXRpbWUgYW5kIGdyYWRlIGV4YW1wbGUsIDEwIC0yID0gOCkuIExldCdzIHVzZSBhIGNvbmZpZGVuY2UgbGV2ZWwgb2YgOTUlLCB0aGUgY3JpdGljYWwgdmFsdWUgY2FuIGJlIGZvdW5kIHVzaW5nIHRoZSBSIGNvbW1hbmQgYHF0KDAuOTc1LDgpYCwgd2hpY2ggZ2l2ZXMgMi4zMDYuIFRoZSBjb25maWRlbmNlIGxldmVsIGFuZCBjcml0aWNhbCB2YWx1ZSBhcmUgbGFiZWxlZCBvbiB0aGUgZm9sbG93aW5nIHQtZGVuc2l0eSBjdXJ2ZS4NCg0KIA0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9Ijc1JSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZS9NMDItdC1jcml0aWNhbFZhbHVlLnBuZyIpDQpgYGANCg0KQmFzZWQgb24gdGhlIGFib3ZlIGV4cGxhbmF0aW9uLCB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgJFxiZXRhXzEkIGlzIGdpdmVuIGJ5DQoNCiQkDQpiXzEgXHBtIENWXHRpbWVzIFx0ZXh0e1NFfShiXzEpID0gMi40MzY0IFxwbSAyLjMwNlx0aW1lcyAwLjEwMDcgPSAoMi4yMDQxODYsIDIuNjY4NjE0KS4NCiQkDQoNCg0KIyBTdW1tYXJ5DQoNCg0KDQoqKjEuIFN0cnVjdHVyZSoqDQoNCk1vZGVscyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gb25lIHByZWRpY3RvciAoWCkgYW5kIG9uZSByZXNwb25zZSAoWSkuDQoNCioqRXF1YXRpb24qKjogJFkgPSBcYmV0YV8wICsgXGJldGFfMSBYICsgXGVwc2lsb24kLiBUd28gcmVncmVzc29uIGNvZWZmaWNpZW50cyBhcmUgaW50ZXJjZXB0ICQoXGJldGFfMCkkIGFuZCBzbG9wZSAkKFxiZXRhXzEpJC4gJFxlcHNpbG9uJCBpcyB0aGUgcmFuZG9tIGVycm9yLg0KDQoqKjIuIEFzc3VtcHRpb25zKioNCg0KKiAqTGluZWFyaXR5KjogVGhlIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIFggYW5kIFkgaXMgbGluZWFyLg0KDQoqICpJbmRlcGVuZGVuY2UqOiBSZXNpZHVhbHMgYXJlIHVuY29ycmVsYXRlZCAobm8gYXV0b2NvcnJlbGF0aW9uKS4NCg0KKiAqSG9tb3NjZWRhc3RpY2l0eSo6IENvbnN0YW50IHZhcmlhbmNlIG9mIHJlc2lkdWFscyBhY3Jvc3MgWC4NCg0KKiAqTm9ybWFsaXR5KjogUmVzaWR1YWxzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZCAoaW1wb3J0YW50IGZvciBpbmZlcmVuY2UpLg0KDQoNCg0KKiozLiBEaWFnbm9zdGljcyoqDQoNClJlc2lkdWFsIHBsb3RzOiBDaGVjayBmb3IgcGF0dGVybnMgKG5vbi1saW5lYXJpdHksIGhldGVyb3NjZWRhc3RpY2l0eSkuDQoNClEtUSBwbG90OiBBc3Nlc3Mgbm9ybWFsaXR5IG9mIHJlc2lkdWFscy4NCg0KTGV2ZXJhZ2UvQ29va+KAmXMgZGlzdGFuY2U6IElkZW50aWZ5IGluZmx1ZW50aWFsIHBvaW50cy4NCg0KUi1zcXVhcmVkOiBQcm9wb3J0aW9uIG9mIHZhcmlhbmNlIGV4cGxhaW5lZCBieSBYLg0KDQoNCioqNC4gSW50ZXJwcmV0YXRpb24qKg0KDQoqICpTbG9wZSAoJFxiZXRhXzEkKSo6ICBDaGFuZ2UgaW4gWSBwZXIgdW5pdCBpbmNyZWFzZSBpbiBYLg0KDQoqICpJbnRlcmNlcHQgKCRcYmV0YV8wJCo6IEV4cGVjdGVkIFkgd2hlbiBYID0gMCAobWF5IG5vdCBhbHdheXMgYmUgbWVhbmluZ2Z1bCkuDQoNCiogKlItc3F1YXJlZDoqIGJldHdlZW4gMCBhbmQgMTsgaGlnaGVyID0gYmV0dGVyIGZpdCAoYnV0ICoqZG9lc27igJl0IGltcGx5IGNhdXNhdGlvbioqKS4NCg0KDQoNCioqNS4gSW5mZXJlbmNlKioNCg0KKiAqSHlwb3RoZXNpcyB0ZXN0IG9uICRcYmV0YV8xJCo6ICAkSF8wOiBcYmV0YV8xID0gMCBcIFwgXHRleHR7di5zfSBcIFwgSF9hOiBcYmV0YV8xIFxuZSAwJC4gIFVzZSBhIHQtdGVzdCBmb3Igc2lnbmlmaWNhbmNlLg0KDQoqICpDb25maWRlbmNlIGludGVydmFsIG9mICRcYmV0YV8xJCo6IFJhbmdlIGZvciAkXGJldGFfMSQuICAkYl8xIFxwbSB0X3tcdGV4dHtkZn0sIFwgXCAxLVxhbHBoYS8yfSQNCg0KKiAqcC12YWx1ZSo6IFByb2JhYmlsaXR5IG9mIG9ic2VydmluZyB0aGUgc2xvcGUgdW5kZXIgJEhfMDogXGJldGFfMSA9IDAkLiANCg0KDQoNCioqNi4gS2V5IFIgRnVuY3Rpb25zKioNCg0KKiBGaXQgbW9kZWw6IGBsbShZIH4gWCwgZGF0YSlgDQoNCiogU3VtbWFyaXplOiBgc3VtbWFyeShtb2RlbClgLiBuZWVkIHRvIHVuZGVyc3RhbmQgZXN0aW1hdGVkIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLCBSLXNxdWFyZWQsIHAtdmFsdWVzLCBldGMuDQoNCiogRGlhZ25vc3RpY3M6DQoNCiAgKyBwbG90KG1vZGVsKSAocmVzaWR1YWwgcGxvdHMpLg0KICArIHFxbm9ybShyZXNpZChtb2RlbCkpIChub3JtYWxpdHkgY2hlY2spLg0KDQoqIFByZWRpY3Rpb25zOiBwcmVkaWN0KG1vZGVsLCBuZXdkYXRhKQ0KDQoNCg0KDQoNCg0K