library(tidyverse)
library(openintro)
Exercise 1
The dimensions of this dataset are 123 columns or variables and 1458 rows or observations.
## [1] 1458 123
Exercise 2
Relationships between 2 numerical variables are usually best shown in scatterplots. The relationship between pf_expression_control and pf_score can be estimated to be linear as paired data points each case can be seen to overall to move in same direction.
Cases where one or the other of these variables included NA were dropped, shaving the dimensions of the dataset down to 1378 cases (dropping 80 rows).
hfi <- hfi %>% filter(!is.na(pf_expression_control), !is.na(pf_score))
ggplot(hfi, aes(pf_expression_control,pf_score)) + geom_point()
The correlation of the data is fairly high at .796. Correlation is the normalized value of covariance and measures how the values of 2 quantitative variables vary together (i.e. joint variability). It is important to visualize the the relationship first in a scatterplot as the correlation coefficient assumes a linear relationship.
hfi %>%
summarise(correlation = cor(pf_expression_control, pf_score))
## # A tibble: 1 x 1
## correlation
## <dbl>
## 1 0.796
Exercise 3
could not get the plot_ss() function to work for me despite dropping the NA values
Exercise 4
model_pf_score <- lm(pf_score ~ pf_expression_control, data=hfi)
summary(model_pf_score)
##
## Call:
## lm(formula = pf_score ~ pf_expression_control, data = hfi)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.8467 -0.5704 0.1452 0.6066 3.2060
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.61707 0.05745 80.36 <2e-16 ***
## pf_expression_control 0.49143 0.01006 48.85 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.8318 on 1376 degrees of freedom
## Multiple R-squared: 0.6342, Adjusted R-squared: 0.634
## F-statistic: 2386 on 1 and 1376 DF, p-value: < 2.2e-16
Exercise 5
The linear model to predict total human freedom score using personal freedom expression control as the explanatory variable:
y^hat = 5.15368 + .3498 x pf_expression_control
Starting at intercept of 5 when personal freedom expression score is 0, the total human score increases by .35 for every unit of 1 increase in personal freedom of expression score.
Only 57% of variation in total human score is explained by this model.
model_hf_score <- lm(hf_score ~ pf_expression_control, data=hfi)
summary(model_hf_score)
##
## Call:
## lm(formula = hf_score ~ pf_expression_control, data = hfi)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.6198 -0.4908 0.1031 0.4703 2.2933
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.153687 0.046070 111.87 <2e-16 ***
## pf_expression_control 0.349862 0.008067 43.37 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.667 on 1376 degrees of freedom
## Multiple R-squared: 0.5775, Adjusted R-squared: 0.5772
## F-statistic: 1881 on 1 and 1376 DF, p-value: < 2.2e-16
Exercise 6
At 6.7 rating for pf_expression_control score, the linear model would predict the personal freedom score as 7.9097.
hfi$predicted_pf_score <- predict(model_pf_score)
hfi$residuals_pf_score <- residuals(model_pf_score)
ggplot(data = hfi, aes(x = pf_expression_control, y = pf_score)) +
geom_segment(aes(xend=pf_expression_control, yend=predicted_pf_score), alpha=.4) +
geom_point(aes(color=residuals_pf_score)) +
scale_color_gradient2(low = "blue", mid = "lightblue", high = "red") +
stat_smooth(method = "lm", se = FALSE)
## `geom_smooth()` using formula 'y ~ x'
How do you extract the residual for model at a specific value of the explanatory variable within a large dataset?
Exercise 7
No pattern is apparent in the plot of absolute values of the residuals against fitted line.
ggplot(data = model_pf_score, aes(x = .fitted, y = .resid)) +
geom_point(aes(color=.resid)) +
scale_color_gradient2(low = "blue", mid = "lightblue", high = "red") +
geom_hline(yintercept = 0, linetype = "dashed") +
xlab("Fitted values") +
ylab("Residuals")

