1 Nominal Variables

  • Things like gender or color (terms we would have as factors in ANOVA)
  • Decisions have to made on how to treat these variables in a regression
  • We will assume (for now) that a subject can be a member of only one level of a factor a variable (i.e., you can blue or red, but not both)
  • There are three basic methods we will cover and how to interpret their effects and interactions
  • Key to remember you are basically doing to t-tests so you are always just comparing two things, but what those two things are will chagne as you change you codings (think the concept of contrasts in ANOVA from last semester)

2 Models with no Interactions (1 Nominal variable)

2.1 Dummy Coding

  • The most common and basic type used (default in R if it senses a categorical variable)
  • For each variable you must assign a reference group (a baseline) for each variable
  • Each group is compared to the reference group
  • We ask the question, how much does each group deviate from the reference
  • Here are two levels of one factor
Variable C1
Female 0
Male 1
  • Here are Three levels, but now you have to make 2 new variables
  • Female is the reference group
Variable C1 C2
Female 0 0
Male 0 1
Trans 1 1
  • Male is the reference group
Variable C1 C2
Female 0 1
Male 0 0
Trans 1 1
  • Here are Four levels, but now you have to make 3 new variables
  • Female is the reference group
Variable C1 C2 C3
Cis Female 0 0 0
Cis Male 0 0 1
Trans Female 0 1 0
Trans Male 1 0 0

2.1.1 Regression equation

  • Two Levels: \(Y = B_1C1 + B_0\)
  • Three Levels: \(Y = B_1C1 +B_2C2+ B_0\)
  • Four Levels: \(Y = B_1C1 + B_2C2 + B_2C3 + B_0\)

2.1.2 Creating Dummy Variables

  • In SPSS you would have to HAND create dummy variables using Recode, but it R its a little easier
  • In R, we simply have to convert our variable into a factor
  • R will default to alphabetical order, so easiest to work with numbers (not words)
  • Best practice in R: Convert all your words into numbers (start with 0)
  • Next, convert your variable into a factor (as.factor)
  • First, lets simulate a simple factor to work with
  • Emotion rating ~ Expressive intentions of the actor (0 = flat, 1 = Normal, 2 = Exaggerated )
  • Three Levels: \(Emotion Rating = 0*Flat + 5*Normal +10*Exaggerated + 50 + \epsilon\)
Variable C1 C2
Flat 0 0
Normal 1 0
Exaggerated 0 1
library(car)
#Set up simulation
set.seed(42)
N <- 200
X<- sample(rep(c(0,1,2),N),N,replace = FALSE)
# Our equation to create Y
Y <- 5*X + 50 + rnorm(N, sd=10)
#Built our data frame
Emotion.Data<-data.frame(Emotion=Y,Style=X)

scatterplot(Emotion~Style, data= Emotion.Data, reg.line=FALSE, smoother=loessLine)

  • If the data is already coded as 0, 1,2 all we have to do is (also note R will not scatterplot it the same way)
Emotion.Data$StyleD<-as.factor(Emotion.Data$Style)
scatterplot(Emotion~StyleD, data= Emotion.Data, reg.line=FALSE, smoother=loessLine)

## [1] "169" "18"  "187"
  • if the data were coded as words (Flat, Normal, Exaggerated), R MIGHT have put Exaggerated as baseline
  • We can fix that manually like by creating the factor ourselves
# Here I will convert the data into words first (cause I had to simulate numbers)
Emotion.Data$StyleF <- factor(Emotion.Data$Style,
                              level=c(0,1,2),
                              labels=c("Flat", "Normal", "Exaggerated"))

Emotion.Data$StyleN<- relevel(Emotion.Data$StyleF, ref = "Normal")

scatterplot(Emotion~StyleF, data= Emotion.Data, reg.line=FALSE, smoother=loessLine)

## [1] "169" "18"  "187"

2.1.3 Interpret Regression

  • Order of the factors matters
  • Remember you are making each level of the variable a term in the equation as you have made a new variable for each level (except baseline)
  • R make these dummy coded automatically so its easy to forget this
  • for 3 levels we will have 3 terms: intercept and Style 1 and Style 2.
