Lab 2: Statistics in R1

Introduction

The goal of this lecture is to get us working with how to answer questions from data. In general, we will think that we have some relationship of interest between an independent variable (\(x\)) and a dependent variable (\(y\)) which are thought to be bound up in some causal relationship.

\[ x \rightarrow y\]

  1. We want to move from concrete questions to the appropriate data
  2. The primary workhorse we will work up to is linear regression
    • If we change \(x\), what happens to \(y\)?
    • What is the (partial) correlation between these variables?
  3. Confidence and Hypothesis Testing
    • What can we say (and what can we not say) about any found relationship?
  4. Can we go back to the data to find better answers after learning empirical relationships?
  5. Causality: Does \(x\) cause \(y\) or are they only correlated?

A Concrete Example

What is the relationship between the unemployment rate and the % votes for an incumbent? I.e.

\[ \text{Unemployment Rate} \rightarrow \text{% Vote for Incumbent ?} \] A quotation of interest: “No American president since Franklin Delano Roosevelt has won a second term in office when the unemployment rate on Election Day topped 7.2 percent.” Binyamin Appelbaum (NYT) 2011.

So what is the effect of the unemployment rate on incumbent vote share? Do we even need to ask? How might we go about answering?

FIRST we need to establish what data we need to collect to take a first pass at the relationship.

  • Dependent Variable: Incumbent Vote Share
  • Independent Variable: Unemployment Rate

Lucky for us, this data was made easily available by FiveThirtyEight! Let’s load it into our current R environment:

unemp <- read.csv("https://www.dropbox.com/s/k4wq9idqoxa2ha0/unemployment.csv?dl=1")
head(unemp)
##   year incumbent_party incumbent_president  nominee unemployment_rate_start
## 1 1912               R                Taft     Taft                     5.1
## 2 1916               D              Wilson   Wilson                     4.9
## 3 1920               D              Wilson      Cox                     5.2
## 4 1924               R             Harding Coolidge                     8.7
## 5 1928               R            Coolidge   Hoover                     4.9
## 6 1932               R              Hoover   Hoover                     4.6
##   unemployment_rate_election election_margin
## 1                        5.3           -18.6
## 2                        5.6             3.1
## 3                        5.2           -26.2
## 4                        5.8            25.2
## 5                        5.0            17.4
## 6                       18.8           -17.7

Let’s take a look at a scatterplot of the two variables of interest, the unemployment rate at the start of the election versus the election margin:

library(ggplot2)
ggplot(unemp, aes(x=unemployment_rate_election, y=election_margin)) +
  geom_point() +
  ggtitle("Unemployment Rate and Incumbent Vote Margin") +
  xlab("Unemployment (%) at Time of Election") +
  ylab("Margin of Victory or Defeat (%)")

At least visually, there doesn’t appear to be a particularly clear relationship. What if we looked at the change in unemployment instead?

unemp$unemployment_change <- unemp$unemployment_rate_election - unemp$unemployment_rate_start

ggplot(unemp, aes(x = unemployment_change, y = election_margin)) +
  geom_point() +
  ggtitle("Change in Unemployment Rate and Incumbent Vote Margin") +
  xlab("Change in Unemployment (%) at Time of Election vs Start of Term") +
  ylab("Margin of Victory or Defeat (%)")

Obviously neither relationship is particularly clear visually. What can we do to take a more rigorous look?

Linear Regression

Linear regression is the work-horse statistical model within political science and beyond. It essentially models the relationship between a dependent variable and one (or more) independent variables as being linear, i.e. able to be adequately modeled by a straight line. The goal, in other terms, is to find the “best-fitting” line for the data as described by the equation

\[ y = X \beta + \epsilon \]

where \(y\) is the dependent variable, \(X\) is the (matrix of) independent variable(s), and \(\beta\) is the (vector of) slop coefficient(s) describing the impact of \(X\) on \(y\), recognizing that there will be some \(\epsilon\) (random) error in the model.

Before going back to the unemployment example, it is useful to think of this in a simulated setting. First, let’s remind ourselves what a perfect linear relationship might look like:

vote_share <- seq(100,0,length=6)
unemp_rate <- seq(0,100,length=6)

ex1 <- data.frame(vote_share,
                 unemp_rate,
                 ex = "ex1")

ggplot(ex1, aes(x=unemp_rate,y=vote_share)) +
  geom_point() +
  geom_line()

Intuitively, the relationship given here takes the form

\[ y = 100 - 1 x \]

where the slope/coefficient value is -1 and the intercept value is 100. We might also imagine some other relationship as follows…

vote_share <- seq(100,0,length=6)
unemp_rate <- seq(0,50,length=6)

ex2 <- data.frame(vote_share,
                 unemp_rate,
                 ex = "ex2")

ex <- rbind(ex1,ex2)

ggplot(ex, aes(x=unemp_rate,y=vote_share, color = ex)) +
  geom_point() +
  geom_line()

where now the (blue) relationship is

\[ y = 100 - 2 x \]

where the slope/coefficient value is -2 and the intercept value is 100. How might these two relationships be interpreted?

