In total 242 participants were invited, 175 began the battery, 157 completed the battery and 150 provided data that passed qc for both time points. Our target sample size was determined in advance of data collection and data collection continued until this number of participants with data that survived qc was reached.

Data collection took place on average 115 number of days after the completion of the initial battery with a range of 60 to 228 days.

The variables included in this report are:
- meaningful variables (includes only hdddm parameters)
- EZ diffusion parameters
- Raw RT and Accuracy measures
- Variables found in the literature (for comparison)

For reference here are the variables that are not included in the analyses of the remainder of this report because they were not of theoretical interest in factor structure analyses of this data. These include drift diffusion and other model parameters for specific conditions within a task; survey variables that are not part of the dependant variables for that survey in the literature and demographics (these are saved for prediction analyses).

test_data2 <- read.csv(paste0(retest_data_path, 't1_data/variables_exhaustive.csv'))

df <- data.frame(names(test_data2)[which(names(test_data2) %in% names(test_data) == FALSE)])
names(df) = c('vars')

df %>%
  filter(vars != "X")
rm(test_data2, df)

Results

Demographics

summary(test_demog %>%
          select(Sex, Age))
      Sex            Age      
 Min.   :0.00   Min.   :21.0  
 1st Qu.:0.00   1st Qu.:28.0  
 Median :1.00   Median :33.0  
 Mean   :0.52   Mean   :34.1  
 3rd Qu.:1.00   3rd Qu.:38.8  
 Max.   :1.00   Max.   :59.0  
summary(retest_demog %>%
          select(Sex, Age))
      Sex             Age      
 Min.   :0.000   Min.   :21.0  
 1st Qu.:0.000   1st Qu.:29.0  
 Median :1.000   Median :33.0  
 Mean   :0.527   Mean   :34.5  
 3rd Qu.:1.000   3rd Qu.:38.8  
 Max.   :1.000   Max.   :60.0  

Literature review

Here’s what our literature review looks like

lit_review
tmp = lit_review[duplicated(lit_review$reference)==FALSE,]

The literature review included 151 papers, 17167 participants and 574 data points on reliability.

rm(tmp)

An interactive version of this plot could be find here

Takeaways from this review are:
- Survey measures have been reported to higher reliability compared to task measures
- Survey measures have less variability in the reported reliabiltiy estimates compared to task measures

Data quality checks

Demographics reliability

Point estimates of reliability for the demographic variabels.

demog_boot_df %>%
  group_by(dv) %>%
  summarise(median_icc2.1 = quantile(icc2.1, probs=0.5),
            icc2.1_2.5 = quantile(icc2.1, probs = 0.025),
            icc2.1_97.5 = quantile(icc2.1, probs = 0.975)) %>%
  arrange(-median_icc2.1)

Point estimates of reliability for demog items

demog_rel_df = make_rel_df(test_demog, t2_df = retest_demog, metrics=c('icc2.1'))

demog_rel_df %>%
  select(dv, icc2.1) %>%
  arrange(-icc2.1)

Plotting point estimates of reliability for demographic items coloring those that have a time limit darker in the histogram.

timed_demogs <- c("DoctorVisitsLastMonth","DaysHalfLastMonth","Worthless","DaysPhysicalHealthFeelings","Depressed","EverythingIsEffort","Hopeless","RestlessFidgety","Nervous","DaysLostLastMonth","Last30DaysUsual")

demog_rel_df %>%
  mutate(timed = ifelse(dv %in% timed_demogs, 1, 0)) %>%
  ggplot(aes(icc2.1, fill = factor(timed)))+
  geom_histogram(position = "identity", alpha = 0.7, color = NA)+
  xlab("icc2.1")+
  ylab("Count")+
  scale_fill_manual(values = c("grey", "grey25"))+
  theme(legend.position = "none")

Effect of delays between the two measurements

Instead of the summary metric like the retest reliability estimate for each measure we can check whether the difference score distribution for each measure depends on the delay between the two measurements. Since the difference score distribution is at subject level we can check whether the order of subjects in this distribution depends on their order in the distribution of days between completing the two tests.

To check this we make data frame with difference between two scores for each measure for each subject. Since the scores for different measures are on different scales for comparability the difference scores are normalized (ie demeaned and dividied by the sd of the difference score distribution.) Note that the variance of the difference score distribution accounts for the variance in both time points by summing them. Normalization equates the means of each difference score distribution to 0 which would mask any meaningful change between the two time points but the analysis here does not interpret the mean of the difference score distributions but is interested in its relation to the days between completion. We check if the variables show systematic differences between the two points later.

Here we check if the difference is larger the longer the delay.

numeric_cols = get_numeric_cols(test_data)

t1_2_difference = data.frame()

for(i in 1:length(numeric_cols)){
  tmp = match_t1_t2(numeric_cols[i],t1_df=test_data ,t2_df=retest_data,format='wide')
  tmp = tmp %>%
  mutate(difference = scale(`2` - `1`))
  t1_2_difference = rbind(t1_2_difference, tmp)
}

t1_2_difference$difference = as.data.frame(t1_2_difference$difference)$V1

t1_2_difference = t1_2_difference %>% separate(dv, c("task", "dv2"), sep="\\.", remove=FALSE)

Add completion dates to this data frame.

t1_2_difference = merge(t1_2_difference, task_comp_times[,c('sub_id', 'task','days_btw')], by=c('sub_id', 'task'))

What does the distribution of differences look like: The distribution of differences between two time points for each measure

t1_2_difference %>%
  ggplot(aes(difference, alpha=dv))+
  geom_histogram(position='identity')+
  theme(legend.position = 'none')

How do the difference score distributions look like with respect to the days between completion?

t1_2_difference %>%
  ggplot()+
  geom_smooth(aes(as.numeric(days_btw), abs(difference), group=factor(dv)), method='lm', se=FALSE, color = 'grey', alpha = 0.5)+
  geom_smooth(aes(as.numeric(days_btw), abs(difference)), method='lm', color = "black", se=FALSE)+
  theme(legend.title = element_blank())+
  xlab('Days between completion')+
  ylab('Scaled difference score')

To test if the slope of the black is significant we would run a mixed effects model with a fixed effect for days between completion, random slope for each dv depending on the days between and random intercept for each dv.

Before I was using subjects as a random effect but days between the two time points for each measure depends on subj id. What varies randomly is which dv we are looking for its distribution of differences in relation to the days between the time points. So I changed the model to have fixed effect for the days between, a random slope for (dependent variables can be differentially sensitive to th effect of days between) and a random intercept for dependent variable.

Significant fixed effect suggests that on average the longer the delay the smaller the difference.

summary(lmerTest::lmer(abs(difference) ~ scale(days_btw)+(scale(days_btw) | dv), data=t1_2_difference))
Linear mixed model fit by REML t-tests use Satterthwaite approximations
  to degrees of freedom [lmerMod]
Formula: abs(difference) ~ scale(days_btw) + (scale(days_btw) | dv)
   Data: t1_2_difference

REML criterion at convergence: 132273

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-1.127 -0.719 -0.260  0.402 15.807 

Random effects:
 Groups   Name            Variance Std.Dev. Corr
 dv       (Intercept)     0.003190 0.0565       
          scale(days_btw) 0.000149 0.0122   1.00
 Residual                 0.468366 0.6844       
Number of obs: 63454, groups:  dv, 446

Fixed effects:
                  Estimate Std. Error         df t value Pr(>|t|)    
(Intercept)        0.72218    0.00382  457.00000  189.05   <2e-16 ***
scale(days_btw)   -0.00985    0.00278 3236.00000   -3.55   0.0004 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
            (Intr)
scl(dys_bt) 0.146 
# summary(tmp <- MCMCglmm(abs(difference) ~ scale(days_btw), random = ~us(scale(days_btw)):dv, data=t1_2_difference, verbose=FALSE))

But if I just run one mixed effects model then we don’t get a sense of the simple effects (how many of the variables this effect of the days between is significant and in which direction). I can run it separately for each dv to see if all difference score distributions are affected the same way depending on the days between completion. But since we are running so many tests we need to correct for multiple comparisons. How many of these tests are significant FDR correcting? None.

get_delay_effect = function(df){
  mod = lm(abs(difference) ~ scale(days_btw), data = df)
  out = data.frame(estimate=coef(summary(mod))["scale(days_btw)","Estimate"], pval=coef(summary(mod))["scale(days_btw)","Pr(>|t|)"])
  return(out)
}

days_effect  = t1_2_difference %>%
  group_by(dv) %>%
  do(get_delay_effect(.))

#Correct p-values for multiple comparisons
sum(p.adjust(days_effect$pval, method = "fdr") < 0.05)
[1] 0

Conclusion: The average difference between the scores of a measure doesn’t change with the increased delay.

Overlapping survey questions

Some surveys have overlapping questions. Do these correlate within and across sessions?

First determine the overlapping questions.

duplicate_items
#surveys to read in
extract_items = c('worker',unique(with(duplicate_items, c(item1_ID, item2_ID))))

#correlations to compute:
#item1_t1 - item2_t1,
#item1_t2 - item2_t2,
#item1_t1 - item2_t2,
#item1_t2 - item2_t1

duplicate_items_data_t1 = duplicate_items_data_t1 %>%
  filter(worker %in% duplicate_items_data_t2$worker) %>%
  select(extract_items)

duplicate_items_data_t2=duplicate_items_data_t2 %>%
  filter(worker %in% duplicate_items_data_t1$worker) %>%
  select(extract_items)

duplicate_items = duplicate_items %>%
  mutate(t1_t1_cor = NA,
         t2_t2_cor = NA,
         t1_t2_cor = NA,
         t2_t1_cor = NA,
         t1_t1_polycor = NA,
         t2_t2_polycor = NA,
         t1_t2_polycor = NA,
         t2_t1_polycor = NA)

for(i in 1:nrow(duplicate_items)){
  duplicate_items$t1_t1_cor[i] = abs(cor(duplicate_items_data_t1[,c(duplicate_items$item1_ID[i])],
                                  duplicate_items_data_t1[,c(duplicate_items$item2_ID[i])]))

  duplicate_items$t2_t2_cor[i] = abs(cor(duplicate_items_data_t2[,c(duplicate_items$item1_ID[i])],
                                  duplicate_items_data_t2[,c(duplicate_items$item2_ID[i])]))

  duplicate_items$t1_t2_cor[i] = abs(cor(duplicate_items_data_t1[,c(duplicate_items$item1_ID[i])],
                                  duplicate_items_data_t2[,c(duplicate_items$item2_ID[i])]))

  duplicate_items$t2_t1_cor[i] = abs(cor(duplicate_items_data_t2[,c(duplicate_items$item1_ID[i])],
                                  duplicate_items_data_t1[,c(duplicate_items$item2_ID[i])]))

  duplicate_items$t1_t1_polycor[i] = abs(polychoric(data.frame(duplicate_items_data_t1[,c(duplicate_items$item1_ID[i])],
                      duplicate_items_data_t1[,c(duplicate_items$item2_ID[i])]))$rho[2])

  duplicate_items$t2_t2_polycor[i] = abs(polychoric(data.frame(duplicate_items_data_t2[,c(duplicate_items$item1_ID[i])],
                      duplicate_items_data_t2[,c(duplicate_items$item2_ID[i])]))$rho[2])

  duplicate_items$t1_t2_polycor[i] = abs(polychoric(data.frame(duplicate_items_data_t1[,c(duplicate_items$item1_ID[i])],
                      duplicate_items_data_t2[,c(duplicate_items$item2_ID[i])]))$rho[2])

  duplicate_items$t2_t1_polycor[i] = abs(polychoric(data.frame(duplicate_items_data_t2[,c(duplicate_items$item1_ID[i])],
                      duplicate_items_data_t1[,c(duplicate_items$item2_ID[i])]))$rho[2])
}

for(i in 1:nrow(duplicate_items)){
  duplicate_items$t1_t1_cor[i] = abs(cor(scale(duplicate_items_data_t1[,c(duplicate_items$item1_ID[i])]),
                                  scale(duplicate_items_data_t1[,c(duplicate_items$item2_ID[i])])))

  duplicate_items$t2_t2_cor[i] = abs(cor(scale(duplicate_items_data_t2[,c(duplicate_items$item1_ID[i])]),
                                  scale(duplicate_items_data_t2[,c(duplicate_items$item2_ID[i])])))

  duplicate_items$t1_t2_cor[i] = abs(cor(scale(duplicate_items_data_t1[,c(duplicate_items$item1_ID[i])]),
                                  scale(duplicate_items_data_t2[,c(duplicate_items$item2_ID[i])])))

  duplicate_items$t2_t1_cor[i] = abs(cor(scale(duplicate_items_data_t2[,c(duplicate_items$item1_ID[i])]),
                                  scale(duplicate_items_data_t1[,c(duplicate_items$item2_ID[i])])))

  duplicate_items$t1_t1_polycor[i] = abs(polychoric(data.frame(duplicate_items_data_t1[,c(duplicate_items$item1_ID[i])],
                      duplicate_items_data_t1[,c(duplicate_items$item2_ID[i])]))$rho[2])

  duplicate_items$t2_t2_polycor[i] = abs(polychoric(data.frame(duplicate_items_data_t2[,c(duplicate_items$item1_ID[i])],
                      duplicate_items_data_t2[,c(duplicate_items$item2_ID[i])]))$rho[2])

  duplicate_items$t1_t2_polycor[i] = abs(polychoric(data.frame(duplicate_items_data_t1[,c(duplicate_items$item1_ID[i])],
                      duplicate_items_data_t2[,c(duplicate_items$item2_ID[i])]))$rho[2])

  duplicate_items$t2_t1_polycor[i] = abs(polychoric(data.frame(duplicate_items_data_t2[,c(duplicate_items$item1_ID[i])],
                      duplicate_items_data_t1[,c(duplicate_items$item2_ID[i])]))$rho[2])
}

duplicate_items %>%
  arrange(-t1_t1_polycor, -t2_t2_polycor)
# summary(duplicate_items$t1_t1_cor)
# summary(duplicate_items$t2_t2_cor)
# summary(duplicate_items$t1_t2_cor)
# summary(duplicate_items$t2_t1_cor)

summary(duplicate_items$t1_t1_polycor)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.284   0.355   0.583   0.567   0.742   0.822 
summary(duplicate_items$t2_t2_polycor)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.101   0.446   0.612   0.580   0.700   0.904 
# summary(duplicate_items$t1_t2_polycor)
# summary(duplicate_items$t2_t1_polycor)
tmp = duplicate_items %>%
  select(similarity, t1_t1_polycor, t2_t2_polycor) %>%
  gather(key, value, -similarity)

tmp %>%
  ggplot(aes(similarity, value, col=key))+
  geom_smooth(method="lm", alpha = 0.15)+
  ylab("Polychoric correlation")+
  xlab("Levenshtein distance")+
  scale_color_discrete(breaks = c("t1_t1_polycor", "t2_t2_polycor"),
                       labels = c("T1 correlations", "T2 correlations"),
                       name = element_blank())+
  theme_bw()

summary(lm(value~key*scale(similarity),tmp))

Call:
lm(formula = value ~ key * scale(similarity), data = tmp)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.4483 -0.1631  0.0159  0.1343  0.3367 

Coefficients:
                                   Estimate Std. Error t value Pr(>|t|)
(Intercept)                          0.5675     0.0448   12.66    2e-14
keyt2_t2_polycor                     0.0127     0.0634    0.20     0.84
scale(similarity)                    0.0924     0.0454    2.03     0.05
keyt2_t2_polycor:scale(similarity)  -0.0515     0.0643   -0.80     0.43
                                      
(Intercept)                        ***
keyt2_t2_polycor                      
scale(similarity)                  *  
keyt2_t2_polycor:scale(similarity)    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.195 on 34 degrees of freedom
Multiple R-squared:  0.128, Adjusted R-squared:  0.051 
F-statistic: 1.66 on 3 and 34 DF,  p-value: 0.193

Comparison to prior literature

Summarize bootstrapped results and merge to lit review data

Here’s what our data looks like: (583 data points for 171 measures)

rel_comp

Lit review results

Distribution of reliabilities, sample sizes and delays in the literature

rel_comp %>%
  select(dv, task, retest_reliability, sample_size, days) %>%
  filter(days < 3600) %>%
  gather(key, value, -dv, -task) %>%
  ggplot(aes(value, fill=task))+
  geom_density(alpha=0.5, position='identity')+
  facet_wrap(~key, scales='free')+
  theme(legend.title = element_blank())

summary(rel_comp$sample_size[rel_comp$task == "survey"])
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
     11      38      73     126     153     791 
summary(rel_comp$sample_size[rel_comp$task == "task"])
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   10.0    30.0    45.5    76.6    79.5  1120.0 
rel_comp %>%
  group_by(task) %>%
  summarise(mean_sample_size = mean(sample_size),
            sem_sample_size = sem(sample_size)) %>%
  ggplot(aes(task,mean_sample_size,col=task))+
  geom_point(size=5)+
  geom_errorbar(aes(ymin=mean_sample_size-sem_sample_size, ymax=mean_sample_size+sem_sample_size), width = 0, size=2)+
  xlab("")+
  ylab("Sample size")+
  theme(legend.position = 'none',
        axis.text.x = element_text(size=14),
        axis.title.y = element_text(size=14))

The literature has smaller sized samples for task measures compared to survey measures that report retest reliability.

# summary(lm(sample_size ~ task,rel_comp))
summary(m1 <- MCMCglmm(sample_size ~ task, data=rel_comp, verbose=FALSE))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: 7197 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units     16224    14178    17956     1000

 Location effects: sample_size ~ task 

            post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)     126.6    110.9    143.4     1000 <0.001 ***
tasktask        -50.2    -69.8    -28.8     1000 <0.001 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

What predicts retest reliability in the literature? Task, sample size, days

mod1 = lmer(retest_reliability ~ task + (1|dv), rel_comp)
mod2 = lmer(retest_reliability ~ task + sample_size + (1|dv), rel_comp)

anova(mod1, mod2)
refitting model(s) with ML (instead of REML)
mod3 = lmer(retest_reliability ~ task + sample_size + days+ (1|dv), rel_comp)

anova(mod2, mod3)
refitting model(s) with ML (instead of REML)
#summary(mod2)
summary(MCMCglmm(retest_reliability ~ task + sample_size, random = ~ dv, data = rel_comp, verbose=FALSE))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: -482.3 

 G-structure:  ~dv

   post.mean l-95% CI u-95% CI eff.samp
dv    0.0177   0.0115   0.0246     1000

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units    0.0208   0.0176   0.0238     1000

 Location effects: retest_reliability ~ task + sample_size 

             post.mean   l-95% CI   u-95% CI eff.samp  pMCMC    
(Intercept)  0.7239222  0.6768852  0.7610282     1000 <0.001 ***
tasktask    -0.1399050 -0.1914627 -0.0884644     1000 <0.001 ***
sample_size -0.0001260 -0.0002276 -0.0000173     1000  0.022 *  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
rel_comp %>%
  group_by(task) %>%
  summarise(mean_rr = mean(retest_reliability))

Are the residuals of this model heteroscedastic? Yes the residuals do not depend on the predictor.

tmp = data.frame(rel_comp$sample_size, resid(mod2)) %>%
  rename(sample_size = rel_comp.sample_size, resid = resid.mod2.)

tmp %>%
  ggplot(aes(sample_size, resid))+
  geom_point()+
  geom_smooth(method = "lm")

summary(lm(resid ~ sample_size, tmp))

Call:
lm(formula = resid ~ sample_size, data = tmp)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.4573 -0.0702  0.0183  0.0783  0.3691 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) -5.54e-16   6.71e-03       0        1
sample_size  3.71e-18   4.16e-05       0        1

Residual standard error: 0.129 on 572 degrees of freedom
Multiple R-squared:  1.34e-29,  Adjusted R-squared:  -0.00175 
F-statistic: 7.65e-27 on 1 and 572 DF,  p-value: 1

Tasks have significantly lower reliability and reliability decreases with increasing sample size.

rel_comp %>%
  ggplot(aes(sample_size, retest_reliability, color=task))+
  geom_smooth(method='lm')+
  # geom_point(alpha = 0.2)+
  theme(legend.title = element_blank(),
        axis.title.y = element_text(size=14),
        axis.title.x = element_text(size=14))+
  xlab("Sample Size")+
  ylab("Retest reliability")+
  ylim(-0.15, 1)

