This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

IsosWing1 <- read_csv("IsogenicWingArea_60LINES_omitted10lines.csv", 
     col_types = cols(Diet_dilution = col_double(), 
       Line = col_character(), Replicate = col_character(), Block = col_character(),
        Temp = col_character()))
head (IsosWing1)

nrow (IsosWing1)
[1] 3899

function to rotate text on the x and y axes


rotatedAxisElementText = function(angle,position='x'){
  angle     = angle[1]; 
  position  = position[1]
  positions = list(x=0,y=90,top=180,right=270)
  if(!position %in% names(positions))
    stop(sprintf("'position' must be one of [%s]",paste(names(positions),collapse=", ")),call.=FALSE)
  if(!is.numeric(angle))
    stop("'angle' must be numeric",call.=FALSE)
  rads  = (angle - positions[[ position ]])*pi/180
  hjust = 0.5*(1 - sin(rads))
  vjust = 0.5*(1 + cos(rads))
  element_text(angle=angle,vjust=vjust,hjust=hjust)
}

rr means1 <- IsosWing1 %>% group_by(Line, Temp, Diet_dilution) %>% summarise(mean = mean(wing_area)) means1

       mean
1 0.9371405

rr #write.csv(means1, _means.csv) #for orginial 60lines dataset new_dataframe_means <- IsosWing %>% group_by(Line, Temp, Diet_dilution) %>% mutate (means= mean(wing_area)) new_dataframe_means

# A tibble: 3,010 x 7
# Groups:   Line, Temp, Diet_dilution [245]
   Diet        Temp  Line Replicate wing_area Diet_dilution means
   <chr>      <int> <int>     <int>     <dbl>         <dbl> <dbl>
 1 2:3(X1)       25    29         1     1.05            100 0.930
 2 2:3(X1)       25    29         2     0.971           100 0.930
 3 2:3(X1)       25    29         3     1.03            100 0.930
 4 2:3(X1)       25    29         4     0.985           100 0.930
 5 2:3(X1)       25    29         5     0.985           100 0.930
 6 2:3(X1)       25    29         6     1.00            100 0.930
 7 2:3(X1)       25    29         7     0.99            100 0.930
 8 2:3(X1)       25    29         8     0.892           100 0.930
 9 2:3(X1)       25    29         9     0.983           100 0.930
10 2:3(X0.25)    25    29         1     0.946            25 0.930
# … with 3,000 more rows

rr means2 <- IsosWing %>% group_by(Line) %>% summarise(mean = mean(wing_area), sd = sd(wing_area)) means2

       mean       sd
1 0.9299233 0.113709
lrtest (IsosWing.lm4,IsosWing.lm2)
Likelihood ratio test

Model 1: wing_area ~ 1 + Diet_dilution * Temp + (1 | Line) + (1 | Diet_dilution:Line) + 
    (1 | Temp:Line) + (1 | Diet_dilution:Temp:Line) + (1 | Block)
Model 2: wing_area ~ -1 + Diet_dilution * Temp + (1 | Block) + (1 | Line)
  #Df LogLik Df  Chisq Pr(>Chisq)    
1  10 4727.0                         
2   7 4484.4 -3 485.07  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
chi2 <- 2*(summary(mod5)$logLik - summary(mod4)$logLik)
1-pchisq(chi2, 3)
'log Lik.' 3.026083e-10 (df=16)

rr summary(mod2b)

#making a new diet_dilution by temp to see if the model fits better IsosWing\(diet_dilution_by_temp<-as.factor(paste(IsosWing\)Diet_dilution,IsosWing$Temp,sep=;)) mod3<-lme(wing_area ~ 1+Diet_dilution * Temp,random=c(~-1+diet_dilution_by_temp|Line),data=IsosWing,control=list(opt=)) summary (mod3)

anova(mod3,mod2b) anova(mod2b,mod2a)

summary(mod3) confint(mod3) ranef(model3.1)

library() library(4) dotplot(ranef(mod3, condVar=TRUE), lattice.options=list(layout=c(1,2))) mod3<-lmer(wing_area ~ 1+Diet_dilution * Temp + (-1+diet_dilution|Line), data=IsosWing) dotplot(ranef(mod3, condVar=TRUE), lattice.options=list(layout=c(1,2)))

IsosWing_scaled <- IsosWing1 %>% mutate(Diet_dilution_scaled = scale(Diet_dilution, center = T, scale = T), Diet_Temp = paste(Diet_dilution, Temp, sep = _)) IsosWing_scaled

model3.1 <- lmer(wing_area ~ 1+Diet_dilution_scaled * Temp + (1+Diet_dilution_scaled*Temp|Line) + (1|Block), REML = FALSE, data=IsosWing_scaled) plot(model3.1)

summary(model3.1) car::Anova(model3.1) model3.2 <- lmer(wing_area ~ 1+Diet_dilution_scaled + Temp + (1+Diet_dilution_scaled*Temp|Line) + (1|Block), REML = FALSE, data=IsosWing_scaled)

summary (model3.2) dotplot(ranef(model3.1, condVar=TRUE), lattice.options=list(layout=c(1,2)))

#ranef gives us the BLUPs, which represents the response of a given genotype to the fixed effect of the diet at each temp, as difference betwen the genotype’s predicted response and the population level average predicted response genotype_blups <- ranef(model3.1)$Line

genotype_index <- as.factor(genotype_blups$Line) genotype_index <- data.frame(rownames(genotype_blups), genotype_blups) genotype_data <- cbind( genotype_index, genotype_blups) colnames(genotype_data) <- c(, _int, _slope, ,_slope_by_temp )

#there are two random effects for RRMs: intercept and slopes #BLUPs by intercept, indicates the difference in genotype elevation relative to the population average, more +ve BLUP intercept means that the genotype’s reaction norm occurs above the pop-level average response. -ve indicated the genotype’s reaction norm is below pop-level average response. these are not a measure of plasticity. ggplot(genotype_data, aes(Line, BLUP_int )) + geom_point(aes(group = Line, colour = Line), size = 4) + ylab(intercept estimate) + geom_hline(yintercept = 0, lty = 2) + theme_classic()

#BLUPs by slope estimate is the difference in slope(relative steepness of change) between the pop-level average response and the response of the individual genotype. ggplot(genotype_data, aes(Line, BLUP_slope)) + geom_point(aes(group = Line, colour = Line), size = 4) + ylab((BLUP slope estimate)) + geom_hline(yintercept = 0, lty = 2) + theme_classic()

#is there any coorelation with BLUP intercept and BLUP slope? ggplot(genotype_data, aes(BLUP_int, BLUP_slope)) + geom_point(aes(group = Line, colour = Line), size = 4) + xlab(intercept estimate) + ylab(slope estimate) + theme_classic() #answer: not really a positive corelation, as can be seen from summary table of the model as well?

