This is the R code to the manuscript
Deciduous tundra shrubs shift toward more acquisitive light absorption strategy under climate change treatments
by R. J. Heim, M. Iturrate-Garcia, M. Reji Chacko, S. Karsanaev, T. C. Maximov, M. M. P. D. Heijmans, G. Schaepman-Strub

Data preparation

lops_salp = read.csv("FAPAR_salix.csv")
lops_salp$species = "salix"
lops_betn = read.csv("FAPAR_betula.csv")
lops_betn$species = "betula"
lops = as.data.frame(rbind(lops_salp, lops_betn))
agg_final = read.csv("WE_traits_all.csv")
agg_final = subset(agg_final, (betula == "Y" | salix == "Y"), select = c(blk, plt, ind, betula, cable, heating, ftr, LNC, LPC, CN_ratio, NP_ratio,LA, SLA, LDMC, LA, LMA1, LMA2))
agg_final$thickness = 1/(agg_final$SLA*agg_final$LDMC)
agg_final$LMA = (agg_final$LMA1+agg_final$LMA2)/2
agg_final$species[agg_final$betula == "Y"] = "betula"
agg_final$species[agg_final$betula == "N"] = "salix"
agg_final$Treatment = agg_final$ftr
agg_final$Plot = agg_final$plt
agg_final <- merge(agg_final, lops, by=c("species","Treatment", "Plot"))
agg_final<-as.data.frame(aggregate(cbind(FAPAR, thickness, SLA, LMA,LNC, LPC, LDMC,CN_ratio,NP_ratio, LA) ~ 1 + 
                                     Plot + blk + species + cable + heating + ftr, data=agg_final, FUN=mean))
agg_final$heat_treatment<-as.factor(paste(agg_final$heating, agg_final$cable))
agg_final$fert_treatment<-as.factor(paste(agg_final$ftr))
agg_final$species<-as.factor(paste(agg_final$species))

load packages

library(igraph)
library(brms)
library(rstan)
library(DHARMa)
library(ggplot2)
library(bayesplot)
library(ggExtra)
library(data.table)
library(png)
library(grid)

Model preparation

Models that allow group level variance parameters to covary across traits (1| p |blk)

agg_final$scale_FAPAR<-scale(agg_final$FAPAR)
agg_final$scale_thickness<-scale(agg_final$thickness)
agg_final$scale_SLA<-scale(agg_final$SLA)
agg_final$scale_LDMC<-scale(agg_final$LDMC)
agg_final$scale_LNC<-scale(agg_final$LNC)
agg_final$scale_LPC<-scale(agg_final$LPC)
agg_final$scale_CN_ratio<-scale(agg_final$CN_ratio)
agg_final$scale_NP_ratio<-scale(agg_final$NP_ratio)
agg_final$scale_LA<-scale(agg_final$LA)
agg_final$scale_LMA<-scale(agg_final$LMA)

Model for complete dataset

mod_fapar_cor4<- brm(bf(mvbind(scale_FAPAR,scale_thickness,
                               scale_SLA,scale_LMA,scale_LA,scale_LDMC,scale_LNC,scale_LPC,scale_CN_ratio,
                               scale_NP_ratio) ~ 1 + species+
                          (1| p |blk),
                        (sigma ~ species)) + 
                       set_rescor(TRUE),
                     family = student(),
                     data   = agg_final, 
                     iter   = 4000, 
                     warmup = 2000,
                     chains = 4,
                     control=list(adapt_delta=0.99,max_treedepth=15)
)
mod_fapar_cor4
summary(mod_fapar_cor4)$rescor_pars


#plot(mod_fapar_cor4)
##pp_check(mod_fapar_cor4)
##pp_check(mod_fapar_cor4, type = "ecdf_overlay")

hypothesis test if correlation >0

post<-posterior_samples(mod_fapar_cor4)
hypothesis(post, "rescor__scaleFAPAR__scalethickness > 0") #0.92 
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
hypothesis(post, "rescor__scaleFAPAR__scaleSLA > 0") #0.51 
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
hypothesis(post, "rescor__scaleFAPAR__scaleLMA > 0") #0.54
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
hypothesis(post, "rescor__scaleFAPAR__scaleLA > 0") #0.88 
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
hypothesis(post, "rescor__scaleFAPAR__scaleLDMC > 0") #0.18     
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
hypothesis(post, "rescor__scaleFAPAR__scaleLNC > 0") #1
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
hypothesis(post, "rescor__scaleFAPAR__scaleLPC > 0") #0.98
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
hypothesis(post, "rescor__scaleFAPAR__scaleCNratio > 0") #0.00
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
hypothesis(post, "rescor__scaleFAPAR__scaleNPratio > 0") #0.28
Hypothesis Tests for class :
---
'CI': 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
'*': For one-sided hypotheses, the posterior probability exceeds 95%;
for two-sided hypotheses, the value tested against lies outside the 95%-CI.
Posterior probabilities of point hypotheses assume equal prior probabilities.
###get rescor summary
#all
library(data.table)
ar_mod_fapar_cor4<-as.array(summary(mod_fapar_cor4))
resc_mod_fapar_cor4<-ar_mod_fapar_cor4$rescor_pars
resc_mod_fapar_cor4_F<- resc_mod_fapar_cor4[row.names(resc_mod_fapar_cor4) %like% "FAPAR", ]
resc_mod_fapar_cor4_F$y <- c("Thickness","SLA","LMA","LA","LDMC" ,"LNC","LPC","CN ratio","NP ratio")
resc_mod_fapar_cor4_F$y
resc_mod_fapar_cor4_F$lower<-resc_mod_fapar_cor4_F[,3]
resc_mod_fapar_cor4_F$upper<-resc_mod_fapar_cor4_F[,4]
resc_mod_fapar_cor4_F

resc_mod_fapar_cor4_F$facet<-"Both shrub species"
resc_mod_fapar_cor4_F$y <- factor(resc_mod_fapar_cor4_F$y,levels=c("NP ratio","CN ratio","LPC","LNC","LDMC" ,"LA","LMA","SLA","Thickness"))
plot_cor4<-ggplot(data=resc_mod_fapar_cor4_F, aes(x = Estimate, y = y))+
  labs(y="")+
  labs(x="")+
  xlim(c(-0.9,0.9))+
  facet_grid(~facet)+
  geom_vline(xintercept = 0,col="black") +
  geom_linerange(data=resc_mod_fapar_cor4_F, aes(xmin = lower, xmax=upper,y = y,col=Estimate))+
  geom_point(data=resc_mod_fapar_cor4_F, aes(x = Estimate, y = y,col=Estimate))+
  scale_color_gradient2(low="blue",mid="grey60",high="#C90076")+
  theme_bw()+
  theme(legend.position="n")+
  guides(colour = guide_legend(override.aes = list(alpha=1)))+
  theme(axis.line = element_line(colour = "black"),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_blank(),
        strip.text = element_text(face = "italic"))+
  theme(plot.margin = unit(c(0.1,0.1,0.1, 0.1), "cm"))