library(stargazer)
Model.1<-lm(Emotion ~ StyleD, data = Emotion.Data)
stargazer(Model.1,type="html",
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Constant 49.726*** (1.256)
StyleD1 5.099** (1.735)
StyleD2 9.349*** (1.674)
Observations 200
R2 0.137
Adjusted R2 0.128
F Statistic 15.597*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001
  • if we use our factor coded as words so we can read it easier
Model.1.F<-lm(Emotion ~ StyleF, data = Emotion.Data)
stargazer(Model.1.F,type="html",
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Constant 49.726*** (1.256)
StyleFNormal 5.099** (1.735)
StyleFExaggerated 9.349*** (1.674)
Observations 200
R2 0.137
Adjusted R2 0.128
F Statistic 15.597*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001

2.1.3.1 Coefficients

  • Intercept = Intercept of the equation (Which is the mean of Flat)
  • StyleFNormal = coefficient (slope of Normal) from baseline (Flat)
  • StyleFExaggerated = coefficient (slope of Exaggerated) from baseline (Flat)

2.1.3.2 Means per Condition

  • Flat = Intercept
  • Normal = Intercept + StyleFNormal
  • Exaggerated = Intercept + StyleFExaggerated

2.1.3.3 Pvalues

  • The pvalue on the intercept asks if the baseline (Flat) condition different from zero
  • The pvalue on the slopes asks if each of the other levels is different from baseline (Flat)

2.1.4 Rotate the matrix

  • What if we want to know if Normal is different from Exaggerated?
  • We need to relevel (aka change what is zero)
Variable C1 C2
Flat 1 0
Normal 0 0
Exaggerated 0 1
# Here I will convert the data into words first (cause I had to simulate numbers)
Emotion.Data$StyleN<- relevel(Emotion.Data$StyleF, ref = "Normal")
scatterplot(Emotion~StyleN, data= Emotion.Data, reg.line=FALSE, smoother=loessLine)

## [1] "169" "18"  "187"
  • Notice in the table the labels and values have changed
Model.1.N<-lm(Emotion ~ StyleN, data = Emotion.Data)
stargazer(Model.1.N,type="html",
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Constant 54.825*** (1.197)
StyleNFlat -5.099** (1.735)
StyleNExaggerated 4.249** (1.630)
Observations 200
R2 0.137
Adjusted R2 0.128
F Statistic 15.597*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001

2.2 Contrast Coding

2.2.1 Deviation Coding

  • Note: R calls them Contrast Sums
  • Lets make the Flat the reference again
Variable C1 C2
Normal 0 1
Exaggerated 1 0
Flat -1 -1
  • For deviatation code, R will use the LAST variable as references so we need to recode it by hand to be first as to match the order we want in the above table
Emotion.Data$Style.C.S <- factor(Emotion.Data$Style,
                              level=c(1,2,0),
                              labels=c("Normal", "Exaggerated", "Flat"))
contrasts(Emotion.Data$Style.C.S) = contr.sum
attributes(Emotion.Data$Style.C.S)$contrasts
##             [,1] [,2]
## Normal         1    0
## Exaggerated    0    1
## Flat          -1   -1
  • Lets look at how things differ from the mean of all conditions (grand mean)
Model.1.CS<-lm(Emotion ~ Style.C.S, data = Emotion.Data)
stargazer(Model.1.CS,type="html",
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Constant 54.542*** (0.686)
Style.C.S1 0.283 (0.974)
Style.C.S2 4.533*** (0.937)
Observations 200
R2 0.137
Adjusted R2 0.128
F Statistic 15.597*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001
  • Intercept = Mean of means (grand mean)
library(knitr)
#Mean of each condition
Mean.Interaction<-aggregate(Emotion~StyleF,data = Emotion.Data, FUN=mean)
kable(Mean.Interaction)
StyleF Emotion
Flat 49.72607
Normal 54.82525
Exaggerated 59.07459
#grand mean = 
sum(aggregate(Emotion~StyleF,data = Emotion.Data, FUN=mean)[2])/3
## [1] 54.54197

2.2.1.1 Coefficients

  • Style.C.S1 = coefficient on Normal as it differs from grand mean
  • Style.C.S2 = coefficient on Exaggerated as it differs from grand mean
  • To get the means for each condition:

2.2.1.2 Means per Condition

  • Flat = Cannot get from this model
  • Normal = Intercept + Style.C.S1
  • Exaggerated = Intercept + Style.C.S2

2.2.1.3 Pvalues

  • The pvalue on the intercept asks if the grand mean different from zero
  • The pvalue on the slopes asks if each of the other levels is different from grand mean
  • Note: We have lost any ability to ask about Flat condition, to get it back we would have to rotate the baseline and do it again

2.2.2 Simple Coding

  • They must sum to zero and the abs(values) must sum to 1
  • Like in ANOVA you can design these to ask specific questions by merging conditions (or not)
  • We will use the contr.treatment treatment (which R is using to automatically convert your categorical variables already)
  • Just like dummy coding but we change the meaning of the intercept
  • Reference level is first again
Variable C1 C2
Flat -1/3 -1/3
Normal 2/3 -1/3
Exaggerated -1/3 2/3
Emotion.Data$Style.Simple <- factor(Emotion.Data$Style,
                              level=c(0,1,2),
                              labels=c("Flat", "Normal", "Exaggerated"))

Levels<-3
Simple.1<-contr.treatment(Levels)
#Dummy code
Simple.1
##   2 3
## 1 0 0
## 2 1 0
## 3 0 1
#Make your custom codes
my.coding<-matrix(rep(1/Levels, Levels*(Levels-1)), ncol=Levels-1)
my.simple<-Simple.1-my.coding
my.simple
##            2          3
## 1 -0.3333333 -0.3333333
## 2  0.6666667 -0.3333333
## 3 -0.3333333  0.6666667
contrasts(Emotion.Data$Style.Simple)<-my.simple
Model.1.Simple<-lm(Emotion ~ Style.Simple, data = Emotion.Data)
stargazer(Model.1.Simple,type="html",
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Constant 54.542*** (0.686)
Style.Simple2 5.099** (1.735)
Style.Simple3 9.349*** (1.674)
Observations 200
R2 0.137
Adjusted R2 0.128
F Statistic 15.597*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001

2.2.2.1 Coefficients

  • This merges the dummy and devience codings thus:
  • Intercept = Mean of means (grand mean)
  • StyleFNormal = slope of Normal from baseline (Flat)
  • StyleFExaggerated = slope of Exaggerated from baseline (Flat)

2.2.2.2 Means per Condition

-You cannot get means of each condition from this model

2.2.2.3 Pvalues

  • The pvalue on the intercept asks if the grand mean different from zero
  • The pvalue on the slopes asks if each of the other levels is different from baseline (Flat)

2.2.3 Other types of contrast coding

  • Helmert: compares each level to the mean of the subsequent levels [can be reversed]
  • Forward Difference coding: one level is compared to the next (adjacent) level. (level 1 vs 2. level 2 vs 3) [can be reversed]
  • Custom: Merge and compare levels at will

2.2.3.1 Center variables and test slopes

  • There is no reason why you cannot treat the variables as continuous is they are ordinal
  • just center them and treat like continuous variable

3 Models with Interactions (2 Nominal variables)

  • Interactions can be tricky as the interpretation depends on how you code IVs
  • First lets try some categorical vs categorical interactions
  • We will add a variable to our experiment from above, we will add the location where the actors work (Movie vs Theatre)
  • Emotion rating ~ Expressive intentions*location of the actor
  • \(Emotion Rating = -3*Flat + 0*Normal +3*Exaggerated +0*Movie - 1.5*Theatre - 0*Flat*Movie + 0*Normal*Movie +0*Exaggerated*Movie - 10*Flat*Theatre +0*Normal*Theatre +10*Exaggerated*Theatre + 50 + \epsilon\)
#Set up simulation

set.seed(42)
N <- 200
X <- sample(rep(c(-1,0,1),N),N,replace = FALSE)
Z <- sample(rep(c(0,1),N*3/2),N,replace = FALSE)

# Our equation to create Y
Y <- 3*X -1.5*Z+10*X*Z+ 50 + rnorm(N, sd=10)
#Built our data frame
Emotion.Data.2<-data.frame(Emotion=Y,Style=X,Location=Z)
Emotion.Data.2$Style<-Emotion.Data.2$Style+1

3.1 Dummy coding

  • Lets dummy code all of them: convert them to a label in the other we want
# Convert all our factors
Emotion.Data.2$StyleF <- factor(Emotion.Data.2$Style,
                              level=c(0,1,2),
                              labels=c("Flat", "Normal", "Exaggerated"))

Emotion.Data.2$LocationF <- factor(Emotion.Data.2$Location,
                              level=c(0,1),
                              labels=c("Movie Set", "Theatre"))

-Lets look at the collapsed means and the means per cell

Mean.Style<-aggregate(Emotion~StyleF,data = Emotion.Data.2, FUN=mean)
kable(Mean.Style)
StyleF Emotion
Flat 42.31459
Normal 47.71393
Exaggerated 57.61318
Mean.Location<-aggregate(Emotion~LocationF,data = Emotion.Data.2, FUN=mean)
kable(Mean.Location)
LocationF Emotion
Movie Set 50.51464
Theatre 49.22526
Mean.Interaction<-aggregate(Emotion~StyleF*LocationF,data = Emotion.Data.2, FUN=mean)
kable(Mean.Interaction)
StyleF LocationF Emotion
Flat Movie Set 48.09662
Normal Movie Set 49.25575
Exaggerated Movie Set 53.42796
Flat Theatre 37.75905
Normal Theatre 45.54397
Exaggerated Theatre 61.79840
  • Let examine our regression, but we need to examine a main effects and interaction model
Model.I1.Dummy<-lm(Emotion ~ StyleF+LocationF, data = Emotion.Data.2)
Model.I2.Dummy<-lm(Emotion ~ StyleF*LocationF, data = Emotion.Data.2)

stargazer(Model.I1.Dummy,Model.I2.Dummy,type="html",
          column.labels = c("Main Effects", "Interaction"),
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 42.880*** (1.558) 48.097*** (1.857)
StyleFNormal 5.254** (1.848) 1.159 (2.409)
StyleFExaggerated 15.239*** (1.774) 5.331* (2.409)
LocationFTheatre -1.011 (1.454) -10.338*** (2.482)
StyleFNormal:LocationFTheatre 6.626 (3.441)
StyleFExaggerated:LocationFTheatre 18.708*** (3.298)
Observations 200 200
R2 0.288 0.395
Adjusted R2 0.277 0.379
F Statistic 26.460*** (df = 3; 196) 25.285*** (df = 5; 194)
Note: p<0.05; p<0.01; p<0.001
  • You will notice large differences between the main effects and interaction model
  • This is because the meaning coefficients in the interaction differ from the main effects model
  • The main effects were explained above, but they change meaning alittle because there is second variable

3.1.1 Main Effects

3.1.1.1 Coefficients

  • These do not connect back to the individual cells as you are assuming the two factors have independent effects
  • Thus these are hypthotical values (not connected to the individual cells)
  • Intercept = Estimate of the mean, assuming the two factors have independent effects at their 0 points [baseline]
  • StyleFNormal = Normal - Flat (assuming the two factors are independent)
  • StyleFExaggerated = Exaggerated - Flat (assuming the two factors are independent)
  • LocationFTheatre = Theatre - Movie(assuming the two factors are independent)

3.1.1.2 Means per Condition

  • You cannot get them

3.1.1.3 Pvalues

  • The pvalue on the intercept asks if the baseline is different from zero
  • The pvalue on the differences asks if they are from different from baseline

3.1.2 Interactions

3.1.2.1 Coefficients

  • These cells connect back to experimental cells
  • Intercept = Location(0) @ Style(0) aka Movie @ Flat [real value]
  • StyleFNormal = Differnce of [Location(0) @ Style(1)] - [Location(0) @ Style(0)]
  • StyleFExaggerated = Differnce of [Location(0) @ Style(2)] - [Location(0) @ Style(0)]
  • LocationFTheatre = Differnce of [Location(1) @ Style(0)] - [Location(0) @ Style(0)]
  • StyleFNormal:LocationFTheatre = Differnce of [Location(1) @ Style(1)] - [Location(0) @ Style(1) - Location(0) @ Style(0) + [Location(1) @ Style(0)] - [Location(0) @ Style(0)]
  • StyleFExaggerated:LocationFTheatre = Differnce of [Location(1) @ Style(2)] - [Location(0) @ Style(2) - Location(0) @ Style(0) + [Location(2) @ Style(0)] - [Location(0) @ Style(0)]

3.1.2.2 Means per Condition

  • You can find all means for all cells!
  • Flat @ Movie = Intercept
  • Normal @ Movie = Intercept + StyleFNormal
  • Exaggerated @ Movie = Intercept + StyleFExaggerated
  • Flat @ Theatre = Intercept + LocationFTheatre
  • Normal @ Theatre = Intercept + LocationFTheatre+StyleFNormal+StyleFNormal:LocationFTheatre
  • Exaggerated @ Theatre = Intercept + LocationFTheatre + StyleFExaggerated + StyleFExaggerated:LocationFTheatre

3.1.2.3 Pvalues

  • The pvalue on the intercept asks if the baseline is different from zero
  • The pvalue on the differences asks if they are from different from baseline
  • But these are now are now simple effects

3.1.3 Main effect model vs Interaction model

  • Since the results are clearly not additive, the main effect model is useful only in which to understand how the terms have changed
  • Gives some insight into the interaction

3.1.4 Graph Model

library(effects)
Main.1<-effect("LocationF", Model.I2.Dummy)
plot(Main.1, multiline = TRUE)

Main.2<-effect("StyleF", Model.I2.Dummy)
plot(Main.2, multiline = TRUE)

Inter.1<-effect("StyleF*LocationF", Model.I2.Dummy)
plot(Inter.1, multiline = TRUE)

3.1.5 Connection to between-subject ANOVA

  • Regression with only categorical variables can be converted into an ANOVA very easily
  • Thus it can be treated just like ANOVA
  • but the regression makes the ANOVA process moot as you can now the regression can be coded in such a way that you can test follow up tests in a way you want to test them all
Anova(Model.I2.Dummy, type="III")
## Anova Table (Type III tests)
## 
## Response: Emotion
##                  Sum Sq  Df  F value    Pr(>F)    
## (Intercept)       60145   1 671.1619 < 2.2e-16 ***
## StyleF              535   2   2.9837   0.05293 .  
## LocationF          1554   1  17.3419 4.695e-05 ***
## StyleF:LocationF   3052   2  17.0304 1.534e-07 ***
## Residuals         17385 194                       
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  • Note, we have to call for a Type III sum of squares to match SPSS output as R would default to Type I

3.2 Contrast Coding

3.2.1 Deviation Coding

  • Lets code each variable as we did above
Emotion.Data.2$Style.C.S <- factor(Emotion.Data.2$Style,
                              level=c(1,2,0),
                              labels=c("Normal", "Exaggerated", "Flat"))
Emotion.Data.2$Location.C.S <- factor(Emotion.Data.2$Location,
                              level=c(1,0),
                              labels=c("Theatre", "Movie Set"))

contrasts(Emotion.Data.2$Style.C.S) = contr.sum
contrasts(Emotion.Data.2$Location.C.S) = contr.sum
attributes(Emotion.Data.2$Style.C.S)$contrasts
##             [,1] [,2]
## Normal         1    0
## Exaggerated    0    1
## Flat          -1   -1
attributes(Emotion.Data.2$Location.C.S)$contrasts
##           [,1]
## Theatre      1
## Movie Set   -1
  • Lets look at how things differ from the mean of all conditions (grand mean)
Model.I1.C.S<-lm(Emotion ~ Style.C.S+Location.C.S, data = Emotion.Data.2)
Model.I2.C.S<-lm(Emotion ~ Style.C.S*Location.C.S, data = Emotion.Data.2)

stargazer(Model.I1.C.S,Model.I2.C.S,type="html",
          column.labels = c("Main Effects", "Interaction"),
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 49.205*** (0.726) 49.314*** (0.678)
Style.C.S1 -1.577 (1.036) -1.914* (0.966)
Style.C.S2 8.408*** (0.992) 8.300*** (0.924)
Location.C.S1 -0.506 (0.727) -0.946 (0.678)
Style.C.S1:Location.C.S1 -0.909 (0.966)
Style.C.S2:Location.C.S1 5.132*** (0.924)
Observations 200 200
R2 0.288 0.395
Adjusted R2 0.277 0.379
F Statistic 26.460*** (df = 3; 196) 25.285*** (df = 5; 194)
Note: p<0.05; p<0.01; p<0.001
  • Again we are testing between the grand mean and the individual terms

3.2.1.1 Main Effects

3.2.1.1.1 Coefficients
  • These do not connect back to the individual cells as you are assuming the two factors have independent effects
  • Thus these are hypthotical Grand mean values
  • Intercept = Grand Mean, but assuming the two factors have independent effects
  • Style.C.S1 = Normal (averaged over location) - Grand Mean (assuming the two factors are independent)
  • Style.C.S2 = Exaggerated (averaged over location) - Grand Mean (assuming the two factors are independent)
  • Location.C.S1 = Theatre (averaged over Style) - Grand Mean (assuming the two factors are independent)
3.2.1.1.2 Means per Condition
  • Cannot get from this model
3.2.1.1.3 Pvalues
  • The pvalue on the intercept asks if the baseline (Grand Mean) is different from zero
  • The pvalue on the slopes asks if each of the other levels is different from the baseline (Grand Mean)
  • Note we missing tests on Flat and Movie cell, we would need to rotate the matrix and run again

3.2.1.2 Interactions

3.2.1.2.1 Coefficients
  • Intercept = Grand Mean (all 6 cells mean averaged)
  • Style.C.S1 = Normal (averaged over location) from Grand Mean
  • Style.C.S2 = Exaggerated (averaged over location) from Grand Mean
  • Location.C.S1 = Theatre (averaged over Style) from Grand Mean
  • Style.C.S1:Location.C.S1 = difference of Normal @ Theatre from Grand Mean
  • Style.C.S2:Location.C.S1 = difference of Exaggerated @ Theatre from Grand Mean
3.2.1.2.2 Means per Condition
  • Cannot get from this model
3.2.1.2.3 Pvalues
  • The pvalue on the intercept asks if the baseline (Grand Mean) is different from zero
  • The pvalue on the differences asks if each of the other levels is from the (Grand Mean)
  • Note we missing tests on Flat and movie cell, we would need to rotate the matrix and run again

4 Models with Interactions (1 Nominal and 1 Continuous Variable)

  • We will change our experiment from above, we will add a likert scale which the actor rates how “good” they think the performance was [0 terrible to 7 excellent]
  • Emotion rating ~ Quality Rating*location of the actor
  • \(Emotion Rating = -3*qua + 0*Normal +3*Exaggerated +0*Movie - 1.5*Theatre - 0*Flat*Movie + 0*Normal*Movie +0*Exaggerated*Movie - 10*Flat*Theatre +0*Normal*Theatre +10*Exaggerated*Theatre + 50 + \epsilon\)
#Set up simulation
set.seed(42)
N <- 200
X <- runif(N,-3,3)
Z <- sample(rep(c(0,1),N),N,replace = FALSE)

# Our equation to create Y
Y <- 4*X +2*Z+8*X*Z+ 50 + rnorm(N, sd=10)
#Built our data frame
Emotion.Data.3<-data.frame(Emotion=Y,Quality=X,Location=Z)

4.1 Center the continuous variable

  • Best to center as its will help us interpret
# Convert all our factors
Emotion.Data.3$Quality.C <- scale(Emotion.Data.3$Quality, scale = FALSE)[,]

4.2 Dummy coding of our nominal variable

  • Dummy coding will allow us to interpret the interaction as simple slopes analysis
  • Lets dummy code Location
# Convert all our factors
Emotion.Data.3$LocationF <- factor(Emotion.Data.3$Location,
                                   level=c(0,1),
                                   labels=c("Movie Set","Theatre"))

4.2.1 Interpret Regression

Model.E3.1<-lm(Emotion ~ Quality.C+LocationF, data = Emotion.Data.3)
Model.E3.2<-lm(Emotion ~ Quality.C*LocationF, data = Emotion.Data.3)

stargazer(Model.E3.1,Model.E3.2,type="html",
          column.labels = c("Main Effects", "Interaction"),
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 49.344*** (1.243) 50.207*** (0.959)
Quality.C 7.970*** (0.502) 3.573*** (0.539)
LocationFTheatre 4.106* (1.755) 4.137** (1.350)
Quality.C:LocationFTheatre 9.044*** (0.772)
Observations 200 200
R2 0.562 0.742
Adjusted R2 0.557 0.738
F Statistic 126.183*** (df = 2; 197) 187.927*** (df = 3; 196)
Note: p<0.05; p<0.01; p<0.001

4.2.2 Plotting Interaction

  • Often times you will need to use the effects package and plot by hand
  • The rochchalk package will work for simple models like this one
library(rockchalk)
plotSlopes(Model.E3.2, plotx = "Quality.C", modx = "LocationF")

4.2.3 Main Effects

4.2.3.1 Coefficients & Pvalues

  • Intercept = Mean of Quality @ Movies [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope [p = Is slope different from 0]
  • LocationFTheatre = Threatre difference from intercept [p = Is mean of Theatre different from movies @ mean of quality]

4.2.4 Interactions

4.2.4.1 Coefficients & Pvalues

  • Intercept = Mean of Quality @ Movies [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope @ Movies [p = Is the simple slope at movies different from 0]
  • LocationFTheatre = Threatre difference from intercept [p = Is mean of Theatre different from movies @ mean of quality]
  • Quality.C:LocationFTheatre= Quality.C slope @ Theatre [p = Is the simple slope at Theatre different from 0]

4.3 Deviation coding of our nomimal variable

  • We will still center quality
  • This creates a more ANOVA like interpretation of the interaction
Emotion.Data.3$LocationD <- factor(Emotion.Data.3$Location,
                                   level=c(1,0),
                                   labels=c("Theatre","Movie Set"))
contrasts(Emotion.Data.3$LocationD) = contr.sum
attributes(Emotion.Data.3$LocationD)$contrasts
##           [,1]
## Theatre      1
## Movie Set   -1

4.3.1 Interpret Regression

Model.E3.D1<-lm(Emotion ~ Quality.C+LocationD, data = Emotion.Data.3)
Model.E3.D2<-lm(Emotion ~ Quality.C*LocationD, data = Emotion.Data.3)

stargazer(Model.E3.D1,Model.E3.D2,type="html",
          column.labels = c("Main Effects", "Interaction"),
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 51.397*** (0.872) 52.275*** (0.675)
Quality.C 7.970*** (0.502) 8.095*** (0.386)
LocationD1 2.053* (0.877) 2.068** (0.675)
Quality.C:LocationD1 4.522*** (0.386)
Observations 200 200
R2 0.562 0.742
Adjusted R2 0.557 0.738
F Statistic 126.183*** (df = 2; 197) 187.927*** (df = 3; 196)
Note: p<0.05; p<0.01; p<0.001

4.3.2 Main Effects

4.3.2.1 Coefficients & Pvalues

  • Intercept = Mean of Quality @ mean of Movie & Theatre (imaginary thing) [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope [p = Is slope different from 0]
  • LocationFTheatre = Threatre difference from 0 (not - 1) thus is 1/2 the slope of the dummy code [p = Is mean of Theatre different from movies @ mean of quality]

4.3.3 Interactions

4.3.3.1 Coefficients & Pvalues

  • Intercept = Mean of Quality @ mean of Movie & Theatre (imaginary thing) [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope @ mean of Movie & Theatre (imaginary thing) [p = Is the Main effect of quality @ mean of Movie & Theatre]
  • LocationFTheatre = Threatre difference from intercept [p = Is the Main effect of Location @ mean of quality]
  • Quality.C:LocationFTheatre= Quality.C slope difference between Movie and theatre [p = Is the interaction]
  • Note all coefficients are 1/2 of the size they should be!

4.4 Simple coding of our nomimal variable

  • We will still center quality
  • This creates a more ANOVA like interpretation of the interaction,
  • Most importantly it does not screw up our coefficients as they match the dummy code values (which make the most sense)
  • This time I will hand code the it into a factor (easy with only 2 levels)
Emotion.Data.3$LocationS<-as.numeric(Emotion.Data.3$Location)-.5

4.4.1 Interpret Regression

Model.E3.S1<-lm(Emotion ~ Quality.C+LocationS, data = Emotion.Data.3)
Model.E3.S2<-lm(Emotion ~ Quality.C*LocationS, data = Emotion.Data.3)

stargazer(Model.E3.S1,Model.E3.S2,type="html",
          column.labels = c("Main Effects", "Interaction"),
          intercept.bottom = FALSE,
          single.row=TRUE, 
          notes.append = FALSE,
          omit.stat=c("ser"),
          star.cutoffs = c(0.05, 0.01, 0.001),
          header=FALSE)
Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 51.397*** (0.872) 52.275*** (0.675)
Quality.C 7.970*** (0.502) 8.095*** (0.386)
LocationS 4.106* (1.755) 4.137** (1.350)
Quality.C:LocationS 9.044*** (0.772)
Observations 200 200
R2 0.562 0.742
Adjusted R2 0.557 0.738
F Statistic 126.183*** (df = 2; 197) 187.927*** (df = 3; 196)
Note: p<0.05; p<0.01; p<0.001

4.4.2 Main Effects

4.4.2.1 Coefficients & Pvalues

  • Intercept = Mean of Quality @ mean of Movie & Theatre (imaginary thing) [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope [p = Is slope different from 0]
  • LocationFTheatre = Threatre difference from 0 [p = Is mean of Theatre different from movies @ mean of quality]

4.4.3 Interactions

4.4.3.1 Coefficients & Pvalues

  • Intercept = Mean of Quality @ mean of Movie & Theatre (imaginary thing) [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope @ mean of Movie & Theatre (imaginary thing) [p = Is the Main effect of quality @ mean of Movie & Theatre]
  • LocationS = Threatre difference from intercept [p = Is the Main effect of Location @ mean of quality]
  • Quality.C:LocationS= Quality.C slope difference between Movie and theatre [p = Is their an interaction]
  • Note all coefficients are their proper size now (to match true differences)
  • Best option is often dummy or simple, deviation here is weird
LS0tDQp0aXRsZTogJ0NhdGVnb3JpY2FsIFZhcmlhYmxlcycNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBmb250c2l6ZTogOHB0DQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KLS0tDQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTUpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLmhlaWdodD0zLjc1KQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5hbGlnbj0nY2VudGVyJykgDQpgYGANCg0KIyBOb21pbmFsIFZhcmlhYmxlcyANCi0gVGhpbmdzIGxpa2UgZ2VuZGVyIG9yIGNvbG9yICh0ZXJtcyB3ZSB3b3VsZCBoYXZlIGFzIGZhY3RvcnMgaW4gQU5PVkEpDQotIERlY2lzaW9ucyBoYXZlIHRvIG1hZGUgb24gaG93IHRvIHRyZWF0IHRoZXNlIHZhcmlhYmxlcyBpbiBhIHJlZ3Jlc3Npb24NCi0gV2Ugd2lsbCBhc3N1bWUgKGZvciBub3cpIHRoYXQgYSBzdWJqZWN0IGNhbiBiZSBhIG1lbWJlciBvZiAqb25seSBvbmUqIGxldmVsIG9mIGEgZmFjdG9yIGEgdmFyaWFibGUgKGkuZS4sIHlvdSBjYW4gYmx1ZSBvciByZWQsIGJ1dCBub3QgYm90aCkNCi0gVGhlcmUgYXJlIHRocmVlIGJhc2ljIG1ldGhvZHMgd2Ugd2lsbCBjb3ZlciBhbmQgaG93IHRvIGludGVycHJldCB0aGVpciBlZmZlY3RzIGFuZCBpbnRlcmFjdGlvbnMNCi0gS2V5IHRvIHJlbWVtYmVyIHlvdSBhcmUgYmFzaWNhbGx5IGRvaW5nIHRvIHQtdGVzdHMgc28geW91IGFyZSBhbHdheXMganVzdCBjb21wYXJpbmcgdHdvIHRoaW5ncywgYnV0IHdoYXQgdGhvc2UgdHdvIHRoaW5ncyBhcmUgd2lsbCBjaGFnbmUgYXMgeW91IGNoYW5nZSB5b3UgY29kaW5ncyAodGhpbmsgdGhlIGNvbmNlcHQgb2YgY29udHJhc3RzIGluIEFOT1ZBIGZyb20gbGFzdCBzZW1lc3RlcikNCg0KIyBNb2RlbHMgd2l0aCBubyBJbnRlcmFjdGlvbnMgKDEgTm9taW5hbCB2YXJpYWJsZSkNCg0KIyMgRHVtbXkgQ29kaW5nDQotIFRoZSBtb3N0IGNvbW1vbiBhbmQgYmFzaWMgdHlwZSB1c2VkIChkZWZhdWx0IGluIFIgaWYgaXQgc2Vuc2VzIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUpDQotIEZvciBlYWNoIHZhcmlhYmxlIHlvdSBtdXN0IGFzc2lnbiBhIHJlZmVyZW5jZSBncm91cCAoYSBiYXNlbGluZSkgZm9yIGVhY2ggdmFyaWFibGUNCi0gRWFjaCBncm91cCBpcyBjb21wYXJlZCB0byB0aGUgcmVmZXJlbmNlIGdyb3VwDQotIFdlIGFzayB0aGUgcXVlc3Rpb24sICpob3cgbXVjaCBkb2VzIGVhY2ggZ3JvdXAgZGV2aWF0ZSBmcm9tIHRoZSByZWZlcmVuY2UqDQotIEhlcmUgYXJlIHR3byBsZXZlbHMgb2Ygb25lIGZhY3Rvcg0KDQpWYXJpYWJsZSB8IEMxIA0KLS0tLS0tLS0tfCAtLS0NCkZlbWFsZSAgIHwgMA0KTWFsZSAgICAgfCAxDQoNCi0gSGVyZSBhcmUgVGhyZWUgbGV2ZWxzLCBidXQgbm93IHlvdSBoYXZlIHRvIG1ha2UgMiBuZXcgdmFyaWFibGVzIA0KLSBGZW1hbGUgaXMgdGhlIHJlZmVyZW5jZSBncm91cA0KDQpWYXJpYWJsZXwgQzF8IEMyDQotLS0tLS0tLXwgLS18IC0tDQpGZW1hbGUgIHwgMCB8IDANCk1hbGUgICAgfCAwIHwgMQ0KVHJhbnMgICB8IDEgfCAxDQoNCi0gTWFsZSBpcyB0aGUgcmVmZXJlbmNlIGdyb3VwDQoNClZhcmlhYmxlfCBDMXwgQzINCi0tLS0tLS0tfCAtLXwgLS0tDQpGZW1hbGUgIHwgMCB8IDENCk1hbGUgICAgfCAwIHwgMA0KVHJhbnMgICB8IDEgfCAxDQoNCi0gSGVyZSBhcmUgRm91ciBsZXZlbHMsIGJ1dCBub3cgeW91IGhhdmUgdG8gbWFrZSAzIG5ldyB2YXJpYWJsZXMgDQotIEZlbWFsZSBpcyB0aGUgcmVmZXJlbmNlIGdyb3VwDQoNClZhcmlhYmxlICAgICB8IEMxIHwgQzIgfCBDMw0KLS0tLS0tLS0tLS0tLXwgLS0gfCAtLSB8IC0tIA0KQ2lzIEZlbWFsZSAgIHwgMCAgfCAwICB8IDANCkNpcyBNYWxlICAgICB8IDAgIHwgMCAgfCAxDQpUcmFucyBGZW1hbGUgfCAwICB8IDEgIHwgMA0KVHJhbnMgTWFsZSAgIHwgMSAgfCAwICB8IDANCg0KDQojIyMgUmVncmVzc2lvbiBlcXVhdGlvbg0KLSBUd28gTGV2ZWxzOiAkWSA9IEJfMUMxICsgQl8wJA0KLSBUaHJlZSBMZXZlbHM6ICRZID0gQl8xQzEgK0JfMkMyKyBCXzAkDQotIEZvdXIgTGV2ZWxzOiAkWSA9IEJfMUMxICsgQl8yQzIgKyBCXzJDMyArIEJfMCQNCg0KIyMjIENyZWF0aW5nIER1bW15IFZhcmlhYmxlcw0KLSBJbiBTUFNTIHlvdSB3b3VsZCBoYXZlIHRvIEhBTkQgY3JlYXRlIGR1bW15IHZhcmlhYmxlcyB1c2luZyBSZWNvZGUsIGJ1dCBpdCBSIGl0cyBhIGxpdHRsZSBlYXNpZXINCi0gSW4gUiwgd2Ugc2ltcGx5IGhhdmUgdG8gY29udmVydCBvdXIgdmFyaWFibGUgaW50byBhIGZhY3Rvcg0KLSBSIHdpbGwgZGVmYXVsdCB0byBhbHBoYWJldGljYWwgb3JkZXIsIHNvIGVhc2llc3QgdG8gd29yayB3aXRoIG51bWJlcnMgKG5vdCB3b3JkcykNCi0gQmVzdCBwcmFjdGljZSBpbiBSOiBDb252ZXJ0IGFsbCB5b3VyIHdvcmRzIGludG8gbnVtYmVycyAoc3RhcnQgd2l0aCAwKQ0KLSBOZXh0LCBjb252ZXJ0IHlvdXIgdmFyaWFibGUgaW50byBhIGZhY3RvciAoYXMuZmFjdG9yKQ0KLSBGaXJzdCwgbGV0cyBzaW11bGF0ZSBhIHNpbXBsZSBmYWN0b3IgdG8gd29yayB3aXRoDQotIEVtb3Rpb24gcmF0aW5nIH4gRXhwcmVzc2l2ZSBpbnRlbnRpb25zIG9mIHRoZSBhY3RvciAoMCA9IGZsYXQsIDEgPSBOb3JtYWwsIDIgPSBFeGFnZ2VyYXRlZCApDQotIFRocmVlIExldmVsczogJEVtb3Rpb24gUmF0aW5nID0gMCpGbGF0ICsgNSpOb3JtYWwgKzEwKkV4YWdnZXJhdGVkICsgNTAgKyBcZXBzaWxvbiQNCg0KVmFyaWFibGUgICAgfCBDMXwgQzINCi0tLS0tLS0tLS0tLXwgLS18IC0tLQ0KRmxhdCAgICAgICAgfCAwIHwgMA0KTm9ybWFsICAgICAgfCAxIHwgMA0KRXhhZ2dlcmF0ZWQgfCAwIHwgMQ0KDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGNhcikNCiNTZXQgdXAgc2ltdWxhdGlvbg0Kc2V0LnNlZWQoNDIpDQpOIDwtIDIwMA0KWDwtIHNhbXBsZShyZXAoYygwLDEsMiksTiksTixyZXBsYWNlID0gRkFMU0UpDQojIE91ciBlcXVhdGlvbiB0byBjcmVhdGUgWQ0KWSA8LSA1KlggKyA1MCArIHJub3JtKE4sIHNkPTEwKQ0KI0J1aWx0IG91ciBkYXRhIGZyYW1lDQpFbW90aW9uLkRhdGE8LWRhdGEuZnJhbWUoRW1vdGlvbj1ZLFN0eWxlPVgpDQoNCnNjYXR0ZXJwbG90KEVtb3Rpb25+U3R5bGUsIGRhdGE9IEVtb3Rpb24uRGF0YSwgcmVnLmxpbmU9RkFMU0UsIHNtb290aGVyPWxvZXNzTGluZSkNCmBgYA0KDQotIElmIHRoZSBkYXRhIGlzIGFscmVhZHkgY29kZWQgYXMgMCwgMSwyIGFsbCB3ZSBoYXZlIHRvIGRvIGlzIChhbHNvIG5vdGUgUiB3aWxsIG5vdCBzY2F0dGVycGxvdCBpdCB0aGUgc2FtZSB3YXkpDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KRW1vdGlvbi5EYXRhJFN0eWxlRDwtYXMuZmFjdG9yKEVtb3Rpb24uRGF0YSRTdHlsZSkNCnNjYXR0ZXJwbG90KEVtb3Rpb25+U3R5bGVELCBkYXRhPSBFbW90aW9uLkRhdGEsIHJlZy5saW5lPUZBTFNFLCBzbW9vdGhlcj1sb2Vzc0xpbmUpDQpgYGANCi0gaWYgdGhlIGRhdGEgd2VyZSBjb2RlZCBhcyB3b3JkcyAoRmxhdCwgTm9ybWFsLCBFeGFnZ2VyYXRlZCksIFIgTUlHSFQgaGF2ZSBwdXQgRXhhZ2dlcmF0ZWQgYXMgYmFzZWxpbmUNCi0gV2UgY2FuIGZpeCB0aGF0IG1hbnVhbGx5IGxpa2UgYnkgY3JlYXRpbmcgdGhlIGZhY3RvciBvdXJzZWx2ZXMgDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KIyBIZXJlIEkgd2lsbCBjb252ZXJ0IHRoZSBkYXRhIGludG8gd29yZHMgZmlyc3QgKGNhdXNlIEkgaGFkIHRvIHNpbXVsYXRlIG51bWJlcnMpDQpFbW90aW9uLkRhdGEkU3R5bGVGIDwtIGZhY3RvcihFbW90aW9uLkRhdGEkU3R5bGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1jKDAsMSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJGbGF0IiwgIk5vcm1hbCIsICJFeGFnZ2VyYXRlZCIpKQ0KDQpFbW90aW9uLkRhdGEkU3R5bGVOPC0gcmVsZXZlbChFbW90aW9uLkRhdGEkU3R5bGVGLCByZWYgPSAiTm9ybWFsIikNCg0Kc2NhdHRlcnBsb3QoRW1vdGlvbn5TdHlsZUYsIGRhdGE9IEVtb3Rpb24uRGF0YSwgcmVnLmxpbmU9RkFMU0UsIHNtb290aGVyPWxvZXNzTGluZSkNCmBgYA0KDQojIyMgSW50ZXJwcmV0IFJlZ3Jlc3Npb24NCi0gT3JkZXIgb2YgdGhlIGZhY3RvcnMgbWF0dGVycw0KLSBSZW1lbWJlciB5b3UgYXJlIG1ha2luZyBlYWNoIGxldmVsIG9mIHRoZSB2YXJpYWJsZSBhIHRlcm0gaW4gdGhlIGVxdWF0aW9uIGFzIHlvdSBoYXZlIG1hZGUgYSBuZXcgdmFyaWFibGUgZm9yIGVhY2ggbGV2ZWwgKGV4Y2VwdCBiYXNlbGluZSkNCi0gKlIgbWFrZSB0aGVzZSBkdW1teSBjb2RlZCBhdXRvbWF0aWNhbGx5IHNvIGl0cyBlYXN5IHRvIGZvcmdldCB0aGlzKg0KLSBmb3IgMyBsZXZlbHMgd2Ugd2lsbCBoYXZlIDMgdGVybXM6IGludGVyY2VwdCBhbmQgU3R5bGUgMSBhbmQgU3R5bGUgMi4NCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J2FzaXMnfQ0KbGlicmFyeShzdGFyZ2F6ZXIpDQpNb2RlbC4xPC1sbShFbW90aW9uIH4gU3R5bGVELCBkYXRhID0gRW1vdGlvbi5EYXRhKQ0Kc3RhcmdhemVyKE1vZGVsLjEsdHlwZT0iaHRtbCIsDQogICAgICAgICAgaW50ZXJjZXB0LmJvdHRvbSA9IEZBTFNFLA0KICAgICAgICAgIHNpbmdsZS5yb3c9VFJVRSwgDQogICAgICAgICAgbm90ZXMuYXBwZW5kID0gRkFMU0UsDQogICAgICAgICAgb21pdC5zdGF0PWMoInNlciIpLA0KICAgICAgICAgIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KLSBpZiB3ZSB1c2Ugb3VyIGZhY3RvciBjb2RlZCBhcyB3b3JkcyBzbyB3ZSBjYW4gcmVhZCBpdCBlYXNpZXINCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J2FzaXMnfQ0KTW9kZWwuMS5GPC1sbShFbW90aW9uIH4gU3R5bGVGLCBkYXRhID0gRW1vdGlvbi5EYXRhKQ0Kc3RhcmdhemVyKE1vZGVsLjEuRix0eXBlPSJodG1sIiwNCiAgICAgICAgICBpbnRlcmNlcHQuYm90dG9tID0gRkFMU0UsDQogICAgICAgICAgc2luZ2xlLnJvdz1UUlVFLCANCiAgICAgICAgICBub3Rlcy5hcHBlbmQgPSBGQUxTRSwNCiAgICAgICAgICBvbWl0LnN0YXQ9Yygic2VyIiksDQogICAgICAgICAgc3Rhci5jdXRvZmZzID0gYygwLjA1LCAwLjAxLCAwLjAwMSksDQogICAgICAgICAgaGVhZGVyPUZBTFNFKQ0KYGBgDQoNCiMjIyMgQ29lZmZpY2llbnRzDQotIEludGVyY2VwdCA9IEludGVyY2VwdCBvZiB0aGUgZXF1YXRpb24gKFdoaWNoIGlzIHRoZSBtZWFuIG9mIEZsYXQpDQotIFN0eWxlRk5vcm1hbCA9IGNvZWZmaWNpZW50IChzbG9wZSBvZiBOb3JtYWwpIGZyb20gYmFzZWxpbmUgKEZsYXQpDQotIFN0eWxlRkV4YWdnZXJhdGVkID0gY29lZmZpY2llbnQgKHNsb3BlIG9mIEV4YWdnZXJhdGVkKSBmcm9tIGJhc2VsaW5lIChGbGF0KQ0KDQojIyMjIE1lYW5zIHBlciBDb25kaXRpb24NCg0KLSAqRmxhdCA9IEludGVyY2VwdCoNCi0gKk5vcm1hbCA9IEludGVyY2VwdCArIFN0eWxlRk5vcm1hbCoNCi0gKkV4YWdnZXJhdGVkID0gSW50ZXJjZXB0ICsgU3R5bGVGRXhhZ2dlcmF0ZWQqDQoNCiMjIyMgUHZhbHVlcw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBpbnRlcmNlcHQgYXNrcyBpZiB0aGUgYmFzZWxpbmUgKCpGbGF0KikgY29uZGl0aW9uIGRpZmZlcmVudCBmcm9tIHplcm8NCi0gVGhlIHB2YWx1ZSBvbiB0aGUgc2xvcGVzIGFza3MgaWYgZWFjaCBvZiB0aGUgb3RoZXIgbGV2ZWxzIGlzIGRpZmZlcmVudCBmcm9tIGJhc2VsaW5lICgqRmxhdCopDQoNCg0KIyMjIFJvdGF0ZSB0aGUgbWF0cml4DQotIFdoYXQgaWYgd2Ugd2FudCB0byBrbm93IGlmIE5vcm1hbCBpcyBkaWZmZXJlbnQgZnJvbSBFeGFnZ2VyYXRlZD8NCi0gV2UgbmVlZCB0byByZWxldmVsIChha2EgY2hhbmdlIHdoYXQgaXMgemVybykNCg0KVmFyaWFibGUgICAgfCBDMXwgQzINCi0tLS0tLS0tLS0tLXwgLS18IC0tLQ0KRmxhdCAgICAgICAgfCAxIHwgMA0KTm9ybWFsICAgICAgfCAwIHwgMA0KRXhhZ2dlcmF0ZWQgfCAwIHwgMQ0KDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQojIEhlcmUgSSB3aWxsIGNvbnZlcnQgdGhlIGRhdGEgaW50byB3b3JkcyBmaXJzdCAoY2F1c2UgSSBoYWQgdG8gc2ltdWxhdGUgbnVtYmVycykNCkVtb3Rpb24uRGF0YSRTdHlsZU48LSByZWxldmVsKEVtb3Rpb24uRGF0YSRTdHlsZUYsIHJlZiA9ICJOb3JtYWwiKQ0Kc2NhdHRlcnBsb3QoRW1vdGlvbn5TdHlsZU4sIGRhdGE9IEVtb3Rpb24uRGF0YSwgcmVnLmxpbmU9RkFMU0UsIHNtb290aGVyPWxvZXNzTGluZSkNCmBgYA0KDQotIE5vdGljZSBpbiB0aGUgdGFibGUgdGhlIGxhYmVscyBhbmQgdmFsdWVzIGhhdmUgY2hhbmdlZA0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J2FzaXMnfQ0KTW9kZWwuMS5OPC1sbShFbW90aW9uIH4gU3R5bGVOLCBkYXRhID0gRW1vdGlvbi5EYXRhKQ0Kc3RhcmdhemVyKE1vZGVsLjEuTix0eXBlPSJodG1sIiwNCiAgICAgICAgICBpbnRlcmNlcHQuYm90dG9tID0gRkFMU0UsDQogICAgICAgICAgc2luZ2xlLnJvdz1UUlVFLCANCiAgICAgICAgICBub3Rlcy5hcHBlbmQgPSBGQUxTRSwNCiAgICAgICAgICBvbWl0LnN0YXQ9Yygic2VyIiksDQogICAgICAgICAgc3Rhci5jdXRvZmZzID0gYygwLjA1LCAwLjAxLCAwLjAwMSksDQogICAgICAgICAgaGVhZGVyPUZBTFNFKQ0KYGBgDQoNCiMjIENvbnRyYXN0IENvZGluZw0KLSBTYW1lIGNvbnRyYXN0cyBhcyBpbiBvdXIgQU5PVkFzIGJ1dCB0aGVyZSBhcmUgdHdvIHZlcnNpb25zICh1bndlaWdodGVkIGFuZCB3ZWlnaHRlZCkgYW5kIGJvdGggbmVlZCB0byBzdW0gdG8gemVybw0KLSBXZSBhc2sgbm93IGEgZGlmZmVyZW50IHF1ZXN0aW9uLCAqaG93IG11Y2ggZG9lcyBlYWNoIGdyb3VwIGRldmlhdGUgZnJvbSB0aGUgbWVhbiBvZiBhbGwgZ3JvdXBzKg0KLSBJIHdpbGwgcmV2aWV3IG9ubHkgdGhlIG1vc3QgY29tbW9uIHNlZSBmb3IgdGhlIG90aGVyczoNCi0gaHR0cDovL3N0YXRzLmlkcmUudWNsYS5lZHUvci9saWJyYXJ5L3ItbGlicmFyeS1jb250cmFzdC1jb2Rpbmctc3lzdGVtcy1mb3ItY2F0ZWdvcmljYWwtdmFyaWFibGVzLw0KLSBJIHdpbGwgbm90IHNob3cgeW91IHRoZSB3ZWlnaHRlZCB2ZXJzaW9uIGFzIG5vdCBub3Qgb2Z0ZW4gdXNlZA0KLSBOb3RlIFIgY2FsbHMgZHVtbXkgY29kaW5nIGFzIGNvbnRyLnRyZWF0bWVudA0KDQojIyMgRGV2aWF0aW9uIENvZGluZyANCi0gTm90ZTogUiBjYWxscyB0aGVtIENvbnRyYXN0IFN1bXMNCi0gTGV0cyBtYWtlIHRoZSBGbGF0IHRoZSByZWZlcmVuY2UgYWdhaW4NCg0KVmFyaWFibGUgICAgfCBDMXwgQzINCi0tLS0tLS0tLS0tLXwgLS18IC0tLQ0KTm9ybWFsICAgICAgfCAwIHwgMQ0KRXhhZ2dlcmF0ZWQgfCAxIHwgMA0KRmxhdCAgICAgICAgfC0xIHwgLTENCg0KLSBGb3IgZGV2aWF0YXRpb24gY29kZSwgUiB3aWxsIHVzZSB0aGUgTEFTVCB2YXJpYWJsZSBhcyByZWZlcmVuY2VzIHNvIHdlIG5lZWQgdG8gcmVjb2RlIGl0IGJ5IGhhbmQgdG8gYmUgZmlyc3QgYXMgdG8gbWF0Y2ggdGhlIG9yZGVyIHdlIHdhbnQgaW4gdGhlIGFib3ZlIHRhYmxlDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQpFbW90aW9uLkRhdGEkU3R5bGUuQy5TIDwtIGZhY3RvcihFbW90aW9uLkRhdGEkU3R5bGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1jKDEsMiwwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJOb3JtYWwiLCAiRXhhZ2dlcmF0ZWQiLCAiRmxhdCIpKQ0KY29udHJhc3RzKEVtb3Rpb24uRGF0YSRTdHlsZS5DLlMpID0gY29udHIuc3VtDQphdHRyaWJ1dGVzKEVtb3Rpb24uRGF0YSRTdHlsZS5DLlMpJGNvbnRyYXN0cw0KYGBgDQoNCi0gTGV0cyBsb29rIGF0IGhvdyB0aGluZ3MgZGlmZmVyIGZyb20gdGhlIG1lYW4gb2YgYWxsIGNvbmRpdGlvbnMgKGdyYW5kIG1lYW4pDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdhc2lzJ30NCk1vZGVsLjEuQ1M8LWxtKEVtb3Rpb24gfiBTdHlsZS5DLlMsIGRhdGEgPSBFbW90aW9uLkRhdGEpDQpzdGFyZ2F6ZXIoTW9kZWwuMS5DUyx0eXBlPSJodG1sIiwNCiAgICAgICAgICBpbnRlcmNlcHQuYm90dG9tID0gRkFMU0UsDQogICAgICAgICAgc2luZ2xlLnJvdz1UUlVFLCANCiAgICAgICAgICBub3Rlcy5hcHBlbmQgPSBGQUxTRSwNCiAgICAgICAgICBvbWl0LnN0YXQ9Yygic2VyIiksDQogICAgICAgICAgc3Rhci5jdXRvZmZzID0gYygwLjA1LCAwLjAxLCAwLjAwMSksDQogICAgICAgICAgaGVhZGVyPUZBTFNFKQ0KYGBgDQoNCi0gSW50ZXJjZXB0ID0gTWVhbiBvZiBtZWFucyAoZ3JhbmQgbWVhbikNCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30NCmxpYnJhcnkoa25pdHIpDQojTWVhbiBvZiBlYWNoIGNvbmRpdGlvbg0KTWVhbi5JbnRlcmFjdGlvbjwtYWdncmVnYXRlKEVtb3Rpb25+U3R5bGVGLGRhdGEgPSBFbW90aW9uLkRhdGEsIEZVTj1tZWFuKQ0Ka2FibGUoTWVhbi5JbnRlcmFjdGlvbikNCmBgYA0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0V9DQojZ3JhbmQgbWVhbiA9IA0Kc3VtKGFnZ3JlZ2F0ZShFbW90aW9uflN0eWxlRixkYXRhID0gRW1vdGlvbi5EYXRhLCBGVU49bWVhbilbMl0pLzMNCmBgYA0KDQojIyMjIENvZWZmaWNpZW50cw0KLSBTdHlsZS5DLlMxID0gY29lZmZpY2llbnQgb24gTm9ybWFsIGFzIGl0IGRpZmZlcnMgZnJvbSBncmFuZCBtZWFuDQotIFN0eWxlLkMuUzIgPSBjb2VmZmljaWVudCBvbiBFeGFnZ2VyYXRlZCBhcyBpdCBkaWZmZXJzIGZyb20gZ3JhbmQgbWVhbg0KLSBUbyBnZXQgdGhlIG1lYW5zIGZvciBlYWNoIGNvbmRpdGlvbjogDQoNCiMjIyMgTWVhbnMgcGVyIENvbmRpdGlvbg0KLSAqRmxhdCA9IENhbm5vdCBnZXQgZnJvbSB0aGlzIG1vZGVsKg0KLSAqTm9ybWFsID0gSW50ZXJjZXB0ICsgU3R5bGUuQy5TMSoNCi0gKkV4YWdnZXJhdGVkID0gSW50ZXJjZXB0ICsgU3R5bGUuQy5TMioNCg0KIyMjIyBQdmFsdWVzDQotIFRoZSBwdmFsdWUgb24gdGhlIGludGVyY2VwdCBhc2tzIGlmIHRoZSAqZ3JhbmQgbWVhbiogZGlmZmVyZW50IGZyb20gemVybw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBzbG9wZXMgYXNrcyBpZiBlYWNoIG9mIHRoZSBvdGhlciBsZXZlbHMgaXMgZGlmZmVyZW50IGZyb20gKmdyYW5kIG1lYW4qDQotIE5vdGU6IFdlIGhhdmUgbG9zdCBhbnkgYWJpbGl0eSB0byBhc2sgYWJvdXQgRmxhdCBjb25kaXRpb24sIHRvIGdldCBpdCBiYWNrIHdlIHdvdWxkIGhhdmUgdG8gcm90YXRlIHRoZSBiYXNlbGluZSBhbmQgZG8gaXQgYWdhaW4NCg0KIyMjICBTaW1wbGUgQ29kaW5nDQotIFRoZXkgbXVzdCBzdW0gdG8gemVybyBhbmQgdGhlIGFicyh2YWx1ZXMpIG11c3Qgc3VtIHRvIDENCi0gTGlrZSBpbiBBTk9WQSB5b3UgY2FuIGRlc2lnbiB0aGVzZSB0byBhc2sgc3BlY2lmaWMgcXVlc3Rpb25zIGJ5IG1lcmdpbmcgY29uZGl0aW9ucyAob3Igbm90KQ0KLSBXZSB3aWxsIHVzZSB0aGUgY29udHIudHJlYXRtZW50IHRyZWF0bWVudCAod2hpY2ggUiBpcyB1c2luZyB0byBhdXRvbWF0aWNhbGx5IGNvbnZlcnQgeW91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYWxyZWFkeSkNCi0gKipKdXN0IGxpa2UgZHVtbXkgY29kaW5nIGJ1dCB3ZSBjaGFuZ2UgdGhlIG1lYW5pbmcgb2YgdGhlIGludGVyY2VwdCoqDQotIFJlZmVyZW5jZSBsZXZlbCBpcyBmaXJzdCBhZ2Fpbg0KDQpWYXJpYWJsZSAgICB8IEMxICAgfCBDMg0KLS0tLS0tLS0tLS0tfCAtLS0tIHwgLS0tDQpGbGF0ICAgICAgICB8IC0xLzMgfCAtMS8zDQpOb3JtYWwgICAgICB8ICAyLzMgfCAtMS8zDQpFeGFnZ2VyYXRlZCB8IC0xLzMgfCAgMi8zDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRX0NCkVtb3Rpb24uRGF0YSRTdHlsZS5TaW1wbGUgPC0gZmFjdG9yKEVtb3Rpb24uRGF0YSRTdHlsZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWMoMCwxLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkZsYXQiLCAiTm9ybWFsIiwgIkV4YWdnZXJhdGVkIikpDQoNCkxldmVsczwtMw0KU2ltcGxlLjE8LWNvbnRyLnRyZWF0bWVudChMZXZlbHMpDQojRHVtbXkgY29kZQ0KU2ltcGxlLjENCiNNYWtlIHlvdXIgY3VzdG9tIGNvZGVzDQpteS5jb2Rpbmc8LW1hdHJpeChyZXAoMS9MZXZlbHMsIExldmVscyooTGV2ZWxzLTEpKSwgbmNvbD1MZXZlbHMtMSkNCm15LnNpbXBsZTwtU2ltcGxlLjEtbXkuY29kaW5nDQpteS5zaW1wbGUNCmNvbnRyYXN0cyhFbW90aW9uLkRhdGEkU3R5bGUuU2ltcGxlKTwtbXkuc2ltcGxlDQoNCmBgYA0KDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdhc2lzJ30NCk1vZGVsLjEuU2ltcGxlPC1sbShFbW90aW9uIH4gU3R5bGUuU2ltcGxlLCBkYXRhID0gRW1vdGlvbi5EYXRhKQ0Kc3RhcmdhemVyKE1vZGVsLjEuU2ltcGxlLHR5cGU9Imh0bWwiLA0KICAgICAgICAgIGludGVyY2VwdC5ib3R0b20gPSBGQUxTRSwNCiAgICAgICAgICBzaW5nbGUucm93PVRSVUUsIA0KICAgICAgICAgIG5vdGVzLmFwcGVuZCA9IEZBTFNFLA0KICAgICAgICAgIG9taXQuc3RhdD1jKCJzZXIiKSwNCiAgICAgICAgICBzdGFyLmN1dG9mZnMgPSBjKDAuMDUsIDAuMDEsIDAuMDAxKSwNCiAgICAgICAgICBoZWFkZXI9RkFMU0UpDQpgYGANCg0KIyMjIyBDb2VmZmljaWVudHMNCi0gVGhpcyBtZXJnZXMgdGhlIGR1bW15IGFuZCBkZXZpZW5jZSBjb2RpbmdzIHRodXM6IA0KLSBJbnRlcmNlcHQgPSBNZWFuIG9mIG1lYW5zIChncmFuZCBtZWFuKQ0KLSBTdHlsZUZOb3JtYWwgPSAgc2xvcGUgb2YgTm9ybWFsIGZyb20gYmFzZWxpbmUgKEZsYXQpDQotIFN0eWxlRkV4YWdnZXJhdGVkID0gc2xvcGUgb2YgRXhhZ2dlcmF0ZWQgZnJvbSBiYXNlbGluZSAoRmxhdCkNCg0KIyMjIyBNZWFucyBwZXIgQ29uZGl0aW9uDQotKllvdSBjYW5ub3QgZ2V0IG1lYW5zIG9mIGVhY2ggY29uZGl0aW9uIGZyb20gdGhpcyBtb2RlbCoNCg0KIyMjIyBQdmFsdWVzDQotIFRoZSBwdmFsdWUgb24gdGhlIGludGVyY2VwdCBhc2tzIGlmIHRoZSAqZ3JhbmQgbWVhbiogZGlmZmVyZW50IGZyb20gemVybw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBzbG9wZXMgYXNrcyBpZiBlYWNoIG9mIHRoZSBvdGhlciBsZXZlbHMgaXMgZGlmZmVyZW50IGZyb20gYmFzZWxpbmUgKCpGbGF0KikNCg0KDQojIyMgT3RoZXIgdHlwZXMgb2YgY29udHJhc3QgY29kaW5nDQotIEhlbG1lcnQ6IGNvbXBhcmVzIGVhY2ggbGV2ZWwgdG8gdGhlIG1lYW4gb2YgdGhlIHN1YnNlcXVlbnQgbGV2ZWxzIFtjYW4gYmUgcmV2ZXJzZWRdDQotIEZvcndhcmQgRGlmZmVyZW5jZSBjb2Rpbmc6IG9uZSBsZXZlbCBpcyBjb21wYXJlZCB0byB0aGUgbmV4dCAoYWRqYWNlbnQpIGxldmVsLiAobGV2ZWwgMSB2cyAyLiBsZXZlbCAyIHZzIDMpIFtjYW4gYmUgcmV2ZXJzZWRdDQotIEN1c3RvbTogTWVyZ2UgYW5kIGNvbXBhcmUgbGV2ZWxzIGF0IHdpbGwNCg0KIyMjIyBDZW50ZXIgdmFyaWFibGVzIGFuZCB0ZXN0IHNsb3Blcw0KLSBUaGVyZSBpcyBubyByZWFzb24gd2h5IHlvdSBjYW5ub3QgdHJlYXQgdGhlIHZhcmlhYmxlcyBhcyBjb250aW51b3VzIGlzIHRoZXkgYXJlICpvcmRpbmFsKg0KLSBqdXN0IGNlbnRlciB0aGVtIGFuZCB0cmVhdCBsaWtlIGNvbnRpbnVvdXMgdmFyaWFibGUNCg0KKioqKioqKioqKioqKioqDQoNCiMgTW9kZWxzIHdpdGggSW50ZXJhY3Rpb25zICgyIE5vbWluYWwgdmFyaWFibGVzKQ0KLSBJbnRlcmFjdGlvbnMgY2FuIGJlIHRyaWNreSBhcyB0aGUgaW50ZXJwcmV0YXRpb24gZGVwZW5kcyBvbiBob3cgeW91IGNvZGUgSVZzDQotIEZpcnN0IGxldHMgdHJ5IHNvbWUgY2F0ZWdvcmljYWwgdnMgY2F0ZWdvcmljYWwgaW50ZXJhY3Rpb25zDQotIFdlIHdpbGwgYWRkIGEgdmFyaWFibGUgdG8gb3VyIGV4cGVyaW1lbnQgZnJvbSBhYm92ZSwgd2Ugd2lsbCBhZGQgdGhlIGxvY2F0aW9uIHdoZXJlIHRoZSBhY3RvcnMgd29yayAoTW92aWUgdnMgVGhlYXRyZSkNCi0gRW1vdGlvbiByYXRpbmcgfiBFeHByZXNzaXZlIGludGVudGlvbnMqbG9jYXRpb24gb2YgdGhlIGFjdG9yIA0KLSAkRW1vdGlvbiBSYXRpbmcgPSAtMypGbGF0ICsgMCpOb3JtYWwgKzMqRXhhZ2dlcmF0ZWQgKzAqTW92aWUgLSAxLjUqVGhlYXRyZSAtIDAqRmxhdCpNb3ZpZSArIDAqTm9ybWFsKk1vdmllICswKkV4YWdnZXJhdGVkKk1vdmllIC0gMTAqRmxhdCpUaGVhdHJlICswKk5vcm1hbCpUaGVhdHJlICsxMCpFeGFnZ2VyYXRlZCpUaGVhdHJlICsgNTAgKyBcZXBzaWxvbiQNCg0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KI1NldCB1cCBzaW11bGF0aW9uDQoNCnNldC5zZWVkKDQyKQ0KTiA8LSAyMDANClggPC0gc2FtcGxlKHJlcChjKC0xLDAsMSksTiksTixyZXBsYWNlID0gRkFMU0UpDQpaIDwtIHNhbXBsZShyZXAoYygwLDEpLE4qMy8yKSxOLHJlcGxhY2UgPSBGQUxTRSkNCg0KIyBPdXIgZXF1YXRpb24gdG8gY3JlYXRlIFkNClkgPC0gMypYIC0xLjUqWisxMCpYKlorIDUwICsgcm5vcm0oTiwgc2Q9MTApDQojQnVpbHQgb3VyIGRhdGEgZnJhbWUNCkVtb3Rpb24uRGF0YS4yPC1kYXRhLmZyYW1lKEVtb3Rpb249WSxTdHlsZT1YLExvY2F0aW9uPVopDQpFbW90aW9uLkRhdGEuMiRTdHlsZTwtRW1vdGlvbi5EYXRhLjIkU3R5bGUrMQ0KYGBgDQoNCg0KIyMgRHVtbXkgY29kaW5nDQotIExldHMgZHVtbXkgY29kZSBhbGwgb2YgdGhlbTogY29udmVydCB0aGVtIHRvIGEgbGFiZWwgaW4gdGhlIG90aGVyIHdlIHdhbnQNCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCiMgQ29udmVydCBhbGwgb3VyIGZhY3RvcnMNCkVtb3Rpb24uRGF0YS4yJFN0eWxlRiA8LSBmYWN0b3IoRW1vdGlvbi5EYXRhLjIkU3R5bGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1jKDAsMSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJGbGF0IiwgIk5vcm1hbCIsICJFeGFnZ2VyYXRlZCIpKQ0KDQpFbW90aW9uLkRhdGEuMiRMb2NhdGlvbkYgPC0gZmFjdG9yKEVtb3Rpb24uRGF0YS4yJExvY2F0aW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9YygwLDEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk1vdmllIFNldCIsICJUaGVhdHJlIikpDQoNCmBgYA0KDQotTGV0cyBsb29rIGF0IHRoZSBjb2xsYXBzZWQgbWVhbnMgYW5kIHRoZSBtZWFucyBwZXIgY2VsbA0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nYXNpcyd9DQpNZWFuLlN0eWxlPC1hZ2dyZWdhdGUoRW1vdGlvbn5TdHlsZUYsZGF0YSA9IEVtb3Rpb24uRGF0YS4yLCBGVU49bWVhbikNCmthYmxlKE1lYW4uU3R5bGUpDQpNZWFuLkxvY2F0aW9uPC1hZ2dyZWdhdGUoRW1vdGlvbn5Mb2NhdGlvbkYsZGF0YSA9IEVtb3Rpb24uRGF0YS4yLCBGVU49bWVhbikNCmthYmxlKE1lYW4uTG9jYXRpb24pDQpNZWFuLkludGVyYWN0aW9uPC1hZ2dyZWdhdGUoRW1vdGlvbn5TdHlsZUYqTG9jYXRpb25GLGRhdGEgPSBFbW90aW9uLkRhdGEuMiwgRlVOPW1lYW4pDQprYWJsZShNZWFuLkludGVyYWN0aW9uKQ0KYGBgDQoNCi0gTGV0IGV4YW1pbmUgb3VyIHJlZ3Jlc3Npb24sIGJ1dCB3ZSBuZWVkIHRvIGV4YW1pbmUgYSBtYWluIGVmZmVjdHMgYW5kIGludGVyYWN0aW9uIG1vZGVsDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdhc2lzJ30NCk1vZGVsLkkxLkR1bW15PC1sbShFbW90aW9uIH4gU3R5bGVGK0xvY2F0aW9uRiwgZGF0YSA9IEVtb3Rpb24uRGF0YS4yKQ0KTW9kZWwuSTIuRHVtbXk8LWxtKEVtb3Rpb24gfiBTdHlsZUYqTG9jYXRpb25GLCBkYXRhID0gRW1vdGlvbi5EYXRhLjIpDQoNCnN0YXJnYXplcihNb2RlbC5JMS5EdW1teSxNb2RlbC5JMi5EdW1teSx0eXBlPSJodG1sIiwNCiAgICAgICAgICBjb2x1bW4ubGFiZWxzID0gYygiTWFpbiBFZmZlY3RzIiwgIkludGVyYWN0aW9uIiksDQogICAgICAgICAgaW50ZXJjZXB0LmJvdHRvbSA9IEZBTFNFLA0KICAgICAgICAgIHNpbmdsZS5yb3c9VFJVRSwgDQogICAgICAgICAgbm90ZXMuYXBwZW5kID0gRkFMU0UsDQogICAgICAgICAgb21pdC5zdGF0PWMoInNlciIpLA0KICAgICAgICAgIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KDQotIFlvdSB3aWxsIG5vdGljZSBsYXJnZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBtYWluIGVmZmVjdHMgYW5kIGludGVyYWN0aW9uIG1vZGVsDQotIFRoaXMgaXMgYmVjYXVzZSB0aGUgbWVhbmluZyBjb2VmZmljaWVudHMgaW4gdGhlIGludGVyYWN0aW9uIGRpZmZlciBmcm9tIHRoZSBtYWluIGVmZmVjdHMgbW9kZWwNCi0gVGhlIG1haW4gZWZmZWN0cyB3ZXJlIGV4cGxhaW5lZCBhYm92ZSwgYnV0IHRoZXkgY2hhbmdlIG1lYW5pbmcgYWxpdHRsZSBiZWNhdXNlIHRoZXJlIGlzIHNlY29uZCB2YXJpYWJsZQ0KDQojIyMgTWFpbiBFZmZlY3RzDQoNCiMjIyMgQ29lZmZpY2llbnRzDQotIFRoZXNlIGRvIG5vdCBjb25uZWN0IGJhY2sgdG8gdGhlIGluZGl2aWR1YWwgY2VsbHMgYXMgeW91IGFyZSBhc3N1bWluZyB0aGUgdHdvIGZhY3RvcnMgaGF2ZSBpbmRlcGVuZGVudCBlZmZlY3RzDQotIFRodXMgdGhlc2UgYXJlIGh5cHRob3RpY2FsIHZhbHVlcyAobm90IGNvbm5lY3RlZCB0byB0aGUgaW5kaXZpZHVhbCBjZWxscykNCi0gSW50ZXJjZXB0ID0gRXN0aW1hdGUgb2YgdGhlIG1lYW4sIGFzc3VtaW5nIHRoZSB0d28gZmFjdG9ycyBoYXZlIGluZGVwZW5kZW50IGVmZmVjdHMgYXQgdGhlaXIgMCBwb2ludHMgW2Jhc2VsaW5lXQ0KLSBTdHlsZUZOb3JtYWwgPSBOb3JtYWwgLSBGbGF0IChhc3N1bWluZyB0aGUgdHdvIGZhY3RvcnMgYXJlIGluZGVwZW5kZW50KQ0KLSBTdHlsZUZFeGFnZ2VyYXRlZCA9IEV4YWdnZXJhdGVkIC0gRmxhdCAoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCi0gTG9jYXRpb25GVGhlYXRyZSA9IFRoZWF0cmUgLSBNb3ZpZShhc3N1bWluZyB0aGUgdHdvIGZhY3RvcnMgYXJlIGluZGVwZW5kZW50KQ0KDQojIyMjIE1lYW5zIHBlciBDb25kaXRpb24gDQotIFlvdSBjYW5ub3QgZ2V0IHRoZW0NCg0KIyMjIyBQdmFsdWVzDQotIFRoZSBwdmFsdWUgb24gdGhlIGludGVyY2VwdCBhc2tzIGlmIHRoZSBiYXNlbGluZSBpcyBkaWZmZXJlbnQgZnJvbSB6ZXJvDQotIFRoZSBwdmFsdWUgb24gdGhlIGRpZmZlcmVuY2VzIGFza3MgaWYgdGhleSBhcmUgZnJvbSBkaWZmZXJlbnQgZnJvbSBiYXNlbGluZSANCg0KIyMjIEludGVyYWN0aW9ucw0KDQojIyMjIENvZWZmaWNpZW50cw0KLSBUaGVzZSBjZWxscyBjb25uZWN0IGJhY2sgdG8gZXhwZXJpbWVudGFsIGNlbGxzDQotIEludGVyY2VwdCA9IExvY2F0aW9uKDApIEAgU3R5bGUoMCkgYWthIE1vdmllIEAgRmxhdCBbcmVhbCB2YWx1ZV0NCi0gU3R5bGVGTm9ybWFsID0gRGlmZmVybmNlIG9mIFtMb2NhdGlvbigwKSBAIFN0eWxlKDEpXSAtIFtMb2NhdGlvbigwKSBAIFN0eWxlKDApXQ0KLSBTdHlsZUZFeGFnZ2VyYXRlZCA9IERpZmZlcm5jZSBvZiBbTG9jYXRpb24oMCkgQCBTdHlsZSgyKV0gLSBbTG9jYXRpb24oMCkgQCBTdHlsZSgwKV0NCi0gTG9jYXRpb25GVGhlYXRyZSA9IERpZmZlcm5jZSBvZiBbTG9jYXRpb24oMSkgQCBTdHlsZSgwKV0gLSBbTG9jYXRpb24oMCkgQCBTdHlsZSgwKV0NCi0gU3R5bGVGTm9ybWFsOkxvY2F0aW9uRlRoZWF0cmUgPSBEaWZmZXJuY2Ugb2YgW0xvY2F0aW9uKDEpIEAgU3R5bGUoMSldIC0gW0xvY2F0aW9uKDApIEAgU3R5bGUoMSkgLSBMb2NhdGlvbigwKSBAIFN0eWxlKDApICsgW0xvY2F0aW9uKDEpIEAgU3R5bGUoMCldIC0gW0xvY2F0aW9uKDApIEAgU3R5bGUoMCldDQotIFN0eWxlRkV4YWdnZXJhdGVkOkxvY2F0aW9uRlRoZWF0cmUgPSBEaWZmZXJuY2Ugb2YgW0xvY2F0aW9uKDEpIEAgU3R5bGUoMildIC0gW0xvY2F0aW9uKDApIEAgU3R5bGUoMikgLSBMb2NhdGlvbigwKSBAIFN0eWxlKDApICsgW0xvY2F0aW9uKDIpIEAgU3R5bGUoMCldIC0gW0xvY2F0aW9uKDApIEAgU3R5bGUoMCldDQoNCg0KIyMjIyBNZWFucyBwZXIgQ29uZGl0aW9uDQotIFlvdSBjYW4gZmluZCBhbGwgbWVhbnMgZm9yIGFsbCBjZWxscyEgDQotICpGbGF0IEAgTW92aWUgPSBJbnRlcmNlcHQqDQotICpOb3JtYWwgQCBNb3ZpZSA9IEludGVyY2VwdCArIFN0eWxlRk5vcm1hbCogDQotICpFeGFnZ2VyYXRlZCBAIE1vdmllID0gSW50ZXJjZXB0ICsgU3R5bGVGRXhhZ2dlcmF0ZWQqIA0KLSAqRmxhdCBAIFRoZWF0cmUgPSBJbnRlcmNlcHQgKyBMb2NhdGlvbkZUaGVhdHJlKg0KLSAqTm9ybWFsIEAgVGhlYXRyZSA9IEludGVyY2VwdCArIExvY2F0aW9uRlRoZWF0cmUrU3R5bGVGTm9ybWFsK1N0eWxlRk5vcm1hbDpMb2NhdGlvbkZUaGVhdHJlKiANCi0gKkV4YWdnZXJhdGVkIEAgVGhlYXRyZSA9ICBJbnRlcmNlcHQgKyBMb2NhdGlvbkZUaGVhdHJlICsgU3R5bGVGRXhhZ2dlcmF0ZWQgKyBTdHlsZUZFeGFnZ2VyYXRlZDpMb2NhdGlvbkZUaGVhdHJlICogDQoNCiMjIyMgUHZhbHVlcw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBpbnRlcmNlcHQgYXNrcyBpZiB0aGUgYmFzZWxpbmUgaXMgZGlmZmVyZW50IGZyb20gemVybw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBkaWZmZXJlbmNlcyBhc2tzIGlmIHRoZXkgYXJlIGZyb20gZGlmZmVyZW50IGZyb20gYmFzZWxpbmUgDQotIEJ1dCB0aGVzZSBhcmUgbm93IGFyZSBub3cgc2ltcGxlIGVmZmVjdHMgDQoNCg0KIyMjIE1haW4gZWZmZWN0IG1vZGVsIHZzIEludGVyYWN0aW9uIG1vZGVsDQotIFNpbmNlIHRoZSByZXN1bHRzIGFyZSBjbGVhcmx5IG5vdCBhZGRpdGl2ZSwgdGhlIG1haW4gZWZmZWN0IG1vZGVsIGlzIHVzZWZ1bCBvbmx5IGluIHdoaWNoIHRvIHVuZGVyc3RhbmQgaG93IHRoZSB0ZXJtcyBoYXZlIGNoYW5nZWQNCi0gR2l2ZXMgc29tZSBpbnNpZ2h0IGludG8gdGhlIGludGVyYWN0aW9uDQoNCiMjIyBHcmFwaCBNb2RlbA0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeShlZmZlY3RzKQ0KTWFpbi4xPC1lZmZlY3QoIkxvY2F0aW9uRiIsIE1vZGVsLkkyLkR1bW15KQ0KcGxvdChNYWluLjEsIG11bHRpbGluZSA9IFRSVUUpDQpNYWluLjI8LWVmZmVjdCgiU3R5bGVGIiwgTW9kZWwuSTIuRHVtbXkpDQpwbG90KE1haW4uMiwgbXVsdGlsaW5lID0gVFJVRSkNCkludGVyLjE8LWVmZmVjdCgiU3R5bGVGKkxvY2F0aW9uRiIsIE1vZGVsLkkyLkR1bW15KQ0KcGxvdChJbnRlci4xLCBtdWx0aWxpbmUgPSBUUlVFKQ0KYGBgDQoNCiMjIyBDb25uZWN0aW9uIHRvIGJldHdlZW4tc3ViamVjdCBBTk9WQQ0KLSBSZWdyZXNzaW9uIHdpdGggb25seSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgY2FuIGJlIGNvbnZlcnRlZCBpbnRvIGFuIEFOT1ZBIHZlcnkgZWFzaWx5IA0KLSBUaHVzIGl0IGNhbiBiZSB0cmVhdGVkIGp1c3QgbGlrZSBBTk9WQQ0KLSBidXQgdGhlIHJlZ3Jlc3Npb24gbWFrZXMgdGhlIEFOT1ZBIHByb2Nlc3MgbW9vdCBhcyB5b3UgY2FuIG5vdyB0aGUgcmVncmVzc2lvbiBjYW4gYmUgY29kZWQgaW4gc3VjaCBhIHdheSB0aGF0IHlvdSBjYW4gdGVzdCBmb2xsb3cgdXAgdGVzdHMgaW4gYSB3YXkgeW91IHdhbnQgdG8gdGVzdCB0aGVtIGFsbCANCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCkFub3ZhKE1vZGVsLkkyLkR1bW15LCB0eXBlPSJJSUkiKQ0KYGBgDQoNCi0gTm90ZSwgd2UgaGF2ZSB0byBjYWxsIGZvciBhIFR5cGUgSUlJIHN1bSBvZiBzcXVhcmVzIHRvIG1hdGNoIFNQU1Mgb3V0cHV0IGFzIFIgd291bGQgZGVmYXVsdCB0byBUeXBlIEkNCg0KDQojIyBDb250cmFzdCBDb2RpbmcNCg0KIyMjIERldmlhdGlvbiBDb2RpbmcNCi0gTGV0cyBjb2RlIGVhY2ggdmFyaWFibGUgYXMgd2UgZGlkIGFib3ZlDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQpFbW90aW9uLkRhdGEuMiRTdHlsZS5DLlMgPC0gZmFjdG9yKEVtb3Rpb24uRGF0YS4yJFN0eWxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9YygxLDIsMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiTm9ybWFsIiwgIkV4YWdnZXJhdGVkIiwgIkZsYXQiKSkNCkVtb3Rpb24uRGF0YS4yJExvY2F0aW9uLkMuUyA8LSBmYWN0b3IoRW1vdGlvbi5EYXRhLjIkTG9jYXRpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1jKDEsMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiVGhlYXRyZSIsICJNb3ZpZSBTZXQiKSkNCg0KY29udHJhc3RzKEVtb3Rpb24uRGF0YS4yJFN0eWxlLkMuUykgPSBjb250ci5zdW0NCmNvbnRyYXN0cyhFbW90aW9uLkRhdGEuMiRMb2NhdGlvbi5DLlMpID0gY29udHIuc3VtDQphdHRyaWJ1dGVzKEVtb3Rpb24uRGF0YS4yJFN0eWxlLkMuUykkY29udHJhc3RzDQphdHRyaWJ1dGVzKEVtb3Rpb24uRGF0YS4yJExvY2F0aW9uLkMuUykkY29udHJhc3RzDQpgYGANCg0KLSBMZXRzIGxvb2sgYXQgaG93IHRoaW5ncyBkaWZmZXIgZnJvbSB0aGUgbWVhbiBvZiBhbGwgY29uZGl0aW9ucyAoZ3JhbmQgbWVhbikNCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J2FzaXMnfQ0KTW9kZWwuSTEuQy5TPC1sbShFbW90aW9uIH4gU3R5bGUuQy5TK0xvY2F0aW9uLkMuUywgZGF0YSA9IEVtb3Rpb24uRGF0YS4yKQ0KTW9kZWwuSTIuQy5TPC1sbShFbW90aW9uIH4gU3R5bGUuQy5TKkxvY2F0aW9uLkMuUywgZGF0YSA9IEVtb3Rpb24uRGF0YS4yKQ0KDQpzdGFyZ2F6ZXIoTW9kZWwuSTEuQy5TLE1vZGVsLkkyLkMuUyx0eXBlPSJodG1sIiwNCiAgICAgICAgICBjb2x1bW4ubGFiZWxzID0gYygiTWFpbiBFZmZlY3RzIiwgIkludGVyYWN0aW9uIiksDQogICAgICAgICAgaW50ZXJjZXB0LmJvdHRvbSA9IEZBTFNFLA0KICAgICAgICAgIHNpbmdsZS5yb3c9VFJVRSwgDQogICAgICAgICAgbm90ZXMuYXBwZW5kID0gRkFMU0UsDQogICAgICAgICAgb21pdC5zdGF0PWMoInNlciIpLA0KICAgICAgICAgIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KDQotIEFnYWluIHdlIGFyZSB0ZXN0aW5nIGJldHdlZW4gdGhlIGdyYW5kIG1lYW4gYW5kIHRoZSBpbmRpdmlkdWFsIHRlcm1zDQoNCiMjIyMgTWFpbiBFZmZlY3RzDQoNCiMjIyMjIENvZWZmaWNpZW50cw0KLSBUaGVzZSBkbyBub3QgY29ubmVjdCBiYWNrIHRvIHRoZSBpbmRpdmlkdWFsIGNlbGxzIGFzIHlvdSBhcmUgYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGhhdmUgaW5kZXBlbmRlbnQgZWZmZWN0cw0KLSBUaHVzIHRoZXNlIGFyZSBoeXB0aG90aWNhbCAqR3JhbmQgbWVhbiogdmFsdWVzIA0KLSBJbnRlcmNlcHQgPSAqR3JhbmQgTWVhbiosIGJ1dCBhc3N1bWluZyB0aGUgdHdvIGZhY3RvcnMgaGF2ZSBpbmRlcGVuZGVudCBlZmZlY3RzDQotIFN0eWxlLkMuUzEgID0gTm9ybWFsIChhdmVyYWdlZCBvdmVyIGxvY2F0aW9uKSAtICpHcmFuZCBNZWFuKiAoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCi0gU3R5bGUuQy5TMiA9IEV4YWdnZXJhdGVkIChhdmVyYWdlZCBvdmVyIGxvY2F0aW9uKSAtICpHcmFuZCBNZWFuKiAoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCi0gTG9jYXRpb24uQy5TMSA9IFRoZWF0cmUgKGF2ZXJhZ2VkIG92ZXIgU3R5bGUpIC0gICpHcmFuZCBNZWFuKiAoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCg0KIyMjIyMgTWVhbnMgcGVyIENvbmRpdGlvbg0KLSAqQ2Fubm90IGdldCBmcm9tIHRoaXMgbW9kZWwqDQoNCiMjIyMjIFB2YWx1ZXMNCi0gVGhlIHB2YWx1ZSBvbiB0aGUgaW50ZXJjZXB0IGFza3MgaWYgdGhlIGJhc2VsaW5lICgqR3JhbmQgTWVhbiopIGlzIGRpZmZlcmVudCBmcm9tIHplcm8NCi0gVGhlIHB2YWx1ZSBvbiB0aGUgc2xvcGVzIGFza3MgaWYgZWFjaCBvZiB0aGUgb3RoZXIgbGV2ZWxzIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBiYXNlbGluZSAoKkdyYW5kIE1lYW4qKQ0KLSBOb3RlIHdlIG1pc3NpbmcgdGVzdHMgb24gRmxhdCBhbmQgTW92aWUgY2VsbCwgd2Ugd291bGQgbmVlZCB0byByb3RhdGUgdGhlIG1hdHJpeCBhbmQgcnVuIGFnYWluDQoNCiMjIyMgSW50ZXJhY3Rpb25zDQojIyMjIyBDb2VmZmljaWVudHMNCi0gSW50ZXJjZXB0ID0gICpHcmFuZCBNZWFuKiAoYWxsIDYgY2VsbHMgbWVhbiBhdmVyYWdlZCkNCi0gU3R5bGUuQy5TMSA9IE5vcm1hbCAoYXZlcmFnZWQgb3ZlciBsb2NhdGlvbikgZnJvbSAqR3JhbmQgTWVhbioNCi0gU3R5bGUuQy5TMiA9IEV4YWdnZXJhdGVkIChhdmVyYWdlZCBvdmVyIGxvY2F0aW9uKSBmcm9tICpHcmFuZCBNZWFuKg0KLSBMb2NhdGlvbi5DLlMxID0gVGhlYXRyZSAoYXZlcmFnZWQgb3ZlciBTdHlsZSkgZnJvbSAqR3JhbmQgTWVhbioNCi0gU3R5bGUuQy5TMTpMb2NhdGlvbi5DLlMxID0gZGlmZmVyZW5jZSBvZiBOb3JtYWwgQCBUaGVhdHJlIGZyb20gKkdyYW5kIE1lYW4qDQotIFN0eWxlLkMuUzI6TG9jYXRpb24uQy5TMSA9IGRpZmZlcmVuY2Ugb2YgRXhhZ2dlcmF0ZWQgQCBUaGVhdHJlIGZyb20gKkdyYW5kIE1lYW4qDQogDQojIyMjIyBNZWFucyBwZXIgQ29uZGl0aW9uDQotICpDYW5ub3QgZ2V0IGZyb20gdGhpcyBtb2RlbCoNCg0KIyMjIyMgUHZhbHVlcw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBpbnRlcmNlcHQgYXNrcyBpZiB0aGUgYmFzZWxpbmUgKCpHcmFuZCBNZWFuKikgaXMgZGlmZmVyZW50IGZyb20gemVybw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBkaWZmZXJlbmNlcyBhc2tzIGlmIGVhY2ggb2YgdGhlIG90aGVyIGxldmVscyBpcyBmcm9tIHRoZSAoKkdyYW5kIE1lYW4qKQ0KLSBOb3RlIHdlIG1pc3NpbmcgdGVzdHMgb24gRmxhdCBhbmQgbW92aWUgY2VsbCwgd2Ugd291bGQgbmVlZCB0byByb3RhdGUgdGhlIG1hdHJpeCBhbmQgcnVuIGFnYWluDQoNCg0KIyBNb2RlbHMgd2l0aCBJbnRlcmFjdGlvbnMgKDEgTm9taW5hbCBhbmQgMSBDb250aW51b3VzIFZhcmlhYmxlKQ0KLSBXZSB3aWxsIGNoYW5nZSBvdXIgZXhwZXJpbWVudCBmcm9tIGFib3ZlLCB3ZSB3aWxsIGFkZCBhIGxpa2VydCBzY2FsZSB3aGljaCB0aGUgYWN0b3IgcmF0ZXMgaG93ICJnb29kIiB0aGV5IHRoaW5rIHRoZSBwZXJmb3JtYW5jZSB3YXMgWzAgdGVycmlibGUgdG8gNyBleGNlbGxlbnRdDQotIEVtb3Rpb24gcmF0aW5nIH4gUXVhbGl0eSBSYXRpbmcqbG9jYXRpb24gb2YgdGhlIGFjdG9yIA0KLSAkRW1vdGlvbiBSYXRpbmcgPSAtMypxdWEgKyAwKk5vcm1hbCArMypFeGFnZ2VyYXRlZCArMCpNb3ZpZSAtIDEuNSpUaGVhdHJlIC0gMCpGbGF0Kk1vdmllICsgMCpOb3JtYWwqTW92aWUgKzAqRXhhZ2dlcmF0ZWQqTW92aWUgLSAxMCpGbGF0KlRoZWF0cmUgKzAqTm9ybWFsKlRoZWF0cmUgKzEwKkV4YWdnZXJhdGVkKlRoZWF0cmUgKyA1MCArIFxlcHNpbG9uJA0KDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQojU2V0IHVwIHNpbXVsYXRpb24NCnNldC5zZWVkKDQyKQ0KTiA8LSAyMDANClggPC0gcnVuaWYoTiwtMywzKQ0KWiA8LSBzYW1wbGUocmVwKGMoMCwxKSxOKSxOLHJlcGxhY2UgPSBGQUxTRSkNCg0KIyBPdXIgZXF1YXRpb24gdG8gY3JlYXRlIFkNClkgPC0gNCpYICsyKlorOCpYKlorIDUwICsgcm5vcm0oTiwgc2Q9MTApDQojQnVpbHQgb3VyIGRhdGEgZnJhbWUNCkVtb3Rpb24uRGF0YS4zPC1kYXRhLmZyYW1lKEVtb3Rpb249WSxRdWFsaXR5PVgsTG9jYXRpb249WikNCg0KDQpgYGANCg0KDQoNCiMjIENlbnRlciB0aGUgY29udGludW91cyB2YXJpYWJsZQ0KLSBCZXN0IHRvIGNlbnRlciBhcyBpdHMgd2lsbCBoZWxwIHVzIGludGVycHJldCANCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQojIENvbnZlcnQgYWxsIG91ciBmYWN0b3JzDQpFbW90aW9uLkRhdGEuMyRRdWFsaXR5LkMgPC0gc2NhbGUoRW1vdGlvbi5EYXRhLjMkUXVhbGl0eSwgc2NhbGUgPSBGQUxTRSlbLF0NCg0KYGBgDQoNCg0KIyMgRHVtbXkgY29kaW5nIG9mIG91ciBub21pbmFsIHZhcmlhYmxlDQotIER1bW15IGNvZGluZyB3aWxsIGFsbG93IHVzIHRvIGludGVycHJldCB0aGUgaW50ZXJhY3Rpb24gYXMgc2ltcGxlIHNsb3BlcyBhbmFseXNpcw0KLSBMZXRzIGR1bW15IGNvZGUgTG9jYXRpb24NCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCiMgQ29udmVydCBhbGwgb3VyIGZhY3RvcnMNCkVtb3Rpb24uRGF0YS4zJExvY2F0aW9uRiA8LSBmYWN0b3IoRW1vdGlvbi5EYXRhLjMkTG9jYXRpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWMoMCwxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk1vdmllIFNldCIsIlRoZWF0cmUiKSkNCg0KYGBgDQoNCiMjIyBJbnRlcnByZXQgUmVncmVzc2lvbg0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nYXNpcyd9DQpNb2RlbC5FMy4xPC1sbShFbW90aW9uIH4gUXVhbGl0eS5DK0xvY2F0aW9uRiwgZGF0YSA9IEVtb3Rpb24uRGF0YS4zKQ0KTW9kZWwuRTMuMjwtbG0oRW1vdGlvbiB+IFF1YWxpdHkuQypMb2NhdGlvbkYsIGRhdGEgPSBFbW90aW9uLkRhdGEuMykNCg0Kc3RhcmdhemVyKE1vZGVsLkUzLjEsTW9kZWwuRTMuMix0eXBlPSJodG1sIiwNCiAgICAgICAgICBjb2x1bW4ubGFiZWxzID0gYygiTWFpbiBFZmZlY3RzIiwgIkludGVyYWN0aW9uIiksDQogICAgICAgICAgaW50ZXJjZXB0LmJvdHRvbSA9IEZBTFNFLA0KICAgICAgICAgIHNpbmdsZS5yb3c9VFJVRSwgDQogICAgICAgICAgbm90ZXMuYXBwZW5kID0gRkFMU0UsDQogICAgICAgICAgb21pdC5zdGF0PWMoInNlciIpLA0KICAgICAgICAgIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KDQojIyMgUGxvdHRpbmcgSW50ZXJhY3Rpb24NCi0gT2Z0ZW4gdGltZXMgeW91IHdpbGwgbmVlZCB0byB1c2UgdGhlIGVmZmVjdHMgcGFja2FnZSBhbmQgcGxvdCBieSBoYW5kDQotIFRoZSByb2NoY2hhbGsgcGFja2FnZSB3aWxsIHdvcmsgZm9yIHNpbXBsZSBtb2RlbHMgbGlrZSB0aGlzIG9uZQ0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHJvY2tjaGFsaykNCnBsb3RTbG9wZXMoTW9kZWwuRTMuMiwgcGxvdHggPSAiUXVhbGl0eS5DIiwgbW9keCA9ICJMb2NhdGlvbkYiKQ0KYGBgDQoNCiMjIyBNYWluIEVmZmVjdHMNCg0KIyMjIyBDb2VmZmljaWVudHMgJiBQdmFsdWVzDQotIEludGVyY2VwdCA9IE1lYW4gb2YgUXVhbGl0eSBAIE1vdmllcyBbcCA9IElzIHRoZSBpbnRlcmNlcHQgZGlmZmVyZW50IGZyb20gMF0NCi0gUXVhbGl0eS5DICA9IFF1YWxpdHkuQyBzbG9wZSBbcCA9IElzIHNsb3BlIGRpZmZlcmVudCBmcm9tIDBdDQotIExvY2F0aW9uRlRoZWF0cmUgPSBUaHJlYXRyZSBkaWZmZXJlbmNlIGZyb20gaW50ZXJjZXB0IFtwID0gSXMgbWVhbiBvZiBUaGVhdHJlIGRpZmZlcmVudCBmcm9tIG1vdmllcyBAIG1lYW4gb2YgcXVhbGl0eV0NCg0KIyMjIEludGVyYWN0aW9ucw0KIyMjIyBDb2VmZmljaWVudHMgJiBQdmFsdWVzDQotIEludGVyY2VwdCA9IE1lYW4gb2YgUXVhbGl0eSBAIE1vdmllcyBbcCA9IElzIHRoZSBpbnRlcmNlcHQgZGlmZmVyZW50IGZyb20gMF0NCi0gUXVhbGl0eS5DICA9IFF1YWxpdHkuQyBzbG9wZSBAIE1vdmllcyBbcCA9IElzIHRoZSBzaW1wbGUgc2xvcGUgYXQgbW92aWVzIGRpZmZlcmVudCBmcm9tIDBdDQotIExvY2F0aW9uRlRoZWF0cmUgPSBUaHJlYXRyZSBkaWZmZXJlbmNlIGZyb20gaW50ZXJjZXB0IFtwID0gSXMgbWVhbiBvZiBUaGVhdHJlIGRpZmZlcmVudCBmcm9tIG1vdmllcyBAIG1lYW4gb2YgcXVhbGl0eV0NCi0gUXVhbGl0eS5DOkxvY2F0aW9uRlRoZWF0cmU9IFF1YWxpdHkuQyBzbG9wZSBAIFRoZWF0cmUgW3AgPSBJcyB0aGUgc2ltcGxlIHNsb3BlIGF0IFRoZWF0cmUgZGlmZmVyZW50IGZyb20gMF0NCiANCg0KIyMgRGV2aWF0aW9uIGNvZGluZyBvZiBvdXIgbm9taW1hbCB2YXJpYWJsZQ0KLSBXZSB3aWxsIHN0aWxsIGNlbnRlciBxdWFsaXR5DQotIFRoaXMgY3JlYXRlcyBhIG1vcmUgQU5PVkEgbGlrZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgaW50ZXJhY3Rpb24gDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KRW1vdGlvbi5EYXRhLjMkTG9jYXRpb25EIDwtIGZhY3RvcihFbW90aW9uLkRhdGEuMyRMb2NhdGlvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9YygxLDApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiVGhlYXRyZSIsIk1vdmllIFNldCIpKQ0KY29udHJhc3RzKEVtb3Rpb24uRGF0YS4zJExvY2F0aW9uRCkgPSBjb250ci5zdW0NCmF0dHJpYnV0ZXMoRW1vdGlvbi5EYXRhLjMkTG9jYXRpb25EKSRjb250cmFzdHMNCmBgYA0KDQojIyMgSW50ZXJwcmV0IFJlZ3Jlc3Npb24NCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J2FzaXMnfQ0KTW9kZWwuRTMuRDE8LWxtKEVtb3Rpb24gfiBRdWFsaXR5LkMrTG9jYXRpb25ELCBkYXRhID0gRW1vdGlvbi5EYXRhLjMpDQpNb2RlbC5FMy5EMjwtbG0oRW1vdGlvbiB+IFF1YWxpdHkuQypMb2NhdGlvbkQsIGRhdGEgPSBFbW90aW9uLkRhdGEuMykNCg0Kc3RhcmdhemVyKE1vZGVsLkUzLkQxLE1vZGVsLkUzLkQyLHR5cGU9Imh0bWwiLA0KICAgICAgICAgIGNvbHVtbi5sYWJlbHMgPSBjKCJNYWluIEVmZmVjdHMiLCAiSW50ZXJhY3Rpb24iKSwNCiAgICAgICAgICBpbnRlcmNlcHQuYm90dG9tID0gRkFMU0UsDQogICAgICAgICAgc2luZ2xlLnJvdz1UUlVFLCANCiAgICAgICAgICBub3Rlcy5hcHBlbmQgPSBGQUxTRSwNCiAgICAgICAgICBvbWl0LnN0YXQ9Yygic2VyIiksDQogICAgICAgICAgc3Rhci5jdXRvZmZzID0gYygwLjA1LCAwLjAxLCAwLjAwMSksDQogICAgICAgICAgaGVhZGVyPUZBTFNFKQ0KYGBgDQoNCg0KIyMjIE1haW4gRWZmZWN0cw0KDQojIyMjIENvZWZmaWNpZW50cyAmIFB2YWx1ZXMNCi0gSW50ZXJjZXB0ID0gTWVhbiBvZiBRdWFsaXR5IEAgbWVhbiBvZiBNb3ZpZSAmIFRoZWF0cmUgKGltYWdpbmFyeSB0aGluZykgW3AgPSBJcyB0aGUgaW50ZXJjZXB0IGRpZmZlcmVudCBmcm9tIDBdDQotIFF1YWxpdHkuQyAgPSBRdWFsaXR5LkMgc2xvcGUgW3AgPSBJcyBzbG9wZSBkaWZmZXJlbnQgZnJvbSAwXQ0KLSBMb2NhdGlvbkZUaGVhdHJlID0gVGhyZWF0cmUgZGlmZmVyZW5jZSBmcm9tIDAgKG5vdCAtIDEpIHRodXMgaXMgMS8yIHRoZSBzbG9wZSBvZiB0aGUgZHVtbXkgY29kZSBbcCA9IElzIG1lYW4gb2YgVGhlYXRyZSBkaWZmZXJlbnQgZnJvbSBtb3ZpZXMgQCBtZWFuIG9mIHF1YWxpdHldDQoNCiMjIyBJbnRlcmFjdGlvbnMNCiMjIyMgQ29lZmZpY2llbnRzICYgUHZhbHVlcyANCi0gSW50ZXJjZXB0ID0gTWVhbiBvZiBRdWFsaXR5IEAgbWVhbiBvZiBNb3ZpZSAmIFRoZWF0cmUgKGltYWdpbmFyeSB0aGluZykgW3AgPSBJcyB0aGUgaW50ZXJjZXB0IGRpZmZlcmVudCBmcm9tIDBdDQotIFF1YWxpdHkuQyAgPSBRdWFsaXR5LkMgc2xvcGUgQCBtZWFuIG9mIE1vdmllICYgVGhlYXRyZSAoaW1hZ2luYXJ5IHRoaW5nKSBbcCA9IElzIHRoZSBNYWluIGVmZmVjdCBvZiBxdWFsaXR5IEAgbWVhbiBvZiBNb3ZpZSAmIFRoZWF0cmVdDQotIExvY2F0aW9uRlRoZWF0cmUgPSBUaHJlYXRyZSBkaWZmZXJlbmNlIGZyb20gaW50ZXJjZXB0IFtwID0gSXMgdGhlIE1haW4gZWZmZWN0IG9mIExvY2F0aW9uIEAgbWVhbiBvZiBxdWFsaXR5XQ0KLSBRdWFsaXR5LkM6TG9jYXRpb25GVGhlYXRyZT0gUXVhbGl0eS5DIHNsb3BlIGRpZmZlcmVuY2UgYmV0d2VlbiBNb3ZpZSBhbmQgdGhlYXRyZSBbcCA9IElzIHRoZSBpbnRlcmFjdGlvbl0NCi0gTm90ZSBhbGwgY29lZmZpY2llbnRzIGFyZSAxLzIgb2YgdGhlIHNpemUgdGhleSBzaG91bGQgYmUhIA0KIA0KIA0KIA0KIyMgU2ltcGxlIGNvZGluZyBvZiBvdXIgbm9taW1hbCB2YXJpYWJsZQ0KLSBXZSB3aWxsIHN0aWxsIGNlbnRlciBxdWFsaXR5DQotIFRoaXMgY3JlYXRlcyBhIG1vcmUgQU5PVkEgbGlrZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgaW50ZXJhY3Rpb24sDQotIE1vc3QgaW1wb3J0YW50bHkgaXQgZG9lcyBub3Qgc2NyZXcgdXAgb3VyIGNvZWZmaWNpZW50cyBhcyB0aGV5IG1hdGNoIHRoZSBkdW1teSBjb2RlIHZhbHVlcyAod2hpY2ggbWFrZSB0aGUgbW9zdCBzZW5zZSkNCi0gVGhpcyB0aW1lIEkgd2lsbCBoYW5kIGNvZGUgdGhlIGl0IGludG8gYSBmYWN0b3IgKGVhc3kgd2l0aCBvbmx5IDIgbGV2ZWxzKQ0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCkVtb3Rpb24uRGF0YS4zJExvY2F0aW9uUzwtYXMubnVtZXJpYyhFbW90aW9uLkRhdGEuMyRMb2NhdGlvbiktLjUNCg0KYGBgDQoNCiMjIyBJbnRlcnByZXQgUmVncmVzc2lvbg0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nYXNpcyd9DQpNb2RlbC5FMy5TMTwtbG0oRW1vdGlvbiB+IFF1YWxpdHkuQytMb2NhdGlvblMsIGRhdGEgPSBFbW90aW9uLkRhdGEuMykNCk1vZGVsLkUzLlMyPC1sbShFbW90aW9uIH4gUXVhbGl0eS5DKkxvY2F0aW9uUywgZGF0YSA9IEVtb3Rpb24uRGF0YS4zKQ0KDQpzdGFyZ2F6ZXIoTW9kZWwuRTMuUzEsTW9kZWwuRTMuUzIsdHlwZT0iaHRtbCIsDQogICAgICAgICAgY29sdW1uLmxhYmVscyA9IGMoIk1haW4gRWZmZWN0cyIsICJJbnRlcmFjdGlvbiIpLA0KICAgICAgICAgIGludGVyY2VwdC5ib3R0b20gPSBGQUxTRSwNCiAgICAgICAgICBzaW5nbGUucm93PVRSVUUsIA0KICAgICAgICAgIG5vdGVzLmFwcGVuZCA9IEZBTFNFLA0KICAgICAgICAgIG9taXQuc3RhdD1jKCJzZXIiKSwNCiAgICAgICAgICBzdGFyLmN1dG9mZnMgPSBjKDAuMDUsIDAuMDEsIDAuMDAxKSwNCiAgICAgICAgICBoZWFkZXI9RkFMU0UpDQpgYGANCg0KDQojIyMgTWFpbiBFZmZlY3RzDQoNCiMjIyMgQ29lZmZpY2llbnRzICYgUHZhbHVlcw0KLSBJbnRlcmNlcHQgPSBNZWFuIG9mIFF1YWxpdHkgQCBtZWFuIG9mIE1vdmllICYgVGhlYXRyZSAoaW1hZ2luYXJ5IHRoaW5nKSBbcCA9IElzIHRoZSBpbnRlcmNlcHQgZGlmZmVyZW50IGZyb20gMF0NCi0gUXVhbGl0eS5DICA9IFF1YWxpdHkuQyBzbG9wZSBbcCA9IElzIHNsb3BlIGRpZmZlcmVudCBmcm9tIDBdDQotIExvY2F0aW9uRlRoZWF0cmUgPSBUaHJlYXRyZSBkaWZmZXJlbmNlIGZyb20gMCBbcCA9IElzIG1lYW4gb2YgVGhlYXRyZSBkaWZmZXJlbnQgZnJvbSBtb3ZpZXMgQCBtZWFuIG9mIHF1YWxpdHldDQoNCiMjIyBJbnRlcmFjdGlvbnMNCg0KIyMjIyBDb2VmZmljaWVudHMgJiBQdmFsdWVzIA0KLSBJbnRlcmNlcHQgPSBNZWFuIG9mIFF1YWxpdHkgQCBtZWFuIG9mIE1vdmllICYgVGhlYXRyZSAoaW1hZ2luYXJ5IHRoaW5nKSBbcCA9IElzIHRoZSBpbnRlcmNlcHQgZGlmZmVyZW50IGZyb20gMF0NCi0gUXVhbGl0eS5DICA9IFF1YWxpdHkuQyBzbG9wZSBAIG1lYW4gb2YgTW92aWUgJiBUaGVhdHJlIChpbWFnaW5hcnkgdGhpbmcpIFtwID0gSXMgdGhlIE1haW4gZWZmZWN0IG9mIHF1YWxpdHkgQCBtZWFuIG9mIE1vdmllICYgVGhlYXRyZV0NCi0gTG9jYXRpb25TID0gVGhyZWF0cmUgZGlmZmVyZW5jZSBmcm9tIGludGVyY2VwdCBbcCA9IElzIHRoZSBNYWluIGVmZmVjdCBvZiBMb2NhdGlvbiBAIG1lYW4gb2YgcXVhbGl0eV0NCi0gUXVhbGl0eS5DOkxvY2F0aW9uUz0gUXVhbGl0eS5DIHNsb3BlIGRpZmZlcmVuY2UgYmV0d2VlbiBNb3ZpZSBhbmQgdGhlYXRyZSBbcCA9IElzIHRoZWlyIGFuIGludGVyYWN0aW9uXQ0KLSBOb3RlIGFsbCBjb2VmZmljaWVudHMgYXJlIHRoZWlyIHByb3BlciBzaXplIG5vdyAodG8gbWF0Y2ggdHJ1ZSBkaWZmZXJlbmNlcykNCi0gQmVzdCBvcHRpb24gaXMgb2Z0ZW4gZHVtbXkgb3Igc2ltcGxlLCBkZXZpYXRpb24gaGVyZSBpcyB3ZWlyZCANCg0KDQoNCjxzY3JpcHQ+DQogIChmdW5jdGlvbihpLHMsbyxnLHIsYSxtKXtpWydHb29nbGVBbmFseXRpY3NPYmplY3QnXT1yO2lbcl09aVtyXXx8ZnVuY3Rpb24oKXsNCiAgKGlbcl0ucT1pW3JdLnF8fFtdKS5wdXNoKGFyZ3VtZW50cyl9LGlbcl0ubD0xKm5ldyBEYXRlKCk7YT1zLmNyZWF0ZUVsZW1lbnQobyksDQogIG09cy5nZXRFbGVtZW50c0J5VGFnTmFtZShvKVswXTthLmFzeW5jPTE7YS5zcmM9ZzttLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGEsbSkNCiAgfSkod2luZG93LGRvY3VtZW50LCdzY3JpcHQnLCdodHRwczovL3d3dy5nb29nbGUtYW5hbHl0aWNzLmNvbS9hbmFseXRpY3MuanMnLCdnYScpOw0KDQogIGdhKCdjcmVhdGUnLCAnVUEtOTA0MTUxNjAtMScsICdhdXRvJyk7DQogIGdhKCdzZW5kJywgJ3BhZ2V2aWV3Jyk7DQoNCjwvc2NyaXB0Pg==