#rank BLUPs in order, sort by slope of most to least plastic. more negative BLUP slope estimate represent greater plasticity and more positive BLUP slope estimates represents less plasticity in the relative wing area across nutritional conditions at 25 vs 28. genotype_data\(genotype_ordered <- factor(genotype_data\)Line, levels = genotype_data\(Line[order(genotype_data\)BLUP_slope_by_temp)]) plotf<-ggplot(genotype_data, aes(genotype_ordered, BLUP_slope_by_temp)) + geom_bar(stat = , aes(group = Line, fill = Line)) + xlab((in ranked order of plasticity)) + ylab((BLUP slope estimate)) + theme_classic()

pdf(./plotf.pdf, useDingbats=FALSE, width = 12 , height = 7 ) grid.arrange(plotf) dev.off()

rr #plot the raw values of wing area against mean-centred and scaled diet_dilution for each line. ggplot(IsosWing_scaled, aes(x = Diet_dilution_scaled, y = wing_area, group = Line)) + geom_line(aes(colour = Line)) + ylab(wing area) + xlab(-centered and scaled rearing diet_dilution) + facet_grid(~ Temp)+theme_classic()

#fit the model on this to visualise fit?

pdf("./50lines_population_mean_response.pdf", useDingbats=FALSE) 
grid.arrange(PLOT)
dev.off()
null device 
          1 
pdf("./50lines_response.pdf", useDingbats=FALSE) 
grid.arrange(PLOT)
dev.off()
IsosWing1$Temp <- as.numeric(IsosWing1$Temp)
IsosWing1$Diet_dilution <- as.numeric(IsosWing1$Diet_dilution)
as.numeric(as.character(Temp))
IsosDT.lm <- lmer (wing_area ~ Temp * Line * Diet_dilution + (1|Block), data = IsosWing1) #line as fixed effect since we have chosen them from prior analysis (RRMs)
anova (IsosDT.lm) #supplimentary table with wing area and dev time, but refer to it saying evrything differs
Isos_trend1 <- emtrends(IsosDT.lm, ~ Temp | Line, var = "Diet_dilution")
multcomp::cld(Isos_trend1)

Isos_trend2 <- emtrends(IsosDT.lm, ~ Line | Temp, var = "Diet_dilution")
multcomp::cld(Isos_trend2)

Isos_trend3 <- emtrends(IsosDT.lm, ~ Diet_dilution | Line, var = "Temp")
multcomp::cld(Isos_trend3)

New$Temp <- as.numeric(New$Temp)
New$Diet_dilution <- as.numeric(New$Diet_dilution)
as.numeric(as.character(Temp))
IsosDT.lm <- lmer (wing_area ~ Temp * Line * Diet_dilution + (1|Block), data = New) #line as fixed effect since we have chosen them from prior analysis (RRMs)
anova (IsosDT.lm) #supplimentary table with wing area and dev time, but refer to it saying evrything differs
Isos_trend1 <- emtrends(IsosDT.lm, ~ Temp | Line, var = "Diet_dilution")
multcomp::cld(Isos_trend1)

Isos_trend2 <- emtrends(IsosDT.lm, ~ Line | Temp, var = "Diet_dilution")
multcomp::cld(Isos_trend2)

Isos_trend3 <- emtrends(IsosDT.lm, ~ Diet_dilution | Line, var = "Temp")
multcomp::cld(Isos_trend3)
Isos_trend1 <- emtrends(IsosDT.lm, ~ Temp | Line, var = "Diet_dilution_scaled")
Note: D.f. calculations have been disabled because the number of observations exceeds 3000.
To enable adjustments, add the argument 'pbkrtest.limit = 3899' (or larger)
[or, globally, 'set emm_options(pbkrtest.limit = 3899)' or larger];
but be warned that this may result in large computation time and memory use.
Note: D.f. calculations have been disabled because the number of observations exceeds 3000.
To enable adjustments, add the argument 'lmerTest.limit = 3899' (or larger)
[or, globally, 'set emm_options(lmerTest.limit = 3899)' or larger];
but be warned that this may result in large computation time and memory use.

rr pdf(./5lines_response.pdf, useDingbats=FALSE) grid.arrange(PLOT2) dev.off()

