Getting Started
library(tidyverse)
library(openintro)
The data
Exercise 1
What are the dimensions of the dataset?
## [1] 1458 123
The dataset has 1458 rows and 123 columns.
Exercise 2
What type of plot would you use to display the relationship between
the personal freedom score, pf_score, and one of the other numerical
variables? Plot this relationship using the variable
pf_expression_control as the predictor. Does the relationship look
linear? If you knew a country’s pf_expression_control, or its score out
of 10, with 0 being the most, of political pressures and controls on
media content, would you be comfortable using a linear model to predict
the personal freedom score?
ggplot(hfi, aes(pf_expression_control, pf_score)) +
geom_point() +
labs(title = "PF Score Predicted by PF Expression Control")
## Warning: Removed 80 rows containing missing values or values outside the scale range
## (`geom_point()`).

A scatter plot effectively shows the relationship between two
numerical variables, helping us assess whether the relationship is
linear or nonlinear.
If the relationship looks linear, we can quantify the strength of the
relationship with the correlation coefficient.
hfi %>%
summarise(cor(pf_expression_control, pf_score, use = "complete.obs"))
## # A tibble: 1 × 1
## `cor(pf_expression_control, pf_score, use = "complete.obs")`
## <dbl>
## 1 0.796
Exercise 3
Looking at your plot from the previous exercise, describe the
relationship between these two variables. Make sure to discuss the form,
direction, and strength of the relationship as well as any unusual
observations.
This is a positive linear relationship: as the expression control
value increases, the score also tends to rise. The relationship is
linear in form, with a positive direction and a strong correlation of
0.796.
# This will only work interactively (i.e. will not show in the knitted document)
hfi <- hfi %>% filter(complete.cases(pf_expression_control, pf_score))
Exercise 4
Using plot_ss, choose a line that does a good job of minimizing the
sum of squares. Run the function several times. What was the smallest
sum of squares that you got? How does it compare to your neighbors?
df <- hfi %>% select(pf_expression_control, pf_score) %>% drop_na()
m1 <- lm(pf_score ~ pf_expression_control, data = hfi)
The first argument in the function lm is a formula that takes the
form y ~ x. Here it can be read that we want to make a linear model of
pf_score as a function of pf_expression_control. The second argument
specifies that R should look in the hfi data frame to find the two
variables.
The output of lm is an object that contains all of the information we
need about the linear model that was just fit. We can access this
information using the summary function.
##
## 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
Fit a new model that uses pf_expression_control to predict hf_score,
or the total human freedom score. Using the estimates from the R output,
write the equation of the regression line. What does the slope tell us
in the context of the relationship between human freedom and the amount
of political pressure on media content?
m1 <- lm(pf_score ~ pf_expression_control, data = hfi)
summary(m1)
##
## 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
m2 <- lm(hf_score ~ pf_expression_control, data = hfi)
summary(m2)
##
## 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
Prediction and prediction errors
ggplot(data = hfi, aes(x = pf_expression_control, y = pf_score)) +
geom_point() +
stat_smooth(method = "lm", se = FALSE)
## `geom_smooth()` using formula = 'y ~ x'

Exercise 6
If someone saw the least squares regression line and not the actual
data, how would they predict a country’s personal freedom school for one
with a 6.7 rating for pf_expression_control? Is this an overestimate or
an underestimate, and by how much? In other words, what is the residual
for this prediction?
The personal freedom score is 7.9
Model diagnostics
ggplot(data = m1, aes(x = .fitted, y = .resid)) +
geom_point() +
geom_hline(yintercept = 0, linetype = "dashed") +
xlab("Fitted values") +
ylab("Residuals")

Exercise 7
Is there any apparent pattern in the residuals plot? What does this
indicate about the linearity of the relationship between the two
variables?
ggplot(data = m1, aes(x = .fitted, y = .resid)) +
geom_point() +
geom_hline(yintercept = 0, linetype = "dashed") +
xlab("Fitted values") +
ylab("Residuals")

The residual plot shows a random distribution of points, suggesting
that a linear regression model would be appropriate for this
dataset.
Nearly normal residuals
ggplot(data = m1, aes(x = .resid)) +
geom_histogram(binwidth = 25) +
xlab("Residuals")

normal probability plot of the residuals.
ggplot(data = m1, aes(sample = .resid)) +
stat_qq()

Exercise 8
Based on the histogram and the normal probability plot, does the
nearly normal residuals condition appear to be met?
The histogram and probability plot of the residuals display a normal
distribution, indicating that the normality condition is satisfied.
Exercise 9
Based on the residuals vs. fitted plot, does the constant variability
condition appear to be met?
Yes, the constant variance condition is satisfied. The variability
remains consistent in both the positive and negative directions along
the x-axis.
More practice
Choose another freedom variable and a variable you think would
strongly correlate with it. Produce a scatterplot of the two variables
and fit a linear model. At a glance, does there seem to be a linear
relationship?
hfi %>% ggplot(aes(x = pf_religion_restrictions , y = pf_religion_harassment)) +
geom_point()
## Warning: Removed 14 rows containing missing values or values outside the scale range
## (`geom_point()`).

Based on a preliminary look, there doesn’t appear to be a linear
relationship, as the points are dispersed around the 9 and 10 range.
lm_model <- lm(pf_religion_harassment ~ pf_religion_restrictions, data = hfi)
summary(lm_model)
##
## Call:
## lm(formula = pf_religion_harassment ~ pf_religion_restrictions,
## data = hfi)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.76723 -0.41159 0.06432 0.47713 2.03376
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.28916 0.08628 72.89 <2e-16 ***
## pf_religion_restrictions 0.34151 0.01151 29.67 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7272 on 1362 degrees of freedom
## (14 observations deleted due to missingness)
## Multiple R-squared: 0.3926, Adjusted R-squared: 0.3921
## F-statistic: 880.2 on 1 and 1362 DF, p-value: < 2.2e-16
From the above, it appears that the first model has a significantly
stronger correlation.
LS0tDQp0aXRsZTogIkxhYiA4OiBJbnRyb2R1Y3Rpb24gdG8gbGluZWFyIHJlZ3Jlc3Npb24iDQphdXRob3I6ICJMYXVyYSBCIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQNCi0tLQ0KDQojIyMgR2V0dGluZyBTdGFydGVkDQoNCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkob3BlbmludHJvKQ0KDQoNCmBgYA0KDQoNCiMjIyBUaGUgZGF0YQ0KDQoNCiMjIyBFeGVyY2lzZSAxDQoNCldoYXQgYXJlIHRoZSBkaW1lbnNpb25zIG9mIHRoZSBkYXRhc2V0Pw0KDQpgYGB7cn0NCmRpbShoZmkpDQpgYGANClRoZSBkYXRhc2V0IGhhcyAxNDU4IHJvd3MgYW5kIDEyMyBjb2x1bW5zLg0KDQojIyMgRXhlcmNpc2UgMg0KDQpXaGF0IHR5cGUgb2YgcGxvdCB3b3VsZCB5b3UgdXNlIHRvIGRpc3BsYXkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwZXJzb25hbCBmcmVlZG9tIHNjb3JlLCBwZl9zY29yZSwgYW5kIG9uZSBvZiB0aGUgb3RoZXIgbnVtZXJpY2FsIHZhcmlhYmxlcz8gUGxvdCB0aGlzIHJlbGF0aW9uc2hpcCB1c2luZyB0aGUgdmFyaWFibGUgcGZfZXhwcmVzc2lvbl9jb250cm9sIGFzIHRoZSBwcmVkaWN0b3IuIERvZXMgdGhlIHJlbGF0aW9uc2hpcCBsb29rIGxpbmVhcj8gSWYgeW91IGtuZXcgYSBjb3VudHJ54oCZcyBwZl9leHByZXNzaW9uX2NvbnRyb2wsIG9yIGl0cyBzY29yZSBvdXQgb2YgMTAsIHdpdGggMCBiZWluZyB0aGUgbW9zdCwgb2YgcG9saXRpY2FsIHByZXNzdXJlcyBhbmQgY29udHJvbHMgb24gbWVkaWEgY29udGVudCwgd291bGQgeW91IGJlIGNvbWZvcnRhYmxlIHVzaW5nIGEgbGluZWFyIG1vZGVsIHRvIHByZWRpY3QgdGhlIHBlcnNvbmFsIGZyZWVkb20gc2NvcmU/DQoNCmBgYHtyfQ0KZ2dwbG90KGhmaSwgYWVzKHBmX2V4cHJlc3Npb25fY29udHJvbCwgcGZfc2NvcmUpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGxhYnModGl0bGUgPSAiUEYgU2NvcmUgUHJlZGljdGVkIGJ5IFBGIEV4cHJlc3Npb24gQ29udHJvbCIpDQpgYGANCg0KQSBzY2F0dGVyIHBsb3QgZWZmZWN0aXZlbHkgc2hvd3MgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byBudW1lcmljYWwgdmFyaWFibGVzLCBoZWxwaW5nIHVzIGFzc2VzcyB3aGV0aGVyIHRoZSByZWxhdGlvbnNoaXAgaXMgbGluZWFyIG9yIG5vbmxpbmVhci4NCg0KSWYgdGhlIHJlbGF0aW9uc2hpcCBsb29rcyBsaW5lYXIsIHdlIGNhbiBxdWFudGlmeSB0aGUgc3RyZW5ndGggb2YgdGhlIHJlbGF0aW9uc2hpcCB3aXRoIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudC4NCg0KYGBge3J9DQpoZmkgJT4lDQogIHN1bW1hcmlzZShjb3IocGZfZXhwcmVzc2lvbl9jb250cm9sLCBwZl9zY29yZSwgdXNlID0gImNvbXBsZXRlLm9icyIpKQ0KYGBgDQoNCg0KIyMjIEV4ZXJjaXNlIDMNCg0KTG9va2luZyBhdCB5b3VyIHBsb3QgZnJvbSB0aGUgcHJldmlvdXMgZXhlcmNpc2UsIGRlc2NyaWJlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVzZSB0d28gdmFyaWFibGVzLiBNYWtlIHN1cmUgdG8gZGlzY3VzcyB0aGUgZm9ybSwgZGlyZWN0aW9uLCBhbmQgc3RyZW5ndGggb2YgdGhlIHJlbGF0aW9uc2hpcCBhcyB3ZWxsIGFzIGFueSB1bnVzdWFsIG9ic2VydmF0aW9ucy4NCg0KVGhpcyBpcyBhIHBvc2l0aXZlIGxpbmVhciByZWxhdGlvbnNoaXA6IGFzIHRoZSBleHByZXNzaW9uIGNvbnRyb2wgdmFsdWUgaW5jcmVhc2VzLCB0aGUgc2NvcmUgYWxzbyB0ZW5kcyB0byByaXNlLiBUaGUgcmVsYXRpb25zaGlwIGlzIGxpbmVhciBpbiBmb3JtLCB3aXRoIGEgcG9zaXRpdmUgZGlyZWN0aW9uIGFuZCBhIHN0cm9uZyBjb3JyZWxhdGlvbiBvZiAwLjc5Ni4NCg0KYGBge3J9DQojIFRoaXMgd2lsbCBvbmx5IHdvcmsgaW50ZXJhY3RpdmVseSAoaS5lLiB3aWxsIG5vdCBzaG93IGluIHRoZSBrbml0dGVkIGRvY3VtZW50KQ0KaGZpIDwtIGhmaSAlPiUgZmlsdGVyKGNvbXBsZXRlLmNhc2VzKHBmX2V4cHJlc3Npb25fY29udHJvbCwgcGZfc2NvcmUpKQ0KDQpgYGANCg0KDQojIyMgRXhlcmNpc2UgNA0KDQpVc2luZyBwbG90X3NzLCBjaG9vc2UgYSBsaW5lIHRoYXQgZG9lcyBhIGdvb2Qgam9iIG9mIG1pbmltaXppbmcgdGhlIHN1bSBvZiBzcXVhcmVzLiBSdW4gdGhlIGZ1bmN0aW9uIHNldmVyYWwgdGltZXMuIFdoYXQgd2FzIHRoZSBzbWFsbGVzdCBzdW0gb2Ygc3F1YXJlcyB0aGF0IHlvdSBnb3Q/IEhvdyBkb2VzIGl0IGNvbXBhcmUgdG8geW91ciBuZWlnaGJvcnM/DQoNCmBgYHtyfQ0KZGYgPC0gaGZpICU+JSBzZWxlY3QocGZfZXhwcmVzc2lvbl9jb250cm9sLCBwZl9zY29yZSkgJT4lIGRyb3BfbmEoKQ0KDQpgYGANCg0KYGBge3J9DQptMSA8LSBsbShwZl9zY29yZSB+IHBmX2V4cHJlc3Npb25fY29udHJvbCwgZGF0YSA9IGhmaSkNCmBgYA0KDQpUaGUgZmlyc3QgYXJndW1lbnQgaW4gdGhlIGZ1bmN0aW9uIGxtIGlzIGEgZm9ybXVsYSB0aGF0IHRha2VzIHRoZSBmb3JtIHkgfiB4LiBIZXJlIGl0IGNhbiBiZSByZWFkIHRoYXQgd2Ugd2FudCB0byBtYWtlIGEgbGluZWFyIG1vZGVsIG9mIHBmX3Njb3JlIGFzIGEgZnVuY3Rpb24gb2YgcGZfZXhwcmVzc2lvbl9jb250cm9sLiBUaGUgc2Vjb25kIGFyZ3VtZW50IHNwZWNpZmllcyB0aGF0IFIgc2hvdWxkIGxvb2sgaW4gdGhlIGhmaSBkYXRhIGZyYW1lIHRvIGZpbmQgdGhlIHR3byB2YXJpYWJsZXMuDQoNClRoZSBvdXRwdXQgb2YgbG0gaXMgYW4gb2JqZWN0IHRoYXQgY29udGFpbnMgYWxsIG9mIHRoZSBpbmZvcm1hdGlvbiB3ZSBuZWVkIGFib3V0IHRoZSBsaW5lYXIgbW9kZWwgdGhhdCB3YXMganVzdCBmaXQuIFdlIGNhbiBhY2Nlc3MgdGhpcyBpbmZvcm1hdGlvbiB1c2luZyB0aGUgc3VtbWFyeSBmdW5jdGlvbi4NCg0KYGBge3J9DQpzdW1tYXJ5KG0xKQ0KYGBgDQoNCg0KIyMjIEV4ZXJjaXNlIDUNCg0KRml0IGEgbmV3IG1vZGVsIHRoYXQgdXNlcyBwZl9leHByZXNzaW9uX2NvbnRyb2wgdG8gcHJlZGljdCBoZl9zY29yZSwgb3IgdGhlIHRvdGFsIGh1bWFuIGZyZWVkb20gc2NvcmUuIFVzaW5nIHRoZSBlc3RpbWF0ZXMgZnJvbSB0aGUgUiBvdXRwdXQsIHdyaXRlIHRoZSBlcXVhdGlvbiBvZiB0aGUgcmVncmVzc2lvbiBsaW5lLiBXaGF0IGRvZXMgdGhlIHNsb3BlIHRlbGwgdXMgaW4gdGhlIGNvbnRleHQgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGh1bWFuIGZyZWVkb20gYW5kIHRoZSBhbW91bnQgb2YgcG9saXRpY2FsIHByZXNzdXJlIG9uIG1lZGlhIGNvbnRlbnQ/DQoNCmBgYHtyfQ0KbTEgPC0gbG0ocGZfc2NvcmUgfiBwZl9leHByZXNzaW9uX2NvbnRyb2wsIGRhdGEgPSBoZmkpDQpzdW1tYXJ5KG0xKQ0KYGBgDQpgYGB7cn0NCm0yIDwtIGxtKGhmX3Njb3JlIH4gcGZfZXhwcmVzc2lvbl9jb250cm9sLCBkYXRhID0gaGZpKQ0Kc3VtbWFyeShtMikNCmBgYA0KDQojIyMjIFByZWRpY3Rpb24gYW5kIHByZWRpY3Rpb24gZXJyb3JzDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBoZmksIGFlcyh4ID0gcGZfZXhwcmVzc2lvbl9jb250cm9sLCB5ID0gcGZfc2NvcmUpKSArDQogIGdlb21fcG9pbnQoKSArDQogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpDQpgYGANCg0KDQojIyMgRXhlcmNpc2UgNg0KDQpJZiBzb21lb25lIHNhdyB0aGUgbGVhc3Qgc3F1YXJlcyByZWdyZXNzaW9uIGxpbmUgYW5kIG5vdCB0aGUgYWN0dWFsIGRhdGEsIGhvdyB3b3VsZCB0aGV5IHByZWRpY3QgYSBjb3VudHJ54oCZcyBwZXJzb25hbCBmcmVlZG9tIHNjaG9vbCBmb3Igb25lIHdpdGggYSA2LjcgcmF0aW5nIGZvciBwZl9leHByZXNzaW9uX2NvbnRyb2w/IElzIHRoaXMgYW4gb3ZlcmVzdGltYXRlIG9yIGFuIHVuZGVyZXN0aW1hdGUsIGFuZCBieSBob3cgbXVjaD8gSW4gb3RoZXIgd29yZHMsIHdoYXQgaXMgdGhlIHJlc2lkdWFsIGZvciB0aGlzIHByZWRpY3Rpb24/DQoNClRoZSBwZXJzb25hbCBmcmVlZG9tIHNjb3JlIGlzIDcuOQ0KDQojIyMjIE1vZGVsIGRpYWdub3N0aWNzDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtMSwgYWVzKHggPSAuZml0dGVkLCB5ID0gLnJlc2lkKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHhsYWIoIkZpdHRlZCB2YWx1ZXMiKSArDQogIHlsYWIoIlJlc2lkdWFscyIpDQpgYGANCg0KDQojIyMgRXhlcmNpc2UgNw0KDQpJcyB0aGVyZSBhbnkgYXBwYXJlbnQgcGF0dGVybiBpbiB0aGUgcmVzaWR1YWxzIHBsb3Q/IFdoYXQgZG9lcyB0aGlzIGluZGljYXRlIGFib3V0IHRoZSBsaW5lYXJpdHkgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzPw0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbTEsIGFlcyh4ID0gLmZpdHRlZCwgeSA9IC5yZXNpZCkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB4bGFiKCJGaXR0ZWQgdmFsdWVzIikgKw0KICB5bGFiKCJSZXNpZHVhbHMiKQ0KYGBgDQoNClRoZSByZXNpZHVhbCBwbG90IHNob3dzIGEgcmFuZG9tIGRpc3RyaWJ1dGlvbiBvZiBwb2ludHMsIHN1Z2dlc3RpbmcgdGhhdCBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHdvdWxkIGJlIGFwcHJvcHJpYXRlIGZvciB0aGlzIGRhdGFzZXQuDQoNCiMjIyMgTmVhcmx5IG5vcm1hbCByZXNpZHVhbHMNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG0xLCBhZXMoeCA9IC5yZXNpZCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAyNSkgKw0KICB4bGFiKCJSZXNpZHVhbHMiKQ0KYGBgDQoNCg0Kbm9ybWFsIHByb2JhYmlsaXR5IHBsb3Qgb2YgdGhlIHJlc2lkdWFscy4NCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtMSwgYWVzKHNhbXBsZSA9IC5yZXNpZCkpICsNCiAgc3RhdF9xcSgpDQpgYGANCg0KDQojIyMgRXhlcmNpc2UgOA0KDQpCYXNlZCBvbiB0aGUgaGlzdG9ncmFtIGFuZCB0aGUgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3QsIGRvZXMgdGhlIG5lYXJseSBub3JtYWwgcmVzaWR1YWxzIGNvbmRpdGlvbiBhcHBlYXIgdG8gYmUgbWV0Pw0KDQpUaGUgaGlzdG9ncmFtIGFuZCBwcm9iYWJpbGl0eSBwbG90IG9mIHRoZSByZXNpZHVhbHMgZGlzcGxheSBhIG5vcm1hbCBkaXN0cmlidXRpb24sIGluZGljYXRpbmcgdGhhdCB0aGUgbm9ybWFsaXR5IGNvbmRpdGlvbiBpcyBzYXRpc2ZpZWQuDQoNCiMjIyBFeGVyY2lzZSA5DQoNCkJhc2VkIG9uIHRoZSByZXNpZHVhbHMgdnMuIGZpdHRlZCBwbG90LCBkb2VzIHRoZSBjb25zdGFudCB2YXJpYWJpbGl0eSBjb25kaXRpb24gYXBwZWFyIHRvIGJlIG1ldD8NCg0KWWVzLCB0aGUgY29uc3RhbnQgdmFyaWFuY2UgY29uZGl0aW9uIGlzIHNhdGlzZmllZC4gVGhlIHZhcmlhYmlsaXR5IHJlbWFpbnMgY29uc2lzdGVudCBpbiBib3RoIHRoZSBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgZGlyZWN0aW9ucyBhbG9uZyB0aGUgeC1heGlzLg0KDQojIyMgTW9yZSBwcmFjdGljZQ0KDQpDaG9vc2UgYW5vdGhlciBmcmVlZG9tIHZhcmlhYmxlIGFuZCBhIHZhcmlhYmxlIHlvdSB0aGluayB3b3VsZCBzdHJvbmdseSBjb3JyZWxhdGUgd2l0aCBpdC4gUHJvZHVjZSBhIHNjYXR0ZXJwbG90IG9mIHRoZSB0d28gdmFyaWFibGVzIGFuZCBmaXQgYSBsaW5lYXIgbW9kZWwuIEF0IGEgZ2xhbmNlLCBkb2VzIHRoZXJlIHNlZW0gdG8gYmUgYSBsaW5lYXIgcmVsYXRpb25zaGlwPw0KDQpgYGB7cn0NCmhmaSAlPiUgZ2dwbG90KGFlcyh4ID0gcGZfcmVsaWdpb25fcmVzdHJpY3Rpb25zICwgeSA9IHBmX3JlbGlnaW9uX2hhcmFzc21lbnQpKSArDQogIGdlb21fcG9pbnQoKQ0KDQpgYGANCg0KQmFzZWQgb24gYSBwcmVsaW1pbmFyeSBsb29rLCB0aGVyZSBkb2VzbuKAmXQgYXBwZWFyIHRvIGJlIGEgbGluZWFyIHJlbGF0aW9uc2hpcCwgYXMgdGhlIHBvaW50cyBhcmUgZGlzcGVyc2VkIGFyb3VuZCB0aGUgOSBhbmQgMTAgcmFuZ2UuDQoNCmBgYHtyfQ0KbG1fbW9kZWwgPC0gbG0ocGZfcmVsaWdpb25faGFyYXNzbWVudCB+IHBmX3JlbGlnaW9uX3Jlc3RyaWN0aW9ucywgZGF0YSA9IGhmaSkNCnN1bW1hcnkobG1fbW9kZWwpDQoNCmBgYA0KDQpGcm9tIHRoZSBhYm92ZSwgaXQgYXBwZWFycyB0aGF0IHRoZSBmaXJzdCBtb2RlbCBoYXMgYSBzaWduaWZpY2FudGx5IHN0cm9uZ2VyIGNvcnJlbGF0aW9uLg0K