Highlighting the difference between survey and task reliability for comparability to our results.

rel_comp %>%
  ggplot(aes(task, retest_reliability, fill = task))+
  geom_boxplot()+
  theme(legend.position = 'none',
        axis.text.x = element_text(size=14),
        axis.title.y = element_text(size=14))+
  xlab("")+
  ylab("Mean icc2.1")+
  ylim(-0.4,1)

Note: We checked whether our results diverge most from studies with smaller sample sizes. Square difference between our mean estimate and the reliability from the literature decreases exponentially with sample size. The smaller the sample size in the literature the more the reliability estimate differs from our results. But this was a weak result because most of the studies in the literature have smaller sample sizes and you see both small and large deviations for these studies (these were not significant either).

Correlation with our results

Correlation between our mean estimates from bootstrapped samples and the literature review for task variables

n_df = rel_comp %>%
  group_by(dv) %>%
  tally()

lit_emp_cor = function(){

  boot_comp = data.frame()

  for(i in 1:length(unique(rel_comp$dv)) ){
    cur_dv = unique(rel_comp$dv)[i]
    n = n_df$n[n_df$dv == cur_dv]
    sample_df = boot_df %>% filter(dv == cur_dv)
    tmp = sample_n(sample_df, n)
    boot_comp = rbind(boot_comp, tmp)
  }  

  rm(cur_dv, n, sample_df, tmp)

  #check if cbind is ok
  # sum(boot_comp$dv == rel_comp$dv)
  #cbinding pearson because that is the most common metric in the lit
  rel_comp = cbind(rel_comp, boot_comp$pearson)
  #rename new column
  names(rel_comp)[which(names(rel_comp) == "boot_comp$pearson")] = "pearson"

  out = data.frame(task = NA, survey = NA)

  out$task = with(rel_comp %>% filter(task == "task"), cor(pearson, retest_reliability))

  out$survey = with(rel_comp %>% filter(task == "survey"), cor(pearson, retest_reliability))

  rel_comp = rel_comp[,-16]

  return(out)
}

lit_emp_cor_out = plyr::rdply(100, lit_emp_cor)

write.csv(lit_emp_cor_out,'/Users/zeynepenkavi/Dropbox/PoldrackLab/SRO_Retest_Analyses/output/tables/lit_emp_cor_out.csv')
       X               .n             task           survey       
 Min.   :  1.0   Min.   :  1.0   Min.   :0.176   Min.   :-0.0236  
 1st Qu.: 25.8   1st Qu.: 25.8   1st Qu.:0.233   1st Qu.: 0.0414  
 Median : 50.5   Median : 50.5   Median :0.247   Median : 0.0663  
 Mean   : 50.5   Mean   : 50.5   Mean   :0.247   Mean   : 0.0627  
 3rd Qu.: 75.2   3rd Qu.: 75.2   3rd Qu.:0.262   3rd Qu.: 0.0858  
 Max.   :100.0   Max.   :100.0   Max.   :0.297   Max.   : 0.1644  

Noise ceiling

Model comparisons building model to predict the reliabilities in the literature from a sample from our results versus a sample form the literature.

sample one row per measure out of lit review r^2 of retest_reliability ~ sampled_reliability vs. r^2 of retest_reliability ~ mean_icc2.1

coef of retest_reliability ~ sampled_reliability vs. coef of retest_reliability ~ mean_icc2.1

comp_lit_pred <- function(df){

  sample_from_dv <- function(df){
    if(nrow(df)>1){
      row_num = sample(1:nrow(df),1)
      sample_row = df[row_num,]
      df = df[-row_num,]
      df$lit_predictor = sample_row$retest_reliability
    }
    return(df)
  }

  sampled_df = df %>%
    group_by(dv) %>%
    do(sample_from_dv(.)) %>%
    na.omit()

  if(length(unique(sampled_df$task))>1){
    mod_lit = lm(retest_reliability ~ lit_predictor+scale(sample_size)+task, data=sampled_df)
    mod_boot = lm(retest_reliability ~ mean_pearson+scale(sample_size)+task, data=sampled_df)
  }
  else{
    mod_lit = lm(retest_reliability ~ lit_predictor+scale(sample_size), data=sampled_df)
    mod_boot = lm(retest_reliability ~ mean_pearson+scale(sample_size), data=sampled_df)
  }


  out = data.frame(r2_lit = summary(mod_lit)$adj.r.squared,
                   r2_boot = summary(mod_boot)$adj.r.squared,
                   m_lit = coef(summary(mod_lit))["lit_predictor","Estimate"],
                   m_boot = coef(summary(mod_boot))["mean_pearson","Estimate"])

  return(out)
}

comp_lit_pred_out = plyr::rdply(1000, comp_lit_pred(rel_comp))

write.csv(comp_lit_pred_out,'/Users/zeynepenkavi/Dropbox/PoldrackLab/SRO_Retest_Analyses/output/tables/comp_lit_pred_out.csv')

with(comp_lit_pred_out, t.test(r2_lit, r2_boot, paired=T))

    Paired t-test

data:  r2_lit and r2_boot
t = 13, df = 1000, p-value <2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.03962 0.05431
sample estimates:
mean of the differences 
                0.04696 
tmp = comp_lit_pred_out %>%
  select(r2_lit, r2_boot) %>%
  gather(key, value)

summary(MCMCglmm(value ~ key, data = tmp, verbose=F))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: -4132 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units   0.00741  0.00699  0.00788      664

 Location effects: value ~ key 

            post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)    0.1654   0.1595   0.1705     1000 <0.001 ***
keyr2_lit      0.0469   0.0389   0.0540     1000 <0.001 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

We checked if survey and task measures differed in how close our results were to the literature (i.e. Are you better in estimating the literature using our data for surveys vs tasks?). We found an interaction, such that: The literature does a better job in predicting itself for tasks compared to surveys. On the other hand, our data is better in predicting the literature estimates for the surveys than it is in predicting tasks.

One might wonder: Why are the reliability estimates from surveys worse compared to tasks in predicting the literature? Because they are less variable. In this procedure having high variance in what is being predicted (i.e. the literature reliability estimates) is better.

We also conducted LOOCV on this data and checked what it looked like if we estimate the left one out using the remaining ones for the noise ceiling model? The procedure followed these steps: - Sample one row of literature,
- fit model of sample size+task on remaining data,
- use that model to predict the reliability estimates,
- compare those to the left out reliability estimate from the literature versus the average reliability estimate from our data

We found that the (squared) difference is slightly larger when predicting the left-out value from our data versus predicting left out value from literature. The squared differences were larger for predicting the literature compared to predicting our data for surveys while for tasks the squared differences were larger when predicting our data compared to predicting the literature. (This fits with other results too: our results differ from the literature more for the survey measures).

We do not present these results in further detail as they yield only converging evidence as the analyses above.

Measure level comparison

Literature vs. our data on a measure basis

rel_comp %>%
  group_by(dv, task) %>%
  summarise(mean_lit = mean(retest_reliability),
            mean_emp = unique(mean_pearson)) %>%
  ggplot(aes(mean_emp, mean_lit, col=task, shape=task))+
  geom_smooth(method="lm")+
  geom_point()+
  xlim(-0.25, 1)+
  ylim(-0.25, 1)+
  ylab("Average Literature Reliability Estimate")+
  xlab("Average Empirical Reliability Estimate")+
  theme(legend.title = element_blank(),
        legend.position = 'bottom',
        plot.caption = element_text(family = "Times", lineheight = 2, hjust = 0))+
  labs(caption = str_wrap("FIGURE 2: Correlation between mean reliability estimates for each measure found in the literature with the mean reliability from our data.", width = 120))

Warning in rm(tmp, rel_comp, mod1, mod2, mod3, i, lit_emp_cor_out,
comp_lit_pred, : object 'comp_lit_pred' not found

Relationship between reliability metrics (point estimates)

Though we are primarily reporting icc2.1’s as our metric of reliability the results don’t change depending on the metric chosen. Here we plot point estimates of three different reliability metrics against each other (icc2.1, Pearson, Spearman). The bootstrapped version is essentially the same but the plots are busier due to more datapoints.

rel_df = make_rel_df(t1_df = test_data, t2_df = retest_data, metrics = c('spearman', 'icc2.1','icc3.k', 'pearson', 'var_breakdown', 'partial_eta', 'sem'))

rel_df$task = 'task'
rel_df[grep('survey', rel_df$dv), 'task'] = 'survey'
rel_df[grep('holt', rel_df$dv), 'task'] = "task"
rel_df = rel_df %>%
  select(dv, task, spearman, icc2.1,icc3.k, pearson, partial_eta, sem, var_subs, var_ind, var_resid)

We calculated 74 measures for surveys and 372 measures for cognitive tasks.

As the scatter plots depict the correlations between different types reliability metrics were very high.

cor(rel_df[,c('spearman', 'icc2.1', 'icc3.k', 'pearson')])
         spearman icc2.1 icc3.k pearson
spearman   1.0000 0.9529 0.9324  0.9577
icc2.1     0.9529 1.0000 0.9788  0.9983
icc3.k     0.9324 0.9788 1.0000  0.9800
pearson    0.9577 0.9983 0.9800  1.0000

Note: Some variables have <0 icc2.1’s. This would be the case if the \(MS_{error}\)>\(MS_{between}\). Data for these variables have no relationship between the two time points.

Summary of all measure reliabilities

Summarized bootstrapped reliabilities

boot_df %>%
  group_by(dv) %>%
  summarise(icc2.1_median = quantile(icc2.1, probs = 0.5),
            icc2.1_2.5 = quantile(icc2.1, probs = 0.025),
            icc2.1_97.5 = quantile(icc2.1, probs = 0.975),
            spearman_median = quantile(spearman, probs = 0.5),
            spearman_2.5 = quantile(spearman, probs = 0.025),
            spearman_97.5 = quantile(spearman, probs = 0.975)) %>%
  datatable() %>%
  formatRound(columns=c('icc2.1_median', 'icc2.1_2.5', 'icc2.1_97.5', 'spearman_median', 'spearman_2.5', 'spearman_97.5'), digits=3)

Variable level summary of bootstrapped reliabilities.

Example of the overlaying procedure.

Survey vs Tasks

Comparison of survey measures to cognitive task measures in the bootstrapped results. Multilevel model with random intercepts for each measure and fixed effect of survey versus cognitive measure.

boot_df = boot_df %>%
    mutate(task = ifelse(grepl("survey",dv), "survey","task"),
           task = ifelse(grepl("holt",dv), "task", task))

boot_df %>%
  group_by(task) %>%
  summarise(icc2.1_median = quantile(icc2.1, probs = 0.5),
            icc2.1_2.5 = quantile(icc2.1, probs = 0.025),
            icc2.1_97.5 = quantile(icc2.1, probs = 0.975),
            spearman_median = quantile(spearman, probs = 0.5),
            spearman_2.5 = quantile(spearman, probs = 0.025),
            spearman_97.5 = quantile(spearman, probs = 0.975),
            num_vars = n()/1000) %>%
  datatable() %>%
  formatRound(columns=c('icc2.1_median', 'icc2.1_2.5', 'icc2.1_97.5', 'spearman_median', 'spearman_2.5', 'spearman_97.5'), digits=3)
summary(icc2.1_by_task_model)
summary(MCMCglmm(icc2.1 ~ task, data=rel_df, verbose=F))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: -193 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units    0.0379   0.0327   0.0426     1000

 Location effects: icc2.1 ~ task 

            post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)     0.781    0.738    0.825     1000 <0.001 ***
tasktask       -0.432   -0.482   -0.384      869 <0.001 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Variance breakdown

The quantiative explanation for the difference in reliability estimates between surveys and tasks, as recently detailed by Hedge et al. (2017), lies in the difference in sources of variance between these measures. Specifically, the icc2.1 is calculated as the ratio of variance between subjects variance to all sources of variance. Thus, measures with high between subjects variance would have high test-retest reliability. Intuitively, measures with high between subjects variance are also better suited for individual difference analyses as they would capture the differences between the subjects in a sample.

Here we first plot the percentage of variance explained by the three sources of variance for the point estimates of measure reliabilities. The plot only includes raw measures (no DDM parameters) and the measures are ranked by percentage of between subject variability for each task/survey (i.e. the best to worst individual difference measure for each task/survey). Then we compare statistically whether the percentage of variance explained by these sources differ between tasks and surveys.

Comparing types of variance for survey vs task measures: Survey measures have higher between subject variability

Note: This analysis includes DDM variables too.

Running separate models for different sources of variance because interactive model with variance type*task seemed too complicated.

First we find that task measures have a smaller percentage of their overall variance explained by variability between subjects compared to survey measures.

tmp = boot_df %>%
  select(dv, task, var_subs_pct, var_ind_pct, var_resid_pct)

# summary(var_subs_pct_by_task_model)

rel_df = rel_df %>% 
  mutate(var_subs_pct = var_subs/(var_subs+var_ind+var_resid)*100,
                             var_ind_pct = var_ind/(var_subs+var_ind+var_resid)*100,
                             var_resid_pct = var_resid/(var_subs+var_ind+var_resid)*100)

summary(MCMCglmm(var_subs_pct ~ task, data=rel_df, verbose=F))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: 3808 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units       298      260      336     1000

 Location effects: var_subs_pct ~ task 

            post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)      79.5     75.7     83.2     1124 <0.001 ***
tasktask        -30.2    -34.9    -26.1     1000 <0.001 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

We also find that a significantly larger percentage of their variance is explained by between session variability. Larger between session variability suggests systematic differences between the two sessions. Such systematic effects can be due to e.g. learning effects as explored later.

# summary(var_ind_pct_by_task_model)

summary(MCMCglmm(var_ind_pct ~ task, data=rel_df, verbose=F))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: 4043 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units       505      438      570     1000

 Location effects: var_ind_pct ~ task 

            post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)     10.80     5.74    15.68     1000 <0.001 ***
tasktask        16.18    10.68    21.84     1000 <0.001 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# summary(var_resid_pct_by_task_model)

summary(MCMCglmm(var_resid_pct ~ task, data=rel_df, verbose=F))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: 3369 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units       111     96.9      126     1000

 Location effects: var_resid_pct ~ task 

            post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)      9.76     7.23    11.91     1094 <0.001 ***
tasktask        13.91    11.46    16.57     1000 <0.001 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
rm(var_subs_pct_by_task_model, var_ind_pct_by_task_model, var_resid_pct_by_task_model)
tmp_save = tmp%>%
  gather(key, value, -dv, -task) %>%
  group_by(task, key) %>%
  summarise(median = median(value),
            sd = sd(value)) %>%
  mutate(key = ifelse(key == 'var_ind_pct', 'Between session variance', ifelse(key == 'var_subs_pct', 'Between subjects variance', ifelse(key == 'var_resid_pct', 'Residual variance',NA)))) %>%
  rename(Median = median, SD = sd) %>%
  arrange(task, key)

tmp_save

Summarizing for clearer presentation. This graph is currently using the bootstrapped reliabilities and is therefore messier than if just using the point estimates.

Task Reliabilities

Here we summarize the results on a task level to make it more digestable and easier to make contact with the literature.

We reduce the list of task measures to a list of one per task by averaging only the measures that are extracted and used from these tasks in the literature. We call these the ‘meaningful measures.’

tmp = measure_labels %>%
  mutate(dv = as.character(dv)) %>%
  filter(task == 'task',
         dv %in% meaningful_vars) %>%
  left_join(boot_df[,c("dv", "icc2.1")], by = 'dv') %>%
  separate(dv, c('task_name', 'extra_1', 'extra_2'), sep = '\\.',remove=FALSE) %>%
  select(-extra_1, -extra_2) %>%
  group_by(task_name) %>%
  summarise(median_icc2.1 = median(icc2.1),
            icc2.1_2.5 = quantile(icc2.1, probs = 0.025),
            icc2.1_97.5 = quantile(icc2.1, probs = 0.975),
            num_measures = n()/1000,
            mean_num_trials = round(mean(num_all_trials)))%>%
  arrange(-median_icc2.1)

tmp %>%
  datatable() %>%
  formatRound(columns=c('median_icc2.1','icc2.1_2.5','icc2.1_97.5'), digits=3)

Number of trials

Does number of items in a task have a significant effect on the average icc2.1 of meaningful measures for all trials from a task? No.

tmp = measure_labels %>%
  mutate(dv = as.character(dv)) %>%
  filter(task == 'task',
         dv %in% meaningful_vars) %>%
  # left_join(boot_df[,c("dv", "icc2.1")], by = 'dv') %>%
  left_join(rel_df[,c("dv", "icc2.1")], by = 'dv') %>%
  separate(dv, c('task_name', 'extra_1', 'extra_2'), sep = '\\.',remove=FALSE) %>%
  select(-extra_1, -extra_2)

#summary(icc2.1_by_num_trials_model)
summary(MCMCglmm(icc2.1 ~ num_all_trials, data=tmp, verbose=F))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: -11.77 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units    0.0495   0.0357   0.0662     1000

 Location effects: icc2.1 ~ num_all_trials 

               post.mean  l-95% CI  u-95% CI eff.samp  pMCMC    
(Intercept)     0.305240  0.252702  0.368419     1000 <0.001 ***
num_all_trials  0.000188 -0.000196  0.000573     1000   0.34    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
tmp %>%
  ggplot(aes(num_all_trials, icc2.1))+
  geom_point()+
  geom_smooth(method="lm")+
  theme_bw()+
  xlab("Number of trials")+
  ylab("icc2.1")

Trial number dependence intrameasure

The above analysis was looking at the effect of number of trials across tasks. But some tasks might be bad for individual difference measurement regardless of how many trials there are in them whereas for others fewer trials might be yielding a sufficiently reliable measure.

For tasks for which dependent variables are estimated using many trials one can ask: Does the same measure get less reliable if fewer trials are used to estimate its reliability?

This won’t make sense for all tasks. For example to estimate a risk aversion parameter you need all trials for Holt and Laury. For Kirby and Bickel you have specific conditions looking at fewer trials. The Cognitive Reflection Task might be more appropriate to analyze each item seaprately. The writing task does not have trial numbers. For all others it might be interesting to investigate.

These kinds of analyses are too task-specific and in-depth for a paper that is trying to give a global sense of the differences between self-regulation measures in their suitablity for individual difference analyses based on their stability across time. Such analyses would provide a detailed examination of how to extract the most reliable/best individual difference measure from tasks with a set of mediocre variables to begin with. Though we do not provide such a comprehensive analysis of this sort in this paper we provide a single example of this approach and hope the open access we provide to the data spurs further work.

For this example we look at the retest reliability of dependent measures from the threebytwo with >400 trials. Here is a graph of how the point estimates of the retest reliability changes for each of the dependent measures using different numbers of trials to estimate them.

Takeaways from this graph: - Reliability estimates stabilize after about an eigthth of the trials (note that this might not be true for other model parameter estimates; here we are only looking at raw response time and accuracy measures) - Only three measures that are not contrast measures have reliabilities >0 - All the other measures are basically completely unreliable (including the two ‘meaningful variables’ in the literature: the cue switch cost RT’s)

trial_num_rel_df %>%
  gather(key, value, -breaks) %>%
  filter(key %in% c("avg_rt_icc", "learning_to_learn_icc", "nonperseverative_errors_icc")) %>%
  ggplot(aes((breaks+1)*10, value, shape=key))+
  geom_point()+
  geom_line(alpha = 0.5)+
  theme_bw()+
  xlab("Number of trials")+
  ylab("ICC")+
  theme(legend.title = element_blank(),
        legend.position = 'bottom',
                             plot.caption = element_text(family = "Times", lineheight = 2, hjust = 0)) +
  scale_shape_manual(values = c(0:9),
                     breaks = c("avg_rt_icc","learning_to_learn_icc", "nonperseverative_errors_icc"),
                     labels = c("Average Response Time", "Learning to Learn",  "Nonperseverative Errors")) +
  labs(caption = str_wrap("FIGURE 6: Change in point estimates of ICC for three dependent measures selected from the Shift task using increasing numbers of trials to estimate them. These measures show the different types of relationships reliability estimates have based on the trial numbers used to estimate them.", width = 180))

Raw vs DDM

Checking DDM results in the bootstrapped estimates. Variables using all trials are significantly more reliable compared to difference scores. Raw measures don’t differ from DDM parameters. Which DDM is better depends on whether all trials are used.

