About
In a given year, if it rains more, we might see an increase in crop production. This is because more water may lead to more plants. This is a direct relationship; the amount of produce may be predicted by the amount of rainfall in a certain year. This example represents a simple linear regression, an important concept that allows us to model (predict) the output value of a certain variable based off the input of one or many variables.
This lab explores the concepts of simple linear regression, multiple linear regression, and a revisit of Watson analytics.
Setup
Remember to always set your working directory to the source file location. Go to ‘Session’, scroll down to ‘Set Working Directory’, and click ‘To Source File Location’. Read carefully the below and follow the instructions to complete the tasks and answer any questions. Submit your work to RPubs as detailed in previous notes.
Note
For your assignment you may be using different data sets than what is included here. Always read carefully the instructions on Sakai. For clarity, tasks/questions to be completed/answered are highlighted in red color and numbered according to their particular placement in the task section. Quite often you will need to add your own code chunk.
Execute all code chunks, preview, publish, and submit link on Sakai.
Task 1: Simple Linear Regression
First, read in the marketing data that was used in the previous lab. Make sure the file is read in correctly by checking the variables in the environment pane of Rstudio and also displaying the few header ines of the file.
#Read the input file
mydata = read.csv(file="data/marketing.csv")
head(mydata)
Next, apply the cor() function to the entire data set. This is a quick way to compare the correlations between all variables.
#Correlation matrix of all variable columns in the data
corr = cor(mydata)
corr
case_number sales radio paper tv pos
case_number 1.0000000 0.2402344 0.23586825 -0.36838393 0.22282482 0.05397630
sales 0.2402344 1.0000000 0.97713807 -0.28306828 0.95797025 0.01264860
radio 0.2358682 0.9771381 1.00000000 -0.23835848 0.96609579 0.06040209
paper -0.3683839 -0.2830683 -0.23835848 1.00000000 -0.24587896 -0.09006241
tv 0.2228248 0.9579703 0.96609579 -0.24587896 1.00000000 -0.03602314
pos 0.0539763 0.0126486 0.06040209 -0.09006241 -0.03602314 1.00000000
# Correlation matrix of columns 2,4, and 6
corr = cor( mydata[ c(2,4,6) ] )
corr
sales paper pos
sales 1.0000000 -0.28306828 0.01264860
paper -0.2830683 1.00000000 -0.09006241
pos 0.0126486 -0.09006241 1.00000000
#Correlation matrix of all columns except the first column. This is convenient since case_number is only an indicator for the month and should be excluded from the calculations.
corr = cor( mydata[ 2:6 ] )
corr
sales radio paper tv pos
sales 1.0000000 0.97713807 -0.28306828 0.95797025 0.01264860
radio 0.9771381 1.00000000 -0.23835848 0.96609579 0.06040209
paper -0.2830683 -0.23835848 1.00000000 -0.24587896 -0.09006241
tv 0.9579703 0.96609579 -0.24587896 1.00000000 -0.03602314
pos 0.0126486 0.06040209 -0.09006241 -0.03602314 1.00000000
The above matrix is called a square and symmetric matrix.
##### 1A) Explain why the value of “1.0” along the diagonal?
1.0 means perfect correlation, when those variables are compared with themselves, they correlate with themselves 100%.
##### 1B) Explain with an example how the entries of the matrix is symmetric with respect to the diagonal.
Tha radio in the row with tv in the column have the correlation 0.96609579, and it is same correlation with tv in the row and radio in the columa, so does vavariables.
Next we will create a visual diagram of the correlation matrix called a corrgram where the correlations strength are represented by colors intensity. To do this we need first to install two packages in R-Studio as executed by the command lines below
# Generates a corrgram of last computed correlation matrix
corrgram(corr)

# Generates a corrplot, similar a corrgram, but with a different visual display
corrplot(corr)

From the matrix, its clear that Sales, Radio and TV have the strongest correlations. Let’s create now few scatterplots to visualize the data and trending lines. First we need to extract the columns from the data file.
#Extract all variables
pos = mydata$pos
paper = mydata$paper
tv = mydata$tv
sales = mydata$sales
radio = mydata$radio
#Plot of Radio and Sales using plot command from Worksheet 4
scatter.smooth(radio,sales)

From this plot, it seems the points are scattered in an almost linear way. So, we will try to fit a simple linear regression model to the graph.
The lm() linear modeling function is a very useful one. The function is set up as lm(y ~ x) where the x variable, the independent variable, predicts values of the y variable, or the dependent variable.
In the simple linear regression model below, we are using radio ads to predict sales. We print out a summary to view the quantitative facts about the linear model.
#Simple Linear Regression - the R function lm()
reg <- lm(sales ~ radio)
#Summary of Model
summary(reg)
Call:
lm(formula = sales ~ radio)
Residuals:
Min 1Q Median 3Q Max
-1732.85 -198.88 62.64 415.26 637.70
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -9741.92 1362.94 -7.148 1.17e-06 ***
radio 347.69 17.83 19.499 1.49e-13 ***
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 571.6 on 18 degrees of freedom
Multiple R-squared: 0.9548, Adjusted R-squared: 0.9523
F-statistic: 380.2 on 1 and 18 DF, p-value: 1.492e-13
As indicated by the summary report the intercept value is -9741.92 and the slope for radio is 347.69. We can therefore write the following equation for the linear regression model predicting Sales based on Radio Sales_predicted = -9741.92 + 347.69 * Xradio. Given this equation we can predict the value of sales for any given value of radio like for example 75 (investing $75,000 in radio ads). Always watch for units!
### Linear model ( Y = b +- mx )
### Sales_predicted ~ Radio_X1
sales_predicted = -9741.92 + 347.69 * (75)
sales_predicted
[1] 16334.83
### Another way to write the equation is to refer to the coefficients of the equation instead of typing the actual values out.
### This is demonstrated below.
sales_predicted = coef(reg)[1] + coef(reg)[2] * 75
coef(reg)[1] # intercept
(Intercept)
-9741.921
coef(reg)[2] # slope
radio
347.6888
sales_predicted
(Intercept)
16334.74
A high R-Squared value indicates that the model is a good fit, but not perfect. For the case of Sales versus Radio we will overlay the trend line representing the regression equation over the original plot. This will show how far the predicted values are from the actual value. The difference between the actual sales (circles) and the predicted sales (solid line) is captured in the residual error calculations as reported earlier by the summary function.
#Plot Radio and Sales
plot(radio,sales)
#Add a trend line plot using the linear model we created above
abline(reg, col="blue",lwd=2)

Note that the trend line shown here is the one corresponding to the regression equation. It is different from the smooth curved line used earlier in the scatter plot.
##### 1C) Repeat the above calculations to derive the linear regression model for Sales versus TV ?
#Simple Linear Regression - the R function lm()
reg <- lm(sales ~ tv)
#Summary of Model
summary(reg)
Call:
lm(formula = sales ~ tv)
Residuals:
Min 1Q Median 3Q Max
-1921.87 -412.24 7.02 581.59 1081.61
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -42229.21 4164.12 -10.14 7.19e-09 ***
tv 221.10 15.61 14.17 3.34e-11 ***
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 771.3 on 18 degrees of freedom
Multiple R-squared: 0.9177, Adjusted R-squared: 0.9131
F-statistic: 200.7 on 1 and 18 DF, p-value: 3.336e-11
#Plot TV and Sales
plot(tv,sales)
#Add a trend line plot using the linear model we created above
abline(reg, col="blue",lwd=2)

