Long and Porturas (2014) examined the effect of multiple stressors on the performance of a saltmarsh plant that is important for ecological restoration. Their focus was the potential for salinity stress to modify the herbivory coming from scale insects, and they experimentally removed scale insects or left them intact (Factor: Scale), on plots with salinity at ambient levels or elevated (Factor: Salinity). The experiment was repeated at two sites chosen to be very different in overall elevation (Factor: Site, a fixed effect in this context) within a marsh in southern California. These three factors form a three-way factorial design, and from each replicate experimental plot (of which there were 7 and 8 at the two sites). Their response variable was the time to senescence of a single stem of the cordgrass Spartina foliosa.

Spartina foliosa. Pacific Southwest Region U.S. Fish and Wildlife Service, Public domain, via Wikimedia Commons

Spartina foliosa. Pacific Southwest Region U.S. Fish and Wildlife Service, Public domain, via Wikimedia Commons

The paper is here

Long, J. D. & Porturas, L. D. (2014). Herbivore impacts on marsh production depend upon a compensatory continuum mediated by salinity stress. PLoS One, 9, e110419.

Preliminaries

First, load the required packages (car, sjstats, afex, pwr); apaTables added for cleaner output

Import longport data file (longport.csv)

longport <- read.csv("../data/longport.csv")
head(longport,10)

Fit model to untransformed data and check residuals

longport.aov <- aov(days~site*salinity*scale, data=longport)
plot(longport.aov)

Residuals fine so examine analysis with untransformed data

summary(longport.aov)
                    Df Sum Sq Mean Sq F value Pr(>F)   
site                 1   6801    6801    7.58 0.0081 **
salinity             1    491     491    0.55 0.4629   
scale                1    450     450    0.50 0.4818   
site:salinity        1    563     563    0.63 0.4319   
site:scale           1    195     195    0.22 0.6427   
salinity:scale       1   1530    1530    1.71 0.1974   
site:salinity:scale  1   5182    5182    5.78 0.0199 * 
Residuals           51  45740     897                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Get Type III SS

longport2 <- Anova(lm(longport.aov), type=3)
longport2
Anova Table (Type III tests)

Response: days
                    Sum Sq Df F value  Pr(>F)    
(Intercept)          80143  1   89.36 8.5e-13 ***
site                     1  1    0.00   0.974    
salinity              6174  1    6.88   0.011 *  
scale                 3590  1    4.00   0.051 .  
site:salinity         4482  1    5.00   0.030 *  
site:scale            1783  1    1.99   0.165    
salinity:scale        6320  1    7.05   0.011 *  
site:salinity:scale   5182  1    5.78   0.020 *  
Residuals            45740 51                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Get effect size measures (sjstats package) - point estimates match SPSS

effectsize(longport2)
Type 3 ANOVAs only give sensible and informative results when covariates are mean-centered and factors are coded with
  orthogonal contrasts (such as those produced by `contr.sum`, `contr.poly`, or `contr.helmert`, but *not* by the default
  `contr.treatment`).
# Effect Size for ANOVA (Type III)

Parameter           | Eta2 (partial) |       95% CI
---------------------------------------------------
site                |       2.04e-05 | [0.00, 1.00]
salinity            |           0.12 | [0.02, 1.00]
scale               |           0.07 | [0.00, 1.00]
site:salinity       |           0.09 | [0.00, 1.00]
site:scale          |           0.04 | [0.00, 1.00]
salinity:scale      |           0.12 | [0.02, 1.00]
site:salinity:scale |           0.10 | [0.01, 1.00]

- One-sided CIs: upper bound fixed at [1.00].

Simple interaction effects - salinity x scale at North

One way to approach this 3-factor interaction is to look at the interaction between two predictors at each level of the third. For this experiment, salinity and scale are biological effects of interest, and site measures whether those effects are stable across space, so it makes sense to examine each site separately.

One way to do this is to analyze each site separately using, e.g. aov:

longportN.aov <- aov(days~salinity*scale, data=longport, subset=c(site=='North'))
summary(longportN.aov)
               Df Sum Sq Mean Sq F value Pr(>F)  