plot_cor4

Models for species subsets

bet<-subset(agg_final,species=="betula")
sal<-subset(agg_final,species=="salix")

mod_fapar_bet<- brm(bf(mvbind(scale_FAPAR,scale_thickness,
                              scale_SLA,scale_LMA,scale_LA,scale_LDMC,scale_LNC,scale_LPC,scale_CN_ratio,
                              scale_NP_ratio) ~ 1 +
                         (1| p |blk)) + 
                      set_rescor(TRUE),
                    family = student(),
                    data   = bet, 
                    iter   = 4000, 
                    warmup = 2000,
                    chains = 4,
                    control=list(adapt_delta=0.99,max_treedepth=15)
)
mod_fapar_bet
#plot(mod_fapar_bet)
##pp_check(mod_fapar_bet)
##pp_check(mod_fapar_bet, type = "ecdf_overlay")
## hypothesis test if correlation >0 Betula nana
post<-posterior_samples(mod_fapar_bet)
hypothesis(post, "rescor__scaleFAPAR__scalethickness > 0") #0.64  
hypothesis(post, "rescor__scaleFAPAR__scaleSLA > 0") #0.66
hypothesis(post, "rescor__scaleFAPAR__scaleLMA > 0") #0.27
hypothesis(post, "rescor__scaleFAPAR__scaleLA > 0") #0.48
hypothesis(post, "rescor__scaleFAPAR__scaleLDMC > 0") #0.38     
hypothesis(post, "rescor__scaleFAPAR__scaleLNC > 0") #0.99
hypothesis(post, "rescor__scaleFAPAR__scaleLPC > 0") #0.97
hypothesis(post, "rescor__scaleFAPAR__scaleCNratio > 0") #0.02 
hypothesis(post, "rescor__scaleFAPAR__scaleNPratio > 0") #0.03
###get rescor summary
#all
library(data.table)
ar_mod_fapar_bet<-as.array(summary(mod_fapar_bet))
resc_mod_fapar_bet<-ar_mod_fapar_bet$rescor_pars
resc_mod_fapar_bet_F<- resc_mod_fapar_bet[row.names(resc_mod_fapar_bet) %like% "FAPAR", ]
resc_mod_fapar_bet_F$y <- c("Thickness","SLA","LMA","LA","LDMC" ,"LNC","LPC","CN ratio","NP ratio")
resc_mod_fapar_bet_F$y
resc_mod_fapar_bet_F$lower<-resc_mod_fapar_bet_F[,3]
resc_mod_fapar_bet_F$upper<-resc_mod_fapar_bet_F[,4]
resc_mod_fapar_bet_F

resc_mod_fapar_bet_F$facet<-"B. nana"
resc_mod_fapar_bet_F$y <- factor(resc_mod_fapar_bet_F$y,levels=c("NP ratio","CN ratio","LPC","LNC","LDMC" ,"LA","LMA","SLA","Thickness"))
plot_corbet<-ggplot(data=resc_mod_fapar_bet_F, aes(x = Estimate, y = y))+
  labs(y="")+
  labs(x="")+
  xlim(c(-0.9,0.9))+
  facet_grid(~facet)+
  geom_vline(xintercept = 0,col="black") +
  geom_linerange(data=resc_mod_fapar_bet_F, aes(xmin = lower, xmax=upper,y = y,col=Estimate))+
  geom_point(data=resc_mod_fapar_bet_F, aes(x = Estimate, y = y,col=Estimate))+
  scale_color_gradient2(low="blue",mid="grey60",high="#C90076")+
  theme_bw()+
  theme(legend.position="n")+
  guides(colour = guide_legend(override.aes = list(alpha=1)))+
  theme(axis.line = element_line(colour = "black"),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_blank(),
        strip.text = element_text(face = "italic"))+
  theme(plot.margin = unit(c(0.1,0.1,0.1, 0.1), "cm"))
plot_corbet


mod_fapar_sal<- brm(bf(mvbind(scale_FAPAR,scale_thickness,
                              scale_SLA,scale_LMA,scale_LA,scale_LDMC,scale_LNC,scale_LPC,scale_CN_ratio,
                              scale_NP_ratio) ~ 1 + 
                         (1| p |blk)) + 
                      set_rescor(TRUE),
                    family = student(),
                    data   = sal, 
                    iter   = 4000, 
                    warmup = 2000,
                    chains = 4,
                    control=list(adapt_delta=0.99,max_treedepth=15)
)

hypothesis test if correlation >0 Salix pulchra

post<-posterior_samples(mod_fapar_sal)
hypothesis(post, "rescor__scaleFAPAR__scalethickness > 0") #0.88   
hypothesis(post, "rescor__scaleFAPAR__scaleSLA > 0") #0.36
hypothesis(post, "rescor__scaleFAPAR__scaleLMA > 0") #0.54 
hypothesis(post, "rescor__scaleFAPAR__scaleLA > 0") # 0.93
hypothesis(post, "rescor__scaleFAPAR__scaleLDMC > 0") #0.3  
hypothesis(post, "rescor__scaleFAPAR__scaleLNC > 0") #0.99
hypothesis(post, "rescor__scaleFAPAR__scaleLPC > 0") #0.54
hypothesis(post, "rescor__scaleFAPAR__scaleCNratio > 0") #0.02
hypothesis(post, "rescor__scaleFAPAR__scaleNPratio > 0") # 0.87
###get rescor summary
#all
library(data.table)
ar_mod_fapar_sal<-as.array(summary(mod_fapar_sal))
resc_mod_fapar_sal<-ar_mod_fapar_sal$rescor_pars
resc_mod_fapar_sal_F<- resc_mod_fapar_sal[row.names(resc_mod_fapar_sal) %like% "FAPAR", ]
resc_mod_fapar_sal_F$y <- c("Thickness","SLA","LMA","LA","LDMC" ,"LNC","LPC","CN ratio","NP ratio")
resc_mod_fapar_sal_F$y
resc_mod_fapar_sal_F$lower<-resc_mod_fapar_sal_F[,3]
resc_mod_fapar_sal_F$upper<-resc_mod_fapar_sal_F[,4]
resc_mod_fapar_sal_F