Interpretation

A regression coefficient tells us how changing the independent variable \(x\) by one unit changes the dependent variable \(y\). Technically, it is the slope of the best-fitting line that we can draw through all data points where we minimize the sum of squared errors of that regression line.

Here is a bit more of a “realistic” simulated example.

nobs <- 150
x <- rnorm(nobs)
y <- 70 - 1.3*x + rnorm(nobs)

ex <- data.frame(y,x)

ggplot(ex, aes(x=x,y=y)) +
  geom_point()

install.packages("plotly", repos = "http://cran.us.r-project.org")
## 
## The downloaded binary packages are in
##  /var/folders/4n/jrzd6fkx7mn9rgtyb7vz7c4c0000gn/T//RtmpBCiNvW/downloaded_packages

Now that we have those basics out of the way, what do we learn from the first relationship?

library(ggplot2)
ggplot(unemp, aes(x=unemployment_rate_election, y=election_margin)) +
  geom_point() +
  ggtitle("Unemployment Rate and Incumbent Vote Margin") +
  xlab("Unemployment (%) at Time of Election") +
  ylab("Margin of Victory or Defeat (%)") +
  geom_smooth(method="lm")

What is the direction of the correlation? The magnitude? How close does the data fit the line?

lm(election_margin ~ unemployment_rate_election, data = unemp)
## 
## Call:
## lm(formula = election_margin ~ unemployment_rate_election, data = unemp)
## 
## Coefficients:
##                (Intercept)  unemployment_rate_election  
##                    4.15243                    -0.07257
cor(unemp$election_margin,unemp$unemployment_rate_election)
## [1] -0.02119523

What about for the change in unemployment rate?

unemp$unemployment_change <- unemp$unemployment_rate_election - unemp$unemployment_rate_start

ggplot(unemp, aes(x = unemployment_change, y = election_margin)) +
  geom_point() +
  ggtitle("Change in Unemployment Rate and Incumbent Vote Margin") +
  xlab("Change in Unemployment (%) at Time of Election vs Start of Term") +
  ylab("Margin of Victory or Defeat (%)") +
  geom_smooth(method="lm")
## `geom_smooth()` using formula = 'y ~ x'

my_own_creation <- lm(election_margin ~ unemployment_change, data = unemp)
cor(unemp$election_margin, unemp$unemployment_change)
## [1] -0.349543

Multiple Regression (and some pitfalls)

So what else could be going on?

  • We may have omitted a relevant independent variable!
    • Cant (easily) plot the relationship…
    • BUT … we can still calculate slope coefficients, correlations, etc

Mathematically, this leads to multiple regression which takes the form

\[ y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + ... + \beta_n x_n + \epsilon = X \beta + \epsilon \] Now each coefficient shows the effect of a one unit change in \(x\) on \(y\) “irrespective of” or “controlling for” the other variables. Let’s think about this through simulation for a moment…

library(MASS)
nobs <- 100
corm <- matrix(c(1,0.5,0.5,1),nrow=2,byrow=T)

X <- mvrnorm(nobs,rep(0,2),corm)
betas <- c(-1,3)

y <- rnorm(nobs, X %*% betas)

d <- data.frame(y,X)

X <- cbind(1,X)

solve(t(X) %*% X) %*% t(X) %*% y
##             [,1]
## [1,] -0.09773007
## [2,] -0.96591876
## [3,]  3.05344238
summary(lm(y ~ ., data = d))
## 
## Call:
## lm(formula = y ~ ., data = d)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.34068 -0.78611  0.04115  0.54040  2.80682 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -0.09773    0.10080   -0.97    0.335    
## X1          -0.96592    0.11167   -8.65  1.1e-13 ***
## X2           3.05344    0.10649   28.67  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.9821 on 97 degrees of freedom
## Multiple R-squared:  0.8984, Adjusted R-squared:  0.8963 
## F-statistic: 428.9 on 2 and 97 DF,  p-value: < 2.2e-16

Great, we are able to get the correct coefficients! What happens if we don’t include X2?

lm(y ~ X1, data = d)
## 
## Call:
## lm(formula = y ~ X1, data = d)
## 
## Coefficients:
## (Intercept)           X1  
##     -0.5763       0.5838

Oh no! That’s terribly wrong, our first pitfall and a great example of omitted variable bias a topic for a different course.

Our second pitfall has to do with the nature of the data itself – with statistical analysis we believe that there is some random noise in our data generating the error term. This has a direct bearing on how confident we are in our estimates!

Exercises

Before we get ahead of ourselves, we want to make sure that you have fundamentals in order. Do the following:

Write a script which…

  1. Downloads the following data:
  2. Run different commands that help you answer the following questions:
    • How many status updates has NYU Abu Dhabi posted on its page?
    • What is the average number of likes and comments that its post receive?
    • What is the maximum number of likes and comments that its posts receive?
    • What was the content of the last status update of 2014?
  3. Download the following data:
  4. Run different commands that help you answer the following questions:
    • What type of post (photo, status, link, video) is the most common on Donald Trump’s Facebook page?
    • Using linear regression, do posts that contain photos receive more likes on average than links?
    • Using linear regression, are more liked posts also more shared?
    • Create a plot that displays the total number of comments on the page each month. Do you notice any trends? Come up with an explanation (and support it with data).

