Nominal Variables

  • Things like gender or color (what we would have as factors in ANOVA)
    • 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)
  • Decisions have to made on how to treat these variables in a regression
  • 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 change as you change your coding (think the concept of contrasts in ANOVA from last semester)

Models with no Interactions (1 Nominal variable)

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
Happy 0
Sad 1
  • Here are Three levels, but now you have to make 2 new variables
  • Happy is the reference group
Variable C1 C2
Happy 0 0
Sad 0 1
Mad 1 0
  • Sad is the reference group
Variable C1 C2
Happy 0 1
Sad 0 0
Mad 1 0
  • Here are Four levels, but now you have to make 3 new variables
  • Happy is the reference group
Variable C1 C2 C3
Happy 0 0 0
Sad 0 0 1
Mad 0 1 0
Grumpy 1 0 0

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\)

Creating Dummy Variables

  • In SPSS you would have to create dummy variables using Recode, but it R its a little easier
  • In R, we have to convert our variable into a factor
    • R will default to alphabetical order
      • Sometimes easier to convert all your words into numbers (start with 0)
    • Next, convert your variable into a factor (as.factor)
      • Note: R calls dummy coding as contr.treatment
  • First, let’s 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(ggplot2)
#Set up simulation
set.seed(42)
N <- 200
X<- sample(rep(c(0,1,2),N),N,replace = FALSE)
Y <- 5*X + 50 + rnorm(N, sd=10)
Emotion.Data<-data.frame(Emotion=Y,Style=X)
qplot(Style,Emotion, data = Emotion.Data, colour = I("red"))+theme_bw()+geom_smooth(method='lm')

  • If the data is already coded as 0, 1, 2 all we have to do is:
Emotion.Data$StyleF <- factor(Emotion.Data$Style,
                              level=c(0,1,2),
                              labels=c("Flat", "Normal", "Exaggerated"))
  • We can re-plot it as violin/box plot to see our distributions (its a double-sided density plot [smoothed histogram])
ggplot(data = Emotion.Data,aes(StyleF,Emotion))+
  xlab("")+
  geom_violin(aes(fill=StyleF), trim = FALSE,adjust=1.5)+
  geom_boxplot(width=.1)+
  theme_bw()+
  theme(legend.position = "none")

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 StyleFNormal and StyleFExaggerated.
Model.1<-lm(Emotion ~ StyleF, data = Emotion.Data)
Dependent variable:
Emotion
Constant 50.798*** (1.273)
StyleFNormal 2.182 (1.828)
StyleFExaggerated 7.961*** (1.780)
Observations 200
R2 0.098
Adjusted R2 0.089
F Statistic 10.705*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001

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)

Means per Condition

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

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)

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
  • We can fix that manually change what the baseline line level is with the relevel command in car package
Emotion.Data$StyleN<- relevel(Emotion.Data$StyleF, ref = "Normal")
Model.1.N<-lm(Emotion ~ StyleN, data = Emotion.Data)
  • Notice in the table the labels and values have changed
Dependent variable:
Emotion
Constant 52.979*** (1.312)
StyleNFlat -2.182 (1.828)
StyleNExaggerated 5.779** (1.809)
Observations 200
R2 0.098
Adjusted R2 0.089
F Statistic 10.705*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001

Contrast Coding

Deviation Coding

  • Note: R calls them Contrast Sums
  • Let’s make the Flat the reference again
Variable C1 C2
Normal 1 0
Exaggerated 0 1
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"))
  • Then we will create our new contrast contr.sum with three levels (3)
contr.sum(3)
##   [,1] [,2]
## 1    1    0
## 2    0    1
## 3   -1   -1
  • We will add that code to our lm function, by adding the parameters list(Style.C.S=contr.sum(3))
Model.1.CS<-lm(Emotion ~ Style.C.S, data = Emotion.Data,
               contrasts=list(Style.C.S=contr.sum(3)))
  • Let’s look at how things differ from the mean of all conditions (grand mean)
Dependent variable:
Emotion
Constant 54.178*** (0.737)
Style.C.S1 -1.199 (1.057)
Style.C.S2 4.580*** (1.030)
Observations 200
R2 0.098
Adjusted R2 0.089
F Statistic 10.705*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001
  • Intercept = Mean of means (grand mean)
  • Mean of each condition calculated below
Mean.Interaction<-aggregate(Emotion~StyleF,data = Emotion.Data, FUN=mean)
StyleF Emotion
Flat 50.79758
Normal 52.97930
Exaggerated 58.75829
  • Grand mean calculated below
sum(aggregate(Emotion~StyleF,data = Emotion.Data, FUN=mean)[2])/3
## [1] 54.17839

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:

Means per Condition

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

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 the ability to ask about Flat condition, to get it back we would have to rotate the baseline and do it again

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
  • The 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
#Make your 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
  • We will add that code to our lm function, by adding the parameters list(Style.Simple=my.simple)
Model.1.Simple<-lm(Emotion ~ Style.Simple, data = Emotion.Data, 
                   contrasts=list(Style.Simple=my.simple))
Dependent variable:
Emotion
Constant 54.178*** (0.737)
Style.Simple2 2.182 (1.828)
Style.Simple3 7.961*** (1.780)
Observations 200
R2 0.098
Adjusted R2 0.089
F Statistic 10.705*** (df = 2; 197)
Note: p<0.05; p<0.01; p<0.001

Coefficients

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

Means per Condition

  • You cannot get means of each condition from this model

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)

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

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 a continuous variable

Models with Interactions (2 Nominal variables)

  • Interactions can be tricky as the interpretation depends on how you code IVs
    • First, let’s 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 = -3*Flat + 0*Normal +3*Exag +0*Movie - 1.5*Theatre - 0*Flat*Movie + 0*Normal*Movie +0*Exag*Movie - 10*Flat*Theatre +0*Normal*Theatre +10*Exag*Theatre + 50 + \epsilon\)

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

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"))

-Let’s 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 43.13791
Normal 47.56490
Exaggerated 58.39412
Mean.Location<-aggregate(Emotion~LocationF,data = Emotion.Data.2, FUN=mean)
kable(Mean.Location)
LocationF Emotion
Movie Set 49.75709
Theatre 49.99666
Mean.Interaction<-aggregate(Emotion~StyleF*LocationF,data = Emotion.Data.2, FUN=mean)
kable(Mean.Interaction)
StyleF LocationF Emotion
Flat Movie Set 49.69693
Normal Movie Set 45.80954
Exaggerated Movie Set 53.42534
Flat Theatre 34.00214
Normal Theatre 49.26539
Exaggerated Theatre 63.08686
  • 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)
Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 43.412*** (1.534) 49.697*** (1.592)
StyleFNormal 4.486* (1.987) -3.887 (2.392)
StyleFExaggerated 15.319*** (1.936) 3.728 (2.333)
LocationFTheatre -0.655 (1.604) -15.695*** (2.462)
StyleFNormal:LocationFTheatre 19.151*** (3.513)
StyleFExaggerated:LocationFTheatre 25.356*** (3.423)
Observations 200 200
R2 0.253 0.427
Adjusted R2 0.242 0.412
F Statistic 22.170*** (df = 3; 196) 28.924*** (df = 5; 194)
Note: p<0.05; p<0.01; p<0.001
  • You will notice a large difference 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 a little because there is second variable

Main Effects

Coefficients

  • These do not connect back to the individual cells as you are assuming the two factors have independent effects

    • Thus these are hypothetical 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)

  • We can see the main effect models results

library(effects)
allEffects(Model.I1.Dummy)
##  model: Emotion ~ StyleF + LocationF
## 
##  StyleF effect
## StyleF
##        Flat      Normal Exaggerated 
##    43.09724    47.58320    58.41658 
## 
##  LocationF effect
## LocationF
## Movie Set   Theatre 
##  50.18653  49.53144

Means per Condition

  • You cannot get them

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

Interactions

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)]

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

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

Main effect model vs. Interaction model

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

Graph Model

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

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
library(car)
Anova(Model.I2.Dummy, type="III")
## Anova Table (Type III tests)
## 
## Response: Emotion
##                  Sum Sq  Df  F value    Pr(>F)    
## (Intercept)       96322   1 974.6213 < 2.2e-16 ***
## StyleF              941   2   4.7593  0.009598 ** 
## LocationF          4015   1  40.6229 1.316e-09 ***
## StyleF:LocationF   5814   2  29.4130 6.967e-12 ***
## Residuals         19173 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

Contrast Coding

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"))

Model.I1.C.S<-lm(Emotion ~ Style.C.S+Location.C.S, data = Emotion.Data.2, 
                 contrasts=list(Style.C.S=contr.sum(3),Location.C.S=contr.sum(2)))
Model.I2.C.S<-lm(Emotion ~ Style.C.S*Location.C.S, data = Emotion.Data.2,
                contrasts=list(Style.C.S=contr.sum(3),Location.C.S=contr.sum(2)))
  • Let’s look at how things differ from the mean of all conditions (grand mean)
Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 49.686*** (0.800) 49.214*** (0.707)
Style.C.S1 -2.116 (1.147) -1.677 (1.011)
Style.C.S2 8.718*** (1.117) 9.042*** (0.985)
Location.C.S1 -0.328 (0.802) -0.430 (0.707)
Style.C.S1:Location.C.S1 2.157* (1.011)
Style.C.S2:Location.C.S1 5.260*** (0.985)
Observations 200 200
R2 0.253 0.427
Adjusted R2 0.242 0.412
F Statistic 22.170*** (df = 3; 196) 28.924*** (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

Main Effects

Coefficients
  • These do not connect back to the individual cells as you are assuming the two factors have independent effects
  • Thus these are hypothetical 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)
Means per Condition
  • Cannot get from this model
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 are missing tests on Flat and Movie cell, we would need to rotate the matrix and run again

Interactions

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
Means per Condition
  • Cannot get from this model
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 are missing tests on Flat and movie cell, we would need to rotate the matrix and run again

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 [-3 terrible to 3 excellent]
  • Emotion rating ~ Quality Rating X location of the actor (i.e., Movie Set, Theatre)
#Set up simulation
set.seed(42)
N <- 200
X <- runif(N,-3,3)
Z <- sample(rep(c(0,1),N/2),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)

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)[,]

Dummy coding of our nominal variable

  • Make Location into a factor
# Convert all our factors
Emotion.Data.3$LocationF <- factor(Emotion.Data.3$Location,
                                   level=c(0,1),
                                   labels=c("Movie Set","Theatre"))
  • First to understand what the interaction will yield lets us run two regressions where we seperate our factor to see what the slopes would be just for actors at Movie Set vs at the Theatre

Movie Set ONLY vs Theatre Only

  • We will subset the data and test for the Quality slopes
Model.Movie<-lm(Emotion ~ Quality.C, 
                data = subset(Emotion.Data.3,LocationF=="Movie Set"))
Model.Theatre<-lm(Emotion ~ Quality.C, 
                data = subset(Emotion.Data.3,LocationF=="Theatre"))
Dependent variable:
Emotion
Movie Set ONLY Theatre Only
(1) (2)
Constant 50.468*** (0.976) 52.426*** (1.051)
Quality.C 4.551*** (0.593) 12.083*** (0.569)
Observations 100 100
R2 0.375 0.821
Adjusted R2 0.369 0.819
F Statistic (df = 1; 98) 58.842*** 450.430***
Note: p<0.05; p<0.01; p<0.001
  • Ignore the intercepts and pay attention to the slopes:
    • Quality @ the Movie Set ONLY is \(b\)= 4.551
      • The pvalues tells you if the slope of quality is differnet from a slope of 0
    • Quality @ the Theatre Only ONLY is \(b\)= 12.083
      • The pvalues tells you if the slope of quality is differnet from a slope of 0
  • What we really want to test is if there is a difference in slopes between quality at Movies sets VS Theatre

Testing the Interaction

  • We will test a main effects model, Quality+Location and compare it to an interaction model Quality*Location
Model.E3.1<-lm(Emotion ~ Quality.C+LocationF, data = Emotion.Data.3)
Model.E3.2<-lm(Emotion ~ Quality.C*LocationF, data = Emotion.Data.3)
  • Does model interaction improve the model fit? (Just like we did with hierarchical testing)
Model.Fit.E3<-anova(Model.E3.1,Model.E3.2)
library(knitr)
kable(Model.Fit.E3)
Res.Df RSS Df Sum of Sq F Pr(>F)
197 28691.61 NA NA NA NA
196 20141.73 1 8549.886 83.19931 0
  • Yes! The interaction is significant improvement
  • Let’s go examine the individual regression paramaters:

Interpret Regression

Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 50.513*** (1.207) 50.468*** (1.014)
Quality.C 8.749*** (0.488) 4.551*** (0.616)
LocationFTheatre 1.948 (1.707) 1.958 (1.434)
Quality.C:LocationFTheatre 7.532*** (0.826)
Observations 200 200
R2 0.621 0.734
Adjusted R2 0.617 0.730
F Statistic 161.308*** (df = 2; 197) 180.143*** (df = 3; 196)
Note: p<0.05; p<0.01; p<0.001