resc_mod_fapar_sal_F$facet<-"S. pulchra"
resc_mod_fapar_sal_F$y <- factor(resc_mod_fapar_sal_F$y,levels=c("NP ratio","CN ratio","LPC","LNC","LDMC" ,"LA","LMA","SLA","Thickness"))
resc_mod_fapar_sal_F$y
plot_corsal<-ggplot(data=resc_mod_fapar_sal_F, aes(x = Estimate, y = y))+
  labs(y="")+
  labs(x="")+
  xlim(c(-0.9,0.9))+
  facet_grid(~facet)+
  geom_vline(xintercept = 0,col="black") +
  geom_linerange(data=resc_mod_fapar_sal_F, aes(xmin = lower, xmax=upper,y = y,col=Estimate))+
  geom_point(data=resc_mod_fapar_sal_F, aes(x = Estimate, y = y,col=Estimate))+
  scale_color_gradient2(low="blue",mid="grey60",high="#C90076")+
  theme_bw()+
  theme(legend.position="n")+
  guides(colour = guide_legend(override.aes = list(alpha=1)))+
  theme(axis.line = element_line(colour = "black"),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_blank(),
        strip.text = element_text(face = "italic"))+
  theme(plot.margin = unit(c(0.1,0.1,0.1, 0.1), "cm"))
plot_corsal

Preparation for Plots

###plots
img_betula <- readPNG("betula.png")
g_betula <- rasterGrob(img_betula, interpolate=TRUE)
img_salix <- readPNG("salix.png")
g_salix <- rasterGrob(img_salix, interpolate=TRUE)
img_fert <- readPNG("fert.png")
g_fert <- rasterGrob(img_fert, interpolate=TRUE)
img_nofert <- readPNG("nofert.png")
g_nofert <- rasterGrob(img_nofert, interpolate=TRUE)
img_heat <- readPNG("heat.png")
g_heat <- rasterGrob(img_heat, interpolate=TRUE)
img_noheat <- readPNG("noheat.png")
g_noheat <- rasterGrob(img_noheat, interpolate=TRUE)
img_control <- readPNG("control.png")
g_control <- rasterGrob(img_control, interpolate=TRUE)
annotation_custom2 <- 
  function (grob, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, data){ layer(data = data, stat = StatIdentity, position = PositionIdentity, 
                                                                                 geom = ggplot2:::GeomCustomAnn,
                                                                                 inherit.aes = TRUE, params = list(grob = grob, 
                                                                                                                   xmin = xmin, xmax = xmax, 
                                                                                                                   ymin = ymin, ymax = ymax))}
#betula
a1 = annotation_custom2(rasterGrob(img_betula, interpolate=TRUE), xmin=-0.9, xmax=-0.5, ymin=8.5, ymax=9.5, data=resc_mod_fapar_bet_F[1,])
plot_cor2_fin<-plot_corbet + a1
plot_cor2_fin

#plot3
a2 = annotation_custom2(rasterGrob(img_salix, interpolate=TRUE), xmin=-0.9, xmax=-0.5, ymin=8.5, ymax=9.5, data=resc_mod_fapar_sal_F[1,])
plot_cor3_fin<-plot_corsal + a2
plot_cor3_fin

#plot4
plot_cor4

a3 = annotation_custom2(rasterGrob(img_betula, interpolate=TRUE), xmin=-0.9, xmax=-0.5, ymin=8.5, ymax=9.5, data=resc_mod_fapar_cor4_F[1,])
a4 = annotation_custom2(rasterGrob(img_salix, interpolate=TRUE), xmin=-0.55, xmax=-0.15, ymin=8.2, ymax=9.2, data=resc_mod_fapar_cor4_F[1,])
plot_cor4_fin<-plot_cor4 + a4 + a3
plot_cor4_fin

combine plots

library(cowplot)
xlab <- ggdraw() + 
  draw_label("Correlation",  hjust = -0.04,  vjust = -0.5,size=10)

all1<-plot_grid(plot_cor4_fin,plot_cor2_fin,plot_cor3_fin,labels=c("A","B", "C"),ncol=3)
all1