salinity        1   1073    1073    1.11  0.303  
scale           1     14      14    0.01  0.905  
salinity:scale  1   6320    6320    6.53  0.018 *
Residuals      23  22269     968                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

This approach creates a residual MS specific to this data subset. An alternative approach is to use the the original error term from the 3 factor model. Anova() function from car package tests simple main effect against whole model residual.

longportN1.aov <- Anova(lm(longportN.aov), lm(longport.aov), type=3)
longportN1.aov
Anova Table (Type III tests)

Response: days
               Sum Sq Df F value  Pr(>F)    
(Intercept)     80143  1   89.36 8.5e-13 ***
salinity         6174  1    6.88   0.011 *  
scale            3590  1    4.00   0.051 .  
salinity:scale   6320  1    7.05   0.011 *  
Residuals       45740 51                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
effectsize(longportN1.aov)
Type 3 ANOVAs only give sensible and informative results when covariates are mean-centered and factors are coded with
  orthogonal contrasts (such as those produced by `contr.sum`, `contr.poly`, or `contr.helmert`, but *not* by the default
  `contr.treatment`).
# Effect Size for ANOVA (Type III)

Parameter      | Eta2 (partial) |       95% CI
----------------------------------------------
salinity       |           0.12 | [0.02, 1.00]
scale          |           0.07 | [0.00, 1.00]
salinity:scale |           0.12 | [0.02, 1.00]

- One-sided CIs: upper bound fixed at [1.00].

Simple interaction effects - salinity x scale at South

longportS.aov <- aov(days~salinity*scale, data=longport, subset=c(site=='South'))
longportS1.aov <- Anova(lm(longportS.aov), lm(longport.aov), type=3)
longportS1.aov
Anova Table (Type III tests)

Response: days
               Sum Sq Df F value  Pr(>F)    
(Intercept)     92450  1  103.08 7.7e-14 ***
salinity          196  1    0.22    0.64    
scale              12  1    0.01    0.91    
salinity:scale    392  1    0.44    0.51    
Residuals       45740 51                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
effectsize(longportS1.aov)
Type 3 ANOVAs only give sensible and informative results when covariates are mean-centered and factors are coded with
  orthogonal contrasts (such as those produced by `contr.sum`, `contr.poly`, or `contr.helmert`, but *not* by the default
  `contr.treatment`).
# Effect Size for ANOVA (Type III)

Parameter      | Eta2 (partial) |       95% CI
----------------------------------------------
salinity       |       4.27e-03 | [0.00, 1.00]
scale          |       2.68e-04 | [0.00, 1.00]
salinity:scale |       8.50e-03 | [0.00, 1.00]

- One-sided CIs: upper bound fixed at [1.00].

Generate figure

Residual plot

p1<-ggplot(longport.aov, aes(x = longport.aov$fitted.values, y = longport.aov$residuals)) +
geom_point(color=sc, alpha=0.5) +
theme_classic(base_size = 10)+
theme(
axis.text = element_text(colour = ac),
axis.line = element_line(color = ac),
axis.ticks = element_line(color = ac),
)+labs(x = "Predicted", y = "Residuals"
)

p1

Interaction plots

Use emmeans to make file of means and se

emm1<-emmeans(longport.aov, ~site|salinity|scale)
emm2<-as.data.frame(emm1)
emm2
salinity = Ambient, scale = NoScale:
 site  emmean   SE df lower.CL upper.CL
 North  107.0 11.3 51     84.3    129.7
 South  107.5 10.6 51     86.2    128.8

salinity = Enhanced, scale = NoScale:
 site  emmean   SE df lower.CL upper.CL
 North   65.0 11.3 51     42.3     87.7
 South  114.5 10.6 51     93.2    135.8

salinity = Ambient, scale = Scale:
 site  emmean   SE df lower.CL upper.CL
 North   73.7 12.2 51     49.1     98.2
 South  105.7 10.6 51     84.5    127.0

salinity = Enhanced, scale = Scale:
 site  emmean   SE df lower.CL upper.CL
 North   93.0 11.3 51     70.3    115.7
 South   98.7 10.6 51     77.5    120.0

Confidence level used: 0.95 