Main Effects Model

  • Intercept = Mean of Quality @ Movies [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope averaged across Movies & * Threatre*
    • This is a Main Effect [p = Is slope different from 0 slope]
      • This would almost be like averaging the slopes from our Movie Set ONLY and Theatre Only Models
        • \(b\) = (4.551 + 12.083)/2 = 8.317
  • LocationFTheatre = Threatre difference from intercept [p = Is mean of Theatre different from Movies @ mean of quality]
    • This is a Simple Effect

Interaction Model

  • Intercept = Mean of Quality @ Movies [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope @ Movies
    • This is a Simple Slope [p = Is slope different from 0 slope]
      • To prove it we can see it matches the slopes from our Movie Set ONLY Model, \(b\)= 4.551
  • LocationFTheatre = Threatre difference from intercept [p = Is mean of Theatre different from movies @ mean of quality]
    • This is a Simple Effect
  • Quality.C:LocationFTheatre= slope difference between Movie and Theatre [p = Is the slope of quality @ Theatre different from slope at ]
    • This is an Interaction
      • To prove it we can see it matches the slopes of Theatre Only - Movie Set ONLY Model
        • \(b\)= (12.083 - 4.551) = 7.532
  • If you wanted to know the simple slope of Theatre Only you would have to relevel Location and make Theatre = 0 (i.e., the reference)
Emotion.Data.3$LocationT<- relevel(Emotion.Data.3$LocationF, ref = "Theatre")
Model.E3.2.ReLevel<-lm(Emotion ~ Quality.C*LocationT, data = Emotion.Data.3)
Dependent variable:
Emotion
Theatre is Ref
Constant 52.426*** (1.014)
Quality.C 12.083*** (0.549)
LocationTMovie Set -1.958 (1.434)
Quality.C:LocationTMovie Set -7.532*** (0.826)
Observations 200
R2 0.734
Adjusted R2 0.730
F Statistic 180.143*** (df = 3; 196)
Note: p<0.05; p<0.01; p<0.001
  • You will notice the interaction flipped direction and now the Quality.C coefficient \(b\) = 12.083 = the Theatre Only model \(b\) = 12.083

Plotting Interaction

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

Deviation coding of our nominal 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"))
Model.E3.D1<-lm(Emotion ~ Quality.C+LocationD, data = Emotion.Data.3,
                 contrasts=list(LocationD=contr.sum(2)))
Model.E3.D2<-lm(Emotion ~ Quality.C*LocationD, data = Emotion.Data.3,
                 contrasts=list(LocationD=contr.sum(2)))

Interpret Regression

Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 51.487*** (0.853) 51.447*** (0.717)
Quality.C 8.749*** (0.488) 8.317*** (0.413)
LocationD1 0.974 (0.853) 0.979 (0.717)
Quality.C:LocationD1 3.766*** (0.413)
Observations 200 200
R2 0.621 0.734
Adjusted R2 0.617 0.730
F Statistic 161.308*** (df = 2; 197) 180.143*** (df = 3; 196)
Note: p<0.05; p<0.01; p<0.001

Main Effects

Coefficients & Pvalues

  • Intercept = Mean of Quality @ mean of Movie & Theatre (imaginary) [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]

Interactions

Coefficients & Pvalues

  • Intercept = Mean of Quality @ mean of Movie & Theatre (imaginary) [p = Is the intercept different from 0]
  • Quality.C = Quality.C slope @ mean of Movie & Theatre (imaginary) [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!

Simple coding of our nominal 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 it into a factor (easy with only 2 levels)
Emotion.Data.3$LocationS<-as.numeric(Emotion.Data.3$Location)-.5
Model.E3.S1<-lm(Emotion ~ Quality.C+LocationS, data = Emotion.Data.3)
Model.E3.S2<-lm(Emotion ~ Quality.C*LocationS, data = Emotion.Data.3)

Interpret Regression

Dependent variable:
Emotion
Main Effects Interaction
(1) (2)
Constant 51.487*** (0.853) 51.447*** (0.717)
Quality.C 8.749*** (0.488) 8.317*** (0.413)
LocationS 1.948 (1.707) 1.958 (1.434)
Quality.C:LocationS 7.532*** (0.826)
Observations 200 200
R2 0.621 0.734
Adjusted R2 0.617 0.730
F Statistic 161.308*** (df = 2; 197) 180.143*** (df = 3; 196)
Note: p<0.05; p<0.01; p<0.001

Main Effects

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]

Interactions

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
LS0tDQp0aXRsZTogJ0NhdGVnb3JpY2FsIFZhcmlhYmxlcycNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBmb250c2l6ZTogOHB0DQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0aGVtZTogZmxhdGx5DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IG5vDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoY2FjaGU9VFJVRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRkFMU0UpDQprbml0cjo6b3B0c19jaHVuayRzZXQod2FybmluZyA9ICBGQUxTRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGg9NC4yNSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcuaGVpZ2h0PTQuMCkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcuYWxpZ249J2NlbnRlcicpIA0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHJlc3VsdHM9J2hvbGQnKSANCmBgYA0KDQoNCiMgTm9taW5hbCBWYXJpYWJsZXMgDQotIFRoaW5ncyBsaWtlIGdlbmRlciBvciBjb2xvciAod2hhdCB3ZSB3b3VsZCBoYXZlIGFzIGZhY3RvcnMgaW4gQU5PVkEpDQogICAgLSBXZSB3aWxsIGFzc3VtZSAoZm9yIG5vdykgdGhhdCBhIHN1YmplY3QgY2FuIGJlIGEgbWVtYmVyIG9mICpvbmx5IG9uZSogbGV2ZWwgb2YgYSBmYWN0b3IgYSB2YXJpYWJsZSAoaS5lLiwgeW91IGNhbiBibHVlIG9yIHJlZCwgYnV0IG5vdCBib3RoKQ0KLSBEZWNpc2lvbnMgaGF2ZSB0byBtYWRlIG9uIGhvdyB0byB0cmVhdCB0aGVzZSB2YXJpYWJsZXMgaW4gYSByZWdyZXNzaW9uDQotIFRoZXJlIGFyZSB0aHJlZSBiYXNpYyBtZXRob2RzIHdlIHdpbGwgY292ZXIgYW5kIGhvdyB0byBpbnRlcnByZXQgdGhlaXIgZWZmZWN0cyBhbmQgaW50ZXJhY3Rpb25zDQotIEtleSB0byByZW1lbWJlciB5b3UgYXJlIGJhc2ljYWxseSBkb2luZyB0byB0LXRlc3RzLCBzbyB5b3UgYXJlIGFsd2F5cyBqdXN0IGNvbXBhcmluZyB0d28gdGhpbmdzLCBidXQgd2hhdCB0aG9zZSB0d28gdGhpbmdzIGFyZSB3aWxsIGNoYW5nZSBhcyB5b3UgY2hhbmdlIHlvdXIgY29kaW5nICh0aGluayB0aGUgY29uY2VwdCBvZiBjb250cmFzdHMgaW4gQU5PVkEgZnJvbSBsYXN0IHNlbWVzdGVyKQ0KDQoNCiMgTW9kZWxzIHdpdGggbm8gSW50ZXJhY3Rpb25zICgxIE5vbWluYWwgdmFyaWFibGUpDQoNCiMjIER1bW15IENvZGluZw0KLSBUaGUgbW9zdCBjb21tb24gYW5kIGJhc2ljIHR5cGUgdXNlZCAoZGVmYXVsdCBpbiBSIGlmIGl0IHNlbnNlcyBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlKQ0KLSBGb3IgZWFjaCB2YXJpYWJsZSwgeW91IG11c3QgYXNzaWduIGEgcmVmZXJlbmNlIGdyb3VwIChhIGJhc2VsaW5lKSBmb3IgZWFjaCB2YXJpYWJsZQ0KLSBFYWNoIGdyb3VwIGlzIGNvbXBhcmVkIHRvIHRoZSByZWZlcmVuY2UgZ3JvdXANCi0gV2UgYXNrIHRoZSBxdWVzdGlvbiwgKmhvdyBtdWNoIGRvZXMgZWFjaCBncm91cCBkZXZpYXRlIGZyb20gdGhlIHJlZmVyZW5jZSoNCi0gSGVyZSBhcmUgdHdvIGxldmVscyBvZiBvbmUgZmFjdG9yDQoNCg0KVmFyaWFibGUgfCBDMSANCi0tLS0tLS0tLXwgLS0tDQpIYXBweSAgICB8IDANClNhZCAgICAgIHwgMQ0KDQotIEhlcmUgYXJlIFRocmVlIGxldmVscywgYnV0IG5vdyB5b3UgaGF2ZSB0byBtYWtlIDIgbmV3IHZhcmlhYmxlcyANCi0gSGFwcHkgaXMgdGhlIHJlZmVyZW5jZSBncm91cA0KDQpWYXJpYWJsZXwgQzF8IEMyDQotLS0tLS0tLXwgLS18IC0tDQpIYXBweSAgIHwgMCB8IDANClNhZCAgICAgfCAwIHwgMQ0KTWFkICAgICB8IDEgfCAwDQoNCi0gU2FkIGlzIHRoZSByZWZlcmVuY2UgZ3JvdXANCg0KVmFyaWFibGV8IEMxfCBDMg0KLS0tLS0tLS18IC0tfCAtLQ0KSGFwcHkgICB8IDAgfCAxDQpTYWQgICAgIHwgMCB8IDANCk1hZCAgICAgfCAxIHwgMA0KDQotIEhlcmUgYXJlIEZvdXIgbGV2ZWxzLCBidXQgbm93IHlvdSBoYXZlIHRvIG1ha2UgMyBuZXcgdmFyaWFibGVzIA0KLSBIYXBweSBpcyB0aGUgcmVmZXJlbmNlIGdyb3VwDQoNClZhcmlhYmxlICAgICB8IEMxIHwgQzIgfCBDMw0KLS0tLS0tLS0tLS0tLXwgLS0gfCAtLSB8IC0tIA0KSGFwcHkgICAgICAgIHwgMCAgfCAwICB8IDANClNhZCAgICAgICAgICB8IDAgIHwgMCAgfCAxDQpNYWQgICAgICAgICAgfCAwICB8IDEgIHwgMA0KR3J1bXB5ICAgICAgIHwgMSAgfCAwICB8IDANCg0KDQojIyMgUmVncmVzc2lvbiBlcXVhdGlvbg0KLSBUd28gTGV2ZWxzOiAkWSA9IEJfMUMxICsgQl8wJA0KLSBUaHJlZSBMZXZlbHM6ICRZID0gQl8xQzEgK0JfMkMyKyBCXzAkDQotIEZvdXIgTGV2ZWxzOiAkWSA9IEJfMUMxICsgQl8yQzIgKyBCXzJDMyArIEJfMCQNCg0KIyMjIENyZWF0aW5nIER1bW15IFZhcmlhYmxlcw0KLSBJbiBTUFNTIHlvdSB3b3VsZCBoYXZlIHRvIGNyZWF0ZSBkdW1teSB2YXJpYWJsZXMgdXNpbmcgUmVjb2RlLCBidXQgaXQgUiBpdHMgYSBsaXR0bGUgZWFzaWVyDQotIEluIFIsIHdlIGhhdmUgdG8gY29udmVydCBvdXIgdmFyaWFibGUgaW50byBhIGZhY3Rvcg0KICAgIC0gUiB3aWxsIGRlZmF1bHQgdG8gYWxwaGFiZXRpY2FsIG9yZGVyDQogICAgICAgIC0gU29tZXRpbWVzIGVhc2llciB0byBjb252ZXJ0IGFsbCB5b3VyIHdvcmRzIGludG8gbnVtYmVycyAoc3RhcnQgd2l0aCAwKQ0KICAgIC0gTmV4dCwgY29udmVydCB5b3VyIHZhcmlhYmxlIGludG8gYSBmYWN0b3IgKGFzLmZhY3RvcikNCiAgICAgICAgLSBOb3RlOiBSIGNhbGxzIGR1bW15IGNvZGluZyBhcyBjb250ci50cmVhdG1lbnQNCi0gRmlyc3QsIGxldCdzIHNpbXVsYXRlIGEgc2ltcGxlIGZhY3RvciB0byB3b3JrIHdpdGgNCiAgICAtIEVtb3Rpb24gcmF0aW5nIH4gRXhwcmVzc2l2ZSBpbnRlbnRpb25zIG9mIHRoZSBhY3RvciAoMCA9IEZsYXQsIDEgPSBOb3JtYWwsIDIgPSBFeGFnZ2VyYXRlZCApDQogICAgLSBUaHJlZSBMZXZlbHM6ICRFbW90aW9uIFJhdGluZyA9IDAqRmxhdCArIDUqTm9ybWFsICsxMCpFeGFnZ2VyYXRlZCArIDUwICsgXGVwc2lsb24kDQoNCg0KVmFyaWFibGUgICAgfCBDMXwgQzINCi0tLS0tLS0tLS0tLXwgLS18IC0tLQ0KRmxhdCAgICAgICAgfCAwIHwgMA0KTm9ybWFsICAgICAgfCAxIHwgMA0KRXhhZ2dlcmF0ZWQgfCAwIHwgMQ0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KI1NldCB1cCBzaW11bGF0aW9uDQpzZXQuc2VlZCg0MikNCk4gPC0gMjAwDQpYPC0gc2FtcGxlKHJlcChjKDAsMSwyKSxOKSxOLHJlcGxhY2UgPSBGQUxTRSkNClkgPC0gNSpYICsgNTAgKyBybm9ybShOLCBzZD0xMCkNCkVtb3Rpb24uRGF0YTwtZGF0YS5mcmFtZShFbW90aW9uPVksU3R5bGU9WCkNCnFwbG90KFN0eWxlLEVtb3Rpb24sIGRhdGEgPSBFbW90aW9uLkRhdGEsIGNvbG91ciA9IEkoInJlZCIpKSt0aGVtZV9idygpK2dlb21fc21vb3RoKG1ldGhvZD0nbG0nKQ0KYGBgDQoNCi0gSWYgdGhlIGRhdGEgaXMgYWxyZWFkeSBjb2RlZCBhcyAwLCAxLCAyIGFsbCB3ZSBoYXZlIHRvIGRvIGlzOiANCg0KYGBge3J9DQpFbW90aW9uLkRhdGEkU3R5bGVGIDwtIGZhY3RvcihFbW90aW9uLkRhdGEkU3R5bGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1jKDAsMSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJGbGF0IiwgIk5vcm1hbCIsICJFeGFnZ2VyYXRlZCIpKQ0KYGBgDQoNCi0gV2UgY2FuIHJlLXBsb3QgaXQgYXMgdmlvbGluL2JveCBwbG90IHRvIHNlZSBvdXIgZGlzdHJpYnV0aW9ucyAoaXRzIGEgZG91YmxlLXNpZGVkIGRlbnNpdHkgcGxvdCBbc21vb3RoZWQgaGlzdG9ncmFtXSkNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IEVtb3Rpb24uRGF0YSxhZXMoU3R5bGVGLEVtb3Rpb24pKSsNCiAgeGxhYigiIikrDQogIGdlb21fdmlvbGluKGFlcyhmaWxsPVN0eWxlRiksIHRyaW0gPSBGQUxTRSxhZGp1c3Q9MS41KSsNCiAgZ2VvbV9ib3hwbG90KHdpZHRoPS4xKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCg0KIyMjIEludGVycHJldCBSZWdyZXNzaW9uDQotIE9yZGVyIG9mIHRoZSBmYWN0b3JzIG1hdHRlcnMNCi0gUmVtZW1iZXIgeW91IGFyZSBtYWtpbmcgZWFjaCBsZXZlbCBvZiB0aGUgdmFyaWFibGUgYSB0ZXJtIGluIHRoZSBlcXVhdGlvbiBhcyB5b3UgaGF2ZSBtYWRlIGEgbmV3IHZhcmlhYmxlIGZvciBlYWNoIGxldmVsIChleGNlcHQgYmFzZWxpbmUpDQotICpSIG1ha2UgdGhlc2UgZHVtbXkgY29kZWQgYXV0b21hdGljYWxseSBzbyBpdHMgZWFzeSB0byBmb3JnZXQgdGhpcyoNCiAgICAtIGZvciAzIGxldmVscyB3ZSB3aWxsIGhhdmUgMyB0ZXJtczogaW50ZXJjZXB0IGFuZCBTdHlsZUZOb3JtYWwgYW5kIFN0eWxlRkV4YWdnZXJhdGVkLg0KDQpgYGB7cn0NCk1vZGVsLjE8LWxtKEVtb3Rpb24gfiBTdHlsZUYsIGRhdGEgPSBFbW90aW9uLkRhdGEpDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRSxyZXN1bHRzPSdhc2lzJ30NCmxpYnJhcnkoc3RhcmdhemVyKQ0Kc3RhcmdhemVyKE1vZGVsLjEsdHlwZT0iaHRtbCIsDQogICAgICAgICAgaW50ZXJjZXB0LmJvdHRvbSA9IEZBTFNFLCAgc2luZ2xlLnJvdz1UUlVFLCBub3Rlcy5hcHBlbmQgPSBGQUxTRSwNCiAgICAgICAgICBvbWl0LnN0YXQ9Yygic2VyIiksIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KDQojIyMjIENvZWZmaWNpZW50cw0KLSBJbnRlcmNlcHQgPSBJbnRlcmNlcHQgb2YgdGhlIGVxdWF0aW9uIChXaGljaCBpcyB0aGUgbWVhbiBvZiBGbGF0KQ0KLSBTdHlsZUZOb3JtYWwgPSBjb2VmZmljaWVudCAoc2xvcGUgb2YgTm9ybWFsKSBmcm9tIGJhc2VsaW5lIChGbGF0KQ0KLSBTdHlsZUZFeGFnZ2VyYXRlZCA9IGNvZWZmaWNpZW50IChzbG9wZSBvZiBFeGFnZ2VyYXRlZCkgZnJvbSBiYXNlbGluZSAoRmxhdCkNCg0KIyMjIyBNZWFucyBwZXIgQ29uZGl0aW9uDQoNCi0gKkZsYXQgPSBJbnRlcmNlcHQqDQotICpOb3JtYWwgPSBJbnRlcmNlcHQgKyBTdHlsZUZOb3JtYWwqDQotICpFeGFnZ2VyYXRlZCA9IEludGVyY2VwdCArIFN0eWxlRkV4YWdnZXJhdGVkKg0KDQojIyMjIFB2YWx1ZXMNCi0gVGhlIHB2YWx1ZSBvbiB0aGUgaW50ZXJjZXB0IGFza3MgaWYgdGhlIGJhc2VsaW5lICgqRmxhdCopIGNvbmRpdGlvbiBkaWZmZXJlbnQgZnJvbSB6ZXJvDQotIFRoZSBwdmFsdWUgb24gdGhlIHNsb3BlcyBhc2tzIGlmIGVhY2ggb2YgdGhlIG90aGVyIGxldmVscyBpcyBkaWZmZXJlbnQgZnJvbSBiYXNlbGluZSAoKkZsYXQqKQ0KDQoNCiMjIyBSb3RhdGUgdGhlIG1hdHJpeA0KLSBXaGF0IGlmIHdlIHdhbnQgdG8ga25vdyBpZiBOb3JtYWwgaXMgZGlmZmVyZW50IGZyb20gRXhhZ2dlcmF0ZWQ/DQotIFdlIG5lZWQgdG8gcmVsZXZlbCAoYWthIGNoYW5nZSB3aGF0IGlzICoqemVybyoqKQ0KDQpWYXJpYWJsZSAgICB8IEMxfCBDMg0KLS0tLS0tLS0tLS0tfCAtLXwgLS0tDQpGbGF0ICAgICAgICB8IDEgfCAwDQpOb3JtYWwgICAgICB8IDAgfCAwDQpFeGFnZ2VyYXRlZCB8IDAgfCAxDQoNCi0gV2UgY2FuIGZpeCB0aGF0IG1hbnVhbGx5IGNoYW5nZSB3aGF0IHRoZSBiYXNlbGluZSBsaW5lIGxldmVsIGlzIHdpdGggdGhlIGByZWxldmVsYCBjb21tYW5kIGluIGBjYXJgIHBhY2thZ2UNCg0KYGBge3J9DQpFbW90aW9uLkRhdGEkU3R5bGVOPC0gcmVsZXZlbChFbW90aW9uLkRhdGEkU3R5bGVGLCByZWYgPSAiTm9ybWFsIikNCk1vZGVsLjEuTjwtbG0oRW1vdGlvbiB+IFN0eWxlTiwgZGF0YSA9IEVtb3Rpb24uRGF0YSkNCmBgYA0KDQotIE5vdGljZSBpbiB0aGUgdGFibGUgdGhlIGxhYmVscyBhbmQgdmFsdWVzIGhhdmUgY2hhbmdlZA0KDQpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9DQpzdGFyZ2F6ZXIoTW9kZWwuMS5OLHR5cGU9Imh0bWwiLA0KICAgICAgICAgIGludGVyY2VwdC5ib3R0b20gPSBGQUxTRSxzaW5nbGUucm93PVRSVUUsIG5vdGVzLmFwcGVuZCA9IEZBTFNFLCANCiAgICAgICAgICBvbWl0LnN0YXQ9Yygic2VyIiksIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KDQoNCiMjIENvbnRyYXN0IENvZGluZw0KLSBTYW1lIGNvbnRyYXN0cyBhcyBpbiBvdXIgQU5PVkFzIGJ1dCB0aGVyZSBhcmUgdHdvIHZlcnNpb25zICh1bndlaWdodGVkIGFuZCB3ZWlnaHRlZCkgYW5kIGJvdGggbmVlZCB0byBzdW0gdG8gemVybw0KLSBXZSBhc2sgbm93IGEgZGlmZmVyZW50IHF1ZXN0aW9uOiAqSG93IG11Y2ggZG9lcyBlYWNoIGdyb3VwIGRldmlhdGUgZnJvbSB0aGUgbWVhbiBvZiBhbGwgZ3JvdXBzKg0KLSBJIHdpbGwgcmV2aWV3IG9ubHkgdGhlIG1vc3QgY29tbW9uIHNlZSBmb3IgdGhlIG90aGVyczoNCiAgICAtIGh0dHA6Ly9zdGF0cy5pZHJlLnVjbGEuZWR1L3IvbGlicmFyeS9yLWxpYnJhcnktY29udHJhc3QtY29kaW5nLXN5c3RlbXMtZm9yLWNhdGVnb3JpY2FsLXZhcmlhYmxlcy8NCi0gSSB3aWxsIG5vdCBzaG93IHlvdSB0aGUgd2VpZ2h0ZWQgdmVyc2lvbiBhcyBub3Qgb2Z0ZW4gdXNlZA0KDQojIyMgRGV2aWF0aW9uIENvZGluZyANCi0gTm90ZTogUiBjYWxscyB0aGVtIENvbnRyYXN0IFN1bXMNCi0gTGV0J3MgbWFrZSB0aGUgRmxhdCB0aGUgcmVmZXJlbmNlIGFnYWluDQoNClZhcmlhYmxlICAgIHwgQzF8IEMyDQotLS0tLS0tLS0tLS18IC0tfCAtLS0NCk5vcm1hbCAgICAgIHwgMSB8IDANCkV4YWdnZXJhdGVkIHwgMCB8IDENCkZsYXQgICAgICAgIHwtMSB8IC0xDQoNCi0gRm9yIGRldmlhdGF0aW9uIGNvZGUsIFIgd2lsbCB1c2UgdGhlICoqTEFTVCoqIHZhcmlhYmxlIGFzIHJlZmVyZW5jZXMgc28gd2UgbmVlZCB0byByZWNvZGUgaXQgYnkgaGFuZCB0byBiZSBmaXJzdCBhcyB0byBtYXRjaCB0aGUgb3JkZXIgd2Ugd2FudCBpbiB0aGUgYWJvdmUgdGFibGUNCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCkVtb3Rpb24uRGF0YSRTdHlsZS5DLlMgPC0gZmFjdG9yKEVtb3Rpb24uRGF0YSRTdHlsZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWMoMSwyLDApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk5vcm1hbCIsICJFeGFnZ2VyYXRlZCIsICJGbGF0IikpDQpgYGANCg0KLSBUaGVuIHdlIHdpbGwgY3JlYXRlIG91ciBuZXcgY29udHJhc3QgYGNvbnRyLnN1bWAgd2l0aCB0aHJlZSBsZXZlbHMgYCgzKWAgIA0KDQpgYGB7cn0NCmNvbnRyLnN1bSgzKQ0KYGBgDQoNCi0gV2Ugd2lsbCBhZGQgdGhhdCBjb2RlIHRvIG91ciBgbG1gIGZ1bmN0aW9uLCBieSBhZGRpbmcgdGhlIHBhcmFtZXRlcnMgYGxpc3QoU3R5bGUuQy5TPWNvbnRyLnN1bSgzKSlgICANCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCk1vZGVsLjEuQ1M8LWxtKEVtb3Rpb24gfiBTdHlsZS5DLlMsIGRhdGEgPSBFbW90aW9uLkRhdGEsDQogICAgICAgICAgICAgICBjb250cmFzdHM9bGlzdChTdHlsZS5DLlM9Y29udHIuc3VtKDMpKSkNCmBgYA0KDQotIExldCdzIGxvb2sgYXQgaG93IHRoaW5ncyBkaWZmZXIgZnJvbSB0aGUgbWVhbiBvZiBhbGwgY29uZGl0aW9ucyAoZ3JhbmQgbWVhbikNCg0KYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0Kc3RhcmdhemVyKE1vZGVsLjEuQ1MsdHlwZT0iaHRtbCIsDQogICAgICAgICAgaW50ZXJjZXB0LmJvdHRvbSA9IEZBTFNFLA0KICAgICAgICAgIHNpbmdsZS5yb3c9VFJVRSwgbm90ZXMuYXBwZW5kID0gRkFMU0UsDQogICAgICAgICAgb21pdC5zdGF0PWMoInNlciIpLCBzdGFyLmN1dG9mZnMgPSBjKDAuMDUsIDAuMDEsIDAuMDAxKSwNCiAgICAgICAgICBoZWFkZXI9RkFMU0UpDQpgYGANCg0KLSBJbnRlcmNlcHQgPSBNZWFuIG9mIG1lYW5zIChncmFuZCBtZWFuKQ0KLSBNZWFuIG9mIGVhY2ggY29uZGl0aW9uIGNhbGN1bGF0ZWQgYmVsb3cNCg0KYGBge3J9DQpNZWFuLkludGVyYWN0aW9uPC1hZ2dyZWdhdGUoRW1vdGlvbn5TdHlsZUYsZGF0YSA9IEVtb3Rpb24uRGF0YSwgRlVOPW1lYW4pDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0KbGlicmFyeShrbml0cikNCmthYmxlKE1lYW4uSW50ZXJhY3Rpb24pDQpgYGANCg0KLSBHcmFuZCBtZWFuIGNhbGN1bGF0ZWQgYmVsb3cNCg0KYGBge3J9DQpzdW0oYWdncmVnYXRlKEVtb3Rpb25+U3R5bGVGLGRhdGEgPSBFbW90aW9uLkRhdGEsIEZVTj1tZWFuKVsyXSkvMw0KYGBgDQoNCiMjIyMgQ29lZmZpY2llbnRzDQotIFN0eWxlLkMuUzEgPSBjb2VmZmljaWVudCBvbiBOb3JtYWwgYXMgaXQgZGlmZmVycyBmcm9tIGdyYW5kIG1lYW4NCi0gU3R5bGUuQy5TMiA9IGNvZWZmaWNpZW50IG9uIEV4YWdnZXJhdGVkIGFzIGl0IGRpZmZlcnMgZnJvbSBncmFuZCBtZWFuDQotIFRvIGdldCB0aGUgbWVhbnMgZm9yIGVhY2ggY29uZGl0aW9uOiANCg0KIyMjIyBNZWFucyBwZXIgQ29uZGl0aW9uDQotICpGbGF0ID0gQ2Fubm90IGdldCBmcm9tIHRoaXMgbW9kZWwqDQotICpOb3JtYWwgPSBJbnRlcmNlcHQgKyBTdHlsZS5DLlMxKg0KLSAqRXhhZ2dlcmF0ZWQgPSBJbnRlcmNlcHQgKyBTdHlsZS5DLlMyKg0KDQojIyMjIFB2YWx1ZXMNCi0gVGhlIHB2YWx1ZSBvbiB0aGUgaW50ZXJjZXB0IGFza3MgaWYgdGhlICpncmFuZCBtZWFuKiBkaWZmZXJlbnQgZnJvbSB6ZXJvDQotIFRoZSBwdmFsdWUgb24gdGhlIHNsb3BlcyBhc2tzIGlmIGVhY2ggb2YgdGhlIG90aGVyIGxldmVscyBpcyBkaWZmZXJlbnQgZnJvbSAqZ3JhbmQgbWVhbioNCi0gKk5vdGUqOiBXZSBoYXZlIGxvc3QgdGhlIGFiaWxpdHkgdG8gYXNrIGFib3V0IEZsYXQgY29uZGl0aW9uLCB0byBnZXQgaXQgYmFjayB3ZSB3b3VsZCBoYXZlIHRvIHJvdGF0ZSB0aGUgYmFzZWxpbmUgYW5kIGRvIGl0IGFnYWluDQoNCiMjIyAgU2ltcGxlIENvZGluZw0KLSBUaGV5IG11c3Qgc3VtIHRvIHplcm8sIGFuZCB0aGUgYWJzKHZhbHVlcykgbXVzdCBzdW0gdG8gMQ0KLSBMaWtlIGluIEFOT1ZBIHlvdSBjYW4gZGVzaWduIHRoZXNlIHRvIGFzayBzcGVjaWZpYyBxdWVzdGlvbnMgYnkgbWVyZ2luZyBjb25kaXRpb25zIChvciBub3QpDQotIFdlIHdpbGwgdXNlIHRoZSBjb250ci50cmVhdG1lbnQgdHJlYXRtZW50ICh3aGljaCBSIGlzIHVzaW5nIHRvIGF1dG9tYXRpY2FsbHkgY29udmVydCB5b3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhbHJlYWR5KQ0KLSAqKkp1c3QgbGlrZSBkdW1teSBjb2RpbmcgYnV0IHdlIGNoYW5nZSB0aGUgbWVhbmluZyBvZiB0aGUgaW50ZXJjZXB0KioNCi0gVGhlIHJlZmVyZW5jZSBsZXZlbCBpcyAqKkZpcnN0KiogYWdhaW4NCg0KVmFyaWFibGUgICAgfCBDMSAgIHwgQzINCi0tLS0tLS0tLS0tLXwgLS0tLSB8IC0tLQ0KRmxhdCAgICAgICAgfCAtMS8zIHwgLTEvMw0KTm9ybWFsICAgICAgfCAgMi8zIHwgLTEvMw0KRXhhZ2dlcmF0ZWQgfCAtMS8zIHwgIDIvMw0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0V9DQpFbW90aW9uLkRhdGEkU3R5bGUuU2ltcGxlIDwtIGZhY3RvcihFbW90aW9uLkRhdGEkU3R5bGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1jKDAsMSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJGbGF0IiwgIk5vcm1hbCIsICJFeGFnZ2VyYXRlZCIpKQ0KDQpMZXZlbHM8LTMNClNpbXBsZS4xPC1jb250ci50cmVhdG1lbnQoTGV2ZWxzKSAjIER1bW15IGNvZGUNCiNNYWtlIHlvdXIgY29kZXMNCm15LmNvZGluZzwtbWF0cml4KHJlcCgxL0xldmVscywgTGV2ZWxzKihMZXZlbHMtMSkpLCBuY29sPUxldmVscy0xKQ0KbXkuc2ltcGxlPC1TaW1wbGUuMS1teS5jb2RpbmcNCm15LnNpbXBsZQ0KYGBgDQoNCi0gV2Ugd2lsbCBhZGQgdGhhdCBjb2RlIHRvIG91ciBgbG1gIGZ1bmN0aW9uLCBieSBhZGRpbmcgdGhlIHBhcmFtZXRlcnMgYGxpc3QoU3R5bGUuU2ltcGxlPW15LnNpbXBsZSlgICANCg0KYGBge3J9DQpNb2RlbC4xLlNpbXBsZTwtbG0oRW1vdGlvbiB+IFN0eWxlLlNpbXBsZSwgZGF0YSA9IEVtb3Rpb24uRGF0YSwgDQogICAgICAgICAgICAgICAgICAgY29udHJhc3RzPWxpc3QoU3R5bGUuU2ltcGxlPW15LnNpbXBsZSkpDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0Kc3RhcmdhemVyKE1vZGVsLjEuU2ltcGxlLHR5cGU9Imh0bWwiLA0KICAgICAgICAgIGludGVyY2VwdC5ib3R0b20gPSBGQUxTRSwNCiAgICAgICAgICBzaW5nbGUucm93PVRSVUUsICBub3Rlcy5hcHBlbmQgPSBGQUxTRSwNCiAgICAgICAgICBvbWl0LnN0YXQ9Yygic2VyIiksIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KDQojIyMjIENvZWZmaWNpZW50cw0KLSBUaGlzIG1lcmdlcyB0aGUgZHVtbXkgYW5kIGRldmlhbmNlIGNvZGluZ3MgdGh1czogDQotIEludGVyY2VwdCA9IE1lYW4gb2YgbWVhbnMgKGdyYW5kIG1lYW4pDQotIFN0eWxlRk5vcm1hbCA9ICBzbG9wZSBvZiBOb3JtYWwgZnJvbSBiYXNlbGluZSAoRmxhdCkNCi0gU3R5bGVGRXhhZ2dlcmF0ZWQgPSBzbG9wZSBvZiBFeGFnZ2VyYXRlZCBmcm9tIGJhc2VsaW5lIChGbGF0KQ0KDQojIyMjIE1lYW5zIHBlciBDb25kaXRpb24NCi0gKllvdSBjYW5ub3QgZ2V0IG1lYW5zIG9mIGVhY2ggY29uZGl0aW9uIGZyb20gdGhpcyBtb2RlbCoNCg0KIyMjIyBQdmFsdWVzDQotIFRoZSBwdmFsdWUgb24gdGhlIGludGVyY2VwdCBhc2tzIGlmIHRoZSAqZ3JhbmQgbWVhbiogZGlmZmVyZW50IGZyb20gemVybw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBzbG9wZXMgYXNrcyBpZiBlYWNoIG9mIHRoZSBvdGhlciBsZXZlbHMgaXMgZGlmZmVyZW50IGZyb20gYmFzZWxpbmUgKCpGbGF0KikNCg0KIyMjIE90aGVyIHR5cGVzIG9mIGNvbnRyYXN0IGNvZGluZw0KLSBIZWxtZXJ0OiBjb21wYXJlcyBlYWNoIGxldmVsIHRvIHRoZSBtZWFuIG9mIHRoZSBzdWJzZXF1ZW50IGxldmVscyBbY2FuIGJlIHJldmVyc2VkXQ0KLSBGb3J3YXJkIERpZmZlcmVuY2UgY29kaW5nOiBvbmUgbGV2ZWwgaXMgY29tcGFyZWQgdG8gdGhlIG5leHQgKGFkamFjZW50KSBsZXZlbC4gKGxldmVsIDEgdnMuIDIuIGxldmVsIDIgdnMuIDMpIFtjYW4gYmUgcmV2ZXJzZWRdDQotIEN1c3RvbTogTWVyZ2UgYW5kIGNvbXBhcmUgbGV2ZWxzIGF0IHdpbGwNCg0KIyMjIyBDZW50ZXIgdmFyaWFibGVzIGFuZCB0ZXN0IHNsb3Blcw0KLSBUaGVyZSBpcyBubyByZWFzb24gd2h5IHlvdSBjYW5ub3QgdHJlYXQgdGhlIHZhcmlhYmxlcyBhcyBjb250aW51b3VzIGlzIHRoZXkgYXJlICpvcmRpbmFsKg0KLSBqdXN0IGNlbnRlciB0aGVtIGFuZCB0cmVhdCBsaWtlIGEgY29udGludW91cyB2YXJpYWJsZQ0KDQoNCiMgTW9kZWxzIHdpdGggSW50ZXJhY3Rpb25zICgyIE5vbWluYWwgdmFyaWFibGVzKQ0KLSBJbnRlcmFjdGlvbnMgY2FuIGJlIHRyaWNreSBhcyB0aGUgaW50ZXJwcmV0YXRpb24gZGVwZW5kcyBvbiBob3cgeW91IGNvZGUgSVZzDQogICAgLSBGaXJzdCwgbGV0J3MgdHJ5IHNvbWUgY2F0ZWdvcmljYWwgdnMuIGNhdGVnb3JpY2FsIGludGVyYWN0aW9ucw0KLSBXZSB3aWxsIGFkZCBhIHZhcmlhYmxlIHRvIG91ciBleHBlcmltZW50IGZyb20gYWJvdmU7IHdlIHdpbGwgYWRkIHRoZSBsb2NhdGlvbiB3aGVyZSB0aGUgYWN0b3JzIHdvcmsgKE1vdmllIHZzLiBUaGVhdHJlKQ0KLSBFbW90aW9uIHJhdGluZyB+IEV4cHJlc3NpdmUgaW50ZW50aW9ucypsb2NhdGlvbiBvZiB0aGUgYWN0b3IgDQoNCiRFbW90aW9uID0gLTMqRmxhdCArIDAqTm9ybWFsICszKkV4YWcgKzAqTW92aWUgLSAxLjUqVGhlYXRyZSAtIDAqRmxhdCpNb3ZpZSArIDAqTm9ybWFsKk1vdmllICswKkV4YWcqTW92aWUgLSAxMCpGbGF0KlRoZWF0cmUgKzAqTm9ybWFsKlRoZWF0cmUgKzEwKkV4YWcqVGhlYXRyZSArIDUwICsgXGVwc2lsb24kDQoNCg0KYGBge3J9DQpzZXQuc2VlZCg0MikNCk4gPC0gMjAwDQpYIDwtIHNhbXBsZShyZXAoYygtMSwwLDEpLE4pLE4scmVwbGFjZSA9IEZBTFNFKQ0KWiA8LSBzYW1wbGUocmVwKGMoMCwxKSxOKjMvMiksTixyZXBsYWNlID0gRkFMU0UpDQoNCiMgT3VyIGVxdWF0aW9uIHRvIGNyZWF0ZSBZDQpZIDwtIDMqWCAtMS41KlorMTAqWCpaKyA1MCArIHJub3JtKE4sIHNkPTEwKQ0KI0J1aWx0IG91ciBkYXRhIGZyYW1lDQpFbW90aW9uLkRhdGEuMjwtZGF0YS5mcmFtZShFbW90aW9uPVksU3R5bGU9WCxMb2NhdGlvbj1aKQ0KRW1vdGlvbi5EYXRhLjIkU3R5bGU8LUVtb3Rpb24uRGF0YS4yJFN0eWxlKzENCmBgYA0KDQoNCiMjIER1bW15IGNvZGluZw0KLSBMZXRzIGR1bW15IGNvZGUgYWxsIG9mIHRoZW06IGNvbnZlcnQgdGhlbSB0byBhIGxhYmVsIGluIHRoZSBvdGhlciB3ZSB3YW50DQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQojIENvbnZlcnQgYWxsIG91ciBmYWN0b3JzDQpFbW90aW9uLkRhdGEuMiRTdHlsZUYgPC0gZmFjdG9yKEVtb3Rpb24uRGF0YS4yJFN0eWxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9YygwLDEsMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiRmxhdCIsICJOb3JtYWwiLCAiRXhhZ2dlcmF0ZWQiKSkNCg0KRW1vdGlvbi5EYXRhLjIkTG9jYXRpb25GIDwtIGZhY3RvcihFbW90aW9uLkRhdGEuMiRMb2NhdGlvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWMoMCwxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJNb3ZpZSBTZXQiLCAiVGhlYXRyZSIpKQ0KDQpgYGANCg0KLUxldCdzIGxvb2sgYXQgdGhlIGNvbGxhcHNlZCBtZWFucyBhbmQgdGhlIG1lYW5zIHBlciBjZWxsDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdhc2lzJ30NCk1lYW4uU3R5bGU8LWFnZ3JlZ2F0ZShFbW90aW9uflN0eWxlRixkYXRhID0gRW1vdGlvbi5EYXRhLjIsIEZVTj1tZWFuKQ0Ka2FibGUoTWVhbi5TdHlsZSkNCk1lYW4uTG9jYXRpb248LWFnZ3JlZ2F0ZShFbW90aW9ufkxvY2F0aW9uRixkYXRhID0gRW1vdGlvbi5EYXRhLjIsIEZVTj1tZWFuKQ0Ka2FibGUoTWVhbi5Mb2NhdGlvbikNCk1lYW4uSW50ZXJhY3Rpb248LWFnZ3JlZ2F0ZShFbW90aW9uflN0eWxlRipMb2NhdGlvbkYsZGF0YSA9IEVtb3Rpb24uRGF0YS4yLCBGVU49bWVhbikNCmthYmxlKE1lYW4uSW50ZXJhY3Rpb24pDQpgYGANCg0KLSBMZXQgZXhhbWluZSBvdXIgcmVncmVzc2lvbiwgYnV0IHdlIG5lZWQgdG8gZXhhbWluZSBhIG1haW4gZWZmZWN0cyBhbmQgaW50ZXJhY3Rpb24gbW9kZWwNCg0KYGBge3J9DQpNb2RlbC5JMS5EdW1teTwtbG0oRW1vdGlvbiB+IFN0eWxlRitMb2NhdGlvbkYsIGRhdGEgPSBFbW90aW9uLkRhdGEuMikNCk1vZGVsLkkyLkR1bW15PC1sbShFbW90aW9uIH4gU3R5bGVGKkxvY2F0aW9uRiwgZGF0YSA9IEVtb3Rpb24uRGF0YS4yKQ0KYGBgDQoNCg0KYGBge3IsIGVjaG89RkFMU0UscmVzdWx0cz0nYXNpcyd9DQpzdGFyZ2F6ZXIoTW9kZWwuSTEuRHVtbXksTW9kZWwuSTIuRHVtbXksdHlwZT0iaHRtbCIsDQogICAgICAgICAgY29sdW1uLmxhYmVscyA9IGMoIk1haW4gRWZmZWN0cyIsICJJbnRlcmFjdGlvbiIpLA0KICAgICAgICAgIGludGVyY2VwdC5ib3R0b20gPSBGQUxTRSwNCiAgICAgICAgICBzaW5nbGUucm93PVRSVUUsbm90ZXMuYXBwZW5kID0gRkFMU0UsDQogICAgICAgICAgb21pdC5zdGF0PWMoInNlciIpLCBzdGFyLmN1dG9mZnMgPSBjKDAuMDUsIDAuMDEsIDAuMDAxKSwNCiAgICAgICAgICBoZWFkZXI9RkFMU0UpDQpgYGANCg0KDQotIFlvdSB3aWxsIG5vdGljZSBhIGxhcmdlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbWFpbiBlZmZlY3RzIGFuZCBpbnRlcmFjdGlvbiBtb2RlbA0KLSBUaGlzIGlzIGJlY2F1c2UgdGhlIG1lYW5pbmcgY29lZmZpY2llbnRzIGluIHRoZSBpbnRlcmFjdGlvbiBkaWZmZXIgZnJvbSB0aGUgbWFpbiBlZmZlY3RzIG1vZGVsDQotIFRoZSBtYWluIGVmZmVjdHMgd2VyZSBleHBsYWluZWQgYWJvdmUsIGJ1dCB0aGV5IGNoYW5nZSBtZWFuaW5nIGEgbGl0dGxlIGJlY2F1c2UgdGhlcmUgaXMgc2Vjb25kIHZhcmlhYmxlDQoNCiMjIyBNYWluIEVmZmVjdHMNCg0KIyMjIyBDb2VmZmljaWVudHMNCi0gVGhlc2UgZG8gbm90IGNvbm5lY3QgYmFjayB0byB0aGUgaW5kaXZpZHVhbCBjZWxscyBhcyB5b3UgYXJlIGFzc3VtaW5nIHRoZSB0d28gZmFjdG9ycyBoYXZlIGluZGVwZW5kZW50IGVmZmVjdHMNCiAgICAtIFRodXMgdGhlc2UgYXJlIGh5cG90aGV0aWNhbCB2YWx1ZXMgKG5vdCBjb25uZWN0ZWQgdG8gdGhlIGluZGl2aWR1YWwgY2VsbHMpDQotIEludGVyY2VwdCA9IEVzdGltYXRlIG9mIHRoZSBtZWFuLCBhc3N1bWluZyB0aGUgdHdvIGZhY3RvcnMgaGF2ZSBpbmRlcGVuZGVudCBlZmZlY3RzIGF0IHRoZWlyIDAgcG9pbnRzIFtiYXNlbGluZV0NCi0gU3R5bGVGTm9ybWFsID0gTm9ybWFsIC0gRmxhdCAoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCi0gU3R5bGVGRXhhZ2dlcmF0ZWQgPSBFeGFnZ2VyYXRlZCAtIEZsYXQgKGFzc3VtaW5nIHRoZSB0d28gZmFjdG9ycyBhcmUgaW5kZXBlbmRlbnQpDQotIExvY2F0aW9uRlRoZWF0cmUgPSBUaGVhdHJlIC0gTW92aWUoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCg0KLSBXZSBjYW4gc2VlIHRoZSBtYWluIGVmZmVjdCBtb2RlbHMgcmVzdWx0cw0KDQpgYGB7cn0NCmxpYnJhcnkoZWZmZWN0cykNCmFsbEVmZmVjdHMoTW9kZWwuSTEuRHVtbXkpDQpgYGANCg0KIyMjIyBNZWFucyBwZXIgQ29uZGl0aW9uIA0KLSBZb3UgY2Fubm90IGdldCB0aGVtDQoNCiMjIyMgUHZhbHVlcw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBpbnRlcmNlcHQgYXNrcyBpZiB0aGUgYmFzZWxpbmUgaXMgZGlmZmVyZW50IGZyb20gemVybw0KLSBUaGUgcHZhbHVlIG9uIHRoZSBkaWZmZXJlbmNlcyBhc2tzIGlmIHRoZXkgYXJlIGZyb20gZGlmZmVyZW50IGZyb20gYmFzZWxpbmUgDQoNCiMjIyBJbnRlcmFjdGlvbnMNCg0KIyMjIyBDb2VmZmljaWVudHMNCi0gVGhlc2UgY2VsbHMgY29ubmVjdCBiYWNrIHRvIGV4cGVyaW1lbnRhbCBjZWxscw0KLSBJbnRlcmNlcHQgPSBMb2NhdGlvbigwKSBAIFN0eWxlKDApIGFrYSBNb3ZpZSBAIEZsYXQgW3JlYWwgdmFsdWVdDQotIFN0eWxlRk5vcm1hbCA9IERpZmZlcm5jZSBvZiBbTG9jYXRpb24oMCkgQCBTdHlsZSgxKV0gLSBbTG9jYXRpb24oMCkgQCBTdHlsZSgwKV0NCi0gU3R5bGVGRXhhZ2dlcmF0ZWQgPSBEaWZmZXJuY2Ugb2YgW0xvY2F0aW9uKDApIEAgU3R5bGUoMildIC0gW0xvY2F0aW9uKDApIEAgU3R5bGUoMCldDQotIExvY2F0aW9uRlRoZWF0cmUgPSBEaWZmZXJuY2Ugb2YgW0xvY2F0aW9uKDEpIEAgU3R5bGUoMCldIC0gW0xvY2F0aW9uKDApIEAgU3R5bGUoMCldDQotIFN0eWxlRk5vcm1hbDpMb2NhdGlvbkZUaGVhdHJlID0gRGlmZmVybmNlIG9mIFtMb2NhdGlvbigxKSBAIFN0eWxlKDEpXSAtIFtMb2NhdGlvbigwKSBAIFN0eWxlKDEpIC0gTG9jYXRpb24oMCkgQCBTdHlsZSgwKSArIFtMb2NhdGlvbigxKSBAIFN0eWxlKDApXSAtIFtMb2NhdGlvbigwKSBAIFN0eWxlKDApXQ0KLSBTdHlsZUZFeGFnZ2VyYXRlZDpMb2NhdGlvbkZUaGVhdHJlID0gRGlmZmVybmNlIG9mIFtMb2NhdGlvbigxKSBAIFN0eWxlKDIpXSAtIFtMb2NhdGlvbigwKSBAIFN0eWxlKDIpIC0gTG9jYXRpb24oMCkgQCBTdHlsZSgwKSArIFtMb2NhdGlvbigyKSBAIFN0eWxlKDApXSAtIFtMb2NhdGlvbigwKSBAIFN0eWxlKDApXQ0KDQoNCiMjIyMgTWVhbnMgcGVyIENvbmRpdGlvbg0KLSBZb3UgY2FuIGZpbmQgYWxsIG1lYW5zIGZvciBhbGwgY2VsbHMhIA0KLSAqRmxhdCBAIE1vdmllID0gSW50ZXJjZXB0Kg0KLSAqTm9ybWFsIEAgTW92aWUgPSBJbnRlcmNlcHQgKyBTdHlsZUZOb3JtYWwqIA0KLSAqRXhhZ2dlcmF0ZWQgQCBNb3ZpZSA9IEludGVyY2VwdCArIFN0eWxlRkV4YWdnZXJhdGVkKiANCi0gKkZsYXQgQCBUaGVhdHJlID0gSW50ZXJjZXB0ICsgTG9jYXRpb25GVGhlYXRyZSoNCi0gKk5vcm1hbCBAIFRoZWF0cmUgPSBJbnRlcmNlcHQgKyBMb2NhdGlvbkZUaGVhdHJlK1N0eWxlRk5vcm1hbCtTdHlsZUZOb3JtYWw6TG9jYXRpb25GVGhlYXRyZSogDQotICpFeGFnZ2VyYXRlZCBAIFRoZWF0cmUgPSAgSW50ZXJjZXB0ICsgTG9jYXRpb25GVGhlYXRyZSArIFN0eWxlRkV4YWdnZXJhdGVkICsgU3R5bGVGRXhhZ2dlcmF0ZWQ6TG9jYXRpb25GVGhlYXRyZSAqIA0KDQojIyMjIFB2YWx1ZXMNCi0gVGhlIHB2YWx1ZSBvbiB0aGUgaW50ZXJjZXB0IGFza3MgaWYgdGhlIGJhc2VsaW5lIGlzIGRpZmZlcmVudCBmcm9tIHplcm8NCi0gVGhlIHB2YWx1ZSBvbiB0aGUgZGlmZmVyZW5jZXMgYXNrcyBpZiB0aGV5IGFyZSBmcm9tIGRpZmZlcmVudCBmcm9tIGJhc2VsaW5lIA0KLSBCdXQgdGhlc2UgYXJlIG5vdyBhcmUgbm93IHNpbXBsZSBlZmZlY3RzIA0KDQoNCiMjIyBNYWluIGVmZmVjdCBtb2RlbCB2cy4gSW50ZXJhY3Rpb24gbW9kZWwNCi0gU2luY2UgdGhlIHJlc3VsdHMgYXJlIG5vdCBhZGRpdGl2ZSwgdGhlIG1haW4gZWZmZWN0IG1vZGVsIGlzIHVzZWZ1bCBvbmx5IGluIHdoaWNoIHRvIHVuZGVyc3RhbmQgaG93IHRoZSB0ZXJtcyBoYXZlIGNoYW5nZWQNCi0gR2l2ZXMgc29tZSBpbnNpZ2h0IGludG8gdGhlIGludGVyYWN0aW9uDQoNCiMjIyBHcmFwaCBNb2RlbA0KDQpgYGB7cn0NCkludGVyLjE8LWVmZmVjdCgiU3R5bGVGKkxvY2F0aW9uRiIsIE1vZGVsLkkyLkR1bW15KQ0KcGxvdChJbnRlci4xLCBtdWx0aWxpbmUgPSBUUlVFKQ0KYGBgDQoNCiMjIyBDb25uZWN0aW9uIHRvIGJldHdlZW4tc3ViamVjdCBBTk9WQQ0KLSBSZWdyZXNzaW9uIHdpdGggb25seSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgY2FuIGJlIGNvbnZlcnRlZCBpbnRvIGFuIEFOT1ZBIHZlcnkgZWFzaWx5IA0KLSBUaHVzIGl0IGNhbiBiZSB0cmVhdGVkIGp1c3QgbGlrZSBBTk9WQQ0KLSBidXQgdGhlIHJlZ3Jlc3Npb24gbWFrZXMgdGhlIEFOT1ZBIHByb2Nlc3MgbW9vdCBhcyB5b3UgY2FuIG5vdyB0aGUgcmVncmVzc2lvbiBjYW4gYmUgY29kZWQgaW4gc3VjaCBhIHdheSB0aGF0IHlvdSBjYW4gdGVzdCBmb2xsb3cgdXAgdGVzdHMgaW4gYSB3YXkgeW91IHdhbnQgdG8gdGVzdCB0aGVtIGFsbCANCg0KYGBge3J9DQpsaWJyYXJ5KGNhcikNCkFub3ZhKE1vZGVsLkkyLkR1bW15LCB0eXBlPSJJSUkiKQ0KYGBgDQoNCi0gTm90ZSwgd2UgaGF2ZSB0byBjYWxsIGZvciBhIFR5cGUgSUlJIHN1bSBvZiBzcXVhcmVzIHRvIG1hdGNoIFNQU1Mgb3V0cHV0IGFzIFIgd291bGQgZGVmYXVsdCB0byBUeXBlIEkNCg0KIyMgQ29udHJhc3QgQ29kaW5nDQoNCiMjIyBEZXZpYXRpb24gQ29kaW5nDQotIExldHMgY29kZSBlYWNoIHZhcmlhYmxlIGFzIHdlIGRpZCBhYm92ZQ0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KRW1vdGlvbi5EYXRhLjIkU3R5bGUuQy5TIDwtIGZhY3RvcihFbW90aW9uLkRhdGEuMiRTdHlsZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWMoMSwyLDApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk5vcm1hbCIsICJFeGFnZ2VyYXRlZCIsICJGbGF0IikpDQpFbW90aW9uLkRhdGEuMiRMb2NhdGlvbi5DLlMgPC0gZmFjdG9yKEVtb3Rpb24uRGF0YS4yJExvY2F0aW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9YygxLDApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIlRoZWF0cmUiLCAiTW92aWUgU2V0IikpDQoNCk1vZGVsLkkxLkMuUzwtbG0oRW1vdGlvbiB+IFN0eWxlLkMuUytMb2NhdGlvbi5DLlMsIGRhdGEgPSBFbW90aW9uLkRhdGEuMiwgDQogICAgICAgICAgICAgICAgIGNvbnRyYXN0cz1saXN0KFN0eWxlLkMuUz1jb250ci5zdW0oMyksTG9jYXRpb24uQy5TPWNvbnRyLnN1bSgyKSkpDQpNb2RlbC5JMi5DLlM8LWxtKEVtb3Rpb24gfiBTdHlsZS5DLlMqTG9jYXRpb24uQy5TLCBkYXRhID0gRW1vdGlvbi5EYXRhLjIsDQogICAgICAgICAgICAgICAgY29udHJhc3RzPWxpc3QoU3R5bGUuQy5TPWNvbnRyLnN1bSgzKSxMb2NhdGlvbi5DLlM9Y29udHIuc3VtKDIpKSkNCmBgYA0KDQotIExldCdzIGxvb2sgYXQgaG93IHRoaW5ncyBkaWZmZXIgZnJvbSB0aGUgbWVhbiBvZiBhbGwgY29uZGl0aW9ucyAoZ3JhbmQgbWVhbikNCg0KYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0Kc3RhcmdhemVyKE1vZGVsLkkxLkMuUyxNb2RlbC5JMi5DLlMsdHlwZT0iaHRtbCIsDQogICAgICAgICAgY29sdW1uLmxhYmVscyA9IGMoIk1haW4gRWZmZWN0cyIsICJJbnRlcmFjdGlvbiIpLA0KICAgICAgICAgIGludGVyY2VwdC5ib3R0b20gPSBGQUxTRSwNCiAgICAgICAgICBzaW5nbGUucm93PVRSVUUsIG5vdGVzLmFwcGVuZCA9IEZBTFNFLA0KICAgICAgICAgIG9taXQuc3RhdD1jKCJzZXIiKSwgc3Rhci5jdXRvZmZzID0gYygwLjA1LCAwLjAxLCAwLjAwMSksDQogICAgICAgICAgaGVhZGVyPUZBTFNFKQ0KYGBgDQoNCi0gQWdhaW4gd2UgYXJlIHRlc3RpbmcgYmV0d2VlbiB0aGUgZ3JhbmQgbWVhbiBhbmQgdGhlIGluZGl2aWR1YWwgdGVybXMNCg0KIyMjIyBNYWluIEVmZmVjdHMNCg0KIyMjIyMgQ29lZmZpY2llbnRzDQotIFRoZXNlIGRvIG5vdCBjb25uZWN0IGJhY2sgdG8gdGhlIGluZGl2aWR1YWwgY2VsbHMgYXMgeW91IGFyZSBhc3N1bWluZyB0aGUgdHdvIGZhY3RvcnMgaGF2ZSBpbmRlcGVuZGVudCBlZmZlY3RzDQotIFRodXMgdGhlc2UgYXJlIGh5cG90aGV0aWNhbCAqR3JhbmQgbWVhbiogdmFsdWVzIA0KLSBJbnRlcmNlcHQgPSAqR3JhbmQgTWVhbiosIGJ1dCBhc3N1bWluZyB0aGUgdHdvIGZhY3RvcnMgaGF2ZSBpbmRlcGVuZGVudCBlZmZlY3RzDQotIFN0eWxlLkMuUzEgID0gTm9ybWFsIChhdmVyYWdlZCBvdmVyIGxvY2F0aW9uKSAtICpHcmFuZCBNZWFuKiAoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCi0gU3R5bGUuQy5TMiA9IEV4YWdnZXJhdGVkIChhdmVyYWdlZCBvdmVyIGxvY2F0aW9uKSAtICpHcmFuZCBNZWFuKiAoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCi0gTG9jYXRpb24uQy5TMSA9IFRoZWF0cmUgKGF2ZXJhZ2VkIG92ZXIgU3R5bGUpIC0gICpHcmFuZCBNZWFuKiAoYXNzdW1pbmcgdGhlIHR3byBmYWN0b3JzIGFyZSBpbmRlcGVuZGVudCkNCg0KIyMjIyMgTWVhbnMgcGVyIENvbmRpdGlvbg0KLSAqQ2Fubm90IGdldCBmcm9tIHRoaXMgbW9kZWwqDQoNCiMjIyMjIFB2YWx1ZXMNCi0gVGhlIHB2YWx1ZSBvbiB0aGUgaW50ZXJjZXB0IGFza3MgaWYgdGhlIGJhc2VsaW5lICgqR3JhbmQgTWVhbiopIGlzIGRpZmZlcmVudCBmcm9tIHplcm8NCi0gVGhlIHB2YWx1ZSBvbiB0aGUgc2xvcGVzIGFza3MgaWYgZWFjaCBvZiB0aGUgb3RoZXIgbGV2ZWxzIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBiYXNlbGluZSAoKkdyYW5kIE1lYW4qKQ0KLSBOb3RlIHdlIGFyZSBtaXNzaW5nIHRlc3RzIG9uIEZsYXQgYW5kIE1vdmllIGNlbGwsIHdlIHdvdWxkIG5lZWQgdG8gcm90YXRlIHRoZSBtYXRyaXggYW5kIHJ1biBhZ2Fpbg0KDQojIyMjIEludGVyYWN0aW9ucw0KIyMjIyMgQ29lZmZpY2llbnRzDQotIEludGVyY2VwdCA9ICAqR3JhbmQgTWVhbiogKGFsbCA2IGNlbGxzIG1lYW4gYXZlcmFnZWQpDQotIFN0eWxlLkMuUzEgPSBOb3JtYWwgKGF2ZXJhZ2VkIG92ZXIgbG9jYXRpb24pIGZyb20gKkdyYW5kIE1lYW4qDQotIFN0eWxlLkMuUzIgPSBFeGFnZ2VyYXRlZCAoYXZlcmFnZWQgb3ZlciBsb2NhdGlvbikgZnJvbSAqR3JhbmQgTWVhbioNCi0gTG9jYXRpb24uQy5TMSA9IFRoZWF0cmUgKGF2ZXJhZ2VkIG92ZXIgU3R5bGUpIGZyb20gKkdyYW5kIE1lYW4qDQotIFN0eWxlLkMuUzE6TG9jYXRpb24uQy5TMSA9IGRpZmZlcmVuY2Ugb2YgTm9ybWFsIEAgVGhlYXRyZSBmcm9tICpHcmFuZCBNZWFuKg0KLSBTdHlsZS5DLlMyOkxvY2F0aW9uLkMuUzEgPSBkaWZmZXJlbmNlIG9mIEV4YWdnZXJhdGVkIEAgVGhlYXRyZSBmcm9tICpHcmFuZCBNZWFuKg0KIA0KIyMjIyMgTWVhbnMgcGVyIENvbmRpdGlvbg0KLSAqQ2Fubm90IGdldCBmcm9tIHRoaXMgbW9kZWwqDQoNCiMjIyMjIFB2YWx1ZXMNCi0gVGhlIHB2YWx1ZSBvbiB0aGUgaW50ZXJjZXB0IGFza3MgaWYgdGhlIGJhc2VsaW5lICgqR3JhbmQgTWVhbiopIGlzIGRpZmZlcmVudCBmcm9tIHplcm8NCi0gVGhlIHB2YWx1ZSBvbiB0aGUgZGlmZmVyZW5jZXMgYXNrcyBpZiBlYWNoIG9mIHRoZSBvdGhlciBsZXZlbHMgaXMgZnJvbSB0aGUgKCpHcmFuZCBNZWFuKikNCi0gTm90ZSB3ZSBhcmUgbWlzc2luZyB0ZXN0cyBvbiBGbGF0IGFuZCBtb3ZpZSBjZWxsLCB3ZSB3b3VsZCBuZWVkIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGFuZCBydW4gYWdhaW4NCg0KDQojIE1vZGVscyB3aXRoIEludGVyYWN0aW9ucyAoMSBOb21pbmFsIGFuZCAxIENvbnRpbnVvdXMgVmFyaWFibGUpDQotIFdlIHdpbGwgY2hhbmdlIG91ciBleHBlcmltZW50IGZyb20gYWJvdmUsIHdlIHdpbGwgYWRkIGEgbGlrZXJ0IHNjYWxlIHdoaWNoIHRoZSBhY3RvciByYXRlcyBob3cgImdvb2QiIHRoZXkgdGhpbmsgdGhlIHBlcmZvcm1hbmNlIHdhcyBbLTMgdGVycmlibGUgdG8gMyBleGNlbGxlbnRdDQotICpFbW90aW9uIHJhdGluZyB+IFF1YWxpdHkgUmF0aW5nIFggbG9jYXRpb24gb2YgdGhlIGFjdG9yIChpLmUuLCBNb3ZpZSBTZXQsIFRoZWF0cmUpKiANCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCiNTZXQgdXAgc2ltdWxhdGlvbg0Kc2V0LnNlZWQoNDIpDQpOIDwtIDIwMA0KWCA8LSBydW5pZihOLC0zLDMpDQpaIDwtIHNhbXBsZShyZXAoYygwLDEpLE4vMiksTixyZXBsYWNlID0gRkFMU0UpDQojIE91ciBlcXVhdGlvbiB0byBjcmVhdGUgWQ0KWSA8LSA0KlggKzIqWis4KlgqWisgNTAgKyBybm9ybShOLCBzZD0xMCkNCiNCdWlsdCBvdXIgZGF0YSBmcmFtZQ0KRW1vdGlvbi5EYXRhLjM8LWRhdGEuZnJhbWUoRW1vdGlvbj1ZLFF1YWxpdHk9WCxMb2NhdGlvbj1aKQ0KYGBgDQoNCiMjIENlbnRlciB0aGUgY29udGludW91cyB2YXJpYWJsZQ0KLSBCZXN0IHRvIGNlbnRlciBhcyBpdHMgd2lsbCBoZWxwIHVzIGludGVycHJldCANCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCiMgQ29udmVydCBhbGwgb3VyIGZhY3RvcnMNCkVtb3Rpb24uRGF0YS4zJFF1YWxpdHkuQyA8LSBzY2FsZShFbW90aW9uLkRhdGEuMyRRdWFsaXR5LCBzY2FsZSA9IEZBTFNFKVssXQ0KYGBgDQoNCiMjIER1bW15IGNvZGluZyBvZiBvdXIgbm9taW5hbCB2YXJpYWJsZQ0KLSBNYWtlIExvY2F0aW9uIGludG8gYSBmYWN0b3INCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCiMgQ29udmVydCBhbGwgb3VyIGZhY3RvcnMNCkVtb3Rpb24uRGF0YS4zJExvY2F0aW9uRiA8LSBmYWN0b3IoRW1vdGlvbi5EYXRhLjMkTG9jYXRpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWMoMCwxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk1vdmllIFNldCIsIlRoZWF0cmUiKSkNCmBgYA0KDQotIEZpcnN0IHRvIHVuZGVyc3RhbmQgd2hhdCB0aGUgaW50ZXJhY3Rpb24gd2lsbCB5aWVsZCBsZXRzIHVzIHJ1biB0d28gcmVncmVzc2lvbnMgd2hlcmUgd2Ugc2VwZXJhdGUgb3VyIGZhY3RvciB0byBzZWUgd2hhdCB0aGUgc2xvcGVzIHdvdWxkIGJlIGp1c3QgZm9yIGFjdG9ycyBhdCAqTW92aWUgU2V0KiB2cyBhdCB0aGUgKlRoZWF0cmUqDQoNCiMjIyBNb3ZpZSBTZXQgT05MWSB2cyBUaGVhdHJlIE9ubHkNCi0gV2Ugd2lsbCBzdWJzZXQgdGhlIGRhdGEgYW5kIHRlc3QgZm9yIHRoZSBRdWFsaXR5IHNsb3Blcw0KDQpgYGB7cn0NCk1vZGVsLk1vdmllPC1sbShFbW90aW9uIH4gUXVhbGl0eS5DLCANCiAgICAgICAgICAgICAgICBkYXRhID0gc3Vic2V0KEVtb3Rpb24uRGF0YS4zLExvY2F0aW9uRj09Ik1vdmllIFNldCIpKQ0KTW9kZWwuVGhlYXRyZTwtbG0oRW1vdGlvbiB+IFF1YWxpdHkuQywgDQogICAgICAgICAgICAgICAgZGF0YSA9IHN1YnNldChFbW90aW9uLkRhdGEuMyxMb2NhdGlvbkY9PSJUaGVhdHJlIikpDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0UscmVzdWx0cz0nYXNpcyd9DQpsaWJyYXJ5KHN0YXJnYXplcikNCnN0YXJnYXplcihNb2RlbC5Nb3ZpZSxNb2RlbC5UaGVhdHJlLHR5cGU9Imh0bWwiLA0KICAgICAgICAgIGNvbHVtbi5sYWJlbHMgPSBjKCJNb3ZpZSBTZXQgT05MWSIsICJUaGVhdHJlIE9ubHkiKSwNCiAgICAgICAgICBpbnRlcmNlcHQuYm90dG9tID0gRkFMU0UsDQogICAgICAgICAgc2luZ2xlLnJvdz1UUlVFLCAgbm90ZXMuYXBwZW5kID0gRkFMU0UsDQogICAgICAgICAgb21pdC5zdGF0PWMoInNlciIpLA0KICAgICAgICAgIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KDQotIElnbm9yZSB0aGUgaW50ZXJjZXB0cyBhbmQgcGF5IGF0dGVudGlvbiB0byB0aGUgc2xvcGVzOiANCiAgICAtIFF1YWxpdHkgQCB0aGUgKk1vdmllIFNldCBPTkxZKiBpcyAkYiQ9IGByIHJvdW5kKE1vZGVsLk1vdmllJGNvZWZmaWNpZW50c1syXSwzKWANCiAgICAgICAgLSBUaGUgcHZhbHVlcyB0ZWxscyB5b3UgaWYgdGhlIHNsb3BlIG9mIHF1YWxpdHkgaXMgZGlmZmVybmV0IGZyb20gYSBzbG9wZSBvZiAwICAgDQogICAgLSBRdWFsaXR5IEAgdGhlICpUaGVhdHJlIE9ubHkqIE9OTFkgaXMgJGIkPSBgciByb3VuZChNb2RlbC5UaGVhdHJlJGNvZWZmaWNpZW50c1syXSwzKWANCiAgICAgICAgLSBUaGUgcHZhbHVlcyB0ZWxscyB5b3UgaWYgdGhlIHNsb3BlIG9mIHF1YWxpdHkgaXMgZGlmZmVybmV0IGZyb20gYSBzbG9wZSBvZiAwICAgICAgICAgDQotIFdoYXQgd2UgcmVhbGx5IHdhbnQgdG8gdGVzdCBpcyBpZiB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgaW4gc2xvcGVzIGJldHdlZW4gcXVhbGl0eSBhdCAqTW92aWVzIHNldHMqIFZTICpUaGVhdHJlKg0KDQojIyMgVGVzdGluZyB0aGUgSW50ZXJhY3Rpb24NCi0gV2Ugd2lsbCB0ZXN0IGEgbWFpbiBlZmZlY3RzIG1vZGVsLCBgUXVhbGl0eStMb2NhdGlvbmAgYW5kIGNvbXBhcmUgaXQgdG8gYW4gaW50ZXJhY3Rpb24gbW9kZWwgYFF1YWxpdHkqTG9jYXRpb25gDQoNCmBgYHtyfQ0KTW9kZWwuRTMuMTwtbG0oRW1vdGlvbiB+IFF1YWxpdHkuQytMb2NhdGlvbkYsIGRhdGEgPSBFbW90aW9uLkRhdGEuMykNCk1vZGVsLkUzLjI8LWxtKEVtb3Rpb24gfiBRdWFsaXR5LkMqTG9jYXRpb25GLCBkYXRhID0gRW1vdGlvbi5EYXRhLjMpDQpgYGANCg0KLSBEb2VzIG1vZGVsIGludGVyYWN0aW9uIGltcHJvdmUgdGhlIG1vZGVsIGZpdD8gKEp1c3QgbGlrZSB3ZSBkaWQgd2l0aCBoaWVyYXJjaGljYWwgdGVzdGluZykNCmBgYHtyfQ0KTW9kZWwuRml0LkUzPC1hbm92YShNb2RlbC5FMy4xLE1vZGVsLkUzLjIpDQpgYGANCg0KYGBge3IsIGVjaD1GQUxTRX0NCmxpYnJhcnkoa25pdHIpDQprYWJsZShNb2RlbC5GaXQuRTMpDQpgYGANCg0KLSBZZXMhIFRoZSBpbnRlcmFjdGlvbiBpcyBzaWduaWZpY2FudCBpbXByb3ZlbWVudA0KLSBMZXQncyBnbyBleGFtaW5lIHRoZSBpbmRpdmlkdWFsIHJlZ3Jlc3Npb24gcGFyYW1hdGVyczoNCg0KIyMjIEludGVycHJldCBSZWdyZXNzaW9uDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2FzaXMnfQ0Kc3RhcmdhemVyKE1vZGVsLkUzLjEsTW9kZWwuRTMuMix0eXBlPSJodG1sIiwNCiAgICAgICAgICBjb2x1bW4ubGFiZWxzID0gYygiTWFpbiBFZmZlY3RzIiwgIkludGVyYWN0aW9uIiksDQogICAgICAgICAgaW50ZXJjZXB0LmJvdHRvbSA9IEZBTFNFLA0KICAgICAgICAgIHNpbmdsZS5yb3c9VFJVRSwgIG5vdGVzLmFwcGVuZCA9IEZBTFNFLA0KICAgICAgICAgIG9taXQuc3RhdD1jKCJzZXIiKSwNCiAgICAgICAgICBzdGFyLmN1dG9mZnMgPSBjKDAuMDUsIDAuMDEsIDAuMDAxKSwNCiAgICAgICAgICBoZWFkZXI9RkFMU0UpDQpgYGANCg0KDQoNCiMjIyMgTWFpbiBFZmZlY3RzIE1vZGVsDQotIEludGVyY2VwdCA9IE1lYW4gb2YgUXVhbGl0eSBAIE1vdmllcyBbKnAqID0gSXMgdGhlIGludGVyY2VwdCBkaWZmZXJlbnQgZnJvbSAwXQ0KLSBRdWFsaXR5LkMgID0gUXVhbGl0eS5DIHNsb3BlIGF2ZXJhZ2VkIGFjcm9zcyAqTW92aWVzKiAmICogVGhyZWF0cmUqICAgDQogICAgLSBUaGlzIGlzIGEgKipNYWluIEVmZmVjdCoqIFsqcCogPSBJcyBzbG9wZSBkaWZmZXJlbnQgZnJvbSAwIHNsb3BlXSANCiAgICAgICAgLSBUaGlzIHdvdWxkIGFsbW9zdCBiZSBsaWtlIGF2ZXJhZ2luZyB0aGUgc2xvcGVzIGZyb20gb3VyICpNb3ZpZSBTZXQgT05MWSogYW5kICpUaGVhdHJlIE9ubHkqIE1vZGVscw0KICAgICAgICAgICAgLSAkYiQgPSAoYHIgcm91bmQoTW9kZWwuTW92aWUkY29lZmZpY2llbnRzWzJdLDMpYCArICBgciByb3VuZChNb2RlbC5UaGVhdHJlJGNvZWZmaWNpZW50c1syXSwzKWApLzIgPSBgciByb3VuZCgoKE1vZGVsLk1vdmllJGNvZWZmaWNpZW50c1syXStNb2RlbC5UaGVhdHJlJGNvZWZmaWNpZW50c1syXSkvMiksMylgIA0KLSBMb2NhdGlvbkZUaGVhdHJlID0gVGhyZWF0cmUgZGlmZmVyZW5jZSBmcm9tIGludGVyY2VwdCBbcCA9IElzIG1lYW4gb2YgKlRoZWF0cmUqIGRpZmZlcmVudCBmcm9tICpNb3ZpZXMqIEAgbWVhbiBvZiBxdWFsaXR5XSANCiAgICAtIFRoaXMgaXMgYSAqKlNpbXBsZSBFZmZlY3QqKg0KDQojIyMjIEludGVyYWN0aW9uIE1vZGVsDQotIEludGVyY2VwdCA9IE1lYW4gb2YgUXVhbGl0eSBAIE1vdmllcyBbKnAqID0gSXMgdGhlIGludGVyY2VwdCBkaWZmZXJlbnQgZnJvbSAwXQ0KLSBRdWFsaXR5LkMgID0gUXVhbGl0eS5DIHNsb3BlIEAgTW92aWVzIA0KICAgIC0gVGhpcyBpcyBhICoqU2ltcGxlIFNsb3BlKiogWypwKiA9IElzIHNsb3BlIGRpZmZlcmVudCBmcm9tIDAgc2xvcGVdIA0KICAgICAgICAtIFRvIHByb3ZlIGl0IHdlIGNhbiBzZWUgaXQgbWF0Y2hlcyB0aGUgc2xvcGVzIGZyb20gb3VyICpNb3ZpZSBTZXQgT05MWSogTW9kZWwsICRiJD0gYHIgcm91bmQoTW9kZWwuTW92aWUkY29lZmZpY2llbnRzWzJdLDMpYA0KLSBMb2NhdGlvbkZUaGVhdHJlID0gVGhyZWF0cmUgZGlmZmVyZW5jZSBmcm9tIGludGVyY2VwdCBbKnAqID0gSXMgbWVhbiBvZiAqVGhlYXRyZSogZGlmZmVyZW50IGZyb20gbW92aWVzIEAgbWVhbiBvZiBxdWFsaXR5XQ0KICAgIC0gVGhpcyBpcyBhICoqU2ltcGxlIEVmZmVjdCoqDQotIFF1YWxpdHkuQzpMb2NhdGlvbkZUaGVhdHJlPSBzbG9wZSBkaWZmZXJlbmNlIGJldHdlZW4gKk1vdmllKiBhbmQgKlRoZWF0cmUqIFtwID0gSXMgdGhlIHNsb3BlIG9mIHF1YWxpdHkgQCBUaGVhdHJlIGRpZmZlcmVudCBmcm9tIHNsb3BlIGF0IF0NCiAgICAtIFRoaXMgaXMgYW4gKipJbnRlcmFjdGlvbioqDQogICAgICAgIC0gVG8gcHJvdmUgaXQgd2UgY2FuIHNlZSBpdCBtYXRjaGVzIHRoZSBzbG9wZXMgb2YgKlRoZWF0cmUgT25seSogLSAqTW92aWUgU2V0IE9OTFkqIE1vZGVsDQogICAgICAgICAgICAtICRiJD0gKGByIHJvdW5kKE1vZGVsLlRoZWF0cmUkY29lZmZpY2llbnRzWzJdLDMpYCAtICBgciByb3VuZChNb2RlbC5Nb3ZpZSRjb2VmZmljaWVudHNbMl0sMylgKSA9IGByIHJvdW5kKChNb2RlbC5UaGVhdHJlJGNvZWZmaWNpZW50c1syXS1Nb2RlbC5Nb3ZpZSRjb2VmZmljaWVudHNbMl0pLDMpYA0KICAgICAgICAgICAgDQotIElmIHlvdSB3YW50ZWQgdG8ga25vdyB0aGUgc2ltcGxlIHNsb3BlIG9mICpUaGVhdHJlIE9ubHkqIHlvdSB3b3VsZCBoYXZlIHRvIHJlbGV2ZWwgTG9jYXRpb24gYW5kIG1ha2UgVGhlYXRyZSA9IDAgKGkuZS4sIHRoZSByZWZlcmVuY2UpDQoNCmBgYHtyfQ0KRW1vdGlvbi5EYXRhLjMkTG9jYXRpb25UPC0gcmVsZXZlbChFbW90aW9uLkRhdGEuMyRMb2NhdGlvbkYsIHJlZiA9ICJUaGVhdHJlIikNCk1vZGVsLkUzLjIuUmVMZXZlbDwtbG0oRW1vdGlvbiB+IFF1YWxpdHkuQypMb2NhdGlvblQsIGRhdGEgPSBFbW90aW9uLkRhdGEuMykNCmBgYA0KICAgDQpgYGB7ciwgZWNobz1GQUxTRSxyZXN1bHRzPSdhc2lzJ30NCnN0YXJnYXplcihNb2RlbC5FMy4yLlJlTGV2ZWwsdHlwZT0iaHRtbCIsDQogICAgICAgICAgY29sdW1uLmxhYmVscyA9IGMoIlRoZWF0cmUgaXMgUmVmIiksDQogICAgICAgICAgaW50ZXJjZXB0LmJvdHRvbSA9IEZBTFNFLA0KICAgICAgICAgIHNpbmdsZS5yb3c9VFJVRSwgIG5vdGVzLmFwcGVuZCA9IEZBTFNFLA0KICAgICAgICAgIG9taXQuc3RhdD1jKCJzZXIiKSwNCiAgICAgICAgICBzdGFyLmN1dG9mZnMgPSBjKDAuMDUsIDAuMDEsIDAuMDAxKSwNCiAgICAgICAgICBoZWFkZXI9RkFMU0UpDQpgYGAgICANCg0KLSBZb3Ugd2lsbCBub3RpY2UgdGhlIGludGVyYWN0aW9uIGZsaXBwZWQgZGlyZWN0aW9uIGFuZCBub3cgdGhlIFF1YWxpdHkuQyBjb2VmZmljaWVudCAkYiQgPSBgciByb3VuZChNb2RlbC5FMy4yLlJlTGV2ZWwkY29lZmZpY2llbnRzWzJdLDMpYCA9ICB0aGUgKlRoZWF0cmUgT25seSogbW9kZWwgJGIkID0gYHIgcm91bmQoTW9kZWwuVGhlYXRyZSRjb2VmZmljaWVudHNbMl0sMylgICAgICAgICAgICANCg0KIyMjIFBsb3R0aW5nIEludGVyYWN0aW9uDQotIE9mdGVuIHRpbWVzIHlvdSB3aWxsIG5lZWQgdG8gdXNlIHRoZSBlZmZlY3RzIHBhY2thZ2UgYW5kIHBsb3QgYnkgaGFuZA0KLSBUaGUgcm9ja2NoYWxrIHBhY2thZ2Ugd2lsbCB3b3JrIGZvciBzaW1wbGUgbW9kZWxzIGxpa2UgdGhpcyBvbmUNCg0KYGBge3J9DQpsaWJyYXJ5KHJvY2tjaGFsaykNCnBsb3RTbG9wZXMoTW9kZWwuRTMuMiwgcGxvdHggPSAiUXVhbGl0eS5DIiwgbW9keCA9ICJMb2NhdGlvbkYiKQ0KYGBgDQoNCiMjIERldmlhdGlvbiBjb2Rpbmcgb2Ygb3VyIG5vbWluYWwgdmFyaWFibGUNCi0gV2Ugd2lsbCBzdGlsbCBjZW50ZXIgcXVhbGl0eQ0KLSBUaGlzIGNyZWF0ZXMgYSBtb3JlIEFOT1ZBIGxpa2UgaW50ZXJwcmV0YXRpb24gb2YgdGhlIGludGVyYWN0aW9uIA0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCkVtb3Rpb24uRGF0YS4zJExvY2F0aW9uRCA8LSBmYWN0b3IoRW1vdGlvbi5EYXRhLjMkTG9jYXRpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWMoMSwwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIlRoZWF0cmUiLCJNb3ZpZSBTZXQiKSkNCk1vZGVsLkUzLkQxPC1sbShFbW90aW9uIH4gUXVhbGl0eS5DK0xvY2F0aW9uRCwgZGF0YSA9IEVtb3Rpb24uRGF0YS4zLA0KICAgICAgICAgICAgICAgICBjb250cmFzdHM9bGlzdChMb2NhdGlvbkQ9Y29udHIuc3VtKDIpKSkNCk1vZGVsLkUzLkQyPC1sbShFbW90aW9uIH4gUXVhbGl0eS5DKkxvY2F0aW9uRCwgZGF0YSA9IEVtb3Rpb24uRGF0YS4zLA0KICAgICAgICAgICAgICAgICBjb250cmFzdHM9bGlzdChMb2NhdGlvbkQ9Y29udHIuc3VtKDIpKSkNCmBgYA0KDQojIyMgSW50ZXJwcmV0IFJlZ3Jlc3Npb24NCg0KYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0Kc3RhcmdhemVyKE1vZGVsLkUzLkQxLE1vZGVsLkUzLkQyLHR5cGU9Imh0bWwiLA0KICAgICAgICAgIGNvbHVtbi5sYWJlbHMgPSBjKCJNYWluIEVmZmVjdHMiLCAiSW50ZXJhY3Rpb24iKSwNCiAgICAgICAgICBpbnRlcmNlcHQuYm90dG9tID0gRkFMU0UsDQogICAgICAgICAgc2luZ2xlLnJvdz1UUlVFLG5vdGVzLmFwcGVuZCA9IEZBTFNFLCAgb21pdC5zdGF0PWMoInNlciIpLA0KICAgICAgICAgIHN0YXIuY3V0b2ZmcyA9IGMoMC4wNSwgMC4wMSwgMC4wMDEpLA0KICAgICAgICAgIGhlYWRlcj1GQUxTRSkNCmBgYA0KDQoNCiMjIyBNYWluIEVmZmVjdHMNCg0KIyMjIyBDb2VmZmljaWVudHMgJiBQdmFsdWVzDQotIEludGVyY2VwdCA9IE1lYW4gb2YgUXVhbGl0eSBAIG1lYW4gb2YgTW92aWUgJiBUaGVhdHJlIChpbWFnaW5hcnkpIFtwID0gSXMgdGhlIGludGVyY2VwdCBkaWZmZXJlbnQgZnJvbSAwXQ0KLSBRdWFsaXR5LkMgID0gUXVhbGl0eS5DIHNsb3BlIFtwID0gSXMgc2xvcGUgZGlmZmVyZW50IGZyb20gMF0NCi0gTG9jYXRpb25GVGhlYXRyZSA9IFRocmVhdHJlIGRpZmZlcmVuY2UgZnJvbSAwIChub3QgLSAxKSB0aHVzIGlzIDEvMiB0aGUgc2xvcGUgb2YgdGhlIGR1bW15IGNvZGUgW3AgPSBJcyBtZWFuIG9mIFRoZWF0cmUgZGlmZmVyZW50IGZyb20gbW92aWVzIEAgbWVhbiBvZiBxdWFsaXR5XQ0KDQojIyMgSW50ZXJhY3Rpb25zDQojIyMjIENvZWZmaWNpZW50cyAmIFB2YWx1ZXMgDQotIEludGVyY2VwdCA9IE1lYW4gb2YgUXVhbGl0eSBAIG1lYW4gb2YgTW92aWUgJiBUaGVhdHJlIChpbWFnaW5hcnkpIFtwID0gSXMgdGhlIGludGVyY2VwdCBkaWZmZXJlbnQgZnJvbSAwXQ0KLSBRdWFsaXR5LkMgID0gUXVhbGl0eS5DIHNsb3BlIEAgbWVhbiBvZiBNb3ZpZSAmIFRoZWF0cmUgKGltYWdpbmFyeSkgW3AgPSBJcyB0aGUgTWFpbiBlZmZlY3Qgb2YgcXVhbGl0eSBAIG1lYW4gb2YgTW92aWUgJiBUaGVhdHJlXQ0KLSBMb2NhdGlvbkZUaGVhdHJlID0gVGhyZWF0cmUgZGlmZmVyZW5jZSBmcm9tIGludGVyY2VwdCBbKnAqID0gSXMgdGhlIE1haW4gZWZmZWN0IG9mIExvY2F0aW9uIEAgbWVhbiBvZiBxdWFsaXR5XQ0KLSBRdWFsaXR5LkM6TG9jYXRpb25GVGhlYXRyZT0gUXVhbGl0eS5DIHNsb3BlIGRpZmZlcmVuY2UgYmV0d2VlbiBNb3ZpZSBhbmQgdGhlYXRyZSBbKnAqID0gSXMgdGhlIGludGVyYWN0aW9uXQ0KLSBOb3RlIGFsbCBjb2VmZmljaWVudHMgYXJlIDEvMiBvZiB0aGUgc2l6ZSB0aGV5IHNob3VsZCBiZSEgDQogDQogDQojIyBTaW1wbGUgY29kaW5nIG9mIG91ciBub21pbmFsIHZhcmlhYmxlDQotIFdlIHdpbGwgc3RpbGwgY2VudGVyIHF1YWxpdHkNCi0gVGhpcyBjcmVhdGVzIGEgbW9yZSBBTk9WQS1saWtlIGludGVycHJldGF0aW9uIG9mIHRoZSBpbnRlcmFjdGlvbiwNCiAgICAtIE1vc3QgaW1wb3J0YW50bHkgaXQgZG9lcyBub3Qgc2NyZXcgdXAgb3VyIGNvZWZmaWNpZW50cyBhcyB0aGV5IG1hdGNoIHRoZSBkdW1teSBjb2RlIHZhbHVlcyAod2hpY2ggbWFrZSB0aGUgbW9zdCBzZW5zZSkNCi0gVGhpcyB0aW1lIEkgd2lsbCBoYW5kIGNvZGUgaXQgaW50byBhIGZhY3RvciAoZWFzeSB3aXRoIG9ubHkgMiBsZXZlbHMpDQoNCmBgYHtyfQ0KRW1vdGlvbi5EYXRhLjMkTG9jYXRpb25TPC1hcy5udW1lcmljKEVtb3Rpb24uRGF0YS4zJExvY2F0aW9uKS0uNQ0KTW9kZWwuRTMuUzE8LWxtKEVtb3Rpb24gfiBRdWFsaXR5LkMrTG9jYXRpb25TLCBkYXRhID0gRW1vdGlvbi5EYXRhLjMpDQpNb2RlbC5FMy5TMjwtbG0oRW1vdGlvbiB+IFF1YWxpdHkuQypMb2NhdGlvblMsIGRhdGEgPSBFbW90aW9uLkRhdGEuMykNCmBgYA0KDQojIyMgSW50ZXJwcmV0IFJlZ3Jlc3Npb24NCg0KYGBge3IsIGVjaG89RkFMU0UscmVzdWx0cz0nYXNpcyd9DQpzdGFyZ2F6ZXIoTW9kZWwuRTMuUzEsTW9kZWwuRTMuUzIsdHlwZT0iaHRtbCIsDQogICAgICAgICAgY29sdW1uLmxhYmVscyA9IGMoIk1haW4gRWZmZWN0cyIsICJJbnRlcmFjdGlvbiIpLA0KICAgICAgICAgIGludGVyY2VwdC5ib3R0b20gPSBGQUxTRSwNCiAgICAgICAgICBzaW5nbGUucm93PVRSVUUsIA0KICAgICAgICAgIG5vdGVzLmFwcGVuZCA9IEZBTFNFLA0KICAgICAgICAgIG9taXQuc3RhdD1jKCJzZXIiKSwNCiAgICAgICAgICBzdGFyLmN1dG9mZnMgPSBjKDAuMDUsIDAuMDEsIDAuMDAxKSwNCiAgICAgICAgICBoZWFkZXI9RkFMU0UpDQpgYGANCg0KDQojIyMgTWFpbiBFZmZlY3RzDQoNCiMjIyMgQ29lZmZpY2llbnRzICYgUHZhbHVlcw0KLSBJbnRlcmNlcHQgPSBNZWFuIG9mIFF1YWxpdHkgQCBtZWFuIG9mIE1vdmllICYgVGhlYXRyZSAoaW1hZ2luYXJ5IHRoaW5nKSBbcCA9IElzIHRoZSBpbnRlcmNlcHQgZGlmZmVyZW50IGZyb20gMF0NCi0gUXVhbGl0eS5DICA9IFF1YWxpdHkuQyBzbG9wZSBbcCA9IElzIHNsb3BlIGRpZmZlcmVudCBmcm9tIDBdDQotIExvY2F0aW9uRlRoZWF0cmUgPSBUaHJlYXRyZSBkaWZmZXJlbmNlIGZyb20gMCBbcCA9IElzIG1lYW4gb2YgVGhlYXRyZSBkaWZmZXJlbnQgZnJvbSBtb3ZpZXMgQCBtZWFuIG9mIHF1YWxpdHldDQoNCiMjIyBJbnRlcmFjdGlvbnMNCg0KIyMjIyBDb2VmZmljaWVudHMgJiBQdmFsdWVzIA0KLSBJbnRlcmNlcHQgPSBNZWFuIG9mIFF1YWxpdHkgQCBtZWFuIG9mIE1vdmllICYgVGhlYXRyZSAoaW1hZ2luYXJ5IHRoaW5nKSBbcCA9IElzIHRoZSBpbnRlcmNlcHQgZGlmZmVyZW50IGZyb20gMF0NCi0gUXVhbGl0eS5DICA9IFF1YWxpdHkuQyBzbG9wZSBAIG1lYW4gb2YgTW92aWUgJiBUaGVhdHJlIChpbWFnaW5hcnkgdGhpbmcpIFtwID0gSXMgdGhlIE1haW4gZWZmZWN0IG9mIHF1YWxpdHkgQCBtZWFuIG9mIE1vdmllICYgVGhlYXRyZV0NCi0gTG9jYXRpb25TID0gVGhyZWF0cmUgZGlmZmVyZW5jZSBmcm9tIGludGVyY2VwdCBbcCA9IElzIHRoZSBNYWluIGVmZmVjdCBvZiBMb2NhdGlvbiBAIG1lYW4gb2YgcXVhbGl0eV0NCi0gUXVhbGl0eS5DOkxvY2F0aW9uUz0gUXVhbGl0eS5DIHNsb3BlIGRpZmZlcmVuY2UgYmV0d2VlbiBNb3ZpZSBhbmQgdGhlYXRyZSBbcCA9IElzIHRoZWlyIGFuIGludGVyYWN0aW9uXQ0KLSBOb3RlIGFsbCBjb2VmZmljaWVudHMgYXJlIHRoZWlyIHByb3BlciBzaXplIG5vdyAodG8gbWF0Y2ggdHJ1ZSBkaWZmZXJlbmNlcykNCi0gQmVzdCBvcHRpb24gaXMgb2Z0ZW4gZHVtbXkgb3Igc2ltcGxlLCBkZXZpYXRpb24gaGVyZSBpcyB3ZWlyZCANCg0K