tmp = measure_labels %>%
  mutate(dv = as.character(dv),
         contrast = ifelse(overall_difference == "difference", "contrast", "non-contrast")) %>%
  filter(ddm_task == 1,
         rt_acc != 'other') %>%
  drop_na() %>%
  # left_join(boot_df[,c("dv", "icc2.1")], by = 'dv')
  left_join(rel_df[,c("dv", "icc2.1")], by = 'dv')

tmp_save = tmp %>%
  drop_na() %>% #try removing this in final release
  group_by(contrast, raw_fit, rt_acc) %>%
  summarise(icc2.1_median = quantile(icc2.1, probs = 0.5),
            icc2.1_2.5 = quantile(icc2.1, probs = 0.025),
            icc2.1_97.5 = quantile(icc2.1, probs = 0.975),
            num_vars = n()/1000)

tmp_save %>%
  datatable() %>%
  formatRound(columns=c('icc2.1_median', 'icc2.1_2.5', 'icc2.1_97.5'), digits=3)

Comparing contrast vs non-contrast: overall has higher reliability than difference.

# summary(lmerTest::lmer(icc2.1 ~ contrast + (1|dv) ,tmp))
# summary(MCMCglmm(icc2.1 ~ contrast, random = ~ dv, data=tmp, verbose=FALSE))
summary(MCMCglmm(icc2.1 ~ contrast, data=tmp, verbose=FALSE))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: -261.1 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units    0.0219   0.0184   0.0257     1000

 Location effects: icc2.1 ~ contrast 

                     post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)              0.154    0.127    0.184     1000 <0.001 ***
contrastnon-contrast     0.288    0.249    0.326     1000 <0.001 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Comparing raw vs ddm in overall estimates: EZ is significantly better than HDDM and comparable to raw estimates.

# summary(icc2.1_by_rawfit_noncon_model)
summary(MCMCglmm(icc2.1 ~ raw_fit, data=tmp %>% filter(contrast == "non-contrast"), verbose=FALSE))
Warning in MCMCglmm(icc2.1 ~ raw_fit, data = tmp %>% filter(contrast
== : some fixed effects are not estimable and have been removed. Use
singular.ok=TRUE to sample these effects, but use an informative prior!

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: -150.2 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units    0.0223   0.0173   0.0274     1000

 Location effects: icc2.1 ~ raw_fit 

            post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)    0.4810   0.4354   0.5257     1000 <0.001 ***
raw_fithddm   -0.0971  -0.1577  -0.0268     1000  0.002 ** 
raw_fitraw    -0.0281  -0.0895   0.0276     1000  0.358    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Comparing raw vs ddm in difference scores: EZ is significantly worse than HDDM and comparable to raw estimates.

# summary(icc2.1_by_rawfit_con_model)
summary(MCMCglmm(icc2.1 ~ raw_fit, data=tmp %>% filter(contrast == "contrast"), verbose=FALSE))
Warning in MCMCglmm(icc2.1 ~ raw_fit, data = tmp %>% filter(contrast
== : some fixed effects are not estimable and have been removed. Use
singular.ok=TRUE to sample these effects, but use an informative prior!

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: -119.2 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units    0.0189   0.0135   0.0239     1000

 Location effects: icc2.1 ~ raw_fit 

            post.mean  l-95% CI  u-95% CI eff.samp  pMCMC    
(Intercept)  0.118627  0.081777  0.157888     1000 <0.001 ***
raw_fithddm  0.095471  0.018056  0.164123     1000  0.014 *  
raw_fitraw   0.051217 -0.000661  0.106071     1000  0.068 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

tmp %>%
  group_by(contrast) %>%
  summarise(mean_icc2.1 = mean(icc2.1),
            sd_icc2.1 = sd(icc2.1))

Survey reliabilities

tmp = measure_labels %>%
  mutate(dv = as.character(dv)) %>%
  filter(task == 'survey') %>%
  # left_join(boot_df[,c("dv", "icc2.1")], by = 'dv') %>%
  left_join(rel_df[,c("dv", "icc2.1")], by = 'dv') %>%
  separate(dv, c('task_name', 'extra_1', 'extra_2'), sep = '\\.',remove=FALSE) %>%
  select(-extra_1, -extra_2)

tmp_save = tmp %>%
  group_by(task_name) %>%
  summarise(median_icc2.1 = median(icc2.1),
            icc2.1_2.5 = quantile(icc2.1, probs = 0.025),
            icc2.1_97.5 = quantile(icc2.1, probs = 0.975),
            num_measures = n()/1000,
            mean_num_trials = round(mean(num_all_trials)))%>%
  arrange(-median_icc2.1)

tmp_save %>%
  datatable() %>%
  formatRound(columns=c('median_icc2.1', 'icc2.1_2.5','icc2.1_97.5'), digits=3)

Number of items

Does number of items in a survey have a significant effect on the average icc2.1 of survey measures? No.

# summary(lmerTest::lmer(icc2.1 ~ num_all_trials + (1|dv), data = tmp))
summary(MCMCglmm(icc2.1 ~ num_all_trials, data=tmp, verbose=FALSE))

 Iterations = 3001:12991
 Thinning interval  = 10
 Sample size  = 1000 

 DIC: -144.7 

 R-structure:  ~units

      post.mean l-95% CI u-95% CI eff.samp
units   0.00767  0.00528   0.0103     1038

 Location effects: icc2.1 ~ num_all_trials 

               post.mean l-95% CI u-95% CI eff.samp  pMCMC    
(Intercept)      0.76555  0.73139  0.80103      725 <0.001 ***
num_all_trials   0.00179 -0.00126  0.00437     1000   0.21    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
tmp %>%
  ggplot(aes(num_all_trials, icc2.1))+
  geom_point()+
  geom_smooth(method="lm")+
  theme_bw()+
  xlab("Number of trials")+
  ylab("icc2.1")

LS0tCnRpdGxlOiAnU2VsZiBSZWd1bGF0aW9uIE9udG9sb2d5IFJldGVzdCBBbmFseXNlcycKb3V0cHV0OgpnaXRodWJfZG9jdW1lbnQ6CnRvYzogeWVzCnRvY19mbG9hdDogeWVzCi0tLQoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnNldC5zZWVkKDEwMzk0ODM5KQpmcm9tX2doID0gVFJVRQpzb3VyY2UoJy9Vc2Vycy96ZXluZXBlbmthdmkvRHJvcGJveC9Qb2xkcmFja0xhYi9TUk9fUmV0ZXN0X0FuYWx5c2VzL2NvZGUvd29ya3NwYWNlX3NjcmlwdHMvU1JPX1JldGVzdF9BbmFseXNlc19Xb3Jrc3BhY2UuUicpCmBgYAoKSW4gdG90YWwgYHIgc3VtKHdvcmtlcnMkUmV0ZXN0X3dvcmtlcilgIHBhcnRpY2lwYW50cyB3ZXJlIGludml0ZWQsIGByIG5yb3cod29ya2VyX2NvdW50cylgIGJlZ2FuIHRoZSBiYXR0ZXJ5LCBgciBzdW0od29ya2VyX2NvdW50cyR0YXNrX2NvdW50ID49IDYyKWAgY29tcGxldGVkIHRoZSBiYXR0ZXJ5IGFuZCAxNTAgcHJvdmlkZWQgZGF0YSB0aGF0IHBhc3NlZCBxYyBmb3IgYm90aCB0aW1lIHBvaW50cy4gT3VyIHRhcmdldCBzYW1wbGUgc2l6ZSB3YXMgZGV0ZXJtaW5lZCBpbiBhZHZhbmNlIG9mIGRhdGEgY29sbGVjdGlvbiBhbmQgZGF0YSBjb2xsZWN0aW9uIGNvbnRpbnVlZCB1bnRpbCB0aGlzIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgd2l0aCBkYXRhIHRoYXQgc3Vydml2ZWQgcWMgd2FzIHJlYWNoZWQuCgpEYXRhIGNvbGxlY3Rpb24gdG9vayBwbGFjZSBvbiBhdmVyYWdlIGByIHJvdW5kKG1lYW4oYXMubnVtZXJpYyhjb21wX2RhdGVzJGRheXNfYnR3KSkpYCBudW1iZXIgb2YgZGF5cyBhZnRlciB0aGUgY29tcGxldGlvbiBvZiB0aGUgaW5pdGlhbCBiYXR0ZXJ5IHdpdGggYSByYW5nZSBvZiBgciByb3VuZChyYW5nZShhcy5udW1lcmljKGNvbXBfZGF0ZXMkZGF5c19idHcpKSlbMV1gIHRvIGByIHJvdW5kKHJhbmdlKGFzLm51bWVyaWMoY29tcF9kYXRlcyRkYXlzX2J0dykpKVsyXWAgZGF5cy4KClRoZSB2YXJpYWJsZXMgaW5jbHVkZWQgaW4gdGhpcyByZXBvcnQgYXJlOiAgCi0gbWVhbmluZ2Z1bCB2YXJpYWJsZXMgKGluY2x1ZGVzIG9ubHkgaGRkZG0gcGFyYW1ldGVycykgIAotIEVaIGRpZmZ1c2lvbiBwYXJhbWV0ZXJzICAKLSBSYXcgUlQgYW5kIEFjY3VyYWN5IG1lYXN1cmVzICAKLSBWYXJpYWJsZXMgZm91bmQgaW4gdGhlIGxpdGVyYXR1cmUgKGZvciBjb21wYXJpc29uKSAgCgpGb3IgcmVmZXJlbmNlIGhlcmUgYXJlIHRoZSB2YXJpYWJsZXMgdGhhdCBhcmUgKipub3QqKiBpbmNsdWRlZCBpbiB0aGUgYW5hbHlzZXMgb2YgdGhlIHJlbWFpbmRlciBvZiB0aGlzIHJlcG9ydCBiZWNhdXNlIHRoZXkgd2VyZSBub3Qgb2YgdGhlb3JldGljYWwgaW50ZXJlc3QgaW4gZmFjdG9yIHN0cnVjdHVyZSBhbmFseXNlcyBvZiB0aGlzIGRhdGEuIFRoZXNlIGluY2x1ZGUgZHJpZnQgZGlmZnVzaW9uIGFuZCBvdGhlciBtb2RlbCBwYXJhbWV0ZXJzIGZvciBzcGVjaWZpYyBjb25kaXRpb25zIHdpdGhpbiBhIHRhc2s7IHN1cnZleSB2YXJpYWJsZXMgdGhhdCBhcmUgbm90IHBhcnQgb2YgdGhlIGRlcGVuZGFudCB2YXJpYWJsZXMgZm9yIHRoYXQgc3VydmV5IGluIHRoZSBsaXRlcmF0dXJlIGFuZCBkZW1vZ3JhcGhpY3MgKHRoZXNlIGFyZSBzYXZlZCBmb3IgcHJlZGljdGlvbiBhbmFseXNlcykuCgpgYGB7cn0KdGVzdF9kYXRhMiA8LSByZWFkLmNzdihwYXN0ZTAocmV0ZXN0X2RhdGFfcGF0aCwgJ3QxX2RhdGEvdmFyaWFibGVzX2V4aGF1c3RpdmUuY3N2JykpCgpkZiA8LSBkYXRhLmZyYW1lKG5hbWVzKHRlc3RfZGF0YTIpW3doaWNoKG5hbWVzKHRlc3RfZGF0YTIpICVpbiUgbmFtZXModGVzdF9kYXRhKSA9PSBGQUxTRSldKQpuYW1lcyhkZikgPSBjKCd2YXJzJykKCmRmICU+JQogIGZpbHRlcih2YXJzICE9ICJYIikKYGBgCgpgYGB7cn0Kcm0odGVzdF9kYXRhMiwgZGYpCmBgYAoKIyBSZXN1bHRzCgojIyBEZW1vZ3JhcGhpY3MKCmBgYHtyfQpzdW1tYXJ5KHRlc3RfZGVtb2cgJT4lCiAgICAgICAgICBzZWxlY3QoU2V4LCBBZ2UpKQoKc3VtbWFyeShyZXRlc3RfZGVtb2cgJT4lCiAgICAgICAgICBzZWxlY3QoU2V4LCBBZ2UpKQpgYGAKCiMjIExpdGVyYXR1cmUgcmV2aWV3CgpIZXJlJ3Mgd2hhdCBvdXIgbGl0ZXJhdHVyZSByZXZpZXcgbG9va3MgbGlrZQoKYGBge3J9CmxpdF9yZXZpZXcKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQp0bXAgPSBsaXRfcmV2aWV3W2R1cGxpY2F0ZWQobGl0X3JldmlldyRyZWZlcmVuY2UpPT1GQUxTRSxdCmBgYAoKVGhlIGxpdGVyYXR1cmUgcmV2aWV3IGluY2x1ZGVkIGByIG5yb3codG1wKWAgcGFwZXJzLCBgciBzdW0odG1wJHNhbXBsZV9zaXplKWAgcGFydGljaXBhbnRzIGFuZCBgciBucm93KGxpdF9yZXZpZXcpYCBkYXRhIHBvaW50cyBvbiByZWxpYWJpbGl0eS4KCmBgYHtyfQpybSh0bXApCmBgYAoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPScxMDAlJ30KZmlnX25hbWUgPSAnTGl0X1Jldmlld19QbG90X3QuanBlZycKCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKHBhc3RlMChmaWdfcGF0aCwgZmlnX25hbWUpKQpgYGAKCkFuIGludGVyYWN0aXZlIHZlcnNpb24gb2YgdGhpcyBwbG90IGNvdWxkIGJlIGZpbmQgW2hlcmVdKGh0dHBzOi8vemVua2F2aS5naXRodWIuaW8vU1JPX1JldGVzdF9BbmFseXNlcy9vdXRwdXQvcmVwb3J0cy9JbnRlcmFjdGl2ZV9GaWd1cmVzLmh0bWwpCgpUYWtlYXdheXMgZnJvbSB0aGlzIHJldmlldyBhcmU6ICAgCi0gU3VydmV5IG1lYXN1cmVzIGhhdmUgYmVlbiByZXBvcnRlZCB0byBoaWdoZXIgcmVsaWFiaWxpdHkgY29tcGFyZWQgdG8gdGFzayBtZWFzdXJlcyAgCi0gU3VydmV5IG1lYXN1cmVzIGhhdmUgbGVzcyB2YXJpYWJpbGl0eSBpbiB0aGUgcmVwb3J0ZWQgcmVsaWFiaWx0aXkgZXN0aW1hdGVzIGNvbXBhcmVkIHRvIHRhc2sgbWVhc3VyZXMgICAKCiMjIERhdGEgcXVhbGl0eSBjaGVja3MKCiMjIyBEZW1vZ3JhcGhpY3MgcmVsaWFiaWxpdHkKClBvaW50IGVzdGltYXRlcyBvZiByZWxpYWJpbGl0eSBmb3IgdGhlIGRlbW9ncmFwaGljIHZhcmlhYmVscy4KCmBgYHtyfQpkZW1vZ19ib290X2RmICU+JQogIGdyb3VwX2J5KGR2KSAlPiUKICBzdW1tYXJpc2UobWVkaWFuX2ljYzIuMSA9IHF1YW50aWxlKGljYzIuMSwgcHJvYnM9MC41KSwKICAgICAgICAgICAgaWNjMi4xXzIuNSA9IHF1YW50aWxlKGljYzIuMSwgcHJvYnMgPSAwLjAyNSksCiAgICAgICAgICAgIGljYzIuMV85Ny41ID0gcXVhbnRpbGUoaWNjMi4xLCBwcm9icyA9IDAuOTc1KSkgJT4lCiAgYXJyYW5nZSgtbWVkaWFuX2ljYzIuMSkKYGBgCgpQb2ludCBlc3RpbWF0ZXMgb2YgcmVsaWFiaWxpdHkgZm9yIGRlbW9nIGl0ZW1zCgpgYGB7cn0KZGVtb2dfcmVsX2RmID0gbWFrZV9yZWxfZGYodGVzdF9kZW1vZywgdDJfZGYgPSByZXRlc3RfZGVtb2csIG1ldHJpY3M9YygnaWNjMi4xJykpCgpkZW1vZ19yZWxfZGYgJT4lCiAgc2VsZWN0KGR2LCBpY2MyLjEpICU+JQogIGFycmFuZ2UoLWljYzIuMSkKYGBgCgpQbG90dGluZyBwb2ludCBlc3RpbWF0ZXMgb2YgcmVsaWFiaWxpdHkgZm9yIGRlbW9ncmFwaGljIGl0ZW1zIGNvbG9yaW5nIHRob3NlIHRoYXQgaGF2ZSBhIHRpbWUgbGltaXQgZGFya2VyIGluIHRoZSBoaXN0b2dyYW0uCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0aW1lZF9kZW1vZ3MgPC0gYygiRG9jdG9yVmlzaXRzTGFzdE1vbnRoIiwiRGF5c0hhbGZMYXN0TW9udGgiLCJXb3J0aGxlc3MiLCJEYXlzUGh5c2ljYWxIZWFsdGhGZWVsaW5ncyIsIkRlcHJlc3NlZCIsIkV2ZXJ5dGhpbmdJc0VmZm9ydCIsIkhvcGVsZXNzIiwiUmVzdGxlc3NGaWRnZXR5IiwiTmVydm91cyIsIkRheXNMb3N0TGFzdE1vbnRoIiwiTGFzdDMwRGF5c1VzdWFsIikKCmRlbW9nX3JlbF9kZiAlPiUKICBtdXRhdGUodGltZWQgPSBpZmVsc2UoZHYgJWluJSB0aW1lZF9kZW1vZ3MsIDEsIDApKSAlPiUKICBnZ3Bsb3QoYWVzKGljYzIuMSwgZmlsbCA9IGZhY3Rvcih0aW1lZCkpKSsKICBnZW9tX2hpc3RvZ3JhbShwb3NpdGlvbiA9ICJpZGVudGl0eSIsIGFscGhhID0gMC43LCBjb2xvciA9IE5BKSsKICB4bGFiKCJpY2MyLjEiKSsKICB5bGFiKCJDb3VudCIpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImdyZXkiLCAiZ3JleTI1IikpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpybSh0ZXN0X2RlbW9nLCByZXRlc3RfZGVtb2csIGRlbW9nX3JlbF9kZiwgdGltZWRfZGVtb2dzKQpgYGAKCiMjIyBFZmZlY3Qgb2YgZGVsYXlzIGJldHdlZW4gdGhlIHR3byBtZWFzdXJlbWVudHMKCkluc3RlYWQgb2YgdGhlIHN1bW1hcnkgbWV0cmljIGxpa2UgdGhlIHJldGVzdCByZWxpYWJpbGl0eSBlc3RpbWF0ZSBmb3IgZWFjaCBtZWFzdXJlIHdlIGNhbiBjaGVjayB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlIHNjb3JlIGRpc3RyaWJ1dGlvbiBmb3IgZWFjaCBtZWFzdXJlIGRlcGVuZHMgb24gdGhlIGRlbGF5IGJldHdlZW4gdGhlIHR3byBtZWFzdXJlbWVudHMuIFNpbmNlIHRoZSBkaWZmZXJlbmNlIHNjb3JlIGRpc3RyaWJ1dGlvbiBpcyBhdCBzdWJqZWN0IGxldmVsIHdlIGNhbiBjaGVjayB3aGV0aGVyIHRoZSBvcmRlciBvZiBzdWJqZWN0cyBpbiB0aGlzIGRpc3RyaWJ1dGlvbiBkZXBlbmRzIG9uIHRoZWlyIG9yZGVyIGluIHRoZSBkaXN0cmlidXRpb24gb2YgZGF5cyBiZXR3ZWVuIGNvbXBsZXRpbmcgdGhlIHR3byB0ZXN0cy4gIAoKVG8gY2hlY2sgdGhpcyB3ZSBtYWtlIGRhdGEgZnJhbWUgd2l0aCBkaWZmZXJlbmNlIGJldHdlZW4gdHdvIHNjb3JlcyBmb3IgZWFjaCBtZWFzdXJlIGZvciBlYWNoIHN1YmplY3QuIFNpbmNlIHRoZSBzY29yZXMgZm9yIGRpZmZlcmVudCBtZWFzdXJlcyBhcmUgb24gZGlmZmVyZW50IHNjYWxlcyBmb3IgY29tcGFyYWJpbGl0eSB0aGUgZGlmZmVyZW5jZSBzY29yZXMgYXJlIG5vcm1hbGl6ZWQgKGllIGRlbWVhbmVkIGFuZCBkaXZpZGllZCBieSB0aGUgc2Qgb2YgdGhlIGRpZmZlcmVuY2Ugc2NvcmUgZGlzdHJpYnV0aW9uLikgTm90ZSB0aGF0IHRoZSB2YXJpYW5jZSBvZiB0aGUgZGlmZmVyZW5jZSBzY29yZSBkaXN0cmlidXRpb24gYWNjb3VudHMgZm9yIHRoZSB2YXJpYW5jZSBpbiBib3RoIHRpbWUgcG9pbnRzIGJ5IHN1bW1pbmcgdGhlbS4gTm9ybWFsaXphdGlvbiBlcXVhdGVzIHRoZSBtZWFucyBvZiBlYWNoIGRpZmZlcmVuY2Ugc2NvcmUgZGlzdHJpYnV0aW9uIHRvIDAgd2hpY2ggd291bGQgbWFzayBhbnkgbWVhbmluZ2Z1bCBjaGFuZ2UgYmV0d2VlbiB0aGUgdHdvIHRpbWUgcG9pbnRzIGJ1dCB0aGUgYW5hbHlzaXMgaGVyZSBkb2VzIG5vdCBpbnRlcnByZXQgdGhlIG1lYW4gb2YgdGhlIGRpZmZlcmVuY2Ugc2NvcmUgZGlzdHJpYnV0aW9ucyBidXQgaXMgaW50ZXJlc3RlZCBpbiBpdHMgcmVsYXRpb24gdG8gdGhlIGRheXMgYmV0d2VlbiBjb21wbGV0aW9uLiBXZSBjaGVjayBpZiB0aGUgdmFyaWFibGVzIHNob3cgc3lzdGVtYXRpYyBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSB0d28gcG9pbnRzIGxhdGVyLiAgCgpIZXJlIHdlIGNoZWNrIGlmIHRoZSBkaWZmZXJlbmNlIGlzIGxhcmdlciB0aGUgbG9uZ2VyIHRoZSBkZWxheS4gIAoKYGBge3Igd2FybmluZz1GQUxTRX0KbnVtZXJpY19jb2xzID0gZ2V0X251bWVyaWNfY29scyh0ZXN0X2RhdGEpCgp0MV8yX2RpZmZlcmVuY2UgPSBkYXRhLmZyYW1lKCkKCmZvcihpIGluIDE6bGVuZ3RoKG51bWVyaWNfY29scykpewogIHRtcCA9IG1hdGNoX3QxX3QyKG51bWVyaWNfY29sc1tpXSx0MV9kZj10ZXN0X2RhdGEgLHQyX2RmPXJldGVzdF9kYXRhLGZvcm1hdD0nd2lkZScpCiAgdG1wID0gdG1wICU+JQogIG11dGF0ZShkaWZmZXJlbmNlID0gc2NhbGUoYDJgIC0gYDFgKSkKICB0MV8yX2RpZmZlcmVuY2UgPSByYmluZCh0MV8yX2RpZmZlcmVuY2UsIHRtcCkKfQoKdDFfMl9kaWZmZXJlbmNlJGRpZmZlcmVuY2UgPSBhcy5kYXRhLmZyYW1lKHQxXzJfZGlmZmVyZW5jZSRkaWZmZXJlbmNlKSRWMQoKdDFfMl9kaWZmZXJlbmNlID0gdDFfMl9kaWZmZXJlbmNlICU+JSBzZXBhcmF0ZShkdiwgYygidGFzayIsICJkdjIiKSwgc2VwPSJcXC4iLCByZW1vdmU9RkFMU0UpCmBgYAoKYGBge3IgZWNobz1GQUxTRX0Kcm0odG1wLCBpLCBudW1lcmljX2NvbHMpCmBgYAoKQWRkIGNvbXBsZXRpb24gZGF0ZXMgdG8gdGhpcyBkYXRhIGZyYW1lLgoKYGBge3Igd2FybmluZz1GQUxTRX0KdDFfMl9kaWZmZXJlbmNlID0gbWVyZ2UodDFfMl9kaWZmZXJlbmNlLCB0YXNrX2NvbXBfdGltZXNbLGMoJ3N1Yl9pZCcsICd0YXNrJywnZGF5c19idHcnKV0sIGJ5PWMoJ3N1Yl9pZCcsICd0YXNrJykpCmBgYAoKYGBge3IgZWNobz1GQUxTRX0Kcm0odGFza19jb21wX3RpbWVzKQpgYGAKCldoYXQgZG9lcyB0aGUgZGlzdHJpYnV0aW9uIG9mIGRpZmZlcmVuY2VzIGxvb2sgbGlrZTogVGhlIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbmNlcyBiZXR3ZWVuIHR3byB0aW1lIHBvaW50cyBmb3IgZWFjaCBtZWFzdXJlCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0MV8yX2RpZmZlcmVuY2UgJT4lCiAgZ2dwbG90KGFlcyhkaWZmZXJlbmNlLCBhbHBoYT1kdikpKwogIGdlb21faGlzdG9ncmFtKHBvc2l0aW9uPSdpZGVudGl0eScpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykKYGBgCgpIb3cgZG8gdGhlIGRpZmZlcmVuY2Ugc2NvcmUgZGlzdHJpYnV0aW9ucyBsb29rIGxpa2Ugd2l0aCByZXNwZWN0IHRvIHRoZSBkYXlzIGJldHdlZW4gY29tcGxldGlvbj8KCmBgYHtyfQp0MV8yX2RpZmZlcmVuY2UgJT4lCiAgZ2dwbG90KCkrCiAgZ2VvbV9zbW9vdGgoYWVzKGFzLm51bWVyaWMoZGF5c19idHcpLCBhYnMoZGlmZmVyZW5jZSksIGdyb3VwPWZhY3RvcihkdikpLCBtZXRob2Q9J2xtJywgc2U9RkFMU0UsIGNvbG9yID0gJ2dyZXknLCBhbHBoYSA9IDAuNSkrCiAgZ2VvbV9zbW9vdGgoYWVzKGFzLm51bWVyaWMoZGF5c19idHcpLCBhYnMoZGlmZmVyZW5jZSkpLCBtZXRob2Q9J2xtJywgY29sb3IgPSAiYmxhY2siLCBzZT1GQUxTRSkrCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSsKICB4bGFiKCdEYXlzIGJldHdlZW4gY29tcGxldGlvbicpKwogIHlsYWIoJ1NjYWxlZCBkaWZmZXJlbmNlIHNjb3JlJykKYGBgCgpUbyB0ZXN0IGlmIHRoZSBzbG9wZSBvZiB0aGUgYmxhY2sgaXMgc2lnbmlmaWNhbnQgd2Ugd291bGQgcnVuIGEgbWl4ZWQgZWZmZWN0cyBtb2RlbCB3aXRoIGEgZml4ZWQgZWZmZWN0IGZvciBkYXlzIGJldHdlZW4gY29tcGxldGlvbiwgcmFuZG9tIHNsb3BlIGZvciBlYWNoIGR2IGRlcGVuZGluZyBvbiB0aGUgZGF5cyBiZXR3ZWVuIGFuZCByYW5kb20gaW50ZXJjZXB0IGZvciBlYWNoIGR2LiAgCgpCZWZvcmUgSSB3YXMgdXNpbmcgc3ViamVjdHMgYXMgYSByYW5kb20gZWZmZWN0IGJ1dCBkYXlzIGJldHdlZW4gdGhlIHR3byB0aW1lIHBvaW50cyBmb3IgZWFjaCBtZWFzdXJlIGRlcGVuZHMgb24gc3ViaiBpZC4gV2hhdCB2YXJpZXMgcmFuZG9tbHkgaXMgd2hpY2ggZHYgd2UgYXJlIGxvb2tpbmcgZm9yIGl0cyBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW5jZXMgaW4gcmVsYXRpb24gdG8gdGhlIGRheXMgYmV0d2VlbiB0aGUgdGltZSBwb2ludHMuIFNvIEkgY2hhbmdlZCB0aGUgbW9kZWwgdG8gaGF2ZSBmaXhlZCBlZmZlY3QgZm9yIHRoZSBkYXlzIGJldHdlZW4sIGEgcmFuZG9tIHNsb3BlIGZvciAoZGVwZW5kZW50IHZhcmlhYmxlcyBjYW4gYmUgZGlmZmVyZW50aWFsbHkgc2Vuc2l0aXZlIHRvIHRoIGVmZmVjdCBvZiBkYXlzIGJldHdlZW4pIGFuZCBhIHJhbmRvbSBpbnRlcmNlcHQgZm9yIGRlcGVuZGVudCB2YXJpYWJsZS4gIAoKU2lnbmlmaWNhbnQgZml4ZWQgZWZmZWN0IHN1Z2dlc3RzIHRoYXQgb24gYXZlcmFnZSB0aGUgbG9uZ2VyIHRoZSBkZWxheSB0aGUgc21hbGxlciB0aGUgZGlmZmVyZW5jZS4gIAoKYGBge3J9CnN1bW1hcnkobG1lclRlc3Q6OmxtZXIoYWJzKGRpZmZlcmVuY2UpIH4gc2NhbGUoZGF5c19idHcpKyhzY2FsZShkYXlzX2J0dykgfCBkdiksIGRhdGE9dDFfMl9kaWZmZXJlbmNlKSkKCiMgc3VtbWFyeSh0bXAgPC0gTUNNQ2dsbW0oYWJzKGRpZmZlcmVuY2UpIH4gc2NhbGUoZGF5c19idHcpLCByYW5kb20gPSB+dXMoc2NhbGUoZGF5c19idHcpKTpkdiwgZGF0YT10MV8yX2RpZmZlcmVuY2UsIHZlcmJvc2U9RkFMU0UpKQpgYGAKCkJ1dCBpZiBJIGp1c3QgcnVuIG9uZSBtaXhlZCBlZmZlY3RzIG1vZGVsIHRoZW4gd2UgZG9uJ3QgZ2V0IGEgc2Vuc2Ugb2YgdGhlIHNpbXBsZSBlZmZlY3RzIChob3cgbWFueSBvZiB0aGUgdmFyaWFibGVzIHRoaXMgZWZmZWN0IG9mIHRoZSBkYXlzIGJldHdlZW4gaXMgc2lnbmlmaWNhbnQgYW5kIGluIHdoaWNoIGRpcmVjdGlvbikuIEkgY2FuIHJ1biBpdCBzZXBhcmF0ZWx5IGZvciBlYWNoIGR2IHRvIHNlZSBpZiBhbGwgZGlmZmVyZW5jZSBzY29yZSBkaXN0cmlidXRpb25zIGFyZSBhZmZlY3RlZCB0aGUgc2FtZSB3YXkgZGVwZW5kaW5nIG9uIHRoZSBkYXlzIGJldHdlZW4gY29tcGxldGlvbi4gQnV0IHNpbmNlIHdlIGFyZSBydW5uaW5nIHNvIG1hbnkgdGVzdHMgd2UgbmVlZCB0byBjb3JyZWN0IGZvciBtdWx0aXBsZSBjb21wYXJpc29ucy4gSG93IG1hbnkgb2YgdGhlc2UgdGVzdHMgYXJlIHNpZ25pZmljYW50IEZEUiBjb3JyZWN0aW5nPyBOb25lLgoKYGBge3J9CmdldF9kZWxheV9lZmZlY3QgPSBmdW5jdGlvbihkZil7CiAgbW9kID0gbG0oYWJzKGRpZmZlcmVuY2UpIH4gc2NhbGUoZGF5c19idHcpLCBkYXRhID0gZGYpCiAgb3V0ID0gZGF0YS5mcmFtZShlc3RpbWF0ZT1jb2VmKHN1bW1hcnkobW9kKSlbInNjYWxlKGRheXNfYnR3KSIsIkVzdGltYXRlIl0sIHB2YWw9Y29lZihzdW1tYXJ5KG1vZCkpWyJzY2FsZShkYXlzX2J0dykiLCJQcig+fHR8KSJdKQogIHJldHVybihvdXQpCn0KCmRheXNfZWZmZWN0ICA9IHQxXzJfZGlmZmVyZW5jZSAlPiUKICBncm91cF9ieShkdikgJT4lCiAgZG8oZ2V0X2RlbGF5X2VmZmVjdCguKSkKCiNDb3JyZWN0IHAtdmFsdWVzIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucwpzdW0ocC5hZGp1c3QoZGF5c19lZmZlY3QkcHZhbCwgbWV0aG9kID0gImZkciIpIDwgMC4wNSkKYGBgCgpDb25jbHVzaW9uOiBUaGUgYXZlcmFnZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHNjb3JlcyBvZiBhIG1lYXN1cmUgZG9lc24ndCBjaGFuZ2Ugd2l0aCB0aGUgaW5jcmVhc2VkIGRlbGF5LgoKIyMjIE92ZXJsYXBwaW5nIHN1cnZleSBxdWVzdGlvbnMKClNvbWUgc3VydmV5cyBoYXZlIG92ZXJsYXBwaW5nIHF1ZXN0aW9ucy4gRG8gdGhlc2UgY29ycmVsYXRlIHdpdGhpbiBhbmQgYWNyb3NzIHNlc3Npb25zPwoKRmlyc3QgZGV0ZXJtaW5lIHRoZSBvdmVybGFwcGluZyBxdWVzdGlvbnMuCgpgYGB7cn0KZHVwbGljYXRlX2l0ZW1zCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KI3N1cnZleXMgdG8gcmVhZCBpbgpleHRyYWN0X2l0ZW1zID0gYygnd29ya2VyJyx1bmlxdWUod2l0aChkdXBsaWNhdGVfaXRlbXMsIGMoaXRlbTFfSUQsIGl0ZW0yX0lEKSkpKQoKI2NvcnJlbGF0aW9ucyB0byBjb21wdXRlOgojaXRlbTFfdDEgLSBpdGVtMl90MSwKI2l0ZW0xX3QyIC0gaXRlbTJfdDIsCiNpdGVtMV90MSAtIGl0ZW0yX3QyLAojaXRlbTFfdDIgLSBpdGVtMl90MQoKZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDEgPSBkdXBsaWNhdGVfaXRlbXNfZGF0YV90MSAlPiUKICBmaWx0ZXIod29ya2VyICVpbiUgZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDIkd29ya2VyKSAlPiUKICBzZWxlY3QoZXh0cmFjdF9pdGVtcykKCmR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyPWR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyICU+JQogIGZpbHRlcih3b3JrZXIgJWluJSBkdXBsaWNhdGVfaXRlbXNfZGF0YV90MSR3b3JrZXIpICU+JQogIHNlbGVjdChleHRyYWN0X2l0ZW1zKQoKZHVwbGljYXRlX2l0ZW1zID0gZHVwbGljYXRlX2l0ZW1zICU+JQogIG11dGF0ZSh0MV90MV9jb3IgPSBOQSwKICAgICAgICAgdDJfdDJfY29yID0gTkEsCiAgICAgICAgIHQxX3QyX2NvciA9IE5BLAogICAgICAgICB0Ml90MV9jb3IgPSBOQSwKICAgICAgICAgdDFfdDFfcG9seWNvciA9IE5BLAogICAgICAgICB0Ml90Ml9wb2x5Y29yID0gTkEsCiAgICAgICAgIHQxX3QyX3BvbHljb3IgPSBOQSwKICAgICAgICAgdDJfdDFfcG9seWNvciA9IE5BKQoKZm9yKGkgaW4gMTpucm93KGR1cGxpY2F0ZV9pdGVtcykpewogIGR1cGxpY2F0ZV9pdGVtcyR0MV90MV9jb3JbaV0gPSBhYnMoY29yKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QxWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMV9JRFtpXSldLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDFbLGMoZHVwbGljYXRlX2l0ZW1zJGl0ZW0yX0lEW2ldKV0pKQoKICBkdXBsaWNhdGVfaXRlbXMkdDJfdDJfY29yW2ldID0gYWJzKGNvcihkdXBsaWNhdGVfaXRlbXNfZGF0YV90MlssYyhkdXBsaWNhdGVfaXRlbXMkaXRlbTFfSURbaV0pXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMl9JRFtpXSldKSkKCiAgZHVwbGljYXRlX2l0ZW1zJHQxX3QyX2NvcltpXSA9IGFicyhjb3IoZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDFbLGMoZHVwbGljYXRlX2l0ZW1zJGl0ZW0xX0lEW2ldKV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkdXBsaWNhdGVfaXRlbXNfZGF0YV90MlssYyhkdXBsaWNhdGVfaXRlbXMkaXRlbTJfSURbaV0pXSkpCgogIGR1cGxpY2F0ZV9pdGVtcyR0Ml90MV9jb3JbaV0gPSBhYnMoY29yKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMV9JRFtpXSldLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDFbLGMoZHVwbGljYXRlX2l0ZW1zJGl0ZW0yX0lEW2ldKV0pKQoKICBkdXBsaWNhdGVfaXRlbXMkdDFfdDFfcG9seWNvcltpXSA9IGFicyhwb2x5Y2hvcmljKGRhdGEuZnJhbWUoZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDFbLGMoZHVwbGljYXRlX2l0ZW1zJGl0ZW0xX0lEW2ldKV0sCiAgICAgICAgICAgICAgICAgICAgICBkdXBsaWNhdGVfaXRlbXNfZGF0YV90MVssYyhkdXBsaWNhdGVfaXRlbXMkaXRlbTJfSURbaV0pXSkpJHJob1syXSkKCiAgZHVwbGljYXRlX2l0ZW1zJHQyX3QyX3BvbHljb3JbaV0gPSBhYnMocG9seWNob3JpYyhkYXRhLmZyYW1lKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMV9JRFtpXSldLAogICAgICAgICAgICAgICAgICAgICAgZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDJbLGMoZHVwbGljYXRlX2l0ZW1zJGl0ZW0yX0lEW2ldKV0pKSRyaG9bMl0pCgogIGR1cGxpY2F0ZV9pdGVtcyR0MV90Ml9wb2x5Y29yW2ldID0gYWJzKHBvbHljaG9yaWMoZGF0YS5mcmFtZShkdXBsaWNhdGVfaXRlbXNfZGF0YV90MVssYyhkdXBsaWNhdGVfaXRlbXMkaXRlbTFfSURbaV0pXSwKICAgICAgICAgICAgICAgICAgICAgIGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMl9JRFtpXSldKSkkcmhvWzJdKQoKICBkdXBsaWNhdGVfaXRlbXMkdDJfdDFfcG9seWNvcltpXSA9IGFicyhwb2x5Y2hvcmljKGRhdGEuZnJhbWUoZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDJbLGMoZHVwbGljYXRlX2l0ZW1zJGl0ZW0xX0lEW2ldKV0sCiAgICAgICAgICAgICAgICAgICAgICBkdXBsaWNhdGVfaXRlbXNfZGF0YV90MVssYyhkdXBsaWNhdGVfaXRlbXMkaXRlbTJfSURbaV0pXSkpJHJob1syXSkKfQoKZm9yKGkgaW4gMTpucm93KGR1cGxpY2F0ZV9pdGVtcykpewogIGR1cGxpY2F0ZV9pdGVtcyR0MV90MV9jb3JbaV0gPSBhYnMoY29yKHNjYWxlKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QxWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMV9JRFtpXSldKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QxWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMl9JRFtpXSldKSkpCgogIGR1cGxpY2F0ZV9pdGVtcyR0Ml90Ml9jb3JbaV0gPSBhYnMoY29yKHNjYWxlKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMV9JRFtpXSldKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMl9JRFtpXSldKSkpCgogIGR1cGxpY2F0ZV9pdGVtcyR0MV90Ml9jb3JbaV0gPSBhYnMoY29yKHNjYWxlKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QxWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMV9JRFtpXSldKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMl9JRFtpXSldKSkpCgogIGR1cGxpY2F0ZV9pdGVtcyR0Ml90MV9jb3JbaV0gPSBhYnMoY29yKHNjYWxlKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMV9JRFtpXSldKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QxWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMl9JRFtpXSldKSkpCgogIGR1cGxpY2F0ZV9pdGVtcyR0MV90MV9wb2x5Y29yW2ldID0gYWJzKHBvbHljaG9yaWMoZGF0YS5mcmFtZShkdXBsaWNhdGVfaXRlbXNfZGF0YV90MVssYyhkdXBsaWNhdGVfaXRlbXMkaXRlbTFfSURbaV0pXSwKICAgICAgICAgICAgICAgICAgICAgIGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QxWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMl9JRFtpXSldKSkkcmhvWzJdKQoKICBkdXBsaWNhdGVfaXRlbXMkdDJfdDJfcG9seWNvcltpXSA9IGFicyhwb2x5Y2hvcmljKGRhdGEuZnJhbWUoZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDJbLGMoZHVwbGljYXRlX2l0ZW1zJGl0ZW0xX0lEW2ldKV0sCiAgICAgICAgICAgICAgICAgICAgICBkdXBsaWNhdGVfaXRlbXNfZGF0YV90MlssYyhkdXBsaWNhdGVfaXRlbXMkaXRlbTJfSURbaV0pXSkpJHJob1syXSkKCiAgZHVwbGljYXRlX2l0ZW1zJHQxX3QyX3BvbHljb3JbaV0gPSBhYnMocG9seWNob3JpYyhkYXRhLmZyYW1lKGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QxWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMV9JRFtpXSldLAogICAgICAgICAgICAgICAgICAgICAgZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDJbLGMoZHVwbGljYXRlX2l0ZW1zJGl0ZW0yX0lEW2ldKV0pKSRyaG9bMl0pCgogIGR1cGxpY2F0ZV9pdGVtcyR0Ml90MV9wb2x5Y29yW2ldID0gYWJzKHBvbHljaG9yaWMoZGF0YS5mcmFtZShkdXBsaWNhdGVfaXRlbXNfZGF0YV90MlssYyhkdXBsaWNhdGVfaXRlbXMkaXRlbTFfSURbaV0pXSwKICAgICAgICAgICAgICAgICAgICAgIGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QxWyxjKGR1cGxpY2F0ZV9pdGVtcyRpdGVtMl9JRFtpXSldKSkkcmhvWzJdKQp9CgpkdXBsaWNhdGVfaXRlbXMgJT4lCiAgYXJyYW5nZSgtdDFfdDFfcG9seWNvciwgLXQyX3QyX3BvbHljb3IpCmBgYAoKYGBge3J9CiMgc3VtbWFyeShkdXBsaWNhdGVfaXRlbXMkdDFfdDFfY29yKQojIHN1bW1hcnkoZHVwbGljYXRlX2l0ZW1zJHQyX3QyX2NvcikKIyBzdW1tYXJ5KGR1cGxpY2F0ZV9pdGVtcyR0MV90Ml9jb3IpCiMgc3VtbWFyeShkdXBsaWNhdGVfaXRlbXMkdDJfdDFfY29yKQoKc3VtbWFyeShkdXBsaWNhdGVfaXRlbXMkdDFfdDFfcG9seWNvcikKc3VtbWFyeShkdXBsaWNhdGVfaXRlbXMkdDJfdDJfcG9seWNvcikKIyBzdW1tYXJ5KGR1cGxpY2F0ZV9pdGVtcyR0MV90Ml9wb2x5Y29yKQojIHN1bW1hcnkoZHVwbGljYXRlX2l0ZW1zJHQyX3QxX3BvbHljb3IpCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRX0KdG1wID0gZHVwbGljYXRlX2l0ZW1zICU+JQogIHNlbGVjdChzaW1pbGFyaXR5LCB0MV90MV9wb2x5Y29yLCB0Ml90Ml9wb2x5Y29yKSAlPiUKICBnYXRoZXIoa2V5LCB2YWx1ZSwgLXNpbWlsYXJpdHkpCgp0bXAgJT4lCiAgZ2dwbG90KGFlcyhzaW1pbGFyaXR5LCB2YWx1ZSwgY29sPWtleSkpKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLCBhbHBoYSA9IDAuMTUpKwogIHlsYWIoIlBvbHljaG9yaWMgY29ycmVsYXRpb24iKSsKICB4bGFiKCJMZXZlbnNodGVpbiBkaXN0YW5jZSIpKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKGJyZWFrcyA9IGMoInQxX3QxX3BvbHljb3IiLCAidDJfdDJfcG9seWNvciIpLAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlQxIGNvcnJlbGF0aW9ucyIsICJUMiBjb3JyZWxhdGlvbnMiKSwKICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gZWxlbWVudF9ibGFuaygpKSsKICB0aGVtZV9idygpCmBgYAoKCmBgYHtyfQpzdW1tYXJ5KGxtKHZhbHVlfmtleSpzY2FsZShzaW1pbGFyaXR5KSx0bXApKQpgYGAKCmBgYHtyIGV2YWw9RkFMU0UsIGVjaG89RkFMU0V9CiMgc3VtbWFyeShNQ01DZ2xtbSh2YWx1ZSB+IGtleSpzY2FsZShzaW1pbGFyaXR5KSwgZGF0YT10bXAsIG5pdHQgPSA1MDAwMCkpCmBgYAoKYGBge3IgZWNobz1GQUxTRX0Kcm0odG1wLCBjb21iLCB0MV8yX2RpZmZlcmVuY2UsIGR1cGxpY2F0ZV9pdGVtcywgZHVwbGljYXRlX2l0ZW1zX2RhdGFfdDEsIGR1cGxpY2F0ZV9pdGVtc19kYXRhX3QyLCBleHRyYWN0X2l0ZW1zKQpgYGAKCiMjIENvbXBhcmlzb24gdG8gcHJpb3IgbGl0ZXJhdHVyZQoKU3VtbWFyaXplIGJvb3RzdHJhcHBlZCByZXN1bHRzIGFuZCBtZXJnZSB0byBsaXQgcmV2aWV3IGRhdGEKCkhlcmUncyB3aGF0IG91ciBkYXRhIGxvb2tzIGxpa2U6ICg1ODMgZGF0YSBwb2ludHMgZm9yIDE3MSBtZWFzdXJlcykKCmBgYHtyfQpyZWxfY29tcApgYGAKCiMjIyBMaXQgcmV2aWV3IHJlc3VsdHMKCkRpc3RyaWJ1dGlvbiBvZiByZWxpYWJpbGl0aWVzLCBzYW1wbGUgc2l6ZXMgYW5kIGRlbGF5cyBpbiB0aGUgbGl0ZXJhdHVyZQoKYGBge3J9CnJlbF9jb21wICU+JQogIHNlbGVjdChkdiwgdGFzaywgcmV0ZXN0X3JlbGlhYmlsaXR5LCBzYW1wbGVfc2l6ZSwgZGF5cykgJT4lCiAgZmlsdGVyKGRheXMgPCAzNjAwKSAlPiUKICBnYXRoZXIoa2V5LCB2YWx1ZSwgLWR2LCAtdGFzaykgJT4lCiAgZ2dwbG90KGFlcyh2YWx1ZSwgZmlsbD10YXNrKSkrCiAgZ2VvbV9kZW5zaXR5KGFscGhhPTAuNSwgcG9zaXRpb249J2lkZW50aXR5JykrCiAgZmFjZXRfd3JhcCh+a2V5LCBzY2FsZXM9J2ZyZWUnKSsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKYGBge3J9CnN1bW1hcnkocmVsX2NvbXAkc2FtcGxlX3NpemVbcmVsX2NvbXAkdGFzayA9PSAic3VydmV5Il0pCnN1bW1hcnkocmVsX2NvbXAkc2FtcGxlX3NpemVbcmVsX2NvbXAkdGFzayA9PSAidGFzayJdKQpgYGAKCmBgYHtyfQpyZWxfY29tcCAlPiUKICBncm91cF9ieSh0YXNrKSAlPiUKICBzdW1tYXJpc2UobWVhbl9zYW1wbGVfc2l6ZSA9IG1lYW4oc2FtcGxlX3NpemUpLAogICAgICAgICAgICBzZW1fc2FtcGxlX3NpemUgPSBzZW0oc2FtcGxlX3NpemUpKSAlPiUKICBnZ3Bsb3QoYWVzKHRhc2ssbWVhbl9zYW1wbGVfc2l6ZSxjb2w9dGFzaykpKwogIGdlb21fcG9pbnQoc2l6ZT01KSsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPW1lYW5fc2FtcGxlX3NpemUtc2VtX3NhbXBsZV9zaXplLCB5bWF4PW1lYW5fc2FtcGxlX3NpemUrc2VtX3NhbXBsZV9zaXplKSwgd2lkdGggPSAwLCBzaXplPTIpKwogIHhsYWIoIiIpKwogIHlsYWIoIlNhbXBsZSBzaXplIikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSkKYGBgCgpUaGUgbGl0ZXJhdHVyZSBoYXMgc21hbGxlciBzaXplZCBzYW1wbGVzIGZvciB0YXNrIG1lYXN1cmVzIGNvbXBhcmVkIHRvIHN1cnZleSBtZWFzdXJlcyB0aGF0IHJlcG9ydCByZXRlc3QgcmVsaWFiaWxpdHkuCgpgYGB7cn0KIyBzdW1tYXJ5KGxtKHNhbXBsZV9zaXplIH4gdGFzayxyZWxfY29tcCkpCnN1bW1hcnkobTEgPC0gTUNNQ2dsbW0oc2FtcGxlX3NpemUgfiB0YXNrLCBkYXRhPXJlbF9jb21wLCB2ZXJib3NlPUZBTFNFKSkKYGBgCgpXaGF0IHByZWRpY3RzIHJldGVzdCByZWxpYWJpbGl0eSBpbiB0aGUgbGl0ZXJhdHVyZT8KVGFzaywgc2FtcGxlIHNpemUsIGRheXMKCmBgYHtyfQptb2QxID0gbG1lcihyZXRlc3RfcmVsaWFiaWxpdHkgfiB0YXNrICsgKDF8ZHYpLCByZWxfY29tcCkKbW9kMiA9IGxtZXIocmV0ZXN0X3JlbGlhYmlsaXR5IH4gdGFzayArIHNhbXBsZV9zaXplICsgKDF8ZHYpLCByZWxfY29tcCkKCmFub3ZhKG1vZDEsIG1vZDIpCmBgYAoKYGBge3J9Cm1vZDMgPSBsbWVyKHJldGVzdF9yZWxpYWJpbGl0eSB+IHRhc2sgKyBzYW1wbGVfc2l6ZSArIGRheXMrICgxfGR2KSwgcmVsX2NvbXApCgphbm92YShtb2QyLCBtb2QzKQpgYGAKCmBgYHtyfQojc3VtbWFyeShtb2QyKQpzdW1tYXJ5KE1DTUNnbG1tKHJldGVzdF9yZWxpYWJpbGl0eSB+IHRhc2sgKyBzYW1wbGVfc2l6ZSwgcmFuZG9tID0gfiBkdiwgZGF0YSA9IHJlbF9jb21wLCB2ZXJib3NlPUZBTFNFKSkKYGBgCgpgYGB7cn0KcmVsX2NvbXAgJT4lCiAgZ3JvdXBfYnkodGFzaykgJT4lCiAgc3VtbWFyaXNlKG1lYW5fcnIgPSBtZWFuKHJldGVzdF9yZWxpYWJpbGl0eSkpCmBgYAoKQXJlIHRoZSByZXNpZHVhbHMgb2YgdGhpcyBtb2RlbCBoZXRlcm9zY2VkYXN0aWM/IFllcyB0aGUgcmVzaWR1YWxzIGRvIG5vdCBkZXBlbmQgb24gdGhlIHByZWRpY3Rvci4KCmBgYHtyfQp0bXAgPSBkYXRhLmZyYW1lKHJlbF9jb21wJHNhbXBsZV9zaXplLCByZXNpZChtb2QyKSkgJT4lCiAgcmVuYW1lKHNhbXBsZV9zaXplID0gcmVsX2NvbXAuc2FtcGxlX3NpemUsIHJlc2lkID0gcmVzaWQubW9kMi4pCgp0bXAgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGVfc2l6ZSwgcmVzaWQpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikKYGBgCgoKYGBge3J9CnN1bW1hcnkobG0ocmVzaWQgfiBzYW1wbGVfc2l6ZSwgdG1wKSkKYGBgCgpUYXNrcyBoYXZlIHNpZ25pZmljYW50bHkgbG93ZXIgcmVsaWFiaWxpdHkgYW5kIHJlbGlhYmlsaXR5IGRlY3JlYXNlcyB3aXRoIGluY3JlYXNpbmcgc2FtcGxlIHNpemUuCgpgYGB7cn0KcmVsX2NvbXAgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGVfc2l6ZSwgcmV0ZXN0X3JlbGlhYmlsaXR5LCBjb2xvcj10YXNrKSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSdsbScpKwogICMgZ2VvbV9wb2ludChhbHBoYSA9IDAuMikrCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpKwogIHhsYWIoIlNhbXBsZSBTaXplIikrCiAgeWxhYigiUmV0ZXN0IHJlbGlhYmlsaXR5IikrCiAgeWxpbSgtMC4xNSwgMSkKYGBgCgpIaWdobGlnaHRpbmcgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBzdXJ2ZXkgYW5kIHRhc2sgcmVsaWFiaWxpdHkgZm9yIGNvbXBhcmFiaWxpdHkgdG8gb3VyIHJlc3VsdHMuCgpgYGB7cn0KcmVsX2NvbXAgJT4lCiAgZ2dwbG90KGFlcyh0YXNrLCByZXRlc3RfcmVsaWFiaWxpdHksIGZpbGwgPSB0YXNrKSkrCiAgZ2VvbV9ib3hwbG90KCkrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSkrCiAgeGxhYigiIikrCiAgeWxhYigiTWVhbiBpY2MyLjEiKSsKICB5bGltKC0wLjQsMSkKYGBgCgpOb3RlOiBXZSBjaGVja2VkIHdoZXRoZXIgb3VyIHJlc3VsdHMgZGl2ZXJnZSBtb3N0IGZyb20gc3R1ZGllcyB3aXRoIHNtYWxsZXIgc2FtcGxlIHNpemVzLiBTcXVhcmUgZGlmZmVyZW5jZSBiZXR3ZWVuIG91ciBtZWFuIGVzdGltYXRlIGFuZCB0aGUgcmVsaWFiaWxpdHkgZnJvbSB0aGUgbGl0ZXJhdHVyZSBkZWNyZWFzZXMgZXhwb25lbnRpYWxseSB3aXRoIHNhbXBsZSBzaXplLiBUaGUgc21hbGxlciB0aGUgc2FtcGxlIHNpemUgaW4gdGhlIGxpdGVyYXR1cmUgdGhlIG1vcmUgdGhlIHJlbGlhYmlsaXR5IGVzdGltYXRlIGRpZmZlcnMgZnJvbSBvdXIgcmVzdWx0cy4gQnV0IHRoaXMgd2FzIGEgd2VhayByZXN1bHQgYmVjYXVzZSBtb3N0IG9mIHRoZSBzdHVkaWVzIGluIHRoZSBsaXRlcmF0dXJlIGhhdmUgc21hbGxlciBzYW1wbGUgc2l6ZXMgYW5kIHlvdSBzZWUgYm90aCBzbWFsbCBhbmQgbGFyZ2UgZGV2aWF0aW9ucyBmb3IgdGhlc2Ugc3R1ZGllcyAodGhlc2Ugd2VyZSBub3Qgc2lnbmlmaWNhbnQgZWl0aGVyKS4KCiMjIyBDb3JyZWxhdGlvbiB3aXRoIG91ciByZXN1bHRzCgpDb3JyZWxhdGlvbiBiZXR3ZWVuIG91ciBtZWFuIGVzdGltYXRlcyBmcm9tIGJvb3RzdHJhcHBlZCBzYW1wbGVzIGFuZCB0aGUgbGl0ZXJhdHVyZSByZXZpZXcgZm9yIHRhc2sgdmFyaWFibGVzCgpgYGB7ciBldmFsPUZBTFNFfQpuX2RmID0gcmVsX2NvbXAgJT4lCiAgZ3JvdXBfYnkoZHYpICU+JQogIHRhbGx5KCkKCmxpdF9lbXBfY29yID0gZnVuY3Rpb24oKXsKCiAgYm9vdF9jb21wID0gZGF0YS5mcmFtZSgpCgogIGZvcihpIGluIDE6bGVuZ3RoKHVuaXF1ZShyZWxfY29tcCRkdikpICl7CiAgICBjdXJfZHYgPSB1bmlxdWUocmVsX2NvbXAkZHYpW2ldCiAgICBuID0gbl9kZiRuW25fZGYkZHYgPT0gY3VyX2R2XQogICAgc2FtcGxlX2RmID0gYm9vdF9kZiAlPiUgZmlsdGVyKGR2ID09IGN1cl9kdikKICAgIHRtcCA9IHNhbXBsZV9uKHNhbXBsZV9kZiwgbikKICAgIGJvb3RfY29tcCA9IHJiaW5kKGJvb3RfY29tcCwgdG1wKQogIH0gIAoKICBybShjdXJfZHYsIG4sIHNhbXBsZV9kZiwgdG1wKQoKICAjY2hlY2sgaWYgY2JpbmQgaXMgb2sKICAjIHN1bShib290X2NvbXAkZHYgPT0gcmVsX2NvbXAkZHYpCiAgI2NiaW5kaW5nIHBlYXJzb24gYmVjYXVzZSB0aGF0IGlzIHRoZSBtb3N0IGNvbW1vbiBtZXRyaWMgaW4gdGhlIGxpdAogIHJlbF9jb21wID0gY2JpbmQocmVsX2NvbXAsIGJvb3RfY29tcCRwZWFyc29uKQogICNyZW5hbWUgbmV3IGNvbHVtbgogIG5hbWVzKHJlbF9jb21wKVt3aGljaChuYW1lcyhyZWxfY29tcCkgPT0gImJvb3RfY29tcCRwZWFyc29uIildID0gInBlYXJzb24iCgogIG91dCA9IGRhdGEuZnJhbWUodGFzayA9IE5BLCBzdXJ2ZXkgPSBOQSkKCiAgb3V0JHRhc2sgPSB3aXRoKHJlbF9jb21wICU+JSBmaWx0ZXIodGFzayA9PSAidGFzayIpLCBjb3IocGVhcnNvbiwgcmV0ZXN0X3JlbGlhYmlsaXR5KSkKCiAgb3V0JHN1cnZleSA9IHdpdGgocmVsX2NvbXAgJT4lIGZpbHRlcih0YXNrID09ICJzdXJ2ZXkiKSwgY29yKHBlYXJzb24sIHJldGVzdF9yZWxpYWJpbGl0eSkpCgogIHJlbF9jb21wID0gcmVsX2NvbXBbLC0xNl0KCiAgcmV0dXJuKG91dCkKfQoKbGl0X2VtcF9jb3Jfb3V0ID0gcGx5cjo6cmRwbHkoMTAwLCBsaXRfZW1wX2NvcikKCndyaXRlLmNzdihsaXRfZW1wX2Nvcl9vdXQsJy9Vc2Vycy96ZXluZXBlbmthdmkvRHJvcGJveC9Qb2xkcmFja0xhYi9TUk9fUmV0ZXN0X0FuYWx5c2VzL291dHB1dC90YWJsZXMvbGl0X2VtcF9jb3Jfb3V0LmNzdicpCmBgYAoKCmBgYHtyIGVjaG89RkFMU0V9CmxpdF9lbXBfY29yX291dCA9IHJlYWQuY3N2KCcvVXNlcnMvemV5bmVwZW5rYXZpL0Ryb3Bib3gvUG9sZHJhY2tMYWIvU1JPX1JldGVzdF9BbmFseXNlcy9vdXRwdXQvdGFibGVzL2xpdF9lbXBfY29yX291dC5jc3YnKQoKc3VtbWFyeShsaXRfZW1wX2Nvcl9vdXQpCmBgYAoKIyMjIE5vaXNlIGNlaWxpbmcKCk1vZGVsIGNvbXBhcmlzb25zIGJ1aWxkaW5nIG1vZGVsIHRvIHByZWRpY3QgdGhlIHJlbGlhYmlsaXRpZXMgaW4gdGhlIGxpdGVyYXR1cmUgZnJvbSBhIHNhbXBsZSBmcm9tIG91ciByZXN1bHRzIHZlcnN1cyBhIHNhbXBsZSBmb3JtIHRoZSBsaXRlcmF0dXJlLgoKc2FtcGxlIG9uZSByb3cgcGVyIG1lYXN1cmUgb3V0IG9mIGxpdCByZXZpZXcKcl4yIG9mIHJldGVzdF9yZWxpYWJpbGl0eSB+IHNhbXBsZWRfcmVsaWFiaWxpdHkgdnMuCnJeMiBvZiByZXRlc3RfcmVsaWFiaWxpdHkgfiBtZWFuX2ljYzIuMQoKY29lZiBvZiByZXRlc3RfcmVsaWFiaWxpdHkgfiBzYW1wbGVkX3JlbGlhYmlsaXR5IHZzLgpjb2VmIG9mIHJldGVzdF9yZWxpYWJpbGl0eSB+IG1lYW5faWNjMi4xCgpgYGB7ciBldmFsPUZBTFNFfQpjb21wX2xpdF9wcmVkIDwtIGZ1bmN0aW9uKGRmKXsKCiAgc2FtcGxlX2Zyb21fZHYgPC0gZnVuY3Rpb24oZGYpewogICAgaWYobnJvdyhkZik+MSl7CiAgICAgIHJvd19udW0gPSBzYW1wbGUoMTpucm93KGRmKSwxKQogICAgICBzYW1wbGVfcm93ID0gZGZbcm93X251bSxdCiAgICAgIGRmID0gZGZbLXJvd19udW0sXQogICAgICBkZiRsaXRfcHJlZGljdG9yID0gc2FtcGxlX3JvdyRyZXRlc3RfcmVsaWFiaWxpdHkKICAgIH0KICAgIHJldHVybihkZikKICB9CgogIHNhbXBsZWRfZGYgPSBkZiAlPiUKICAgIGdyb3VwX2J5KGR2KSAlPiUKICAgIGRvKHNhbXBsZV9mcm9tX2R2KC4pKSAlPiUKICAgIG5hLm9taXQoKQoKICBpZihsZW5ndGgodW5pcXVlKHNhbXBsZWRfZGYkdGFzaykpPjEpewogICAgbW9kX2xpdCA9IGxtKHJldGVzdF9yZWxpYWJpbGl0eSB+IGxpdF9wcmVkaWN0b3Irc2NhbGUoc2FtcGxlX3NpemUpK3Rhc2ssIGRhdGE9c2FtcGxlZF9kZikKICAgIG1vZF9ib290ID0gbG0ocmV0ZXN0X3JlbGlhYmlsaXR5IH4gbWVhbl9wZWFyc29uK3NjYWxlKHNhbXBsZV9zaXplKSt0YXNrLCBkYXRhPXNhbXBsZWRfZGYpCiAgfQogIGVsc2V7CiAgICBtb2RfbGl0ID0gbG0ocmV0ZXN0X3JlbGlhYmlsaXR5IH4gbGl0X3ByZWRpY3RvcitzY2FsZShzYW1wbGVfc2l6ZSksIGRhdGE9c2FtcGxlZF9kZikKICAgIG1vZF9ib290ID0gbG0ocmV0ZXN0X3JlbGlhYmlsaXR5IH4gbWVhbl9wZWFyc29uK3NjYWxlKHNhbXBsZV9zaXplKSwgZGF0YT1zYW1wbGVkX2RmKQogIH0KCgogIG91dCA9IGRhdGEuZnJhbWUocjJfbGl0ID0gc3VtbWFyeShtb2RfbGl0KSRhZGouci5zcXVhcmVkLAogICAgICAgICAgICAgICAgICAgcjJfYm9vdCA9IHN1bW1hcnkobW9kX2Jvb3QpJGFkai5yLnNxdWFyZWQsCiAgICAgICAgICAgICAgICAgICBtX2xpdCA9IGNvZWYoc3VtbWFyeShtb2RfbGl0KSlbImxpdF9wcmVkaWN0b3IiLCJFc3RpbWF0ZSJdLAogICAgICAgICAgICAgICAgICAgbV9ib290ID0gY29lZihzdW1tYXJ5KG1vZF9ib290KSlbIm1lYW5fcGVhcnNvbiIsIkVzdGltYXRlIl0pCgogIHJldHVybihvdXQpCn0KCmNvbXBfbGl0X3ByZWRfb3V0ID0gcGx5cjo6cmRwbHkoMTAwMCwgY29tcF9saXRfcHJlZChyZWxfY29tcCkpCgp3cml0ZS5jc3YoY29tcF9saXRfcHJlZF9vdXQsJy9Vc2Vycy96ZXluZXBlbmthdmkvRHJvcGJveC9Qb2xkcmFja0xhYi9TUk9fUmV0ZXN0X0FuYWx5c2VzL291dHB1dC90YWJsZXMvY29tcF9saXRfcHJlZF9vdXQuY3N2JykKYGBgCgoKYGBge3IgZWNobz1GQUxTRX0KY29tcF9saXRfcHJlZF9vdXQgPSByZWFkLmNzdignL1VzZXJzL3pleW5lcGVua2F2aS9Ecm9wYm94L1BvbGRyYWNrTGFiL1NST19SZXRlc3RfQW5hbHlzZXMvb3V0cHV0L3RhYmxlcy9jb21wX2xpdF9wcmVkX291dC5jc3YnKQpgYGAKCmBgYHtyIGVjaG89RkFMU0UsIG91dC53aWR0aD0nMTAwJSd9CmZpZ19uYW1lID0gJ0xpdEFuZEJvb3RfTm9pc2VfQ2VpbGluZy5qcGVnJwoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MocGFzdGUwKGZpZ19wYXRoLCBmaWdfbmFtZSkpCmBgYAoKYGBge3J9CndpdGgoY29tcF9saXRfcHJlZF9vdXQsIHQudGVzdChyMl9saXQsIHIyX2Jvb3QsIHBhaXJlZD1UKSkKYGBgCgpgYGB7cn0KdG1wID0gY29tcF9saXRfcHJlZF9vdXQgJT4lCiAgc2VsZWN0KHIyX2xpdCwgcjJfYm9vdCkgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUpCgpzdW1tYXJ5KE1DTUNnbG1tKHZhbHVlIH4ga2V5LCBkYXRhID0gdG1wLCB2ZXJib3NlPUYpKQpgYGAKCldlIGNoZWNrZWQgaWYgc3VydmV5IGFuZCB0YXNrIG1lYXN1cmVzIGRpZmZlcmVkIGluIGhvdyBjbG9zZSBvdXIgcmVzdWx0cyB3ZXJlIHRvIHRoZSBsaXRlcmF0dXJlIChpLmUuIEFyZSB5b3UgYmV0dGVyIGluIGVzdGltYXRpbmcgdGhlIGxpdGVyYXR1cmUgdXNpbmcgb3VyIGRhdGEgZm9yIHN1cnZleXMgdnMgdGFza3M/KS4gV2UgZm91bmQgYW4gaW50ZXJhY3Rpb24sIHN1Y2ggdGhhdDogVGhlIGxpdGVyYXR1cmUgZG9lcyBhIGJldHRlciBqb2IgaW4gcHJlZGljdGluZyBpdHNlbGYgZm9yIHRhc2tzIGNvbXBhcmVkIHRvIHN1cnZleXMuIE9uIHRoZSBvdGhlciBoYW5kLCBvdXIgZGF0YSBpcyBiZXR0ZXIgaW4gcHJlZGljdGluZyB0aGUgbGl0ZXJhdHVyZSBlc3RpbWF0ZXMgZm9yIHRoZSBzdXJ2ZXlzIHRoYW4gaXQgaXMgaW4gcHJlZGljdGluZyB0YXNrcy4gIAoKT25lIG1pZ2h0IHdvbmRlcjogV2h5IGFyZSB0aGUgcmVsaWFiaWxpdHkgZXN0aW1hdGVzIGZyb20gc3VydmV5cyB3b3JzZSBjb21wYXJlZCB0byB0YXNrcyBpbiBwcmVkaWN0aW5nIHRoZSBsaXRlcmF0dXJlPyBCZWNhdXNlIHRoZXkgYXJlIGxlc3MgdmFyaWFibGUuIEluIHRoaXMgcHJvY2VkdXJlIGhhdmluZyBoaWdoIHZhcmlhbmNlIGluIHdoYXQgaXMgYmVpbmcgcHJlZGljdGVkIChpLmUuIHRoZSBsaXRlcmF0dXJlIHJlbGlhYmlsaXR5IGVzdGltYXRlcykgaXMgYmV0dGVyLiAgCgpXZSBhbHNvIGNvbmR1Y3RlZCBMT09DViBvbiB0aGlzIGRhdGEgYW5kIGNoZWNrZWQgd2hhdCBpdCBsb29rZWQgbGlrZSBpZiB3ZSBlc3RpbWF0ZSB0aGUgbGVmdCBvbmUgb3V0IHVzaW5nIHRoZSByZW1haW5pbmcgb25lcyBmb3IgdGhlIG5vaXNlIGNlaWxpbmcgbW9kZWw/IFRoZSBwcm9jZWR1cmUgZm9sbG93ZWQgdGhlc2Ugc3RlcHM6Ci0gU2FtcGxlIG9uZSByb3cgb2YgbGl0ZXJhdHVyZSwgICAKLSBmaXQgbW9kZWwgb2Ygc2FtcGxlIHNpemUrdGFzayBvbiByZW1haW5pbmcgZGF0YSwgICAKLSB1c2UgdGhhdCBtb2RlbCB0byBwcmVkaWN0IHRoZSByZWxpYWJpbGl0eSBlc3RpbWF0ZXMsICAgCi0gY29tcGFyZSB0aG9zZSB0byB0aGUgbGVmdCBvdXQgcmVsaWFiaWxpdHkgZXN0aW1hdGUgZnJvbSB0aGUgbGl0ZXJhdHVyZSB2ZXJzdXMgdGhlIGF2ZXJhZ2UgcmVsaWFiaWxpdHkgZXN0aW1hdGUgZnJvbSBvdXIgZGF0YSAgCgpXZSBmb3VuZCB0aGF0IHRoZSAoc3F1YXJlZCkgZGlmZmVyZW5jZSBpcyBzbGlnaHRseSBsYXJnZXIgd2hlbiBwcmVkaWN0aW5nIHRoZSBsZWZ0LW91dCB2YWx1ZSBmcm9tIG91ciBkYXRhIHZlcnN1cyBwcmVkaWN0aW5nIGxlZnQgb3V0IHZhbHVlIGZyb20gbGl0ZXJhdHVyZS4gVGhlIHNxdWFyZWQgZGlmZmVyZW5jZXMgd2VyZSBsYXJnZXIgZm9yIHByZWRpY3RpbmcgdGhlIGxpdGVyYXR1cmUgY29tcGFyZWQgdG8gcHJlZGljdGluZyBvdXIgZGF0YSBmb3Igc3VydmV5cyB3aGlsZSBmb3IgdGFza3MgdGhlIHNxdWFyZWQgZGlmZmVyZW5jZXMgd2VyZSBsYXJnZXIgd2hlbiBwcmVkaWN0aW5nIG91ciBkYXRhIGNvbXBhcmVkIHRvIHByZWRpY3RpbmcgdGhlIGxpdGVyYXR1cmUuIChUaGlzIGZpdHMgd2l0aCBvdGhlciByZXN1bHRzIHRvbzogb3VyIHJlc3VsdHMgZGlmZmVyIGZyb20gdGhlIGxpdGVyYXR1cmUgbW9yZSBmb3IgdGhlIHN1cnZleSBtZWFzdXJlcykuICAKCldlIGRvIG5vdCBwcmVzZW50IHRoZXNlIHJlc3VsdHMgaW4gZnVydGhlciBkZXRhaWwgYXMgdGhleSB5aWVsZCBvbmx5IGNvbnZlcmdpbmcgZXZpZGVuY2UgYXMgdGhlIGFuYWx5c2VzIGFib3ZlLgoKIyMjIE1lYXN1cmUgbGV2ZWwgY29tcGFyaXNvbgoKTGl0ZXJhdHVyZSB2cy4gb3VyIGRhdGEgb24gYSAgbWVhc3VyZSBiYXNpcwoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPScxMDAlJ30KZmlnX25hbWUgPSAnTGl0VnNFbXBfTWVhc3VyZV9QbG90LmpwZWcnCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhwYXN0ZTAoZmlnX3BhdGgsIGZpZ19uYW1lKSkKYGBgCgpgYGB7cn0KcmVsX2NvbXAgJT4lCiAgZ3JvdXBfYnkoZHYsIHRhc2spICU+JQogIHN1bW1hcmlzZShtZWFuX2xpdCA9IG1lYW4ocmV0ZXN0X3JlbGlhYmlsaXR5KSwKICAgICAgICAgICAgbWVhbl9lbXAgPSB1bmlxdWUobWVhbl9wZWFyc29uKSkgJT4lCiAgZ2dwbG90KGFlcyhtZWFuX2VtcCwgbWVhbl9saXQsIGNvbD10YXNrLCBzaGFwZT10YXNrKSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpKwogIGdlb21fcG9pbnQoKSsKICB4bGltKC0wLjI1LCAxKSsKICB5bGltKC0wLjI1LCAxKSsKICB5bGFiKCJBdmVyYWdlIExpdGVyYXR1cmUgUmVsaWFiaWxpdHkgRXN0aW1hdGUiKSsKICB4bGFiKCJBdmVyYWdlIEVtcGlyaWNhbCBSZWxpYWJpbGl0eSBFc3RpbWF0ZSIpKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJywKICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIlRpbWVzIiwgbGluZWhlaWdodCA9IDIsIGhqdXN0ID0gMCkpKwogIGxhYnMoY2FwdGlvbiA9IHN0cl93cmFwKCJGSUdVUkUgMjogQ29ycmVsYXRpb24gYmV0d2VlbiBtZWFuIHJlbGlhYmlsaXR5IGVzdGltYXRlcyBmb3IgZWFjaCBtZWFzdXJlIGZvdW5kIGluIHRoZSBsaXRlcmF0dXJlIHdpdGggdGhlIG1lYW4gcmVsaWFiaWxpdHkgZnJvbSBvdXIgZGF0YS4iLCB3aWR0aCA9IDEyMCkpCmBgYAoKYGBge3IgZWNobz1GQUxTRX0Kcm0odG1wLCByZWxfY29tcCwgbW9kMSwgbW9kMiwgbW9kMywgaSwgbGl0X2VtcF9jb3Jfb3V0LCBjb21wX2xpdF9wcmVkLCBjb21wX2xpdF9wcmVkX291dCkKYGBgCgojIyBSZWxhdGlvbnNoaXAgYmV0d2VlbiByZWxpYWJpbGl0eSBtZXRyaWNzIChwb2ludCBlc3RpbWF0ZXMpCgpUaG91Z2ggd2UgYXJlIHByaW1hcmlseSByZXBvcnRpbmcgaWNjMi4xJ3MgYXMgb3VyIG1ldHJpYyBvZiByZWxpYWJpbGl0eSB0aGUgcmVzdWx0cyBkb24ndCBjaGFuZ2UgZGVwZW5kaW5nIG9uIHRoZSBtZXRyaWMgY2hvc2VuLiBIZXJlIHdlIHBsb3QgcG9pbnQgZXN0aW1hdGVzIG9mIHRocmVlIGRpZmZlcmVudCByZWxpYWJpbGl0eSBtZXRyaWNzIGFnYWluc3QgZWFjaCBvdGhlciAoaWNjMi4xLCBQZWFyc29uLCBTcGVhcm1hbikuIFRoZSBib290c3RyYXBwZWQgdmVyc2lvbiBpcyBlc3NlbnRpYWxseSB0aGUgc2FtZSBidXQgdGhlIHBsb3RzIGFyZSBidXNpZXIgZHVlIHRvIG1vcmUgZGF0YXBvaW50cy4KCmBgYHtyfQpyZWxfZGYgPSBtYWtlX3JlbF9kZih0MV9kZiA9IHRlc3RfZGF0YSwgdDJfZGYgPSByZXRlc3RfZGF0YSwgbWV0cmljcyA9IGMoJ3NwZWFybWFuJywgJ2ljYzIuMScsJ2ljYzMuaycsICdwZWFyc29uJywgJ3Zhcl9icmVha2Rvd24nLCAncGFydGlhbF9ldGEnLCAnc2VtJykpCgpyZWxfZGYkdGFzayA9ICd0YXNrJwpyZWxfZGZbZ3JlcCgnc3VydmV5JywgcmVsX2RmJGR2KSwgJ3Rhc2snXSA9ICdzdXJ2ZXknCnJlbF9kZltncmVwKCdob2x0JywgcmVsX2RmJGR2KSwgJ3Rhc2snXSA9ICJ0YXNrIgpyZWxfZGYgPSByZWxfZGYgJT4lCiAgc2VsZWN0KGR2LCB0YXNrLCBzcGVhcm1hbiwgaWNjMi4xLGljYzMuaywgcGVhcnNvbiwgcGFydGlhbF9ldGEsIHNlbSwgdmFyX3N1YnMsIHZhcl9pbmQsIHZhcl9yZXNpZCkKYGBgCgpXZSBjYWxjdWxhdGVkIGByIGFzLm51bWVyaWModGFibGUocmVsX2RmJHRhc2spWzFdKWAgbWVhc3VyZXMgZm9yIHN1cnZleXMgYW5kIGByIGFzLm51bWVyaWModGFibGUocmVsX2RmJHRhc2spWzJdKWAgbWVhc3VyZXMgZm9yIGNvZ25pdGl2ZSB0YXNrcy4gIAoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPScxMDAlJ30KZmlnX25hbWUgPSAnTWV0cmljX1NjYXR0ZXJwbG90cy5qcGVnJwoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MocGFzdGUwKGZpZ19wYXRoLCBmaWdfbmFtZSkpCmBgYAoKQXMgdGhlIHNjYXR0ZXIgcGxvdHMgZGVwaWN0IHRoZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiBkaWZmZXJlbnQgdHlwZXMgcmVsaWFiaWxpdHkgbWV0cmljcyB3ZXJlIHZlcnkgaGlnaC4KCmBgYHtyfQpjb3IocmVsX2RmWyxjKCdzcGVhcm1hbicsICdpY2MyLjEnLCAnaWNjMy5rJywgJ3BlYXJzb24nKV0pCmBgYAoKTm90ZTogU29tZSB2YXJpYWJsZXMgaGF2ZSA8MCBpY2MyLjEncy4gVGhpcyB3b3VsZCBiZSB0aGUgY2FzZSBpZiB0aGUgJE1TX3tlcnJvcn0kPiRNU197YmV0d2Vlbn0kLiBEYXRhIGZvciB0aGVzZSB2YXJpYWJsZXMgaGF2ZSBubyByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIHRpbWUgcG9pbnRzLgoKIyMgU3VtbWFyeSBvZiBhbGwgbWVhc3VyZSByZWxpYWJpbGl0aWVzCgpTdW1tYXJpemVkIGJvb3RzdHJhcHBlZCByZWxpYWJpbGl0aWVzCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpib290X2RmICU+JQogIGdyb3VwX2J5KGR2KSAlPiUKICBzdW1tYXJpc2UoaWNjMi4xX21lZGlhbiA9IHF1YW50aWxlKGljYzIuMSwgcHJvYnMgPSAwLjUpLAogICAgICAgICAgICBpY2MyLjFfMi41ID0gcXVhbnRpbGUoaWNjMi4xLCBwcm9icyA9IDAuMDI1KSwKICAgICAgICAgICAgaWNjMi4xXzk3LjUgPSBxdWFudGlsZShpY2MyLjEsIHByb2JzID0gMC45NzUpLAogICAgICAgICAgICBzcGVhcm1hbl9tZWRpYW4gPSBxdWFudGlsZShzcGVhcm1hbiwgcHJvYnMgPSAwLjUpLAogICAgICAgICAgICBzcGVhcm1hbl8yLjUgPSBxdWFudGlsZShzcGVhcm1hbiwgcHJvYnMgPSAwLjAyNSksCiAgICAgICAgICAgIHNwZWFybWFuXzk3LjUgPSBxdWFudGlsZShzcGVhcm1hbiwgcHJvYnMgPSAwLjk3NSkpICU+JQogIGRhdGF0YWJsZSgpICU+JQogIGZvcm1hdFJvdW5kKGNvbHVtbnM9YygnaWNjMi4xX21lZGlhbicsICdpY2MyLjFfMi41JywgJ2ljYzIuMV85Ny41JywgJ3NwZWFybWFuX21lZGlhbicsICdzcGVhcm1hbl8yLjUnLCAnc3BlYXJtYW5fOTcuNScpLCBkaWdpdHM9MykKYGBgCgoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPScxMDAlJ30KZmlnX25hbWUgPSAnQm9vdF9Cb3RoX3dfdHJpYWxpbmZvLmpwZWcnCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhwYXN0ZTAoZmlnX3BhdGgsIGZpZ19uYW1lKSkKYGBgCgpWYXJpYWJsZSBsZXZlbCBzdW1tYXJ5IG9mIGJvb3RzdHJhcHBlZCByZWxpYWJpbGl0aWVzLgoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPScxMDAlJ30KZmlnX25hbWUgPSAnQm9vdHN0cmFwX1Jhd19WYXJfUGxvdC5qcGVnJwoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MocGFzdGUwKGZpZ19wYXRoLCBmaWdfbmFtZSkpCmBgYAoKRXhhbXBsZSBvZiB0aGUgb3ZlcmxheWluZyBwcm9jZWR1cmUuCgpgYGB7ciBlY2hvPUZBTFNFLCBvdXQud2lkdGg9JzEwMCUnfQpmaWdfbmFtZSA9ICdCb290c3RyYXBfRXhhbXBsZV9QbG90X3QuanBlZycKCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKHBhc3RlMChmaWdfcGF0aCwgZmlnX25hbWUpKQpgYGAKCiMjIFN1cnZleSB2cyBUYXNrcwoKQ29tcGFyaXNvbiBvZiBzdXJ2ZXkgbWVhc3VyZXMgdG8gY29nbml0aXZlIHRhc2sgbWVhc3VyZXMgaW4gdGhlIGJvb3RzdHJhcHBlZCByZXN1bHRzLiBNdWx0aWxldmVsIG1vZGVsIHdpdGggcmFuZG9tIGludGVyY2VwdHMgZm9yIGVhY2ggbWVhc3VyZSBhbmQgZml4ZWQgZWZmZWN0IG9mIHN1cnZleSB2ZXJzdXMgY29nbml0aXZlIG1lYXN1cmUuCgpgYGB7cn0KYm9vdF9kZiA9IGJvb3RfZGYgJT4lCiAgICBtdXRhdGUodGFzayA9IGlmZWxzZShncmVwbCgic3VydmV5IixkdiksICJzdXJ2ZXkiLCJ0YXNrIiksCiAgICAgICAgICAgdGFzayA9IGlmZWxzZShncmVwbCgiaG9sdCIsZHYpLCAidGFzayIsIHRhc2spKQoKYm9vdF9kZiAlPiUKICBncm91cF9ieSh0YXNrKSAlPiUKICBzdW1tYXJpc2UoaWNjMi4xX21lZGlhbiA9IHF1YW50aWxlKGljYzIuMSwgcHJvYnMgPSAwLjUpLAogICAgICAgICAgICBpY2MyLjFfMi41ID0gcXVhbnRpbGUoaWNjMi4xLCBwcm9icyA9IDAuMDI1KSwKICAgICAgICAgICAgaWNjMi4xXzk3LjUgPSBxdWFudGlsZShpY2MyLjEsIHByb2JzID0gMC45NzUpLAogICAgICAgICAgICBzcGVhcm1hbl9tZWRpYW4gPSBxdWFudGlsZShzcGVhcm1hbiwgcHJvYnMgPSAwLjUpLAogICAgICAgICAgICBzcGVhcm1hbl8yLjUgPSBxdWFudGlsZShzcGVhcm1hbiwgcHJvYnMgPSAwLjAyNSksCiAgICAgICAgICAgIHNwZWFybWFuXzk3LjUgPSBxdWFudGlsZShzcGVhcm1hbiwgcHJvYnMgPSAwLjk3NSksCiAgICAgICAgICAgIG51bV92YXJzID0gbigpLzEwMDApICU+JQogIGRhdGF0YWJsZSgpICU+JQogIGZvcm1hdFJvdW5kKGNvbHVtbnM9YygnaWNjMi4xX21lZGlhbicsICdpY2MyLjFfMi41JywgJ2ljYzIuMV85Ny41JywgJ3NwZWFybWFuX21lZGlhbicsICdzcGVhcm1hbl8yLjUnLCAnc3BlYXJtYW5fOTcuNScpLCBkaWdpdHM9MykKYGBgCgoKYGBge3IgZXZhbD1GQUxTRX0Kc3VtbWFyeShpY2MyLjFfYnlfdGFza19tb2RlbCkKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpybShpY2NfYnlfdGFza19tb2RlbCkKYGBgCgpgYGB7cn0Kc3VtbWFyeShNQ01DZ2xtbShpY2MyLjEgfiB0YXNrLCBkYXRhPXJlbF9kZiwgdmVyYm9zZT1GKSkKYGBgCgojIyMgVmFyaWFuY2UgYnJlYWtkb3duCgpUaGUgcXVhbnRpYXRpdmUgZXhwbGFuYXRpb24gZm9yIHRoZSBkaWZmZXJlbmNlIGluIHJlbGlhYmlsaXR5IGVzdGltYXRlcyBiZXR3ZWVuIHN1cnZleXMgYW5kIHRhc2tzLCBhcyByZWNlbnRseSBkZXRhaWxlZCBieSBIZWRnZSBldCBhbC4gKDIwMTcpLCBsaWVzIGluIHRoZSBkaWZmZXJlbmNlIGluIHNvdXJjZXMgb2YgdmFyaWFuY2UgYmV0d2VlbiB0aGVzZSBtZWFzdXJlcy4gU3BlY2lmaWNhbGx5LCB0aGUgaWNjMi4xIGlzIGNhbGN1bGF0ZWQgYXMgdGhlIHJhdGlvIG9mIHZhcmlhbmNlIGJldHdlZW4gc3ViamVjdHMgdmFyaWFuY2UgdG8gYWxsIHNvdXJjZXMgb2YgdmFyaWFuY2UuIFRodXMsIG1lYXN1cmVzIHdpdGggaGlnaCBiZXR3ZWVuIHN1YmplY3RzIHZhcmlhbmNlIHdvdWxkIGhhdmUgaGlnaCB0ZXN0LXJldGVzdCByZWxpYWJpbGl0eS4gSW50dWl0aXZlbHksIG1lYXN1cmVzIHdpdGggaGlnaCBiZXR3ZWVuIHN1YmplY3RzIHZhcmlhbmNlIGFyZSBhbHNvIGJldHRlciBzdWl0ZWQgZm9yIGluZGl2aWR1YWwgZGlmZmVyZW5jZSBhbmFseXNlcyBhcyB0aGV5IHdvdWxkIGNhcHR1cmUgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHN1YmplY3RzIGluIGEgc2FtcGxlLgoKSGVyZSB3ZSBmaXJzdCBwbG90IHRoZSBwZXJjZW50YWdlIG9mIHZhcmlhbmNlIGV4cGxhaW5lZCBieSB0aGUgdGhyZWUgc291cmNlcyBvZiB2YXJpYW5jZSBmb3IgdGhlIHBvaW50IGVzdGltYXRlcyBvZiBtZWFzdXJlIHJlbGlhYmlsaXRpZXMuIFRoZSBwbG90IG9ubHkgaW5jbHVkZXMgcmF3IG1lYXN1cmVzIChubyBERE0gcGFyYW1ldGVycykgYW5kIHRoZSBtZWFzdXJlcyBhcmUgcmFua2VkIGJ5IHBlcmNlbnRhZ2Ugb2YgYmV0d2VlbiBzdWJqZWN0IHZhcmlhYmlsaXR5IGZvciBlYWNoIHRhc2svc3VydmV5IChpLmUuIHRoZSBiZXN0IHRvIHdvcnN0IGluZGl2aWR1YWwgZGlmZmVyZW5jZSBtZWFzdXJlIGZvciBlYWNoIHRhc2svc3VydmV5KS4gVGhlbiB3ZSBjb21wYXJlIHN0YXRpc3RpY2FsbHkgd2hldGhlciB0aGUgcGVyY2VudGFnZSBvZiB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlc2Ugc291cmNlcyBkaWZmZXIgYmV0d2VlbiB0YXNrcyBhbmQgc3VydmV5cy4KCmBgYHtyIGVjaG89RkFMU0UsIG91dC53aWR0aD0nMTAwJSd9CmZpZ19uYW1lID0gJ1ZhcmlhbmNlX0JyZWFrZG93bl9QbG90LmpwZWcnCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhwYXN0ZTAoZmlnX3BhdGgsIGZpZ19uYW1lKSkKYGBgCgpDb21wYXJpbmcgdHlwZXMgb2YgdmFyaWFuY2UgZm9yIHN1cnZleSB2cyB0YXNrIG1lYXN1cmVzOiBTdXJ2ZXkgbWVhc3VyZXMgaGF2ZSBoaWdoZXIgYmV0d2VlbiBzdWJqZWN0IHZhcmlhYmlsaXR5ICAKCk5vdGU6IFRoaXMgYW5hbHlzaXMgaW5jbHVkZXMgRERNIHZhcmlhYmxlcyB0b28uCgpSdW5uaW5nIHNlcGFyYXRlIG1vZGVscyBmb3IgZGlmZmVyZW50IHNvdXJjZXMgb2YgdmFyaWFuY2UgYmVjYXVzZSBpbnRlcmFjdGl2ZSBtb2RlbCB3aXRoIHZhcmlhbmNlIHR5cGUqdGFzayBzZWVtZWQgdG9vIGNvbXBsaWNhdGVkLgoKRmlyc3Qgd2UgZmluZCB0aGF0IHRhc2sgbWVhc3VyZXMgaGF2ZSBhIHNtYWxsZXIgcGVyY2VudGFnZSBvZiB0aGVpciBvdmVyYWxsIHZhcmlhbmNlIGV4cGxhaW5lZCBieSB2YXJpYWJpbGl0eSBiZXR3ZWVuIHN1YmplY3RzIGNvbXBhcmVkIHRvIHN1cnZleSBtZWFzdXJlcy4KCmBgYHtyfQp0bXAgPSBib290X2RmICU+JQogIHNlbGVjdChkdiwgdGFzaywgdmFyX3N1YnNfcGN0LCB2YXJfaW5kX3BjdCwgdmFyX3Jlc2lkX3BjdCkKCiMgc3VtbWFyeSh2YXJfc3Vic19wY3RfYnlfdGFza19tb2RlbCkKCnJlbF9kZiA9IHJlbF9kZiAlPiUgCiAgbXV0YXRlKHZhcl9zdWJzX3BjdCA9IHZhcl9zdWJzLyh2YXJfc3Vicyt2YXJfaW5kK3Zhcl9yZXNpZCkqMTAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcl9pbmRfcGN0ID0gdmFyX2luZC8odmFyX3N1YnMrdmFyX2luZCt2YXJfcmVzaWQpKjEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJfcmVzaWRfcGN0ID0gdmFyX3Jlc2lkLyh2YXJfc3Vicyt2YXJfaW5kK3Zhcl9yZXNpZCkqMTAwKQoKc3VtbWFyeShNQ01DZ2xtbSh2YXJfc3Vic19wY3QgfiB0YXNrLCBkYXRhPXJlbF9kZiwgdmVyYm9zZT1GKSkKYGBgCgpXZSBhbHNvIGZpbmQgdGhhdCBhIHNpZ25pZmljYW50bHkgbGFyZ2VyIHBlcmNlbnRhZ2Ugb2YgdGhlaXIgdmFyaWFuY2UgaXMgZXhwbGFpbmVkIGJ5IGJldHdlZW4gc2Vzc2lvbiB2YXJpYWJpbGl0eS4gTGFyZ2VyIGJldHdlZW4gc2Vzc2lvbiB2YXJpYWJpbGl0eSBzdWdnZXN0cyBzeXN0ZW1hdGljIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHR3byBzZXNzaW9ucy4gU3VjaCBzeXN0ZW1hdGljIGVmZmVjdHMgY2FuIGJlIGR1ZSB0byBlLmcuIGxlYXJuaW5nIGVmZmVjdHMgYXMgZXhwbG9yZWQgbGF0ZXIuCgpgYGB7cn0KIyBzdW1tYXJ5KHZhcl9pbmRfcGN0X2J5X3Rhc2tfbW9kZWwpCgpzdW1tYXJ5KE1DTUNnbG1tKHZhcl9pbmRfcGN0IH4gdGFzaywgZGF0YT1yZWxfZGYsIHZlcmJvc2U9RikpCmBgYAoKYGBge3J9CiMgc3VtbWFyeSh2YXJfcmVzaWRfcGN0X2J5X3Rhc2tfbW9kZWwpCgpzdW1tYXJ5KE1DTUNnbG1tKHZhcl9yZXNpZF9wY3QgfiB0YXNrLCBkYXRhPXJlbF9kZiwgdmVyYm9zZT1GKSkKYGBgCgpgYGB7cn0Kcm0odmFyX3N1YnNfcGN0X2J5X3Rhc2tfbW9kZWwsIHZhcl9pbmRfcGN0X2J5X3Rhc2tfbW9kZWwsIHZhcl9yZXNpZF9wY3RfYnlfdGFza19tb2RlbCkKYGBgCgpgYGB7cn0KdG1wX3NhdmUgPSB0bXAlPiUKICBnYXRoZXIoa2V5LCB2YWx1ZSwgLWR2LCAtdGFzaykgJT4lCiAgZ3JvdXBfYnkodGFzaywga2V5KSAlPiUKICBzdW1tYXJpc2UobWVkaWFuID0gbWVkaWFuKHZhbHVlKSwKICAgICAgICAgICAgc2QgPSBzZCh2YWx1ZSkpICU+JQogIG11dGF0ZShrZXkgPSBpZmVsc2Uoa2V5ID09ICd2YXJfaW5kX3BjdCcsICdCZXR3ZWVuIHNlc3Npb24gdmFyaWFuY2UnLCBpZmVsc2Uoa2V5ID09ICd2YXJfc3Vic19wY3QnLCAnQmV0d2VlbiBzdWJqZWN0cyB2YXJpYW5jZScsIGlmZWxzZShrZXkgPT0gJ3Zhcl9yZXNpZF9wY3QnLCAnUmVzaWR1YWwgdmFyaWFuY2UnLE5BKSkpKSAlPiUKICByZW5hbWUoTWVkaWFuID0gbWVkaWFuLCBTRCA9IHNkKSAlPiUKICBhcnJhbmdlKHRhc2ssIGtleSkKCnRtcF9zYXZlCmBgYAoKU3VtbWFyaXppbmcgZm9yIGNsZWFyZXIgcHJlc2VudGF0aW9uLiBUaGlzIGdyYXBoIGlzIGN1cnJlbnRseSB1c2luZyB0aGUgYm9vdHN0cmFwcGVkIHJlbGlhYmlsaXRpZXMgYW5kIGlzIHRoZXJlZm9yZSBtZXNzaWVyIHRoYW4gaWYganVzdCB1c2luZyB0aGUgcG9pbnQgZXN0aW1hdGVzLgoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPScxMDAlJ30KZmlnX25hbWUgPSAnVmFyaWFuY2VfQnJlYWtkb3duX0RvdFBsb3QuanBlZycKCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKHBhc3RlMChmaWdfcGF0aCwgZmlnX25hbWUpKQpgYGAKCiMjIFRhc2sgUmVsaWFiaWxpdGllcwoKSGVyZSB3ZSBzdW1tYXJpemUgdGhlIHJlc3VsdHMgb24gYSB0YXNrIGxldmVsIHRvIG1ha2UgaXQgbW9yZSBkaWdlc3RhYmxlIGFuZCBlYXNpZXIgdG8gbWFrZSBjb250YWN0IHdpdGggdGhlIGxpdGVyYXR1cmUuICAKCldlIHJlZHVjZSB0aGUgbGlzdCBvZiB0YXNrIG1lYXN1cmVzIHRvIGEgbGlzdCBvZiBvbmUgcGVyIHRhc2sgYnkgYXZlcmFnaW5nIG9ubHkgdGhlIG1lYXN1cmVzIHRoYXQgYXJlIGV4dHJhY3RlZCBhbmQgdXNlZCBmcm9tIHRoZXNlIHRhc2tzIGluIHRoZSBsaXRlcmF0dXJlLiBXZSBjYWxsIHRoZXNlIHRoZSAnbWVhbmluZ2Z1bCBtZWFzdXJlcy4nCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0bXAgPSBtZWFzdXJlX2xhYmVscyAlPiUKICBtdXRhdGUoZHYgPSBhcy5jaGFyYWN0ZXIoZHYpKSAlPiUKICBmaWx0ZXIodGFzayA9PSAndGFzaycsCiAgICAgICAgIGR2ICVpbiUgbWVhbmluZ2Z1bF92YXJzKSAlPiUKICBsZWZ0X2pvaW4oYm9vdF9kZlssYygiZHYiLCAiaWNjMi4xIildLCBieSA9ICdkdicpICU+JQogIHNlcGFyYXRlKGR2LCBjKCd0YXNrX25hbWUnLCAnZXh0cmFfMScsICdleHRyYV8yJyksIHNlcCA9ICdcXC4nLHJlbW92ZT1GQUxTRSkgJT4lCiAgc2VsZWN0KC1leHRyYV8xLCAtZXh0cmFfMikgJT4lCiAgZ3JvdXBfYnkodGFza19uYW1lKSAlPiUKICBzdW1tYXJpc2UobWVkaWFuX2ljYzIuMSA9IG1lZGlhbihpY2MyLjEpLAogICAgICAgICAgICBpY2MyLjFfMi41ID0gcXVhbnRpbGUoaWNjMi4xLCBwcm9icyA9IDAuMDI1KSwKICAgICAgICAgICAgaWNjMi4xXzk3LjUgPSBxdWFudGlsZShpY2MyLjEsIHByb2JzID0gMC45NzUpLAogICAgICAgICAgICBudW1fbWVhc3VyZXMgPSBuKCkvMTAwMCwKICAgICAgICAgICAgbWVhbl9udW1fdHJpYWxzID0gcm91bmQobWVhbihudW1fYWxsX3RyaWFscykpKSU+JQogIGFycmFuZ2UoLW1lZGlhbl9pY2MyLjEpCgp0bXAgJT4lCiAgZGF0YXRhYmxlKCkgJT4lCiAgZm9ybWF0Um91bmQoY29sdW1ucz1jKCdtZWRpYW5faWNjMi4xJywnaWNjMi4xXzIuNScsJ2ljYzIuMV85Ny41JyksIGRpZ2l0cz0zKQpgYGAKCiMjIyBOdW1iZXIgb2YgdHJpYWxzCgpEb2VzIG51bWJlciBvZiBpdGVtcyBpbiBhIHRhc2sgaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiB0aGUgYXZlcmFnZSBpY2MyLjEgb2YgbWVhbmluZ2Z1bCBtZWFzdXJlcyBmb3IgYWxsIHRyaWFscyBmcm9tIGEgdGFzaz8gTm8uCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0bXAgPSBtZWFzdXJlX2xhYmVscyAlPiUKICBtdXRhdGUoZHYgPSBhcy5jaGFyYWN0ZXIoZHYpKSAlPiUKICBmaWx0ZXIodGFzayA9PSAndGFzaycsCiAgICAgICAgIGR2ICVpbiUgbWVhbmluZ2Z1bF92YXJzKSAlPiUKICAjIGxlZnRfam9pbihib290X2RmWyxjKCJkdiIsICJpY2MyLjEiKV0sIGJ5ID0gJ2R2JykgJT4lCiAgbGVmdF9qb2luKHJlbF9kZlssYygiZHYiLCAiaWNjMi4xIildLCBieSA9ICdkdicpICU+JQogIHNlcGFyYXRlKGR2LCBjKCd0YXNrX25hbWUnLCAnZXh0cmFfMScsICdleHRyYV8yJyksIHNlcCA9ICdcXC4nLHJlbW92ZT1GQUxTRSkgJT4lCiAgc2VsZWN0KC1leHRyYV8xLCAtZXh0cmFfMikKCiNzdW1tYXJ5KGljYzIuMV9ieV9udW1fdHJpYWxzX21vZGVsKQpzdW1tYXJ5KE1DTUNnbG1tKGljYzIuMSB+IG51bV9hbGxfdHJpYWxzLCBkYXRhPXRtcCwgdmVyYm9zZT1GKSkKYGBgCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0bXAgJT4lCiAgZ2dwbG90KGFlcyhudW1fYWxsX3RyaWFscywgaWNjMi4xKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKSsKICB0aGVtZV9idygpKwogIHhsYWIoIk51bWJlciBvZiB0cmlhbHMiKSsKICB5bGFiKCJpY2MyLjEiKQpgYGAKCiMjIyMgVHJpYWwgbnVtYmVyIGRlcGVuZGVuY2UgaW50cmFtZWFzdXJlCgpUaGUgYWJvdmUgYW5hbHlzaXMgd2FzIGxvb2tpbmcgYXQgdGhlIGVmZmVjdCBvZiBudW1iZXIgb2YgdHJpYWxzIGFjcm9zcyB0YXNrcy4gQnV0IHNvbWUgdGFza3MgbWlnaHQgYmUgYmFkIGZvciBpbmRpdmlkdWFsIGRpZmZlcmVuY2UgbWVhc3VyZW1lbnQgcmVnYXJkbGVzcyBvZiBob3cgbWFueSB0cmlhbHMgdGhlcmUgYXJlIGluIHRoZW0gd2hlcmVhcyBmb3Igb3RoZXJzIGZld2VyIHRyaWFscyBtaWdodCBiZSB5aWVsZGluZyBhIHN1ZmZpY2llbnRseSByZWxpYWJsZSBtZWFzdXJlLgoKRm9yIHRhc2tzIGZvciB3aGljaCBkZXBlbmRlbnQgdmFyaWFibGVzIGFyZSBlc3RpbWF0ZWQgdXNpbmcgbWFueSB0cmlhbHMgb25lIGNhbiBhc2s6IERvZXMgdGhlIHNhbWUgbWVhc3VyZSBnZXQgbGVzcyByZWxpYWJsZSBpZiBmZXdlciB0cmlhbHMgYXJlIHVzZWQgdG8gZXN0aW1hdGUgaXRzIHJlbGlhYmlsaXR5PwoKVGhpcyB3b24ndCBtYWtlIHNlbnNlIGZvciBhbGwgdGFza3MuIEZvciBleGFtcGxlIHRvIGVzdGltYXRlIGEgcmlzayBhdmVyc2lvbiBwYXJhbWV0ZXIgeW91IG5lZWQgYWxsIHRyaWFscyBmb3IgSG9sdCBhbmQgTGF1cnkuIEZvciBLaXJieSBhbmQgQmlja2VsIHlvdSBoYXZlIHNwZWNpZmljIGNvbmRpdGlvbnMgbG9va2luZyBhdCBmZXdlciB0cmlhbHMuIFRoZSBDb2duaXRpdmUgUmVmbGVjdGlvbiBUYXNrIG1pZ2h0IGJlIG1vcmUgYXBwcm9wcmlhdGUgdG8gYW5hbHl6ZSBlYWNoIGl0ZW0gc2VhcHJhdGVseS4gVGhlIHdyaXRpbmcgdGFzayBkb2VzIG5vdCBoYXZlIHRyaWFsIG51bWJlcnMuIEZvciBhbGwgb3RoZXJzIGl0IG1pZ2h0IGJlIGludGVyZXN0aW5nIHRvIGludmVzdGlnYXRlLgoKVGhlc2Uga2luZHMgb2YgYW5hbHlzZXMgYXJlIHRvbyB0YXNrLXNwZWNpZmljIGFuZCBpbi1kZXB0aCBmb3IgYSBwYXBlciB0aGF0IGlzIHRyeWluZyB0byBnaXZlIGEgZ2xvYmFsIHNlbnNlIG9mIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHNlbGYtcmVndWxhdGlvbiBtZWFzdXJlcyBpbiB0aGVpciBzdWl0YWJsaXR5IGZvciBpbmRpdmlkdWFsIGRpZmZlcmVuY2UgYW5hbHlzZXMgYmFzZWQgb24gdGhlaXIgc3RhYmlsaXR5IGFjcm9zcyB0aW1lLiBTdWNoIGFuYWx5c2VzIHdvdWxkIHByb3ZpZGUgYSBkZXRhaWxlZCBleGFtaW5hdGlvbiBvZiBob3cgdG8gZXh0cmFjdCB0aGUgbW9zdCByZWxpYWJsZS9iZXN0IGluZGl2aWR1YWwgZGlmZmVyZW5jZSBtZWFzdXJlIGZyb20gdGFza3Mgd2l0aCBhIHNldCBvZiBtZWRpb2NyZSB2YXJpYWJsZXMgdG8gYmVnaW4gd2l0aC4gVGhvdWdoIHdlIGRvIG5vdCBwcm92aWRlIHN1Y2ggYSBjb21wcmVoZW5zaXZlIGFuYWx5c2lzIG9mIHRoaXMgc29ydCBpbiB0aGlzIHBhcGVyIHdlIHByb3ZpZGUgYSBzaW5nbGUgZXhhbXBsZSBvZiB0aGlzIGFwcHJvYWNoIGFuZCBob3BlIHRoZSBvcGVuIGFjY2VzcyB3ZSBwcm92aWRlIHRvIHRoZSBkYXRhIHNwdXJzIGZ1cnRoZXIgd29yay4KCkZvciB0aGlzIGV4YW1wbGUgd2UgbG9vayBhdCB0aGUgcmV0ZXN0IHJlbGlhYmlsaXR5IG9mIGRlcGVuZGVudCBtZWFzdXJlcyBmcm9tIHRoZSB0aHJlZWJ5dHdvIHdpdGggPjQwMCB0cmlhbHMuIEhlcmUgaXMgYSBncmFwaCBvZiBob3cgdGhlIHBvaW50IGVzdGltYXRlcyBvZiB0aGUgcmV0ZXN0IHJlbGlhYmlsaXR5IGNoYW5nZXMgZm9yIGVhY2ggb2YgdGhlIGRlcGVuZGVudCBtZWFzdXJlcyB1c2luZyBkaWZmZXJlbnQgbnVtYmVycyBvZiB0cmlhbHMgdG8gZXN0aW1hdGUgdGhlbS4KClRha2Vhd2F5cyBmcm9tIHRoaXMgZ3JhcGg6Ci0gUmVsaWFiaWxpdHkgZXN0aW1hdGVzIHN0YWJpbGl6ZSBhZnRlciBhYm91dCBhbiBlaWd0aHRoIG9mIHRoZSB0cmlhbHMgKG5vdGUgdGhhdCB0aGlzIG1pZ2h0IG5vdCBiZSB0cnVlIGZvciBvdGhlciBtb2RlbCBwYXJhbWV0ZXIgZXN0aW1hdGVzOyBoZXJlIHdlIGFyZSBvbmx5IGxvb2tpbmcgYXQgcmF3IHJlc3BvbnNlIHRpbWUgYW5kIGFjY3VyYWN5IG1lYXN1cmVzKQotIE9ubHkgdGhyZWUgbWVhc3VyZXMgdGhhdCBhcmUgbm90IGNvbnRyYXN0IG1lYXN1cmVzIGhhdmUgcmVsaWFiaWxpdGllcyA+MAotIEFsbCB0aGUgb3RoZXIgbWVhc3VyZXMgYXJlIGJhc2ljYWxseSBjb21wbGV0ZWx5IHVucmVsaWFibGUgKGluY2x1ZGluZyB0aGUgdHdvICdtZWFuaW5nZnVsIHZhcmlhYmxlcycgaW4gdGhlIGxpdGVyYXR1cmU6IHRoZSBjdWUgc3dpdGNoIGNvc3QgUlQncykKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnRyaWFsX251bV9yZWxfZGYgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUsIC1icmVha3MpICU+JQogIGZpbHRlcihrZXkgJWluJSBjKCJhdmdfcnRfaWNjIiwgImxlYXJuaW5nX3RvX2xlYXJuX2ljYyIsICJub25wZXJzZXZlcmF0aXZlX2Vycm9yc19pY2MiKSkgJT4lCiAgZ2dwbG90KGFlcygoYnJlYWtzKzEpKjEwLCB2YWx1ZSwgc2hhcGU9a2V5KSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fbGluZShhbHBoYSA9IDAuNSkrCiAgdGhlbWVfYncoKSsKICB4bGFiKCJOdW1iZXIgb2YgdHJpYWxzIikrCiAgeWxhYigiSUNDIikrCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiVGltZXMiLCBsaW5laGVpZ2h0ID0gMiwgaGp1c3QgPSAwKSkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDA6OSksCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoImF2Z19ydF9pY2MiLCJsZWFybmluZ190b19sZWFybl9pY2MiLCAibm9ucGVyc2V2ZXJhdGl2ZV9lcnJvcnNfaWNjIiksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkF2ZXJhZ2UgUmVzcG9uc2UgVGltZSIsICJMZWFybmluZyB0byBMZWFybiIsICAiTm9ucGVyc2V2ZXJhdGl2ZSBFcnJvcnMiKSkgKwogIGxhYnMoY2FwdGlvbiA9IHN0cl93cmFwKCJGSUdVUkUgNjogQ2hhbmdlIGluIHBvaW50IGVzdGltYXRlcyBvZiBJQ0MgZm9yIHRocmVlIGRlcGVuZGVudCBtZWFzdXJlcyBzZWxlY3RlZCBmcm9tIHRoZSBTaGlmdCB0YXNrIHVzaW5nIGluY3JlYXNpbmcgbnVtYmVycyBvZiB0cmlhbHMgdG8gZXN0aW1hdGUgdGhlbS4gVGhlc2UgbWVhc3VyZXMgc2hvdyB0aGUgZGlmZmVyZW50IHR5cGVzIG9mIHJlbGF0aW9uc2hpcHMgcmVsaWFiaWxpdHkgZXN0aW1hdGVzIGhhdmUgYmFzZWQgb24gdGhlIHRyaWFsIG51bWJlcnMgdXNlZCB0byBlc3RpbWF0ZSB0aGVtLiIsIHdpZHRoID0gMTgwKSkKYGBgCgojIyMgUmF3IHZzIERETQoKQ2hlY2tpbmcgRERNIHJlc3VsdHMgaW4gdGhlIGJvb3RzdHJhcHBlZCBlc3RpbWF0ZXMuIFZhcmlhYmxlcyB1c2luZyBhbGwgdHJpYWxzIGFyZSBzaWduaWZpY2FudGx5IG1vcmUgcmVsaWFibGUgY29tcGFyZWQgdG8gZGlmZmVyZW5jZSBzY29yZXMuIFJhdyBtZWFzdXJlcyBkb24ndCBkaWZmZXIgZnJvbSBERE0gcGFyYW1ldGVycy4gV2hpY2ggRERNIGlzIGJldHRlciBkZXBlbmRzIG9uIHdoZXRoZXIgYWxsIHRyaWFscyBhcmUgdXNlZC4KCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnRtcCA9IG1lYXN1cmVfbGFiZWxzICU+JQogIG11dGF0ZShkdiA9IGFzLmNoYXJhY3RlcihkdiksCiAgICAgICAgIGNvbnRyYXN0ID0gaWZlbHNlKG92ZXJhbGxfZGlmZmVyZW5jZSA9PSAiZGlmZmVyZW5jZSIsICJjb250cmFzdCIsICJub24tY29udHJhc3QiKSkgJT4lCiAgZmlsdGVyKGRkbV90YXNrID09IDEsCiAgICAgICAgIHJ0X2FjYyAhPSAnb3RoZXInKSAlPiUKICBkcm9wX25hKCkgJT4lCiAgIyBsZWZ0X2pvaW4oYm9vdF9kZlssYygiZHYiLCAiaWNjMi4xIildLCBieSA9ICdkdicpCiAgbGVmdF9qb2luKHJlbF9kZlssYygiZHYiLCAiaWNjMi4xIildLCBieSA9ICdkdicpCgp0bXBfc2F2ZSA9IHRtcCAlPiUKICBkcm9wX25hKCkgJT4lICN0cnkgcmVtb3ZpbmcgdGhpcyBpbiBmaW5hbCByZWxlYXNlCiAgZ3JvdXBfYnkoY29udHJhc3QsIHJhd19maXQsIHJ0X2FjYykgJT4lCiAgc3VtbWFyaXNlKGljYzIuMV9tZWRpYW4gPSBxdWFudGlsZShpY2MyLjEsIHByb2JzID0gMC41KSwKICAgICAgICAgICAgaWNjMi4xXzIuNSA9IHF1YW50aWxlKGljYzIuMSwgcHJvYnMgPSAwLjAyNSksCiAgICAgICAgICAgIGljYzIuMV85Ny41ID0gcXVhbnRpbGUoaWNjMi4xLCBwcm9icyA9IDAuOTc1KSwKICAgICAgICAgICAgbnVtX3ZhcnMgPSBuKCkvMTAwMCkKCnRtcF9zYXZlICU+JQogIGRhdGF0YWJsZSgpICU+JQogIGZvcm1hdFJvdW5kKGNvbHVtbnM9YygnaWNjMi4xX21lZGlhbicsICdpY2MyLjFfMi41JywgJ2ljYzIuMV85Ny41JyksIGRpZ2l0cz0zKQpgYGAKCkNvbXBhcmluZyBjb250cmFzdCB2cyBub24tY29udHJhc3Q6IG92ZXJhbGwgaGFzIGhpZ2hlciByZWxpYWJpbGl0eSB0aGFuIGRpZmZlcmVuY2UuCgpgYGB7cn0KIyBzdW1tYXJ5KGxtZXJUZXN0OjpsbWVyKGljYzIuMSB+IGNvbnRyYXN0ICsgKDF8ZHYpICx0bXApKQojIHN1bW1hcnkoTUNNQ2dsbW0oaWNjMi4xIH4gY29udHJhc3QsIHJhbmRvbSA9IH4gZHYsIGRhdGE9dG1wLCB2ZXJib3NlPUZBTFNFKSkKc3VtbWFyeShNQ01DZ2xtbShpY2MyLjEgfiBjb250cmFzdCwgZGF0YT10bXAsIHZlcmJvc2U9RkFMU0UpKQpgYGAKCkNvbXBhcmluZyByYXcgdnMgZGRtIGluIG92ZXJhbGwgZXN0aW1hdGVzOiBFWiBpcyBzaWduaWZpY2FudGx5IGJldHRlciB0aGFuIEhERE0gYW5kIGNvbXBhcmFibGUgdG8gcmF3IGVzdGltYXRlcy4KCmBgYHtyfQojIHN1bW1hcnkoaWNjMi4xX2J5X3Jhd2ZpdF9ub25jb25fbW9kZWwpCnN1bW1hcnkoTUNNQ2dsbW0oaWNjMi4xIH4gcmF3X2ZpdCwgZGF0YT10bXAgJT4lIGZpbHRlcihjb250cmFzdCA9PSAibm9uLWNvbnRyYXN0IiksIHZlcmJvc2U9RkFMU0UpKQpgYGAKCkNvbXBhcmluZyByYXcgdnMgZGRtIGluIGRpZmZlcmVuY2Ugc2NvcmVzOiBFWiBpcyBzaWduaWZpY2FudGx5IHdvcnNlIHRoYW4gSERETSBhbmQgY29tcGFyYWJsZSB0byByYXcgZXN0aW1hdGVzLgoKYGBge3J9CiMgc3VtbWFyeShpY2MyLjFfYnlfcmF3Zml0X2Nvbl9tb2RlbCkKc3VtbWFyeShNQ01DZ2xtbShpY2MyLjEgfiByYXdfZml0LCBkYXRhPXRtcCAlPiUgZmlsdGVyKGNvbnRyYXN0ID09ICJjb250cmFzdCIpLCB2ZXJib3NlPUZBTFNFKSkKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpybShpY2NfYnlfcmF3Zml0X2Nvbl9tb2RlbCwgaWNjX2J5X3Jhd2ZpdF9ub25jb25fbW9kZWwpCmBgYAoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPScxMDAlJ30KZmlnX25hbWUgPSAnQm9vdHN0cmFwX0RETV9Db21wX0xlZ2VuZC5qcGVnJwoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MocGFzdGUwKGZpZ19wYXRoLCBmaWdfbmFtZSkpCmBgYAoKYGBge3J9CnRtcCAlPiUKICBncm91cF9ieShjb250cmFzdCkgJT4lCiAgc3VtbWFyaXNlKG1lYW5faWNjMi4xID0gbWVhbihpY2MyLjEpLAogICAgICAgICAgICBzZF9pY2MyLjEgPSBzZChpY2MyLjEpKQpgYGAKCmBgYHtyIGVjaG89RkFMU0UsIG91dC53aWR0aD0nMTAwJSd9CmZpZ19uYW1lID0gJ1BvaW50RXN0X0RETV9Db21wLmpwZWcnCgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhwYXN0ZTAoZmlnX3BhdGgsIGZpZ19uYW1lKSkKYGBgCgojIyBTdXJ2ZXkgcmVsaWFiaWxpdGllcwoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KdG1wID0gbWVhc3VyZV9sYWJlbHMgJT4lCiAgbXV0YXRlKGR2ID0gYXMuY2hhcmFjdGVyKGR2KSkgJT4lCiAgZmlsdGVyKHRhc2sgPT0gJ3N1cnZleScpICU+JQogICMgbGVmdF9qb2luKGJvb3RfZGZbLGMoImR2IiwgImljYzIuMSIpXSwgYnkgPSAnZHYnKSAlPiUKICBsZWZ0X2pvaW4ocmVsX2RmWyxjKCJkdiIsICJpY2MyLjEiKV0sIGJ5ID0gJ2R2JykgJT4lCiAgc2VwYXJhdGUoZHYsIGMoJ3Rhc2tfbmFtZScsICdleHRyYV8xJywgJ2V4dHJhXzInKSwgc2VwID0gJ1xcLicscmVtb3ZlPUZBTFNFKSAlPiUKICBzZWxlY3QoLWV4dHJhXzEsIC1leHRyYV8yKQoKdG1wX3NhdmUgPSB0bXAgJT4lCiAgZ3JvdXBfYnkodGFza19uYW1lKSAlPiUKICBzdW1tYXJpc2UobWVkaWFuX2ljYzIuMSA9IG1lZGlhbihpY2MyLjEpLAogICAgICAgICAgICBpY2MyLjFfMi41ID0gcXVhbnRpbGUoaWNjMi4xLCBwcm9icyA9IDAuMDI1KSwKICAgICAgICAgICAgaWNjMi4xXzk3LjUgPSBxdWFudGlsZShpY2MyLjEsIHByb2JzID0gMC45NzUpLAogICAgICAgICAgICBudW1fbWVhc3VyZXMgPSBuKCkvMTAwMCwKICAgICAgICAgICAgbWVhbl9udW1fdHJpYWxzID0gcm91bmQobWVhbihudW1fYWxsX3RyaWFscykpKSU+JQogIGFycmFuZ2UoLW1lZGlhbl9pY2MyLjEpCgp0bXBfc2F2ZSAlPiUKICBkYXRhdGFibGUoKSAlPiUKICBmb3JtYXRSb3VuZChjb2x1bW5zPWMoJ21lZGlhbl9pY2MyLjEnLCAnaWNjMi4xXzIuNScsJ2ljYzIuMV85Ny41JyksIGRpZ2l0cz0zKQpgYGAKCiMjIyBOdW1iZXIgb2YgaXRlbXMKCkRvZXMgbnVtYmVyIG9mIGl0ZW1zIGluIGEgc3VydmV5IGhhdmUgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gdGhlIGF2ZXJhZ2UgaWNjMi4xIG9mIHN1cnZleSBtZWFzdXJlcz8gTm8uCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIHN1bW1hcnkobG1lclRlc3Q6OmxtZXIoaWNjMi4xIH4gbnVtX2FsbF90cmlhbHMgKyAoMXxkdiksIGRhdGEgPSB0bXApKQpzdW1tYXJ5KE1DTUNnbG1tKGljYzIuMSB+IG51bV9hbGxfdHJpYWxzLCBkYXRhPXRtcCwgdmVyYm9zZT1GQUxTRSkpCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KdG1wICU+JQogIGdncGxvdChhZXMobnVtX2FsbF90cmlhbHMsIGljYzIuMSkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikrCiAgdGhlbWVfYncoKSsKICB4bGFiKCJOdW1iZXIgb2YgdHJpYWxzIikrCiAgeWxhYigiaWNjMi4xIikKYGBgCg==