Load all necessary packages for analysis

library(ggplot2)
library(ggthemes)
library(RColorBrewer)
library(extrafont)
library(grid)
library(tidyr)
library(plyr)
library(car)

Load in my dataset. Cleaning the dataset of any toads we don’t have the lifestage for and one outlier that is an obvious measurement error

setwd('/Users/Connor/Dropbox/Old Mac/School_Stuff/Amphibian Seminar/Cane toad project')
toads = read.csv('Cane.Toad.Data.csv')
toads = toads[1:13]
toads = toads %>% drop_na(Year) %>% drop_na(Lifestage)
toads = subset(toads, Catalog != 23988)

Create new columns in my data set for tibia difference correction, from Palmer 1994. This adjustment corrects for size-biased tibia length differences. Eq: 2 * abs(Right - Left) / (Right - Left)

tibia_dif = toads$Tibia_Right - toads$Tibia_Left
tibia_correction = (toads$Tibia_Right + toads$Tibia_Left) / 2 
tibia_corrected = tibia_dif/tibia_correction
toads = cbind(toads, tibia_dif)
toads = cbind(toads, tibia_correction)
toads = cbind(toads, tibia_corrected)
toads = droplevels.data.frame(toads)

I’m grouping years for a categorical analysis of FA across years that I’ll perform later. The sample sizes aren’t even across blocks of years (1960s- 5, 1970s- 56 (16 S, 40 C), 1990s- 60 (45 S, 15 C), 2000s- 42 (15 S, 27 C)). This is important for later analyses, where we will have to conduct a type III anova for an unbalanced design. Since our sample size from the 1960s is so small, we need to obtain more measurements for a publication-worthy analysis.

breaks_yrs = c(0, 1970,1980,1999,2015)
labels_yrs = c('sixties', 'seventies', 'nineties', 'oughts')
toads$year_groups = cut(toads$Year,
                                    breaks = breaks_yrs,
                                    labels = labels_yrs)
#year_groups plot
ggplot(toads, aes(x = year_groups, fill = Region)) + 
  geom_bar()

For statistical analysis, I excluded the 1960s individuals. It doesn’t include both regions and has a tiny sample size (N = 5). If I include the 1960s, I run into the problem of perfect multicollinearity, and the 2000s southern region tibia differences get excluded from the model.

toads_new = droplevels(subset(toads, year_groups != 'sixties'))

Justification for inclusion of juveniles. Juveniles don’t appear to differ from adults. The low number of juveniles doesn’t justify the use of a statistical test.

juveniles = subset(toads_new, toads_new$Lifestage == "J")
#histogram
ggplot(juveniles, aes(x = abs(tibia_corrected), fill = Region)) +
  geom_histogram(alpha = 0.75, binwidth = 0.005, position = 'dodge') +
  geom_density(alpha = 0, aes(color = Region))

#scatterplot of juveniles
ggplot(juveniles, aes(x = Year, y = abs(tibia_corrected), color = Region)) +
  geom_point(alpha = 0.75)

#scatterplot of juveniles vs. adults
ggplot(toads_new, aes(x = Year, y = abs(tibia_corrected), color = Lifestage)) +
  geom_point(alpha = 0.75)

The beginning of my tibia FA analysis. My workflow (checking assumptions aside) is as follows: 1) Correct for size. -I did the actual correction earlier to accomodate for adding a year grouping variable. Below is my assessment to make sure it was necessary 2) Check distribution of tibia length differences 3) Assess directional asymmetry 4) Assess fluctuating asymmetry 5) Compare fluctuating asymmetry

Step 1) Correct for size. I am checking to make sure a size correction is necessary.

plot(tibia_dif ~ SVL, data = toads_new)

plot(abs(tibia_dif) ~ tibia_correction, data = toads_new)

It is. SVL definitely varies with differences in tibia length.

Step 2) Check the distribution of tibia length differences. A non-normal distribution may lead to incorrect statistical inference later on.

Total sample:

shapiro.test(toads_new$tibia_corrected)

    Shapiro-Wilk normality test

data:  toads_new$tibia_corrected
W = 0.91112, p-value = 3.118e-08
ggplot(toads_new, aes(x = tibia_corrected)) + 
  geom_histogram(binwidth = 0.005) +
  geom_density(alpha = 0, color = 'red')

The distribution of tibia differences is leptokurtic. This may lead to an overabundance of false negatives.

Southern Region:

shapiro.test(toads_new$tibia_corrected[toads_new$Region == 'South'])

    Shapiro-Wilk normality test

data:  toads_new$tibia_corrected[toads_new$Region == "South"]
W = 0.9205, p-value = 0.0001499
ggplot(subset(toads_new, Region == "South"), aes(x = tibia_corrected)) + 
  geom_histogram(binwidth = 0.005) +
  geom_density(alpha = 0, color = 'red') +
  labs(x = "Tibia Differences (South)")

Also leptokurtic. An outlier may affect the test as well.

Central Region:

shapiro.test(toads_new$tibia_corrected[toads_new$Region == 'Central'])

    Shapiro-Wilk normality test

data:  toads_new$tibia_corrected[toads_new$Region == "Central"]
W = 0.85828, p-value = 2.376e-07
ggplot(subset(toads_new, Region == "Central"), aes(x = tibia_corrected)) + 
  geom_histogram(binwidth = 0.005) +
  geom_density(alpha = 0, color = 'red') +
  labs(x = "Tibia Differences (Central)")

Leptokurtic and may also be slightly left-skewed.

QQplots of the three distributions.

par(mfrow = c(2,2))
qqnorm(total_dist, main = 'Total')
qqline(total_dist)
qqnorm(south_dist, main = 'South')
qqline(south_dist)
qqnorm(central_dist, main = 'Central')
qqline(central_dist)

This tells us that our analysis may not be ideal for a study of fluctuating asymmetry since our distributions are not normal. Since the distributions are mainly leptokurtic and not extremely right or left skewed, I think interpretations of any significant test statistics will be accurate.

Step 3) Assessment of directional assymetry. Looking at the plots above, there doesn’t appear to be any, but I will use a one-sample t-test to test for any deviations of mean tibia differences from zero to check.

DA Total:

t.test(toads_new$tibia_corrected)

    One Sample t-test

data:  toads_new$tibia_corrected
t = -0.36686, df = 157, p-value = 0.7142
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 -0.004881135  0.003351951
sample estimates:
    mean of x 
-0.0007645922 

There is no significant directional asymmetry.

DA South:

t.test(toads_new$tibia_corrected[toads_new$Region == 'South'])

    One Sample t-test

data:  toads_new$tibia_corrected[toads_new$Region == "South"]
t = 1.1499, df = 75, p-value = 0.2538
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 -0.002477156  0.009242170
sample estimates:
  mean of x 
0.003382507 

There is no significant directional asymmetry.

DA Central:

t.test(toads_new$tibia_corrected[toads_new$Region == 'Central'])

    One Sample t-test

data:  toads_new$tibia_corrected[toads_new$Region == "Central"]
t = -1.5883, df = 81, p-value = 0.1161
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 -0.010381026  0.001164535
sample estimates:
   mean of x 
-0.004608245 

There is no significant directional asymmetry.

Step 4) Assess fluctuating asymmetry.

Total FA:

t.test(abs(toads_new$tibia_corrected)) #p < 0.001 ###Do this per region

    One Sample t-test

data:  abs(toads_new$tibia_corrected)
t = 10.052, df = 157, p-value < 2.2e-16
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 0.01313521 0.01956003
sample estimates:
 mean of x 
0.01634762 
ggplot(toads_new, aes(x = abs(tibia_corrected))) + 
  geom_histogram(binwidth = 0.005) +
  geom_density(alpha = 0, color = 'red') +
  labs(x = "Tibia Difference Magnitudes")

There is significant overall fluctuating asymmetry.

South FA:

t.test(abs(toads_new$tibia_corrected[toads_new$Region == 'South']))

    One Sample t-test

data:  abs(toads_new$tibia_corrected[toads_new$Region == "South"])
t = 7.9618, df = 75, p-value = 1.411e-11
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 0.01304029 0.02174342
sample estimates:
 mean of x 
0.01739186 
ggplot(subset(toads_new, Region == 'South'), aes(x = abs(tibia_corrected))) + 
  geom_histogram(binwidth = 0.005) +
  geom_density(alpha = 0, color = 'red') +
  labs(x = "Tibia Difference Magnitudes (South)")

There is significant fluctuating asymmetry in the southern region.

Central FA:

t.test(abs(toads_new$tibia_corrected[toads_new$Region == 'Central']))

    One Sample t-test

data:  abs(toads_new$tibia_corrected[toads_new$Region == "Central"])
t = 6.4084, df = 81, p-value = 9.11e-09
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 0.01060463 0.02015495
sample estimates:
 mean of x 
0.01537979 
ggplot(subset(toads_new, Region == 'Central'), aes(x = abs(tibia_corrected))) + 
  geom_histogram(binwidth = 0.005) +
  geom_density(alpha = 0, color = 'red') +
  labs(x = "Tibia Difference Magnitudes (Central)")

There is significant fluctuating asymmetry in the central region.

Step 4) Compare fluctuating asymmetry levels. I approached the comparison by both binning years into categorical variables and including years as a continuous variable.

First I need to check assumptions and any potential confounding affects that I can account for.

Assumptions:

#linear model fit
fit_cat = lm(abs(tibia_corrected) ~ Region * year_groups, data = toads_new)
#Check assumptions
par(mfrow = c(2, 2))
plot(fit_cat)

The response deviates quite a bit from normality, and the residuals vs leverage plot extends beyond Cook’s distance. Therefore, I need to transform the response variable.

I’m transforming the corrected tibia lengths with a logit transformation since we have proportional data that is not binomial. I had to set a low number (the lowest non-zero tibia length difference) so there are no infinity values.

Here’s the transformation compared to the non-transformed data.

logit_tibia = logit(abs(toads_new$tibia_corrected), adjust = 0.001177941) #Change
toads_new = cbind.data.frame(toads_new, logit_tibia)
par(mfrow = c(1, 2)) #to compare the distributions
plot(toads_new$logit_tibia)
plot(abs(toads_new$tibia_corrected)) 

It looks overall more varied with fewer outliers.

Testing the assumptions again with transformed data:

fit_tibia = lm(logit_tibia ~ Region * year_groups, data = toads_new)
plot(fit_tibia)

This still deviates a bit from normality, but is better than the untransformed data. The variance is more even as well.

Now I need to make sure sex doesn’t covary with either year or region.

Year:

ggplot(toads_new, aes(x = year_groups, y = abs(tibia_corrected), fill = Sex)) +
  geom_boxplot(alpha = 0.75)

fit_sex_year = lm(logit_tibia ~ Sex * year_groups, data = toads_new)
model_fit_sex_year = Anova(fit_sex_year, type = 3) 
model_fit_sex_year
Anova Table (Type III tests)

Response: logit_tibia
                Sum Sq  Df F value Pr(>F)    
(Intercept)        515   1  263.30 <2e-16 ***
Sex                  1   1    0.26   0.61    
year_groups          3   2    0.65   0.52    
Sex:year_groups      2   2    0.52   0.59    
Residuals          231 118                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Region:

ggplot(toads_new, aes(x = Region, y = abs(tibia_corrected), fill = Sex)) +
  geom_boxplot(alpha = 0.75)

fit_sex_region = lm(logit_tibia ~ Sex * Region, data = toads_new)
model_fit_sex_region = Anova(fit_sex_region, type = 3)
model_fit_sex_region
Anova Table (Type III tests)

Response: logit_tibia
            Sum Sq  Df F value Pr(>F)    
(Intercept)    930   1  486.96 <2e-16 ***
Sex              3   1    1.37  0.245    
Region           0   1    0.01  0.909    
Sex:Region       5   1    2.85  0.094 .  
Residuals      229 120                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Sex doesn’t affect anything, so we’re good to continue.

It’s finally time to make the model!

ggplot(toads_new, aes(x = year_groups, y = logit_tibia, color = Region)) +
  geom_boxplot(alpha = 0.75) +
  scale_y_continuous(limits = c(-10, 0))

model_cat_trans = Anova(fit_tibia, type = 3)
model_cat_trans
Anova Table (Type III tests)

Response: logit_tibia
                   Sum Sq  Df F value  Pr(>F)    
(Intercept)          1191   1  646.88 < 2e-16 ***
Region                 28   1   15.09 0.00015 ***
year_groups            14   2    3.89 0.02252 *  
Region:year_groups     22   2    6.08 0.00288 ** 
Residuals             280 152                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Since the time frame from the 1990s-2000s doesn’t have a clear-cut separation, I’m also going to analyze the data with a linear model. The linear model assumptions are met, so we can go ahead and look at the least-squares regression.

ggplot(toads_new, aes(x = Year, y = logit_tibia, color = Region)) +
  geom_point(alpha = 0.75) +
  geom_smooth(method = "lm")

fit_continuous = lm(logit_tibia ~ Region * Year, data = toads_new)
summary(fit_continuous)

Call:
lm(formula = logit_tibia ~ Region * Year, data = toads_new)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.1357 -1.3842  0.0511  1.0649  2.7544 

Coefficients:
                 Estimate Std. Error t value Pr(>|t|)   
(Intercept)      -50.7549    23.8993   -2.12   0.0353 * 
RegionSouth      134.4906    44.1253    3.05   0.0027 **
Year               0.0229     0.0120    1.91   0.0578 . 
RegionSouth:Year  -0.0672     0.0221   -3.04   0.0028 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.37 on 154 degrees of freedom
Multiple R-squared:  0.0924,    Adjusted R-squared:  0.0748 
F-statistic: 5.23 on 3 and 154 DF,  p-value: 0.00183

I reran the model using the southern region as the reference region, so we can see the change across years for the central region.

fit_continuous_C = lm(logit_tibia ~ relevel(Region, ref = 'South') * Year, data = toads_new)
summary(fit_continuous_C)

Call:
lm(formula = logit_tibia ~ relevel(Region, ref = "South") * Year, 
    data = toads_new)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.1357 -1.3842  0.0511  1.0649  2.7544 

Coefficients:
                                            Estimate Std. Error t value Pr(>|t|)   
(Intercept)                                  83.7357    37.0926    2.26   0.0254 * 
relevel(Region, ref = "South")Central      -134.4906    44.1253   -3.05   0.0027 **
Year                                         -0.0443     0.0186   -2.38   0.0186 * 
relevel(Region, ref = "South")Central:Year    0.0672     0.0221    3.04   0.0028 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.37 on 154 degrees of freedom
Multiple R-squared:  0.0924,    Adjusted R-squared:  0.0748 
F-statistic: 5.23 on 3 and 154 DF,  p-value: 0.00183

I think the general trends are more clear with the continuous model, but the initial increase in FA with subsequent decrease in FA over time with the Central region gets lost with a single regression line.

Here’s a plot of tibia differences across years when including the sixties specimens. It shows the initial increase and subsequent decrease in FA for the southern region specimens shifted ahead of the central region’s similar pattern.

ggplot(toads, aes(x = year_groups, y = logit_tibia, fill = Region)) +
  geom_boxplot(alpha = 0.75) +
  scale_y_continuous(limits = c(-10, 0))

To obtain an index of relative tibia length, we conducted a general linear regression of mean tibia length against SVL and extracted the residuals.

length_glm = glm(mean_tibia ~ SVL, data = toads_new)
length_residuals = length_glm$residuals
toads_new = cbind(toads_new, length_residuals)

We then constructed an ANCOVA with relative tibia length as the response and the interaction of region and year as the fixed effect

ggplot(toads_new, aes(x = year_groups, y = length_residuals, color = Region)) +
  geom_boxplot() +
  scale_y_continuous(limits = c(-7, 7))

#model.
length_yr_fit = lm(length_residuals ~ Region * year_groups, 
                       data = toads_new)
length_yr_model = Anova(length_yr_fit, type = 3)
length_yr_model
Anova Table (Type III tests)

Response: length_residuals
                   Sum Sq  Df F value  Pr(>F)  
(Intercept)          3.65   1  0.9999 0.31893  
Region              12.55   1  3.4337 0.06582 .
year_groups         29.78   2  4.0740 0.01890 *
Region:year_groups  11.39   2  1.5575 0.21400  
Residuals          555.62 152                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Plot of leg length across time, including the 1960s individuals

mean_tibia_old = (toads$Tibia_Left + toads$Tibia_Right) / 2
toads = cbind(toads, mean_tibia_old)
#Correct for SVL by using residuals of GLM
length_glm_old = glm(mean_tibia_old ~ SVL, data = toads)
length_residuals_old = length_glm_old$residuals
toads = cbind(toads, length_residuals_old)
##Linear model of length residuals as a function of year
#plot
ggplot(toads, aes(x = year_groups, y = length_residuals_old, color = Region)) +
  geom_boxplot() +
  scale_y_continuous(limits = c(-7, 7))

LS0tCnRpdGxlOiAiQ2FuZSBUb2FkIEFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpMb2FkIGFsbCBuZWNlc3NhcnkgcGFja2FnZXMgZm9yIGFuYWx5c2lzCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KGV4dHJhZm9udCkKbGlicmFyeShncmlkKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHBseXIpCmxpYnJhcnkoY2FyKQpgYGAKCgpMb2FkIGluIG15IGRhdGFzZXQuIENsZWFuaW5nIHRoZSBkYXRhc2V0IG9mIGFueSB0b2FkcyB3ZSBkb24ndCBoYXZlIHRoZSBsaWZlc3RhZ2UgZm9yIGFuZCBvbmUgb3V0bGllciB0aGF0IGlzIGFuIG9idmlvdXMgbWVhc3VyZW1lbnQgZXJyb3IKYGBge3J9CnNldHdkKCcvVXNlcnMvQ29ubm9yL0Ryb3Bib3gvT2xkIE1hYy9TY2hvb2xfU3R1ZmYvQW1waGliaWFuIFNlbWluYXIvQ2FuZSB0b2FkIHByb2plY3QnKQp0b2FkcyA9IHJlYWQuY3N2KCdDYW5lLlRvYWQuRGF0YS5jc3YnKQp0b2FkcyA9IHRvYWRzWzE6MTNdCnRvYWRzID0gdG9hZHMgJT4lIGRyb3BfbmEoWWVhcikgJT4lIGRyb3BfbmEoTGlmZXN0YWdlKQp0b2FkcyA9IHN1YnNldCh0b2FkcywgQ2F0YWxvZyAhPSAyMzk4OCkKYGBgCgpDcmVhdGUgbmV3IGNvbHVtbnMgaW4gbXkgZGF0YSBzZXQgZm9yIHRpYmlhIGRpZmZlcmVuY2UgY29ycmVjdGlvbiwgZnJvbSBQYWxtZXIgMTk5NC4gVGhpcyBhZGp1c3RtZW50IGNvcnJlY3RzIGZvciBzaXplLWJpYXNlZCB0aWJpYSBsZW5ndGggZGlmZmVyZW5jZXMuIEVxOiAyICogYWJzKFJpZ2h0IC0gTGVmdCkgLyAoUmlnaHQgLSBMZWZ0KQpgYGB7cn0KdGliaWFfZGlmID0gdG9hZHMkVGliaWFfUmlnaHQgLSB0b2FkcyRUaWJpYV9MZWZ0CnRpYmlhX2NvcnJlY3Rpb24gPSAodG9hZHMkVGliaWFfUmlnaHQgKyB0b2FkcyRUaWJpYV9MZWZ0KSAvIDIgCnRpYmlhX2NvcnJlY3RlZCA9IHRpYmlhX2RpZi90aWJpYV9jb3JyZWN0aW9uCnRvYWRzID0gY2JpbmQodG9hZHMsIHRpYmlhX2RpZikKdG9hZHMgPSBjYmluZCh0b2FkcywgdGliaWFfY29ycmVjdGlvbikKdG9hZHMgPSBjYmluZCh0b2FkcywgdGliaWFfY29ycmVjdGVkKQp0b2FkcyA9IGRyb3BsZXZlbHMuZGF0YS5mcmFtZSh0b2FkcykKYGBgCgpJJ20gZ3JvdXBpbmcgeWVhcnMgZm9yIGEgY2F0ZWdvcmljYWwgYW5hbHlzaXMgb2YgRkEgYWNyb3NzIHllYXJzIHRoYXQgSSdsbCBwZXJmb3JtIGxhdGVyLiBUaGUgc2FtcGxlIHNpemVzIGFyZW4ndCBldmVuIGFjcm9zcyBibG9ja3Mgb2YgeWVhcnMgKDE5NjBzLSA1LCAxOTcwcy0gNTYgKDE2IFMsIDQwIEMpLCAxOTkwcy0gNjAgKDQ1IFMsIDE1IEMpLCAyMDAwcy0gNDIgKDE1IFMsIDI3IEMpKS4gVGhpcyBpcyBpbXBvcnRhbnQgZm9yIGxhdGVyIGFuYWx5c2VzLCB3aGVyZSB3ZSB3aWxsIGhhdmUgdG8gY29uZHVjdCBhIHR5cGUgSUlJIGFub3ZhIGZvciBhbiB1bmJhbGFuY2VkIGRlc2lnbi4gIFNpbmNlIG91ciBzYW1wbGUgc2l6ZSBmcm9tIHRoZSAxOTYwcyBpcyBzbyBzbWFsbCwgd2UgbmVlZCB0byBvYnRhaW4gbW9yZSBtZWFzdXJlbWVudHMgZm9yIGEgcHVibGljYXRpb24td29ydGh5IGFuYWx5c2lzLgpgYGB7cn0KYnJlYWtzX3lycyA9IGMoMCwgMTk3MCwxOTgwLDE5OTksMjAxNSkKbGFiZWxzX3lycyA9IGMoJ3NpeHRpZXMnLCAnc2V2ZW50aWVzJywgJ25pbmV0aWVzJywgJ291Z2h0cycpCnRvYWRzJHllYXJfZ3JvdXBzID0gY3V0KHRvYWRzJFllYXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGJyZWFrc195cnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGxhYmVsc195cnMpCiN5ZWFyX2dyb3VwcyBwbG90CmdncGxvdCh0b2FkcywgYWVzKHggPSB5ZWFyX2dyb3VwcywgZmlsbCA9IFJlZ2lvbikpICsgCiAgZ2VvbV9iYXIoKQpgYGAKCkZvciBzdGF0aXN0aWNhbCBhbmFseXNpcywgSSBleGNsdWRlZCB0aGUgMTk2MHMgaW5kaXZpZHVhbHMuIEl0IGRvZXNuJ3QgaW5jbHVkZSBib3RoIHJlZ2lvbnMgYW5kIGhhcyBhIHRpbnkgc2FtcGxlIHNpemUgKE4gPSA1KS4gSWYgSSBpbmNsdWRlIHRoZSAxOTYwcywgSSBydW4gaW50byB0aGUgcHJvYmxlbSBvZiBwZXJmZWN0IG11bHRpY29sbGluZWFyaXR5LCBhbmQgdGhlIDIwMDBzIHNvdXRoZXJuIHJlZ2lvbiB0aWJpYSBkaWZmZXJlbmNlcyBnZXQgZXhjbHVkZWQgZnJvbSB0aGUgbW9kZWwuCgpgYGB7cn0KdG9hZHNfbmV3ID0gZHJvcGxldmVscyhzdWJzZXQodG9hZHMsIHllYXJfZ3JvdXBzICE9ICdzaXh0aWVzJykpCmBgYAoKCkp1c3RpZmljYXRpb24gZm9yIGluY2x1c2lvbiBvZiBqdXZlbmlsZXMuIEp1dmVuaWxlcyBkb24ndCBhcHBlYXIgdG8gZGlmZmVyIGZyb20gYWR1bHRzLiBUaGUgbG93IG51bWJlciBvZiBqdXZlbmlsZXMgZG9lc24ndCBqdXN0aWZ5IHRoZSB1c2Ugb2YgYSBzdGF0aXN0aWNhbCB0ZXN0LgpgYGB7cn0KanV2ZW5pbGVzID0gc3Vic2V0KHRvYWRzX25ldywgdG9hZHNfbmV3JExpZmVzdGFnZSA9PSAiSiIpCiNoaXN0b2dyYW0KZ2dwbG90KGp1dmVuaWxlcywgYWVzKHggPSBhYnModGliaWFfY29ycmVjdGVkKSwgZmlsbCA9IFJlZ2lvbikpICsKICBnZW9tX2hpc3RvZ3JhbShhbHBoYSA9IDAuNzUsIGJpbndpZHRoID0gMC4wMDUsIHBvc2l0aW9uID0gJ2RvZGdlJykgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAsIGFlcyhjb2xvciA9IFJlZ2lvbikpCiNzY2F0dGVycGxvdCBvZiBqdXZlbmlsZXMKZ2dwbG90KGp1dmVuaWxlcywgYWVzKHggPSBZZWFyLCB5ID0gYWJzKHRpYmlhX2NvcnJlY3RlZCksIGNvbG9yID0gUmVnaW9uKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KQojc2NhdHRlcnBsb3Qgb2YganV2ZW5pbGVzIHZzLiBhZHVsdHMKZ2dwbG90KHRvYWRzX25ldywgYWVzKHggPSBZZWFyLCB5ID0gYWJzKHRpYmlhX2NvcnJlY3RlZCksIGNvbG9yID0gTGlmZXN0YWdlKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KQpgYGAKClRoZSBiZWdpbm5pbmcgb2YgbXkgdGliaWEgRkEgYW5hbHlzaXMuIE15IHdvcmtmbG93IChjaGVja2luZyBhc3N1bXB0aW9ucyBhc2lkZSkgaXMgYXMgZm9sbG93czoKICAxKSBDb3JyZWN0IGZvciBzaXplLiAKICAgIC1JIGRpZCB0aGUgYWN0dWFsIGNvcnJlY3Rpb24gZWFybGllciB0byBhY2NvbW9kYXRlIGZvciBhZGRpbmcgYSB5ZWFyIGdyb3VwaW5nIHZhcmlhYmxlLiBCZWxvdyBpcyBteSBhc3Nlc3NtZW50IHRvIG1ha2Ugc3VyZSBpdCB3YXMgbmVjZXNzYXJ5CiAgMikgQ2hlY2sgZGlzdHJpYnV0aW9uIG9mIHRpYmlhIGxlbmd0aCBkaWZmZXJlbmNlcwogIDMpIEFzc2VzcyBkaXJlY3Rpb25hbCBhc3ltbWV0cnkKICA0KSBBc3Nlc3MgZmx1Y3R1YXRpbmcgYXN5bW1ldHJ5CiAgNSkgQ29tcGFyZSBmbHVjdHVhdGluZyBhc3ltbWV0cnkKICAKU3RlcCAxKSBDb3JyZWN0IGZvciBzaXplLiBJIGFtIGNoZWNraW5nIHRvIG1ha2Ugc3VyZSBhIHNpemUgY29ycmVjdGlvbiBpcyBuZWNlc3NhcnkuCmBgYHtyfQpwbG90KHRpYmlhX2RpZiB+IFNWTCwgZGF0YSA9IHRvYWRzX25ldykKcGxvdChhYnModGliaWFfZGlmKSB+IHRpYmlhX2NvcnJlY3Rpb24sIGRhdGEgPSB0b2Fkc19uZXcpCmBgYAoKSXQgaXMuIFNWTCBkZWZpbml0ZWx5IHZhcmllcyB3aXRoIGRpZmZlcmVuY2VzIGluIHRpYmlhIGxlbmd0aC4KClN0ZXAgMikgQ2hlY2sgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aWJpYSBsZW5ndGggZGlmZmVyZW5jZXMuCkEgbm9uLW5vcm1hbCBkaXN0cmlidXRpb24gbWF5IGxlYWQgdG8gaW5jb3JyZWN0IHN0YXRpc3RpY2FsIGluZmVyZW5jZSBsYXRlciBvbi4KClRvdGFsIHNhbXBsZToKCmBgYHtyfQpzaGFwaXJvLnRlc3QodG9hZHNfbmV3JHRpYmlhX2NvcnJlY3RlZCkKZ2dwbG90KHRvYWRzX25ldywgYWVzKHggPSB0aWJpYV9jb3JyZWN0ZWQpKSArIAogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMDUpICsKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLCBjb2xvciA9ICdyZWQnKQpgYGAKClRoZSBkaXN0cmlidXRpb24gb2YgdGliaWEgZGlmZmVyZW5jZXMgaXMgbGVwdG9rdXJ0aWMuIFRoaXMgbWF5IGxlYWQgdG8gYW4gb3ZlcmFidW5kYW5jZSBvZiBmYWxzZSBuZWdhdGl2ZXMuCgpTb3V0aGVybiBSZWdpb246CmBgYHtyfQpzaGFwaXJvLnRlc3QodG9hZHNfbmV3JHRpYmlhX2NvcnJlY3RlZFt0b2Fkc19uZXckUmVnaW9uID09ICdTb3V0aCddKQpnZ3Bsb3Qoc3Vic2V0KHRvYWRzX25ldywgUmVnaW9uID09ICJTb3V0aCIpLCBhZXMoeCA9IHRpYmlhX2NvcnJlY3RlZCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAwNSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAsIGNvbG9yID0gJ3JlZCcpICsKICBsYWJzKHggPSAiVGliaWEgRGlmZmVyZW5jZXMgKFNvdXRoKSIpCmBgYAoKQWxzbyBsZXB0b2t1cnRpYy4gQW4gb3V0bGllciBtYXkgYWZmZWN0IHRoZSB0ZXN0IGFzIHdlbGwuCgpDZW50cmFsIFJlZ2lvbjoKYGBge3J9CnNoYXBpcm8udGVzdCh0b2Fkc19uZXckdGliaWFfY29ycmVjdGVkW3RvYWRzX25ldyRSZWdpb24gPT0gJ0NlbnRyYWwnXSkKZ2dwbG90KHN1YnNldCh0b2Fkc19uZXcsIFJlZ2lvbiA9PSAiQ2VudHJhbCIpLCBhZXMoeCA9IHRpYmlhX2NvcnJlY3RlZCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAwNSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAsIGNvbG9yID0gJ3JlZCcpICsKICBsYWJzKHggPSAiVGliaWEgRGlmZmVyZW5jZXMgKENlbnRyYWwpIikKYGBgCgpMZXB0b2t1cnRpYyBhbmQgbWF5IGFsc28gYmUgc2xpZ2h0bHkgbGVmdC1za2V3ZWQuCgpRUXBsb3RzIG9mIHRoZSB0aHJlZSBkaXN0cmlidXRpb25zLgoKYGBge3J9CnBhcihtZnJvdyA9IGMoMiwyKSkKcXFub3JtKHRvdGFsX2Rpc3QsIG1haW4gPSAnVG90YWwnKQpxcWxpbmUodG90YWxfZGlzdCkKcXFub3JtKHNvdXRoX2Rpc3QsIG1haW4gPSAnU291dGgnKQpxcWxpbmUoc291dGhfZGlzdCkKcXFub3JtKGNlbnRyYWxfZGlzdCwgbWFpbiA9ICdDZW50cmFsJykKcXFsaW5lKGNlbnRyYWxfZGlzdCkKYGBgCgoKVGhpcyB0ZWxscyB1cyB0aGF0IG91ciBhbmFseXNpcyBtYXkgbm90IGJlIGlkZWFsIGZvciBhIHN0dWR5IG9mIGZsdWN0dWF0aW5nIGFzeW1tZXRyeSBzaW5jZSBvdXIgZGlzdHJpYnV0aW9ucyBhcmUgbm90IG5vcm1hbC4gU2luY2UgdGhlIGRpc3RyaWJ1dGlvbnMgYXJlIG1haW5seSBsZXB0b2t1cnRpYyBhbmQgbm90IGV4dHJlbWVseSByaWdodCBvciBsZWZ0IHNrZXdlZCwgSSB0aGluayBpbnRlcnByZXRhdGlvbnMgb2YgYW55IHNpZ25pZmljYW50IHRlc3Qgc3RhdGlzdGljcyB3aWxsIGJlIGFjY3VyYXRlLgoKU3RlcCAzKSBBc3Nlc3NtZW50IG9mIGRpcmVjdGlvbmFsIGFzc3ltZXRyeS4gTG9va2luZyBhdCB0aGUgcGxvdHMgYWJvdmUsIHRoZXJlIGRvZXNuJ3QgYXBwZWFyIHRvIGJlIGFueSwgYnV0IEkgd2lsbCB1c2UgYSBvbmUtc2FtcGxlIHQtdGVzdCB0byB0ZXN0IGZvciBhbnkgZGV2aWF0aW9ucyBvZiBtZWFuIHRpYmlhIGRpZmZlcmVuY2VzIGZyb20gemVybyB0byBjaGVjay4KCkRBIFRvdGFsOgpgYGB7cn0KdC50ZXN0KHRvYWRzX25ldyR0aWJpYV9jb3JyZWN0ZWQpCmBgYAoKVGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgZGlyZWN0aW9uYWwgYXN5bW1ldHJ5LgoKREEgU291dGg6CmBgYHtyfQp0LnRlc3QodG9hZHNfbmV3JHRpYmlhX2NvcnJlY3RlZFt0b2Fkc19uZXckUmVnaW9uID09ICdTb3V0aCddKQpgYGAKClRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGRpcmVjdGlvbmFsIGFzeW1tZXRyeS4KCkRBIENlbnRyYWw6CmBgYHtyfQp0LnRlc3QodG9hZHNfbmV3JHRpYmlhX2NvcnJlY3RlZFt0b2Fkc19uZXckUmVnaW9uID09ICdDZW50cmFsJ10pCmBgYAoKVGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgZGlyZWN0aW9uYWwgYXN5bW1ldHJ5LgoKU3RlcCA0KSBBc3Nlc3MgZmx1Y3R1YXRpbmcgYXN5bW1ldHJ5LiAKClRvdGFsIEZBOgpgYGB7cn0KdC50ZXN0KGFicyh0b2Fkc19uZXckdGliaWFfY29ycmVjdGVkKSkgI3AgPCAwLjAwMSAjIyNEbyB0aGlzIHBlciByZWdpb24KZ2dwbG90KHRvYWRzX25ldywgYWVzKHggPSBhYnModGliaWFfY29ycmVjdGVkKSkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAwNSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAsIGNvbG9yID0gJ3JlZCcpICsKICBsYWJzKHggPSAiVGliaWEgRGlmZmVyZW5jZSBNYWduaXR1ZGVzIikKYGBgCgpUaGVyZSBpcyBzaWduaWZpY2FudCBvdmVyYWxsIGZsdWN0dWF0aW5nIGFzeW1tZXRyeS4KClNvdXRoIEZBOgpgYGB7cn0KdC50ZXN0KGFicyh0b2Fkc19uZXckdGliaWFfY29ycmVjdGVkW3RvYWRzX25ldyRSZWdpb24gPT0gJ1NvdXRoJ10pKQpnZ3Bsb3Qoc3Vic2V0KHRvYWRzX25ldywgUmVnaW9uID09ICdTb3V0aCcpLCBhZXMoeCA9IGFicyh0aWJpYV9jb3JyZWN0ZWQpKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDA1KSArCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMCwgY29sb3IgPSAncmVkJykgKwogIGxhYnMoeCA9ICJUaWJpYSBEaWZmZXJlbmNlIE1hZ25pdHVkZXMgKFNvdXRoKSIpCmBgYAoKVGhlcmUgaXMgc2lnbmlmaWNhbnQgZmx1Y3R1YXRpbmcgYXN5bW1ldHJ5IGluIHRoZSBzb3V0aGVybiByZWdpb24uCgpDZW50cmFsIEZBOgpgYGB7cn0KdC50ZXN0KGFicyh0b2Fkc19uZXckdGliaWFfY29ycmVjdGVkW3RvYWRzX25ldyRSZWdpb24gPT0gJ0NlbnRyYWwnXSkpCmdncGxvdChzdWJzZXQodG9hZHNfbmV3LCBSZWdpb24gPT0gJ0NlbnRyYWwnKSwgYWVzKHggPSBhYnModGliaWFfY29ycmVjdGVkKSkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAwNSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAsIGNvbG9yID0gJ3JlZCcpICsKICBsYWJzKHggPSAiVGliaWEgRGlmZmVyZW5jZSBNYWduaXR1ZGVzIChDZW50cmFsKSIpCmBgYApUaGVyZSBpcyBzaWduaWZpY2FudCBmbHVjdHVhdGluZyBhc3ltbWV0cnkgaW4gdGhlIGNlbnRyYWwgcmVnaW9uLgoKClN0ZXAgNCkgQ29tcGFyZSBmbHVjdHVhdGluZyBhc3ltbWV0cnkgbGV2ZWxzLiBJIGFwcHJvYWNoZWQgdGhlIGNvbXBhcmlzb24gYnkgYm90aCBiaW5uaW5nIHllYXJzIGludG8gY2F0ZWdvcmljYWwgdmFyaWFibGVzIGFuZCBpbmNsdWRpbmcgeWVhcnMgYXMgYSBjb250aW51b3VzIHZhcmlhYmxlLiAKCkZpcnN0IEkgbmVlZCB0byBjaGVjayBhc3N1bXB0aW9ucyBhbmQgYW55IHBvdGVudGlhbCBjb25mb3VuZGluZyBhZmZlY3RzIHRoYXQgSSBjYW4gYWNjb3VudCBmb3IuCgpBc3N1bXB0aW9uczoKYGBge3J9CiNsaW5lYXIgbW9kZWwgZml0CmZpdF9jYXQgPSBsbShhYnModGliaWFfY29ycmVjdGVkKSB+IFJlZ2lvbiAqIHllYXJfZ3JvdXBzLCBkYXRhID0gdG9hZHNfbmV3KQoKI0NoZWNrIGFzc3VtcHRpb25zCnBhcihtZnJvdyA9IGMoMiwgMikpCnBsb3QoZml0X2NhdCkKYGBgClRoZSByZXNwb25zZSBkZXZpYXRlcyBxdWl0ZSBhIGJpdCBmcm9tIG5vcm1hbGl0eSwgYW5kIHRoZSByZXNpZHVhbHMgdnMgbGV2ZXJhZ2UgcGxvdCBleHRlbmRzIGJleW9uZCBDb29rJ3MgZGlzdGFuY2UuIFRoZXJlZm9yZSwgSSBuZWVkIHRvIHRyYW5zZm9ybSB0aGUgcmVzcG9uc2UgdmFyaWFibGUuCgpJJ20gdHJhbnNmb3JtaW5nIHRoZSBjb3JyZWN0ZWQgdGliaWEgbGVuZ3RocyB3aXRoIGEgbG9naXQgdHJhbnNmb3JtYXRpb24gc2luY2Ugd2UgaGF2ZSBwcm9wb3J0aW9uYWwgZGF0YSB0aGF0IGlzIG5vdCBiaW5vbWlhbC4gSSBoYWQgdG8gc2V0IGEgbG93IG51bWJlciAodGhlIGxvd2VzdCBub24temVybyB0aWJpYSBsZW5ndGggZGlmZmVyZW5jZSkgc28gdGhlcmUgYXJlIG5vIGluZmluaXR5IHZhbHVlcy4KCkhlcmUncyB0aGUgdHJhbnNmb3JtYXRpb24gY29tcGFyZWQgdG8gdGhlIG5vbi10cmFuc2Zvcm1lZCBkYXRhLiAKYGBge3J9CmxvZ2l0X3RpYmlhID0gbG9naXQoYWJzKHRvYWRzX25ldyR0aWJpYV9jb3JyZWN0ZWQpLCBhZGp1c3QgPSAwLjAwMTE3Nzk0MSkgI0NoYW5nZQp0b2Fkc19uZXcgPSBjYmluZC5kYXRhLmZyYW1lKHRvYWRzX25ldywgbG9naXRfdGliaWEpCnBhcihtZnJvdyA9IGMoMSwgMikpICN0byBjb21wYXJlIHRoZSBkaXN0cmlidXRpb25zCnBsb3QodG9hZHNfbmV3JGxvZ2l0X3RpYmlhKQpwbG90KGFicyh0b2Fkc19uZXckdGliaWFfY29ycmVjdGVkKSkgCmBgYApJdCBsb29rcyBvdmVyYWxsIG1vcmUgdmFyaWVkIHdpdGggZmV3ZXIgb3V0bGllcnMuCgpUZXN0aW5nIHRoZSBhc3N1bXB0aW9ucyBhZ2FpbiB3aXRoIHRyYW5zZm9ybWVkIGRhdGE6CmBgYHtyfQpmaXRfdGliaWEgPSBsbShsb2dpdF90aWJpYSB+IFJlZ2lvbiAqIHllYXJfZ3JvdXBzLCBkYXRhID0gdG9hZHNfbmV3KQpwbG90KGZpdF90aWJpYSkKYGBgClRoaXMgc3RpbGwgZGV2aWF0ZXMgYSBiaXQgZnJvbSBub3JtYWxpdHksIGJ1dCBpcyBiZXR0ZXIgdGhhbiB0aGUgdW50cmFuc2Zvcm1lZCBkYXRhLiBUaGUgdmFyaWFuY2UgaXMgbW9yZSBldmVuIGFzIHdlbGwuCgpOb3cgSSBuZWVkIHRvIG1ha2Ugc3VyZSBzZXggZG9lc24ndCBjb3Zhcnkgd2l0aCBlaXRoZXIgeWVhciBvciByZWdpb24uCgpZZWFyOgpgYGB7cn0KZ2dwbG90KHRvYWRzX25ldywgYWVzKHggPSB5ZWFyX2dyb3VwcywgeSA9IGFicyh0aWJpYV9jb3JyZWN0ZWQpLCBmaWxsID0gU2V4KSkgKwogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNzUpCmZpdF9zZXhfeWVhciA9IGxtKGxvZ2l0X3RpYmlhIH4gU2V4ICogeWVhcl9ncm91cHMsIGRhdGEgPSB0b2Fkc19uZXcpCm1vZGVsX2ZpdF9zZXhfeWVhciA9IEFub3ZhKGZpdF9zZXhfeWVhciwgdHlwZSA9IDMpIAptb2RlbF9maXRfc2V4X3llYXIKYGBgCgpSZWdpb246CmBgYHtyfQpnZ3Bsb3QodG9hZHNfbmV3LCBhZXMoeCA9IFJlZ2lvbiwgeSA9IGFicyh0aWJpYV9jb3JyZWN0ZWQpLCBmaWxsID0gU2V4KSkgKwogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNzUpCmZpdF9zZXhfcmVnaW9uID0gbG0obG9naXRfdGliaWEgfiBTZXggKiBSZWdpb24sIGRhdGEgPSB0b2Fkc19uZXcpCm1vZGVsX2ZpdF9zZXhfcmVnaW9uID0gQW5vdmEoZml0X3NleF9yZWdpb24sIHR5cGUgPSAzKQptb2RlbF9maXRfc2V4X3JlZ2lvbgpgYGAKU2V4IGRvZXNuJ3QgYWZmZWN0IGFueXRoaW5nLCBzbyB3ZSdyZSBnb29kIHRvIGNvbnRpbnVlLgoKSXQncyBmaW5hbGx5IHRpbWUgdG8gbWFrZSB0aGUgbW9kZWwhIApgYGB7cn0KZ2dwbG90KHRvYWRzX25ldywgYWVzKHggPSB5ZWFyX2dyb3VwcywgeSA9IGxvZ2l0X3RpYmlhLCBjb2xvciA9IFJlZ2lvbikpICsKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjc1KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEwLCAwKSkKbW9kZWxfY2F0X3RyYW5zID0gQW5vdmEoZml0X3RpYmlhLCB0eXBlID0gMykKbW9kZWxfY2F0X3RyYW5zCmBgYAoKClNpbmNlIHRoZSB0aW1lIGZyYW1lIGZyb20gdGhlIDE5OTBzLTIwMDBzIGRvZXNuJ3QgaGF2ZSBhIGNsZWFyLWN1dCBzZXBhcmF0aW9uLCBJJ20gYWxzbyBnb2luZyB0byBhbmFseXplIHRoZSBkYXRhIHdpdGggYSBsaW5lYXIgbW9kZWwuIFRoZSBsaW5lYXIgbW9kZWwgYXNzdW1wdGlvbnMgYXJlIG1ldCwgc28gd2UgY2FuIGdvIGFoZWFkIGFuZCBsb29rIGF0IHRoZSBsZWFzdC1zcXVhcmVzIHJlZ3Jlc3Npb24uCmBgYHtyfQpnZ3Bsb3QodG9hZHNfbmV3LCBhZXMoeCA9IFllYXIsIHkgPSBsb2dpdF90aWJpYSwgY29sb3IgPSBSZWdpb24pKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKQpmaXRfY29udGludW91cyA9IGxtKGxvZ2l0X3RpYmlhIH4gUmVnaW9uICogWWVhciwgZGF0YSA9IHRvYWRzX25ldykKc3VtbWFyeShmaXRfY29udGludW91cykKYGBgCgpJIHJlcmFuIHRoZSBtb2RlbCB1c2luZyB0aGUgc291dGhlcm4gcmVnaW9uIGFzIHRoZSByZWZlcmVuY2UgcmVnaW9uLCBzbyB3ZSBjYW4gc2VlIHRoZSBjaGFuZ2UgYWNyb3NzIHllYXJzIGZvciB0aGUgY2VudHJhbCByZWdpb24uCgpgYGB7cn0KZml0X2NvbnRpbnVvdXNfQyA9IGxtKGxvZ2l0X3RpYmlhIH4gcmVsZXZlbChSZWdpb24sIHJlZiA9ICdTb3V0aCcpICogWWVhciwgZGF0YSA9IHRvYWRzX25ldykKc3VtbWFyeShmaXRfY29udGludW91c19DKQpgYGAKCkkgdGhpbmsgdGhlIGdlbmVyYWwgdHJlbmRzIGFyZSBtb3JlIGNsZWFyIHdpdGggdGhlIGNvbnRpbnVvdXMgbW9kZWwsIGJ1dCB0aGUgaW5pdGlhbCBpbmNyZWFzZSBpbiBGQSB3aXRoIHN1YnNlcXVlbnQgZGVjcmVhc2UgaW4gRkEgb3ZlciB0aW1lIHdpdGggdGhlIENlbnRyYWwgcmVnaW9uIGdldHMgbG9zdCB3aXRoIGEgc2luZ2xlIHJlZ3Jlc3Npb24gbGluZS4KCgpIZXJlJ3MgYSBwbG90IG9mIHRpYmlhIGRpZmZlcmVuY2VzIGFjcm9zcyB5ZWFycyB3aGVuIGluY2x1ZGluZyB0aGUgc2l4dGllcyBzcGVjaW1lbnMuIEl0IHNob3dzIHRoZSBpbml0aWFsIGluY3JlYXNlIGFuZCBzdWJzZXF1ZW50IGRlY3JlYXNlIGluIEZBIGZvciB0aGUgc291dGhlcm4gcmVnaW9uIHNwZWNpbWVucyBzaGlmdGVkIGFoZWFkIG9mIHRoZSBjZW50cmFsIHJlZ2lvbidzIHNpbWlsYXIgcGF0dGVybi4KCmBgYHtyfQpnZ3Bsb3QodG9hZHMsIGFlcyh4ID0geWVhcl9ncm91cHMsIHkgPSBsb2dpdF90aWJpYSwgZmlsbCA9IFJlZ2lvbikpICsKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjc1KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEwLCAwKSkKYGBgCgoKVG8gb2J0YWluIGFuIGluZGV4IG9mIHJlbGF0aXZlIHRpYmlhIGxlbmd0aCwgd2UgY29uZHVjdGVkIGEgZ2VuZXJhbCBsaW5lYXIgcmVncmVzc2lvbiBvZiBtZWFuIHRpYmlhIGxlbmd0aCBhZ2FpbnN0IFNWTCBhbmQgZXh0cmFjdGVkIHRoZSByZXNpZHVhbHMuIApgYGB7cn0KbGVuZ3RoX2dsbSA9IGdsbShtZWFuX3RpYmlhIH4gU1ZMLCBkYXRhID0gdG9hZHNfbmV3KQpsZW5ndGhfcmVzaWR1YWxzID0gbGVuZ3RoX2dsbSRyZXNpZHVhbHMKdG9hZHNfbmV3ID0gY2JpbmQodG9hZHNfbmV3LCBsZW5ndGhfcmVzaWR1YWxzKQpgYGAKCldlIHRoZW4gY29uc3RydWN0ZWQgYW4gQU5DT1ZBIHdpdGggcmVsYXRpdmUgdGliaWEgbGVuZ3RoIGFzIHRoZSByZXNwb25zZSBhbmQgdGhlIGludGVyYWN0aW9uIG9mIHJlZ2lvbiBhbmQgeWVhciBhcyB0aGUgZml4ZWQgZWZmZWN0CmBgYHtyfQpnZ3Bsb3QodG9hZHNfbmV3LCBhZXMoeCA9IHllYXJfZ3JvdXBzLCB5ID0gbGVuZ3RoX3Jlc2lkdWFscywgY29sb3IgPSBSZWdpb24pKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC03LCA3KSkKCiNtb2RlbC4KbGVuZ3RoX3lyX2ZpdCA9IGxtKGxlbmd0aF9yZXNpZHVhbHMgfiBSZWdpb24gKiB5ZWFyX2dyb3VwcywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHRvYWRzX25ldykKbGVuZ3RoX3lyX21vZGVsID0gQW5vdmEobGVuZ3RoX3lyX2ZpdCwgdHlwZSA9IDMpCmxlbmd0aF95cl9tb2RlbApgYGAKCgpQbG90IG9mIGxlZyBsZW5ndGggYWNyb3NzIHRpbWUsIGluY2x1ZGluZyB0aGUgMTk2MHMgaW5kaXZpZHVhbHMKYGBge3J9Cm1lYW5fdGliaWFfb2xkID0gKHRvYWRzJFRpYmlhX0xlZnQgKyB0b2FkcyRUaWJpYV9SaWdodCkgLyAyCnRvYWRzID0gY2JpbmQodG9hZHMsIG1lYW5fdGliaWFfb2xkKQoKI0NvcnJlY3QgZm9yIFNWTCBieSB1c2luZyByZXNpZHVhbHMgb2YgR0xNCmxlbmd0aF9nbG1fb2xkID0gZ2xtKG1lYW5fdGliaWFfb2xkIH4gU1ZMLCBkYXRhID0gdG9hZHMpCmxlbmd0aF9yZXNpZHVhbHNfb2xkID0gbGVuZ3RoX2dsbV9vbGQkcmVzaWR1YWxzCnRvYWRzID0gY2JpbmQodG9hZHMsIGxlbmd0aF9yZXNpZHVhbHNfb2xkKQoKIyNMaW5lYXIgbW9kZWwgb2YgbGVuZ3RoIHJlc2lkdWFscyBhcyBhIGZ1bmN0aW9uIG9mIHllYXIKI3Bsb3QKZ2dwbG90KHRvYWRzLCBhZXMoeCA9IHllYXJfZ3JvdXBzLCB5ID0gbGVuZ3RoX3Jlc2lkdWFsc19vbGQsIGNvbG9yID0gUmVnaW9uKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNywgNykpCmBgYAoKCgoKCgo=