##### 1D) Write down the equation for the linear regression model. Identify the values for the intercept and the slope.
Ysales= -42229.21 + 221.10Xtv intercept is -42229.21, and slope is 221.10.
Task 2: Multiple Linear Regression
Many times there are more than one factor or variable that affect the prediction of an outcome. While increased rainfall is a good predictor of increased crop supply, decreased herbivores can also result in an increase of crops. This idea is a loose metaphor for multiple linear regression.
In R, multiple linear regression takes the form of lm(y ~ x0 + x1 + x2 + ... ), where y is the value that is being predicted, or the dependent variable, and the x variables are the predictors or the independent variables
Lets create a multiple linear regression predicting sales using both independent variables radio and tv.
#Multiple Linear Regression Model
mlr1 <-lm(sales ~ radio + tv)
#Summary of Multiple Linear Regression Model
summary(mlr1)
Call:
lm(formula = sales ~ radio + tv)
Residuals:
Min 1Q Median 3Q Max
-1729.58 -205.97 56.95 335.15 759.26
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -17150.46 6965.59 -2.462 0.024791 *
radio 275.69 68.73 4.011 0.000905 ***
tv 48.34 44.58 1.084 0.293351
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 568.9 on 17 degrees of freedom
Multiple R-squared: 0.9577, Adjusted R-squared: 0.9527
F-statistic: 192.6 on 2 and 17 DF, p-value: 2.098e-12
Note the values of 0.9577 for R-squared and 0.9527 for the Adjusted R-squared. The predicted sales can again be calculated given the coefficients of the regression model. The example below calculates the predicted sales for TV = 270 and Radio = 75.
# sales_predicted = radio + tv
sales_predicted = coef(mlr1)[1] + coef(mlr1)[2]*(75) + coef(mlr1)[3]*(270)
sales_predicted
(Intercept)
16578.3
##### 2A) Compare the calculated predicted sales to the actual sales found in the file, by calculating the difference error squared.
The predicted salesis $16578.3, and the actual sales is 16876.
errorsquared = (16578.3-16876)^2
errorsquared
[1] 88625.29
##### 2B) Fill in the code chunk below to create multiple linear regression model for each of the specified two use cases, and display the summary statistics.
#mlr2 = Sales predicted by radio, tv, and pos
#Summary of Multiple Linear Regression Model
mlr2 <-lm(sales ~ radio + tv + pos)
summary(mlr2)
Call:
lm(formula = sales ~ radio + tv + pos)
Residuals:
Min 1Q Median 3Q Max
-1748.20 -187.42 -61.14 352.07 734.20
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -15491.23 7697.08 -2.013 0.06130 .
radio 291.36 75.48 3.860 0.00139 **
tv 38.26 48.90 0.782 0.44538
pos -107.62 191.25 -0.563 0.58142
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 580.7 on 16 degrees of freedom
Multiple R-squared: 0.9585, Adjusted R-squared: 0.9508
F-statistic: 123.3 on 3 and 16 DF, p-value: 2.859e-11
#mlr3 = Sales predicted by radio, tv, pos, and paper
#Summary of Multiple Linear Regression Model
mlr3 <-lm(sales ~ radio + tv + pos + paper)
summary(mlr3)
Call:
lm(formula = sales ~ radio + tv + pos + paper)
Residuals:
Min 1Q Median 3Q Max
-1558.13 -239.35 7.25 387.02 728.02
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -13801.015 7865.017 -1.755 0.09970 .
radio 294.224 75.442 3.900 0.00142 **
tv 33.369 49.080 0.680 0.50693
pos -128.875 192.156 -0.671 0.51262
paper -9.159 8.991 -1.019 0.32449
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 580 on 15 degrees of freedom
Multiple R-squared: 0.9612, Adjusted R-squared: 0.9509
F-statistic: 92.96 on 4 and 15 DF, p-value: 2.13e-10
##### 2C) Write down a summary paragraph of the regression equations and corresponding values for R-squared and Adjusted R-squared for each of the three cases: mlr1, mlr2, and mlr3
mlr1: Ysales = -17150.46 + 275.69Xradio + 48.34Xtv r-squared = 0.9577 adjusted r-squared = 0.9527
mlr2: Ysales = -15491.23 + 291.36Xradio + 38.26 Xtv - 107.62Xpos r-squared = 0.9585 adjusted r-squared = 0.9508
mlr3: Ysales = -13801.015 + 294.224Xradio + 33.369Xtv - 128.875Xpos - 9.159Xpaper r-squared = 0.9612 adjusted r-squared = 0.9509
##### 2D) Based solely on the values for R-squared and Adj R-squared, which of the three multiple linear regression models mlr1, mlr2, mlr3, is best in predicting sales. Explain why.
According to Adj R-squared, the best in predictin is mlr1 becuase it is have higher Adj r-square value than other two.
##### 2E) Calculate the sales value for each of the above three models by substituting for the values Radio = 69 , TV = 255 , POS = 1.5, and Paper = 75. Compare your calculated sales to the actual value as obtained from the data file. Which model is best at fitting the actual sales value? Quantify your answer by calculating the error squared for each case. Compare your findings to your answer in 2D) and explain any discrepencies. Hint: best fitting is not same as best predicting!
# Compute
sales_predicted = coef(mlr1)[1] + coef(mlr1)[2]*69 + coef(mlr1)[3]*255
sales_predicted
(Intercept)
14199.05
errorsquared = (14199.05-13965)^2
errorsquared
[1] 54779.4
# sales_predicted = radio + tv + pos
sales_predicted = coef(mlr2)[1] + coef(mlr2)[2]*(69) + coef(mlr2)[3]*(255)+ coef(mlr2)[4]*1.5
sales_predicted
(Intercept)
14208.44
errorsquared = (14208.44-13965)^2
errorsquared
[1] 59263.03
# sales_predicted = radio + tv + pos + paper
sales_predicted = coef(mlr3)[1] + coef(mlr3)[2]*(69) + coef(mlr3)[3]*(255)+ coef(mlr3)[4]*1.5+ coef(mlr3)[5]*75
sales_predicted
(Intercept)
14129.32
errorsquared = (14129.32-13965)^2
errorsquared
[1] 27001.06
The best model fit the actual sales value is mlr3 because it has lower value of error squared than other two,also if there are more independent variables are added, the R-squared will keep on increasing. But in 2D, model 3 is not the best in predicting sales based on its lower adjusted r-squared than other two, because adjusted r-squared increases only if the added variable provides better prediction.
Task 3: Watson Analytics Predict
Watson Analytics contains a module for Predict, besides the two others for Explore and Assemble. Although Watson is a useful tool it should never be treated as a black box. In other words there are many circumstances where Watson can fail to make the proper diagnosis and suggest the correct remedies. This is why it is critical, as more of the cognitive analytics and advanced machine learning tools invade our environment, that we also allow room for human intervention and learn how to best interact.
There are many details in the Predict module. We will keep it relatively simple for this introductory phase. To complete this task, follow the directions below. Make sure to capture any screenshots and to answer any questions where requested
- Logon to your Watson Analytics account at http://watsonanalytics.com
- Upload the file marketing.csv unless already in your folder
- Double-click on the file you just uploaded.
You will be guided to a new window where you can go to the Predictive Analysis menu and select the Spiral option. You will be presented with a new discovery window where you will have to select your target variable.
##### 3A) Include a screen shot of the top predictors of sales. Consider the one field (driver) predictive model only and note the predictive power strength for each driver 
Based on the screenshots above, radio and tv are the top predictors of sale. Tv has a predictive strength of 86% and radio has a predictive strength of 93%.
Note that Watson follows a different approach to identify and quantify the predictive strength of each variable. Such details are outside the scope of this exercise. Watson provides a lot of on-line help, and the interested reader is encouraged to independently check the on-line documentation and explore the many capabilities of Watson.
##### 3B) How do Watson results reconcile with your findings based on the R regression analysis in task 2? Explain.
The adjusted R square value and Watson both proved that radio and tv have the highest predictive power for sales. Which indicate that the result we found in task 2 is true. Radio had predicting strength of 93% and tv had 86%
LS0tDQp0aXRsZTogIkJTQUQzNDMgRmFsbCAyMDE4IExhYiBXb3Jrc2hlZXQgMDYiDQphdXRob3I6ICJZaSBQYW4iDQpkYXRlOiAiMTAtMjQtMjAxOCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0Kc3VidGl0bGU6IExpbmVhciBSZWdyZXNzaW9uICYgV2F0c29uIEFuYWx5dGljcyAoYnNhZC1sYWIwNikNCi0tLQ0KDQojIyMgQWJvdXQNCg0KSW4gYSBnaXZlbiB5ZWFyLCBpZiBpdCByYWlucyBtb3JlLCB3ZSBtaWdodCBzZWUgYW4gaW5jcmVhc2UgaW4gY3JvcCBwcm9kdWN0aW9uLiBUaGlzIGlzIGJlY2F1c2UgbW9yZSB3YXRlciBtYXkgbGVhZCB0byBtb3JlIHBsYW50cy4gVGhpcyBpcyBhIGRpcmVjdCByZWxhdGlvbnNoaXA7IHRoZSBhbW91bnQgb2YgcHJvZHVjZSBtYXkgYmUgcHJlZGljdGVkIGJ5IHRoZSBhbW91bnQgb2YgcmFpbmZhbGwgaW4gYSBjZXJ0YWluIHllYXIuIFRoaXMgZXhhbXBsZSByZXByZXNlbnRzIGEgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uLCBhbiBpbXBvcnRhbnQgY29uY2VwdCB0aGF0IGFsbG93cyB1cyB0byBtb2RlbCAocHJlZGljdCkgdGhlIG91dHB1dCB2YWx1ZSBvZiBhIGNlcnRhaW4gdmFyaWFibGUgYmFzZWQgb2ZmIHRoZSBpbnB1dCBvZiBvbmUgb3IgbWFueSB2YXJpYWJsZXMuIA0KDQpUaGlzIGxhYiBleHBsb3JlcyB0aGUgY29uY2VwdHMgb2Ygc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uLCBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiwgYW5kIGEgcmV2aXNpdCBvZiBXYXRzb24gYW5hbHl0aWNzLiANCg0KIyMjIFNldHVwDQoNClJlbWVtYmVyIHRvIGFsd2F5cyBzZXQgeW91ciB3b3JraW5nIGRpcmVjdG9yeSB0byB0aGUgc291cmNlIGZpbGUgbG9jYXRpb24uIEdvIHRvICdTZXNzaW9uJywgc2Nyb2xsIGRvd24gdG8gJ1NldCBXb3JraW5nIERpcmVjdG9yeScsIGFuZCBjbGljayAnVG8gU291cmNlIEZpbGUgTG9jYXRpb24nLiBSZWFkIGNhcmVmdWxseSB0aGUgYmVsb3cgYW5kIGZvbGxvdyB0aGUgaW5zdHJ1Y3Rpb25zIHRvIGNvbXBsZXRlIHRoZSB0YXNrcyBhbmQgYW5zd2VyIGFueSBxdWVzdGlvbnMuICBTdWJtaXQgeW91ciB3b3JrIHRvIFJQdWJzIGFzIGRldGFpbGVkIGluIHByZXZpb3VzIG5vdGVzLiANCg0KIyMjIE5vdGUNCg0KRm9yIHlvdXIgYXNzaWdubWVudCB5b3UgbWF5IGJlIHVzaW5nIGRpZmZlcmVudCBkYXRhIHNldHMgdGhhbiB3aGF0IGlzIGluY2x1ZGVkIGhlcmUuIEFsd2F5cyByZWFkIGNhcmVmdWxseSB0aGUgaW5zdHJ1Y3Rpb25zIG9uIFNha2FpLiAgRm9yIGNsYXJpdHksIHRhc2tzL3F1ZXN0aW9ucyB0byBiZSBjb21wbGV0ZWQvYW5zd2VyZWQgYXJlIGhpZ2hsaWdodGVkIGluIHJlZCBjb2xvciBhbmQgbnVtYmVyZWQgYWNjb3JkaW5nIHRvIHRoZWlyIHBhcnRpY3VsYXIgcGxhY2VtZW50IGluIHRoZSB0YXNrIHNlY3Rpb24uICBRdWl0ZSBvZnRlbiB5b3Ugd2lsbCBuZWVkIHRvIGFkZCB5b3VyIG93biBjb2RlIGNodW5rLg0KDQpFeGVjdXRlIGFsbCBjb2RlIGNodW5rcywgcHJldmlldywgcHVibGlzaCwgYW5kIHN1Ym1pdCBsaW5rIG9uIFNha2FpLg0KDQotLS0tLS0tLS0tLS0tLQ0KDQojIyMgVGFzayAxOiBTaW1wbGUgTGluZWFyIFJlZ3Jlc3Npb24NCg0KRmlyc3QsIHJlYWQgaW4gdGhlIG1hcmtldGluZyBkYXRhIHRoYXQgd2FzIHVzZWQgaW4gdGhlIHByZXZpb3VzIGxhYi4gTWFrZSBzdXJlIHRoZSBmaWxlIGlzIHJlYWQgaW4gY29ycmVjdGx5IGJ5IGNoZWNraW5nIHRoZSB2YXJpYWJsZXMgaW4gdGhlIGVudmlyb25tZW50IHBhbmUgb2YgUnN0dWRpbyBhbmQgYWxzbyBkaXNwbGF5aW5nIHRoZSBmZXcgaGVhZGVyIGluZXMgb2YgdGhlIGZpbGUuDQoNCmBgYHtyfQ0KI1JlYWQgdGhlIGlucHV0IGZpbGUNCm15ZGF0YSA9IHJlYWQuY3N2KGZpbGU9ImRhdGEvbWFya2V0aW5nLmNzdiIpDQpoZWFkKG15ZGF0YSkNCmBgYA0KDQpOZXh0LCBhcHBseSB0aGUgYGNvcigpYCBmdW5jdGlvbiB0byB0aGUgZW50aXJlIGRhdGEgc2V0LiBUaGlzIGlzIGEgcXVpY2sgd2F5IHRvIGNvbXBhcmUgdGhlIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIGFsbCB2YXJpYWJsZXMuDQoNCg0KYGBge3J9DQojQ29ycmVsYXRpb24gbWF0cml4IG9mIGFsbCB2YXJpYWJsZSBjb2x1bW5zIGluIHRoZSBkYXRhDQpjb3JyID0gY29yKG15ZGF0YSkNCmNvcnINCg0KIyBDb3JyZWxhdGlvbiBtYXRyaXggb2YgY29sdW1ucyAyLDQsIGFuZCA2DQpjb3JyID0gY29yKCBteWRhdGFbIGMoMiw0LDYpIF0gKQ0KY29ycg0KDQojQ29ycmVsYXRpb24gbWF0cml4IG9mIGFsbCBjb2x1bW5zIGV4Y2VwdCB0aGUgZmlyc3QgY29sdW1uLiBUaGlzIGlzIGNvbnZlbmllbnQgc2luY2UgY2FzZV9udW1iZXIgaXMgb25seSBhbiBpbmRpY2F0b3IgZm9yIHRoZSBtb250aCBhbmQgc2hvdWxkIGJlIGV4Y2x1ZGVkIGZyb20gdGhlIGNhbGN1bGF0aW9ucy4NCmNvcnIgPSBjb3IoIG15ZGF0YVsgMjo2IF0gKQ0KY29ycg0KYGBgDQoNClRoZSBhYm92ZSBtYXRyaXggaXMgY2FsbGVkIGEgc3F1YXJlIGFuZCBzeW1tZXRyaWMgbWF0cml4LiANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAxQSkgRXhwbGFpbiB3aHkgdGhlIHZhbHVlIG9mICIxLjAiIGFsb25nIHRoZSBkaWFnb25hbD8NCjwvc3Bhbj4NCg0KIDEuMCBtZWFucyBwZXJmZWN0IGNvcnJlbGF0aW9uLCB3aGVuIHRob3NlIHZhcmlhYmxlcyBhcmUgY29tcGFyZWQgd2l0aCB0aGVtc2VsdmVzLCB0aGV5IGNvcnJlbGF0ZSB3aXRoIHRoZW1zZWx2ZXMgMTAwJS4NCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAxQikgRXhwbGFpbiB3aXRoIGFuIGV4YW1wbGUgaG93IHRoZSBlbnRyaWVzIG9mIHRoZSBtYXRyaXggaXMgc3ltbWV0cmljIHdpdGggcmVzcGVjdCB0byB0aGUgZGlhZ29uYWwuIA0KPC9zcGFuPg0KDQpUaGEgcmFkaW8gaW4gdGhlIHJvdyB3aXRoIHR2IGluIHRoZSBjb2x1bW4gaGF2ZSB0aGUgY29ycmVsYXRpb24gMC45NjYwOTU3OSwgYW5kIGl0IGlzIHNhbWUgY29ycmVsYXRpb24gd2l0aCB0diBpbiB0aGUgcm93IGFuZCByYWRpbyBpbiB0aGUgY29sdW1hLCBzbyBkb2VzIHZhdmFyaWFibGVzLiANCg0KTmV4dCB3ZSB3aWxsIGNyZWF0ZSBhIHZpc3VhbCBkaWFncmFtIG9mIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggY2FsbGVkIGEgY29ycmdyYW0gd2hlcmUgdGhlIGNvcnJlbGF0aW9ucyBzdHJlbmd0aCBhcmUgcmVwcmVzZW50ZWQgYnkgY29sb3JzIGludGVuc2l0eS4gIFRvIGRvIHRoaXMgd2UgbmVlZCBmaXJzdCB0byBpbnN0YWxsIHR3byBwYWNrYWdlcyBpbiBSLVN0dWRpbyBhcyBleGVjdXRlZCBieSB0aGUgY29tbWFuZCBsaW5lcyBiZWxvdw0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCg0KIyBSZXF1aXJlIHdpbGwgbG9hZCB0aGUgcGFja2FnZSBvbmx5IGlmIG5vdCBpbnN0YWxsZWQgDQojIERlcGVuZGVuY2llcyA9IFRSVUUgbWFrZXMgc3VyZSB0aGF0IGRlcGVuZGVuY2llcyBhcmUgaW5zdGFsbA0KDQppZighcmVxdWlyZSgiY29ycnBsb3QiLHF1aWV0bHkgPSBUUlVFKSkNCiAgaW5zdGFsbC5wYWNrYWdlcygiY29ycnBsb3QiLGRlcGVuZGVuY2llcyA9IFRSVUUsIHJlcG9zID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIpDQoNCmlmKCFyZXF1aXJlKCJjb3JyZ3JhbSIscXVpZXRseSA9IFRSVUUpKQ0KICBpbnN0YWxsLnBhY2thZ2VzKCJjb3JyZ3JhbSIsZGVwZW5kZW5jaWVzID0gVFJVRSwgcmVwb3MgPSAiaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnIikNCg0KYGBgDQoNCmBgYHtyfQ0KIyBHZW5lcmF0ZXMgYSBjb3JyZ3JhbSBvZiBsYXN0IGNvbXB1dGVkIGNvcnJlbGF0aW9uIG1hdHJpeA0KY29ycmdyYW0oY29ycikNCiMgR2VuZXJhdGVzIGEgY29ycnBsb3QsIHNpbWlsYXIgYSBjb3JyZ3JhbSwgYnV0IHdpdGggYSBkaWZmZXJlbnQgdmlzdWFsIGRpc3BsYXkNCmNvcnJwbG90KGNvcnIpDQpgYGANCg0KRnJvbSB0aGUgbWF0cml4LCBpdHMgY2xlYXIgdGhhdCBTYWxlcywgUmFkaW8gYW5kIFRWIGhhdmUgdGhlIHN0cm9uZ2VzdCBjb3JyZWxhdGlvbnMuIExldCdzIGNyZWF0ZSBub3cgZmV3IHNjYXR0ZXJwbG90cyB0byB2aXN1YWxpemUgdGhlIGRhdGEgYW5kIHRyZW5kaW5nIGxpbmVzLiBGaXJzdCB3ZSBuZWVkIHRvIGV4dHJhY3QgdGhlIGNvbHVtbnMgZnJvbSB0aGUgZGF0YSBmaWxlLg0KDQpgYGB7cn0NCiNFeHRyYWN0IGFsbCB2YXJpYWJsZXMNCnBvcyAgPSBteWRhdGEkcG9zDQpwYXBlciA9IG15ZGF0YSRwYXBlcg0KdHYgPSBteWRhdGEkdHYNCnNhbGVzID0gbXlkYXRhJHNhbGVzDQpyYWRpbyA9IG15ZGF0YSRyYWRpbw0KYGBgDQoNCmBgYHtyfQ0KI1Bsb3Qgb2YgUmFkaW8gYW5kIFNhbGVzIHVzaW5nIHBsb3QgY29tbWFuZCBmcm9tIFdvcmtzaGVldCA0DQpzY2F0dGVyLnNtb290aChyYWRpbyxzYWxlcykNCmBgYA0KDQpGcm9tIHRoaXMgcGxvdCwgaXQgc2VlbXMgdGhlIHBvaW50cyBhcmUgc2NhdHRlcmVkIGluIGFuIGFsbW9zdCBsaW5lYXIgd2F5LiBTbywgd2Ugd2lsbCB0cnkgdG8gZml0IGEgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHRvIHRoZSBncmFwaC4gDQoNClRoZSBgbG0oKWAgbGluZWFyIG1vZGVsaW5nIGZ1bmN0aW9uIGlzIGEgdmVyeSB1c2VmdWwgb25lLiBUaGUgZnVuY3Rpb24gaXMgc2V0IHVwIGFzIGBsbSh5IH4geClgIHdoZXJlIHRoZSB4IHZhcmlhYmxlLCB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUsIHByZWRpY3RzIHZhbHVlcyBvZiB0aGUgeSB2YXJpYWJsZSwgb3IgdGhlIGRlcGVuZGVudCB2YXJpYWJsZS4NCg0KSW4gdGhlIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBiZWxvdywgd2UgYXJlIHVzaW5nIHJhZGlvIGFkcyB0byBwcmVkaWN0IHNhbGVzLiBXZSBwcmludCBvdXQgYSBzdW1tYXJ5IHRvIHZpZXcgdGhlIHF1YW50aXRhdGl2ZSBmYWN0cyBhYm91dCB0aGUgbGluZWFyIG1vZGVsLiANCg0KYGBge3J9DQojU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uIC0gdGhlIFIgZnVuY3Rpb24gbG0oKQ0KcmVnIDwtIGxtKHNhbGVzIH4gcmFkaW8pDQoNCiNTdW1tYXJ5IG9mIE1vZGVsDQpzdW1tYXJ5KHJlZykNCg0KYGBgDQoNCkFzIGluZGljYXRlZCBieSB0aGUgc3VtbWFyeSByZXBvcnQgdGhlIGludGVyY2VwdCB2YWx1ZSBpcyAtOTc0MS45MiBhbmQgdGhlIHNsb3BlIGZvciByYWRpbyBpcyAzNDcuNjkuICBXZSBjYW4gdGhlcmVmb3JlIHdyaXRlIHRoZSBmb2xsb3dpbmcgZXF1YXRpb24gZm9yIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBwcmVkaWN0aW5nIFNhbGVzIGJhc2VkIG9uIFJhZGlvIGBTYWxlc19wcmVkaWN0ZWQgPSAtOTc0MS45MiArIDM0Ny42OSAqIFhyYWRpb2AuIEdpdmVuIHRoaXMgZXF1YXRpb24gIHdlIGNhbiBwcmVkaWN0IHRoZSB2YWx1ZSBvZiBzYWxlcyBmb3IgYW55IGdpdmVuIHZhbHVlIG9mIHJhZGlvIGxpa2UgZm9yIGV4YW1wbGUgNzUgKGludmVzdGluZyAkNzUsMDAwIGluIHJhZGlvIGFkcykuIEFsd2F5cyB3YXRjaCBmb3IgdW5pdHMhDQoNCmBgYHtyfQ0KIyMjIExpbmVhciBtb2RlbCAgKCBZID0gYiArLSBteCApIA0KIyMjIFNhbGVzX3ByZWRpY3RlZCAgfiBSYWRpb19YMQ0KDQpzYWxlc19wcmVkaWN0ZWQgPSAtOTc0MS45MiArIDM0Ny42OSAqICg3NSkNCnNhbGVzX3ByZWRpY3RlZA0KDQojIyMgQW5vdGhlciB3YXkgdG8gd3JpdGUgdGhlIGVxdWF0aW9uIGlzIHRvIHJlZmVyIHRvIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIGVxdWF0aW9uIGluc3RlYWQgb2YgdHlwaW5nIHRoZSBhY3R1YWwgdmFsdWVzIG91dC4NCiMjIyBUaGlzIGlzIGRlbW9uc3RyYXRlZCBiZWxvdy4NCg0Kc2FsZXNfcHJlZGljdGVkID0gY29lZihyZWcpWzFdICsgY29lZihyZWcpWzJdICogNzUNCmNvZWYocmVnKVsxXSAjIGludGVyY2VwdA0KY29lZihyZWcpWzJdICMgc2xvcGUNCnNhbGVzX3ByZWRpY3RlZA0KDQpgYGANCg0KDQpBIGhpZ2ggUi1TcXVhcmVkIHZhbHVlIGluZGljYXRlcyB0aGF0IHRoZSBtb2RlbCBpcyBhIGdvb2QgZml0LCBidXQgbm90IHBlcmZlY3QuIEZvciB0aGUgY2FzZSBvZiBTYWxlcyB2ZXJzdXMgUmFkaW8gd2Ugd2lsbCBvdmVybGF5IHRoZSB0cmVuZCBsaW5lIHJlcHJlc2VudGluZyB0aGUgcmVncmVzc2lvbiBlcXVhdGlvbiBvdmVyIHRoZSBvcmlnaW5hbCBwbG90LiBUaGlzIHdpbGwgc2hvdyBob3cgZmFyIHRoZSBwcmVkaWN0ZWQgdmFsdWVzIGFyZSBmcm9tIHRoZSBhY3R1YWwgdmFsdWUuIFRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGFjdHVhbCBzYWxlcyAoY2lyY2xlcykgYW5kIHRoZSBwcmVkaWN0ZWQgc2FsZXMgKHNvbGlkIGxpbmUpIGlzIGNhcHR1cmVkIGluIHRoZSByZXNpZHVhbCBlcnJvciBjYWxjdWxhdGlvbnMgYXMgcmVwb3J0ZWQgZWFybGllciBieSB0aGUgc3VtbWFyeSBmdW5jdGlvbi4NCg0KYGBge3J9DQojUGxvdCBSYWRpbyBhbmQgU2FsZXMgDQpwbG90KHJhZGlvLHNhbGVzKQ0KDQojQWRkIGEgdHJlbmQgbGluZSBwbG90IHVzaW5nIHRoZSBsaW5lYXIgbW9kZWwgd2UgY3JlYXRlZCBhYm92ZQ0KYWJsaW5lKHJlZywgY29sPSJibHVlIixsd2Q9MikgDQpgYGANCg0KTm90ZSB0aGF0IHRoZSB0cmVuZCBsaW5lIHNob3duIGhlcmUgaXMgdGhlIG9uZSBjb3JyZXNwb25kaW5nIHRvIHRoZSByZWdyZXNzaW9uIGVxdWF0aW9uLiAgSXQgaXMgZGlmZmVyZW50IGZyb20gdGhlIHNtb290aCBjdXJ2ZWQgbGluZSB1c2VkIGVhcmxpZXIgaW4gdGhlIHNjYXR0ZXIgcGxvdC4NCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAxQykgUmVwZWF0IHRoZSBhYm92ZSBjYWxjdWxhdGlvbnMgdG8gZGVyaXZlIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBmb3IgU2FsZXMgdmVyc3VzIFRWID8gDQo8L3NwYW4+DQpgYGB7cn0NCiNTaW1wbGUgTGluZWFyIFJlZ3Jlc3Npb24gLSB0aGUgUiBmdW5jdGlvbiBsbSgpDQpyZWcgPC0gbG0oc2FsZXMgfiB0dikNCg0KI1N1bW1hcnkgb2YgTW9kZWwNCnN1bW1hcnkocmVnKQ0KDQpgYGANCg0KYGBge3J9DQojUGxvdCBUViBhbmQgU2FsZXMgDQpwbG90KHR2LHNhbGVzKQ0KDQojQWRkIGEgdHJlbmQgbGluZSBwbG90IHVzaW5nIHRoZSBsaW5lYXIgbW9kZWwgd2UgY3JlYXRlZCBhYm92ZQ0KYWJsaW5lKHJlZywgY29sPSJibHVlIixsd2Q9MikgDQpgYGANCg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFEKSBXcml0ZSBkb3duIHRoZSBlcXVhdGlvbiBmb3IgdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLiBJZGVudGlmeSB0aGUgdmFsdWVzIGZvciB0aGUgaW50ZXJjZXB0IGFuZCB0aGUgc2xvcGUuDQo8L3NwYW4+DQoNCllzYWxlcz0gLTQyMjI5LjIxICsgMjIxLjEwWHR2IGludGVyY2VwdCBpcyAtNDIyMjkuMjEsIGFuZCBzbG9wZSBpcyAyMjEuMTAuIA0KDQoNCg0KLS0tLS0tLS0tLQ0KDQojIyMgVGFzayAyOiBNdWx0aXBsZSBMaW5lYXIgUmVncmVzc2lvbg0KDQpNYW55IHRpbWVzIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIGZhY3RvciBvciB2YXJpYWJsZSB0aGF0IGFmZmVjdCB0aGUgcHJlZGljdGlvbiBvZiBhbiBvdXRjb21lLiBXaGlsZSBpbmNyZWFzZWQgcmFpbmZhbGwgaXMgYSBnb29kIHByZWRpY3RvciBvZiBpbmNyZWFzZWQgY3JvcCBzdXBwbHksIGRlY3JlYXNlZCBoZXJiaXZvcmVzIGNhbiBhbHNvIHJlc3VsdCBpbiBhbiBpbmNyZWFzZSBvZiBjcm9wcy4gVGhpcyBpZGVhIGlzIGEgbG9vc2UgbWV0YXBob3IgZm9yIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uLiANCg0KSW4gUiwgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gdGFrZXMgdGhlIGZvcm0gb2YgYGxtKHkgfiB4MCArIHgxICsgeDIgKyAuLi4gKWAsIHdoZXJlIHkgaXMgdGhlIHZhbHVlIHRoYXQgaXMgYmVpbmcgcHJlZGljdGVkLCBvciB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLCBhbmQgdGhlIHggdmFyaWFibGVzIGFyZSB0aGUgcHJlZGljdG9ycyBvciB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIA0KDQpMZXRzIGNyZWF0ZSBhIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIHByZWRpY3Rpbmcgc2FsZXMgdXNpbmcgYm90aCBpbmRlcGVuZGVudCB2YXJpYWJsZXMgcmFkaW8gYW5kIHR2LiANCg0KYGBge3J9DQojTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24gTW9kZWwNCm1scjEgPC1sbShzYWxlcyB+IHJhZGlvICsgdHYpDQoNCiNTdW1tYXJ5IG9mIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsDQpzdW1tYXJ5KG1scjEpDQpgYGANCg0KTm90ZSB0aGUgdmFsdWVzIG9mIDAuOTU3NyBmb3IgUi1zcXVhcmVkIGFuZCAwLjk1MjcgZm9yIHRoZSBBZGp1c3RlZCBSLXNxdWFyZWQuICBUaGUgcHJlZGljdGVkIHNhbGVzIGNhbiBhZ2FpbiBiZSBjYWxjdWxhdGVkIGdpdmVuIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwuICBUaGUgZXhhbXBsZSBiZWxvdyBjYWxjdWxhdGVzIHRoZSBwcmVkaWN0ZWQgc2FsZXMgZm9yIFRWID0gMjcwIGFuZCBSYWRpbyA9IDc1Lg0KDQpgYGB7cn0NCiMgc2FsZXNfcHJlZGljdGVkID0gcmFkaW8gKyB0dg0Kc2FsZXNfcHJlZGljdGVkID0gY29lZihtbHIxKVsxXSArIGNvZWYobWxyMSlbMl0qKDc1KSArIGNvZWYobWxyMSlbM10qKDI3MCkNCnNhbGVzX3ByZWRpY3RlZA0KDQpgYGANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAyQSkgQ29tcGFyZSB0aGUgY2FsY3VsYXRlZCBwcmVkaWN0ZWQgc2FsZXMgIHRvIHRoZSBhY3R1YWwgc2FsZXMgZm91bmQgaW4gdGhlIGZpbGUsIGJ5IGNhbGN1bGF0aW5nIHRoZSBkaWZmZXJlbmNlIGVycm9yIHNxdWFyZWQuDQo8L3NwYW4+DQoNClRoZSBwcmVkaWN0ZWQgc2FsZXNpcyAkMTY1NzguMywgYW5kIHRoZSBhY3R1YWwgc2FsZXMgaXMgMTY4NzYuDQpgYGB7cn0NCmVycm9yc3F1YXJlZCA9ICgxNjU3OC4zLTE2ODc2KV4yDQplcnJvcnNxdWFyZWQNCmBgYA0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAyQikgRmlsbCBpbiB0aGUgY29kZSBjaHVuayBiZWxvdyB0byBjcmVhdGUgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIGVhY2ggb2YgdGhlIHNwZWNpZmllZCB0d28gdXNlIGNhc2VzLCBhbmQgZGlzcGxheSB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzLg0KPC9zcGFuPg0KDQpgYGB7cn0NCiNtbHIyID0gU2FsZXMgcHJlZGljdGVkIGJ5IHJhZGlvLCB0diwgYW5kIHBvcw0KI1N1bW1hcnkgb2YgTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24gTW9kZWwNCm1scjIgPC1sbShzYWxlcyB+IHJhZGlvICsgdHYgKyBwb3MpDQpzdW1tYXJ5KG1scjIpDQoNCiNtbHIzID0gU2FsZXMgcHJlZGljdGVkIGJ5IHJhZGlvLCB0diwgcG9zLCBhbmQgcGFwZXINCiNTdW1tYXJ5IG9mIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsDQptbHIzIDwtbG0oc2FsZXMgfiByYWRpbyArIHR2ICsgcG9zICsgcGFwZXIpDQpzdW1tYXJ5KG1scjMpDQpgYGANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAyQykgV3JpdGUgZG93biBhIHN1bW1hcnkgcGFyYWdyYXBoIG9mIHRoZSByZWdyZXNzaW9uIGVxdWF0aW9ucyBhbmQgY29ycmVzcG9uZGluZyB2YWx1ZXMgZm9yIFItc3F1YXJlZCBhbmQgQWRqdXN0ZWQgUi1zcXVhcmVkIGZvciBlYWNoIG9mIHRoZSB0aHJlZSBjYXNlczogbWxyMSwgbWxyMiwgYW5kIG1scjMNCjwvc3Bhbj4NCg0KbWxyMTogWXNhbGVzID0gLTE3MTUwLjQ2ICsgMjc1LjY5WHJhZGlvICsgNDguMzRYdHYgci1zcXVhcmVkID0gMC45NTc3IGFkanVzdGVkIHItc3F1YXJlZCA9IDAuOTUyNw0KDQptbHIyOiBZc2FsZXMgPSAtMTU0OTEuMjMgKyAyOTEuMzZYcmFkaW8gKyAzOC4yNiBYdHYgLSAxMDcuNjJYcG9zIHItc3F1YXJlZCA9IDAuOTU4NSBhZGp1c3RlZCByLXNxdWFyZWQgPSAwLjk1MDggDQoNCm1scjM6IFlzYWxlcyA9IC0xMzgwMS4wMTUgKyAyOTQuMjI0WHJhZGlvICsgMzMuMzY5WHR2IC0gMTI4Ljg3NVhwb3MgLSA5LjE1OVhwYXBlciByLXNxdWFyZWQgPSAwLjk2MTIgYWRqdXN0ZWQgci1zcXVhcmVkID0gMC45NTA5DQoNCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPg0KIyMjIyMgMkQpIEJhc2VkIHNvbGVseSBvbiB0aGUgdmFsdWVzIGZvciBSLXNxdWFyZWQgYW5kIEFkaiBSLXNxdWFyZWQsIHdoaWNoIG9mIHRoZSB0aHJlZSBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbHMgbWxyMSwgbWxyMiwgbWxyMywgaXMgYmVzdCBpbiBwcmVkaWN0aW5nIHNhbGVzLiBFeHBsYWluIHdoeS4gDQo8L3NwYW4+DQoNCkFjY29yZGluZyB0byBBZGogUi1zcXVhcmVkLCB0aGUgYmVzdCBpbiBwcmVkaWN0aW4gaXMgbWxyMSBiZWN1YXNlIGl0IGlzIGhhdmUgaGlnaGVyIEFkaiByLXNxdWFyZSB2YWx1ZSB0aGFuIG90aGVyIHR3by4gDQoNCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPg0KIyMjIyMgMkUpIENhbGN1bGF0ZSB0aGUgc2FsZXMgdmFsdWUgZm9yIGVhY2ggb2YgdGhlIGFib3ZlIHRocmVlIG1vZGVscyBieSBzdWJzdGl0dXRpbmcgZm9yIHRoZSB2YWx1ZXMgYFJhZGlvID0gNjlgICwgYFRWID0gMjU1YCAsIGBQT1MgPSAxLjVgLCBhbmQgYFBhcGVyID0gNzVgLiBDb21wYXJlIHlvdXIgY2FsY3VsYXRlZCBzYWxlcyB0byB0aGUgYWN0dWFsIHZhbHVlIGFzIG9idGFpbmVkIGZyb20gdGhlIGRhdGEgZmlsZS4gV2hpY2ggbW9kZWwgaXMgYmVzdCBhdCBmaXR0aW5nIHRoZSBhY3R1YWwgc2FsZXMgdmFsdWU/IFF1YW50aWZ5IHlvdXIgYW5zd2VyIGJ5IGNhbGN1bGF0aW5nIHRoZSBlcnJvciBzcXVhcmVkIGZvciBlYWNoIGNhc2UuICBDb21wYXJlIHlvdXIgZmluZGluZ3MgdG8geW91ciBhbnN3ZXIgaW4gMkQpIGFuZCBleHBsYWluIGFueSBkaXNjcmVwZW5jaWVzLiAgSGludDogYmVzdCBmaXR0aW5nIGlzIG5vdCBzYW1lIGFzIGJlc3QgcHJlZGljdGluZyENCjwvc3Bhbj4NCmBgYHtyfQ0KIyBDb21wdXRlDQpzYWxlc19wcmVkaWN0ZWQgPSBjb2VmKG1scjEpWzFdICsgY29lZihtbHIxKVsyXSo2OSArIGNvZWYobWxyMSlbM10qMjU1DQpzYWxlc19wcmVkaWN0ZWQNCmBgYA0KYGBge3J9DQplcnJvcnNxdWFyZWQgPSAoMTQxOTkuMDUtMTM5NjUpXjINCmVycm9yc3F1YXJlZA0KYGBgDQpgYGB7cn0NCiMgc2FsZXNfcHJlZGljdGVkID0gcmFkaW8gKyB0diArIHBvcyANCnNhbGVzX3ByZWRpY3RlZCA9IGNvZWYobWxyMilbMV0gKyBjb2VmKG1scjIpWzJdKig2OSkgKyBjb2VmKG1scjIpWzNdKigyNTUpKyBjb2VmKG1scjIpWzRdKjEuNQ0Kc2FsZXNfcHJlZGljdGVkDQpgYGANCmBgYHtyfQ0KZXJyb3JzcXVhcmVkID0gKDE0MjA4LjQ0LTEzOTY1KV4yDQplcnJvcnNxdWFyZWQNCmBgYA0KYGBge3J9DQojIHNhbGVzX3ByZWRpY3RlZCA9IHJhZGlvICsgdHYgKyBwb3MgKyBwYXBlcg0Kc2FsZXNfcHJlZGljdGVkID0gY29lZihtbHIzKVsxXSArIGNvZWYobWxyMylbMl0qKDY5KSArIGNvZWYobWxyMylbM10qKDI1NSkrIGNvZWYobWxyMylbNF0qMS41KyBjb2VmKG1scjMpWzVdKjc1DQpzYWxlc19wcmVkaWN0ZWQNCmBgYA0KYGBge3J9DQplcnJvcnNxdWFyZWQgPSAoMTQxMjkuMzItMTM5NjUpXjINCmVycm9yc3F1YXJlZA0KYGBgDQoNClRoZSBiZXN0IG1vZGVsIGZpdCB0aGUgYWN0dWFsIHNhbGVzIHZhbHVlIGlzIG1scjMgYmVjYXVzZSBpdCBoYXMgbG93ZXIgdmFsdWUgb2YgZXJyb3Igc3F1YXJlZCB0aGFuIG90aGVyIHR3byxhbHNvIGlmIHRoZXJlIGFyZSAgbW9yZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYXJlIGFkZGVkLCB0aGUgUi1zcXVhcmVkIHdpbGwga2VlcCBvbiBpbmNyZWFzaW5nLiBCdXQgaW4gMkQsIG1vZGVsIDMgaXMgbm90IHRoZSBiZXN0IGluIHByZWRpY3Rpbmcgc2FsZXMgYmFzZWQgb24gaXRzIGxvd2VyIGFkanVzdGVkIHItc3F1YXJlZCB0aGFuIG90aGVyIHR3bywgYmVjYXVzZSBhZGp1c3RlZCByLXNxdWFyZWQgaW5jcmVhc2VzIG9ubHkgaWYgdGhlIGFkZGVkIHZhcmlhYmxlIHByb3ZpZGVzIGJldHRlciBwcmVkaWN0aW9uLiAgDQotLS0tLS0tLS0tDQoNCiMjIyBUYXNrIDM6IFdhdHNvbiBBbmFseXRpY3MgUHJlZGljdA0KDQpXYXRzb24gQW5hbHl0aWNzIGNvbnRhaW5zIGEgbW9kdWxlIGZvciBQcmVkaWN0LCBiZXNpZGVzIHRoZSB0d28gb3RoZXJzIGZvciBFeHBsb3JlIGFuZCBBc3NlbWJsZS4gIEFsdGhvdWdoIFdhdHNvbiBpcyBhIHVzZWZ1bCB0b29sIGl0IHNob3VsZCBuZXZlciBiZSB0cmVhdGVkIGFzIGEgYmxhY2sgYm94LiAgSW4gb3RoZXIgd29yZHMgdGhlcmUgYXJlIG1hbnkgY2lyY3Vtc3RhbmNlcyB3aGVyZSBXYXRzb24gY2FuIGZhaWwgdG8gbWFrZSB0aGUgcHJvcGVyIGRpYWdub3NpcyBhbmQgc3VnZ2VzdCB0aGUgY29ycmVjdCByZW1lZGllcy4gIFRoaXMgaXMgd2h5IGl0IGlzIGNyaXRpY2FsLCBhcyBtb3JlIG9mIHRoZSBjb2duaXRpdmUgYW5hbHl0aWNzIGFuZCBhZHZhbmNlZCBtYWNoaW5lIGxlYXJuaW5nIHRvb2xzIGludmFkZSBvdXIgZW52aXJvbm1lbnQsIHRoYXQgd2UgYWxzbyBhbGxvdyByb29tIGZvciBodW1hbiBpbnRlcnZlbnRpb24gYW5kIGxlYXJuIGhvdyB0byBiZXN0IGludGVyYWN0LiANCg0KVGhlcmUgYXJlIG1hbnkgZGV0YWlscyBpbiB0aGUgUHJlZGljdCBtb2R1bGUuICBXZSB3aWxsIGtlZXAgaXQgcmVsYXRpdmVseSBzaW1wbGUgZm9yIHRoaXMgaW50cm9kdWN0b3J5IHBoYXNlLiBUbyBjb21wbGV0ZSB0aGlzIHRhc2ssIGZvbGxvdyB0aGUgZGlyZWN0aW9ucyBiZWxvdy4gTWFrZSBzdXJlIHRvIGNhcHR1cmUgYW55IHNjcmVlbnNob3RzIGFuZCB0byBhbnN3ZXIgYW55IHF1ZXN0aW9ucyB3aGVyZSByZXF1ZXN0ZWQgDQoNCiAgMS4gTG9nb24gdG8geW91ciBXYXRzb24gQW5hbHl0aWNzIGFjY291bnQgYXQgaHR0cDovL3dhdHNvbmFuYWx5dGljcy5jb20NCiAgMi4gVXBsb2FkIHRoZSBmaWxlIG1hcmtldGluZy5jc3YgdW5sZXNzIGFscmVhZHkgaW4geW91ciBmb2xkZXINCiAgMy4gRG91YmxlLWNsaWNrIG9uIHRoZSBmaWxlIHlvdSBqdXN0IHVwbG9hZGVkLg0KICANCiFbXShpbWdzL3dhdHNvbi5wbmcpDQogIA0KWW91IHdpbGwgYmUgZ3VpZGVkIHRvIGEgbmV3IHdpbmRvdyB3aGVyZSB5b3UgY2FuIGdvIHRvIHRoZSBQcmVkaWN0aXZlIEFuYWx5c2lzIG1lbnUgYW5kIHNlbGVjdCB0aGUgU3BpcmFsIG9wdGlvbi4gWW91IHdpbGwgYmUgcHJlc2VudGVkIHdpdGggYSBuZXcgZGlzY292ZXJ5IHdpbmRvdyB3aGVyZSB5b3Ugd2lsbCBoYXZlIHRvIHNlbGVjdCB5b3VyIHRhcmdldCB2YXJpYWJsZS4gIA0KICANCiFbXShpbWdzL2Rpc2NvdmVyLnBuZykNCiAgDQoNCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPg0KIyMjIyMgM0EpIEluY2x1ZGUgYSBzY3JlZW4gc2hvdCBvZiB0aGUgdG9wIHByZWRpY3RvcnMgb2Ygc2FsZXMuIENvbnNpZGVyIHRoZSBvbmUgZmllbGQgKGRyaXZlcikgcHJlZGljdGl2ZSBtb2RlbCBvbmx5IGFuZCBub3RlIHRoZSBwcmVkaWN0aXZlIHBvd2VyIHN0cmVuZ3RoIGZvciBlYWNoIGRyaXZlcg0KPC9zcGFuPg0KIVtdKGltZ3MvMS5wbmcpDQoNCg0KQmFzZWQgb24gdGhlIHNjcmVlbnNob3RzIGFib3ZlLCByYWRpbyBhbmQgdHYgYXJlIHRoZSB0b3AgcHJlZGljdG9ycyBvZiBzYWxlLiBUdiBoYXMgYSBwcmVkaWN0aXZlIHN0cmVuZ3RoIG9mIDg2JSBhbmQgcmFkaW8gaGFzIGEgcHJlZGljdGl2ZSBzdHJlbmd0aCBvZiA5MyUuDQoNCg0KDQoNCk5vdGUgdGhhdCBXYXRzb24gZm9sbG93cyBhIGRpZmZlcmVudCBhcHByb2FjaCB0byBpZGVudGlmeSBhbmQgcXVhbnRpZnkgdGhlIHByZWRpY3RpdmUgc3RyZW5ndGggb2YgZWFjaCB2YXJpYWJsZS4gU3VjaCBkZXRhaWxzIGFyZSBvdXRzaWRlIHRoZSBzY29wZSBvZiB0aGlzIGV4ZXJjaXNlLiAgV2F0c29uIHByb3ZpZGVzIGEgbG90IG9mIG9uLWxpbmUgaGVscCwgYW5kIHRoZSBpbnRlcmVzdGVkIHJlYWRlciBpcyBlbmNvdXJhZ2VkIHRvIGluZGVwZW5kZW50bHkgY2hlY2sgdGhlIG9uLWxpbmUgZG9jdW1lbnRhdGlvbiBhbmQgZXhwbG9yZSB0aGUgbWFueSBjYXBhYmlsaXRpZXMgb2YgV2F0c29uLg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDNCKSBIb3cgZG8gV2F0c29uIHJlc3VsdHMgcmVjb25jaWxlIHdpdGggeW91ciBmaW5kaW5ncyBiYXNlZCBvbiB0aGUgUiByZWdyZXNzaW9uIGFuYWx5c2lzIGluIHRhc2sgMj8gRXhwbGFpbi4NCjwvc3Bhbj4NCg0KVGhlIGFkanVzdGVkIFIgc3F1YXJlIHZhbHVlIGFuZCBXYXRzb24gYm90aCBwcm92ZWQgdGhhdCByYWRpbyBhbmQgdHYgaGF2ZSB0aGUgaGlnaGVzdCBwcmVkaWN0aXZlIHBvd2VyIGZvciBzYWxlcy4gV2hpY2ggaW5kaWNhdGUgdGhhdCB0aGUgcmVzdWx0IHdlIGZvdW5kIGluIHRhc2sgMiBpcyB0cnVlLiBSYWRpbyBoYWQgcHJlZGljdGluZyBzdHJlbmd0aCBvZiA5MyUgYW5kIHR2IGhhZCA4NiUNCg==