Separate interaction plots for N and S Means and error bars Use filter to subset data for ggplot

emm3<-subset(emm2,site=="North")
pd=position_dodge(width=0)
p2<-ggplot(emm3,aes(x=salinity,y=emmean,shape=scale, group=scale, color=scale))+
  geom_point(position=pd,aes(shape=scale), size=3,show.legend = FALSE)+
  geom_errorbar(aes(ymin = emmean-SE, ymax = emmean+SE), width=0, position = pd,show.legend = FALSE)+
  geom_line(aes(color=scale), position=pd, size=1.5, show.legend = FALSE)+
  scale_color_uchicago(labels = c("No scale", "Scale"))+
    scale_linetype_manual(values=c("solid", "solid"))+
  labs(x = "Salinity", y = "Days to senescence", title="North Site"
       )+
  ylim(50,150)+
  scale_x_discrete(labels=c("Ambient", "Enhanced"))+
  theme_classic(base_size = 10)+
  theme(
    axis.text.x = element_text(color="black"),
    axis.text.y= element_text(color=ac),
    axis.line = element_line(color = ac),
    axis.ticks = element_line(color = ac),
        )+
  theme(
  legend.position = c(.9, .50),
  legend.justification = c("right", "top"),
  legend.box.just = "right",
  legend.margin = margin(6, 6, 6, 6),
  plot.title = element_text(hjust=0.5),
  legend.title=element_blank()
)
  
p2

Now S site

emm4<-subset(emm2, site=="South")
pd=position_dodge(width=0)
p3<-ggplot(emm4, aes(x=salinity,y=emmean,shape=scale, group=scale, color=scale))+
  geom_point(position=pd,aes(shape=scale), size=3,show.legend = FALSE)+
  geom_errorbar(aes(ymin = emmean-SE, ymax = emmean+SE), width=0, position = pd,show.legend = FALSE)+
  geom_line(aes(color=scale), position=pd, size=1.5)+
  scale_color_uchicago(labels = c("No scale", "Scale"))+
    scale_linetype_manual(values=c("solid", "solid"))+
  labs(x = "Salinity", y = NULL, title="South Site"
       )+
  ylim(50,150)+
  scale_x_discrete(labels=c("Ambient", "Enhanced"))+
  theme_classic(base_size = 10)+
  theme(
    axis.text.x = element_text(color="black"),
    axis.text.y= element_text(color=ac),
    axis.line = element_line(color = ac),
    axis.ticks = element_line(color = ac),
        )+
  theme(
  legend.position = c(.8, .4),
  legend.justification = c("right", "top"),
  legend.box.just = "right",
  legend.margin = margin(6, 6, 6, 6),
  plot.title = element_text(hjust=0.5),
  legend.title=element_blank()
)
  
p3

p1+p2+p3