Exercise 8
Yes, the conditions for nearly normal residuals have been met.
The histogram of the residuals suggest the distribution is left skewed where the peak of the data is right of center and the tail is much longer on the left.
This shows that more residuals tended to be negative than positive or in other words, that the model predicted more personal freedom scores that were higher than their actual observed values.
The skewness does not appear to be greater than 1 and is in the acceptable range to assume data is normally distributed.
ggplot(data = model_pf_score, aes(x = .resid, fill= cut(.resid, 100))) +
geom_histogram(binwidth = .5, show.legend=FALSE) +
xlab("Residuals")
Normal probability plots of the residuals are helpful to see if there are any outliers to the data that skews normality assumptions. We can see there is deviation from the theoretical line where multiple observed data points had lower residuals (higher observed personal freedom scores) than would have been predicted using the linear model under the assumption of normal distribution.
These can be attributed to outliers in the response variable personal freedom score that could not be predicted accurately by the model and the fact that the model has an adjusted R^2 of only 63%.
ggplot(data = model_pf_score, aes(sample = .resid)) +
stat_qq() +
stat_qq_line(line.p = c(0.25, 0.75), color="red",size=1)

Exercise 9
The residuals roughly form a “horizontal band” around the 0 line. This indicates that the variance of the residuals is approximately constant. It should be noted that there are clear outliers observed and these outliers are mostly negative residuals. This indicates that there are more outliers representing low freedom scores in the dataset. One could argue their presence negates the assumption of normally distributed data. However, there are no extreme outliers in the response variable and so normality can still be assumed.
pf_score_Q1 = fivenum(hfi$pf_score)[2]
pf_score_Q3 = fivenum(hfi$pf_score)[4]
pf_score_IQR = IQR(hfi$pf_score)
EOF1 = pf_score_Q1 - 3*pf_score_IQR
EOF2 = pf_score_Q3 + 3*pf_score_IQR
EO_min_count <- sum(hfi$pf_score < EOF1)
EO_max_count <- sum(hfi$pf_score > EOF2)
EO_min_count
## [1] 0
## [1] 0
More Practice
Exercise 1
At a glance, there does appear to be a linear relationship between the 2 variables pf_expression_influence and pf_score. Values appear to jointly increase for both variables.
ggplot(hfi, aes(pf_expression_influence,pf_score)) + geom_point()

Exercise 2
This seems to be a comparable model to using pf_expression_control as predictor variable to the personal freedom score. Adjusted R^2 is 62% in comparison to the 63% of using pf_expression_control as predictor variable. The intercept is similar at approximately 5; the rate of change in personal freedom is slightly higher at .41 increase in pf_score for every unit increase of pf_expression_influence. Rate of change predicted was only .35 increase when using pf_expression_control.
This model is not a noticeably better predicting personal freedom than using pf_expression_control.
model_pf_score_2 <- lm(pf_score ~ pf_expression_influence, data=hfi)
summary(model_pf_score_2)
##
## Call:
## lm(formula = pf_score ~ pf_expression_influence, data = hfi)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.9688 -0.5830 0.1681 0.5903 3.6730
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.06135 0.05064 99.95 <2e-16 ***
## pf_expression_influence 0.41150 0.00869 47.36 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.8482 on 1376 degrees of freedom
## Multiple R-squared: 0.6197, Adjusted R-squared: 0.6195
## F-statistic: 2243 on 1 and 1376 DF, p-value: < 2.2e-16
hfi %>%
summarise(correlation = cor(pf_expression_influence, pf_score))
## # A tibble: 1 x 1
## correlation
## <dbl>
## 1 0.787
Exercise 3
I would have expected that those countries with the most political influence in newspapers to have a strong predictor on personal freedom. Freedom of press has long been tied up in the idea of personal liberty & freedom. However, on graphing these two variables, it is obvious there is no linear relationship between the 2 variables. Even newspapers that rate a 10 as least exterted poltical influence were associated with a range of personal freedom scores.
The linear model, using influence on newspapers as predictor variable only has an adjusted R^2 of 32%. If only 32% of the variation in personal freedom scores can be supposedly accounted for by the model, this is not a good fit model for making predictions and should be rejected.
ggplot(hfi, aes(pf_expression_newspapers,pf_score)) + geom_point()
## Warning: Removed 255 rows containing missing values (geom_point).

