Loading in Necessary Packages

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ ggplot2 3.3.5.9000     ✓ purrr   0.3.4     
## ✓ tibble  3.1.3          ✓ dplyr   1.0.7     
## ✓ tidyr   1.1.3          ✓ stringr 1.4.0     
## ✓ readr   2.0.1          ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(openintro)
## Loading required package: airports
## Loading required package: cherryblossom
## Loading required package: usdata
library(statsr)
## Loading required package: BayesFactor
## Loading required package: coda
## Loading required package: Matrix
## 
## Attaching package: 'Matrix'
## The following objects are masked from 'package:tidyr':
## 
##     expand, pack, unpack
## ************
## Welcome to BayesFactor 0.9.12-4.2. If you have questions, please contact Richard Morey (richarddmorey@gmail.com).
## 
## Type BFManual() to open the manual.
## ************
## 
## Attaching package: 'statsr'
## The following objects are masked from 'package:openintro':
## 
##     calc_streak, evals, nycflights, present
library(broom)

First Set of Questions

Exercise 1

What are the dimensions of the data set?

data(hfi)
dim(hfi)
## [1] 1458  123

Using the “dim()” code, I was able to determine that this data set has 123 variables and a total of 1458 observations

Exercise 2

The dataset spans a lot of years, but we are only interested in data from year 2016. Filter the data hfi data frame for year 2016, select the six variables, and assign the result to a data frame named hfi_2016.

hfi_2016 <- hfi %>%
  filter(year == "2016") %>%
  select(pf_expression_control, pf_score, year, countries, hf_score, pf_ss)

Year: The year in which the personal freedom rankings were collected Countries: The countries in which the personal freedom rankings were collected pf_expression_control: Amount of political pressure on media content score pf_score: Human individual (personal) freedom score hf_score: Human freedom score pf_ss: Security and safety score

Exercise 3

What type of plot would you use to display the relationship between the personal freedom score, pf_score, and pf_expression_control? 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?

hfi_2016 %>%
  ggplot(aes(x = pf_expression_control, y = pf_score)) +
  geom_point() +
  labs(x = "Expression Control",
       y = "Pf Score",
       title = "Pf Score as a Function of Pf Expression Control") +
  theme(plot.title = element_text(hjust = 0.50)) +
  scale_x_continuous(breaks = seq(0, 10, 1))

I would use a scatterplot as its primary use is to observe and show relationships between 2 numeric variables. The relationship seems somewhat linear, but many of the points are scattered randomly. As of looking at the graph for the first time, I would not be comfortable with using a linear model to predict personal freedom score.

hfi_2016 %>%
  summarise(cor(pf_expression_control, pf_score))
## # A tibble: 1 × 1
##   `cor(pf_expression_control, pf_score)`
##                                    <dbl>
## 1                                  0.845

Exercise 4

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

The plot displays a moderately strong, positive correlation between the two variables. As pf_express_control increases, the pf_score does as well. However, there seems to be a couple outliers in the plot.

Exercise 5

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?

plot_ss(x = pf_expression_control, y = pf_score, data = hfi_2016, showSquares = TRUE)

## Click two points to make a line.
                                
## Call:
## lm(formula = y ~ x, data = pts)
## 
## Coefficients:
## (Intercept)            x  
##      4.2838       0.5418  
## 
## Sum of Squares:  102.213

The smallest I could get for the Sum of Sqaures was 104.469

Exercise 6

We cant take a quick look at some of the summary stats of the data set by using the commands “tidy()” and “glance()”. Some of these include the y-intercept and slope of the regression line and the \(R^2\) (0.714).

lm1 <- lm(pf_score ~ pf_expression_control, data = hfi_2016)

tidy(lm1)
## # A tibble: 2 × 5
##   term                  estimate std.error statistic  p.value
##   <chr>                    <dbl>     <dbl>     <dbl>    <dbl>
## 1 (Intercept)              4.28     0.149       28.8 4.23e-65
## 2 pf_expression_control    0.542    0.0271      20.0 2.31e-45
glance(lm1)
## # A tibble: 1 × 12
##   r.squared adj.r.squared sigma statistic  p.value    df logLik   AIC   BIC
##       <dbl>         <dbl> <dbl>     <dbl>    <dbl> <dbl>  <dbl> <dbl> <dbl>
## 1     0.714         0.712 0.799      400. 2.31e-45     1  -193.  391.  400.
## # … with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>

And through this we can determine that the equation of the regression line is:

\(ŷ = 4.28 + 0.542x\)

This tells us 1. For countries with pf_expression_control of 0, (those with the largest amount of political pressure on media content), the expected mean personal freedom score is 4.28. 2. For every 1 unit increase in pf_expression_control, the expected mean personal freedom score should increase by 0.542 units.