png(file="plot_cor_final.png", width=18, height=8, units="cm", pointsize=12,res=600)
all1
dev.off() 
LS0tCnRpdGxlOiAiRkFQQVIgY29ycmVsYXRpb25zIHVuZGVyIHdhcm0gYW5kIGZlcnQgZWZmZWN0cyIKYXV0aG9yOiAiUmFtb25hIEhlaW0iCmRhdGU6ICIyMDIyLTEyLTA5IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCgpUaGlzIGlzIHRoZSBSIGNvZGUgdG8gdGhlIG1hbnVzY3JpcHQgIAogICpEZWNpZHVvdXMgdHVuZHJhIHNocnVicyBzaGlmdCB0b3dhcmQgbW9yZSBhY3F1aXNpdGl2ZSBsaWdodCBhYnNvcnB0aW9uIHN0cmF0ZWd5IHVuZGVyIGNsaW1hdGUgY2hhbmdlIHRyZWF0bWVudHMqICAKICBieSBSLiBKLiBIZWltLCBNLiBJdHVycmF0ZS1HYXJjaWEsIE0uIFJlamkgQ2hhY2tvLCBTLiBLYXJzYW5hZXYsIFQuIEMuIE1heGltb3YsIE0uIE0uIFAuIEQuIEhlaWptYW5zLCBHLiBTY2hhZXBtYW4tU3RydWIKCiMjIERhdGEgcHJlcGFyYXRpb24KYGBge3IscmVzdWx0cz0iaGlkZSIsIG1lc3NhZ2U9RkFMU0Usd2FybmluZyA9IEZBTFNFfQpsb3BzX3NhbHAgPSByZWFkLmNzdigiRkFQQVJfc2FsaXguY3N2IikKbG9wc19zYWxwJHNwZWNpZXMgPSAic2FsaXgiCmxvcHNfYmV0biA9IHJlYWQuY3N2KCJGQVBBUl9iZXR1bGEuY3N2IikKbG9wc19iZXRuJHNwZWNpZXMgPSAiYmV0dWxhIgpsb3BzID0gYXMuZGF0YS5mcmFtZShyYmluZChsb3BzX3NhbHAsIGxvcHNfYmV0bikpCmFnZ19maW5hbCA9IHJlYWQuY3N2KCJXRV90cmFpdHNfYWxsLmNzdiIpCmFnZ19maW5hbCA9IHN1YnNldChhZ2dfZmluYWwsIChiZXR1bGEgPT0gIlkiIHwgc2FsaXggPT0gIlkiKSwgc2VsZWN0ID0gYyhibGssIHBsdCwgaW5kLCBiZXR1bGEsIGNhYmxlLCBoZWF0aW5nLCBmdHIsIExOQywgTFBDLCBDTl9yYXRpbywgTlBfcmF0aW8sTEEsIFNMQSwgTERNQywgTEEsIExNQTEsIExNQTIpKQphZ2dfZmluYWwkdGhpY2tuZXNzID0gMS8oYWdnX2ZpbmFsJFNMQSphZ2dfZmluYWwkTERNQykKYWdnX2ZpbmFsJExNQSA9IChhZ2dfZmluYWwkTE1BMSthZ2dfZmluYWwkTE1BMikvMgphZ2dfZmluYWwkc3BlY2llc1thZ2dfZmluYWwkYmV0dWxhID09ICJZIl0gPSAiYmV0dWxhIgphZ2dfZmluYWwkc3BlY2llc1thZ2dfZmluYWwkYmV0dWxhID09ICJOIl0gPSAic2FsaXgiCmFnZ19maW5hbCRUcmVhdG1lbnQgPSBhZ2dfZmluYWwkZnRyCmFnZ19maW5hbCRQbG90ID0gYWdnX2ZpbmFsJHBsdAphZ2dfZmluYWwgPC0gbWVyZ2UoYWdnX2ZpbmFsLCBsb3BzLCBieT1jKCJzcGVjaWVzIiwiVHJlYXRtZW50IiwgIlBsb3QiKSkKYWdnX2ZpbmFsPC1hcy5kYXRhLmZyYW1lKGFnZ3JlZ2F0ZShjYmluZChGQVBBUiwgdGhpY2tuZXNzLCBTTEEsIExNQSxMTkMsIExQQywgTERNQyxDTl9yYXRpbyxOUF9yYXRpbywgTEEpIH4gMSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGxvdCArIGJsayArIHNwZWNpZXMgKyBjYWJsZSArIGhlYXRpbmcgKyBmdHIsIGRhdGE9YWdnX2ZpbmFsLCBGVU49bWVhbikpCmFnZ19maW5hbCRoZWF0X3RyZWF0bWVudDwtYXMuZmFjdG9yKHBhc3RlKGFnZ19maW5hbCRoZWF0aW5nLCBhZ2dfZmluYWwkY2FibGUpKQphZ2dfZmluYWwkZmVydF90cmVhdG1lbnQ8LWFzLmZhY3RvcihwYXN0ZShhZ2dfZmluYWwkZnRyKSkKYWdnX2ZpbmFsJHNwZWNpZXM8LWFzLmZhY3RvcihwYXN0ZShhZ2dfZmluYWwkc3BlY2llcykpCmBgYAoKIyMgbG9hZCBwYWNrYWdlcwpgYGB7cixyZXN1bHRzPSJoaWRlIiwgbWVzc2FnZT1GQUxTRSx3YXJuaW5nID0gRkFMU0V9CmxpYnJhcnkoaWdyYXBoKQpsaWJyYXJ5KGJybXMpCmxpYnJhcnkocnN0YW4pCmxpYnJhcnkoREhBUk1hKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoYmF5ZXNwbG90KQpsaWJyYXJ5KGdnRXh0cmEpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShwbmcpCmxpYnJhcnkoZ3JpZCkKYGBgCgoKIyMgTW9kZWwgcHJlcGFyYXRpb24KTW9kZWxzIHRoYXQgYWxsb3cgZ3JvdXAgbGV2ZWwgdmFyaWFuY2UgcGFyYW1ldGVycyB0byBjb3ZhcnkgYWNyb3NzIHRyYWl0cyAoMXwgcCB8YmxrKQoKYGBge3IscmVzdWx0cz0iaGlkZSIsIG1lc3NhZ2U9RkFMU0Usd2FybmluZyA9IEZBTFNFfQphZ2dfZmluYWwkc2NhbGVfRkFQQVI8LXNjYWxlKGFnZ19maW5hbCRGQVBBUikKYWdnX2ZpbmFsJHNjYWxlX3RoaWNrbmVzczwtc2NhbGUoYWdnX2ZpbmFsJHRoaWNrbmVzcykKYWdnX2ZpbmFsJHNjYWxlX1NMQTwtc2NhbGUoYWdnX2ZpbmFsJFNMQSkKYWdnX2ZpbmFsJHNjYWxlX0xETUM8LXNjYWxlKGFnZ19maW5hbCRMRE1DKQphZ2dfZmluYWwkc2NhbGVfTE5DPC1zY2FsZShhZ2dfZmluYWwkTE5DKQphZ2dfZmluYWwkc2NhbGVfTFBDPC1zY2FsZShhZ2dfZmluYWwkTFBDKQphZ2dfZmluYWwkc2NhbGVfQ05fcmF0aW88LXNjYWxlKGFnZ19maW5hbCRDTl9yYXRpbykKYWdnX2ZpbmFsJHNjYWxlX05QX3JhdGlvPC1zY2FsZShhZ2dfZmluYWwkTlBfcmF0aW8pCmFnZ19maW5hbCRzY2FsZV9MQTwtc2NhbGUoYWdnX2ZpbmFsJExBKQphZ2dfZmluYWwkc2NhbGVfTE1BPC1zY2FsZShhZ2dfZmluYWwkTE1BKQpgYGAKCiMjIE1vZGVsIGZvciBjb21wbGV0ZSBkYXRhc2V0CmBgYHtyLHJlc3VsdHM9ImhpZGUiLCBtZXNzYWdlPUZBTFNFLHdhcm5pbmcgPSBGQUxTRX0KbW9kX2ZhcGFyX2NvcjQ8LSBicm0oYmYobXZiaW5kKHNjYWxlX0ZBUEFSLHNjYWxlX3RoaWNrbmVzcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX1NMQSxzY2FsZV9MTUEsc2NhbGVfTEEsc2NhbGVfTERNQyxzY2FsZV9MTkMsc2NhbGVfTFBDLHNjYWxlX0NOX3JhdGlvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfTlBfcmF0aW8pIH4gMSArIHNwZWNpZXMrCiAgICAgICAgICAgICAgICAgICAgICAgICAgKDF8IHAgfGJsayksCiAgICAgICAgICAgICAgICAgICAgICAgIChzaWdtYSB+IHNwZWNpZXMpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHNldF9yZXNjb3IoVFJVRSksCiAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IHN0dWRlbnQoKSwKICAgICAgICAgICAgICAgICAgICAgZGF0YSAgID0gYWdnX2ZpbmFsLCAKICAgICAgICAgICAgICAgICAgICAgaXRlciAgID0gNDAwMCwgCiAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsCiAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsCiAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2w9bGlzdChhZGFwdF9kZWx0YT0wLjk5LG1heF90cmVlZGVwdGg9MTUpCikKbW9kX2ZhcGFyX2NvcjQKc3VtbWFyeShtb2RfZmFwYXJfY29yNCkkcmVzY29yX3BhcnMKCgojcGxvdChtb2RfZmFwYXJfY29yNCkKIyNwcF9jaGVjayhtb2RfZmFwYXJfY29yNCkKIyNwcF9jaGVjayhtb2RfZmFwYXJfY29yNCwgdHlwZSA9ICJlY2RmX292ZXJsYXkiKQpgYGAKCgojIyBoeXBvdGhlc2lzIHRlc3QgaWYgY29ycmVsYXRpb24gPjAKYGBge3IsbWVzc2FnZT1GQUxTRSx3YXJuaW5nID0gRkFMU0V9CnBvc3Q8LXBvc3Rlcmlvcl9zYW1wbGVzKG1vZF9mYXBhcl9jb3I0KQpoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxldGhpY2tuZXNzID4gMCIpICMwLjkyIApoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlU0xBID4gMCIpICMwLjUxIApoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlTE1BID4gMCIpICMwLjU0Cmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGVMQSA+IDAiKSAjMC44OCAKaHlwb3RoZXNpcyhwb3N0LCAicmVzY29yX19zY2FsZUZBUEFSX19zY2FsZUxETUMgPiAwIikgIzAuMTggICAgIApoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlTE5DID4gMCIpICMxCmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGVMUEMgPiAwIikgIzAuOTgKaHlwb3RoZXNpcyhwb3N0LCAicmVzY29yX19zY2FsZUZBUEFSX19zY2FsZUNOcmF0aW8gPiAwIikgIzAuMDAKaHlwb3RoZXNpcyhwb3N0LCAicmVzY29yX19zY2FsZUZBUEFSX19zY2FsZU5QcmF0aW8gPiAwIikgIzAuMjgKYGBgCgpgYGB7cixyZXN1bHRzPSJoaWRlIiwgbWVzc2FnZT1GQUxTRSx3YXJuaW5nID0gRkFMU0UsIGZpZy5zaG93PUZ9CiMjI2dldCByZXNjb3Igc3VtbWFyeQojYWxsCmxpYnJhcnkoZGF0YS50YWJsZSkKYXJfbW9kX2ZhcGFyX2NvcjQ8LWFzLmFycmF5KHN1bW1hcnkobW9kX2ZhcGFyX2NvcjQpKQpyZXNjX21vZF9mYXBhcl9jb3I0PC1hcl9tb2RfZmFwYXJfY29yNCRyZXNjb3JfcGFycwpyZXNjX21vZF9mYXBhcl9jb3I0X0Y8LSByZXNjX21vZF9mYXBhcl9jb3I0W3Jvdy5uYW1lcyhyZXNjX21vZF9mYXBhcl9jb3I0KSAlbGlrZSUgIkZBUEFSIiwgXQpyZXNjX21vZF9mYXBhcl9jb3I0X0YkeSA8LSBjKCJUaGlja25lc3MiLCJTTEEiLCJMTUEiLCJMQSIsIkxETUMiICwiTE5DIiwiTFBDIiwiQ04gcmF0aW8iLCJOUCByYXRpbyIpCnJlc2NfbW9kX2ZhcGFyX2NvcjRfRiR5CnJlc2NfbW9kX2ZhcGFyX2NvcjRfRiRsb3dlcjwtcmVzY19tb2RfZmFwYXJfY29yNF9GWywzXQpyZXNjX21vZF9mYXBhcl9jb3I0X0YkdXBwZXI8LXJlc2NfbW9kX2ZhcGFyX2NvcjRfRlssNF0KcmVzY19tb2RfZmFwYXJfY29yNF9GCgpyZXNjX21vZF9mYXBhcl9jb3I0X0YkZmFjZXQ8LSJCb3RoIHNocnViIHNwZWNpZXMiCnJlc2NfbW9kX2ZhcGFyX2NvcjRfRiR5IDwtIGZhY3RvcihyZXNjX21vZF9mYXBhcl9jb3I0X0YkeSxsZXZlbHM9YygiTlAgcmF0aW8iLCJDTiByYXRpbyIsIkxQQyIsIkxOQyIsIkxETUMiICwiTEEiLCJMTUEiLCJTTEEiLCJUaGlja25lc3MiKSkKcGxvdF9jb3I0PC1nZ3Bsb3QoZGF0YT1yZXNjX21vZF9mYXBhcl9jb3I0X0YsIGFlcyh4ID0gRXN0aW1hdGUsIHkgPSB5KSkrCiAgbGFicyh5PSIiKSsKICBsYWJzKHg9IiIpKwogIHhsaW0oYygtMC45LDAuOSkpKwogIGZhY2V0X2dyaWQofmZhY2V0KSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLGNvbD0iYmxhY2siKSArCiAgZ2VvbV9saW5lcmFuZ2UoZGF0YT1yZXNjX21vZF9mYXBhcl9jb3I0X0YsIGFlcyh4bWluID0gbG93ZXIsIHhtYXg9dXBwZXIseSA9IHksY29sPUVzdGltYXRlKSkrCiAgZ2VvbV9wb2ludChkYXRhPXJlc2NfbW9kX2ZhcGFyX2NvcjRfRiwgYWVzKHggPSBFc3RpbWF0ZSwgeSA9IHksY29sPUVzdGltYXRlKSkrCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdz0iYmx1ZSIsbWlkPSJncmV5NjAiLGhpZ2g9IiNDOTAwNzYiKSsKICB0aGVtZV9idygpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibiIpKwogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYT0xKSkpKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIikpKwogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAuMSwwLjEsMC4xLCAwLjEpLCAiY20iKSkKcGxvdF9jb3I0CmBgYAoKIyMgTW9kZWxzIGZvciBzcGVjaWVzIHN1YnNldHMKYGBge3IscmVzdWx0cz0iaGlkZSIsIG1lc3NhZ2U9RkFMU0Usd2FybmluZyA9IEZBTFNFfQpiZXQ8LXN1YnNldChhZ2dfZmluYWwsc3BlY2llcz09ImJldHVsYSIpCnNhbDwtc3Vic2V0KGFnZ19maW5hbCxzcGVjaWVzPT0ic2FsaXgiKQoKbW9kX2ZhcGFyX2JldDwtIGJybShiZihtdmJpbmQoc2NhbGVfRkFQQVIsc2NhbGVfdGhpY2tuZXNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9TTEEsc2NhbGVfTE1BLHNjYWxlX0xBLHNjYWxlX0xETUMsc2NhbGVfTE5DLHNjYWxlX0xQQyxzY2FsZV9DTl9yYXRpbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfTlBfcmF0aW8pIH4gMSArCiAgICAgICAgICAgICAgICAgICAgICAgICAoMXwgcCB8YmxrKSkgKyAKICAgICAgICAgICAgICAgICAgICAgIHNldF9yZXNjb3IoVFJVRSksCiAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gc3R1ZGVudCgpLAogICAgICAgICAgICAgICAgICAgIGRhdGEgICA9IGJldCwgCiAgICAgICAgICAgICAgICAgICAgaXRlciAgID0gNDAwMCwgCiAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwKICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LAogICAgICAgICAgICAgICAgICAgIGNvbnRyb2w9bGlzdChhZGFwdF9kZWx0YT0wLjk5LG1heF90cmVlZGVwdGg9MTUpCikKbW9kX2ZhcGFyX2JldAojcGxvdChtb2RfZmFwYXJfYmV0KQojI3BwX2NoZWNrKG1vZF9mYXBhcl9iZXQpCiMjcHBfY2hlY2sobW9kX2ZhcGFyX2JldCwgdHlwZSA9ICJlY2RmX292ZXJsYXkiKQpgYGAKCmBgYHtyLHJlc3VsdHM9ImhpZGUiLCBtZXNzYWdlPUZBTFNFLHdhcm5pbmcgPSBGQUxTRX0KIyMgaHlwb3RoZXNpcyB0ZXN0IGlmIGNvcnJlbGF0aW9uID4wIEJldHVsYSBuYW5hCnBvc3Q8LXBvc3Rlcmlvcl9zYW1wbGVzKG1vZF9mYXBhcl9iZXQpCmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGV0aGlja25lc3MgPiAwIikgIzAuNjQgIApoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlU0xBID4gMCIpICMwLjY2Cmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGVMTUEgPiAwIikgIzAuMjcKaHlwb3RoZXNpcyhwb3N0LCAicmVzY29yX19zY2FsZUZBUEFSX19zY2FsZUxBID4gMCIpICMwLjQ4Cmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGVMRE1DID4gMCIpICMwLjM4ICAgICAKaHlwb3RoZXNpcyhwb3N0LCAicmVzY29yX19zY2FsZUZBUEFSX19zY2FsZUxOQyA+IDAiKSAjMC45OQpoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlTFBDID4gMCIpICMwLjk3Cmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGVDTnJhdGlvID4gMCIpICMwLjAyIApoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlTlByYXRpbyA+IDAiKSAjMC4wMwpgYGAKCmBgYHtyLHJlc3VsdHM9ImhpZGUiLCBtZXNzYWdlPUZBTFNFLHdhcm5pbmcgPSBGQUxTRSwgZmlnLnNob3c9Rn0KIyMjZ2V0IHJlc2NvciBzdW1tYXJ5CiNhbGwKbGlicmFyeShkYXRhLnRhYmxlKQphcl9tb2RfZmFwYXJfYmV0PC1hcy5hcnJheShzdW1tYXJ5KG1vZF9mYXBhcl9iZXQpKQpyZXNjX21vZF9mYXBhcl9iZXQ8LWFyX21vZF9mYXBhcl9iZXQkcmVzY29yX3BhcnMKcmVzY19tb2RfZmFwYXJfYmV0X0Y8LSByZXNjX21vZF9mYXBhcl9iZXRbcm93Lm5hbWVzKHJlc2NfbW9kX2ZhcGFyX2JldCkgJWxpa2UlICJGQVBBUiIsIF0KcmVzY19tb2RfZmFwYXJfYmV0X0YkeSA8LSBjKCJUaGlja25lc3MiLCJTTEEiLCJMTUEiLCJMQSIsIkxETUMiICwiTE5DIiwiTFBDIiwiQ04gcmF0aW8iLCJOUCByYXRpbyIpCnJlc2NfbW9kX2ZhcGFyX2JldF9GJHkKcmVzY19tb2RfZmFwYXJfYmV0X0YkbG93ZXI8LXJlc2NfbW9kX2ZhcGFyX2JldF9GWywzXQpyZXNjX21vZF9mYXBhcl9iZXRfRiR1cHBlcjwtcmVzY19tb2RfZmFwYXJfYmV0X0ZbLDRdCnJlc2NfbW9kX2ZhcGFyX2JldF9GCgpyZXNjX21vZF9mYXBhcl9iZXRfRiRmYWNldDwtIkIuIG5hbmEiCnJlc2NfbW9kX2ZhcGFyX2JldF9GJHkgPC0gZmFjdG9yKHJlc2NfbW9kX2ZhcGFyX2JldF9GJHksbGV2ZWxzPWMoIk5QIHJhdGlvIiwiQ04gcmF0aW8iLCJMUEMiLCJMTkMiLCJMRE1DIiAsIkxBIiwiTE1BIiwiU0xBIiwiVGhpY2tuZXNzIikpCnBsb3RfY29yYmV0PC1nZ3Bsb3QoZGF0YT1yZXNjX21vZF9mYXBhcl9iZXRfRiwgYWVzKHggPSBFc3RpbWF0ZSwgeSA9IHkpKSsKICBsYWJzKHk9IiIpKwogIGxhYnMoeD0iIikrCiAgeGxpbShjKC0wLjksMC45KSkrCiAgZmFjZXRfZ3JpZCh+ZmFjZXQpKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsY29sPSJibGFjayIpICsKICBnZW9tX2xpbmVyYW5nZShkYXRhPXJlc2NfbW9kX2ZhcGFyX2JldF9GLCBhZXMoeG1pbiA9IGxvd2VyLCB4bWF4PXVwcGVyLHkgPSB5LGNvbD1Fc3RpbWF0ZSkpKwogIGdlb21fcG9pbnQoZGF0YT1yZXNjX21vZF9mYXBhcl9iZXRfRiwgYWVzKHggPSBFc3RpbWF0ZSwgeSA9IHksY29sPUVzdGltYXRlKSkrCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdz0iYmx1ZSIsbWlkPSJncmV5NjAiLGhpZ2g9IiNDOTAwNzYiKSsKICB0aGVtZV9idygpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibiIpKwogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYT0xKSkpKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIikpKwogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAuMSwwLjEsMC4xLCAwLjEpLCAiY20iKSkKcGxvdF9jb3JiZXQKCm1vZF9mYXBhcl9zYWw8LSBicm0oYmYobXZiaW5kKHNjYWxlX0ZBUEFSLHNjYWxlX3RoaWNrbmVzcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfU0xBLHNjYWxlX0xNQSxzY2FsZV9MQSxzY2FsZV9MRE1DLHNjYWxlX0xOQyxzY2FsZV9MUEMsc2NhbGVfQ05fcmF0aW8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX05QX3JhdGlvKSB+IDEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICgxfCBwIHxibGspKSArIAogICAgICAgICAgICAgICAgICAgICAgc2V0X3Jlc2NvcihUUlVFKSwKICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBzdHVkZW50KCksCiAgICAgICAgICAgICAgICAgICAgZGF0YSAgID0gc2FsLCAKICAgICAgICAgICAgICAgICAgICBpdGVyICAgPSA0MDAwLCAKICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLAogICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsCiAgICAgICAgICAgICAgICAgICAgY29udHJvbD1saXN0KGFkYXB0X2RlbHRhPTAuOTksbWF4X3RyZWVkZXB0aD0xNSkKKQptb2RfZmFwYXJfc2FsCiNwbG90KG1vZF9mYXBhcl9zYWwpCiMjcHBfY2hlY2sobW9kX2ZhcGFyX3NhbCkKIyNwcF9jaGVjayhtb2RfZmFwYXJfc2FsLCB0eXBlID0gImVjZGZfb3ZlcmxheSIpCmBgYAoKCiMjIGh5cG90aGVzaXMgdGVzdCBpZiBjb3JyZWxhdGlvbiA+MCBTYWxpeCBwdWxjaHJhCmBgYHtyLHJlc3VsdHM9ImhpZGUiLCBtZXNzYWdlPUZBTFNFLHdhcm5pbmcgPSBGQUxTRX0KcG9zdDwtcG9zdGVyaW9yX3NhbXBsZXMobW9kX2ZhcGFyX3NhbCkKaHlwb3RoZXNpcyhwb3N0LCAicmVzY29yX19zY2FsZUZBUEFSX19zY2FsZXRoaWNrbmVzcyA+IDAiKSAjMC44OCAgIApoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlU0xBID4gMCIpICMwLjM2Cmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGVMTUEgPiAwIikgIzAuNTQgCmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGVMQSA+IDAiKSAjIDAuOTMKaHlwb3RoZXNpcyhwb3N0LCAicmVzY29yX19zY2FsZUZBUEFSX19zY2FsZUxETUMgPiAwIikgIzAuMyAgCmh5cG90aGVzaXMocG9zdCwgInJlc2Nvcl9fc2NhbGVGQVBBUl9fc2NhbGVMTkMgPiAwIikgIzAuOTkKaHlwb3RoZXNpcyhwb3N0LCAicmVzY29yX19zY2FsZUZBUEFSX19zY2FsZUxQQyA+IDAiKSAjMC41NApoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlQ05yYXRpbyA+IDAiKSAjMC4wMgpoeXBvdGhlc2lzKHBvc3QsICJyZXNjb3JfX3NjYWxlRkFQQVJfX3NjYWxlTlByYXRpbyA+IDAiKSAjIDAuODcKYGBgCgpgYGB7cixyZXN1bHRzPSJoaWRlIiwgbWVzc2FnZT1GQUxTRSx3YXJuaW5nID0gRkFMU0UsIGZpZy5zaG93PUZ9CiMjI2dldCByZXNjb3Igc3VtbWFyeQojYWxsCmxpYnJhcnkoZGF0YS50YWJsZSkKYXJfbW9kX2ZhcGFyX3NhbDwtYXMuYXJyYXkoc3VtbWFyeShtb2RfZmFwYXJfc2FsKSkKcmVzY19tb2RfZmFwYXJfc2FsPC1hcl9tb2RfZmFwYXJfc2FsJHJlc2Nvcl9wYXJzCnJlc2NfbW9kX2ZhcGFyX3NhbF9GPC0gcmVzY19tb2RfZmFwYXJfc2FsW3Jvdy5uYW1lcyhyZXNjX21vZF9mYXBhcl9zYWwpICVsaWtlJSAiRkFQQVIiLCBdCnJlc2NfbW9kX2ZhcGFyX3NhbF9GJHkgPC0gYygiVGhpY2tuZXNzIiwiU0xBIiwiTE1BIiwiTEEiLCJMRE1DIiAsIkxOQyIsIkxQQyIsIkNOIHJhdGlvIiwiTlAgcmF0aW8iKQpyZXNjX21vZF9mYXBhcl9zYWxfRiR5CnJlc2NfbW9kX2ZhcGFyX3NhbF9GJGxvd2VyPC1yZXNjX21vZF9mYXBhcl9zYWxfRlssM10KcmVzY19tb2RfZmFwYXJfc2FsX0YkdXBwZXI8LXJlc2NfbW9kX2ZhcGFyX3NhbF9GWyw0XQpyZXNjX21vZF9mYXBhcl9zYWxfRgoKcmVzY19tb2RfZmFwYXJfc2FsX0YkZmFjZXQ8LSJTLiBwdWxjaHJhIgpyZXNjX21vZF9mYXBhcl9zYWxfRiR5IDwtIGZhY3RvcihyZXNjX21vZF9mYXBhcl9zYWxfRiR5LGxldmVscz1jKCJOUCByYXRpbyIsIkNOIHJhdGlvIiwiTFBDIiwiTE5DIiwiTERNQyIgLCJMQSIsIkxNQSIsIlNMQSIsIlRoaWNrbmVzcyIpKQpyZXNjX21vZF9mYXBhcl9zYWxfRiR5CnBsb3RfY29yc2FsPC1nZ3Bsb3QoZGF0YT1yZXNjX21vZF9mYXBhcl9zYWxfRiwgYWVzKHggPSBFc3RpbWF0ZSwgeSA9IHkpKSsKICBsYWJzKHk9IiIpKwogIGxhYnMoeD0iIikrCiAgeGxpbShjKC0wLjksMC45KSkrCiAgZmFjZXRfZ3JpZCh+ZmFjZXQpKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsY29sPSJibGFjayIpICsKICBnZW9tX2xpbmVyYW5nZShkYXRhPXJlc2NfbW9kX2ZhcGFyX3NhbF9GLCBhZXMoeG1pbiA9IGxvd2VyLCB4bWF4PXVwcGVyLHkgPSB5LGNvbD1Fc3RpbWF0ZSkpKwogIGdlb21fcG9pbnQoZGF0YT1yZXNjX21vZF9mYXBhcl9zYWxfRiwgYWVzKHggPSBFc3RpbWF0ZSwgeSA9IHksY29sPUVzdGltYXRlKSkrCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdz0iYmx1ZSIsbWlkPSJncmV5NjAiLGhpZ2g9IiNDOTAwNzYiKSsKICB0aGVtZV9idygpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibiIpKwogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYT0xKSkpKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIikpKwogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAuMSwwLjEsMC4xLCAwLjEpLCAiY20iKSkKcGxvdF9jb3JzYWwKYGBgCgoKIyMgIFByZXBhcmF0aW9uIGZvciBQbG90cwpgYGB7cixyZXN1bHRzPSJoaWRlIiwgbWVzc2FnZT1GQUxTRSx3YXJuaW5nID0gRkFMU0UsIGZpZy5zaG93PUZ9CiMjI3Bsb3RzCmltZ19iZXR1bGEgPC0gcmVhZFBORygiYmV0dWxhLnBuZyIpCmdfYmV0dWxhIDwtIHJhc3Rlckdyb2IoaW1nX2JldHVsYSwgaW50ZXJwb2xhdGU9VFJVRSkKaW1nX3NhbGl4IDwtIHJlYWRQTkcoInNhbGl4LnBuZyIpCmdfc2FsaXggPC0gcmFzdGVyR3JvYihpbWdfc2FsaXgsIGludGVycG9sYXRlPVRSVUUpCmltZ19mZXJ0IDwtIHJlYWRQTkcoImZlcnQucG5nIikKZ19mZXJ0IDwtIHJhc3Rlckdyb2IoaW1nX2ZlcnQsIGludGVycG9sYXRlPVRSVUUpCmltZ19ub2ZlcnQgPC0gcmVhZFBORygibm9mZXJ0LnBuZyIpCmdfbm9mZXJ0IDwtIHJhc3Rlckdyb2IoaW1nX25vZmVydCwgaW50ZXJwb2xhdGU9VFJVRSkKaW1nX2hlYXQgPC0gcmVhZFBORygiaGVhdC5wbmciKQpnX2hlYXQgPC0gcmFzdGVyR3JvYihpbWdfaGVhdCwgaW50ZXJwb2xhdGU9VFJVRSkKaW1nX25vaGVhdCA8LSByZWFkUE5HKCJub2hlYXQucG5nIikKZ19ub2hlYXQgPC0gcmFzdGVyR3JvYihpbWdfbm9oZWF0LCBpbnRlcnBvbGF0ZT1UUlVFKQppbWdfY29udHJvbCA8LSByZWFkUE5HKCJjb250cm9sLnBuZyIpCmdfY29udHJvbCA8LSByYXN0ZXJHcm9iKGltZ19jb250cm9sLCBpbnRlcnBvbGF0ZT1UUlVFKQphbm5vdGF0aW9uX2N1c3RvbTIgPC0gCiAgZnVuY3Rpb24gKGdyb2IsIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZGF0YSl7IGxheWVyKGRhdGEgPSBkYXRhLCBzdGF0ID0gU3RhdElkZW50aXR5LCBwb3NpdGlvbiA9IFBvc2l0aW9uSWRlbnRpdHksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tID0gZ2dwbG90Mjo6Okdlb21DdXN0b21Bbm4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gVFJVRSwgcGFyYW1zID0gbGlzdChncm9iID0gZ3JvYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bWluID0geG1pbiwgeG1heCA9IHhtYXgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IHltaW4sIHltYXggPSB5bWF4KSl9CiNiZXR1bGEKYTEgPSBhbm5vdGF0aW9uX2N1c3RvbTIocmFzdGVyR3JvYihpbWdfYmV0dWxhLCBpbnRlcnBvbGF0ZT1UUlVFKSwgeG1pbj0tMC45LCB4bWF4PS0wLjUsIHltaW49OC41LCB5bWF4PTkuNSwgZGF0YT1yZXNjX21vZF9mYXBhcl9iZXRfRlsxLF0pCnBsb3RfY29yMl9maW48LXBsb3RfY29yYmV0ICsgYTEKcGxvdF9jb3IyX2ZpbgojcGxvdDMKYTIgPSBhbm5vdGF0aW9uX2N1c3RvbTIocmFzdGVyR3JvYihpbWdfc2FsaXgsIGludGVycG9sYXRlPVRSVUUpLCB4bWluPS0wLjksIHhtYXg9LTAuNSwgeW1pbj04LjUsIHltYXg9OS41LCBkYXRhPXJlc2NfbW9kX2ZhcGFyX3NhbF9GWzEsXSkKcGxvdF9jb3IzX2ZpbjwtcGxvdF9jb3JzYWwgKyBhMgpwbG90X2NvcjNfZmluCiNwbG90NApwbG90X2NvcjQKYTMgPSBhbm5vdGF0aW9uX2N1c3RvbTIocmFzdGVyR3JvYihpbWdfYmV0dWxhLCBpbnRlcnBvbGF0ZT1UUlVFKSwgeG1pbj0tMC45LCB4bWF4PS0wLjUsIHltaW49OC41LCB5bWF4PTkuNSwgZGF0YT1yZXNjX21vZF9mYXBhcl9jb3I0X0ZbMSxdKQphNCA9IGFubm90YXRpb25fY3VzdG9tMihyYXN0ZXJHcm9iKGltZ19zYWxpeCwgaW50ZXJwb2xhdGU9VFJVRSksIHhtaW49LTAuNTUsIHhtYXg9LTAuMTUsIHltaW49OC4yLCB5bWF4PTkuMiwgZGF0YT1yZXNjX21vZF9mYXBhcl9jb3I0X0ZbMSxdKQpwbG90X2NvcjRfZmluPC1wbG90X2NvcjQgKyBhNCArIGEzCnBsb3RfY29yNF9maW4KYGBgCgoKIyMgY29tYmluZSBwbG90cwpgYGB7cixyZXN1bHRzPSJoaWRlIiwgbWVzc2FnZT1GQUxTRSx3YXJuaW5nID0gRkFMU0UsIGZpZy5zaG93PUZ9CmxpYnJhcnkoY293cGxvdCkKeGxhYiA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoIkNvcnJlbGF0aW9uIiwgIGhqdXN0ID0gLTAuMDQsICB2anVzdCA9IC0wLjUsc2l6ZT0xMCkKCmFsbDE8LXBsb3RfZ3JpZChwbG90X2NvcjRfZmluLHBsb3RfY29yMl9maW4scGxvdF9jb3IzX2ZpbixsYWJlbHM9YygiQSIsIkIiLCAiQyIpLG5jb2w9MykKYGBgCgpgYGB7cixtZXNzYWdlPUZBTFNFLHdhcm5pbmcgPSBGQUxTRX0KYWxsMQpgYGAKCmBgYHtyLHJlc3VsdHM9ImhpZGUiLCBtZXNzYWdlPUZBTFNFLHdhcm5pbmcgPSBGQUxTRX0KcG5nKGZpbGU9InBsb3RfY29yX2ZpbmFsLnBuZyIsIHdpZHRoPTE4LCBoZWlnaHQ9OCwgdW5pdHM9ImNtIiwgcG9pbnRzaXplPTEyLHJlcz02MDApCmFsbDEKZGV2Lm9mZigpIApgYGAKCg==