Save and email your working R script to aae322@nyu.edu by the end of the lab session.

Hint! These data are saved as .csv files so you’ll have to read them in with something like the following:

d <- read.csv("https://www.dropbox.com/s/kyzun4zl7c12j5z/lab2_nyu_data.csv?dl=1")

  1. This lab is partially based off of materials provided by Sean Kates, Pablo Barbera, and Drew Dimmery.↩︎

LS0tCnRpdGxlOiAiIgphdXRob3I6ICJDaHJpc3RvcGhlciBTY2h3YXJ6LCBlZGl0cyBieSBBbGlhIEVsS2F0dGFuIgpwYWdlczoKICBleHRyYTogdHJ1ZQpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIExhYiAyOiBTdGF0aXN0aWNzIGluIFJeW1RoaXMgbGFiIGlzIHBhcnRpYWxseSBiYXNlZCBvZmYgb2YgbWF0ZXJpYWxzIHByb3ZpZGVkIGJ5IFNlYW4gS2F0ZXMsIFBhYmxvIEJhcmJlcmEsIGFuZCBEcmV3IERpbW1lcnkuXQoKIyMgSW50cm9kdWN0aW9uCgpUaGUgZ29hbCBvZiB0aGlzIGxlY3R1cmUgaXMgdG8gZ2V0IHVzIHdvcmtpbmcgd2l0aCBob3cgdG8gYW5zd2VyIHF1ZXN0aW9ucyBmcm9tIGRhdGEuICAgSW4gZ2VuZXJhbCwgd2Ugd2lsbCB0aGluayB0aGF0IHdlIGhhdmUgc29tZSByZWxhdGlvbnNoaXAgb2YgaW50ZXJlc3QgYmV0d2VlbiBhbiAqKmluZGVwZW5kZW50IHZhcmlhYmxlKiogKCR4JCkgYW5kIGEgKipkZXBlbmRlbnQgdmFyaWFibGUqKiAoJHkkKSB3aGljaCBhcmUgdGhvdWdodCB0byBiZSBib3VuZCB1cCBpbiBzb21lIGNhdXNhbCByZWxhdGlvbnNoaXAuCgokJCB4IFxyaWdodGFycm93IHkkJAoKMS4gV2Ugd2FudCB0byBtb3ZlIGZyb20gY29uY3JldGUgcXVlc3Rpb25zIHRvIHRoZSBhcHByb3ByaWF0ZSBkYXRhCjIuIFRoZSBwcmltYXJ5IHdvcmtob3JzZSB3ZSB3aWxsIHdvcmsgdXAgdG8gaXMgKmxpbmVhciByZWdyZXNzaW9uKgogICAgKiBJZiB3ZSBjaGFuZ2UgJHgkLCB3aGF0IGhhcHBlbnMgdG8gJHkkPwogICAgKiBXaGF0IGlzIHRoZSAocGFydGlhbCkgY29ycmVsYXRpb24gYmV0d2VlbiB0aGVzZSB2YXJpYWJsZXM/CjMuIENvbmZpZGVuY2UgYW5kIEh5cG90aGVzaXMgVGVzdGluZwogICAgKiBXaGF0IGNhbiB3ZSBzYXkgKGFuZCB3aGF0IGNhbiB3ZSBub3Qgc2F5KSBhYm91dCBhbnkgZm91bmQgcmVsYXRpb25zaGlwPwo0LiBDYW4gd2UgZ28gYmFjayB0byB0aGUgZGF0YSB0byBmaW5kIGJldHRlciBhbnN3ZXJzIGFmdGVyIGxlYXJuaW5nIGVtcGlyaWNhbCByZWxhdGlvbnNoaXBzPwo1LiBDYXVzYWxpdHk6IERvZXMgJHgkIGNhdXNlICR5JCBvciBhcmUgdGhleSBvbmx5IGNvcnJlbGF0ZWQ/CgoKIyMgQSBDb25jcmV0ZSBFeGFtcGxlCgpXaGF0IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdW5lbXBsb3ltZW50IHJhdGUgYW5kIHRoZSAlIHZvdGVzIGZvciBhbiBpbmN1bWJlbnQ/ICBJLmUuCgokJCBcdGV4dHtVbmVtcGxveW1lbnQgUmF0ZX0gXHJpZ2h0YXJyb3cgXHRleHR7JSBWb3RlIGZvciBJbmN1bWJlbnQgP30gJCQKQSBxdW90YXRpb24gb2YgaW50ZXJlc3Q6ICJObyBBbWVyaWNhbiBwcmVzaWRlbnQgc2luY2UgRnJhbmtsaW4gRGVsYW5vIFJvb3NldmVsdCBoYXMgd29uIGEgc2Vjb25kIHRlcm0gaW4gb2ZmaWNlIHdoZW4gdGhlIHVuZW1wbG95bWVudCByYXRlIG9uIEVsZWN0aW9uIERheSB0b3BwZWQgNy4yIHBlcmNlbnQuIiAgW0JpbnlhbWluIEFwcGVsYmF1bSAoTllUKSAyMDExXShodHRwczovL3d3dy5ueXRpbWVzLmNvbS8yMDExLzA2LzAyL2J1c2luZXNzL2Vjb25vbXkvMDJqb2JzLmh0bWwpLgoKU28gd2hhdCBpcyB0aGUgZWZmZWN0IG9mIHRoZSB1bmVtcGxveW1lbnQgcmF0ZSBvbiBpbmN1bWJlbnQgdm90ZSBzaGFyZT8gIERvIHdlIGV2ZW4gbmVlZCB0byBhc2s/ICBIb3cgbWlnaHQgd2UgZ28gYWJvdXQgYW5zd2VyaW5nPwoKKipGSVJTVCoqIHdlIG5lZWQgdG8gZXN0YWJsaXNoIHdoYXQgKmRhdGEqIHdlIG5lZWQgdG8gY29sbGVjdCB0byB0YWtlIGEgZmlyc3QgcGFzcyBhdCB0aGUgcmVsYXRpb25zaGlwLgoKKiAqKkRlcGVuZGVudCBWYXJpYWJsZSoqOiBJbmN1bWJlbnQgVm90ZSBTaGFyZQoqICoqSW5kZXBlbmRlbnQgVmFyaWFibGUqKjogVW5lbXBsb3ltZW50IFJhdGUKCkx1Y2t5IGZvciB1cywgdGhpcyBkYXRhIHdhcyBtYWRlIGVhc2lseSBhdmFpbGFibGUgYnkgW0ZpdmVUaGlydHlFaWdodF0oaHR0cHM6Ly9maXZldGhpcnR5ZWlnaHQuY29tL2ZlYXR1cmVzL29uLXRoZS1tYWRkZW5pbmdseS1pbmV4YWN0LXJlbGF0aW9uc2hpcC1iZXR3ZWVuLXVuZW1wbG95bWVudC1hbmQtcmUtZWxlY3Rpb24vKSEgIExldCdzIGxvYWQgaXQgaW50byBvdXIgY3VycmVudCBSIGVudmlyb25tZW50OgoKYGBge3J9CnVuZW1wIDwtIHJlYWQuY3N2KCJodHRwczovL3d3dy5kcm9wYm94LmNvbS9zL2s0d3E5aWRxb3hhMmhhMC91bmVtcGxveW1lbnQuY3N2P2RsPTEiKQpoZWFkKHVuZW1wKQpgYGAKTGV0J3MgdGFrZSBhIGxvb2sgYXQgYSBzY2F0dGVycGxvdCBvZiB0aGUgdHdvIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCwgdGhlIHVuZW1wbG95bWVudCByYXRlIGF0IHRoZSBzdGFydCBvZiB0aGUgZWxlY3Rpb24gdmVyc3VzIHRoZSBlbGVjdGlvbiBtYXJnaW46CgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmdncGxvdCh1bmVtcCwgYWVzKHg9dW5lbXBsb3ltZW50X3JhdGVfZWxlY3Rpb24sIHk9ZWxlY3Rpb25fbWFyZ2luKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2d0aXRsZSgiVW5lbXBsb3ltZW50IFJhdGUgYW5kIEluY3VtYmVudCBWb3RlIE1hcmdpbiIpICsKICB4bGFiKCJVbmVtcGxveW1lbnQgKCUpIGF0IFRpbWUgb2YgRWxlY3Rpb24iKSArCiAgeWxhYigiTWFyZ2luIG9mIFZpY3Rvcnkgb3IgRGVmZWF0ICglKSIpCmBgYAoKQXQgbGVhc3QgdmlzdWFsbHksIHRoZXJlIGRvZXNuJ3QgYXBwZWFyIHRvIGJlIGEgcGFydGljdWxhcmx5IGNsZWFyIHJlbGF0aW9uc2hpcC4gIFdoYXQgaWYgd2UgbG9va2VkIGF0IHRoZSBjaGFuZ2UgaW4gdW5lbXBsb3ltZW50IGluc3RlYWQ/CgpgYGB7cn0KdW5lbXAkdW5lbXBsb3ltZW50X2NoYW5nZSA8LSB1bmVtcCR1bmVtcGxveW1lbnRfcmF0ZV9lbGVjdGlvbiAtIHVuZW1wJHVuZW1wbG95bWVudF9yYXRlX3N0YXJ0CgpnZ3Bsb3QodW5lbXAsIGFlcyh4ID0gdW5lbXBsb3ltZW50X2NoYW5nZSwgeSA9IGVsZWN0aW9uX21hcmdpbikpICsKICBnZW9tX3BvaW50KCkgKwogIGdndGl0bGUoIkNoYW5nZSBpbiBVbmVtcGxveW1lbnQgUmF0ZSBhbmQgSW5jdW1iZW50IFZvdGUgTWFyZ2luIikgKwogIHhsYWIoIkNoYW5nZSBpbiBVbmVtcGxveW1lbnQgKCUpIGF0IFRpbWUgb2YgRWxlY3Rpb24gdnMgU3RhcnQgb2YgVGVybSIpICsKICB5bGFiKCJNYXJnaW4gb2YgVmljdG9yeSBvciBEZWZlYXQgKCUpIikKYGBgCgpPYnZpb3VzbHkgbmVpdGhlciByZWxhdGlvbnNoaXAgaXMgcGFydGljdWxhcmx5IGNsZWFyIHZpc3VhbGx5LiAgV2hhdCBjYW4gd2UgZG8gdG8gdGFrZSBhIG1vcmUgcmlnb3JvdXMgbG9vaz8KCiMjIExpbmVhciBSZWdyZXNzaW9uCgpMaW5lYXIgcmVncmVzc2lvbiBpcyB0aGUgd29yay1ob3JzZSBzdGF0aXN0aWNhbCBtb2RlbCB3aXRoaW4gcG9saXRpY2FsIHNjaWVuY2UgYW5kIGJleW9uZC4gSXQgZXNzZW50aWFsbHkgbW9kZWxzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgb25lIChvciBtb3JlKSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYXMgYmVpbmcgbGluZWFyLCBpLmUuIGFibGUgdG8gYmUgYWRlcXVhdGVseSBtb2RlbGVkIGJ5IGEgc3RyYWlnaHQgbGluZS4gVGhlIGdvYWwsIGluIG90aGVyIHRlcm1zLCBpcyB0byBmaW5kIHRoZSAiYmVzdC1maXR0aW5nIiBsaW5lIGZvciB0aGUgZGF0YSBhcyBkZXNjcmliZWQgYnkgdGhlIGVxdWF0aW9uCgokJCB5ID0gWCBcYmV0YSArIFxlcHNpbG9uICQkCgp3aGVyZSAkeSQgaXMgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSwgJFgkIGlzIHRoZSAobWF0cml4IG9mKSBpbmRlcGVuZGVudCB2YXJpYWJsZShzKSwgYW5kICRcYmV0YSQgaXMgdGhlICh2ZWN0b3Igb2YpIHNsb3AgY29lZmZpY2llbnQocykgZGVzY3JpYmluZyB0aGUgaW1wYWN0IG9mICRYJCBvbiAkeSQsIHJlY29nbml6aW5nIHRoYXQgdGhlcmUgd2lsbCBiZSBzb21lICRcZXBzaWxvbiQgKHJhbmRvbSkgZXJyb3IgaW4gdGhlIG1vZGVsLgoKQmVmb3JlIGdvaW5nIGJhY2sgdG8gdGhlIHVuZW1wbG95bWVudCBleGFtcGxlLCBpdCBpcyB1c2VmdWwgdG8gdGhpbmsgb2YgdGhpcyBpbiBhIHNpbXVsYXRlZCBzZXR0aW5nLiAgRmlyc3QsIGxldCdzIHJlbWluZCBvdXJzZWx2ZXMgd2hhdCBhIHBlcmZlY3QgbGluZWFyIHJlbGF0aW9uc2hpcCBtaWdodCBsb29rIGxpa2U6CgpgYGB7cn0Kdm90ZV9zaGFyZSA8LSBzZXEoMTAwLDAsbGVuZ3RoPTYpCnVuZW1wX3JhdGUgPC0gc2VxKDAsMTAwLGxlbmd0aD02KQoKZXgxIDwtIGRhdGEuZnJhbWUodm90ZV9zaGFyZSwKICAgICAgICAgICAgICAgICB1bmVtcF9yYXRlLAogICAgICAgICAgICAgICAgIGV4ID0gImV4MSIpCgpnZ3Bsb3QoZXgxLCBhZXMoeD11bmVtcF9yYXRlLHk9dm90ZV9zaGFyZSkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZSgpCgpgYGAKCkludHVpdGl2ZWx5LCB0aGUgcmVsYXRpb25zaGlwIGdpdmVuIGhlcmUgdGFrZXMgdGhlIGZvcm0KCiQkIHkgPSAxMDAgLSAxIHggJCQKCndoZXJlIHRoZSBzbG9wZS9jb2VmZmljaWVudCB2YWx1ZSBpcyAtMSBhbmQgdGhlIGludGVyY2VwdCB2YWx1ZSBpcyAxMDAuICBXZSBtaWdodCBhbHNvIGltYWdpbmUgc29tZSBvdGhlciByZWxhdGlvbnNoaXAgYXMgZm9sbG93cy4uLgoKYGBge3J9CnZvdGVfc2hhcmUgPC0gc2VxKDEwMCwwLGxlbmd0aD02KQp1bmVtcF9yYXRlIDwtIHNlcSgwLDUwLGxlbmd0aD02KQoKZXgyIDwtIGRhdGEuZnJhbWUodm90ZV9zaGFyZSwKICAgICAgICAgICAgICAgICB1bmVtcF9yYXRlLAogICAgICAgICAgICAgICAgIGV4ID0gImV4MiIpCgpleCA8LSByYmluZChleDEsZXgyKQoKZ2dwbG90KGV4LCBhZXMoeD11bmVtcF9yYXRlLHk9dm90ZV9zaGFyZSwgY29sb3IgPSBleCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZSgpCgpgYGAKCndoZXJlIG5vdyB0aGUgKGJsdWUpIHJlbGF0aW9uc2hpcCBpcyAKCiQkIHkgPSAxMDAgLSAyIHggJCQKCndoZXJlIHRoZSBzbG9wZS9jb2VmZmljaWVudCB2YWx1ZSBpcyAtMiBhbmQgdGhlIGludGVyY2VwdCB2YWx1ZSBpcyAxMDAuICBIb3cgbWlnaHQgdGhlc2UgdHdvIHJlbGF0aW9uc2hpcHMgYmUgaW50ZXJwcmV0ZWQ/CgojIyMgSW50ZXJwcmV0YXRpb24KCkEgcmVncmVzc2lvbiBjb2VmZmljaWVudCB0ZWxscyB1cyBob3cgY2hhbmdpbmcgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlICR4JCAqKmJ5IG9uZSB1bml0KiogY2hhbmdlcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlICR5JC4gIFRlY2huaWNhbGx5LCBpdCBpcyB0aGUgKipzbG9wZSoqIG9mIHRoZSBiZXN0LWZpdHRpbmcgbGluZSB0aGF0IHdlIGNhbiBkcmF3IHRocm91Z2ggYWxsIGRhdGEgcG9pbnRzIHdoZXJlIHdlIG1pbmltaXplIHRoZSAqKnN1bSBvZiBzcXVhcmVkIGVycm9ycyoqIG9mIHRoYXQgcmVncmVzc2lvbiBsaW5lLgoKSGVyZSBpcyBhIGJpdCBtb3JlIG9mIGEgInJlYWxpc3RpYyIgc2ltdWxhdGVkIGV4YW1wbGUuCgpgYGB7cn0Kbm9icyA8LSAxNTAKeCA8LSBybm9ybShub2JzKQp5IDwtIDcwIC0gMS4zKnggKyBybm9ybShub2JzKQoKZXggPC0gZGF0YS5mcmFtZSh5LHgpCgpnZ3Bsb3QoZXgsIGFlcyh4PXgseT15KSkgKwogIGdlb21fcG9pbnQoKQoKYGBgCgoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cmluc3RhbGwucGFja2FnZXMoInBsb3RseSIsIHJlcG9zID0gImh0dHA6Ly9jcmFuLnVzLnItcHJvamVjdC5vcmciKQpgYGAKCk5vdyB0aGF0IHdlIGhhdmUgdGhvc2UgYmFzaWNzIG91dCBvZiB0aGUgd2F5LCB3aGF0IGRvIHdlIGxlYXJuIGZyb20gdGhlIGZpcnN0IHJlbGF0aW9uc2hpcD8KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KHVuZW1wLCBhZXMoeD11bmVtcGxveW1lbnRfcmF0ZV9lbGVjdGlvbiwgeT1lbGVjdGlvbl9tYXJnaW4pKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZ3RpdGxlKCJVbmVtcGxveW1lbnQgUmF0ZSBhbmQgSW5jdW1iZW50IFZvdGUgTWFyZ2luIikgKwogIHhsYWIoIlVuZW1wbG95bWVudCAoJSkgYXQgVGltZSBvZiBFbGVjdGlvbiIpICsKICB5bGFiKCJNYXJnaW4gb2YgVmljdG9yeSBvciBEZWZlYXQgKCUpIikgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKQpgYGAKCldoYXQgaXMgdGhlIGRpcmVjdGlvbiBvZiB0aGUgY29ycmVsYXRpb24/ICBUaGUgbWFnbml0dWRlPyAgSG93IGNsb3NlIGRvZXMgdGhlIGRhdGEgZml0IHRoZSBsaW5lPwoKYGBge3J9CmxtKGVsZWN0aW9uX21hcmdpbiB+IHVuZW1wbG95bWVudF9yYXRlX2VsZWN0aW9uLCBkYXRhID0gdW5lbXApCmNvcih1bmVtcCRlbGVjdGlvbl9tYXJnaW4sdW5lbXAkdW5lbXBsb3ltZW50X3JhdGVfZWxlY3Rpb24pCmBgYAoKV2hhdCBhYm91dCBmb3IgdGhlIGNoYW5nZSBpbiB1bmVtcGxveW1lbnQgcmF0ZT8KCmBgYHtyfQp1bmVtcCR1bmVtcGxveW1lbnRfY2hhbmdlIDwtIHVuZW1wJHVuZW1wbG95bWVudF9yYXRlX2VsZWN0aW9uIC0gdW5lbXAkdW5lbXBsb3ltZW50X3JhdGVfc3RhcnQKCmdncGxvdCh1bmVtcCwgYWVzKHggPSB1bmVtcGxveW1lbnRfY2hhbmdlLCB5ID0gZWxlY3Rpb25fbWFyZ2luKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2d0aXRsZSgiQ2hhbmdlIGluIFVuZW1wbG95bWVudCBSYXRlIGFuZCBJbmN1bWJlbnQgVm90ZSBNYXJnaW4iKSArCiAgeGxhYigiQ2hhbmdlIGluIFVuZW1wbG95bWVudCAoJSkgYXQgVGltZSBvZiBFbGVjdGlvbiB2cyBTdGFydCBvZiBUZXJtIikgKwogIHlsYWIoIk1hcmdpbiBvZiBWaWN0b3J5IG9yIERlZmVhdCAoJSkiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpCmBgYAoKYGBge3J9Cm15X293bl9jcmVhdGlvbiA8LSBsbShlbGVjdGlvbl9tYXJnaW4gfiB1bmVtcGxveW1lbnRfY2hhbmdlLCBkYXRhID0gdW5lbXApCmNvcih1bmVtcCRlbGVjdGlvbl9tYXJnaW4sIHVuZW1wJHVuZW1wbG95bWVudF9jaGFuZ2UpCmBgYAoKIyMjIE11bHRpcGxlIFJlZ3Jlc3Npb24gKGFuZCBzb21lIHBpdGZhbGxzKQoKU28gd2hhdCBlbHNlIGNvdWxkIGJlIGdvaW5nIG9uPwoKKyBXZSBtYXkgaGF2ZSBvbWl0dGVkIGEgcmVsZXZhbnQgaW5kZXBlbmRlbnQgdmFyaWFibGUhCiAgICArIENhbnQgKGVhc2lseSkgcGxvdCB0aGUgcmVsYXRpb25zaGlwLi4uCiAgICArIEJVVCAuLi4gd2UgY2FuIHN0aWxsIGNhbGN1bGF0ZSBzbG9wZSBjb2VmZmljaWVudHMsIGNvcnJlbGF0aW9ucywgZXRjCiAgICAKTWF0aGVtYXRpY2FsbHksIHRoaXMgbGVhZHMgdG8gKiptdWx0aXBsZSByZWdyZXNzaW9uKiogd2hpY2ggdGFrZXMgdGhlIGZvcm0KCiQkIHkgPSBcYmV0YV8wICsgXGJldGFfMSB4XzEgKyBcYmV0YV8yIHhfMiArIC4uLiArIFxiZXRhX24geF9uICsgXGVwc2lsb24gPSBYIFxiZXRhICsgXGVwc2lsb24gJCQKTm93IGVhY2ggY29lZmZpY2llbnQgc2hvd3MgdGhlIGVmZmVjdCBvZiBhIG9uZSB1bml0IGNoYW5nZSBpbiAkeCQgb24gJHkkICJpcnJlc3BlY3RpdmUgb2YiIG9yICJjb250cm9sbGluZyBmb3IiIHRoZSBvdGhlciB2YXJpYWJsZXMuICBMZXQncyB0aGluayBhYm91dCB0aGlzIHRocm91Z2ggc2ltdWxhdGlvbiBmb3IgYSBtb21lbnQuLi4KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoTUFTUykKbm9icyA8LSAxMDAKY29ybSA8LSBtYXRyaXgoYygxLDAuNSwwLjUsMSksbnJvdz0yLGJ5cm93PVQpCgpYIDwtIG12cm5vcm0obm9icyxyZXAoMCwyKSxjb3JtKQpiZXRhcyA8LSBjKC0xLDMpCgp5IDwtIHJub3JtKG5vYnMsIFggJSolIGJldGFzKQoKZCA8LSBkYXRhLmZyYW1lKHksWCkKClggPC0gY2JpbmQoMSxYKQoKc29sdmUodChYKSAlKiUgWCkgJSolIHQoWCkgJSolIHkKCnN1bW1hcnkobG0oeSB+IC4sIGRhdGEgPSBkKSkKCmBgYAoKR3JlYXQsIHdlIGFyZSBhYmxlIHRvIGdldCB0aGUgY29ycmVjdCBjb2VmZmljaWVudHMhICBXaGF0IGhhcHBlbnMgaWYgd2UgZG9uJ3QgaW5jbHVkZSBYMj8KCmBgYHtyfQpsbSh5IH4gWDEsIGRhdGEgPSBkKQpgYGAKCk9oIG5vISAgVGhhdCdzIHRlcnJpYmx5IHdyb25nLCBvdXIgKipmaXJzdCBwaXRmYWxsKiogYW5kIGEgZ3JlYXQgZXhhbXBsZSBvZiAqKm9taXR0ZWQgdmFyaWFibGUgYmlhcyoqIGEgdG9waWMgZm9yIGEgZGlmZmVyZW50IGNvdXJzZS4gIAoKCk91ciAqKnNlY29uZCBwaXRmYWxsKiogaGFzIHRvIGRvIHdpdGggdGhlIG5hdHVyZSBvZiB0aGUgZGF0YSBpdHNlbGYgLS0gd2l0aCBzdGF0aXN0aWNhbCBhbmFseXNpcyB3ZSBiZWxpZXZlIHRoYXQgdGhlcmUgaXMgc29tZSByYW5kb20gbm9pc2UgaW4gb3VyIGRhdGEgZ2VuZXJhdGluZyB0aGUgZXJyb3IgdGVybS4gIFRoaXMgaGFzIGEgZGlyZWN0IGJlYXJpbmcgb24gaG93IGNvbmZpZGVudCB3ZSBhcmUgaW4gb3VyIGVzdGltYXRlcyEgCgoKIyMgRXhlcmNpc2VzCgpCZWZvcmUgd2UgZ2V0IGFoZWFkIG9mIG91cnNlbHZlcywgd2Ugd2FudCB0byBtYWtlIHN1cmUgdGhhdCB5b3UgaGF2ZSBmdW5kYW1lbnRhbHMgaW4gb3JkZXIuICBEbyB0aGUgZm9sbG93aW5nOgoKV3JpdGUgYSBzY3JpcHQgd2hpY2guLi4KCjEuIERvd25sb2FkcyB0aGUgZm9sbG93aW5nIGRhdGE6CiAgICArIGh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3Mva3l6dW40emw3YzEyajV6L2xhYjJfbnl1X2RhdGEuY3N2P2RsPTEKMi4gUnVuIGRpZmZlcmVudCBjb21tYW5kcyB0aGF0IGhlbHAgeW91IGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczoKICAgICsgSG93IG1hbnkgc3RhdHVzIHVwZGF0ZXMgaGFzIE5ZVSBBYnUgRGhhYmkgcG9zdGVkIG9uIGl0cyBwYWdlPwogICAgKyBXaGF0IGlzIHRoZSBhdmVyYWdlIG51bWJlciBvZiBsaWtlcyBhbmQgY29tbWVudHMgdGhhdCBpdHMgcG9zdCByZWNlaXZlPwogICAgKyBXaGF0IGlzIHRoZSBtYXhpbXVtIG51bWJlciBvZiBsaWtlcyBhbmQgY29tbWVudHMgdGhhdCBpdHMgcG9zdHMgcmVjZWl2ZT8KICAgICsgV2hhdCB3YXMgdGhlIGNvbnRlbnQgb2YgdGhlIGxhc3Qgc3RhdHVzIHVwZGF0ZSBvZiAyMDE0PwozLiBEb3dubG9hZCB0aGUgZm9sbG93aW5nIGRhdGE6CiAgICArIGh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3MvaG5xbWI4ZnlxbGEzZWd4L2xhYjJfdHJ1bXBfZGF0YS5jc3Y/ZGw9MQo0LiBSdW4gZGlmZmVyZW50IGNvbW1hbmRzIHRoYXQgaGVscCB5b3UgYW5zd2VyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOgogICAgKyBXaGF0IHR5cGUgb2YgcG9zdCAocGhvdG8sIHN0YXR1cywgbGluaywgdmlkZW8pIGlzIHRoZSBtb3N0IGNvbW1vbiBvbiBEb25hbGQgVHJ1bXAncyBGYWNlYm9vayBwYWdlPwogICAgKyBVc2luZyBsaW5lYXIgcmVncmVzc2lvbiwgZG8gcG9zdHMgdGhhdCBjb250YWluIHBob3RvcyByZWNlaXZlIG1vcmUgbGlrZXMgb24gYXZlcmFnZSB0aGFuIGxpbmtzPwogICAgKyBVc2luZyBsaW5lYXIgcmVncmVzc2lvbiwgYXJlIG1vcmUgbGlrZWQgcG9zdHMgYWxzbyBtb3JlIHNoYXJlZD8gIAogICAgKyBDcmVhdGUgYSBwbG90IHRoYXQgZGlzcGxheXMgdGhlIHRvdGFsIG51bWJlciBvZiBjb21tZW50cyBvbiB0aGUgcGFnZSBlYWNoIG1vbnRoLiAgRG8geW91IG5vdGljZSBhbnkgdHJlbmRzPyAgQ29tZSB1cCB3aXRoIGFuIGV4cGxhbmF0aW9uIChhbmQgc3VwcG9ydCBpdCB3aXRoIGRhdGEpLgogICAgClNhdmUgYW5kIGVtYWlsIHlvdXIgd29ya2luZyBSIHNjcmlwdCB0byBhYWUzMjJcQG55dS5lZHUgYnkgdGhlIGVuZCBvZiB0aGUgbGFiIHNlc3Npb24uCgoKSGludCEgIFRoZXNlIGRhdGEgYXJlIHNhdmVkIGFzIC5jc3YgZmlsZXMgc28geW91J2xsIGhhdmUgdG8gcmVhZCB0aGVtIGluIHdpdGggc29tZXRoaW5nIGxpa2UgdGhlIGZvbGxvd2luZzoKYGBge3J9CmQgPC0gcmVhZC5jc3YoImh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3Mva3l6dW40emw3YzEyajV6L2xhYjJfbnl1X2RhdGEuY3N2P2RsPTEiKQoKCmBgYAoK