LS0tCnRpdGxlOiAiUUsgQm94IDcuNSIKCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBmbGF0bHkKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCkxvbmcgYW5kIFBvcnR1cmFzICgyMDE0KSBleGFtaW5lZCB0aGUgZWZmZWN0IG9mIG11bHRpcGxlIHN0cmVzc29ycyBvbiB0aGUgcGVyZm9ybWFuY2Ugb2YgYSBzYWx0bWFyc2ggcGxhbnQgdGhhdCBpcyBpbXBvcnRhbnQgZm9yIGVjb2xvZ2ljYWwgcmVzdG9yYXRpb24uIFRoZWlyIGZvY3VzIHdhcyB0aGUgcG90ZW50aWFsIGZvciBzYWxpbml0eSBzdHJlc3MgdG8gbW9kaWZ5IHRoZSBoZXJiaXZvcnkgY29taW5nIGZyb20gc2NhbGUgaW5zZWN0cywgYW5kIHRoZXkgZXhwZXJpbWVudGFsbHkgcmVtb3ZlZCBzY2FsZSBpbnNlY3RzIG9yIGxlZnQgdGhlbSBpbnRhY3QgKEZhY3RvcjogU2NhbGUpLCBvbiBwbG90cyB3aXRoIHNhbGluaXR5IGF0IGFtYmllbnQgbGV2ZWxzIG9yIGVsZXZhdGVkIChGYWN0b3I6IFNhbGluaXR5KS4gVGhlIGV4cGVyaW1lbnQgd2FzIHJlcGVhdGVkIGF0IHR3byBzaXRlcyBjaG9zZW4gdG8gYmUgdmVyeSBkaWZmZXJlbnQgaW4gb3ZlcmFsbCBlbGV2YXRpb24gKEZhY3RvcjogU2l0ZSwgYSBmaXhlZCBlZmZlY3QgaW4gdGhpcyBjb250ZXh0KSB3aXRoaW4gYSBtYXJzaCBpbiBzb3V0aGVybiBDYWxpZm9ybmlhLiBUaGVzZSB0aHJlZSBmYWN0b3JzIGZvcm0gYSB0aHJlZS13YXkgZmFjdG9yaWFsIGRlc2lnbiwgYW5kIGZyb20gZWFjaCByZXBsaWNhdGUgZXhwZXJpbWVudGFsIHBsb3QgKG9mIHdoaWNoIHRoZXJlIHdlcmUgNyBhbmQgOCBhdCB0aGUgdHdvIHNpdGVzKS4gVGhlaXIgcmVzcG9uc2UgdmFyaWFibGUgd2FzIHRoZSB0aW1lIHRvIHNlbmVzY2VuY2Ugb2YgYSBzaW5nbGUgc3RlbSBvZiB0aGUgY29yZGdyYXNzICpTcGFydGluYSBmb2xpb3NhKi4KClshW1NwYXJ0aW5hIGZvbGlvc2EuIFBhY2lmaWMgU291dGh3ZXN0IFJlZ2lvbiBVLlMuIEZpc2ggYW5kIFdpbGRsaWZlIFNlcnZpY2UsIFB1YmxpYyBkb21haW4sIHZpYSBXaWtpbWVkaWEgQ29tbW9uc10oLi4vbWVkaWEvNjQwcHgtU3BhcnRpbmFfZm9saW9zYS5qcGcpXShodHRwczovL2NvbW1vbnMud2lraW1lZGlhLm9yZy93aWtpL0ZpbGU6U3BhcnRpbmFfZm9saW9zYS5qcGcpCgoqU3BhcnRpbmEgZm9saW9zYSouIFBhY2lmaWMgU291dGh3ZXN0IFJlZ2lvbiBVLlMuIEZpc2ggYW5kIFdpbGRsaWZlIFNlcnZpY2UsIFB1YmxpYyBkb21haW4sIHZpYSBXaWtpbWVkaWEgQ29tbW9ucwoKVGhlIHBhcGVyIGlzIFtoZXJlXShodHRwczpkb2kub3JnLzEwLjEzNzEvam91cm5hbC5wb25lLjAxMTA0MTkpCgpMb25nLCBKLiBELiAmIFBvcnR1cmFzLCBMLiBELiAoMjAxNCkuIEhlcmJpdm9yZSBpbXBhY3RzIG9uIG1hcnNoIHByb2R1Y3Rpb24gZGVwZW5kIHVwb24gYSBjb21wZW5zYXRvcnkgY29udGludXVtIG1lZGlhdGVkIGJ5IHNhbGluaXR5IHN0cmVzcy4gKlBMb1MgT25lKiwgOSwgZTExMDQxOS4KCiMjIyBQcmVsaW1pbmFyaWVzCgpGaXJzdCwgbG9hZCB0aGUgcmVxdWlyZWQgcGFja2FnZXMgKGNhciwgc2pzdGF0cywgYWZleCwgcHdyKTsgYXBhVGFibGVzIGFkZGVkIGZvciBjbGVhbmVyIG91dHB1dAoKYGBge3IgaW5jbHVkZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CnNvdXJjZSgiLi4vUi9saWJyYXJpZXMuUiIpICAgI1RoaXMgaXMgdGhlIGNvbW1vbiBsaWJyYXJ5CmxpYnJhcnkocHdyKQpgYGAKCkltcG9ydCBsb25ncG9ydCBkYXRhIGZpbGUgKGxvbmdwb3J0LmNzdikKCmBgYHtyfQpsb25ncG9ydCA8LSByZWFkLmNzdigiLi4vZGF0YS9sb25ncG9ydC5jc3YiKQpoZWFkKGxvbmdwb3J0LDEwKQpgYGAKCiMjIyBGaXQgbW9kZWwgdG8gdW50cmFuc2Zvcm1lZCBkYXRhIGFuZCBjaGVjayByZXNpZHVhbHMKCmBgYHtyIH0KbG9uZ3BvcnQuYW92IDwtIGFvdihkYXlzfnNpdGUqc2FsaW5pdHkqc2NhbGUsIGRhdGE9bG9uZ3BvcnQpCnBsb3QobG9uZ3BvcnQuYW92KQpgYGAKClJlc2lkdWFscyBmaW5lIHNvIGV4YW1pbmUgYW5hbHlzaXMgd2l0aCB1bnRyYW5zZm9ybWVkIGRhdGEKCmBgYHtyIH0Kc3VtbWFyeShsb25ncG9ydC5hb3YpCmBgYAoKIyMjIEdldCBUeXBlIElJSSBTUwoKYGBge3IgfQpsb25ncG9ydDIgPC0gQW5vdmEobG0obG9uZ3BvcnQuYW92KSwgdHlwZT0zKQpsb25ncG9ydDIKYGBgCgpHZXQgZWZmZWN0IHNpemUgbWVhc3VyZXMgKHNqc3RhdHMgcGFja2FnZSkgLSBwb2ludCBlc3RpbWF0ZXMgbWF0Y2ggU1BTUwoKYGBge3IgfQplZmZlY3RzaXplKGxvbmdwb3J0MikKYGBgCgojIyMgU2ltcGxlIGludGVyYWN0aW9uIGVmZmVjdHMgLSBzYWxpbml0eSB4IHNjYWxlIGF0IE5vcnRoCgpPbmUgd2F5IHRvIGFwcHJvYWNoIHRoaXMgMy1mYWN0b3IgaW50ZXJhY3Rpb24gaXMgdG8gbG9vayBhdCB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiB0d28gcHJlZGljdG9ycyBhdCBlYWNoIGxldmVsIG9mIHRoZSB0aGlyZC4gRm9yIHRoaXMgZXhwZXJpbWVudCwgc2FsaW5pdHkgYW5kIHNjYWxlIGFyZSBiaW9sb2dpY2FsIGVmZmVjdHMgb2YgaW50ZXJlc3QsIGFuZCBzaXRlIG1lYXN1cmVzIHdoZXRoZXIgdGhvc2UgZWZmZWN0cyBhcmUgc3RhYmxlIGFjcm9zcyBzcGFjZSwgc28gaXQgbWFrZXMgc2Vuc2UgdG8gZXhhbWluZSBlYWNoIHNpdGUgc2VwYXJhdGVseS4KCk9uZSB3YXkgdG8gZG8gdGhpcyBpcyB0byBhbmFseXplIGVhY2ggc2l0ZSBzZXBhcmF0ZWx5IHVzaW5nLCBlLmcuIGFvdjoKCmBgYHtyIH0KbG9uZ3BvcnROLmFvdiA8LSBhb3YoZGF5c35zYWxpbml0eSpzY2FsZSwgZGF0YT1sb25ncG9ydCwgc3Vic2V0PWMoc2l0ZT09J05vcnRoJykpCnN1bW1hcnkobG9uZ3BvcnROLmFvdikKYGBgCgpUaGlzIGFwcHJvYWNoIGNyZWF0ZXMgYSByZXNpZHVhbCBNUyBzcGVjaWZpYyB0byB0aGlzIGRhdGEgc3Vic2V0LiBBbiBhbHRlcm5hdGl2ZSBhcHByb2FjaCBpcyB0byB1c2UgdGhlIHRoZSBvcmlnaW5hbCBlcnJvciB0ZXJtIGZyb20gdGhlIDMgZmFjdG9yIG1vZGVsLiBBbm92YSgpIGZ1bmN0aW9uIGZyb20gY2FyIHBhY2thZ2UgdGVzdHMgc2ltcGxlIG1haW4gZWZmZWN0IGFnYWluc3Qgd2hvbGUgbW9kZWwgcmVzaWR1YWwuCgpgYGB7ciB9Cmxvbmdwb3J0TjEuYW92IDwtIEFub3ZhKGxtKGxvbmdwb3J0Ti5hb3YpLCBsbShsb25ncG9ydC5hb3YpLCB0eXBlPTMpCmxvbmdwb3J0TjEuYW92CmVmZmVjdHNpemUobG9uZ3BvcnROMS5hb3YpCmBgYAoKIyMjIFNpbXBsZSBpbnRlcmFjdGlvbiBlZmZlY3RzIC0gc2FsaW5pdHkgeCBzY2FsZSBhdCBTb3V0aAoKYGBge3IgfQpsb25ncG9ydFMuYW92IDwtIGFvdihkYXlzfnNhbGluaXR5KnNjYWxlLCBkYXRhPWxvbmdwb3J0LCBzdWJzZXQ9YyhzaXRlPT0nU291dGgnKSkKbG9uZ3BvcnRTMS5hb3YgPC0gQW5vdmEobG0obG9uZ3BvcnRTLmFvdiksIGxtKGxvbmdwb3J0LmFvdiksIHR5cGU9MykKbG9uZ3BvcnRTMS5hb3YKZWZmZWN0c2l6ZShsb25ncG9ydFMxLmFvdikKYGBgCgojIyBHZW5lcmF0ZSBmaWd1cmUKYGBge3IgaW5jbHVkZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CnNvdXJjZSgiLi4vUi9hcHBlYXJhbmNlLlIiKSAgICNUaGlzIGlzIHRoZSBjb21tb24gbGlicmFyeSBvZiBncmFwaGljcyB0d2Vha3MsIGRlZmluaW5nIHRoZSBxayB0aGVtZQpgYGAKCiMjIyBSZXNpZHVhbCBwbG90CgpgYGB7cn0KcDE8LWdncGxvdChsb25ncG9ydC5hb3YsIGFlcyh4ID0gbG9uZ3BvcnQuYW92JGZpdHRlZC52YWx1ZXMsIHkgPSBsb25ncG9ydC5hb3YkcmVzaWR1YWxzKSkgKwpnZW9tX3BvaW50KGNvbG9yPXNjLCBhbHBoYT0wLjUpICsKdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxMCkrCnRoZW1lKApheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gYWMpLApheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSBhYyksCmF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3IgPSBhYyksCikrbGFicyh4ID0gIlByZWRpY3RlZCIsIHkgPSAiUmVzaWR1YWxzIgopCgpwMQoKYGBgCgojIyMgSW50ZXJhY3Rpb24gcGxvdHMKClVzZSBlbW1lYW5zIHRvIG1ha2UgZmlsZSBvZiBtZWFucyBhbmQgc2UKCmBgYHtyfQplbW0xPC1lbW1lYW5zKGxvbmdwb3J0LmFvdiwgfnNpdGV8c2FsaW5pdHl8c2NhbGUpCmVtbTI8LWFzLmRhdGEuZnJhbWUoZW1tMSkKZW1tMgpgYGAKClNlcGFyYXRlIGludGVyYWN0aW9uIHBsb3RzIGZvciBOIGFuZCBTIE1lYW5zIGFuZCBlcnJvciBiYXJzIFVzZSBmaWx0ZXIgdG8gc3Vic2V0IGRhdGEgZm9yIGdncGxvdAoKYGBge3J9CmVtbTM8LXN1YnNldChlbW0yLHNpdGU9PSJOb3J0aCIpCnBkPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTApCnAyPC1nZ3Bsb3QoZW1tMyxhZXMoeD1zYWxpbml0eSx5PWVtbWVhbixzaGFwZT1zY2FsZSwgZ3JvdXA9c2NhbGUsIGNvbG9yPXNjYWxlKSkrCiAgZ2VvbV9wb2ludChwb3NpdGlvbj1wZCxhZXMoc2hhcGU9c2NhbGUpLCBzaXplPTMsc2hvdy5sZWdlbmQgPSBGQUxTRSkrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGVtbWVhbi1TRSwgeW1heCA9IGVtbWVhbitTRSksIHdpZHRoPTAsIHBvc2l0aW9uID0gcGQsc2hvdy5sZWdlbmQgPSBGQUxTRSkrCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1zY2FsZSksIHBvc2l0aW9uPXBkLCBzaXplPTEuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkrCiAgc2NhbGVfY29sb3JfdWNoaWNhZ28obGFiZWxzID0gYygiTm8gc2NhbGUiLCAiU2NhbGUiKSkrCiAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzPWMoInNvbGlkIiwgInNvbGlkIikpKwogIGxhYnMoeCA9ICJTYWxpbml0eSIsIHkgPSAiRGF5cyB0byBzZW5lc2NlbmNlIiwgdGl0bGU9Ik5vcnRoIFNpdGUiCiAgICAgICApKwogIHlsaW0oNTAsMTUwKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJBbWJpZW50IiwgIkVuaGFuY2VkIikpKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTApKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiksCiAgICBheGlzLnRleHQueT0gZWxlbWVudF90ZXh0KGNvbG9yPWFjKSwKICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvciA9IGFjKSwKICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3IgPSBhYyksCiAgICAgICAgKSsKICB0aGVtZSgKICBsZWdlbmQucG9zaXRpb24gPSBjKC45LCAuNTApLAogIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygicmlnaHQiLCAidG9wIiksCiAgbGVnZW5kLmJveC5qdXN0ID0gInJpZ2h0IiwKICBsZWdlbmQubWFyZ2luID0gbWFyZ2luKDYsIDYsIDYsIDYpLAogIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41KSwKICBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpCikKICAKcDIKYGBgCgpOb3cgUyBzaXRlCgpgYGB7cn0KZW1tNDwtc3Vic2V0KGVtbTIsIHNpdGU9PSJTb3V0aCIpCnBkPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTApCnAzPC1nZ3Bsb3QoZW1tNCwgYWVzKHg9c2FsaW5pdHkseT1lbW1lYW4sc2hhcGU9c2NhbGUsIGdyb3VwPXNjYWxlLCBjb2xvcj1zY2FsZSkpKwogIGdlb21fcG9pbnQocG9zaXRpb249cGQsYWVzKHNoYXBlPXNjYWxlKSwgc2l6ZT0zLHNob3cubGVnZW5kID0gRkFMU0UpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBlbW1lYW4tU0UsIHltYXggPSBlbW1lYW4rU0UpLCB3aWR0aD0wLCBwb3NpdGlvbiA9IHBkLHNob3cubGVnZW5kID0gRkFMU0UpKwogIGdlb21fbGluZShhZXMoY29sb3I9c2NhbGUpLCBwb3NpdGlvbj1wZCwgc2l6ZT0xLjUpKwogIHNjYWxlX2NvbG9yX3VjaGljYWdvKGxhYmVscyA9IGMoIk5vIHNjYWxlIiwgIlNjYWxlIikpKwogICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcz1jKCJzb2xpZCIsICJzb2xpZCIpKSsKICBsYWJzKHggPSAiU2FsaW5pdHkiLCB5ID0gTlVMTCwgdGl0bGU9IlNvdXRoIFNpdGUiCiAgICAgICApKwogIHlsaW0oNTAsMTUwKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJBbWJpZW50IiwgIkVuaGFuY2VkIikpKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTApKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiksCiAgICBheGlzLnRleHQueT0gZWxlbWVudF90ZXh0KGNvbG9yPWFjKSwKICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvciA9IGFjKSwKICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3IgPSBhYyksCiAgICAgICAgKSsKICB0aGVtZSgKICBsZWdlbmQucG9zaXRpb24gPSBjKC44LCAuNCksCiAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKCJyaWdodCIsICJ0b3AiKSwKICBsZWdlbmQuYm94Lmp1c3QgPSAicmlnaHQiLAogIGxlZ2VuZC5tYXJnaW4gPSBtYXJnaW4oNiwgNiwgNiwgNiksCiAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUpLAogIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkKKQogIApwMwpgYGAKCmBgYHtyfQpwMStwMitwMwpgYGAK