1 Summary

This document details the analyses reported in The effects of bidialectalism on executive function (Poarch, Vanhove & Berthele). For this study, Simon and flanker data of 34 participants who also filled out a Bilingual Language Profile for Standard German and the Swabian dialect were analysed.

Note: Participant 108 was removed since he wasn’t bidialectal.

The main points are summarised here:

  1. For the main analyses, we re-expressed the individual response latencies (ms) as response speeds (stimuli/s). For instance, a response latency of 333 ms corresponds to 3 stimuli per second. Re-expressing latencies as speeds results in a more normal-ish distribution of responses, and response speeds are also readily interpretable. For follow-up analyses (Chapter “A multiverse analysis”), we also considered latency-based analyses (both raw latencies and log-transformed latencies).

  2. For the main analyses, we did not exclude incorrect responses (of which there are very few) or responses that are too fast or too slow as no exclusion criteria were formulated beforehand. For follow-up analyses (Chapter “A multiverse analysis”), we also considered excluding incorrect responses, responses faster than a given threshold, or responses too far away from the participant’s or overall mean.

  3. Similarly, we have a choice in how to express the predictor variable (language dominance). See paper on this.

  4. We didn’t consider education level and Raven performance as covariates since these may be post-treatment variables: if bidialectalism affects executive function, it may directly or indirectly affect Raven and Education, too.

  5. Please note that the possible predictor variables are correlated (item 5) as are the flanker and Simon effects (Chapter “Correlation between flanker and Simon effects”). As a result, the different analyses are not independent from one another: If two different analyses produce similar results, this doesn’t carry the same weight as when two independent experiments produce a similar result. This is important to keep in mind when interpreting the results.

  6. We also conducted a multiverse analysis. For this, we automatically analysed the data according to all possible sensible combinations of choices we have (how to transform the data, whether to exclude outliers, etc.). You find the results at the bottom of the page. The take-home point here is that slightly different, but sensible choices in the analysis can yield substantially different results (here: p-values).

2 Settings and packages

This code empties the workspace, overrides some R defaults (nothing too important) and loads the packages used in the analysis. To install the packages, run install.packages("packageName").

# EMPTYING WORKSPACE!!
rm(list = ls())
# R settings
options(digits = 4, # fewer digits in output
        show.signif.stars = FALSE, # no significance stars
        na.action = na.fail) # explicit error for missing data
# Load packages
# see bottom of page for versions and sources
library(ggplot2)  # for plotting
library(cowplot)  # ..
library(dplyr)    # for working with dataframes
library(tidyr)    # ..
library(magrittr) # for writing more transparent code
library(lme4)     # for mixed-effects models
library(mgcv)     # for generalised additive models
library(pbkrtest) # for bootstrapping mixed-effects models
# Set default plotting theme
theme_set(theme_cowplot(10))

Software versions:

devtools::session_info()
Session info -----------------------------------------------------------------------------------------------------------------------------
 setting  value                       
 version  R version 3.3.2 (2016-10-31)
 system   x86_64, linux-gnu           
 ui       RStudio (1.0.143)           
 language en_US                       
 collate  en_US.UTF-8                 
 tz       Europe/Brussels             
 date     2017-07-03                  
Packages ---------------------------------------------------------------------------------------------------------------------------------
 package    * version    date       source                         
 assertthat   0.2.0      2017-04-11 cran (@0.2.0)                  
 base       * 3.3.2      2016-11-01 local                          
 colorspace   1.3-2      2016-12-14 cran (@1.3-2)                  
 cowplot    * 0.7.0      2016-10-28 CRAN (R 3.3.2)                 
 datasets   * 3.3.2      2016-11-01 local                          
 DBI          0.6-1      2017-04-01 cran (@0.6-1)                  
 devtools     1.13.1     2017-05-13 CRAN (R 3.3.2)                 
 digest       0.6.12     2017-01-27 cran (@0.6.12)                 
 dplyr      * 0.5.0      2016-06-24 CRAN (R 3.3.1)                 
 ggplot2    * 2.2.1.9000 2017-05-09 Github (hadley/ggplot2@f4398b6)
 graphics   * 3.3.2      2016-11-01 local                          
 grDevices  * 3.3.2      2016-11-01 local                          
 grid         3.3.2      2016-11-01 local                          
 gtable       0.2.0      2016-02-26 CRAN (R 3.3.0)                 
 knitr        1.16       2017-05-18 CRAN (R 3.3.2)                 
 lattice      0.20-35    2017-03-25 CRAN (R 3.3.2)                 
 lazyeval     0.2.0      2016-06-12 CRAN (R 3.3.1)                 
 lme4       * 1.1-14     2017-05-23 Github (lme4/lme4@245b16e)     
 magrittr   * 1.5        2014-11-22 CRAN (R 3.3.1)                 
 MASS         7.3-45     2015-11-10 CRAN (R 3.2.5)                 
 Matrix     * 1.2-8      2017-01-20 CRAN (R 3.3.2)                 
 memoise      1.1.0      2017-04-21 CRAN (R 3.3.2)                 
 methods    * 3.3.2      2016-11-01 local                          
 mgcv       * 1.8-16     2016-11-07 CRAN (R 3.3.2)                 
 minqa        1.2.4      2014-10-09 CRAN (R 3.3.0)                 
 munsell      0.4.3      2016-02-13 CRAN (R 3.3.0)                 
 nlme       * 3.1-131    2017-02-06 CRAN (R 3.3.2)                 
 nloptr       1.0.4      2014-08-04 CRAN (R 3.3.0)                 
 parallel     3.3.2      2016-11-01 local                          
 pbkrtest   * 0.4-7      2017-03-15 cran (@0.4-7)                  
 plyr         1.8.4      2016-06-08 cran (@1.8.4)                  
 R6           2.2.1      2017-05-10 CRAN (R 3.3.2)                 
 Rcpp         0.12.11    2017-05-22 cran (@0.12.11)                
 rlang        0.1.1      2017-05-18 cran (@0.1.1)                  
 scales       0.4.1      2016-11-09 cran (@0.4.1)                  
 splines      3.3.2      2016-11-01 local                          
 stats      * 3.3.2      2016-11-01 local                          
 tibble       1.3.3      2017-05-28 CRAN (R 3.3.2)                 
 tidyr      * 0.6.3      2017-05-15 CRAN (R 3.3.2)                 
 tools        3.3.2      2016-11-01 local                          
 utils      * 3.3.2      2016-11-01 local                          
 withr        1.0.2      2016-06-20 cran (@1.0.2)                  

3 Read in data

Read in the Simon and flanker data.

# Read in flanker/Simon data
dat <- read.csv("bidialectalism_ef.csv")
# Recode Subject as factor
dat$Subject <- factor(dat$Subject)
# Remove subject 108 (not bidialectal)
dat <- dat %>% 
  filter(Subject != "108")
summary(dat)
    Subject          SessionDate       Block          Task          Trial     PresentationFlanker.ACC PresentationFlanker.RT
 100    :  384   05-14-2015:1920   Min.   :1.0   Flanker:6528   Min.   :  9   Min.   :0               Min.   : 232          
 101    :  384   06-16-2015:1536   1st Qu.:1.0   Simon  :6528   1st Qu.: 60   1st Qu.:1               1st Qu.: 370          
 102    :  384   07-02-2015:1536   Median :1.5                  Median :108   Median :1               Median : 416          
 103    :  384   05-12-2015:1152   Mean   :1.5                  Mean   :108   Mean   :1               Mean   : 442          
 104    :  384   05-13-2015:1152   3rd Qu.:2.0                  3rd Qu.:156   3rd Qu.:1               3rd Qu.: 480          
 105    :  384   06-09-2015:1152   Max.   :2.0                  Max.   :216   Max.   :1               Max.   :1901          
 (Other):10752   (Other)   :4608                                              NA's   :6528            NA's   :6528          
 PresentationSimon.ACC PresentationSimon.RT         Status     TrialsFlanker.Cycle TrialsFlanker.Sample TrialsSimon.Sample       RT      
 Min.   :0             Min.   : 212         congruent  :6528   Min.   :1           Min.   :  1          Min.   :  1        Min.   : 212  
 1st Qu.:1             1st Qu.: 335         incongruent:6528   1st Qu.:1           1st Qu.: 49          1st Qu.: 49        1st Qu.: 352  
 Median :1             Median : 385                            Median :1           Median : 96          Median : 96        Median : 401  
 Mean   :1             Mean   : 417                            Mean   :1           Mean   : 96          Mean   : 96        Mean   : 430  
 3rd Qu.:1             3rd Qu.: 453                            3rd Qu.:1           3rd Qu.:144          3rd Qu.:144        3rd Qu.: 468  
 Max.   :1             Max.   :5851                            Max.   :1           Max.   :192          Max.   :192        Max.   :5851  
 NA's   :6528          NA's   :6528                            NA's   :6528        NA's   :6528         NA's   :6528                     
    Accuracy    
 Min.   :0.000  
 1st Qu.:1.000  
 Median :1.000  
 Mean   :0.983  
 3rd Qu.:1.000  
 Max.   :1.000  
                

Brief explanation of the variables:

The following code adds the variable TrialNumber, i.e., trial number regardless of the task, for convenience:

dat$TrialNumber <- ifelse(dat$Task == "Flanker",
                          dat$TrialsFlanker.Sample,
                          dat$TrialsSimon.Sample)

There was a self-paced break between the 64th and 65th as well as between the 128th and 129th trial. The following code adds this information:

dat$BlockInTask <- cut(dat$TrialNumber, c(0, 64, 128, 192))

4 Response latency distribution and transformation

As could be expected, the response latencies were right skewed.

ggplot(dat,
       aes(x = RT)) +
  geom_histogram(colour = "lightgrey", fill = "red3", binwidth = 100) +
  xlab("Response latency in ms") +
  ylab("Number of observations") +
  facet_wrap(~ Task + Status, scales = "free_x")

Dotcharts (RTs sorted from low to high by task by participants):

ggplot(dat,
       aes(x = RT,
           y = rank(RT))) +
  geom_point(pch = 1, size = 0.3) +
  facet_grid(Subject ~ Task, scales = "free") +
  theme(axis.text.y  = element_blank(),
        axis.ticks.y = element_blank())

Across all tasks and conditions, only 0.54 % of the response latencies were faster than 250 ms, and 5.9 % were faster than 300 ms. The table below shows the percentage of response latencies under 250 ms per task per condition.

dat %>% 
  group_by(Task, Status) %>% 
  summarise(PercentUnder250ms = (mean(RT < 250) * 100) %>% signif(2))

In light of the (anticipated) positive skew, it makes sense to transform the response latencies to response speeds (inverse transformation). Instead of answering the question How much milliseconds does it take to respond to a stimulus?, this answers the (equivalent) question How many stimuli can be responded to in one second?. Note that higher values now mean faster responses.

# Inverse transformation * 1000 (milliseconds to seconds)
dat$Speed <- 1000/dat$RT
ggplot(dat,
       aes(x = Speed)) +
  geom_histogram(colour = "lightgrey", fill = "red3", binwidth = 0.2) +
  xlab("Response speed (stimuli/s)") +
  ylab("Number of observations") +
  facet_wrap(~ Task + Status, scales = "free")

This already looks much better.

We did not decide on a latency/speed-based outlier criterion beforehand, since the idea was to use this dataset to pick such criteria for a larger study. For this reason, we will not exclude any observations at this stage.

ggplot(dat,
       aes(x = Speed,
           y = rank(Speed))) +
  geom_point(pch = 1, size = 0.5) +
  facet_grid(Subject ~ Task, scales = "free") +
  theme(axis.text.y  = element_blank(),
        axis.ticks.y = element_blank())

We also tried another common RT transformation, viz. the logarithmic transformation. This retained some of the right skew, however (plots below), and seems to necessitate the exclusion of long outliers:

ggplot(dat,
       aes(x = log10(RT))) +
  geom_histogram(colour = "lightgrey", fill = "red3", binwidth = 0.1) +
  xlab("log10 response speed (log10 ms)") +
  ylab("Number of observations") +
  facet_wrap(~ Task + Status, scales = "free")

5 Accuracy distribution

Overall, 98.3 % of the responses provided were accurate. The table below shows their breakdown by task and condition.

dat %>% 
  group_by(Task, Status) %>% 
  summarise(`Percentage of accurate responses` = (mean(Accuracy) * 100) %>% signif(3))

Or per participant:

dat %>% 
  group_by(Task, Status, Subject) %>% 
  summarise(`Accuracy` = (mean(Accuracy) * 100)) %>%
  group_by(Task, Status) %>% 
  summarise(`Mean` = mean(Accuracy),
            `SD` = sd(Accuracy),
            `Minimum` = min(Accuracy),
            `Maximum` = max(Accuracy))

For now, we will not exclude incorrect responses from the dataset, but we will later check whether there is any suggestion of a speed–accuracy trade-off.

6 Simon and flanker effects and their correlation

The following code calculates mean and median response speeds as well as the proportion of correct responses by congruence status and task for each participant. Then these summaries are used to compute Simon and flanker effects as both difference (\(\textrm{speed congruent} - \textrm{speed incongruent}\)) and ratio scores (\(\frac{\textrm{speed congruent}}{\textrm{speed incongruent}}\)).

6.1 Computing the effects

See source code.

6.2 Visualising the flanker and Simon effects

Below we have plotted the mean response speed in the congruent condition per participant versus the difference in mean response speed between the congruent and the incongruent condition per participant for both the flanker and Simon tasks. The smaller the difference (\(y\)-axis), the smaller the flanker/Simon effect, which is suggestive of more cognitive control.

Note that there may be some trend towards greater flanker/Simon effects for participants that responsed faster in the congruent condition (the trend lines go up). A straightforward explanation for this is regression to the mean: fast responders in the congruent condition are also fast responders in the incongruent condition, but the prediction is imperfect. Note, also, that there is considerable uncertainty about this trend (the 95% confidence bands are wide).

The dashed lines mark the zero-difference line. Dots above this line indicate participants with flanker/Simon effects that go in the direction expected. For the flanker task, 33 out of 34 participants showed the expected positive effect; for the Simon task, 28 out of 34 did.

ggplot(perPart,
       aes(x = meanSpeedCongruent,
           y = meanSpeedDiff)) +
  geom_point(pch = 1) +
  xlab("Mean response speed (stimuli/s) in congruent condition") +
  ylab("Difference in mean response speeds\n(congruent - incongruent)") +
  facet_wrap(~ Task, scales = "free") +
  geom_smooth(method = "lm") +
  geom_hline(yintercept = 0, lty = 2)

Summary table:

perPart %>% 
  group_by(Task) %>% 
  summarise(mean(meanSpeedCongruent),
            sd(meanSpeedCongruent),
            min(meanSpeedCongruent),
            max(meanSpeedCongruent),
            mean(meanSpeedIncongruent),
            sd(meanSpeedIncongruent),
            min(meanSpeedIncongruent),
            max(meanSpeedIncongruent),
            mean(meanSpeedDiff),
            sd(meanSpeedDiff),
            min(meanSpeedDiff),
            max(meanSpeedDiff))

6.2.1 Speed-accuracy trade-off?

Accuracy is above 90% for all participants in both tasks. Scatterplots of accuracy vs. mean response speed do not suggest a speed–accuracy trade-off.

ggplot(perPart,
       aes(x = (AccuracyCongruent + AccuracyIncongruent)/2,
           y = (meanSpeedIncongruent + meanSpeedCongruent)/2)) +
  geom_point(pch = 1) +
  geom_smooth(method = "lm") +
  xlab("Accuracy") +
  ylab("Mean response speed\n(stimuli/s)") +
  facet_wrap(~ Task, scales = "free")

ggplot(perPart,
       aes(x = AccuracyCongruent,
           y = meanSpeedCongruent)) +
  geom_point(pch = 1) +
  geom_smooth(method = "lm") +
  xlab("Accuracy congruent") +
  ylab("Congruent response speed\n(stimuli/s)") +
  facet_wrap(~ Task, scales = "free")

ggplot(perPart,
       aes(x = AccuracyIncongruent,
           y = meanSpeedIncongruent)) +
  geom_point(pch = 1) +
  geom_smooth(method = "lm") +
  xlab("Accuracy incongruent") +
  ylab("Incongruent response speed\n(stimuli/s)") +
  facet_wrap(~ Task, scales = "free")

6.3 Correlation between flanker and Simon effects

The scatterplot below shows how the participants’ Simon and flanker effects are correlated.

ggplot(perPart %>% 
         select(Subject, Task, meanSpeedDiff) %>%  
         spread(Task, meanSpeedDiff),
       aes(x = Simon, y = Flanker)) +
  geom_point(pch = 1) +
  geom_smooth(method = "gam", formula = y ~ s(x)) +
  xlab("Simon effect\n(mean speed difference congruent-incongruent, stimuli/s)") +
  ylab("Flanker effect\n(mean speed difference congruent-incongruent, stimuli/s)")

The correlation between the Simon and flanker effects expressed as mean speed differences is r = 0.46.

7 Standard–dialect dominance

7.1 Computation of dominance values

Here we calculate the dominance values on the basis of the questionnaire data. Missing/non-stated data were marked as NA, and we used a ceiling of 20 years for the first two questions ( When did you start learning language X?, From what age onwards did you feel comfortable in language X? ).

# Read in raw questionnaire data
questionnaire <- read.csv("bidialectalism_q.csv")
questionnaire$Subject <- factor(questionnaire$Subject)
# Summary of all variables
summary(questionnaire)
    Subject       valid            Age           Sex       Education      X1_DE_AoA       X1_SW_AoA       X2_Age_DE      X2_Age_SW    
 100    : 1   Min.   :0.000   Min.   :16.0   female:15   Min.   :1.00   Min.   : 0.00   Min.   : 0.00   Min.   : 0.0   Min.   : 0.00  
 101    : 1   1st Qu.:1.000   1st Qu.:19.0   male  :20   1st Qu.:2.00   1st Qu.: 0.00   1st Qu.: 0.00   1st Qu.: 6.0   1st Qu.: 3.00  
 102    : 1   Median :1.000   Median :22.0               Median :3.00   Median : 3.00   Median : 1.00   Median :12.0   Median : 5.00  
 103    : 1   Mean   :0.971   Mean   :22.5               Mean   :3.09   Mean   : 3.43   Mean   : 2.52   Mean   :12.1   Mean   : 4.67  
 104    : 1   3rd Qu.:1.000   3rd Qu.:26.0               3rd Qu.:4.00   3rd Qu.: 6.00   3rd Qu.: 2.00   3rd Qu.:17.5   3rd Qu.: 6.00  
 105    : 1   Max.   :1.000   Max.   :29.0               Max.   :5.00   Max.   :12.00   Max.   :16.00   Max.   :24.0   Max.   :10.00  
 (Other):29                                                                             NA's   :1                      NA's   :8      
 X4_Country_DE  X4_Country_SW    X5_Fam_DE      X5_Fam_SW      X6_Job_DE       X6_Job_SW     X7a_DE_SpeakFri X7b_SW_SpeakFri
 Min.   :16.0   Min.   : 0.0   Min.   : 0.0   Min.   : 0.0   Min.   : 0.00   Min.   : 0.00   Min.   :0.000   Min.   :0.000  
 1st Qu.:19.0   1st Qu.:17.5   1st Qu.: 0.0   1st Qu.:17.0   1st Qu.: 0.00   1st Qu.: 0.00   1st Qu.:0.025   1st Qu.:0.325  
 Median :22.0   Median :22.0   Median :16.0   Median :22.0   Median : 1.00   Median : 0.00   Median :0.250   Median :0.700  
 Mean   :22.4   Mean   :21.0   Mean   :11.5   Mean   :18.8   Mean   : 2.54   Mean   : 2.03   Mean   :0.336   Mean   :0.616  
 3rd Qu.:26.0   3rd Qu.:26.0   3rd Qu.:21.5   3rd Qu.:26.0   3rd Qu.: 3.50   3rd Qu.: 2.50   3rd Qu.:0.550   3rd Qu.:0.975  
 Max.   :29.0   Max.   :29.0   Max.   :28.0   Max.   :29.0   Max.   :12.00   Max.   :12.00   Max.   :0.980   Max.   :1.000  
                                                                                                                            
 X8a_DE_SpeakFam X8b_SW_SpeakFam X9a_DE_Job.Uni  X9b_SW_Job.Uni  X10a_DE_SpeakSelf X10b_SW_SpeakSelf X11a_DE_Count   X11b_SW_Count  
 Min.   :0.000   Min.   :0.000   Min.   :0.000   Min.   :0.000   Min.   :0.000     Min.   :0.000     Min.   :0.000   Min.   :0.000  
 1st Qu.:0.000   1st Qu.:0.600   1st Qu.:0.175   1st Qu.:0.100   1st Qu.:0.000     1st Qu.:0.335     1st Qu.:0.100   1st Qu.:0.025  
 Median :0.100   Median :0.900   Median :0.500   Median :0.350   Median :0.300     Median :0.600     Median :0.500   Median :0.400  
 Mean   :0.256   Mean   :0.744   Mean   :0.460   Mean   :0.424   Mean   :0.292     Mean   :0.604     Mean   :0.465   Mean   :0.434  
 3rd Qu.:0.400   3rd Qu.:1.000   3rd Qu.:0.725   3rd Qu.:0.800   3rd Qu.:0.475     3rd Qu.:1.000     3rd Qu.:0.800   3rd Qu.:0.850  
 Max.   :1.000   Max.   :1.000   Max.   :1.000   Max.   :1.000   Max.   :0.980     Max.   :1.000     Max.   :1.000   Max.   :1.000  
                                                                                                                                    
  X12_DE_Speak   X12_SW_Speak   X13_DE_Under   X13_SW_Under      Raven       X3_Years_DE    X3_Years_SW  X14_DE_Read    X14_SW_Read  
 Min.   :1.00   Min.   :0.00   Min.   :1.00   Min.   :0.00   Min.   : 5.0   Min.   : 8.0   Min.   : 0   Min.   :2.00   Min.   :0.00  
 1st Qu.:3.50   1st Qu.:4.00   1st Qu.:6.00   1st Qu.:5.00   1st Qu.:11.0   1st Qu.:11.0   1st Qu.: 0   1st Qu.:6.00   1st Qu.:3.00  
 Median :5.00   Median :5.00   Median :6.00   Median :6.00   Median :13.0   Median :12.0   Median : 0   Median :6.00   Median :4.00  
 Mean   :4.36   Mean   :4.66   Mean   :5.77   Mean   :5.09   Mean   :12.7   Mean   :12.5   Mean   : 1   Mean   :5.69   Mean   :3.97  
 3rd Qu.:5.00   3rd Qu.:6.00   3rd Qu.:6.00   3rd Qu.:6.00   3rd Qu.:15.0   3rd Qu.:13.0   3rd Qu.: 0   3rd Qu.:6.00   3rd Qu.:5.00  
 Max.   :6.00   Max.   :6.00   Max.   :6.00   Max.   :6.00   Max.   :17.0   Max.   :18.0   Max.   :12   Max.   :6.00   Max.   :6.00  
                                                                                           NA's   :2                                 
  X15_DE_Write   X15_SW_Write
 Min.   :2.00   Min.   :0.0  
 1st Qu.:4.50   1st Qu.:2.5  
 Median :5.00   Median :4.0  
 Mean   :5.13   Mean   :3.6  
 3rd Qu.:6.00   3rd Qu.:5.0  
 Max.   :6.00   Max.   :6.0  
                             

Note that there are a couple of missing values:

  • X1_SW_AoA. Age of acquisition of Swabian: One participant never learnt Swabian and doesn’t qualify as a bidialectal. Remove his data.
questionnaire <- questionnaire %>% 
  filter(!is.na(X1_SW_AoA))
  • X2_Age_SW. Question: Ab welchem Alter haben Sie sich in den folgenden Sprachen sicher gefühlt?

One option would be to impute missing values with the group mean, but that wouldn’t seem to make much sense as it would mean that the participants felt comfortable in Swabian before having acquired it:

questionnaire %>% select(X1_SW_AoA, X2_Age_SW) %>% filter(is.na(X2_Age_SW))

Using the maximum possible response (20) makes more sense to me.

questionnaire$X2_Age_SW2 <- questionnaire$X2_Age_SW
# replace by maximum (20)
questionnaire$X2_Age_SW2[is.na(questionnaire$X2_Age_SW2)] <- 20
  • X3_Years_SW. Question: Wie viele Jahre hatten Sie Unterricht in den folgenden Sprachen? (Grundschule, weiterführende Schule, Hochschule)?. In all likelihood, this would be 0 for Swabian.
questionnaire$X3_Years_SW2 <- questionnaire$X3_Years_SW
questionnaire$X3_Years_SW2[is.na(questionnaire$X3_Years_SW2)] <- 0

Note, however, that 3 participants provided non-zero responses, suggesting that they may have interpreted the question differently from other participants: schooling in Swabian just doesn’t exist.

Here we replace non-zero values with 0 for this question.

questionnaire$X3_Years_SW2[questionnaire$X3_Years_SW2 > 0] <- 0
  • The maximum for X4_Country_DE, X4_Country_SW, X5_Fam_DE, X5_Fam_SW should be 20.
questionnaire$X4_Country_DE[questionnaire$X4_Country_DE > 20] <- 20
questionnaire$X4_Country_SW[questionnaire$X4_Country_SW > 20] <- 20
questionnaire$X5_Fam_DE[questionnaire$X5_Fam_DE > 20] <- 20
questionnaire$X5_Fam_SW[questionnaire$X5_Fam_SW > 20] <- 20
summary(questionnaire)
    Subject       valid        Age           Sex       Education      X1_DE_AoA       X1_SW_AoA       X2_Age_DE       X2_Age_SW    
 100    : 1   Min.   :1   Min.   :16.0   female:15   Min.   :1.00   Min.   : 0.00   Min.   : 0.00   Min.   : 0.00   Min.   : 0.00  
 101    : 1   1st Qu.:1   1st Qu.:19.0   male  :19   1st Qu.:2.00   1st Qu.: 0.25   1st Qu.: 0.00   1st Qu.: 6.25   1st Qu.: 3.00  
 102    : 1   Median :1   Median :22.0               Median :3.00   Median : 3.00   Median : 1.00   Median :12.00   Median : 5.00  
 103    : 1   Mean   :1   Mean   :22.6               Mean   :3.09   Mean   : 3.53   Mean   : 2.52   Mean   :12.27   Mean   : 4.67  
 104    : 1   3rd Qu.:1   3rd Qu.:26.0               3rd Qu.:4.00   3rd Qu.: 6.00   3rd Qu.: 2.00   3rd Qu.:17.75   3rd Qu.: 6.00  
 105    : 1   Max.   :1   Max.   :29.0               Max.   :5.00   Max.   :12.00   Max.   :16.00   Max.   :24.00   Max.   :10.00  
 (Other):28                                                                                                         NA's   :7      
 X4_Country_DE  X4_Country_SW    X5_Fam_DE      X5_Fam_SW      X6_Job_DE       X6_Job_SW     X7a_DE_SpeakFri  X7b_SW_SpeakFri
 Min.   :16.0   Min.   : 0.0   Min.   : 0.0   Min.   : 0.0   Min.   : 0.00   Min.   : 0.00   Min.   :0.0000   Min.   :0.000  
 1st Qu.:19.0   1st Qu.:18.0   1st Qu.: 0.0   1st Qu.:17.0   1st Qu.: 0.00   1st Qu.: 0.00   1st Qu.:0.0125   1st Qu.:0.362  
 Median :20.0   Median :20.0   Median :16.0   Median :20.0   Median : 1.50   Median : 0.00   Median :0.2250   Median :0.700  
 Mean   :19.2   Mean   :18.2   Mean   :10.1   Mean   :16.1   Mean   : 2.62   Mean   : 2.09   Mean   :0.3174   Mean   :0.634  
 3rd Qu.:20.0   3rd Qu.:20.0   3rd Qu.:19.8   3rd Qu.:20.0   3rd Qu.: 3.75   3rd Qu.: 2.75   3rd Qu.:0.5000   3rd Qu.:0.988  
 Max.   :20.0   Max.   :20.0   Max.   :20.0   Max.   :20.0   Max.   :12.00   Max.   :12.00   Max.   :0.9000   Max.   :1.000  
                                                                                                                             
 X8a_DE_SpeakFam X8b_SW_SpeakFam X9a_DE_Job.Uni  X9b_SW_Job.Uni  X10a_DE_SpeakSelf X10b_SW_SpeakSelf X11a_DE_Count   X11b_SW_Count   
 Min.   :0.000   Min.   :0.000   Min.   :0.000   Min.   :0.000   Min.   :0.000     Min.   :0.000     Min.   :0.000   Min.   :0.0000  
 1st Qu.:0.000   1st Qu.:0.625   1st Qu.:0.163   1st Qu.:0.100   1st Qu.:0.000     1st Qu.:0.378     1st Qu.:0.100   1st Qu.:0.0625  
 Median :0.075   Median :0.925   Median :0.450   Median :0.375   Median :0.300     Median :0.600     Median :0.500   Median :0.4000  
 Mean   :0.234   Mean   :0.766   Mean   :0.446   Mean   :0.437   Mean   :0.272     Mean   :0.622     Mean   :0.464   Mean   :0.4465  
 3rd Qu.:0.375   3rd Qu.:1.000   3rd Qu.:0.700   3rd Qu.:0.800   3rd Qu.:0.438     3rd Qu.:1.000     3rd Qu.:0.800   3rd Qu.:0.8750  
 Max.   :1.000   Max.   :1.000   Max.   :1.000   Max.   :1.000   Max.   :0.900     Max.   :1.000     Max.   :1.000   Max.   :1.0000  
                                                                                                                                     
  X12_DE_Speak   X12_SW_Speak   X13_DE_Under   X13_SW_Under      Raven       X3_Years_DE    X3_Years_SW     X14_DE_Read    X14_SW_Read  
 Min.   :1.00   Min.   :1.00   Min.   :1.00   Min.   :2.00   Min.   : 5.0   Min.   : 8.0   Min.   : 0.00   Min.   :2.00   Min.   :0.00  
 1st Qu.:3.25   1st Qu.:4.25   1st Qu.:6.00   1st Qu.:5.00   1st Qu.:11.0   1st Qu.:11.0   1st Qu.: 0.00   1st Qu.:6.00   1st Qu.:3.25  
 Median :5.00   Median :5.00   Median :6.00   Median :6.00   Median :12.5   Median :12.0   Median : 0.00   Median :6.00   Median :4.00  
 Mean   :4.32   Mean   :4.79   Mean   :5.76   Mean   :5.24   Mean   :12.6   Mean   :12.5   Mean   : 1.03   Mean   :5.68   Mean   :4.00  
 3rd Qu.:5.00   3rd Qu.:6.00   3rd Qu.:6.00   3rd Qu.:6.00   3rd Qu.:15.0   3rd Qu.:13.0   3rd Qu.: 0.00   3rd Qu.:6.00   3rd Qu.:5.00  
 Max.   :6.00   Max.   :6.00   Max.   :6.00   Max.   :6.00   Max.   :17.0   Max.   :18.0   Max.   :12.00   Max.   :6.00   Max.   :6.00  
                                                                                           NA's   :2                                    
  X15_DE_Write   X15_SW_Write    X2_Age_SW2     X3_Years_SW2
 Min.   :2.00   Min.   :0.00   Min.   : 0.00   Min.   :0    
 1st Qu.:4.25   1st Qu.:2.25   1st Qu.: 4.00   1st Qu.:0    
 Median :5.00   Median :4.00   Median : 5.00   Median :0    
 Mean   :5.10   Mean   :3.59   Mean   : 7.82   Mean   :0    
 3rd Qu.:6.00   3rd Qu.:5.00   3rd Qu.: 9.50   3rd Qu.:0    
 Max.   :6.00   Max.   :6.00   Max.   :20.00   Max.   :0    
                                                            

Now compute the scores for the different dimensions using the protocol proposed on https://sites.la.utexas.edu/bilingual/scoring-and-interpreting-the-results/. The ProficiencyGermanOral and ProficiencySwabianOral variables don’t take into consideration the participants’ reading and writing skills. For the corresponding TotalGermanOral and TotalSwabianOral variables, the proficiency component was weighted doubly to compensate for this.

questionnaire <- questionnaire %>% 
  mutate(HistoryGerman = (20 - X1_DE_AoA) + (20 - X2_Age_DE) + X3_Years_DE + X4_Country_DE + X5_Fam_DE + X6_Job_DE) %>% 
  mutate(HistorySwabian = (20 - X1_SW_AoA) + (20 - X2_Age_SW2) + X3_Years_SW2 + X4_Country_SW + X5_Fam_SW + X6_Job_SW) %>% 
  mutate(UseGerman = 10 * (X7a_DE_SpeakFri + X8a_DE_SpeakFam + X9a_DE_Job.Uni + X10a_DE_SpeakSelf + X11a_DE_Count)) %>% 
  mutate(UseSwabian = 10 * (X7b_SW_SpeakFri + X8b_SW_SpeakFam + X9b_SW_Job.Uni + X10b_SW_SpeakSelf + X11b_SW_Count)) %>% 
  mutate(ProficiencyGerman = X12_DE_Speak + X13_DE_Under + X14_DE_Read + X15_DE_Write) %>% 
  mutate(ProficiencySwabian = X12_SW_Speak + X13_SW_Under + X14_SW_Read + X15_SW_Write) %>% 
  mutate(ProficiencyGermanOral = X12_DE_Speak + X13_DE_Under) %>% 
  mutate(ProficiencySwabianOral = X12_SW_Speak + X13_SW_Under) %>% 
  mutate(TotalGerman = 0.454*HistoryGerman + 1.09*UseGerman + 2.27*ProficiencyGerman) %>% 
  mutate(TotalSwabian = 0.454*HistorySwabian + 1.09*UseSwabian + 2.27*ProficiencySwabian) %>% 
  mutate(TotalGermanOral = 0.454*HistoryGerman + 1.09*UseGerman + 4.54*ProficiencyGermanOral) %>% 
  mutate(TotalSwabianOral = 0.454*HistorySwabian + 1.09*UseSwabian + 4.54*ProficiencySwabian) %>% 
  mutate(DominanceSwabian = TotalSwabian - TotalGerman) %>% 
  mutate(DominanceSwabianOral = TotalSwabianOral - TotalGermanOral) %>% 
  mutate(DominanceSwabianUse = UseSwabian - UseGerman)

7.2 Distribution of dialect–standard dominance

7.2.1 Overall dominance

Dominance of Swabian, i.e., the participants overall Swabian score minus their overall German score:

ggplot(questionnaire,
       aes(x = DominanceSwabian)) +
  geom_histogram(colour = "lightgrey", fill = "red3", binwidth = 25) +
  scale_y_continuous(breaks = c(0, 3, 6, 9)) +
  xlab("Dominance of Swabian") +
  ylab("Number of participants")

Dominance of Swabian, taking only into account oral – not written – proficiency:

ggplot(questionnaire,
       aes(x = DominanceSwabianOral)) +
  geom_histogram(colour = "lightgrey", fill = "red3", binwidth = 25) +
  scale_y_continuous(breaks = c(0, 3, 6, 9)) +
  xlab("Dominance of Swabian (oral)") +
  ylab("Number of participants")

Dominance of Swabian, considering only the use dimension, not the other dimensions:

ggplot(questionnaire,
       aes(x = DominanceSwabianUse)) +
  geom_histogram(colour = "lightgrey", fill = "red3", bins = 12) +
  scale_y_continuous(breaks = c(0, 3, 6, 9)) +
  xlab("Dominance of Swabian (use)") +
  ylab("Number of participants")

7.3 Total Swabian

Total Swabian score, i.e., not taking into account the participants’ German scores:

ggplot(questionnaire,
       aes(x = TotalSwabian)) +
  geom_histogram(colour = "lightgrey", fill = "red3", bins = 10) +
  scale_y_continuous(breaks = c(0, 3, 6, 9)) +
  xlab("Total Swabian score") +
  ylab("Number of participants")

Total Swabian score, oral skills only:

ggplot(questionnaire,
       aes(x = TotalSwabianOral)) +
  geom_histogram(colour = "lightgrey", fill = "red3", bins = 10) +
  scale_y_continuous(breaks = c(0, 3, 6, 9)) +
  xlab("Total Swabian score (oral only)") +
  ylab("Number of participants")

7.4 Raven

ggplot(questionnaire,
       aes(x = Raven)) +
  geom_histogram(colour = "lightgrey", fill = "red3", binwidth = 2) +
  scale_x_continuous(breaks = c(5, 9, 13, 17)) +
  xlab("Raven score (out of 18") + 
  ylab("Number of participants")

7.5 Table with summary statistics

# Age
questionnaire %>% 
  summarise(mean = mean(Age),
            sd = sd(Age),
            min = min(Age),
            max = max(Age))
# Raven
questionnaire %>% 
  summarise(mean = mean(Raven),
            sd = sd(Raven),
            min = min(Raven),
            max = max(Raven))
# AoA St. German
questionnaire %>% 
  summarise(mean = mean(X1_DE_AoA),
            sd = sd(X1_DE_AoA),
            min = min(X1_DE_AoA),
            max = max(X1_DE_AoA))
# AoA Swabian
questionnaire %>% 
  summarise(mean = mean(X1_SW_AoA),
            sd = sd(X1_SW_AoA),
            min = min(X1_SW_AoA),
            max = max(X1_SW_AoA))
# Proficiency St. German
questionnaire %>% 
  mutate(StandardGerman = (X12_DE_Speak + X13_DE_Under + X14_DE_Read + X15_DE_Write)/4) %>% 
  summarise(mean = mean(StandardGerman),
            sd = sd(StandardGerman),
            min = min(StandardGerman),
            max = max(StandardGerman))
# Proficiency Schwäbisch
questionnaire %>% 
  mutate(Swabian = (X12_SW_Speak + X13_SW_Under)/2) %>% 
  summarise(mean = mean(Swabian),
            sd = sd(Swabian),
            min = min(Swabian),
            max = max(Swabian))
# Use St. German
questionnaire %>% 
  mutate(StandardGerman = (X7a_DE_SpeakFri + X8a_DE_SpeakFam + X9a_DE_Job.Uni)/3) %>% 
  summarise(mean = mean(StandardGerman),
            sd = sd(StandardGerman),
            min = min(StandardGerman),
            max = max(StandardGerman))
# Use Swabian
questionnaire %>% 
  mutate(Swabian = (X7b_SW_SpeakFri + X8b_SW_SpeakFam + X9b_SW_Job.Uni)/3) %>% 
  summarise(mean = mean(Swabian),
            sd = sd(Swabian),
            min = min(Swabian),
            max = max(Swabian))

8 Planned analysis: Relationship between bidialectal dominance and Simon/flanker effects

8.1 Raw dominance

8.1.1 Graph

The expectation at the outset of the study was that the Simon/flanker effects should be lowest for balanced bidialects, i.e., participants whose dominance values are closest to zero.

# Combine datasets
combined <- perPart %>% 
  select(Subject, Task, meanSpeedDiff) %>% 
  full_join(., questionnaire, by = "Subject")
# Plot with DominanceSwabian
p1 <- ggplot(combined,
       aes(x = DominanceSwabian,
           y = meanSpeedDiff)) +
  geom_point(pch = 1) +
  geom_smooth(method = "gam", formula = y ~ s(x, bs = "tp"),
              fill = "grey70",
              colour = "black") +
  facet_wrap(~ Task, scales = "free_y") +
  geom_vline(xintercept = 0, lty = 2, colour = "black") +
  geom_hline(yintercept = 0, lty = 2, colour = "black") +
  xlab("Dominance of Swabian") +
  ylab("Difference in mean speed\n(stimuli/s)")
print(p1)

8.1.2 Models

8.1.2.1 Flanker

# Flanker
FlankerPerPart <- perPart %>% 
  full_join(., questionnaire, by = "Subject") %>% 
  filter(Task == "Flanker")
# GAM: allow DominanceSwabian to have a nonlinear effect
# This corresponds to the scatterplot smoother above
flanker.gam <- gam(meanSpeedDiff ~ s(DominanceSwabian, bs = "tp"),
                 data = FlankerPerPart)
summary(flanker.gam)

Family: gaussian 
Link function: identity 

Formula:
meanSpeedDiff ~ s(DominanceSwabian, bs = "tp")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)   0.2292     0.0181    12.7  5.2e-14

Approximate significance of smooth terms:
                     edf Ref.df   F p-value
s(DominanceSwabian) 1.04   1.09 4.7   0.032

R-sq.(adj) =  0.116   Deviance explained = 14.4%
GCV = 0.011832  Scale est. = 0.011121  n = 34
# edf = 1.04 means that the effect of DominanceSwabian is linear,
# as the scatterplot shows. This is not what was predicted.
# Refit in linear model:
flanker.lm <- lm(meanSpeedDiff ~ DominanceSwabian, data = FlankerPerPart)
summary(flanker.lm)

Call:
lm(formula = meanSpeedDiff ~ DominanceSwabian, data = FlankerPerPart)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.22226 -0.06279  0.00021  0.05844  0.28014 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)
(Intercept)       0.232797   0.018164    12.8  3.8e-14
DominanceSwabian -0.000836   0.000363    -2.3    0.028

Residual standard error: 0.106 on 32 degrees of freedom
Multiple R-squared:  0.142, Adjusted R-squared:  0.115 
F-statistic: 5.29 on 1 and 32 DF,  p-value: 0.0281
# Visual model check:
par(mfrow = c(2, 2))
plot(flanker.lm)
par(mfrow = c(1, 1))

# All of this looks fine.

Conclusion: no evidence for a non-linear trend. Linear trend: \(\hat{\beta} = -0.0008 \pm 0.0004\), \(t(32) = 2.3\), \(p = 0.03\).

8.1.2.2 Simon

# Simon
SimonPerPart <- perPart %>% 
  full_join(., questionnaire, by = "Subject") %>% 
  filter(Task == "Simon")
# GAM: allow DominanceSwabian to have a nonlinear effect
# This corresponds to the scatterplot smoother above
simon.gam <- gam(meanSpeedDiff ~ s(DominanceSwabian, bs = "tp"),
                 data = SimonPerPart)
summary(simon.gam)

Family: gaussian 
Link function: identity 

Formula:
meanSpeedDiff ~ s(DominanceSwabian, bs = "tp")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)   0.1334     0.0193    6.92  7.8e-08

Approximate significance of smooth terms:
                    edf Ref.df    F p-value
s(DominanceSwabian)   1      1 5.74   0.022

R-sq.(adj) =  0.126   Deviance explained = 15.2%
GCV = 0.013432  Scale est. = 0.012642  n = 34
# edf = 1 suggests that the effect of Swabian dominance
# is linear.
simon.lm <- lm(meanSpeedDiff ~ DominanceSwabian,
                 data = SimonPerPart)
summary(simon.lm)

Call:
lm(formula = meanSpeedDiff ~ DominanceSwabian, data = SimonPerPart)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.20956 -0.06982  0.00704  0.07276  0.31447 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)
(Intercept)       0.137374   0.019353     7.1  4.7e-08
DominanceSwabian -0.000928   0.000387    -2.4    0.023

Residual standard error: 0.112 on 32 degrees of freedom
Multiple R-squared:  0.152, Adjusted R-squared:  0.126 
F-statistic: 5.74 on 1 and 32 DF,  p-value: 0.0226

Conclusion: no evidence for a non-linear trend. Linear trend: \(\hat{\beta} = -0.0009 \pm 0.0004\), \(t(32) = 2.4\), \(p = 0.02\).

8.2 Absolute dominance

8.2.1 Graph

Another way of putting this is to say that the participants with the lowest absolute dominance values should have the lowest Flanker/Simon effects.

# Plot with DominanceSwabian
p2 <- ggplot(combined,
       aes(x = abs(DominanceSwabian),
           y = meanSpeedDiff)) +
    geom_point(pch = 1) +
  geom_smooth(method = "gam", formula = y ~ s(x, bs = "tp"),
              fill = "grey70",
              colour = "black") +
  facet_wrap(~ Task, scales = "free_y") +
  geom_vline(xintercept = 0, lty = 2, colour = "black") +
  geom_hline(yintercept = 0, lty = 2, colour = "black") +
  xlab("Absolute dominance") +
  ylab("Difference in mean speed\n(stimuli/s)")
print(p2)

Analysis1 <- plot_grid(p1, p2,
                       ncol = 1, align = "h")
save_plot("Analysis1_RawData.svg", Analysis1, base_height = 4, base_width = 6)

8.2.2 Models

8.2.2.1 Flanker

# GAM: allow abs(DominanceSwabian) to have a nonlinear effect
# This corresponds to the scatterplot smoother above
flanker.gam <- gam(meanSpeedDiff ~ s(abs(DominanceSwabian), bs = "tp"),
                 data = FlankerPerPart)
summary(flanker.gam)

Family: gaussian 
Link function: identity 

Formula:
meanSpeedDiff ~ s(abs(DominanceSwabian), bs = "tp")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)   0.2292     0.0195    11.7  3.9e-13

Approximate significance of smooth terms:
                         edf Ref.df    F p-value
s(abs(DominanceSwabian))   1      1 0.03    0.85

R-sq.(adj) =  -0.0302   Deviance explained = 0.106%
GCV = 0.013775  Scale est. = 0.012965  n = 34
# edf = 1 means that the effect of DominanceSwabian is linear,
# as the scatterplot shows.
# Refit in linear model:
flanker.lm <- lm(meanSpeedDiff ~ abs(DominanceSwabian), data = FlankerPerPart)
summary(flanker.lm)

Call:
lm(formula = meanSpeedDiff ~ abs(DominanceSwabian), data = FlankerPerPart)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.24621 -0.08791 -0.00312  0.05304  0.26211 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)
(Intercept)            0.234583   0.034945    6.71  1.4e-07
abs(DominanceSwabian) -0.000129   0.000699   -0.18     0.85

Residual standard error: 0.114 on 32 degrees of freedom
Multiple R-squared:  0.00106,   Adjusted R-squared:  -0.0302 
F-statistic: 0.0341 on 1 and 32 DF,  p-value: 0.855
# Visual model check:
par(mfrow = c(2, 2))
plot(flanker.lm)
par(mfrow = c(1, 1))

# All of this looks fine.

Conclusion: no evidence for a linear trend. Linear trend: \(\hat{\beta} = -0.0001 \pm 0.0007\), \(t(32) = 0.2\), \(p = 0.85\).

8.2.2.2 Simon

# GAM: allow abs(DominanceSwabian) to have a nonlinear effect
# This corresponds to the scatterplot smoother above
simon.gam <- gam(meanSpeedDiff ~ s(abs(DominanceSwabian), bs = "tp"),
                 data = SimonPerPart)
summary(simon.gam)

Family: gaussian 
Link function: identity 

Formula:
meanSpeedDiff ~ s(abs(DominanceSwabian), bs = "tp")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)   0.1334     0.0207    6.43  3.1e-07

Approximate significance of smooth terms:
                         edf Ref.df    F p-value
s(abs(DominanceSwabian))   1      1 0.63    0.43

R-sq.(adj) =  -0.0114   Deviance explained = 1.92%
GCV = 0.015537  Scale est. = 0.014623  n = 34
# edf = 1 means that the effect of DominanceSwabian is linear,
# as the scatterplot shows.
# Refit in linear model:
simon.lm <- lm(meanSpeedDiff ~ abs(DominanceSwabian), data = SimonPerPart)
summary(simon.lm)

Call:
lm(formula = meanSpeedDiff ~ abs(DominanceSwabian), data = SimonPerPart)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.22380 -0.07440 -0.00828  0.07814  0.24256 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)
(Intercept)           0.109038   0.037112    2.94   0.0061
abs(DominanceSwabian) 0.000588   0.000743    0.79   0.4340

Residual standard error: 0.121 on 32 degrees of freedom
Multiple R-squared:  0.0192,    Adjusted R-squared:  -0.0114 
F-statistic: 0.628 on 1 and 32 DF,  p-value: 0.434
# Visual model check:
par(mfrow = c(2, 2))
plot(simon.lm)
par(mfrow = c(1, 1))

# All of this looks fine.

Conclusion: no evidence for a linear trend. Linear trend: \(\hat{\beta} = 0.0006 \pm 0.0007\), \(t(32) = 0.8\), \(p = 0.43\).

8.3 Conclusion

There is no indication of any effect consistent with our a priori hypothesis here.

9 Post-hoc analysis: Contribution of Swabian to the bidialectal repertoire

9.1 Graphs

# Plot with TotalSwabian
p3 <- ggplot(combined,
       aes(x = TotalSwabian,
           y = meanSpeedDiff)) +
  geom_point(pch = 1) +
  geom_smooth(method = "gam", formula = y ~ s(x, bs = "tp"),
              fill = "grey70",
              colour = "black") +
  facet_wrap(~ Task, scales = "free_y") +
  geom_vline(xintercept = 0, lty = 2, colour = "black") +
  geom_hline(yintercept = 0, lty = 2, colour = "black") +
  xlab("Total Swabian score") +
  ylab("Difference in mean speed\n(stimuli/s)")
print(p3)
save_plot("Analysis2_RawData.svg", p3, base_height = 2, base_width = 6)

9.2 Models

9.2.1 Flanker

# GAM: allow TotalSwabian to have a nonlinear effect
# This corresponds to the scatterplot smoother above
flanker.gam <- gam(meanSpeedDiff ~ s(TotalSwabian, bs = "tp"),
                 data = FlankerPerPart)
summary(flanker.gam)

Family: gaussian 
Link function: identity 

Formula:
meanSpeedDiff ~ s(TotalSwabian, bs = "tp")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)   0.2292     0.0187    12.2  1.3e-13

Approximate significance of smooth terms:
                edf Ref.df    F p-value
s(TotalSwabian)   1      1 2.89   0.099

R-sq.(adj) =  0.0541   Deviance explained = 8.28%
GCV = 0.012648  Scale est. = 0.011904  n = 34
# edf = 1 means that the effect of DominanceSwabian is linear,
# as the scatterplot shows.
# Refit in linear model:
flanker.lm <- lm(meanSpeedDiff ~ TotalSwabian, data = FlankerPerPart)
summary(flanker.lm)

Call:
lm(formula = meanSpeedDiff ~ TotalSwabian, data = FlankerPerPart)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.23424 -0.08612  0.00749  0.05810  0.28041 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)
(Intercept)   0.326822   0.060387    5.41    6e-06
TotalSwabian -0.000960   0.000565   -1.70    0.099

Residual standard error: 0.109 on 32 degrees of freedom
Multiple R-squared:  0.0828,    Adjusted R-squared:  0.0541 
F-statistic: 2.89 on 1 and 32 DF,  p-value: 0.0989
# Visual model check:
par(mfrow = c(2, 2))
plot(flanker.lm)
par(mfrow = c(1, 1))

# All of this looks fine.

Linear trend: \(\hat{\beta} = -0.0010 \pm 0.0006\), \(t(32) = 1.7\), \(p = 0.10\).

9.2.2 Simon

# GAM: allow TotalSwabian to have a nonlinear effect
# This corresponds to the scatterplot smoother above
simon.gam <- gam(meanSpeedDiff ~ s(TotalSwabian, bs = "tp"),
                 data = SimonPerPart)
summary(simon.gam)

Family: gaussian 
Link function: identity 

Formula:
meanSpeedDiff ~ s(TotalSwabian, bs = "tp")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)   0.1334     0.0195    6.85  9.5e-08

Approximate significance of smooth terms:
                edf Ref.df    F p-value
s(TotalSwabian)   1      1 4.98   0.033

R-sq.(adj) =  0.108   Deviance explained = 13.5%
GCV = 0.013709  Scale est. = 0.012903  n = 34
# edf = 1 means that the effect of DominanceSwabian is linear,
# as the scatterplot shows.
# Refit in linear model:
simon.lm <- lm(meanSpeedDiff ~ TotalSwabian, data = SimonPerPart)
summary(simon.lm)

Call:
lm(formula = meanSpeedDiff ~ TotalSwabian, data = SimonPerPart)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.2125 -0.0715  0.0120  0.0699  0.3077 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)
(Intercept)   0.266781   0.062868    4.24  0.00018
TotalSwabian -0.001312   0.000588   -2.23  0.03281

Residual standard error: 0.114 on 32 degrees of freedom
Multiple R-squared:  0.135, Adjusted R-squared:  0.108 
F-statistic: 4.98 on 1 and 32 DF,  p-value: 0.0328
# Visual model check:
par(mfrow = c(2, 2))
plot(simon.lm)
par(mfrow = c(1, 1))

# All of this looks fine.

Linear trend: \(\hat{\beta} = -0.0013 \pm 0.0006\), \(t(32) = 2.2\), \(p = 0.03\).

10 Mixed-effects models

The models reported above rely on aggregated data. For the sake of completeness, we will also analyse non-aggregated data in mixed-effects models.

# Combine questionnaire and non-aggregated data
dat <- merge(dat, questionnaire, by = "Subject")
# Sum-code 'Status' (congruent vs. incongruent) (0.5 vs. -0.5)
dat$n.Status <- (as.numeric(dat$Status) - 1.5) * -1
xtabs(~ n.Status + Status, dat)
        Status
n.Status congruent incongruent
    -0.5         0        6528
    0.5       6528           0
# Centre DominanceSwabian
dat$c.DominanceSwabian <- dat$DominanceSwabian - mean(dat$DominanceSwabian)
# Compute and centre absolute DominanceSwabian
dat$a.DominanceSwabian <- abs(dat$DominanceSwabian)
dat$ca.DominanceSwabian <- dat$a.DominanceSwabian - mean(dat$a.DominanceSwabian)
# Centre TotalSwabian
dat$c.TotalSwabian <- dat$TotalSwabian - mean(dat$TotalSwabian)
# Split up by task
datFlanker <- dat %>% filter(Task == "Flanker")
datSimon <- dat %>% filter(Task == "Simon")

10.1 Raw dominance

The minimum requirement is that DominanceSwabian interacts with n.Status, that is to say, that the effect of congruent vs. incongruent trials varies depending on the participants’ bidialectal dominance. A significant interaction in itself would not be in line with our predictions, since these specify that the flanker/Simon effects should be lowest around DominanceSwabian = 0; a significant interaction that suggests, say, that the flanker/Simon effects grower larger with increasing Swabian dominance would be incompatible with the predictions.

10.1.1 Flanker

10.1.1.1 Model fitting

# Fit model in GAMM
flanker.gam <- gam(Speed ~ n.Status + 
                     s(DominanceSwabian, by = factor(n.Status)) +
                     s(Subject, bs = "re") +                  # random intercept for subject
                     s(n.Status, Subject, bs = "re"),      # random slope of n.Congruent by subject. 
                   # This is equivalent to saying that the Flanker effect
                   # varies between participants
                   data = datFlanker)
plot(flanker.gam)

The DominanceSwabian effects are linear, so we’ll model them linearly using lmer().

flanker.mer <- lmer(Speed ~ n.Status + c.DominanceSwabian +
                      c.DominanceSwabian:n.Status +
                      (1 + n.Status | Subject),
                    data = datFlanker)
AIC(flanker.mer)
[1] 5988
summary(flanker.mer)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.DominanceSwabian + c.DominanceSwabian:n.Status +      (1 + n.Status | Subject)
   Data: datFlanker

REML criterion at convergence: 5972

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.563 -0.573  0.036  0.623  4.988 

Random effects:
 Groups   Name        Variance Std.Dev. Corr 
 Subject  (Intercept) 0.0779   0.2791        
          n.Status    0.0082   0.0906   -0.06
 Residual             0.1410   0.3755        
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                             Estimate Std. Error t value
(Intercept)                  2.379575   0.048091    49.5
n.Status                     0.229235   0.018098    12.7
c.DominanceSwabian          -0.000882   0.000966    -0.9
n.Status:c.DominanceSwabian -0.000836   0.000363    -2.3

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    -0.048              
c.DmnncSwbn  0.000  0.000       
n.Stts:c.DS  0.000  0.000 -0.048
# Without random correlation?
flanker.mer2 <- lmer(Speed ~ n.Status + c.DominanceSwabian +
                      c.DominanceSwabian:n.Status +
                      (1 + n.Status || Subject),
                    data = datFlanker)
AIC(flanker.mer2)
[1] 5987
summary(flanker.mer2)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.DominanceSwabian + c.DominanceSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datFlanker

REML criterion at convergence: 5972

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.564 -0.574  0.036  0.623  4.989 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.0779   0.2791  
 Subject.1 n.Status    0.0082   0.0906  
 Residual              0.1410   0.3755  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                             Estimate Std. Error t value
(Intercept)                  2.379575   0.048091    49.5
n.Status                     0.229235   0.018098    12.7
c.DominanceSwabian          -0.000882   0.000966    -0.9
n.Status:c.DominanceSwabian -0.000836   0.000363    -2.3

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.000               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.000 

flanker.mer2, which pegs the correlation between the random intercepts and slopes at 0, seems to be a slightly better model, though it doesn’t matter much.

The source code for this document explores whether this model is correctly specified (distribution of random effects and residuals). In conclusion, all seems to be in order.

10.1.1.2 Inference tests

Here we test the significance of the interaction between n.Status and c.DominanceSwabian.

# 1. Normal approximation
summary(flanker.mer2) 
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.DominanceSwabian + c.DominanceSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datFlanker

REML criterion at convergence: 5972

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.564 -0.574  0.036  0.623  4.989 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.0779   0.2791  
 Subject.1 n.Status    0.0082   0.0906  
 Residual              0.1410   0.3755  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                             Estimate Std. Error t value
(Intercept)                  2.379575   0.048091    49.5
n.Status                     0.229235   0.018098    12.7
c.DominanceSwabian          -0.000882   0.000966    -0.9
n.Status:c.DominanceSwabian -0.000836   0.000363    -2.3

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.000               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.000 
# |t| = 2.3  corresponds to roughly p = 0.02, if we assume
# the t-distribution is well approximated by a normal distribution.
# 2. Likelihood ratio test
# Fit null model
flanker.mer20 <- lmer(Speed ~ n.Status + c.DominanceSwabian +
                        (1 + n.Status || Subject),
                      data = datFlanker)
anova(flanker.mer20, flanker.mer2)
refitting model(s) with ML (instead of REML)
Data: datFlanker
Models:
flanker.mer20: Speed ~ n.Status + c.DominanceSwabian + ((1 | Subject) + (0 + 
flanker.mer20:     n.Status | Subject))
flanker.mer2: Speed ~ n.Status + c.DominanceSwabian + c.DominanceSwabian:n.Status + 
flanker.mer2:     ((1 | Subject) + (0 + n.Status | Subject))
              Df  AIC  BIC logLik deviance Chisq Chi Df Pr(>Chisq)
flanker.mer20  6 5953 5994  -2971     5941                        
flanker.mer2   7 5950 5997  -2968     5936   5.2      1      0.023
# LRT: X²(1) = 5.2, p = 0.023
# 3. Last--and better--solution: Parametric bootstrapping:
#PBmodcomp(flanker.mer2, flanker.mer20, nsim = 1000)
# p =~ 0.04; the p-value will vary from run to run

10.1.1.3 Visualisation of interaction

As pointed out above, the mere presence of a significant interaction doesn’t mean the data are consistent with our hypothesis. For this reason, we’ll visualise the modelled flanker effect (speed for congruent trials - speed for incongruent trials) according to the participants’ Swabian dominance values.

(Since the GAMM above suggested the interaction to be linear, it is impossible that the significant interaction above is indeed consistent with our prediction, but this will be more obvious once plotted.)

# Data frame to fill with predictions
newdat <- expand.grid(n.Status = c(-0.5, 0.5),
                      c.DominanceSwabian = seq(min(datFlanker$c.DominanceSwabian), 
                                               max(datFlanker$c.DominanceSwabian)))
# Fill with predictions, ignore random effects
newdat$Prediction <- predict(flanker.mer2, newdat, re.form = NA)
# Add original variables
newdat$Status <- ifelse(newdat$n.Status == -0.5, "incongruent", "congruent")
newdat$DominanceSwabian <- newdat$c.DominanceSwabian + mean(datFlanker$DominanceSwabian)
# Plot effect of DominanceSwabian
ggplot(newdat,
       aes(x = DominanceSwabian,
           y = Prediction,
           linetype = Status)) +
  geom_line() +
  xlab("Swabian dominance") +
  ylab("Predicted response speed\n(stimuli/s)")

# Compute difference between congruent and incongruent for each Dominance value
newdatDiffs <- newdat %>% 
  select(Status, Prediction, DominanceSwabian) %>% 
  spread(., Status, Prediction) %>% 
  mutate(Difference = congruent - incongruent)
# Difference in response speeds:
ggplot(newdatDiffs,
       aes(x = DominanceSwabian,
           y = Difference)) +
  geom_line() +
  xlab("Swabian dominance") +
  ylab("Flanker effect\n(response speed difference in stimuli/s)")

I.e., like for the simpler regression models on aggregated flanker data, we find that the flanker effect is lowest for high Swabian dominance, not for balanced bidialectalism.

10.1.2 Simon

10.1.2.1 Model fitting

# Fit model in GAMM
simon.gam <- gam(Speed ~ n.Status + 
                     s(DominanceSwabian, by = factor(n.Status)) +
                     s(Subject, bs = "re") +                  # random intercept for subject
                     s(n.Status, Subject, bs = "re"),      # random slope of n.Congruent by subject. 
                   # This is equivalent to saying that the Simon effect
                   # varies between participants
                   data = datSimon)
plot(simon.gam)

The DominanceSwabian effects are linear, so we’ll model them linearly using lmer().

simon.mer <- lmer(Speed ~ n.Status + c.DominanceSwabian +
                      c.DominanceSwabian:n.Status +
                      (1 + n.Status | Subject),
                    data = datSimon)
AIC(simon.mer)
[1] 10137
summary(simon.mer)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.DominanceSwabian + c.DominanceSwabian:n.Status +      (1 + n.Status | Subject)
   Data: datSimon

REML criterion at convergence: 10122

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.497 -0.597  0.013  0.621  4.021 

Random effects:
 Groups   Name        Variance Std.Dev. Corr
 Subject  (Intercept) 0.09350  0.3058       
          n.Status    0.00707  0.0841   0.06
 Residual             0.26753  0.5172       
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                             Estimate Std. Error t value
(Intercept)                  2.589867   0.052831    49.0
n.Status                     0.133422   0.019282     6.9
c.DominanceSwabian          -0.001638   0.001061    -1.5
n.Status:c.DominanceSwabian -0.000928   0.000387    -2.4

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.044               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.044 
# Without random correlation?
simon.mer2 <- lmer(Speed ~ n.Status + c.DominanceSwabian +
                      c.DominanceSwabian:n.Status +
                      (1 + n.Status || Subject),
                    data = datSimon)
AIC(simon.mer2)
[1] 10136
summary(simon.mer2)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.DominanceSwabian + c.DominanceSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datSimon

REML criterion at convergence: 10122

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.499 -0.597  0.014  0.623  4.020 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.09350  0.3058  
 Subject.1 n.Status    0.00707  0.0841  
 Residual              0.26753  0.5172  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                             Estimate Std. Error t value
(Intercept)                  2.589867   0.052831    49.0
n.Status                     0.133422   0.019282     6.9
c.DominanceSwabian          -0.001638   0.001061    -1.5
n.Status:c.DominanceSwabian -0.000928   0.000387    -2.4

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.000               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.000 

simon.mer2, which pegs the correlation between the random intercepts and slopes at 0, seems to be a slightly better model, though it doesn’t matter much.

The source code for this document explores whether this model is correctly specified (distribution of random effects and residuals). In conclusion, all seems to be in order.

10.1.2.2 Inference tests

Here we test the significance of the interaction between n.Status and c.DominanceSwabian.

# 1. Normal approximation
summary(simon.mer2) 
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.DominanceSwabian + c.DominanceSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datSimon

REML criterion at convergence: 10122

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.499 -0.597  0.014  0.623  4.020 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.09350  0.3058  
 Subject.1 n.Status    0.00707  0.0841  
 Residual              0.26753  0.5172  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                             Estimate Std. Error t value
(Intercept)                  2.589867   0.052831    49.0
n.Status                     0.133422   0.019282     6.9
c.DominanceSwabian          -0.001638   0.001061    -1.5
n.Status:c.DominanceSwabian -0.000928   0.000387    -2.4

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.000               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.000 
# |t| = 2.4  corresponds to roughly p = 0.016, if we assume
# the t-distribution is well approximated by a normal distribution.
# 2. Likelihood ratio test
# Fit null model
simon.mer20 <- lmer(Speed ~ n.Status + c.DominanceSwabian +
                        (1 + n.Status || Subject),
                      data = datSimon)
anova(simon.mer20, simon.mer2)
refitting model(s) with ML (instead of REML)
Data: datSimon
Models:
simon.mer20: Speed ~ n.Status + c.DominanceSwabian + ((1 | Subject) + (0 + 
simon.mer20:     n.Status | Subject))
simon.mer2: Speed ~ n.Status + c.DominanceSwabian + c.DominanceSwabian:n.Status + 
simon.mer2:     ((1 | Subject) + (0 + n.Status | Subject))
            Df   AIC   BIC logLik deviance Chisq Chi Df Pr(>Chisq)
simon.mer20  6 10103 10144  -5046    10091                        
simon.mer2   7 10100 10147  -5043    10086  5.61      1      0.018
# LRT: X²(1) = 5.6, p = 0.018
# 3. Last--and better--solution: Parametric bootstrapping:
#PBmodcomp(simon.mer2, simon.mer20, nsim = 1000)
# p =~ 0.020; the p-value will vary from run to run

10.1.2.3 Visualisation of interaction

As pointed out above, the mere presence of a significant interaction doesn’t mean the data are consistent with our hypothesis. For this reason, we’ll visualise the modelled Simon effect (speed for congruent trials - speed for incongruent trials) according to the participants’ Swabian dominance values.

(Since the GAMM above suggested the interaction to be linear, it is impossible that the significant interaction above is indeed consistent with our prediction, but this will be more obvious once plotted.)

# Data frame to fill with predictions
newdat <- expand.grid(n.Status = c(-0.5, 0.5),
                      c.DominanceSwabian = seq(min(datSimon$c.DominanceSwabian), 
                                               max(datSimon$c.DominanceSwabian)))
# Fill with predictions, ignore random effects
newdat$Prediction <- predict(simon.mer2, newdat, re.form = NA)
# Add original variables
newdat$Status <- ifelse(newdat$n.Status == -0.5, "incongruent", "congruent")
newdat$DominanceSwabian <- newdat$c.DominanceSwabian + mean(datSimon$DominanceSwabian)
# Plot effect of DominanceSwabian
ggplot(newdat,
       aes(x = DominanceSwabian,
           y = Prediction,
           linetype = Status)) +
  geom_line() +
  xlab("Swabian dominance") +
  ylab("Predicted response speed\n(stimuli/s)")

# Compute difference between congruent and incongruent for each Dominance value
newdatDiffs <- newdat %>% 
  select(Status, Prediction, DominanceSwabian) %>% 
  spread(., Status, Prediction) %>% 
  mutate(Difference = congruent - incongruent)
# Difference in response speeds:
ggplot(newdatDiffs,
       aes(x = DominanceSwabian,
           y = Difference)) +
  geom_line() +
  xlab("Swabian dominance") +
  ylab("Simon effect\n(response speed difference in stimuli/s)")

I.e., like for the simpler regression models on aggregated flanker data, we find that the Simon effect is lowest for high Swabian dominance, not for balanced bidialectalism.

10.2 Absolute dominance

The minimum requirement is that a.DominanceSwabian interacts with n.Status, that is to say, that the effect of congruent vs. incongruent trials varies depending on the participants’ bidialectal dominance. A significant interaction in itself would not be in line with our predictions, since these specify that the flanker/Simon effects should be lowest around a.DominanceSwabian = 0.

10.2.1 Flanker

10.2.1.1 Model fitting

# Fit model in GAM
flanker.gam <- gam(Speed ~ n.Status + 
                     s(a.DominanceSwabian, by = factor(n.Status)) +
                     s(Subject, bs = "re") +                  # random intercept for subject
                     s(n.Status, Subject, bs = "re"),      # random slope of n.Congruent by subject. 
                   # This is equivalent to saying that the Flanker effect
                   # varies between participants
                   data = datFlanker)
plot(flanker.gam)

The a.DominanceSwabian effects are linear, so we’ll model them linearly using lmer().

flanker.mer <- lmer(Speed ~ n.Status + ca.DominanceSwabian +
                      ca.DominanceSwabian:n.Status +
                      (1 + n.Status | Subject),
                    data = datFlanker)
AIC(flanker.mer)
[1] 5989
summary(flanker.mer)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + ca.DominanceSwabian + ca.DominanceSwabian:n.Status +      (1 + n.Status | Subject)
   Data: datFlanker

REML criterion at convergence: 5973

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.527 -0.572  0.035  0.625  4.978 

Random effects:
 Groups   Name        Variance Std.Dev. Corr
 Subject  (Intercept) 0.0729   0.270        
          n.Status    0.0100   0.100    0.01
 Residual             0.1410   0.375        
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                              Estimate Std. Error t value
(Intercept)                   2.379575   0.046550    51.1
n.Status                      0.229235   0.019528    11.7
ca.DominanceSwabian          -0.002908   0.001667    -1.7
n.Status:ca.DominanceSwabian -0.000129   0.000699    -0.2

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.006               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.006 
# Without random correlation?
flanker.mer2 <- lmer(Speed ~ n.Status + ca.DominanceSwabian +
                      ca.DominanceSwabian:n.Status +
                      (1 + n.Status || Subject),
                    data = datFlanker)
AIC(flanker.mer2)
[1] 5987
summary(flanker.mer2)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + ca.DominanceSwabian + ca.DominanceSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datFlanker

REML criterion at convergence: 5973

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.527 -0.572  0.035  0.625  4.977 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.0729   0.270   
 Subject.1 n.Status    0.0100   0.100   
 Residual              0.1410   0.375   
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                              Estimate Std. Error t value
(Intercept)                   2.379575   0.046550    51.1
n.Status                      0.229235   0.019528    11.7
ca.DominanceSwabian          -0.002908   0.001667    -1.7
n.Status:ca.DominanceSwabian -0.000129   0.000699    -0.2

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.000               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.000 

flanker.mer2, which pegs the correlation between the random intercepts and slopes at 0, seems to be a slightly better model, though it doesn’t matter much.

The source code for this document explores whether this model is correctly specified (distribution of random effects and residuals). In conclusion, all seems to be in order.

10.2.1.2 Inference tests

Here we test the significance of the interaction between n.Status and ca.DominanceSwabian.

# 1. Normal approximation
summary(flanker.mer2) 
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + ca.DominanceSwabian + ca.DominanceSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datFlanker

REML criterion at convergence: 5973

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.527 -0.572  0.035  0.625  4.977 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.0729   0.270   
 Subject.1 n.Status    0.0100   0.100   
 Residual              0.1410   0.375   
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                              Estimate Std. Error t value
(Intercept)                   2.379575   0.046550    51.1
n.Status                      0.229235   0.019528    11.7
ca.DominanceSwabian          -0.002908   0.001667    -1.7
n.Status:ca.DominanceSwabian -0.000129   0.000699    -0.2

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.000               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.000 
# |t| = 0.2  corresponds to roughly p = 0.84, if we assume
# the t-distribution is well approximated by a normal distribution.
# 2. Likelihood ratio test
# Fit null model
flanker.mer20 <- lmer(Speed ~ n.Status + ca.DominanceSwabian +
                        (1 + n.Status || Subject),
                      data = datFlanker)
anova(flanker.mer20, flanker.mer2)
refitting model(s) with ML (instead of REML)
Data: datFlanker
Models:
flanker.mer20: Speed ~ n.Status + ca.DominanceSwabian + ((1 | Subject) + (0 + 
flanker.mer20:     n.Status | Subject))
flanker.mer2: Speed ~ n.Status + ca.DominanceSwabian + ca.DominanceSwabian:n.Status + 
flanker.mer2:     ((1 | Subject) + (0 + n.Status | Subject))
              Df  AIC  BIC logLik deviance Chisq Chi Df Pr(>Chisq)
flanker.mer20  6 5951 5992  -2969     5939                        
flanker.mer2   7 5953 6000  -2969     5939  0.04      1       0.85
# LRT: X²(1) = 0.04, p = 0.85
# 3. With these p-values, parametric bootstrapping is superfluous.

We find no interaction between n.Status and ca.DominanceSwabian and hence no evidence for our prediction.

10.2.2 Simon

10.2.2.1 Model fitting

# Fit model in GAM
simon.gam <- gam(Speed ~ n.Status + 
                     s(a.DominanceSwabian, by = factor(n.Status)) +
                     s(Subject, bs = "re") +                  # random intercept for subject
                     s(n.Status, Subject, bs = "re"),      # random slope of n.Congruent by subject. 
                   # This is equivalent to saying that the Simon effect
                   # varies between participants
                   data = datSimon)
plot(simon.gam)

The a.DominanceSwabian effects are linear, so we’ll model them linearly using lmer().

simon.mer <- lmer(Speed ~ n.Status + ca.DominanceSwabian +
                      ca.DominanceSwabian:n.Status +
                      (1 + n.Status | Subject),
                    data = datSimon)
AIC(simon.mer)
[1] 10138
summary(simon.mer)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + ca.DominanceSwabian + ca.DominanceSwabian:n.Status +      (1 + n.Status | Subject)
   Data: datSimon

REML criterion at convergence: 10122

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.505 -0.595  0.014  0.621  4.037 

Random effects:
 Groups   Name        Variance Std.Dev. Corr
 Subject  (Intercept) 0.09198  0.3033       
          n.Status    0.00905  0.0951   0.25
 Residual             0.26753  0.5172       
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                              Estimate Std. Error t value
(Intercept)                   2.589867   0.052404    49.4
n.Status                      0.133422   0.020738     6.4
ca.DominanceSwabian          -0.003221   0.001876    -1.7
n.Status:ca.DominanceSwabian  0.000588   0.000743     0.8

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.192               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.192 
# Without random correlation?
simon.mer2 <- lmer(Speed ~ n.Status + ca.DominanceSwabian +
                      ca.DominanceSwabian:n.Status +
                      (1 + n.Status || Subject),
                    data = datSimon)
AIC(simon.mer2)
[1] 10137
summary(simon.mer2)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + ca.DominanceSwabian + ca.DominanceSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datSimon

REML criterion at convergence: 10123

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.510 -0.594  0.014  0.623  4.029 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.09198  0.3033  
 Subject.1 n.Status    0.00905  0.0951  
 Residual              0.26753  0.5172  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                              Estimate Std. Error t value
(Intercept)                   2.589867   0.052404    49.4
n.Status                      0.133422   0.020738     6.4
ca.DominanceSwabian          -0.003221   0.001876    -1.7
n.Status:ca.DominanceSwabian  0.000588   0.000743     0.8

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.000               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.000 

simon.mer2, which pegs the correlation between the random intercepts and slopes at 0, seems to be a slightly better model, though it doesn’t matter much.

The source code for this document explores whether this model is correctly specified (distribution of random effects and residuals). In conclusion, all seems to be in order.

10.2.2.2 Inference tests

Here we test the significance of the interaction between n.Status and ca.DominanceSwabian.

# 1. Normal approximation
summary(simon.mer2) 
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + ca.DominanceSwabian + ca.DominanceSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datSimon

REML criterion at convergence: 10123

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.510 -0.594  0.014  0.623  4.029 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.09198  0.3033  
 Subject.1 n.Status    0.00905  0.0951  
 Residual              0.26753  0.5172  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                              Estimate Std. Error t value
(Intercept)                   2.589867   0.052404    49.4
n.Status                      0.133422   0.020738     6.4
ca.DominanceSwabian          -0.003221   0.001876    -1.7
n.Status:ca.DominanceSwabian  0.000588   0.000743     0.8

Correlation of Fixed Effects:
            (Intr) n.Stts c.DmnS
n.Status    0.000               
c.DmnncSwbn 0.000  0.000        
n.Stts:c.DS 0.000  0.000  0.000 
# |t| = 0.8  corresponds to roughly p = 0.42, if we assume
# the t-distribution is well approximated by a normal distribution.
# 2. Likelihood ratio test
# Fit null model
simon.mer20 <- lmer(Speed ~ n.Status + ca.DominanceSwabian +
                        (1 + n.Status || Subject),
                      data = datSimon)
anova(simon.mer20, simon.mer2)
refitting model(s) with ML (instead of REML)
Data: datSimon
Models:
simon.mer20: Speed ~ n.Status + ca.DominanceSwabian + ((1 | Subject) + (0 + 
simon.mer20:     n.Status | Subject))
simon.mer2: Speed ~ n.Status + ca.DominanceSwabian + ca.DominanceSwabian:n.Status + 
simon.mer2:     ((1 | Subject) + (0 + n.Status | Subject))
            Df   AIC   BIC logLik deviance Chisq Chi Df Pr(>Chisq)
simon.mer20  6 10103 10143  -5045    10091                        
simon.mer2   7 10104 10151  -5045    10090  0.66      1       0.42
# LRT: X²(1) = 0.66, p = 0.42
# 3. Parametric bootstrapping: superfluous

We find no solid interaction between n.Status and ca.DominanceSwabian and hence no evidence for our prediction.

10.3 Total Swabian

10.3.1 Flanker

10.3.1.1 Model fitting

# Fit model in GAM
flanker.gam <- gam(Speed ~ n.Status + 
                     s(TotalSwabian, by = factor(n.Status)) +
                     s(Subject, bs = "re") +                  # random intercept for subject
                     s(n.Status, Subject, bs = "re"),      # random slope of n.Congruent by subject. 
                   # This is equivalent to saying that the Flanker effect
                   # varies between participants
                   data = datFlanker)
plot(flanker.gam)

The TotalSwabian effects are linear, so we’ll model them linearly using lmer().

flanker.mer <- lmer(Speed ~ n.Status + c.TotalSwabian +
                      c.TotalSwabian:n.Status +
                      (1 + n.Status | Subject),
                    data = datFlanker)
AIC(flanker.mer)
[1] 5990
summary(flanker.mer)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.TotalSwabian + c.TotalSwabian:n.Status +      (1 + n.Status | Subject)
   Data: datFlanker

REML criterion at convergence: 5974

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.555 -0.574  0.036  0.625  4.986 

Random effects:
 Groups   Name        Variance Std.Dev. Corr
 Subject  (Intercept) 0.07959  0.2821       
          n.Status    0.00897  0.0947   0.00
 Residual             0.14097  0.3755       
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                         Estimate Std. Error t value
(Intercept)              2.379575   0.048605    49.0
n.Status                 0.229235   0.018712    12.3
c.TotalSwabian          -0.000555   0.001467    -0.4
n.Status:c.TotalSwabian -0.000960   0.000565    -1.7

Correlation of Fixed Effects:
            (Intr) n.Stts c.TtlS
n.Status    -0.004              
c.TotalSwbn  0.000  0.000       
n.Stts:c.TS  0.000  0.000 -0.004
# Without random correlation?
flanker.mer2 <- lmer(Speed ~ n.Status + c.TotalSwabian +
                      c.TotalSwabian:n.Status +
                      (1 + n.Status || Subject),
                    data = datFlanker)
AIC(flanker.mer2)
[1] 5988
summary(flanker.mer2)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.TotalSwabian + c.TotalSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datFlanker

REML criterion at convergence: 5974

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.555 -0.573  0.036  0.625  4.986 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.07959  0.2821  
 Subject.1 n.Status    0.00897  0.0947  
 Residual              0.14097  0.3755  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                         Estimate Std. Error t value
(Intercept)              2.379575   0.048605    49.0
n.Status                 0.229235   0.018712    12.3
c.TotalSwabian          -0.000555   0.001467    -0.4
n.Status:c.TotalSwabian -0.000960   0.000565    -1.7

Correlation of Fixed Effects:
            (Intr) n.Stts c.TtlS
n.Status    0.000               
c.TotalSwbn 0.000  0.000        
n.Stts:c.TS 0.000  0.000  0.000 

flanker.mer2, which pegs the correlation between the random intercepts and slopes at 0, seems to be a slightly better model, though it doesn’t matter much.

The source code for this document explores whether this model is correctly specified (distribution of random effects and residuals). In conclusion, all seems to be in order.

10.3.1.2 Inference tests

Here we test the significance of the interaction between n.Status and c.TotalSwabian.

# 1. Normal approximation
summary(flanker.mer2) 
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.TotalSwabian + c.TotalSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datFlanker

REML criterion at convergence: 5974

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.555 -0.573  0.036  0.625  4.986 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.07959  0.2821  
 Subject.1 n.Status    0.00897  0.0947  
 Residual              0.14097  0.3755  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                         Estimate Std. Error t value
(Intercept)              2.379575   0.048605    49.0
n.Status                 0.229235   0.018712    12.3
c.TotalSwabian          -0.000555   0.001467    -0.4
n.Status:c.TotalSwabian -0.000960   0.000565    -1.7

Correlation of Fixed Effects:
            (Intr) n.Stts c.TtlS
n.Status    0.000               
c.TotalSwbn 0.000  0.000        
n.Stts:c.TS 0.000  0.000  0.000 
# |t| = 1.7  corresponds to roughly p = 0.09, if we assume
# the t-distribution is well approximated by a normal distribution.
# 2. Likelihood ratio test
# Fit null model
flanker.mer20 <- lmer(Speed ~ n.Status + c.TotalSwabian +
                        (1 + n.Status || Subject),
                      data = datFlanker)
anova(flanker.mer20, flanker.mer2)
refitting model(s) with ML (instead of REML)
Data: datFlanker
Models:
flanker.mer20: Speed ~ n.Status + c.TotalSwabian + ((1 | Subject) + (0 + n.Status | 
flanker.mer20:     Subject))
flanker.mer2: Speed ~ n.Status + c.TotalSwabian + c.TotalSwabian:n.Status + 
flanker.mer2:     ((1 | Subject) + (0 + n.Status | Subject))
              Df  AIC  BIC logLik deviance Chisq Chi Df Pr(>Chisq)
flanker.mer20  6 5954 5995  -2971     5942                        
flanker.mer2   7 5953 6000  -2969     5939  2.94      1      0.086
# LRT: X²(1) = 2.9, p = 0.086
# 3. Last--and better--solution: Parametric bootstrapping:
#PBmodcomp(flanker.mer2, flanker.mer20, nsim = 1000)
# p =~ 0.099; the p-value will vary from run to run

We find no interaction between n.Status and c.TotalSwabian and hence no evidence for our prediction.

10.3.2 Simon

10.3.2.1 Model fitting

# Fit model in GAM
simon.gam <- gam(Speed ~ n.Status + 
                     s(TotalSwabian, by = factor(n.Status)) +
                     s(Subject, bs = "re") +                  # random intercept for subject
                     s(n.Status, Subject, bs = "re"),      # random slope of n.Congruent by subject. 
                   # This is equivalent to saying that the Simon effect
                   # varies between participants
                   data = datSimon)
plot(simon.gam)

The TotalSwabian effects are linear, so we’ll model them linearly using lmer().

simon.mer <- lmer(Speed ~ n.Status + c.TotalSwabian +
                      c.TotalSwabian:n.Status +
                      (1 + n.Status | Subject),
                    data = datSimon)
AIC(simon.mer)
[1] 10138
summary(simon.mer)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.TotalSwabian + c.TotalSwabian:n.Status +      (1 + n.Status | Subject)
   Data: datSimon

REML criterion at convergence: 10122

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.497 -0.597  0.014  0.620  4.033 

Random effects:
 Groups   Name        Variance Std.Dev. Corr
 Subject  (Intercept) 0.09758  0.3124       
          n.Status    0.00733  0.0856   0.11
 Residual             0.26753  0.5172       
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                         Estimate Std. Error t value
(Intercept)              2.589867   0.053953    48.0
n.Status                 0.133422   0.019480     6.8
c.TotalSwabian          -0.001602   0.001629    -1.0
n.Status:c.TotalSwabian -0.001312   0.000588    -2.2

Correlation of Fixed Effects:
            (Intr) n.Stts c.TtlS
n.Status    0.086               
c.TotalSwbn 0.000  0.000        
n.Stts:c.TS 0.000  0.000  0.086 
# Without random correlation?
simon.mer2 <- lmer(Speed ~ n.Status + c.TotalSwabian +
                      c.TotalSwabian:n.Status +
                      (1 + n.Status || Subject),
                    data = datSimon)
AIC(simon.mer2)
[1] 10136
summary(simon.mer2)
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.TotalSwabian + c.TotalSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datSimon

REML criterion at convergence: 10122

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.501 -0.597  0.013  0.625  4.031 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.09758  0.3124  
 Subject.1 n.Status    0.00733  0.0856  
 Residual              0.26753  0.5172  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                         Estimate Std. Error t value
(Intercept)              2.589867   0.053953    48.0
n.Status                 0.133422   0.019480     6.8
c.TotalSwabian          -0.001602   0.001629    -1.0
n.Status:c.TotalSwabian -0.001312   0.000588    -2.2

Correlation of Fixed Effects:
            (Intr) n.Stts c.TtlS
n.Status    0.000               
c.TotalSwbn 0.000  0.000        
n.Stts:c.TS 0.000  0.000  0.000 

simon.mer2, which pegs the correlation between the random intercepts and slopes at 0, seems to be a slightly better model, though it doesn’t matter much.

The source code for this document explores whether this model is correctly specified (distribution of random effects and residuals). In conclusion, all seems to be in order.

10.3.2.2 Inference tests

Here we test the significance of the interaction between n.Status and c.TotalSwabian.

# 1. Normal approximation
summary(simon.mer2) 
Linear mixed model fit by REML ['lmerMod']
Formula: Speed ~ n.Status + c.TotalSwabian + c.TotalSwabian:n.Status +      ((1 | Subject) + (0 + n.Status | Subject))
   Data: datSimon

REML criterion at convergence: 10122

Scaled residuals: 
   Min     1Q Median     3Q    Max 
-4.501 -0.597  0.013  0.625  4.031 

Random effects:
 Groups    Name        Variance Std.Dev.
 Subject   (Intercept) 0.09758  0.3124  
 Subject.1 n.Status    0.00733  0.0856  
 Residual              0.26753  0.5172  
Number of obs: 6528, groups:  Subject, 34

Fixed effects:
                         Estimate Std. Error t value
(Intercept)              2.589867   0.053953    48.0
n.Status                 0.133422   0.019480     6.8
c.TotalSwabian          -0.001602   0.001629    -1.0
n.Status:c.TotalSwabian -0.001312   0.000588    -2.2

Correlation of Fixed Effects:
            (Intr) n.Stts c.TtlS
n.Status    0.000               
c.TotalSwbn 0.000  0.000        
n.Stts:c.TS 0.000  0.000  0.000 
# |t| = 2.2  corresponds to roughly p = 0.028, if we assume
# the t-distribution is well approximated by a normal distribution.
# 2. Likelihood ratio test
# Fit null model
simon.mer20 <- lmer(Speed ~ n.Status + c.TotalSwabian +
                        (1 + n.Status || Subject),
                      data = datSimon)
anova(simon.mer20, simon.mer2)
refitting model(s) with ML (instead of REML)
Data: datSimon
Models:
simon.mer20: Speed ~ n.Status + c.TotalSwabian + ((1 | Subject) + (0 + n.Status | 
simon.mer20:     Subject))
simon.mer2: Speed ~ n.Status + c.TotalSwabian + c.TotalSwabian:n.Status + 
simon.mer2:     ((1 | Subject) + (0 + n.Status | Subject))
            Df   AIC   BIC logLik deviance Chisq Chi Df Pr(>Chisq)
simon.mer20  6 10105 10145  -5046    10093                        
simon.mer2   7 10102 10149  -5044    10088  4.92      1      0.027
# LRT: X²(1) = 4.9, p = 0.027
# 3. Last--and better--solution: Parametric bootstrapping:
#PBmodcomp(simon.mer2, simon.mer20, nsim = 1000)
# p =~ 0.030; the p-value will vary from run to run

11 A multiverse analysis

For the analyses reported above, we took a number of more or less arbitrary decisions (our decisions in bold):

By combining all of these possibilities, there are (easily) 3,072 alternative ways of analysing these data.

# Matrix that lists all analysis parameters
alternatives <- expand.grid(data = "data",
                            Task = c("Simon", "Flanker"),
                            Transformation = c("raw", "speed", "log"),
                            ExclusionAccuracy = c("yes", "no"),
                            ExclusionLatency = c(0, 200, 250, 300),
                            ExclusionSDs = c(NA, 2.5),
                            ExclusionSDsOverall = c(NA, 2.5), # not yet implemented
                            DV = c("mean difference", "mean ratio"),
                            IV = c("raw dominance", "absolute dominance",
                                   "raw dominance, oral", "absolute dominance, oral", 
                                   "raw use", "absolute use",
                                   "total Swabian", "total Swabian, oral"))
nrow(alternatives)
[1] 3072

11.1 Define analysis walkthrough

allAnalyses <-
  function(data,
           Task,
           Transformation,
           ExclusionAccuracy = "no",
           ExclusionLatency = 0,
           ExclusionSDs = NULL,
           ExclusionSDsOverall = NULL,
           DV,
           IV) {
    
    require("dplyr")
    require("tidyr")
    require("magrittr")
    
    # Select task
    if (Task %in% c("Simon", "Flanker")) {
      if (Task == "Simon") {
        dat <- subset(data, Task == "Simon")
      } else if (Task == "Flanker") {
        dat <- subset(data, Task == "Flanker")
      }
    } else {
      stop("Task not 'Simon' or 'Flanker'.")
    }
    
    # Transform data
    if (!(Transformation %in% c("raw", "speed", "log"))) {
      stop("Transformation not 'raw', 'speed' or 'log'.")
    } else if (Transformation == "raw") {
      dat$Response <- dat[, "RT"]
    } else if (Transformation == "speed") {
      dat$Response <- 1000 / dat[, "RT"]
    } else if (Transformation == "log") {
      dat$Response <- log10(dat[, "RT"])
      # Note that the base of the logarithm is immaterial.
    }
    
    # Exclude incorrect responses
    # Track how many were excluded
    excludedAccuracy <- 0
    if (!(ExclusionAccuracy %in% c("yes", "no"))) {
      stop("ExclusionAccuracy needs to be either yes or no.")
    } else if (ExclusionAccuracy == "yes") {
      excludedAccuracy <- sum(dat$Accuracy == "0")
      dat <- dat[dat$Accuracy == "1",]
    }
    
    # Exclude overly fast responses
    # Track how many were excluded
    excludedLatency <- 0
    if (!missing(ExclusionLatency)) {
      if (ExclusionLatency < 0) {
        stop("Set ExclusionLatency to a positive (or zero) numeric variable.")
      } else {
        excludedLatency <- sum(dat$RT < ExclusionLatency)
        dat <- dat[dat$RT > ExclusionLatency, ]
      }
    }
    
    # Exclude responses (not reaction times) more than x SDs away from the participants' mean
    # Track how many were excluded
    excludedOutliers <- 0
    
    if (!is.na(ExclusionSDs)) {
      if (ExclusionSDs < 0) {
        stop("Set ExclusionSDs to a positive (or zero) numeric variable.")
      } else {
        # Compute mean and sd per participant
        perParticipant <- dat %>%
          group_by_(., "Subject") %>%
          summarise_(meanResponse = "mean(Response)",
                     sdResponse = "sd(Response)")
        
        # Add perParticipant to dat
        dat <- left_join(dat, perParticipant, by = "Subject")
        
        # Check how many responses are more than x sds away from participant mean
        # dat$Low <- dat$meanResponse - ExclusionSDs * dat$sdResponse
        dat$Outlier <-
          (dat$Response < dat$meanResponse - ExclusionSDs * dat$sdResponse) |
          (dat$Response > dat$meanResponse + ExclusionSDs * dat$sdResponse)
        excludedOutliers <- sum(dat$Outlier)
        
        # Remove outliers
        dat <- dat %>% filter(Outlier == FALSE)
      }
    } else if (is.na(ExclusionSDs)) {
      dat <- dat
    }
    
    # Exclude responses (not reaction times) more than x SDs away from the overall mean
        
    # Track how many were excluded
    excludedOutliersOverall <- 0
    if (!is.na(ExclusionSDsOverall)) {
      if (ExclusionSDsOverall < 0) {
        stop("Set ExclusionSDsOverall to a positive (or zero) numeric variable.")
      } else {
        # Check how many responses are more than x sds away from participant mean
        OutlierOverall <- 
          (dat$Response < mean(dat$Response) - ExclusionSDsOverall * sd(dat$Response)) | 
          (dat$Response > mean(dat$Response) + ExclusionSDsOverall * sd(dat$Response))
        excludedOutliersOverall <- sum(OutlierOverall)
        # Remove outliers
        dat <- dat[OutlierOverall == FALSE, ]
      }
    } else if (is.na(ExclusionSDsOverall)) {
      dat <- dat
    }
    
    
    # Select dependent variable
    if (!(DV %in% c(
      "mean difference",
      "mean ratio",
      "median difference",
      "median ratio"
    ))) {
      stop(
        "The dependent variable (DV) should be 'mean difference', 'mean ratio', 'median difference' or 'mean ratio'.
  Please note that 'no aggregation' is not currently supported."
      )
      
    } else if (DV == "mean difference") {
      dat_DV <- dat %>%
        group_by_("Subject", "Status") %>%
        summarise_(average = "mean(Response)") %>% # mean response
        spread_("Status", "average") %>%
        mutate_(DV = quote(congruent - incongruent))    # difference score
      
      # For raw latencies: How much _SLOWER_ are participants in the congruent condition?
      #   We'd expect this to be a negative number for most participants
      #   (i.e. they're actually faster in the congruent condition).
      #   Lower numbers (= more negative numbers) indicate larger Simon effects.
      #   Prediction: This number should be LARGER for more balanced bilinguals. (sign: 1)
      
      # For speeds: How much _FASTER_ are participants in the congruent condition?
      #   We'd expect this to be positive number for most participants.
      #   Larger numbers indicate larger Simon effects.
      #   Prediction: This number should be SMALLER for more balanced bilinguals. (sign: -1)
      
      # For logs: Same as for raw latencies. (sign: 1)
      
    } else if (DV == "mean ratio") {
      dat_DV <- dat %>%
        group_by_("Subject", "Status") %>%
        summarise_(average = "mean(Response)") %>% # mean response
        spread_("Status", "average") %>%
        mutate_(DV = quote(congruent / incongruent))    # ratio score
      
      # For raw latencies: Relative to the incongruent condition, how slow are participants in the congruent condition?
      #   This number will be less than 1 for most participants.
      #   Lower numbers (more towards 0) indicate larger Simon effects.
      #   Prediction: This number should be LARGER for more balanced bilinguals. (sign: 1)
      
      # For speeds: Relative to the incongruent condition, how fast are participants in the congruent condition?
      #   This number will be more than 1 for most participants.
      #   Larger numbers indicate larger Simon effects.
      #   Prediction: This number should be SMALLER for more balanced bilinguals. (sign: -1)
      
      # For logs: Same as for raw latencies. (sign: 1)
      
      # We don't consider analyses on medians in this multiverse analysis:
      
    } else if (DV == "median difference") {
      dat_DV <- dat %>%
        group_by_("Subject", "Status") %>%
        summarise_(average = ~ median(Response)) %>% # median response
        spread_("Status", "average") %>%
        mutate_(DV = quote(congruent - incongruent))      # difference score
      
      # Predictions: see mean difference.
      
    } else if (DV == "median ratio") {
      dat_DV <- dat %>%
        group_by_("Subject", "Status") %>%
        summarise_(average = ~ median(Response)) %>% # median response
        spread_("Status", "average") %>%
        mutate_(DV = quote(congruent / incongruent))      # ratio score
      
      # Predictions: see mean ratio.
      
    }
    
    # Select predictor
    
    if (!(
      IV %in% c(
        "raw dominance",
        "absolute dominance",
        "raw dominance, oral",
        "absolute dominance, oral",
        "raw use",
        "absolute use",
        "total Swabian",
        "total Swabian, oral"
      )
    )) {
      stop(
        "The independent variable (IV) should be 'raw dominance', 'absolute dominance',
  'raw dominance, oral', 'absolute dominance, oral',
  'raw use', or 'absolute use'."
      )
      
    } else if (IV == "raw dominance") {
      dat_IV <- dat %>%
        select_("Subject", "DominanceSwabian") %>%
        distinct_() %>%
        rename_(IV = "DominanceSwabian")
      
    } else if (IV == "absolute dominance") {
      dat_IV <- dat %>%
        select_("Subject", "DominanceSwabian") %>%
        distinct_() %>%
        mutate_(IV = ~ abs(DominanceSwabian))
      
    } else if (IV == "raw dominance, oral") {
      dat_IV <- dat %>%
        select_("Subject", "DominanceSwabianOral") %>%
        distinct_() %>%
        mutate_(IV = "DominanceSwabianOral")
      
    } else if (IV == "absolute dominance, oral") {
      dat_IV <- dat %>%
        select_("Subject", "DominanceSwabianOral") %>%
        distinct_() %>%
        mutate_(IV = ~ abs(DominanceSwabianOral))
      
    } else if (IV == "raw use") {
      dat_IV <- dat %>%
        select_("Subject", "DominanceSwabianUse") %>%
        distinct_() %>%
        rename_(IV = "DominanceSwabianUse")
      
    } else if (IV == "absolute use") {
      dat_IV <- dat %>%
        select_("Subject", "DominanceSwabianUse") %>%
        distinct_() %>%
        mutate_(IV = ~ abs(DominanceSwabianUse))
      
    } else if (IV == "total Swabian") {
      dat_IV <- dat %>%
        select_("Subject", "TotalSwabian") %>%
        distinct_() %>%
        rename_(IV = "TotalSwabian")
      
    } else if (IV == "total Swabian, oral") {
      dat_IV <- dat %>%
        select_("Subject", "TotalSwabianOral") %>%
        distinct_() %>%
        rename_(IV = "TotalSwabianOral")
      
    }
    
    # Combine datasets
    dat_combined <- left_join(dat_DV, as.tbl(dat_IV), by = "Subject")
    
    # Run analysis; simple regression model.
    mod.lm <- lm(DV ~ IV, dat_combined)
    
    return(
      list(
        excludedAccuracy = excludedAccuracy,
        excludedLatency = excludedLatency,
        excludedOutliers = excludedOutliers,
        excludedOutliersOverall = excludedOutliersOverall,
        pValue =  summary(mod.lm)$coef[2, 4],
        direction = sign(coef(mod.lm)[2])
      )
    )
  }
# See if this works:
allAnalyses(data = dat,
            Task = "Flanker",
            ExclusionAccuracy = "yes",
            Transformation = "log",
            ExclusionLatency = 250,
            ExclusionSDs = 2.5,
            ExclusionSDsOverall = 2.5,
            DV = "mean difference",
            IV = "raw dominance")
$excludedAccuracy
[1] 78

$excludedLatency
[1] 6

$excludedOutliers
[1] 156

$excludedOutliersOverall
[1] 121

$pValue
[1] 0.05935

$direction
IV 
 1 

11.2 Run all analyses in grid

# Some parameter settings need to be converted to character strings.
Transformations <- as.character(alternatives$Transformation)
Tasks <- as.character(alternatives$Task)
Accuracies <- as.character(alternatives$ExclusionAccuracy)
DVs <- as.character(alternatives$DV)
IVs <- as.character(alternatives$IV)
# Prepare dataframe for the multiverse analysis
multiverse <- data.frame(Task = alternatives$Task,
                         Transformation = alternatives$Transformation,
                         ExclusionAccuracy = alternatives$ExclusionAccuracy,
                         ExclusionLatency = alternatives$ExclusionLatency,
                         ExclusionSDs = alternatives$ExclusionSDs,
                         ExclusionSDsOverall = alternatives$ExclusionSDsOverall, # not yet implemented
                         DV = alternatives$DV,
                         IV = alternatives$IV,
                         excludedAccuracy = NA,
                         excludedLatency = NA,
                         excludedOutliers = NA,
                         excludedOutliersOverall = NA,
                         pValue = NA,
                         direction = NA)
multiverse
# Loop through entire grid.
# It must be possible to do this more elegantly, but mapply() causes difficulties.
for (i in 1:nrow(alternatives)) {
  results <- allAnalyses(data = dat,
                         Task = Tasks[i],
                         Transformation = Transformations[i],
                         ExclusionAccuracy = Accuracies[i], 
                         ExclusionLatency = alternatives$ExclusionLatency[i], 
                         ExclusionSDs = alternatives$ExclusionSDs[i], 
                         ExclusionSDsOverall = alternatives$ExclusionSDsOverall[i],  # not yet implemented
                         DV = DVs[i],
                         IV = IVs[i])
  multiverse$excludedAccuracy[i] <- results$excludedAccuracy
  multiverse$excludedLatency[i] <- results$excludedLatency
  multiverse$excludedOutliers[i] <- results$excludedOutliers
  multiverse$excludedOutliersOverall[i] <- results$excludedOutliersOverall # not yet implemented
  multiverse$pValue[i] <- results$pValue
  multiverse$direction[i] <- results$direction
}
# summary(multiverse)

11.3 Results

We’re going to add a couple of variable to the multiverse dataframe:

# Was the sign of the regression coefficient,
# regardless of its significance,
# in the direction expected under the overall "bidialectalism > better executive function" hypothesis?
multiverse$DirectionExpected <- "no"
multiverse[multiverse$Transformation %in% c("raw", "log") & multiverse$direction == 1, ]$DirectionExpected <- "yes"
multiverse[multiverse$Transformation == "speed" & multiverse$direction == -1, ]$DirectionExpected <- "yes"
multiverse$DirectionExpected <- factor(multiverse$DirectionExpected)
# Was the regression coefficient significant?
multiverse$Significant <- multiverse$pValue < 0.05

We deem a handful of combinations of analytical choices to be internally inconsistent. Specifically, we don’t see how it would make sense to take the ratio of two means of logarithmically transformed values. We’ll remove these from consideration:

multiverse_sensible <- multiverse %>% 
  filter(!(Transformation == "log" & DV == "mean ratio"))

This leaves 2560 from the original 3072 analyses.

theme_set(theme_cowplot(12))
p_multi <- ggplot(multiverse_sensible,
       aes(x = pValue,
           fill = Significant)) +
  geom_histogram(colour = "black", binwidth = 0.10) +
  geom_vline(xintercept = 0.05, lty = 2, colour = "black") +
  facet_grid(Task + Transformation ~ IV) +
  scale_x_log10(breaks = c(0.01, 0.05, 0.2, 1)) +
  scale_fill_manual(values = c("white", "red3")) +
  xlab("p-value") +
  ylab("no. observations") +
  theme(legend.position = "none")
print(p_multi)

save_plot("MultiverseAnalysis.svg", p_multi, base_width = 14, base_height = 8)

Breakdown of significant results per panel:

multiverse_sensible %>% 
  group_by(Task, Transformation, IV) %>% 
  summarise(`Proportion significant` = mean(Significant),
            `Proportion expected` = mean(DirectionExpected == "yes"),
            `Median p-value` = median(pValue)) %>% 
  arrange(desc(`Proportion significant`))

Aggregate by Task and IV only:

multiverse_sensible %>% 
  group_by(Task, IV) %>% 
  summarise(`Percentage significant` = mean(Significant)*100,
            `Percentage expected` = mean(DirectionExpected == "yes")*100,
            `Median p-value` = median(pValue)) %>% 
  arrange(desc(`Percentage significant`),
          `Median p-value`)

A clickable list of all analyses sorted from the lowest p-value to the highest:

multiverse_sensible %>% 
  arrange(pValue)

Follow-up question: What causes the variability within the raw use cells?

# Excluding observations based on deviation from overall mean?
multiverse_sensible %>% 
  filter(IV == "raw use") %>% 
  ggplot(.,
       aes(x = pValue,
           fill = Significant)) +
  geom_histogram(colour = "black", binwidth = 0.10) +
  geom_vline(xintercept = 0.05, lty = 2, colour = "black") +
  facet_grid(Task + Transformation ~  ExclusionSDsOverall) +
  scale_x_log10(breaks = c(0.01, 0.05, 0.2, 1)) +
  scale_fill_manual(values = c("white", "red3")) +
  xlab("p-value") +
  ylab("no. observations") +
  theme(legend.position = "none")

# Excluding observations based on deviation from participant mean?
multiverse_sensible %>% 
  filter(IV == "raw use") %>% 
  ggplot(.,
       aes(x = pValue,
           fill = Significant)) +
  geom_histogram(colour = "black", binwidth = 0.10) +
  geom_vline(xintercept = 0.05, lty = 2, colour = "black") +
  facet_grid(Task + Transformation ~  ExclusionSDs) +
  scale_x_log10(breaks = c(0.01, 0.05, 0.2, 1)) +
  scale_fill_manual(values = c("white", "red3")) +
  xlab("p-value") +
  ylab("no. observations") +
  theme(legend.position = "none")

# Expression of DV
multiverse_sensible %>% 
  filter(IV == "raw use") %>% 
  ggplot(.,
       aes(x = pValue,
           fill = Significant)) +
  geom_histogram(colour = "black", binwidth = 0.10) +
  geom_vline(xintercept = 0.05, lty = 2, colour = "black") +
  facet_grid(Task + Transformation ~  DV) +
  scale_x_log10(breaks = c(0.01, 0.05, 0.2, 1)) +
  scale_fill_manual(values = c("white", "red3")) +
  xlab("p-value") +
  ylab("no. observations") +
  theme(legend.position = "none")

# Exclusion of incorrect responses
multiverse_sensible %>% 
  filter(IV == "raw use") %>% 
  ggplot(.,
       aes(x = pValue,
           fill = Significant)) +
  geom_histogram(colour = "black", binwidth = 0.10) +
  geom_vline(xintercept = 0.05, lty = 2, colour = "black") +
  facet_grid(Task + Transformation ~  ExclusionAccuracy) +
  scale_x_log10(breaks = c(0.01, 0.05, 0.2, 1)) +
  scale_fill_manual(values = c("white", "red3")) +
  xlab("p-value") +
  ylab("no. observations") +
  theme(legend.position = "none")

LS0tCnRpdGxlOiAiQW5hbHlzaXMgY29nbml0aXZlIGNvbnRyb2wgaW4gU3dhYmlhbiBiaWRpYWxlY3RhbHMiCmF1dGhvcjogIkphbiBWYW5ob3ZlIgpkYXRlOiAnbGFzdCB1cGRhdGU6IGByIFN5cy5EYXRlKClgJwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCmJpYmxpb2dyYXBoeTogL2hvbWUvamFuL293bkNsb3VkL0RvY3VtZW50cy9MaXRlcmF0dXJlL2JpYmxpb2dyYXBoeS5iaWIKYmlibGlvLXN0eWxlOiBhcGFsaWtlCi0tLQoKIyBTdW1tYXJ5ClRoaXMgZG9jdW1lbnQgZGV0YWlscyB0aGUgYW5hbHlzZXMgcmVwb3J0ZWQgaW4gX1RoZSBlZmZlY3RzIG9mIGJpZGlhbGVjdGFsaXNtIG9uIGV4ZWN1dGl2ZSBmdW5jdGlvbl8gKFBvYXJjaCwgVmFuaG92ZSAmIEJlcnRoZWxlKS4KRm9yIHRoaXMgc3R1ZHksIFNpbW9uIGFuZCBmbGFua2VyIGRhdGEgb2YgMzQgcGFydGljaXBhbnRzCndobyBhbHNvIGZpbGxlZCBvdXQgYSBCaWxpbmd1YWwgTGFuZ3VhZ2UgUHJvZmlsZSBmb3IgU3RhbmRhcmQgR2VybWFuIGFuZCB0aGUgU3dhYmlhbiBkaWFsZWN0IHdlcmUgYW5hbHlzZWQuCgoqKk5vdGU6KiogUGFydGljaXBhbnQgMTA4IHdhcyByZW1vdmVkIHNpbmNlIGhlIHdhc24ndCBiaWRpYWxlY3RhbC4KClRoZSBtYWluIHBvaW50cyBhcmUgc3VtbWFyaXNlZCBoZXJlOgoKMS4gRm9yIHRoZSBtYWluIGFuYWx5c2VzLCB3ZSByZS1leHByZXNzZWQgdGhlIGluZGl2aWR1YWwgcmVzcG9uc2UgbGF0ZW5jaWVzIChtcykgCmFzIHJlc3BvbnNlIF9zcGVlZHNfIChzdGltdWxpL3MpLgpGb3IgaW5zdGFuY2UsIGEgcmVzcG9uc2UgbGF0ZW5jeSBvZiAzMzMgbXMgY29ycmVzcG9uZHMgdG8gMyBzdGltdWxpIHBlciBzZWNvbmQuClJlLWV4cHJlc3NpbmcgbGF0ZW5jaWVzIGFzIHNwZWVkcyByZXN1bHRzIGluIGEgbW9yZSBub3JtYWwtaXNoIGRpc3RyaWJ1dGlvbiBvZiByZXNwb25zZXMsIAphbmQgcmVzcG9uc2Ugc3BlZWRzIGFyZSBhbHNvIHJlYWRpbHkgaW50ZXJwcmV0YWJsZS4KRm9yIGZvbGxvdy11cCBhbmFseXNlcyAoQ2hhcHRlciAiQSBtdWx0aXZlcnNlIGFuYWx5c2lzIiksIAp3ZSBhbHNvIGNvbnNpZGVyZWQgbGF0ZW5jeS1iYXNlZCBhbmFseXNlcyAoYm90aCByYXcgbGF0ZW5jaWVzIGFuZCBsb2ctdHJhbnNmb3JtZWQgbGF0ZW5jaWVzKS4KCjIuIEZvciB0aGUgbWFpbiBhbmFseXNlcywgd2UgZGlkIG5vdCBleGNsdWRlIGluY29ycmVjdCByZXNwb25zZXMgCihvZiB3aGljaCB0aGVyZSBhcmUgdmVyeSBmZXcpIG9yIHJlc3BvbnNlcyB0aGF0IGFyZSB0b28gZmFzdCBvciB0b28gc2xvdwphcyBubyBleGNsdXNpb24gY3JpdGVyaWEgd2VyZSBmb3JtdWxhdGVkIGJlZm9yZWhhbmQuCkZvciBmb2xsb3ctdXAgYW5hbHlzZXMgKENoYXB0ZXIgIkEgbXVsdGl2ZXJzZSBhbmFseXNpcyIpLCAKd2UgYWxzbyBjb25zaWRlcmVkIGV4Y2x1ZGluZyBpbmNvcnJlY3QgcmVzcG9uc2VzLCAKcmVzcG9uc2VzIGZhc3RlciB0aGFuIGEgZ2l2ZW4gdGhyZXNob2xkLApvciByZXNwb25zZXMgdG9vIGZhciBhd2F5IGZyb20gdGhlIHBhcnRpY2lwYW50J3Mgb3Igb3ZlcmFsbCBtZWFuLgoKMy4gU2ltaWxhcmx5LCB3ZSBoYXZlIGEgY2hvaWNlIGluIGhvdyB0byBleHByZXNzIHRoZSBwcmVkaWN0b3IgdmFyaWFibGUgKGxhbmd1YWdlIGRvbWluYW5jZSkuIFNlZSBwYXBlciBvbiB0aGlzLgoKNC4gV2UgZGlkbid0IGNvbnNpZGVyIGVkdWNhdGlvbiBsZXZlbCBhbmQgUmF2ZW4gcGVyZm9ybWFuY2UgYXMgY292YXJpYXRlcyBzaW5jZSB0aGVzZSBtYXkgYmUgX3Bvc3QtdHJlYXRtZW50IHZhcmlhYmxlc186IGlmIGJpZGlhbGVjdGFsaXNtIGFmZmVjdHMgZXhlY3V0aXZlIGZ1bmN0aW9uLCBpdCBtYXkgZGlyZWN0bHkgb3IgaW5kaXJlY3RseSBhZmZlY3QgYFJhdmVuYCBhbmQgYEVkdWNhdGlvbmAsIHRvby4KCjUuIFBsZWFzZSBub3RlIHRoYXQgdGhlIHBvc3NpYmxlIHByZWRpY3RvciB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQgKGl0ZW0gNSkgYXMgYXJlIHRoZSBmbGFua2VyIGFuZCBTaW1vbiBlZmZlY3RzIChDaGFwdGVyICJDb3JyZWxhdGlvbiBiZXR3ZWVuIGZsYW5rZXIgYW5kIFNpbW9uIGVmZmVjdHMiKS4KQXMgYSByZXN1bHQsIHRoZSBkaWZmZXJlbnQgYW5hbHlzZXMgYXJlIG5vdCBpbmRlcGVuZGVudCBmcm9tIG9uZSBhbm90aGVyOiAKSWYgdHdvIGRpZmZlcmVudCBhbmFseXNlcyBwcm9kdWNlIHNpbWlsYXIgcmVzdWx0cywgCnRoaXMgZG9lc24ndCBjYXJyeSB0aGUgc2FtZSB3ZWlnaHQgYXMgd2hlbiB0d28gaW5kZXBlbmRlbnQgZXhwZXJpbWVudHMgcHJvZHVjZSBhIHNpbWlsYXIgcmVzdWx0LgpUaGlzIGlzIGltcG9ydGFudCB0byBrZWVwIGluIG1pbmQgd2hlbiBpbnRlcnByZXRpbmcgdGhlIHJlc3VsdHMuCgo2LiBXZSBhbHNvIGNvbmR1Y3RlZCBhIF9tdWx0aXZlcnNlXyBhbmFseXNpcy4gCkZvciB0aGlzLCB3ZSBhdXRvbWF0aWNhbGx5IGFuYWx5c2VkIHRoZSBkYXRhIGFjY29yZGluZyB0byBhbGwgcG9zc2libGUgc2Vuc2libGUgY29tYmluYXRpb25zIG9mIGNob2ljZXMgd2UgaGF2ZSAoaG93IHRvIHRyYW5zZm9ybSB0aGUgZGF0YSwgd2hldGhlciB0byBleGNsdWRlIG91dGxpZXJzLCBldGMuKS4KWW91IGZpbmQgdGhlIHJlc3VsdHMgYXQgdGhlIGJvdHRvbSBvZiB0aGUgcGFnZS4KVGhlIHRha2UtaG9tZSBwb2ludCBoZXJlIGlzIHRoYXQgc2xpZ2h0bHkgZGlmZmVyZW50LCBidXQgc2Vuc2libGUgY2hvaWNlcyBpbiB0aGUgYW5hbHlzaXMgY2FuIHlpZWxkIHN1YnN0YW50aWFsbHkgZGlmZmVyZW50IHJlc3VsdHMgKGhlcmU6IF9wXy12YWx1ZXMpLgoKIyBTZXR0aW5ncyBhbmQgcGFja2FnZXMKVGhpcyBjb2RlIGVtcHRpZXMgdGhlIHdvcmtzcGFjZSwgb3ZlcnJpZGVzIHNvbWUgUiBkZWZhdWx0cyAobm90aGluZyB0b28gaW1wb3J0YW50KQphbmQgbG9hZHMgdGhlIHBhY2thZ2VzIHVzZWQgaW4gdGhlIGFuYWx5c2lzLgpUbyBpbnN0YWxsIHRoZSBwYWNrYWdlcywgcnVuIGBpbnN0YWxsLnBhY2thZ2VzKCJwYWNrYWdlTmFtZSIpYC4KCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KIyBFTVBUWUlORyBXT1JLU1BBQ0UhIQpybShsaXN0ID0gbHMoKSkKCiMgUiBzZXR0aW5ncwpvcHRpb25zKGRpZ2l0cyA9IDQsICMgZmV3ZXIgZGlnaXRzIGluIG91dHB1dAogICAgICAgIHNob3cuc2lnbmlmLnN0YXJzID0gRkFMU0UsICMgbm8gc2lnbmlmaWNhbmNlIHN0YXJzCiAgICAgICAgbmEuYWN0aW9uID0gbmEuZmFpbCkgIyBleHBsaWNpdCBlcnJvciBmb3IgbWlzc2luZyBkYXRhCgojIExvYWQgcGFja2FnZXMKIyBzZWUgYm90dG9tIG9mIHBhZ2UgZm9yIHZlcnNpb25zIGFuZCBzb3VyY2VzCmxpYnJhcnkoZ2dwbG90MikgICMgZm9yIHBsb3R0aW5nCmxpYnJhcnkoY293cGxvdCkgICMgLi4KbGlicmFyeShkcGx5cikgICAgIyBmb3Igd29ya2luZyB3aXRoIGRhdGFmcmFtZXMKbGlicmFyeSh0aWR5cikgICAgIyAuLgpsaWJyYXJ5KG1hZ3JpdHRyKSAjIGZvciB3cml0aW5nIG1vcmUgdHJhbnNwYXJlbnQgY29kZQpsaWJyYXJ5KGxtZTQpICAgICAjIGZvciBtaXhlZC1lZmZlY3RzIG1vZGVscwpsaWJyYXJ5KG1nY3YpICAgICAjIGZvciBnZW5lcmFsaXNlZCBhZGRpdGl2ZSBtb2RlbHMKbGlicmFyeShwYmtydGVzdCkgIyBmb3IgYm9vdHN0cmFwcGluZyBtaXhlZC1lZmZlY3RzIG1vZGVscwoKIyBTZXQgZGVmYXVsdCBwbG90dGluZyB0aGVtZQp0aGVtZV9zZXQodGhlbWVfY293cGxvdCgxMCkpCmBgYAoKU29mdHdhcmUgdmVyc2lvbnM6CgpgYGB7cn0KZGV2dG9vbHM6OnNlc3Npb25faW5mbygpCmBgYAoKCiMgUmVhZCBpbiBkYXRhClJlYWQgaW4gdGhlIFNpbW9uIGFuZCBmbGFua2VyIGRhdGEuCgpgYGB7cn0KIyBSZWFkIGluIGZsYW5rZXIvU2ltb24gZGF0YQpkYXQgPC0gcmVhZC5jc3YoImJpZGlhbGVjdGFsaXNtX2VmLmNzdiIpCgojIFJlY29kZSBTdWJqZWN0IGFzIGZhY3RvcgpkYXQkU3ViamVjdCA8LSBmYWN0b3IoZGF0JFN1YmplY3QpCgojIFJlbW92ZSBzdWJqZWN0IDEwOCAobm90IGJpZGlhbGVjdGFsKQpkYXQgPC0gZGF0ICU+JSAKICBmaWx0ZXIoU3ViamVjdCAhPSAiMTA4IikKCnN1bW1hcnkoZGF0KQpgYGAKCkJyaWVmIGV4cGxhbmF0aW9uIG9mIHRoZSB2YXJpYWJsZXM6CgoqIGBTdWJqZWN0YDogU3ViamVjdCBJRC4KKiBgU2Vzc2lvbkRhdGVgOiBXaGVuIHdlcmUgdGhlIGRhdGEgY29sbGVjdGVkPyAobW0tZGQteXl5eSkKKiBgQmxvY2tgOiBUaGUgU2ltb24gYW5kIGZsYW5rZXIgdGFza3Mgd2VyZSBwcmVzZW50ZWQgaW4gYSByYW5kb20gb3JkZXIuIElmIGBCbG9jayA9PSAxYCwgdGhlbiB0aGUgcm93IGNvbnRhaW5zIGRhdGEgZm9yIHRoZSB0YXNrIHRoYXQgd2FzIHByZXNlbnRlZCBmaXJzdDsgaWYgYEJsb2NrID09IDJgLCB0aGVuIGZvciB0aGUgdGFzayB0aGF0IHdhcyBwcmVzZW50ZWQgc2Vjb25kLgoqIGBUcmlhbGA6IFRyaWFsIG51bWJlci4gVGhpcyBkb2VzIG5vdCBzdGFydCBhdCAxIHNpbmNlIHRyYWluaW5nIHRyaWFscyB3ZXJlIHJlbW92ZWQgZnJvbSB0aGUgZGF0YXNldC4gRnVydGhlcm1vcmUsIHNvbWUgcGFydGljaXBhbnRzIG5lZWRlZCB0byByZWRvIHRoZSB0cmFpbmluZyB0cmlhbHMgc28gdGhhdCB0aGVpciBmaXJzdCB0cmlhbCBpcyBub3QgOSAoYXMgZm9yIG90aGVyIHBhcnRpY2lwYW50cykuIElmIGFueW9uZSB3YW50cyB0byBpbmNsdWRlIHRyaWFsIG51bWJlciBpbiB0aGUgYW5hbHlzZXM6IGl0IGlzIGJldHRlciB0byB1c2UgYFRyaWFsc0ZsYW5rZXIuU2FtcGxlYC9gVHJpYWxzU2ltb24uU2FtcGxlYCBpbnN0ZWFkLgoqIGBQcmVzZW50YXRpb25GbGFua2VyLkFDQ2A6IEFjY3VyYWN5IG9uIGZsYW5rZXIgdHJpYWxzLiBgMGAgPSBpbmNvcnJlY3Q7IGAxYCA9IGNvcnJlY3Q7IGBOQWAgPSBubyBmbGFua2VyIHRyaWFsLgoqIGBQcmVzZW50YXRpb25GbGFua2VyLlJUYDogUmVzcG9uc2UgbGF0ZW5jeSBvbiBmbGFua2VyIHRyaWFscyBpbiBtaWxsaXNlY29uZHMuIGBOQWAgPSBubyBmbGFua2VyIHRyaWFsLgoqIGBQcmVzZW50YXRpb25TaW1vbi5BQ0NgOiBBY2N1cmFjeSBvbiBTaW1vbiB0cmlhbHMuIGAwYCA9IGluY29ycmVjdDsgYDFgID0gY29ycmVjdDsgYE5BYCA9IG5vIFNpbW9uIHRyaWFsLgoqIGBQcmVzZW50YXRpb25TaW1vbi5SVGA6IFJlc3BvbnNlIGxhdGVuY3kgb24gU2ltb24gdHJpYWxzIGluIG1pbGxpc2Vjb25kcy4gYE5BYCA9IG5vIGZsYW5rZXIgdHJpYWwuCiogYFN0YXR1c2A6IFdhcyB0aGUgc3RpbXVsdXMgYSBgY29uZ3J1ZW50YCBvciBhbiBgaW5jb25ncnVlbnRgIHN0aW11bHVzPwoqIGBUcmlhbHNGbGFua2VyLkN5Y2xlYDogU3VwZXJmbHVvdXMuCiogYFRyaWFsc0ZsYW5rZXIuU2FtcGxlYDogVHJpYWwgbnVtYmVyIGZvciB0aGUgZmxhbmtlciBzdGltdWxpLgoqIGBUcmlhbHNTaW1vbi5TYW1wbGVgOiBUcmlhbCBudW1iZXIgZm9yIHRoZSBTaW1vbiBzdGltdWxpLgoqIGBSVGA6IFJlc3BvbnNlIGxhdGVuY3kgaW4gbWlsbGlzZWNvbmRzIHJlZ2FyZGxlc3Mgb2YgdGhlIHRhc2suCiogYEFjY3VyYWN5YDogQWNjdXJhY3kgKGAwYCB2cy4gYDFgKSByZWdhcmRsZXNzIG9mIHRoZSB0YXNrLgoKVGhlIGZvbGxvd2luZyBjb2RlIGFkZHMgdGhlIHZhcmlhYmxlIGBUcmlhbE51bWJlcmAsIGkuZS4sIHRyaWFsIG51bWJlciByZWdhcmRsZXNzIG9mIHRoZSB0YXNrLCBmb3IgY29udmVuaWVuY2U6CgpgYGB7cn0KZGF0JFRyaWFsTnVtYmVyIDwtIGlmZWxzZShkYXQkVGFzayA9PSAiRmxhbmtlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0JFRyaWFsc0ZsYW5rZXIuU2FtcGxlLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdCRUcmlhbHNTaW1vbi5TYW1wbGUpCmBgYAoKVGhlcmUgd2FzIGEgc2VsZi1wYWNlZCBicmVhayBiZXR3ZWVuIHRoZSA2NHRoIGFuZCA2NXRoIGFzIHdlbGwgYXMgYmV0d2VlbiB0aGUgMTI4dGggYW5kIDEyOXRoIHRyaWFsLgpUaGUgZm9sbG93aW5nIGNvZGUgYWRkcyB0aGlzIGluZm9ybWF0aW9uOgoKYGBge3J9CmRhdCRCbG9ja0luVGFzayA8LSBjdXQoZGF0JFRyaWFsTnVtYmVyLCBjKDAsIDY0LCAxMjgsIDE5MikpCmBgYAoKIyBSZXNwb25zZSBsYXRlbmN5IGRpc3RyaWJ1dGlvbiBhbmQgdHJhbnNmb3JtYXRpb24KCkFzIGNvdWxkIGJlIGV4cGVjdGVkLCB0aGUgcmVzcG9uc2UgbGF0ZW5jaWVzIHdlcmUgcmlnaHQgc2tld2VkLgoKYGBge3IsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSA0fQpnZ3Bsb3QoZGF0LAogICAgICAgYWVzKHggPSBSVCkpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAibGlnaHRncmV5IiwgZmlsbCA9ICJyZWQzIiwgYmlud2lkdGggPSAxMDApICsKICB4bGFiKCJSZXNwb25zZSBsYXRlbmN5IGluIG1zIikgKwogIHlsYWIoIk51bWJlciBvZiBvYnNlcnZhdGlvbnMiKSArCiAgZmFjZXRfd3JhcCh+IFRhc2sgKyBTdGF0dXMsIHNjYWxlcyA9ICJmcmVlX3giKQpgYGAKCkRvdGNoYXJ0cyAoUlRzIHNvcnRlZCBmcm9tIGxvdyB0byBoaWdoIGJ5IHRhc2sgYnkgcGFydGljaXBhbnRzKToKCmBgYHtyLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gMTh9CmdncGxvdChkYXQsCiAgICAgICBhZXMoeCA9IFJULAogICAgICAgICAgIHkgPSByYW5rKFJUKSkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEsIHNpemUgPSAwLjMpICsKICBmYWNldF9ncmlkKFN1YmplY3QgfiBUYXNrLCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZShheGlzLnRleHQueSAgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCkFjcm9zcyBhbGwgdGFza3MgYW5kIGNvbmRpdGlvbnMsIApvbmx5IGByIChtZWFuKGRhdCRSVCA8IDI1MCkgKiAxMDApICU+JSBzaWduaWYoMilgICUgb2YgdGhlIHJlc3BvbnNlIGxhdGVuY2llcyB3ZXJlIGZhc3RlciB0aGFuIDI1MCBtcywKYW5kIGByIChtZWFuKGRhdCRSVCA8IDMwMCkgKiAxMDApICU+JSBzaWduaWYoMilgICUgd2VyZSBmYXN0ZXIgdGhhbiAzMDAgbXMuClRoZSB0YWJsZSBiZWxvdyBzaG93cyB0aGUgcGVyY2VudGFnZSBvZiByZXNwb25zZSBsYXRlbmNpZXMgdW5kZXIgMjUwIG1zIHBlciB0YXNrIHBlciBjb25kaXRpb24uCgpgYGB7cn0KZGF0ICU+JSAKICBncm91cF9ieShUYXNrLCBTdGF0dXMpICU+JSAKICBzdW1tYXJpc2UoUGVyY2VudFVuZGVyMjUwbXMgPSAobWVhbihSVCA8IDI1MCkgKiAxMDApICU+JSBzaWduaWYoMikpCmBgYAoKSW4gbGlnaHQgb2YgdGhlIChhbnRpY2lwYXRlZCkgcG9zaXRpdmUgc2tldywgCml0IG1ha2VzIHNlbnNlIHRvIHRyYW5zZm9ybSB0aGUgcmVzcG9uc2UgKipsYXRlbmNpZXMqKiB0byByZXNwb25zZSAqKnNwZWVkcyoqIChpbnZlcnNlIHRyYW5zZm9ybWF0aW9uKS4gCkluc3RlYWQgb2YgYW5zd2VyaW5nIHRoZSBxdWVzdGlvbiBfSG93IG11Y2ggbWlsbGlzZWNvbmRzIGRvZXMgaXQgdGFrZSB0byByZXNwb25kIHRvIGEgc3RpbXVsdXM/XywKdGhpcyBhbnN3ZXJzIHRoZSAoZXF1aXZhbGVudCkgcXVlc3Rpb24gX0hvdyBtYW55IHN0aW11bGkgY2FuIGJlIHJlc3BvbmRlZCB0byBpbiBvbmUgc2Vjb25kP18uCk5vdGUgdGhhdCBfaGlnaGVyXyB2YWx1ZXMgbm93IG1lYW4gX2Zhc3Rlcl8gcmVzcG9uc2VzLgoKYGBge3J9CiMgSW52ZXJzZSB0cmFuc2Zvcm1hdGlvbiAqIDEwMDAgKG1pbGxpc2Vjb25kcyB0byBzZWNvbmRzKQpkYXQkU3BlZWQgPC0gMTAwMC9kYXQkUlQKYGBgCgpgYGB7ciwgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDR9CmdncGxvdChkYXQsCiAgICAgICBhZXMoeCA9IFNwZWVkKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJsaWdodGdyZXkiLCBmaWxsID0gInJlZDMiLCBiaW53aWR0aCA9IDAuMikgKwogIHhsYWIoIlJlc3BvbnNlIHNwZWVkIChzdGltdWxpL3MpIikgKwogIHlsYWIoIk51bWJlciBvZiBvYnNlcnZhdGlvbnMiKSArCiAgZmFjZXRfd3JhcCh+IFRhc2sgKyBTdGF0dXMsIHNjYWxlcyA9ICJmcmVlIikKYGBgCgpUaGlzIGFscmVhZHkgbG9va3MgbXVjaCBiZXR0ZXIuCgpXZSBkaWQgbm90IGRlY2lkZSBvbiBhIGxhdGVuY3kvc3BlZWQtYmFzZWQgb3V0bGllciBjcml0ZXJpb24gYmVmb3JlaGFuZCwgCnNpbmNlIHRoZSBpZGVhIHdhcyB0byB1c2UgdGhpcyBkYXRhc2V0IHRvIHBpY2sgc3VjaCBjcml0ZXJpYSBmb3IgYSBsYXJnZXIgc3R1ZHkuCkZvciB0aGlzIHJlYXNvbiwgd2Ugd2lsbCBub3QgZXhjbHVkZSBhbnkgb2JzZXJ2YXRpb25zIGF0IHRoaXMgc3RhZ2UuCgpgYGB7ciwgZmlnLndpZHRoID0gNCwgZmlnLmhlaWdodCA9IDE4fQpnZ3Bsb3QoZGF0LAogICAgICAgYWVzKHggPSBTcGVlZCwKICAgICAgICAgICB5ID0gcmFuayhTcGVlZCkpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxLCBzaXplID0gMC41KSArCiAgZmFjZXRfZ3JpZChTdWJqZWN0IH4gVGFzaywgc2NhbGVzID0gImZyZWUiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgoKV2UgYWxzbyB0cmllZCBhbm90aGVyIGNvbW1vbiBSVCB0cmFuc2Zvcm1hdGlvbiwgCnZpei4gdGhlIGxvZ2FyaXRobWljIHRyYW5zZm9ybWF0aW9uLgpUaGlzIHJldGFpbmVkIHNvbWUgb2YgdGhlIHJpZ2h0IHNrZXcsIGhvd2V2ZXIgKHBsb3RzIGJlbG93KSwgCmFuZCBzZWVtcyB0byBuZWNlc3NpdGF0ZSB0aGUgZXhjbHVzaW9uIG9mIGxvbmcgb3V0bGllcnM6CgpgYGB7ciwgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDR9CmdncGxvdChkYXQsCiAgICAgICBhZXMoeCA9IGxvZzEwKFJUKSkpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAibGlnaHRncmV5IiwgZmlsbCA9ICJyZWQzIiwgYmlud2lkdGggPSAwLjEpICsKICB4bGFiKCJsb2cxMCByZXNwb25zZSBzcGVlZCAobG9nMTAgbXMpIikgKwogIHlsYWIoIk51bWJlciBvZiBvYnNlcnZhdGlvbnMiKSArCiAgZmFjZXRfd3JhcCh+IFRhc2sgKyBTdGF0dXMsIHNjYWxlcyA9ICJmcmVlIikKYGBgCgojIEFjY3VyYWN5IGRpc3RyaWJ1dGlvbgoKT3ZlcmFsbCwgYHIgKG1lYW4oZGF0JEFjY3VyYWN5KSoxMDApICU+JSBzaWduaWYoMylgICUgb2YgdGhlIHJlc3BvbnNlcyBwcm92aWRlZCB3ZXJlIGFjY3VyYXRlLgpUaGUgdGFibGUgYmVsb3cgc2hvd3MgdGhlaXIgYnJlYWtkb3duIGJ5IHRhc2sgYW5kIGNvbmRpdGlvbi4KCmBgYHtyfQpkYXQgJT4lIAogIGdyb3VwX2J5KFRhc2ssIFN0YXR1cykgJT4lIAogIHN1bW1hcmlzZShgUGVyY2VudGFnZSBvZiBhY2N1cmF0ZSByZXNwb25zZXNgID0gKG1lYW4oQWNjdXJhY3kpICogMTAwKSAlPiUgc2lnbmlmKDMpKQpgYGAKCk9yIHBlciBwYXJ0aWNpcGFudDoKCmBgYHtyfQpkYXQgJT4lIAogIGdyb3VwX2J5KFRhc2ssIFN0YXR1cywgU3ViamVjdCkgJT4lIAogIHN1bW1hcmlzZShgQWNjdXJhY3lgID0gKG1lYW4oQWNjdXJhY3kpICogMTAwKSkgJT4lCiAgZ3JvdXBfYnkoVGFzaywgU3RhdHVzKSAlPiUgCiAgc3VtbWFyaXNlKGBNZWFuYCA9IG1lYW4oQWNjdXJhY3kpLAogICAgICAgICAgICBgU0RgID0gc2QoQWNjdXJhY3kpLAogICAgICAgICAgICBgTWluaW11bWAgPSBtaW4oQWNjdXJhY3kpLAogICAgICAgICAgICBgTWF4aW11bWAgPSBtYXgoQWNjdXJhY3kpKQpgYGAKCgpGb3Igbm93LCB3ZSB3aWxsIG5vdCBleGNsdWRlIGluY29ycmVjdCByZXNwb25zZXMgZnJvbSB0aGUgZGF0YXNldCwgCmJ1dCB3ZSB3aWxsIGxhdGVyIGNoZWNrIHdoZXRoZXIgdGhlcmUgaXMgYW55IHN1Z2dlc3Rpb24gb2YgYSBzcGVlZC0tYWNjdXJhY3kgdHJhZGUtb2ZmLgoKIyBTaW1vbiBhbmQgZmxhbmtlciBlZmZlY3RzIGFuZCB0aGVpciBjb3JyZWxhdGlvbgoKVGhlIGZvbGxvd2luZyBjb2RlIGNhbGN1bGF0ZXMgbWVhbiBhbmQgbWVkaWFuIHJlc3BvbnNlIHNwZWVkcyBhcyB3ZWxsIGFzIHRoZSBwcm9wb3J0aW9uIG9mIGNvcnJlY3QgcmVzcG9uc2VzIApieSBjb25ncnVlbmNlIHN0YXR1cyBhbmQgdGFzayBmb3IgZWFjaCBwYXJ0aWNpcGFudC4KVGhlbiB0aGVzZSBzdW1tYXJpZXMgYXJlIHVzZWQgdG8gY29tcHV0ZSBTaW1vbiBhbmQgZmxhbmtlciBlZmZlY3RzIGFzIGJvdGggX2RpZmZlcmVuY2VfICgkXHRleHRybXtzcGVlZCBjb25ncnVlbnR9IC0gXHRleHRybXtzcGVlZCBpbmNvbmdydWVudH0kKSBhbmQgX3JhdGlvIHNjb3Jlc18gKCRcZnJhY3tcdGV4dHJte3NwZWVkIGNvbmdydWVudH19e1x0ZXh0cm17c3BlZWQgaW5jb25ncnVlbnR9fSQpLgoKIyMgQ29tcHV0aW5nIHRoZSBlZmZlY3RzCgpTZWUgc291cmNlIGNvZGUuCgpgYGB7ciwgZWNobyA9IEZBTFNFfQojIFN1bW1hcmlzZSBkYXRhIHBlciBwYXJ0aWNpcGFudAoKIyBBY2N1cmFjeQpwZXJQYXJ0QWNjIDwtIGRhdCAlPiUgCiAgZ3JvdXBfYnkoU3ViamVjdCwgVGFzaywgU3RhdHVzKSAlPiUgCiAgc3VtbWFyaXNlKEFjY3VyYWN5ID0gbWVhbihBY2N1cmFjeSkpICU+JSAKICBzcHJlYWQoU3RhdHVzLCBBY2N1cmFjeSkgJT4lIAogIHJlbmFtZShBY2N1cmFjeUNvbmdydWVudCA9IGNvbmdydWVudCkgJT4lIAogIHJlbmFtZShBY2N1cmFjeUluY29uZ3J1ZW50ID0gaW5jb25ncnVlbnQpCgojIE1lYW4gc3BlZWQKcGVyUGFydE1lYW5TcGVlZCA8LSBkYXQgJT4lIAogIGdyb3VwX2J5KFN1YmplY3QsIFRhc2ssIFN0YXR1cykgJT4lIAogIHN1bW1hcmlzZShtZWFuU3BlZWQgPSBtZWFuKFNwZWVkKSkgJT4lIAogIHNwcmVhZChTdGF0dXMsIG1lYW5TcGVlZCkgJT4lIAogIG11dGF0ZShtZWFuU3BlZWREaWZmID0gY29uZ3J1ZW50IC0gaW5jb25ncnVlbnQpICU+JSAKICBtdXRhdGUobWVhblNwZWVkUmF0aW8gPSBjb25ncnVlbnQgLyBpbmNvbmdydWVudCkgJT4lIAogIHJlbmFtZShtZWFuU3BlZWRDb25ncnVlbnQgPSBjb25ncnVlbnQpICU+JSAKICByZW5hbWUobWVhblNwZWVkSW5jb25ncnVlbnQgPSBpbmNvbmdydWVudCkKCiMgTWVkaWFuIHNwZWVkCnBlclBhcnRNZWRpYW5TcGVlZCA8LSBkYXQgJT4lIAogIGdyb3VwX2J5KFN1YmplY3QsIFRhc2ssIFN0YXR1cykgJT4lIAogIHN1bW1hcmlzZShtZWRpYW5TcGVlZCA9IG1lZGlhbihTcGVlZCkpICU+JSAKICBzcHJlYWQoU3RhdHVzLCBtZWRpYW5TcGVlZCkgJT4lIAogIG11dGF0ZShtZWRpYW5TcGVlZERpZmYgPSBjb25ncnVlbnQgLSBpbmNvbmdydWVudCkgJT4lIAogIG11dGF0ZShtZWRpYW5TcGVlZFJhdGlvID0gY29uZ3J1ZW50IC8gaW5jb25ncnVlbnQpICU+JSAKICByZW5hbWUobWVkaWFuU3BlZWRDb25ncnVlbnQgPSBjb25ncnVlbnQpICU+JSAKICByZW5hbWUobWVkaWFuU3BlZWRJbmNvbmdydWVudCA9IGluY29uZ3J1ZW50KQoKIyBDb21iaW5lIGFsbApwZXJQYXJ0IDwtIHBlclBhcnRBY2MgJT4lIAogIGZ1bGxfam9pbiguLCBwZXJQYXJ0TWVhblNwZWVkLCBieSA9IGMoIlN1YmplY3QiLCAiVGFzayIpKSAlPiUgCiAgZnVsbF9qb2luKC4sIHBlclBhcnRNZWRpYW5TcGVlZCwgYnkgPSBjKCJTdWJqZWN0IiwgIlRhc2siKSkKYGBgCgojIyBWaXN1YWxpc2luZyB0aGUgZmxhbmtlciBhbmQgU2ltb24gZWZmZWN0cwoKQmVsb3cgd2UgaGF2ZSBwbG90dGVkIHRoZSBtZWFuIHJlc3BvbnNlIHNwZWVkIGluIHRoZSBjb25ncnVlbnQgY29uZGl0aW9uIHBlciBwYXJ0aWNpcGFudAp2ZXJzdXMgdGhlIGRpZmZlcmVuY2UgaW4gbWVhbiByZXNwb25zZSBzcGVlZCBiZXR3ZWVuIHRoZSBjb25ncnVlbnQgYW5kIHRoZSBpbmNvbmdydWVudCBjb25kaXRpb24gcGVyIHBhcnRpY2lwYW50CmZvciBib3RoIHRoZSBmbGFua2VyIGFuZCBTaW1vbiB0YXNrcy4KVGhlIF9zbWFsbGVyXyB0aGUgZGlmZmVyZW5jZSAoJHkkLWF4aXMpLCB0aGUgc21hbGxlciB0aGUgZmxhbmtlci9TaW1vbiBlZmZlY3QsCndoaWNoIGlzIHN1Z2dlc3RpdmUgb2YgX21vcmVfIGNvZ25pdGl2ZSBjb250cm9sLgoKTm90ZSB0aGF0IHRoZXJlIG1heSBiZSBzb21lIHRyZW5kIHRvd2FyZHMgZ3JlYXRlciBmbGFua2VyL1NpbW9uIGVmZmVjdHMKZm9yIHBhcnRpY2lwYW50cyB0aGF0IHJlc3BvbnNlZCBmYXN0ZXIgaW4gdGhlIGNvbmdydWVudCBjb25kaXRpb24gKHRoZSB0cmVuZCBsaW5lcyBnbyB1cCkuCkEgc3RyYWlnaHRmb3J3YXJkIGV4cGxhbmF0aW9uIGZvciB0aGlzIGlzIHJlZ3Jlc3Npb24gdG8gdGhlIG1lYW46IApmYXN0IHJlc3BvbmRlcnMgaW4gdGhlIGNvbmdydWVudCBjb25kaXRpb24KYXJlIGFsc28gZmFzdCByZXNwb25kZXJzIGluIHRoZSBpbmNvbmdydWVudCBjb25kaXRpb24sCmJ1dCB0aGUgcHJlZGljdGlvbiBpcyBpbXBlcmZlY3QuCk5vdGUsIGFsc28sIHRoYXQgdGhlcmUgaXMgY29uc2lkZXJhYmxlIHVuY2VydGFpbnR5IGFib3V0IHRoaXMgdHJlbmQgKHRoZSA5NSUgY29uZmlkZW5jZSBiYW5kcyBhcmUgd2lkZSkuCgpUaGUgZGFzaGVkIGxpbmVzIG1hcmsgdGhlIHplcm8tZGlmZmVyZW5jZSBsaW5lLgpEb3RzIGFib3ZlIHRoaXMgbGluZSBpbmRpY2F0ZSBwYXJ0aWNpcGFudHMgd2l0aCBmbGFua2VyL1NpbW9uIGVmZmVjdHMKdGhhdCBnbyBpbiB0aGUgZGlyZWN0aW9uIGV4cGVjdGVkLgpGb3IgdGhlIGZsYW5rZXIgdGFzaywgMzMgb3V0IG9mIDM0IHBhcnRpY2lwYW50cyBzaG93ZWQgdGhlIGV4cGVjdGVkIHBvc2l0aXZlIGVmZmVjdDsKZm9yIHRoZSBTaW1vbiB0YXNrLCAyOCBvdXQgb2YgMzQgZGlkLgoKYGBge3IsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSAyLjV9CmdncGxvdChwZXJQYXJ0LAogICAgICAgYWVzKHggPSBtZWFuU3BlZWRDb25ncnVlbnQsCiAgICAgICAgICAgeSA9IG1lYW5TcGVlZERpZmYpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgeGxhYigiTWVhbiByZXNwb25zZSBzcGVlZCAoc3RpbXVsaS9zKSBpbiBjb25ncnVlbnQgY29uZGl0aW9uIikgKwogIHlsYWIoIkRpZmZlcmVuY2UgaW4gbWVhbiByZXNwb25zZSBzcGVlZHNcbihjb25ncnVlbnQgLSBpbmNvbmdydWVudCkiKSArCiAgZmFjZXRfd3JhcCh+IFRhc2ssIHNjYWxlcyA9ICJmcmVlIikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsdHkgPSAyKQpgYGAKClN1bW1hcnkgdGFibGU6CgpgYGB7cn0KcGVyUGFydCAlPiUgCiAgZ3JvdXBfYnkoVGFzaykgJT4lIAogIHN1bW1hcmlzZShtZWFuKG1lYW5TcGVlZENvbmdydWVudCksCiAgICAgICAgICAgIHNkKG1lYW5TcGVlZENvbmdydWVudCksCiAgICAgICAgICAgIG1pbihtZWFuU3BlZWRDb25ncnVlbnQpLAogICAgICAgICAgICBtYXgobWVhblNwZWVkQ29uZ3J1ZW50KSwKICAgICAgICAgICAgbWVhbihtZWFuU3BlZWRJbmNvbmdydWVudCksCiAgICAgICAgICAgIHNkKG1lYW5TcGVlZEluY29uZ3J1ZW50KSwKICAgICAgICAgICAgbWluKG1lYW5TcGVlZEluY29uZ3J1ZW50KSwKICAgICAgICAgICAgbWF4KG1lYW5TcGVlZEluY29uZ3J1ZW50KSwKICAgICAgICAgICAgbWVhbihtZWFuU3BlZWREaWZmKSwKICAgICAgICAgICAgc2QobWVhblNwZWVkRGlmZiksCiAgICAgICAgICAgIG1pbihtZWFuU3BlZWREaWZmKSwKICAgICAgICAgICAgbWF4KG1lYW5TcGVlZERpZmYpKQpgYGAKCgojIyMgU3BlZWQtYWNjdXJhY3kgdHJhZGUtb2ZmPwpBY2N1cmFjeSBpcyBhYm92ZSA5MCUgZm9yIGFsbCBwYXJ0aWNpcGFudHMgaW4gYm90aCB0YXNrcy4KU2NhdHRlcnBsb3RzIG9mIGFjY3VyYWN5IHZzLiBtZWFuIHJlc3BvbnNlIHNwZWVkIGRvIG5vdCBzdWdnZXN0IGEgc3BlZWQtLWFjY3VyYWN5IHRyYWRlLW9mZi4KCmBgYHtyLCBmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gMi41fQpnZ3Bsb3QocGVyUGFydCwKICAgICAgIGFlcyh4ID0gKEFjY3VyYWN5Q29uZ3J1ZW50ICsgQWNjdXJhY3lJbmNvbmdydWVudCkvMiwKICAgICAgICAgICB5ID0gKG1lYW5TcGVlZEluY29uZ3J1ZW50ICsgbWVhblNwZWVkQ29uZ3J1ZW50KS8yKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICB4bGFiKCJBY2N1cmFjeSIpICsKICB5bGFiKCJNZWFuIHJlc3BvbnNlIHNwZWVkXG4oc3RpbXVsaS9zKSIpICsKICBmYWNldF93cmFwKH4gVGFzaywgc2NhbGVzID0gImZyZWUiKQoKZ2dwbG90KHBlclBhcnQsCiAgICAgICBhZXMoeCA9IEFjY3VyYWN5Q29uZ3J1ZW50LAogICAgICAgICAgIHkgPSBtZWFuU3BlZWRDb25ncnVlbnQpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIHhsYWIoIkFjY3VyYWN5IGNvbmdydWVudCIpICsKICB5bGFiKCJDb25ncnVlbnQgcmVzcG9uc2Ugc3BlZWRcbihzdGltdWxpL3MpIikgKwogIGZhY2V0X3dyYXAofiBUYXNrLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3Bsb3QocGVyUGFydCwKICAgICAgIGFlcyh4ID0gQWNjdXJhY3lJbmNvbmdydWVudCwKICAgICAgICAgICB5ID0gbWVhblNwZWVkSW5jb25ncnVlbnQpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIHhsYWIoIkFjY3VyYWN5IGluY29uZ3J1ZW50IikgKwogIHlsYWIoIkluY29uZ3J1ZW50IHJlc3BvbnNlIHNwZWVkXG4oc3RpbXVsaS9zKSIpICsKICBmYWNldF93cmFwKH4gVGFzaywgc2NhbGVzID0gImZyZWUiKQpgYGAKCiMjIENvcnJlbGF0aW9uIGJldHdlZW4gZmxhbmtlciBhbmQgU2ltb24gZWZmZWN0cwoKVGhlIHNjYXR0ZXJwbG90IGJlbG93IHNob3dzIGhvdyB0aGUgcGFydGljaXBhbnRzJyBTaW1vbiBhbmQgZmxhbmtlciBlZmZlY3RzIGFyZSBjb3JyZWxhdGVkLgoKYGBge3J9CmdncGxvdChwZXJQYXJ0ICU+JSAKICAgICAgICAgc2VsZWN0KFN1YmplY3QsIFRhc2ssIG1lYW5TcGVlZERpZmYpICU+JSAgCiAgICAgICAgIHNwcmVhZChUYXNrLCBtZWFuU3BlZWREaWZmKSwKICAgICAgIGFlcyh4ID0gU2ltb24sIHkgPSBGbGFua2VyKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJnYW0iLCBmb3JtdWxhID0geSB+IHMoeCkpICsKICB4bGFiKCJTaW1vbiBlZmZlY3RcbihtZWFuIHNwZWVkIGRpZmZlcmVuY2UgY29uZ3J1ZW50LWluY29uZ3J1ZW50LCBzdGltdWxpL3MpIikgKwogIHlsYWIoIkZsYW5rZXIgZWZmZWN0XG4obWVhbiBzcGVlZCBkaWZmZXJlbmNlIGNvbmdydWVudC1pbmNvbmdydWVudCwgc3RpbXVsaS9zKSIpCmBgYAoKVGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIFNpbW9uIGFuZCBmbGFua2VyIGVmZmVjdHMKZXhwcmVzc2VkIGFzIG1lYW4gc3BlZWQgZGlmZmVyZW5jZXMgaXMgX3JfID0gYHIgcGVyUGFydCAlPiUgc2VsZWN0KFN1YmplY3QsIFRhc2ssIG1lYW5TcGVlZERpZmYpICU+JSAgc3ByZWFkKFRhc2ssIG1lYW5TcGVlZERpZmYpICU+JSB1bmdyb3VwKCkgJT4lICBzdW1tYXJpc2UoY29yKEZsYW5rZXIsIFNpbW9uKSkgJT4lIHNpZ25pZigyKSAlPiUgYXMuY2hhcmFjdGVyKClgLgoKIyBTdGFuZGFyZC0tZGlhbGVjdCBkb21pbmFuY2UKCiMjIENvbXB1dGF0aW9uIG9mIGRvbWluYW5jZSB2YWx1ZXMKSGVyZSB3ZSBjYWxjdWxhdGUgdGhlIGRvbWluYW5jZSB2YWx1ZXMgb24gdGhlIGJhc2lzIG9mIHRoZSBxdWVzdGlvbm5haXJlIGRhdGEuCk1pc3Npbmcvbm9uLXN0YXRlZCBkYXRhIHdlcmUgbWFya2VkIGFzIGBOQWAsCmFuZCB3ZSB1c2VkIGEgY2VpbGluZyBvZiAyMCB5ZWFycyBmb3IgdGhlIGZpcnN0IHR3byBxdWVzdGlvbnMKKCBfV2hlbiBkaWQgeW91IHN0YXJ0IGxlYXJuaW5nIGxhbmd1YWdlIFg/XywgX0Zyb20gd2hhdCBhZ2Ugb253YXJkcyBkaWQgeW91IGZlZWwgY29tZm9ydGFibGUgaW4gbGFuZ3VhZ2UgWD9fICkuCgpgYGB7cn0KIyBSZWFkIGluIHJhdyBxdWVzdGlvbm5haXJlIGRhdGEKcXVlc3Rpb25uYWlyZSA8LSByZWFkLmNzdigiYmlkaWFsZWN0YWxpc21fcS5jc3YiKQpxdWVzdGlvbm5haXJlJFN1YmplY3QgPC0gZmFjdG9yKHF1ZXN0aW9ubmFpcmUkU3ViamVjdCkKCiMgU3VtbWFyeSBvZiBhbGwgdmFyaWFibGVzCnN1bW1hcnkocXVlc3Rpb25uYWlyZSkKYGBgCgpOb3RlIHRoYXQgdGhlcmUgYXJlIGEgY291cGxlIG9mIG1pc3NpbmcgdmFsdWVzOgoKKiBgWDFfU1dfQW9BYC4gQWdlIG9mIGFjcXVpc2l0aW9uIG9mIFN3YWJpYW46IE9uZSBwYXJ0aWNpcGFudCBuZXZlciBsZWFybnQgU3dhYmlhbiBhbmQgZG9lc24ndCBxdWFsaWZ5IGFzIGEgYmlkaWFsZWN0YWwuIFJlbW92ZSBoaXMgZGF0YS4KCmBgYHtyfQpxdWVzdGlvbm5haXJlIDwtIHF1ZXN0aW9ubmFpcmUgJT4lIAogIGZpbHRlcighaXMubmEoWDFfU1dfQW9BKSkKYGBgCgoqIGBYMl9BZ2VfU1dgLiBRdWVzdGlvbjogX0FiIHdlbGNoZW0gQWx0ZXIgaGFiZW4gU2llIHNpY2ggaW4gZGVuIGZvbGdlbmRlbiBTcHJhY2hlbiBzaWNoZXIgZ2Vmw7xobHQ/XyAKCk9uZSBvcHRpb24gd291bGQgYmUgdG8gaW1wdXRlIG1pc3NpbmcgdmFsdWVzIHdpdGggdGhlIGdyb3VwIG1lYW4sCmJ1dCB0aGF0IHdvdWxkbid0IHNlZW0gdG8gbWFrZSBtdWNoIHNlbnNlIGFzIGl0IHdvdWxkIG1lYW4gdGhhdCB0aGUgcGFydGljaXBhbnRzIGZlbHQgY29tZm9ydGFibGUgaW4gU3dhYmlhbiBiZWZvcmUgaGF2aW5nIGFjcXVpcmVkIGl0OgoKYGBge3J9CnF1ZXN0aW9ubmFpcmUgJT4lIHNlbGVjdChYMV9TV19Bb0EsIFgyX0FnZV9TVykgJT4lIGZpbHRlcihpcy5uYShYMl9BZ2VfU1cpKQpgYGAKClVzaW5nIHRoZSBtYXhpbXVtIHBvc3NpYmxlIHJlc3BvbnNlICgyMCkgbWFrZXMgbW9yZSBzZW5zZSB0byBtZS4KCmBgYHtyfQpxdWVzdGlvbm5haXJlJFgyX0FnZV9TVzIgPC0gcXVlc3Rpb25uYWlyZSRYMl9BZ2VfU1cKIyByZXBsYWNlIGJ5IG1heGltdW0gKDIwKQpxdWVzdGlvbm5haXJlJFgyX0FnZV9TVzJbaXMubmEocXVlc3Rpb25uYWlyZSRYMl9BZ2VfU1cyKV0gPC0gMjAKYGBgCgoqIGBYM19ZZWFyc19TV2AuIFF1ZXN0aW9uOiBfV2llIHZpZWxlIEphaHJlIGhhdHRlbiBTaWUgVW50ZXJyaWNodCBpbiBkZW4gZm9sZ2VuZGVuIFNwcmFjaGVuPyAoR3J1bmRzY2h1bGUsIHdlaXRlcmbDvGhyZW5kZSBTY2h1bGUsIEhvY2hzY2h1bGUpP18uIEluIGFsbCBsaWtlbGlob29kLCB0aGlzIHdvdWxkIGJlIDAgZm9yIFN3YWJpYW4uCgpgYGB7cn0KcXVlc3Rpb25uYWlyZSRYM19ZZWFyc19TVzIgPC0gcXVlc3Rpb25uYWlyZSRYM19ZZWFyc19TVwpxdWVzdGlvbm5haXJlJFgzX1llYXJzX1NXMltpcy5uYShxdWVzdGlvbm5haXJlJFgzX1llYXJzX1NXMildIDwtIDAKYGBgCgpOb3RlLCBob3dldmVyLCB0aGF0IDMgcGFydGljaXBhbnRzIHByb3ZpZGVkIG5vbi16ZXJvIHJlc3BvbnNlcywgc3VnZ2VzdGluZyB0aGF0IHRoZXkgbWF5IGhhdmUgaW50ZXJwcmV0ZWQgdGhlIHF1ZXN0aW9uIGRpZmZlcmVudGx5IGZyb20gb3RoZXIgcGFydGljaXBhbnRzOiBzY2hvb2xpbmcgaW4gU3dhYmlhbiBqdXN0IGRvZXNuJ3QgZXhpc3QuCgoqKkhlcmUgd2UgcmVwbGFjZSBub24temVybyB2YWx1ZXMgd2l0aCAwIGZvciB0aGlzIHF1ZXN0aW9uLioqCgpgYGB7cn0KcXVlc3Rpb25uYWlyZSRYM19ZZWFyc19TVzJbcXVlc3Rpb25uYWlyZSRYM19ZZWFyc19TVzIgPiAwXSA8LSAwCmBgYAoKKiBUaGUgbWF4aW11bSBmb3IgYFg0X0NvdW50cnlfREVgLCBgWDRfQ291bnRyeV9TV2AsIGBYNV9GYW1fREVgLCBgWDVfRmFtX1NXYCBzaG91bGQgYmUgMjAuCgpgYGB7cn0KcXVlc3Rpb25uYWlyZSRYNF9Db3VudHJ5X0RFW3F1ZXN0aW9ubmFpcmUkWDRfQ291bnRyeV9ERSA+IDIwXSA8LSAyMApxdWVzdGlvbm5haXJlJFg0X0NvdW50cnlfU1dbcXVlc3Rpb25uYWlyZSRYNF9Db3VudHJ5X1NXID4gMjBdIDwtIDIwCnF1ZXN0aW9ubmFpcmUkWDVfRmFtX0RFW3F1ZXN0aW9ubmFpcmUkWDVfRmFtX0RFID4gMjBdIDwtIDIwCnF1ZXN0aW9ubmFpcmUkWDVfRmFtX1NXW3F1ZXN0aW9ubmFpcmUkWDVfRmFtX1NXID4gMjBdIDwtIDIwCmBgYAoKYGBge3J9CnN1bW1hcnkocXVlc3Rpb25uYWlyZSkKYGBgCgpOb3cgY29tcHV0ZSB0aGUgc2NvcmVzIGZvciB0aGUgZGlmZmVyZW50IGRpbWVuc2lvbnMgdXNpbmcgdGhlIHByb3RvY29sIHByb3Bvc2VkIG9uIGh0dHBzOi8vc2l0ZXMubGEudXRleGFzLmVkdS9iaWxpbmd1YWwvc2NvcmluZy1hbmQtaW50ZXJwcmV0aW5nLXRoZS1yZXN1bHRzLy4KVGhlIGBQcm9maWNpZW5jeUdlcm1hbk9yYWxgIGFuZCBgUHJvZmljaWVuY3lTd2FiaWFuT3JhbGAgdmFyaWFibGVzIGRvbid0IHRha2UgaW50byBjb25zaWRlcmF0aW9uIHRoZSBwYXJ0aWNpcGFudHMnIHJlYWRpbmcgYW5kIHdyaXRpbmcgc2tpbGxzLgpGb3IgdGhlIGNvcnJlc3BvbmRpbmcgYFRvdGFsR2VybWFuT3JhbGAgYW5kIGBUb3RhbFN3YWJpYW5PcmFsYCB2YXJpYWJsZXMsIHRoZSBwcm9maWNpZW5jeSBjb21wb25lbnQgd2FzIHdlaWdodGVkIGRvdWJseSB0byBjb21wZW5zYXRlIGZvciB0aGlzLgoKYGBge3J9CnF1ZXN0aW9ubmFpcmUgPC0gcXVlc3Rpb25uYWlyZSAlPiUgCiAgbXV0YXRlKEhpc3RvcnlHZXJtYW4gPSAoMjAgLSBYMV9ERV9Bb0EpICsgKDIwIC0gWDJfQWdlX0RFKSArIFgzX1llYXJzX0RFICsgWDRfQ291bnRyeV9ERSArIFg1X0ZhbV9ERSArIFg2X0pvYl9ERSkgJT4lIAogIG11dGF0ZShIaXN0b3J5U3dhYmlhbiA9ICgyMCAtIFgxX1NXX0FvQSkgKyAoMjAgLSBYMl9BZ2VfU1cyKSArIFgzX1llYXJzX1NXMiArIFg0X0NvdW50cnlfU1cgKyBYNV9GYW1fU1cgKyBYNl9Kb2JfU1cpICU+JSAKICBtdXRhdGUoVXNlR2VybWFuID0gMTAgKiAoWDdhX0RFX1NwZWFrRnJpICsgWDhhX0RFX1NwZWFrRmFtICsgWDlhX0RFX0pvYi5VbmkgKyBYMTBhX0RFX1NwZWFrU2VsZiArIFgxMWFfREVfQ291bnQpKSAlPiUgCiAgbXV0YXRlKFVzZVN3YWJpYW4gPSAxMCAqIChYN2JfU1dfU3BlYWtGcmkgKyBYOGJfU1dfU3BlYWtGYW0gKyBYOWJfU1dfSm9iLlVuaSArIFgxMGJfU1dfU3BlYWtTZWxmICsgWDExYl9TV19Db3VudCkpICU+JSAKICBtdXRhdGUoUHJvZmljaWVuY3lHZXJtYW4gPSBYMTJfREVfU3BlYWsgKyBYMTNfREVfVW5kZXIgKyBYMTRfREVfUmVhZCArIFgxNV9ERV9Xcml0ZSkgJT4lIAogIG11dGF0ZShQcm9maWNpZW5jeVN3YWJpYW4gPSBYMTJfU1dfU3BlYWsgKyBYMTNfU1dfVW5kZXIgKyBYMTRfU1dfUmVhZCArIFgxNV9TV19Xcml0ZSkgJT4lIAogIG11dGF0ZShQcm9maWNpZW5jeUdlcm1hbk9yYWwgPSBYMTJfREVfU3BlYWsgKyBYMTNfREVfVW5kZXIpICU+JSAKICBtdXRhdGUoUHJvZmljaWVuY3lTd2FiaWFuT3JhbCA9IFgxMl9TV19TcGVhayArIFgxM19TV19VbmRlcikgJT4lIAogIG11dGF0ZShUb3RhbEdlcm1hbiA9IDAuNDU0Kkhpc3RvcnlHZXJtYW4gKyAxLjA5KlVzZUdlcm1hbiArIDIuMjcqUHJvZmljaWVuY3lHZXJtYW4pICU+JSAKICBtdXRhdGUoVG90YWxTd2FiaWFuID0gMC40NTQqSGlzdG9yeVN3YWJpYW4gKyAxLjA5KlVzZVN3YWJpYW4gKyAyLjI3KlByb2ZpY2llbmN5U3dhYmlhbikgJT4lIAogIG11dGF0ZShUb3RhbEdlcm1hbk9yYWwgPSAwLjQ1NCpIaXN0b3J5R2VybWFuICsgMS4wOSpVc2VHZXJtYW4gKyA0LjU0KlByb2ZpY2llbmN5R2VybWFuT3JhbCkgJT4lIAogIG11dGF0ZShUb3RhbFN3YWJpYW5PcmFsID0gMC40NTQqSGlzdG9yeVN3YWJpYW4gKyAxLjA5KlVzZVN3YWJpYW4gKyA0LjU0KlByb2ZpY2llbmN5U3dhYmlhbikgJT4lIAogIG11dGF0ZShEb21pbmFuY2VTd2FiaWFuID0gVG90YWxTd2FiaWFuIC0gVG90YWxHZXJtYW4pICU+JSAKICBtdXRhdGUoRG9taW5hbmNlU3dhYmlhbk9yYWwgPSBUb3RhbFN3YWJpYW5PcmFsIC0gVG90YWxHZXJtYW5PcmFsKSAlPiUgCiAgbXV0YXRlKERvbWluYW5jZVN3YWJpYW5Vc2UgPSBVc2VTd2FiaWFuIC0gVXNlR2VybWFuKQpgYGAKCiMjIERpc3RyaWJ1dGlvbiBvZiBkaWFsZWN0LS1zdGFuZGFyZCBkb21pbmFuY2UKCiMjIyBPdmVyYWxsIGRvbWluYW5jZQoKRG9taW5hbmNlIG9mIFN3YWJpYW4sIGkuZS4sIHRoZSBwYXJ0aWNpcGFudHMgb3ZlcmFsbCBTd2FiaWFuIHNjb3JlIG1pbnVzIHRoZWlyIG92ZXJhbGwgR2VybWFuIHNjb3JlOgoKYGBge3IsIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSAyLjV9CmdncGxvdChxdWVzdGlvbm5haXJlLAogICAgICAgYWVzKHggPSBEb21pbmFuY2VTd2FiaWFuKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJsaWdodGdyZXkiLCBmaWxsID0gInJlZDMiLCBiaW53aWR0aCA9IDI1KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwgMywgNiwgOSkpICsKICB4bGFiKCJEb21pbmFuY2Ugb2YgU3dhYmlhbiIpICsKICB5bGFiKCJOdW1iZXIgb2YgcGFydGljaXBhbnRzIikKYGBgCgpEb21pbmFuY2Ugb2YgU3dhYmlhbiwgdGFraW5nIG9ubHkgaW50byBhY2NvdW50IG9yYWwgLS0gbm90IHdyaXR0ZW4gLS0gcHJvZmljaWVuY3k6CgpgYGB7ciwgZmlnLndpZHRoID0gNCwgZmlnLmhlaWdodCA9IDIuNX0KZ2dwbG90KHF1ZXN0aW9ubmFpcmUsCiAgICAgICBhZXMoeCA9IERvbWluYW5jZVN3YWJpYW5PcmFsKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJsaWdodGdyZXkiLCBmaWxsID0gInJlZDMiLCBiaW53aWR0aCA9IDI1KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwgMywgNiwgOSkpICsKICB4bGFiKCJEb21pbmFuY2Ugb2YgU3dhYmlhbiAob3JhbCkiKSArCiAgeWxhYigiTnVtYmVyIG9mIHBhcnRpY2lwYW50cyIpCmBgYAoKRG9taW5hbmNlIG9mIFN3YWJpYW4sIGNvbnNpZGVyaW5nIG9ubHkgdGhlIF91c2VfIGRpbWVuc2lvbiwgbm90IHRoZSBvdGhlciBkaW1lbnNpb25zOgoKYGBge3IsIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSAyLjV9CmdncGxvdChxdWVzdGlvbm5haXJlLAogICAgICAgYWVzKHggPSBEb21pbmFuY2VTd2FiaWFuVXNlKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJsaWdodGdyZXkiLCBmaWxsID0gInJlZDMiLCBiaW5zID0gMTIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLCAzLCA2LCA5KSkgKwogIHhsYWIoIkRvbWluYW5jZSBvZiBTd2FiaWFuICh1c2UpIikgKwogIHlsYWIoIk51bWJlciBvZiBwYXJ0aWNpcGFudHMiKQpgYGAKCgojIyBUb3RhbCBTd2FiaWFuCgpUb3RhbCBTd2FiaWFuIHNjb3JlLCBpLmUuLCBub3QgdGFraW5nIGludG8gYWNjb3VudCB0aGUgcGFydGljaXBhbnRzJyBHZXJtYW4gc2NvcmVzOgoKYGBge3IsIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSAyLjV9CmdncGxvdChxdWVzdGlvbm5haXJlLAogICAgICAgYWVzKHggPSBUb3RhbFN3YWJpYW4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oY29sb3VyID0gImxpZ2h0Z3JleSIsIGZpbGwgPSAicmVkMyIsIGJpbnMgPSAxMCkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDAsIDMsIDYsIDkpKSArCiAgeGxhYigiVG90YWwgU3dhYmlhbiBzY29yZSIpICsKICB5bGFiKCJOdW1iZXIgb2YgcGFydGljaXBhbnRzIikKYGBgCgpUb3RhbCBTd2FiaWFuIHNjb3JlLCBvcmFsIHNraWxscyBvbmx5OgoKYGBge3IsIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSAyLjV9CmdncGxvdChxdWVzdGlvbm5haXJlLAogICAgICAgYWVzKHggPSBUb3RhbFN3YWJpYW5PcmFsKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJsaWdodGdyZXkiLCBmaWxsID0gInJlZDMiLCBiaW5zID0gMTApICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLCAzLCA2LCA5KSkgKwogIHhsYWIoIlRvdGFsIFN3YWJpYW4gc2NvcmUgKG9yYWwgb25seSkiKSArCiAgeWxhYigiTnVtYmVyIG9mIHBhcnRpY2lwYW50cyIpCmBgYAoKIyMgUmF2ZW4KCmBgYHtyLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gMi41fQpnZ3Bsb3QocXVlc3Rpb25uYWlyZSwKICAgICAgIGFlcyh4ID0gUmF2ZW4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oY29sb3VyID0gImxpZ2h0Z3JleSIsIGZpbGwgPSAicmVkMyIsIGJpbndpZHRoID0gMikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDUsIDksIDEzLCAxNykpICsKICB4bGFiKCJSYXZlbiBzY29yZSAob3V0IG9mIDE4IikgKyAKICB5bGFiKCJOdW1iZXIgb2YgcGFydGljaXBhbnRzIikKYGBgCgojIyBUYWJsZSB3aXRoIHN1bW1hcnkgc3RhdGlzdGljcwoKYGBge3J9CiMgQWdlCnF1ZXN0aW9ubmFpcmUgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihBZ2UpLAogICAgICAgICAgICBzZCA9IHNkKEFnZSksCiAgICAgICAgICAgIG1pbiA9IG1pbihBZ2UpLAogICAgICAgICAgICBtYXggPSBtYXgoQWdlKSkKCiMgUmF2ZW4KcXVlc3Rpb25uYWlyZSAlPiUgCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKFJhdmVuKSwKICAgICAgICAgICAgc2QgPSBzZChSYXZlbiksCiAgICAgICAgICAgIG1pbiA9IG1pbihSYXZlbiksCiAgICAgICAgICAgIG1heCA9IG1heChSYXZlbikpCgojIEFvQSBTdC4gR2VybWFuCnF1ZXN0aW9ubmFpcmUgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihYMV9ERV9Bb0EpLAogICAgICAgICAgICBzZCA9IHNkKFgxX0RFX0FvQSksCiAgICAgICAgICAgIG1pbiA9IG1pbihYMV9ERV9Bb0EpLAogICAgICAgICAgICBtYXggPSBtYXgoWDFfREVfQW9BKSkKCiMgQW9BIFN3YWJpYW4KcXVlc3Rpb25uYWlyZSAlPiUgCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKFgxX1NXX0FvQSksCiAgICAgICAgICAgIHNkID0gc2QoWDFfU1dfQW9BKSwKICAgICAgICAgICAgbWluID0gbWluKFgxX1NXX0FvQSksCiAgICAgICAgICAgIG1heCA9IG1heChYMV9TV19Bb0EpKQoKIyBQcm9maWNpZW5jeSBTdC4gR2VybWFuCnF1ZXN0aW9ubmFpcmUgJT4lIAogIG11dGF0ZShTdGFuZGFyZEdlcm1hbiA9IChYMTJfREVfU3BlYWsgKyBYMTNfREVfVW5kZXIgKyBYMTRfREVfUmVhZCArIFgxNV9ERV9Xcml0ZSkvNCkgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihTdGFuZGFyZEdlcm1hbiksCiAgICAgICAgICAgIHNkID0gc2QoU3RhbmRhcmRHZXJtYW4pLAogICAgICAgICAgICBtaW4gPSBtaW4oU3RhbmRhcmRHZXJtYW4pLAogICAgICAgICAgICBtYXggPSBtYXgoU3RhbmRhcmRHZXJtYW4pKQoKIyBQcm9maWNpZW5jeSBTY2h3w6RiaXNjaApxdWVzdGlvbm5haXJlICU+JSAKICBtdXRhdGUoU3dhYmlhbiA9IChYMTJfU1dfU3BlYWsgKyBYMTNfU1dfVW5kZXIpLzIpICU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oU3dhYmlhbiksCiAgICAgICAgICAgIHNkID0gc2QoU3dhYmlhbiksCiAgICAgICAgICAgIG1pbiA9IG1pbihTd2FiaWFuKSwKICAgICAgICAgICAgbWF4ID0gbWF4KFN3YWJpYW4pKQoKIyBVc2UgU3QuIEdlcm1hbgpxdWVzdGlvbm5haXJlICU+JSAKICBtdXRhdGUoU3RhbmRhcmRHZXJtYW4gPSAoWDdhX0RFX1NwZWFrRnJpICsgWDhhX0RFX1NwZWFrRmFtICsgWDlhX0RFX0pvYi5VbmkpLzMpICU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oU3RhbmRhcmRHZXJtYW4pLAogICAgICAgICAgICBzZCA9IHNkKFN0YW5kYXJkR2VybWFuKSwKICAgICAgICAgICAgbWluID0gbWluKFN0YW5kYXJkR2VybWFuKSwKICAgICAgICAgICAgbWF4ID0gbWF4KFN0YW5kYXJkR2VybWFuKSkKCiMgVXNlIFN3YWJpYW4KcXVlc3Rpb25uYWlyZSAlPiUgCiAgbXV0YXRlKFN3YWJpYW4gPSAoWDdiX1NXX1NwZWFrRnJpICsgWDhiX1NXX1NwZWFrRmFtICsgWDliX1NXX0pvYi5VbmkpLzMpICU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oU3dhYmlhbiksCiAgICAgICAgICAgIHNkID0gc2QoU3dhYmlhbiksCiAgICAgICAgICAgIG1pbiA9IG1pbihTd2FiaWFuKSwKICAgICAgICAgICAgbWF4ID0gbWF4KFN3YWJpYW4pKQpgYGAKCgojIFBsYW5uZWQgYW5hbHlzaXM6IFJlbGF0aW9uc2hpcCBiZXR3ZWVuIGJpZGlhbGVjdGFsIGRvbWluYW5jZSBhbmQgU2ltb24vZmxhbmtlciBlZmZlY3RzCgojIyBSYXcgZG9taW5hbmNlCgojIyMgR3JhcGgKClRoZSBleHBlY3RhdGlvbiBhdCB0aGUgb3V0c2V0IG9mIHRoZSBzdHVkeSB3YXMgdGhhdCB0aGUgU2ltb24vZmxhbmtlciBlZmZlY3RzCnNob3VsZCBiZSBsb3dlc3QgZm9yIGJhbGFuY2VkIGJpZGlhbGVjdHMsCmkuZS4sIHBhcnRpY2lwYW50cyB3aG9zZSBkb21pbmFuY2UgdmFsdWVzIGFyZSBjbG9zZXN0IHRvIHplcm8uCgpgYGB7ciwgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDIuNX0KIyBDb21iaW5lIGRhdGFzZXRzCmNvbWJpbmVkIDwtIHBlclBhcnQgJT4lIAogIHNlbGVjdChTdWJqZWN0LCBUYXNrLCBtZWFuU3BlZWREaWZmKSAlPiUgCiAgZnVsbF9qb2luKC4sIHF1ZXN0aW9ubmFpcmUsIGJ5ID0gIlN1YmplY3QiKQoKIyBQbG90IHdpdGggRG9taW5hbmNlU3dhYmlhbgpwMSA8LSBnZ3Bsb3QoY29tYmluZWQsCiAgICAgICBhZXMoeCA9IERvbWluYW5jZVN3YWJpYW4sCiAgICAgICAgICAgeSA9IG1lYW5TcGVlZERpZmYpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImdhbSIsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJ0cCIpLAogICAgICAgICAgICAgIGZpbGwgPSAiZ3JleTcwIiwKICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siKSArCiAgZmFjZXRfd3JhcCh+IFRhc2ssIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbHR5ID0gMiwgY29sb3VyID0gImJsYWNrIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGx0eSA9IDIsIGNvbG91ciA9ICJibGFjayIpICsKICB4bGFiKCJEb21pbmFuY2Ugb2YgU3dhYmlhbiIpICsKICB5bGFiKCJEaWZmZXJlbmNlIGluIG1lYW4gc3BlZWRcbihzdGltdWxpL3MpIikKCnByaW50KHAxKQpgYGAKCiMjIyBNb2RlbHMKCiMjIyMgRmxhbmtlcgoKYGBge3J9CiMgRmxhbmtlcgpGbGFua2VyUGVyUGFydCA8LSBwZXJQYXJ0ICU+JSAKICBmdWxsX2pvaW4oLiwgcXVlc3Rpb25uYWlyZSwgYnkgPSAiU3ViamVjdCIpICU+JSAKICBmaWx0ZXIoVGFzayA9PSAiRmxhbmtlciIpCgojIEdBTTogYWxsb3cgRG9taW5hbmNlU3dhYmlhbiB0byBoYXZlIGEgbm9ubGluZWFyIGVmZmVjdAojIFRoaXMgY29ycmVzcG9uZHMgdG8gdGhlIHNjYXR0ZXJwbG90IHNtb290aGVyIGFib3ZlCmZsYW5rZXIuZ2FtIDwtIGdhbShtZWFuU3BlZWREaWZmIH4gcyhEb21pbmFuY2VTd2FiaWFuLCBicyA9ICJ0cCIpLAogICAgICAgICAgICAgICAgIGRhdGEgPSBGbGFua2VyUGVyUGFydCkKc3VtbWFyeShmbGFua2VyLmdhbSkKCiMgZWRmID0gMS4wNCBtZWFucyB0aGF0IHRoZSBlZmZlY3Qgb2YgRG9taW5hbmNlU3dhYmlhbiBpcyBsaW5lYXIsCiMgYXMgdGhlIHNjYXR0ZXJwbG90IHNob3dzLiBUaGlzIGlzIG5vdCB3aGF0IHdhcyBwcmVkaWN0ZWQuCgojIFJlZml0IGluIGxpbmVhciBtb2RlbDoKZmxhbmtlci5sbSA8LSBsbShtZWFuU3BlZWREaWZmIH4gRG9taW5hbmNlU3dhYmlhbiwgZGF0YSA9IEZsYW5rZXJQZXJQYXJ0KQpzdW1tYXJ5KGZsYW5rZXIubG0pCgojIFZpc3VhbCBtb2RlbCBjaGVjazoKcGFyKG1mcm93ID0gYygyLCAyKSkKcGxvdChmbGFua2VyLmxtKQpwYXIobWZyb3cgPSBjKDEsIDEpKQojIEFsbCBvZiB0aGlzIGxvb2tzIGZpbmUuCmBgYAoKQ29uY2x1c2lvbjogbm8gZXZpZGVuY2UgZm9yIGEgbm9uLWxpbmVhciB0cmVuZC4gCkxpbmVhciB0cmVuZDogJFxoYXR7XGJldGF9ID0gLTAuMDAwOCBccG0gMC4wMDA0JCwgJHQoMzIpID0gMi4zJCwgJHAgPSAwLjAzJC4KCiMjIyMgU2ltb24KCmBgYHtyfQojIFNpbW9uClNpbW9uUGVyUGFydCA8LSBwZXJQYXJ0ICU+JSAKICBmdWxsX2pvaW4oLiwgcXVlc3Rpb25uYWlyZSwgYnkgPSAiU3ViamVjdCIpICU+JSAKICBmaWx0ZXIoVGFzayA9PSAiU2ltb24iKQoKIyBHQU06IGFsbG93IERvbWluYW5jZVN3YWJpYW4gdG8gaGF2ZSBhIG5vbmxpbmVhciBlZmZlY3QKIyBUaGlzIGNvcnJlc3BvbmRzIHRvIHRoZSBzY2F0dGVycGxvdCBzbW9vdGhlciBhYm92ZQpzaW1vbi5nYW0gPC0gZ2FtKG1lYW5TcGVlZERpZmYgfiBzKERvbWluYW5jZVN3YWJpYW4sIGJzID0gInRwIiksCiAgICAgICAgICAgICAgICAgZGF0YSA9IFNpbW9uUGVyUGFydCkKc3VtbWFyeShzaW1vbi5nYW0pCgojIGVkZiA9IDEgc3VnZ2VzdHMgdGhhdCB0aGUgZWZmZWN0IG9mIFN3YWJpYW4gZG9taW5hbmNlCiMgaXMgbGluZWFyLgpzaW1vbi5sbSA8LSBsbShtZWFuU3BlZWREaWZmIH4gRG9taW5hbmNlU3dhYmlhbiwKICAgICAgICAgICAgICAgICBkYXRhID0gU2ltb25QZXJQYXJ0KQpzdW1tYXJ5KHNpbW9uLmxtKQpgYGAKCkNvbmNsdXNpb246IG5vIGV2aWRlbmNlIGZvciBhIG5vbi1saW5lYXIgdHJlbmQuIApMaW5lYXIgdHJlbmQ6ICRcaGF0e1xiZXRhfSA9IC0wLjAwMDkgXHBtIDAuMDAwNCQsICR0KDMyKSA9IDIuNCQsICRwID0gMC4wMiQuCgojIyBBYnNvbHV0ZSBkb21pbmFuY2UKCiMjIyBHcmFwaAoKQW5vdGhlciB3YXkgb2YgcHV0dGluZyB0aGlzIGlzIHRvIHNheSB0aGF0IHRoZSBwYXJ0aWNpcGFudHMgd2l0aCB0aGUgbG93ZXN0IGFic29sdXRlIGRvbWluYW5jZSB2YWx1ZXMgCnNob3VsZCBoYXZlIHRoZSBsb3dlc3QgRmxhbmtlci9TaW1vbiBlZmZlY3RzLgoKYGBge3IsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSAyLjV9CiMgUGxvdCB3aXRoIERvbWluYW5jZVN3YWJpYW4KcDIgPC0gZ2dwbG90KGNvbWJpbmVkLAogICAgICAgYWVzKHggPSBhYnMoRG9taW5hbmNlU3dhYmlhbiksCiAgICAgICAgICAgeSA9IG1lYW5TcGVlZERpZmYpKSArCiAgICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAiZ2FtIiwgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gInRwIiksCiAgICAgICAgICAgICAgZmlsbCA9ICJncmV5NzAiLAogICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsKICBmYWNldF93cmFwKH4gVGFzaywgc2NhbGVzID0gImZyZWVfeSIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsdHkgPSAyLCBjb2xvdXIgPSAiYmxhY2siKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbHR5ID0gMiwgY29sb3VyID0gImJsYWNrIikgKwogIHhsYWIoIkFic29sdXRlIGRvbWluYW5jZSIpICsKICB5bGFiKCJEaWZmZXJlbmNlIGluIG1lYW4gc3BlZWRcbihzdGltdWxpL3MpIikKCnByaW50KHAyKQoKQW5hbHlzaXMxIDwtIHBsb3RfZ3JpZChwMSwgcDIsCiAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDEsIGFsaWduID0gImgiKQpzYXZlX3Bsb3QoIkFuYWx5c2lzMV9SYXdEYXRhLnN2ZyIsIEFuYWx5c2lzMSwgYmFzZV9oZWlnaHQgPSA0LCBiYXNlX3dpZHRoID0gNikKYGBgCgojIyMgTW9kZWxzCgojIyMjIEZsYW5rZXIKCmBgYHtyfQojIEdBTTogYWxsb3cgYWJzKERvbWluYW5jZVN3YWJpYW4pIHRvIGhhdmUgYSBub25saW5lYXIgZWZmZWN0CiMgVGhpcyBjb3JyZXNwb25kcyB0byB0aGUgc2NhdHRlcnBsb3Qgc21vb3RoZXIgYWJvdmUKZmxhbmtlci5nYW0gPC0gZ2FtKG1lYW5TcGVlZERpZmYgfiBzKGFicyhEb21pbmFuY2VTd2FiaWFuKSwgYnMgPSAidHAiKSwKICAgICAgICAgICAgICAgICBkYXRhID0gRmxhbmtlclBlclBhcnQpCnN1bW1hcnkoZmxhbmtlci5nYW0pCgojIGVkZiA9IDEgbWVhbnMgdGhhdCB0aGUgZWZmZWN0IG9mIERvbWluYW5jZVN3YWJpYW4gaXMgbGluZWFyLAojIGFzIHRoZSBzY2F0dGVycGxvdCBzaG93cy4KCiMgUmVmaXQgaW4gbGluZWFyIG1vZGVsOgpmbGFua2VyLmxtIDwtIGxtKG1lYW5TcGVlZERpZmYgfiBhYnMoRG9taW5hbmNlU3dhYmlhbiksIGRhdGEgPSBGbGFua2VyUGVyUGFydCkKc3VtbWFyeShmbGFua2VyLmxtKQoKIyBWaXN1YWwgbW9kZWwgY2hlY2s6CnBhcihtZnJvdyA9IGMoMiwgMikpCnBsb3QoZmxhbmtlci5sbSkKcGFyKG1mcm93ID0gYygxLCAxKSkKIyBBbGwgb2YgdGhpcyBsb29rcyBmaW5lLgpgYGAKCkNvbmNsdXNpb246IG5vIGV2aWRlbmNlIGZvciBhIGxpbmVhciB0cmVuZC4gCkxpbmVhciB0cmVuZDogJFxoYXR7XGJldGF9ID0gLTAuMDAwMSBccG0gMC4wMDA3JCwgJHQoMzIpID0gMC4yJCwgJHAgPSAwLjg1JC4KCiMjIyMgU2ltb24KCmBgYHtyfQojIEdBTTogYWxsb3cgYWJzKERvbWluYW5jZVN3YWJpYW4pIHRvIGhhdmUgYSBub25saW5lYXIgZWZmZWN0CiMgVGhpcyBjb3JyZXNwb25kcyB0byB0aGUgc2NhdHRlcnBsb3Qgc21vb3RoZXIgYWJvdmUKc2ltb24uZ2FtIDwtIGdhbShtZWFuU3BlZWREaWZmIH4gcyhhYnMoRG9taW5hbmNlU3dhYmlhbiksIGJzID0gInRwIiksCiAgICAgICAgICAgICAgICAgZGF0YSA9IFNpbW9uUGVyUGFydCkKc3VtbWFyeShzaW1vbi5nYW0pCgojIGVkZiA9IDEgbWVhbnMgdGhhdCB0aGUgZWZmZWN0IG9mIERvbWluYW5jZVN3YWJpYW4gaXMgbGluZWFyLAojIGFzIHRoZSBzY2F0dGVycGxvdCBzaG93cy4KCiMgUmVmaXQgaW4gbGluZWFyIG1vZGVsOgpzaW1vbi5sbSA8LSBsbShtZWFuU3BlZWREaWZmIH4gYWJzKERvbWluYW5jZVN3YWJpYW4pLCBkYXRhID0gU2ltb25QZXJQYXJ0KQpzdW1tYXJ5KHNpbW9uLmxtKQoKIyBWaXN1YWwgbW9kZWwgY2hlY2s6CnBhcihtZnJvdyA9IGMoMiwgMikpCnBsb3Qoc2ltb24ubG0pCnBhcihtZnJvdyA9IGMoMSwgMSkpCiMgQWxsIG9mIHRoaXMgbG9va3MgZmluZS4KYGBgCgpDb25jbHVzaW9uOiBubyBldmlkZW5jZSBmb3IgYSBsaW5lYXIgdHJlbmQuIApMaW5lYXIgdHJlbmQ6ICRcaGF0e1xiZXRhfSA9IDAuMDAwNiBccG0gMC4wMDA3JCwgJHQoMzIpID0gMC44JCwgJHAgPSAwLjQzJC4KCiMjIENvbmNsdXNpb24KClRoZXJlIGlzIG5vIGluZGljYXRpb24gb2YgYW55IGVmZmVjdCBjb25zaXN0ZW50IHdpdGggb3VyIGEgcHJpb3JpIGh5cG90aGVzaXMgaGVyZS4KCiMgUG9zdC1ob2MgYW5hbHlzaXM6IENvbnRyaWJ1dGlvbiBvZiBTd2FiaWFuIHRvIHRoZSBiaWRpYWxlY3RhbCByZXBlcnRvaXJlCgojIyBHcmFwaHMKYGBge3J9CiMgUGxvdCB3aXRoIFRvdGFsU3dhYmlhbgpwMyA8LSBnZ3Bsb3QoY29tYmluZWQsCiAgICAgICBhZXMoeCA9IFRvdGFsU3dhYmlhbiwKICAgICAgICAgICB5ID0gbWVhblNwZWVkRGlmZikpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAiZ2FtIiwgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gInRwIiksCiAgICAgICAgICAgICAgZmlsbCA9ICJncmV5NzAiLAogICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsKICBmYWNldF93cmFwKH4gVGFzaywgc2NhbGVzID0gImZyZWVfeSIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsdHkgPSAyLCBjb2xvdXIgPSAiYmxhY2siKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbHR5ID0gMiwgY29sb3VyID0gImJsYWNrIikgKwogIHhsYWIoIlRvdGFsIFN3YWJpYW4gc2NvcmUiKSArCiAgeWxhYigiRGlmZmVyZW5jZSBpbiBtZWFuIHNwZWVkXG4oc3RpbXVsaS9zKSIpCnByaW50KHAzKQpzYXZlX3Bsb3QoIkFuYWx5c2lzMl9SYXdEYXRhLnN2ZyIsIHAzLCBiYXNlX2hlaWdodCA9IDIsIGJhc2Vfd2lkdGggPSA2KQpgYGAKCiMjIE1vZGVscwoKIyMjIEZsYW5rZXIKCmBgYHtyfQojIEdBTTogYWxsb3cgVG90YWxTd2FiaWFuIHRvIGhhdmUgYSBub25saW5lYXIgZWZmZWN0CiMgVGhpcyBjb3JyZXNwb25kcyB0byB0aGUgc2NhdHRlcnBsb3Qgc21vb3RoZXIgYWJvdmUKZmxhbmtlci5nYW0gPC0gZ2FtKG1lYW5TcGVlZERpZmYgfiBzKFRvdGFsU3dhYmlhbiwgYnMgPSAidHAiKSwKICAgICAgICAgICAgICAgICBkYXRhID0gRmxhbmtlclBlclBhcnQpCnN1bW1hcnkoZmxhbmtlci5nYW0pCgojIGVkZiA9IDEgbWVhbnMgdGhhdCB0aGUgZWZmZWN0IG9mIERvbWluYW5jZVN3YWJpYW4gaXMgbGluZWFyLAojIGFzIHRoZSBzY2F0dGVycGxvdCBzaG93cy4KCiMgUmVmaXQgaW4gbGluZWFyIG1vZGVsOgpmbGFua2VyLmxtIDwtIGxtKG1lYW5TcGVlZERpZmYgfiBUb3RhbFN3YWJpYW4sIGRhdGEgPSBGbGFua2VyUGVyUGFydCkKc3VtbWFyeShmbGFua2VyLmxtKQoKIyBWaXN1YWwgbW9kZWwgY2hlY2s6CnBhcihtZnJvdyA9IGMoMiwgMikpCnBsb3QoZmxhbmtlci5sbSkKcGFyKG1mcm93ID0gYygxLCAxKSkKIyBBbGwgb2YgdGhpcyBsb29rcyBmaW5lLgpgYGAKCkxpbmVhciB0cmVuZDogJFxoYXR7XGJldGF9ID0gLTAuMDAxMCBccG0gMC4wMDA2JCwgJHQoMzIpID0gMS43JCwgJHAgPSAwLjEwJC4KCiMjIyBTaW1vbgoKYGBge3J9CiMgR0FNOiBhbGxvdyBUb3RhbFN3YWJpYW4gdG8gaGF2ZSBhIG5vbmxpbmVhciBlZmZlY3QKIyBUaGlzIGNvcnJlc3BvbmRzIHRvIHRoZSBzY2F0dGVycGxvdCBzbW9vdGhlciBhYm92ZQpzaW1vbi5nYW0gPC0gZ2FtKG1lYW5TcGVlZERpZmYgfiBzKFRvdGFsU3dhYmlhbiwgYnMgPSAidHAiKSwKICAgICAgICAgICAgICAgICBkYXRhID0gU2ltb25QZXJQYXJ0KQpzdW1tYXJ5KHNpbW9uLmdhbSkKCiMgZWRmID0gMSBtZWFucyB0aGF0IHRoZSBlZmZlY3Qgb2YgRG9taW5hbmNlU3dhYmlhbiBpcyBsaW5lYXIsCiMgYXMgdGhlIHNjYXR0ZXJwbG90IHNob3dzLgoKIyBSZWZpdCBpbiBsaW5lYXIgbW9kZWw6CnNpbW9uLmxtIDwtIGxtKG1lYW5TcGVlZERpZmYgfiBUb3RhbFN3YWJpYW4sIGRhdGEgPSBTaW1vblBlclBhcnQpCnN1bW1hcnkoc2ltb24ubG0pCgojIFZpc3VhbCBtb2RlbCBjaGVjazoKcGFyKG1mcm93ID0gYygyLCAyKSkKcGxvdChzaW1vbi5sbSkKcGFyKG1mcm93ID0gYygxLCAxKSkKIyBBbGwgb2YgdGhpcyBsb29rcyBmaW5lLgpgYGAKCkxpbmVhciB0cmVuZDogJFxoYXR7XGJldGF9ID0gLTAuMDAxMyBccG0gMC4wMDA2JCwgJHQoMzIpID0gMi4yJCwgJHAgPSAwLjAzJC4KCiMgTWl4ZWQtZWZmZWN0cyBtb2RlbHMKVGhlIG1vZGVscyByZXBvcnRlZCBhYm92ZSByZWx5IG9uIGFnZ3JlZ2F0ZWQgZGF0YS4KRm9yIHRoZSBzYWtlIG9mIGNvbXBsZXRlbmVzcywgd2Ugd2lsbCBhbHNvIGFuYWx5c2Ugbm9uLWFnZ3JlZ2F0ZWQgZGF0YSBpbiBtaXhlZC1lZmZlY3RzIG1vZGVscy4KCmBgYHtyfQojIENvbWJpbmUgcXVlc3Rpb25uYWlyZSBhbmQgbm9uLWFnZ3JlZ2F0ZWQgZGF0YQpkYXQgPC0gbWVyZ2UoZGF0LCBxdWVzdGlvbm5haXJlLCBieSA9ICJTdWJqZWN0IikKCiMgU3VtLWNvZGUgJ1N0YXR1cycgKGNvbmdydWVudCB2cy4gaW5jb25ncnVlbnQpICgwLjUgdnMuIC0wLjUpCmRhdCRuLlN0YXR1cyA8LSAoYXMubnVtZXJpYyhkYXQkU3RhdHVzKSAtIDEuNSkgKiAtMQp4dGFicyh+IG4uU3RhdHVzICsgU3RhdHVzLCBkYXQpCgojIENlbnRyZSBEb21pbmFuY2VTd2FiaWFuCmRhdCRjLkRvbWluYW5jZVN3YWJpYW4gPC0gZGF0JERvbWluYW5jZVN3YWJpYW4gLSBtZWFuKGRhdCREb21pbmFuY2VTd2FiaWFuKQoKIyBDb21wdXRlIGFuZCBjZW50cmUgYWJzb2x1dGUgRG9taW5hbmNlU3dhYmlhbgpkYXQkYS5Eb21pbmFuY2VTd2FiaWFuIDwtIGFicyhkYXQkRG9taW5hbmNlU3dhYmlhbikKZGF0JGNhLkRvbWluYW5jZVN3YWJpYW4gPC0gZGF0JGEuRG9taW5hbmNlU3dhYmlhbiAtIG1lYW4oZGF0JGEuRG9taW5hbmNlU3dhYmlhbikKCiMgQ2VudHJlIFRvdGFsU3dhYmlhbgpkYXQkYy5Ub3RhbFN3YWJpYW4gPC0gZGF0JFRvdGFsU3dhYmlhbiAtIG1lYW4oZGF0JFRvdGFsU3dhYmlhbikKCiMgU3BsaXQgdXAgYnkgdGFzawpkYXRGbGFua2VyIDwtIGRhdCAlPiUgZmlsdGVyKFRhc2sgPT0gIkZsYW5rZXIiKQpkYXRTaW1vbiA8LSBkYXQgJT4lIGZpbHRlcihUYXNrID09ICJTaW1vbiIpCmBgYAoKIyMgUmF3IGRvbWluYW5jZQoKVGhlIF9taW5pbXVtXyByZXF1aXJlbWVudCBpcyB0aGF0IGBEb21pbmFuY2VTd2FiaWFuYCBpbnRlcmFjdHMgd2l0aCBgbi5TdGF0dXNgLAp0aGF0IGlzIHRvIHNheSwgdGhhdCB0aGUgZWZmZWN0IG9mIGNvbmdydWVudCB2cy4gaW5jb25ncnVlbnQgdHJpYWxzIHZhcmllcwpkZXBlbmRpbmcgb24gdGhlIHBhcnRpY2lwYW50cycgYmlkaWFsZWN0YWwgZG9taW5hbmNlLgpBIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGluIGl0c2VsZiB3b3VsZCBfbm90XyBiZSBpbiBsaW5lIHdpdGggb3VyIHByZWRpY3Rpb25zLApzaW5jZSB0aGVzZSBzcGVjaWZ5IHRoYXQgdGhlIGZsYW5rZXIvU2ltb24gZWZmZWN0cyBzaG91bGQgYmUgbG93ZXN0IGFyb3VuZCBgRG9taW5hbmNlU3dhYmlhbiA9IDBgOwphIHNpZ25pZmljYW50IGludGVyYWN0aW9uIHRoYXQgc3VnZ2VzdHMsIHNheSwgdGhhdCB0aGUgZmxhbmtlci9TaW1vbiBlZmZlY3RzIGdyb3dlciBsYXJnZXIgd2l0aAppbmNyZWFzaW5nIFN3YWJpYW4gZG9taW5hbmNlIHdvdWxkIGJlIGluY29tcGF0aWJsZSB3aXRoIHRoZSBwcmVkaWN0aW9ucy4KCiMjIyBGbGFua2VyCgojIyMjIE1vZGVsIGZpdHRpbmcKCmBgYHtyfQojIEZpdCBtb2RlbCBpbiBHQU1NCmZsYW5rZXIuZ2FtIDwtIGdhbShTcGVlZCB+IG4uU3RhdHVzICsgCiAgICAgICAgICAgICAgICAgICAgIHMoRG9taW5hbmNlU3dhYmlhbiwgYnkgPSBmYWN0b3Iobi5TdGF0dXMpKSArCiAgICAgICAgICAgICAgICAgICAgIHMoU3ViamVjdCwgYnMgPSAicmUiKSArICAgICAgICAgICAgICAgICAgIyByYW5kb20gaW50ZXJjZXB0IGZvciBzdWJqZWN0CiAgICAgICAgICAgICAgICAgICAgIHMobi5TdGF0dXMsIFN1YmplY3QsIGJzID0gInJlIiksICAgICAgIyByYW5kb20gc2xvcGUgb2Ygbi5Db25ncnVlbnQgYnkgc3ViamVjdC4gCiAgICAgICAgICAgICAgICAgICAjIFRoaXMgaXMgZXF1aXZhbGVudCB0byBzYXlpbmcgdGhhdCB0aGUgRmxhbmtlciBlZmZlY3QKICAgICAgICAgICAgICAgICAgICMgdmFyaWVzIGJldHdlZW4gcGFydGljaXBhbnRzCiAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0RmxhbmtlcikKcGxvdChmbGFua2VyLmdhbSkKYGBgCgpUaGUgYERvbWluYW5jZVN3YWJpYW5gIGVmZmVjdHMgYXJlIGxpbmVhciwgc28gd2UnbGwgbW9kZWwgdGhlbSBsaW5lYXJseSB1c2luZyBgbG1lcigpYC4KCmBgYHtyfQpmbGFua2VyLm1lciA8LSBsbWVyKFNwZWVkIH4gbi5TdGF0dXMgKyBjLkRvbWluYW5jZVN3YWJpYW4gKwogICAgICAgICAgICAgICAgICAgICAgYy5Eb21pbmFuY2VTd2FiaWFuOm4uU3RhdHVzICsKICAgICAgICAgICAgICAgICAgICAgICgxICsgbi5TdGF0dXMgfCBTdWJqZWN0KSwKICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0RmxhbmtlcikKQUlDKGZsYW5rZXIubWVyKQpzdW1tYXJ5KGZsYW5rZXIubWVyKQoKIyBXaXRob3V0IHJhbmRvbSBjb3JyZWxhdGlvbj8KZmxhbmtlci5tZXIyIDwtIGxtZXIoU3BlZWQgfiBuLlN0YXR1cyArIGMuRG9taW5hbmNlU3dhYmlhbiArCiAgICAgICAgICAgICAgICAgICAgICBjLkRvbWluYW5jZVN3YWJpYW46bi5TdGF0dXMgKwogICAgICAgICAgICAgICAgICAgICAgKDEgKyBuLlN0YXR1cyB8fCBTdWJqZWN0KSwKICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0RmxhbmtlcikKQUlDKGZsYW5rZXIubWVyMikKc3VtbWFyeShmbGFua2VyLm1lcjIpCmBgYAoKYGZsYW5rZXIubWVyMmAsIHdoaWNoIHBlZ3MgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHJhbmRvbSBpbnRlcmNlcHRzIGFuZCBzbG9wZXMgYXQgMCwKc2VlbXMgdG8gYmUgYSBzbGlnaHRseSBiZXR0ZXIgbW9kZWwsIHRob3VnaCBpdCBkb2Vzbid0IG1hdHRlciBtdWNoLgoKVGhlIHNvdXJjZSBjb2RlIGZvciB0aGlzIGRvY3VtZW50IGV4cGxvcmVzIHdoZXRoZXIgdGhpcyBtb2RlbCBpcyBjb3JyZWN0bHkgc3BlY2lmaWVkCihkaXN0cmlidXRpb24gb2YgcmFuZG9tIGVmZmVjdHMgYW5kIHJlc2lkdWFscykuCkluIGNvbmNsdXNpb24sIGFsbCBzZWVtcyB0byBiZSBpbiBvcmRlci4KCmBgYHtyLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gMi41LCBldmFsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KIyBFeHRyYWN0IHJhbmRvbSBlZmZlY3RzIChpbnRlcmNlcHQgYW5kIHNsb3BlKQpGbGFua2VyLnJhbmRvbUVmZmVjdHMgPC0gcmFuZWYoZmxhbmtlci5tZXIyKSRTdWJqZWN0ICU+JSAKICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogIHJlbmFtZShJbnRlcmNlcHQgPSBgKEludGVyY2VwdClgLAogICAgICAgICBTbG9wZSA9IG4uU3RhdHVzKSAlPiUgCiAgbXV0YXRlKFBhcnRpY2lwYW50ID0gcm93bmFtZXMoLikpCgojIFBsb3QgdGhlbQpsYXR0aWNlOjpkb3RwbG90KHJhbmVmKGZsYW5rZXIubWVyMikpCgpnZ3Bsb3QoRmxhbmtlci5yYW5kb21FZmZlY3RzLAogICAgICAgYWVzKHggPSBJbnRlcmNlcHQsIHkgPSBTbG9wZSkpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gUGFydGljaXBhbnQpLCBzaXplID0gMikKCiMgVGhlIHJhbmRvbSBlZmZlY3RzIHNlZW0gdG8gYmUgb2theS4KCiMgQWRkIHJlc2lkdWFscyB0byBkYXRhZnJhbWUKZGF0RmxhbmtlciRSZXNpZHVhbCA8LSByZXNpZChmbGFua2VyLm1lcjIpCgojIEFkZCBwcmVkaWN0aW9ucyB0byBkYXRhZnJhbWUKZGF0RmxhbmtlciRGaXR0ZWQgPC0gZml0dGVkKGZsYW5rZXIubWVyMikKCiMgQXJlIHRoZSAoYXZlcmFnZSkgcmVzaWR1YWxzIHJlbGF0ZWQgdG8gdGhlIG1vZGVsIHByZWRpY3Rpb25zPwpnZ3Bsb3QoZGF0RmxhbmtlciwKICAgICAgIGFlcyh4ID0gRml0dGVkLAogICAgICAgICAgIHkgPSBSZXNpZHVhbCkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aCgpCiMgTm8sIHdoaWNoIGlzIGdvb2QuCgojIEhldGVyb3NrZWRhc3RpY2l0eTogc2VlbXMgZmluZQpnZ3Bsb3QoZGF0RmxhbmtlciwKICAgICAgIGFlcyh4ID0gRml0dGVkLAogICAgICAgICAgIHkgPSBzcXJ0KGFicyhSZXNpZHVhbCkpKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKCkKIyBUaGlzIGRvZXNuJ3Qgc2VlbSB0byBiZSB0b28gd29ycnlpbmcuCgojIFJlc2lkdWFsIHBhdHRlcm4gd2l0aCBkb21pbmFuY2U/CmdncGxvdChkYXRGbGFua2VyLAogICAgICAgYWVzKHggPSBEb21pbmFuY2VTd2FiaWFuLAogICAgICAgICAgIHkgPSBSZXNpZHVhbCkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aCgpCiMgTm8uCgojIEhldGVyb3NrZWRhc3RpY2l0eSB3aXRoIGRvbWluYW5jZT8KZ2dwbG90KGRhdEZsYW5rZXIsCiAgICAgICBhZXMoeCA9IERvbWluYW5jZVN3YWJpYW4sCiAgICAgICAgICAgeSA9IHNxcnQoYWJzKFJlc2lkdWFsKSkpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgoKQojIFRoaXMgZG9lc24ndCBzZWVtIHRvIGJlIHRvbyB3b3JyeWluZy4KCiMgTm9ybWFsaXR5IG9mIHJlc2lkdWFscwpnZ3Bsb3QoZGF0RmxhbmtlciwKICAgICAgIGFlcyh4ID0gUmVzaWR1YWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAibGlnaHRncmV5IiwgYmlud2lkdGggPSAwLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDIuNSpzZChkYXRGbGFua2VyJFJlc2lkdWFsKSwgLTIuNSpzZChkYXRGbGFua2VyJFJlc2lkdWFsKSksIGx0eSA9IDIpCgojIFRoZSByZXNpZHVhbHMgYXJlIHByZXR0eSBtdWNoIHN5bW1ldHJpY2FsbHkgZGlzdHJpYnV0ZWQsIGJ1dCBtYXkgYmUgYSBiaXQgaGVhdnktdGFpbGVkLgoKIyBSZXNpZHVhbHMgcGVyIHBhcnRpY2lwYW50CmdncGxvdChkYXRGbGFua2VyLAogICAgICAgYWVzKHggPSBSZXNpZHVhbCkpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gImxpZ2h0Z3JleSIsIGJpbndpZHRoID0gMC4yNSkgKwogIGZhY2V0X3dyYXAofiBTdWJqZWN0LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgSW5mZXJlbmNlIHRlc3RzCgpIZXJlIHdlIHRlc3QgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiBgbi5TdGF0dXNgIGFuZCBgYy5Eb21pbmFuY2VTd2FiaWFuYC4KCmBgYHtyLCBjYWNoZSA9IFRSVUV9CiMgMS4gTm9ybWFsIGFwcHJveGltYXRpb24Kc3VtbWFyeShmbGFua2VyLm1lcjIpIAojIHx0fCA9IDIuMyAgY29ycmVzcG9uZHMgdG8gcm91Z2hseSBwID0gMC4wMiwgaWYgd2UgYXNzdW1lCiMgdGhlIHQtZGlzdHJpYnV0aW9uIGlzIHdlbGwgYXBwcm94aW1hdGVkIGJ5IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KCiMgMi4gTGlrZWxpaG9vZCByYXRpbyB0ZXN0CiMgRml0IG51bGwgbW9kZWwKZmxhbmtlci5tZXIyMCA8LSBsbWVyKFNwZWVkIH4gbi5TdGF0dXMgKyBjLkRvbWluYW5jZVN3YWJpYW4gKwogICAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHx8IFN1YmplY3QpLAogICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdEZsYW5rZXIpCmFub3ZhKGZsYW5rZXIubWVyMjAsIGZsYW5rZXIubWVyMikKIyBMUlQ6IFjCsigxKSA9IDUuMiwgcCA9IDAuMDIzCgojIDMuIExhc3QtLWFuZCBiZXR0ZXItLXNvbHV0aW9uOiBQYXJhbWV0cmljIGJvb3RzdHJhcHBpbmc6CiNQQm1vZGNvbXAoZmxhbmtlci5tZXIyLCBmbGFua2VyLm1lcjIwLCBuc2ltID0gMTAwMCkKIyBwID1+IDAuMDQ7IHRoZSBwLXZhbHVlIHdpbGwgdmFyeSBmcm9tIHJ1biB0byBydW4KYGBgCgojIyMjIFZpc3VhbGlzYXRpb24gb2YgaW50ZXJhY3Rpb24KQXMgcG9pbnRlZCBvdXQgYWJvdmUsIHRoZSBtZXJlIHByZXNlbmNlIG9mIGEgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24KZG9lc24ndCBtZWFuIHRoZSBkYXRhIGFyZSBjb25zaXN0ZW50IHdpdGggb3VyIGh5cG90aGVzaXMuCkZvciB0aGlzIHJlYXNvbiwgd2UnbGwgdmlzdWFsaXNlIHRoZSBtb2RlbGxlZCBmbGFua2VyIGVmZmVjdAooc3BlZWQgZm9yIGNvbmdydWVudCB0cmlhbHMgLSBzcGVlZCBmb3IgaW5jb25ncnVlbnQgdHJpYWxzKQphY2NvcmRpbmcgdG8gdGhlIHBhcnRpY2lwYW50cycgU3dhYmlhbiBkb21pbmFuY2UgdmFsdWVzLgoKKFNpbmNlIHRoZSBHQU1NIGFib3ZlIHN1Z2dlc3RlZCB0aGUgaW50ZXJhY3Rpb24gdG8gYmUgbGluZWFyLAppdCBpcyBpbXBvc3NpYmxlIHRoYXQgdGhlIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGFib3ZlIGlzIGluZGVlZApjb25zaXN0ZW50IHdpdGggb3VyIHByZWRpY3Rpb24sIGJ1dCB0aGlzIHdpbGwgYmUgbW9yZSBvYnZpb3VzIG9uY2UgcGxvdHRlZC4pCgpgYGB7cn0KIyBEYXRhIGZyYW1lIHRvIGZpbGwgd2l0aCBwcmVkaWN0aW9ucwpuZXdkYXQgPC0gZXhwYW5kLmdyaWQobi5TdGF0dXMgPSBjKC0wLjUsIDAuNSksCiAgICAgICAgICAgICAgICAgICAgICBjLkRvbWluYW5jZVN3YWJpYW4gPSBzZXEobWluKGRhdEZsYW5rZXIkYy5Eb21pbmFuY2VTd2FiaWFuKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGRhdEZsYW5rZXIkYy5Eb21pbmFuY2VTd2FiaWFuKSkpCgojIEZpbGwgd2l0aCBwcmVkaWN0aW9ucywgaWdub3JlIHJhbmRvbSBlZmZlY3RzCm5ld2RhdCRQcmVkaWN0aW9uIDwtIHByZWRpY3QoZmxhbmtlci5tZXIyLCBuZXdkYXQsIHJlLmZvcm0gPSBOQSkKCiMgQWRkIG9yaWdpbmFsIHZhcmlhYmxlcwpuZXdkYXQkU3RhdHVzIDwtIGlmZWxzZShuZXdkYXQkbi5TdGF0dXMgPT0gLTAuNSwgImluY29uZ3J1ZW50IiwgImNvbmdydWVudCIpCm5ld2RhdCREb21pbmFuY2VTd2FiaWFuIDwtIG5ld2RhdCRjLkRvbWluYW5jZVN3YWJpYW4gKyBtZWFuKGRhdEZsYW5rZXIkRG9taW5hbmNlU3dhYmlhbikKCiMgUGxvdCBlZmZlY3Qgb2YgRG9taW5hbmNlU3dhYmlhbgpnZ3Bsb3QobmV3ZGF0LAogICAgICAgYWVzKHggPSBEb21pbmFuY2VTd2FiaWFuLAogICAgICAgICAgIHkgPSBQcmVkaWN0aW9uLAogICAgICAgICAgIGxpbmV0eXBlID0gU3RhdHVzKSkgKwogIGdlb21fbGluZSgpICsKICB4bGFiKCJTd2FiaWFuIGRvbWluYW5jZSIpICsKICB5bGFiKCJQcmVkaWN0ZWQgcmVzcG9uc2Ugc3BlZWRcbihzdGltdWxpL3MpIikKCiMgQ29tcHV0ZSBkaWZmZXJlbmNlIGJldHdlZW4gY29uZ3J1ZW50IGFuZCBpbmNvbmdydWVudCBmb3IgZWFjaCBEb21pbmFuY2UgdmFsdWUKbmV3ZGF0RGlmZnMgPC0gbmV3ZGF0ICU+JSAKICBzZWxlY3QoU3RhdHVzLCBQcmVkaWN0aW9uLCBEb21pbmFuY2VTd2FiaWFuKSAlPiUgCiAgc3ByZWFkKC4sIFN0YXR1cywgUHJlZGljdGlvbikgJT4lIAogIG11dGF0ZShEaWZmZXJlbmNlID0gY29uZ3J1ZW50IC0gaW5jb25ncnVlbnQpCgojIERpZmZlcmVuY2UgaW4gcmVzcG9uc2Ugc3BlZWRzOgpnZ3Bsb3QobmV3ZGF0RGlmZnMsCiAgICAgICBhZXMoeCA9IERvbWluYW5jZVN3YWJpYW4sCiAgICAgICAgICAgeSA9IERpZmZlcmVuY2UpKSArCiAgZ2VvbV9saW5lKCkgKwogIHhsYWIoIlN3YWJpYW4gZG9taW5hbmNlIikgKwogIHlsYWIoIkZsYW5rZXIgZWZmZWN0XG4ocmVzcG9uc2Ugc3BlZWQgZGlmZmVyZW5jZSBpbiBzdGltdWxpL3MpIikKYGBgCgpJLmUuLCBsaWtlIGZvciB0aGUgc2ltcGxlciByZWdyZXNzaW9uIG1vZGVscyBvbiBhZ2dyZWdhdGVkIGZsYW5rZXIgZGF0YSwgd2UgZmluZCB0aGF0CnRoZSBmbGFua2VyIGVmZmVjdCBpcyBsb3dlc3QgZm9yIGhpZ2ggU3dhYmlhbiBkb21pbmFuY2UsIG5vdCBmb3IgYmFsYW5jZWQgYmlkaWFsZWN0YWxpc20uCgojIyMgU2ltb24KCiMjIyMgTW9kZWwgZml0dGluZwoKYGBge3J9CiMgRml0IG1vZGVsIGluIEdBTU0Kc2ltb24uZ2FtIDwtIGdhbShTcGVlZCB+IG4uU3RhdHVzICsgCiAgICAgICAgICAgICAgICAgICAgIHMoRG9taW5hbmNlU3dhYmlhbiwgYnkgPSBmYWN0b3Iobi5TdGF0dXMpKSArCiAgICAgICAgICAgICAgICAgICAgIHMoU3ViamVjdCwgYnMgPSAicmUiKSArICAgICAgICAgICAgICAgICAgIyByYW5kb20gaW50ZXJjZXB0IGZvciBzdWJqZWN0CiAgICAgICAgICAgICAgICAgICAgIHMobi5TdGF0dXMsIFN1YmplY3QsIGJzID0gInJlIiksICAgICAgIyByYW5kb20gc2xvcGUgb2Ygbi5Db25ncnVlbnQgYnkgc3ViamVjdC4gCiAgICAgICAgICAgICAgICAgICAjIFRoaXMgaXMgZXF1aXZhbGVudCB0byBzYXlpbmcgdGhhdCB0aGUgU2ltb24gZWZmZWN0CiAgICAgICAgICAgICAgICAgICAjIHZhcmllcyBiZXR3ZWVuIHBhcnRpY2lwYW50cwogICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdFNpbW9uKQpwbG90KHNpbW9uLmdhbSkKYGBgCgpUaGUgYERvbWluYW5jZVN3YWJpYW5gIGVmZmVjdHMgYXJlIGxpbmVhciwgc28gd2UnbGwgbW9kZWwgdGhlbSBsaW5lYXJseSB1c2luZyBgbG1lcigpYC4KCmBgYHtyfQpzaW1vbi5tZXIgPC0gbG1lcihTcGVlZCB+IG4uU3RhdHVzICsgYy5Eb21pbmFuY2VTd2FiaWFuICsKICAgICAgICAgICAgICAgICAgICAgIGMuRG9taW5hbmNlU3dhYmlhbjpuLlN0YXR1cyArCiAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHwgU3ViamVjdCksCiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdFNpbW9uKQpBSUMoc2ltb24ubWVyKQpzdW1tYXJ5KHNpbW9uLm1lcikKCiMgV2l0aG91dCByYW5kb20gY29ycmVsYXRpb24/CnNpbW9uLm1lcjIgPC0gbG1lcihTcGVlZCB+IG4uU3RhdHVzICsgYy5Eb21pbmFuY2VTd2FiaWFuICsKICAgICAgICAgICAgICAgICAgICAgIGMuRG9taW5hbmNlU3dhYmlhbjpuLlN0YXR1cyArCiAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHx8IFN1YmplY3QpLAogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRTaW1vbikKQUlDKHNpbW9uLm1lcjIpCnN1bW1hcnkoc2ltb24ubWVyMikKYGBgCgpgc2ltb24ubWVyMmAsIHdoaWNoIHBlZ3MgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHJhbmRvbSBpbnRlcmNlcHRzIGFuZCBzbG9wZXMgYXQgMCwKc2VlbXMgdG8gYmUgYSBzbGlnaHRseSBiZXR0ZXIgbW9kZWwsIHRob3VnaCBpdCBkb2Vzbid0IG1hdHRlciBtdWNoLgoKVGhlIHNvdXJjZSBjb2RlIGZvciB0aGlzIGRvY3VtZW50IGV4cGxvcmVzIHdoZXRoZXIgdGhpcyBtb2RlbCBpcyBjb3JyZWN0bHkgc3BlY2lmaWVkCihkaXN0cmlidXRpb24gb2YgcmFuZG9tIGVmZmVjdHMgYW5kIHJlc2lkdWFscykuCkluIGNvbmNsdXNpb24sIGFsbCBzZWVtcyB0byBiZSBpbiBvcmRlci4KCmBgYHtyLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gMi41LCBldmFsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KIyBFeHRyYWN0IHJhbmRvbSBlZmZlY3RzIChpbnRlcmNlcHQgYW5kIHNsb3BlKQpTaW1vbi5yYW5kb21FZmZlY3RzIDwtIHJhbmVmKHNpbW9uLm1lcjIpJFN1YmplY3QgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKEludGVyY2VwdCA9IGAoSW50ZXJjZXB0KWAsCiAgICAgICAgIFNsb3BlID0gbi5TdGF0dXMpICU+JSAKICBtdXRhdGUoUGFydGljaXBhbnQgPSByb3duYW1lcyguKSkKCiMgUGxvdCB0aGVtCmxhdHRpY2U6OmRvdHBsb3QocmFuZWYoc2ltb24ubWVyMikpCgpnZ3Bsb3QoU2ltb24ucmFuZG9tRWZmZWN0cywKICAgICAgIGFlcyh4ID0gSW50ZXJjZXB0LCB5ID0gU2xvcGUpKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBhcnRpY2lwYW50KSwgc2l6ZSA9IDIpCgojIFRoZSByYW5kb20gZWZmZWN0cyBzZWVtIHRvIGJlIG9rYXkuCgojIEFkZCByZXNpZHVhbHMgdG8gZGF0YWZyYW1lCmRhdFNpbW9uJFJlc2lkdWFsIDwtIHJlc2lkKHNpbW9uLm1lcjIpCgojIEFkZCBwcmVkaWN0aW9ucyB0byBkYXRhZnJhbWUKZGF0U2ltb24kRml0dGVkIDwtIGZpdHRlZChzaW1vbi5tZXIyKQoKIyBBcmUgdGhlIChhdmVyYWdlKSByZXNpZHVhbHMgcmVsYXRlZCB0byB0aGUgbW9kZWwgcHJlZGljdGlvbnM/CmdncGxvdChkYXRTaW1vbiwKICAgICAgIGFlcyh4ID0gRml0dGVkLAogICAgICAgICAgIHkgPSBSZXNpZHVhbCkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aCgpCiMgTm8sIHdoaWNoIGlzIGdvb2QuCgojIEhldGVyb3NrZWRhc3RpY2l0eTogc2VlbXMgZmluZQpnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IEZpdHRlZCwKICAgICAgICAgICB5ID0gc3FydChhYnMoUmVzaWR1YWwpKSkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aCgpCiMgVGhpcyBkb2Vzbid0IHNlZW0gdG8gYmUgdG9vIHdvcnJ5aW5nLgoKIyBSZXNpZHVhbCBwYXR0ZXJuIHdpdGggZG9taW5hbmNlPwpnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IERvbWluYW5jZVN3YWJpYW4sCiAgICAgICAgICAgeSA9IFJlc2lkdWFsKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKCkKIyBOby4KCiMgSGV0ZXJvc2tlZGFzdGljaXR5IHdpdGggZG9taW5hbmNlPwpnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IERvbWluYW5jZVN3YWJpYW4sCiAgICAgICAgICAgeSA9IHNxcnQoYWJzKFJlc2lkdWFsKSkpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgoKQojIFRoaXMgZG9lc24ndCBzZWVtIHRvIGJlIHRvbyB3b3JyeWluZy4KCiMgTm9ybWFsaXR5IG9mIHJlc2lkdWFscwpnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IFJlc2lkdWFsKSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gImxpZ2h0Z3JleSIsIGJpbndpZHRoID0gMC4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygyLjUqc2QoZGF0U2ltb24kUmVzaWR1YWwpLCAtMi41KnNkKGRhdFNpbW9uJFJlc2lkdWFsKSksIGx0eSA9IDIpCgojIFRoZSByZXNpZHVhbHMgYXJlIHByZXR0eSBtdWNoIHN5bW1ldHJpY2FsbHkgZGlzdHJpYnV0ZWQuCgojIFJlc2lkdWFscyBwZXIgcGFydGljaXBhbnQKZ2dwbG90KGRhdFNpbW9uLAogICAgICAgYWVzKHggPSBSZXNpZHVhbCkpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gImxpZ2h0Z3JleSIsIGJpbndpZHRoID0gMC4yNSkgKwogIGZhY2V0X3dyYXAofiBTdWJqZWN0LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgSW5mZXJlbmNlIHRlc3RzCgpIZXJlIHdlIHRlc3QgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiBgbi5TdGF0dXNgIGFuZCBgYy5Eb21pbmFuY2VTd2FiaWFuYC4KCmBgYHtyLCBjYWNoZSA9IFRSVUV9CiMgMS4gTm9ybWFsIGFwcHJveGltYXRpb24Kc3VtbWFyeShzaW1vbi5tZXIyKSAKIyB8dHwgPSAyLjQgIGNvcnJlc3BvbmRzIHRvIHJvdWdobHkgcCA9IDAuMDE2LCBpZiB3ZSBhc3N1bWUKIyB0aGUgdC1kaXN0cmlidXRpb24gaXMgd2VsbCBhcHByb3hpbWF0ZWQgYnkgYSBub3JtYWwgZGlzdHJpYnV0aW9uLgoKIyAyLiBMaWtlbGlob29kIHJhdGlvIHRlc3QKIyBGaXQgbnVsbCBtb2RlbApzaW1vbi5tZXIyMCA8LSBsbWVyKFNwZWVkIH4gbi5TdGF0dXMgKyBjLkRvbWluYW5jZVN3YWJpYW4gKwogICAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHx8IFN1YmplY3QpLAogICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdFNpbW9uKQphbm92YShzaW1vbi5tZXIyMCwgc2ltb24ubWVyMikKIyBMUlQ6IFjCsigxKSA9IDUuNiwgcCA9IDAuMDE4CgojIDMuIExhc3QtLWFuZCBiZXR0ZXItLXNvbHV0aW9uOiBQYXJhbWV0cmljIGJvb3RzdHJhcHBpbmc6CiNQQm1vZGNvbXAoc2ltb24ubWVyMiwgc2ltb24ubWVyMjAsIG5zaW0gPSAxMDAwKQojIHAgPX4gMC4wMjA7IHRoZSBwLXZhbHVlIHdpbGwgdmFyeSBmcm9tIHJ1biB0byBydW4KYGBgCgojIyMjIFZpc3VhbGlzYXRpb24gb2YgaW50ZXJhY3Rpb24KQXMgcG9pbnRlZCBvdXQgYWJvdmUsIHRoZSBtZXJlIHByZXNlbmNlIG9mIGEgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24KZG9lc24ndCBtZWFuIHRoZSBkYXRhIGFyZSBjb25zaXN0ZW50IHdpdGggb3VyIGh5cG90aGVzaXMuCkZvciB0aGlzIHJlYXNvbiwgd2UnbGwgdmlzdWFsaXNlIHRoZSBtb2RlbGxlZCBTaW1vbiBlZmZlY3QKKHNwZWVkIGZvciBjb25ncnVlbnQgdHJpYWxzIC0gc3BlZWQgZm9yIGluY29uZ3J1ZW50IHRyaWFscykKYWNjb3JkaW5nIHRvIHRoZSBwYXJ0aWNpcGFudHMnIFN3YWJpYW4gZG9taW5hbmNlIHZhbHVlcy4KCihTaW5jZSB0aGUgR0FNTSBhYm92ZSBzdWdnZXN0ZWQgdGhlIGludGVyYWN0aW9uIHRvIGJlIGxpbmVhciwKaXQgaXMgaW1wb3NzaWJsZSB0aGF0IHRoZSBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBhYm92ZSBpcyBpbmRlZWQKY29uc2lzdGVudCB3aXRoIG91ciBwcmVkaWN0aW9uLCBidXQgdGhpcyB3aWxsIGJlIG1vcmUgb2J2aW91cyBvbmNlIHBsb3R0ZWQuKQoKYGBge3J9CiMgRGF0YSBmcmFtZSB0byBmaWxsIHdpdGggcHJlZGljdGlvbnMKbmV3ZGF0IDwtIGV4cGFuZC5ncmlkKG4uU3RhdHVzID0gYygtMC41LCAwLjUpLAogICAgICAgICAgICAgICAgICAgICAgYy5Eb21pbmFuY2VTd2FiaWFuID0gc2VxKG1pbihkYXRTaW1vbiRjLkRvbWluYW5jZVN3YWJpYW4pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoZGF0U2ltb24kYy5Eb21pbmFuY2VTd2FiaWFuKSkpCgojIEZpbGwgd2l0aCBwcmVkaWN0aW9ucywgaWdub3JlIHJhbmRvbSBlZmZlY3RzCm5ld2RhdCRQcmVkaWN0aW9uIDwtIHByZWRpY3Qoc2ltb24ubWVyMiwgbmV3ZGF0LCByZS5mb3JtID0gTkEpCgojIEFkZCBvcmlnaW5hbCB2YXJpYWJsZXMKbmV3ZGF0JFN0YXR1cyA8LSBpZmVsc2UobmV3ZGF0JG4uU3RhdHVzID09IC0wLjUsICJpbmNvbmdydWVudCIsICJjb25ncnVlbnQiKQpuZXdkYXQkRG9taW5hbmNlU3dhYmlhbiA8LSBuZXdkYXQkYy5Eb21pbmFuY2VTd2FiaWFuICsgbWVhbihkYXRTaW1vbiREb21pbmFuY2VTd2FiaWFuKQoKIyBQbG90IGVmZmVjdCBvZiBEb21pbmFuY2VTd2FiaWFuCmdncGxvdChuZXdkYXQsCiAgICAgICBhZXMoeCA9IERvbWluYW5jZVN3YWJpYW4sCiAgICAgICAgICAgeSA9IFByZWRpY3Rpb24sCiAgICAgICAgICAgbGluZXR5cGUgPSBTdGF0dXMpKSArCiAgZ2VvbV9saW5lKCkgKwogIHhsYWIoIlN3YWJpYW4gZG9taW5hbmNlIikgKwogIHlsYWIoIlByZWRpY3RlZCByZXNwb25zZSBzcGVlZFxuKHN0aW11bGkvcykiKQoKIyBDb21wdXRlIGRpZmZlcmVuY2UgYmV0d2VlbiBjb25ncnVlbnQgYW5kIGluY29uZ3J1ZW50IGZvciBlYWNoIERvbWluYW5jZSB2YWx1ZQpuZXdkYXREaWZmcyA8LSBuZXdkYXQgJT4lIAogIHNlbGVjdChTdGF0dXMsIFByZWRpY3Rpb24sIERvbWluYW5jZVN3YWJpYW4pICU+JSAKICBzcHJlYWQoLiwgU3RhdHVzLCBQcmVkaWN0aW9uKSAlPiUgCiAgbXV0YXRlKERpZmZlcmVuY2UgPSBjb25ncnVlbnQgLSBpbmNvbmdydWVudCkKCiMgRGlmZmVyZW5jZSBpbiByZXNwb25zZSBzcGVlZHM6CmdncGxvdChuZXdkYXREaWZmcywKICAgICAgIGFlcyh4ID0gRG9taW5hbmNlU3dhYmlhbiwKICAgICAgICAgICB5ID0gRGlmZmVyZW5jZSkpICsKICBnZW9tX2xpbmUoKSArCiAgeGxhYigiU3dhYmlhbiBkb21pbmFuY2UiKSArCiAgeWxhYigiU2ltb24gZWZmZWN0XG4ocmVzcG9uc2Ugc3BlZWQgZGlmZmVyZW5jZSBpbiBzdGltdWxpL3MpIikKYGBgCgpJLmUuLCBsaWtlIGZvciB0aGUgc2ltcGxlciByZWdyZXNzaW9uIG1vZGVscyBvbiBhZ2dyZWdhdGVkIGZsYW5rZXIgZGF0YSwgd2UgZmluZCB0aGF0CnRoZSBTaW1vbiBlZmZlY3QgaXMgbG93ZXN0IGZvciBoaWdoIFN3YWJpYW4gZG9taW5hbmNlLCBub3QgZm9yIGJhbGFuY2VkIGJpZGlhbGVjdGFsaXNtLgoKIyMgQWJzb2x1dGUgZG9taW5hbmNlCgpUaGUgX21pbmltdW1fIHJlcXVpcmVtZW50IGlzIHRoYXQgYGEuRG9taW5hbmNlU3dhYmlhbmAgaW50ZXJhY3RzIHdpdGggYG4uU3RhdHVzYCwKdGhhdCBpcyB0byBzYXksIHRoYXQgdGhlIGVmZmVjdCBvZiBjb25ncnVlbnQgdnMuIGluY29uZ3J1ZW50IHRyaWFscyB2YXJpZXMKZGVwZW5kaW5nIG9uIHRoZSBwYXJ0aWNpcGFudHMnIGJpZGlhbGVjdGFsIGRvbWluYW5jZS4KQSBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBpbiBpdHNlbGYgd291bGQgX25vdF8gYmUgaW4gbGluZSB3aXRoIG91ciBwcmVkaWN0aW9ucywKc2luY2UgdGhlc2Ugc3BlY2lmeSB0aGF0IHRoZSBmbGFua2VyL1NpbW9uIGVmZmVjdHMgc2hvdWxkIGJlIGxvd2VzdCBhcm91bmQgYGEuRG9taW5hbmNlU3dhYmlhbiA9IDBgLgoKIyMjIEZsYW5rZXIKCiMjIyMgTW9kZWwgZml0dGluZwoKYGBge3J9CiMgRml0IG1vZGVsIGluIEdBTQpmbGFua2VyLmdhbSA8LSBnYW0oU3BlZWQgfiBuLlN0YXR1cyArIAogICAgICAgICAgICAgICAgICAgICBzKGEuRG9taW5hbmNlU3dhYmlhbiwgYnkgPSBmYWN0b3Iobi5TdGF0dXMpKSArCiAgICAgICAgICAgICAgICAgICAgIHMoU3ViamVjdCwgYnMgPSAicmUiKSArICAgICAgICAgICAgICAgICAgIyByYW5kb20gaW50ZXJjZXB0IGZvciBzdWJqZWN0CiAgICAgICAgICAgICAgICAgICAgIHMobi5TdGF0dXMsIFN1YmplY3QsIGJzID0gInJlIiksICAgICAgIyByYW5kb20gc2xvcGUgb2Ygbi5Db25ncnVlbnQgYnkgc3ViamVjdC4gCiAgICAgICAgICAgICAgICAgICAjIFRoaXMgaXMgZXF1aXZhbGVudCB0byBzYXlpbmcgdGhhdCB0aGUgRmxhbmtlciBlZmZlY3QKICAgICAgICAgICAgICAgICAgICMgdmFyaWVzIGJldHdlZW4gcGFydGljaXBhbnRzCiAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0RmxhbmtlcikKcGxvdChmbGFua2VyLmdhbSkKYGBgCgpUaGUgYGEuRG9taW5hbmNlU3dhYmlhbmAgZWZmZWN0cyBhcmUgbGluZWFyLCBzbyB3ZSdsbCBtb2RlbCB0aGVtIGxpbmVhcmx5IHVzaW5nIGBsbWVyKClgLgoKYGBge3J9CmZsYW5rZXIubWVyIDwtIGxtZXIoU3BlZWQgfiBuLlN0YXR1cyArIGNhLkRvbWluYW5jZVN3YWJpYW4gKwogICAgICAgICAgICAgICAgICAgICAgY2EuRG9taW5hbmNlU3dhYmlhbjpuLlN0YXR1cyArCiAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHwgU3ViamVjdCksCiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdEZsYW5rZXIpCkFJQyhmbGFua2VyLm1lcikKc3VtbWFyeShmbGFua2VyLm1lcikKCiMgV2l0aG91dCByYW5kb20gY29ycmVsYXRpb24/CmZsYW5rZXIubWVyMiA8LSBsbWVyKFNwZWVkIH4gbi5TdGF0dXMgKyBjYS5Eb21pbmFuY2VTd2FiaWFuICsKICAgICAgICAgICAgICAgICAgICAgIGNhLkRvbWluYW5jZVN3YWJpYW46bi5TdGF0dXMgKwogICAgICAgICAgICAgICAgICAgICAgKDEgKyBuLlN0YXR1cyB8fCBTdWJqZWN0KSwKICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0RmxhbmtlcikKQUlDKGZsYW5rZXIubWVyMikKc3VtbWFyeShmbGFua2VyLm1lcjIpCmBgYAoKYGZsYW5rZXIubWVyMmAsIHdoaWNoIHBlZ3MgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHJhbmRvbSBpbnRlcmNlcHRzIGFuZCBzbG9wZXMgYXQgMCwKc2VlbXMgdG8gYmUgYSBzbGlnaHRseSBiZXR0ZXIgbW9kZWwsIHRob3VnaCBpdCBkb2Vzbid0IG1hdHRlciBtdWNoLgoKVGhlIHNvdXJjZSBjb2RlIGZvciB0aGlzIGRvY3VtZW50IGV4cGxvcmVzIHdoZXRoZXIgdGhpcyBtb2RlbCBpcyBjb3JyZWN0bHkgc3BlY2lmaWVkCihkaXN0cmlidXRpb24gb2YgcmFuZG9tIGVmZmVjdHMgYW5kIHJlc2lkdWFscykuCkluIGNvbmNsdXNpb24sIGFsbCBzZWVtcyB0byBiZSBpbiBvcmRlci4KCmBgYHtyLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gMi41LCBldmFsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KIyBFeHRyYWN0IHJhbmRvbSBlZmZlY3RzIChpbnRlcmNlcHQgYW5kIHNsb3BlKQpGbGFua2VyLnJhbmRvbUVmZmVjdHMgPC0gcmFuZWYoZmxhbmtlci5tZXIyKSRTdWJqZWN0ICU+JSAKICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogIHJlbmFtZShJbnRlcmNlcHQgPSBgKEludGVyY2VwdClgLAogICAgICAgICBTbG9wZSA9IG4uU3RhdHVzKSAlPiUgCiAgbXV0YXRlKFBhcnRpY2lwYW50ID0gcm93bmFtZXMoLikpCgojIFBsb3QgdGhlbQpsYXR0aWNlOjpkb3RwbG90KHJhbmVmKGZsYW5rZXIubWVyMikpCgpnZ3Bsb3QoRmxhbmtlci5yYW5kb21FZmZlY3RzLAogICAgICAgYWVzKHggPSBJbnRlcmNlcHQsIHkgPSBTbG9wZSkpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gUGFydGljaXBhbnQpLCBzaXplID0gMikKCiMgVGhlIHJhbmRvbSBlZmZlY3RzIHNlZW0gdG8gYmUgb2theS4KCiMgQWRkIHJlc2lkdWFscyB0byBkYXRhZnJhbWUKZGF0RmxhbmtlciRSZXNpZHVhbCA8LSByZXNpZChmbGFua2VyLm1lcjIpCgojIEFkZCBwcmVkaWN0aW9ucyB0byBkYXRhZnJhbWUKZGF0RmxhbmtlciRGaXR0ZWQgPC0gZml0dGVkKGZsYW5rZXIubWVyMikKCiMgQXJlIHRoZSAoYXZlcmFnZSkgcmVzaWR1YWxzIHJlbGF0ZWQgdG8gdGhlIG1vZGVsIHByZWRpY3Rpb25zPwpnZ3Bsb3QoZGF0RmxhbmtlciwKICAgICAgIGFlcyh4ID0gRml0dGVkLAogICAgICAgICAgIHkgPSBSZXNpZHVhbCkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aCgpCiMgTm8sIHdoaWNoIGlzIGdvb2QuCgojIEhldGVyb3NrZWRhc3RpY2l0eTogc2VlbXMgZmluZQpnZ3Bsb3QoZGF0RmxhbmtlciwKICAgICAgIGFlcyh4ID0gRml0dGVkLAogICAgICAgICAgIHkgPSBzcXJ0KGFicyhSZXNpZHVhbCkpKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKCkKIyBUaGlzIGRvZXNuJ3Qgc2VlbSB0byBiZSB0b28gd29ycnlpbmcuCgojIFJlc2lkdWFsIHBhdHRlcm4gd2l0aCBkb21pbmFuY2U/CmdncGxvdChkYXRGbGFua2VyLAogICAgICAgYWVzKHggPSBhLkRvbWluYW5jZVN3YWJpYW4sCiAgICAgICAgICAgeSA9IFJlc2lkdWFsKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKCkKIyBOby4KCiMgSGV0ZXJvc2tlZGFzdGljaXR5IHdpdGggZG9taW5hbmNlPwpnZ3Bsb3QoZGF0RmxhbmtlciwKICAgICAgIGFlcyh4ID0gYS5Eb21pbmFuY2VTd2FiaWFuLAogICAgICAgICAgIHkgPSBzcXJ0KGFicyhSZXNpZHVhbCkpKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKCkKIyBUaGlzIGRvZXNuJ3Qgc2VlbSB0byBiZSB0b28gd29ycnlpbmcuCgojIE5vcm1hbGl0eSBvZiByZXNpZHVhbHMKZ2dwbG90KGRhdEZsYW5rZXIsCiAgICAgICBhZXMoeCA9IFJlc2lkdWFsKSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gImxpZ2h0Z3JleSIsIGJpbndpZHRoID0gMC4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygyLjUqc2QoZGF0RmxhbmtlciRSZXNpZHVhbCksIC0yLjUqc2QoZGF0RmxhbmtlciRSZXNpZHVhbCkpLCBsdHkgPSAyKQoKIyBUaGUgcmVzaWR1YWxzIGFyZSBwcmV0dHkgbXVjaCBzeW1tZXRyaWNhbGx5IGRpc3RyaWJ1dGVkLgoKIyBSZXNpZHVhbHMgcGVyIHBhcnRpY2lwYW50CmdncGxvdChkYXRGbGFua2VyLAogICAgICAgYWVzKHggPSBSZXNpZHVhbCkpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gImxpZ2h0Z3JleSIsIGJpbndpZHRoID0gMC4yNSkgKwogIGZhY2V0X3dyYXAofiBTdWJqZWN0LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMgSW5mZXJlbmNlIHRlc3RzCgpIZXJlIHdlIHRlc3QgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiBgbi5TdGF0dXNgIGFuZCBgY2EuRG9taW5hbmNlU3dhYmlhbmAuCgpgYGB7ciwgY2FjaGUgPSBUUlVFfQojIDEuIE5vcm1hbCBhcHByb3hpbWF0aW9uCnN1bW1hcnkoZmxhbmtlci5tZXIyKSAKIyB8dHwgPSAwLjIgIGNvcnJlc3BvbmRzIHRvIHJvdWdobHkgcCA9IDAuODQsIGlmIHdlIGFzc3VtZQojIHRoZSB0LWRpc3RyaWJ1dGlvbiBpcyB3ZWxsIGFwcHJveGltYXRlZCBieSBhIG5vcm1hbCBkaXN0cmlidXRpb24uCgojIDIuIExpa2VsaWhvb2QgcmF0aW8gdGVzdAojIEZpdCBudWxsIG1vZGVsCmZsYW5rZXIubWVyMjAgPC0gbG1lcihTcGVlZCB+IG4uU3RhdHVzICsgY2EuRG9taW5hbmNlU3dhYmlhbiArCiAgICAgICAgICAgICAgICAgICAgICAgICgxICsgbi5TdGF0dXMgfHwgU3ViamVjdCksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0RmxhbmtlcikKYW5vdmEoZmxhbmtlci5tZXIyMCwgZmxhbmtlci5tZXIyKQojIExSVDogWMKyKDEpID0gMC4wNCwgcCA9IDAuODUKCiMgMy4gV2l0aCB0aGVzZSBwLXZhbHVlcywgcGFyYW1ldHJpYyBib290c3RyYXBwaW5nIGlzIHN1cGVyZmx1b3VzLgpgYGAKCldlIGZpbmQgbm8gaW50ZXJhY3Rpb24gYmV0d2VlbiBgbi5TdGF0dXNgIGFuZCBgY2EuRG9taW5hbmNlU3dhYmlhbmAKYW5kIGhlbmNlIG5vIGV2aWRlbmNlIGZvciBvdXIgcHJlZGljdGlvbi4KCiMjIyBTaW1vbgoKIyMjIyBNb2RlbCBmaXR0aW5nCgpgYGB7cn0KIyBGaXQgbW9kZWwgaW4gR0FNCnNpbW9uLmdhbSA8LSBnYW0oU3BlZWQgfiBuLlN0YXR1cyArIAogICAgICAgICAgICAgICAgICAgICBzKGEuRG9taW5hbmNlU3dhYmlhbiwgYnkgPSBmYWN0b3Iobi5TdGF0dXMpKSArCiAgICAgICAgICAgICAgICAgICAgIHMoU3ViamVjdCwgYnMgPSAicmUiKSArICAgICAgICAgICAgICAgICAgIyByYW5kb20gaW50ZXJjZXB0IGZvciBzdWJqZWN0CiAgICAgICAgICAgICAgICAgICAgIHMobi5TdGF0dXMsIFN1YmplY3QsIGJzID0gInJlIiksICAgICAgIyByYW5kb20gc2xvcGUgb2Ygbi5Db25ncnVlbnQgYnkgc3ViamVjdC4gCiAgICAgICAgICAgICAgICAgICAjIFRoaXMgaXMgZXF1aXZhbGVudCB0byBzYXlpbmcgdGhhdCB0aGUgU2ltb24gZWZmZWN0CiAgICAgICAgICAgICAgICAgICAjIHZhcmllcyBiZXR3ZWVuIHBhcnRpY2lwYW50cwogICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdFNpbW9uKQpwbG90KHNpbW9uLmdhbSkKYGBgCgpUaGUgYGEuRG9taW5hbmNlU3dhYmlhbmAgZWZmZWN0cyBhcmUgbGluZWFyLCBzbyB3ZSdsbCBtb2RlbCB0aGVtIGxpbmVhcmx5IHVzaW5nIGBsbWVyKClgLgoKYGBge3J9CnNpbW9uLm1lciA8LSBsbWVyKFNwZWVkIH4gbi5TdGF0dXMgKyBjYS5Eb21pbmFuY2VTd2FiaWFuICsKICAgICAgICAgICAgICAgICAgICAgIGNhLkRvbWluYW5jZVN3YWJpYW46bi5TdGF0dXMgKwogICAgICAgICAgICAgICAgICAgICAgKDEgKyBuLlN0YXR1cyB8IFN1YmplY3QpLAogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRTaW1vbikKQUlDKHNpbW9uLm1lcikKc3VtbWFyeShzaW1vbi5tZXIpCgojIFdpdGhvdXQgcmFuZG9tIGNvcnJlbGF0aW9uPwpzaW1vbi5tZXIyIDwtIGxtZXIoU3BlZWQgfiBuLlN0YXR1cyArIGNhLkRvbWluYW5jZVN3YWJpYW4gKwogICAgICAgICAgICAgICAgICAgICAgY2EuRG9taW5hbmNlU3dhYmlhbjpuLlN0YXR1cyArCiAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHx8IFN1YmplY3QpLAogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRTaW1vbikKQUlDKHNpbW9uLm1lcjIpCnN1bW1hcnkoc2ltb24ubWVyMikKYGBgCgpgc2ltb24ubWVyMmAsIHdoaWNoIHBlZ3MgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHJhbmRvbSBpbnRlcmNlcHRzIGFuZCBzbG9wZXMgYXQgMCwKc2VlbXMgdG8gYmUgYSBzbGlnaHRseSBiZXR0ZXIgbW9kZWwsIHRob3VnaCBpdCBkb2Vzbid0IG1hdHRlciBtdWNoLgoKVGhlIHNvdXJjZSBjb2RlIGZvciB0aGlzIGRvY3VtZW50IGV4cGxvcmVzIHdoZXRoZXIgdGhpcyBtb2RlbCBpcyBjb3JyZWN0bHkgc3BlY2lmaWVkCihkaXN0cmlidXRpb24gb2YgcmFuZG9tIGVmZmVjdHMgYW5kIHJlc2lkdWFscykuCkluIGNvbmNsdXNpb24sIGFsbCBzZWVtcyB0byBiZSBpbiBvcmRlci4KCmBgYHtyLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gMi41LCBldmFsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KIyBFeHRyYWN0IHJhbmRvbSBlZmZlY3RzIChpbnRlcmNlcHQgYW5kIHNsb3BlKQpTaW1vbi5yYW5kb21FZmZlY3RzIDwtIHJhbmVmKHNpbW9uLm1lcjIpJFN1YmplY3QgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKEludGVyY2VwdCA9IGAoSW50ZXJjZXB0KWAsCiAgICAgICAgIFNsb3BlID0gbi5TdGF0dXMpICU+JSAKICBtdXRhdGUoUGFydGljaXBhbnQgPSByb3duYW1lcyguKSkKCiMgUGxvdCB0aGVtCmxhdHRpY2U6OmRvdHBsb3QocmFuZWYoc2ltb24ubWVyMikpCgpnZ3Bsb3QoU2ltb24ucmFuZG9tRWZmZWN0cywKICAgICAgIGFlcyh4ID0gSW50ZXJjZXB0LCB5ID0gU2xvcGUpKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBhcnRpY2lwYW50KSwgc2l6ZSA9IDIpCgojIFRoZSByYW5kb20gZWZmZWN0cyBzZWVtIHRvIGJlIG9rYXkuCgojIEFkZCByZXNpZHVhbHMgdG8gZGF0YWZyYW1lCmRhdFNpbW9uJFJlc2lkdWFsIDwtIHJlc2lkKHNpbW9uLm1lcjIpCgojIEFkZCBwcmVkaWN0aW9ucyB0byBkYXRhZnJhbWUKZGF0U2ltb24kRml0dGVkIDwtIGZpdHRlZChzaW1vbi5tZXIyKQoKIyBBcmUgdGhlIChhdmVyYWdlKSByZXNpZHVhbHMgcmVsYXRlZCB0byB0aGUgbW9kZWwgcHJlZGljdGlvbnM/CmdncGxvdChkYXRTaW1vbiwKICAgICAgIGFlcyh4ID0gRml0dGVkLAogICAgICAgICAgIHkgPSBSZXNpZHVhbCkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aCgpCiMgTm8sIHdoaWNoIGlzIGdvb2QuCgojIEhldGVyb3NrZWRhc3RpY2l0eTogc2VlbXMgZmluZQpnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IEZpdHRlZCwKICAgICAgICAgICB5ID0gc3FydChhYnMoUmVzaWR1YWwpKSkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aCgpCiMgVGhpcyBkb2Vzbid0IHNlZW0gdG8gYmUgdG9vIHdvcnJ5aW5nLgoKIyBSZXNpZHVhbCBwYXR0ZXJuIHdpdGggZG9taW5hbmNlPwpnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IGEuRG9taW5hbmNlU3dhYmlhbiwKICAgICAgICAgICB5ID0gUmVzaWR1YWwpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgoKQojIE5vLgoKIyBIZXRlcm9za2VkYXN0aWNpdHkgd2l0aCBkb21pbmFuY2U/CmdncGxvdChkYXRTaW1vbiwKICAgICAgIGFlcyh4ID0gYS5Eb21pbmFuY2VTd2FiaWFuLAogICAgICAgICAgIHkgPSBzcXJ0KGFicyhSZXNpZHVhbCkpKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKCkKIyBUaGlzIGRvZXNuJ3Qgc2VlbSB0byBiZSB0b28gd29ycnlpbmcuCgojIE5vcm1hbGl0eSBvZiByZXNpZHVhbHMKZ2dwbG90KGRhdFNpbW9uLAogICAgICAgYWVzKHggPSBSZXNpZHVhbCkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSwgY29sb3VyID0gImJsYWNrIiwgZmlsbCA9ICJsaWdodGdyZXkiLCBiaW53aWR0aCA9IDAuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoMi41KnNkKGRhdFNpbW9uJFJlc2lkdWFsKSwgLTIuNSpzZChkYXRTaW1vbiRSZXNpZHVhbCkpLCBsdHkgPSAyKQoKIyBUaGUgcmVzaWR1YWxzIGFyZSBwcmV0dHkgbXVjaCBzeW1tZXRyaWNhbGx5IGRpc3RyaWJ1dGVkLgoKIyBSZXNpZHVhbHMgcGVyIHBhcnRpY2lwYW50CmdncGxvdChkYXRTaW1vbiwKICAgICAgIGFlcyh4ID0gUmVzaWR1YWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oY29sb3VyID0gImJsYWNrIiwgZmlsbCA9ICJsaWdodGdyZXkiLCBiaW53aWR0aCA9IDAuMjUpICsKICBmYWNldF93cmFwKH4gU3ViamVjdCwgc2NhbGVzID0gImZyZWVfeSIpICsKICB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkKYGBgCgojIyMjIEluZmVyZW5jZSB0ZXN0cwoKSGVyZSB3ZSB0ZXN0IHRoZSBzaWduaWZpY2FuY2Ugb2YgdGhlIGludGVyYWN0aW9uIGJldHdlZW4gYG4uU3RhdHVzYCBhbmQgYGNhLkRvbWluYW5jZVN3YWJpYW5gLgoKYGBge3IsIGNhY2hlID0gVFJVRX0KIyAxLiBOb3JtYWwgYXBwcm94aW1hdGlvbgpzdW1tYXJ5KHNpbW9uLm1lcjIpIAojIHx0fCA9IDAuOCAgY29ycmVzcG9uZHMgdG8gcm91Z2hseSBwID0gMC40MiwgaWYgd2UgYXNzdW1lCiMgdGhlIHQtZGlzdHJpYnV0aW9uIGlzIHdlbGwgYXBwcm94aW1hdGVkIGJ5IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KCiMgMi4gTGlrZWxpaG9vZCByYXRpbyB0ZXN0CiMgRml0IG51bGwgbW9kZWwKc2ltb24ubWVyMjAgPC0gbG1lcihTcGVlZCB+IG4uU3RhdHVzICsgY2EuRG9taW5hbmNlU3dhYmlhbiArCiAgICAgICAgICAgICAgICAgICAgICAgICgxICsgbi5TdGF0dXMgfHwgU3ViamVjdCksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0U2ltb24pCmFub3ZhKHNpbW9uLm1lcjIwLCBzaW1vbi5tZXIyKQojIExSVDogWMKyKDEpID0gMC42NiwgcCA9IDAuNDIKCiMgMy4gUGFyYW1ldHJpYyBib290c3RyYXBwaW5nOiBzdXBlcmZsdW91cwpgYGAKCldlIGZpbmQgbm8gc29saWQgaW50ZXJhY3Rpb24gYmV0d2VlbiBgbi5TdGF0dXNgIGFuZCBgY2EuRG9taW5hbmNlU3dhYmlhbmAKYW5kIGhlbmNlIG5vIGV2aWRlbmNlIGZvciBvdXIgcHJlZGljdGlvbi4KCiMjIFRvdGFsIFN3YWJpYW4KCiMjIyBGbGFua2VyCgojIyMjIE1vZGVsIGZpdHRpbmcKCmBgYHtyfQojIEZpdCBtb2RlbCBpbiBHQU0KZmxhbmtlci5nYW0gPC0gZ2FtKFNwZWVkIH4gbi5TdGF0dXMgKyAKICAgICAgICAgICAgICAgICAgICAgcyhUb3RhbFN3YWJpYW4sIGJ5ID0gZmFjdG9yKG4uU3RhdHVzKSkgKwogICAgICAgICAgICAgICAgICAgICBzKFN1YmplY3QsIGJzID0gInJlIikgKyAgICAgICAgICAgICAgICAgICMgcmFuZG9tIGludGVyY2VwdCBmb3Igc3ViamVjdAogICAgICAgICAgICAgICAgICAgICBzKG4uU3RhdHVzLCBTdWJqZWN0LCBicyA9ICJyZSIpLCAgICAgICMgcmFuZG9tIHNsb3BlIG9mIG4uQ29uZ3J1ZW50IGJ5IHN1YmplY3QuIAogICAgICAgICAgICAgICAgICAgIyBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gc2F5aW5nIHRoYXQgdGhlIEZsYW5rZXIgZWZmZWN0CiAgICAgICAgICAgICAgICAgICAjIHZhcmllcyBiZXR3ZWVuIHBhcnRpY2lwYW50cwogICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdEZsYW5rZXIpCnBsb3QoZmxhbmtlci5nYW0pCmBgYAoKVGhlIGBUb3RhbFN3YWJpYW5gIGVmZmVjdHMgYXJlIGxpbmVhciwgc28gd2UnbGwgbW9kZWwgdGhlbSBsaW5lYXJseSB1c2luZyBgbG1lcigpYC4KCmBgYHtyfQpmbGFua2VyLm1lciA8LSBsbWVyKFNwZWVkIH4gbi5TdGF0dXMgKyBjLlRvdGFsU3dhYmlhbiArCiAgICAgICAgICAgICAgICAgICAgICBjLlRvdGFsU3dhYmlhbjpuLlN0YXR1cyArCiAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHwgU3ViamVjdCksCiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdEZsYW5rZXIpCkFJQyhmbGFua2VyLm1lcikKc3VtbWFyeShmbGFua2VyLm1lcikKCiMgV2l0aG91dCByYW5kb20gY29ycmVsYXRpb24/CmZsYW5rZXIubWVyMiA8LSBsbWVyKFNwZWVkIH4gbi5TdGF0dXMgKyBjLlRvdGFsU3dhYmlhbiArCiAgICAgICAgICAgICAgICAgICAgICBjLlRvdGFsU3dhYmlhbjpuLlN0YXR1cyArCiAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHx8IFN1YmplY3QpLAogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRGbGFua2VyKQpBSUMoZmxhbmtlci5tZXIyKQpzdW1tYXJ5KGZsYW5rZXIubWVyMikKYGBgCgpgZmxhbmtlci5tZXIyYCwgd2hpY2ggcGVncyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgcmFuZG9tIGludGVyY2VwdHMgYW5kIHNsb3BlcyBhdCAwLApzZWVtcyB0byBiZSBhIHNsaWdodGx5IGJldHRlciBtb2RlbCwgdGhvdWdoIGl0IGRvZXNuJ3QgbWF0dGVyIG11Y2guCgpUaGUgc291cmNlIGNvZGUgZm9yIHRoaXMgZG9jdW1lbnQgZXhwbG9yZXMgd2hldGhlciB0aGlzIG1vZGVsIGlzIGNvcnJlY3RseSBzcGVjaWZpZWQKKGRpc3RyaWJ1dGlvbiBvZiByYW5kb20gZWZmZWN0cyBhbmQgcmVzaWR1YWxzKS4KSW4gY29uY2x1c2lvbiwgYWxsIHNlZW1zIHRvIGJlIGluIG9yZGVyLgoKYGBge3IsIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSAyLjUsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQojIEV4dHJhY3QgcmFuZG9tIGVmZmVjdHMgKGludGVyY2VwdCBhbmQgc2xvcGUpCkZsYW5rZXIucmFuZG9tRWZmZWN0cyA8LSByYW5lZihmbGFua2VyLm1lcjIpJFN1YmplY3QgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKEludGVyY2VwdCA9IGAoSW50ZXJjZXB0KWAsCiAgICAgICAgIFNsb3BlID0gbi5TdGF0dXMpICU+JSAKICBtdXRhdGUoUGFydGljaXBhbnQgPSByb3duYW1lcyguKSkKCiMgUGxvdCB0aGVtCmxhdHRpY2U6OmRvdHBsb3QocmFuZWYoZmxhbmtlci5tZXIyKSkKCmdncGxvdChGbGFua2VyLnJhbmRvbUVmZmVjdHMsCiAgICAgICBhZXMoeCA9IEludGVyY2VwdCwgeSA9IFNsb3BlKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBQYXJ0aWNpcGFudCksIHNpemUgPSAyKQoKIyBUaGUgcmFuZG9tIGVmZmVjdHMgc2VlbSB0byBiZSBva2F5LgoKIyBBZGQgcmVzaWR1YWxzIHRvIGRhdGFmcmFtZQpkYXRGbGFua2VyJFJlc2lkdWFsIDwtIHJlc2lkKGZsYW5rZXIubWVyMikKCiMgQWRkIHByZWRpY3Rpb25zIHRvIGRhdGFmcmFtZQpkYXRGbGFua2VyJEZpdHRlZCA8LSBmaXR0ZWQoZmxhbmtlci5tZXIyKQoKIyBBcmUgdGhlIChhdmVyYWdlKSByZXNpZHVhbHMgcmVsYXRlZCB0byB0aGUgbW9kZWwgcHJlZGljdGlvbnM/CmdncGxvdChkYXRGbGFua2VyLAogICAgICAgYWVzKHggPSBGaXR0ZWQsCiAgICAgICAgICAgeSA9IFJlc2lkdWFsKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKCkKIyBObywgd2hpY2ggaXMgZ29vZC4KCiMgSGV0ZXJvc2tlZGFzdGljaXR5OiBzZWVtcyBmaW5lCmdncGxvdChkYXRGbGFua2VyLAogICAgICAgYWVzKHggPSBGaXR0ZWQsCiAgICAgICAgICAgeSA9IHNxcnQoYWJzKFJlc2lkdWFsKSkpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgoKQojIFRoaXMgZG9lc24ndCBzZWVtIHRvIGJlIHRvbyB3b3JyeWluZy4KCiMgUmVzaWR1YWwgcGF0dGVybiB3aXRoIGRvbWluYW5jZT8KZ2dwbG90KGRhdEZsYW5rZXIsCiAgICAgICBhZXMoeCA9IFRvdGFsU3dhYmlhbiwKICAgICAgICAgICB5ID0gUmVzaWR1YWwpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgoKQojIE5vLgoKIyBIZXRlcm9za2VkYXN0aWNpdHkgd2l0aCBkb21pbmFuY2U/CmdncGxvdChkYXRGbGFua2VyLAogICAgICAgYWVzKHggPSBUb3RhbFN3YWJpYW4sCiAgICAgICAgICAgeSA9IHNxcnQoYWJzKFJlc2lkdWFsKSkpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgoKQojIFRoaXMgZG9lc24ndCBzZWVtIHRvIGJlIHRvbyB3b3JyeWluZy4KCiMgTm9ybWFsaXR5IG9mIHJlc2lkdWFscwpnZ3Bsb3QoZGF0RmxhbmtlciwKICAgICAgIGFlcyh4ID0gUmVzaWR1YWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAibGlnaHRncmV5IiwgYmlud2lkdGggPSAwLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDIuNSpzZChkYXRGbGFua2VyJFJlc2lkdWFsKSwgLTIuNSpzZChkYXRGbGFua2VyJFJlc2lkdWFsKSksIGx0eSA9IDIpCgojIFRoZSByZXNpZHVhbHMgYXJlIHByZXR0eSBtdWNoIHN5bW1ldHJpY2FsbHkgZGlzdHJpYnV0ZWQuCgojIFJlc2lkdWFscyBwZXIgcGFydGljaXBhbnQKZ2dwbG90KGRhdEZsYW5rZXIsCiAgICAgICBhZXMoeCA9IFJlc2lkdWFsKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAibGlnaHRncmV5IiwgYmlud2lkdGggPSAwLjI1KSArCiAgZmFjZXRfd3JhcCh+IFN1YmplY3QsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpCmBgYAoKIyMjIyBJbmZlcmVuY2UgdGVzdHMKCkhlcmUgd2UgdGVzdCB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIGBuLlN0YXR1c2AgYW5kIGBjLlRvdGFsU3dhYmlhbmAuCgpgYGB7ciwgY2FjaGUgPSBUUlVFfQojIDEuIE5vcm1hbCBhcHByb3hpbWF0aW9uCnN1bW1hcnkoZmxhbmtlci5tZXIyKSAKIyB8dHwgPSAxLjcgIGNvcnJlc3BvbmRzIHRvIHJvdWdobHkgcCA9IDAuMDksIGlmIHdlIGFzc3VtZQojIHRoZSB0LWRpc3RyaWJ1dGlvbiBpcyB3ZWxsIGFwcHJveGltYXRlZCBieSBhIG5vcm1hbCBkaXN0cmlidXRpb24uCgojIDIuIExpa2VsaWhvb2QgcmF0aW8gdGVzdAojIEZpdCBudWxsIG1vZGVsCmZsYW5rZXIubWVyMjAgPC0gbG1lcihTcGVlZCB+IG4uU3RhdHVzICsgYy5Ub3RhbFN3YWJpYW4gKwogICAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHx8IFN1YmplY3QpLAogICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdEZsYW5rZXIpCmFub3ZhKGZsYW5rZXIubWVyMjAsIGZsYW5rZXIubWVyMikKIyBMUlQ6IFjCsigxKSA9IDIuOSwgcCA9IDAuMDg2CgojIDMuIExhc3QtLWFuZCBiZXR0ZXItLXNvbHV0aW9uOiBQYXJhbWV0cmljIGJvb3RzdHJhcHBpbmc6CiNQQm1vZGNvbXAoZmxhbmtlci5tZXIyLCBmbGFua2VyLm1lcjIwLCBuc2ltID0gMTAwMCkKIyBwID1+IDAuMDk5OyB0aGUgcC12YWx1ZSB3aWxsIHZhcnkgZnJvbSBydW4gdG8gcnVuCmBgYAoKV2UgZmluZCBubyBpbnRlcmFjdGlvbiBiZXR3ZWVuIGBuLlN0YXR1c2AgYW5kIGBjLlRvdGFsU3dhYmlhbmAKYW5kIGhlbmNlIG5vIGV2aWRlbmNlIGZvciBvdXIgcHJlZGljdGlvbi4KCiMjIyBTaW1vbgoKIyMjIyBNb2RlbCBmaXR0aW5nCgpgYGB7cn0KIyBGaXQgbW9kZWwgaW4gR0FNCnNpbW9uLmdhbSA8LSBnYW0oU3BlZWQgfiBuLlN0YXR1cyArIAogICAgICAgICAgICAgICAgICAgICBzKFRvdGFsU3dhYmlhbiwgYnkgPSBmYWN0b3Iobi5TdGF0dXMpKSArCiAgICAgICAgICAgICAgICAgICAgIHMoU3ViamVjdCwgYnMgPSAicmUiKSArICAgICAgICAgICAgICAgICAgIyByYW5kb20gaW50ZXJjZXB0IGZvciBzdWJqZWN0CiAgICAgICAgICAgICAgICAgICAgIHMobi5TdGF0dXMsIFN1YmplY3QsIGJzID0gInJlIiksICAgICAgIyByYW5kb20gc2xvcGUgb2Ygbi5Db25ncnVlbnQgYnkgc3ViamVjdC4gCiAgICAgICAgICAgICAgICAgICAjIFRoaXMgaXMgZXF1aXZhbGVudCB0byBzYXlpbmcgdGhhdCB0aGUgU2ltb24gZWZmZWN0CiAgICAgICAgICAgICAgICAgICAjIHZhcmllcyBiZXR3ZWVuIHBhcnRpY2lwYW50cwogICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdFNpbW9uKQpwbG90KHNpbW9uLmdhbSkKYGBgCgpUaGUgYFRvdGFsU3dhYmlhbmAgZWZmZWN0cyBhcmUgbGluZWFyLCBzbyB3ZSdsbCBtb2RlbCB0aGVtIGxpbmVhcmx5IHVzaW5nIGBsbWVyKClgLgoKYGBge3J9CnNpbW9uLm1lciA8LSBsbWVyKFNwZWVkIH4gbi5TdGF0dXMgKyBjLlRvdGFsU3dhYmlhbiArCiAgICAgICAgICAgICAgICAgICAgICBjLlRvdGFsU3dhYmlhbjpuLlN0YXR1cyArCiAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHwgU3ViamVjdCksCiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdFNpbW9uKQpBSUMoc2ltb24ubWVyKQpzdW1tYXJ5KHNpbW9uLm1lcikKCiMgV2l0aG91dCByYW5kb20gY29ycmVsYXRpb24/CnNpbW9uLm1lcjIgPC0gbG1lcihTcGVlZCB+IG4uU3RhdHVzICsgYy5Ub3RhbFN3YWJpYW4gKwogICAgICAgICAgICAgICAgICAgICAgYy5Ub3RhbFN3YWJpYW46bi5TdGF0dXMgKwogICAgICAgICAgICAgICAgICAgICAgKDEgKyBuLlN0YXR1cyB8fCBTdWJqZWN0KSwKICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0U2ltb24pCkFJQyhzaW1vbi5tZXIyKQpzdW1tYXJ5KHNpbW9uLm1lcjIpCmBgYAoKYHNpbW9uLm1lcjJgLCB3aGljaCBwZWdzIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSByYW5kb20gaW50ZXJjZXB0cyBhbmQgc2xvcGVzIGF0IDAsCnNlZW1zIHRvIGJlIGEgc2xpZ2h0bHkgYmV0dGVyIG1vZGVsLCB0aG91Z2ggaXQgZG9lc24ndCBtYXR0ZXIgbXVjaC4KClRoZSBzb3VyY2UgY29kZSBmb3IgdGhpcyBkb2N1bWVudCBleHBsb3JlcyB3aGV0aGVyIHRoaXMgbW9kZWwgaXMgY29ycmVjdGx5IHNwZWNpZmllZAooZGlzdHJpYnV0aW9uIG9mIHJhbmRvbSBlZmZlY3RzIGFuZCByZXNpZHVhbHMpLgpJbiBjb25jbHVzaW9uLCBhbGwgc2VlbXMgdG8gYmUgaW4gb3JkZXIuCgpgYGB7ciwgZmlnLndpZHRoID0gNCwgZmlnLmhlaWdodCA9IDIuNSwgZXZhbCA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CiMgRXh0cmFjdCByYW5kb20gZWZmZWN0cyAoaW50ZXJjZXB0IGFuZCBzbG9wZSkKU2ltb24ucmFuZG9tRWZmZWN0cyA8LSByYW5lZihzaW1vbi5tZXIyKSRTdWJqZWN0ICU+JSAKICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogIHJlbmFtZShJbnRlcmNlcHQgPSBgKEludGVyY2VwdClgLAogICAgICAgICBTbG9wZSA9IG4uU3RhdHVzKSAlPiUgCiAgbXV0YXRlKFBhcnRpY2lwYW50ID0gcm93bmFtZXMoLikpCgojIFBsb3QgdGhlbQpsYXR0aWNlOjpkb3RwbG90KHJhbmVmKHNpbW9uLm1lcjIpKQoKZ2dwbG90KFNpbW9uLnJhbmRvbUVmZmVjdHMsCiAgICAgICBhZXMoeCA9IEludGVyY2VwdCwgeSA9IFNsb3BlKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBQYXJ0aWNpcGFudCksIHNpemUgPSAyKQoKIyBUaGUgcmFuZG9tIGVmZmVjdHMgc2VlbSB0byBiZSBva2F5LgoKIyBBZGQgcmVzaWR1YWxzIHRvIGRhdGFmcmFtZQpkYXRTaW1vbiRSZXNpZHVhbCA8LSByZXNpZChzaW1vbi5tZXIyKQoKIyBBZGQgcHJlZGljdGlvbnMgdG8gZGF0YWZyYW1lCmRhdFNpbW9uJEZpdHRlZCA8LSBmaXR0ZWQoc2ltb24ubWVyMikKCiMgQXJlIHRoZSAoYXZlcmFnZSkgcmVzaWR1YWxzIHJlbGF0ZWQgdG8gdGhlIG1vZGVsIHByZWRpY3Rpb25zPwpnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IEZpdHRlZCwKICAgICAgICAgICB5ID0gUmVzaWR1YWwpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgoKQojIE5vLCB3aGljaCBpcyBnb29kLgoKIyBIZXRlcm9za2VkYXN0aWNpdHk6IHNlZW1zIGZpbmUKZ2dwbG90KGRhdFNpbW9uLAogICAgICAgYWVzKHggPSBGaXR0ZWQsCiAgICAgICAgICAgeSA9IHNxcnQoYWJzKFJlc2lkdWFsKSkpKSArCiAgZ2VvbV9wb2ludChwY2ggPSAxKSArCiAgZ2VvbV9zbW9vdGgoKQojIFRoaXMgZG9lc24ndCBzZWVtIHRvIGJlIHRvbyB3b3JyeWluZy4KCiMgUmVzaWR1YWwgcGF0dGVybiB3aXRoIGRvbWluYW5jZT8KZ2dwbG90KGRhdFNpbW9uLAogICAgICAgYWVzKHggPSBUb3RhbFN3YWJpYW4sCiAgICAgICAgICAgeSA9IFJlc2lkdWFsKSkgKwogIGdlb21fcG9pbnQocGNoID0gMSkgKwogIGdlb21fc21vb3RoKCkKIyBOby4KCiMgSGV0ZXJvc2tlZGFzdGljaXR5IHdpdGggZG9taW5hbmNlPwpnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IFRvdGFsU3dhYmlhbiwKICAgICAgICAgICB5ID0gc3FydChhYnMoUmVzaWR1YWwpKSkpICsKICBnZW9tX3BvaW50KHBjaCA9IDEpICsKICBnZW9tX3Ntb290aCgpCiMgVGhpcyBkb2Vzbid0IHNlZW0gdG8gYmUgdG9vIHdvcnJ5aW5nLgoKIyBOb3JtYWxpdHkgb2YgcmVzaWR1YWxzCmdncGxvdChkYXRTaW1vbiwKICAgICAgIGFlcyh4ID0gUmVzaWR1YWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAibGlnaHRncmV5IiwgYmlud2lkdGggPSAwLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDIuNSpzZChkYXRTaW1vbiRSZXNpZHVhbCksIC0yLjUqc2QoZGF0U2ltb24kUmVzaWR1YWwpKSwgbHR5ID0gMikKCiMgVGhlIHJlc2lkdWFscyBhcmUgcHJldHR5IG11Y2ggc3ltbWV0cmljYWxseSBkaXN0cmlidXRlZC4KCiMgUmVzaWR1YWxzIHBlciBwYXJ0aWNpcGFudApnZ3Bsb3QoZGF0U2ltb24sCiAgICAgICBhZXMoeCA9IFJlc2lkdWFsKSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAibGlnaHRncmV5IiwgYmlud2lkdGggPSAwLjI1KSArCiAgZmFjZXRfd3JhcCh+IFN1YmplY3QsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpCmBgYAoKIyMjIyBJbmZlcmVuY2UgdGVzdHMKCkhlcmUgd2UgdGVzdCB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIGBuLlN0YXR1c2AgYW5kIGBjLlRvdGFsU3dhYmlhbmAuCgpgYGB7ciwgY2FjaGUgPSBUUlVFfQojIDEuIE5vcm1hbCBhcHByb3hpbWF0aW9uCnN1bW1hcnkoc2ltb24ubWVyMikgCiMgfHR8ID0gMi4yICBjb3JyZXNwb25kcyB0byByb3VnaGx5IHAgPSAwLjAyOCwgaWYgd2UgYXNzdW1lCiMgdGhlIHQtZGlzdHJpYnV0aW9uIGlzIHdlbGwgYXBwcm94aW1hdGVkIGJ5IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KCiMgMi4gTGlrZWxpaG9vZCByYXRpbyB0ZXN0CiMgRml0IG51bGwgbW9kZWwKc2ltb24ubWVyMjAgPC0gbG1lcihTcGVlZCB+IG4uU3RhdHVzICsgYy5Ub3RhbFN3YWJpYW4gKwogICAgICAgICAgICAgICAgICAgICAgICAoMSArIG4uU3RhdHVzIHx8IFN1YmplY3QpLAogICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdFNpbW9uKQphbm92YShzaW1vbi5tZXIyMCwgc2ltb24ubWVyMikKIyBMUlQ6IFjCsigxKSA9IDQuOSwgcCA9IDAuMDI3CgojIDMuIExhc3QtLWFuZCBiZXR0ZXItLXNvbHV0aW9uOiBQYXJhbWV0cmljIGJvb3RzdHJhcHBpbmc6CiNQQm1vZGNvbXAoc2ltb24ubWVyMiwgc2ltb24ubWVyMjAsIG5zaW0gPSAxMDAwKQojIHAgPX4gMC4wMzA7IHRoZSBwLXZhbHVlIHdpbGwgdmFyeSBmcm9tIHJ1biB0byBydW4KYGBgCgoKIyBBIG11bHRpdmVyc2UgYW5hbHlzaXMKRm9yIHRoZSBhbmFseXNlcyByZXBvcnRlZCBhYm92ZSwgd2UgdG9vayBhIG51bWJlciBvZiBtb3JlIG9yIGxlc3MgYXJiaXRyYXJ5IGRlY2lzaW9ucyAob3VyIGRlY2lzaW9ucyBpbiBib2xkKToKCiogYFRyYW5zZm9ybWF0aW9uYDogU2hvdWxkIHRoZSBhbmFseXNpcyBiZSBiYXNlZCBvbiB0aGUgdW50cmFuc2Zvcm1lZCAocmF3KSBsYXRlbmNpZXMsIG9uIGludmVyc2UtdHJhbnNmb3JtZWQgbGF0ZW5jaWVzICgqKnNwZWVkKiopIG9yIGxvZy10cmFuc2Zvcm1lZCBsYXRlbmNpZXMgKGxvZyk/ICgzIHBvc3NpYmlsaXRpZXMpCiogYEV4Y2x1c2lvbkFjY3VyYWN5YDogU2hvdWxkIGxhdGVuY2llcyBmb3IgaW5jb3JyZWN0IHJlc3BvbnNlcyBiZSBleGNsdWRlZD8gKCoqbm8qKiB2cy4geWVzOyAyKQoqIGBFeGNsdXNpb25MYXRlbmN5YDogU2hvdWxkIHRoZXJlIGJlIGEgbG93ZXIgdGhyZXNob2xkIGZvciByZXNwb25zZSBsYXRlbmNpZXMsIGFuZCBpZiBzbywgd2hpY2ggc2hvdWxkIHRoZSB0aHJlc2hvbGQgYmU/ICgqKm5vbmUqKiwgMjAwIG1zLCAyNTAgbXMsIDMwMCBtcywgdG8gbmFtZSBidXQgNCBwb3NzaWJpbGl0aWVzKQoqIGBFeGNsdXNpb25TRHNgOiBTaG91bGQgcmVzcG9uc2VzIGJlIGV4Y2x1ZGVkIGJlY2F1c2UgdGhleSBhcmUgbW9yZSB0aGFuIGEgc2V0IG51bWJlciBvZiBzdGFuZGFyZCBkZXZpYXRpb25zIHJlbW92ZWQgZnJvbSB0aGUgcGFydGljaXBhbnRzJyBtZWFuLCBhbmQgaWYgc28sIHdoYXQgc2hvdWxkIHRoaXMgbnVtYmVyIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMgYmU/IFRoZSBzdGFuZGFyZCBkZXZpYXRpb25zIGFuZCBtZWFucyBhcmUgY29tcHV0ZWQgZm9yIGVhY2ggcGFydGljaXBhbnQgb24gdGhlIF90cmFuc2Zvcm1lZF8gbGF0ZW5jeSBkYXRhIChpLmUuLCByYXcsIHNwZWVkIG9yIGxvZykuIEFueSByZXNwb25zZXMgbW9yZSB0aGFuIGBFeGNsdXNpb25TRHNgIHN0YW5kYXJkIGRldmlhdGlvbnMgYXdheSBmcm9tIHRoZSBwYXJ0aWNpcGFudCdzIHdpbGwgYmUgZHJvcHBlZC4gKCoqbm9uZSoqLCAyLjUgU0RzLCB0byBuYW1lIGJ1dCAyIHBvc3NpYmlsaXRpZXMpCiogYEV4Y2x1c2lvblNEc092ZXJhbGxgOiBTaG91bGQgcmVzcG9uc2VzIGJlIGV4Y2x1ZGVkIGJlY2F1c2UgdGhleSBhcmUgbW9yZSB0aGFuIGEgc2V0IG51bWJlciBvZiBzdGFuZGFyZCBkZXZpYXRpb25zIHJlbW92ZWQgZnJvbSB0aGUgX292ZXJhbGxfIG1lYW4sIGFuZCBpZiBzbywgd2hhdCBzaG91bGQgdGhpcyBudW1iZXIgb2Ygc3RhbmRhcmQgZGV2aWF0aW9ucyBiZT8gVGhlIHN0YW5kYXJkIGRldmlhdGlvbnMgYW5kIG1lYW5zIGFyZSBjb21wdXRlZCBvbiB0aGUgX3RyYW5zZm9ybWVkXyBsYXRlbmN5IGRhdGEgKGkuZS4sIHJhdywgc3BlZWQgb3IgbG9nKS4gQW55IHJlc3BvbnNlcyBtb3JlIHRoYW4gYEV4Y2x1c2lvblNEc092ZXJhbGxgIHN0YW5kYXJkIGRldmlhdGlvbnMgYXdheSBmcm9tIHRoZSBvdmVyYWxsIG1lYW4gd2lsbCBiZSBkcm9wcGVkLiAoKipub25lKiosIDIuNSBTRHMsIHRvIG5hbWUgYnV0IDIgcG9zc2liaWxpdGllcykKKiBgRFZgOiBXaGljaCB2YXJpYWJsZSBzaG91bGQgYmUgdXNlZCBhcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlOiB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBjb25kaXRpb24gbWVhbnMgKCoqbWVhbiBkaWZmZXJlbmNlKiopIG9yIHRoZSByYXRpbyBiZXR3ZWVuIHRoZSBjb25kaXRpb24gbWVhbnMgKCoqbWVhbiByYXRpbyoqKSAodG8gbmFtZSBidXQgMiBwb3NzaWJpbGl0aWVzKS4KKiBgSVZgOiBXaGljaCB2YXJpYWJsZSBzaG91bGQgYmUgdXNlZCBhcyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGU6ICoqcmF3IGRvbWluYW5jZSoqLCAqKmFic29sdXRlIGRvbWluYW5jZSoqLCByYXcgZG9taW5hbmNlIGJ1dCBvbmx5IGNvbnNpZGVyaW5nIG9yYWwgc2tpbGxzLCBhYnNvbHV0ZSBkb21pbmFuY2UgYnV0IG9ubHkgY29uc2lkZXJpbmcgb3JhbCBza2lsbHMsIHJhdyBkb21pbmFuY2Ugb2YgdXNlIG9ubHksIGFic29sdXRlIGRvbWluYW5jZSBvZiB1c2Ugb25seSwgKip0b3RhbCBTd2FiaWFuIHNjb3JlKiosIG9yIHRvdGFsIFN3YWJpYW4gc2NvcmUgYnV0IGNvbnNpZGVyaW5nIG9yYWwgc2tpbGxzIG9ubHkgKDggcG9zc2liaWxpdGllcyB0aGF0IHdlIGNvbnNpZGVyZWQgZGVmZW5zaWJsZSkuCiogYFRhc2tgOiBTaG91bGQgdGhlICoqU2ltb24qKiBvciAqKmZsYW5rZXIqKiBkYXRhIGJlIGFuYWx5c2VkPyAoMikKCkJ5IGNvbWJpbmluZyBhbGwgb2YgdGhlc2UgcG9zc2liaWxpdGllcywgdGhlcmUgYXJlIChlYXNpbHkpIDMsMDcyIGFsdGVybmF0aXZlIHdheXMKb2YgYW5hbHlzaW5nIHRoZXNlIGRhdGEuCgpgYGB7cn0KIyBNYXRyaXggdGhhdCBsaXN0cyBhbGwgYW5hbHlzaXMgcGFyYW1ldGVycwphbHRlcm5hdGl2ZXMgPC0gZXhwYW5kLmdyaWQoZGF0YSA9ICJkYXRhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRhc2sgPSBjKCJTaW1vbiIsICJGbGFua2VyIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmFuc2Zvcm1hdGlvbiA9IGMoInJhdyIsICJzcGVlZCIsICJsb2ciKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV4Y2x1c2lvbkFjY3VyYWN5ID0gYygieWVzIiwgIm5vIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFeGNsdXNpb25MYXRlbmN5ID0gYygwLCAyMDAsIDI1MCwgMzAwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV4Y2x1c2lvblNEcyA9IGMoTkEsIDIuNSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFeGNsdXNpb25TRHNPdmVyYWxsID0gYyhOQSwgMi41KSwgIyBub3QgeWV0IGltcGxlbWVudGVkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEViA9IGMoIm1lYW4gZGlmZmVyZW5jZSIsICJtZWFuIHJhdGlvIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJViA9IGMoInJhdyBkb21pbmFuY2UiLCAiYWJzb2x1dGUgZG9taW5hbmNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicmF3IGRvbWluYW5jZSwgb3JhbCIsICJhYnNvbHV0ZSBkb21pbmFuY2UsIG9yYWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicmF3IHVzZSIsICJhYnNvbHV0ZSB1c2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0b3RhbCBTd2FiaWFuIiwgInRvdGFsIFN3YWJpYW4sIG9yYWwiKSkKbnJvdyhhbHRlcm5hdGl2ZXMpCmBgYAoKCiMjIERlZmluZSBhbmFseXNpcyB3YWxrdGhyb3VnaAoKYGBge3J9CmFsbEFuYWx5c2VzIDwtCiAgZnVuY3Rpb24oZGF0YSwKICAgICAgICAgICBUYXNrLAogICAgICAgICAgIFRyYW5zZm9ybWF0aW9uLAogICAgICAgICAgIEV4Y2x1c2lvbkFjY3VyYWN5ID0gIm5vIiwKICAgICAgICAgICBFeGNsdXNpb25MYXRlbmN5ID0gMCwKICAgICAgICAgICBFeGNsdXNpb25TRHMgPSBOVUxMLAogICAgICAgICAgIEV4Y2x1c2lvblNEc092ZXJhbGwgPSBOVUxMLAogICAgICAgICAgIERWLAogICAgICAgICAgIElWKSB7CiAgICAKICAgIHJlcXVpcmUoImRwbHlyIikKICAgIHJlcXVpcmUoInRpZHlyIikKICAgIHJlcXVpcmUoIm1hZ3JpdHRyIikKICAgIAogICAgIyBTZWxlY3QgdGFzawogICAgaWYgKFRhc2sgJWluJSBjKCJTaW1vbiIsICJGbGFua2VyIikpIHsKICAgICAgaWYgKFRhc2sgPT0gIlNpbW9uIikgewogICAgICAgIGRhdCA8LSBzdWJzZXQoZGF0YSwgVGFzayA9PSAiU2ltb24iKQogICAgICB9IGVsc2UgaWYgKFRhc2sgPT0gIkZsYW5rZXIiKSB7CiAgICAgICAgZGF0IDwtIHN1YnNldChkYXRhLCBUYXNrID09ICJGbGFua2VyIikKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgc3RvcCgiVGFzayBub3QgJ1NpbW9uJyBvciAnRmxhbmtlcicuIikKICAgIH0KICAgIAogICAgIyBUcmFuc2Zvcm0gZGF0YQogICAgaWYgKCEoVHJhbnNmb3JtYXRpb24gJWluJSBjKCJyYXciLCAic3BlZWQiLCAibG9nIikpKSB7CiAgICAgIHN0b3AoIlRyYW5zZm9ybWF0aW9uIG5vdCAncmF3JywgJ3NwZWVkJyBvciAnbG9nJy4iKQogICAgfSBlbHNlIGlmIChUcmFuc2Zvcm1hdGlvbiA9PSAicmF3IikgewogICAgICBkYXQkUmVzcG9uc2UgPC0gZGF0WywgIlJUIl0KICAgIH0gZWxzZSBpZiAoVHJhbnNmb3JtYXRpb24gPT0gInNwZWVkIikgewogICAgICBkYXQkUmVzcG9uc2UgPC0gMTAwMCAvIGRhdFssICJSVCJdCiAgICB9IGVsc2UgaWYgKFRyYW5zZm9ybWF0aW9uID09ICJsb2ciKSB7CiAgICAgIGRhdCRSZXNwb25zZSA8LSBsb2cxMChkYXRbLCAiUlQiXSkKICAgICAgIyBOb3RlIHRoYXQgdGhlIGJhc2Ugb2YgdGhlIGxvZ2FyaXRobSBpcyBpbW1hdGVyaWFsLgogICAgfQogICAgCiAgICAjIEV4Y2x1ZGUgaW5jb3JyZWN0IHJlc3BvbnNlcwogICAgIyBUcmFjayBob3cgbWFueSB3ZXJlIGV4Y2x1ZGVkCiAgICBleGNsdWRlZEFjY3VyYWN5IDwtIDAKICAgIGlmICghKEV4Y2x1c2lvbkFjY3VyYWN5ICVpbiUgYygieWVzIiwgIm5vIikpKSB7CiAgICAgIHN0b3AoIkV4Y2x1c2lvbkFjY3VyYWN5IG5lZWRzIHRvIGJlIGVpdGhlciB5ZXMgb3Igbm8uIikKICAgIH0gZWxzZSBpZiAoRXhjbHVzaW9uQWNjdXJhY3kgPT0gInllcyIpIHsKICAgICAgZXhjbHVkZWRBY2N1cmFjeSA8LSBzdW0oZGF0JEFjY3VyYWN5ID09ICIwIikKICAgICAgZGF0IDwtIGRhdFtkYXQkQWNjdXJhY3kgPT0gIjEiLF0KICAgIH0KICAgIAogICAgIyBFeGNsdWRlIG92ZXJseSBmYXN0IHJlc3BvbnNlcwogICAgIyBUcmFjayBob3cgbWFueSB3ZXJlIGV4Y2x1ZGVkCiAgICBleGNsdWRlZExhdGVuY3kgPC0gMAogICAgaWYgKCFtaXNzaW5nKEV4Y2x1c2lvbkxhdGVuY3kpKSB7CiAgICAgIGlmIChFeGNsdXNpb25MYXRlbmN5IDwgMCkgewogICAgICAgIHN0b3AoIlNldCBFeGNsdXNpb25MYXRlbmN5IHRvIGEgcG9zaXRpdmUgKG9yIHplcm8pIG51bWVyaWMgdmFyaWFibGUuIikKICAgICAgfSBlbHNlIHsKICAgICAgICBleGNsdWRlZExhdGVuY3kgPC0gc3VtKGRhdCRSVCA8IEV4Y2x1c2lvbkxhdGVuY3kpCiAgICAgICAgZGF0IDwtIGRhdFtkYXQkUlQgPiBFeGNsdXNpb25MYXRlbmN5LCBdCiAgICAgIH0KICAgIH0KICAgIAogICAgIyBFeGNsdWRlIHJlc3BvbnNlcyAobm90IHJlYWN0aW9uIHRpbWVzKSBtb3JlIHRoYW4geCBTRHMgYXdheSBmcm9tIHRoZSBwYXJ0aWNpcGFudHMnIG1lYW4KICAgICMgVHJhY2sgaG93IG1hbnkgd2VyZSBleGNsdWRlZAogICAgZXhjbHVkZWRPdXRsaWVycyA8LSAwCiAgICAKICAgIGlmICghaXMubmEoRXhjbHVzaW9uU0RzKSkgewogICAgICBpZiAoRXhjbHVzaW9uU0RzIDwgMCkgewogICAgICAgIHN0b3AoIlNldCBFeGNsdXNpb25TRHMgdG8gYSBwb3NpdGl2ZSAob3IgemVybykgbnVtZXJpYyB2YXJpYWJsZS4iKQogICAgICB9IGVsc2UgewogICAgICAgICMgQ29tcHV0ZSBtZWFuIGFuZCBzZCBwZXIgcGFydGljaXBhbnQKICAgICAgICBwZXJQYXJ0aWNpcGFudCA8LSBkYXQgJT4lCiAgICAgICAgICBncm91cF9ieV8oLiwgIlN1YmplY3QiKSAlPiUKICAgICAgICAgIHN1bW1hcmlzZV8obWVhblJlc3BvbnNlID0gIm1lYW4oUmVzcG9uc2UpIiwKICAgICAgICAgICAgICAgICAgICAgc2RSZXNwb25zZSA9ICJzZChSZXNwb25zZSkiKQogICAgICAgIAogICAgICAgICMgQWRkIHBlclBhcnRpY2lwYW50IHRvIGRhdAogICAgICAgIGRhdCA8LSBsZWZ0X2pvaW4oZGF0LCBwZXJQYXJ0aWNpcGFudCwgYnkgPSAiU3ViamVjdCIpCiAgICAgICAgCiAgICAgICAgIyBDaGVjayBob3cgbWFueSByZXNwb25zZXMgYXJlIG1vcmUgdGhhbiB4IHNkcyBhd2F5IGZyb20gcGFydGljaXBhbnQgbWVhbgogICAgICAgICMgZGF0JExvdyA8LSBkYXQkbWVhblJlc3BvbnNlIC0gRXhjbHVzaW9uU0RzICogZGF0JHNkUmVzcG9uc2UKICAgICAgICBkYXQkT3V0bGllciA8LQogICAgICAgICAgKGRhdCRSZXNwb25zZSA8IGRhdCRtZWFuUmVzcG9uc2UgLSBFeGNsdXNpb25TRHMgKiBkYXQkc2RSZXNwb25zZSkgfAogICAgICAgICAgKGRhdCRSZXNwb25zZSA+IGRhdCRtZWFuUmVzcG9uc2UgKyBFeGNsdXNpb25TRHMgKiBkYXQkc2RSZXNwb25zZSkKICAgICAgICBleGNsdWRlZE91dGxpZXJzIDwtIHN1bShkYXQkT3V0bGllcikKICAgICAgICAKICAgICAgICAjIFJlbW92ZSBvdXRsaWVycwogICAgICAgIGRhdCA8LSBkYXQgJT4lIGZpbHRlcihPdXRsaWVyID09IEZBTFNFKQogICAgICB9CiAgICB9IGVsc2UgaWYgKGlzLm5hKEV4Y2x1c2lvblNEcykpIHsKICAgICAgZGF0IDwtIGRhdAogICAgfQogICAgCgogICAgIyBFeGNsdWRlIHJlc3BvbnNlcyAobm90IHJlYWN0aW9uIHRpbWVzKSBtb3JlIHRoYW4geCBTRHMgYXdheSBmcm9tIHRoZSBvdmVyYWxsIG1lYW4KICAgICAgICAKICAgICMgVHJhY2sgaG93IG1hbnkgd2VyZSBleGNsdWRlZAogICAgZXhjbHVkZWRPdXRsaWVyc092ZXJhbGwgPC0gMAoKICAgIGlmICghaXMubmEoRXhjbHVzaW9uU0RzT3ZlcmFsbCkpIHsKICAgICAgaWYgKEV4Y2x1c2lvblNEc092ZXJhbGwgPCAwKSB7CiAgICAgICAgc3RvcCgiU2V0IEV4Y2x1c2lvblNEc092ZXJhbGwgdG8gYSBwb3NpdGl2ZSAob3IgemVybykgbnVtZXJpYyB2YXJpYWJsZS4iKQogICAgICB9IGVsc2UgewogICAgICAgICMgQ2hlY2sgaG93IG1hbnkgcmVzcG9uc2VzIGFyZSBtb3JlIHRoYW4geCBzZHMgYXdheSBmcm9tIHBhcnRpY2lwYW50IG1lYW4KICAgICAgICBPdXRsaWVyT3ZlcmFsbCA8LSAKICAgICAgICAgIChkYXQkUmVzcG9uc2UgPCBtZWFuKGRhdCRSZXNwb25zZSkgLSBFeGNsdXNpb25TRHNPdmVyYWxsICogc2QoZGF0JFJlc3BvbnNlKSkgfCAKICAgICAgICAgIChkYXQkUmVzcG9uc2UgPiBtZWFuKGRhdCRSZXNwb25zZSkgKyBFeGNsdXNpb25TRHNPdmVyYWxsICogc2QoZGF0JFJlc3BvbnNlKSkKICAgICAgICBleGNsdWRlZE91dGxpZXJzT3ZlcmFsbCA8LSBzdW0oT3V0bGllck92ZXJhbGwpCgogICAgICAgICMgUmVtb3ZlIG91dGxpZXJzCiAgICAgICAgZGF0IDwtIGRhdFtPdXRsaWVyT3ZlcmFsbCA9PSBGQUxTRSwgXQogICAgICB9CiAgICB9IGVsc2UgaWYgKGlzLm5hKEV4Y2x1c2lvblNEc092ZXJhbGwpKSB7CiAgICAgIGRhdCA8LSBkYXQKICAgIH0KICAgIAogICAgCiAgICAjIFNlbGVjdCBkZXBlbmRlbnQgdmFyaWFibGUKICAgIGlmICghKERWICVpbiUgYygKICAgICAgIm1lYW4gZGlmZmVyZW5jZSIsCiAgICAgICJtZWFuIHJhdGlvIiwKICAgICAgIm1lZGlhbiBkaWZmZXJlbmNlIiwKICAgICAgIm1lZGlhbiByYXRpbyIKICAgICkpKSB7CiAgICAgIHN0b3AoCiAgICAgICAgIlRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKERWKSBzaG91bGQgYmUgJ21lYW4gZGlmZmVyZW5jZScsICdtZWFuIHJhdGlvJywgJ21lZGlhbiBkaWZmZXJlbmNlJyBvciAnbWVhbiByYXRpbycuCiAgUGxlYXNlIG5vdGUgdGhhdCAnbm8gYWdncmVnYXRpb24nIGlzIG5vdCBjdXJyZW50bHkgc3VwcG9ydGVkLiIKICAgICAgKQogICAgICAKICAgIH0gZWxzZSBpZiAoRFYgPT0gIm1lYW4gZGlmZmVyZW5jZSIpIHsKICAgICAgZGF0X0RWIDwtIGRhdCAlPiUKICAgICAgICBncm91cF9ieV8oIlN1YmplY3QiLCAiU3RhdHVzIikgJT4lCiAgICAgICAgc3VtbWFyaXNlXyhhdmVyYWdlID0gIm1lYW4oUmVzcG9uc2UpIikgJT4lICMgbWVhbiByZXNwb25zZQogICAgICAgIHNwcmVhZF8oIlN0YXR1cyIsICJhdmVyYWdlIikgJT4lCiAgICAgICAgbXV0YXRlXyhEViA9IHF1b3RlKGNvbmdydWVudCAtIGluY29uZ3J1ZW50KSkgICAgIyBkaWZmZXJlbmNlIHNjb3JlCiAgICAgIAogICAgICAjIEZvciByYXcgbGF0ZW5jaWVzOiBIb3cgbXVjaCBfU0xPV0VSXyBhcmUgcGFydGljaXBhbnRzIGluIHRoZSBjb25ncnVlbnQgY29uZGl0aW9uPwogICAgICAjICAgV2UnZCBleHBlY3QgdGhpcyB0byBiZSBhIG5lZ2F0aXZlIG51bWJlciBmb3IgbW9zdCBwYXJ0aWNpcGFudHMKICAgICAgIyAgIChpLmUuIHRoZXkncmUgYWN0dWFsbHkgZmFzdGVyIGluIHRoZSBjb25ncnVlbnQgY29uZGl0aW9uKS4KICAgICAgIyAgIExvd2VyIG51bWJlcnMgKD0gbW9yZSBuZWdhdGl2ZSBudW1iZXJzKSBpbmRpY2F0ZSBsYXJnZXIgU2ltb24gZWZmZWN0cy4KICAgICAgIyAgIFByZWRpY3Rpb246IFRoaXMgbnVtYmVyIHNob3VsZCBiZSBMQVJHRVIgZm9yIG1vcmUgYmFsYW5jZWQgYmlsaW5ndWFscy4gKHNpZ246IDEpCiAgICAgIAogICAgICAjIEZvciBzcGVlZHM6IEhvdyBtdWNoIF9GQVNURVJfIGFyZSBwYXJ0aWNpcGFudHMgaW4gdGhlIGNvbmdydWVudCBjb25kaXRpb24/CiAgICAgICMgICBXZSdkIGV4cGVjdCB0aGlzIHRvIGJlIHBvc2l0aXZlIG51bWJlciBmb3IgbW9zdCBwYXJ0aWNpcGFudHMuCiAgICAgICMgICBMYXJnZXIgbnVtYmVycyBpbmRpY2F0ZSBsYXJnZXIgU2ltb24gZWZmZWN0cy4KICAgICAgIyAgIFByZWRpY3Rpb246IFRoaXMgbnVtYmVyIHNob3VsZCBiZSBTTUFMTEVSIGZvciBtb3JlIGJhbGFuY2VkIGJpbGluZ3VhbHMuIChzaWduOiAtMSkKICAgICAgCiAgICAgICMgRm9yIGxvZ3M6IFNhbWUgYXMgZm9yIHJhdyBsYXRlbmNpZXMuIChzaWduOiAxKQogICAgICAKICAgIH0gZWxzZSBpZiAoRFYgPT0gIm1lYW4gcmF0aW8iKSB7CiAgICAgIGRhdF9EViA8LSBkYXQgJT4lCiAgICAgICAgZ3JvdXBfYnlfKCJTdWJqZWN0IiwgIlN0YXR1cyIpICU+JQogICAgICAgIHN1bW1hcmlzZV8oYXZlcmFnZSA9ICJtZWFuKFJlc3BvbnNlKSIpICU+JSAjIG1lYW4gcmVzcG9uc2UKICAgICAgICBzcHJlYWRfKCJTdGF0dXMiLCAiYXZlcmFnZSIpICU+JQogICAgICAgIG11dGF0ZV8oRFYgPSBxdW90ZShjb25ncnVlbnQgLyBpbmNvbmdydWVudCkpICAgICMgcmF0aW8gc2NvcmUKICAgICAgCiAgICAgICMgRm9yIHJhdyBsYXRlbmNpZXM6IFJlbGF0aXZlIHRvIHRoZSBpbmNvbmdydWVudCBjb25kaXRpb24sIGhvdyBzbG93IGFyZSBwYXJ0aWNpcGFudHMgaW4gdGhlIGNvbmdydWVudCBjb25kaXRpb24/CiAgICAgICMgICBUaGlzIG51bWJlciB3aWxsIGJlIGxlc3MgdGhhbiAxIGZvciBtb3N0IHBhcnRpY2lwYW50cy4KICAgICAgIyAgIExvd2VyIG51bWJlcnMgKG1vcmUgdG93YXJkcyAwKSBpbmRpY2F0ZSBsYXJnZXIgU2ltb24gZWZmZWN0cy4KICAgICAgIyAgIFByZWRpY3Rpb246IFRoaXMgbnVtYmVyIHNob3VsZCBiZSBMQVJHRVIgZm9yIG1vcmUgYmFsYW5jZWQgYmlsaW5ndWFscy4gKHNpZ246IDEpCiAgICAgIAogICAgICAjIEZvciBzcGVlZHM6IFJlbGF0aXZlIHRvIHRoZSBpbmNvbmdydWVudCBjb25kaXRpb24sIGhvdyBmYXN0IGFyZSBwYXJ0aWNpcGFudHMgaW4gdGhlIGNvbmdydWVudCBjb25kaXRpb24/CiAgICAgICMgICBUaGlzIG51bWJlciB3aWxsIGJlIG1vcmUgdGhhbiAxIGZvciBtb3N0IHBhcnRpY2lwYW50cy4KICAgICAgIyAgIExhcmdlciBudW1iZXJzIGluZGljYXRlIGxhcmdlciBTaW1vbiBlZmZlY3RzLgogICAgICAjICAgUHJlZGljdGlvbjogVGhpcyBudW1iZXIgc2hvdWxkIGJlIFNNQUxMRVIgZm9yIG1vcmUgYmFsYW5jZWQgYmlsaW5ndWFscy4gKHNpZ246IC0xKQogICAgICAKICAgICAgIyBGb3IgbG9nczogU2FtZSBhcyBmb3IgcmF3IGxhdGVuY2llcy4gKHNpZ246IDEpCiAgICAgIAogICAgICAjIFdlIGRvbid0IGNvbnNpZGVyIGFuYWx5c2VzIG9uIG1lZGlhbnMgaW4gdGhpcyBtdWx0aXZlcnNlIGFuYWx5c2lzOgogICAgICAKICAgIH0gZWxzZSBpZiAoRFYgPT0gIm1lZGlhbiBkaWZmZXJlbmNlIikgewogICAgICBkYXRfRFYgPC0gZGF0ICU+JQogICAgICAgIGdyb3VwX2J5XygiU3ViamVjdCIsICJTdGF0dXMiKSAlPiUKICAgICAgICBzdW1tYXJpc2VfKGF2ZXJhZ2UgPSB+IG1lZGlhbihSZXNwb25zZSkpICU+JSAjIG1lZGlhbiByZXNwb25zZQogICAgICAgIHNwcmVhZF8oIlN0YXR1cyIsICJhdmVyYWdlIikgJT4lCiAgICAgICAgbXV0YXRlXyhEViA9IHF1b3RlKGNvbmdydWVudCAtIGluY29uZ3J1ZW50KSkgICAgICAjIGRpZmZlcmVuY2Ugc2NvcmUKICAgICAgCiAgICAgICMgUHJlZGljdGlvbnM6IHNlZSBtZWFuIGRpZmZlcmVuY2UuCiAgICAgIAogICAgfSBlbHNlIGlmIChEViA9PSAibWVkaWFuIHJhdGlvIikgewogICAgICBkYXRfRFYgPC0gZGF0ICU+JQogICAgICAgIGdyb3VwX2J5XygiU3ViamVjdCIsICJTdGF0dXMiKSAlPiUKICAgICAgICBzdW1tYXJpc2VfKGF2ZXJhZ2UgPSB+IG1lZGlhbihSZXNwb25zZSkpICU+JSAjIG1lZGlhbiByZXNwb25zZQogICAgICAgIHNwcmVhZF8oIlN0YXR1cyIsICJhdmVyYWdlIikgJT4lCiAgICAgICAgbXV0YXRlXyhEViA9IHF1b3RlKGNvbmdydWVudCAvIGluY29uZ3J1ZW50KSkgICAgICAjIHJhdGlvIHNjb3JlCiAgICAgIAogICAgICAjIFByZWRpY3Rpb25zOiBzZWUgbWVhbiByYXRpby4KICAgICAgCiAgICB9CiAgICAKICAgICMgU2VsZWN0IHByZWRpY3RvcgogICAgCiAgICBpZiAoISgKICAgICAgSVYgJWluJSBjKAogICAgICAgICJyYXcgZG9taW5hbmNlIiwKICAgICAgICAiYWJzb2x1dGUgZG9taW5hbmNlIiwKICAgICAgICAicmF3IGRvbWluYW5jZSwgb3JhbCIsCiAgICAgICAgImFic29sdXRlIGRvbWluYW5jZSwgb3JhbCIsCiAgICAgICAgInJhdyB1c2UiLAogICAgICAgICJhYnNvbHV0ZSB1c2UiLAogICAgICAgICJ0b3RhbCBTd2FiaWFuIiwKICAgICAgICAidG90YWwgU3dhYmlhbiwgb3JhbCIKICAgICAgKQogICAgKSkgewogICAgICBzdG9wKAogICAgICAgICJUaGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgKElWKSBzaG91bGQgYmUgJ3JhdyBkb21pbmFuY2UnLCAnYWJzb2x1dGUgZG9taW5hbmNlJywKICAncmF3IGRvbWluYW5jZSwgb3JhbCcsICdhYnNvbHV0ZSBkb21pbmFuY2UsIG9yYWwnLAogICdyYXcgdXNlJywgb3IgJ2Fic29sdXRlIHVzZScuIgogICAgICApCiAgICAgIAogICAgfSBlbHNlIGlmIChJViA9PSAicmF3IGRvbWluYW5jZSIpIHsKICAgICAgZGF0X0lWIDwtIGRhdCAlPiUKICAgICAgICBzZWxlY3RfKCJTdWJqZWN0IiwgIkRvbWluYW5jZVN3YWJpYW4iKSAlPiUKICAgICAgICBkaXN0aW5jdF8oKSAlPiUKICAgICAgICByZW5hbWVfKElWID0gIkRvbWluYW5jZVN3YWJpYW4iKQogICAgICAKICAgIH0gZWxzZSBpZiAoSVYgPT0gImFic29sdXRlIGRvbWluYW5jZSIpIHsKICAgICAgZGF0X0lWIDwtIGRhdCAlPiUKICAgICAgICBzZWxlY3RfKCJTdWJqZWN0IiwgIkRvbWluYW5jZVN3YWJpYW4iKSAlPiUKICAgICAgICBkaXN0aW5jdF8oKSAlPiUKICAgICAgICBtdXRhdGVfKElWID0gfiBhYnMoRG9taW5hbmNlU3dhYmlhbikpCiAgICAgIAogICAgfSBlbHNlIGlmIChJViA9PSAicmF3IGRvbWluYW5jZSwgb3JhbCIpIHsKICAgICAgZGF0X0lWIDwtIGRhdCAlPiUKICAgICAgICBzZWxlY3RfKCJTdWJqZWN0IiwgIkRvbWluYW5jZVN3YWJpYW5PcmFsIikgJT4lCiAgICAgICAgZGlzdGluY3RfKCkgJT4lCiAgICAgICAgbXV0YXRlXyhJViA9ICJEb21pbmFuY2VTd2FiaWFuT3JhbCIpCiAgICAgIAogICAgfSBlbHNlIGlmIChJViA9PSAiYWJzb2x1dGUgZG9taW5hbmNlLCBvcmFsIikgewogICAgICBkYXRfSVYgPC0gZGF0ICU+JQogICAgICAgIHNlbGVjdF8oIlN1YmplY3QiLCAiRG9taW5hbmNlU3dhYmlhbk9yYWwiKSAlPiUKICAgICAgICBkaXN0aW5jdF8oKSAlPiUKICAgICAgICBtdXRhdGVfKElWID0gfiBhYnMoRG9taW5hbmNlU3dhYmlhbk9yYWwpKQogICAgICAKICAgIH0gZWxzZSBpZiAoSVYgPT0gInJhdyB1c2UiKSB7CiAgICAgIGRhdF9JViA8LSBkYXQgJT4lCiAgICAgICAgc2VsZWN0XygiU3ViamVjdCIsICJEb21pbmFuY2VTd2FiaWFuVXNlIikgJT4lCiAgICAgICAgZGlzdGluY3RfKCkgJT4lCiAgICAgICAgcmVuYW1lXyhJViA9ICJEb21pbmFuY2VTd2FiaWFuVXNlIikKICAgICAgCiAgICB9IGVsc2UgaWYgKElWID09ICJhYnNvbHV0ZSB1c2UiKSB7CiAgICAgIGRhdF9JViA8LSBkYXQgJT4lCiAgICAgICAgc2VsZWN0XygiU3ViamVjdCIsICJEb21pbmFuY2VTd2FiaWFuVXNlIikgJT4lCiAgICAgICAgZGlzdGluY3RfKCkgJT4lCiAgICAgICAgbXV0YXRlXyhJViA9IH4gYWJzKERvbWluYW5jZVN3YWJpYW5Vc2UpKQogICAgICAKICAgIH0gZWxzZSBpZiAoSVYgPT0gInRvdGFsIFN3YWJpYW4iKSB7CiAgICAgIGRhdF9JViA8LSBkYXQgJT4lCiAgICAgICAgc2VsZWN0XygiU3ViamVjdCIsICJUb3RhbFN3YWJpYW4iKSAlPiUKICAgICAgICBkaXN0aW5jdF8oKSAlPiUKICAgICAgICByZW5hbWVfKElWID0gIlRvdGFsU3dhYmlhbiIpCiAgICAgIAogICAgfSBlbHNlIGlmIChJViA9PSAidG90YWwgU3dhYmlhbiwgb3JhbCIpIHsKICAgICAgZGF0X0lWIDwtIGRhdCAlPiUKICAgICAgICBzZWxlY3RfKCJTdWJqZWN0IiwgIlRvdGFsU3dhYmlhbk9yYWwiKSAlPiUKICAgICAgICBkaXN0aW5jdF8oKSAlPiUKICAgICAgICByZW5hbWVfKElWID0gIlRvdGFsU3dhYmlhbk9yYWwiKQogICAgICAKICAgIH0KICAgIAogICAgIyBDb21iaW5lIGRhdGFzZXRzCiAgICBkYXRfY29tYmluZWQgPC0gbGVmdF9qb2luKGRhdF9EViwgYXMudGJsKGRhdF9JViksIGJ5ID0gIlN1YmplY3QiKQogICAgCiAgICAjIFJ1biBhbmFseXNpczsgc2ltcGxlIHJlZ3Jlc3Npb24gbW9kZWwuCiAgICBtb2QubG0gPC0gbG0oRFYgfiBJViwgZGF0X2NvbWJpbmVkKQogICAgCiAgICByZXR1cm4oCiAgICAgIGxpc3QoCiAgICAgICAgZXhjbHVkZWRBY2N1cmFjeSA9IGV4Y2x1ZGVkQWNjdXJhY3ksCiAgICAgICAgZXhjbHVkZWRMYXRlbmN5ID0gZXhjbHVkZWRMYXRlbmN5LAogICAgICAgIGV4Y2x1ZGVkT3V0bGllcnMgPSBleGNsdWRlZE91dGxpZXJzLAogICAgICAgIGV4Y2x1ZGVkT3V0bGllcnNPdmVyYWxsID0gZXhjbHVkZWRPdXRsaWVyc092ZXJhbGwsCiAgICAgICAgcFZhbHVlID0gIHN1bW1hcnkobW9kLmxtKSRjb2VmWzIsIDRdLAogICAgICAgIGRpcmVjdGlvbiA9IHNpZ24oY29lZihtb2QubG0pWzJdKQogICAgICApCiAgICApCiAgfQoKIyBTZWUgaWYgdGhpcyB3b3JrczoKYWxsQW5hbHlzZXMoZGF0YSA9IGRhdCwKICAgICAgICAgICAgVGFzayA9ICJGbGFua2VyIiwKICAgICAgICAgICAgRXhjbHVzaW9uQWNjdXJhY3kgPSAieWVzIiwKICAgICAgICAgICAgVHJhbnNmb3JtYXRpb24gPSAibG9nIiwKICAgICAgICAgICAgRXhjbHVzaW9uTGF0ZW5jeSA9IDI1MCwKICAgICAgICAgICAgRXhjbHVzaW9uU0RzID0gMi41LAogICAgICAgICAgICBFeGNsdXNpb25TRHNPdmVyYWxsID0gMi41LAogICAgICAgICAgICBEViA9ICJtZWFuIGRpZmZlcmVuY2UiLAogICAgICAgICAgICBJViA9ICJyYXcgZG9taW5hbmNlIikKYGBgCgojIyBSdW4gYWxsIGFuYWx5c2VzIGluIGdyaWQKCmBgYHtyLCBjYWNoZSA9IFRSVUV9CiMgU29tZSBwYXJhbWV0ZXIgc2V0dGluZ3MgbmVlZCB0byBiZSBjb252ZXJ0ZWQgdG8gY2hhcmFjdGVyIHN0cmluZ3MuClRyYW5zZm9ybWF0aW9ucyA8LSBhcy5jaGFyYWN0ZXIoYWx0ZXJuYXRpdmVzJFRyYW5zZm9ybWF0aW9uKQpUYXNrcyA8LSBhcy5jaGFyYWN0ZXIoYWx0ZXJuYXRpdmVzJFRhc2spCkFjY3VyYWNpZXMgPC0gYXMuY2hhcmFjdGVyKGFsdGVybmF0aXZlcyRFeGNsdXNpb25BY2N1cmFjeSkKRFZzIDwtIGFzLmNoYXJhY3RlcihhbHRlcm5hdGl2ZXMkRFYpCklWcyA8LSBhcy5jaGFyYWN0ZXIoYWx0ZXJuYXRpdmVzJElWKQoKIyBQcmVwYXJlIGRhdGFmcmFtZSBmb3IgdGhlIG11bHRpdmVyc2UgYW5hbHlzaXMKbXVsdGl2ZXJzZSA8LSBkYXRhLmZyYW1lKFRhc2sgPSBhbHRlcm5hdGl2ZXMkVGFzaywKICAgICAgICAgICAgICAgICAgICAgICAgIFRyYW5zZm9ybWF0aW9uID0gYWx0ZXJuYXRpdmVzJFRyYW5zZm9ybWF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgRXhjbHVzaW9uQWNjdXJhY3kgPSBhbHRlcm5hdGl2ZXMkRXhjbHVzaW9uQWNjdXJhY3ksCiAgICAgICAgICAgICAgICAgICAgICAgICBFeGNsdXNpb25MYXRlbmN5ID0gYWx0ZXJuYXRpdmVzJEV4Y2x1c2lvbkxhdGVuY3ksCiAgICAgICAgICAgICAgICAgICAgICAgICBFeGNsdXNpb25TRHMgPSBhbHRlcm5hdGl2ZXMkRXhjbHVzaW9uU0RzLAogICAgICAgICAgICAgICAgICAgICAgICAgRXhjbHVzaW9uU0RzT3ZlcmFsbCA9IGFsdGVybmF0aXZlcyRFeGNsdXNpb25TRHNPdmVyYWxsLCAjIG5vdCB5ZXQgaW1wbGVtZW50ZWQKICAgICAgICAgICAgICAgICAgICAgICAgIERWID0gYWx0ZXJuYXRpdmVzJERWLAogICAgICAgICAgICAgICAgICAgICAgICAgSVYgPSBhbHRlcm5hdGl2ZXMkSVYsCiAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlZEFjY3VyYWN5ID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlZExhdGVuY3kgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVkT3V0bGllcnMgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVkT3V0bGllcnNPdmVyYWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICBwVmFsdWUgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IE5BKQoKbXVsdGl2ZXJzZQoKIyBMb29wIHRocm91Z2ggZW50aXJlIGdyaWQuCiMgSXQgbXVzdCBiZSBwb3NzaWJsZSB0byBkbyB0aGlzIG1vcmUgZWxlZ2FudGx5LCBidXQgbWFwcGx5KCkgY2F1c2VzIGRpZmZpY3VsdGllcy4KZm9yIChpIGluIDE6bnJvdyhhbHRlcm5hdGl2ZXMpKSB7CiAgcmVzdWx0cyA8LSBhbGxBbmFseXNlcyhkYXRhID0gZGF0LAogICAgICAgICAgICAgICAgICAgICAgICAgVGFzayA9IFRhc2tzW2ldLAogICAgICAgICAgICAgICAgICAgICAgICAgVHJhbnNmb3JtYXRpb24gPSBUcmFuc2Zvcm1hdGlvbnNbaV0sCiAgICAgICAgICAgICAgICAgICAgICAgICBFeGNsdXNpb25BY2N1cmFjeSA9IEFjY3VyYWNpZXNbaV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgRXhjbHVzaW9uTGF0ZW5jeSA9IGFsdGVybmF0aXZlcyRFeGNsdXNpb25MYXRlbmN5W2ldLCAKICAgICAgICAgICAgICAgICAgICAgICAgIEV4Y2x1c2lvblNEcyA9IGFsdGVybmF0aXZlcyRFeGNsdXNpb25TRHNbaV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgRXhjbHVzaW9uU0RzT3ZlcmFsbCA9IGFsdGVybmF0aXZlcyRFeGNsdXNpb25TRHNPdmVyYWxsW2ldLCAgIyBub3QgeWV0IGltcGxlbWVudGVkCiAgICAgICAgICAgICAgICAgICAgICAgICBEViA9IERWc1tpXSwKICAgICAgICAgICAgICAgICAgICAgICAgIElWID0gSVZzW2ldKQogIG11bHRpdmVyc2UkZXhjbHVkZWRBY2N1cmFjeVtpXSA8LSByZXN1bHRzJGV4Y2x1ZGVkQWNjdXJhY3kKICBtdWx0aXZlcnNlJGV4Y2x1ZGVkTGF0ZW5jeVtpXSA8LSByZXN1bHRzJGV4Y2x1ZGVkTGF0ZW5jeQogIG11bHRpdmVyc2UkZXhjbHVkZWRPdXRsaWVyc1tpXSA8LSByZXN1bHRzJGV4Y2x1ZGVkT3V0bGllcnMKICBtdWx0aXZlcnNlJGV4Y2x1ZGVkT3V0bGllcnNPdmVyYWxsW2ldIDwtIHJlc3VsdHMkZXhjbHVkZWRPdXRsaWVyc092ZXJhbGwgIyBub3QgeWV0IGltcGxlbWVudGVkCiAgbXVsdGl2ZXJzZSRwVmFsdWVbaV0gPC0gcmVzdWx0cyRwVmFsdWUKICBtdWx0aXZlcnNlJGRpcmVjdGlvbltpXSA8LSByZXN1bHRzJGRpcmVjdGlvbgp9CgojIHN1bW1hcnkobXVsdGl2ZXJzZSkKYGBgCgojIyBSZXN1bHRzCgpXZSdyZSBnb2luZyB0byBhZGQgYSBjb3VwbGUgb2YgdmFyaWFibGUgdG8gdGhlIGBtdWx0aXZlcnNlYCBkYXRhZnJhbWU6CgpgYGB7cn0KIyBXYXMgdGhlIHNpZ24gb2YgdGhlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnQsCiMgcmVnYXJkbGVzcyBvZiBpdHMgc2lnbmlmaWNhbmNlLAojIGluIHRoZSBkaXJlY3Rpb24gZXhwZWN0ZWQgdW5kZXIgdGhlIG92ZXJhbGwgImJpZGlhbGVjdGFsaXNtID4gYmV0dGVyIGV4ZWN1dGl2ZSBmdW5jdGlvbiIgaHlwb3RoZXNpcz8KbXVsdGl2ZXJzZSREaXJlY3Rpb25FeHBlY3RlZCA8LSAibm8iCm11bHRpdmVyc2VbbXVsdGl2ZXJzZSRUcmFuc2Zvcm1hdGlvbiAlaW4lIGMoInJhdyIsICJsb2ciKSAmIG11bHRpdmVyc2UkZGlyZWN0aW9uID09IDEsIF0kRGlyZWN0aW9uRXhwZWN0ZWQgPC0gInllcyIKbXVsdGl2ZXJzZVttdWx0aXZlcnNlJFRyYW5zZm9ybWF0aW9uID09ICJzcGVlZCIgJiBtdWx0aXZlcnNlJGRpcmVjdGlvbiA9PSAtMSwgXSREaXJlY3Rpb25FeHBlY3RlZCA8LSAieWVzIgptdWx0aXZlcnNlJERpcmVjdGlvbkV4cGVjdGVkIDwtIGZhY3RvcihtdWx0aXZlcnNlJERpcmVjdGlvbkV4cGVjdGVkKQoKIyBXYXMgdGhlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnQgc2lnbmlmaWNhbnQ/Cm11bHRpdmVyc2UkU2lnbmlmaWNhbnQgPC0gbXVsdGl2ZXJzZSRwVmFsdWUgPCAwLjA1CmBgYAoKV2UgZGVlbSBhIGhhbmRmdWwgb2YgY29tYmluYXRpb25zIG9mIGFuYWx5dGljYWwgY2hvaWNlcyB0byBiZSBpbnRlcm5hbGx5IGluY29uc2lzdGVudC4KU3BlY2lmaWNhbGx5LCB3ZSBkb24ndCBzZWUgaG93IGl0IHdvdWxkIG1ha2Ugc2Vuc2UgdG8gdGFrZSB0aGUgcmF0aW8gb2YgdHdvIG1lYW5zIG9mIGxvZ2FyaXRobWljYWxseSB0cmFuc2Zvcm1lZCB2YWx1ZXMuCldlJ2xsIHJlbW92ZSB0aGVzZSBmcm9tIGNvbnNpZGVyYXRpb246CgpgYGB7cn0KbXVsdGl2ZXJzZV9zZW5zaWJsZSA8LSBtdWx0aXZlcnNlICU+JSAKICBmaWx0ZXIoIShUcmFuc2Zvcm1hdGlvbiA9PSAibG9nIiAmIERWID09ICJtZWFuIHJhdGlvIikpCmBgYAoKVGhpcyBsZWF2ZXMgYHIgbnJvdyhtdWx0aXZlcnNlX3NlbnNpYmxlKWAgZnJvbSB0aGUgb3JpZ2luYWwgYHIgbnJvdyhtdWx0aXZlcnNlKWAgYW5hbHlzZXMuCgoKYGBge3IsIGZpZy53aWR0aCA9IDE0LCBmaWcuaGVpZ2h0ID0gOH0KdGhlbWVfc2V0KHRoZW1lX2Nvd3Bsb3QoMTIpKQpwX211bHRpIDwtIGdncGxvdChtdWx0aXZlcnNlX3NlbnNpYmxlLAogICAgICAgYWVzKHggPSBwVmFsdWUsCiAgICAgICAgICAgZmlsbCA9IFNpZ25pZmljYW50KSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJibGFjayIsIGJpbndpZHRoID0gMC4xMCkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuMDUsIGx0eSA9IDIsIGNvbG91ciA9ICJibGFjayIpICsKICBmYWNldF9ncmlkKFRhc2sgKyBUcmFuc2Zvcm1hdGlvbiB+IElWKSArCiAgc2NhbGVfeF9sb2cxMChicmVha3MgPSBjKDAuMDEsIDAuMDUsIDAuMiwgMSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsICJyZWQzIikpICsKICB4bGFiKCJwLXZhbHVlIikgKwogIHlsYWIoIm5vLiBvYnNlcnZhdGlvbnMiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpwcmludChwX211bHRpKQpzYXZlX3Bsb3QoIk11bHRpdmVyc2VBbmFseXNpcy5zdmciLCBwX211bHRpLCBiYXNlX3dpZHRoID0gMTQsIGJhc2VfaGVpZ2h0ID0gOCkKYGBgCgpCcmVha2Rvd24gb2Ygc2lnbmlmaWNhbnQgcmVzdWx0cyBwZXIgcGFuZWw6CgpgYGB7cn0KbXVsdGl2ZXJzZV9zZW5zaWJsZSAlPiUgCiAgZ3JvdXBfYnkoVGFzaywgVHJhbnNmb3JtYXRpb24sIElWKSAlPiUgCiAgc3VtbWFyaXNlKGBQcm9wb3J0aW9uIHNpZ25pZmljYW50YCA9IG1lYW4oU2lnbmlmaWNhbnQpLAogICAgICAgICAgICBgUHJvcG9ydGlvbiBleHBlY3RlZGAgPSBtZWFuKERpcmVjdGlvbkV4cGVjdGVkID09ICJ5ZXMiKSwKICAgICAgICAgICAgYE1lZGlhbiBwLXZhbHVlYCA9IG1lZGlhbihwVmFsdWUpKSAlPiUgCiAgYXJyYW5nZShkZXNjKGBQcm9wb3J0aW9uIHNpZ25pZmljYW50YCkpCmBgYAoKQWdncmVnYXRlIGJ5IFRhc2sgYW5kIElWIG9ubHk6CmBgYHtyfQptdWx0aXZlcnNlX3NlbnNpYmxlICU+JSAKICBncm91cF9ieShUYXNrLCBJVikgJT4lIAogIHN1bW1hcmlzZShgUGVyY2VudGFnZSBzaWduaWZpY2FudGAgPSBtZWFuKFNpZ25pZmljYW50KSoxMDAsCiAgICAgICAgICAgIGBQZXJjZW50YWdlIGV4cGVjdGVkYCA9IG1lYW4oRGlyZWN0aW9uRXhwZWN0ZWQgPT0gInllcyIpKjEwMCwKICAgICAgICAgICAgYE1lZGlhbiBwLXZhbHVlYCA9IG1lZGlhbihwVmFsdWUpKSAlPiUgCiAgYXJyYW5nZShkZXNjKGBQZXJjZW50YWdlIHNpZ25pZmljYW50YCksCiAgICAgICAgICBgTWVkaWFuIHAtdmFsdWVgKQpgYGAKCgoKQSBjbGlja2FibGUgbGlzdCBvZiBhbGwgYW5hbHlzZXMgc29ydGVkIGZyb20gdGhlIGxvd2VzdCBwLXZhbHVlIHRvIHRoZSBoaWdoZXN0OgpgYGB7cn0KbXVsdGl2ZXJzZV9zZW5zaWJsZSAlPiUgCiAgYXJyYW5nZShwVmFsdWUpCmBgYAoKRm9sbG93LXVwIHF1ZXN0aW9uOiBXaGF0IGNhdXNlcyB0aGUgdmFyaWFiaWxpdHkgd2l0aGluIHRoZSBfcmF3IHVzZV8gY2VsbHM/CgpgYGB7cn0KIyBFeGNsdWRpbmcgb2JzZXJ2YXRpb25zIGJhc2VkIG9uIGRldmlhdGlvbiBmcm9tIG92ZXJhbGwgbWVhbj8KbXVsdGl2ZXJzZV9zZW5zaWJsZSAlPiUgCiAgZmlsdGVyKElWID09ICJyYXcgdXNlIikgJT4lIAogIGdncGxvdCguLAogICAgICAgYWVzKHggPSBwVmFsdWUsCiAgICAgICAgICAgZmlsbCA9IFNpZ25pZmljYW50KSkgKwogIGdlb21faGlzdG9ncmFtKGNvbG91ciA9ICJibGFjayIsIGJpbndpZHRoID0gMC4xMCkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuMDUsIGx0eSA9IDIsIGNvbG91ciA9ICJibGFjayIpICsKICBmYWNldF9ncmlkKFRhc2sgKyBUcmFuc2Zvcm1hdGlvbiB+ICBFeGNsdXNpb25TRHNPdmVyYWxsKSArCiAgc2NhbGVfeF9sb2cxMChicmVha3MgPSBjKDAuMDEsIDAuMDUsIDAuMiwgMSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsICJyZWQzIikpICsKICB4bGFiKCJwLXZhbHVlIikgKwogIHlsYWIoIm5vLiBvYnNlcnZhdGlvbnMiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKIyBFeGNsdWRpbmcgb2JzZXJ2YXRpb25zIGJhc2VkIG9uIGRldmlhdGlvbiBmcm9tIHBhcnRpY2lwYW50IG1lYW4/Cm11bHRpdmVyc2Vfc2Vuc2libGUgJT4lIAogIGZpbHRlcihJViA9PSAicmF3IHVzZSIpICU+JSAKICBnZ3Bsb3QoLiwKICAgICAgIGFlcyh4ID0gcFZhbHVlLAogICAgICAgICAgIGZpbGwgPSBTaWduaWZpY2FudCkpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAiYmxhY2siLCBiaW53aWR0aCA9IDAuMTApICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjA1LCBsdHkgPSAyLCBjb2xvdXIgPSAiYmxhY2siKSArCiAgZmFjZXRfZ3JpZChUYXNrICsgVHJhbnNmb3JtYXRpb24gfiAgRXhjbHVzaW9uU0RzKSArCiAgc2NhbGVfeF9sb2cxMChicmVha3MgPSBjKDAuMDEsIDAuMDUsIDAuMiwgMSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsICJyZWQzIikpICsKICB4bGFiKCJwLXZhbHVlIikgKwogIHlsYWIoIm5vLiBvYnNlcnZhdGlvbnMiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKIyBFeHByZXNzaW9uIG9mIERWCm11bHRpdmVyc2Vfc2Vuc2libGUgJT4lIAogIGZpbHRlcihJViA9PSAicmF3IHVzZSIpICU+JSAKICBnZ3Bsb3QoLiwKICAgICAgIGFlcyh4ID0gcFZhbHVlLAogICAgICAgICAgIGZpbGwgPSBTaWduaWZpY2FudCkpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAiYmxhY2siLCBiaW53aWR0aCA9IDAuMTApICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjA1LCBsdHkgPSAyLCBjb2xvdXIgPSAiYmxhY2siKSArCiAgZmFjZXRfZ3JpZChUYXNrICsgVHJhbnNmb3JtYXRpb24gfiAgRFYpICsKICBzY2FsZV94X2xvZzEwKGJyZWFrcyA9IGMoMC4wMSwgMC4wNSwgMC4yLCAxKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIndoaXRlIiwgInJlZDMiKSkgKwogIHhsYWIoInAtdmFsdWUiKSArCiAgeWxhYigibm8uIG9ic2VydmF0aW9ucyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgojIEV4Y2x1c2lvbiBvZiBpbmNvcnJlY3QgcmVzcG9uc2VzCm11bHRpdmVyc2Vfc2Vuc2libGUgJT4lIAogIGZpbHRlcihJViA9PSAicmF3IHVzZSIpICU+JSAKICBnZ3Bsb3QoLiwKICAgICAgIGFlcyh4ID0gcFZhbHVlLAogICAgICAgICAgIGZpbGwgPSBTaWduaWZpY2FudCkpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvdXIgPSAiYmxhY2siLCBiaW53aWR0aCA9IDAuMTApICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjA1LCBsdHkgPSAyLCBjb2xvdXIgPSAiYmxhY2siKSArCiAgZmFjZXRfZ3JpZChUYXNrICsgVHJhbnNmb3JtYXRpb24gfiAgRXhjbHVzaW9uQWNjdXJhY3kpICsKICBzY2FsZV94X2xvZzEwKGJyZWFrcyA9IGMoMC4wMSwgMC4wNSwgMC4yLCAxKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIndoaXRlIiwgInJlZDMiKSkgKwogIHhsYWIoInAtdmFsdWUiKSArCiAgeWxhYigibm8uIG9ic2VydmF0aW9ucyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAo=