Getting Started

library(tidyverse)
library(openintro)

The data

Exercise 1

What are the dimensions of the dataset?

dim(hfi)
## [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.

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

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