model_pf_score_3 <- lm(pf_score ~ pf_expression_newspapers, data=hfi)
summary(model_pf_score_3)
##
## Call:
## lm(formula = pf_score ~ pf_expression_newspapers, data = hfi)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.9877 -0.8174 0.0780 0.9253 2.4888
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.77611 0.13553 27.86 <2e-16 ***
## pf_expression_newspapers 0.40639 0.01532 26.53 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.095 on 1121 degrees of freedom
## (255 observations deleted due to missingness)
## Multiple R-squared: 0.3858, Adjusted R-squared: 0.3852
## F-statistic: 704.1 on 1 and 1121 DF, p-value: < 2.2e-16
LS0tDQp0aXRsZTogIkxhYiA4IC0gU2ltcGxlIFJlZ3Jlc3Npb24iDQphdXRob3I6ICJDYXNzYW5kcmEgQm95bGFuIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQNCi0tLQ0KDQpgYGB7ciBsb2FkLXBhY2thZ2VzLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG9wZW5pbnRybykNCmBgYA0KDQojIEV4ZXJjaXNlIDENCg0KVGhlIGRpbWVuc2lvbnMgb2YgdGhpcyBkYXRhc2V0IGFyZSAxMjMgY29sdW1ucyBvciB2YXJpYWJsZXMgYW5kIDE0NTggcm93cyBvciBvYnNlcnZhdGlvbnMuDQoNCmBgYHtyfQ0KZGltKGhmaSkNCiNnbGltcHNlKGhmaSkNCmBgYA0KDQojIEV4ZXJjaXNlIDINClJlbGF0aW9uc2hpcHMgYmV0d2VlbiAyIG51bWVyaWNhbCB2YXJpYWJsZXMgYXJlIHVzdWFsbHkgYmVzdCBzaG93biBpbiBzY2F0dGVycGxvdHMuICBUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcGZfZXhwcmVzc2lvbl9jb250cm9sIGFuZCBwZl9zY29yZSBjYW4gYmUgZXN0aW1hdGVkIHRvIGJlIGxpbmVhciBhcyBwYWlyZWQgZGF0YSBwb2ludHMgZWFjaCBjYXNlIGNhbiBiZSBzZWVuIHRvIG92ZXJhbGwgdG8gbW92ZSBpbiBzYW1lIGRpcmVjdGlvbi4NCg0KQ2FzZXMgd2hlcmUgb25lIG9yIHRoZSBvdGhlciBvZiB0aGVzZSB2YXJpYWJsZXMgaW5jbHVkZWQgTkEgd2VyZSBkcm9wcGVkLCBzaGF2aW5nIHRoZSBkaW1lbnNpb25zIG9mIHRoZSBkYXRhc2V0IGRvd24gdG8gMTM3OCBjYXNlcyAoZHJvcHBpbmcgODAgcm93cykuDQpgYGB7ciByZW1vdmluZy1OQS12YWx1ZXN9DQpoZmkgPC0gaGZpICU+JSBmaWx0ZXIoIWlzLm5hKHBmX2V4cHJlc3Npb25fY29udHJvbCksICFpcy5uYShwZl9zY29yZSkpDQoNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChoZmksIGFlcyhwZl9leHByZXNzaW9uX2NvbnRyb2wscGZfc2NvcmUpKSArIGdlb21fcG9pbnQoKQ0KYGBgDQpUaGUgY29ycmVsYXRpb24gb2YgdGhlIGRhdGEgaXMgZmFpcmx5IGhpZ2ggYXQgLjc5Ni4gDQpDb3JyZWxhdGlvbiBpcyB0aGUgbm9ybWFsaXplZCB2YWx1ZSBvZiBjb3ZhcmlhbmNlIGFuZCBtZWFzdXJlcyBob3cgdGhlIHZhbHVlcyBvZiAyIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMgdmFyeSB0b2dldGhlciAoaS5lLiBqb2ludCB2YXJpYWJpbGl0eSkuICBJdCBpcyBpbXBvcnRhbnQgdG8gdmlzdWFsaXplIHRoZSB0aGUgcmVsYXRpb25zaGlwIGZpcnN0IGluIGEgc2NhdHRlcnBsb3QgYXMgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGFzc3VtZXMgYSBsaW5lYXIgcmVsYXRpb25zaGlwLiANCg0KYGBge3J9DQpoZmkgJT4lDQogIHN1bW1hcmlzZShjb3JyZWxhdGlvbiA9IGNvcihwZl9leHByZXNzaW9uX2NvbnRyb2wsIHBmX3Njb3JlKSkNCmBgYA0KIyBFeGVyY2lzZSAzDQpjb3VsZCBub3QgZ2V0IHRoZSBwbG90X3NzKCkgZnVuY3Rpb24gdG8gd29yayBmb3IgbWUgZGVzcGl0ZSBkcm9wcGluZyB0aGUgTkEgdmFsdWVzDQoNCiMgRXhlcmNpc2UgNA0KYGBge3J9DQptb2RlbF9wZl9zY29yZSA8LSBsbShwZl9zY29yZSB+IHBmX2V4cHJlc3Npb25fY29udHJvbCwgZGF0YT1oZmkpDQoNCnN1bW1hcnkobW9kZWxfcGZfc2NvcmUpDQpgYGANCg0KIyBFeGVyY2lzZSA1DQoNClRoZSBsaW5lYXIgbW9kZWwgdG8gcHJlZGljdCB0b3RhbCBodW1hbiBmcmVlZG9tIHNjb3JlIHVzaW5nIHBlcnNvbmFsIGZyZWVkb20gZXhwcmVzc2lvbiBjb250cm9sIGFzIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZToNCg0KeV5oYXQgPSA1LjE1MzY4ICsgLjM0OTggeCBwZl9leHByZXNzaW9uX2NvbnRyb2wNCg0KU3RhcnRpbmcgYXQgaW50ZXJjZXB0IG9mIDUgd2hlbiBwZXJzb25hbCBmcmVlZG9tIGV4cHJlc3Npb24gc2NvcmUgaXMgMCwgdGhlIHRvdGFsIGh1bWFuIHNjb3JlIGluY3JlYXNlcyBieSAuMzUgZm9yIGV2ZXJ5IHVuaXQgb2YgMSBpbmNyZWFzZSBpbiBwZXJzb25hbCBmcmVlZG9tIG9mIGV4cHJlc3Npb24gc2NvcmUuDQoNCk9ubHkgNTclIG9mIHZhcmlhdGlvbiBpbiB0b3RhbCBodW1hbiBzY29yZSBpcyBleHBsYWluZWQgYnkgdGhpcyBtb2RlbC4NCmBgYHtyfQ0KbW9kZWxfaGZfc2NvcmUgPC0gbG0oaGZfc2NvcmUgfiBwZl9leHByZXNzaW9uX2NvbnRyb2wsIGRhdGE9aGZpKQ0KDQpzdW1tYXJ5KG1vZGVsX2hmX3Njb3JlKQ0KYGBgDQojIEV4ZXJjaXNlIDYNCg0KQXQgNi43IHJhdGluZyBmb3IgcGZfZXhwcmVzc2lvbl9jb250cm9sIHNjb3JlLCB0aGUgbGluZWFyIG1vZGVsIHdvdWxkIHByZWRpY3QgdGhlIHBlcnNvbmFsIGZyZWVkb20gc2NvcmUgYXMgNy45MDk3Lg0KYGBge3J9DQpoZmkkcHJlZGljdGVkX3BmX3Njb3JlIDwtIHByZWRpY3QobW9kZWxfcGZfc2NvcmUpDQpoZmkkcmVzaWR1YWxzX3BmX3Njb3JlIDwtIHJlc2lkdWFscyhtb2RlbF9wZl9zY29yZSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gaGZpLCBhZXMoeCA9IHBmX2V4cHJlc3Npb25fY29udHJvbCwgeSA9IHBmX3Njb3JlKSkgKw0KICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQ9cGZfZXhwcmVzc2lvbl9jb250cm9sLCB5ZW5kPXByZWRpY3RlZF9wZl9zY29yZSksIGFscGhhPS40KSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yPXJlc2lkdWFsc19wZl9zY29yZSkpICsNCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJibHVlIiwgbWlkID0gImxpZ2h0Ymx1ZSIsIGhpZ2ggPSAicmVkIikgKw0KICBzdGF0X3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKQ0KYGBgDQpIb3cgZG8geW91IGV4dHJhY3QgdGhlIHJlc2lkdWFsIGZvciBtb2RlbCBhdCBhIHNwZWNpZmljIHZhbHVlIG9mIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZSB3aXRoaW4gYSBsYXJnZSBkYXRhc2V0Pw0KDQojIEV4ZXJjaXNlIDcNCk5vIHBhdHRlcm4gaXMgYXBwYXJlbnQgaW4gdGhlIHBsb3Qgb2YgYWJzb2x1dGUgdmFsdWVzIG9mIHRoZSByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgbGluZS4gDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbW9kZWxfcGZfc2NvcmUsIGFlcyh4ID0gLmZpdHRlZCwgeSA9IC5yZXNpZCkpICsNCiAgICBnZW9tX3BvaW50KGFlcyhjb2xvcj0ucmVzaWQpKSArDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAiYmx1ZSIsIG1pZCA9ICJsaWdodGJsdWUiLCBoaWdoID0gInJlZCIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB4bGFiKCJGaXR0ZWQgdmFsdWVzIikgKw0KICB5bGFiKCJSZXNpZHVhbHMiKQ0KYGBgDQoNCiMgRXhlcmNpc2UgOA0KWWVzLCB0aGUgY29uZGl0aW9ucyBmb3IgbmVhcmx5IG5vcm1hbCByZXNpZHVhbHMgaGF2ZSBiZWVuIG1ldC4NCg0KVGhlIGhpc3RvZ3JhbSBvZiB0aGUgcmVzaWR1YWxzIHN1Z2dlc3QgdGhlIGRpc3RyaWJ1dGlvbiBpcyBsZWZ0IHNrZXdlZCB3aGVyZSB0aGUgcGVhayBvZiB0aGUgZGF0YSBpcyByaWdodCBvZiBjZW50ZXIgYW5kIHRoZSB0YWlsIGlzIG11Y2ggbG9uZ2VyIG9uIHRoZSBsZWZ0LiANCg0KVGhpcyBzaG93cyB0aGF0IG1vcmUgcmVzaWR1YWxzIHRlbmRlZCB0byBiZSBuZWdhdGl2ZSB0aGFuIHBvc2l0aXZlIG9yIGluIG90aGVyIHdvcmRzLCB0aGF0IHRoZSBtb2RlbCBwcmVkaWN0ZWQgbW9yZSBwZXJzb25hbCBmcmVlZG9tIHNjb3JlcyB0aGF0IHdlcmUgaGlnaGVyIHRoYW4gdGhlaXIgYWN0dWFsIG9ic2VydmVkIHZhbHVlcy4NCg0KVGhlIHNrZXduZXNzIGRvZXMgbm90IGFwcGVhciB0byBiZSBncmVhdGVyIHRoYW4gMSBhbmQgaXMgaW4gdGhlIGFjY2VwdGFibGUgcmFuZ2UgdG8gYXNzdW1lIGRhdGEgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbW9kZWxfcGZfc2NvcmUsIGFlcyh4ID0gLnJlc2lkLCBmaWxsPSBjdXQoLnJlc2lkLCAxMDApKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC41LCBzaG93LmxlZ2VuZD1GQUxTRSkgKw0KICANCiAgeGxhYigiUmVzaWR1YWxzIikNCg0KYGBgDQpOb3JtYWwgcHJvYmFiaWxpdHkgcGxvdHMgb2YgdGhlIHJlc2lkdWFscyBhcmUgaGVscGZ1bCB0byBzZWUgaWYgdGhlcmUgYXJlIGFueSBvdXRsaWVycyB0byB0aGUgZGF0YSB0aGF0IHNrZXdzIG5vcm1hbGl0eSBhc3N1bXB0aW9ucy4gIFdlIGNhbiBzZWUgdGhlcmUgaXMgZGV2aWF0aW9uIGZyb20gdGhlIHRoZW9yZXRpY2FsIGxpbmUgd2hlcmUgbXVsdGlwbGUgb2JzZXJ2ZWQgZGF0YSBwb2ludHMgaGFkIGxvd2VyIHJlc2lkdWFscyAoaGlnaGVyIG9ic2VydmVkIHBlcnNvbmFsIGZyZWVkb20gc2NvcmVzKSB0aGFuIHdvdWxkIGhhdmUgYmVlbiBwcmVkaWN0ZWQgdXNpbmcgdGhlIGxpbmVhciBtb2RlbCB1bmRlciB0aGUgYXNzdW1wdGlvbiBvZiBub3JtYWwgZGlzdHJpYnV0aW9uLiAgDQoNClRoZXNlIGNhbiBiZSBhdHRyaWJ1dGVkIHRvIG91dGxpZXJzIGluIHRoZSByZXNwb25zZSB2YXJpYWJsZSBwZXJzb25hbCBmcmVlZG9tIHNjb3JlIHRoYXQgY291bGQgbm90IGJlIHByZWRpY3RlZCBhY2N1cmF0ZWx5IGJ5IHRoZSBtb2RlbCBhbmQgdGhlIGZhY3QgdGhhdCB0aGUgbW9kZWwgaGFzIGFuIGFkanVzdGVkIFJeMiBvZiBvbmx5IDYzJS4gDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbW9kZWxfcGZfc2NvcmUsIGFlcyhzYW1wbGUgPSAucmVzaWQpKSArDQogIHN0YXRfcXEoKSArIA0KICBzdGF0X3FxX2xpbmUobGluZS5wID0gYygwLjI1LCAwLjc1KSwgY29sb3I9InJlZCIsc2l6ZT0xKQ0KYGBgDQoNCiMgRXhlcmNpc2UgOQ0KVGhlIHJlc2lkdWFscyByb3VnaGx5IGZvcm0gYSAiaG9yaXpvbnRhbCBiYW5kIiBhcm91bmQgdGhlIDAgbGluZS4gIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlIHZhcmlhbmNlIG9mIHRoZSByZXNpZHVhbHMgaXMgYXBwcm94aW1hdGVseSBjb25zdGFudC4gIEl0IHNob3VsZCBiZSBub3RlZCB0aGF0IHRoZXJlIGFyZSBjbGVhciBvdXRsaWVycyBvYnNlcnZlZCBhbmQgdGhlc2Ugb3V0bGllcnMgYXJlIG1vc3RseSBuZWdhdGl2ZSByZXNpZHVhbHMuICBUaGlzIGluZGljYXRlcyB0aGF0IHRoZXJlIGFyZSBtb3JlIG91dGxpZXJzIHJlcHJlc2VudGluZyBsb3cgZnJlZWRvbSBzY29yZXMgaW4gdGhlIGRhdGFzZXQuICBPbmUgY291bGQgYXJndWUgdGhlaXIgcHJlc2VuY2UgbmVnYXRlcyB0aGUgYXNzdW1wdGlvbiBvZiBub3JtYWxseSBkaXN0cmlidXRlZCBkYXRhLiAgSG93ZXZlciwgdGhlcmUgYXJlIG5vIGV4dHJlbWUgb3V0bGllcnMgaW4gdGhlIHJlc3BvbnNlIHZhcmlhYmxlIGFuZCBzbyBub3JtYWxpdHkgY2FuIHN0aWxsIGJlIGFzc3VtZWQuDQoNCmBgYHtyIGV4dHJlbWUtb3V0bGllci1jaGVja30NCnBmX3Njb3JlX1ExID0gZml2ZW51bShoZmkkcGZfc2NvcmUpWzJdDQpwZl9zY29yZV9RMyA9IGZpdmVudW0oaGZpJHBmX3Njb3JlKVs0XQ0KcGZfc2NvcmVfSVFSID0gSVFSKGhmaSRwZl9zY29yZSkNCg0KRU9GMSA9IHBmX3Njb3JlX1ExIC0gMypwZl9zY29yZV9JUVINCkVPRjIgPSBwZl9zY29yZV9RMyArIDMqcGZfc2NvcmVfSVFSDQoNCkVPX21pbl9jb3VudCA8LSBzdW0oaGZpJHBmX3Njb3JlIDwgRU9GMSkNCkVPX21heF9jb3VudCA8LSBzdW0oaGZpJHBmX3Njb3JlID4gRU9GMikNCg0KRU9fbWluX2NvdW50DQpFT19tYXhfY291bnQNCg0KYGBgDQoNCiMgTW9yZSBQcmFjdGljZQ0KDQojIyBFeGVyY2lzZSAxDQpBdCBhIGdsYW5jZSwgdGhlcmUgZG9lcyBhcHBlYXIgdG8gYmUgYSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIDIgdmFyaWFibGVzIHBmX2V4cHJlc3Npb25faW5mbHVlbmNlIGFuZCBwZl9zY29yZS4gIFZhbHVlcyBhcHBlYXIgdG8gam9pbnRseSBpbmNyZWFzZSBmb3IgYm90aCB2YXJpYWJsZXMuDQpgYGB7cn0NCmdncGxvdChoZmksIGFlcyhwZl9leHByZXNzaW9uX2luZmx1ZW5jZSxwZl9zY29yZSkpICsgZ2VvbV9wb2ludCgpDQpgYGANCg0KIyMgRXhlcmNpc2UgMg0KVGhpcyBzZWVtcyB0byBiZSBhIGNvbXBhcmFibGUgbW9kZWwgdG8gdXNpbmcgcGZfZXhwcmVzc2lvbl9jb250cm9sIGFzIHByZWRpY3RvciB2YXJpYWJsZSB0byB0aGUgcGVyc29uYWwgZnJlZWRvbSBzY29yZS4gIEFkanVzdGVkIFJeMiBpcyA2MiUgaW4gY29tcGFyaXNvbiB0byB0aGUgNjMlIG9mIHVzaW5nIHBmX2V4cHJlc3Npb25fY29udHJvbCBhcyBwcmVkaWN0b3IgdmFyaWFibGUuICBUaGUgaW50ZXJjZXB0IGlzIHNpbWlsYXIgYXQgYXBwcm94aW1hdGVseSA1OyAgdGhlIHJhdGUgb2YgY2hhbmdlIGluIHBlcnNvbmFsIGZyZWVkb20gaXMgc2xpZ2h0bHkgaGlnaGVyIGF0IC40MSBpbmNyZWFzZSBpbiBwZl9zY29yZSBmb3IgZXZlcnkgdW5pdCBpbmNyZWFzZSBvZiBwZl9leHByZXNzaW9uX2luZmx1ZW5jZS4gIFJhdGUgb2YgY2hhbmdlIHByZWRpY3RlZCB3YXMgb25seSAuMzUgaW5jcmVhc2Ugd2hlbiB1c2luZyBwZl9leHByZXNzaW9uX2NvbnRyb2wuDQoNClRoaXMgbW9kZWwgaXMgbm90IGEgbm90aWNlYWJseSBiZXR0ZXIgcHJlZGljdGluZyBwZXJzb25hbCBmcmVlZG9tIHRoYW4gdXNpbmcgcGZfZXhwcmVzc2lvbl9jb250cm9sLg0KYGBge3J9DQptb2RlbF9wZl9zY29yZV8yIDwtIGxtKHBmX3Njb3JlIH4gcGZfZXhwcmVzc2lvbl9pbmZsdWVuY2UsIGRhdGE9aGZpKQ0KDQpzdW1tYXJ5KG1vZGVsX3BmX3Njb3JlXzIpDQoNCmhmaSAlPiUNCiAgc3VtbWFyaXNlKGNvcnJlbGF0aW9uID0gY29yKHBmX2V4cHJlc3Npb25faW5mbHVlbmNlLCBwZl9zY29yZSkpDQpgYGANCiMjIEV4ZXJjaXNlIDMNCkkgd291bGQgaGF2ZSBleHBlY3RlZCB0aGF0IHRob3NlIGNvdW50cmllcyB3aXRoIHRoZSBtb3N0IHBvbGl0aWNhbCBpbmZsdWVuY2UgaW4gbmV3c3BhcGVycyB0byBoYXZlIGEgc3Ryb25nIHByZWRpY3RvciBvbiBwZXJzb25hbCBmcmVlZG9tLiAgRnJlZWRvbSBvZiBwcmVzcyBoYXMgbG9uZyBiZWVuIHRpZWQgdXAgaW4gdGhlIGlkZWEgb2YgcGVyc29uYWwgbGliZXJ0eSAmIGZyZWVkb20uICBIb3dldmVyLCBvbiBncmFwaGluZyB0aGVzZSB0d28gdmFyaWFibGVzLCBpdCBpcyBvYnZpb3VzIHRoZXJlIGlzIG5vIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgMiB2YXJpYWJsZXMuICBFdmVuIG5ld3NwYXBlcnMgdGhhdCByYXRlIGEgMTAgYXMgbGVhc3QgZXh0ZXJ0ZWQgcG9sdGljYWwgaW5mbHVlbmNlIHdlcmUgYXNzb2NpYXRlZCB3aXRoIGEgcmFuZ2Ugb2YgcGVyc29uYWwgZnJlZWRvbSBzY29yZXMuDQoNClRoZSBsaW5lYXIgbW9kZWwsIHVzaW5nIGluZmx1ZW5jZSBvbiBuZXdzcGFwZXJzIGFzIHByZWRpY3RvciB2YXJpYWJsZSBvbmx5IGhhcyBhbiBhZGp1c3RlZCBSXjIgb2YgMzIlLiAgSWYgb25seSAzMiUgb2YgdGhlIHZhcmlhdGlvbiBpbiBwZXJzb25hbCBmcmVlZG9tIHNjb3JlcyBjYW4gYmUgc3VwcG9zZWRseSBhY2NvdW50ZWQgZm9yIGJ5IHRoZSBtb2RlbCwgdGhpcyBpcyBub3QgYSBnb29kIGZpdCBtb2RlbCBmb3IgbWFraW5nIHByZWRpY3Rpb25zIGFuZCBzaG91bGQgYmUgcmVqZWN0ZWQuDQpgYGB7cn0NCmdncGxvdChoZmksIGFlcyhwZl9leHByZXNzaW9uX25ld3NwYXBlcnMscGZfc2NvcmUpKSArIGdlb21fcG9pbnQoKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfcGZfc2NvcmVfMyA8LSBsbShwZl9zY29yZSB+IHBmX2V4cHJlc3Npb25fbmV3c3BhcGVycywgZGF0YT1oZmkpDQoNCnN1bW1hcnkobW9kZWxfcGZfc2NvcmVfMykNCg0KYGBgDQoNCg0K