hfi_2016 %>%
  ggplot(aes(x = pf_expression_control, y = pf_score)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  labs(x = "Expression Control",
       y = "Pf Score",
       title = "Pf Score as a Function of Pf Expression Control") +
  theme(plot.title = element_text(hjust = 0.50)) +
  scale_x_continuous(breaks = seq(0, 10, 1))
## `geom_smooth()` using formula 'y ~ x'

This new plot only adds the least squares line on top of the original. This was done by adding one line of code - “geom_smooth(). We defined the line by using”lm" or linear model and hid the standard error, “se”, for now

Exercise 7

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 3 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?

pf_exp_control <- 3

pf_score6 <- 4.28 + 0.542 * pf_exp_control
pf_score6
## [1] 5.906

Then we can Check observed values of pf_score with 3.0 rating for pf_expression_control

hfi_2016 %>%
  group_by(pf_score) %>%
  filter(pf_expression_control == 3.0)
## # A tibble: 1 × 6
## # Groups:   pf_score [1]
##   pf_expression_control pf_score  year countries         hf_score pf_ss
##                   <dbl>    <dbl> <dbl> <chr>                <dbl> <dbl>
## 1                     3     5.47  2016 Central Afr. Rep.     5.29  4.37

There is only one observation with a pf_expression_control of 3.0. And the observed pf_score for this is 5.466, which is fairly close to the predicted pf_score of 5.906. Therefore, the residual for this would be \(5.466 - 5.906 = -0.440\). The prediction was an overestimation by 0.44

Exercise 8

Is there any apparent pattern in the residuals plot? What does this indicate about the linearity of the relationship between the two variables?

The “augment()” function helps us calculate the residuals for each point. All we need to do is create a scatterplot for those residuals.

lm1_aug <- augment(lm1)
ggplot(data = lm1_aug, aes(x = .fitted, y = .resid)) +
  geom_point() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(
    x ="Fitted values", 
    y ="Residuals",
    title = "Plot of Residuals") +
  theme(plot.title = element_text(hjust = 0.50))

Overall, there is not an apparent pattern in the residuals plot and this indicates there is a linear relationship between the two variables. The points look randomly scattered.

Exercise 9

Nearly normal residuals: To check this condition, we can look at a histogram of the residuals.

ggplot(data = lm1_aug, aes(x = .resid)) +
  geom_histogram(binwidth = 0.25) +
  labs(
    x = "Residuals",
    y = "Count",
    title = "Histogram of Residuals") +
  theme(plot.title = element_text(hjust = 0.50))

The histogram of residuals shows that the residuals are fairly normally distributed. Although there is some skew to the left. Generally, the normal residuals condition appears to be met.

Exercise 10

Constant Variability: Based on the residuals vs. fitted plot, does the constant variability condition appear to be met?

ggplot(data = lm1, aes(sample = .resid)) +
  stat_qq() +
  labs(
    x = "Residuals",
    y = "Fitted",
    title = "Residuals vs Fitted") +
  theme(plot.title = element_text(hjust = 0.50))

The points residuals vs. fitted plot show that points are scattered around 0, there is a constant variability. Thus, the constant variability condition appear to be met.

Additional Practice

Excerise 1

Choose another freedom variable and a variable you think would strongly correlate with it.. Produce a scatter plot of the two variables and fit a linear model. At a glance, does there seem to be a linear relationship?

Use pf_ss as the predictor, and predict the hf_rank with it

ggplot(data = hfi, aes(x = pf_ss, y = pf_score)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  labs(x = "Security and Safety Score",
       y = "Human Freedom Ranking",
       title = "Human Freedom Ranking as a Function of Security and Safety Score") +
  theme(plot.title = element_text(hjust = 0.50)) +
  scale_x_continuous(breaks = seq(0, 10, 1))
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 80 rows containing non-finite values (stat_smooth).
## Warning: Removed 80 rows containing missing values (geom_point).

At a glance, the relationship between these two variables seems linear. It displays a positive relationship, meaning as pf_ss increases, hf_score increases as well.

Exercise 2

How does this relationship compare to the relationship between pf_score and pf_expression_control? Use the R2 values from the two model summaries to compare. Does your independent variable seem to predict pf_score better? Why or why not?

lmPF <- lm(pf_score ~ pf_expression_control, data = hfi)
summary(lmPF)
## 
## 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
##   (80 observations deleted due to missingness)
## Multiple R-squared:  0.6342, Adjusted R-squared:  0.634 
## F-statistic:  2386 on 1 and 1376 DF,  p-value: < 2.2e-16
lmPF2 <- lm(pf_score ~ pf_ss, hfi)

summary(lmPF2)
## 
## Call:
## lm(formula = pf_score ~ pf_ss, data = hfi)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -2.6872 -0.6502  0.1600  0.7018  2.6868 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  1.10202    0.15058   7.319 4.24e-13 ***
## pf_ss        0.74553    0.01815  41.069  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.9219 on 1376 degrees of freedom
##   (80 observations deleted due to missingness)
## Multiple R-squared:  0.5507, Adjusted R-squared:  0.5504 
## F-statistic:  1687 on 1 and 1376 DF,  p-value: < 2.2e-16

From the \(R^2\) values of both models, we have this:

pf_expression_control and pf_score model: 63.42% of the data fits the regression model

pf_ss and pf_score model: 55.07% of the data fits the regression model

The independent variable, pf_ss, does not seem to predict the dependent, pf_score, better than the first model. The \(R^2\) is higher on the first model (63.42% vs 55.07%). This indicates less variation on the first model.

Exercise 3

Check the model diagnostics using appropriate visualizations and evaluate if the model conditions have been met.

First we need to find the residuals using the augment function:

lm2_aug <- augment(lmPF2)

Linearity: We should also verify this condition with a plot of the residuals vs. fitted (predicted) values.

ggplot(data = lm2_aug, aes(x = .fitted, y = .resid)) +
  geom_point() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(
    x ="Fitted values", 
    y ="Residuals",
    title = "Plot of Residuals") +
  theme(plot.title = element_text(hjust = 0.50))

Overall, there is not an apparent pattern in the residuals plot and this indicates there is a linear relationship between the two variables. However, the points do become more concentrated in one area as the Fitted Values increase. This can also be seen in the scatterplot (as pf_ss increases). Nevertheless, overall the points look randomly scattered.

Normality of Residuals:

ggplot(data = lm2_aug, aes(x = .resid)) +
  geom_histogram(binwidth = 0.25) +
  labs(
    x = "Residuals",
    y = "Count",
    title = "Histogram of Residuals") +
  theme(plot.title = element_text(hjust = 0.50))

Generally, the histogram of residuals looks fairly normal with most of the residuals being concetrated in the middle.

Exercise 4

LS0tCnRpdGxlOiAiREFUQSAxMDEgRmluYWwgUHJvamVjdCAtIEh1bWFuIEZyZWVkb20gSW5kZXgiCmF1dGhvcjogIkp1c3RpbiBQYXJrIgpkYXRlOiAiOC85LzIwMjEiCm91dHB1dDogb3BlbmludHJvOjpsYWJfcmVwb3J0Ci0tLQoKIyMgTG9hZGluZyBpbiBOZWNlc3NhcnkgUGFja2FnZXMKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShvcGVuaW50cm8pCmxpYnJhcnkoc3RhdHNyKQpsaWJyYXJ5KGJyb29tKQpgYGAKCiMjIEZpcnN0IFNldCBvZiBRdWVzdGlvbnMKCiMjIyBFeGVyY2lzZSAxCgpXaGF0IGFyZSB0aGUgZGltZW5zaW9ucyBvZiB0aGUgZGF0YSBzZXQ/CgpgYGB7cn0KZGF0YShoZmkpCmRpbShoZmkpCmBgYAoKKipVc2luZyB0aGUgImRpbSgpIiBjb2RlLCBJIHdhcyBhYmxlIHRvIGRldGVybWluZSB0aGF0IHRoaXMgZGF0YSBzZXQgaGFzIDEyMyB2YXJpYWJsZXMgYW5kIGEgdG90YWwgb2YgMTQ1OCBvYnNlcnZhdGlvbnMqKgoKCiMjIyBFeGVyY2lzZSAyCgpUaGUgZGF0YXNldCBzcGFucyBhIGxvdCBvZiB5ZWFycywgYnV0IHdlIGFyZSBvbmx5IGludGVyZXN0ZWQgaW4gZGF0YSBmcm9tIHllYXIgMjAxNi4gRmlsdGVyIHRoZSBkYXRhIGhmaSBkYXRhIGZyYW1lIGZvciB5ZWFyIDIwMTYsIHNlbGVjdCB0aGUgc2l4IHZhcmlhYmxlcywgYW5kIGFzc2lnbiB0aGUgcmVzdWx0IHRvIGEgZGF0YSBmcmFtZSBuYW1lZCBoZmlfMjAxNi4KCmBgYHtyfQpoZmlfMjAxNiA8LSBoZmkgJT4lCiAgZmlsdGVyKHllYXIgPT0gIjIwMTYiKSAlPiUKICBzZWxlY3QocGZfZXhwcmVzc2lvbl9jb250cm9sLCBwZl9zY29yZSwgeWVhciwgY291bnRyaWVzLCBoZl9zY29yZSwgcGZfc3MpCmBgYAoKKipZZWFyOioqIFRoZSB5ZWFyIGluIHdoaWNoIHRoZSBwZXJzb25hbCBmcmVlZG9tIHJhbmtpbmdzIHdlcmUgY29sbGVjdGVkCioqQ291bnRyaWVzOioqIFRoZSBjb3VudHJpZXMgaW4gd2hpY2ggdGhlIHBlcnNvbmFsIGZyZWVkb20gcmFua2luZ3Mgd2VyZSBjb2xsZWN0ZWQKKipwZl9leHByZXNzaW9uX2NvbnRyb2w6KiogQW1vdW50IG9mIHBvbGl0aWNhbCBwcmVzc3VyZSBvbiBtZWRpYSBjb250ZW50IHNjb3JlCioqcGZfc2NvcmU6KiogSHVtYW4gaW5kaXZpZHVhbCAocGVyc29uYWwpIGZyZWVkb20gc2NvcmUKKipoZl9zY29yZToqKiBIdW1hbiBmcmVlZG9tIHNjb3JlCioqcGZfc3M6KiogU2VjdXJpdHkgYW5kIHNhZmV0eSBzY29yZQoKIyMjIEV4ZXJjaXNlIDMKCldoYXQgdHlwZSBvZiBwbG90IHdvdWxkIHlvdSB1c2UgdG8gZGlzcGxheSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHBlcnNvbmFsIGZyZWVkb20gc2NvcmUsIHBmX3Njb3JlLCBhbmQgcGZfZXhwcmVzc2lvbl9jb250cm9sPyBQbG90IHRoaXMgcmVsYXRpb25zaGlwIHVzaW5nIHRoZSB2YXJpYWJsZSBwZl9leHByZXNzaW9uX2NvbnRyb2wgYXMgdGhlIHByZWRpY3Rvci4gRG9lcyB0aGUgcmVsYXRpb25zaGlwIGxvb2sgbGluZWFyPyBJZiB5b3Uga25ldyBhIGNvdW50cnnigJlzIHBmX2V4cHJlc3Npb25fY29udHJvbCwgb3IgaXRzIHNjb3JlIG91dCBvZiAxMCwgd2l0aCAwIGJlaW5nIHRoZSBtb3N0LCBvZiBwb2xpdGljYWwgcHJlc3N1cmVzIGFuZCBjb250cm9scyBvbiBtZWRpYSBjb250ZW50LCB3b3VsZCB5b3UgYmUgY29tZm9ydGFibGUgdXNpbmcgYSBsaW5lYXIgbW9kZWwgdG8gcHJlZGljdCB0aGUgcGVyc29uYWwgZnJlZWRvbSBzY29yZT8KCmBgYHtyfQpoZmlfMjAxNiAlPiUKICBnZ3Bsb3QoYWVzKHggPSBwZl9leHByZXNzaW9uX2NvbnRyb2wsIHkgPSBwZl9zY29yZSkpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeCA9ICJFeHByZXNzaW9uIENvbnRyb2wiLAogICAgICAgeSA9ICJQZiBTY29yZSIsCiAgICAgICB0aXRsZSA9ICJQZiBTY29yZSBhcyBhIEZ1bmN0aW9uIG9mIFBmIEV4cHJlc3Npb24gQ29udHJvbCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41MCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwLCAxKSkKYGBgCgoqKkkgd291bGQgdXNlIGEgc2NhdHRlcnBsb3QgYXMgaXRzIHByaW1hcnkgdXNlIGlzIHRvIG9ic2VydmUgYW5kIHNob3cgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIDIgbnVtZXJpYyB2YXJpYWJsZXMuIFRoZSByZWxhdGlvbnNoaXAgc2VlbXMgc29tZXdoYXQgbGluZWFyLCBidXQgbWFueSBvZiB0aGUgcG9pbnRzIGFyZSBzY2F0dGVyZWQgcmFuZG9tbHkuIEFzIG9mIGxvb2tpbmcgYXQgdGhlIGdyYXBoIGZvciB0aGUgZmlyc3QgdGltZSwgSSB3b3VsZCBub3QgYmUgY29tZm9ydGFibGUgd2l0aCB1c2luZyBhIGxpbmVhciBtb2RlbCB0byBwcmVkaWN0IHBlcnNvbmFsIGZyZWVkb20gc2NvcmUuKioKCmBgYHtyfQpoZmlfMjAxNiAlPiUKICBzdW1tYXJpc2UoY29yKHBmX2V4cHJlc3Npb25fY29udHJvbCwgcGZfc2NvcmUpKQpgYGAKCgojIyMgRXhlcmNpc2UgNAoKTG9va2luZyBhdCB5b3VyIHBsb3QgZnJvbSB0aGUgcHJldmlvdXMgZXhlcmNpc2UsIGRlc2NyaWJlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVzZSB0d28gdmFyaWFibGVzLiBNYWtlIHN1cmUgdG8gZGlzY3VzcyB0aGUgZm9ybSwgZGlyZWN0aW9uLCBhbmQgc3RyZW5ndGggb2YgdGhlIHJlbGF0aW9uc2hpcCBhcyB3ZWxsIGFzIGFueSB1bnVzdWFsIG9ic2VydmF0aW9ucwoKKipUaGUgcGxvdCBkaXNwbGF5cyBhIG1vZGVyYXRlbHkgc3Ryb25nLCBwb3NpdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzLiBBcyBwZl9leHByZXNzX2NvbnRyb2wgaW5jcmVhc2VzLCB0aGUgcGZfc2NvcmUgZG9lcyBhcyB3ZWxsLiBIb3dldmVyLCB0aGVyZSBzZWVtcyB0byBiZSBhIGNvdXBsZSBvdXRsaWVycyBpbiB0aGUgcGxvdC4qKgoKCiMjIyBFeGVyY2lzZSA1CgpVc2luZyBwbG90X3NzLCBjaG9vc2UgYSBsaW5lIHRoYXQgZG9lcyBhIGdvb2Qgam9iIG9mIG1pbmltaXppbmcgdGhlIHN1bSBvZiBzcXVhcmVzLiBSdW4gdGhlIGZ1bmN0aW9uIHNldmVyYWwgdGltZXMuIFdoYXQgd2FzIHRoZSBzbWFsbGVzdCBzdW0gb2Ygc3F1YXJlcyB0aGF0IHlvdSBnb3Q/CgpgYGB7cn0KcGxvdF9zcyh4ID0gcGZfZXhwcmVzc2lvbl9jb250cm9sLCB5ID0gcGZfc2NvcmUsIGRhdGEgPSBoZmlfMjAxNiwgc2hvd1NxdWFyZXMgPSBUUlVFKQpgYGAKCioqVGhlIHNtYWxsZXN0IEkgY291bGQgZ2V0IGZvciB0aGUgU3VtIG9mIFNxYXVyZXMgd2FzIDEwNC40NjkqKgoKCiMjIyBFeGVyY2lzZSA2CgpXZSBjYW50IHRha2UgYSBxdWljayBsb29rIGF0IHNvbWUgb2YgdGhlIHN1bW1hcnkgc3RhdHMgb2YgdGhlIGRhdGEgc2V0IGJ5IHVzaW5nIHRoZSBjb21tYW5kcyAidGlkeSgpIiBhbmQgImdsYW5jZSgpIi4gU29tZSBvZiB0aGVzZSBpbmNsdWRlIHRoZSB5LWludGVyY2VwdCBhbmQgc2xvcGUgb2YgdGhlIHJlZ3Jlc3Npb24gbGluZSBhbmQgdGhlICAkUl4yJCAoMC43MTQpLgpgYGB7cn0KbG0xIDwtIGxtKHBmX3Njb3JlIH4gcGZfZXhwcmVzc2lvbl9jb250cm9sLCBkYXRhID0gaGZpXzIwMTYpCgp0aWR5KGxtMSkKCmdsYW5jZShsbTEpCmBgYAoKQW5kIHRocm91Z2ggdGhpcyB3ZSBjYW4gZGV0ZXJtaW5lIHRoYXQgdGhlIGVxdWF0aW9uIG9mIHRoZSByZWdyZXNzaW9uIGxpbmUgaXM6CgokxbcgPSA0LjI4ICsgMC41NDJ4JAoKVGhpcyB0ZWxscyB1cwoxLiBGb3IgY291bnRyaWVzIHdpdGggcGZfZXhwcmVzc2lvbl9jb250cm9sIG9mIDAsICh0aG9zZSB3aXRoIHRoZSBsYXJnZXN0IGFtb3VudCBvZiBwb2xpdGljYWwgcHJlc3N1cmUgb24gbWVkaWEgY29udGVudCksIHRoZSBleHBlY3RlZCBtZWFuIHBlcnNvbmFsIGZyZWVkb20gc2NvcmUgaXMgNC4yOC4KMi4gRm9yIGV2ZXJ5IDEgdW5pdCBpbmNyZWFzZSBpbiBwZl9leHByZXNzaW9uX2NvbnRyb2wsIHRoZSBleHBlY3RlZCBtZWFuIHBlcnNvbmFsIGZyZWVkb20gc2NvcmUgc2hvdWxkIGluY3JlYXNlIGJ5IDAuNTQyIHVuaXRzLgoKYGBge3J9CmhmaV8yMDE2ICU+JQogIGdncGxvdChhZXMoeCA9IHBmX2V4cHJlc3Npb25fY29udHJvbCwgeSA9IHBmX3Njb3JlKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKwogIGxhYnMoeCA9ICJFeHByZXNzaW9uIENvbnRyb2wiLAogICAgICAgeSA9ICJQZiBTY29yZSIsCiAgICAgICB0aXRsZSA9ICJQZiBTY29yZSBhcyBhIEZ1bmN0aW9uIG9mIFBmIEV4cHJlc3Npb24gQ29udHJvbCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41MCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwLCAxKSkKYGBgCgoqKlRoaXMgbmV3IHBsb3Qgb25seSBhZGRzIHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgb24gdG9wIG9mIHRoZSBvcmlnaW5hbC4gVGhpcyB3YXMgZG9uZSBieSBhZGRpbmcgb25lIGxpbmUgb2YgY29kZSAtICJnZW9tX3Ntb290aCgpLiBXZSBkZWZpbmVkIHRoZSBsaW5lIGJ5IHVzaW5nICJsbSIgb3IgbGluZWFyIG1vZGVsIGFuZCBoaWQgdGhlIHN0YW5kYXJkIGVycm9yLCAic2UiLCBmb3Igbm93KioKCgojIyMgRXhlcmNpc2UgNwoKSWYgc29tZW9uZSBzYXcgdGhlIGxlYXN0IHNxdWFyZXMgcmVncmVzc2lvbiBsaW5lIGFuZCBub3QgdGhlIGFjdHVhbCBkYXRhLCBob3cgd291bGQgdGhleSBwcmVkaWN0IGEgY291bnRyeeKAmXMgcGVyc29uYWwgZnJlZWRvbSBzY2hvb2wgZm9yIG9uZSB3aXRoIGEgMyByYXRpbmcgZm9yIHBmX2V4cHJlc3Npb25fY29udHJvbD8gSXMgdGhpcyBhbiBvdmVyZXN0aW1hdGUgb3IgYW4gdW5kZXJlc3RpbWF0ZSwgYW5kIGJ5IGhvdyBtdWNoPyBJbiBvdGhlciB3b3Jkcywgd2hhdCBpcyB0aGUgcmVzaWR1YWwgZm9yIHRoaXMgcHJlZGljdGlvbj8KCmBgYHtyfQpwZl9leHBfY29udHJvbCA8LSAzCgpwZl9zY29yZTYgPC0gNC4yOCArIDAuNTQyICogcGZfZXhwX2NvbnRyb2wKcGZfc2NvcmU2CmBgYAoKVGhlbiB3ZSBjYW4gQ2hlY2sgb2JzZXJ2ZWQgdmFsdWVzIG9mIHBmX3Njb3JlIHdpdGggMy4wIHJhdGluZyBmb3IgYHBmX2V4cHJlc3Npb25fY29udHJvbGAKCmBgYHtyfQpoZmlfMjAxNiAlPiUKICBncm91cF9ieShwZl9zY29yZSkgJT4lCiAgZmlsdGVyKHBmX2V4cHJlc3Npb25fY29udHJvbCA9PSAzLjApCmBgYAoKKipUaGVyZSBpcyBvbmx5IG9uZSBvYnNlcnZhdGlvbiB3aXRoIGEgcGZfZXhwcmVzc2lvbl9jb250cm9sIG9mIDMuMC4gQW5kIHRoZSBvYnNlcnZlZCBwZl9zY29yZSBmb3IgdGhpcyBpcyA1LjQ2Niwgd2hpY2ggaXMgZmFpcmx5IGNsb3NlIHRvIHRoZSBwcmVkaWN0ZWQgcGZfc2NvcmUgb2YgNS45MDYuKioKKipUaGVyZWZvcmUsIHRoZSByZXNpZHVhbCBmb3IgdGhpcyB3b3VsZCBiZSAkNS40NjYgLSA1LjkwNiA9IC0wLjQ0MCQuIFRoZSBwcmVkaWN0aW9uIHdhcyBhbiBvdmVyZXN0aW1hdGlvbiBieSAwLjQ0KioKCgojIyMgRXhlcmNpc2UgOAoKSXMgdGhlcmUgYW55IGFwcGFyZW50IHBhdHRlcm4gaW4gdGhlIHJlc2lkdWFscyBwbG90PyBXaGF0IGRvZXMgdGhpcyBpbmRpY2F0ZSBhYm91dCB0aGUgbGluZWFyaXR5IG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcz8KCioqVGhlICJhdWdtZW50KCkiIGZ1bmN0aW9uIGhlbHBzIHVzIGNhbGN1bGF0ZSB0aGUgcmVzaWR1YWxzIGZvciBlYWNoIHBvaW50LiBBbGwgd2UgbmVlZCB0byBkbyBpcyBjcmVhdGUgYSBzY2F0dGVycGxvdCBmb3IgdGhvc2UgcmVzaWR1YWxzLioqCgpgYGB7cn0KbG0xX2F1ZyA8LSBhdWdtZW50KGxtMSkKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBsbTFfYXVnLCBhZXMoeCA9IC5maXR0ZWQsIHkgPSAucmVzaWQpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSArCiAgbGFicygKICAgIHggPSJGaXR0ZWQgdmFsdWVzIiwgCiAgICB5ID0iUmVzaWR1YWxzIiwKICAgIHRpdGxlID0gIlBsb3Qgb2YgUmVzaWR1YWxzIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUwKSkKYGBgCgoqKk92ZXJhbGwsIHRoZXJlIGlzIG5vdCBhbiBhcHBhcmVudCBwYXR0ZXJuIGluIHRoZSByZXNpZHVhbHMgcGxvdCBhbmQgdGhpcyBpbmRpY2F0ZXMgdGhlcmUgaXMgYSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHR3byB2YXJpYWJsZXMuIFRoZSBwb2ludHMgbG9vayByYW5kb21seSBzY2F0dGVyZWQuKioKCgojIyMgRXhlcmNpc2UgOQoKKipOZWFybHkgbm9ybWFsIHJlc2lkdWFsczoqKiBUbyBjaGVjayB0aGlzIGNvbmRpdGlvbiwgd2UgY2FuIGxvb2sgYXQgYSBoaXN0b2dyYW0gb2YgdGhlIHJlc2lkdWFscy4KCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGxtMV9hdWcsIGFlcyh4ID0gLnJlc2lkKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4yNSkgKwogIGxhYnMoCiAgICB4ID0gIlJlc2lkdWFscyIsCiAgICB5ID0gIkNvdW50IiwKICAgIHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBSZXNpZHVhbHMiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNTApKQpgYGAKCioqVGhlIGhpc3RvZ3JhbSBvZiByZXNpZHVhbHMgc2hvd3MgdGhhdCB0aGUgcmVzaWR1YWxzIGFyZSBmYWlybHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIEFsdGhvdWdoIHRoZXJlIGlzIHNvbWUgc2tldyB0byB0aGUgbGVmdC4gR2VuZXJhbGx5LCB0aGUgbm9ybWFsIHJlc2lkdWFscyBjb25kaXRpb24gYXBwZWFycyB0byBiZSBtZXQuKioKCiMjIyBFeGVyY2lzZSAxMAoKKipDb25zdGFudCBWYXJpYWJpbGl0eToqKiBCYXNlZCBvbiB0aGUgcmVzaWR1YWxzIHZzLiBmaXR0ZWQgcGxvdCwgZG9lcyB0aGUgY29uc3RhbnQgdmFyaWFiaWxpdHkgY29uZGl0aW9uIGFwcGVhciB0byBiZSBtZXQ/CgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBsbTEsIGFlcyhzYW1wbGUgPSAucmVzaWQpKSArCiAgc3RhdF9xcSgpICsKICBsYWJzKAogICAgeCA9ICJSZXNpZHVhbHMiLAogICAgeSA9ICJGaXR0ZWQiLAogICAgdGl0bGUgPSAiUmVzaWR1YWxzIHZzIEZpdHRlZCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41MCkpCmBgYAoKKipUaGUgcG9pbnRzIHJlc2lkdWFscyB2cy4gZml0dGVkIHBsb3Qgc2hvdyB0aGF0IHBvaW50cyBhcmUgc2NhdHRlcmVkIGFyb3VuZCAwLCB0aGVyZSBpcyBhIGNvbnN0YW50IHZhcmlhYmlsaXR5LiBUaHVzLCB0aGUgY29uc3RhbnQgdmFyaWFiaWxpdHkgY29uZGl0aW9uIGFwcGVhciB0byBiZSBtZXQuKioKCgoKIyMgQWRkaXRpb25hbCBQcmFjdGljZQoKIyMjIEV4Y2VyaXNlIDEKCkNob29zZSBhbm90aGVyIGZyZWVkb20gdmFyaWFibGUgYW5kIGEgdmFyaWFibGUgeW91IHRoaW5rIHdvdWxkIHN0cm9uZ2x5IGNvcnJlbGF0ZSB3aXRoIGl0Li4gUHJvZHVjZSBhIHNjYXR0ZXIgcGxvdCBvZiB0aGUgdHdvIHZhcmlhYmxlcyBhbmQgZml0IGEgbGluZWFyIG1vZGVsLiBBdCBhIGdsYW5jZSwgZG9lcyB0aGVyZSBzZWVtIHRvIGJlIGEgbGluZWFyIHJlbGF0aW9uc2hpcD8KCioqVXNlIHBmX3NzIGFzIHRoZSBwcmVkaWN0b3IsIGFuZCBwcmVkaWN0IHRoZSBoZl9yYW5rIHdpdGggaXQqKgoKYGBge3J9CmdncGxvdChkYXRhID0gaGZpLCBhZXMoeCA9IHBmX3NzLCB5ID0gcGZfc2NvcmUpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArCiAgbGFicyh4ID0gIlNlY3VyaXR5IGFuZCBTYWZldHkgU2NvcmUiLAogICAgICAgeSA9ICJIdW1hbiBGcmVlZG9tIFJhbmtpbmciLAogICAgICAgdGl0bGUgPSAiSHVtYW4gRnJlZWRvbSBSYW5raW5nIGFzIGEgRnVuY3Rpb24gb2YgU2VjdXJpdHkgYW5kIFNhZmV0eSBTY29yZSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41MCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwLCAxKSkKYGBgCgoqKkF0IGEgZ2xhbmNlLCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlc2UgdHdvIHZhcmlhYmxlcyBzZWVtcyBsaW5lYXIuKioKKipJdCBkaXNwbGF5cyBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCwgbWVhbmluZyBhcyBwZl9zcyBpbmNyZWFzZXMsIGhmX3Njb3JlIGluY3JlYXNlcyBhcyB3ZWxsLioqCgojIyMgRXhlcmNpc2UgMgoKSG93IGRvZXMgdGhpcyByZWxhdGlvbnNoaXAgY29tcGFyZSB0byB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcGZfc2NvcmUgYW5kIHBmX2V4cHJlc3Npb25fY29udHJvbD8gVXNlIHRoZSBSMiB2YWx1ZXMgZnJvbSB0aGUgdHdvIG1vZGVsIHN1bW1hcmllcyB0byBjb21wYXJlLiBEb2VzIHlvdXIgaW5kZXBlbmRlbnQgdmFyaWFibGUgc2VlbSB0byBwcmVkaWN0IHBmX3Njb3JlIGJldHRlcj8gV2h5IG9yIHdoeSBub3Q/CgpgYGB7cn0KbG1QRiA8LSBsbShwZl9zY29yZSB+IHBmX2V4cHJlc3Npb25fY29udHJvbCwgZGF0YSA9IGhmaSkKc3VtbWFyeShsbVBGKQpgYGAKCmBgYHtyfQpsbVBGMiA8LSBsbShwZl9zY29yZSB+IHBmX3NzLCBoZmkpCgpzdW1tYXJ5KGxtUEYyKQpgYGAKCkZyb20gdGhlICRSXjIkIHZhbHVlcyBvZiBib3RoIG1vZGVscywgd2UgaGF2ZSB0aGlzOgoKKipwZl9leHByZXNzaW9uX2NvbnRyb2wgYW5kIHBmX3Njb3JlIG1vZGVsOioqIDYzLjQyJSBvZiB0aGUgZGF0YSBmaXRzIHRoZSByZWdyZXNzaW9uIG1vZGVsCgoqKnBmX3NzIGFuZCBwZl9zY29yZSBtb2RlbDoqKiA1NS4wNyUgb2YgdGhlIGRhdGEgZml0cyB0aGUgcmVncmVzc2lvbiBtb2RlbAoKVGhlIGluZGVwZW5kZW50IHZhcmlhYmxlLCBwZl9zcywgZG9lcyBub3Qgc2VlbSB0byBwcmVkaWN0IHRoZSBkZXBlbmRlbnQsIHBmX3Njb3JlLCBiZXR0ZXIgdGhhbiB0aGUgZmlyc3QgbW9kZWwuIFRoZSAkUl4yJCBpcyBoaWdoZXIgb24gdGhlIGZpcnN0IG1vZGVsICg2My40MiUgdnMgNTUuMDclKS4gVGhpcyBpbmRpY2F0ZXMgbGVzcyB2YXJpYXRpb24gb24gdGhlIGZpcnN0IG1vZGVsLgoKCgojIyMgRXhlcmNpc2UgMwoKQ2hlY2sgdGhlIG1vZGVsIGRpYWdub3N0aWNzIHVzaW5nIGFwcHJvcHJpYXRlIHZpc3VhbGl6YXRpb25zIGFuZCBldmFsdWF0ZSBpZiB0aGUgbW9kZWwgY29uZGl0aW9ucyBoYXZlIGJlZW4gbWV0LgoKRmlyc3Qgd2UgbmVlZCB0byBmaW5kIHRoZSByZXNpZHVhbHMgdXNpbmcgdGhlIGF1Z21lbnQgZnVuY3Rpb246CgpgYGB7cn0KbG0yX2F1ZyA8LSBhdWdtZW50KGxtUEYyKQpgYGAKCioqTGluZWFyaXR5OioqIFdlIHNob3VsZCBhbHNvIHZlcmlmeSB0aGlzIGNvbmRpdGlvbiB3aXRoIGEgcGxvdCBvZiB0aGUgcmVzaWR1YWxzIHZzLiBmaXR0ZWQgKHByZWRpY3RlZCkgdmFsdWVzLgoKYGBge3J9CmdncGxvdChkYXRhID0gbG0yX2F1ZywgYWVzKHggPSAuZml0dGVkLCB5ID0gLnJlc2lkKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIikgKwogIGxhYnMoCiAgICB4ID0iRml0dGVkIHZhbHVlcyIsIAogICAgeSA9IlJlc2lkdWFscyIsCiAgICB0aXRsZSA9ICJQbG90IG9mIFJlc2lkdWFscyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41MCkpCmBgYAoKKipPdmVyYWxsLCB0aGVyZSBpcyBub3QgYW4gYXBwYXJlbnQgcGF0dGVybiBpbiB0aGUgcmVzaWR1YWxzIHBsb3QgYW5kIHRoaXMgaW5kaWNhdGVzIHRoZXJlIGlzIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzLiBIb3dldmVyLCB0aGUgcG9pbnRzIGRvIGJlY29tZSBtb3JlIGNvbmNlbnRyYXRlZCBpbiBvbmUgYXJlYSBhcyB0aGUgRml0dGVkIFZhbHVlcyBpbmNyZWFzZS4gVGhpcyBjYW4gYWxzbyBiZSBzZWVuIGluIHRoZSBzY2F0dGVycGxvdCAoYXMgcGZfc3MgaW5jcmVhc2VzKS4gTmV2ZXJ0aGVsZXNzLCBvdmVyYWxsIHRoZSBwb2ludHMgbG9vayByYW5kb21seSBzY2F0dGVyZWQuKioKCioqTm9ybWFsaXR5IG9mIFJlc2lkdWFsczoqKiAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGxtMl9hdWcsIGFlcyh4ID0gLnJlc2lkKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4yNSkgKwogIGxhYnMoCiAgICB4ID0gIlJlc2lkdWFscyIsCiAgICB5ID0gIkNvdW50IiwKICAgIHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBSZXNpZHVhbHMiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNTApKQpgYGAKCioqR2VuZXJhbGx5LCB0aGUgaGlzdG9ncmFtIG9mIHJlc2lkdWFscyBsb29rcyBmYWlybHkgbm9ybWFsIHdpdGggbW9zdCBvZiB0aGUgcmVzaWR1YWxzIGJlaW5nIGNvbmNldHJhdGVkIGluIHRoZSBtaWRkbGUuKioKCiMjIyBFeGVyY2lzZSA0