null device 
          1 

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ21kK1NoaWZ0K0VudGVyKi4gCgpgYGB7cn0KCiNvbWl0dGVkIGxpbmVzIHRoYXQgZGlkbnQgaGF2ZSBhbGwgNiB0cmVhdG1lbnRzIGFuZCBjcmVhdGVkIG5ldyBkYXRhIGZyYW1lIAoKSXNvc1dpbmcxIDwtIHJlYWRfY3N2KCJJc29nZW5pY1dpbmdBcmVhXzYwTElORVNfb21pdHRlZDEwbGluZXMuY3N2IiwgCiAgICAgY29sX3R5cGVzID0gY29scyhEaWV0X2RpbHV0aW9uID0gY29sX2RvdWJsZSgpLCAKICAgICAgIExpbmUgPSBjb2xfY2hhcmFjdGVyKCksIFJlcGxpY2F0ZSA9IGNvbF9jaGFyYWN0ZXIoKSwgQmxvY2sgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgVGVtcCA9IGNvbF9jaGFyYWN0ZXIoKSkpCmhlYWQgKElzb3NXaW5nMSkKbnJvdyAoSXNvc1dpbmcxKQoKcmVxdWlyZSgiZ2RhdGEiKQpyZXF1aXJlKCJkYXRhLnRhYmxlIikKcmVxdWlyZSgiZ2dwbG90MiIpCnJlcXVpcmUoInBseXIiKQpyZXF1aXJlKCJsc21lYW5zIikKcmVxdWlyZSgibWdjdiIpCnJlcXVpcmUoIm5sbWUiKQpyZXF1aXJlKCJmaWVsZHMiKQpyZXF1aXJlKCJtdWx0Y29tcFZpZXciKQpyZXF1aXJlKCdjb3dwbG90JykKcmVxdWlyZSAoImNvbXB1dGUuZXMiKQpyZXF1aXJlICgiZWZmZWN0cyIpCnJlcXVpcmUgKCJtdWx0Y29tcCIpCnJlcXVpcmUgKCJwYXN0ZWNzIikKcmVxdWlyZSAoIldSUyIpCmxpYnJhcnkoInJlYWRyIikKbGlicmFyeSgiZ3JpZEV4dHJhIikKbGlicmFyeSgiZW1tZWFucyIpCnJlcXVpcmUgKCJsbWU0IikKbGlicmFyeSgicmNvbXBhbmlvbiIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG1vZGVscikKbGlicmFyeShtZ2N2KQpsaWJyYXJ5KE11TUluKQpyZXF1aXJlIChsbXRlc3QpCmxpYnJhcnkobG10ZXN0KQoKYGBgCgpmdW5jdGlvbiB0byByb3RhdGUgdGV4dCBvbiB0aGUgeCBhbmQgeSBheGVzCgpgYGB7cn0KCnJvdGF0ZWRBeGlzRWxlbWVudFRleHQgPSBmdW5jdGlvbihhbmdsZSxwb3NpdGlvbj0neCcpewogIGFuZ2xlICAgICA9IGFuZ2xlWzFdOyAKICBwb3NpdGlvbiAgPSBwb3NpdGlvblsxXQogIHBvc2l0aW9ucyA9IGxpc3QoeD0wLHk9OTAsdG9wPTE4MCxyaWdodD0yNzApCiAgaWYoIXBvc2l0aW9uICVpbiUgbmFtZXMocG9zaXRpb25zKSkKICAgIHN0b3Aoc3ByaW50ZigiJ3Bvc2l0aW9uJyBtdXN0IGJlIG9uZSBvZiBbJXNdIixwYXN0ZShuYW1lcyhwb3NpdGlvbnMpLGNvbGxhcHNlPSIsICIpKSxjYWxsLj1GQUxTRSkKICBpZighaXMubnVtZXJpYyhhbmdsZSkpCiAgICBzdG9wKCInYW5nbGUnIG11c3QgYmUgbnVtZXJpYyIsY2FsbC49RkFMU0UpCiAgcmFkcyAgPSAoYW5nbGUgLSBwb3NpdGlvbnNbWyBwb3NpdGlvbiBdXSkqcGkvMTgwCiAgaGp1c3QgPSAwLjUqKDEgLSBzaW4ocmFkcykpCiAgdmp1c3QgPSAwLjUqKDEgKyBjb3MocmFkcykpCiAgZWxlbWVudF90ZXh0KGFuZ2xlPWFuZ2xlLHZqdXN0PXZqdXN0LGhqdXN0PWhqdXN0KQp9CgpgYGAKCgoKYGBge3J9CgptZWFuczEgPC0gSXNvc1dpbmcxICU+JSBncm91cF9ieShMaW5lLCBUZW1wLCBEaWV0X2RpbHV0aW9uKSAlPiUgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHdpbmdfYXJlYSkpCm1lYW5zMQoKI3dyaXRlLmNzdihtZWFuczEsICJJc29nZW5pY1dpbmdBcmVhX21lYW5zLmNzdiIpICNmb3Igb3JnaW5pYWwgNjBsaW5lcyBkYXRhc2V0CgpuZXdfZGF0YWZyYW1lX21lYW5zIDwtIElzb3NXaW5nICAlPiUgZ3JvdXBfYnkoTGluZSwgVGVtcCwgRGlldF9kaWx1dGlvbikgICU+JSBtdXRhdGUgKG1lYW5zPSBtZWFuKHdpbmdfYXJlYSkpCm5ld19kYXRhZnJhbWVfbWVhbnMKCm1lYW5zMiA8LSBJc29zV2luZyAlPiUgZ3JvdXBfYnkoTGluZSkgJT4lIHN1bW1hcmlzZShtZWFuID0gbWVhbih3aW5nX2FyZWEpLCBzZCA9IHNkKHdpbmdfYXJlYSkpCm1lYW5zMgpgYGAKCmBgYHtyfQpJc29zV2luZy5sbSA8LSBsbWVyICh3aW5nX2FyZWEgfiBEaWV0X2RpbHV0aW9uICogTGluZSAqIFRlbXAgKyAoMXxCbG9jaykgLCBSRU1MID0gRkFMU0UgLGRhdGEgPSBJc29zV2luZzEgKQpwYXIobWZyb3c9YygyLDIpKQpwbG90KElzb3NXaW5nLmxtKQpzdW1tYXJ5KElzb3NXaW5nLmxtKQpjYXI6OkFub3ZhKElzb3NXaW5nLmxtKQpyLnNxdWFyZWRHTE1NKElzb3NXaW5nLmxtKQpxcW5vcm0oSXNvc1dpbmcubG0pCnFxUGxvdChyZXNpZHVhbHMkSXNvc1dpbmcxKQoKaGlzdCAoSXNvc1dpbmcxJHdpbmdfYXJlYSkKCiNpZiB5b3UgZG9udCBwdXQgMCBvciAtMSBpdCB3aWxsIHN0aWxsIGluY2x1ZGUgb3ZlcmFsbCBpbnRlcmNlcHQgaW4gdGhlIG1vZGVsCgpJc29zV2luZy5sbTEgPC0gbG1lciAod2luZ19hcmVhIH4gLTEgK0RpZXRfZGlsdXRpb24gKiBUZW1wICsgKDF8QmxvY2spICwgUkVNTCA9IEZBTFNFICxkYXRhID0gSXNvc1dpbmcxICkKcGFyKG1mcm93PWMoMiwyKSkKcGxvdChJc29zV2luZy5sbTEpCnN1bW1hcnkoSXNvc1dpbmcubG0xKQpjYXI6OkFub3ZhKElzb3NXaW5nLmxtMSkKci5zcXVhcmVkR0xNTShJc29zV2luZy5sbTEpCgpJc29zV2luZy5sbTIgPC0gbG1lciAod2luZ19hcmVhIH4gLTErIERpZXRfZGlsdXRpb24gKiBUZW1wICsgKDF8QmxvY2spICsgKDF8TGluZSkgLCBSRU1MID0gRkFMU0UgLGRhdGEgPSBJc29zV2luZzEgKQpwYXIobWZyb3c9YygyLDIpKQpwbG90KElzb3NXaW5nLmxtMikKc3VtbWFyeShJc29zV2luZy5sbTIpCmNhcjo6QW5vdmEoSXNvc1dpbmcubG0yKQpyLnNxdWFyZWRHTE1NKElzb3NXaW5nLmxtMikKCgpJc29zV2luZy5sbTMgPC0gbG1lciAod2luZ19hcmVhIH4gLTErRGlldF9kaWx1dGlvbiAqIFRlbXAgKyAoMXxCbG9jaykgKyAoMXxUZW1wOkRpZXRfZGlsdXRpb246TGluZSkgLCBSRU1MID0gRkFMU0UgLGRhdGEgPSBJc29zV2luZzEgKQpwYXIobWZyb3c9YygyLDIpKQpwbG90KElzb3NXaW5nLmxtMykKc3VtbWFyeShJc29zV2luZy5sbTMpCmNhcjo6QW5vdmEoSXNvc1dpbmcubG0zKQpyLnNxdWFyZWRHTE1NKElzb3NXaW5nLmxtMykKCmxydGVzdCAoSXNvc1dpbmcubG0yLElzb3NXaW5nLmxtMSkKCmxydGVzdCAoSXNvc1dpbmcubG0zLElzb3NXaW5nLmxtMikKCgoKbHJ0ZXN0IChJc29zV2luZy5sbTUsSXNvc1dpbmcubG0pCgpJc29zV2luZy5sbTQgPC0gbG1lciAod2luZ19hcmVhIH4gMSsgRGlldF9kaWx1dGlvbiAqVGVtcCArICgxfExpbmUpICsgKDF8RGlldF9kaWx1dGlvbjpMaW5lKSArKDF8VGVtcDpMaW5lKSArICgxfERpZXRfZGlsdXRpb246VGVtcDpMaW5lKSArICgxfEJsb2NrKSAsIGRhdGEgPSBJc29zV2luZzEgKQpwYXIobWZyb3c9YygyLDIpKQpwbG90KElzb3NXaW5nLmxtNCkKc3VtbWFyeShJc29zV2luZy5sbTQpCmNhcjo6QW5vdmEoSXNvc1dpbmcubG00KQoKbHJ0ZXN0IChJc29zV2luZy5sbTQsSXNvc1dpbmcubG0yKQoKYGBgIAoKYGBge3J9Cklzb3NXaW5nX3NjYWxlZCA8LSBJc29zV2luZzEgJT4lIG11dGF0ZShEaWV0X2RpbHV0aW9uX3NjYWxlZCA9IHNjYWxlKERpZXRfZGlsdXRpb24sIGNlbnRlciA9IFQsIHNjYWxlID0gVCksIERpZXRfVGVtcCA9IHBhc3RlKERpZXRfZGlsdXRpb24sIFRlbXAsIHNlcCA9ICJfIikpCklzb3NXaW5nX3NjYWxlZApoaXN0KElzb3NXaW5nJHdpbmdfYXJlYSkKI2NoZWNraW5nIGRpZmZlcmVudCBtb2RlbHMKCm1vZDE8LWxtZXIgKHdpbmdfYXJlYSB+IDErRGlldF9kaWx1dGlvbl9zY2FsZWQgKiBUZW1wICsgKDF8QmxvY2spLGRhdGE9SXNvc1dpbmdfc2NhbGVkKSAKbW9kMjwtbG1lciAod2luZ19hcmVhIH4gMStEaWV0X2RpbHV0aW9uX3NjYWxlZCAqIFRlbXAgKyAoMXxCbG9jaykgKyAoMXxMaW5lKSxkYXRhPUlzb3NXaW5nX3NjYWxlZCkgCm1vZDNhPC1sbWVyICh3aW5nX2FyZWEgfiAxK0RpZXRfZGlsdXRpb25fc2NhbGVkICogVGVtcCArICgxfEJsb2NrKSArICgxK0RpZXRfZGlsdXRpb25fc2NhbGVkfExpbmUpLGRhdGE9SXNvc1dpbmdfc2NhbGVkKQptb2QzYjwtbG1lciAod2luZ19hcmVhIH4gMStEaWV0X2RpbHV0aW9uX3NjYWxlZCAqIFRlbXAgKyAoMXxCbG9jaykgKyAoMStUZW1wfExpbmUpLGRhdGE9SXNvc1dpbmdfc2NhbGVkKSAKCgptb2Q0PC1sbWVyICh3aW5nX2FyZWEgfiAxK0RpZXRfZGlsdXRpb25fc2NhbGVkICogVGVtcCArICgxfEJsb2NrKSArICgxK1RlbXB8TGluZSkrICgxK0RpZXRfZGlsdXRpb25fc2NhbGVkfExpbmUpLGRhdGE9SXNvc1dpbmdfc2NhbGVkKSAKCiAKbW9kNTwtIGxtZXIgKHdpbmdfYXJlYSB+IDErRGlldF9kaWx1dGlvbl9zY2FsZWQgKiBUZW1wICsgKDF8QmxvY2spICsgKDErRGlldF9kaWx1dGlvbl9zY2FsZWQqVGVtcHxMaW5lKSxkYXRhPUlzb3NXaW5nX3NjYWxlZCkKCgoKQUlDKG1vZDEpCkFJQyhtb2QyKQpBSUMobW9kM2EpCkFJQyhtb2QzYikKCkFJQyhtb2Q0KQpBSUMobW9kNSkKCgpyLnNxdWFyZWRHTE1NKG1vZDEpCnIuc3F1YXJlZEdMTU0obW9kMikKci5zcXVhcmVkR0xNTShtb2QzYSkKci5zcXVhcmVkR0xNTShtb2QzYikKci5zcXVhcmVkR0xNTShtb2Q0KQpyLnNxdWFyZWRHTE1NKG1vZDUpCgpsaWJyYXJ5KE11TUluKQpyZXF1aXJlIChNdU1JbikKI2xvd2VyIHRoZSBBSUMgdmFsdWUsIHRoZSBtb3JlIHBhcnNpbW9uaW91cyB0aGUgZml0IG9mIHRoZSBtb2RlbCBpcyB0byB0aGUgZGF0YSAoZ3JlYXRlciBleHBsYW5hdG9yeS9wcmVkaWN0aXZlIHBvd2VyKS4gVGhlIGxhcmdlciB0aGUgbGlrZWxpaG9vZCBvZiBvdXIgZGF0YSBnaXZlbiB0aGUgbW9kZWzigJlzIGVzdGltYXRlcywgdGhlIOKAmGJldHRlcuKAmSB0aGUgbW9kZWwgZml0cyB0aGUgZGF0YQoKI1IybSB2YWx1ZSBpcyB0aGUgbWFyZ2luYWwgUjIgdGhhdCBpcyB0aGUgZml0IG9mIHRoZSBmaXhlZC1lZmZlY3RzIG9ubHksIGFuZCB0aGUgUjJjIHZhbHVlIGlzIHRoZSBjb25kaXRpb25hbCBSMiB0aGF0IGV4cGxhaW5zIHRoZSBwcm9wb3J0aW9uIG9mIHZhcmlhbmNlIGFjY291bnRlZCBmb3IgYnkgdGhlIHJhbmRvbSBhbmQgZml4ZWQgZWZmZWN0cyBjb21iaW5lZC4gV2UgYXJlIHRoZXJlZm9yZSBpbnRlcmVzdGVkIHByaW1hcmlseSBpbiB0aGUgdmFsdWUgb2YgUjJjLgoKbGlicmFyeSAoY2FyKQpyZXF1aXJlICggY2FyKQphbm92YSAobW9kMiwgbW9kMSkKY2hpMiA8LSAyKihzdW1tYXJ5KG1vZDIpJGxvZ0xpayAtIHN1bW1hcnkobW9kMSkkbG9nTGlrICkKMS1wY2hpc3EoY2hpMiwgMSkKCmFub3ZhIChtb2QyLCBtb2QzKQpjaGkyIDwtIDIqKHN1bW1hcnkobW9kM2EpJGxvZ0xpayAtIHN1bW1hcnkobW9kMikkbG9nTGlrKQoxLXBjaGlzcShjaGkyLCAyKQoKY2hpMiA8LSAyKihzdW1tYXJ5KG1vZDNiKSRsb2dMaWsgLSBzdW1tYXJ5KG1vZDIpJGxvZ0xpaykKMS1wY2hpc3EoY2hpMiwgMikKCmFub3ZhIChtb2QzLCBtb2Q0KQpjaGkyIDwtIDIqKHN1bW1hcnkobW9kNCkkbG9nTGlrIC0gc3VtbWFyeShtb2QzYSkkbG9nTGlrKQoxLXBjaGlzcShjaGkyLCAwKQoKY2hpMiA8LSAyKihzdW1tYXJ5KG1vZDQpJGxvZ0xpayAtIHN1bW1hcnkobW9kM2IpJGxvZ0xpaykKMS1wY2hpc3EoY2hpMiwgMCkKCmFub3ZhIChtb2Q0LCBtb2Q1KQpjaGkyIDwtIDIqKHN1bW1hcnkobW9kNSkkbG9nTGlrIC0gc3VtbWFyeShtb2Q0KSRsb2dMaWspCjEtcGNoaXNxKGNoaTIsIDMpCgoKCiNkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHBhcmFtZXRlcnMgKG5wYXIpIGlzIHRoZSBjaGkyIHZhbHVlIGluIGRmICwgcHV0IHRoZSBtb3JlIGNvbXBsaWNhdGVkIG1vZGVsIGZpcnN0CmBgYApgYGB7cn0Kc3VtbWFyeShtb2QyYikKCiNtYWtpbmcgYSBuZXcgZGlldF9kaWx1dGlvbiBieSB0ZW1wIHRvIHNlZSBpZiB0aGUgbW9kZWwgZml0cyBiZXR0ZXIKSXNvc1dpbmckZGlldF9kaWx1dGlvbl9ieV90ZW1wPC1hcy5mYWN0b3IocGFzdGUoSXNvc1dpbmckRGlldF9kaWx1dGlvbixJc29zV2luZyRUZW1wLHNlcD0iOyIpKQptb2QzPC1sbWUod2luZ19hcmVhIH4gMStEaWV0X2RpbHV0aW9uICogVGVtcCxyYW5kb209Yyh+LTErZGlldF9kaWx1dGlvbl9ieV90ZW1wfExpbmUpLGRhdGE9SXNvc1dpbmcsY29udHJvbD1saXN0KG9wdD0ib3B0aW0iKSkKc3VtbWFyeSAobW9kMykKCmFub3ZhKG1vZDMsbW9kMmIpCmFub3ZhKG1vZDJiLG1vZDJhKQoKc3VtbWFyeShtb2QzKQpjb25maW50KG1vZDMpCnJhbmVmKG1vZGVsMy4xKQoKbGlicmFyeSgibGF0dGljZSIpCmxpYnJhcnkoImxtZTQiKQpkb3RwbG90KHJhbmVmKG1vZDMsIGNvbmRWYXI9VFJVRSksIGxhdHRpY2Uub3B0aW9ucz1saXN0KGxheW91dD1jKDEsMikpKQptb2QzPC1sbWVyKHdpbmdfYXJlYSB+IDErRGlldF9kaWx1dGlvbiAqIFRlbXAgKyAoLTErZGlldF9kaWx1dGlvbnxMaW5lKSwgZGF0YT1Jc29zV2luZykKZG90cGxvdChyYW5lZihtb2QzLCBjb25kVmFyPVRSVUUpLCBsYXR0aWNlLm9wdGlvbnM9bGlzdChsYXlvdXQ9YygxLDIpKSkKCklzb3NXaW5nX3NjYWxlZCA8LSBJc29zV2luZzEgJT4lIG11dGF0ZShEaWV0X2RpbHV0aW9uX3NjYWxlZCA9IHNjYWxlKERpZXRfZGlsdXRpb24sIGNlbnRlciA9IFQsIHNjYWxlID0gVCksIERpZXRfVGVtcCA9IHBhc3RlKERpZXRfZGlsdXRpb24sIFRlbXAsIHNlcCA9ICJfIikpCklzb3NXaW5nX3NjYWxlZAoKbW9kZWwzLjEgPC0gbG1lcih3aW5nX2FyZWEgfiAxK0RpZXRfZGlsdXRpb25fc2NhbGVkICogVGVtcCAgKyAoMStEaWV0X2RpbHV0aW9uX3NjYWxlZCpUZW1wfExpbmUpICsgKDF8QmxvY2spLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MID0gRkFMU0UsIGRhdGE9SXNvc1dpbmdfc2NhbGVkKQpwbG90KG1vZGVsMy4xKQoKc3VtbWFyeShtb2RlbDMuMSkKY2FyOjpBbm92YShtb2RlbDMuMSkKbW9kZWwzLjIgPC0gbG1lcih3aW5nX2FyZWEgfiAxK0RpZXRfZGlsdXRpb25fc2NhbGVkICsgVGVtcCAgKyAoMStEaWV0X2RpbHV0aW9uX3NjYWxlZCpUZW1wfExpbmUpICsgKDF8QmxvY2spLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MID0gRkFMU0UsIGRhdGE9SXNvc1dpbmdfc2NhbGVkKQoKc3VtbWFyeSAobW9kZWwzLjIpCiBkb3RwbG90KHJhbmVmKG1vZGVsMy4xLCBjb25kVmFyPVRSVUUpLCBsYXR0aWNlLm9wdGlvbnM9bGlzdChsYXlvdXQ9YygxLDIpKSkKCiAjcmFuZWYgZ2l2ZXMgdXMgdGhlIEJMVVBzLCB3aGljaCByZXByZXNlbnRzIHRoZSByZXNwb25zZSBvZiBhIGdpdmVuIGdlbm90eXBlIHRvIHRoZSBmaXhlZCBlZmZlY3Qgb2YgdGhlIGRpZXQgYXQgZWFjaCB0ZW1wLCBhcyBkaWZmZXJlbmNlIGJldHdlbiB0aGUgZ2Vub3R5cGUncyBwcmVkaWN0ZWQgcmVzcG9uc2UgYW5kIHRoZSBwb3B1bGF0aW9uIGxldmVsIGF2ZXJhZ2UgcHJlZGljdGVkIHJlc3BvbnNlCmdlbm90eXBlX2JsdXBzIDwtIHJhbmVmKG1vZGVsMy4xKSRgTGluZWAKCmdlbm90eXBlX2luZGV4IDwtIGFzLmZhY3RvcihnZW5vdHlwZV9ibHVwcyRMaW5lKQpnZW5vdHlwZV9pbmRleCA8LSBkYXRhLmZyYW1lKHJvd25hbWVzKGdlbm90eXBlX2JsdXBzKSwgZ2Vub3R5cGVfYmx1cHMpCmdlbm90eXBlX2RhdGEgIDwtIGNiaW5kKCBnZW5vdHlwZV9pbmRleCwgZ2Vub3R5cGVfYmx1cHMpCmNvbG5hbWVzKGdlbm90eXBlX2RhdGEpIDwtIGMoIkxpbmUiLCAiQkxVUF9pbnQiLCAiQkxVUF9zbG9wZSIsICJUZW1wIiwiQkxVUF9zbG9wZV9ieV90ZW1wIiApCgojdGhlcmUgYXJlIHR3byByYW5kb20gZWZmZWN0cyBmb3IgUlJNczogaW50ZXJjZXB0IGFuZCBzbG9wZXMKI0JMVVBzIGJ5IGludGVyY2VwdCwgaW5kaWNhdGVzIHRoZSBkaWZmZXJlbmNlIGluIGdlbm90eXBlIGVsZXZhdGlvbiByZWxhdGl2ZSB0byB0aGUgcG9wdWxhdGlvbiBhdmVyYWdlLCBtb3JlICt2ZSBCTFVQIGludGVyY2VwdCBtZWFucyB0aGF0IHRoZSBnZW5vdHlwZSdzIHJlYWN0aW9uIG5vcm0gb2NjdXJzIGFib3ZlIHRoZSBwb3AtbGV2ZWwgYXZlcmFnZSByZXNwb25zZS4gLXZlIGluZGljYXRlZCB0aGUgZ2Vub3R5cGUncyByZWFjdGlvbiBub3JtIGlzIGJlbG93IHBvcC1sZXZlbCBhdmVyYWdlIHJlc3BvbnNlLiB0aGVzZSBhcmUgbm90IGEgbWVhc3VyZSBvZiBwbGFzdGljaXR5LgpnZ3Bsb3QoZ2Vub3R5cGVfZGF0YSwgYWVzKExpbmUsIEJMVVBfaW50ICkpICsKZ2VvbV9wb2ludChhZXMoZ3JvdXAgPSBMaW5lLCBjb2xvdXIgPSBMaW5lKSwgc2l6ZSA9IDQpICsKeWxhYigiQkxVUCBpbnRlcmNlcHQgZXN0aW1hdGUiKSArCmdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGx0eSA9IDIpICsgdGhlbWVfY2xhc3NpYygpCgojQkxVUHMgYnkgc2xvcGUgZXN0aW1hdGUgaXMgdGhlIGRpZmZlcmVuY2UgaW4gc2xvcGUocmVsYXRpdmUgc3RlZXBuZXNzIG9mIGNoYW5nZSkgYmV0d2VlbiB0aGUgcG9wLWxldmVsIGF2ZXJhZ2UgcmVzcG9uc2UgYW5kIHRoZSByZXNwb25zZSBvZiB0aGUgaW5kaXZpZHVhbCBnZW5vdHlwZS4KZ2dwbG90KGdlbm90eXBlX2RhdGEsIGFlcyhMaW5lLCBCTFVQX3Nsb3BlKSkgKwogIGdlb21fcG9pbnQoYWVzKGdyb3VwID0gTGluZSwgY29sb3VyID0gTGluZSksIHNpemUgPSA0KSArCnlsYWIoIlBMYXN0aWNpdHkoQkxVUCBzbG9wZSBlc3RpbWF0ZSkiKSArCmdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGx0eSA9IDIpICsgdGhlbWVfY2xhc3NpYygpCgojaXMgdGhlcmUgYW55IGNvb3JlbGF0aW9uIHdpdGggQkxVUCBpbnRlcmNlcHQgYW5kIEJMVVAgc2xvcGU/CmdncGxvdChnZW5vdHlwZV9kYXRhLCBhZXMoQkxVUF9pbnQsIEJMVVBfc2xvcGUpKSArCmdlb21fcG9pbnQoYWVzKGdyb3VwID0gTGluZSwgY29sb3VyID0gTGluZSksIHNpemUgPSA0KSArCnhsYWIoIkJMVVAgaW50ZXJjZXB0IGVzdGltYXRlIikgKwp5bGFiKCJCTFVQIHNsb3BlIGVzdGltYXRlIikgKwp0aGVtZV9jbGFzc2ljKCkKI2Fuc3dlcjogbm90IHJlYWxseSBhIHBvc2l0aXZlIGNvcmVsYXRpb24sIGFzIGNhbiBiZSBzZWVuIGZyb20gc3VtbWFyeSB0YWJsZSBvZiB0aGUgbW9kZWwgYXMgd2VsbD8KCiNyYW5rIEJMVVBzIGluIG9yZGVyLCBzb3J0IGJ5IHNsb3BlIG9mIG1vc3QgdG8gbGVhc3QgcGxhc3RpYy4gbW9yZSBuZWdhdGl2ZSBCTFVQIHNsb3BlIGVzdGltYXRlIHJlcHJlc2VudCBncmVhdGVyIHBsYXN0aWNpdHkgYW5kIG1vcmUgcG9zaXRpdmUgQkxVUCBzbG9wZSBlc3RpbWF0ZXMgcmVwcmVzZW50cyBsZXNzIHBsYXN0aWNpdHkgaW4gdGhlIHJlbGF0aXZlIHdpbmcgYXJlYSBhY3Jvc3MgbnV0cml0aW9uYWwgY29uZGl0aW9ucyBhdCAyNSB2cyAyOC4KZ2Vub3R5cGVfZGF0YSRnZW5vdHlwZV9vcmRlcmVkIDwtIGZhY3RvcihnZW5vdHlwZV9kYXRhJExpbmUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGdlbm90eXBlX2RhdGEkTGluZVtvcmRlcihnZW5vdHlwZV9kYXRhJEJMVVBfc2xvcGVfYnlfdGVtcCldKQpwbG90ZjwtZ2dwbG90KGdlbm90eXBlX2RhdGEsIGFlcyhnZW5vdHlwZV9vcmRlcmVkLCBCTFVQX3Nsb3BlX2J5X3RlbXApKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGFlcyhncm91cCA9IExpbmUsIGZpbGwgPSBMaW5lKSkgKwogIHhsYWIoIkdlbm90eXBlIChpbiByYW5rZWQgb3JkZXIgb2YgcGxhc3RpY2l0eSkiKSArCiAgeWxhYigiUGxhc3RpY2l0eSAoQkxVUCBzbG9wZSBlc3RpbWF0ZSkiKSArCiAgdGhlbWVfY2xhc3NpYygpCgoKcGRmKCIuL3Bsb3RmLnBkZiIsIHVzZURpbmdiYXRzPUZBTFNFLCB3aWR0aCA9IDEyICwgaGVpZ2h0ID0gNyApIApncmlkLmFycmFuZ2UocGxvdGYpCmRldi5vZmYoKQpgYGAKYGBge3J9CiNwbG90IHRoZSByYXcgdmFsdWVzIG9mIHdpbmcgYXJlYSBhZ2FpbnN0IG1lYW4tY2VudHJlZCBhbmQgc2NhbGVkIGRpZXRfZGlsdXRpb24gZm9yIGVhY2ggbGluZS4KZ2dwbG90KElzb3NXaW5nX3NjYWxlZCwgYWVzKHggPSBEaWV0X2RpbHV0aW9uX3NjYWxlZCwgeSA9IHdpbmdfYXJlYSwgZ3JvdXAgPSBMaW5lKSkgKwpnZW9tX2xpbmUoYWVzKGNvbG91ciA9IExpbmUpKSArIHlsYWIoIlJlbGF0aXZlIHdpbmcgYXJlYSIpICsKIHhsYWIoIk1lYW4tY2VudGVyZWQgYW5kIHNjYWxlZCByZWFyaW5nIGRpZXRfZGlsdXRpb24iKSArIGZhY2V0X2dyaWQofiBUZW1wKSt0aGVtZV9jbGFzc2ljKCkKCiNmaXQgdGhlIG1vZGVsIG9uIHRoaXMgdG8gdmlzdWFsaXNlIGZpdD8KYGBgCgoKCmBgYHtyfQpQTE9UIDwtIGdncGxvdChkYXRhID0gSXNvc1dpbmcxICAsIGFlcyh4PURpZXRfZGlsdXRpb24sIHk9d2luZ19hcmVhKSkrCnRoZW1lX2J3KCkrCiAgdGhlbWUocGFuZWwuZ3JpZD1lbGVtZW50X2JsYW5rKCksYXhpcy50aXRsZS54PWVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTYpLCBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xNCksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gIndoaXRlIiksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChmYWNlPSJpdGFsaWMiLCBzaXplPTEyKSkrIAogIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLCBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkrCiNnZW9tX3Ntb290aChhZXMoZ3JvdXA9TGluZSwgY29sb3VyPWFzLmZhY3RvcihMaW5lKSksIG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpKwpzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYyAoMTIuNSwgMjUsIDEwMCksIGd1aWRlID0gZ3VpZGVfYXhpcyhhbmdsZSA9IDYwKSkrIHNjYWxlX3lfY29udGludW91cyAobGltaXRzPSBjKDAuNywxLjIpLCBicmVha3MgPSBzZXEgKDAuNywgMS4yLCAwLjEpKSArCiMgdGhlbWUoYXhpcy50ZXh0LnggPSByb3RhdGVkQXhpc0VsZW1lbnRUZXh0KDMwLCd4JykpICsKICAjZ2VvbV9zbW9vdGggZm9yIGJsYWNrIGxpbmUgbWVhbgogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAyLCBhbHBoYSA9IDAuNSkrCmZhY2V0X2dyaWQofiBUZW1wKSsKeGxhYigiRGlldCBkaWx1dGlvbiIpK3lsYWIoIldpbmcgYXJlYSAobW0yKSIpKwogICAgZ2VvbV9ibGFuaygpCgpQTE9UCgpwZGYoIi4vNTBsaW5lc19wb3B1bGF0aW9uX21lYW5fcmVzcG9uc2UucGRmIiwgdXNlRGluZ2JhdHM9RkFMU0UpIApncmlkLmFycmFuZ2UoUExPVCkKZGV2Lm9mZigpCgpgYGAKYGBge3J9CnBkZigiLi81MGxpbmVzX3Jlc3BvbnNlLnBkZiIsIHVzZURpbmdiYXRzPUZBTFNFKSAKZ3JpZC5hcnJhbmdlKFBMT1QpCmRldi5vZmYoKQpgYGAKCgoKIApgYGB7cn0KSXNvc1dpbmcxJFRlbXAgPC0gYXMubnVtZXJpYyhJc29zV2luZzEkVGVtcCkKSXNvc1dpbmcxJERpZXRfZGlsdXRpb24gPC0gYXMubnVtZXJpYyhJc29zV2luZzEkRGlldF9kaWx1dGlvbikKYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoVGVtcCkpCklzb3NEVC5sbSA8LSBsbWVyICh3aW5nX2FyZWEgfiBUZW1wICogTGluZSAqIERpZXRfZGlsdXRpb24gKyAoMXxCbG9jayksIGRhdGEgPSBJc29zV2luZzEpICNsaW5lIGFzIGZpeGVkIGVmZmVjdCBzaW5jZSB3ZSBoYXZlIGNob3NlbiB0aGVtIGZyb20gcHJpb3IgYW5hbHlzaXMgKFJSTXMpCmFub3ZhIChJc29zRFQubG0pICNzdXBwbGltZW50YXJ5IHRhYmxlIHdpdGggd2luZyBhcmVhIGFuZCBkZXYgdGltZSwgYnV0IHJlZmVyIHRvIGl0IHNheWluZyBldnJ5dGhpbmcgZGlmZmVycwpJc29zX3RyZW5kMSA8LSBlbXRyZW5kcyhJc29zRFQubG0sIH4gVGVtcCB8IExpbmUsIHZhciA9ICJEaWV0X2RpbHV0aW9uIikKbXVsdGNvbXA6OmNsZChJc29zX3RyZW5kMSkKCklzb3NfdHJlbmQyIDwtIGVtdHJlbmRzKElzb3NEVC5sbSwgfiBMaW5lIHwgVGVtcCwgdmFyID0gIkRpZXRfZGlsdXRpb24iKQptdWx0Y29tcDo6Y2xkKElzb3NfdHJlbmQyKQoKSXNvc190cmVuZDMgPC0gZW10cmVuZHMoSXNvc0RULmxtLCB+IERpZXRfZGlsdXRpb24gfCBMaW5lLCB2YXIgPSAiVGVtcCIpCm11bHRjb21wOjpjbGQoSXNvc190cmVuZDMpCgpOZXckVGVtcCA8LSBhcy5udW1lcmljKE5ldyRUZW1wKQpOZXckRGlldF9kaWx1dGlvbiA8LSBhcy5udW1lcmljKE5ldyREaWV0X2RpbHV0aW9uKQphcy5udW1lcmljKGFzLmNoYXJhY3RlcihUZW1wKSkKSXNvc0RULmxtIDwtIGxtZXIgKHdpbmdfYXJlYSB+IFRlbXAgKiBMaW5lICogRGlldF9kaWx1dGlvbiArICgxfEJsb2NrKSwgZGF0YSA9IE5ldykgI2xpbmUgYXMgZml4ZWQgZWZmZWN0IHNpbmNlIHdlIGhhdmUgY2hvc2VuIHRoZW0gZnJvbSBwcmlvciBhbmFseXNpcyAoUlJNcykKYW5vdmEgKElzb3NEVC5sbSkgI3N1cHBsaW1lbnRhcnkgdGFibGUgd2l0aCB3aW5nIGFyZWEgYW5kIGRldiB0aW1lLCBidXQgcmVmZXIgdG8gaXQgc2F5aW5nIGV2cnl0aGluZyBkaWZmZXJzCklzb3NfdHJlbmQxIDwtIGVtdHJlbmRzKElzb3NEVC5sbSwgfiBUZW1wIHwgTGluZSwgdmFyID0gIkRpZXRfZGlsdXRpb24iKQptdWx0Y29tcDo6Y2xkKElzb3NfdHJlbmQxKQoKSXNvc190cmVuZDIgPC0gZW10cmVuZHMoSXNvc0RULmxtLCB+IExpbmUgfCBUZW1wLCB2YXIgPSAiRGlldF9kaWx1dGlvbiIpCm11bHRjb21wOjpjbGQoSXNvc190cmVuZDIpCgpJc29zX3RyZW5kMyA8LSBlbXRyZW5kcyhJc29zRFQubG0sIH4gRGlldF9kaWx1dGlvbiB8IExpbmUsIHZhciA9ICJUZW1wIikKbXVsdGNvbXA6OmNsZChJc29zX3RyZW5kMykKYGBgCgoKYGBge3J9CgpJc29zV2luZ19zY2FsZWQkVGVtcCA8LSBhcy5udW1lcmljKElzb3NXaW5nX3NjYWxlZCRUZW1wKQpJc29zV2luZ19zY2FsZWQkRGlldF9kaWx1dGlvbl9zY2FsZWQgPC0gYXMubnVtZXJpYyhJc29zV2luZ19zY2FsZWQkRGlldF9kaWx1dGlvbl9zY2FsZWQpCmFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKFRlbXApKQpJc29zRFQubG0gPC0gbG1lciAod2luZ19hcmVhIH4gVGVtcCAqIExpbmUgKiBEaWV0X2RpbHV0aW9uX3NjYWxlZCArICgxfEJsb2NrKSwgZGF0YSA9IElzb3NXaW5nX3NjYWxlZCkgI2xpbmUgYXMgZml4ZWQgZWZmZWN0IHNpbmNlIHdlIGhhdmUgY2hvc2VuIHRoZW0gZnJvbSBwcmlvciBhbmFseXNpcyAoUlJNcykKYW5vdmEgKElzb3NEVC5sbSkgI3N1cHBsaW1lbnRhcnkgdGFibGUgd2l0aCB3aW5nIGFyZWEgYW5kIGRldiB0aW1lLCBidXQgcmVmZXIgdG8gaXQgc2F5aW5nIGV2cnl0aGluZyBkaWZmZXJzCklzb3NfdHJlbmQxIDwtIGVtdHJlbmRzKElzb3NEVC5sbSwgfiBUZW1wIHwgTGluZSwgdmFyID0gIkRpZXRfZGlsdXRpb25fc2NhbGVkIikKbXVsdGNvbXA6OmNsZChJc29zX3RyZW5kMSkKCklzb3NfdHJlbmQyIDwtIGVtdHJlbmRzKElzb3NEVC5sbSwgfiBMaW5lIHwgVGVtcCwgdmFyID0gIkRpZXRfZGlsdXRpb24iKQptdWx0Y29tcDo6Y2xkKElzb3NfdHJlbmQyKQoKSXNvc190cmVuZDMgPC0gZW10cmVuZHMoSXNvc0RULmxtLCB+IERpZXRfZGlsdXRpb24gfCBMaW5lLCB2YXIgPSAiVGVtcCIpCm11bHRjb21wOjpjbGQoSXNvc190cmVuZDMpCgpOZXckVGVtcCA8LSBhcy5udW1lcmljKE5ldyRUZW1wKQpOZXckRGlldF9kaWx1dGlvbiA8LSBhcy5udW1lcmljKE5ldyREaWV0X2RpbHV0aW9uKQphcy5udW1lcmljKGFzLmNoYXJhY3RlcihUZW1wKSkKSXNvc0RULmxtIDwtIGxtZXIgKHdpbmdfYXJlYSB+IFRlbXAgKiBMaW5lICogRGlldF9kaWx1dGlvbiArICgxfEJsb2NrKSwgZGF0YSA9IE5ldykgI2xpbmUgYXMgZml4ZWQgZWZmZWN0IHNpbmNlIHdlIGhhdmUgY2hvc2VuIHRoZW0gZnJvbSBwcmlvciBhbmFseXNpcyAoUlJNcykKYW5vdmEgKElzb3NEVC5sbSkgI3N1cHBsaW1lbnRhcnkgdGFibGUgd2l0aCB3aW5nIGFyZWEgYW5kIGRldiB0aW1lLCBidXQgcmVmZXIgdG8gaXQgc2F5aW5nIGV2cnl0aGluZyBkaWZmZXJzCklzb3NfdHJlbmQxIDwtIGVtdHJlbmRzKElzb3NEVC5sbSwgfiBUZW1wIHwgTGluZSwgdmFyID0gIkRpZXRfZGlsdXRpb24iKQptdWx0Y29tcDo6Y2xkKElzb3NfdHJlbmQxKQoKSXNvc190cmVuZDIgPC0gZW10cmVuZHMoSXNvc0RULmxtLCB+IExpbmUgfCBUZW1wLCB2YXIgPSAiRGlldF9kaWx1dGlvbiIpCm11bHRjb21wOjpjbGQoSXNvc190cmVuZDIpCgpJc29zX3RyZW5kMyA8LSBlbXRyZW5kcyhJc29zRFQubG0sIH4gRGlldF9kaWx1dGlvbiB8IExpbmUsIHZhciA9ICJUZW1wIikKbXVsdGNvbXA6OmNsZChJc29zX3RyZW5kMykKYGBgCgoKICAKYGBge3J9CiNsaW5lcyBmcm9tIHRoZSB0d28gZW5kcyBvZiB0aGUgQkxVUCBzbG9wZSBlc3RpbWF0ZSByYW5rZWQgcGxvdApOZXcgPC0gSXNvc1dpbmcxICU+JSBmaWx0ZXIoTGluZT09IjIxIiB8IExpbmU9PSI2MyIgfCBMaW5lPT0iNTUiIHwgTGluZT09IjM2InxMaW5lPT0iNTYiIHwgTGluZT09IjIwIiB8IExpbmU9PSIyMiIgfCBMaW5lPT0iODUiICkKCiNsaW5lcyB0aGF0IEkgaGFkIHNlbGVjdGVkIGFuZCBjdXJyZW50bHkgZXhwYW5kZWQgYXQgMjUnQwpOZXcgPC0gSXNvc1dpbmcxICU+JSBmaWx0ZXIoTGluZT09IjIxIiB8IExpbmU9PSI2MyIgfCBMaW5lPT0iMzYifExpbmU9PSI1NiIgIHwgTGluZT09Ijg1IiApCgpQTE9UMiA8LSBnZ3Bsb3QoZGF0YSA9IE5ldywgYWVzKHg9RGlldF9kaWx1dGlvbiwgeT13aW5nX2FyZWEpKSsKdGhlbWVfYncoKSsKIHRoZW1lKHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoc2l6ZT0xNiksIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoc2l6ZT0xNiksIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgpLCBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJ3aGl0ZSIpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoZmFjZT0iaXRhbGljIiwgc2l6ZT0xMikpKyAKICB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSsgCiAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSsKICBnZW9tX3Ntb290aChhZXMoZ3JvdXA9TGluZSwgY29sb3VyPWFzLmZhY3RvcihMaW5lKSksIG1ldGhvZD0ibG0iLCBzZT1GQUxTRSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDIsIGFscGhhID0gMC41KSsKICBzY2FsZV94X2NvbnRpbnVvdXMoIGJyZWFrcyA9IGMgKDEyLjUsIDI1LCAxMDApLCBndWlkZSA9IGd1aWRlX2F4aXMoYW5nbGUgPSA2MCkpKyBzY2FsZV95X2NvbnRpbnVvdXMgKGxpbWl0cz0gYygwLjY1LDEuMjUpLCBicmVha3MgPSBzZXEgKDAuNjUsIDEuMjUsIDAuMSkpICsgCiAgZ2VvbV9qaXR0ZXIgKGFlcyhncm91cD1MaW5lLCBjb2xvdXI9YXMuZmFjdG9yKExpbmUpKSwgYWxwaGE9MC4zKSsKZmFjZXRfZ3JpZCh+IFRlbXApKyB4bGFiKCJEaWV0IGRpbHV0aW9uIikreWxhYigiV2luZyBhcmVhIChtbTIpIikrCiAgICBnZW9tX2JsYW5rKCkKClBMT1QyCgpgYGAKYGBge3J9CnBkZigiLi81bGluZXNfcmVzcG9uc2UucGRmIiwgdXNlRGluZ2JhdHM9RkFMU0UpIApncmlkLmFycmFuZ2UoUExPVDIpCmRldi5vZmYoKQpgYGAKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDbWQrT3B0aW9uK0kqLgoKV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDbWQrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4gCgpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuCgo=