Load workspace

load("/Users/zeynepenkavi/Dropbox/CDSPart1/TransitivityOpen/Transitivity_OpenDataOrganizationWS052817.RData")

Group differences in intransitivies

Summary Statistics

both.Intransitive %>%
  group_by(Task, Group) %>%
  summarise(mean_CleanIntr = mean(CleanIntr),
            median_CleanIntr = median(CleanIntr),
            sd_CleanIntr = sd(CleanIntr),
            mean_CleanPercentIntr = mean(CleanPercentIntr),
            median_CleanPercentIntr = median(CleanPercentIntr),
            sd_CleanPercentIntr = sd(CleanPercentIntr))
both.Intransitive %>% 
  group_by(Task, Group) %>% 
  summarise(MeanCleanPercentIntr = mean(CleanPercentIntr, na.rm=T),
            SeCleanPercentIntr = sem(CleanPercentIntr),
            eb.low = MeanCleanPercentIntr - SeCleanPercentIntr,
            eb.high = MeanCleanPercentIntr + SeCleanPercentIntr) %>%
ggplot(aes(x = Group, y=MeanCleanPercentIntr, group = Task))+
  geom_point(aes(shape = Task))+
  geom_line(aes(linetype = Task))+
  geom_errorbar(aes(ymax = eb.high, ymin=eb.low), width=0.25)+
  ylab("Mean Percentage of Intransitivities")+
  xlab("")+
  theme_bw()+
  theme(axis.title.y = element_text(face="bold", size = 14),
        axis.text.x  = element_text(face="bold", size = 14),
        legend.text = element_text(size = 14),
        legend.title = element_text(size = 14))+
  scale_shape_discrete(breaks = c("choice", "numbers"),
                       labels = c("Value-based", "Numbers"))+
  scale_linetype_discrete(breaks = c("choice", "numbers"),
                          labels = c("Value-based", "Numbers"))

ggsave("/Users/zeynepenkavi/Dropbox/CDSPart1/TransitivityOpen/CleanFigure2.png", width=6, height=4, dpi=300)

Looking at the plot we are interested in whether the difference between the two lines is the same for all groups. In other words: Is there a significant intereaction between task and group, i.e. is the effect of changing the task same for the MTL group as it is for the control groups.

To choose the correct model that would check for statistical differences between the groups we checked the assumptions for each possibility. Though all methods yield essentially the same answer we chose to use a linear mixed model with orthogonal contrasts because it was the most appropriate method.

The first thing we could do would be a one-way ANOVA for both tasks checking whether the main dependent measure (percentage of intransitivities) differs depending on the group and task. The distribution of effect sizes within tasks, however, is not normal for either task, which is why this would not be an appropriate test.

both.Intransitive %>%
  ggplot(aes(CleanPercentIntr, fill=Group))+
  geom_histogram(position="identity", alpha=0.5)+
  theme_bw()+
  xlab("Percentage of intransitivity")+
  facet_wrap(~Task)

shapiro.test(both.Intransitive[both.Intransitive$Task == "numbers",]$CleanPercentIntr)

    Shapiro-Wilk normality test

data:  both.Intransitive[both.Intransitive$Task == "numbers", ]$CleanPercentIntr
W = 0.36, p-value <2e-16
shapiro.test(both.Intransitive[both.Intransitive$Task == "choice",]$CleanPercentIntr)

    Shapiro-Wilk normality test

data:  both.Intransitive[both.Intransitive$Task == "choice", ]$CleanPercentIntr
W = 0.69, p-value = 1e-12

To solve this we could try a non-parametric test (e.g. Kruskall-Wallis) but this wouldn’t allow us to check the interaction of group by task and more importantly the variance in the effect size distributions are unequal. That is, as the Bartlett test below and the plot above shows variance in effect size is not independent of task.

bartlett.test(CleanPercentIntr ~ Task, data = both.Intransitive)

    Bartlett test of homogeneity of variances

data:  CleanPercentIntr by Task
Bartlett's K-squared = 58, df = 1, p-value = 3e-14

To deal with this issue of task dependence of the variance we log transform the effect sizes.

bartlett.test(log(CleanPercentIntr + 1) ~ Task, data = both.Intransitive)

    Bartlett test of homogeneity of variances

data:  log(CleanPercentIntr + 1) by Task
Bartlett's K-squared = 3.4, df = 1, p-value = 0.07

Using transformed dependent variables we first confirm that the interactive model is the best fitting model by comparing it to nested simpler models.

gm1a <- lm(log(CleanPercentIntr+1) ~ Task, both.Intransitive)#; summary(gm1a)
gm1b <- lm(log(CleanPercentIntr+1) ~ Group, both.Intransitive)# ; summary(gm1b)
gm2 <- lm(log(CleanPercentIntr+1) ~ Group+Task, both.Intransitive)# ; summary(gm2)
gm3 <- lm(log(CleanPercentIntr+1) ~ Group*Task, both.Intransitive)# ; summary(gm3)
anova(gm1a, gm2, gm3)
anova(gm1b, gm2, gm3)

So what does this interactive model say? To get a better understanding of this we first look at the contrasts used in this model.

contrasts(both.Intransitive$Task)
        numbers
choice        0
numbers       1
contrasts(both.Intransitive$Group)
    ETL MTL
C     0   0
ETL   1   0
MTL   0   1

Based on these contrasts the group differences in this model compare both patient groups to the healthy control alone. Accordingly the parameters of the linear model would have the following interpretations.

summary(gm3)

Call:
lm(formula = log(CleanPercentIntr + 1) ~ Group * Task, data = both.Intransitive)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.2678 -0.3590 -0.0785  0.2261  2.1345 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)            1.2508     0.0839   14.90  < 2e-16 ***
GroupETL               0.1011     0.1187    0.85    0.395    
GroupMTL               0.5441     0.1178    4.62  7.4e-06 ***
Tasknumbers           -1.1322     0.1187   -9.54  < 2e-16 ***
GroupETL:Tasknumbers   0.1422     0.1679    0.85    0.398    
GroupMTL:Tasknumbers  -0.3019     0.1665   -1.81    0.072 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.46 on 176 degrees of freedom
Multiple R-squared:  0.655, Adjusted R-squared:  0.645 
F-statistic: 66.7 on 5 and 176 DF,  p-value: <2e-16

b0 = mean percentage of intransitivity for both tasks for the C group is >0 (not interesting) b1 = ETL group doesn’t make significantly more intrans in CHOICE task! (good) - simple effect b2 = MTL group DOES make sig more intrans in CHOICE task! (good) - simple effect b3 = C group makes sig less intrans in NUMBERS task! (not surprising, easy task) b4 = Is the effect of task in ETL group same as C. Yes. b5 = Is the effect of task in MTL group same as C. Marginally no.

As mentioned above, however, these are not orthogonal contrasts and are comparing both groups to Healthy controls only! But we are interested in comparing the MTL group to both control groups. To answer this question and to avoid overlapping variance we orthogonalize the contrasts. This would results in first comparing the ETL group to the C group and then the MTL group to BOTH CONTROL GROUPS!

#Change the contrasts, make them orthogonal
both.Intransitive.contrast <- both.Intransitive
contrasts(both.Intransitive.contrast$Group) <- cbind(c(-1,1, 0), c(-1, -1, 2))
contrasts(both.Intransitive.contrast$Task) <- c(-1, 1)

gm3.con <- lm(log(CleanPercentIntr+1) ~ Group*Task, both.Intransitive.contrast) 
summary(gm3.con)

Call:
lm(formula = log(CleanPercentIntr + 1) ~ Group * Task, data = both.Intransitive.contrast)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.2678 -0.3590 -0.0785  0.2261  2.1345 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)    0.8732     0.0341   25.62  < 2e-16 ***
Group1         0.0861     0.0420    2.05    0.042 *  
Group2         0.1023     0.0240    4.27 0.000032 ***
Task1         -0.5927     0.0341  -17.39  < 2e-16 ***
Group1:Task1   0.0356     0.0420    0.85    0.398    
Group2:Task1  -0.0622     0.0240   -2.59    0.010 *  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.46 on 176 degrees of freedom
Multiple R-squared:  0.655, Adjusted R-squared:  0.645 
F-statistic: 66.7 on 5 and 176 DF,  p-value: <2e-16

What does the model say now:

b0 = Unweighted grand mean (mean of group means) (sum(aggregate(CleanPercentIntr ~ Group, both.Intransitive.contrast, mean)[,2])/3) b1 = Total group effect for ETL compared to healthy controls only (quantified) b2 = Total group effect for MTL compared to both control groups (quantified) b3 = Total task effect b4 = Is the effect of task change same for ETL and C groups? (yes.) b5 = Is the effect of task change same for MTL vs both control groups? (No!)

Since there are two measures per subject we check if a mixed model necessary comparing the log-likelihoods of a model with random effects to one without them. We find that that a model with random effects is indeed significantly better fit to data.

gm3.lmer.con <- lmerTest::lmer(log(CleanPercentIntr+1) ~ Group*Task + (1|f.id), both.Intransitive.contrast, REML = F)

x2 = -2*logLik(gm3.con) +2*logLik(gm3.lmer.con)
x2
'log Lik.' 4.39 (df=7)
pchisq(x2, df=1, lower.tail=F)
'log Lik.' 0.03614 (df=7)
summary(gm3.lmer.con) 
Linear mixed model fit by maximum likelihood t-tests use Satterthwaite
  approximations to degrees of freedom [lmerMod]
Formula: log(CleanPercentIntr + 1) ~ Group * Task + (1 | f.id)
   Data: both.Intransitive.contrast

     AIC      BIC   logLik deviance df.resid 
   239.2    264.8   -111.6    223.2      174 

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-2.442 -0.601 -0.152  0.543  4.294 

Random effects:
 Groups   Name        Variance Std.Dev.
 f.id     (Intercept) 0.0444   0.211   
 Residual             0.1601   0.400   
Number of obs: 182, groups:  f.id, 91

Fixed effects:
             Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)    0.8732     0.0370 91.0000   23.61  < 2e-16 ***
Group1         0.0861     0.0455 91.0000    1.89  0.06175 .  
Group2         0.1023     0.0260 91.0000    3.93  0.00016 ***
Task1         -0.5927     0.0297 91.0000  -19.98  < 2e-16 ***
Group1:Task1   0.0356     0.0365 91.0000    0.97  0.33288    
Group2:Task1  -0.0622     0.0209 91.0000   -2.98  0.00369 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
            (Intr) Group1 Group2 Task1  Gr1:T1
Group1       0.000                            
Group2      -0.015  0.000                     
Task1        0.000  0.000  0.000              
Group1:Tsk1  0.000  0.000  0.000  0.000       
Group2:Tsk1  0.000  0.000  0.000 -0.015  0.000

The linear mixed model with orthogonal contrasts is the most appropriate analysis and reveals a significant group task interaction in the percentage of intransitivities. Accordingly the MTL group had a higher percentage of intransitivities in the choice task than the numbers task compared to both control groups, while the difference between the percentage of intransitivities did not differ between tasks between the health controls and the ETL group.

Lesion size and intransitivies

symmetry.data <- read.xlsx("/Users/zeynepenkavi/Dropbox/CDSPart1/Transitivity/TransitivityData/Symmetry_index_zeynep.xlsx", 1)

symmetry.data = both.Intransitive %>%
  filter(Task == 'choice') %>%
  mutate(ID = as.numeric(as.character(f.id))) %>%
  right_join(symmetry.data, by= 'ID') %>%
  drop_na()

Spearman correlation between instransitivity percentage and lesion size

cor(symmetry.data$Symmetry.index, symmetry.data$CleanPercentIntr, method = "spearman")
[1] 0.676

Significance test for the Spearman correlation

spearman.test(symmetry.data$Symmetry.index, symmetry.data$CleanPercentIntr)
  Rsquare         F       df1       df2    pvalue         n 
 0.456969 11.781218  1.000000 14.000000  0.004044 16.000000 

Plot of correlation between

ggplot(symmetry.data, aes(Symmetry.index, CleanPercentIntr))+
  geom_point()+
  geom_smooth(method = 'loess', span = 2, color = "black", alpha = 0.1, linetype = "dashed")+
  theme_bw()+
  ylab("Percentage of Intransitve Choice")+
  xlab("Compromised Hippocampal Ratio")+
  theme(axis.title.y = element_text(face="bold", size = 14),
        axis.title.x  = element_text(face="bold", size = 14),
        legend.text = element_text(size = 14),
        legend.title = element_text(size = 14))

ggsave("/Users/zeynepenkavi/Dropbox/CDSPart1/TransitivityOpen/CleanFigure3.png", width=4, height=4, dpi=300)

Simulations

path = '/Users/zeynepenkavi/Dropbox/CDSPart1/TransitivityOpen/sim_output/'

fileList = list.files(path,pattern = "*_hardmax.csv")

read_csv_fn <- function(filename){
    ret <- read.csv(filename)
    ret$Source <- filename 
    ret
}

lapply(paste0(path, fileList), read_csv_fn)  %>% 
  bind_rows() %>%
  separate(Source, c("a", "b", "c", "d", "e", "f","g", "sim"),sep = "/") %>%
  select(pct_Intrans, sim) %>%
  separate(sim, c("a", "b", "c", "d", "noise", "e", "f"), sep = "_") %>%
  select(pct_Intrans, noise) %>%
  filter(noise %in% c(0.05, 0.25) == FALSE) %>%
  group_by(noise) %>%
  summarise(mean_Intrans = mean(pct_Intrans),
            sem_Intrans = sem(pct_Intrans)) %>%
  ggplot(aes(noise, mean_Intrans))+
  geom_point()+
  theme_bw()+
  geom_errorbar(aes(ymin = mean_Intrans-sem_Intrans, ymax = mean_Intrans+sem_Intrans), width=0.25)+
  ylab("Percentage of Intransivity")+
  xlab("Noise level")#+

  # ggtitle("Results of simulation using hardmax")
fileList = list.files(path,pattern = "*_rbinom.csv")

lapply(paste0(path, fileList), read_csv_fn)  %>% 
  bind_rows() %>%
  separate(Source, c("a", "b", "c", "d", "e", "f","g", "sim"),sep = "/") %>%
  select(pct_Intrans, sim) %>%
  separate(sim, c("a", "b", "c", "d", "noise", "e", "f"), sep = "_") %>%
  select(pct_Intrans, noise) %>%
  filter(noise %in% c(0.05, 0.25) == FALSE) %>%
  group_by(noise) %>%
  summarise(mean_Intrans = mean(pct_Intrans),
            sem_Intrans = sem(pct_Intrans)) %>%
  ggplot(aes(noise, mean_Intrans))+
  geom_point()+
  theme_bw()+
  geom_errorbar(aes(ymin = mean_Intrans-sem_Intrans, ymax = mean_Intrans+sem_Intrans), width=0.25)+
  ylab("Percentage of Intransivity")+
  xlab("Noise level")+
  scale_y_continuous(breaks=seq(0,25,5), limits=c(0, 26))+
  ggtitle("Results of simulation flipping coin with noisy choice p")

fileList = list.files(path,pattern = "*_epsilon.csv")

lapply(paste0(path, fileList), read_csv_fn)  %>% 
  bind_rows() %>%
  separate(Source, c("a", "b", "c", "d", "e", "f","g", "sim"),sep = "/") %>%
  select(pct_Intrans, sim) %>%
  separate(sim, c("a", "b", "c", "d", "noise", "e", "f"), sep = "_") %>%
  select(pct_Intrans, noise) %>%
  filter(noise %in% c(0.05, 0.25) == FALSE) %>%
  group_by(noise) %>%
  summarise(mean_Intrans = mean(pct_Intrans),
            sem_Intrans = sem(pct_Intrans)) %>%
  ggplot(aes(noise, mean_Intrans))+
  geom_point()+
  theme_bw()+
  geom_errorbar(aes(ymin = mean_Intrans-sem_Intrans, ymax = mean_Intrans+sem_Intrans), width=0.25)+
  ylab("Percentage of Intransivity")+
  xlab("Noise level")+
  scale_y_continuous(breaks=seq(0,25,5), limits=c(0, 26))+
  ggtitle("Results of simulation with epsilon greedy")

Alternative explanations of intransitivity

Episodic memory

One alternative explanation of the higher level of intransitivities in the MTL group is about episodic memory deficits. Accordingly, the MTL group might be showing higher rates of intransitivity because they are unable to recall choices they have made earlier in the task. This hypothesis would predict a pattern of proportion of intransitive triplets each trial was involved in that increases towards the end of the task (the later the trial the more intransitive triplets it was involved in). The figure below shows the empirical change of intransitive triplet involvement with trial number.

choice2.trial.data$Task <- "choice"
numbers.trial.data$Task <- "numbers"

both.trial.data <- rbind(choice2.trial.data[,c("f.id", "Group", "RT", "Task", "Trialnumber", "IntransTripleCounted")], numbers.trial.data[,c("f.id", "Group", "RT", "Task", "Trialnumber", "IntransTripleCounted")])

both.trial.data = both.Intransitive %>%
  select(f.id, CleanIntr, Task) %>%
  right_join(both.trial.data, by=c("f.id", "Task")) %>%
  mutate(PropInIntransTriplet = IntransTripleCounted/(CleanIntr*3)*100,
         Task = factor(Task, levels = c("choice", "numbers"), labels = c("Value-based", "Perceptual")))%>%
  filter(RT>0, RT<6000)

Note that most of the trials are not involved in any intransitivities so the averaged proportion of intransitivities for each trial number is pretty small (i.e why the y-axis is so small).

both.trial.data %>%
  ggplot(aes(x = Trialnumber, y = PropInIntransTriplet, group = Group, color = Group))+
  geom_smooth(method = "loess", span=5) +
  theme_bw()+
  facet_grid(~Task)+
  ylab("Percent of intransitive Triplets involved") +
  xlab("Order choice was made")

To test if there are any statistical differences both between the groups and throughout each task and between the two tasks we first compare three models where the proportion of intransitive triplets a trial is involved is regressed over the trial number and experimental group. The first model is additive, the second interactive and the third includes a quadratic effect of trial number as well. Model comparison shows that the addition of the interaction terms and the quadratic effect do not lead to significant improvements in fit. Thus we report the effects in the simplest additive model.

mem1 = lmer(PropInIntransTriplet ~ (1|f.id)+scale(Trialnumber)+Group*Task, both.trial.data)

#adding interaction of linear effect of RT between tasks and groups
mem2 = lmer(PropInIntransTriplet ~ (1|f.id)+scale(Trialnumber)*Group*Task, both.trial.data)

#adding the quadratic effect
mem3 = lmer(PropInIntransTriplet ~ (1|f.id)+scale(poly(Trialnumber,2))*Task*Group, both.trial.data)

anova(mem1, mem2, mem3)

The additive model suggests that contrary to the prediction of an episodic memory during the task account there is both no change in the proportion of intransitive triplets a trial in involved in throughout the task and this is true for all groups in both tasks.

summary(mem1)
Linear mixed model fit by REML ['lmerMod']
Formula: PropInIntransTriplet ~ (1 | f.id) + scale(Trialnumber) + Group *  
    Task
   Data: both.trial.data

REML criterion at convergence: 125147

Scaled residuals: 
   Min     1Q Median     3Q    Max 
 -2.22  -0.23  -0.22  -0.11  39.76 

Random effects:
 Groups   Name        Variance Std.Dev.
 f.id     (Intercept) 0.266    0.516   
 Residual             5.676    2.383   
Number of obs: 27302, groups:  f.id, 91

Fixed effects:
                        Estimate Std. Error t value
(Intercept)              0.52975    0.09936    5.33
scale(Trialnumber)      -0.00241    0.01442   -0.17
GroupETL                 0.17915    0.14053    1.27
GroupMTL                 0.01709    0.13946    0.12
TaskPerceptual          -0.00167    0.06236   -0.03
GroupETL:TaskPerceptual -0.02376    0.09162   -0.26
GroupMTL:TaskPerceptual  0.00819    0.07879    0.10

Correlation of Fixed Effects:
            (Intr) scl(T) GrpETL GrpMTL TskPrc GETL:T
scl(Trlnmb)  0.000                                   
GroupETL    -0.707  0.000                            
GroupMTL    -0.712  0.000  0.504                     
TaskPercptl -0.161  0.001  0.114  0.115              
GrpETL:TskP  0.110  0.000 -0.156 -0.078 -0.681       
GrpMTL:TskP  0.128  0.000 -0.090 -0.181 -0.792  0.539

In her comments Elke suggested that based on the episodic memory hypothesis the episodic memory of the choices in the first two trials would only help/influence the decision for the third trial in a triplet. To address this I analyzed the episodic memory hypothesis at the triplet level. Previously we looked at the number of intransitive triplets each trial was involved in depending on when it appeared during the task. This might seem confusing because depending on when they appeared during the task each trial is not equally likely to have lead to an intransitive triplet. That is, as Elke implied not every trial was the third trial in a triplet and looking at all tasks without discriminating the order in which they appeared for a triplet masks this.

The analyses here should take care of this and indeed lead to the same conclusion but might be more intuitive. Here we look at whether a triplet is intransitive depending on when the last trial in that triplet appeared.

both.triplet.data = both.triplet.data %>%
   mutate(CleanIntr = ifelse(Intrans == 1 & Error == 0,1, 0)) %>%
  mutate(Task = factor(Task, levels = c("choice", "numbers"), labels = c("Value-based", "Perceptual")))
both.triplet.data %>%
  ggplot(aes(ThirdTrial, CleanIntr, group=Group, color=Group))+
  geom_smooth(method="glm", method.args = list(family="binomial"))+
  theme_bw()+
  facet_grid(~Task)+
  xlab("Last seen trial in triplet")+
  ylab("Intransitive triplet")

Running model for choice task only because looking at both takes a while. The DV in these regressions is whether the triplet is intransitive and the independent variables are random effects for subjects and fixed effects for patient group and the trial number of the last seen trial in that triplet.

For the choice task there is only a fixed effect of the MTL group suggesting that this group has more intransitive triplets than the control group. The effect of the trial number of the last seen trial in a triplet on whether or not it is intransitive is not significant.

mem_val = glmer(CleanIntr ~ (1|f.id)+Group*scale(ThirdTrial),family=binomial, both.triplet.data[both.triplet.data$Task == "Value-based",])
summary(mem_val)
Generalized linear mixed model fit by maximum likelihood (Laplace
  Approximation) [glmerMod]
 Family: binomial  ( logit )
Formula: CleanIntr ~ (1 | f.id) + Group * scale(ThirdTrial)
   Data: both.triplet.data[both.triplet.data$Task == "Value-based", ]

     AIC      BIC   logLik deviance df.resid 
   32336    32403   -16161    32322   103733 

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-0.553 -0.218 -0.178 -0.136 15.281 

Random effects:
 Groups Name        Variance Std.Dev.
 f.id   (Intercept) 0.466    0.682   
Number of obs: 103740, groups:  f.id, 91

Fixed effects:
                           Estimate Std. Error z value Pr(>|z|)    
(Intercept)                 -3.7174     0.1302  -28.56  < 2e-16 ***
GroupETL                     0.0972     0.1840    0.53  0.59725    
GroupMTL                     0.6825     0.1811    3.77  0.00016 ***
scale(ThirdTrial)            0.0266     0.0335    0.79  0.42713    
GroupETL:scale(ThirdTrial)  -0.0442     0.0452   -0.98  0.32817    
GroupMTL:scale(ThirdTrial)  -0.0319     0.0409   -0.78  0.43417    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
            (Intr) GrpETL GrpMTL sc(TT) GETL:(
GroupETL    -0.706                            
GroupMTL    -0.719  0.509                     
scl(ThrdTr) -0.006  0.004  0.004              
GrpETL:(TT)  0.004 -0.001 -0.003 -0.742       
GrpMTL:(TT)  0.005 -0.003 -0.003 -0.821  0.609

The episodic memory hypothesis might make a more specific hypothesis that depends not just on when each trial appears but how far apart each trial in a triplet appears from each other. Specifically, it could be the case that the further apart the trials of a triplet are the more likely they are to form an intransitive triplet because the episodic memory of the choices fade away and can’t help the decision in the thirdpair. For this hypothesis to explain the group difference in intransitivities for the choice task this trend would have to be particularly pronounced for the MTL group.

both.triplet.data %>%
    mutate(TrialNumVar = ((TrialA-((TrialA+TrialB+TrialC)/3))^2+(TrialB-((TrialA+TrialB+TrialC)/3))^2+(TrialC-((TrialA+TrialB+TrialC)/3))^2)/2) %>%
  ggplot(aes(TrialNumVar, CleanIntr, group=Group, color=Group))+
  geom_smooth(method="glm", method.args = list(family="binomial"))+
  theme_bw()+
  facet_grid(~Task)+
  xlab("Variance of the trial numbers involved in the triplet")+
  ylab("Intransitive triplet")

Again, however, this hypothesis does not seem to explain the group difference in intransitivies in the choice task: It is the case that the further apart from each other trials in a triplet appear the more likely is that triplet intransitive but this trend is the same for all groups.

both.triplet.data=both.triplet.data %>%
    mutate(TrialNumVar = ((TrialA-((TrialA+TrialB+TrialC)/3))^2+(TrialB-((TrialA+TrialB+TrialC)/3))^2+(TrialC-((TrialA+TrialB+TrialC)/3))^2)/2)

mem_val_var <- glmer(CleanIntr ~ (1|f.id)+Group*scale(TrialNumVar),family=binomial, both.triplet.data[both.triplet.data$Task == "Value-based",])
summary(mem_val_var)
Generalized linear mixed model fit by maximum likelihood (Laplace
  Approximation) [glmerMod]
 Family: binomial  ( logit )
Formula: CleanIntr ~ (1 | f.id) + Group * scale(TrialNumVar)
   Data: both.triplet.data[both.triplet.data$Task == "Value-based", ]

     AIC      BIC   logLik deviance df.resid 
   32312    32379   -16149    32298   103733 

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-0.608 -0.217 -0.177 -0.134 15.406 

Random effects:
 Groups Name        Variance Std.Dev.
 f.id   (Intercept) 0.466    0.683   
Number of obs: 103740, groups:  f.id, 91

Fixed effects:
                            Estimate Std. Error z value Pr(>|z|)    
(Intercept)                  -3.7228     0.1302  -28.59  < 2e-16 ***
GroupETL                      0.0997     0.1841    0.54  0.58825    
GroupMTL                      0.6861     0.1810    3.79  0.00015 ***
scale(TrialNumVar)            0.1088     0.0320    3.40  0.00068 ***
GroupETL:scale(TrialNumVar)  -0.0271     0.0437   -0.62  0.53493    
GroupMTL:scale(TrialNumVar)  -0.0489     0.0393   -1.25  0.21308    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
            (Intr) GrpETL GrpMTL s(TNV) GETL:(
GroupETL    -0.706                            
GroupMTL    -0.719  0.509                     
scl(TrlNmV) -0.026  0.018  0.019              
GrETL:(TNV)  0.019 -0.022 -0.014 -0.732       
GrMTL:(TNV)  0.021 -0.015 -0.019 -0.815  0.597

Response Times

Intransitivities and response times (speed-accuracy tradeoff)

The y-axis is the proportion of intransitive triplets a trial is involved in. The higher lines for the numbers task might be confusing at first look given the few number of intransitivities in this task. It is because there are so few intransitivities that if a trial is involved in even a single intransitivity it translates to a larger proportions. The lower number if intransitivities for the numbers task is captured by the large error bars around the task (i.e. for each response time there are fewer non-zero data points involved in intransitivities compared to the choice task).

both.trial.data %>%
  ggplot(aes(RT, PropInIntransTriplet, group=Group, color=Group))+
  # You don't want to plot the raw measure because then a single subject who has done a lot of intransitivities and is in general faster can make it seem like faster trials are associated with more intransitivities. You want the proportional involvement given the total number of intransitivities a subject makes over response time
  # ggplot(aes(RT, IntransTripleCounted, group=Group, color=Group))+
  theme_bw()+
  geom_smooth(method = "loess", span = 5)+
  facet_grid(~Task)+
  ylim(c(0,NA))+
  xlab("Response Time")+
  ylab("Percent of intransitive Triplets involved")

Is there a statistical difference in the effect of response times on intransitivities between the two tasks?

We’re not necessarily interested in whether the exact slopes are different in the two tasks. We can see they might be visually. The main question of interest is two-fold:

  • Is there a speed-accuracy tradeoff? Are shorter RTs associated with more intransitivities (in a linear model: does the linear effect of RT have a negative slope)

  • Does this differ between groups and across the two different tasks.

First we do a model comparison and check whether the three-way interactions of RTs with groups and tasks as well as a quadratic effect of RTs lead to significant imporevements. Both do.

rt1 = lmer(PropInIntransTriplet ~ (1|f.id)+scale(RT)+Group*Task, both.trial.data)

#adding interaction of linear effect of RT between tasks and groups
rt2 = lmer(PropInIntransTriplet ~ (1|f.id)+scale(RT)*Group*Task, both.trial.data)

#adding the quadratic effect
rt3 = lmer(PropInIntransTriplet ~ (1|f.id)+scale(poly(RT,2))*Task*Group, both.trial.data)

anova(rt1, rt2, rt3)

So what does this model say? There is a significant linear effect of time where longer RTs are associated with more intransitivies (the opposite of a speed-accuracy tradeoff). There is a main effect of task where the numbers task has larger proportions of intransitivities but this as mentioned above is due to the lower number intransitivities per subject. The linear and quadratic effects of time are different for the ETL group compared to the control group. The increase in the proportion of intransitivities for the MTL group is less than the increase in this proportion for the control group (this isn’t interesting because the control group makes barely any intransitivities in the perceptual task). The change in the linear effect of time in the numbers task compared to the choice task is less this change for the control group (also not interesting because there is a quadratic effect of time for the ETL group and this change is not significant).

As qualitatively suggested in the above figure there is no negative slopes indicating a speed accuracy tradeoff for either task. Also crucially the interactions for the significant effects of time for each group are not significant: The interaction between the linear effect time and task for the control group, the threeway interaction between the linear effect of time and task for the MTL group and the threeway interaction between the quadratic effect of time and task for the ETL group are not significant. That is, the effect of time on intransitivities is the same for both tasks.

summary(rt3)
Linear mixed model fit by REML ['lmerMod']
Formula: PropInIntransTriplet ~ (1 | f.id) + scale(poly(RT, 2)) * Task *  
    Group
   Data: both.trial.data

REML criterion at convergence: 124868

Scaled residuals: 
   Min     1Q Median     3Q    Max 
 -2.52  -0.25  -0.17  -0.06  39.92 

Random effects:
 Groups   Name        Variance Std.Dev.
 f.id     (Intercept) 0.282    0.531   
 Residual             5.611    2.369   
Number of obs: 27302, groups:  f.id, 91

Fixed effects:
                                            Estimate Std. Error t value
(Intercept)                                   0.4000     0.1038    3.85
scale(poly(RT, 2))1                           0.2971     0.0365    8.13
scale(poly(RT, 2))2                          -0.0459     0.0345   -1.33
TaskPerceptual                                0.6372     0.1163    5.48
GroupETL                                      0.1094     0.1467    0.75
GroupMTL                                     -0.0145     0.1473   -0.10
scale(poly(RT, 2))1:TaskPerceptual            0.3847     0.2090    1.84
scale(poly(RT, 2))2:TaskPerceptual           -0.1390     0.1427   -0.97
scale(poly(RT, 2))1:GroupETL                  0.1083     0.0507    2.13
scale(poly(RT, 2))2:GroupETL                 -0.1066     0.0462   -2.31
scale(poly(RT, 2))1:GroupMTL                 -0.0974     0.0503   -1.93
scale(poly(RT, 2))2:GroupMTL                 -0.0239     0.0441   -0.54
TaskPerceptual:GroupETL                      -0.2695     0.1418   -1.90
TaskPerceptual:GroupMTL                      -0.2740     0.1332   -2.06
scale(poly(RT, 2))1:TaskPerceptual:GroupETL  -0.5733     0.2263   -2.53
scale(poly(RT, 2))2:TaskPerceptual:GroupETL   0.0283     0.1603    0.18
scale(poly(RT, 2))1:TaskPerceptual:GroupMTL  -0.1785     0.2228   -0.80
scale(poly(RT, 2))2:TaskPerceptual:GroupMTL   0.1121     0.1548    0.72

We can also analyze the speed accuracy tradeoff on triplet level by checking whether the response times to any of the three trials in each triplet is associated with whether that triplet is intransitive or not. The conclusions don’t change but this analysis is more fine-grained and the dependent measure might be more interpretable.

both.triplet.data = both.triplet.data %>%
  left_join(both.trial.data[,c("Task", "f.id", "Trialnumber", "RT")], by = c("Task", "f.id", "TrialA" = "Trialnumber")) %>%
  rename(RT_A = RT) %>%
    left_join(both.trial.data[,c("Task", "f.id", "Trialnumber", "RT")], by = c("Task", "f.id", "TrialB" = "Trialnumber")) %>%
  rename(RT_B = RT) %>%
    left_join(both.trial.data[,c("Task", "f.id", "Trialnumber", "RT")], by = c("Task", "f.id", "TrialC" = "Trialnumber")) %>%
  rename(RT_C = RT) %>%
  drop_na()
both.triplet.data %>%
  select(RT_A, RT_B, RT_C, Task, CleanIntr, Group, f.id) %>%
  gather(key, value, -Task, -CleanIntr, -f.id, -Group) %>%
  ggplot(aes(value, CleanIntr, group=Group, color=Group))+
  geom_smooth(method = "glm", method.args = list(family = "binomial"))+
  # geom_smooth(method = "lm")+
  theme_bw()+
  facet_grid(key~Task)+
  xlab("Response time")+
  ylab("Intransitive triplet")

In the linear regression I chose to look only at the effect of the response time in the third trial because:
- that’s the trial that would determine whether a trial is intransitive or not - the graph suggests that the relationship between response times and intransitive triplets is the same for the three trials - the response times for each trial in a triplet are higly correlated with each othe - Note: the full interactive model with all three response times does lead to significantly improved model but becomes too uninterpretable

#Note these should all be glmers; ran these because it was faster.
sa1 = lmer(CleanIntr ~ (1|f.id)+Task*Group+scale(RT_C), both.triplet.data)
sa2 = lmer(CleanIntr ~ (1|f.id)+Task*Group*scale(RT_C), both.triplet.data)
sa3 = lmer(CleanIntr ~ (1|f.id)+Task*Group+scale(RT_A)+scale(RT_B)+scale(RT_C), both.triplet.data)
sa4 = lmer(CleanIntr ~ (1|f.id)+Task*Group*scale(RT_C)+scale(RT_B)+scale(RT_A), both.triplet.data)
sa5 = lmer(CleanIntr ~ (1|f.id)+Task*Group+scale(RT_C)*scale(RT_B)*scale(RT_A), both.triplet.data)
sa6 = lmer(CleanIntr ~ (1|f.id)+Task*Group*scale(RT_C)*scale(RT_B)*scale(RT_A), both.triplet.data)

#need the interaction of rt_c
anova(sa1, sa2)
#additive with 3 rt's is better than only the third rt
anova(sa1, sa3)
#interactive with 3'rts is better than additive with 3 rt's
anova(sa3, sa4)
#for interactive do you need the main of the other two  - yes
anova(sa2, sa4)
#when using all three rt's is making them interactive better? - yes
anova(sa3, sa5)
#is the full interactive model with 3 rt's better than adding the other two rt's additively?-yes
anova(sa4, sa6)
#is the full interactive model with 3 rt's better than adding the rt interactions additively?-yes
anova(sa5, sa6)

Looking at the tasks in separate models because the interactive mode including the task takes a while to run: The model confirms that the slope is positive for all groups, suggesting that there is no speed accuracy tradeoff. In fact, we observe the opposite pattern where triplets are more likely to be intransitive if the response time for the last seen trial in that triplet is longer.

sa_val = lme4::glmer(CleanIntr ~ (1|f.id)+Group*scale(RT_C), family = binomial, both.triplet.data[both.triplet.data$Task == 'Value-based',])
summary(sa_val)
Generalized linear mixed model fit by maximum likelihood (Laplace
  Approximation) [glmerMod]
 Family: binomial  ( logit )
Formula: CleanIntr ~ (1 | f.id) + Group * scale(RT_C)
   Data: both.triplet.data[both.triplet.data$Task == "Value-based", ]

     AIC      BIC   logLik deviance df.resid 
   31766    31833   -15876    31752   100470 

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-0.809 -0.222 -0.175 -0.132 15.669 

Random effects:
 Groups Name        Variance Std.Dev.
 f.id   (Intercept) 0.494    0.703   
Number of obs: 100477, groups:  f.id, 91

Fixed effects:
                     Estimate Std. Error z value Pr(>|z|)    
(Intercept)           -3.7406     0.1340  -27.92  < 2e-16 ***
GroupETL               0.1337     0.1893    0.71  0.47987    
GroupMTL               0.7099     0.1865    3.81  0.00014 ***
scale(RT_C)            0.4479     0.0333   13.45  < 2e-16 ***
GroupETL:scale(RT_C)  -0.1470     0.0459   -3.20  0.00136 ** 
GroupMTL:scale(RT_C)  -0.2213     0.0417   -5.31  1.1e-07 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
            (Intr) GrpETL GrpMTL s(RT_C GETL:(
GroupETL    -0.706                            
GroupMTL    -0.718  0.508                     
scale(RT_C) -0.064  0.043  0.045              
GETL:(RT_C)  0.045 -0.050 -0.033 -0.724       
GMTL:(RT_C)  0.050 -0.035 -0.067 -0.798  0.579

Response times for groups

ggplot(data = both.trial.data, aes(x = Trialnumber, y = RT, group = Group, linetype = Group))+
  geom_smooth(method = "lm", color = "black")+
  theme_bw()+
  facet_grid(~Task)+
  xlab("Trial number")+
  ylab("Response time")

both.trial.data %>%
  group_by(Group, Task) %>%
  summarise(mean_RT = mean(RT),
            sd_RT = sd(RT),
            median_RT = median(RT))
# Full model for above graph. Not run because too long.
rt.lmer1 <- lmerTest::lmer(scale(RT) ~ Group*Task*scale(Trialnumber) + (1|f.id), data = RT.df[RT.df$RT>0,])

summary(rt.lmer1)

Group differences response times (reported)

summary(lmerTest::lmer(scale(RT) ~ Group + (1|f.id), data = choice2.trial.data[choice2.trial.data$RT>0,]))
Linear mixed model fit by REML t-tests use Satterthwaite approximations
  to degrees of freedom [lmerMod]
Formula: scale(RT) ~ Group + (1 | f.id)
   Data: choice2.trial.data[choice2.trial.data$RT > 0, ]

REML criterion at convergence: 42472

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-3.447 -0.614 -0.221  0.374 12.102 

Random effects:
 Groups   Name        Variance Std.Dev.
 f.id     (Intercept) 0.310    0.557   
 Residual             0.687    0.829   
Number of obs: 17084, groups:  f.id, 91

Fixed effects:
            Estimate Std. Error       df t value Pr(>|t|)  
(Intercept) -0.09598    0.10228 87.90000   -0.94    0.351  
GroupETL     0.00416    0.14465 87.90000    0.03    0.977  
GroupMTL     0.30282    0.14349 88.00000    2.11    0.038 *
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
         (Intr) GrpETL
GroupETL -0.707       
GroupMTL -0.713  0.504

Idiosyncratic stimulus effects

id.df = choice2.trial.data %>%
  select(IntransTripleCounted, Image_right, Image_left, f.id) %>%
  gather(key, value, -IntransTripleCounted, -f.id) %>%
  group_by(f.id,value) %>%
  summarise(sum_Intrans = sum(IntransTripleCounted))

summary(aov(sum_Intrans ~ factor(value) + Error(f.id/value), data = id.df))

Error: f.id
          Df Sum Sq Mean Sq F value Pr(>F)
Residuals 90 251369    2793               

Error: f.id:value
              Df Sum Sq Mean Sq F value Pr(>F)
factor(value)  1      1     0.5       0   0.96
Residuals     90  15112   167.9               

Error: Within
                Df Sum Sq Mean Sq F value Pr(>F)   
factor(value)   18   3572   198.5    2.12 0.0039 **
Residuals     1620 151328    93.4                  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#For exact values
# str(summary(aov(sum_Intrans ~ factor(value) + Error(f.id/value), data = id.df)))

Appendix

Correlations between response times for each trial in a triplet

both.triplet.data %>%
  select(Task, RT_A, RT_B, RT_C, Group, f.id) %>%
  gather(key, value, -Task, -RT_C, -Group, -f.id) %>%
  ggplot(aes(RT_C, value, group=Group, color=Group))+
  geom_smooth(method="lm")+
  theme_bw()+
  facet_grid(key ~ Task)+
  xlab("Response time for the third trial in the triplet")+
  ylab("Response times for the first \n and second trials in triplet")

LS0tCnRpdGxlOiAnSGlwcG9jYW1wYWwgZGVwZW5kZW5jZSBvZiB2YWx1ZS1iYXNlZCBkZWNpc2lvbnM6IFN0YXRpc3RpY2FsIEFuYWx5c2VzJwpvdXRwdXQ6CmdpdGh1Yl9kb2N1bWVudDoKdG9jOiB5ZXMKdG9jX2Zsb2F0OiB5ZXMKLS0tCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShsbWU0KQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeSh4bHN4KQpsaWJyYXJ5KEhtaXNjKQpzZW0gPC0gZnVuY3Rpb24oeCkge3NkKHgsIG5hLnJtPVQpIC8gc3FydChsZW5ndGgoeCkpfQpyZW5kZXJfdGhpcyA8LSBmdW5jdGlvbigpe3JtYXJrZG93bjo6cmVuZGVyKCdUcmFuc2l0aXZpdHlfT3BlbkFuYWx5c2VzLlJtZCcsIG91dHB1dF9kaXIgPSAnL1VzZXJzL3pleW5lcGVua2F2aS9Ecm9wYm94L0NEU1BhcnQxL1RyYW5zaXRpdml0eU9wZW4vJywgaHRtbF9ub3RlYm9vayh0b2MgPSBULCB0b2NfZmxvYXQgPSBULCBjb2RlX2ZvbGRpbmcgPSAnaGlkZScpKX0Kb3B0aW9ucyhzY2lwZW4gPSAxLCBkaWdpdHMgPSA0KQpgYGAKCkxvYWQgd29ya3NwYWNlCgpgYGB7cn0KbG9hZCgiL1VzZXJzL3pleW5lcGVua2F2aS9Ecm9wYm94L0NEU1BhcnQxL1RyYW5zaXRpdml0eU9wZW4vVHJhbnNpdGl2aXR5X09wZW5EYXRhT3JnYW5pemF0aW9uV1MwNTI4MTcuUkRhdGEiKQpgYGAKCkdyb3VwIGRpZmZlcmVuY2VzIGluIGludHJhbnNpdGl2aWVzCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMgU3VtbWFyeSBTdGF0aXN0aWNzCgpgYGB7cn0KYm90aC5JbnRyYW5zaXRpdmUgJT4lCiAgZ3JvdXBfYnkoVGFzaywgR3JvdXApICU+JQogIHN1bW1hcmlzZShtZWFuX0NsZWFuSW50ciA9IG1lYW4oQ2xlYW5JbnRyKSwKICAgICAgICAgICAgbWVkaWFuX0NsZWFuSW50ciA9IG1lZGlhbihDbGVhbkludHIpLAogICAgICAgICAgICBzZF9DbGVhbkludHIgPSBzZChDbGVhbkludHIpLAogICAgICAgICAgICBtZWFuX0NsZWFuUGVyY2VudEludHIgPSBtZWFuKENsZWFuUGVyY2VudEludHIpLAogICAgICAgICAgICBtZWRpYW5fQ2xlYW5QZXJjZW50SW50ciA9IG1lZGlhbihDbGVhblBlcmNlbnRJbnRyKSwKICAgICAgICAgICAgc2RfQ2xlYW5QZXJjZW50SW50ciA9IHNkKENsZWFuUGVyY2VudEludHIpKQpgYGAKCmBgYHtyfQpib3RoLkludHJhbnNpdGl2ZSAlPiUgCiAgZ3JvdXBfYnkoVGFzaywgR3JvdXApICU+JSAKICBzdW1tYXJpc2UoTWVhbkNsZWFuUGVyY2VudEludHIgPSBtZWFuKENsZWFuUGVyY2VudEludHIsIG5hLnJtPVQpLAogICAgICAgICAgICBTZUNsZWFuUGVyY2VudEludHIgPSBzZW0oQ2xlYW5QZXJjZW50SW50ciksCiAgICAgICAgICAgIGViLmxvdyA9IE1lYW5DbGVhblBlcmNlbnRJbnRyIC0gU2VDbGVhblBlcmNlbnRJbnRyLAogICAgICAgICAgICBlYi5oaWdoID0gTWVhbkNsZWFuUGVyY2VudEludHIgKyBTZUNsZWFuUGVyY2VudEludHIpICU+JQpnZ3Bsb3QoYWVzKHggPSBHcm91cCwgeT1NZWFuQ2xlYW5QZXJjZW50SW50ciwgZ3JvdXAgPSBUYXNrKSkrCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBUYXNrKSkrCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZSA9IFRhc2spKSsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWF4ID0gZWIuaGlnaCwgeW1pbj1lYi5sb3cpLCB3aWR0aD0wLjI1KSsKICB5bGFiKCJNZWFuIFBlcmNlbnRhZ2Ugb2YgSW50cmFuc2l0aXZpdGllcyIpKwogIHhsYWIoIiIpKwogIHRoZW1lX2J3KCkrCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLCBzaXplID0gMTQpLAogICAgICAgIGF4aXMudGV4dC54ICA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiwgc2l6ZSA9IDE0KSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSsKICBzY2FsZV9zaGFwZV9kaXNjcmV0ZShicmVha3MgPSBjKCJjaG9pY2UiLCAibnVtYmVycyIpLAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlZhbHVlLWJhc2VkIiwgIk51bWJlcnMiKSkrCiAgc2NhbGVfbGluZXR5cGVfZGlzY3JldGUoYnJlYWtzID0gYygiY2hvaWNlIiwgIm51bWJlcnMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJWYWx1ZS1iYXNlZCIsICJOdW1iZXJzIikpCmBgYAoKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cmdnc2F2ZSgiL1VzZXJzL3pleW5lcGVua2F2aS9Ecm9wYm94L0NEU1BhcnQxL1RyYW5zaXRpdml0eU9wZW4vQ2xlYW5GaWd1cmUyLnBuZyIsIHdpZHRoPTYsIGhlaWdodD00LCBkcGk9MzAwKQpgYGAKCkxvb2tpbmcgYXQgdGhlIHBsb3Qgd2UgYXJlIGludGVyZXN0ZWQgaW4gd2hldGhlciB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gbGluZXMgaXMgdGhlIHNhbWUgZm9yIGFsbCBncm91cHMuIEluIG90aGVyIHdvcmRzOiBJcyB0aGVyZSBhIHNpZ25pZmljYW50IGludGVyZWFjdGlvbiBiZXR3ZWVuIHRhc2sgYW5kIGdyb3VwLCBpLmUuIGlzIHRoZSBlZmZlY3Qgb2YgY2hhbmdpbmcgdGhlIHRhc2sgc2FtZSBmb3IgdGhlIE1UTCBncm91cCBhcyBpdCBpcyBmb3IgdGhlIGNvbnRyb2wgZ3JvdXBzLgoKVG8gY2hvb3NlIHRoZSBjb3JyZWN0IG1vZGVsIHRoYXQgd291bGQgY2hlY2sgZm9yIHN0YXRpc3RpY2FsIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGdyb3VwcyB3ZSBjaGVja2VkIHRoZSBhc3N1bXB0aW9ucyBmb3IgZWFjaCBwb3NzaWJpbGl0eS4gVGhvdWdoIGFsbCBtZXRob2RzIHlpZWxkIGVzc2VudGlhbGx5IHRoZSBzYW1lIGFuc3dlciB3ZSBjaG9zZSB0byB1c2UgYSBsaW5lYXIgbWl4ZWQgbW9kZWwgd2l0aCBvcnRob2dvbmFsIGNvbnRyYXN0cyBiZWNhdXNlIGl0IHdhcyB0aGUgbW9zdCBhcHByb3ByaWF0ZSBtZXRob2QuIAoKVGhlIGZpcnN0IHRoaW5nIHdlIGNvdWxkIGRvIHdvdWxkIGJlIGEgb25lLXdheSBBTk9WQSBmb3IgYm90aCB0YXNrcyBjaGVja2luZyB3aGV0aGVyIHRoZSBtYWluIGRlcGVuZGVudCBtZWFzdXJlIChwZXJjZW50YWdlIG9mIGludHJhbnNpdGl2aXRpZXMpIGRpZmZlcnMgZGVwZW5kaW5nIG9uIHRoZSBncm91cCBhbmQgdGFzay4gVGhlIGRpc3RyaWJ1dGlvbiBvZiBlZmZlY3Qgc2l6ZXMgd2l0aGluIHRhc2tzLCBob3dldmVyLCBpcyBub3Qgbm9ybWFsIGZvciBlaXRoZXIgdGFzaywgd2hpY2ggaXMgd2h5IHRoaXMgd291bGQgbm90IGJlIGFuIGFwcHJvcHJpYXRlIHRlc3QuIAoKYGBge3IgbWVzc2FnZT1GQUxTRX0gCmJvdGguSW50cmFuc2l0aXZlICU+JQogIGdncGxvdChhZXMoQ2xlYW5QZXJjZW50SW50ciwgZmlsbD1Hcm91cCkpKwogIGdlb21faGlzdG9ncmFtKHBvc2l0aW9uPSJpZGVudGl0eSIsIGFscGhhPTAuNSkrCiAgdGhlbWVfYncoKSsKICB4bGFiKCJQZXJjZW50YWdlIG9mIGludHJhbnNpdGl2aXR5IikrCiAgZmFjZXRfd3JhcCh+VGFzaykKYGBgICAKCgpgYGB7cn0Kc2hhcGlyby50ZXN0KGJvdGguSW50cmFuc2l0aXZlW2JvdGguSW50cmFuc2l0aXZlJFRhc2sgPT0gIm51bWJlcnMiLF0kQ2xlYW5QZXJjZW50SW50cikKYGBgCgpgYGB7cn0Kc2hhcGlyby50ZXN0KGJvdGguSW50cmFuc2l0aXZlW2JvdGguSW50cmFuc2l0aXZlJFRhc2sgPT0gImNob2ljZSIsXSRDbGVhblBlcmNlbnRJbnRyKQpgYGAKClRvIHNvbHZlIHRoaXMgd2UgY291bGQgdHJ5IGEgbm9uLXBhcmFtZXRyaWMgdGVzdCAoZS5nLiBLcnVza2FsbC1XYWxsaXMpIGJ1dCB0aGlzIHdvdWxkbid0IGFsbG93IHVzIHRvIGNoZWNrIHRoZSBpbnRlcmFjdGlvbiBvZiBncm91cCBieSB0YXNrIGFuZCBtb3JlIGltcG9ydGFudGx5IHRoZSB2YXJpYW5jZSBpbiB0aGUgZWZmZWN0IHNpemUgZGlzdHJpYnV0aW9ucyBhcmUgdW5lcXVhbC4gVGhhdCBpcywgYXMgdGhlIEJhcnRsZXR0IHRlc3QgYmVsb3cgYW5kIHRoZSBwbG90IGFib3ZlIHNob3dzIHZhcmlhbmNlIGluIGVmZmVjdCBzaXplIGlzIG5vdCBpbmRlcGVuZGVudCBvZiB0YXNrLgoKYGBge3IgbWVzc2FnZT1GQUxTRX0KYmFydGxldHQudGVzdChDbGVhblBlcmNlbnRJbnRyIH4gVGFzaywgZGF0YSA9IGJvdGguSW50cmFuc2l0aXZlKQpgYGAKClRvIGRlYWwgd2l0aCB0aGlzIGlzc3VlIG9mIHRhc2sgZGVwZW5kZW5jZSBvZiB0aGUgdmFyaWFuY2Ugd2UgbG9nIHRyYW5zZm9ybSB0aGUgZWZmZWN0IHNpemVzLgoKYGBge3J9CmJhcnRsZXR0LnRlc3QobG9nKENsZWFuUGVyY2VudEludHIgKyAxKSB+IFRhc2ssIGRhdGEgPSBib3RoLkludHJhbnNpdGl2ZSkKYGBgCgpVc2luZyB0cmFuc2Zvcm1lZCBkZXBlbmRlbnQgdmFyaWFibGVzIHdlIGZpcnN0IGNvbmZpcm0gdGhhdCB0aGUgaW50ZXJhY3RpdmUgbW9kZWwgaXMgdGhlIGJlc3QgZml0dGluZyBtb2RlbCBieSBjb21wYXJpbmcgaXQgdG8gbmVzdGVkIHNpbXBsZXIgbW9kZWxzLgoKYGBge3J9CmdtMWEgPC0gbG0obG9nKENsZWFuUGVyY2VudEludHIrMSkgfiBUYXNrLCBib3RoLkludHJhbnNpdGl2ZSkjOyBzdW1tYXJ5KGdtMWEpCmdtMWIgPC0gbG0obG9nKENsZWFuUGVyY2VudEludHIrMSkgfiBHcm91cCwgYm90aC5JbnRyYW5zaXRpdmUpIyA7IHN1bW1hcnkoZ20xYikKZ20yIDwtIGxtKGxvZyhDbGVhblBlcmNlbnRJbnRyKzEpIH4gR3JvdXArVGFzaywgYm90aC5JbnRyYW5zaXRpdmUpIyA7IHN1bW1hcnkoZ20yKQpnbTMgPC0gbG0obG9nKENsZWFuUGVyY2VudEludHIrMSkgfiBHcm91cCpUYXNrLCBib3RoLkludHJhbnNpdGl2ZSkjIDsgc3VtbWFyeShnbTMpCmBgYAoKYGBge3J9CmFub3ZhKGdtMWEsIGdtMiwgZ20zKQpgYGAKCmBgYHtyfQphbm92YShnbTFiLCBnbTIsIGdtMykKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpybShnbTFhLCBnbTFiLCBnbTIpCmBgYAoKU28gd2hhdCBkb2VzIHRoaXMgaW50ZXJhY3RpdmUgbW9kZWwgc2F5PyBUbyBnZXQgYSBiZXR0ZXIgdW5kZXJzdGFuZGluZyBvZiB0aGlzIHdlIGZpcnN0IGxvb2sgYXQgdGhlIGNvbnRyYXN0cyB1c2VkIGluIHRoaXMgbW9kZWwuCgpgYGB7cn0KY29udHJhc3RzKGJvdGguSW50cmFuc2l0aXZlJFRhc2spCmBgYAoKYGBge3J9CmNvbnRyYXN0cyhib3RoLkludHJhbnNpdGl2ZSRHcm91cCkKYGBgCgpCYXNlZCBvbiB0aGVzZSBjb250cmFzdHMgdGhlIGdyb3VwIGRpZmZlcmVuY2VzIGluIHRoaXMgbW9kZWwgY29tcGFyZSBib3RoIHBhdGllbnQgZ3JvdXBzIHRvIHRoZSBoZWFsdGh5IGNvbnRyb2wgYWxvbmUuIEFjY29yZGluZ2x5IHRoZSBwYXJhbWV0ZXJzIG9mIHRoZSBsaW5lYXIgbW9kZWwgd291bGQgaGF2ZSB0aGUgZm9sbG93aW5nIGludGVycHJldGF0aW9ucy4KCmBgYHtyfQpzdW1tYXJ5KGdtMykKYGBgCgpiMCA9IG1lYW4gcGVyY2VudGFnZSBvZiBpbnRyYW5zaXRpdml0eSBmb3IgYm90aCB0YXNrcyBmb3IgdGhlIEMgZ3JvdXAgaXMgPjAgKG5vdCBpbnRlcmVzdGluZykKYjEgPSBFVEwgZ3JvdXAgZG9lc24ndCBtYWtlIHNpZ25pZmljYW50bHkgbW9yZSBpbnRyYW5zIGluIENIT0lDRSB0YXNrISAoZ29vZCkgLSBzaW1wbGUgZWZmZWN0CmIyID0gTVRMIGdyb3VwIERPRVMgbWFrZSBzaWcgbW9yZSBpbnRyYW5zIGluIENIT0lDRSB0YXNrISAoZ29vZCkgLSBzaW1wbGUgZWZmZWN0CmIzID0gQyBncm91cCBtYWtlcyBzaWcgbGVzcyBpbnRyYW5zIGluIE5VTUJFUlMgdGFzayEgKG5vdCBzdXJwcmlzaW5nLCBlYXN5IHRhc2spCmI0ID0gSXMgdGhlIGVmZmVjdCBvZiB0YXNrIGluIEVUTCBncm91cCBzYW1lIGFzIEMuIFllcy4KYjUgPSBJcyB0aGUgZWZmZWN0IG9mIHRhc2sgaW4gTVRMIGdyb3VwIHNhbWUgYXMgQy4gTWFyZ2luYWxseSBuby4gCgpBcyBtZW50aW9uZWQgYWJvdmUsIGhvd2V2ZXIsIHRoZXNlIGFyZSBub3Qgb3J0aG9nb25hbCBjb250cmFzdHMgYW5kIGFyZSBjb21wYXJpbmcgYm90aCBncm91cHMgdG8gSGVhbHRoeSBjb250cm9scyBvbmx5ISBCdXQgd2UgYXJlIGludGVyZXN0ZWQgaW4gY29tcGFyaW5nIHRoZSBNVEwgZ3JvdXAgdG8gYm90aCBjb250cm9sIGdyb3Vwcy4gVG8gYW5zd2VyIHRoaXMgcXVlc3Rpb24gYW5kIHRvIGF2b2lkIG92ZXJsYXBwaW5nIHZhcmlhbmNlIHdlIG9ydGhvZ29uYWxpemUgdGhlIGNvbnRyYXN0cy4gVGhpcyB3b3VsZCByZXN1bHRzIGluIGZpcnN0IGNvbXBhcmluZyB0aGUgRVRMIGdyb3VwIHRvIHRoZSBDIGdyb3VwIGFuZCB0aGVuIHRoZSBNVEwgZ3JvdXAgdG8gQk9USCBDT05UUk9MIEdST1VQUyEKCmBgYHtyfQojQ2hhbmdlIHRoZSBjb250cmFzdHMsIG1ha2UgdGhlbSBvcnRob2dvbmFsCmJvdGguSW50cmFuc2l0aXZlLmNvbnRyYXN0IDwtIGJvdGguSW50cmFuc2l0aXZlCmNvbnRyYXN0cyhib3RoLkludHJhbnNpdGl2ZS5jb250cmFzdCRHcm91cCkgPC0gY2JpbmQoYygtMSwxLCAwKSwgYygtMSwgLTEsIDIpKQpjb250cmFzdHMoYm90aC5JbnRyYW5zaXRpdmUuY29udHJhc3QkVGFzaykgPC0gYygtMSwgMSkKCmdtMy5jb24gPC0gbG0obG9nKENsZWFuUGVyY2VudEludHIrMSkgfiBHcm91cCpUYXNrLCBib3RoLkludHJhbnNpdGl2ZS5jb250cmFzdCkgCnN1bW1hcnkoZ20zLmNvbikKYGBgCgpXaGF0IGRvZXMgdGhlIG1vZGVsIHNheSBub3c6CgpiMCA9IFVud2VpZ2h0ZWQgZ3JhbmQgbWVhbiAobWVhbiBvZiBncm91cCBtZWFucykgKHN1bShhZ2dyZWdhdGUoQ2xlYW5QZXJjZW50SW50ciB+IEdyb3VwLCBib3RoLkludHJhbnNpdGl2ZS5jb250cmFzdCwgbWVhbilbLDJdKS8zKQpiMSA9IFRvdGFsIGdyb3VwIGVmZmVjdCBmb3IgRVRMIGNvbXBhcmVkIHRvIGhlYWx0aHkgY29udHJvbHMgb25seSAocXVhbnRpZmllZCkKYjIgPSBUb3RhbCBncm91cCBlZmZlY3QgZm9yIE1UTCBjb21wYXJlZCB0byBib3RoIGNvbnRyb2wgZ3JvdXBzIChxdWFudGlmaWVkKQpiMyA9IFRvdGFsIHRhc2sgZWZmZWN0CmI0ID0gSXMgdGhlIGVmZmVjdCBvZiB0YXNrIGNoYW5nZSBzYW1lIGZvciBFVEwgYW5kIEMgZ3JvdXBzPyAoeWVzLikKYjUgPSBJcyB0aGUgZWZmZWN0IG9mIHRhc2sgY2hhbmdlIHNhbWUgZm9yIE1UTCB2cyBib3RoIGNvbnRyb2wgZ3JvdXBzPyAoTm8hKQoKU2luY2UgdGhlcmUgYXJlIHR3byBtZWFzdXJlcyBwZXIgc3ViamVjdCB3ZSBjaGVjayBpZiBhIG1peGVkIG1vZGVsIG5lY2Vzc2FyeSBjb21wYXJpbmcgdGhlIGxvZy1saWtlbGlob29kcyBvZiBhIG1vZGVsIHdpdGggcmFuZG9tIGVmZmVjdHMgdG8gb25lIHdpdGhvdXQgdGhlbS4gV2UgZmluZCB0aGF0IHRoYXQgYSBtb2RlbCB3aXRoIHJhbmRvbSBlZmZlY3RzIGlzIGluZGVlZCBzaWduaWZpY2FudGx5IGJldHRlciBmaXQgdG8gZGF0YS4KCmBgYHtyfQpnbTMubG1lci5jb24gPC0gbG1lclRlc3Q6OmxtZXIobG9nKENsZWFuUGVyY2VudEludHIrMSkgfiBHcm91cCpUYXNrICsgKDF8Zi5pZCksIGJvdGguSW50cmFuc2l0aXZlLmNvbnRyYXN0LCBSRU1MID0gRikKCngyID0gLTIqbG9nTGlrKGdtMy5jb24pICsyKmxvZ0xpayhnbTMubG1lci5jb24pCngyCnBjaGlzcSh4MiwgZGY9MSwgbG93ZXIudGFpbD1GKQpgYGAKCgpgYGB7cn0Kc3VtbWFyeShnbTMubG1lci5jb24pIApgYGAKClRoZSBsaW5lYXIgbWl4ZWQgbW9kZWwgd2l0aCBvcnRob2dvbmFsIGNvbnRyYXN0cyBpcyB0aGUgbW9zdCBhcHByb3ByaWF0ZSBhbmFseXNpcyBhbmQgcmV2ZWFscyBhIHNpZ25pZmljYW50IGdyb3VwIHRhc2sgaW50ZXJhY3Rpb24gaW4gdGhlIHBlcmNlbnRhZ2Ugb2YgaW50cmFuc2l0aXZpdGllcy4gQWNjb3JkaW5nbHkgdGhlIE1UTCBncm91cCBoYWQgYSBoaWdoZXIgcGVyY2VudGFnZSBvZiBpbnRyYW5zaXRpdml0aWVzIGluIHRoZSBjaG9pY2UgdGFzayB0aGFuIHRoZSBudW1iZXJzIHRhc2sgY29tcGFyZWQgdG8gYm90aCBjb250cm9sIGdyb3Vwcywgd2hpbGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcGVyY2VudGFnZSBvZiBpbnRyYW5zaXRpdml0aWVzIGRpZCBub3QgZGlmZmVyIGJldHdlZW4gdGFza3MgYmV0d2VlbiB0aGUgaGVhbHRoIGNvbnRyb2xzIGFuZCB0aGUgRVRMIGdyb3VwLgoKTGVzaW9uIHNpemUgYW5kIGludHJhbnNpdGl2aWVzCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpgYGB7cn0Kc3ltbWV0cnkuZGF0YSA8LSByZWFkLnhsc3goIi9Vc2Vycy96ZXluZXBlbmthdmkvRHJvcGJveC9DRFNQYXJ0MS9UcmFuc2l0aXZpdHkvVHJhbnNpdGl2aXR5RGF0YS9TeW1tZXRyeV9pbmRleF96ZXluZXAueGxzeCIsIDEpCgpzeW1tZXRyeS5kYXRhID0gYm90aC5JbnRyYW5zaXRpdmUgJT4lCiAgZmlsdGVyKFRhc2sgPT0gJ2Nob2ljZScpICU+JQogIG11dGF0ZShJRCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGYuaWQpKSkgJT4lCiAgcmlnaHRfam9pbihzeW1tZXRyeS5kYXRhLCBieT0gJ0lEJykgJT4lCiAgZHJvcF9uYSgpCmBgYAoKU3BlYXJtYW4gY29ycmVsYXRpb24gYmV0d2VlbiBpbnN0cmFuc2l0aXZpdHkgcGVyY2VudGFnZSBhbmQgbGVzaW9uIHNpemUKCmBgYHtyfQpjb3Ioc3ltbWV0cnkuZGF0YSRTeW1tZXRyeS5pbmRleCwgc3ltbWV0cnkuZGF0YSRDbGVhblBlcmNlbnRJbnRyLCBtZXRob2QgPSAic3BlYXJtYW4iKQpgYGAKClNpZ25pZmljYW5jZSB0ZXN0IGZvciB0aGUgU3BlYXJtYW4gY29ycmVsYXRpb24KCmBgYHtyfQpzcGVhcm1hbi50ZXN0KHN5bW1ldHJ5LmRhdGEkU3ltbWV0cnkuaW5kZXgsIHN5bW1ldHJ5LmRhdGEkQ2xlYW5QZXJjZW50SW50cikKYGBgCgpQbG90IG9mIGNvcnJlbGF0aW9uIGJldHdlZW4gCgpgYGB7cn0KZ2dwbG90KHN5bW1ldHJ5LmRhdGEsIGFlcyhTeW1tZXRyeS5pbmRleCwgQ2xlYW5QZXJjZW50SW50cikpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG9lc3MnLCBzcGFuID0gMiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuMSwgbGluZXR5cGUgPSAiZGFzaGVkIikrCiAgdGhlbWVfYncoKSsKICB5bGFiKCJQZXJjZW50YWdlIG9mIEludHJhbnNpdHZlIENob2ljZSIpKwogIHhsYWIoIkNvbXByb21pc2VkIEhpcHBvY2FtcGFsIFJhdGlvIikrCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLCBzaXplID0gMTQpLAogICAgICAgIGF4aXMudGl0bGUueCAgPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsIHNpemUgPSAxNCksCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkKYGBgCgoKYGBge3J9Cmdnc2F2ZSgiL1VzZXJzL3pleW5lcGVua2F2aS9Ecm9wYm94L0NEU1BhcnQxL1RyYW5zaXRpdml0eU9wZW4vQ2xlYW5GaWd1cmUzLnBuZyIsIHdpZHRoPTQsIGhlaWdodD00LCBkcGk9MzAwKQoKYGBgCgpTaW11bGF0aW9ucwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQpwYXRoID0gJy9Vc2Vycy96ZXluZXBlbmthdmkvRHJvcGJveC9DRFNQYXJ0MS9UcmFuc2l0aXZpdHlPcGVuL3NpbV9vdXRwdXQvJwoKZmlsZUxpc3QgPSBsaXN0LmZpbGVzKHBhdGgscGF0dGVybiA9ICIqX2hhcmRtYXguY3N2IikKCnJlYWRfY3N2X2ZuIDwtIGZ1bmN0aW9uKGZpbGVuYW1lKXsKICAgIHJldCA8LSByZWFkLmNzdihmaWxlbmFtZSkKICAgIHJldCRTb3VyY2UgPC0gZmlsZW5hbWUgCiAgICByZXQKfQoKbGFwcGx5KHBhc3RlMChwYXRoLCBmaWxlTGlzdCksIHJlYWRfY3N2X2ZuKSAgJT4lIAogIGJpbmRfcm93cygpICU+JQogIHNlcGFyYXRlKFNvdXJjZSwgYygiYSIsICJiIiwgImMiLCAiZCIsICJlIiwgImYiLCJnIiwgInNpbSIpLHNlcCA9ICIvIikgJT4lCiAgc2VsZWN0KHBjdF9JbnRyYW5zLCBzaW0pICU+JQogIHNlcGFyYXRlKHNpbSwgYygiYSIsICJiIiwgImMiLCAiZCIsICJub2lzZSIsICJlIiwgImYiKSwgc2VwID0gIl8iKSAlPiUKICBzZWxlY3QocGN0X0ludHJhbnMsIG5vaXNlKSAlPiUKICBmaWx0ZXIobm9pc2UgJWluJSBjKDAuMDUsIDAuMjUpID09IEZBTFNFKSAlPiUKICBncm91cF9ieShub2lzZSkgJT4lCiAgc3VtbWFyaXNlKG1lYW5fSW50cmFucyA9IG1lYW4ocGN0X0ludHJhbnMpLAogICAgICAgICAgICBzZW1fSW50cmFucyA9IHNlbShwY3RfSW50cmFucykpICU+JQogIGdncGxvdChhZXMobm9pc2UsIG1lYW5fSW50cmFucykpKwogIGdlb21fcG9pbnQoKSsKICB0aGVtZV9idygpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuX0ludHJhbnMtc2VtX0ludHJhbnMsIHltYXggPSBtZWFuX0ludHJhbnMrc2VtX0ludHJhbnMpLCB3aWR0aD0wLjI1KSsKICB5bGFiKCJQZXJjZW50YWdlIG9mIEludHJhbnNpdml0eSIpKwogIHhsYWIoIk5vaXNlIGxldmVsIikjKwogICMgZ2d0aXRsZSgiUmVzdWx0cyBvZiBzaW11bGF0aW9uIHVzaW5nIGhhcmRtYXgiKQpgYGAKCmBgYHtyfQpmaWxlTGlzdCA9IGxpc3QuZmlsZXMocGF0aCxwYXR0ZXJuID0gIipfcmJpbm9tLmNzdiIpCgpsYXBwbHkocGFzdGUwKHBhdGgsIGZpbGVMaXN0KSwgcmVhZF9jc3ZfZm4pICAlPiUgCiAgYmluZF9yb3dzKCkgJT4lCiAgc2VwYXJhdGUoU291cmNlLCBjKCJhIiwgImIiLCAiYyIsICJkIiwgImUiLCAiZiIsImciLCAic2ltIiksc2VwID0gIi8iKSAlPiUKICBzZWxlY3QocGN0X0ludHJhbnMsIHNpbSkgJT4lCiAgc2VwYXJhdGUoc2ltLCBjKCJhIiwgImIiLCAiYyIsICJkIiwgIm5vaXNlIiwgImUiLCAiZiIpLCBzZXAgPSAiXyIpICU+JQogIHNlbGVjdChwY3RfSW50cmFucywgbm9pc2UpICU+JQogIGZpbHRlcihub2lzZSAlaW4lIGMoMC4wNSwgMC4yNSkgPT0gRkFMU0UpICU+JQogIGdyb3VwX2J5KG5vaXNlKSAlPiUKICBzdW1tYXJpc2UobWVhbl9JbnRyYW5zID0gbWVhbihwY3RfSW50cmFucyksCiAgICAgICAgICAgIHNlbV9JbnRyYW5zID0gc2VtKHBjdF9JbnRyYW5zKSkgJT4lCiAgZ2dwbG90KGFlcyhub2lzZSwgbWVhbl9JbnRyYW5zKSkrCiAgZ2VvbV9wb2ludCgpKwogIHRoZW1lX2J3KCkrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW5fSW50cmFucy1zZW1fSW50cmFucywgeW1heCA9IG1lYW5fSW50cmFucytzZW1fSW50cmFucyksIHdpZHRoPTAuMjUpKwogIHlsYWIoIlBlcmNlbnRhZ2Ugb2YgSW50cmFuc2l2aXR5IikrCiAgeGxhYigiTm9pc2UgbGV2ZWwiKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDI1LDUpLCBsaW1pdHM9YygwLCAyNikpKwogIGdndGl0bGUoIlJlc3VsdHMgb2Ygc2ltdWxhdGlvbiBmbGlwcGluZyBjb2luIHdpdGggbm9pc3kgY2hvaWNlIHAiKQpgYGAKCmBgYHtyfQpmaWxlTGlzdCA9IGxpc3QuZmlsZXMocGF0aCxwYXR0ZXJuID0gIipfZXBzaWxvbi5jc3YiKQoKbGFwcGx5KHBhc3RlMChwYXRoLCBmaWxlTGlzdCksIHJlYWRfY3N2X2ZuKSAgJT4lIAogIGJpbmRfcm93cygpICU+JQogIHNlcGFyYXRlKFNvdXJjZSwgYygiYSIsICJiIiwgImMiLCAiZCIsICJlIiwgImYiLCJnIiwgInNpbSIpLHNlcCA9ICIvIikgJT4lCiAgc2VsZWN0KHBjdF9JbnRyYW5zLCBzaW0pICU+JQogIHNlcGFyYXRlKHNpbSwgYygiYSIsICJiIiwgImMiLCAiZCIsICJub2lzZSIsICJlIiwgImYiKSwgc2VwID0gIl8iKSAlPiUKICBzZWxlY3QocGN0X0ludHJhbnMsIG5vaXNlKSAlPiUKICBmaWx0ZXIobm9pc2UgJWluJSBjKDAuMDUsIDAuMjUpID09IEZBTFNFKSAlPiUKICBncm91cF9ieShub2lzZSkgJT4lCiAgc3VtbWFyaXNlKG1lYW5fSW50cmFucyA9IG1lYW4ocGN0X0ludHJhbnMpLAogICAgICAgICAgICBzZW1fSW50cmFucyA9IHNlbShwY3RfSW50cmFucykpICU+JQogIGdncGxvdChhZXMobm9pc2UsIG1lYW5fSW50cmFucykpKwogIGdlb21fcG9pbnQoKSsKICB0aGVtZV9idygpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuX0ludHJhbnMtc2VtX0ludHJhbnMsIHltYXggPSBtZWFuX0ludHJhbnMrc2VtX0ludHJhbnMpLCB3aWR0aD0wLjI1KSsKICB5bGFiKCJQZXJjZW50YWdlIG9mIEludHJhbnNpdml0eSIpKwogIHhsYWIoIk5vaXNlIGxldmVsIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwyNSw1KSwgbGltaXRzPWMoMCwgMjYpKSsKICBnZ3RpdGxlKCJSZXN1bHRzIG9mIHNpbXVsYXRpb24gd2l0aCBlcHNpbG9uIGdyZWVkeSIpCmBgYAoKQWx0ZXJuYXRpdmUgZXhwbGFuYXRpb25zIG9mIGludHJhbnNpdGl2aXR5Ci0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIEVwaXNvZGljIG1lbW9yeQoKT25lIGFsdGVybmF0aXZlIGV4cGxhbmF0aW9uIG9mIHRoZSBoaWdoZXIgbGV2ZWwgb2YgaW50cmFuc2l0aXZpdGllcyBpbiB0aGUgTVRMIGdyb3VwIGlzIGFib3V0IGVwaXNvZGljIG1lbW9yeSBkZWZpY2l0cy4gQWNjb3JkaW5nbHksIHRoZSBNVEwgZ3JvdXAgbWlnaHQgYmUgc2hvd2luZyBoaWdoZXIgcmF0ZXMgb2YgaW50cmFuc2l0aXZpdHkgYmVjYXVzZSB0aGV5IGFyZSB1bmFibGUgdG8gcmVjYWxsIGNob2ljZXMgdGhleSBoYXZlIG1hZGUgZWFybGllciBpbiB0aGUgdGFzay4gVGhpcyBoeXBvdGhlc2lzIHdvdWxkIHByZWRpY3QgYSBwYXR0ZXJuIG9mIHByb3BvcnRpb24gb2YgaW50cmFuc2l0aXZlIHRyaXBsZXRzIGVhY2ggdHJpYWwgd2FzIGludm9sdmVkIGluIHRoYXQgaW5jcmVhc2VzIHRvd2FyZHMgdGhlIGVuZCBvZiB0aGUgdGFzayAodGhlIGxhdGVyIHRoZSB0cmlhbCB0aGUgbW9yZSBpbnRyYW5zaXRpdmUgdHJpcGxldHMgaXQgd2FzIGludm9sdmVkIGluKS4gVGhlIGZpZ3VyZSBiZWxvdyBzaG93cyB0aGUgZW1waXJpY2FsIGNoYW5nZSBvZiBpbnRyYW5zaXRpdmUgdHJpcGxldCBpbnZvbHZlbWVudCB3aXRoIHRyaWFsIG51bWJlci4KCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmNob2ljZTIudHJpYWwuZGF0YSRUYXNrIDwtICJjaG9pY2UiCm51bWJlcnMudHJpYWwuZGF0YSRUYXNrIDwtICJudW1iZXJzIgoKYm90aC50cmlhbC5kYXRhIDwtIHJiaW5kKGNob2ljZTIudHJpYWwuZGF0YVssYygiZi5pZCIsICJHcm91cCIsICJSVCIsICJUYXNrIiwgIlRyaWFsbnVtYmVyIiwgIkludHJhbnNUcmlwbGVDb3VudGVkIildLCBudW1iZXJzLnRyaWFsLmRhdGFbLGMoImYuaWQiLCAiR3JvdXAiLCAiUlQiLCAiVGFzayIsICJUcmlhbG51bWJlciIsICJJbnRyYW5zVHJpcGxlQ291bnRlZCIpXSkKCmJvdGgudHJpYWwuZGF0YSA9IGJvdGguSW50cmFuc2l0aXZlICU+JQogIHNlbGVjdChmLmlkLCBDbGVhbkludHIsIFRhc2spICU+JQogIHJpZ2h0X2pvaW4oYm90aC50cmlhbC5kYXRhLCBieT1jKCJmLmlkIiwgIlRhc2siKSkgJT4lCiAgbXV0YXRlKFByb3BJbkludHJhbnNUcmlwbGV0ID0gSW50cmFuc1RyaXBsZUNvdW50ZWQvKENsZWFuSW50ciozKSoxMDAsCiAgICAgICAgIFRhc2sgPSBmYWN0b3IoVGFzaywgbGV2ZWxzID0gYygiY2hvaWNlIiwgIm51bWJlcnMiKSwgbGFiZWxzID0gYygiVmFsdWUtYmFzZWQiLCAiUGVyY2VwdHVhbCIpKSklPiUKICBmaWx0ZXIoUlQ+MCwgUlQ8NjAwMCkKYGBgCgpOb3RlIHRoYXQgbW9zdCBvZiB0aGUgdHJpYWxzIGFyZSBub3QgaW52b2x2ZWQgaW4gYW55IGludHJhbnNpdGl2aXRpZXMgc28gdGhlIGF2ZXJhZ2VkIHByb3BvcnRpb24gb2YgaW50cmFuc2l0aXZpdGllcyBmb3IgZWFjaCB0cmlhbCBudW1iZXIgaXMgcHJldHR5IHNtYWxsIChpLmUgd2h5IHRoZSB5LWF4aXMgaXMgc28gc21hbGwpLiAKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KYm90aC50cmlhbC5kYXRhICU+JQogIGdncGxvdChhZXMoeCA9IFRyaWFsbnVtYmVyLCB5ID0gUHJvcEluSW50cmFuc1RyaXBsZXQsIGdyb3VwID0gR3JvdXAsIGNvbG9yID0gR3JvdXApKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzcGFuPTUpICsKICB0aGVtZV9idygpKwogIGZhY2V0X2dyaWQoflRhc2spKwogIHlsYWIoIlBlcmNlbnQgb2YgaW50cmFuc2l0aXZlIFRyaXBsZXRzIGludm9sdmVkIikgKwogIHhsYWIoIk9yZGVyIGNob2ljZSB3YXMgbWFkZSIpCmBgYAoKVG8gdGVzdCBpZiB0aGVyZSBhcmUgYW55IHN0YXRpc3RpY2FsIGRpZmZlcmVuY2VzIGJvdGggYmV0d2VlbiB0aGUgZ3JvdXBzIGFuZCB0aHJvdWdob3V0IGVhY2ggdGFzayBhbmQgYmV0d2VlbiB0aGUgdHdvIHRhc2tzIHdlIGZpcnN0IGNvbXBhcmUgdGhyZWUgbW9kZWxzIHdoZXJlIHRoZSBwcm9wb3J0aW9uIG9mIGludHJhbnNpdGl2ZSB0cmlwbGV0cyBhIHRyaWFsIGlzIGludm9sdmVkIGlzIHJlZ3Jlc3NlZCBvdmVyIHRoZSB0cmlhbCBudW1iZXIgYW5kIGV4cGVyaW1lbnRhbCBncm91cC4gVGhlIGZpcnN0IG1vZGVsIGlzIGFkZGl0aXZlLCB0aGUgc2Vjb25kIGludGVyYWN0aXZlIGFuZCB0aGUgdGhpcmQgaW5jbHVkZXMgYSBxdWFkcmF0aWMgZWZmZWN0IG9mIHRyaWFsIG51bWJlciBhcyB3ZWxsLiBNb2RlbCBjb21wYXJpc29uIHNob3dzIHRoYXQgdGhlIGFkZGl0aW9uIG9mIHRoZSBpbnRlcmFjdGlvbiB0ZXJtcyBhbmQgdGhlIHF1YWRyYXRpYyBlZmZlY3QgZG8gbm90IGxlYWQgdG8gc2lnbmlmaWNhbnQgaW1wcm92ZW1lbnRzIGluIGZpdC4gVGh1cyB3ZSByZXBvcnQgdGhlIGVmZmVjdHMgaW4gdGhlIHNpbXBsZXN0IGFkZGl0aXZlIG1vZGVsLgoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbWVtMSA9IGxtZXIoUHJvcEluSW50cmFuc1RyaXBsZXQgfiAoMXxmLmlkKStzY2FsZShUcmlhbG51bWJlcikrR3JvdXAqVGFzaywgYm90aC50cmlhbC5kYXRhKQoKI2FkZGluZyBpbnRlcmFjdGlvbiBvZiBsaW5lYXIgZWZmZWN0IG9mIFJUIGJldHdlZW4gdGFza3MgYW5kIGdyb3VwcwptZW0yID0gbG1lcihQcm9wSW5JbnRyYW5zVHJpcGxldCB+ICgxfGYuaWQpK3NjYWxlKFRyaWFsbnVtYmVyKSpHcm91cCpUYXNrLCBib3RoLnRyaWFsLmRhdGEpCgojYWRkaW5nIHRoZSBxdWFkcmF0aWMgZWZmZWN0Cm1lbTMgPSBsbWVyKFByb3BJbkludHJhbnNUcmlwbGV0IH4gKDF8Zi5pZCkrc2NhbGUocG9seShUcmlhbG51bWJlciwyKSkqVGFzaypHcm91cCwgYm90aC50cmlhbC5kYXRhKQoKYW5vdmEobWVtMSwgbWVtMiwgbWVtMykKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpybShtZW0yLCBtZW0zKQpgYGAKClRoZSBhZGRpdGl2ZSBtb2RlbCBzdWdnZXN0cyB0aGF0IGNvbnRyYXJ5IHRvIHRoZSBwcmVkaWN0aW9uIG9mIGFuIGVwaXNvZGljIG1lbW9yeSBkdXJpbmcgdGhlIHRhc2sgYWNjb3VudCB0aGVyZSBpcyBib3RoIG5vIGNoYW5nZSBpbiB0aGUgcHJvcG9ydGlvbiBvZiBpbnRyYW5zaXRpdmUgdHJpcGxldHMgYSB0cmlhbCBpbiBpbnZvbHZlZCBpbiB0aHJvdWdob3V0IHRoZSB0YXNrIGFuZCB0aGlzIGlzIHRydWUgZm9yIGFsbCBncm91cHMgaW4gYm90aCB0YXNrcy4KCmBgYHtyfQpzdW1tYXJ5KG1lbTEpCmBgYAoKSW4gaGVyIGNvbW1lbnRzIEVsa2Ugc3VnZ2VzdGVkIHRoYXQgYmFzZWQgb24gdGhlIGVwaXNvZGljIG1lbW9yeSBoeXBvdGhlc2lzIHRoZSBlcGlzb2RpYyBtZW1vcnkgb2YgdGhlIGNob2ljZXMgaW4gdGhlIGZpcnN0IHR3byB0cmlhbHMgd291bGQgb25seSBoZWxwL2luZmx1ZW5jZSB0aGUgZGVjaXNpb24gZm9yIHRoZSB0aGlyZCB0cmlhbCBpbiBhIHRyaXBsZXQuIFRvIGFkZHJlc3MgdGhpcyBJIGFuYWx5emVkIHRoZSBlcGlzb2RpYyBtZW1vcnkgaHlwb3RoZXNpcyBhdCB0aGUgdHJpcGxldCBsZXZlbC4gUHJldmlvdXNseSB3ZSBsb29rZWQgYXQgdGhlIG51bWJlciBvZiBpbnRyYW5zaXRpdmUgdHJpcGxldHMgZWFjaCB0cmlhbCB3YXMgaW52b2x2ZWQgaW4gZGVwZW5kaW5nIG9uIHdoZW4gaXQgYXBwZWFyZWQgZHVyaW5nIHRoZSB0YXNrLiBUaGlzIG1pZ2h0IHNlZW0gY29uZnVzaW5nIGJlY2F1c2UgZGVwZW5kaW5nIG9uIHdoZW4gdGhleSBhcHBlYXJlZCBkdXJpbmcgdGhlIHRhc2sgZWFjaCB0cmlhbCBpcyBub3QgZXF1YWxseSBsaWtlbHkgdG8gaGF2ZSBsZWFkIHRvIGFuIGludHJhbnNpdGl2ZSB0cmlwbGV0LiBUaGF0IGlzLCBhcyBFbGtlIGltcGxpZWQgbm90IGV2ZXJ5IHRyaWFsIHdhcyB0aGUgdGhpcmQgdHJpYWwgaW4gYSB0cmlwbGV0IGFuZCBsb29raW5nIGF0IGFsbCB0YXNrcyB3aXRob3V0IGRpc2NyaW1pbmF0aW5nIHRoZSBvcmRlciBpbiB3aGljaCB0aGV5IGFwcGVhcmVkIGZvciBhIHRyaXBsZXQgbWFza3MgdGhpcy4gIAoKVGhlIGFuYWx5c2VzIGhlcmUgc2hvdWxkIHRha2UgY2FyZSBvZiB0aGlzIGFuZCBpbmRlZWQgbGVhZCB0byB0aGUgc2FtZSBjb25jbHVzaW9uIGJ1dCBtaWdodCBiZSBtb3JlIGludHVpdGl2ZS4gSGVyZSB3ZSBsb29rIGF0IHdoZXRoZXIgYSB0cmlwbGV0IGlzIGludHJhbnNpdGl2ZSBkZXBlbmRpbmcgb24gd2hlbiB0aGUgbGFzdCB0cmlhbCBpbiB0aGF0IHRyaXBsZXQgYXBwZWFyZWQuCgpgYGB7cn0KYm90aC50cmlwbGV0LmRhdGEgPSBib3RoLnRyaXBsZXQuZGF0YSAlPiUKICAgbXV0YXRlKENsZWFuSW50ciA9IGlmZWxzZShJbnRyYW5zID09IDEgJiBFcnJvciA9PSAwLDEsIDApKSAlPiUKICBtdXRhdGUoVGFzayA9IGZhY3RvcihUYXNrLCBsZXZlbHMgPSBjKCJjaG9pY2UiLCAibnVtYmVycyIpLCBsYWJlbHMgPSBjKCJWYWx1ZS1iYXNlZCIsICJQZXJjZXB0dWFsIikpKQpgYGAKCmBgYHtyfQpib3RoLnRyaXBsZXQuZGF0YSAlPiUKICBnZ3Bsb3QoYWVzKFRoaXJkVHJpYWwsIENsZWFuSW50ciwgZ3JvdXA9R3JvdXAsIGNvbG9yPUdyb3VwKSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJnbG0iLCBtZXRob2QuYXJncyA9IGxpc3QoZmFtaWx5PSJiaW5vbWlhbCIpKSsKICB0aGVtZV9idygpKwogIGZhY2V0X2dyaWQoflRhc2spKwogIHhsYWIoIkxhc3Qgc2VlbiB0cmlhbCBpbiB0cmlwbGV0IikrCiAgeWxhYigiSW50cmFuc2l0aXZlIHRyaXBsZXQiKQpgYGAKClJ1bm5pbmcgbW9kZWwgZm9yIGNob2ljZSB0YXNrIG9ubHkgYmVjYXVzZSBsb29raW5nIGF0IGJvdGggdGFrZXMgYSB3aGlsZS4gVGhlIERWIGluIHRoZXNlIHJlZ3Jlc3Npb25zIGlzIHdoZXRoZXIgdGhlIHRyaXBsZXQgaXMgaW50cmFuc2l0aXZlIGFuZCB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFyZSByYW5kb20gZWZmZWN0cyBmb3Igc3ViamVjdHMgYW5kIGZpeGVkIGVmZmVjdHMgZm9yIHBhdGllbnQgZ3JvdXAgYW5kIHRoZSB0cmlhbCBudW1iZXIgb2YgdGhlIGxhc3Qgc2VlbiB0cmlhbCBpbiB0aGF0IHRyaXBsZXQuIAoKRm9yIHRoZSBjaG9pY2UgdGFzayB0aGVyZSBpcyBvbmx5IGEgZml4ZWQgZWZmZWN0IG9mIHRoZSBNVEwgZ3JvdXAgc3VnZ2VzdGluZyB0aGF0IHRoaXMgZ3JvdXAgaGFzIG1vcmUgaW50cmFuc2l0aXZlIHRyaXBsZXRzIHRoYW4gdGhlIGNvbnRyb2wgZ3JvdXAuIFRoZSBlZmZlY3Qgb2YgdGhlIHRyaWFsIG51bWJlciBvZiB0aGUgbGFzdCBzZWVuIHRyaWFsIGluIGEgdHJpcGxldCBvbiB3aGV0aGVyIG9yIG5vdCBpdCBpcyBpbnRyYW5zaXRpdmUgaXMgbm90IHNpZ25pZmljYW50LgoKYGBge3J9Cm1lbV92YWwgPSBnbG1lcihDbGVhbkludHIgfiAoMXxmLmlkKStHcm91cCpzY2FsZShUaGlyZFRyaWFsKSxmYW1pbHk9Ymlub21pYWwsIGJvdGgudHJpcGxldC5kYXRhW2JvdGgudHJpcGxldC5kYXRhJFRhc2sgPT0gIlZhbHVlLWJhc2VkIixdKQpzdW1tYXJ5KG1lbV92YWwpCmBgYAoKYGBge3IgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0KIyBJbiB0aGUgbnVtYmVycyB0YXNrIHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9mIHRoZSBsYXN0IHRyaWFsIG51bWJlciBvbiBwZXJmb3JtYW5jZS4gTGF0ZXIgdHJpYWwgbnVtYmVycyBhcmUgbW9yZSBsaWtlbHkgdG8gYmUgaW52b2x2ZWQgaW4gaW50cmFuc2l0aXZlIHRyaXBsZXRzIGZvciB0aGUgY29udHJvbCBncm91cC4gVGhlIE1UTCBncm91cCBhZ2FpbiBoYXMgbW9yZSBpbnRyYW5zaXRpdmUgdHJpcGxldHMgY29tcGFyZWQgdG8gdGhlIGNvbnRyb2wgZ3JvdXAgYnV0IHRoZSBlZmZlY3Qgb2YgdGhlIGxhc3Qgc2VlbiB0cmlhbCBkb2VzIG5vdCBkaWZmZXIgZnJvbSB0aGUgY29udHJvbCBncm91cC4gVGhlIGVmZmVjdCBvZiB0aGUgbGFzdCBzZWVuIHRyaWFsIG9uIHBlcmZvcm1hbmNlIGlzIGxlc3MgcHJvbm91bmNlZCBmb3IgdGhlIEVUTCBncm91cC4KbWVtX3BlciA9IGdsbWVyKENsZWFuSW50ciB+ICgxfGYuaWQpK0dyb3VwKnNjYWxlKFRoaXJkVHJpYWwpLGZhbWlseT1iaW5vbWlhbCwgYm90aC50cmlwbGV0LmRhdGFbYm90aC50cmlwbGV0LmRhdGEkVGFzayA9PSAiUGVyY2VwdHVhbCIsXSkKc3VtbWFyeShtZW1fcGVyKQpgYGAKClRoZSBlcGlzb2RpYyBtZW1vcnkgaHlwb3RoZXNpcyBtaWdodCBtYWtlIGEgbW9yZSBzcGVjaWZpYyBoeXBvdGhlc2lzIHRoYXQgZGVwZW5kcyBub3QganVzdCBvbiB3aGVuIGVhY2ggdHJpYWwgYXBwZWFycyBidXQgaG93IGZhciBhcGFydCBlYWNoIHRyaWFsIGluIGEgdHJpcGxldCBhcHBlYXJzIGZyb20gZWFjaCBvdGhlci4gU3BlY2lmaWNhbGx5LCBpdCBjb3VsZCBiZSB0aGUgY2FzZSB0aGF0IHRoZSBmdXJ0aGVyIGFwYXJ0IHRoZSB0cmlhbHMgb2YgYSB0cmlwbGV0IGFyZSB0aGUgbW9yZSBsaWtlbHkgdGhleSBhcmUgdG8gZm9ybSBhbiBpbnRyYW5zaXRpdmUgdHJpcGxldCBiZWNhdXNlIHRoZSBlcGlzb2RpYyBtZW1vcnkgb2YgdGhlIGNob2ljZXMgZmFkZSBhd2F5IGFuZCBjYW4ndCBoZWxwIHRoZSBkZWNpc2lvbiBpbiB0aGUgdGhpcmRwYWlyLiBGb3IgdGhpcyBoeXBvdGhlc2lzIHRvIGV4cGxhaW4gdGhlIGdyb3VwIGRpZmZlcmVuY2UgaW4gaW50cmFuc2l0aXZpdGllcyBmb3IgdGhlIGNob2ljZSB0YXNrIHRoaXMgdHJlbmQgd291bGQgaGF2ZSB0byBiZSBwYXJ0aWN1bGFybHkgcHJvbm91bmNlZCBmb3IgdGhlIE1UTCBncm91cC4KCmBgYHtyfQpib3RoLnRyaXBsZXQuZGF0YSAlPiUKICAgIG11dGF0ZShUcmlhbE51bVZhciA9ICgoVHJpYWxBLSgoVHJpYWxBK1RyaWFsQitUcmlhbEMpLzMpKV4yKyhUcmlhbEItKChUcmlhbEErVHJpYWxCK1RyaWFsQykvMykpXjIrKFRyaWFsQy0oKFRyaWFsQStUcmlhbEIrVHJpYWxDKS8zKSleMikvMikgJT4lCiAgZ2dwbG90KGFlcyhUcmlhbE51bVZhciwgQ2xlYW5JbnRyLCBncm91cD1Hcm91cCwgY29sb3I9R3JvdXApKSsKICBnZW9tX3Ntb290aChtZXRob2Q9ImdsbSIsIG1ldGhvZC5hcmdzID0gbGlzdChmYW1pbHk9ImJpbm9taWFsIikpKwogIHRoZW1lX2J3KCkrCiAgZmFjZXRfZ3JpZCh+VGFzaykrCiAgeGxhYigiVmFyaWFuY2Ugb2YgdGhlIHRyaWFsIG51bWJlcnMgaW52b2x2ZWQgaW4gdGhlIHRyaXBsZXQiKSsKICB5bGFiKCJJbnRyYW5zaXRpdmUgdHJpcGxldCIpCmBgYAoKQWdhaW4sIGhvd2V2ZXIsIHRoaXMgaHlwb3RoZXNpcyBkb2VzIG5vdCBzZWVtIHRvIGV4cGxhaW4gdGhlIGdyb3VwIGRpZmZlcmVuY2UgaW4gaW50cmFuc2l0aXZpZXMgaW4gdGhlIGNob2ljZSB0YXNrOiBJdCBpcyB0aGUgY2FzZSB0aGF0IHRoZSBmdXJ0aGVyIGFwYXJ0IGZyb20gZWFjaCBvdGhlciB0cmlhbHMgaW4gYSB0cmlwbGV0IGFwcGVhciB0aGUgbW9yZSBsaWtlbHkgaXMgdGhhdCB0cmlwbGV0IGludHJhbnNpdGl2ZSBidXQgdGhpcyB0cmVuZCBpcyB0aGUgc2FtZSBmb3IgYWxsIGdyb3Vwcy4KCmBgYHtyfQpib3RoLnRyaXBsZXQuZGF0YT1ib3RoLnRyaXBsZXQuZGF0YSAlPiUKICAgIG11dGF0ZShUcmlhbE51bVZhciA9ICgoVHJpYWxBLSgoVHJpYWxBK1RyaWFsQitUcmlhbEMpLzMpKV4yKyhUcmlhbEItKChUcmlhbEErVHJpYWxCK1RyaWFsQykvMykpXjIrKFRyaWFsQy0oKFRyaWFsQStUcmlhbEIrVHJpYWxDKS8zKSleMikvMikKCm1lbV92YWxfdmFyIDwtIGdsbWVyKENsZWFuSW50ciB+ICgxfGYuaWQpK0dyb3VwKnNjYWxlKFRyaWFsTnVtVmFyKSxmYW1pbHk9Ymlub21pYWwsIGJvdGgudHJpcGxldC5kYXRhW2JvdGgudHJpcGxldC5kYXRhJFRhc2sgPT0gIlZhbHVlLWJhc2VkIixdKQpzdW1tYXJ5KG1lbV92YWxfdmFyKQpgYGAKCgpSZXNwb25zZSBUaW1lcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyBJbnRyYW5zaXRpdml0aWVzIGFuZCByZXNwb25zZSB0aW1lcyAoc3BlZWQtYWNjdXJhY3kgdHJhZGVvZmYpCgpUaGUgeS1heGlzIGlzIHRoZSBwcm9wb3J0aW9uIG9mIGludHJhbnNpdGl2ZSB0cmlwbGV0cyBhIHRyaWFsIGlzIGludm9sdmVkIGluLiBUaGUgaGlnaGVyIGxpbmVzIGZvciB0aGUgbnVtYmVycyB0YXNrIG1pZ2h0IGJlIGNvbmZ1c2luZyBhdCBmaXJzdCBsb29rIGdpdmVuIHRoZSBmZXcgbnVtYmVyIG9mIGludHJhbnNpdGl2aXRpZXMgaW4gdGhpcyB0YXNrLiBJdCBpcyBiZWNhdXNlIHRoZXJlIGFyZSBzbyBmZXcgaW50cmFuc2l0aXZpdGllcyB0aGF0IGlmIGEgdHJpYWwgaXMgaW52b2x2ZWQgaW4gZXZlbiBhIHNpbmdsZSBpbnRyYW5zaXRpdml0eSBpdCB0cmFuc2xhdGVzIHRvIGEgbGFyZ2VyIHByb3BvcnRpb25zLiBUaGUgbG93ZXIgbnVtYmVyIGlmIGludHJhbnNpdGl2aXRpZXMgZm9yIHRoZSBudW1iZXJzIHRhc2sgaXMgY2FwdHVyZWQgYnkgdGhlIGxhcmdlIGVycm9yIGJhcnMgYXJvdW5kIHRoZSB0YXNrIChpLmUuIGZvciBlYWNoIHJlc3BvbnNlIHRpbWUgdGhlcmUgYXJlIGZld2VyIG5vbi16ZXJvIGRhdGEgcG9pbnRzIGludm9sdmVkIGluIGludHJhbnNpdGl2aXRpZXMgY29tcGFyZWQgdG8gdGhlIGNob2ljZSB0YXNrKS4KCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz1GQUxTRX0KYm90aC50cmlhbC5kYXRhICU+JQogIGdncGxvdChhZXMoUlQsIFByb3BJbkludHJhbnNUcmlwbGV0LCBncm91cD1Hcm91cCwgY29sb3I9R3JvdXApKSsKICAjIFlvdSBkb24ndCB3YW50IHRvIHBsb3QgdGhlIHJhdyBtZWFzdXJlIGJlY2F1c2UgdGhlbiBhIHNpbmdsZSBzdWJqZWN0IHdobyBoYXMgZG9uZSBhIGxvdCBvZiBpbnRyYW5zaXRpdml0aWVzIGFuZCBpcyBpbiBnZW5lcmFsIGZhc3RlciBjYW4gbWFrZSBpdCBzZWVtIGxpa2UgZmFzdGVyIHRyaWFscyBhcmUgYXNzb2NpYXRlZCB3aXRoIG1vcmUgaW50cmFuc2l0aXZpdGllcy4gWW91IHdhbnQgdGhlIHByb3BvcnRpb25hbCBpbnZvbHZlbWVudCBnaXZlbiB0aGUgdG90YWwgbnVtYmVyIG9mIGludHJhbnNpdGl2aXRpZXMgYSBzdWJqZWN0IG1ha2VzIG92ZXIgcmVzcG9uc2UgdGltZQogICMgZ2dwbG90KGFlcyhSVCwgSW50cmFuc1RyaXBsZUNvdW50ZWQsIGdyb3VwPUdyb3VwLCBjb2xvcj1Hcm91cCkpKwogIHRoZW1lX2J3KCkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc3BhbiA9IDUpKwogIGZhY2V0X2dyaWQoflRhc2spKwogIHlsaW0oYygwLE5BKSkrCiAgeGxhYigiUmVzcG9uc2UgVGltZSIpKwogIHlsYWIoIlBlcmNlbnQgb2YgaW50cmFuc2l0aXZlIFRyaXBsZXRzIGludm9sdmVkIikKYGBgCgpJcyB0aGVyZSBhIHN0YXRpc3RpY2FsIGRpZmZlcmVuY2UgaW4gdGhlIGVmZmVjdCBvZiByZXNwb25zZSB0aW1lcyBvbiBpbnRyYW5zaXRpdml0aWVzIGJldHdlZW4gdGhlIHR3byB0YXNrcz8gIAoKV2UncmUgbm90IG5lY2Vzc2FyaWx5IGludGVyZXN0ZWQgaW4gd2hldGhlciB0aGUgZXhhY3Qgc2xvcGVzIGFyZSBkaWZmZXJlbnQgaW4gdGhlIHR3byB0YXNrcy4gV2UgY2FuIHNlZSB0aGV5IG1pZ2h0IGJlIHZpc3VhbGx5LiBUaGUgbWFpbiBxdWVzdGlvbiBvZiBpbnRlcmVzdCBpcyB0d28tZm9sZDogIAoKLSBJcyB0aGVyZSBhIHNwZWVkLWFjY3VyYWN5IHRyYWRlb2ZmPyBBcmUgc2hvcnRlciBSVHMgYXNzb2NpYXRlZCB3aXRoIG1vcmUgaW50cmFuc2l0aXZpdGllcyAoaW4gYSBsaW5lYXIgbW9kZWw6IGRvZXMgdGhlIGxpbmVhciBlZmZlY3Qgb2YgUlQgaGF2ZSBhIG5lZ2F0aXZlIHNsb3BlKSAgCgotIERvZXMgdGhpcyBkaWZmZXIgYmV0d2VlbiBncm91cHMgYW5kIGFjcm9zcyB0aGUgdHdvIGRpZmZlcmVudCB0YXNrcy4gIAoKRmlyc3Qgd2UgZG8gYSBtb2RlbCBjb21wYXJpc29uIGFuZCBjaGVjayB3aGV0aGVyIHRoZSB0aHJlZS13YXkgaW50ZXJhY3Rpb25zIG9mIFJUcyB3aXRoIGdyb3VwcyBhbmQgdGFza3MgYXMgd2VsbCBhcyBhIHF1YWRyYXRpYyBlZmZlY3Qgb2YgUlRzIGxlYWQgdG8gc2lnbmlmaWNhbnQgaW1wb3JldmVtZW50cy4gQm90aCBkby4gICAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJ0MSA9IGxtZXIoUHJvcEluSW50cmFuc1RyaXBsZXQgfiAoMXxmLmlkKStzY2FsZShSVCkrR3JvdXAqVGFzaywgYm90aC50cmlhbC5kYXRhKQoKI2FkZGluZyBpbnRlcmFjdGlvbiBvZiBsaW5lYXIgZWZmZWN0IG9mIFJUIGJldHdlZW4gdGFza3MgYW5kIGdyb3VwcwpydDIgPSBsbWVyKFByb3BJbkludHJhbnNUcmlwbGV0IH4gKDF8Zi5pZCkrc2NhbGUoUlQpKkdyb3VwKlRhc2ssIGJvdGgudHJpYWwuZGF0YSkKCiNhZGRpbmcgdGhlIHF1YWRyYXRpYyBlZmZlY3QKcnQzID0gbG1lcihQcm9wSW5JbnRyYW5zVHJpcGxldCB+ICgxfGYuaWQpK3NjYWxlKHBvbHkoUlQsMikpKlRhc2sqR3JvdXAsIGJvdGgudHJpYWwuZGF0YSkKCmFub3ZhKHJ0MSwgcnQyLCBydDMpCmBgYAoKYGBge3IgZWNobz1GQUxTRX0Kcm0ocnQxLCBydDIpCmBgYAoKU28gd2hhdCBkb2VzIHRoaXMgbW9kZWwgc2F5PyBUaGVyZSBpcyBhIHNpZ25pZmljYW50IGxpbmVhciBlZmZlY3Qgb2YgdGltZSB3aGVyZSBsb25nZXIgUlRzIGFyZSBhc3NvY2lhdGVkIHdpdGggbW9yZSBpbnRyYW5zaXRpdmllcyAodGhlIG9wcG9zaXRlIG9mIGEgc3BlZWQtYWNjdXJhY3kgdHJhZGVvZmYpLiBUaGVyZSBpcyBhIG1haW4gZWZmZWN0IG9mIHRhc2sgd2hlcmUgdGhlIG51bWJlcnMgdGFzayBoYXMgbGFyZ2VyIHByb3BvcnRpb25zIG9mIGludHJhbnNpdGl2aXRpZXMgYnV0IHRoaXMgYXMgbWVudGlvbmVkIGFib3ZlIGlzIGR1ZSB0byB0aGUgbG93ZXIgbnVtYmVyIGludHJhbnNpdGl2aXRpZXMgcGVyIHN1YmplY3QuIFRoZSBsaW5lYXIgYW5kIHF1YWRyYXRpYyBlZmZlY3RzIG9mIHRpbWUgYXJlIGRpZmZlcmVudCBmb3IgdGhlIEVUTCBncm91cCBjb21wYXJlZCB0byB0aGUgY29udHJvbCBncm91cC4gVGhlIGluY3JlYXNlIGluIHRoZSBwcm9wb3J0aW9uIG9mIGludHJhbnNpdGl2aXRpZXMgZm9yIHRoZSBNVEwgZ3JvdXAgaXMgbGVzcyB0aGFuIHRoZSBpbmNyZWFzZSBpbiB0aGlzIHByb3BvcnRpb24gZm9yIHRoZSBjb250cm9sIGdyb3VwICh0aGlzIGlzbid0IGludGVyZXN0aW5nIGJlY2F1c2UgdGhlIGNvbnRyb2wgZ3JvdXAgbWFrZXMgYmFyZWx5IGFueSBpbnRyYW5zaXRpdml0aWVzIGluIHRoZSBwZXJjZXB0dWFsIHRhc2spLiBUaGUgY2hhbmdlIGluIHRoZSBsaW5lYXIgZWZmZWN0IG9mIHRpbWUgaW4gdGhlIG51bWJlcnMgdGFzayBjb21wYXJlZCB0byB0aGUgY2hvaWNlIHRhc2sgaXMgbGVzcyB0aGlzIGNoYW5nZSBmb3IgdGhlIGNvbnRyb2wgZ3JvdXAgKGFsc28gbm90IGludGVyZXN0aW5nIGJlY2F1c2UgdGhlcmUgaXMgYSBxdWFkcmF0aWMgZWZmZWN0IG9mIHRpbWUgZm9yIHRoZSBFVEwgZ3JvdXAgYW5kIHRoaXMgY2hhbmdlIGlzIG5vdCBzaWduaWZpY2FudCkuICAKCkFzIHF1YWxpdGF0aXZlbHkgc3VnZ2VzdGVkIGluIHRoZSBhYm92ZSBmaWd1cmUgdGhlcmUgaXMgbm8gbmVnYXRpdmUgc2xvcGVzIGluZGljYXRpbmcgYSBzcGVlZCBhY2N1cmFjeSB0cmFkZW9mZiBmb3IgZWl0aGVyIHRhc2suIEFsc28gY3J1Y2lhbGx5IHRoZSBpbnRlcmFjdGlvbnMgZm9yIHRoZSBzaWduaWZpY2FudCBlZmZlY3RzIG9mIHRpbWUgZm9yIGVhY2ggZ3JvdXAgYXJlIG5vdCBzaWduaWZpY2FudDogVGhlIGludGVyYWN0aW9uIGJldHdlZW4gdGhlIGxpbmVhciBlZmZlY3QgdGltZSBhbmQgdGFzayBmb3IgdGhlIGNvbnRyb2wgZ3JvdXAsIHRoZSB0aHJlZXdheSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHRoZSBsaW5lYXIgZWZmZWN0IG9mIHRpbWUgYW5kIHRhc2sgZm9yIHRoZSBNVEwgZ3JvdXAgYW5kIHRoZSB0aHJlZXdheSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHRoZSBxdWFkcmF0aWMgZWZmZWN0IG9mIHRpbWUgYW5kIHRhc2sgZm9yIHRoZSBFVEwgZ3JvdXAgYXJlIG5vdCBzaWduaWZpY2FudC4gVGhhdCBpcywgdGhlIGVmZmVjdCBvZiB0aW1lIG9uIGludHJhbnNpdGl2aXRpZXMgaXMgdGhlIHNhbWUgZm9yIGJvdGggdGFza3MuICAKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0Kc3VtbWFyeShydDMpCmBgYAoKV2UgY2FuIGFsc28gYW5hbHl6ZSB0aGUgc3BlZWQgYWNjdXJhY3kgdHJhZGVvZmYgb24gdHJpcGxldCBsZXZlbCBieSBjaGVja2luZyB3aGV0aGVyIHRoZSByZXNwb25zZSB0aW1lcyB0byBhbnkgb2YgdGhlIHRocmVlIHRyaWFscyBpbiBlYWNoIHRyaXBsZXQgaXMgYXNzb2NpYXRlZCB3aXRoIHdoZXRoZXIgdGhhdCB0cmlwbGV0IGlzIGludHJhbnNpdGl2ZSBvciBub3QuIFRoZSBjb25jbHVzaW9ucyBkb24ndCBjaGFuZ2UgYnV0IHRoaXMgYW5hbHlzaXMgaXMgbW9yZSBmaW5lLWdyYWluZWQgYW5kIHRoZSBkZXBlbmRlbnQgbWVhc3VyZSBtaWdodCBiZSBtb3JlIGludGVycHJldGFibGUuCgpgYGB7cn0KYm90aC50cmlwbGV0LmRhdGEgPSBib3RoLnRyaXBsZXQuZGF0YSAlPiUKICBsZWZ0X2pvaW4oYm90aC50cmlhbC5kYXRhWyxjKCJUYXNrIiwgImYuaWQiLCAiVHJpYWxudW1iZXIiLCAiUlQiKV0sIGJ5ID0gYygiVGFzayIsICJmLmlkIiwgIlRyaWFsQSIgPSAiVHJpYWxudW1iZXIiKSkgJT4lCiAgcmVuYW1lKFJUX0EgPSBSVCkgJT4lCiAgICBsZWZ0X2pvaW4oYm90aC50cmlhbC5kYXRhWyxjKCJUYXNrIiwgImYuaWQiLCAiVHJpYWxudW1iZXIiLCAiUlQiKV0sIGJ5ID0gYygiVGFzayIsICJmLmlkIiwgIlRyaWFsQiIgPSAiVHJpYWxudW1iZXIiKSkgJT4lCiAgcmVuYW1lKFJUX0IgPSBSVCkgJT4lCiAgICBsZWZ0X2pvaW4oYm90aC50cmlhbC5kYXRhWyxjKCJUYXNrIiwgImYuaWQiLCAiVHJpYWxudW1iZXIiLCAiUlQiKV0sIGJ5ID0gYygiVGFzayIsICJmLmlkIiwgIlRyaWFsQyIgPSAiVHJpYWxudW1iZXIiKSkgJT4lCiAgcmVuYW1lKFJUX0MgPSBSVCkgJT4lCiAgZHJvcF9uYSgpCmBgYAoKYGBge3J9CmJvdGgudHJpcGxldC5kYXRhICU+JQogIHNlbGVjdChSVF9BLCBSVF9CLCBSVF9DLCBUYXNrLCBDbGVhbkludHIsIEdyb3VwLCBmLmlkKSAlPiUKICBnYXRoZXIoa2V5LCB2YWx1ZSwgLVRhc2ssIC1DbGVhbkludHIsIC1mLmlkLCAtR3JvdXApICU+JQogIGdncGxvdChhZXModmFsdWUsIENsZWFuSW50ciwgZ3JvdXA9R3JvdXAsIGNvbG9yPUdyb3VwKSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImdsbSIsIG1ldGhvZC5hcmdzID0gbGlzdChmYW1pbHkgPSAiYmlub21pYWwiKSkrCiAgIyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSsKICB0aGVtZV9idygpKwogIGZhY2V0X2dyaWQoa2V5flRhc2spKwogIHhsYWIoIlJlc3BvbnNlIHRpbWUiKSsKICB5bGFiKCJJbnRyYW5zaXRpdmUgdHJpcGxldCIpCmBgYAoKSW4gdGhlIGxpbmVhciByZWdyZXNzaW9uIEkgY2hvc2UgdG8gbG9vayBvbmx5IGF0IHRoZSBlZmZlY3Qgb2YgdGhlIHJlc3BvbnNlIHRpbWUgaW4gdGhlIHRoaXJkIHRyaWFsIGJlY2F1c2U6ICAKLSB0aGF0J3MgdGhlIHRyaWFsIHRoYXQgd291bGQgZGV0ZXJtaW5lIHdoZXRoZXIgYSB0cmlhbCBpcyBpbnRyYW5zaXRpdmUgb3Igbm90IAotIHRoZSBncmFwaCBzdWdnZXN0cyB0aGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiByZXNwb25zZSB0aW1lcyBhbmQgaW50cmFuc2l0aXZlIHRyaXBsZXRzIGlzIHRoZSBzYW1lIGZvciB0aGUgdGhyZWUgdHJpYWxzCi0gdGhlIHJlc3BvbnNlIHRpbWVzIGZvciBlYWNoIHRyaWFsIGluIGEgdHJpcGxldCBhcmUgW2hpZ2x5IGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVdKCNydF9jb3JfcGxvdCkKLSBOb3RlOiB0aGUgZnVsbCBpbnRlcmFjdGl2ZSBtb2RlbCB3aXRoIGFsbCB0aHJlZSByZXNwb25zZSB0aW1lcyBkb2VzIGxlYWQgdG8gc2lnbmlmaWNhbnRseSBpbXByb3ZlZCBtb2RlbCBidXQgYmVjb21lcyB0b28gdW5pbnRlcnByZXRhYmxlCgpgYGB7ciBldmFsPUZBTFNFfQojTm90ZSB0aGVzZSBzaG91bGQgYWxsIGJlIGdsbWVyczsgcmFuIHRoZXNlIGJlY2F1c2UgaXQgd2FzIGZhc3Rlci4Kc2ExID0gbG1lcihDbGVhbkludHIgfiAoMXxmLmlkKStUYXNrKkdyb3VwK3NjYWxlKFJUX0MpLCBib3RoLnRyaXBsZXQuZGF0YSkKc2EyID0gbG1lcihDbGVhbkludHIgfiAoMXxmLmlkKStUYXNrKkdyb3VwKnNjYWxlKFJUX0MpLCBib3RoLnRyaXBsZXQuZGF0YSkKc2EzID0gbG1lcihDbGVhbkludHIgfiAoMXxmLmlkKStUYXNrKkdyb3VwK3NjYWxlKFJUX0EpK3NjYWxlKFJUX0IpK3NjYWxlKFJUX0MpLCBib3RoLnRyaXBsZXQuZGF0YSkKc2E0ID0gbG1lcihDbGVhbkludHIgfiAoMXxmLmlkKStUYXNrKkdyb3VwKnNjYWxlKFJUX0MpK3NjYWxlKFJUX0IpK3NjYWxlKFJUX0EpLCBib3RoLnRyaXBsZXQuZGF0YSkKc2E1ID0gbG1lcihDbGVhbkludHIgfiAoMXxmLmlkKStUYXNrKkdyb3VwK3NjYWxlKFJUX0MpKnNjYWxlKFJUX0IpKnNjYWxlKFJUX0EpLCBib3RoLnRyaXBsZXQuZGF0YSkKc2E2ID0gbG1lcihDbGVhbkludHIgfiAoMXxmLmlkKStUYXNrKkdyb3VwKnNjYWxlKFJUX0MpKnNjYWxlKFJUX0IpKnNjYWxlKFJUX0EpLCBib3RoLnRyaXBsZXQuZGF0YSkKCiNuZWVkIHRoZSBpbnRlcmFjdGlvbiBvZiBydF9jCmFub3ZhKHNhMSwgc2EyKQojYWRkaXRpdmUgd2l0aCAzIHJ0J3MgaXMgYmV0dGVyIHRoYW4gb25seSB0aGUgdGhpcmQgcnQKYW5vdmEoc2ExLCBzYTMpCiNpbnRlcmFjdGl2ZSB3aXRoIDMncnRzIGlzIGJldHRlciB0aGFuIGFkZGl0aXZlIHdpdGggMyBydCdzCmFub3ZhKHNhMywgc2E0KQojZm9yIGludGVyYWN0aXZlIGRvIHlvdSBuZWVkIHRoZSBtYWluIG9mIHRoZSBvdGhlciB0d28gIC0geWVzCmFub3ZhKHNhMiwgc2E0KQojd2hlbiB1c2luZyBhbGwgdGhyZWUgcnQncyBpcyBtYWtpbmcgdGhlbSBpbnRlcmFjdGl2ZSBiZXR0ZXI/IC0geWVzCmFub3ZhKHNhMywgc2E1KQojaXMgdGhlIGZ1bGwgaW50ZXJhY3RpdmUgbW9kZWwgd2l0aCAzIHJ0J3MgYmV0dGVyIHRoYW4gYWRkaW5nIHRoZSBvdGhlciB0d28gcnQncyBhZGRpdGl2ZWx5Py15ZXMKYW5vdmEoc2E0LCBzYTYpCiNpcyB0aGUgZnVsbCBpbnRlcmFjdGl2ZSBtb2RlbCB3aXRoIDMgcnQncyBiZXR0ZXIgdGhhbiBhZGRpbmcgdGhlIHJ0IGludGVyYWN0aW9ucyBhZGRpdGl2ZWx5Py15ZXMKYW5vdmEoc2E1LCBzYTYpCmBgYAoKTG9va2luZyBhdCB0aGUgdGFza3MgaW4gc2VwYXJhdGUgbW9kZWxzIGJlY2F1c2UgdGhlIGludGVyYWN0aXZlIG1vZGUgaW5jbHVkaW5nIHRoZSB0YXNrIHRha2VzIGEgd2hpbGUgdG8gcnVuOiBUaGUgbW9kZWwgY29uZmlybXMgdGhhdCB0aGUgc2xvcGUgaXMgcG9zaXRpdmUgZm9yIGFsbCBncm91cHMsIHN1Z2dlc3RpbmcgdGhhdCB0aGVyZSBpcyBubyBzcGVlZCBhY2N1cmFjeSB0cmFkZW9mZi4gSW4gZmFjdCwgd2Ugb2JzZXJ2ZSB0aGUgb3Bwb3NpdGUgcGF0dGVybiB3aGVyZSB0cmlwbGV0cyBhcmUgbW9yZSBsaWtlbHkgdG8gYmUgaW50cmFuc2l0aXZlIGlmIHRoZSByZXNwb25zZSB0aW1lIGZvciB0aGUgbGFzdCBzZWVuIHRyaWFsIGluIHRoYXQgdHJpcGxldCBpcyBsb25nZXIuCgpgYGB7cn0Kc2FfdmFsID0gbG1lNDo6Z2xtZXIoQ2xlYW5JbnRyIH4gKDF8Zi5pZCkrR3JvdXAqc2NhbGUoUlRfQyksIGZhbWlseSA9IGJpbm9taWFsLCBib3RoLnRyaXBsZXQuZGF0YVtib3RoLnRyaXBsZXQuZGF0YSRUYXNrID09ICdWYWx1ZS1iYXNlZCcsXSkKc3VtbWFyeShzYV92YWwpCmBgYAoKYGBge3IgZXZhbD1GQUxTRSwgZWNobz1GQUxTRX0Kc2FfcGVyID0gbG1lNDo6Z2xtZXIoQ2xlYW5JbnRyIH4gKDF8Zi5pZCkrR3JvdXAqc2NhbGUoUlRfQyksIGZhbWlseSA9IGJpbm9taWFsLCBib3RoLnRyaXBsZXQuZGF0YVtib3RoLnRyaXBsZXQuZGF0YSRUYXNrID09ICdQZXJjZXB0dWFsJyxdKQpzdW1tYXJ5KHNhX3BlcikKYGBgCgoKIyMjIFJlc3BvbnNlIHRpbWVzIGZvciBncm91cHMKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGJvdGgudHJpYWwuZGF0YSwgYWVzKHggPSBUcmlhbG51bWJlciwgeSA9IFJULCBncm91cCA9IEdyb3VwLCBsaW5ldHlwZSA9IEdyb3VwKSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAiYmxhY2siKSsKICB0aGVtZV9idygpKwogIGZhY2V0X2dyaWQoflRhc2spKwogIHhsYWIoIlRyaWFsIG51bWJlciIpKwogIHlsYWIoIlJlc3BvbnNlIHRpbWUiKQpgYGAKCmBgYHtyfQpib3RoLnRyaWFsLmRhdGEgJT4lCiAgZ3JvdXBfYnkoR3JvdXAsIFRhc2spICU+JQogIHN1bW1hcmlzZShtZWFuX1JUID0gbWVhbihSVCksCiAgICAgICAgICAgIHNkX1JUID0gc2QoUlQpLAogICAgICAgICAgICBtZWRpYW5fUlQgPSBtZWRpYW4oUlQpKQpgYGAKCgpgYGB7ciBldmFsPUZBTFNFfQojIEZ1bGwgbW9kZWwgZm9yIGFib3ZlIGdyYXBoLiBOb3QgcnVuIGJlY2F1c2UgdG9vIGxvbmcuCnJ0LmxtZXIxIDwtIGxtZXJUZXN0OjpsbWVyKHNjYWxlKFJUKSB+IEdyb3VwKlRhc2sqc2NhbGUoVHJpYWxudW1iZXIpICsgKDF8Zi5pZCksIGRhdGEgPSBSVC5kZltSVC5kZiRSVD4wLF0pCgpzdW1tYXJ5KHJ0LmxtZXIxKQpgYGAKCkdyb3VwIGRpZmZlcmVuY2VzIHJlc3BvbnNlIHRpbWVzIChyZXBvcnRlZCkKCmBgYHtyfQpzdW1tYXJ5KGxtZXJUZXN0OjpsbWVyKHNjYWxlKFJUKSB+IEdyb3VwICsgKDF8Zi5pZCksIGRhdGEgPSBjaG9pY2UyLnRyaWFsLmRhdGFbY2hvaWNlMi50cmlhbC5kYXRhJFJUPjAsXSkpCmBgYAoKSWRpb3N5bmNyYXRpYyBzdGltdWx1cyBlZmZlY3RzCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKYGBge3J9CmlkLmRmID0gY2hvaWNlMi50cmlhbC5kYXRhICU+JQogIHNlbGVjdChJbnRyYW5zVHJpcGxlQ291bnRlZCwgSW1hZ2VfcmlnaHQsIEltYWdlX2xlZnQsIGYuaWQpICU+JQogIGdhdGhlcihrZXksIHZhbHVlLCAtSW50cmFuc1RyaXBsZUNvdW50ZWQsIC1mLmlkKSAlPiUKICBncm91cF9ieShmLmlkLHZhbHVlKSAlPiUKICBzdW1tYXJpc2Uoc3VtX0ludHJhbnMgPSBzdW0oSW50cmFuc1RyaXBsZUNvdW50ZWQpKQoKc3VtbWFyeShhb3Yoc3VtX0ludHJhbnMgfiBmYWN0b3IodmFsdWUpICsgRXJyb3IoZi5pZC92YWx1ZSksIGRhdGEgPSBpZC5kZikpCiNGb3IgZXhhY3QgdmFsdWVzCiMgc3RyKHN1bW1hcnkoYW92KHN1bV9JbnRyYW5zIH4gZmFjdG9yKHZhbHVlKSArIEVycm9yKGYuaWQvdmFsdWUpLCBkYXRhID0gaWQuZGYpKSkKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpybShpZC5kZikKYGBgCgpBcHBlbmRpeAotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCjxhIGlkPSJydF9jb3JfcGxvdCI+PC9hPkNvcnJlbGF0aW9ucyBiZXR3ZWVuIHJlc3BvbnNlIHRpbWVzIGZvciBlYWNoIHRyaWFsIGluIGEgdHJpcGxldAoKYGBge3J9CmJvdGgudHJpcGxldC5kYXRhICU+JQogIHNlbGVjdChUYXNrLCBSVF9BLCBSVF9CLCBSVF9DLCBHcm91cCwgZi5pZCkgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUsIC1UYXNrLCAtUlRfQywgLUdyb3VwLCAtZi5pZCkgJT4lCiAgZ2dwbG90KGFlcyhSVF9DLCB2YWx1ZSwgZ3JvdXA9R3JvdXAsIGNvbG9yPUdyb3VwKSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpKwogIHRoZW1lX2J3KCkrCiAgZmFjZXRfZ3JpZChrZXkgfiBUYXNrKSsKICB4bGFiKCJSZXNwb25zZSB0aW1lIGZvciB0aGUgdGhpcmQgdHJpYWwgaW4gdGhlIHRyaXBsZXQiKSsKICB5bGFiKCJSZXNwb25zZSB0aW1lcyBmb3IgdGhlIGZpcnN0IFxuIGFuZCBzZWNvbmQgdHJpYWxzIGluIHRyaXBsZXQiKQpgYGAK