1 Introduction

This analysis accompanies the article “Al-Tamimi, J. and Khattab, G., (2018). Acoustic correlates of the voicing contrast in Lebanese Arabic singleton and geminate plosives. Invited manuscript for the special issue of Journal of Phonetics,”Marking 50 Years of Research on Voice Onset Time and the Voicing Contrast in the World’s Languages" (eds., T. Cho, G. Docherty & D. Whalen). DOI: https://doi.org/10.1016/j.wocn.2018.09.010

This notebook presents the analyses and results of the Linear Mixed Effects Modelling that was used as a confirmatory analysis. The aim was to evaluate the relationship between each of the 19 acoustic correlates (outcome) and the six predictors.

2 Description of the data

The data used here are part of a larger project to investigate the acoustic correlates of gemination in Lebanese Arabic. 20 speakers (10 males) produced a list of items with all possible consonants in Lebanese Arabic. The data used in this notebook (and the paper) are concerned with the following stops: /b t tˤ d dˤ k/ as realised in one of the following syllable structures: ˈCVCVC (e.g. /ˈʕadad/ “number”), ˈCV:CVC (e.g. /ˈʕaːded/ “counting”), ˈCVC:VC (e.g. /ˈʕadːad)/ “he enumerated”), ˈCV:C:VC (e.g. /ˈʕaːdːe(h)/ “having counted”) and CVˈC:V:C (e.g. /ʕaˈdːeːd/ “counter”). The vowels surrounding the medial stop were either /a or aː/. 98 items were recorded from each participant. A total of 1960 words were elicited (98 words by 20 speakers), and 171 tokens were discarded due to noise or technical error, leaving a total of 1793 words for subsequent analyses.

19 acoustic correlates were looked at here to evaluate their impact on the four-way contrast between voicing and gemination, i.e., Voiced Singleton, Voiceless Singleton, Voiced Geminate and Voiceless Geminate. The 19 acoustic correlates used included 6 durational, three voicing, and 10 non-temporal including f0, F1 and harmonic differences. This Notebook looked at how each individual acoustic correlate was associated with the predictors. The next notebook extends the analysis by looking at the combination of these acoustic correlates and their predictive power in discriminating between the four categories above see notebook.

3 Loading required packages

We start by loading the required packages.

requiredPackages = c('dplyr','lme4','lmerTest','emmeans','ggplot2')
for(p in requiredPackages){
  if(!require(p,character.only = TRUE)) install.packages(p)
  library(p,character.only = TRUE)
}

4 Preprocessing the data

4.1 Reading in the data

We start reading in the data and checking the structure.

geminationRes <- read.csv("resultsGemination.csv")
str(geminationRes)
'data.frame':   7172 obs. of  28 variables:
 $ file_name         : Factor w/ 68 levels "01_F_W_main_1.wav",..: 1 1 1 1 4 4 4 4 7 7 ...
 $ speaker           : Factor w/ 20 levels "sp1","sp10","sp11",..: 1 1 1 1 3 3 3 3 12 12 ...
 $ sex               : Factor w/ 2 levels "F","M": 1 1 1 1 2 2 2 2 1 1 ...
 $ Number            : int  364 365 366 367 2379 2380 2381 2382 4373 4374 ...
 $ wordTarget        : Factor w/ 98 levels "2aabbeh","2aabeD",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ word              : Factor w/ 331 levels "2AAbaD","2aabbeh",..: 2 2 2 2 54 54 54 54 54 54 ...
 $ singGem           : Factor w/ 2 levels "geminate","singleton": 1 1 1 1 1 1 1 1 1 1 ...
 $ syllType          : Factor w/ 2 levels "iambic","trochaic": 2 2 2 2 2 2 2 2 2 2 ...
 $ vowelLength       : Factor w/ 2 levels "longV1","shortV1": 1 1 1 1 1 1 1 1 1 1 ...
 $ syllStruct        : Factor w/ 5 levels "V1C2V2","V1CC2V2",..: 5 5 5 5 5 5 5 5 5 5 ...
 $ c.v               : Factor w/ 7 levels "BVOT","C2","CC2",..: 6 3 1 5 6 3 1 5 6 3 ...
 $ phoneme           : Factor w/ 17 levels "a","aa","b","bb",..: 2 4 4 10 11 4 4 10 11 4 ...
 $ modeArticulation4 : Factor w/ 1 level "stop": 1 1 1 1 1 1 1 1 1 1 ...
 $ placeArticulation : Factor w/ 4 levels "alveolar","bilabial",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ voiced.unvoiced   : Factor w/ 2 levels "voiced","voiceless": 1 1 1 1 1 1 1 1 1 1 ...
 $ placeVoicing      : Factor w/ 6 levels "alveolar voiced",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ duration          : num  139.9 165.5 18.5 128.9 158.1 ...
 $ durationBurst     : num  NA NA 4 NA NA NA 5 NA NA NA ...
 $ durationAsp       : num  NA NA 15 NA NA NA 6 NA NA NA ...
 $ durationVoicedPerc: num  NA 46.4 0 NA NA ...
 $ f0Onset           : num  NA 216 NA 247 NA ...
 $ f0Offset          : num  218 NA 248 NA 120 ...
 $ intensityOnset    : num  68.3 60.7 45.4 66.5 73 ...
 $ intensityOffset   : num  61.8 42.5 63.8 67.7 74.6 ...
 $ f1Onset           : num  NA NA NA 427 NA ...
 $ f1Offset          : num  619 NA NA NA 462 ...
 $ h1mnh2OnsetNorm   : num  NA NA NA 1.9 NA ...
 $ h1mnh2OffsetNorm  : num  3.79 NA NA NA 2.69 ...

4.2 Reordering of levels of predictors

Various predictors are available in data-frame, and we are interested in the impact of the following predictors: 1. Voicing: Voiced vs Voiceless 2. Gemination: Singleton vs Geminate 3. Sex: Male vs Female 4. (Preceding) Vowel Length: Short vs Long 5. Syllable Type: Iambic vs Trochaic 6. Place of Articulation: Bilabial, Alveolar, (Alveolar-)Pharyngealised and Velar

# using "dplyr"
levels(geminationRes$voiced.unvoiced)
[1] "voiced"    "voiceless"
geminationRes$voiced.unvoiced <- factor(geminationRes$voiced.unvoiced, 
                                        levels = c("voiceless","voiced"))
levels(geminationRes$voiced.unvoiced)
[1] "voiceless" "voiced"   
levels(geminationRes$singGem)
[1] "geminate"  "singleton"
geminationRes$singGem <- factor(geminationRes$singGem, 
                                levels = c("singleton","geminate"))
levels(geminationRes$singGem)
[1] "singleton" "geminate" 
levels(geminationRes$sex)
[1] "F" "M"
# no change
levels(geminationRes$vowelLength)
[1] "longV1"  "shortV1"
geminationRes$vowelLength <- factor(geminationRes$vowelLength, 
                                    levels = c("shortV1","longV1"))
levels(geminationRes$vowelLength)
[1] "shortV1" "longV1" 
levels(geminationRes$syllType)
[1] "iambic"   "trochaic"
geminationRes$syllType <- factor(geminationRes$syllType, 
                                 levels = c("trochaic","iambic"))
levels(geminationRes$syllType)
[1] "trochaic" "iambic"  
levels(geminationRes$placeArticulation)
[1] "alveolar"       "bilabial"       "pharyngealised" "velar"         
geminationRes$placeArticulation <- factor(geminationRes$placeArticulation, 
                                   levels = c("bilabial","alveolar","pharyngealised","velar"))
levels(geminationRes$placeArticulation)
[1] "bilabial"       "alveolar"       "pharyngealised" "velar"         

4.3 Contrast coding and centring of factor level

In our study, we wanted to use a model that allows for a meaningful interpretation of the coefficients and of the intercept. For this, we used contrast coding on all fixed effects by centring them to values between -0.5 and 0.5. With contrast coding, the Intercept is equal to the weighted average across all predictors, and all the coefficients for predictors will be equal to main effects rather than simple effects.

With this centring, our models will show the overall change from the level assigned the negative value to the level with the positive value. E.g., with voicing, voiceless was assigned -0.5 and voiced 0.5. In our statistical model the overall effect voicing will be shown as a change from voiceless to voiced (see article for more details).

# using "dplyr"
# for change from Voiceless to Voiced
geminationRes <- mutate(geminationRes,
                        voiced.unvoiced_c = ifelse(voiced.unvoiced == 'voiced', 0.5, -0.5))
# for change from Singleton to Geminate
geminationRes <- mutate(geminationRes,
                        singGem_c = ifelse(singGem == 'geminate', 0.5, -0.5))
# for change from Male to Female
geminationRes <- mutate(geminationRes,
                        sex_c = ifelse(sex == 'F', 0.5, -0.5))
# for change from Short V1 to Long V1
geminationRes <- mutate(geminationRes,
                        vowelLength_c = ifelse(vowelLength == 'longV1', 0.5, -0.5))
# for change from Trochaic to Iambic
geminationRes <- mutate(geminationRes,
                        syllType_c = ifelse(syllType == 'iambic', 0.5, -0.5))
# for change from Bilabial, to Alveolar to (Alveolar-)Pharyngealised to Velar
geminationRes <-  mutate(geminationRes, place_c = ifelse(placeArticulation == 'velar', 0.5,
                                                                ifelse(placeVoicing =='pharyngealised', 0.133,
                                                                                     ifelse(placeVoicing == 'alveolar', -0.133,-0.5))))

4.4 Creating four new data-frames

Here we create four new datasets that are subsets of the original dataset. The aim is to have specific data-frames for each of the preceding vowel (V1), medial consonant (CD), Release phase (BVOT) and following vowel (V2). V1 can be either short or long (V1, VV1); CD can be short or long (C2, CC2).

l <- c("a","aa", "e", "ee")
l2 <- c("V2", "VV2")
l3 <- c("V1", "VV1")
l4 <- c("C2","CC2")
l5 <- "BVOT"
geminationVowels <- filter(geminationRes, phoneme %in% l)
geminationV2 <- filter(geminationVowels, c.v %in% l2)
geminationV1 <- filter(geminationVowels, c.v %in% l3)
geminationCons <- filter(geminationRes, c.v %in% l4)
geminationVOT <- filter(geminationRes, c.v %in% l5)

4.5 Creating a new outcome (VOT)

In our original submission, we used the proportion of voicing in both the closure and release phases based the computations we developed see here. This proportion of voicing aims at explaining the patterns of passive devoicing and/or active voicing in the voicing by gemination contrasts. We also wanted to look at the voicing patterns in the voicing by gemination contrasts following the traditional “VOT” notion. Hence we computed the “VOT” by following the revised procedure as described in Abramson, A.S. & Whalen, D. (2017) (https://doi.org/10.1016/j.wocn.2017.05.002). Below is the implementation of this method based on our computations of the proportion of voicing in both closure and release phases. We use the threshold of 50% voicing; if “voicing” is equal or is higher than 50%, the total duration of the closure is considered negative VT, otherwise, the VOT is positive and is equivalent to the total duration of the Release phase (i.e., burst, and aspiration).

# start by creating a new predictor 
geminationCons$VOTDec <- NA
x <- -geminationCons$duration
y <- geminationVOT$duration
# below, we use the same threshold 
geminationCons$VOTDec <- ifelse(geminationCons$durationVoicedPerc >= 50, 
       x,y)

5 Running our Linear Mixed Effects Models

Now that the preprocessing of the data finished, we start with our modelling. As a remonder, our aim is to use these analyses in a confirmatory manner. We aim to evaluate the effects of the six predictors described above on each of the acoustic correlates. Crossed random effects were used for speaker and items.

For all models below, we used a combination of models: fixed effects only; random intercepts; random intercepts and slopes; interactions for the fixed effects; interactions for the slopes; etc. The optimal model in each case was the one presented below and had the following structure:

  1. Fixed effects with no interactions
  2. Random Intercepts for items
  3. Random Intercepts and Slopes for speaker (for all fixed effects minus sex). These random slopes were all within subjects, and were necessary to allow speakers to co-vary with respect to their effects. These random slopes were decorrelated from the Intercept (by using ||).

After each model was run, we compared models with an intercept only model (i.e., without the fixed effects). This is used to provide the statistical significance of our model. We are also using the package “lmerTest” to display the p values of each predictor. This uses an approximation of the degrees of freedom, and allows us to obtain estimated p values. This may be problematic given that these are approximations, and thus it is always best to evaluate the significance levels of our predictors using model comparisons.

We evaluate model’s residuals, and then we present the optimal models’ summaries. We then use the “predict” function from “lme4” to obtain the fitted values that take into account both fixed and random effects structure. The fitted (or predicted) values are adjusted by our statistical model and are then used in the figures.

5.1 Duration (msec)

Within duration, we computed the durations of the vowel preceding the consonant (V1), the medial consonant (CD), Release Phase (Rel), Burst Phase (B), Aspiration Phase (Asp) and the vowel following the consonant (V2)

5.1.1 Duration of the preceding vowel (V1)

5.1.1.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.1.1.1.1 Optimal model (ML)
durationV1.xmdl.Full.M <- lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.1.1.2 Optimal model (REML)
durationV1.xmdl.Full.R <- lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.1.1.3 Null model (ML)
durationV1.xmdl.Null.M <- lmer(duration~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.1.1.2 Results of our model

5.1.1.2.1 Model comparisons
anova(durationV1.xmdl.Null.M,durationV1.xmdl.Full.M)
Data: geminationV1
Models:
durationV1.xmdl.Null.M: duration ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationV1.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationV1.xmdl.Full.M: duration ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
durationV1.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationV1.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                       Df   AIC   BIC  logLik deviance  Chisq Chi Df
durationV1.xmdl.Null.M  9 15286 15335 -7633.9    15268              
durationV1.xmdl.Full.M 15 15162 15244 -7566.0    15132 135.82      6
                       Pr(>Chisq)    
durationV1.xmdl.Null.M               
durationV1.xmdl.Full.M  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.1.1.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationV1.xmdl.Full.R))

qqnorm(residuals(durationV1.xmdl.Full.R)); qqline(residuals(durationV1.xmdl.Full.R))

plot(fitted(durationV1.xmdl.Full.R),residuals(durationV1.xmdl.Full.R), cex = 4)

5.1.1.2.3 Summary of model
summary(durationV1.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
duration ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV1
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 15102

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.2034 -0.5417 -0.0270  0.5011  6.1062 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        99.9410  9.9970 
 speaker    place_c             0.4836  0.6954 
 speaker.1  syllType_c         23.0797  4.8041 
 speaker.2  vowelLength_c     209.1023 14.4604 
 speaker.3  singGem_c          14.8229  3.8500 
 speaker.4  voiced.unvoiced_c   3.9109  1.9776 
 speaker.5  (Intercept)       229.1941 15.1392 
 Residual                     216.9083 14.7278 
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        102.818      3.893  29.724  26.412  < 2e-16 ***
voiced.unvoiced_c   10.567      2.643  92.002   3.998 0.000129 ***
singGem_c          -10.362      2.546  93.293  -4.070 9.83e-05 ***
sex_c                4.038      6.832  17.968   0.591 0.561863    
vowelLength_c       81.472      4.057  39.506  20.082  < 2e-16 ***
syllType_c         -14.920      3.305  94.147  -4.515 1.83e-05 ***
place_c             -2.028      3.427  88.501  -0.592 0.555494    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.091                                   
singGem_c   -0.123 -0.034                            
sex_c       -0.001  0.001  0.001                     
vowlLngth_c  0.098 -0.089  0.045  0.000              
syllType_c   0.282  0.036 -0.343 -0.001  0.162       
place_c      0.265  0.527 -0.012  0.000 -0.035  0.029

5.1.1.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.1.1.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV1$fitted_durationV1 <- predict(lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.1.1.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggdurV1ByVoice <- ggplot(geminationV1, aes(y=fitted_durationV1, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Duration (ms)"))) + labs(title = "V1") +
  coord_cartesian(ylim = c(25,325)) +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV1$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggdurV1ByVoice

5.1.1.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.1.1.4.1 Descriptive statistics

The predicted means and SDs of the preceding vowel duration are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV1 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_durationV1), sd(fitted_durationV1))
5.1.1.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV1$fitted_durationV1, geminationV1$singGem:geminationV1$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV1$fitted_durationV1 and geminationV1$singGem:geminationV1$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   5.8e-16             -               
geminate:voiceless < 2e-16             < 2e-16         
geminate:voiced    0.005               < 2e-16         
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    4.5e-16           

P value adjustment method: fdr 

5.1.2 Duration of the Closure Duration (CD)

5.1.2.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.1.2.1.1 Optimal model (ML)
durationCD.xmdl.Full.M <- lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.2.1.2 Optimal model (REML)
durationCD.xmdl.Full.R <- lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.2.1.3 Null model (ML)
durationCD.xmdl.Null.M <- lmer(duration~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.1.2.2 Results of our model

5.1.2.2.1 Model comparisons
anova(durationCD.xmdl.Null.M,durationCD.xmdl.Full.M)
Data: geminationCons
Models:
durationCD.xmdl.Null.M: duration ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationCD.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationCD.xmdl.Full.M: duration ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
durationCD.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationCD.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                       Df   AIC   BIC  logLik deviance  Chisq Chi Df
durationCD.xmdl.Null.M  9 15398 15447 -7689.7    15380              
durationCD.xmdl.Full.M 15 15272 15355 -7621.1    15242 137.23      6
                       Pr(>Chisq)    
durationCD.xmdl.Null.M               
durationCD.xmdl.Full.M  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.1.2.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationCD.xmdl.Full.R))

qqnorm(residuals(durationCD.xmdl.Full.R)); qqline(residuals(durationCD.xmdl.Full.R))

plot(fitted(durationCD.xmdl.Full.R),residuals(durationCD.xmdl.Full.R), cex = 4)

5.1.2.2.3 Summary of model
summary(durationCD.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
duration ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationCons
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 15214.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.4156 -0.5681 -0.0335  0.5333  6.7738 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        44.77    6.691  
 speaker    place_c            20.75    4.555  
 speaker.1  syllType_c         75.48    8.688  
 speaker.2  vowelLength_c      19.18    4.379  
 speaker.3  singGem_c         294.82   17.170  
 speaker.4  voiced.unvoiced_c  31.33    5.597  
 speaker.5  (Intercept)       154.61   12.434  
 Residual                     234.14   15.302  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        121.250      3.104  25.366  39.060  < 2e-16 ***
voiced.unvoiced_c  -22.568      2.251  65.416 -10.023 7.57e-15 ***
singGem_c          101.658      4.208  24.950  24.157  < 2e-16 ***
sex_c                9.818      5.669  17.818   1.732 0.100556    
vowelLength_c        1.662      2.014  64.632   0.825 0.412313    
syllType_c          -7.409      2.968  50.626  -2.496 0.015862 *  
place_c            -10.939      2.663  72.044  -4.107 0.000104 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.070                                   
singGem_c   -0.048 -0.013                            
sex_c       -0.002  0.000  0.001                     
vowlLngth_c  0.127 -0.108  0.029 -0.001              
syllType_c   0.202  0.025 -0.120 -0.002  0.187       
place_c      0.222  0.410 -0.005 -0.002 -0.047  0.022

5.1.2.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.1.2.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationCons$fitted_durationCD <- predict(lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.1.2.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggdurCDByVoice <- ggplot(geminationCons, aes(y=fitted_durationCD, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Duration (ms)"))) + labs(title = "CD") +
  coord_cartesian(ylim = c(25,325)) +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationCons$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggdurCDByVoice

5.1.2.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.1.2.4.1 Descriptive statistics

The predicted means and SDs of the closure duration are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationCons %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_durationCD), sd(fitted_durationCD))
5.1.2.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationCons$fitted_durationCD, geminationCons$singGem:geminationCons$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationCons$fitted_durationCD and geminationCons$singGem:geminationCons$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   <2e-16              -               
geminate:voiceless <2e-16              <2e-16          
geminate:voiced    <2e-16              <2e-16          
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    <2e-16            

P value adjustment method: fdr 

5.1.3 Duration of the Release Phase (Rel)

5.1.3.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.1.3.1.1 Optimal model (ML)
durationRel.xmdl.Full.M <- lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.3.1.2 Optimal model (REML)
durationRel.xmdl.Full.R <- lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.3.1.3 Null model (ML)
durationRel.xmdl.Null.M <- lmer(duration~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.1.3.2 Results of our model

5.1.3.2.1 Model comparisons
anova(durationRel.xmdl.Null.M,durationRel.xmdl.Full.M)
Data: geminationVOT
Models:
durationRel.xmdl.Null.M: duration ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationRel.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationRel.xmdl.Full.M: duration ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
durationRel.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationRel.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                        Df   AIC   BIC  logLik deviance  Chisq Chi Df
durationRel.xmdl.Null.M  9 12369 12418 -6175.3    12351              
durationRel.xmdl.Full.M 15 12290 12373 -6130.2    12260 90.209      6
                        Pr(>Chisq)    
durationRel.xmdl.Null.M               
durationRel.xmdl.Full.M  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.1.3.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationRel.xmdl.Full.R))

qqnorm(residuals(durationRel.xmdl.Full.R)); qqline(residuals(durationRel.xmdl.Full.R))

plot(fitted(durationRel.xmdl.Full.R),residuals(durationRel.xmdl.Full.R), cex = 4)

5.1.3.2.3 Summary of model
summary(durationRel.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
duration ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationVOT
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 12244.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.5399 -0.5191 -0.0873  0.3942  8.2724 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)       12.958   3.600   
 speaker    place_c           23.041   4.800   
 speaker.1  syllType_c         2.278   1.509   
 speaker.2  vowelLength_c      6.832   2.614   
 speaker.3  singGem_c          4.564   2.136   
 speaker.4  voiced.unvoiced_c 16.655   4.081   
 speaker.5  (Intercept)       21.039   4.587   
 Residual                     44.108   6.641   
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        24.9692     1.2494 33.1458  19.985  < 2e-16 ***
voiced.unvoiced_c  -9.3847     1.3296 53.0690  -7.058 3.61e-09 ***
singGem_c           0.3376     1.0092 77.6741   0.335    0.739    
sex_c               1.6417     2.1058 17.3511   0.780    0.446    
vowelLength_c       5.1409     1.0808 71.5438   4.757 9.93e-06 ***
syllType_c          1.5479     1.2070 85.8098   1.282    0.203    
place_c            12.3890     1.6645 58.2555   7.443 5.15e-10 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.078                                   
singGem_c   -0.133 -0.024                            
sex_c       -0.003  0.000  0.001                     
vowlLngth_c  0.157 -0.091  0.059  0.000              
syllType_c   0.330  0.027 -0.327 -0.001  0.229       
place_c      0.235  0.297 -0.009 -0.003 -0.037  0.023

5.1.3.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.1.3.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationVOT$fitted_durationRel <- predict(lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.1.3.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggdurRelByVoice <- ggplot(geminationVOT, aes(y=fitted_durationRel, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Duration (ms)"))) + labs(title = "Rel") +
  coord_cartesian(ylim = c(0,60)) +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationVOT$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggdurRelByVoice

5.1.3.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.1.3.4.1 Descriptive statistics

The predicted means and SDs of the duration of the release phase are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationVOT %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_durationRel), sd(fitted_durationRel))
5.1.3.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationVOT$fitted_durationRel, geminationVOT$singGem:geminationVOT$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationVOT$fitted_durationRel and geminationVOT$singGem:geminationVOT$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   < 2e-16             -               
geminate:voiceless 6.9e-12             < 2e-16         
geminate:voiced    < 2e-16             1.5e-06         
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    < 2e-16           

P value adjustment method: fdr 

5.1.4 Duration of the Burst phase (B)

5.1.4.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.1.4.1.1 Optimal model (ML)
durationB.xmdl.Full.M <- lmer(durationBurst~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.4.1.2 Optimal model (REML)
durationB.xmdl.Full.R <- lmer(durationBurst~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.4.1.3 Null model (ML)
durationB.xmdl.Null.M <- lmer(durationBurst~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.1.4.2 Results of our model

5.1.4.2.1 Model comparisons
anova(durationB.xmdl.Null.M,durationB.xmdl.Full.M)
Data: geminationVOT
Models:
durationB.xmdl.Null.M: durationBurst ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationB.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationB.xmdl.Full.M: durationBurst ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
durationB.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationB.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                      Df    AIC    BIC  logLik deviance  Chisq Chi Df
durationB.xmdl.Null.M  9 9199.7 9248.8 -4590.8   9181.7              
durationB.xmdl.Full.M 15 9127.6 9209.5 -4548.8   9097.6 84.046      6
                      Pr(>Chisq)    
durationB.xmdl.Null.M               
durationB.xmdl.Full.M  5.204e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.1.4.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationB.xmdl.Full.R))

qqnorm(residuals(durationB.xmdl.Full.R)); qqline(residuals(durationB.xmdl.Full.R))

plot(fitted(durationB.xmdl.Full.R),residuals(durationB.xmdl.Full.R), cex = 4)

5.1.4.2.3 Summary of model
summary(durationB.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
durationBurst ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationVOT
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 9099.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.6555 -0.5779 -0.1718  0.4141  6.7797 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        0.47150 0.6867  
 speaker    place_c            4.96529 2.2283  
 speaker.1  syllType_c         0.03274 0.1810  
 speaker.2  vowelLength_c      0.18264 0.4274  
 speaker.3  singGem_c          0.00000 0.0000  
 speaker.4  voiced.unvoiced_c  0.87766 0.9368  
 speaker.5  (Intercept)        1.74348 1.3204  
 Residual                     10.18220 3.1910  
Number of obs: 1731, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)         8.8508     0.3488 26.1896  25.372  < 2e-16 ***
voiced.unvoiced_c  -2.1172     0.3277 33.2882  -6.462 2.40e-07 ***
singGem_c           0.9949     0.2333 92.1656   4.264 4.86e-05 ***
sex_c               1.0501     0.6258 17.5100   1.678    0.111    
vowelLength_c       0.3432     0.2572 38.4606   1.334    0.190    
syllType_c          0.4512     0.3038 48.9295   1.485    0.144    
place_c             4.1499     0.5979 26.5279   6.941 2.04e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.080                                   
singGem_c   -0.141 -0.038                            
sex_c       -0.009 -0.002  0.003                     
vowlLngth_c  0.161 -0.109  0.080  0.002              
syllType_c   0.316  0.032 -0.384 -0.001  0.260       
place_c      0.159  0.225 -0.007 -0.007 -0.031  0.018

5.1.4.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.1.4.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationVOT$fitted_durationBurst <- predict(lmer(durationBurst~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.1.4.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggdurBByVoice <- ggplot(geminationVOT, aes(y=fitted_durationBurst, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Duration (ms)"))) + labs(title = "B") +
  coord_cartesian(ylim = c(2.5,17.5)) +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationVOT$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggdurBByVoice

5.1.4.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.1.4.4.1 Descriptive statistics

The predicted means and SDs of the duration of the Burst phase are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationVOT %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_durationBurst,na.rm = T), sd(fitted_durationBurst,na.rm = T))
5.1.4.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationVOT$fitted_durationBurst, geminationVOT$singGem:geminationVOT$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationVOT$fitted_durationBurst and geminationVOT$singGem:geminationVOT$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   <2e-16              -               
geminate:voiceless 6e-11               <2e-16          
geminate:voiced    <2e-16              <2e-16          
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    <2e-16            

P value adjustment method: fdr 

5.1.5 Duration of the Aspiration phase (Asp)

5.1.5.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.1.5.1.1 Optimal model (ML)
durationAsp.xmdl.Full.M <- lmer(durationAsp~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.5.1.2 Optimal model (REML)
durationAsp.xmdl.Full.R <- lmer(durationAsp~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.5.1.3 Null model (ML)
durationAsp.xmdl.Null.M <- lmer(durationAsp~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.1.5.2 Results of our model

5.1.5.2.1 Model comparisons
anova(durationAsp.xmdl.Null.M,durationAsp.xmdl.Full.M)
Data: geminationVOT
Models:
durationAsp.xmdl.Null.M: durationAsp ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationAsp.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationAsp.xmdl.Full.M: durationAsp ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
durationAsp.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationAsp.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                        Df   AIC   BIC  logLik deviance  Chisq Chi Df
durationAsp.xmdl.Null.M  9 12101 12150 -6041.3    12083              
durationAsp.xmdl.Full.M 15 12042 12124 -6005.8    12012 70.961      6
                        Pr(>Chisq)    
durationAsp.xmdl.Null.M               
durationAsp.xmdl.Full.M  2.597e-13 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.1.5.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationAsp.xmdl.Full.R))

qqnorm(residuals(durationAsp.xmdl.Full.R)); qqline(residuals(durationAsp.xmdl.Full.R))

plot(fitted(durationAsp.xmdl.Full.R),residuals(durationAsp.xmdl.Full.R), cex = 4)

5.1.5.2.3 Summary of model
summary(durationAsp.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
durationAsp ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationVOT
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 11996.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.9429 -0.5018 -0.0765  0.3343 10.6900 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        9.673   3.110   
 speaker    place_c           20.398   4.516   
 speaker.1  syllType_c         1.129   1.062   
 speaker.2  vowelLength_c      5.792   2.407   
 speaker.3  singGem_c          2.842   1.686   
 speaker.4  voiced.unvoiced_c 14.200   3.768   
 speaker.5  (Intercept)       18.469   4.298   
 Residual                     50.368   7.097   
Number of obs: 1731, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        16.2473     1.1564 31.0503  14.050 5.32e-15 ***
voiced.unvoiced_c  -7.1656     1.2129 47.3349  -5.908 3.62e-07 ***
singGem_c          -1.0769     0.8884 68.9790  -1.212    0.230    
sex_c               0.2458     1.9829 17.3256   0.124    0.903    
vowelLength_c       4.5724     0.9833 60.1015   4.650 1.87e-05 ***
syllType_c          1.0605     1.0709 75.6114   0.990    0.325    
place_c             8.0374     1.5266 50.0638   5.265 2.95e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.076                                   
singGem_c   -0.134 -0.028                            
sex_c       -0.005 -0.001  0.002                     
vowlLngth_c  0.152 -0.091  0.063  0.000              
syllType_c   0.327  0.028 -0.340 -0.002  0.231       
place_c      0.225  0.287 -0.009 -0.004 -0.037  0.023

5.1.5.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.1.5.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationVOT$fitted_durationAsp <- predict(lmer(durationAsp~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.1.5.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggdurAspByVoice <- ggplot(geminationVOT, aes(y=fitted_durationAsp, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Duration (ms)"))) + labs(title = "Asp") +
  coord_cartesian(ylim = c(0,40)) +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationVOT$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggdurAspByVoice

5.1.5.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.1.5.4.1 Descriptive statistics

The predicted means and SDs of the duration of the Aspiration phase are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationVOT %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_durationAsp,na.rm = T), sd(fitted_durationAsp,na.rm = T))
5.1.5.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationVOT$fitted_durationAsp, geminationVOT$singGem:geminationVOT$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationVOT$fitted_durationAsp and geminationVOT$singGem:geminationVOT$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   <2e-16              -               
geminate:voiceless <2e-16              <2e-16          
geminate:voiced    <2e-16              0.84            
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    <2e-16            

P value adjustment method: fdr 

5.1.6 Duration of the Following Vowel (V2)

5.1.6.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.1.6.1.1 Optimal model (ML)
durationV2.xmdl.Full.M <- lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.6.1.2 Optimal model (REML)
durationV2.xmdl.Full.R <- lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.1.6.1.3 Null model (ML)
durationV2.xmdl.Null.M <- lmer(duration~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.1.6.2 Results of our model

5.1.6.2.1 Model comparisons
anova(durationV2.xmdl.Null.M,durationV2.xmdl.Full.M)
Data: geminationV2
Models:
durationV2.xmdl.Null.M: duration ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationV2.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationV2.xmdl.Full.M: duration ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
durationV2.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationV2.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                       Df   AIC   BIC  logLik deviance  Chisq Chi Df
durationV2.xmdl.Null.M  9 17047 17097 -8514.7    17029              
durationV2.xmdl.Full.M 15 16976 17058 -8472.8    16946 83.673      6
                       Pr(>Chisq)    
durationV2.xmdl.Null.M               
durationV2.xmdl.Full.M  6.215e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.1.6.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationV2.xmdl.Full.R))

qqnorm(residuals(durationV2.xmdl.Full.R)); qqline(residuals(durationV2.xmdl.Full.R))

plot(fitted(durationV2.xmdl.Full.R),residuals(durationV2.xmdl.Full.R), cex = 4)

5.1.6.2.3 Summary of model
summary(durationV2.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
duration ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV2
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 16910

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.6382 -0.5865 -0.0072  0.5329  4.5934 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)       182.26   13.501  
 speaker    place_c             0.00    0.000  
 speaker.1  syllType_c        583.55   24.157  
 speaker.2  vowelLength_c      68.01    8.247  
 speaker.3  singGem_c          35.19    5.932  
 speaker.4  voiced.unvoiced_c  39.88    6.315  
 speaker.5  (Intercept)       644.58   25.389  
 Residual                     606.29   24.623  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        182.939      6.273  25.530  29.163  < 2e-16 ***
voiced.unvoiced_c    7.465      3.884  91.598   1.922   0.0577 .  
singGem_c           15.922      3.582  83.903   4.445 2.68e-05 ***
sex_c              -12.002     11.470  17.999  -1.046   0.3092    
vowelLength_c        4.221      3.870  78.721   1.091   0.2788    
syllType_c          94.464      6.929  40.672  13.633  < 2e-16 ***
place_c             -3.281      4.753  92.169  -0.690   0.4918    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.074                                   
singGem_c   -0.105 -0.032                            
sex_c       -0.001  0.001  0.001                     
vowlLngth_c  0.122 -0.122  0.065 -0.001              
syllType_c   0.161  0.023 -0.225 -0.001  0.156       
place_c      0.229  0.498 -0.012  0.000 -0.051  0.020

5.1.6.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.1.6.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV2$fitted_durationV2 <- predict(lmer(duration~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.1.6.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggdurV2ByVoice <- ggplot(geminationV2, aes(y=fitted_durationV2, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Duration (ms)"))) + labs(title = "V2") +
  coord_cartesian(ylim = c(25,325)) +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV2$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggdurV2ByVoice

5.1.6.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.1.6.4.1 Descriptive statistics

The predicted means and SDs of the duration of the following vowel (V2) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV2 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_durationV2), sd(fitted_durationV2))
5.1.6.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV2$fitted_durationV2, geminationV2$singGem:geminationV2$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV2$fitted_durationV2 and geminationV2$singGem:geminationV2$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   0.055               -               
geminate:voiceless <2e-16              <2e-16          
geminate:voiced    <2e-16              <2e-16          
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    0.416             

P value adjustment method: fdr 

5.2 Voicing (msec and %)

Within Voicing, we have computed three metrics: positive and negative VOT (Voicing VOT), proportion of voicing in the closure duration (% Voicing CD) and proportion of voicing in the Release Phase (% Voicing Rel)

5.2.1 Positive and Negative VOT (Voicing VOT)

5.2.1.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.2.1.1.1 Optimal model (ML)
durationVoiceVOT.xmdl.Full.M <- lmer(VOTDec~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.2.1.1.2 Optimal model (REML)
durationVoiceVOT.xmdl.Full.R <- lmer(VOTDec~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.2.1.1.3 Null model (ML)
durationVoiceVOT.xmdl.Null.M <- lmer(VOTDec~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.2.1.2 Results of our model

5.2.1.2.1 Model comparisons
anova(durationVoiceVOT.xmdl.Null.M,durationVoiceVOT.xmdl.Full.M)
Data: geminationCons
Models:
durationVoiceVOT.xmdl.Null.M: VOTDec ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationVoiceVOT.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationVoiceVOT.xmdl.Full.M: VOTDec ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
durationVoiceVOT.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationVoiceVOT.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                             Df   AIC   BIC  logLik deviance Chisq
durationVoiceVOT.xmdl.Null.M  9 19206 19256 -9594.1    19188      
durationVoiceVOT.xmdl.Full.M 15 19123 19206 -9546.5    19093 95.02
                             Chi Df Pr(>Chisq)    
durationVoiceVOT.xmdl.Null.M                      
durationVoiceVOT.xmdl.Full.M      6  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.2.1.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationVoiceVOT.xmdl.Full.R))

qqnorm(residuals(durationVoiceVOT.xmdl.Full.R)); qqline(residuals(durationVoiceVOT.xmdl.Full.R))

plot(fitted(durationVoiceVOT.xmdl.Full.R),residuals(durationVoiceVOT.xmdl.Full.R), cex = 4)

5.2.1.2.3 Summary of model
summary(durationVoiceVOT.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
VOTDec ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationCons
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 19053.3

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.5542 -0.3456  0.0334  0.3465  4.2393 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        520.21  22.808  
 speaker    place_c             73.92   8.598  
 speaker.1  syllType_c           0.00   0.000  
 speaker.2  vowelLength_c      111.91  10.579  
 speaker.3  singGem_c          340.41  18.450  
 speaker.4  voiced.unvoiced_c  627.86  25.057  
 speaker.5  (Intercept)        331.50  18.207  
 Residual                     2085.69  45.669  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)        -42.308      6.127   60.677  -6.905 3.46e-09 ***
voiced.unvoiced_c -115.230      8.364   55.606 -13.776  < 2e-16 ***
singGem_c          -45.268      7.046   66.785  -6.425 1.62e-08 ***
sex_c                6.462      8.521   17.678   0.758   0.4582    
vowelLength_c       10.904      6.300   82.187   1.731   0.0872 .  
syllType_c           5.191      7.442   92.022   0.697   0.4873    
place_c              6.701      8.383   84.233   0.799   0.4263    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.104                                   
singGem_c   -0.160 -0.022                            
sex_c       -0.004  0.001  0.001                     
vowlLngth_c  0.227 -0.103  0.060  0.000              
syllType_c   0.450  0.029 -0.313  0.000  0.263       
place_c      0.392  0.386 -0.010 -0.002 -0.052  0.030

5.2.1.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.2.1.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationCons$fitted_VoiceVOT <- predict(lmer(VOTDec~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.2.1.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggVoiceVOTByVoice <- ggplot(geminationCons, aes(y=fitted_VoiceVOT, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("VOT"))) + labs(title = "VOT") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationCons$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggVoiceVOTByVoice

5.2.1.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.2.1.4.1 Descriptive statistics

The predicted means and SDs of the positive and negative VOT (VoiceVOT) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationCons %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_VoiceVOT), sd(fitted_VoiceVOT))
5.2.1.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationCons$fitted_VoiceVOT, geminationCons$singGem:geminationCons$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationCons$fitted_VoiceVOT and geminationCons$singGem:geminationCons$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   <2e-16              -               
geminate:voiceless 0.064               <2e-16          
geminate:voiced    <2e-16              <2e-16          
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    <2e-16            

P value adjustment method: fdr 

5.2.2 Proportion of voicing in the closure duration (% Voicing CD)

5.2.2.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.2.2.1.1 Optimal model (ML)
durationPropVoiceCD.xmdl.Full.M <- lmer(durationVoicedPerc~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.2.2.1.2 Optimal model (REML)
durationPropVoiceCD.xmdl.Full.R <- lmer(durationVoicedPerc~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.2.2.1.3 Null model (ML)
durationPropVoiceCD.xmdl.Null.M <- lmer(durationVoicedPerc~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.2.2.2 Results of our model

5.2.2.2.1 Model comparisons
anova(durationPropVoiceCD.xmdl.Null.M,durationPropVoiceCD.xmdl.Full.M)
Data: geminationCons
Models:
durationPropVoiceCD.xmdl.Null.M: durationVoicedPerc ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationPropVoiceCD.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationPropVoiceCD.xmdl.Full.M: durationVoicedPerc ~ voiced.unvoiced_c + singGem_c + sex_c + 
durationPropVoiceCD.xmdl.Full.M:     vowelLength_c + syllType_c + place_c + (voiced.unvoiced_c + 
durationPropVoiceCD.xmdl.Full.M:     singGem_c + vowelLength_c + syllType_c + place_c || speaker) + 
durationPropVoiceCD.xmdl.Full.M:     (1 | wordTarget)
                                Df   AIC   BIC  logLik deviance  Chisq
durationPropVoiceCD.xmdl.Null.M  9 15646 15696 -7814.1    15628       
durationPropVoiceCD.xmdl.Full.M 15 15544 15626 -7756.9    15514 114.35
                                Chi Df Pr(>Chisq)    
durationPropVoiceCD.xmdl.Null.M                      
durationPropVoiceCD.xmdl.Full.M      6  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.2.2.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationPropVoiceCD.xmdl.Full.R))

qqnorm(residuals(durationPropVoiceCD.xmdl.Full.R)); qqline(residuals(durationPropVoiceCD.xmdl.Full.R))

plot(fitted(durationPropVoiceCD.xmdl.Full.R),residuals(durationPropVoiceCD.xmdl.Full.R), cex = 4)

5.2.2.2.3 Summary of model
summary(durationPropVoiceCD.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: durationVoicedPerc ~ voiced.unvoiced_c + singGem_c + sex_c +  
    vowelLength_c + syllType_c + place_c + (voiced.unvoiced_c +  
    singGem_c + vowelLength_c + syllType_c + place_c || speaker) +  
    (1 | wordTarget)
   Data: geminationCons
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 15489.7

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.4488 -0.4823  0.0168  0.4620  3.9848 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        12.39    3.519  
 speaker    place_c            21.39    4.625  
 speaker.1  syllType_c         14.54    3.814  
 speaker.2  vowelLength_c      29.42    5.424  
 speaker.3  singGem_c          22.14    4.706  
 speaker.4  voiced.unvoiced_c 228.20   15.106  
 speaker.5  (Intercept)        83.35    9.130  
 Residual                     294.90   17.173  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)         58.368      2.261  23.234  25.816  < 2e-16 ***
voiced.unvoiced_c   63.207      3.626  21.977  17.430 2.36e-14 ***
singGem_c          -14.467      1.608  31.848  -8.995 2.96e-10 ***
sex_c               -9.774      4.229  17.935  -2.311  0.03291 *  
vowelLength_c       -5.577      1.736  29.878  -3.212  0.00315 ** 
syllType_c           1.693      1.795  38.294   0.943  0.35139    
place_c              5.561      2.020  35.168   2.753  0.00928 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.029                                   
singGem_c   -0.084 -0.010                            
sex_c       -0.004  0.001  0.001                     
vowlLngth_c  0.101 -0.039  0.044 -0.001              
syllType_c   0.226  0.014 -0.261 -0.002  0.177       
place_c      0.200  0.167 -0.008 -0.004 -0.037  0.025

5.2.2.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.2.2.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationCons$fitted_PropVoiceCD <- predict(lmer(durationVoicedPerc~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationCons,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.2.2.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggPropVoiceCDByVoice <- ggplot(geminationCons, aes(y=fitted_PropVoiceCD, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Voicing (%)"))) + labs(title = "CD") +
  coord_cartesian(ylim = c(-20,120)) +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationCons$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggPropVoiceCDByVoice

5.2.2.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.2.2.4.1 Descriptive statistics

The predicted means and SDs of the Proportion of voicing in the closure duration (% Voicing CD) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationCons %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_PropVoiceCD), sd(fitted_PropVoiceCD))
5.2.2.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationCons$fitted_PropVoiceCD, geminationCons$singGem:geminationCons$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationCons$fitted_PropVoiceCD and geminationCons$singGem:geminationCons$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   <2e-16              -               
geminate:voiceless <2e-16              <2e-16          
geminate:voiced    <2e-16              <2e-16          
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    <2e-16            

P value adjustment method: fdr 

5.2.3 Proportion of voicing in the Release Phase (% Voicing Rel)

5.2.3.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.2.3.1.1 Optimal model (ML)
durationPropVoiceRel.xmdl.Full.M <- lmer(durationVoicedPerc~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.2.3.1.2 Optimal model (REML)
durationPropVoiceRel.xmdl.Full.R <- lmer(durationVoicedPerc~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.2.3.1.3 Null model (ML)
durationPropVoiceRel.xmdl.Null.M <- lmer(durationVoicedPerc~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.2.3.2 Results of our model

5.2.3.2.1 Model comparisons
anova(durationPropVoiceRel.xmdl.Null.M,durationPropVoiceRel.xmdl.Full.M)
Data: geminationVOT
Models:
durationPropVoiceRel.xmdl.Null.M: durationVoicedPerc ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
durationPropVoiceRel.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
durationPropVoiceRel.xmdl.Full.M: durationVoicedPerc ~ voiced.unvoiced_c + singGem_c + sex_c + 
durationPropVoiceRel.xmdl.Full.M:     vowelLength_c + syllType_c + place_c + (voiced.unvoiced_c + 
durationPropVoiceRel.xmdl.Full.M:     singGem_c + vowelLength_c + syllType_c + place_c || speaker) + 
durationPropVoiceRel.xmdl.Full.M:     (1 | wordTarget)
                                 Df   AIC   BIC  logLik deviance
durationPropVoiceRel.xmdl.Null.M  9 17398 17447 -8689.8    17380
durationPropVoiceRel.xmdl.Full.M 15 17310 17392 -8639.8    17280
                                  Chisq Chi Df Pr(>Chisq)    
durationPropVoiceRel.xmdl.Null.M                             
durationPropVoiceRel.xmdl.Full.M 99.948      6  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.2.3.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(durationPropVoiceRel.xmdl.Full.R))

qqnorm(residuals(durationPropVoiceRel.xmdl.Full.R)); qqline(residuals(durationPropVoiceRel.xmdl.Full.R))

plot(fitted(durationPropVoiceRel.xmdl.Full.R),residuals(durationPropVoiceRel.xmdl.Full.R), cex = 4)

5.2.3.2.3 Summary of model
summary(durationPropVoiceRel.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: durationVoicedPerc ~ voiced.unvoiced_c + singGem_c + sex_c +  
    vowelLength_c + syllType_c + place_c + (voiced.unvoiced_c +  
    singGem_c + vowelLength_c + syllType_c + place_c || speaker) +  
    (1 | wordTarget)
   Data: geminationVOT
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 17250.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.3311 -0.4157 -0.0002  0.4979  2.9874 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        55.52    7.451  
 speaker    place_c             0.00    0.000  
 speaker.1  syllType_c         36.37    6.031  
 speaker.2  vowelLength_c      65.13    8.070  
 speaker.3  singGem_c         112.70   10.616  
 speaker.4  voiced.unvoiced_c 546.69   23.381  
 speaker.5  (Intercept)        66.85    8.176  
 Residual                     791.28   28.130  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)        38.6360     2.5703  41.8188  15.032  < 2e-16 ***
voiced.unvoiced_c  63.1715     5.7754  24.5602  10.938 6.30e-11 ***
singGem_c         -23.5631     3.2786  33.0544  -7.187 3.05e-08 ***
sex_c             -20.6862     3.9928  16.9392  -5.181 7.60e-05 ***
vowelLength_c      -7.8711     2.9311  39.7212  -2.685  0.01052 *  
syllType_c          8.7082     3.2335  50.8425   2.693  0.00956 ** 
place_c             0.7589     3.2208  91.9741   0.236  0.81425    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.056                                   
singGem_c   -0.127 -0.011                            
sex_c       -0.007  0.002  0.002                     
vowlLngth_c  0.182 -0.050  0.044 -0.002              
syllType_c   0.384  0.016 -0.245 -0.003  0.202       
place_c      0.379  0.227 -0.008  0.000 -0.046  0.030

5.2.3.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.2.3.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationVOT$fitted_PropVoiceRel <- predict(lmer(durationVoicedPerc~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.2.3.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggPropVoiceRelByVoice <- ggplot(geminationVOT, aes(y=fitted_PropVoiceRel, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Voicing (%)"))) + labs(title = "Rel") +
  coord_cartesian(ylim = c(-20,120)) +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationVOT$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggPropVoiceRelByVoice

5.2.3.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.2.3.4.1 Descriptive statistics

The predicted means and SDs of the Proportion of voicing in the Release Phase (% Voicing Rel) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationVOT %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_PropVoiceRel), sd(fitted_PropVoiceRel))
5.2.3.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationVOT$fitted_PropVoiceRel, geminationVOT$singGem:geminationVOT$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationVOT$fitted_PropVoiceRel and geminationVOT$singGem:geminationVOT$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   < 2e-16             -               
geminate:voiceless 3.7e-12             < 2e-16         
geminate:voiced    < 2e-16             < 2e-16         
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    < 2e-16           

P value adjustment method: fdr 

5.3 Intensity (dB)

Within Intensity, we have computed the intensity at four locations: At the Offset of the preceding vowel (V1Offset), at the onset of the Release Phase (RelOnset), at the Offset of the Release Phase (RelOffset) and at the Onset of the following vowel (V2Offset).

5.3.1 At the offset of the preceding vowel

5.3.1.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.3.1.1.1 Optimal model (ML)
intensityV1Offset.xmdl.Full.M <- lmer(intensityOffset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.3.1.1.2 Optimal model (REML)
intensityV1Offset.xmdl.Full.R <- lmer(intensityOffset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.3.1.1.3 Null model (ML)
intensityV1Offset.xmdl.Null.M <- lmer(intensityOffset~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.3.1.2 Results of our model

5.3.1.2.1 Model comparisons
anova(intensityV1Offset.xmdl.Null.M,intensityV1Offset.xmdl.Full.M)
Data: geminationV1
Models:
intensityV1Offset.xmdl.Null.M: intensityOffset ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
intensityV1Offset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
intensityV1Offset.xmdl.Full.M: intensityOffset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
intensityV1Offset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
intensityV1Offset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                              Df    AIC  BIC  logLik deviance  Chisq
intensityV1Offset.xmdl.Null.M  9 9091.6 9141 -4536.8   9073.6       
intensityV1Offset.xmdl.Full.M 15 8978.6 9061 -4474.3   8948.6 124.98
                              Chi Df Pr(>Chisq)    
intensityV1Offset.xmdl.Null.M                      
intensityV1Offset.xmdl.Full.M      6  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.3.1.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(intensityV1Offset.xmdl.Full.R))

qqnorm(residuals(intensityV1Offset.xmdl.Full.R)); qqline(residuals(intensityV1Offset.xmdl.Full.R))

plot(fitted(intensityV1Offset.xmdl.Full.R),residuals(intensityV1Offset.xmdl.Full.R), cex = 4)

5.3.1.2.3 Summary of model
summary(intensityV1Offset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
intensityOffset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV1
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 8945.9

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.3661 -0.6119 -0.0346  0.5985  4.8353 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        0.9241  0.9613  
 speaker    place_c            0.1154  0.3398  
 speaker.1  syllType_c         1.1642  1.0790  
 speaker.2  vowelLength_c      0.7610  0.8724  
 speaker.3  singGem_c          0.0000  0.0000  
 speaker.4  voiced.unvoiced_c  0.8781  0.9371  
 speaker.5  (Intercept)       16.8285  4.1023  
 Residual                      7.3419  2.7096  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        67.3528     0.9409 19.5721  71.585  < 2e-16 ***
voiced.unvoiced_c   2.3547     0.3530 53.0072   6.671 1.52e-08 ***
singGem_c           0.1617     0.2613 92.9803   0.619  0.53760    
sex_c              -5.6355     1.8425 18.0004  -3.059  0.00676 ** 
vowelLength_c      -1.5195     0.3309 50.8626  -4.592 2.91e-05 ***
syllType_c         -3.7793     0.4173 56.6523  -9.057 1.31e-12 ***
place_c            -1.8546     0.3808 65.8930  -4.870 7.30e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.034                                   
singGem_c   -0.059 -0.030                            
sex_c        0.000  0.001  0.000                     
vowlLngth_c  0.059 -0.097  0.065  0.000              
syllType_c   0.109  0.027 -0.317 -0.001  0.186       
place_c      0.118  0.421 -0.012  0.000 -0.046  0.026

5.3.1.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.3.1.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV1$fitted_V1IntensityOffset <- predict(lmer(intensityOffset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.3.1.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggIntensityV1OffsetByVoice <- ggplot(geminationV1, aes(y=fitted_V1IntensityOffset, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Intensity (dB)"))) + labs(title = "V1 Offset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(50,80)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV1$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggIntensityV1OffsetByVoice

5.3.1.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.3.1.4.1 Descriptive statistics

The predicted means and SDs of the Intensity at the Offset of the preceding vowel (V1Offset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV1 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_V1IntensityOffset), sd(fitted_V1IntensityOffset))
5.3.1.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV1$fitted_V1IntensityOffset, geminationV1$singGem:geminationV1$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV1$fitted_V1IntensityOffset and geminationV1$singGem:geminationV1$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   5.5e-13             -               
geminate:voiceless 0.0013              < 2e-16         
geminate:voiced    7.6e-10             0.1047          
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    < 2e-16           

P value adjustment method: fdr 

5.3.2 At the onset of the Release phase

5.3.2.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.3.2.1.1 Optimal model (ML)
intensityRelOnset.xmdl.Full.M <- lmer(intensityOnset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.3.2.1.2 Optimal model (REML)
intensityRelOnset.xmdl.Full.R <- lmer(intensityOnset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.3.2.1.3 Null model (ML)
intensityRelOnset.xmdl.Null.M <- lmer(intensityOnset~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.3.2.2 Results of our model

5.3.2.2.1 Model comparisons
anova(intensityRelOnset.xmdl.Null.M,intensityRelOnset.xmdl.Full.M)
Data: geminationVOT
Models:
intensityRelOnset.xmdl.Null.M: intensityOnset ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
intensityRelOnset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
intensityRelOnset.xmdl.Full.M: intensityOnset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
intensityRelOnset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
intensityRelOnset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                              Df    AIC    BIC  logLik deviance  Chisq
intensityRelOnset.xmdl.Null.M  9 9512.7 9562.1 -4747.3   9494.7       
intensityRelOnset.xmdl.Full.M 15 9440.9 9523.3 -4705.5   9410.9 83.755
                              Chi Df Pr(>Chisq)    
intensityRelOnset.xmdl.Null.M                      
intensityRelOnset.xmdl.Full.M      6  5.977e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.3.2.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(intensityRelOnset.xmdl.Full.R))

qqnorm(residuals(intensityRelOnset.xmdl.Full.R)); qqline(residuals(intensityRelOnset.xmdl.Full.R))

plot(fitted(intensityRelOnset.xmdl.Full.R),residuals(intensityRelOnset.xmdl.Full.R), cex = 4)

5.3.2.2.3 Summary of model
summary(intensityRelOnset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
intensityOnset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationVOT
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 9403.7

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-5.2016 -0.5727  0.0334  0.6051  3.6262 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        2.0187  1.4208  
 speaker    place_c            3.6786  1.9180  
 speaker.1  syllType_c         1.8039  1.3431  
 speaker.2  vowelLength_c      0.8808  0.9385  
 speaker.3  singGem_c          1.1726  1.0829  
 speaker.4  voiced.unvoiced_c  9.9030  3.1469  
 speaker.5  (Intercept)       12.5941  3.5488  
 Residual                      8.8587  2.9764  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)       59.33375    0.84419 22.02045  70.285  < 2e-16 ***
voiced.unvoiced_c  5.43892    0.80469 28.71351   6.759 2.14e-07 ***
singGem_c         -2.34891    0.43301 65.32732  -5.425 9.08e-07 ***
sex_c             -3.79889    1.60302 17.95114  -2.370  0.02921 *  
vowelLength_c     -2.59166    0.42277 71.64730  -6.130 4.30e-08 ***
syllType_c         0.09273    0.55597 67.37955   0.167  0.86803    
place_c            1.89781    0.66917 55.03426   2.836  0.00638 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.031                                   
singGem_c   -0.075 -0.015                            
sex_c       -0.001  0.000  0.001                     
vowlLngth_c  0.097 -0.063  0.058  0.000              
syllType_c   0.173  0.016 -0.270 -0.001  0.207       
place_c      0.141  0.199 -0.008 -0.002 -0.039  0.020

5.3.2.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.3.2.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationVOT$fitted_RelIntensityOnset <- predict(lmer(intensityOnset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.3.2.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggIntensityRelOnsetByVoice <- ggplot(geminationVOT, aes(y=fitted_RelIntensityOnset, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Intensity (dB)"))) + labs(title = "Rel Onset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(50,80)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationVOT$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggIntensityRelOnsetByVoice

5.3.2.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.3.2.4.1 Descriptive statistics

The predicted means and SDs of the Intensity at the Onset of the Release phase (RelOnset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationVOT %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_RelIntensityOnset), sd(fitted_RelIntensityOnset))
5.3.2.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationVOT$fitted_RelIntensityOnset, geminationVOT$singGem:geminationVOT$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationVOT$fitted_RelIntensityOnset and geminationVOT$singGem:geminationVOT$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   < 2e-16             -               
geminate:voiceless 0.078               < 2e-16         
geminate:voiced    < 2e-16             9.7e-16         
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    < 2e-16           

P value adjustment method: fdr 

5.3.3 At the offset of the Release phase

5.3.3.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.3.3.1.1 Optimal model (ML)
intensityRelOffset.xmdl.Full.M <- lmer(intensityOffset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.3.3.1.2 Optimal model (REML)
intensityRelOffset.xmdl.Full.R <- lmer(intensityOffset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.3.3.1.3 Null model (ML)
intensityRelOffset.xmdl.Null.M <- lmer(intensityOffset~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.3.3.2 Results of our model

5.3.3.2.1 Model comparisons
anova(intensityRelOffset.xmdl.Null.M,intensityRelOffset.xmdl.Full.M)
Data: geminationVOT
Models:
intensityRelOffset.xmdl.Null.M: intensityOffset ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
intensityRelOffset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
intensityRelOffset.xmdl.Full.M: intensityOffset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
intensityRelOffset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
intensityRelOffset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                               Df    AIC    BIC  logLik deviance Chisq
intensityRelOffset.xmdl.Null.M  9 8651.3 8700.7 -4316.6   8633.3      
intensityRelOffset.xmdl.Full.M 15 8566.1 8648.4 -4268.0   8536.1  97.2
                               Chi Df Pr(>Chisq)    
intensityRelOffset.xmdl.Null.M                      
intensityRelOffset.xmdl.Full.M      6  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.3.3.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(intensityRelOffset.xmdl.Full.R))

qqnorm(residuals(intensityRelOffset.xmdl.Full.R)); qqline(residuals(intensityRelOffset.xmdl.Full.R))

plot(fitted(intensityRelOffset.xmdl.Full.R),residuals(intensityRelOffset.xmdl.Full.R), cex = 4)

5.3.3.2.3 Summary of model
summary(intensityRelOffset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
intensityOffset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationVOT
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 8534.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.4273 -0.6503 -0.0024  0.6486  4.5428 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        0.6806  0.8250  
 speaker    place_c            0.4863  0.6974  
 speaker.1  syllType_c         1.2283  1.1083  
 speaker.2  vowelLength_c      0.3749  0.6123  
 speaker.3  singGem_c          0.2322  0.4819  
 speaker.4  voiced.unvoiced_c  1.0280  1.0139  
 speaker.5  (Intercept)       16.2430  4.0303  
 Residual                      5.7548  2.3989  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        64.5944     0.9193 19.1496  70.265  < 2e-16 ***
voiced.unvoiced_c   1.2817     0.3347 45.3702   3.830 0.000391 ***
singGem_c          -0.7361     0.2509 57.9888  -2.933 0.004794 ** 
sex_c              -4.3568     1.8100 17.9928  -2.407 0.027037 *  
vowelLength_c      -2.4445     0.2691 55.8602  -9.085 1.34e-12 ***
syllType_c          0.8141     0.3854 47.0427   2.113 0.039969 *  
place_c            -1.6463     0.3594 59.2184  -4.581 2.43e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.027                                   
singGem_c   -0.047 -0.025                            
sex_c       -0.001  0.000  0.001                     
vowlLngth_c  0.056 -0.094  0.063  0.000              
syllType_c   0.091  0.023 -0.269 -0.001  0.186       
place_c      0.096  0.354 -0.010 -0.001 -0.045  0.022

5.3.3.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.3.3.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationVOT$fitted_RelIntensityOffset <- predict(lmer(intensityOffset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationVOT,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.3.3.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggIntensityRelOffsetByVoice <- ggplot(geminationVOT, aes(y=fitted_RelIntensityOffset, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Intensity (dB)"))) + labs(title = "Rel Offset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(50,80)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationVOT$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggIntensityRelOffsetByVoice

5.3.3.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.3.3.4.1 Descriptive statistics

The predicted means and SDs of the Intensity at the Offset of the Release phase (RelOffset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationVOT %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_RelIntensityOffset), sd(fitted_RelIntensityOffset))
5.3.3.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationVOT$fitted_RelIntensityOffset, geminationVOT$singGem:geminationVOT$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationVOT$fitted_RelIntensityOffset and geminationVOT$singGem:geminationVOT$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   2.7e-08             -               
geminate:voiceless 0.12                2.0e-05         
geminate:voiced    2.7e-08             0.73            
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    2.2e-05           

P value adjustment method: fdr 

5.3.4 At the onset of the following vowel

5.3.4.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.3.4.1.1 Optimal model (ML)
intensityV2Onset.xmdl.Full.M <- lmer(intensityOnset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.3.4.1.2 Optimal model (REML)
intensityV2Onset.xmdl.Full.R <- lmer(intensityOnset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.3.4.1.3 Null model (ML)
intensityV2Onset.xmdl.Null.M <- lmer(intensityOnset~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.3.4.2 Results of our model

5.3.4.2.1 Model comparisons
anova(intensityV2Onset.xmdl.Null.M,intensityV2Onset.xmdl.Full.M)
Data: geminationV2
Models:
intensityV2Onset.xmdl.Null.M: intensityOnset ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
intensityV2Onset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
intensityV2Onset.xmdl.Full.M: intensityOnset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
intensityV2Onset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
intensityV2Onset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                             Df    AIC    BIC  logLik deviance  Chisq
intensityV2Onset.xmdl.Null.M  9 8549.7 8599.1 -4265.9   8531.7       
intensityV2Onset.xmdl.Full.M 15 8468.1 8550.5 -4219.1   8438.1 93.575
                             Chi Df Pr(>Chisq)    
intensityV2Onset.xmdl.Null.M                      
intensityV2Onset.xmdl.Full.M      6  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.3.4.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(intensityV2Onset.xmdl.Full.R))

qqnorm(residuals(intensityV2Onset.xmdl.Full.R)); qqline(residuals(intensityV2Onset.xmdl.Full.R))

plot(fitted(intensityV2Onset.xmdl.Full.R),residuals(intensityV2Onset.xmdl.Full.R), cex = 4)

5.3.4.2.3 Summary of model
summary(intensityV2Onset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
intensityOnset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV2
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 8435.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.4796 -0.6459 -0.0052  0.6282  3.8583 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        0.6972  0.8350  
 speaker    place_c            0.5136  0.7166  
 speaker.1  syllType_c         1.4878  1.2198  
 speaker.2  vowelLength_c      0.1494  0.3866  
 speaker.3  singGem_c          0.3525  0.5937  
 speaker.4  voiced.unvoiced_c  1.6696  1.2921  
 speaker.5  (Intercept)       17.4143  4.1730  
 Residual                      5.3894  2.3215  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        67.1891     0.9506 19.0806  70.684  < 2e-16 ***
voiced.unvoiced_c   0.7896     0.3793 37.7429   2.082 0.044213 *  
singGem_c          -0.4436     0.2623 56.6391  -1.691 0.096298 .  
sex_c              -6.0558     1.8732 17.9905  -3.233 0.004619 ** 
vowelLength_c      -2.4906     0.2468 65.2472 -10.093  5.9e-15 ***
syllType_c          0.9921     0.4015 44.9078   2.471 0.017328 *  
place_c            -1.4757     0.3607 59.4414  -4.091 0.000131 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.023                                   
singGem_c   -0.043 -0.021                            
sex_c        0.000  0.000  0.000                     
vowlLngth_c  0.058 -0.090  0.065  0.000              
syllType_c   0.084  0.019 -0.246 -0.001  0.194       
place_c      0.092  0.310 -0.010 -0.001 -0.049  0.021

5.3.4.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.3.4.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV2$fitted_V2IntensityOnset <- predict(lmer(intensityOnset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.3.4.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggIntensityV2OnsetByVoice <- ggplot(geminationV2, aes(y=fitted_V2IntensityOnset, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("Intensity (dB)"))) + labs(title = "V2 Onset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(50,80)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV2$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggIntensityV2OnsetByVoice

5.3.4.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.3.4.4.1 Descriptive statistics

The predicted means and SDs of the Intensity at the Onset of the following vowel (V2Onset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV2 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_V2IntensityOnset), sd(fitted_V2IntensityOnset))
5.3.4.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV2$fitted_V2IntensityOnset, geminationV2$singGem:geminationV2$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV2$fitted_V2IntensityOnset and geminationV2$singGem:geminationV2$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   0.0031              -               
geminate:voiceless 0.1039              0.1504          
geminate:voiced    3e-05               0.2000          
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    0.0087            

P value adjustment method: fdr 

5.4 Fundamental frequency (Hz)

Within the fundamental frequency f0, we have computed f0 at two locations: At the Offset of the preceding vowel (V1Offset) and at the Onset of the following vowel (V2Offset).

5.4.1 At the offset of the preceding vowel

5.4.1.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.4.1.1.1 Optimal model (ML)
f0V1Offset.xmdl.Full.M <- lmer(f0Offset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.4.1.1.2 Optimal model (REML)
f0V1Offset.xmdl.Full.R <- lmer(f0Offset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.4.1.1.3 Null model (ML)
f0V1Offset.xmdl.Null.M <- lmer(f0Offset~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.4.1.2 Results of our model

5.4.1.2.1 Model comparisons
anova(f0V1Offset.xmdl.Null.M,f0V1Offset.xmdl.Full.M)
Data: geminationV1
Models:
f0V1Offset.xmdl.Null.M: f0Offset ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
f0V1Offset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
f0V1Offset.xmdl.Full.M: f0Offset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
f0V1Offset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
f0V1Offset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                       Df   AIC   BIC  logLik deviance  Chisq Chi Df
f0V1Offset.xmdl.Null.M  9 14274 14324 -7128.1    14256              
f0V1Offset.xmdl.Full.M 15 14173 14256 -7071.7    14143 112.75      6
                       Pr(>Chisq)    
f0V1Offset.xmdl.Null.M               
f0V1Offset.xmdl.Full.M  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.4.1.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(f0V1Offset.xmdl.Full.R))

qqnorm(residuals(f0V1Offset.xmdl.Full.R)); qqline(residuals(f0V1Offset.xmdl.Full.R))

plot(fitted(f0V1Offset.xmdl.Full.R),residuals(f0V1Offset.xmdl.Full.R), cex = 4)

5.4.1.2.3 Summary of model
summary(f0V1Offset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
f0Offset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV1
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 14118.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.5284 -0.4831 -0.0411  0.5022  5.6981 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        13.704   3.702  
 speaker    place_c             0.000   0.000  
 speaker.1  syllType_c         72.720   8.528  
 speaker.2  vowelLength_c     105.182  10.256  
 speaker.3  singGem_c           5.242   2.290  
 speaker.4  voiced.unvoiced_c  14.319   3.784  
 speaker.5  (Intercept)       435.365  20.865  
 Residual                     128.927  11.355  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        161.417      4.739  18.894  34.064  < 2e-16 ***
voiced.unvoiced_c   -4.657      1.407  55.014  -3.310  0.00165 ** 
singGem_c            4.557      1.155  54.227   3.946  0.00023 ***
sex_c               89.850      9.362  17.997   9.597 1.68e-08 ***
vowelLength_c      -12.207      2.526  24.199  -4.833 6.22e-05 ***
syllType_c         -21.748      2.335  30.551  -9.313 1.96e-10 ***
place_c              0.401      1.476  91.648   0.272  0.78649    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.026                                   
singGem_c   -0.041 -0.027                            
sex_c        0.000  0.001  0.001                     
vowlLngth_c  0.024 -0.050  0.030  0.000              
syllType_c   0.061  0.019 -0.201 -0.001  0.068       
place_c      0.094  0.427 -0.011  0.000 -0.024  0.019

5.4.1.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.4.1.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV1$fitted_V1F0Offset <- predict(lmer(f0Offset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.4.1.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggF0V1OffsetByVoice <- ggplot(geminationV1, aes(y=fitted_V1F0Offset, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("F0 (Hz)"))) + labs(title = "V1 Offset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(80,300)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV1$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggF0V1OffsetByVoice

5.4.1.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.4.1.4.1 Descriptive statistics

The predicted means and SDs of the F0 at the Offset of the preceding vowel (V1Offset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV1 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_V1F0Offset), sd(fitted_V1F0Offset))
5.4.1.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV1$fitted_V1F0Offset, geminationV1$singGem:geminationV1$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV1$fitted_V1F0Offset and geminationV1$singGem:geminationV1$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   0.06                -               
geminate:voiceless 0.44                0.20            
geminate:voiced    0.06                0.94            
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    0.20              

P value adjustment method: fdr 

5.4.2 At the onset of the following vowel

5.4.2.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.4.2.1.1 Optimal model (ML)
f0V2Onset.xmdl.Full.M <- lmer(f0Onset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.4.2.1.2 Optimal model (REML)
f0V2Onset.xmdl.Full.R <- lmer(f0Onset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.4.2.1.3 Null model (ML)
f0V2Onset.xmdl.Null.M <- lmer(f0Onset~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.4.2.2 Results of our model

5.4.2.2.1 Model comparisons
anova(f0V2Onset.xmdl.Null.M,f0V2Onset.xmdl.Full.M)
Data: geminationV2
Models:
f0V2Onset.xmdl.Null.M: f0Onset ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
f0V2Onset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
f0V2Onset.xmdl.Full.M: f0Onset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
f0V2Onset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
f0V2Onset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                      Df   AIC   BIC  logLik deviance  Chisq Chi Df
f0V2Onset.xmdl.Null.M  9 14956 15006 -7469.2    14938              
f0V2Onset.xmdl.Full.M 15 14898 14980 -7433.8    14868 70.926      6
                      Pr(>Chisq)    
f0V2Onset.xmdl.Null.M               
f0V2Onset.xmdl.Full.M   2.64e-13 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.4.2.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(f0V2Onset.xmdl.Full.R))

qqnorm(residuals(f0V2Onset.xmdl.Full.R)); qqline(residuals(f0V2Onset.xmdl.Full.R))

plot(fitted(f0V2Onset.xmdl.Full.R),residuals(f0V2Onset.xmdl.Full.R), cex = 4)

5.4.2.2.3 Summary of model
summary(f0V2Onset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
f0Onset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV2
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 14840.7

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.8461 -0.5214 -0.0433  0.4939  6.3033 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)        19.61    4.429  
 speaker    place_c            14.50    3.807  
 speaker.1  syllType_c        206.14   14.358  
 speaker.2  vowelLength_c      28.80    5.367  
 speaker.3  singGem_c          16.04    4.005  
 speaker.4  voiced.unvoiced_c  28.51    5.339  
 speaker.5  (Intercept)       364.99   19.105  
 Residual                     194.22   13.936  
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        166.589      4.388  19.466  37.968  < 2e-16 ***
voiced.unvoiced_c   -4.001      1.807  44.099  -2.213 0.032089 *  
singGem_c           -3.419      1.538  46.068  -2.223 0.031150 *  
sex_c               86.824      8.605  18.005  10.090 7.75e-09 ***
vowelLength_c       -3.551      1.753  39.840  -2.026 0.049511 *  
syllType_c          15.306      3.599  25.112   4.252 0.000257 ***
place_c              3.116      1.977  57.301   1.576 0.120614    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.032                                   
singGem_c   -0.049 -0.023                            
sex_c       -0.001  0.000  0.001                     
vowlLngth_c  0.054 -0.081  0.048 -0.001              
syllType_c   0.062  0.014 -0.143 -0.001  0.093       
place_c      0.111  0.362 -0.009 -0.001 -0.039  0.013

5.4.2.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.4.2.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV2$fitted_V2F0Onset <- predict(lmer(f0Onset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.4.2.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggF0V2OnsetByVoice <- ggplot(geminationV2, aes(y=fitted_V2F0Onset, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("F0 (Hz)"))) + labs(title = "V2 Onset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(80,300)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV2$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggF0V2OnsetByVoice

5.4.2.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.4.2.4.1 Descriptive statistics

The predicted means and SDs of the F0 at the Onset of the following vowel (V2Onset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV2 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_V2F0Onset), sd(fitted_V2F0Onset))
5.4.2.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV2$fitted_V2F0Onset, geminationV2$singGem:geminationV2$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV2$fitted_V2F0Onset and geminationV2$singGem:geminationV2$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   0.0741              -               
geminate:voiceless 0.3912              0.0053          
geminate:voiced    0.1380              0.5774          
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    0.0090            

P value adjustment method: fdr 

5.5 F1 frequency (Hz)

Within the first formant frequency (F1), we have computed F1 at two locations: At the Offset of the preceding vowel (V1Offset) and at the Onset of the following vowel (V2Offset).

5.5.1 At the offset of the preceding vowel

5.5.1.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.5.1.1.1 Optimal model (ML)
f1V1Offset.xmdl.Full.M <- lmer(f1Offset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.5.1.1.2 Optimal model (REML)
f1V1Offset.xmdl.Full.R <- lmer(f1Offset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.5.1.1.3 Null model (ML)
f1V1Offset.xmdl.Null.M <- lmer(f1Offset~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.5.1.2 Results of our model

5.5.1.2.1 Model comparisons
anova(f1V1Offset.xmdl.Null.M,f1V1Offset.xmdl.Full.M)
Data: geminationV1
Models:
f1V1Offset.xmdl.Null.M: f1Offset ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
f1V1Offset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
f1V1Offset.xmdl.Full.M: f1Offset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
f1V1Offset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
f1V1Offset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                       Df   AIC   BIC logLik deviance Chisq Chi Df
f1V1Offset.xmdl.Null.M  9 21072 21122 -10527    21054             
f1V1Offset.xmdl.Full.M 15 21029 21111 -10500    20999 55.37      6
                       Pr(>Chisq)    
f1V1Offset.xmdl.Null.M               
f1V1Offset.xmdl.Full.M  3.902e-10 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.5.1.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(f1V1Offset.xmdl.Full.R))

qqnorm(residuals(f1V1Offset.xmdl.Full.R)); qqline(residuals(f1V1Offset.xmdl.Full.R))

plot(fitted(f1V1Offset.xmdl.Full.R),residuals(f1V1Offset.xmdl.Full.R), cex = 4)

5.5.1.2.3 Summary of model
summary(f1V1Offset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
f1Offset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV1
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 20948.7

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.8871 -0.5834 -0.0374  0.4792  6.0431 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)       2345.9   48.43   
 speaker    place_c            656.3   25.62   
 speaker.1  syllType_c        2997.7   54.75   
 speaker.2  vowelLength_c      874.6   29.57   
 speaker.3  singGem_c            0.0    0.00   
 speaker.4  voiced.unvoiced_c 1266.7   35.59   
 speaker.5  (Intercept)       1678.2   40.97   
 Residual                     5780.7   76.03   
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        500.385     13.113  54.128  38.159  < 2e-16 ***
voiced.unvoiced_c  -57.289     15.005  81.271  -3.818 0.000262 ***
singGem_c           -1.322     11.689  92.445  -0.113 0.910211    
sex_c               70.557     19.127  18.080   3.689 0.001669 ** 
vowelLength_c      -52.440     13.664  84.584  -3.838 0.000239 ***
syllType_c         -85.399     19.557  68.263  -4.367 4.39e-05 ***
place_c            -64.575     17.674  91.021  -3.654 0.000432 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.114                                   
singGem_c   -0.190 -0.031                            
sex_c       -0.004  0.000  0.001                     
vowlLngth_c  0.205 -0.111  0.070 -0.001              
syllType_c   0.337  0.026 -0.301 -0.002  0.194       
place_c      0.364  0.429 -0.012 -0.003 -0.048  0.023

5.5.1.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.5.1.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV1$fitted_V1F1Offset <- predict(lmer(f1Offset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.5.1.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggF1V1OffsetByVoice <- ggplot(geminationV1, aes(y=fitted_V1F1Offset, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("F1 (Hz)"))) + labs(title = "V1 Offset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(300,900)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV1$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggF1V1OffsetByVoice

5.5.1.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.5.1.4.1 Descriptive statistics

The predicted means and SDs of the F1 at the Offset of the preceding vowel (V1Offset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV1 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_V1F1Offset), sd(fitted_V1F1Offset))
5.5.1.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV1$fitted_V1F1Offset, geminationV1$singGem:geminationV1$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV1$fitted_V1F1Offset and geminationV1$singGem:geminationV1$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   5e-09               -               
geminate:voiceless 0.00055             0.00991         
geminate:voiced    < 2e-16             0.00202         
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    2e-08             

P value adjustment method: fdr 

5.5.2 At the onset of the following vowel

5.5.2.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.5.2.1.1 Optimal model (ML)
f1V2Onset.xmdl.Full.M <- lmer(f1Onset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.5.2.1.2 Optimal model (REML)
f1V2Onset.xmdl.Full.R <- lmer(f1Onset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.5.2.1.3 Null model (ML)
f1V2Onset.xmdl.Null.M <- lmer(f1Onset~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.5.2.2 Results of our model

5.5.2.2.1 Model comparisons
anova(f1V2Onset.xmdl.Null.M,f1V2Onset.xmdl.Full.M)
Data: geminationV2
Models:
f1V2Onset.xmdl.Null.M: f1Onset ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
f1V2Onset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
f1V2Onset.xmdl.Full.M: f1Onset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
f1V2Onset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
f1V2Onset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                      Df   AIC   BIC logLik deviance  Chisq Chi Df
f1V2Onset.xmdl.Null.M  9 20131 20180 -10056    20113              
f1V2Onset.xmdl.Full.M 15 20044 20127 -10007    20014 98.677      6
                      Pr(>Chisq)    
f1V2Onset.xmdl.Null.M               
f1V2Onset.xmdl.Full.M  < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.5.2.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(f1V2Onset.xmdl.Full.R))

qqnorm(residuals(f1V2Onset.xmdl.Full.R)); qqline(residuals(f1V2Onset.xmdl.Full.R))

plot(fitted(f1V2Onset.xmdl.Full.R),residuals(f1V2Onset.xmdl.Full.R), cex = 4)

5.5.2.2.3 Summary of model
summary(f1V2Onset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
f1Onset ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV2
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 19968.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.7533 -0.5218 -0.0820  0.4367  9.4623 

Random effects:
 Groups     Name              Variance Std.Dev.
 wordTarget (Intercept)       1183.657 34.40   
 speaker    place_c            923.620 30.39   
 speaker.1  syllType_c         357.077 18.90   
 speaker.2  vowelLength_c      403.158 20.08   
 speaker.3  singGem_c            3.763  1.94   
 speaker.4  voiced.unvoiced_c  641.256 25.32   
 speaker.5  (Intercept)       1319.244 36.32   
 Residual                     3383.564 58.17   
Number of obs: 1793, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                  Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)        451.219     10.548  41.734  42.778  < 2e-16 ***
voiced.unvoiced_c  -48.764     10.737  78.891  -4.542 1.98e-05 ***
singGem_c          -13.838      8.394  85.723  -1.649 0.102905    
sex_c               66.262     16.766  17.982   3.952 0.000936 ***
vowelLength_c      -82.624      9.680  82.697  -8.536 5.69e-13 ***
syllType_c         -55.577     11.723  91.512  -4.741 7.78e-06 ***
place_c            -61.507     13.788  82.751  -4.461 2.55e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.102                                   
singGem_c   -0.169 -0.031                            
sex_c       -0.004  0.000  0.001                     
vowlLngth_c  0.185 -0.112  0.071  0.000              
syllType_c   0.359  0.031 -0.359 -0.002  0.234       
place_c      0.299  0.395 -0.011 -0.003 -0.045  0.025

5.5.2.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.5.2.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV2$fitted_V2F1Onset <- predict(lmer(f1Onset~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.5.2.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggF1V2OnsetByVoice <- ggplot(geminationV2, aes(y=fitted_V2F1Onset, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste("F1 (Hz)"))) + labs(title = "V2 Onset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(300,900)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV2$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggF1V2OnsetByVoice

5.5.2.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.5.2.4.1 Descriptive statistics

The predicted means and SDs of the F1 at the Onset of the following vowel (V2Onset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV2 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_V2F1Onset), sd(fitted_V2F1Onset))
5.5.2.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV2$fitted_V2F1Onset, geminationV2$singGem:geminationV2$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV2$fitted_V2F1Onset and geminationV2$singGem:geminationV2$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   3.5e-11             -               
geminate:voiceless 0.00103             0.00038         
geminate:voiced    < 2e-16             0.01329         
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    9.5e-10           

P value adjustment method: fdr 

5.6 H1*-H2* (dB)

Within the differences between the normalised first and second harmonics to cue voice quality (H1*-H2*), we have computed H1*-H2* at two locations: At the Offset of the preceding vowel (V1Offset) and at the Onset of the following vowel (V2Offset).

5.6.1 At the offset of the preceding vowel

5.6.1.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.6.1.1.1 Optimal model (ML)
h1mnh2V1Offset.xmdl.Full.M <- lmer(h1mnh2OffsetNorm~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.6.1.1.2 Optimal model (REML)
h1mnh2V1Offset.xmdl.Full.R <- lmer(h1mnh2OffsetNorm~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.6.1.1.3 Null model (ML)
h1mnh2V1Offset.xmdl.Null.M <- lmer(h1mnh2OffsetNorm~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.6.1.2 Results of our model

5.6.1.2.1 Model comparisons
anova(h1mnh2V1Offset.xmdl.Null.M,h1mnh2V1Offset.xmdl.Full.M)
Data: geminationV1
Models:
h1mnh2V1Offset.xmdl.Null.M: h1mnh2OffsetNorm ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
h1mnh2V1Offset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
h1mnh2V1Offset.xmdl.Full.M: h1mnh2OffsetNorm ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
h1mnh2V1Offset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
h1mnh2V1Offset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                           Df    AIC    BIC  logLik deviance  Chisq
h1mnh2V1Offset.xmdl.Null.M  9 9135.3 9183.5 -4558.7   9117.3       
h1mnh2V1Offset.xmdl.Full.M 15 9143.1 9223.4 -4556.5   9113.1 4.2286
                           Chi Df Pr(>Chisq)
h1mnh2V1Offset.xmdl.Null.M                  
h1mnh2V1Offset.xmdl.Full.M      6     0.6458

As can be seen, our optimal model did not improve the model fit. However, we will still use the optimal model to allow for comparison with the other models. This non-significant effect is indicative of a non-association between H1*-H2* and the predictors.

5.6.1.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(h1mnh2V1Offset.xmdl.Full.R))

qqnorm(residuals(h1mnh2V1Offset.xmdl.Full.R)); qqline(residuals(h1mnh2V1Offset.xmdl.Full.R))

plot(fitted(h1mnh2V1Offset.xmdl.Full.R),residuals(h1mnh2V1Offset.xmdl.Full.R), cex = 4)

5.6.1.2.3 Summary of model
summary(h1mnh2V1Offset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
h1mnh2OffsetNorm ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV1
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 9113

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.0232 -0.6442 -0.1055  0.5667  4.2980 

Random effects:
 Groups     Name              Variance  Std.Dev. 
 wordTarget (Intercept)       0.000e+00 0.000e+00
 speaker    place_c           2.997e-15 5.474e-08
 speaker.1  syllType_c        0.000e+00 0.000e+00
 speaker.2  vowelLength_c     7.493e-02 2.737e-01
 speaker.3  singGem_c         0.000e+00 0.000e+00
 speaker.4  voiced.unvoiced_c 1.638e-01 4.047e-01
 speaker.5  (Intercept)       1.194e+01 3.456e+00
 Residual                     1.872e+01 4.326e+00
Number of obs: 1567, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                    Estimate Std. Error         df t value Pr(>|t|)  
(Intercept)       -2.039e+00  7.979e-01  1.962e+01  -2.555   0.0191 *
voiced.unvoiced_c  5.505e-02  2.840e-01  3.357e+01   0.194   0.8475  
singGem_c         -3.431e-03  2.452e-01  1.515e+03  -0.014   0.9888  
sex_c              1.829e+00  1.561e+00  1.798e+01   1.172   0.2566  
vowelLength_c      8.373e-02  2.593e-01  2.352e+01   0.323   0.7496  
syllType_c         3.428e-01  3.223e-01  1.514e+03   1.064   0.2877  
place_c            4.023e-01  3.550e-01  1.521e+03   1.133   0.2573  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.041                                   
singGem_c   -0.064 -0.026                            
sex_c       -0.001  0.003 -0.001                     
vowlLngth_c  0.080 -0.150  0.074 -0.001              
syllType_c   0.150  0.034 -0.392 -0.001  0.264       
place_c      0.134  0.509 -0.010  0.001 -0.065  0.030

5.6.1.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.6.1.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV1$fitted_V1h1mnh2OffsetNorm <- predict(lmer(h1mnh2OffsetNorm~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV1,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.6.1.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggh1mnh2V1OffsetByVoice <- ggplot(geminationV1, aes(y=fitted_V1h1mnh2OffsetNorm, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste(italic("H"),"1*-",italic("H"),"2* (dB)"))) + labs(title = "V1 Offset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(-10,10)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV1$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggh1mnh2V1OffsetByVoice

5.6.1.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.6.1.4.1 Descriptive statistics

The predicted means and SDs of the H1*-H2* at the Offset of the preceding vowel (V1Offset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV1 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_V1h1mnh2OffsetNorm,na.rm = T), sd(fitted_V1h1mnh2OffsetNorm,na.rm = T))
5.6.1.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV1$fitted_V1h1mnh2OffsetNorm, geminationV1$singGem:geminationV1$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV1$fitted_V1h1mnh2OffsetNorm and geminationV1$singGem:geminationV1$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   0.84                -               
geminate:voiceless 0.85                0.84            
geminate:voiced    0.85                0.84            
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    0.84              

P value adjustment method: fdr 

5.6.2 At the onset of the following vowel

5.6.2.1 Model specification

We run three models. For model comparisons, we are required to use Maximum Likelihood (ML) on both Optimal and Null models (by adding REML=F). Then we run a second Optimal models with Restricted Maximum Likelihood (REML), to obtain the coefficients (by adding REML=T)

5.6.2.1.1 Optimal model (ML)
h1mnh2V2Onset.xmdl.Full.M <- lmer(h1mnh2OnsetNorm~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.6.2.1.2 Optimal model (REML)
h1mnh2V2Onset.xmdl.Full.R <- lmer(h1mnh2OnsetNorm~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
5.6.2.1.3 Null model (ML)
h1mnh2V2Onset.xmdl.Null.M <- lmer(h1mnh2OnsetNorm~1+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=F,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))

5.6.2.2 Results of our model

5.6.2.2.1 Model comparisons
anova(h1mnh2V2Onset.xmdl.Null.M,h1mnh2V2Onset.xmdl.Full.M)
Data: geminationV2
Models:
h1mnh2V2Onset.xmdl.Null.M: h1mnh2OnsetNorm ~ 1 + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
h1mnh2V2Onset.xmdl.Null.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
h1mnh2V2Onset.xmdl.Full.M: h1mnh2OnsetNorm ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c + 
h1mnh2V2Onset.xmdl.Full.M:     syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c + 
h1mnh2V2Onset.xmdl.Full.M:     syllType_c + place_c || speaker) + (1 | wordTarget)
                          Df   AIC   BIC  logLik deviance  Chisq
h1mnh2V2Onset.xmdl.Null.M  9 10989 11039 -5485.7    10971       
h1mnh2V2Onset.xmdl.Full.M 15 10988 11070 -5478.7    10958 13.965
                          Chi Df Pr(>Chisq)  
h1mnh2V2Onset.xmdl.Null.M                    
h1mnh2V2Onset.xmdl.Full.M      6    0.03003 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

As can be seen, our optimal model improved the model fit.

5.6.2.2.2 Residuals

We inspect our model below, by looking at the residuals. There are minor deviations observed, due to the nature of our data.

hist(residuals(h1mnh2V2Onset.xmdl.Full.R))

qqnorm(residuals(h1mnh2V2Onset.xmdl.Full.R)); qqline(residuals(h1mnh2V2Onset.xmdl.Full.R))

plot(fitted(h1mnh2V2Onset.xmdl.Full.R),residuals(h1mnh2V2Onset.xmdl.Full.R), cex = 4)

5.6.2.2.3 Summary of model
summary(h1mnh2V2Onset.xmdl.Full.R)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
h1mnh2OnsetNorm ~ voiced.unvoiced_c + singGem_c + sex_c + vowelLength_c +  
    syllType_c + place_c + (voiced.unvoiced_c + singGem_c + vowelLength_c +  
    syllType_c + place_c || speaker) + (1 | wordTarget)
   Data: geminationV2
Control: 
lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))

REML criterion at convergence: 10955.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.8200 -0.5976 -0.1252  0.4466  4.7005 

Random effects:
 Groups     Name              Variance  Std.Dev. 
 wordTarget (Intercept)       0.000e+00 0.000e+00
 speaker    place_c           1.303e+00 1.141e+00
 speaker.1  syllType_c        0.000e+00 0.000e+00
 speaker.2  vowelLength_c     5.084e-12 2.255e-06
 speaker.3  singGem_c         2.356e-01 4.854e-01
 speaker.4  voiced.unvoiced_c 5.053e-01 7.109e-01
 speaker.5  (Intercept)       1.506e+01 3.881e+00
 Residual                     2.595e+01 5.094e+00
Number of obs: 1783, groups:  wordTarget, 98; speaker, 20

Fixed effects:
                   Estimate Std. Error        df t value Pr(>|t|)  
(Intercept)         -2.2902     0.8945   19.2938  -2.560   0.0190 *
voiced.unvoiced_c   -0.1869     0.3347   25.0199  -0.558   0.5816  
singGem_c           -0.7220     0.2933   27.0620  -2.462   0.0205 *
sex_c                2.6897     1.7578   17.9598   1.530   0.1434  
vowelLength_c       -0.2544     0.2779 1713.4068  -0.915   0.3601  
syllType_c           0.3365     0.3524 1710.6079   0.955   0.3397  
place_c              0.8090     0.4643   23.3301   1.742   0.0946 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) vcd.n_ sngGm_ sex_c  vwlLn_ syllT_
vocd.nvcd_c  0.041                                   
singGem_c   -0.058 -0.032                            
sex_c       -0.001  0.001  0.001                     
vowlLngth_c  0.080 -0.130  0.073  0.001              
syllType_c   0.145  0.042 -0.372  0.000  0.281       
place_c      0.110  0.392 -0.010 -0.002 -0.050  0.031

5.6.2.3 Figures

The figure presented below, uses the predicted (or fitted) values; these are the values adjusted by the statistical model. These take into account the random effects’ structure as well as the fixed effects’ structure.

5.6.2.3.1 Using “predict”

The following code is used to record the predicted (or fitted) values into the same data-frame. This will then be used to plot the results of the model

geminationV2$fitted_V2h1mnh2OnsetNorm <- predict(lmer(h1mnh2OnsetNorm~voiced.unvoiced_c+singGem_c+sex_c+vowelLength_c+syllType_c+place_c+
                                (voiced.unvoiced_c+singGem_c+vowelLength_c+syllType_c+place_c||speaker)+(1|wordTarget), 
                              data = geminationV2,na.action=na.exclude,
                              REML=T,
                              control = lmerControl(optimizer = "bobyqa",optCtrl=list(maxfun=1e5)))
)
5.6.2.3.2 Plotting the results

We use “ggplot2” to plot the results. This will use the “predicted” (or fitted) values adjusted by our statistical model. The dashed lines within the boxplots are the mean values; the median is marked by the horizontal straight lines.

labels <- c(singleton = "Singleton", geminate = "Geminate")
ggh1mnh2V2OnsetByVoice <- ggplot(geminationV2, aes(y=fitted_V2h1mnh2OnsetNorm, x=voiced.unvoiced)) + 
  geom_boxplot(outlier.colour = "NA",na.rm=TRUE) +
  stat_summary(fun.y = mean, geom = "errorbar", aes(ymax = ..y.., ymin = ..y..),
               width = .75, linetype = "dashed") +
  ylab(expression(paste(italic("H"),"1*-",italic("H"),"2* (dB)"))) + labs(title = "V2 Onset") +
  theme_set(theme_bw()) + theme(text=element_text(size=20)) +
  coord_cartesian(ylim = c(-10,10)) +
  theme(axis.title.x = element_blank()) + theme(legend.title=element_blank()) +
  scale_x_discrete(breaks=levels(geminationV2$voiced.unvoiced), labels=c("Voiceless","Voiced")) +
  facet_wrap(~singGem,ncol=1,labeller=labeller(singGem = labels))
ggh1mnh2V2OnsetByVoice

5.6.2.4 Pairwise comparisons

After running our statistical model above, we wanted to evaluate whether the differences observed between “voicing” and “gemination” is statistically significant (or not). We present the means and standard deviations for each of the four-way contrast based on the predicted (or fitted) values.

5.6.2.4.1 Descriptive statistics

The predicted means and SDs of the H1*-H2* at the Onset of the following vowel (V2Onset) are provided below. As can be seen, there are already differences observed related to both “voicing” and “gemination”.

# using "dplyr"
geminationV2 %>% group_by(singGem:voiced.unvoiced) %>% summarise(mean(fitted_V2h1mnh2OnsetNorm,na.rm = T), sd(fitted_V2h1mnh2OnsetNorm,na.rm = T))
5.6.2.4.2 Pairwise t-test with FDR corrections

We used the pairwise t-test as available in base R. The input was the predicted (or fitted) values as adjusted by our statistical model. It was not possible to directly use our statistical model’s output to compare models, given that our LMM model was looking at overall change as a main effect rather than as a simple effect’s model. This is why we have used the predicted (or fitted) values as adjusted by our statistical model; the results are the same if we were to use the “actual” results rather than the predicted ones. We used FDR (for False Discovery Rate) correction for multiple comparisons as this allowed for correcting for bias in the differences in doing multiple comparisons.

pairwise.t.test(geminationV2$fitted_V2h1mnh2OnsetNorm, geminationV2$singGem:geminationV2$voiced.unvoiced, p.adj = "fdr")

    Pairwise comparisons using t tests with pooled SD 

data:  geminationV2$fitted_V2h1mnh2OnsetNorm and geminationV2$singGem:geminationV2$voiced.unvoiced 

                   singleton:voiceless singleton:voiced
singleton:voiced   0.05387             -               
geminate:voiceless 0.06751             0.87847         
geminate:voiced    0.00017             0.04972         
                   geminate:voiceless
singleton:voiced   -                 
geminate:voiceless -                 
geminate:voiced    0.04972           

P value adjustment method: fdr 
LS0tDQp0aXRsZTogIlZvaWNpbmcgYW5kIEdlbWluYXRpb24gLSBNaXhlZCBFZmZlY3RzIE1vZGVsbGluZyINCmF1dGhvcjogDQogIG5hbWU6ICJKYWxhbCBBbC1UYW1pbWkiDQogIGFmZmlsaWF0aW9uOiAiTmV3Y2FzdGxlIFVuaXZlcnNpdHkiDQpkYXRlOiAiMTcgSnVseSAyMDE4Ig0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazoNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDYNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHRydWUNCi0tLQ0KDQojIEludHJvZHVjdGlvbg0KVGhpcyBhbmFseXNpcyBhY2NvbXBhbmllcyB0aGUgYXJ0aWNsZSAiQWwtVGFtaW1pLCBKLiBhbmQgS2hhdHRhYiwgRy4sICgyMDE4KS4gKkFjb3VzdGljIGNvcnJlbGF0ZXMgb2YgdGhlIHZvaWNpbmcgY29udHJhc3QgaW4gTGViYW5lc2UgQXJhYmljIHNpbmdsZXRvbiBhbmQgZ2VtaW5hdGUgcGxvc2l2ZXMqLiBJbnZpdGVkIG1hbnVzY3JpcHQgZm9yIHRoZSBzcGVjaWFsIGlzc3VlIG9mIEpvdXJuYWwgb2YgUGhvbmV0aWNzLCAiTWFya2luZyA1MCBZZWFycyBvZiBSZXNlYXJjaCBvbiBWb2ljZSBPbnNldCBUaW1lIGFuZCB0aGUgVm9pY2luZyBDb250cmFzdCBpbiB0aGUgV29ybGTigJlzIExhbmd1YWdlcyIgKGVkcy4sIFQuIENobywgRy4gRG9jaGVydHkgJiBELiBXaGFsZW4pLiBET0k6IGh0dHBzOi8vZG9pLm9yZy8xMC4xMDE2L2oud29jbi4yMDE4LjA5LjAxMA0KDQpUaGlzIG5vdGVib29rIHByZXNlbnRzIHRoZSBhbmFseXNlcyBhbmQgcmVzdWx0cyBvZiB0aGUgTGluZWFyIE1peGVkIEVmZmVjdHMgTW9kZWxsaW5nIHRoYXQgd2FzIHVzZWQgYXMgYSBjb25maXJtYXRvcnkgYW5hbHlzaXMuIFRoZSBhaW0gd2FzIHRvIGV2YWx1YXRlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBlYWNoIG9mIHRoZSAxOSBhY291c3RpYyBjb3JyZWxhdGVzIChvdXRjb21lKSBhbmQgdGhlIHNpeCBwcmVkaWN0b3JzLiANCg0KIyBEZXNjcmlwdGlvbiBvZiB0aGUgZGF0YQ0KDQpUaGUgZGF0YSB1c2VkIGhlcmUgYXJlIHBhcnQgb2YgYSBsYXJnZXIgcHJvamVjdCB0byBpbnZlc3RpZ2F0ZSB0aGUgYWNvdXN0aWMgY29ycmVsYXRlcyBvZiBnZW1pbmF0aW9uIGluIExlYmFuZXNlIEFyYWJpYy4gKioyMCBzcGVha2VycyAoMTAgbWFsZXMpKiogcHJvZHVjZWQgYSBsaXN0IG9mIGl0ZW1zIHdpdGggYWxsIHBvc3NpYmxlIGNvbnNvbmFudHMgaW4gTGViYW5lc2UgQXJhYmljLiBUaGUgZGF0YSB1c2VkIGluIHRoaXMgbm90ZWJvb2sgKGFuZCB0aGUgcGFwZXIpIGFyZSBjb25jZXJuZWQgd2l0aCB0aGUgZm9sbG93aW5nIHN0b3BzOiAvYiB0IHTLpCBkIGTLpCBrLyBhcyByZWFsaXNlZCBpbiBvbmUgb2YgdGhlIGZvbGxvd2luZyBzeWxsYWJsZSBzdHJ1Y3R1cmVzOiDLiENWQ1ZDIChlLmcuIC/LiMqVYWRhZC8g4oCcbnVtYmVy4oCdKSwgy4hDVjpDVkMgKGUuZy4gL8uIypVhy5BkZWQvIOKAnGNvdW50aW5n4oCdKSwgy4hDVkM6VkMgKGUuZy4gL8uIypVhZMuQYWQpLyDigJxoZSBlbnVtZXJhdGVk4oCdKSwgy4hDVjpDOlZDIChlLmcuIC/LiMqVYcuQZMuQZShoKS8g4oCcaGF2aW5nIGNvdW50ZWTigJ0pIGFuZCBDVsuIQzpWOkMgKGUuZy4gL8qVYcuIZMuQZcuQZC8g4oCcY291bnRlcuKAnSkuIFRoZSB2b3dlbHMgc3Vycm91bmRpbmcgdGhlIG1lZGlhbCBzdG9wIHdlcmUgZWl0aGVyIC9hIG9yIGHLkC8uIDk4IGl0ZW1zIHdlcmUgcmVjb3JkZWQgZnJvbSBlYWNoIHBhcnRpY2lwYW50LiBBIHRvdGFsIG9mIDE5NjAgd29yZHMgd2VyZSBlbGljaXRlZCAoOTggd29yZHMgYnkgMjAgc3BlYWtlcnMpLCBhbmQgMTcxIHRva2VucyB3ZXJlIGRpc2NhcmRlZCBkdWUgdG8gbm9pc2Ugb3IgdGVjaG5pY2FsIGVycm9yLCBsZWF2aW5nIGEgdG90YWwgb2YgKioxNzkzKiogd29yZHMgZm9yIHN1YnNlcXVlbnQgYW5hbHlzZXMuIA0KDQoxOSBhY291c3RpYyBjb3JyZWxhdGVzIHdlcmUgbG9va2VkIGF0IGhlcmUgdG8gZXZhbHVhdGUgdGhlaXIgaW1wYWN0IG9uIHRoZSBmb3VyLXdheSBjb250cmFzdCBiZXR3ZWVuIHZvaWNpbmcgYW5kIGdlbWluYXRpb24sIGkuZS4sIFZvaWNlZCBTaW5nbGV0b24sIFZvaWNlbGVzcyBTaW5nbGV0b24sIFZvaWNlZCBHZW1pbmF0ZSBhbmQgVm9pY2VsZXNzIEdlbWluYXRlLiBUaGUgMTkgYWNvdXN0aWMgY29ycmVsYXRlcyB1c2VkIGluY2x1ZGVkIDYgZHVyYXRpb25hbCwgdGhyZWUgdm9pY2luZywgYW5kIDEwIG5vbi10ZW1wb3JhbCBpbmNsdWRpbmcgZjAsIEYxIGFuZCBoYXJtb25pYyBkaWZmZXJlbmNlcy4NClRoaXMgTm90ZWJvb2sgbG9va2VkIGF0IGhvdyBlYWNoICppbmRpdmlkdWFsKiAgYWNvdXN0aWMgY29ycmVsYXRlIHdhcyBhc3NvY2lhdGVkIHdpdGggdGhlIHByZWRpY3RvcnMuIFRoZSBuZXh0IG5vdGVib29rIGV4dGVuZHMgdGhlIGFuYWx5c2lzIGJ5IGxvb2tpbmcgYXQgdGhlICpjb21iaW5hdGlvbiogb2YgdGhlc2UgYWNvdXN0aWMgY29ycmVsYXRlcyBhbmQgdGhlaXIgcHJlZGljdGl2ZSBwb3dlciBpbiBkaXNjcmltaW5hdGluZyBiZXR3ZWVuIHRoZSBmb3VyIGNhdGVnb3JpZXMgYWJvdmUgW3NlZSBub3RlYm9va10oaHR0cHM6Ly9qYWxhbGFsLXRhbWltaS5naXRodWIuaW8vUi1Wb2ljaW5nLUdlbWluYXRpb24tVk9UL1ZvaWNpbmclMjBhbmQlMjBHZW1pbmF0aW9uJTIwLSUyMFJhbmRvbSUyMEZvcmVzdHMubmIuaHRtbCkuIA0KDQoNCiMgTG9hZGluZyByZXF1aXJlZCBwYWNrYWdlcw0KDQpXZSBzdGFydCBieSBsb2FkaW5nIHRoZSByZXF1aXJlZCBwYWNrYWdlcy4NCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQpyZXF1aXJlZFBhY2thZ2VzID0gYygnZHBseXInLCdsbWU0JywnbG1lclRlc3QnLCdlbW1lYW5zJywnZ2dwbG90MicpDQpmb3IocCBpbiByZXF1aXJlZFBhY2thZ2VzKXsNCiAgaWYoIXJlcXVpcmUocCxjaGFyYWN0ZXIub25seSA9IFRSVUUpKSBpbnN0YWxsLnBhY2thZ2VzKHApDQogIGxpYnJhcnkocCxjaGFyYWN0ZXIub25seSA9IFRSVUUpDQp9DQpgYGANCg0KDQojIFByZXByb2Nlc3NpbmcgdGhlIGRhdGENCg0KIyMgUmVhZGluZyBpbiB0aGUgZGF0YQ0KDQpXZSBzdGFydCByZWFkaW5nIGluIHRoZSBkYXRhIGFuZCBjaGVja2luZyB0aGUgc3RydWN0dXJlLiAgDQoNCmBgYHtyfQ0KZ2VtaW5hdGlvblJlcyA8LSByZWFkLmNzdigicmVzdWx0c0dlbWluYXRpb24uY3N2IikNCg0Kc3RyKGdlbWluYXRpb25SZXMpDQoNCmBgYA0KDQojIyBSZW9yZGVyaW5nIG9mIGxldmVscyBvZiBwcmVkaWN0b3JzDQoNClZhcmlvdXMgcHJlZGljdG9ycyBhcmUgYXZhaWxhYmxlIGluIGRhdGEtZnJhbWUsIGFuZCB3ZSBhcmUgaW50ZXJlc3RlZCBpbiB0aGUgaW1wYWN0IG9mIHRoZSBmb2xsb3dpbmcgcHJlZGljdG9yczoNCjEuIFZvaWNpbmc6IFZvaWNlZCB2cyBWb2ljZWxlc3MNCjIuIEdlbWluYXRpb246IFNpbmdsZXRvbiB2cyBHZW1pbmF0ZQ0KMy4gU2V4OiBNYWxlIHZzIEZlbWFsZQ0KNC4gKFByZWNlZGluZykgVm93ZWwgTGVuZ3RoOiBTaG9ydCB2cyBMb25nDQo1LiBTeWxsYWJsZSBUeXBlOiBJYW1iaWMgdnMgVHJvY2hhaWMNCjYuIFBsYWNlIG9mIEFydGljdWxhdGlvbjogQmlsYWJpYWwsIEFsdmVvbGFyLCAoQWx2ZW9sYXItKVBoYXJ5bmdlYWxpc2VkIGFuZCBWZWxhcg0KDQpgYGB7cn0NCiMgdXNpbmcgImRwbHlyIg0KbGV2ZWxzKGdlbWluYXRpb25SZXMkdm9pY2VkLnVudm9pY2VkKQ0KZ2VtaW5hdGlvblJlcyR2b2ljZWQudW52b2ljZWQgPC0gZmFjdG9yKGdlbWluYXRpb25SZXMkdm9pY2VkLnVudm9pY2VkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJ2b2ljZWxlc3MiLCJ2b2ljZWQiKSkNCmxldmVscyhnZW1pbmF0aW9uUmVzJHZvaWNlZC51bnZvaWNlZCkNCg0KbGV2ZWxzKGdlbWluYXRpb25SZXMkc2luZ0dlbSkNCmdlbWluYXRpb25SZXMkc2luZ0dlbSA8LSBmYWN0b3IoZ2VtaW5hdGlvblJlcyRzaW5nR2VtLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygic2luZ2xldG9uIiwiZ2VtaW5hdGUiKSkNCmxldmVscyhnZW1pbmF0aW9uUmVzJHNpbmdHZW0pDQoNCmxldmVscyhnZW1pbmF0aW9uUmVzJHNleCkNCiMgbm8gY2hhbmdlDQoNCmxldmVscyhnZW1pbmF0aW9uUmVzJHZvd2VsTGVuZ3RoKQ0KZ2VtaW5hdGlvblJlcyR2b3dlbExlbmd0aCA8LSBmYWN0b3IoZ2VtaW5hdGlvblJlcyR2b3dlbExlbmd0aCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJzaG9ydFYxIiwibG9uZ1YxIikpDQpsZXZlbHMoZ2VtaW5hdGlvblJlcyR2b3dlbExlbmd0aCkNCg0KbGV2ZWxzKGdlbWluYXRpb25SZXMkc3lsbFR5cGUpDQpnZW1pbmF0aW9uUmVzJHN5bGxUeXBlIDwtIGZhY3RvcihnZW1pbmF0aW9uUmVzJHN5bGxUeXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoInRyb2NoYWljIiwiaWFtYmljIikpDQpsZXZlbHMoZ2VtaW5hdGlvblJlcyRzeWxsVHlwZSkNCg0KbGV2ZWxzKGdlbWluYXRpb25SZXMkcGxhY2VBcnRpY3VsYXRpb24pDQpnZW1pbmF0aW9uUmVzJHBsYWNlQXJ0aWN1bGF0aW9uIDwtIGZhY3RvcihnZW1pbmF0aW9uUmVzJHBsYWNlQXJ0aWN1bGF0aW9uLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYmlsYWJpYWwiLCJhbHZlb2xhciIsInBoYXJ5bmdlYWxpc2VkIiwidmVsYXIiKSkNCmxldmVscyhnZW1pbmF0aW9uUmVzJHBsYWNlQXJ0aWN1bGF0aW9uKQ0KDQpgYGANCg0KIyMgQ29udHJhc3QgY29kaW5nIGFuZCBjZW50cmluZyBvZiBmYWN0b3IgbGV2ZWwNCg0KSW4gb3VyIHN0dWR5LCB3ZSB3YW50ZWQgdG8gdXNlIGEgbW9kZWwgdGhhdCBhbGxvd3MgZm9yIGEgbWVhbmluZ2Z1bCBpbnRlcnByZXRhdGlvbiBvZiB0aGUgY29lZmZpY2llbnRzIGFuZCBvZiB0aGUgaW50ZXJjZXB0LiBGb3IgdGhpcywgd2UgdXNlZCBjb250cmFzdCBjb2Rpbmcgb24gYWxsIGZpeGVkIGVmZmVjdHMgYnkgY2VudHJpbmcgdGhlbSB0byB2YWx1ZXMgYmV0d2VlbiAtMC41IGFuZCAwLjUuIFdpdGggY29udHJhc3QgY29kaW5nLCB0aGUgSW50ZXJjZXB0IGlzIGVxdWFsIHRvIHRoZSB3ZWlnaHRlZCBhdmVyYWdlIGFjcm9zcyBhbGwgcHJlZGljdG9ycywgYW5kIGFsbCB0aGUgY29lZmZpY2llbnRzIGZvciBwcmVkaWN0b3JzIHdpbGwgYmUgZXF1YWwgdG8gbWFpbiBlZmZlY3RzIHJhdGhlciB0aGFuIHNpbXBsZSBlZmZlY3RzLiANCg0KV2l0aCB0aGlzIGNlbnRyaW5nLCBvdXIgbW9kZWxzIHdpbGwgc2hvdyB0aGUgb3ZlcmFsbCBjaGFuZ2UgZnJvbSB0aGUgbGV2ZWwgYXNzaWduZWQgdGhlICpuZWdhdGl2ZSogdmFsdWUgdG8gdGhlIGxldmVsIHdpdGggdGhlICpwb3NpdGl2ZSogdmFsdWUuIEUuZy4sIHdpdGggdm9pY2luZywgdm9pY2VsZXNzIHdhcyBhc3NpZ25lZCAtMC41IGFuZCB2b2ljZWQgMC41LiBJbiBvdXIgc3RhdGlzdGljYWwgbW9kZWwgdGhlIG92ZXJhbGwgZWZmZWN0ICoqdm9pY2luZyoqIHdpbGwgYmUgc2hvd24gYXMgYSBjaGFuZ2UgZnJvbSB2b2ljZWxlc3MgdG8gdm9pY2VkIChzZWUgYXJ0aWNsZSBmb3IgbW9yZSBkZXRhaWxzKS4NCg0KYGBge3J9DQojIHVzaW5nICJkcGx5ciINCiMgZm9yIGNoYW5nZSBmcm9tIFZvaWNlbGVzcyB0byBWb2ljZWQNCmdlbWluYXRpb25SZXMgPC0gbXV0YXRlKGdlbWluYXRpb25SZXMsDQogICAgICAgICAgICAgICAgICAgICAgICB2b2ljZWQudW52b2ljZWRfYyA9IGlmZWxzZSh2b2ljZWQudW52b2ljZWQgPT0gJ3ZvaWNlZCcsIDAuNSwgLTAuNSkpDQojIGZvciBjaGFuZ2UgZnJvbSBTaW5nbGV0b24gdG8gR2VtaW5hdGUNCmdlbWluYXRpb25SZXMgPC0gbXV0YXRlKGdlbWluYXRpb25SZXMsDQogICAgICAgICAgICAgICAgICAgICAgICBzaW5nR2VtX2MgPSBpZmVsc2Uoc2luZ0dlbSA9PSAnZ2VtaW5hdGUnLCAwLjUsIC0wLjUpKQ0KIyBmb3IgY2hhbmdlIGZyb20gTWFsZSB0byBGZW1hbGUNCmdlbWluYXRpb25SZXMgPC0gbXV0YXRlKGdlbWluYXRpb25SZXMsDQogICAgICAgICAgICAgICAgICAgICAgICBzZXhfYyA9IGlmZWxzZShzZXggPT0gJ0YnLCAwLjUsIC0wLjUpKQ0KIyBmb3IgY2hhbmdlIGZyb20gU2hvcnQgVjEgdG8gTG9uZyBWMQ0KZ2VtaW5hdGlvblJlcyA8LSBtdXRhdGUoZ2VtaW5hdGlvblJlcywNCiAgICAgICAgICAgICAgICAgICAgICAgIHZvd2VsTGVuZ3RoX2MgPSBpZmVsc2Uodm93ZWxMZW5ndGggPT0gJ2xvbmdWMScsIDAuNSwgLTAuNSkpDQojIGZvciBjaGFuZ2UgZnJvbSBUcm9jaGFpYyB0byBJYW1iaWMNCmdlbWluYXRpb25SZXMgPC0gbXV0YXRlKGdlbWluYXRpb25SZXMsDQogICAgICAgICAgICAgICAgICAgICAgICBzeWxsVHlwZV9jID0gaWZlbHNlKHN5bGxUeXBlID09ICdpYW1iaWMnLCAwLjUsIC0wLjUpKQ0KIyBmb3IgY2hhbmdlIGZyb20gQmlsYWJpYWwsIHRvIEFsdmVvbGFyIHRvIChBbHZlb2xhci0pUGhhcnluZ2VhbGlzZWQgdG8gVmVsYXINCmdlbWluYXRpb25SZXMgPC0gIG11dGF0ZShnZW1pbmF0aW9uUmVzLCBwbGFjZV9jID0gaWZlbHNlKHBsYWNlQXJ0aWN1bGF0aW9uID09ICd2ZWxhcicsIDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocGxhY2VWb2ljaW5nID09J3BoYXJ5bmdlYWxpc2VkJywgMC4xMzMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHBsYWNlVm9pY2luZyA9PSAnYWx2ZW9sYXInLCAtMC4xMzMsLTAuNSkpKSkNCg0KYGBgDQoNCiMjIENyZWF0aW5nIGZvdXIgbmV3IGRhdGEtZnJhbWVzDQoNCkhlcmUgd2UgY3JlYXRlIGZvdXIgbmV3IGRhdGFzZXRzIHRoYXQgYXJlIHN1YnNldHMgb2YgdGhlIG9yaWdpbmFsIGRhdGFzZXQuIFRoZSBhaW0gaXMgdG8gaGF2ZSBzcGVjaWZpYyBkYXRhLWZyYW1lcyBmb3IgZWFjaCBvZiB0aGUgcHJlY2VkaW5nIHZvd2VsIChWMSksIG1lZGlhbCBjb25zb25hbnQgKENEKSwgUmVsZWFzZSBwaGFzZSAoQlZPVCkgYW5kIGZvbGxvd2luZyB2b3dlbCAoVjIpLiBWMSBjYW4gYmUgZWl0aGVyIHNob3J0IG9yIGxvbmcgKFYxLCBWVjEpOyBDRCBjYW4gYmUgc2hvcnQgb3IgbG9uZyAoQzIsIENDMikuDQoNCmBgYHtyfQ0KbCA8LSBjKCJhIiwiYWEiLCAiZSIsICJlZSIpDQpsMiA8LSBjKCJWMiIsICJWVjIiKQ0KbDMgPC0gYygiVjEiLCAiVlYxIikNCmw0IDwtIGMoIkMyIiwiQ0MyIikNCmw1IDwtICJCVk9UIg0KDQpnZW1pbmF0aW9uVm93ZWxzIDwtIGZpbHRlcihnZW1pbmF0aW9uUmVzLCBwaG9uZW1lICVpbiUgbCkNCmdlbWluYXRpb25WMiA8LSBmaWx0ZXIoZ2VtaW5hdGlvblZvd2VscywgYy52ICVpbiUgbDIpDQpnZW1pbmF0aW9uVjEgPC0gZmlsdGVyKGdlbWluYXRpb25Wb3dlbHMsIGMudiAlaW4lIGwzKQ0KDQpnZW1pbmF0aW9uQ29ucyA8LSBmaWx0ZXIoZ2VtaW5hdGlvblJlcywgYy52ICVpbiUgbDQpDQpnZW1pbmF0aW9uVk9UIDwtIGZpbHRlcihnZW1pbmF0aW9uUmVzLCBjLnYgJWluJSBsNSkNCg0KYGBgDQoNCiMjIENyZWF0aW5nIGEgbmV3IG91dGNvbWUgKFZPVCkNCg0KSW4gb3VyIG9yaWdpbmFsIHN1Ym1pc3Npb24sIHdlIHVzZWQgdGhlIHByb3BvcnRpb24gb2Ygdm9pY2luZyBpbiBib3RoIHRoZSBjbG9zdXJlIGFuZCByZWxlYXNlIHBoYXNlcyBiYXNlZCB0aGUgY29tcHV0YXRpb25zIHdlIGRldmVsb3BlZCBbc2VlIGhlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9KYWxhbEFsLVRhbWltaS9QcmFhdC1Wb2ljaW5nLWRldGVjdGlvbikuIFRoaXMgcHJvcG9ydGlvbiBvZiB2b2ljaW5nIGFpbXMgYXQgZXhwbGFpbmluZyB0aGUgcGF0dGVybnMgb2YgcGFzc2l2ZSBkZXZvaWNpbmcgYW5kL29yIGFjdGl2ZSB2b2ljaW5nIGluIHRoZSB2b2ljaW5nIGJ5IGdlbWluYXRpb24gY29udHJhc3RzLiBXZSBhbHNvIHdhbnRlZCB0byBsb29rIGF0IHRoZSB2b2ljaW5nIHBhdHRlcm5zIGluIHRoZSB2b2ljaW5nIGJ5IGdlbWluYXRpb24gY29udHJhc3RzIGZvbGxvd2luZyB0aGUgdHJhZGl0aW9uYWwgIlZPVCIgbm90aW9uLiBIZW5jZSB3ZSBjb21wdXRlZCB0aGUgIlZPVCIgYnkgZm9sbG93aW5nIHRoZSByZXZpc2VkIHByb2NlZHVyZSBhcyBkZXNjcmliZWQgaW4gQWJyYW1zb24sIEEuUy4gJiBXaGFsZW4sIEQuICgyMDE3KSAoaHR0cHM6Ly9kb2kub3JnLzEwLjEwMTYvai53b2NuLjIwMTcuMDUuMDAyKS4gQmVsb3cgaXMgdGhlIGltcGxlbWVudGF0aW9uIG9mIHRoaXMgbWV0aG9kIGJhc2VkIG9uIG91ciBjb21wdXRhdGlvbnMgb2YgdGhlIHByb3BvcnRpb24gb2Ygdm9pY2luZyBpbiBib3RoIGNsb3N1cmUgYW5kIHJlbGVhc2UgcGhhc2VzLiBXZSB1c2UgdGhlIHRocmVzaG9sZCBvZiA1MCUgdm9pY2luZzsgaWYgInZvaWNpbmciIGlzIGVxdWFsIG9yIGlzIGhpZ2hlciB0aGFuIDUwJSwgdGhlIHRvdGFsIGR1cmF0aW9uIG9mIHRoZSBjbG9zdXJlIGlzIGNvbnNpZGVyZWQgbmVnYXRpdmUgVlQsIG90aGVyd2lzZSwgdGhlIFZPVCBpcyBwb3NpdGl2ZSBhbmQgaXMgZXF1aXZhbGVudCB0byB0aGUgdG90YWwgZHVyYXRpb24gb2YgdGhlIFJlbGVhc2UgcGhhc2UgKGkuZS4sIGJ1cnN0LCBhbmQgYXNwaXJhdGlvbikuDQoNCmBgYHtyfQ0KIyBzdGFydCBieSBjcmVhdGluZyBhIG5ldyBwcmVkaWN0b3IgDQpnZW1pbmF0aW9uQ29ucyRWT1REZWMgPC0gTkENCnggPC0gLWdlbWluYXRpb25Db25zJGR1cmF0aW9uDQp5IDwtIGdlbWluYXRpb25WT1QkZHVyYXRpb24NCiMgYmVsb3csIHdlIHVzZSB0aGUgc2FtZSB0aHJlc2hvbGQgDQpnZW1pbmF0aW9uQ29ucyRWT1REZWMgPC0gaWZlbHNlKGdlbWluYXRpb25Db25zJGR1cmF0aW9uVm9pY2VkUGVyYyA+PSA1MCwgDQogICAgICAgeCx5KQ0KYGBgDQoNCiMgUnVubmluZyBvdXIgTGluZWFyIE1peGVkIEVmZmVjdHMgTW9kZWxzDQoNCk5vdyB0aGF0IHRoZSBwcmVwcm9jZXNzaW5nIG9mIHRoZSBkYXRhIGZpbmlzaGVkLCB3ZSBzdGFydCB3aXRoIG91ciBtb2RlbGxpbmcuIEFzIGEgcmVtb25kZXIsIG91ciBhaW0gaXMgdG8gdXNlIHRoZXNlIGFuYWx5c2VzIGluIGEgY29uZmlybWF0b3J5IG1hbm5lci4gV2UgYWltIHRvIGV2YWx1YXRlIHRoZSBlZmZlY3RzIG9mIHRoZSBzaXggcHJlZGljdG9ycyBkZXNjcmliZWQgYWJvdmUgb24gZWFjaCBvZiB0aGUgYWNvdXN0aWMgY29ycmVsYXRlcy4gQ3Jvc3NlZCByYW5kb20gZWZmZWN0cyB3ZXJlIHVzZWQgZm9yIHNwZWFrZXIgYW5kIGl0ZW1zLg0KDQpGb3IgYWxsIG1vZGVscyBiZWxvdywgd2UgdXNlZCBhIGNvbWJpbmF0aW9uIG9mIG1vZGVsczogZml4ZWQgZWZmZWN0cyBvbmx5OyByYW5kb20gaW50ZXJjZXB0czsgcmFuZG9tIGludGVyY2VwdHMgYW5kIHNsb3BlczsgaW50ZXJhY3Rpb25zIGZvciB0aGUgZml4ZWQgZWZmZWN0czsgaW50ZXJhY3Rpb25zIGZvciB0aGUgc2xvcGVzOyBldGMuIFRoZSBvcHRpbWFsIG1vZGVsIGluIGVhY2ggY2FzZSB3YXMgdGhlIG9uZSBwcmVzZW50ZWQgYmVsb3cgYW5kIGhhZCB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZToNCg0KMS4gRml4ZWQgZWZmZWN0cyB3aXRoIG5vIGludGVyYWN0aW9ucw0KMi4gUmFuZG9tIEludGVyY2VwdHMgZm9yIGl0ZW1zDQozLiBSYW5kb20gSW50ZXJjZXB0cyBhbmQgU2xvcGVzIGZvciBzcGVha2VyIChmb3IgYWxsIGZpeGVkIGVmZmVjdHMgbWludXMgc2V4KS4gVGhlc2UgcmFuZG9tIHNsb3BlcyB3ZXJlIGFsbCAqd2l0aGluKiBzdWJqZWN0cywgYW5kIHdlcmUgbmVjZXNzYXJ5IHRvIGFsbG93IHNwZWFrZXJzIHRvIGNvLXZhcnkgd2l0aCByZXNwZWN0IHRvIHRoZWlyIGVmZmVjdHMuIFRoZXNlIHJhbmRvbSBzbG9wZXMgd2VyZSBkZWNvcnJlbGF0ZWQgZnJvbSB0aGUgSW50ZXJjZXB0IChieSB1c2luZyB8fCkuDQoNCkFmdGVyIGVhY2ggbW9kZWwgd2FzIHJ1biwgd2UgY29tcGFyZWQgbW9kZWxzIHdpdGggYW4gaW50ZXJjZXB0IG9ubHkgbW9kZWwgKGkuZS4sIHdpdGhvdXQgdGhlIGZpeGVkIGVmZmVjdHMpLiBUaGlzIGlzIHVzZWQgdG8gcHJvdmlkZSB0aGUgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIG9mIG91ciBtb2RlbC4gV2UgYXJlIGFsc28gdXNpbmcgdGhlIHBhY2thZ2UgImxtZXJUZXN0IiB0byBkaXNwbGF5IHRoZSBwIHZhbHVlcyBvZiBlYWNoIHByZWRpY3Rvci4gVGhpcyB1c2VzIGFuIGFwcHJveGltYXRpb24gb2YgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSwgYW5kIGFsbG93cyB1cyB0byBvYnRhaW4gZXN0aW1hdGVkIHAgdmFsdWVzLiBUaGlzIG1heSBiZSBwcm9ibGVtYXRpYyBnaXZlbiB0aGF0IHRoZXNlIGFyZSBhcHByb3hpbWF0aW9ucywgYW5kIHRodXMgaXQgaXMgYWx3YXlzIGJlc3QgdG8gZXZhbHVhdGUgdGhlIHNpZ25pZmljYW5jZSBsZXZlbHMgb2Ygb3VyIHByZWRpY3RvcnMgdXNpbmcgbW9kZWwgY29tcGFyaXNvbnMuDQoNCldlIGV2YWx1YXRlIG1vZGVsJ3MgcmVzaWR1YWxzLCBhbmQgdGhlbiB3ZSBwcmVzZW50IHRoZSBvcHRpbWFsIG1vZGVscycgc3VtbWFyaWVzLiBXZSB0aGVuIHVzZSB0aGUgInByZWRpY3QiIGZ1bmN0aW9uIGZyb20gImxtZTQiIHRvIG9idGFpbiB0aGUgZml0dGVkIHZhbHVlcyB0aGF0IHRha2UgaW50byBhY2NvdW50IGJvdGggZml4ZWQgYW5kIHJhbmRvbSBlZmZlY3RzIHN0cnVjdHVyZS4gVGhlIGZpdHRlZCAob3IgcHJlZGljdGVkKSB2YWx1ZXMgYXJlIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbCBhbmQgYXJlIHRoZW4gdXNlZCBpbiB0aGUgZmlndXJlcy4NCg0KIyMgRHVyYXRpb24gKG1zZWMpDQoNCldpdGhpbiBkdXJhdGlvbiwgd2UgY29tcHV0ZWQgdGhlIGR1cmF0aW9ucyBvZiB0aGUgdm93ZWwgcHJlY2VkaW5nIHRoZSBjb25zb25hbnQgKFYxKSwgdGhlIG1lZGlhbCBjb25zb25hbnQgKENEKSwgUmVsZWFzZSBQaGFzZSAoUmVsKSwgQnVyc3QgUGhhc2UgKEIpLCBBc3BpcmF0aW9uIFBoYXNlIChBc3ApIGFuZCB0aGUgdm93ZWwgZm9sbG93aW5nIHRoZSBjb25zb25hbnQgKFYyKQ0KDQojIyMgRHVyYXRpb24gb2YgdGhlIHByZWNlZGluZyB2b3dlbCAoVjEpDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KZHVyYXRpb25WMS54bWRsLkZ1bGwuTSA8LSBsbWVyKGR1cmF0aW9ufnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMSxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgIE9wdGltYWwgbW9kZWwgKFJFTUwpDQoNCmBgYHtyfQ0KZHVyYXRpb25WMS54bWRsLkZ1bGwuUiA8LSBsbWVyKGR1cmF0aW9ufnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMSxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgTnVsbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KZHVyYXRpb25WMS54bWRsLk51bGwuTSA8LSBsbWVyKGR1cmF0aW9ufjErDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjEsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShkdXJhdGlvblYxLnhtZGwuTnVsbC5NLGR1cmF0aW9uVjEueG1kbC5GdWxsLk0pDQpgYGANCg0KQXMgY2FuIGJlIHNlZW4sIG91ciBvcHRpbWFsIG1vZGVsIGltcHJvdmVkIHRoZSBtb2RlbCBmaXQuDQoNCiMjIyMjIFJlc2lkdWFscw0KDQpXZSBpbnNwZWN0IG91ciBtb2RlbCBiZWxvdywgYnkgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLiBUaGVyZSBhcmUgbWlub3IgZGV2aWF0aW9ucyBvYnNlcnZlZCwgZHVlIHRvIHRoZSBuYXR1cmUgb2Ygb3VyIGRhdGEuDQoNCmBgYHtyfQ0KaGlzdChyZXNpZHVhbHMoZHVyYXRpb25WMS54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGR1cmF0aW9uVjEueG1kbC5GdWxsLlIpKTsgcXFsaW5lKHJlc2lkdWFscyhkdXJhdGlvblYxLnhtZGwuRnVsbC5SKSkNCnBsb3QoZml0dGVkKGR1cmF0aW9uVjEueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhkdXJhdGlvblYxLnhtZGwuRnVsbC5SKSwgY2V4ID0gNCkNCmBgYA0KDQojIyMjIyBTdW1tYXJ5IG9mIG1vZGVsDQoNCmBgYHtyfQ0Kc3VtbWFyeShkdXJhdGlvblYxLnhtZGwuRnVsbC5SKQ0KYGBgDQoNCiMjIyMgRmlndXJlcw0KDQpUaGUgZmlndXJlIHByZXNlbnRlZCBiZWxvdywgdXNlcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlczsgdGhlc2UgYXJlIHRoZSB2YWx1ZXMgKmFkanVzdGVkKiBieSB0aGUgc3RhdGlzdGljYWwgbW9kZWwuIFRoZXNlIHRha2UgaW50byBhY2NvdW50IHRoZSByYW5kb20gZWZmZWN0cycgc3RydWN0dXJlIGFzIHdlbGwgYXMgdGhlIGZpeGVkIGVmZmVjdHMnIHN0cnVjdHVyZS4gDQoNCiMjIyMjIFVzaW5nICJwcmVkaWN0Ig0KDQpUaGUgZm9sbG93aW5nIGNvZGUgaXMgdXNlZCB0byByZWNvcmQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgaW50byB0aGUgc2FtZSBkYXRhLWZyYW1lLiBUaGlzIHdpbGwgdGhlbiBiZSB1c2VkIHRvIHBsb3QgdGhlIHJlc3VsdHMgb2YgdGhlIG1vZGVsDQoNCmBgYHtyfQ0KZ2VtaW5hdGlvblYxJGZpdHRlZF9kdXJhdGlvblYxIDwtIHByZWRpY3QobG1lcihkdXJhdGlvbn52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjEsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCikNCmBgYA0KDQoNCiMjIyMjIFBsb3R0aW5nIHRoZSByZXN1bHRzDQoNCldlIHVzZSAiZ2dwbG90MiIgdG8gcGxvdCB0aGUgcmVzdWx0cy4gVGhpcyB3aWxsIHVzZSB0aGUgInByZWRpY3RlZCIgKG9yIGZpdHRlZCkgdmFsdWVzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlIGRhc2hlZCBsaW5lcyAqd2l0aGluKiB0aGUgYm94cGxvdHMgYXJlIHRoZSBtZWFuIHZhbHVlczsgdGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgdGhlIGhvcml6b250YWwgc3RyYWlnaHQgbGluZXMuDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQpsYWJlbHMgPC0gYyhzaW5nbGV0b24gPSAiU2luZ2xldG9uIiwgZ2VtaW5hdGUgPSAiR2VtaW5hdGUiKQ0KDQpnZ2R1clYxQnlWb2ljZSA8LSBnZ3Bsb3QoZ2VtaW5hdGlvblYxLCBhZXMoeT1maXR0ZWRfZHVyYXRpb25WMSwgeD12b2ljZWQudW52b2ljZWQpKSArIA0KICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAiTkEiLG5hLnJtPVRSVUUpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICJlcnJvcmJhciIsIGFlcyh5bWF4ID0gLi55Li4sIHltaW4gPSAuLnkuLiksDQogICAgICAgICAgICAgICB3aWR0aCA9IC43NSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB5bGFiKGV4cHJlc3Npb24ocGFzdGUoIkR1cmF0aW9uIChtcykiKSkpICsgbGFicyh0aXRsZSA9ICJWMSIpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDI1LDMyNSkpICsNCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0yMCkpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9bGV2ZWxzKGdlbWluYXRpb25WMSR2b2ljZWQudW52b2ljZWQpLCBsYWJlbHM9YygiVm9pY2VsZXNzIiwiVm9pY2VkIikpICsNCiAgZmFjZXRfd3JhcCh+c2luZ0dlbSxuY29sPTEsbGFiZWxsZXI9bGFiZWxsZXIoc2luZ0dlbSA9IGxhYmVscykpDQpnZ2R1clYxQnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIHByZWNlZGluZyB2b3dlbCBkdXJhdGlvbiBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uVjEgJT4lIGdyb3VwX2J5KHNpbmdHZW06dm9pY2VkLnVudm9pY2VkKSAlPiUgc3VtbWFyaXNlKG1lYW4oZml0dGVkX2R1cmF0aW9uVjEpLCBzZChmaXR0ZWRfZHVyYXRpb25WMSkpDQpgYGANCg0KIyMjIyMgUGFpcndpc2UgdC10ZXN0IHdpdGggRkRSIGNvcnJlY3Rpb25zDQoNCldlIHVzZWQgdGhlIHBhaXJ3aXNlIHQtdGVzdCBhcyBhdmFpbGFibGUgaW4gYmFzZSBSLiBUaGUgaW5wdXQgd2FzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gSXQgd2FzIG5vdCBwb3NzaWJsZSB0byBkaXJlY3RseSB1c2Ugb3VyIHN0YXRpc3RpY2FsIG1vZGVsJ3Mgb3V0cHV0IHRvIGNvbXBhcmUgbW9kZWxzLCBnaXZlbiB0aGF0IG91ciBMTU0gbW9kZWwgd2FzIGxvb2tpbmcgYXQgb3ZlcmFsbCBjaGFuZ2UgYXMgYSBtYWluIGVmZmVjdCByYXRoZXIgdGhhbiBhcyBhIHNpbXBsZSBlZmZlY3QncyBtb2RlbC4gVGhpcyBpcyB3aHkgd2UgaGF2ZSB1c2VkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbDsgdGhlIHJlc3VsdHMgYXJlIHRoZSBzYW1lIGlmIHdlIHdlcmUgdG8gdXNlIHRoZSAiYWN0dWFsIiByZXN1bHRzIHJhdGhlciB0aGFuIHRoZSBwcmVkaWN0ZWQgb25lcy4gDQpXZSB1c2VkIEZEUiAoZm9yIEZhbHNlIERpc2NvdmVyeSBSYXRlKSBjb3JyZWN0aW9uIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucyBhcyB0aGlzIGFsbG93ZWQgZm9yIGNvcnJlY3RpbmcgZm9yIGJpYXMgaW4gdGhlIGRpZmZlcmVuY2VzIGluIGRvaW5nIG11bHRpcGxlIGNvbXBhcmlzb25zLiANCg0KYGBge3J9DQpwYWlyd2lzZS50LnRlc3QoZ2VtaW5hdGlvblYxJGZpdHRlZF9kdXJhdGlvblYxLCBnZW1pbmF0aW9uVjEkc2luZ0dlbTpnZW1pbmF0aW9uVjEkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCiMjIyBEdXJhdGlvbiBvZiB0aGUgQ2xvc3VyZSBEdXJhdGlvbiAoQ0QpDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KZHVyYXRpb25DRC54bWRsLkZ1bGwuTSA8LSBsbWVyKGR1cmF0aW9ufnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25Db25zLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQpkdXJhdGlvbkNELnhtZGwuRnVsbC5SIDwtIGxtZXIoZHVyYXRpb25+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvbkNvbnMsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjIE51bGwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmR1cmF0aW9uQ0QueG1kbC5OdWxsLk0gPC0gbG1lcihkdXJhdGlvbn4xKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvbkNvbnMsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShkdXJhdGlvbkNELnhtZGwuTnVsbC5NLGR1cmF0aW9uQ0QueG1kbC5GdWxsLk0pDQpgYGANCg0KQXMgY2FuIGJlIHNlZW4sIG91ciBvcHRpbWFsIG1vZGVsIGltcHJvdmVkIHRoZSBtb2RlbCBmaXQuDQoNCiMjIyMjIFJlc2lkdWFscw0KDQpXZSBpbnNwZWN0IG91ciBtb2RlbCBiZWxvdywgYnkgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLiBUaGVyZSBhcmUgbWlub3IgZGV2aWF0aW9ucyBvYnNlcnZlZCwgZHVlIHRvIHRoZSBuYXR1cmUgb2Ygb3VyIGRhdGEuDQoNCmBgYHtyfQ0KaGlzdChyZXNpZHVhbHMoZHVyYXRpb25DRC54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGR1cmF0aW9uQ0QueG1kbC5GdWxsLlIpKTsgcXFsaW5lKHJlc2lkdWFscyhkdXJhdGlvbkNELnhtZGwuRnVsbC5SKSkNCnBsb3QoZml0dGVkKGR1cmF0aW9uQ0QueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhkdXJhdGlvbkNELnhtZGwuRnVsbC5SKSwgY2V4ID0gNCkNCmBgYA0KDQojIyMjIyBTdW1tYXJ5IG9mIG1vZGVsDQoNCmBgYHtyfQ0Kc3VtbWFyeShkdXJhdGlvbkNELnhtZGwuRnVsbC5SKQ0KYGBgDQoNCiMjIyMgRmlndXJlcw0KDQpUaGUgZmlndXJlIHByZXNlbnRlZCBiZWxvdywgdXNlcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlczsgdGhlc2UgYXJlIHRoZSB2YWx1ZXMgKmFkanVzdGVkKiBieSB0aGUgc3RhdGlzdGljYWwgbW9kZWwuIFRoZXNlIHRha2UgaW50byBhY2NvdW50IHRoZSByYW5kb20gZWZmZWN0cycgc3RydWN0dXJlIGFzIHdlbGwgYXMgdGhlIGZpeGVkIGVmZmVjdHMnIHN0cnVjdHVyZS4gDQoNCiMjIyMjIFVzaW5nICJwcmVkaWN0Ig0KDQpUaGUgZm9sbG93aW5nIGNvZGUgaXMgdXNlZCB0byByZWNvcmQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgaW50byB0aGUgc2FtZSBkYXRhLWZyYW1lLiBUaGlzIHdpbGwgdGhlbiBiZSB1c2VkIHRvIHBsb3QgdGhlIHJlc3VsdHMgb2YgdGhlIG1vZGVsDQoNCmBgYHtyfQ0KZ2VtaW5hdGlvbkNvbnMkZml0dGVkX2R1cmF0aW9uQ0QgPC0gcHJlZGljdChsbWVyKGR1cmF0aW9ufnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25Db25zLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQopDQpgYGANCg0KDQojIyMjIyBQbG90dGluZyB0aGUgcmVzdWx0cw0KDQpXZSB1c2UgImdncGxvdDIiIHRvIHBsb3QgdGhlIHJlc3VsdHMuIFRoaXMgd2lsbCB1c2UgdGhlICJwcmVkaWN0ZWQiIChvciBmaXR0ZWQpIHZhbHVlcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIFRoZSBkYXNoZWQgbGluZXMgKndpdGhpbiogdGhlIGJveHBsb3RzIGFyZSB0aGUgbWVhbiB2YWx1ZXM7IHRoZSBtZWRpYW4gaXMgbWFya2VkIGJ5IHRoZSBob3Jpem9udGFsIHN0cmFpZ2h0IGxpbmVzLg0KDQpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQ0KbGFiZWxzIDwtIGMoc2luZ2xldG9uID0gIlNpbmdsZXRvbiIsIGdlbWluYXRlID0gIkdlbWluYXRlIikNCg0KZ2dkdXJDREJ5Vm9pY2UgPC0gZ2dwbG90KGdlbWluYXRpb25Db25zLCBhZXMoeT1maXR0ZWRfZHVyYXRpb25DRCwgeD12b2ljZWQudW52b2ljZWQpKSArIA0KICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAiTkEiLG5hLnJtPVRSVUUpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICJlcnJvcmJhciIsIGFlcyh5bWF4ID0gLi55Li4sIHltaW4gPSAuLnkuLiksDQogICAgICAgICAgICAgICB3aWR0aCA9IC43NSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB5bGFiKGV4cHJlc3Npb24ocGFzdGUoIkR1cmF0aW9uIChtcykiKSkpICsgbGFicyh0aXRsZSA9ICJDRCIpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDI1LDMyNSkpICsNCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0yMCkpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9bGV2ZWxzKGdlbWluYXRpb25Db25zJHZvaWNlZC51bnZvaWNlZCksIGxhYmVscz1jKCJWb2ljZWxlc3MiLCJWb2ljZWQiKSkgKw0KICBmYWNldF93cmFwKH5zaW5nR2VtLG5jb2w9MSxsYWJlbGxlcj1sYWJlbGxlcihzaW5nR2VtID0gbGFiZWxzKSkNCmdnZHVyQ0RCeVZvaWNlDQpgYGANCg0KIyMjIyBQYWlyd2lzZSBjb21wYXJpc29ucw0KDQpBZnRlciBydW5uaW5nIG91ciBzdGF0aXN0aWNhbCBtb2RlbCBhYm92ZSwgd2Ugd2FudGVkIHRvIGV2YWx1YXRlIHdoZXRoZXIgdGhlIGRpZmZlcmVuY2VzIG9ic2VydmVkIGJldHdlZW4gInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCAob3Igbm90KS4gV2UgcHJlc2VudCB0aGUgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgZm9yIGVhY2ggb2YgdGhlIGZvdXItd2F5IGNvbnRyYXN0IGJhc2VkIG9uIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzLg0KDQojIyMjIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzDQoNClRoZSBwcmVkaWN0ZWQgbWVhbnMgYW5kIFNEcyBvZiB0aGUgY2xvc3VyZSBkdXJhdGlvbiBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uQ29ucyAlPiUgZ3JvdXBfYnkoc2luZ0dlbTp2b2ljZWQudW52b2ljZWQpICU+JSBzdW1tYXJpc2UobWVhbihmaXR0ZWRfZHVyYXRpb25DRCksIHNkKGZpdHRlZF9kdXJhdGlvbkNEKSkNCmBgYA0KDQojIyMjIyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBGRFIgY29ycmVjdGlvbnMNCg0KV2UgdXNlZCB0aGUgcGFpcndpc2UgdC10ZXN0IGFzIGF2YWlsYWJsZSBpbiBiYXNlIFIuIFRoZSBpbnB1dCB3YXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGRpcmVjdGx5IHVzZSBvdXIgc3RhdGlzdGljYWwgbW9kZWwncyBvdXRwdXQgdG8gY29tcGFyZSBtb2RlbHMsIGdpdmVuIHRoYXQgb3VyIExNTSBtb2RlbCB3YXMgbG9va2luZyBhdCBvdmVyYWxsIGNoYW5nZSBhcyBhIG1haW4gZWZmZWN0IHJhdGhlciB0aGFuIGFzIGEgc2ltcGxlIGVmZmVjdCdzIG1vZGVsLiBUaGlzIGlzIHdoeSB3ZSBoYXZlIHVzZWQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsOyB0aGUgcmVzdWx0cyBhcmUgdGhlIHNhbWUgaWYgd2Ugd2VyZSB0byB1c2UgdGhlICJhY3R1YWwiIHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhlIHByZWRpY3RlZCBvbmVzLiANCldlIHVzZWQgRkRSIChmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUpIGNvcnJlY3Rpb24gZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIGFzIHRoaXMgYWxsb3dlZCBmb3IgY29ycmVjdGluZyBmb3IgYmlhcyBpbiB0aGUgZGlmZmVyZW5jZXMgaW4gZG9pbmcgbXVsdGlwbGUgY29tcGFyaXNvbnMuIA0KDQpgYGB7cn0NCnBhaXJ3aXNlLnQudGVzdChnZW1pbmF0aW9uQ29ucyRmaXR0ZWRfZHVyYXRpb25DRCwgZ2VtaW5hdGlvbkNvbnMkc2luZ0dlbTpnZW1pbmF0aW9uQ29ucyR2b2ljZWQudW52b2ljZWQsIHAuYWRqID0gImZkciIpDQpgYGANCg0KIyMjIER1cmF0aW9uIG9mIHRoZSBSZWxlYXNlIFBoYXNlIChSZWwpDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KZHVyYXRpb25SZWwueG1kbC5GdWxsLk0gPC0gbG1lcihkdXJhdGlvbn52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVk9ULG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQpkdXJhdGlvblJlbC54bWRsLkZ1bGwuUiA8LSBsbWVyKGR1cmF0aW9ufnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjIE51bGwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmR1cmF0aW9uUmVsLnhtZGwuTnVsbC5NIDwtIGxtZXIoZHVyYXRpb25+MSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShkdXJhdGlvblJlbC54bWRsLk51bGwuTSxkdXJhdGlvblJlbC54bWRsLkZ1bGwuTSkNCmBgYA0KDQpBcyBjYW4gYmUgc2Vlbiwgb3VyIG9wdGltYWwgbW9kZWwgaW1wcm92ZWQgdGhlIG1vZGVsIGZpdC4NCg0KIyMjIyMgUmVzaWR1YWxzDQoNCldlIGluc3BlY3Qgb3VyIG1vZGVsIGJlbG93LCBieSBsb29raW5nIGF0IHRoZSByZXNpZHVhbHMuIFRoZXJlIGFyZSBtaW5vciBkZXZpYXRpb25zIG9ic2VydmVkLCBkdWUgdG8gdGhlIG5hdHVyZSBvZiBvdXIgZGF0YS4NCg0KYGBge3J9DQpoaXN0KHJlc2lkdWFscyhkdXJhdGlvblJlbC54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGR1cmF0aW9uUmVsLnhtZGwuRnVsbC5SKSk7IHFxbGluZShyZXNpZHVhbHMoZHVyYXRpb25SZWwueG1kbC5GdWxsLlIpKQ0KcGxvdChmaXR0ZWQoZHVyYXRpb25SZWwueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhkdXJhdGlvblJlbC54bWRsLkZ1bGwuUiksIGNleCA9IDQpDQpgYGANCg0KIyMjIyMgU3VtbWFyeSBvZiBtb2RlbA0KDQpgYGB7cn0NCnN1bW1hcnkoZHVyYXRpb25SZWwueG1kbC5GdWxsLlIpDQpgYGANCg0KIyMjIyBGaWd1cmVzDQoNClRoZSBmaWd1cmUgcHJlc2VudGVkIGJlbG93LCB1c2VzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzOyB0aGVzZSBhcmUgdGhlIHZhbHVlcyAqYWRqdXN0ZWQqIGJ5IHRoZSBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlc2UgdGFrZSBpbnRvIGFjY291bnQgdGhlIHJhbmRvbSBlZmZlY3RzJyBzdHJ1Y3R1cmUgYXMgd2VsbCBhcyB0aGUgZml4ZWQgZWZmZWN0cycgc3RydWN0dXJlLiANCg0KIyMjIyMgVXNpbmcgInByZWRpY3QiDQoNClRoZSBmb2xsb3dpbmcgY29kZSBpcyB1c2VkIHRvIHJlY29yZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBpbnRvIHRoZSBzYW1lIGRhdGEtZnJhbWUuIFRoaXMgd2lsbCB0aGVuIGJlIHVzZWQgdG8gcGxvdCB0aGUgcmVzdWx0cyBvZiB0aGUgbW9kZWwNCg0KYGBge3J9DQpnZW1pbmF0aW9uVk9UJGZpdHRlZF9kdXJhdGlvblJlbCA8LSBwcmVkaWN0KGxtZXIoZHVyYXRpb25+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblZPVCxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KKQ0KYGBgDQoNCg0KIyMjIyMgUGxvdHRpbmcgdGhlIHJlc3VsdHMNCg0KV2UgdXNlICJnZ3Bsb3QyIiB0byBwbG90IHRoZSByZXN1bHRzLiBUaGlzIHdpbGwgdXNlIHRoZSAicHJlZGljdGVkIiAob3IgZml0dGVkKSB2YWx1ZXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGUgZGFzaGVkIGxpbmVzICp3aXRoaW4qIHRoZSBib3hwbG90cyBhcmUgdGhlIG1lYW4gdmFsdWVzOyB0aGUgbWVkaWFuIGlzIG1hcmtlZCBieSB0aGUgaG9yaXpvbnRhbCBzdHJhaWdodCBsaW5lcy4NCg0KYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9Nn0NCmxhYmVscyA8LSBjKHNpbmdsZXRvbiA9ICJTaW5nbGV0b24iLCBnZW1pbmF0ZSA9ICJHZW1pbmF0ZSIpDQoNCmdnZHVyUmVsQnlWb2ljZSA8LSBnZ3Bsb3QoZ2VtaW5hdGlvblZPVCwgYWVzKHk9Zml0dGVkX2R1cmF0aW9uUmVsLCB4PXZvaWNlZC51bnZvaWNlZCkpICsgDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJOQSIsbmEucm09VFJVRSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImVycm9yYmFyIiwgYWVzKHltYXggPSAuLnkuLiwgeW1pbiA9IC4ueS4uKSwNCiAgICAgICAgICAgICAgIHdpZHRoID0gLjc1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHlsYWIoZXhwcmVzc2lvbihwYXN0ZSgiRHVyYXRpb24gKG1zKSIpKSkgKyBsYWJzKHRpdGxlID0gIlJlbCIpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsNjApKSArDQogIHRoZW1lX3NldCh0aGVtZV9idygpKSArIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArDQogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArDQogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzPWxldmVscyhnZW1pbmF0aW9uVk9UJHZvaWNlZC51bnZvaWNlZCksIGxhYmVscz1jKCJWb2ljZWxlc3MiLCJWb2ljZWQiKSkgKw0KICBmYWNldF93cmFwKH5zaW5nR2VtLG5jb2w9MSxsYWJlbGxlcj1sYWJlbGxlcihzaW5nR2VtID0gbGFiZWxzKSkNCmdnZHVyUmVsQnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIGR1cmF0aW9uIG9mIHRoZSByZWxlYXNlIHBoYXNlIGFyZSBwcm92aWRlZCBiZWxvdy4gQXMgY2FuIGJlIHNlZW4sIHRoZXJlIGFyZSBhbHJlYWR5IGRpZmZlcmVuY2VzIG9ic2VydmVkIHJlbGF0ZWQgdG8gYm90aCAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIi4NCg0KYGBge3J9DQojIHVzaW5nICJkcGx5ciINCmdlbWluYXRpb25WT1QgJT4lIGdyb3VwX2J5KHNpbmdHZW06dm9pY2VkLnVudm9pY2VkKSAlPiUgc3VtbWFyaXNlKG1lYW4oZml0dGVkX2R1cmF0aW9uUmVsKSwgc2QoZml0dGVkX2R1cmF0aW9uUmVsKSkNCmBgYA0KDQojIyMjIyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBGRFIgY29ycmVjdGlvbnMNCg0KV2UgdXNlZCB0aGUgcGFpcndpc2UgdC10ZXN0IGFzIGF2YWlsYWJsZSBpbiBiYXNlIFIuIFRoZSBpbnB1dCB3YXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGRpcmVjdGx5IHVzZSBvdXIgc3RhdGlzdGljYWwgbW9kZWwncyBvdXRwdXQgdG8gY29tcGFyZSBtb2RlbHMsIGdpdmVuIHRoYXQgb3VyIExNTSBtb2RlbCB3YXMgbG9va2luZyBhdCBvdmVyYWxsIGNoYW5nZSBhcyBhIG1haW4gZWZmZWN0IHJhdGhlciB0aGFuIGFzIGEgc2ltcGxlIGVmZmVjdCdzIG1vZGVsLiBUaGlzIGlzIHdoeSB3ZSBoYXZlIHVzZWQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsOyB0aGUgcmVzdWx0cyBhcmUgdGhlIHNhbWUgaWYgd2Ugd2VyZSB0byB1c2UgdGhlICJhY3R1YWwiIHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhlIHByZWRpY3RlZCBvbmVzLiANCldlIHVzZWQgRkRSIChmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUpIGNvcnJlY3Rpb24gZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIGFzIHRoaXMgYWxsb3dlZCBmb3IgY29ycmVjdGluZyBmb3IgYmlhcyBpbiB0aGUgZGlmZmVyZW5jZXMgaW4gZG9pbmcgbXVsdGlwbGUgY29tcGFyaXNvbnMuIA0KDQpgYGB7cn0NCnBhaXJ3aXNlLnQudGVzdChnZW1pbmF0aW9uVk9UJGZpdHRlZF9kdXJhdGlvblJlbCwgZ2VtaW5hdGlvblZPVCRzaW5nR2VtOmdlbWluYXRpb25WT1Qkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCiMjIyBEdXJhdGlvbiBvZiB0aGUgQnVyc3QgcGhhc2UgKEIpDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KZHVyYXRpb25CLnhtZGwuRnVsbC5NIDwtIGxtZXIoZHVyYXRpb25CdXJzdH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVk9ULG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQpkdXJhdGlvbkIueG1kbC5GdWxsLlIgPC0gbG1lcihkdXJhdGlvbkJ1cnN0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjIE51bGwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmR1cmF0aW9uQi54bWRsLk51bGwuTSA8LSBsbWVyKGR1cmF0aW9uQnVyc3R+MSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShkdXJhdGlvbkIueG1kbC5OdWxsLk0sZHVyYXRpb25CLnhtZGwuRnVsbC5NKQ0KYGBgDQoNCkFzIGNhbiBiZSBzZWVuLCBvdXIgb3B0aW1hbCBtb2RlbCBpbXByb3ZlZCB0aGUgbW9kZWwgZml0Lg0KDQojIyMjIyBSZXNpZHVhbHMNCg0KV2UgaW5zcGVjdCBvdXIgbW9kZWwgYmVsb3csIGJ5IGxvb2tpbmcgYXQgdGhlIHJlc2lkdWFscy4gVGhlcmUgYXJlIG1pbm9yIGRldmlhdGlvbnMgb2JzZXJ2ZWQsIGR1ZSB0byB0aGUgbmF0dXJlIG9mIG91ciBkYXRhLg0KDQpgYGB7cn0NCmhpc3QocmVzaWR1YWxzKGR1cmF0aW9uQi54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGR1cmF0aW9uQi54bWRsLkZ1bGwuUikpOyBxcWxpbmUocmVzaWR1YWxzKGR1cmF0aW9uQi54bWRsLkZ1bGwuUikpDQpwbG90KGZpdHRlZChkdXJhdGlvbkIueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhkdXJhdGlvbkIueG1kbC5GdWxsLlIpLCBjZXggPSA0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgbW9kZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGR1cmF0aW9uQi54bWRsLkZ1bGwuUikNCmBgYA0KDQojIyMjIEZpZ3VyZXMNCg0KVGhlIGZpZ3VyZSBwcmVzZW50ZWQgYmVsb3csIHVzZXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXM7IHRoZXNlIGFyZSB0aGUgdmFsdWVzICphZGp1c3RlZCogYnkgdGhlIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGVzZSB0YWtlIGludG8gYWNjb3VudCB0aGUgcmFuZG9tIGVmZmVjdHMnIHN0cnVjdHVyZSBhcyB3ZWxsIGFzIHRoZSBmaXhlZCBlZmZlY3RzJyBzdHJ1Y3R1cmUuIA0KDQojIyMjIyBVc2luZyAicHJlZGljdCINCg0KVGhlIGZvbGxvd2luZyBjb2RlIGlzIHVzZWQgdG8gcmVjb3JkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGludG8gdGhlIHNhbWUgZGF0YS1mcmFtZS4gVGhpcyB3aWxsIHRoZW4gYmUgdXNlZCB0byBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbA0KDQpgYGB7cn0NCmdlbWluYXRpb25WT1QkZml0dGVkX2R1cmF0aW9uQnVyc3QgPC0gcHJlZGljdChsbWVyKGR1cmF0aW9uQnVyc3R+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblZPVCxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KKQ0KYGBgDQoNCg0KIyMjIyMgUGxvdHRpbmcgdGhlIHJlc3VsdHMNCg0KV2UgdXNlICJnZ3Bsb3QyIiB0byBwbG90IHRoZSByZXN1bHRzLiBUaGlzIHdpbGwgdXNlIHRoZSAicHJlZGljdGVkIiAob3IgZml0dGVkKSB2YWx1ZXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGUgZGFzaGVkIGxpbmVzICp3aXRoaW4qIHRoZSBib3hwbG90cyBhcmUgdGhlIG1lYW4gdmFsdWVzOyB0aGUgbWVkaWFuIGlzIG1hcmtlZCBieSB0aGUgaG9yaXpvbnRhbCBzdHJhaWdodCBsaW5lcy4NCg0KYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9Nn0NCmxhYmVscyA8LSBjKHNpbmdsZXRvbiA9ICJTaW5nbGV0b24iLCBnZW1pbmF0ZSA9ICJHZW1pbmF0ZSIpDQoNCmdnZHVyQkJ5Vm9pY2UgPC0gZ2dwbG90KGdlbWluYXRpb25WT1QsIGFlcyh5PWZpdHRlZF9kdXJhdGlvbkJ1cnN0LCB4PXZvaWNlZC51bnZvaWNlZCkpICsgDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJOQSIsbmEucm09VFJVRSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImVycm9yYmFyIiwgYWVzKHltYXggPSAuLnkuLiwgeW1pbiA9IC4ueS4uKSwNCiAgICAgICAgICAgICAgIHdpZHRoID0gLjc1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHlsYWIoZXhwcmVzc2lvbihwYXN0ZSgiRHVyYXRpb24gKG1zKSIpKSkgKyBsYWJzKHRpdGxlID0gIkIiKSArDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygyLjUsMTcuNSkpICsNCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0yMCkpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9bGV2ZWxzKGdlbWluYXRpb25WT1Qkdm9pY2VkLnVudm9pY2VkKSwgbGFiZWxzPWMoIlZvaWNlbGVzcyIsIlZvaWNlZCIpKSArDQogIGZhY2V0X3dyYXAofnNpbmdHZW0sbmNvbD0xLGxhYmVsbGVyPWxhYmVsbGVyKHNpbmdHZW0gPSBsYWJlbHMpKQ0KZ2dkdXJCQnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIGR1cmF0aW9uIG9mIHRoZSBCdXJzdCBwaGFzZSBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uVk9UICU+JSBncm91cF9ieShzaW5nR2VtOnZvaWNlZC51bnZvaWNlZCkgJT4lIHN1bW1hcmlzZShtZWFuKGZpdHRlZF9kdXJhdGlvbkJ1cnN0LG5hLnJtID0gVCksIHNkKGZpdHRlZF9kdXJhdGlvbkJ1cnN0LG5hLnJtID0gVCkpDQpgYGANCg0KIyMjIyMgUGFpcndpc2UgdC10ZXN0IHdpdGggRkRSIGNvcnJlY3Rpb25zDQoNCldlIHVzZWQgdGhlIHBhaXJ3aXNlIHQtdGVzdCBhcyBhdmFpbGFibGUgaW4gYmFzZSBSLiBUaGUgaW5wdXQgd2FzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gSXQgd2FzIG5vdCBwb3NzaWJsZSB0byBkaXJlY3RseSB1c2Ugb3VyIHN0YXRpc3RpY2FsIG1vZGVsJ3Mgb3V0cHV0IHRvIGNvbXBhcmUgbW9kZWxzLCBnaXZlbiB0aGF0IG91ciBMTU0gbW9kZWwgd2FzIGxvb2tpbmcgYXQgb3ZlcmFsbCBjaGFuZ2UgYXMgYSBtYWluIGVmZmVjdCByYXRoZXIgdGhhbiBhcyBhIHNpbXBsZSBlZmZlY3QncyBtb2RlbC4gVGhpcyBpcyB3aHkgd2UgaGF2ZSB1c2VkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbDsgdGhlIHJlc3VsdHMgYXJlIHRoZSBzYW1lIGlmIHdlIHdlcmUgdG8gdXNlIHRoZSAiYWN0dWFsIiByZXN1bHRzIHJhdGhlciB0aGFuIHRoZSBwcmVkaWN0ZWQgb25lcy4gDQpXZSB1c2VkIEZEUiAoZm9yIEZhbHNlIERpc2NvdmVyeSBSYXRlKSBjb3JyZWN0aW9uIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucyBhcyB0aGlzIGFsbG93ZWQgZm9yIGNvcnJlY3RpbmcgZm9yIGJpYXMgaW4gdGhlIGRpZmZlcmVuY2VzIGluIGRvaW5nIG11bHRpcGxlIGNvbXBhcmlzb25zLiANCg0KYGBge3J9DQpwYWlyd2lzZS50LnRlc3QoZ2VtaW5hdGlvblZPVCRmaXR0ZWRfZHVyYXRpb25CdXJzdCwgZ2VtaW5hdGlvblZPVCRzaW5nR2VtOmdlbWluYXRpb25WT1Qkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCiMjIyBEdXJhdGlvbiBvZiB0aGUgQXNwaXJhdGlvbiBwaGFzZSAoQXNwKQ0KDQojIyMjIE1vZGVsIHNwZWNpZmljYXRpb24NCg0KV2UgcnVuIHRocmVlIG1vZGVscy4gRm9yIG1vZGVsIGNvbXBhcmlzb25zLCB3ZSBhcmUgcmVxdWlyZWQgdG8gdXNlIE1heGltdW0gTGlrZWxpaG9vZCAoTUwpIG9uIGJvdGggT3B0aW1hbCBhbmQgTnVsbCBtb2RlbHMgKGJ5IGFkZGluZyBSRU1MPUYpLiBUaGVuIHdlIHJ1biBhIHNlY29uZCBPcHRpbWFsIG1vZGVscyB3aXRoIFJlc3RyaWN0ZWQgTWF4aW11bSBMaWtlbGlob29kIChSRU1MKSwgdG8gb2J0YWluIHRoZSBjb2VmZmljaWVudHMgKGJ5IGFkZGluZyBSRU1MPVQpDQoNCiMjIyMjIE9wdGltYWwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmR1cmF0aW9uQXNwLnhtZGwuRnVsbC5NIDwtIGxtZXIoZHVyYXRpb25Bc3B+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblZPVCxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgIE9wdGltYWwgbW9kZWwgKFJFTUwpDQoNCmBgYHtyfQ0KZHVyYXRpb25Bc3AueG1kbC5GdWxsLlIgPC0gbG1lcihkdXJhdGlvbkFzcH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVk9ULG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyBOdWxsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpkdXJhdGlvbkFzcC54bWRsLk51bGwuTSA8LSBsbWVyKGR1cmF0aW9uQXNwfjErDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVk9ULG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIFJlc3VsdHMgb2Ygb3VyIG1vZGVsDQoNCiMjIyMjIE1vZGVsIGNvbXBhcmlzb25zDQoNCmBgYHtyfQ0KYW5vdmEoZHVyYXRpb25Bc3AueG1kbC5OdWxsLk0sZHVyYXRpb25Bc3AueG1kbC5GdWxsLk0pDQpgYGANCg0KQXMgY2FuIGJlIHNlZW4sIG91ciBvcHRpbWFsIG1vZGVsIGltcHJvdmVkIHRoZSBtb2RlbCBmaXQuDQoNCiMjIyMjIFJlc2lkdWFscw0KDQpXZSBpbnNwZWN0IG91ciBtb2RlbCBiZWxvdywgYnkgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLiBUaGVyZSBhcmUgbWlub3IgZGV2aWF0aW9ucyBvYnNlcnZlZCwgZHVlIHRvIHRoZSBuYXR1cmUgb2Ygb3VyIGRhdGEuDQoNCmBgYHtyfQ0KaGlzdChyZXNpZHVhbHMoZHVyYXRpb25Bc3AueG1kbC5GdWxsLlIpKQ0KcXFub3JtKHJlc2lkdWFscyhkdXJhdGlvbkFzcC54bWRsLkZ1bGwuUikpOyBxcWxpbmUocmVzaWR1YWxzKGR1cmF0aW9uQXNwLnhtZGwuRnVsbC5SKSkNCnBsb3QoZml0dGVkKGR1cmF0aW9uQXNwLnhtZGwuRnVsbC5SKSxyZXNpZHVhbHMoZHVyYXRpb25Bc3AueG1kbC5GdWxsLlIpLCBjZXggPSA0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgbW9kZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGR1cmF0aW9uQXNwLnhtZGwuRnVsbC5SKQ0KYGBgDQoNCiMjIyMgRmlndXJlcw0KDQpUaGUgZmlndXJlIHByZXNlbnRlZCBiZWxvdywgdXNlcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlczsgdGhlc2UgYXJlIHRoZSB2YWx1ZXMgKmFkanVzdGVkKiBieSB0aGUgc3RhdGlzdGljYWwgbW9kZWwuIFRoZXNlIHRha2UgaW50byBhY2NvdW50IHRoZSByYW5kb20gZWZmZWN0cycgc3RydWN0dXJlIGFzIHdlbGwgYXMgdGhlIGZpeGVkIGVmZmVjdHMnIHN0cnVjdHVyZS4gDQoNCiMjIyMjIFVzaW5nICJwcmVkaWN0Ig0KDQpUaGUgZm9sbG93aW5nIGNvZGUgaXMgdXNlZCB0byByZWNvcmQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgaW50byB0aGUgc2FtZSBkYXRhLWZyYW1lLiBUaGlzIHdpbGwgdGhlbiBiZSB1c2VkIHRvIHBsb3QgdGhlIHJlc3VsdHMgb2YgdGhlIG1vZGVsDQoNCmBgYHtyfQ0KZ2VtaW5hdGlvblZPVCRmaXR0ZWRfZHVyYXRpb25Bc3AgPC0gcHJlZGljdChsbWVyKGR1cmF0aW9uQXNwfnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCikNCmBgYA0KDQoNCiMjIyMjIFBsb3R0aW5nIHRoZSByZXN1bHRzDQoNCldlIHVzZSAiZ2dwbG90MiIgdG8gcGxvdCB0aGUgcmVzdWx0cy4gVGhpcyB3aWxsIHVzZSB0aGUgInByZWRpY3RlZCIgKG9yIGZpdHRlZCkgdmFsdWVzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlIGRhc2hlZCBsaW5lcyAqd2l0aGluKiB0aGUgYm94cGxvdHMgYXJlIHRoZSBtZWFuIHZhbHVlczsgdGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgdGhlIGhvcml6b250YWwgc3RyYWlnaHQgbGluZXMuDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQpsYWJlbHMgPC0gYyhzaW5nbGV0b24gPSAiU2luZ2xldG9uIiwgZ2VtaW5hdGUgPSAiR2VtaW5hdGUiKQ0KDQpnZ2R1ckFzcEJ5Vm9pY2UgPC0gZ2dwbG90KGdlbWluYXRpb25WT1QsIGFlcyh5PWZpdHRlZF9kdXJhdGlvbkFzcCwgeD12b2ljZWQudW52b2ljZWQpKSArIA0KICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAiTkEiLG5hLnJtPVRSVUUpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICJlcnJvcmJhciIsIGFlcyh5bWF4ID0gLi55Li4sIHltaW4gPSAuLnkuLiksDQogICAgICAgICAgICAgICB3aWR0aCA9IC43NSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB5bGFiKGV4cHJlc3Npb24ocGFzdGUoIkR1cmF0aW9uIChtcykiKSkpICsgbGFicyh0aXRsZSA9ICJBc3AiKSArDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDQwKSkgKw0KICB0aGVtZV9zZXQodGhlbWVfYncoKSkgKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1sZXZlbHMoZ2VtaW5hdGlvblZPVCR2b2ljZWQudW52b2ljZWQpLCBsYWJlbHM9YygiVm9pY2VsZXNzIiwiVm9pY2VkIikpICsNCiAgZmFjZXRfd3JhcCh+c2luZ0dlbSxuY29sPTEsbGFiZWxsZXI9bGFiZWxsZXIoc2luZ0dlbSA9IGxhYmVscykpDQpnZ2R1ckFzcEJ5Vm9pY2UNCmBgYA0KDQojIyMjIFBhaXJ3aXNlIGNvbXBhcmlzb25zDQoNCkFmdGVyIHJ1bm5pbmcgb3VyIHN0YXRpc3RpY2FsIG1vZGVsIGFib3ZlLCB3ZSB3YW50ZWQgdG8gZXZhbHVhdGUgd2hldGhlciB0aGUgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgYmV0d2VlbiAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChvciBub3QpLiBXZSBwcmVzZW50IHRoZSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3IgZWFjaCBvZiB0aGUgZm91ci13YXkgY29udHJhc3QgYmFzZWQgb24gdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMuDQoNCiMjIyMjIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MNCg0KVGhlIHByZWRpY3RlZCBtZWFucyBhbmQgU0RzIG9mIHRoZSBkdXJhdGlvbiBvZiB0aGUgQXNwaXJhdGlvbiBwaGFzZSBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uVk9UICU+JSBncm91cF9ieShzaW5nR2VtOnZvaWNlZC51bnZvaWNlZCkgJT4lIHN1bW1hcmlzZShtZWFuKGZpdHRlZF9kdXJhdGlvbkFzcCxuYS5ybSA9IFQpLCBzZChmaXR0ZWRfZHVyYXRpb25Bc3AsbmEucm0gPSBUKSkNCmBgYA0KDQojIyMjIyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBGRFIgY29ycmVjdGlvbnMNCg0KV2UgdXNlZCB0aGUgcGFpcndpc2UgdC10ZXN0IGFzIGF2YWlsYWJsZSBpbiBiYXNlIFIuIFRoZSBpbnB1dCB3YXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGRpcmVjdGx5IHVzZSBvdXIgc3RhdGlzdGljYWwgbW9kZWwncyBvdXRwdXQgdG8gY29tcGFyZSBtb2RlbHMsIGdpdmVuIHRoYXQgb3VyIExNTSBtb2RlbCB3YXMgbG9va2luZyBhdCBvdmVyYWxsIGNoYW5nZSBhcyBhIG1haW4gZWZmZWN0IHJhdGhlciB0aGFuIGFzIGEgc2ltcGxlIGVmZmVjdCdzIG1vZGVsLiBUaGlzIGlzIHdoeSB3ZSBoYXZlIHVzZWQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsOyB0aGUgcmVzdWx0cyBhcmUgdGhlIHNhbWUgaWYgd2Ugd2VyZSB0byB1c2UgdGhlICJhY3R1YWwiIHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhlIHByZWRpY3RlZCBvbmVzLiANCldlIHVzZWQgRkRSIChmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUpIGNvcnJlY3Rpb24gZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIGFzIHRoaXMgYWxsb3dlZCBmb3IgY29ycmVjdGluZyBmb3IgYmlhcyBpbiB0aGUgZGlmZmVyZW5jZXMgaW4gZG9pbmcgbXVsdGlwbGUgY29tcGFyaXNvbnMuIA0KDQpgYGB7cn0NCnBhaXJ3aXNlLnQudGVzdChnZW1pbmF0aW9uVk9UJGZpdHRlZF9kdXJhdGlvbkFzcCwgZ2VtaW5hdGlvblZPVCRzaW5nR2VtOmdlbWluYXRpb25WT1Qkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCg0KIyMjIER1cmF0aW9uIG9mIHRoZSBGb2xsb3dpbmcgVm93ZWwgKFYyKQ0KDQojIyMjIE1vZGVsIHNwZWNpZmljYXRpb24NCg0KV2UgcnVuIHRocmVlIG1vZGVscy4gRm9yIG1vZGVsIGNvbXBhcmlzb25zLCB3ZSBhcmUgcmVxdWlyZWQgdG8gdXNlIE1heGltdW0gTGlrZWxpaG9vZCAoTUwpIG9uIGJvdGggT3B0aW1hbCBhbmQgTnVsbCBtb2RlbHMgKGJ5IGFkZGluZyBSRU1MPUYpLiBUaGVuIHdlIHJ1biBhIHNlY29uZCBPcHRpbWFsIG1vZGVscyB3aXRoIFJlc3RyaWN0ZWQgTWF4aW11bSBMaWtlbGlob29kIChSRU1MKSwgdG8gb2J0YWluIHRoZSBjb2VmZmljaWVudHMgKGJ5IGFkZGluZyBSRU1MPVQpDQoNCiMjIyMjIE9wdGltYWwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmR1cmF0aW9uVjIueG1kbC5GdWxsLk0gPC0gbG1lcihkdXJhdGlvbn52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjIsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjICBPcHRpbWFsIG1vZGVsIChSRU1MKQ0KDQpgYGB7cn0NCmR1cmF0aW9uVjIueG1kbC5GdWxsLlIgPC0gbG1lcihkdXJhdGlvbn52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjIsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjIE51bGwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmR1cmF0aW9uVjIueG1kbC5OdWxsLk0gPC0gbG1lcihkdXJhdGlvbn4xKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYyLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIFJlc3VsdHMgb2Ygb3VyIG1vZGVsDQoNCiMjIyMjIE1vZGVsIGNvbXBhcmlzb25zDQoNCmBgYHtyfQ0KYW5vdmEoZHVyYXRpb25WMi54bWRsLk51bGwuTSxkdXJhdGlvblYyLnhtZGwuRnVsbC5NKQ0KYGBgDQoNCkFzIGNhbiBiZSBzZWVuLCBvdXIgb3B0aW1hbCBtb2RlbCBpbXByb3ZlZCB0aGUgbW9kZWwgZml0Lg0KDQojIyMjIyBSZXNpZHVhbHMNCg0KV2UgaW5zcGVjdCBvdXIgbW9kZWwgYmVsb3csIGJ5IGxvb2tpbmcgYXQgdGhlIHJlc2lkdWFscy4gVGhlcmUgYXJlIG1pbm9yIGRldmlhdGlvbnMgb2JzZXJ2ZWQsIGR1ZSB0byB0aGUgbmF0dXJlIG9mIG91ciBkYXRhLg0KDQpgYGB7cn0NCmhpc3QocmVzaWR1YWxzKGR1cmF0aW9uVjIueG1kbC5GdWxsLlIpKQ0KcXFub3JtKHJlc2lkdWFscyhkdXJhdGlvblYyLnhtZGwuRnVsbC5SKSk7IHFxbGluZShyZXNpZHVhbHMoZHVyYXRpb25WMi54bWRsLkZ1bGwuUikpDQpwbG90KGZpdHRlZChkdXJhdGlvblYyLnhtZGwuRnVsbC5SKSxyZXNpZHVhbHMoZHVyYXRpb25WMi54bWRsLkZ1bGwuUiksIGNleCA9IDQpDQpgYGANCg0KIyMjIyMgU3VtbWFyeSBvZiBtb2RlbA0KDQpgYGB7cn0NCnN1bW1hcnkoZHVyYXRpb25WMi54bWRsLkZ1bGwuUikNCmBgYA0KDQojIyMjIEZpZ3VyZXMNCg0KVGhlIGZpZ3VyZSBwcmVzZW50ZWQgYmVsb3csIHVzZXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXM7IHRoZXNlIGFyZSB0aGUgdmFsdWVzICphZGp1c3RlZCogYnkgdGhlIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGVzZSB0YWtlIGludG8gYWNjb3VudCB0aGUgcmFuZG9tIGVmZmVjdHMnIHN0cnVjdHVyZSBhcyB3ZWxsIGFzIHRoZSBmaXhlZCBlZmZlY3RzJyBzdHJ1Y3R1cmUuIA0KDQojIyMjIyBVc2luZyAicHJlZGljdCINCg0KVGhlIGZvbGxvd2luZyBjb2RlIGlzIHVzZWQgdG8gcmVjb3JkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGludG8gdGhlIHNhbWUgZGF0YS1mcmFtZS4gVGhpcyB3aWxsIHRoZW4gYmUgdXNlZCB0byBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbA0KDQpgYGB7cn0NCmdlbWluYXRpb25WMiRmaXR0ZWRfZHVyYXRpb25WMiA8LSBwcmVkaWN0KGxtZXIoZHVyYXRpb25+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYyLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQopDQpgYGANCg0KDQojIyMjIyBQbG90dGluZyB0aGUgcmVzdWx0cw0KDQpXZSB1c2UgImdncGxvdDIiIHRvIHBsb3QgdGhlIHJlc3VsdHMuIFRoaXMgd2lsbCB1c2UgdGhlICJwcmVkaWN0ZWQiIChvciBmaXR0ZWQpIHZhbHVlcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIFRoZSBkYXNoZWQgbGluZXMgKndpdGhpbiogdGhlIGJveHBsb3RzIGFyZSB0aGUgbWVhbiB2YWx1ZXM7IHRoZSBtZWRpYW4gaXMgbWFya2VkIGJ5IHRoZSBob3Jpem9udGFsIHN0cmFpZ2h0IGxpbmVzLg0KDQpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQ0KbGFiZWxzIDwtIGMoc2luZ2xldG9uID0gIlNpbmdsZXRvbiIsIGdlbWluYXRlID0gIkdlbWluYXRlIikNCg0KZ2dkdXJWMkJ5Vm9pY2UgPC0gZ2dwbG90KGdlbWluYXRpb25WMiwgYWVzKHk9Zml0dGVkX2R1cmF0aW9uVjIsIHg9dm9pY2VkLnVudm9pY2VkKSkgKyANCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gIk5BIixuYS5ybT1UUlVFKSArDQogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAiZXJyb3JiYXIiLCBhZXMoeW1heCA9IC4ueS4uLCB5bWluID0gLi55Li4pLA0KICAgICAgICAgICAgICAgd2lkdGggPSAuNzUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgeWxhYihleHByZXNzaW9uKHBhc3RlKCJEdXJhdGlvbiAobXMpIikpKSArIGxhYnModGl0bGUgPSAiVjIiKSArDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygyNSwzMjUpKSArDQogIHRoZW1lX3NldCh0aGVtZV9idygpKSArIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArDQogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArDQogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzPWxldmVscyhnZW1pbmF0aW9uVjIkdm9pY2VkLnVudm9pY2VkKSwgbGFiZWxzPWMoIlZvaWNlbGVzcyIsIlZvaWNlZCIpKSArDQogIGZhY2V0X3dyYXAofnNpbmdHZW0sbmNvbD0xLGxhYmVsbGVyPWxhYmVsbGVyKHNpbmdHZW0gPSBsYWJlbHMpKQ0KZ2dkdXJWMkJ5Vm9pY2UNCmBgYA0KDQojIyMjIFBhaXJ3aXNlIGNvbXBhcmlzb25zDQoNCkFmdGVyIHJ1bm5pbmcgb3VyIHN0YXRpc3RpY2FsIG1vZGVsIGFib3ZlLCB3ZSB3YW50ZWQgdG8gZXZhbHVhdGUgd2hldGhlciB0aGUgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgYmV0d2VlbiAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChvciBub3QpLiBXZSBwcmVzZW50IHRoZSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3IgZWFjaCBvZiB0aGUgZm91ci13YXkgY29udHJhc3QgYmFzZWQgb24gdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMuDQoNCiMjIyMjIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MNCg0KVGhlIHByZWRpY3RlZCBtZWFucyBhbmQgU0RzIG9mIHRoZSBkdXJhdGlvbiBvZiB0aGUgZm9sbG93aW5nIHZvd2VsIChWMikgYXJlIHByb3ZpZGVkIGJlbG93LiBBcyBjYW4gYmUgc2VlbiwgdGhlcmUgYXJlIGFscmVhZHkgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgcmVsYXRlZCB0byBib3RoICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iLg0KDQpgYGB7cn0NCiMgdXNpbmcgImRwbHlyIg0KZ2VtaW5hdGlvblYyICU+JSBncm91cF9ieShzaW5nR2VtOnZvaWNlZC51bnZvaWNlZCkgJT4lIHN1bW1hcmlzZShtZWFuKGZpdHRlZF9kdXJhdGlvblYyKSwgc2QoZml0dGVkX2R1cmF0aW9uVjIpKQ0KYGBgDQoNCiMjIyMjIFBhaXJ3aXNlIHQtdGVzdCB3aXRoIEZEUiBjb3JyZWN0aW9ucw0KDQpXZSB1c2VkIHRoZSBwYWlyd2lzZSB0LXRlc3QgYXMgYXZhaWxhYmxlIGluIGJhc2UgUi4gVGhlIGlucHV0IHdhcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIEl0IHdhcyBub3QgcG9zc2libGUgdG8gZGlyZWN0bHkgdXNlIG91ciBzdGF0aXN0aWNhbCBtb2RlbCdzIG91dHB1dCB0byBjb21wYXJlIG1vZGVscywgZ2l2ZW4gdGhhdCBvdXIgTE1NIG1vZGVsIHdhcyBsb29raW5nIGF0IG92ZXJhbGwgY2hhbmdlIGFzIGEgbWFpbiBlZmZlY3QgcmF0aGVyIHRoYW4gYXMgYSBzaW1wbGUgZWZmZWN0J3MgbW9kZWwuIFRoaXMgaXMgd2h5IHdlIGhhdmUgdXNlZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWw7IHRoZSByZXN1bHRzIGFyZSB0aGUgc2FtZSBpZiB3ZSB3ZXJlIHRvIHVzZSB0aGUgImFjdHVhbCIgcmVzdWx0cyByYXRoZXIgdGhhbiB0aGUgcHJlZGljdGVkIG9uZXMuIA0KV2UgdXNlZCBGRFIgKGZvciBGYWxzZSBEaXNjb3ZlcnkgUmF0ZSkgY29ycmVjdGlvbiBmb3IgbXVsdGlwbGUgY29tcGFyaXNvbnMgYXMgdGhpcyBhbGxvd2VkIGZvciBjb3JyZWN0aW5nIGZvciBiaWFzIGluIHRoZSBkaWZmZXJlbmNlcyBpbiBkb2luZyBtdWx0aXBsZSBjb21wYXJpc29ucy4gDQoNCmBgYHtyfQ0KcGFpcndpc2UudC50ZXN0KGdlbWluYXRpb25WMiRmaXR0ZWRfZHVyYXRpb25WMiwgZ2VtaW5hdGlvblYyJHNpbmdHZW06Z2VtaW5hdGlvblYyJHZvaWNlZC51bnZvaWNlZCwgcC5hZGogPSAiZmRyIikNCmBgYA0KDQoNCiMjIFZvaWNpbmcgKG1zZWMgYW5kICUpDQoNCldpdGhpbiBWb2ljaW5nLCB3ZSBoYXZlIGNvbXB1dGVkIHRocmVlIG1ldHJpY3M6IHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBWT1QgKFZvaWNpbmcgVk9UKSwgcHJvcG9ydGlvbiBvZiB2b2ljaW5nIGluIHRoZSBjbG9zdXJlIGR1cmF0aW9uICglIFZvaWNpbmcgQ0QpIGFuZCBwcm9wb3J0aW9uIG9mIHZvaWNpbmcgaW4gdGhlIFJlbGVhc2UgUGhhc2UgKCUgVm9pY2luZyBSZWwpDQoNCiMjIyBQb3NpdGl2ZSBhbmQgTmVnYXRpdmUgVk9UIChWb2ljaW5nIFZPVCkNCg0KIyMjIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQoNCldlIHJ1biB0aHJlZSBtb2RlbHMuIEZvciBtb2RlbCBjb21wYXJpc29ucywgd2UgYXJlIHJlcXVpcmVkIHRvIHVzZSBNYXhpbXVtIExpa2VsaWhvb2QgKE1MKSBvbiBib3RoIE9wdGltYWwgYW5kIE51bGwgbW9kZWxzIChieSBhZGRpbmcgUkVNTD1GKS4gVGhlbiB3ZSBydW4gYSBzZWNvbmQgT3B0aW1hbCBtb2RlbHMgd2l0aCBSZXN0cmljdGVkIE1heGltdW0gTGlrZWxpaG9vZCAoUkVNTCksIHRvIG9idGFpbiB0aGUgY29lZmZpY2llbnRzIChieSBhZGRpbmcgUkVNTD1UKQ0KDQojIyMjIyBPcHRpbWFsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpkdXJhdGlvblZvaWNlVk9ULnhtZGwuRnVsbC5NIDwtIGxtZXIoVk9URGVjfnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25Db25zLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQpkdXJhdGlvblZvaWNlVk9ULnhtZGwuRnVsbC5SIDwtIGxtZXIoVk9URGVjfnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25Db25zLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyBOdWxsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpkdXJhdGlvblZvaWNlVk9ULnhtZGwuTnVsbC5NIDwtIGxtZXIoVk9URGVjfjErDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uQ29ucyxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyBSZXN1bHRzIG9mIG91ciBtb2RlbA0KDQojIyMjIyBNb2RlbCBjb21wYXJpc29ucw0KDQpgYGB7cn0NCmFub3ZhKGR1cmF0aW9uVm9pY2VWT1QueG1kbC5OdWxsLk0sZHVyYXRpb25Wb2ljZVZPVC54bWRsLkZ1bGwuTSkNCmBgYA0KDQpBcyBjYW4gYmUgc2Vlbiwgb3VyIG9wdGltYWwgbW9kZWwgaW1wcm92ZWQgdGhlIG1vZGVsIGZpdC4NCg0KIyMjIyMgUmVzaWR1YWxzDQoNCldlIGluc3BlY3Qgb3VyIG1vZGVsIGJlbG93LCBieSBsb29raW5nIGF0IHRoZSByZXNpZHVhbHMuIFRoZXJlIGFyZSBtaW5vciBkZXZpYXRpb25zIG9ic2VydmVkLCBkdWUgdG8gdGhlIG5hdHVyZSBvZiBvdXIgZGF0YS4NCg0KYGBge3J9DQpoaXN0KHJlc2lkdWFscyhkdXJhdGlvblZvaWNlVk9ULnhtZGwuRnVsbC5SKSkNCnFxbm9ybShyZXNpZHVhbHMoZHVyYXRpb25Wb2ljZVZPVC54bWRsLkZ1bGwuUikpOyBxcWxpbmUocmVzaWR1YWxzKGR1cmF0aW9uVm9pY2VWT1QueG1kbC5GdWxsLlIpKQ0KcGxvdChmaXR0ZWQoZHVyYXRpb25Wb2ljZVZPVC54bWRsLkZ1bGwuUikscmVzaWR1YWxzKGR1cmF0aW9uVm9pY2VWT1QueG1kbC5GdWxsLlIpLCBjZXggPSA0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgbW9kZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGR1cmF0aW9uVm9pY2VWT1QueG1kbC5GdWxsLlIpDQpgYGANCg0KIyMjIyBGaWd1cmVzDQoNClRoZSBmaWd1cmUgcHJlc2VudGVkIGJlbG93LCB1c2VzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzOyB0aGVzZSBhcmUgdGhlIHZhbHVlcyAqYWRqdXN0ZWQqIGJ5IHRoZSBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlc2UgdGFrZSBpbnRvIGFjY291bnQgdGhlIHJhbmRvbSBlZmZlY3RzJyBzdHJ1Y3R1cmUgYXMgd2VsbCBhcyB0aGUgZml4ZWQgZWZmZWN0cycgc3RydWN0dXJlLiANCg0KIyMjIyMgVXNpbmcgInByZWRpY3QiDQoNClRoZSBmb2xsb3dpbmcgY29kZSBpcyB1c2VkIHRvIHJlY29yZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBpbnRvIHRoZSBzYW1lIGRhdGEtZnJhbWUuIFRoaXMgd2lsbCB0aGVuIGJlIHVzZWQgdG8gcGxvdCB0aGUgcmVzdWx0cyBvZiB0aGUgbW9kZWwNCg0KYGBge3J9DQpnZW1pbmF0aW9uQ29ucyRmaXR0ZWRfVm9pY2VWT1QgPC0gcHJlZGljdChsbWVyKFZPVERlY352b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uQ29ucyxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KKQ0KYGBgDQoNCg0KIyMjIyMgUGxvdHRpbmcgdGhlIHJlc3VsdHMNCg0KV2UgdXNlICJnZ3Bsb3QyIiB0byBwbG90IHRoZSByZXN1bHRzLiBUaGlzIHdpbGwgdXNlIHRoZSAicHJlZGljdGVkIiAob3IgZml0dGVkKSB2YWx1ZXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGUgZGFzaGVkIGxpbmVzICp3aXRoaW4qIHRoZSBib3hwbG90cyBhcmUgdGhlIG1lYW4gdmFsdWVzOyB0aGUgbWVkaWFuIGlzIG1hcmtlZCBieSB0aGUgaG9yaXpvbnRhbCBzdHJhaWdodCBsaW5lcy4NCg0KYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9Nn0NCmxhYmVscyA8LSBjKHNpbmdsZXRvbiA9ICJTaW5nbGV0b24iLCBnZW1pbmF0ZSA9ICJHZW1pbmF0ZSIpDQoNCmdnVm9pY2VWT1RCeVZvaWNlIDwtIGdncGxvdChnZW1pbmF0aW9uQ29ucywgYWVzKHk9Zml0dGVkX1ZvaWNlVk9ULCB4PXZvaWNlZC51bnZvaWNlZCkpICsgDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJOQSIsbmEucm09VFJVRSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImVycm9yYmFyIiwgYWVzKHltYXggPSAuLnkuLiwgeW1pbiA9IC4ueS4uKSwNCiAgICAgICAgICAgICAgIHdpZHRoID0gLjc1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHlsYWIoZXhwcmVzc2lvbihwYXN0ZSgiVk9UIikpKSArIGxhYnModGl0bGUgPSAiVk9UIikgKw0KICB0aGVtZV9zZXQodGhlbWVfYncoKSkgKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1sZXZlbHMoZ2VtaW5hdGlvbkNvbnMkdm9pY2VkLnVudm9pY2VkKSwgbGFiZWxzPWMoIlZvaWNlbGVzcyIsIlZvaWNlZCIpKSArDQogIGZhY2V0X3dyYXAofnNpbmdHZW0sbmNvbD0xLGxhYmVsbGVyPWxhYmVsbGVyKHNpbmdHZW0gPSBsYWJlbHMpKQ0KZ2dWb2ljZVZPVEJ5Vm9pY2UNCmBgYA0KDQojIyMjIFBhaXJ3aXNlIGNvbXBhcmlzb25zDQoNCkFmdGVyIHJ1bm5pbmcgb3VyIHN0YXRpc3RpY2FsIG1vZGVsIGFib3ZlLCB3ZSB3YW50ZWQgdG8gZXZhbHVhdGUgd2hldGhlciB0aGUgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgYmV0d2VlbiAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChvciBub3QpLiBXZSBwcmVzZW50IHRoZSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3IgZWFjaCBvZiB0aGUgZm91ci13YXkgY29udHJhc3QgYmFzZWQgb24gdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMuDQoNCiMjIyMjIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MNCg0KVGhlIHByZWRpY3RlZCBtZWFucyBhbmQgU0RzIG9mIHRoZSBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgVk9UIChWb2ljZVZPVCkgYXJlIHByb3ZpZGVkIGJlbG93LiBBcyBjYW4gYmUgc2VlbiwgdGhlcmUgYXJlIGFscmVhZHkgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgcmVsYXRlZCB0byBib3RoICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iLg0KDQpgYGB7cn0NCiMgdXNpbmcgImRwbHlyIg0KZ2VtaW5hdGlvbkNvbnMgJT4lIGdyb3VwX2J5KHNpbmdHZW06dm9pY2VkLnVudm9pY2VkKSAlPiUgc3VtbWFyaXNlKG1lYW4oZml0dGVkX1ZvaWNlVk9UKSwgc2QoZml0dGVkX1ZvaWNlVk9UKSkNCmBgYA0KDQojIyMjIyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBGRFIgY29ycmVjdGlvbnMNCg0KV2UgdXNlZCB0aGUgcGFpcndpc2UgdC10ZXN0IGFzIGF2YWlsYWJsZSBpbiBiYXNlIFIuIFRoZSBpbnB1dCB3YXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGRpcmVjdGx5IHVzZSBvdXIgc3RhdGlzdGljYWwgbW9kZWwncyBvdXRwdXQgdG8gY29tcGFyZSBtb2RlbHMsIGdpdmVuIHRoYXQgb3VyIExNTSBtb2RlbCB3YXMgbG9va2luZyBhdCBvdmVyYWxsIGNoYW5nZSBhcyBhIG1haW4gZWZmZWN0IHJhdGhlciB0aGFuIGFzIGEgc2ltcGxlIGVmZmVjdCdzIG1vZGVsLiBUaGlzIGlzIHdoeSB3ZSBoYXZlIHVzZWQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsOyB0aGUgcmVzdWx0cyBhcmUgdGhlIHNhbWUgaWYgd2Ugd2VyZSB0byB1c2UgdGhlICJhY3R1YWwiIHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhlIHByZWRpY3RlZCBvbmVzLiANCldlIHVzZWQgRkRSIChmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUpIGNvcnJlY3Rpb24gZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIGFzIHRoaXMgYWxsb3dlZCBmb3IgY29ycmVjdGluZyBmb3IgYmlhcyBpbiB0aGUgZGlmZmVyZW5jZXMgaW4gZG9pbmcgbXVsdGlwbGUgY29tcGFyaXNvbnMuIA0KDQpgYGB7cn0NCnBhaXJ3aXNlLnQudGVzdChnZW1pbmF0aW9uQ29ucyRmaXR0ZWRfVm9pY2VWT1QsIGdlbWluYXRpb25Db25zJHNpbmdHZW06Z2VtaW5hdGlvbkNvbnMkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCg0KIyMjIFByb3BvcnRpb24gb2Ygdm9pY2luZyBpbiB0aGUgY2xvc3VyZSBkdXJhdGlvbiAoJSBWb2ljaW5nIENEKSANCg0KIyMjIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQoNCldlIHJ1biB0aHJlZSBtb2RlbHMuIEZvciBtb2RlbCBjb21wYXJpc29ucywgd2UgYXJlIHJlcXVpcmVkIHRvIHVzZSBNYXhpbXVtIExpa2VsaWhvb2QgKE1MKSBvbiBib3RoIE9wdGltYWwgYW5kIE51bGwgbW9kZWxzIChieSBhZGRpbmcgUkVNTD1GKS4gVGhlbiB3ZSBydW4gYSBzZWNvbmQgT3B0aW1hbCBtb2RlbHMgd2l0aCBSZXN0cmljdGVkIE1heGltdW0gTGlrZWxpaG9vZCAoUkVNTCksIHRvIG9idGFpbiB0aGUgY29lZmZpY2llbnRzIChieSBhZGRpbmcgUkVNTD1UKQ0KDQojIyMjIyBPcHRpbWFsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpkdXJhdGlvblByb3BWb2ljZUNELnhtZGwuRnVsbC5NIDwtIGxtZXIoZHVyYXRpb25Wb2ljZWRQZXJjfnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25Db25zLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQpkdXJhdGlvblByb3BWb2ljZUNELnhtZGwuRnVsbC5SIDwtIGxtZXIoZHVyYXRpb25Wb2ljZWRQZXJjfnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25Db25zLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyBOdWxsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpkdXJhdGlvblByb3BWb2ljZUNELnhtZGwuTnVsbC5NIDwtIGxtZXIoZHVyYXRpb25Wb2ljZWRQZXJjfjErDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uQ29ucyxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyBSZXN1bHRzIG9mIG91ciBtb2RlbA0KDQojIyMjIyBNb2RlbCBjb21wYXJpc29ucw0KDQpgYGB7cn0NCmFub3ZhKGR1cmF0aW9uUHJvcFZvaWNlQ0QueG1kbC5OdWxsLk0sZHVyYXRpb25Qcm9wVm9pY2VDRC54bWRsLkZ1bGwuTSkNCmBgYA0KDQpBcyBjYW4gYmUgc2Vlbiwgb3VyIG9wdGltYWwgbW9kZWwgaW1wcm92ZWQgdGhlIG1vZGVsIGZpdC4NCg0KIyMjIyMgUmVzaWR1YWxzDQoNCldlIGluc3BlY3Qgb3VyIG1vZGVsIGJlbG93LCBieSBsb29raW5nIGF0IHRoZSByZXNpZHVhbHMuIFRoZXJlIGFyZSBtaW5vciBkZXZpYXRpb25zIG9ic2VydmVkLCBkdWUgdG8gdGhlIG5hdHVyZSBvZiBvdXIgZGF0YS4NCg0KYGBge3J9DQpoaXN0KHJlc2lkdWFscyhkdXJhdGlvblByb3BWb2ljZUNELnhtZGwuRnVsbC5SKSkNCnFxbm9ybShyZXNpZHVhbHMoZHVyYXRpb25Qcm9wVm9pY2VDRC54bWRsLkZ1bGwuUikpOyBxcWxpbmUocmVzaWR1YWxzKGR1cmF0aW9uUHJvcFZvaWNlQ0QueG1kbC5GdWxsLlIpKQ0KcGxvdChmaXR0ZWQoZHVyYXRpb25Qcm9wVm9pY2VDRC54bWRsLkZ1bGwuUikscmVzaWR1YWxzKGR1cmF0aW9uUHJvcFZvaWNlQ0QueG1kbC5GdWxsLlIpLCBjZXggPSA0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgbW9kZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGR1cmF0aW9uUHJvcFZvaWNlQ0QueG1kbC5GdWxsLlIpDQpgYGANCg0KIyMjIyBGaWd1cmVzDQoNClRoZSBmaWd1cmUgcHJlc2VudGVkIGJlbG93LCB1c2VzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzOyB0aGVzZSBhcmUgdGhlIHZhbHVlcyAqYWRqdXN0ZWQqIGJ5IHRoZSBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlc2UgdGFrZSBpbnRvIGFjY291bnQgdGhlIHJhbmRvbSBlZmZlY3RzJyBzdHJ1Y3R1cmUgYXMgd2VsbCBhcyB0aGUgZml4ZWQgZWZmZWN0cycgc3RydWN0dXJlLiANCg0KIyMjIyMgVXNpbmcgInByZWRpY3QiDQoNClRoZSBmb2xsb3dpbmcgY29kZSBpcyB1c2VkIHRvIHJlY29yZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBpbnRvIHRoZSBzYW1lIGRhdGEtZnJhbWUuIFRoaXMgd2lsbCB0aGVuIGJlIHVzZWQgdG8gcGxvdCB0aGUgcmVzdWx0cyBvZiB0aGUgbW9kZWwNCg0KYGBge3J9DQpnZW1pbmF0aW9uQ29ucyRmaXR0ZWRfUHJvcFZvaWNlQ0QgPC0gcHJlZGljdChsbWVyKGR1cmF0aW9uVm9pY2VkUGVyY352b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uQ29ucyxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KKQ0KYGBgDQoNCg0KIyMjIyMgUGxvdHRpbmcgdGhlIHJlc3VsdHMNCg0KV2UgdXNlICJnZ3Bsb3QyIiB0byBwbG90IHRoZSByZXN1bHRzLiBUaGlzIHdpbGwgdXNlIHRoZSAicHJlZGljdGVkIiAob3IgZml0dGVkKSB2YWx1ZXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGUgZGFzaGVkIGxpbmVzICp3aXRoaW4qIHRoZSBib3hwbG90cyBhcmUgdGhlIG1lYW4gdmFsdWVzOyB0aGUgbWVkaWFuIGlzIG1hcmtlZCBieSB0aGUgaG9yaXpvbnRhbCBzdHJhaWdodCBsaW5lcy4NCg0KYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9Nn0NCmxhYmVscyA8LSBjKHNpbmdsZXRvbiA9ICJTaW5nbGV0b24iLCBnZW1pbmF0ZSA9ICJHZW1pbmF0ZSIpDQoNCmdnUHJvcFZvaWNlQ0RCeVZvaWNlIDwtIGdncGxvdChnZW1pbmF0aW9uQ29ucywgYWVzKHk9Zml0dGVkX1Byb3BWb2ljZUNELCB4PXZvaWNlZC51bnZvaWNlZCkpICsgDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJOQSIsbmEucm09VFJVRSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImVycm9yYmFyIiwgYWVzKHltYXggPSAuLnkuLiwgeW1pbiA9IC4ueS4uKSwNCiAgICAgICAgICAgICAgIHdpZHRoID0gLjc1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHlsYWIoZXhwcmVzc2lvbihwYXN0ZSgiVm9pY2luZyAoJSkiKSkpICsgbGFicyh0aXRsZSA9ICJDRCIpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0yMCwxMjApKSArDQogIHRoZW1lX3NldCh0aGVtZV9idygpKSArIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArDQogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArDQogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzPWxldmVscyhnZW1pbmF0aW9uQ29ucyR2b2ljZWQudW52b2ljZWQpLCBsYWJlbHM9YygiVm9pY2VsZXNzIiwiVm9pY2VkIikpICsNCiAgZmFjZXRfd3JhcCh+c2luZ0dlbSxuY29sPTEsbGFiZWxsZXI9bGFiZWxsZXIoc2luZ0dlbSA9IGxhYmVscykpDQpnZ1Byb3BWb2ljZUNEQnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIFByb3BvcnRpb24gb2Ygdm9pY2luZyBpbiB0aGUgY2xvc3VyZSBkdXJhdGlvbiAoJSBWb2ljaW5nIENEKSBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uQ29ucyAlPiUgZ3JvdXBfYnkoc2luZ0dlbTp2b2ljZWQudW52b2ljZWQpICU+JSBzdW1tYXJpc2UobWVhbihmaXR0ZWRfUHJvcFZvaWNlQ0QpLCBzZChmaXR0ZWRfUHJvcFZvaWNlQ0QpKQ0KYGBgDQoNCiMjIyMjIFBhaXJ3aXNlIHQtdGVzdCB3aXRoIEZEUiBjb3JyZWN0aW9ucw0KDQpXZSB1c2VkIHRoZSBwYWlyd2lzZSB0LXRlc3QgYXMgYXZhaWxhYmxlIGluIGJhc2UgUi4gVGhlIGlucHV0IHdhcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIEl0IHdhcyBub3QgcG9zc2libGUgdG8gZGlyZWN0bHkgdXNlIG91ciBzdGF0aXN0aWNhbCBtb2RlbCdzIG91dHB1dCB0byBjb21wYXJlIG1vZGVscywgZ2l2ZW4gdGhhdCBvdXIgTE1NIG1vZGVsIHdhcyBsb29raW5nIGF0IG92ZXJhbGwgY2hhbmdlIGFzIGEgbWFpbiBlZmZlY3QgcmF0aGVyIHRoYW4gYXMgYSBzaW1wbGUgZWZmZWN0J3MgbW9kZWwuIFRoaXMgaXMgd2h5IHdlIGhhdmUgdXNlZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWw7IHRoZSByZXN1bHRzIGFyZSB0aGUgc2FtZSBpZiB3ZSB3ZXJlIHRvIHVzZSB0aGUgImFjdHVhbCIgcmVzdWx0cyByYXRoZXIgdGhhbiB0aGUgcHJlZGljdGVkIG9uZXMuIA0KV2UgdXNlZCBGRFIgKGZvciBGYWxzZSBEaXNjb3ZlcnkgUmF0ZSkgY29ycmVjdGlvbiBmb3IgbXVsdGlwbGUgY29tcGFyaXNvbnMgYXMgdGhpcyBhbGxvd2VkIGZvciBjb3JyZWN0aW5nIGZvciBiaWFzIGluIHRoZSBkaWZmZXJlbmNlcyBpbiBkb2luZyBtdWx0aXBsZSBjb21wYXJpc29ucy4gDQoNCmBgYHtyfQ0KcGFpcndpc2UudC50ZXN0KGdlbWluYXRpb25Db25zJGZpdHRlZF9Qcm9wVm9pY2VDRCwgZ2VtaW5hdGlvbkNvbnMkc2luZ0dlbTpnZW1pbmF0aW9uQ29ucyR2b2ljZWQudW52b2ljZWQsIHAuYWRqID0gImZkciIpDQpgYGANCg0KIyMjIFByb3BvcnRpb24gb2Ygdm9pY2luZyBpbiB0aGUgUmVsZWFzZSBQaGFzZSAoJSBWb2ljaW5nIFJlbCkNCg0KIyMjIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQoNCldlIHJ1biB0aHJlZSBtb2RlbHMuIEZvciBtb2RlbCBjb21wYXJpc29ucywgd2UgYXJlIHJlcXVpcmVkIHRvIHVzZSBNYXhpbXVtIExpa2VsaWhvb2QgKE1MKSBvbiBib3RoIE9wdGltYWwgYW5kIE51bGwgbW9kZWxzIChieSBhZGRpbmcgUkVNTD1GKS4gVGhlbiB3ZSBydW4gYSBzZWNvbmQgT3B0aW1hbCBtb2RlbHMgd2l0aCBSZXN0cmljdGVkIE1heGltdW0gTGlrZWxpaG9vZCAoUkVNTCksIHRvIG9idGFpbiB0aGUgY29lZmZpY2llbnRzIChieSBhZGRpbmcgUkVNTD1UKQ0KDQojIyMjIyBPcHRpbWFsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpkdXJhdGlvblByb3BWb2ljZVJlbC54bWRsLkZ1bGwuTSA8LSBsbWVyKGR1cmF0aW9uVm9pY2VkUGVyY352b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVk9ULG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQpkdXJhdGlvblByb3BWb2ljZVJlbC54bWRsLkZ1bGwuUiA8LSBsbWVyKGR1cmF0aW9uVm9pY2VkUGVyY352b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVk9ULG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyBOdWxsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpkdXJhdGlvblByb3BWb2ljZVJlbC54bWRsLk51bGwuTSA8LSBsbWVyKGR1cmF0aW9uVm9pY2VkUGVyY34xKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblZPVCxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyBSZXN1bHRzIG9mIG91ciBtb2RlbA0KDQojIyMjIyBNb2RlbCBjb21wYXJpc29ucw0KDQpgYGB7cn0NCmFub3ZhKGR1cmF0aW9uUHJvcFZvaWNlUmVsLnhtZGwuTnVsbC5NLGR1cmF0aW9uUHJvcFZvaWNlUmVsLnhtZGwuRnVsbC5NKQ0KYGBgDQoNCkFzIGNhbiBiZSBzZWVuLCBvdXIgb3B0aW1hbCBtb2RlbCBpbXByb3ZlZCB0aGUgbW9kZWwgZml0Lg0KDQojIyMjIyBSZXNpZHVhbHMNCg0KV2UgaW5zcGVjdCBvdXIgbW9kZWwgYmVsb3csIGJ5IGxvb2tpbmcgYXQgdGhlIHJlc2lkdWFscy4gVGhlcmUgYXJlIG1pbm9yIGRldmlhdGlvbnMgb2JzZXJ2ZWQsIGR1ZSB0byB0aGUgbmF0dXJlIG9mIG91ciBkYXRhLg0KDQpgYGB7cn0NCmhpc3QocmVzaWR1YWxzKGR1cmF0aW9uUHJvcFZvaWNlUmVsLnhtZGwuRnVsbC5SKSkNCnFxbm9ybShyZXNpZHVhbHMoZHVyYXRpb25Qcm9wVm9pY2VSZWwueG1kbC5GdWxsLlIpKTsgcXFsaW5lKHJlc2lkdWFscyhkdXJhdGlvblByb3BWb2ljZVJlbC54bWRsLkZ1bGwuUikpDQpwbG90KGZpdHRlZChkdXJhdGlvblByb3BWb2ljZVJlbC54bWRsLkZ1bGwuUikscmVzaWR1YWxzKGR1cmF0aW9uUHJvcFZvaWNlUmVsLnhtZGwuRnVsbC5SKSwgY2V4ID0gNCkNCmBgYA0KDQojIyMjIyBTdW1tYXJ5IG9mIG1vZGVsDQoNCmBgYHtyfQ0Kc3VtbWFyeShkdXJhdGlvblByb3BWb2ljZVJlbC54bWRsLkZ1bGwuUikNCmBgYA0KDQojIyMjIEZpZ3VyZXMNCg0KVGhlIGZpZ3VyZSBwcmVzZW50ZWQgYmVsb3csIHVzZXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXM7IHRoZXNlIGFyZSB0aGUgdmFsdWVzICphZGp1c3RlZCogYnkgdGhlIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGVzZSB0YWtlIGludG8gYWNjb3VudCB0aGUgcmFuZG9tIGVmZmVjdHMnIHN0cnVjdHVyZSBhcyB3ZWxsIGFzIHRoZSBmaXhlZCBlZmZlY3RzJyBzdHJ1Y3R1cmUuIA0KDQojIyMjIyBVc2luZyAicHJlZGljdCINCg0KVGhlIGZvbGxvd2luZyBjb2RlIGlzIHVzZWQgdG8gcmVjb3JkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGludG8gdGhlIHNhbWUgZGF0YS1mcmFtZS4gVGhpcyB3aWxsIHRoZW4gYmUgdXNlZCB0byBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbA0KDQpgYGB7cn0NCmdlbWluYXRpb25WT1QkZml0dGVkX1Byb3BWb2ljZVJlbCA8LSBwcmVkaWN0KGxtZXIoZHVyYXRpb25Wb2ljZWRQZXJjfnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCikNCmBgYA0KDQoNCiMjIyMjIFBsb3R0aW5nIHRoZSByZXN1bHRzDQoNCldlIHVzZSAiZ2dwbG90MiIgdG8gcGxvdCB0aGUgcmVzdWx0cy4gVGhpcyB3aWxsIHVzZSB0aGUgInByZWRpY3RlZCIgKG9yIGZpdHRlZCkgdmFsdWVzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlIGRhc2hlZCBsaW5lcyAqd2l0aGluKiB0aGUgYm94cGxvdHMgYXJlIHRoZSBtZWFuIHZhbHVlczsgdGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgdGhlIGhvcml6b250YWwgc3RyYWlnaHQgbGluZXMuDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQpsYWJlbHMgPC0gYyhzaW5nbGV0b24gPSAiU2luZ2xldG9uIiwgZ2VtaW5hdGUgPSAiR2VtaW5hdGUiKQ0KDQpnZ1Byb3BWb2ljZVJlbEJ5Vm9pY2UgPC0gZ2dwbG90KGdlbWluYXRpb25WT1QsIGFlcyh5PWZpdHRlZF9Qcm9wVm9pY2VSZWwsIHg9dm9pY2VkLnVudm9pY2VkKSkgKyANCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gIk5BIixuYS5ybT1UUlVFKSArDQogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAiZXJyb3JiYXIiLCBhZXMoeW1heCA9IC4ueS4uLCB5bWluID0gLi55Li4pLA0KICAgICAgICAgICAgICAgd2lkdGggPSAuNzUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgeWxhYihleHByZXNzaW9uKHBhc3RlKCJWb2ljaW5nICglKSIpKSkgKyBsYWJzKHRpdGxlID0gIlJlbCIpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0yMCwxMjApKSArDQogIHRoZW1lX3NldCh0aGVtZV9idygpKSArIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArDQogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArDQogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzPWxldmVscyhnZW1pbmF0aW9uVk9UJHZvaWNlZC51bnZvaWNlZCksIGxhYmVscz1jKCJWb2ljZWxlc3MiLCJWb2ljZWQiKSkgKw0KICBmYWNldF93cmFwKH5zaW5nR2VtLG5jb2w9MSxsYWJlbGxlcj1sYWJlbGxlcihzaW5nR2VtID0gbGFiZWxzKSkNCmdnUHJvcFZvaWNlUmVsQnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIFByb3BvcnRpb24gb2Ygdm9pY2luZyBpbiB0aGUgUmVsZWFzZSBQaGFzZSAoJSBWb2ljaW5nIFJlbCkgYXJlIHByb3ZpZGVkIGJlbG93LiBBcyBjYW4gYmUgc2VlbiwgdGhlcmUgYXJlIGFscmVhZHkgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgcmVsYXRlZCB0byBib3RoICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iLg0KDQpgYGB7cn0NCiMgdXNpbmcgImRwbHlyIg0KZ2VtaW5hdGlvblZPVCAlPiUgZ3JvdXBfYnkoc2luZ0dlbTp2b2ljZWQudW52b2ljZWQpICU+JSBzdW1tYXJpc2UobWVhbihmaXR0ZWRfUHJvcFZvaWNlUmVsKSwgc2QoZml0dGVkX1Byb3BWb2ljZVJlbCkpDQpgYGANCg0KIyMjIyMgUGFpcndpc2UgdC10ZXN0IHdpdGggRkRSIGNvcnJlY3Rpb25zDQoNCldlIHVzZWQgdGhlIHBhaXJ3aXNlIHQtdGVzdCBhcyBhdmFpbGFibGUgaW4gYmFzZSBSLiBUaGUgaW5wdXQgd2FzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gSXQgd2FzIG5vdCBwb3NzaWJsZSB0byBkaXJlY3RseSB1c2Ugb3VyIHN0YXRpc3RpY2FsIG1vZGVsJ3Mgb3V0cHV0IHRvIGNvbXBhcmUgbW9kZWxzLCBnaXZlbiB0aGF0IG91ciBMTU0gbW9kZWwgd2FzIGxvb2tpbmcgYXQgb3ZlcmFsbCBjaGFuZ2UgYXMgYSBtYWluIGVmZmVjdCByYXRoZXIgdGhhbiBhcyBhIHNpbXBsZSBlZmZlY3QncyBtb2RlbC4gVGhpcyBpcyB3aHkgd2UgaGF2ZSB1c2VkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbDsgdGhlIHJlc3VsdHMgYXJlIHRoZSBzYW1lIGlmIHdlIHdlcmUgdG8gdXNlIHRoZSAiYWN0dWFsIiByZXN1bHRzIHJhdGhlciB0aGFuIHRoZSBwcmVkaWN0ZWQgb25lcy4gDQpXZSB1c2VkIEZEUiAoZm9yIEZhbHNlIERpc2NvdmVyeSBSYXRlKSBjb3JyZWN0aW9uIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucyBhcyB0aGlzIGFsbG93ZWQgZm9yIGNvcnJlY3RpbmcgZm9yIGJpYXMgaW4gdGhlIGRpZmZlcmVuY2VzIGluIGRvaW5nIG11bHRpcGxlIGNvbXBhcmlzb25zLiANCg0KYGBge3J9DQpwYWlyd2lzZS50LnRlc3QoZ2VtaW5hdGlvblZPVCRmaXR0ZWRfUHJvcFZvaWNlUmVsLCBnZW1pbmF0aW9uVk9UJHNpbmdHZW06Z2VtaW5hdGlvblZPVCR2b2ljZWQudW52b2ljZWQsIHAuYWRqID0gImZkciIpDQpgYGANCg0KIyMgSW50ZW5zaXR5IChkQikNCg0KV2l0aGluIEludGVuc2l0eSwgd2UgaGF2ZSBjb21wdXRlZCB0aGUgaW50ZW5zaXR5IGF0IGZvdXIgbG9jYXRpb25zOiBBdCB0aGUgT2Zmc2V0IG9mIHRoZSBwcmVjZWRpbmcgdm93ZWwgKFYxT2Zmc2V0KSwgYXQgdGhlIG9uc2V0IG9mIHRoZSBSZWxlYXNlIFBoYXNlIChSZWxPbnNldCksIGF0IHRoZSBPZmZzZXQgb2YgdGhlIFJlbGVhc2UgUGhhc2UgKFJlbE9mZnNldCkgYW5kIGF0IHRoZSBPbnNldCBvZiB0aGUgZm9sbG93aW5nIHZvd2VsIChWMk9mZnNldCkuDQoNCiMjIyBBdCB0aGUgb2Zmc2V0IG9mIHRoZSBwcmVjZWRpbmcgdm93ZWwNCg0KIyMjIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQoNCldlIHJ1biB0aHJlZSBtb2RlbHMuIEZvciBtb2RlbCBjb21wYXJpc29ucywgd2UgYXJlIHJlcXVpcmVkIHRvIHVzZSBNYXhpbXVtIExpa2VsaWhvb2QgKE1MKSBvbiBib3RoIE9wdGltYWwgYW5kIE51bGwgbW9kZWxzIChieSBhZGRpbmcgUkVNTD1GKS4gVGhlbiB3ZSBydW4gYSBzZWNvbmQgT3B0aW1hbCBtb2RlbHMgd2l0aCBSZXN0cmljdGVkIE1heGltdW0gTGlrZWxpaG9vZCAoUkVNTCksIHRvIG9idGFpbiB0aGUgY29lZmZpY2llbnRzIChieSBhZGRpbmcgUkVNTD1UKQ0KDQojIyMjIyBPcHRpbWFsIG1vZGVsIChNTCkNCg0KYGBge3J9DQppbnRlbnNpdHlWMU9mZnNldC54bWRsLkZ1bGwuTSA8LSBsbWVyKGludGVuc2l0eU9mZnNldH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjEsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjICBPcHRpbWFsIG1vZGVsIChSRU1MKQ0KDQpgYGB7cn0NCmludGVuc2l0eVYxT2Zmc2V0LnhtZGwuRnVsbC5SIDwtIGxtZXIoaW50ZW5zaXR5T2Zmc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMSxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgTnVsbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KaW50ZW5zaXR5VjFPZmZzZXQueG1kbC5OdWxsLk0gPC0gbG1lcihpbnRlbnNpdHlPZmZzZXR+MSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMSxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyBSZXN1bHRzIG9mIG91ciBtb2RlbA0KDQojIyMjIyBNb2RlbCBjb21wYXJpc29ucw0KDQpgYGB7cn0NCmFub3ZhKGludGVuc2l0eVYxT2Zmc2V0LnhtZGwuTnVsbC5NLGludGVuc2l0eVYxT2Zmc2V0LnhtZGwuRnVsbC5NKQ0KYGBgDQoNCkFzIGNhbiBiZSBzZWVuLCBvdXIgb3B0aW1hbCBtb2RlbCBpbXByb3ZlZCB0aGUgbW9kZWwgZml0Lg0KDQojIyMjIyBSZXNpZHVhbHMNCg0KV2UgaW5zcGVjdCBvdXIgbW9kZWwgYmVsb3csIGJ5IGxvb2tpbmcgYXQgdGhlIHJlc2lkdWFscy4gVGhlcmUgYXJlIG1pbm9yIGRldmlhdGlvbnMgb2JzZXJ2ZWQsIGR1ZSB0byB0aGUgbmF0dXJlIG9mIG91ciBkYXRhLg0KDQpgYGB7cn0NCmhpc3QocmVzaWR1YWxzKGludGVuc2l0eVYxT2Zmc2V0LnhtZGwuRnVsbC5SKSkNCnFxbm9ybShyZXNpZHVhbHMoaW50ZW5zaXR5VjFPZmZzZXQueG1kbC5GdWxsLlIpKTsgcXFsaW5lKHJlc2lkdWFscyhpbnRlbnNpdHlWMU9mZnNldC54bWRsLkZ1bGwuUikpDQpwbG90KGZpdHRlZChpbnRlbnNpdHlWMU9mZnNldC54bWRsLkZ1bGwuUikscmVzaWR1YWxzKGludGVuc2l0eVYxT2Zmc2V0LnhtZGwuRnVsbC5SKSwgY2V4ID0gNCkNCmBgYA0KDQojIyMjIyBTdW1tYXJ5IG9mIG1vZGVsDQoNCmBgYHtyfQ0Kc3VtbWFyeShpbnRlbnNpdHlWMU9mZnNldC54bWRsLkZ1bGwuUikNCmBgYA0KDQojIyMjIEZpZ3VyZXMNCg0KVGhlIGZpZ3VyZSBwcmVzZW50ZWQgYmVsb3csIHVzZXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXM7IHRoZXNlIGFyZSB0aGUgdmFsdWVzICphZGp1c3RlZCogYnkgdGhlIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGVzZSB0YWtlIGludG8gYWNjb3VudCB0aGUgcmFuZG9tIGVmZmVjdHMnIHN0cnVjdHVyZSBhcyB3ZWxsIGFzIHRoZSBmaXhlZCBlZmZlY3RzJyBzdHJ1Y3R1cmUuIA0KDQojIyMjIyBVc2luZyAicHJlZGljdCINCg0KVGhlIGZvbGxvd2luZyBjb2RlIGlzIHVzZWQgdG8gcmVjb3JkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGludG8gdGhlIHNhbWUgZGF0YS1mcmFtZS4gVGhpcyB3aWxsIHRoZW4gYmUgdXNlZCB0byBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbA0KDQpgYGB7cn0NCmdlbWluYXRpb25WMSRmaXR0ZWRfVjFJbnRlbnNpdHlPZmZzZXQgPC0gcHJlZGljdChsbWVyKGludGVuc2l0eU9mZnNldH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjEsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCikNCmBgYA0KDQoNCiMjIyMjIFBsb3R0aW5nIHRoZSByZXN1bHRzDQoNCldlIHVzZSAiZ2dwbG90MiIgdG8gcGxvdCB0aGUgcmVzdWx0cy4gVGhpcyB3aWxsIHVzZSB0aGUgInByZWRpY3RlZCIgKG9yIGZpdHRlZCkgdmFsdWVzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlIGRhc2hlZCBsaW5lcyAqd2l0aGluKiB0aGUgYm94cGxvdHMgYXJlIHRoZSBtZWFuIHZhbHVlczsgdGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgdGhlIGhvcml6b250YWwgc3RyYWlnaHQgbGluZXMuDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQpsYWJlbHMgPC0gYyhzaW5nbGV0b24gPSAiU2luZ2xldG9uIiwgZ2VtaW5hdGUgPSAiR2VtaW5hdGUiKQ0KDQpnZ0ludGVuc2l0eVYxT2Zmc2V0QnlWb2ljZSA8LSBnZ3Bsb3QoZ2VtaW5hdGlvblYxLCBhZXMoeT1maXR0ZWRfVjFJbnRlbnNpdHlPZmZzZXQsIHg9dm9pY2VkLnVudm9pY2VkKSkgKyANCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gIk5BIixuYS5ybT1UUlVFKSArDQogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAiZXJyb3JiYXIiLCBhZXMoeW1heCA9IC4ueS4uLCB5bWluID0gLi55Li4pLA0KICAgICAgICAgICAgICAgd2lkdGggPSAuNzUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgeWxhYihleHByZXNzaW9uKHBhc3RlKCJJbnRlbnNpdHkgKGRCKSIpKSkgKyBsYWJzKHRpdGxlID0gIlYxIE9mZnNldCIpICsNCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0yMCkpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDUwLDgwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1sZXZlbHMoZ2VtaW5hdGlvblYxJHZvaWNlZC51bnZvaWNlZCksIGxhYmVscz1jKCJWb2ljZWxlc3MiLCJWb2ljZWQiKSkgKw0KICBmYWNldF93cmFwKH5zaW5nR2VtLG5jb2w9MSxsYWJlbGxlcj1sYWJlbGxlcihzaW5nR2VtID0gbGFiZWxzKSkNCmdnSW50ZW5zaXR5VjFPZmZzZXRCeVZvaWNlDQpgYGANCg0KIyMjIyBQYWlyd2lzZSBjb21wYXJpc29ucw0KDQpBZnRlciBydW5uaW5nIG91ciBzdGF0aXN0aWNhbCBtb2RlbCBhYm92ZSwgd2Ugd2FudGVkIHRvIGV2YWx1YXRlIHdoZXRoZXIgdGhlIGRpZmZlcmVuY2VzIG9ic2VydmVkIGJldHdlZW4gInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCAob3Igbm90KS4gV2UgcHJlc2VudCB0aGUgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgZm9yIGVhY2ggb2YgdGhlIGZvdXItd2F5IGNvbnRyYXN0IGJhc2VkIG9uIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzLg0KDQojIyMjIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzDQoNClRoZSBwcmVkaWN0ZWQgbWVhbnMgYW5kIFNEcyBvZiB0aGUgSW50ZW5zaXR5IGF0IHRoZSBPZmZzZXQgb2YgdGhlIHByZWNlZGluZyB2b3dlbCAoVjFPZmZzZXQpIGFyZSBwcm92aWRlZCBiZWxvdy4gQXMgY2FuIGJlIHNlZW4sIHRoZXJlIGFyZSBhbHJlYWR5IGRpZmZlcmVuY2VzIG9ic2VydmVkIHJlbGF0ZWQgdG8gYm90aCAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIi4NCg0KYGBge3J9DQojIHVzaW5nICJkcGx5ciINCmdlbWluYXRpb25WMSAlPiUgZ3JvdXBfYnkoc2luZ0dlbTp2b2ljZWQudW52b2ljZWQpICU+JSBzdW1tYXJpc2UobWVhbihmaXR0ZWRfVjFJbnRlbnNpdHlPZmZzZXQpLCBzZChmaXR0ZWRfVjFJbnRlbnNpdHlPZmZzZXQpKQ0KYGBgDQoNCiMjIyMjIFBhaXJ3aXNlIHQtdGVzdCB3aXRoIEZEUiBjb3JyZWN0aW9ucw0KDQpXZSB1c2VkIHRoZSBwYWlyd2lzZSB0LXRlc3QgYXMgYXZhaWxhYmxlIGluIGJhc2UgUi4gVGhlIGlucHV0IHdhcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIEl0IHdhcyBub3QgcG9zc2libGUgdG8gZGlyZWN0bHkgdXNlIG91ciBzdGF0aXN0aWNhbCBtb2RlbCdzIG91dHB1dCB0byBjb21wYXJlIG1vZGVscywgZ2l2ZW4gdGhhdCBvdXIgTE1NIG1vZGVsIHdhcyBsb29raW5nIGF0IG92ZXJhbGwgY2hhbmdlIGFzIGEgbWFpbiBlZmZlY3QgcmF0aGVyIHRoYW4gYXMgYSBzaW1wbGUgZWZmZWN0J3MgbW9kZWwuIFRoaXMgaXMgd2h5IHdlIGhhdmUgdXNlZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWw7IHRoZSByZXN1bHRzIGFyZSB0aGUgc2FtZSBpZiB3ZSB3ZXJlIHRvIHVzZSB0aGUgImFjdHVhbCIgcmVzdWx0cyByYXRoZXIgdGhhbiB0aGUgcHJlZGljdGVkIG9uZXMuIA0KV2UgdXNlZCBGRFIgKGZvciBGYWxzZSBEaXNjb3ZlcnkgUmF0ZSkgY29ycmVjdGlvbiBmb3IgbXVsdGlwbGUgY29tcGFyaXNvbnMgYXMgdGhpcyBhbGxvd2VkIGZvciBjb3JyZWN0aW5nIGZvciBiaWFzIGluIHRoZSBkaWZmZXJlbmNlcyBpbiBkb2luZyBtdWx0aXBsZSBjb21wYXJpc29ucy4gDQoNCmBgYHtyfQ0KcGFpcndpc2UudC50ZXN0KGdlbWluYXRpb25WMSRmaXR0ZWRfVjFJbnRlbnNpdHlPZmZzZXQsIGdlbWluYXRpb25WMSRzaW5nR2VtOmdlbWluYXRpb25WMSR2b2ljZWQudW52b2ljZWQsIHAuYWRqID0gImZkciIpDQpgYGANCg0KDQojIyMgQXQgdGhlIG9uc2V0IG9mIHRoZSBSZWxlYXNlIHBoYXNlDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KaW50ZW5zaXR5UmVsT25zZXQueG1kbC5GdWxsLk0gPC0gbG1lcihpbnRlbnNpdHlPbnNldH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVk9ULG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQppbnRlbnNpdHlSZWxPbnNldC54bWRsLkZ1bGwuUiA8LSBsbWVyKGludGVuc2l0eU9uc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjIE51bGwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmludGVuc2l0eVJlbE9uc2V0LnhtZGwuTnVsbC5NIDwtIGxtZXIoaW50ZW5zaXR5T25zZXR+MSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShpbnRlbnNpdHlSZWxPbnNldC54bWRsLk51bGwuTSxpbnRlbnNpdHlSZWxPbnNldC54bWRsLkZ1bGwuTSkNCmBgYA0KDQpBcyBjYW4gYmUgc2Vlbiwgb3VyIG9wdGltYWwgbW9kZWwgaW1wcm92ZWQgdGhlIG1vZGVsIGZpdC4NCg0KIyMjIyMgUmVzaWR1YWxzDQoNCldlIGluc3BlY3Qgb3VyIG1vZGVsIGJlbG93LCBieSBsb29raW5nIGF0IHRoZSByZXNpZHVhbHMuIFRoZXJlIGFyZSBtaW5vciBkZXZpYXRpb25zIG9ic2VydmVkLCBkdWUgdG8gdGhlIG5hdHVyZSBvZiBvdXIgZGF0YS4NCg0KYGBge3J9DQpoaXN0KHJlc2lkdWFscyhpbnRlbnNpdHlSZWxPbnNldC54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGludGVuc2l0eVJlbE9uc2V0LnhtZGwuRnVsbC5SKSk7IHFxbGluZShyZXNpZHVhbHMoaW50ZW5zaXR5UmVsT25zZXQueG1kbC5GdWxsLlIpKQ0KcGxvdChmaXR0ZWQoaW50ZW5zaXR5UmVsT25zZXQueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhpbnRlbnNpdHlSZWxPbnNldC54bWRsLkZ1bGwuUiksIGNleCA9IDQpDQpgYGANCg0KIyMjIyMgU3VtbWFyeSBvZiBtb2RlbA0KDQpgYGB7cn0NCnN1bW1hcnkoaW50ZW5zaXR5UmVsT25zZXQueG1kbC5GdWxsLlIpDQpgYGANCg0KIyMjIyBGaWd1cmVzDQoNClRoZSBmaWd1cmUgcHJlc2VudGVkIGJlbG93LCB1c2VzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzOyB0aGVzZSBhcmUgdGhlIHZhbHVlcyAqYWRqdXN0ZWQqIGJ5IHRoZSBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlc2UgdGFrZSBpbnRvIGFjY291bnQgdGhlIHJhbmRvbSBlZmZlY3RzJyBzdHJ1Y3R1cmUgYXMgd2VsbCBhcyB0aGUgZml4ZWQgZWZmZWN0cycgc3RydWN0dXJlLiANCg0KIyMjIyMgVXNpbmcgInByZWRpY3QiDQoNClRoZSBmb2xsb3dpbmcgY29kZSBpcyB1c2VkIHRvIHJlY29yZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBpbnRvIHRoZSBzYW1lIGRhdGEtZnJhbWUuIFRoaXMgd2lsbCB0aGVuIGJlIHVzZWQgdG8gcGxvdCB0aGUgcmVzdWx0cyBvZiB0aGUgbW9kZWwNCg0KYGBge3J9DQpnZW1pbmF0aW9uVk9UJGZpdHRlZF9SZWxJbnRlbnNpdHlPbnNldCA8LSBwcmVkaWN0KGxtZXIoaW50ZW5zaXR5T25zZXR+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblZPVCxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KKQ0KYGBgDQoNCg0KIyMjIyMgUGxvdHRpbmcgdGhlIHJlc3VsdHMNCg0KV2UgdXNlICJnZ3Bsb3QyIiB0byBwbG90IHRoZSByZXN1bHRzLiBUaGlzIHdpbGwgdXNlIHRoZSAicHJlZGljdGVkIiAob3IgZml0dGVkKSB2YWx1ZXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGUgZGFzaGVkIGxpbmVzICp3aXRoaW4qIHRoZSBib3hwbG90cyBhcmUgdGhlIG1lYW4gdmFsdWVzOyB0aGUgbWVkaWFuIGlzIG1hcmtlZCBieSB0aGUgaG9yaXpvbnRhbCBzdHJhaWdodCBsaW5lcy4NCg0KYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9Nn0NCmxhYmVscyA8LSBjKHNpbmdsZXRvbiA9ICJTaW5nbGV0b24iLCBnZW1pbmF0ZSA9ICJHZW1pbmF0ZSIpDQoNCmdnSW50ZW5zaXR5UmVsT25zZXRCeVZvaWNlIDwtIGdncGxvdChnZW1pbmF0aW9uVk9ULCBhZXMoeT1maXR0ZWRfUmVsSW50ZW5zaXR5T25zZXQsIHg9dm9pY2VkLnVudm9pY2VkKSkgKyANCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gIk5BIixuYS5ybT1UUlVFKSArDQogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAiZXJyb3JiYXIiLCBhZXMoeW1heCA9IC4ueS4uLCB5bWluID0gLi55Li4pLA0KICAgICAgICAgICAgICAgd2lkdGggPSAuNzUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgeWxhYihleHByZXNzaW9uKHBhc3RlKCJJbnRlbnNpdHkgKGRCKSIpKSkgKyBsYWJzKHRpdGxlID0gIlJlbCBPbnNldCIpICsNCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0yMCkpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDUwLDgwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1sZXZlbHMoZ2VtaW5hdGlvblZPVCR2b2ljZWQudW52b2ljZWQpLCBsYWJlbHM9YygiVm9pY2VsZXNzIiwiVm9pY2VkIikpICsNCiAgZmFjZXRfd3JhcCh+c2luZ0dlbSxuY29sPTEsbGFiZWxsZXI9bGFiZWxsZXIoc2luZ0dlbSA9IGxhYmVscykpDQpnZ0ludGVuc2l0eVJlbE9uc2V0QnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIEludGVuc2l0eSBhdCB0aGUgT25zZXQgb2YgdGhlIFJlbGVhc2UgcGhhc2UgKFJlbE9uc2V0KSBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uVk9UICU+JSBncm91cF9ieShzaW5nR2VtOnZvaWNlZC51bnZvaWNlZCkgJT4lIHN1bW1hcmlzZShtZWFuKGZpdHRlZF9SZWxJbnRlbnNpdHlPbnNldCksIHNkKGZpdHRlZF9SZWxJbnRlbnNpdHlPbnNldCkpDQpgYGANCg0KIyMjIyMgUGFpcndpc2UgdC10ZXN0IHdpdGggRkRSIGNvcnJlY3Rpb25zDQoNCldlIHVzZWQgdGhlIHBhaXJ3aXNlIHQtdGVzdCBhcyBhdmFpbGFibGUgaW4gYmFzZSBSLiBUaGUgaW5wdXQgd2FzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gSXQgd2FzIG5vdCBwb3NzaWJsZSB0byBkaXJlY3RseSB1c2Ugb3VyIHN0YXRpc3RpY2FsIG1vZGVsJ3Mgb3V0cHV0IHRvIGNvbXBhcmUgbW9kZWxzLCBnaXZlbiB0aGF0IG91ciBMTU0gbW9kZWwgd2FzIGxvb2tpbmcgYXQgb3ZlcmFsbCBjaGFuZ2UgYXMgYSBtYWluIGVmZmVjdCByYXRoZXIgdGhhbiBhcyBhIHNpbXBsZSBlZmZlY3QncyBtb2RlbC4gVGhpcyBpcyB3aHkgd2UgaGF2ZSB1c2VkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbDsgdGhlIHJlc3VsdHMgYXJlIHRoZSBzYW1lIGlmIHdlIHdlcmUgdG8gdXNlIHRoZSAiYWN0dWFsIiByZXN1bHRzIHJhdGhlciB0aGFuIHRoZSBwcmVkaWN0ZWQgb25lcy4gDQpXZSB1c2VkIEZEUiAoZm9yIEZhbHNlIERpc2NvdmVyeSBSYXRlKSBjb3JyZWN0aW9uIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucyBhcyB0aGlzIGFsbG93ZWQgZm9yIGNvcnJlY3RpbmcgZm9yIGJpYXMgaW4gdGhlIGRpZmZlcmVuY2VzIGluIGRvaW5nIG11bHRpcGxlIGNvbXBhcmlzb25zLiANCg0KYGBge3J9DQpwYWlyd2lzZS50LnRlc3QoZ2VtaW5hdGlvblZPVCRmaXR0ZWRfUmVsSW50ZW5zaXR5T25zZXQsIGdlbWluYXRpb25WT1Qkc2luZ0dlbTpnZW1pbmF0aW9uVk9UJHZvaWNlZC51bnZvaWNlZCwgcC5hZGogPSAiZmRyIikNCmBgYA0KDQoNCiMjIyBBdCB0aGUgb2Zmc2V0IG9mIHRoZSBSZWxlYXNlIHBoYXNlDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KaW50ZW5zaXR5UmVsT2Zmc2V0LnhtZGwuRnVsbC5NIDwtIGxtZXIoaW50ZW5zaXR5T2Zmc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjICBPcHRpbWFsIG1vZGVsIChSRU1MKQ0KDQpgYGB7cn0NCmludGVuc2l0eVJlbE9mZnNldC54bWRsLkZ1bGwuUiA8LSBsbWVyKGludGVuc2l0eU9mZnNldH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVk9ULG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyBOdWxsIG1vZGVsIChNTCkNCg0KYGBge3J9DQppbnRlbnNpdHlSZWxPZmZzZXQueG1kbC5OdWxsLk0gPC0gbG1lcihpbnRlbnNpdHlPZmZzZXR+MSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShpbnRlbnNpdHlSZWxPZmZzZXQueG1kbC5OdWxsLk0saW50ZW5zaXR5UmVsT2Zmc2V0LnhtZGwuRnVsbC5NKQ0KYGBgDQoNCkFzIGNhbiBiZSBzZWVuLCBvdXIgb3B0aW1hbCBtb2RlbCBpbXByb3ZlZCB0aGUgbW9kZWwgZml0Lg0KDQojIyMjIyBSZXNpZHVhbHMNCg0KV2UgaW5zcGVjdCBvdXIgbW9kZWwgYmVsb3csIGJ5IGxvb2tpbmcgYXQgdGhlIHJlc2lkdWFscy4gVGhlcmUgYXJlIG1pbm9yIGRldmlhdGlvbnMgb2JzZXJ2ZWQsIGR1ZSB0byB0aGUgbmF0dXJlIG9mIG91ciBkYXRhLg0KDQpgYGB7cn0NCmhpc3QocmVzaWR1YWxzKGludGVuc2l0eVJlbE9mZnNldC54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGludGVuc2l0eVJlbE9mZnNldC54bWRsLkZ1bGwuUikpOyBxcWxpbmUocmVzaWR1YWxzKGludGVuc2l0eVJlbE9mZnNldC54bWRsLkZ1bGwuUikpDQpwbG90KGZpdHRlZChpbnRlbnNpdHlSZWxPZmZzZXQueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhpbnRlbnNpdHlSZWxPZmZzZXQueG1kbC5GdWxsLlIpLCBjZXggPSA0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgbW9kZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGludGVuc2l0eVJlbE9mZnNldC54bWRsLkZ1bGwuUikNCmBgYA0KDQojIyMjIEZpZ3VyZXMNCg0KVGhlIGZpZ3VyZSBwcmVzZW50ZWQgYmVsb3csIHVzZXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXM7IHRoZXNlIGFyZSB0aGUgdmFsdWVzICphZGp1c3RlZCogYnkgdGhlIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGVzZSB0YWtlIGludG8gYWNjb3VudCB0aGUgcmFuZG9tIGVmZmVjdHMnIHN0cnVjdHVyZSBhcyB3ZWxsIGFzIHRoZSBmaXhlZCBlZmZlY3RzJyBzdHJ1Y3R1cmUuIA0KDQojIyMjIyBVc2luZyAicHJlZGljdCINCg0KVGhlIGZvbGxvd2luZyBjb2RlIGlzIHVzZWQgdG8gcmVjb3JkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGludG8gdGhlIHNhbWUgZGF0YS1mcmFtZS4gVGhpcyB3aWxsIHRoZW4gYmUgdXNlZCB0byBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbA0KDQpgYGB7cn0NCmdlbWluYXRpb25WT1QkZml0dGVkX1JlbEludGVuc2l0eU9mZnNldCA8LSBwcmVkaWN0KGxtZXIoaW50ZW5zaXR5T2Zmc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WT1QsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCikNCmBgYA0KDQoNCiMjIyMjIFBsb3R0aW5nIHRoZSByZXN1bHRzDQoNCldlIHVzZSAiZ2dwbG90MiIgdG8gcGxvdCB0aGUgcmVzdWx0cy4gVGhpcyB3aWxsIHVzZSB0aGUgInByZWRpY3RlZCIgKG9yIGZpdHRlZCkgdmFsdWVzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlIGRhc2hlZCBsaW5lcyAqd2l0aGluKiB0aGUgYm94cGxvdHMgYXJlIHRoZSBtZWFuIHZhbHVlczsgdGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgdGhlIGhvcml6b250YWwgc3RyYWlnaHQgbGluZXMuDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQpsYWJlbHMgPC0gYyhzaW5nbGV0b24gPSAiU2luZ2xldG9uIiwgZ2VtaW5hdGUgPSAiR2VtaW5hdGUiKQ0KDQpnZ0ludGVuc2l0eVJlbE9mZnNldEJ5Vm9pY2UgPC0gZ2dwbG90KGdlbWluYXRpb25WT1QsIGFlcyh5PWZpdHRlZF9SZWxJbnRlbnNpdHlPZmZzZXQsIHg9dm9pY2VkLnVudm9pY2VkKSkgKyANCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gIk5BIixuYS5ybT1UUlVFKSArDQogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAiZXJyb3JiYXIiLCBhZXMoeW1heCA9IC4ueS4uLCB5bWluID0gLi55Li4pLA0KICAgICAgICAgICAgICAgd2lkdGggPSAuNzUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgeWxhYihleHByZXNzaW9uKHBhc3RlKCJJbnRlbnNpdHkgKGRCKSIpKSkgKyBsYWJzKHRpdGxlID0gIlJlbCBPZmZzZXQiKSArDQogIHRoZW1lX3NldCh0aGVtZV9idygpKSArIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYyg1MCw4MCkpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9bGV2ZWxzKGdlbWluYXRpb25WT1Qkdm9pY2VkLnVudm9pY2VkKSwgbGFiZWxzPWMoIlZvaWNlbGVzcyIsIlZvaWNlZCIpKSArDQogIGZhY2V0X3dyYXAofnNpbmdHZW0sbmNvbD0xLGxhYmVsbGVyPWxhYmVsbGVyKHNpbmdHZW0gPSBsYWJlbHMpKQ0KZ2dJbnRlbnNpdHlSZWxPZmZzZXRCeVZvaWNlDQpgYGANCg0KIyMjIyBQYWlyd2lzZSBjb21wYXJpc29ucw0KDQpBZnRlciBydW5uaW5nIG91ciBzdGF0aXN0aWNhbCBtb2RlbCBhYm92ZSwgd2Ugd2FudGVkIHRvIGV2YWx1YXRlIHdoZXRoZXIgdGhlIGRpZmZlcmVuY2VzIG9ic2VydmVkIGJldHdlZW4gInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCAob3Igbm90KS4gV2UgcHJlc2VudCB0aGUgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgZm9yIGVhY2ggb2YgdGhlIGZvdXItd2F5IGNvbnRyYXN0IGJhc2VkIG9uIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzLg0KDQojIyMjIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzDQoNClRoZSBwcmVkaWN0ZWQgbWVhbnMgYW5kIFNEcyBvZiB0aGUgSW50ZW5zaXR5IGF0IHRoZSBPZmZzZXQgb2YgdGhlIFJlbGVhc2UgcGhhc2UgKFJlbE9mZnNldCkgYXJlIHByb3ZpZGVkIGJlbG93LiBBcyBjYW4gYmUgc2VlbiwgdGhlcmUgYXJlIGFscmVhZHkgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgcmVsYXRlZCB0byBib3RoICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iLg0KDQpgYGB7cn0NCiMgdXNpbmcgImRwbHlyIg0KZ2VtaW5hdGlvblZPVCAlPiUgZ3JvdXBfYnkoc2luZ0dlbTp2b2ljZWQudW52b2ljZWQpICU+JSBzdW1tYXJpc2UobWVhbihmaXR0ZWRfUmVsSW50ZW5zaXR5T2Zmc2V0KSwgc2QoZml0dGVkX1JlbEludGVuc2l0eU9mZnNldCkpDQpgYGANCg0KIyMjIyMgUGFpcndpc2UgdC10ZXN0IHdpdGggRkRSIGNvcnJlY3Rpb25zDQoNCldlIHVzZWQgdGhlIHBhaXJ3aXNlIHQtdGVzdCBhcyBhdmFpbGFibGUgaW4gYmFzZSBSLiBUaGUgaW5wdXQgd2FzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gSXQgd2FzIG5vdCBwb3NzaWJsZSB0byBkaXJlY3RseSB1c2Ugb3VyIHN0YXRpc3RpY2FsIG1vZGVsJ3Mgb3V0cHV0IHRvIGNvbXBhcmUgbW9kZWxzLCBnaXZlbiB0aGF0IG91ciBMTU0gbW9kZWwgd2FzIGxvb2tpbmcgYXQgb3ZlcmFsbCBjaGFuZ2UgYXMgYSBtYWluIGVmZmVjdCByYXRoZXIgdGhhbiBhcyBhIHNpbXBsZSBlZmZlY3QncyBtb2RlbC4gVGhpcyBpcyB3aHkgd2UgaGF2ZSB1c2VkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbDsgdGhlIHJlc3VsdHMgYXJlIHRoZSBzYW1lIGlmIHdlIHdlcmUgdG8gdXNlIHRoZSAiYWN0dWFsIiByZXN1bHRzIHJhdGhlciB0aGFuIHRoZSBwcmVkaWN0ZWQgb25lcy4gDQpXZSB1c2VkIEZEUiAoZm9yIEZhbHNlIERpc2NvdmVyeSBSYXRlKSBjb3JyZWN0aW9uIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucyBhcyB0aGlzIGFsbG93ZWQgZm9yIGNvcnJlY3RpbmcgZm9yIGJpYXMgaW4gdGhlIGRpZmZlcmVuY2VzIGluIGRvaW5nIG11bHRpcGxlIGNvbXBhcmlzb25zLiANCg0KYGBge3J9DQpwYWlyd2lzZS50LnRlc3QoZ2VtaW5hdGlvblZPVCRmaXR0ZWRfUmVsSW50ZW5zaXR5T2Zmc2V0LCBnZW1pbmF0aW9uVk9UJHNpbmdHZW06Z2VtaW5hdGlvblZPVCR2b2ljZWQudW52b2ljZWQsIHAuYWRqID0gImZkciIpDQpgYGANCg0KIyMjIEF0IHRoZSBvbnNldCBvZiB0aGUgZm9sbG93aW5nIHZvd2VsDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KaW50ZW5zaXR5VjJPbnNldC54bWRsLkZ1bGwuTSA8LSBsbWVyKGludGVuc2l0eU9uc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMixuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgIE9wdGltYWwgbW9kZWwgKFJFTUwpDQoNCmBgYHtyfQ0KaW50ZW5zaXR5VjJPbnNldC54bWRsLkZ1bGwuUiA8LSBsbWVyKGludGVuc2l0eU9uc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMixuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgTnVsbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KaW50ZW5zaXR5VjJPbnNldC54bWRsLk51bGwuTSA8LSBsbWVyKGludGVuc2l0eU9uc2V0fjErDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjIsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShpbnRlbnNpdHlWMk9uc2V0LnhtZGwuTnVsbC5NLGludGVuc2l0eVYyT25zZXQueG1kbC5GdWxsLk0pDQpgYGANCg0KQXMgY2FuIGJlIHNlZW4sIG91ciBvcHRpbWFsIG1vZGVsIGltcHJvdmVkIHRoZSBtb2RlbCBmaXQuDQoNCiMjIyMjIFJlc2lkdWFscw0KDQpXZSBpbnNwZWN0IG91ciBtb2RlbCBiZWxvdywgYnkgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLiBUaGVyZSBhcmUgbWlub3IgZGV2aWF0aW9ucyBvYnNlcnZlZCwgZHVlIHRvIHRoZSBuYXR1cmUgb2Ygb3VyIGRhdGEuDQoNCmBgYHtyfQ0KaGlzdChyZXNpZHVhbHMoaW50ZW5zaXR5VjJPbnNldC54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGludGVuc2l0eVYyT25zZXQueG1kbC5GdWxsLlIpKTsgcXFsaW5lKHJlc2lkdWFscyhpbnRlbnNpdHlWMk9uc2V0LnhtZGwuRnVsbC5SKSkNCnBsb3QoZml0dGVkKGludGVuc2l0eVYyT25zZXQueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhpbnRlbnNpdHlWMk9uc2V0LnhtZGwuRnVsbC5SKSwgY2V4ID0gNCkNCmBgYA0KDQojIyMjIyBTdW1tYXJ5IG9mIG1vZGVsDQoNCmBgYHtyfQ0Kc3VtbWFyeShpbnRlbnNpdHlWMk9uc2V0LnhtZGwuRnVsbC5SKQ0KYGBgDQoNCiMjIyMgRmlndXJlcw0KDQpUaGUgZmlndXJlIHByZXNlbnRlZCBiZWxvdywgdXNlcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlczsgdGhlc2UgYXJlIHRoZSB2YWx1ZXMgKmFkanVzdGVkKiBieSB0aGUgc3RhdGlzdGljYWwgbW9kZWwuIFRoZXNlIHRha2UgaW50byBhY2NvdW50IHRoZSByYW5kb20gZWZmZWN0cycgc3RydWN0dXJlIGFzIHdlbGwgYXMgdGhlIGZpeGVkIGVmZmVjdHMnIHN0cnVjdHVyZS4gDQoNCiMjIyMjIFVzaW5nICJwcmVkaWN0Ig0KDQpUaGUgZm9sbG93aW5nIGNvZGUgaXMgdXNlZCB0byByZWNvcmQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgaW50byB0aGUgc2FtZSBkYXRhLWZyYW1lLiBUaGlzIHdpbGwgdGhlbiBiZSB1c2VkIHRvIHBsb3QgdGhlIHJlc3VsdHMgb2YgdGhlIG1vZGVsDQoNCmBgYHtyfQ0KZ2VtaW5hdGlvblYyJGZpdHRlZF9WMkludGVuc2l0eU9uc2V0IDwtIHByZWRpY3QobG1lcihpbnRlbnNpdHlPbnNldH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjIsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCikNCmBgYA0KDQoNCiMjIyMjIFBsb3R0aW5nIHRoZSByZXN1bHRzDQoNCldlIHVzZSAiZ2dwbG90MiIgdG8gcGxvdCB0aGUgcmVzdWx0cy4gVGhpcyB3aWxsIHVzZSB0aGUgInByZWRpY3RlZCIgKG9yIGZpdHRlZCkgdmFsdWVzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlIGRhc2hlZCBsaW5lcyAqd2l0aGluKiB0aGUgYm94cGxvdHMgYXJlIHRoZSBtZWFuIHZhbHVlczsgdGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgdGhlIGhvcml6b250YWwgc3RyYWlnaHQgbGluZXMuDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQpsYWJlbHMgPC0gYyhzaW5nbGV0b24gPSAiU2luZ2xldG9uIiwgZ2VtaW5hdGUgPSAiR2VtaW5hdGUiKQ0KDQpnZ0ludGVuc2l0eVYyT25zZXRCeVZvaWNlIDwtIGdncGxvdChnZW1pbmF0aW9uVjIsIGFlcyh5PWZpdHRlZF9WMkludGVuc2l0eU9uc2V0LCB4PXZvaWNlZC51bnZvaWNlZCkpICsgDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJOQSIsbmEucm09VFJVRSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImVycm9yYmFyIiwgYWVzKHltYXggPSAuLnkuLiwgeW1pbiA9IC4ueS4uKSwNCiAgICAgICAgICAgICAgIHdpZHRoID0gLjc1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHlsYWIoZXhwcmVzc2lvbihwYXN0ZSgiSW50ZW5zaXR5IChkQikiKSkpICsgbGFicyh0aXRsZSA9ICJWMiBPbnNldCIpICsNCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0yMCkpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDUwLDgwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1sZXZlbHMoZ2VtaW5hdGlvblYyJHZvaWNlZC51bnZvaWNlZCksIGxhYmVscz1jKCJWb2ljZWxlc3MiLCJWb2ljZWQiKSkgKw0KICBmYWNldF93cmFwKH5zaW5nR2VtLG5jb2w9MSxsYWJlbGxlcj1sYWJlbGxlcihzaW5nR2VtID0gbGFiZWxzKSkNCmdnSW50ZW5zaXR5VjJPbnNldEJ5Vm9pY2UNCmBgYA0KDQojIyMjIFBhaXJ3aXNlIGNvbXBhcmlzb25zDQoNCkFmdGVyIHJ1bm5pbmcgb3VyIHN0YXRpc3RpY2FsIG1vZGVsIGFib3ZlLCB3ZSB3YW50ZWQgdG8gZXZhbHVhdGUgd2hldGhlciB0aGUgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgYmV0d2VlbiAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChvciBub3QpLiBXZSBwcmVzZW50IHRoZSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3IgZWFjaCBvZiB0aGUgZm91ci13YXkgY29udHJhc3QgYmFzZWQgb24gdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMuDQoNCiMjIyMjIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MNCg0KVGhlIHByZWRpY3RlZCBtZWFucyBhbmQgU0RzIG9mIHRoZSBJbnRlbnNpdHkgYXQgdGhlIE9uc2V0IG9mIHRoZSBmb2xsb3dpbmcgdm93ZWwgKFYyT25zZXQpIGFyZSBwcm92aWRlZCBiZWxvdy4gQXMgY2FuIGJlIHNlZW4sIHRoZXJlIGFyZSBhbHJlYWR5IGRpZmZlcmVuY2VzIG9ic2VydmVkIHJlbGF0ZWQgdG8gYm90aCAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIi4NCg0KYGBge3J9DQojIHVzaW5nICJkcGx5ciINCmdlbWluYXRpb25WMiAlPiUgZ3JvdXBfYnkoc2luZ0dlbTp2b2ljZWQudW52b2ljZWQpICU+JSBzdW1tYXJpc2UobWVhbihmaXR0ZWRfVjJJbnRlbnNpdHlPbnNldCksIHNkKGZpdHRlZF9WMkludGVuc2l0eU9uc2V0KSkNCmBgYA0KDQojIyMjIyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBGRFIgY29ycmVjdGlvbnMNCg0KV2UgdXNlZCB0aGUgcGFpcndpc2UgdC10ZXN0IGFzIGF2YWlsYWJsZSBpbiBiYXNlIFIuIFRoZSBpbnB1dCB3YXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGRpcmVjdGx5IHVzZSBvdXIgc3RhdGlzdGljYWwgbW9kZWwncyBvdXRwdXQgdG8gY29tcGFyZSBtb2RlbHMsIGdpdmVuIHRoYXQgb3VyIExNTSBtb2RlbCB3YXMgbG9va2luZyBhdCBvdmVyYWxsIGNoYW5nZSBhcyBhIG1haW4gZWZmZWN0IHJhdGhlciB0aGFuIGFzIGEgc2ltcGxlIGVmZmVjdCdzIG1vZGVsLiBUaGlzIGlzIHdoeSB3ZSBoYXZlIHVzZWQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsOyB0aGUgcmVzdWx0cyBhcmUgdGhlIHNhbWUgaWYgd2Ugd2VyZSB0byB1c2UgdGhlICJhY3R1YWwiIHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhlIHByZWRpY3RlZCBvbmVzLiANCldlIHVzZWQgRkRSIChmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUpIGNvcnJlY3Rpb24gZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIGFzIHRoaXMgYWxsb3dlZCBmb3IgY29ycmVjdGluZyBmb3IgYmlhcyBpbiB0aGUgZGlmZmVyZW5jZXMgaW4gZG9pbmcgbXVsdGlwbGUgY29tcGFyaXNvbnMuIA0KDQpgYGB7cn0NCnBhaXJ3aXNlLnQudGVzdChnZW1pbmF0aW9uVjIkZml0dGVkX1YySW50ZW5zaXR5T25zZXQsIGdlbWluYXRpb25WMiRzaW5nR2VtOmdlbWluYXRpb25WMiR2b2ljZWQudW52b2ljZWQsIHAuYWRqID0gImZkciIpDQpgYGANCg0KDQojIyBGdW5kYW1lbnRhbCBmcmVxdWVuY3kgKEh6KQ0KDQpXaXRoaW4gdGhlIGZ1bmRhbWVudGFsIGZyZXF1ZW5jeSAqZiowLCB3ZSBoYXZlIGNvbXB1dGVkICpmKjAgYXQgdHdvIGxvY2F0aW9uczogQXQgdGhlIE9mZnNldCBvZiB0aGUgcHJlY2VkaW5nIHZvd2VsIChWMU9mZnNldCkgYW5kIGF0IHRoZSBPbnNldCBvZiB0aGUgZm9sbG93aW5nIHZvd2VsIChWMk9mZnNldCkuDQoNCiMjIyBBdCB0aGUgb2Zmc2V0IG9mIHRoZSBwcmVjZWRpbmcgdm93ZWwNCg0KIyMjIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQoNCldlIHJ1biB0aHJlZSBtb2RlbHMuIEZvciBtb2RlbCBjb21wYXJpc29ucywgd2UgYXJlIHJlcXVpcmVkIHRvIHVzZSBNYXhpbXVtIExpa2VsaWhvb2QgKE1MKSBvbiBib3RoIE9wdGltYWwgYW5kIE51bGwgbW9kZWxzIChieSBhZGRpbmcgUkVNTD1GKS4gVGhlbiB3ZSBydW4gYSBzZWNvbmQgT3B0aW1hbCBtb2RlbHMgd2l0aCBSZXN0cmljdGVkIE1heGltdW0gTGlrZWxpaG9vZCAoUkVNTCksIHRvIG9idGFpbiB0aGUgY29lZmZpY2llbnRzIChieSBhZGRpbmcgUkVNTD1UKQ0KDQojIyMjIyBPcHRpbWFsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpmMFYxT2Zmc2V0LnhtZGwuRnVsbC5NIDwtIGxtZXIoZjBPZmZzZXR+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYxLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQpmMFYxT2Zmc2V0LnhtZGwuRnVsbC5SIDwtIGxtZXIoZjBPZmZzZXR+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYxLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyBOdWxsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpmMFYxT2Zmc2V0LnhtZGwuTnVsbC5NIDwtIGxtZXIoZjBPZmZzZXR+MSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMSxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyBSZXN1bHRzIG9mIG91ciBtb2RlbA0KDQojIyMjIyBNb2RlbCBjb21wYXJpc29ucw0KDQpgYGB7cn0NCmFub3ZhKGYwVjFPZmZzZXQueG1kbC5OdWxsLk0sZjBWMU9mZnNldC54bWRsLkZ1bGwuTSkNCmBgYA0KDQpBcyBjYW4gYmUgc2Vlbiwgb3VyIG9wdGltYWwgbW9kZWwgaW1wcm92ZWQgdGhlIG1vZGVsIGZpdC4NCg0KIyMjIyMgUmVzaWR1YWxzDQoNCldlIGluc3BlY3Qgb3VyIG1vZGVsIGJlbG93LCBieSBsb29raW5nIGF0IHRoZSByZXNpZHVhbHMuIFRoZXJlIGFyZSBtaW5vciBkZXZpYXRpb25zIG9ic2VydmVkLCBkdWUgdG8gdGhlIG5hdHVyZSBvZiBvdXIgZGF0YS4NCg0KYGBge3J9DQpoaXN0KHJlc2lkdWFscyhmMFYxT2Zmc2V0LnhtZGwuRnVsbC5SKSkNCnFxbm9ybShyZXNpZHVhbHMoZjBWMU9mZnNldC54bWRsLkZ1bGwuUikpOyBxcWxpbmUocmVzaWR1YWxzKGYwVjFPZmZzZXQueG1kbC5GdWxsLlIpKQ0KcGxvdChmaXR0ZWQoZjBWMU9mZnNldC54bWRsLkZ1bGwuUikscmVzaWR1YWxzKGYwVjFPZmZzZXQueG1kbC5GdWxsLlIpLCBjZXggPSA0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgbW9kZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGYwVjFPZmZzZXQueG1kbC5GdWxsLlIpDQpgYGANCg0KIyMjIyBGaWd1cmVzDQoNClRoZSBmaWd1cmUgcHJlc2VudGVkIGJlbG93LCB1c2VzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzOyB0aGVzZSBhcmUgdGhlIHZhbHVlcyAqYWRqdXN0ZWQqIGJ5IHRoZSBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlc2UgdGFrZSBpbnRvIGFjY291bnQgdGhlIHJhbmRvbSBlZmZlY3RzJyBzdHJ1Y3R1cmUgYXMgd2VsbCBhcyB0aGUgZml4ZWQgZWZmZWN0cycgc3RydWN0dXJlLiANCg0KIyMjIyMgVXNpbmcgInByZWRpY3QiDQoNClRoZSBmb2xsb3dpbmcgY29kZSBpcyB1c2VkIHRvIHJlY29yZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBpbnRvIHRoZSBzYW1lIGRhdGEtZnJhbWUuIFRoaXMgd2lsbCB0aGVuIGJlIHVzZWQgdG8gcGxvdCB0aGUgcmVzdWx0cyBvZiB0aGUgbW9kZWwNCg0KYGBge3J9DQpnZW1pbmF0aW9uVjEkZml0dGVkX1YxRjBPZmZzZXQgPC0gcHJlZGljdChsbWVyKGYwT2Zmc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMSxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KKQ0KYGBgDQoNCg0KIyMjIyMgUGxvdHRpbmcgdGhlIHJlc3VsdHMNCg0KV2UgdXNlICJnZ3Bsb3QyIiB0byBwbG90IHRoZSByZXN1bHRzLiBUaGlzIHdpbGwgdXNlIHRoZSAicHJlZGljdGVkIiAob3IgZml0dGVkKSB2YWx1ZXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGUgZGFzaGVkIGxpbmVzICp3aXRoaW4qIHRoZSBib3hwbG90cyBhcmUgdGhlIG1lYW4gdmFsdWVzOyB0aGUgbWVkaWFuIGlzIG1hcmtlZCBieSB0aGUgaG9yaXpvbnRhbCBzdHJhaWdodCBsaW5lcy4NCg0KYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9Nn0NCmxhYmVscyA8LSBjKHNpbmdsZXRvbiA9ICJTaW5nbGV0b24iLCBnZW1pbmF0ZSA9ICJHZW1pbmF0ZSIpDQoNCmdnRjBWMU9mZnNldEJ5Vm9pY2UgPC0gZ2dwbG90KGdlbWluYXRpb25WMSwgYWVzKHk9Zml0dGVkX1YxRjBPZmZzZXQsIHg9dm9pY2VkLnVudm9pY2VkKSkgKyANCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gIk5BIixuYS5ybT1UUlVFKSArDQogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAiZXJyb3JiYXIiLCBhZXMoeW1heCA9IC4ueS4uLCB5bWluID0gLi55Li4pLA0KICAgICAgICAgICAgICAgd2lkdGggPSAuNzUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgeWxhYihleHByZXNzaW9uKHBhc3RlKCJGMCAoSHopIikpKSArIGxhYnModGl0bGUgPSAiVjEgT2Zmc2V0IikgKw0KICB0aGVtZV9zZXQodGhlbWVfYncoKSkgKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSkgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoODAsMzAwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1sZXZlbHMoZ2VtaW5hdGlvblYxJHZvaWNlZC51bnZvaWNlZCksIGxhYmVscz1jKCJWb2ljZWxlc3MiLCJWb2ljZWQiKSkgKw0KICBmYWNldF93cmFwKH5zaW5nR2VtLG5jb2w9MSxsYWJlbGxlcj1sYWJlbGxlcihzaW5nR2VtID0gbGFiZWxzKSkNCmdnRjBWMU9mZnNldEJ5Vm9pY2UNCmBgYA0KDQojIyMjIFBhaXJ3aXNlIGNvbXBhcmlzb25zDQoNCkFmdGVyIHJ1bm5pbmcgb3VyIHN0YXRpc3RpY2FsIG1vZGVsIGFib3ZlLCB3ZSB3YW50ZWQgdG8gZXZhbHVhdGUgd2hldGhlciB0aGUgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgYmV0d2VlbiAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChvciBub3QpLiBXZSBwcmVzZW50IHRoZSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3IgZWFjaCBvZiB0aGUgZm91ci13YXkgY29udHJhc3QgYmFzZWQgb24gdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMuDQoNCiMjIyMjIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MNCg0KVGhlIHByZWRpY3RlZCBtZWFucyBhbmQgU0RzIG9mIHRoZSBGMCBhdCB0aGUgT2Zmc2V0IG9mIHRoZSBwcmVjZWRpbmcgdm93ZWwgKFYxT2Zmc2V0KSBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uVjEgJT4lIGdyb3VwX2J5KHNpbmdHZW06dm9pY2VkLnVudm9pY2VkKSAlPiUgc3VtbWFyaXNlKG1lYW4oZml0dGVkX1YxRjBPZmZzZXQpLCBzZChmaXR0ZWRfVjFGME9mZnNldCkpDQpgYGANCg0KIyMjIyMgUGFpcndpc2UgdC10ZXN0IHdpdGggRkRSIGNvcnJlY3Rpb25zDQoNCldlIHVzZWQgdGhlIHBhaXJ3aXNlIHQtdGVzdCBhcyBhdmFpbGFibGUgaW4gYmFzZSBSLiBUaGUgaW5wdXQgd2FzIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gSXQgd2FzIG5vdCBwb3NzaWJsZSB0byBkaXJlY3RseSB1c2Ugb3VyIHN0YXRpc3RpY2FsIG1vZGVsJ3Mgb3V0cHV0IHRvIGNvbXBhcmUgbW9kZWxzLCBnaXZlbiB0aGF0IG91ciBMTU0gbW9kZWwgd2FzIGxvb2tpbmcgYXQgb3ZlcmFsbCBjaGFuZ2UgYXMgYSBtYWluIGVmZmVjdCByYXRoZXIgdGhhbiBhcyBhIHNpbXBsZSBlZmZlY3QncyBtb2RlbC4gVGhpcyBpcyB3aHkgd2UgaGF2ZSB1c2VkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGFzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbDsgdGhlIHJlc3VsdHMgYXJlIHRoZSBzYW1lIGlmIHdlIHdlcmUgdG8gdXNlIHRoZSAiYWN0dWFsIiByZXN1bHRzIHJhdGhlciB0aGFuIHRoZSBwcmVkaWN0ZWQgb25lcy4gDQpXZSB1c2VkIEZEUiAoZm9yIEZhbHNlIERpc2NvdmVyeSBSYXRlKSBjb3JyZWN0aW9uIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucyBhcyB0aGlzIGFsbG93ZWQgZm9yIGNvcnJlY3RpbmcgZm9yIGJpYXMgaW4gdGhlIGRpZmZlcmVuY2VzIGluIGRvaW5nIG11bHRpcGxlIGNvbXBhcmlzb25zLiANCg0KYGBge3J9DQpwYWlyd2lzZS50LnRlc3QoZ2VtaW5hdGlvblYxJGZpdHRlZF9WMUYwT2Zmc2V0LCBnZW1pbmF0aW9uVjEkc2luZ0dlbTpnZW1pbmF0aW9uVjEkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCg0KIyMjIEF0IHRoZSBvbnNldCBvZiB0aGUgZm9sbG93aW5nIHZvd2VsDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KZjBWMk9uc2V0LnhtZGwuRnVsbC5NIDwtIGxtZXIoZjBPbnNldH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjIsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjICBPcHRpbWFsIG1vZGVsIChSRU1MKQ0KDQpgYGB7cn0NCmYwVjJPbnNldC54bWRsLkZ1bGwuUiA8LSBsbWVyKGYwT25zZXR+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYyLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyBOdWxsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpmMFYyT25zZXQueG1kbC5OdWxsLk0gPC0gbG1lcihmME9uc2V0fjErDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjIsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShmMFYyT25zZXQueG1kbC5OdWxsLk0sZjBWMk9uc2V0LnhtZGwuRnVsbC5NKQ0KYGBgDQoNCkFzIGNhbiBiZSBzZWVuLCBvdXIgb3B0aW1hbCBtb2RlbCBpbXByb3ZlZCB0aGUgbW9kZWwgZml0Lg0KDQojIyMjIyBSZXNpZHVhbHMNCg0KV2UgaW5zcGVjdCBvdXIgbW9kZWwgYmVsb3csIGJ5IGxvb2tpbmcgYXQgdGhlIHJlc2lkdWFscy4gVGhlcmUgYXJlIG1pbm9yIGRldmlhdGlvbnMgb2JzZXJ2ZWQsIGR1ZSB0byB0aGUgbmF0dXJlIG9mIG91ciBkYXRhLg0KDQpgYGB7cn0NCmhpc3QocmVzaWR1YWxzKGYwVjJPbnNldC54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGYwVjJPbnNldC54bWRsLkZ1bGwuUikpOyBxcWxpbmUocmVzaWR1YWxzKGYwVjJPbnNldC54bWRsLkZ1bGwuUikpDQpwbG90KGZpdHRlZChmMFYyT25zZXQueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhmMFYyT25zZXQueG1kbC5GdWxsLlIpLCBjZXggPSA0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgbW9kZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGYwVjJPbnNldC54bWRsLkZ1bGwuUikNCmBgYA0KDQojIyMjIEZpZ3VyZXMNCg0KVGhlIGZpZ3VyZSBwcmVzZW50ZWQgYmVsb3csIHVzZXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXM7IHRoZXNlIGFyZSB0aGUgdmFsdWVzICphZGp1c3RlZCogYnkgdGhlIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGVzZSB0YWtlIGludG8gYWNjb3VudCB0aGUgcmFuZG9tIGVmZmVjdHMnIHN0cnVjdHVyZSBhcyB3ZWxsIGFzIHRoZSBmaXhlZCBlZmZlY3RzJyBzdHJ1Y3R1cmUuIA0KDQojIyMjIyBVc2luZyAicHJlZGljdCINCg0KVGhlIGZvbGxvd2luZyBjb2RlIGlzIHVzZWQgdG8gcmVjb3JkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGludG8gdGhlIHNhbWUgZGF0YS1mcmFtZS4gVGhpcyB3aWxsIHRoZW4gYmUgdXNlZCB0byBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbA0KDQpgYGB7cn0NCmdlbWluYXRpb25WMiRmaXR0ZWRfVjJGME9uc2V0IDwtIHByZWRpY3QobG1lcihmME9uc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMixuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KKQ0KYGBgDQoNCg0KIyMjIyMgUGxvdHRpbmcgdGhlIHJlc3VsdHMNCg0KV2UgdXNlICJnZ3Bsb3QyIiB0byBwbG90IHRoZSByZXN1bHRzLiBUaGlzIHdpbGwgdXNlIHRoZSAicHJlZGljdGVkIiAob3IgZml0dGVkKSB2YWx1ZXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGUgZGFzaGVkIGxpbmVzICp3aXRoaW4qIHRoZSBib3hwbG90cyBhcmUgdGhlIG1lYW4gdmFsdWVzOyB0aGUgbWVkaWFuIGlzIG1hcmtlZCBieSB0aGUgaG9yaXpvbnRhbCBzdHJhaWdodCBsaW5lcy4NCg0KYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9Nn0NCmxhYmVscyA8LSBjKHNpbmdsZXRvbiA9ICJTaW5nbGV0b24iLCBnZW1pbmF0ZSA9ICJHZW1pbmF0ZSIpDQoNCmdnRjBWMk9uc2V0QnlWb2ljZSA8LSBnZ3Bsb3QoZ2VtaW5hdGlvblYyLCBhZXMoeT1maXR0ZWRfVjJGME9uc2V0LCB4PXZvaWNlZC51bnZvaWNlZCkpICsgDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJOQSIsbmEucm09VFJVRSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImVycm9yYmFyIiwgYWVzKHltYXggPSAuLnkuLiwgeW1pbiA9IC4ueS4uKSwNCiAgICAgICAgICAgICAgIHdpZHRoID0gLjc1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHlsYWIoZXhwcmVzc2lvbihwYXN0ZSgiRjAgKEh6KSIpKSkgKyBsYWJzKHRpdGxlID0gIlYyIE9uc2V0IikgKw0KICB0aGVtZV9zZXQodGhlbWVfYncoKSkgKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSkgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoODAsMzAwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1sZXZlbHMoZ2VtaW5hdGlvblYyJHZvaWNlZC51bnZvaWNlZCksIGxhYmVscz1jKCJWb2ljZWxlc3MiLCJWb2ljZWQiKSkgKw0KICBmYWNldF93cmFwKH5zaW5nR2VtLG5jb2w9MSxsYWJlbGxlcj1sYWJlbGxlcihzaW5nR2VtID0gbGFiZWxzKSkNCmdnRjBWMk9uc2V0QnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIEYwIGF0IHRoZSBPbnNldCBvZiB0aGUgZm9sbG93aW5nIHZvd2VsIChWMk9uc2V0KSBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uVjIgJT4lIGdyb3VwX2J5KHNpbmdHZW06dm9pY2VkLnVudm9pY2VkKSAlPiUgc3VtbWFyaXNlKG1lYW4oZml0dGVkX1YyRjBPbnNldCksIHNkKGZpdHRlZF9WMkYwT25zZXQpKQ0KYGBgDQoNCiMjIyMjIFBhaXJ3aXNlIHQtdGVzdCB3aXRoIEZEUiBjb3JyZWN0aW9ucw0KDQpXZSB1c2VkIHRoZSBwYWlyd2lzZSB0LXRlc3QgYXMgYXZhaWxhYmxlIGluIGJhc2UgUi4gVGhlIGlucHV0IHdhcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIEl0IHdhcyBub3QgcG9zc2libGUgdG8gZGlyZWN0bHkgdXNlIG91ciBzdGF0aXN0aWNhbCBtb2RlbCdzIG91dHB1dCB0byBjb21wYXJlIG1vZGVscywgZ2l2ZW4gdGhhdCBvdXIgTE1NIG1vZGVsIHdhcyBsb29raW5nIGF0IG92ZXJhbGwgY2hhbmdlIGFzIGEgbWFpbiBlZmZlY3QgcmF0aGVyIHRoYW4gYXMgYSBzaW1wbGUgZWZmZWN0J3MgbW9kZWwuIFRoaXMgaXMgd2h5IHdlIGhhdmUgdXNlZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWw7IHRoZSByZXN1bHRzIGFyZSB0aGUgc2FtZSBpZiB3ZSB3ZXJlIHRvIHVzZSB0aGUgImFjdHVhbCIgcmVzdWx0cyByYXRoZXIgdGhhbiB0aGUgcHJlZGljdGVkIG9uZXMuIA0KV2UgdXNlZCBGRFIgKGZvciBGYWxzZSBEaXNjb3ZlcnkgUmF0ZSkgY29ycmVjdGlvbiBmb3IgbXVsdGlwbGUgY29tcGFyaXNvbnMgYXMgdGhpcyBhbGxvd2VkIGZvciBjb3JyZWN0aW5nIGZvciBiaWFzIGluIHRoZSBkaWZmZXJlbmNlcyBpbiBkb2luZyBtdWx0aXBsZSBjb21wYXJpc29ucy4gDQoNCmBgYHtyfQ0KcGFpcndpc2UudC50ZXN0KGdlbWluYXRpb25WMiRmaXR0ZWRfVjJGME9uc2V0LCBnZW1pbmF0aW9uVjIkc2luZ0dlbTpnZW1pbmF0aW9uVjIkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCg0KIyMgRjEgZnJlcXVlbmN5IChIeikNCg0KV2l0aGluIHRoZSBmaXJzdCBmb3JtYW50IGZyZXF1ZW5jeSAoRjEpLCB3ZSBoYXZlIGNvbXB1dGVkIEYxIGF0IHR3byBsb2NhdGlvbnM6IEF0IHRoZSBPZmZzZXQgb2YgdGhlIHByZWNlZGluZyB2b3dlbCAoVjFPZmZzZXQpIGFuZCBhdCB0aGUgT25zZXQgb2YgdGhlIGZvbGxvd2luZyB2b3dlbCAoVjJPZmZzZXQpLg0KDQojIyMgQXQgdGhlIG9mZnNldCBvZiB0aGUgcHJlY2VkaW5nIHZvd2VsDQoNCiMjIyMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KDQpXZSBydW4gdGhyZWUgbW9kZWxzLiBGb3IgbW9kZWwgY29tcGFyaXNvbnMsIHdlIGFyZSByZXF1aXJlZCB0byB1c2UgTWF4aW11bSBMaWtlbGlob29kIChNTCkgb24gYm90aCBPcHRpbWFsIGFuZCBOdWxsIG1vZGVscyAoYnkgYWRkaW5nIFJFTUw9RikuIFRoZW4gd2UgcnVuIGEgc2Vjb25kIE9wdGltYWwgbW9kZWxzIHdpdGggUmVzdHJpY3RlZCBNYXhpbXVtIExpa2VsaWhvb2QgKFJFTUwpLCB0byBvYnRhaW4gdGhlIGNvZWZmaWNpZW50cyAoYnkgYWRkaW5nIFJFTUw9VCkNCg0KIyMjIyMgT3B0aW1hbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KZjFWMU9mZnNldC54bWRsLkZ1bGwuTSA8LSBsbWVyKGYxT2Zmc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMSxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgIE9wdGltYWwgbW9kZWwgKFJFTUwpDQoNCmBgYHtyfQ0KZjFWMU9mZnNldC54bWRsLkZ1bGwuUiA8LSBsbWVyKGYxT2Zmc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMSxuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgTnVsbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KZjFWMU9mZnNldC54bWRsLk51bGwuTSA8LSBsbWVyKGYxT2Zmc2V0fjErDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjEsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMgUmVzdWx0cyBvZiBvdXIgbW9kZWwNCg0KIyMjIyMgTW9kZWwgY29tcGFyaXNvbnMNCg0KYGBge3J9DQphbm92YShmMVYxT2Zmc2V0LnhtZGwuTnVsbC5NLGYxVjFPZmZzZXQueG1kbC5GdWxsLk0pDQpgYGANCg0KQXMgY2FuIGJlIHNlZW4sIG91ciBvcHRpbWFsIG1vZGVsIGltcHJvdmVkIHRoZSBtb2RlbCBmaXQuDQoNCiMjIyMjIFJlc2lkdWFscw0KDQpXZSBpbnNwZWN0IG91ciBtb2RlbCBiZWxvdywgYnkgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLiBUaGVyZSBhcmUgbWlub3IgZGV2aWF0aW9ucyBvYnNlcnZlZCwgZHVlIHRvIHRoZSBuYXR1cmUgb2Ygb3VyIGRhdGEuDQoNCmBgYHtyfQ0KaGlzdChyZXNpZHVhbHMoZjFWMU9mZnNldC54bWRsLkZ1bGwuUikpDQpxcW5vcm0ocmVzaWR1YWxzKGYxVjFPZmZzZXQueG1kbC5GdWxsLlIpKTsgcXFsaW5lKHJlc2lkdWFscyhmMVYxT2Zmc2V0LnhtZGwuRnVsbC5SKSkNCnBsb3QoZml0dGVkKGYxVjFPZmZzZXQueG1kbC5GdWxsLlIpLHJlc2lkdWFscyhmMVYxT2Zmc2V0LnhtZGwuRnVsbC5SKSwgY2V4ID0gNCkNCmBgYA0KDQojIyMjIyBTdW1tYXJ5IG9mIG1vZGVsDQoNCmBgYHtyfQ0Kc3VtbWFyeShmMVYxT2Zmc2V0LnhtZGwuRnVsbC5SKQ0KYGBgDQoNCiMjIyMgRmlndXJlcw0KDQpUaGUgZmlndXJlIHByZXNlbnRlZCBiZWxvdywgdXNlcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlczsgdGhlc2UgYXJlIHRoZSB2YWx1ZXMgKmFkanVzdGVkKiBieSB0aGUgc3RhdGlzdGljYWwgbW9kZWwuIFRoZXNlIHRha2UgaW50byBhY2NvdW50IHRoZSByYW5kb20gZWZmZWN0cycgc3RydWN0dXJlIGFzIHdlbGwgYXMgdGhlIGZpeGVkIGVmZmVjdHMnIHN0cnVjdHVyZS4gDQoNCiMjIyMjIFVzaW5nICJwcmVkaWN0Ig0KDQpUaGUgZm9sbG93aW5nIGNvZGUgaXMgdXNlZCB0byByZWNvcmQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgaW50byB0aGUgc2FtZSBkYXRhLWZyYW1lLiBUaGlzIHdpbGwgdGhlbiBiZSB1c2VkIHRvIHBsb3QgdGhlIHJlc3VsdHMgb2YgdGhlIG1vZGVsDQoNCmBgYHtyfQ0KZ2VtaW5hdGlvblYxJGZpdHRlZF9WMUYxT2Zmc2V0IDwtIHByZWRpY3QobG1lcihmMU9mZnNldH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjEsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCikNCmBgYA0KDQoNCiMjIyMjIFBsb3R0aW5nIHRoZSByZXN1bHRzDQoNCldlIHVzZSAiZ2dwbG90MiIgdG8gcGxvdCB0aGUgcmVzdWx0cy4gVGhpcyB3aWxsIHVzZSB0aGUgInByZWRpY3RlZCIgKG9yIGZpdHRlZCkgdmFsdWVzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlIGRhc2hlZCBsaW5lcyAqd2l0aGluKiB0aGUgYm94cGxvdHMgYXJlIHRoZSBtZWFuIHZhbHVlczsgdGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgdGhlIGhvcml6b250YWwgc3RyYWlnaHQgbGluZXMuDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQpsYWJlbHMgPC0gYyhzaW5nbGV0b24gPSAiU2luZ2xldG9uIiwgZ2VtaW5hdGUgPSAiR2VtaW5hdGUiKQ0KDQpnZ0YxVjFPZmZzZXRCeVZvaWNlIDwtIGdncGxvdChnZW1pbmF0aW9uVjEsIGFlcyh5PWZpdHRlZF9WMUYxT2Zmc2V0LCB4PXZvaWNlZC51bnZvaWNlZCkpICsgDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJOQSIsbmEucm09VFJVRSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImVycm9yYmFyIiwgYWVzKHltYXggPSAuLnkuLiwgeW1pbiA9IC4ueS4uKSwNCiAgICAgICAgICAgICAgIHdpZHRoID0gLjc1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHlsYWIoZXhwcmVzc2lvbihwYXN0ZSgiRjEgKEh6KSIpKSkgKyBsYWJzKHRpdGxlID0gIlYxIE9mZnNldCIpICsNCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0yMCkpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDMwMCw5MDApKSArDQogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArDQogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzPWxldmVscyhnZW1pbmF0aW9uVjEkdm9pY2VkLnVudm9pY2VkKSwgbGFiZWxzPWMoIlZvaWNlbGVzcyIsIlZvaWNlZCIpKSArDQogIGZhY2V0X3dyYXAofnNpbmdHZW0sbmNvbD0xLGxhYmVsbGVyPWxhYmVsbGVyKHNpbmdHZW0gPSBsYWJlbHMpKQ0KZ2dGMVYxT2Zmc2V0QnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIEYxIGF0IHRoZSBPZmZzZXQgb2YgdGhlIHByZWNlZGluZyB2b3dlbCAoVjFPZmZzZXQpIGFyZSBwcm92aWRlZCBiZWxvdy4gQXMgY2FuIGJlIHNlZW4sIHRoZXJlIGFyZSBhbHJlYWR5IGRpZmZlcmVuY2VzIG9ic2VydmVkIHJlbGF0ZWQgdG8gYm90aCAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIi4NCg0KYGBge3J9DQojIHVzaW5nICJkcGx5ciINCmdlbWluYXRpb25WMSAlPiUgZ3JvdXBfYnkoc2luZ0dlbTp2b2ljZWQudW52b2ljZWQpICU+JSBzdW1tYXJpc2UobWVhbihmaXR0ZWRfVjFGMU9mZnNldCksIHNkKGZpdHRlZF9WMUYxT2Zmc2V0KSkNCmBgYA0KDQojIyMjIyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBGRFIgY29ycmVjdGlvbnMNCg0KV2UgdXNlZCB0aGUgcGFpcndpc2UgdC10ZXN0IGFzIGF2YWlsYWJsZSBpbiBiYXNlIFIuIFRoZSBpbnB1dCB3YXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGRpcmVjdGx5IHVzZSBvdXIgc3RhdGlzdGljYWwgbW9kZWwncyBvdXRwdXQgdG8gY29tcGFyZSBtb2RlbHMsIGdpdmVuIHRoYXQgb3VyIExNTSBtb2RlbCB3YXMgbG9va2luZyBhdCBvdmVyYWxsIGNoYW5nZSBhcyBhIG1haW4gZWZmZWN0IHJhdGhlciB0aGFuIGFzIGEgc2ltcGxlIGVmZmVjdCdzIG1vZGVsLiBUaGlzIGlzIHdoeSB3ZSBoYXZlIHVzZWQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsOyB0aGUgcmVzdWx0cyBhcmUgdGhlIHNhbWUgaWYgd2Ugd2VyZSB0byB1c2UgdGhlICJhY3R1YWwiIHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhlIHByZWRpY3RlZCBvbmVzLiANCldlIHVzZWQgRkRSIChmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUpIGNvcnJlY3Rpb24gZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIGFzIHRoaXMgYWxsb3dlZCBmb3IgY29ycmVjdGluZyBmb3IgYmlhcyBpbiB0aGUgZGlmZmVyZW5jZXMgaW4gZG9pbmcgbXVsdGlwbGUgY29tcGFyaXNvbnMuIA0KDQpgYGB7cn0NCnBhaXJ3aXNlLnQudGVzdChnZW1pbmF0aW9uVjEkZml0dGVkX1YxRjFPZmZzZXQsIGdlbWluYXRpb25WMSRzaW5nR2VtOmdlbWluYXRpb25WMSR2b2ljZWQudW52b2ljZWQsIHAuYWRqID0gImZkciIpDQpgYGANCg0KDQojIyMgQXQgdGhlIG9uc2V0IG9mIHRoZSBmb2xsb3dpbmcgdm93ZWwNCg0KIyMjIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQoNCldlIHJ1biB0aHJlZSBtb2RlbHMuIEZvciBtb2RlbCBjb21wYXJpc29ucywgd2UgYXJlIHJlcXVpcmVkIHRvIHVzZSBNYXhpbXVtIExpa2VsaWhvb2QgKE1MKSBvbiBib3RoIE9wdGltYWwgYW5kIE51bGwgbW9kZWxzIChieSBhZGRpbmcgUkVNTD1GKS4gVGhlbiB3ZSBydW4gYSBzZWNvbmQgT3B0aW1hbCBtb2RlbHMgd2l0aCBSZXN0cmljdGVkIE1heGltdW0gTGlrZWxpaG9vZCAoUkVNTCksIHRvIG9idGFpbiB0aGUgY29lZmZpY2llbnRzIChieSBhZGRpbmcgUkVNTD1UKQ0KDQojIyMjIyBPcHRpbWFsIG1vZGVsIChNTCkNCg0KYGBge3J9DQpmMVYyT25zZXQueG1kbC5GdWxsLk0gPC0gbG1lcihmMU9uc2V0fnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMixuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgIE9wdGltYWwgbW9kZWwgKFJFTUwpDQoNCmBgYHtyfQ0KZjFWMk9uc2V0LnhtZGwuRnVsbC5SIDwtIGxtZXIoZjFPbnNldH52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjIsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjIE51bGwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmYxVjJPbnNldC54bWRsLk51bGwuTSA8LSBsbWVyKGYxT25zZXR+MSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMixuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyBSZXN1bHRzIG9mIG91ciBtb2RlbA0KDQojIyMjIyBNb2RlbCBjb21wYXJpc29ucw0KDQpgYGB7cn0NCmFub3ZhKGYxVjJPbnNldC54bWRsLk51bGwuTSxmMVYyT25zZXQueG1kbC5GdWxsLk0pDQpgYGANCg0KQXMgY2FuIGJlIHNlZW4sIG91ciBvcHRpbWFsIG1vZGVsIGltcHJvdmVkIHRoZSBtb2RlbCBmaXQuDQoNCiMjIyMjIFJlc2lkdWFscw0KDQpXZSBpbnNwZWN0IG91ciBtb2RlbCBiZWxvdywgYnkgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLiBUaGVyZSBhcmUgbWlub3IgZGV2aWF0aW9ucyBvYnNlcnZlZCwgZHVlIHRvIHRoZSBuYXR1cmUgb2Ygb3VyIGRhdGEuDQoNCmBgYHtyfQ0KaGlzdChyZXNpZHVhbHMoZjFWMk9uc2V0LnhtZGwuRnVsbC5SKSkNCnFxbm9ybShyZXNpZHVhbHMoZjFWMk9uc2V0LnhtZGwuRnVsbC5SKSk7IHFxbGluZShyZXNpZHVhbHMoZjFWMk9uc2V0LnhtZGwuRnVsbC5SKSkNCnBsb3QoZml0dGVkKGYxVjJPbnNldC54bWRsLkZ1bGwuUikscmVzaWR1YWxzKGYxVjJPbnNldC54bWRsLkZ1bGwuUiksIGNleCA9IDQpDQpgYGANCg0KIyMjIyMgU3VtbWFyeSBvZiBtb2RlbA0KDQpgYGB7cn0NCnN1bW1hcnkoZjFWMk9uc2V0LnhtZGwuRnVsbC5SKQ0KYGBgDQoNCiMjIyMgRmlndXJlcw0KDQpUaGUgZmlndXJlIHByZXNlbnRlZCBiZWxvdywgdXNlcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlczsgdGhlc2UgYXJlIHRoZSB2YWx1ZXMgKmFkanVzdGVkKiBieSB0aGUgc3RhdGlzdGljYWwgbW9kZWwuIFRoZXNlIHRha2UgaW50byBhY2NvdW50IHRoZSByYW5kb20gZWZmZWN0cycgc3RydWN0dXJlIGFzIHdlbGwgYXMgdGhlIGZpeGVkIGVmZmVjdHMnIHN0cnVjdHVyZS4gDQoNCiMjIyMjIFVzaW5nICJwcmVkaWN0Ig0KDQpUaGUgZm9sbG93aW5nIGNvZGUgaXMgdXNlZCB0byByZWNvcmQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgaW50byB0aGUgc2FtZSBkYXRhLWZyYW1lLiBUaGlzIHdpbGwgdGhlbiBiZSB1c2VkIHRvIHBsb3QgdGhlIHJlc3VsdHMgb2YgdGhlIG1vZGVsDQoNCmBgYHtyfQ0KZ2VtaW5hdGlvblYyJGZpdHRlZF9WMkYxT25zZXQgPC0gcHJlZGljdChsbWVyKGYxT25zZXR+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYyLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQopDQpgYGANCg0KDQojIyMjIyBQbG90dGluZyB0aGUgcmVzdWx0cw0KDQpXZSB1c2UgImdncGxvdDIiIHRvIHBsb3QgdGhlIHJlc3VsdHMuIFRoaXMgd2lsbCB1c2UgdGhlICJwcmVkaWN0ZWQiIChvciBmaXR0ZWQpIHZhbHVlcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIFRoZSBkYXNoZWQgbGluZXMgKndpdGhpbiogdGhlIGJveHBsb3RzIGFyZSB0aGUgbWVhbiB2YWx1ZXM7IHRoZSBtZWRpYW4gaXMgbWFya2VkIGJ5IHRoZSBob3Jpem9udGFsIHN0cmFpZ2h0IGxpbmVzLg0KDQpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQ0KbGFiZWxzIDwtIGMoc2luZ2xldG9uID0gIlNpbmdsZXRvbiIsIGdlbWluYXRlID0gIkdlbWluYXRlIikNCg0KZ2dGMVYyT25zZXRCeVZvaWNlIDwtIGdncGxvdChnZW1pbmF0aW9uVjIsIGFlcyh5PWZpdHRlZF9WMkYxT25zZXQsIHg9dm9pY2VkLnVudm9pY2VkKSkgKyANCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gIk5BIixuYS5ybT1UUlVFKSArDQogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAiZXJyb3JiYXIiLCBhZXMoeW1heCA9IC4ueS4uLCB5bWluID0gLi55Li4pLA0KICAgICAgICAgICAgICAgd2lkdGggPSAuNzUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgeWxhYihleHByZXNzaW9uKHBhc3RlKCJGMSAoSHopIikpKSArIGxhYnModGl0bGUgPSAiVjIgT25zZXQiKSArDQogIHRoZW1lX3NldCh0aGVtZV9idygpKSArIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygzMDAsOTAwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1sZXZlbHMoZ2VtaW5hdGlvblYyJHZvaWNlZC51bnZvaWNlZCksIGxhYmVscz1jKCJWb2ljZWxlc3MiLCJWb2ljZWQiKSkgKw0KICBmYWNldF93cmFwKH5zaW5nR2VtLG5jb2w9MSxsYWJlbGxlcj1sYWJlbGxlcihzaW5nR2VtID0gbGFiZWxzKSkNCmdnRjFWMk9uc2V0QnlWb2ljZQ0KYGBgDQoNCiMjIyMgUGFpcndpc2UgY29tcGFyaXNvbnMNCg0KQWZ0ZXIgcnVubmluZyBvdXIgc3RhdGlzdGljYWwgbW9kZWwgYWJvdmUsIHdlIHdhbnRlZCB0byBldmFsdWF0ZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBvYnNlcnZlZCBiZXR3ZWVuICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIFdlIHByZXNlbnQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIGZvciBlYWNoIG9mIHRoZSBmb3VyLXdheSBjb250cmFzdCBiYXNlZCBvbiB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcy4NCg0KIyMjIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KDQpUaGUgcHJlZGljdGVkIG1lYW5zIGFuZCBTRHMgb2YgdGhlIEYxIGF0IHRoZSBPbnNldCBvZiB0aGUgZm9sbG93aW5nIHZvd2VsIChWMk9uc2V0KSBhcmUgcHJvdmlkZWQgYmVsb3cuIEFzIGNhbiBiZSBzZWVuLCB0aGVyZSBhcmUgYWxyZWFkeSBkaWZmZXJlbmNlcyBvYnNlcnZlZCByZWxhdGVkIHRvIGJvdGggInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIuDQoNCmBgYHtyfQ0KIyB1c2luZyAiZHBseXIiDQpnZW1pbmF0aW9uVjIgJT4lIGdyb3VwX2J5KHNpbmdHZW06dm9pY2VkLnVudm9pY2VkKSAlPiUgc3VtbWFyaXNlKG1lYW4oZml0dGVkX1YyRjFPbnNldCksIHNkKGZpdHRlZF9WMkYxT25zZXQpKQ0KYGBgDQoNCiMjIyMjIFBhaXJ3aXNlIHQtdGVzdCB3aXRoIEZEUiBjb3JyZWN0aW9ucw0KDQpXZSB1c2VkIHRoZSBwYWlyd2lzZSB0LXRlc3QgYXMgYXZhaWxhYmxlIGluIGJhc2UgUi4gVGhlIGlucHV0IHdhcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIEl0IHdhcyBub3QgcG9zc2libGUgdG8gZGlyZWN0bHkgdXNlIG91ciBzdGF0aXN0aWNhbCBtb2RlbCdzIG91dHB1dCB0byBjb21wYXJlIG1vZGVscywgZ2l2ZW4gdGhhdCBvdXIgTE1NIG1vZGVsIHdhcyBsb29raW5nIGF0IG92ZXJhbGwgY2hhbmdlIGFzIGEgbWFpbiBlZmZlY3QgcmF0aGVyIHRoYW4gYXMgYSBzaW1wbGUgZWZmZWN0J3MgbW9kZWwuIFRoaXMgaXMgd2h5IHdlIGhhdmUgdXNlZCB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlcyBhcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWw7IHRoZSByZXN1bHRzIGFyZSB0aGUgc2FtZSBpZiB3ZSB3ZXJlIHRvIHVzZSB0aGUgImFjdHVhbCIgcmVzdWx0cyByYXRoZXIgdGhhbiB0aGUgcHJlZGljdGVkIG9uZXMuIA0KV2UgdXNlZCBGRFIgKGZvciBGYWxzZSBEaXNjb3ZlcnkgUmF0ZSkgY29ycmVjdGlvbiBmb3IgbXVsdGlwbGUgY29tcGFyaXNvbnMgYXMgdGhpcyBhbGxvd2VkIGZvciBjb3JyZWN0aW5nIGZvciBiaWFzIGluIHRoZSBkaWZmZXJlbmNlcyBpbiBkb2luZyBtdWx0aXBsZSBjb21wYXJpc29ucy4gDQoNCmBgYHtyfQ0KcGFpcndpc2UudC50ZXN0KGdlbWluYXRpb25WMiRmaXR0ZWRfVjJGMU9uc2V0LCBnZW1pbmF0aW9uVjIkc2luZ0dlbTpnZW1pbmF0aW9uVjIkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCg0KIyMgKkgqMSZhc3Q7LSpIKjImYXN0OyAoZEIpDQoNCldpdGhpbiB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgbm9ybWFsaXNlZCBmaXJzdCBhbmQgc2Vjb25kIGhhcm1vbmljcyB0byBjdWUgdm9pY2UgcXVhbGl0eSAoKkgqMSZhc3Q7LSpIKjImYXN0OyksIHdlIGhhdmUgY29tcHV0ZWQgKkgqMSZhc3Q7LSpIKjImYXN0OyBhdCB0d28gbG9jYXRpb25zOiBBdCB0aGUgT2Zmc2V0IG9mIHRoZSBwcmVjZWRpbmcgdm93ZWwgKFYxT2Zmc2V0KSBhbmQgYXQgdGhlIE9uc2V0IG9mIHRoZSBmb2xsb3dpbmcgdm93ZWwgKFYyT2Zmc2V0KS4NCg0KIyMjIEF0IHRoZSBvZmZzZXQgb2YgdGhlIHByZWNlZGluZyB2b3dlbA0KDQojIyMjIE1vZGVsIHNwZWNpZmljYXRpb24NCg0KV2UgcnVuIHRocmVlIG1vZGVscy4gRm9yIG1vZGVsIGNvbXBhcmlzb25zLCB3ZSBhcmUgcmVxdWlyZWQgdG8gdXNlIE1heGltdW0gTGlrZWxpaG9vZCAoTUwpIG9uIGJvdGggT3B0aW1hbCBhbmQgTnVsbCBtb2RlbHMgKGJ5IGFkZGluZyBSRU1MPUYpLiBUaGVuIHdlIHJ1biBhIHNlY29uZCBPcHRpbWFsIG1vZGVscyB3aXRoIFJlc3RyaWN0ZWQgTWF4aW11bSBMaWtlbGlob29kIChSRU1MKSwgdG8gb2J0YWluIHRoZSBjb2VmZmljaWVudHMgKGJ5IGFkZGluZyBSRU1MPVQpDQoNCiMjIyMjIE9wdGltYWwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmgxbW5oMlYxT2Zmc2V0LnhtZGwuRnVsbC5NIDwtIGxtZXIoaDFtbmgyT2Zmc2V0Tm9ybX52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjEsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjICBPcHRpbWFsIG1vZGVsIChSRU1MKQ0KDQpgYGB7cn0NCmgxbW5oMlYxT2Zmc2V0LnhtZGwuRnVsbC5SIDwtIGxtZXIoaDFtbmgyT2Zmc2V0Tm9ybX52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjEsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCg0KYGBgDQoNCiMjIyMjIE51bGwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmgxbW5oMlYxT2Zmc2V0LnhtZGwuTnVsbC5NIDwtIGxtZXIoaDFtbmgyT2Zmc2V0Tm9ybX4xKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYxLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIFJlc3VsdHMgb2Ygb3VyIG1vZGVsDQoNCiMjIyMjIE1vZGVsIGNvbXBhcmlzb25zDQoNCmBgYHtyfQ0KYW5vdmEoaDFtbmgyVjFPZmZzZXQueG1kbC5OdWxsLk0saDFtbmgyVjFPZmZzZXQueG1kbC5GdWxsLk0pDQpgYGANCg0KQXMgY2FuIGJlIHNlZW4sIG91ciBvcHRpbWFsIG1vZGVsIGRpZCBub3QgaW1wcm92ZSB0aGUgbW9kZWwgZml0LiBIb3dldmVyLCB3ZSB3aWxsIHN0aWxsIHVzZSB0aGUgb3B0aW1hbCBtb2RlbCB0byBhbGxvdyBmb3IgY29tcGFyaXNvbiB3aXRoIHRoZSBvdGhlciBtb2RlbHMuIFRoaXMgbm9uLXNpZ25pZmljYW50IGVmZmVjdCBpcyBpbmRpY2F0aXZlIG9mIGEgbm9uLWFzc29jaWF0aW9uIGJldHdlZW4gKkgqMSZhc3Q7LSpIKjImYXN0OyBhbmQgdGhlIHByZWRpY3RvcnMuDQoNCiMjIyMjIFJlc2lkdWFscw0KDQpXZSBpbnNwZWN0IG91ciBtb2RlbCBiZWxvdywgYnkgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLiBUaGVyZSBhcmUgbWlub3IgZGV2aWF0aW9ucyBvYnNlcnZlZCwgZHVlIHRvIHRoZSBuYXR1cmUgb2Ygb3VyIGRhdGEuDQoNCmBgYHtyfQ0KaGlzdChyZXNpZHVhbHMoaDFtbmgyVjFPZmZzZXQueG1kbC5GdWxsLlIpKQ0KcXFub3JtKHJlc2lkdWFscyhoMW1uaDJWMU9mZnNldC54bWRsLkZ1bGwuUikpOyBxcWxpbmUocmVzaWR1YWxzKGgxbW5oMlYxT2Zmc2V0LnhtZGwuRnVsbC5SKSkNCnBsb3QoZml0dGVkKGgxbW5oMlYxT2Zmc2V0LnhtZGwuRnVsbC5SKSxyZXNpZHVhbHMoaDFtbmgyVjFPZmZzZXQueG1kbC5GdWxsLlIpLCBjZXggPSA0KQ0KYGBgDQoNCiMjIyMjIFN1bW1hcnkgb2YgbW9kZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGgxbW5oMlYxT2Zmc2V0LnhtZGwuRnVsbC5SKQ0KYGBgDQoNCiMjIyMgRmlndXJlcw0KDQpUaGUgZmlndXJlIHByZXNlbnRlZCBiZWxvdywgdXNlcyB0aGUgcHJlZGljdGVkIChvciBmaXR0ZWQpIHZhbHVlczsgdGhlc2UgYXJlIHRoZSB2YWx1ZXMgKmFkanVzdGVkKiBieSB0aGUgc3RhdGlzdGljYWwgbW9kZWwuIFRoZXNlIHRha2UgaW50byBhY2NvdW50IHRoZSByYW5kb20gZWZmZWN0cycgc3RydWN0dXJlIGFzIHdlbGwgYXMgdGhlIGZpeGVkIGVmZmVjdHMnIHN0cnVjdHVyZS4gDQoNCiMjIyMjIFVzaW5nICJwcmVkaWN0Ig0KDQpUaGUgZm9sbG93aW5nIGNvZGUgaXMgdXNlZCB0byByZWNvcmQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgaW50byB0aGUgc2FtZSBkYXRhLWZyYW1lLiBUaGlzIHdpbGwgdGhlbiBiZSB1c2VkIHRvIHBsb3QgdGhlIHJlc3VsdHMgb2YgdGhlIG1vZGVsDQoNCmBgYHtyfQ0KZ2VtaW5hdGlvblYxJGZpdHRlZF9WMWgxbW5oMk9mZnNldE5vcm0gPC0gcHJlZGljdChsbWVyKGgxbW5oMk9mZnNldE5vcm1+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYxLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQopDQpgYGANCg0KDQojIyMjIyBQbG90dGluZyB0aGUgcmVzdWx0cw0KDQpXZSB1c2UgImdncGxvdDIiIHRvIHBsb3QgdGhlIHJlc3VsdHMuIFRoaXMgd2lsbCB1c2UgdGhlICJwcmVkaWN0ZWQiIChvciBmaXR0ZWQpIHZhbHVlcyBhZGp1c3RlZCBieSBvdXIgc3RhdGlzdGljYWwgbW9kZWwuIFRoZSBkYXNoZWQgbGluZXMgKndpdGhpbiogdGhlIGJveHBsb3RzIGFyZSB0aGUgbWVhbiB2YWx1ZXM7IHRoZSBtZWRpYW4gaXMgbWFya2VkIGJ5IHRoZSBob3Jpem9udGFsIHN0cmFpZ2h0IGxpbmVzLg0KDQpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQ0KbGFiZWxzIDwtIGMoc2luZ2xldG9uID0gIlNpbmdsZXRvbiIsIGdlbWluYXRlID0gIkdlbWluYXRlIikNCg0KZ2doMW1uaDJWMU9mZnNldEJ5Vm9pY2UgPC0gZ2dwbG90KGdlbWluYXRpb25WMSwgYWVzKHk9Zml0dGVkX1YxaDFtbmgyT2Zmc2V0Tm9ybSwgeD12b2ljZWQudW52b2ljZWQpKSArIA0KICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAiTkEiLG5hLnJtPVRSVUUpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICJlcnJvcmJhciIsIGFlcyh5bWF4ID0gLi55Li4sIHltaW4gPSAuLnkuLiksDQogICAgICAgICAgICAgICB3aWR0aCA9IC43NSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB5bGFiKGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKCJIIiksIjEqLSIsaXRhbGljKCJIIiksIjIqIChkQikiKSkpICsgbGFicyh0aXRsZSA9ICJWMSBPZmZzZXQiKSArDQogIHRoZW1lX3NldCh0aGVtZV9idygpKSArIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMTAsMTApKSArDQogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArDQogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzPWxldmVscyhnZW1pbmF0aW9uVjEkdm9pY2VkLnVudm9pY2VkKSwgbGFiZWxzPWMoIlZvaWNlbGVzcyIsIlZvaWNlZCIpKSArDQogIGZhY2V0X3dyYXAofnNpbmdHZW0sbmNvbD0xLGxhYmVsbGVyPWxhYmVsbGVyKHNpbmdHZW0gPSBsYWJlbHMpKQ0KZ2doMW1uaDJWMU9mZnNldEJ5Vm9pY2UNCmBgYA0KDQojIyMjIFBhaXJ3aXNlIGNvbXBhcmlzb25zDQoNCkFmdGVyIHJ1bm5pbmcgb3VyIHN0YXRpc3RpY2FsIG1vZGVsIGFib3ZlLCB3ZSB3YW50ZWQgdG8gZXZhbHVhdGUgd2hldGhlciB0aGUgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgYmV0d2VlbiAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChvciBub3QpLiBXZSBwcmVzZW50IHRoZSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3IgZWFjaCBvZiB0aGUgZm91ci13YXkgY29udHJhc3QgYmFzZWQgb24gdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMuDQoNCiMjIyMjIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MNCg0KVGhlIHByZWRpY3RlZCBtZWFucyBhbmQgU0RzIG9mIHRoZSAqSCoxJmFzdDstKkgqMiZhc3Q7IGF0IHRoZSBPZmZzZXQgb2YgdGhlIHByZWNlZGluZyB2b3dlbCAoVjFPZmZzZXQpIGFyZSBwcm92aWRlZCBiZWxvdy4gQXMgY2FuIGJlIHNlZW4sIHRoZXJlIGFyZSBhbHJlYWR5IGRpZmZlcmVuY2VzIG9ic2VydmVkIHJlbGF0ZWQgdG8gYm90aCAidm9pY2luZyIgYW5kICJnZW1pbmF0aW9uIi4NCg0KYGBge3J9DQojIHVzaW5nICJkcGx5ciINCmdlbWluYXRpb25WMSAlPiUgZ3JvdXBfYnkoc2luZ0dlbTp2b2ljZWQudW52b2ljZWQpICU+JSBzdW1tYXJpc2UobWVhbihmaXR0ZWRfVjFoMW1uaDJPZmZzZXROb3JtLG5hLnJtID0gVCksIHNkKGZpdHRlZF9WMWgxbW5oMk9mZnNldE5vcm0sbmEucm0gPSBUKSkNCmBgYA0KDQojIyMjIyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBGRFIgY29ycmVjdGlvbnMNCg0KV2UgdXNlZCB0aGUgcGFpcndpc2UgdC10ZXN0IGFzIGF2YWlsYWJsZSBpbiBiYXNlIFIuIFRoZSBpbnB1dCB3YXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGRpcmVjdGx5IHVzZSBvdXIgc3RhdGlzdGljYWwgbW9kZWwncyBvdXRwdXQgdG8gY29tcGFyZSBtb2RlbHMsIGdpdmVuIHRoYXQgb3VyIExNTSBtb2RlbCB3YXMgbG9va2luZyBhdCBvdmVyYWxsIGNoYW5nZSBhcyBhIG1haW4gZWZmZWN0IHJhdGhlciB0aGFuIGFzIGEgc2ltcGxlIGVmZmVjdCdzIG1vZGVsLiBUaGlzIGlzIHdoeSB3ZSBoYXZlIHVzZWQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsOyB0aGUgcmVzdWx0cyBhcmUgdGhlIHNhbWUgaWYgd2Ugd2VyZSB0byB1c2UgdGhlICJhY3R1YWwiIHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhlIHByZWRpY3RlZCBvbmVzLiANCldlIHVzZWQgRkRSIChmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUpIGNvcnJlY3Rpb24gZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIGFzIHRoaXMgYWxsb3dlZCBmb3IgY29ycmVjdGluZyBmb3IgYmlhcyBpbiB0aGUgZGlmZmVyZW5jZXMgaW4gZG9pbmcgbXVsdGlwbGUgY29tcGFyaXNvbnMuIA0KDQpgYGB7cn0NCnBhaXJ3aXNlLnQudGVzdChnZW1pbmF0aW9uVjEkZml0dGVkX1YxaDFtbmgyT2Zmc2V0Tm9ybSwgZ2VtaW5hdGlvblYxJHNpbmdHZW06Z2VtaW5hdGlvblYxJHZvaWNlZC51bnZvaWNlZCwgcC5hZGogPSAiZmRyIikNCmBgYA0KDQoNCiMjIyBBdCB0aGUgb25zZXQgb2YgdGhlIGZvbGxvd2luZyB2b3dlbA0KDQojIyMjIE1vZGVsIHNwZWNpZmljYXRpb24NCg0KV2UgcnVuIHRocmVlIG1vZGVscy4gRm9yIG1vZGVsIGNvbXBhcmlzb25zLCB3ZSBhcmUgcmVxdWlyZWQgdG8gdXNlIE1heGltdW0gTGlrZWxpaG9vZCAoTUwpIG9uIGJvdGggT3B0aW1hbCBhbmQgTnVsbCBtb2RlbHMgKGJ5IGFkZGluZyBSRU1MPUYpLiBUaGVuIHdlIHJ1biBhIHNlY29uZCBPcHRpbWFsIG1vZGVscyB3aXRoIFJlc3RyaWN0ZWQgTWF4aW11bSBMaWtlbGlob29kIChSRU1MKSwgdG8gb2J0YWluIHRoZSBjb2VmZmljaWVudHMgKGJ5IGFkZGluZyBSRU1MPVQpDQoNCiMjIyMjIE9wdGltYWwgbW9kZWwgKE1MKQ0KDQpgYGB7cn0NCmgxbW5oMlYyT25zZXQueG1kbC5GdWxsLk0gPC0gbG1lcihoMW1uaDJPbnNldE5vcm1+dm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3NleF9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYyLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIyAgT3B0aW1hbCBtb2RlbCAoUkVNTCkNCg0KYGBge3J9DQpoMW1uaDJWMk9uc2V0LnhtZGwuRnVsbC5SIDwtIGxtZXIoaDFtbmgyT25zZXROb3JtfnZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYytzZXhfYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfYysNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWNlZC51bnZvaWNlZF9jK3NpbmdHZW1fYyt2b3dlbExlbmd0aF9jK3N5bGxUeXBlX2MrcGxhY2VfY3x8c3BlYWtlcikrKDF8d29yZFRhcmdldCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdlbWluYXRpb25WMixuYS5hY3Rpb249bmEuZXhjbHVkZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFTUw9VCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIixvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNSkpKQ0KDQpgYGANCg0KIyMjIyMgTnVsbCBtb2RlbCAoTUwpDQoNCmBgYHtyfQ0KaDFtbmgyVjJPbnNldC54bWRsLk51bGwuTSA8LSBsbWVyKGgxbW5oMk9uc2V0Tm9ybX4xKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodm9pY2VkLnVudm9pY2VkX2Mrc2luZ0dlbV9jK3Zvd2VsTGVuZ3RoX2Mrc3lsbFR5cGVfYytwbGFjZV9jfHxzcGVha2VyKSsoMXx3b3JkVGFyZ2V0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZ2VtaW5hdGlvblYyLG5hLmFjdGlvbj1uYS5leGNsdWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVNTD1GLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLG9wdEN0cmw9bGlzdChtYXhmdW49MWU1KSkpDQoNCmBgYA0KDQojIyMjIFJlc3VsdHMgb2Ygb3VyIG1vZGVsDQoNCiMjIyMjIE1vZGVsIGNvbXBhcmlzb25zDQoNCmBgYHtyfQ0KYW5vdmEoaDFtbmgyVjJPbnNldC54bWRsLk51bGwuTSxoMW1uaDJWMk9uc2V0LnhtZGwuRnVsbC5NKQ0KYGBgDQoNCkFzIGNhbiBiZSBzZWVuLCBvdXIgb3B0aW1hbCBtb2RlbCBpbXByb3ZlZCB0aGUgbW9kZWwgZml0Lg0KDQojIyMjIyBSZXNpZHVhbHMNCg0KV2UgaW5zcGVjdCBvdXIgbW9kZWwgYmVsb3csIGJ5IGxvb2tpbmcgYXQgdGhlIHJlc2lkdWFscy4gVGhlcmUgYXJlIG1pbm9yIGRldmlhdGlvbnMgb2JzZXJ2ZWQsIGR1ZSB0byB0aGUgbmF0dXJlIG9mIG91ciBkYXRhLg0KDQpgYGB7cn0NCmhpc3QocmVzaWR1YWxzKGgxbW5oMlYyT25zZXQueG1kbC5GdWxsLlIpKQ0KcXFub3JtKHJlc2lkdWFscyhoMW1uaDJWMk9uc2V0LnhtZGwuRnVsbC5SKSk7IHFxbGluZShyZXNpZHVhbHMoaDFtbmgyVjJPbnNldC54bWRsLkZ1bGwuUikpDQpwbG90KGZpdHRlZChoMW1uaDJWMk9uc2V0LnhtZGwuRnVsbC5SKSxyZXNpZHVhbHMoaDFtbmgyVjJPbnNldC54bWRsLkZ1bGwuUiksIGNleCA9IDQpDQpgYGANCg0KIyMjIyMgU3VtbWFyeSBvZiBtb2RlbA0KDQpgYGB7cn0NCnN1bW1hcnkoaDFtbmgyVjJPbnNldC54bWRsLkZ1bGwuUikNCmBgYA0KDQojIyMjIEZpZ3VyZXMNCg0KVGhlIGZpZ3VyZSBwcmVzZW50ZWQgYmVsb3csIHVzZXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXM7IHRoZXNlIGFyZSB0aGUgdmFsdWVzICphZGp1c3RlZCogYnkgdGhlIHN0YXRpc3RpY2FsIG1vZGVsLiBUaGVzZSB0YWtlIGludG8gYWNjb3VudCB0aGUgcmFuZG9tIGVmZmVjdHMnIHN0cnVjdHVyZSBhcyB3ZWxsIGFzIHRoZSBmaXhlZCBlZmZlY3RzJyBzdHJ1Y3R1cmUuIA0KDQojIyMjIyBVc2luZyAicHJlZGljdCINCg0KVGhlIGZvbGxvd2luZyBjb2RlIGlzIHVzZWQgdG8gcmVjb3JkIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzIGludG8gdGhlIHNhbWUgZGF0YS1mcmFtZS4gVGhpcyB3aWxsIHRoZW4gYmUgdXNlZCB0byBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbA0KDQpgYGB7cn0NCmdlbWluYXRpb25WMiRmaXR0ZWRfVjJoMW1uaDJPbnNldE5vcm0gPC0gcHJlZGljdChsbWVyKGgxbW5oMk9uc2V0Tm9ybX52b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrc2V4X2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2MrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2b2ljZWQudW52b2ljZWRfYytzaW5nR2VtX2Mrdm93ZWxMZW5ndGhfYytzeWxsVHlwZV9jK3BsYWNlX2N8fHNwZWFrZXIpKygxfHdvcmRUYXJnZXQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZW1pbmF0aW9uVjIsbmEuYWN0aW9uPW5hLmV4Y2x1ZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRU1MPVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsb3B0Q3RybD1saXN0KG1heGZ1bj0xZTUpKSkNCikNCmBgYA0KDQoNCiMjIyMjIFBsb3R0aW5nIHRoZSByZXN1bHRzDQoNCldlIHVzZSAiZ2dwbG90MiIgdG8gcGxvdCB0aGUgcmVzdWx0cy4gVGhpcyB3aWxsIHVzZSB0aGUgInByZWRpY3RlZCIgKG9yIGZpdHRlZCkgdmFsdWVzIGFkanVzdGVkIGJ5IG91ciBzdGF0aXN0aWNhbCBtb2RlbC4gVGhlIGRhc2hlZCBsaW5lcyAqd2l0aGluKiB0aGUgYm94cGxvdHMgYXJlIHRoZSBtZWFuIHZhbHVlczsgdGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgdGhlIGhvcml6b250YWwgc3RyYWlnaHQgbGluZXMuDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQpsYWJlbHMgPC0gYyhzaW5nbGV0b24gPSAiU2luZ2xldG9uIiwgZ2VtaW5hdGUgPSAiR2VtaW5hdGUiKQ0KDQpnZ2gxbW5oMlYyT25zZXRCeVZvaWNlIDwtIGdncGxvdChnZW1pbmF0aW9uVjIsIGFlcyh5PWZpdHRlZF9WMmgxbW5oMk9uc2V0Tm9ybSwgeD12b2ljZWQudW52b2ljZWQpKSArIA0KICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAiTkEiLG5hLnJtPVRSVUUpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICJlcnJvcmJhciIsIGFlcyh5bWF4ID0gLi55Li4sIHltaW4gPSAuLnkuLiksDQogICAgICAgICAgICAgICB3aWR0aCA9IC43NSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB5bGFiKGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKCJIIiksIjEqLSIsaXRhbGljKCJIIiksIjIqIChkQikiKSkpICsgbGFicyh0aXRsZSA9ICJWMiBPbnNldCIpICsNCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0yMCkpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0xMCwxMCkpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9bGV2ZWxzKGdlbWluYXRpb25WMiR2b2ljZWQudW52b2ljZWQpLCBsYWJlbHM9YygiVm9pY2VsZXNzIiwiVm9pY2VkIikpICsNCiAgZmFjZXRfd3JhcCh+c2luZ0dlbSxuY29sPTEsbGFiZWxsZXI9bGFiZWxsZXIoc2luZ0dlbSA9IGxhYmVscykpDQpnZ2gxbW5oMlYyT25zZXRCeVZvaWNlDQpgYGANCg0KIyMjIyBQYWlyd2lzZSBjb21wYXJpc29ucw0KDQpBZnRlciBydW5uaW5nIG91ciBzdGF0aXN0aWNhbCBtb2RlbCBhYm92ZSwgd2Ugd2FudGVkIHRvIGV2YWx1YXRlIHdoZXRoZXIgdGhlIGRpZmZlcmVuY2VzIG9ic2VydmVkIGJldHdlZW4gInZvaWNpbmciIGFuZCAiZ2VtaW5hdGlvbiIgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCAob3Igbm90KS4gV2UgcHJlc2VudCB0aGUgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgZm9yIGVhY2ggb2YgdGhlIGZvdXItd2F5IGNvbnRyYXN0IGJhc2VkIG9uIHRoZSBwcmVkaWN0ZWQgKG9yIGZpdHRlZCkgdmFsdWVzLg0KDQojIyMjIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzDQoNClRoZSBwcmVkaWN0ZWQgbWVhbnMgYW5kIFNEcyBvZiB0aGUgKkgqMSZhc3Q7LSpIKjImYXN0OyBhdCB0aGUgT25zZXQgb2YgdGhlIGZvbGxvd2luZyB2b3dlbCAoVjJPbnNldCkgYXJlIHByb3ZpZGVkIGJlbG93LiBBcyBjYW4gYmUgc2VlbiwgdGhlcmUgYXJlIGFscmVhZHkgZGlmZmVyZW5jZXMgb2JzZXJ2ZWQgcmVsYXRlZCB0byBib3RoICJ2b2ljaW5nIiBhbmQgImdlbWluYXRpb24iLg0KDQpgYGB7cn0NCiMgdXNpbmcgImRwbHlyIg0KZ2VtaW5hdGlvblYyICU+JSBncm91cF9ieShzaW5nR2VtOnZvaWNlZC51bnZvaWNlZCkgJT4lIHN1bW1hcmlzZShtZWFuKGZpdHRlZF9WMmgxbW5oMk9uc2V0Tm9ybSxuYS5ybSA9IFQpLCBzZChmaXR0ZWRfVjJoMW1uaDJPbnNldE5vcm0sbmEucm0gPSBUKSkNCmBgYA0KDQojIyMjIyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBGRFIgY29ycmVjdGlvbnMNCg0KV2UgdXNlZCB0aGUgcGFpcndpc2UgdC10ZXN0IGFzIGF2YWlsYWJsZSBpbiBiYXNlIFIuIFRoZSBpbnB1dCB3YXMgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsLiBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGRpcmVjdGx5IHVzZSBvdXIgc3RhdGlzdGljYWwgbW9kZWwncyBvdXRwdXQgdG8gY29tcGFyZSBtb2RlbHMsIGdpdmVuIHRoYXQgb3VyIExNTSBtb2RlbCB3YXMgbG9va2luZyBhdCBvdmVyYWxsIGNoYW5nZSBhcyBhIG1haW4gZWZmZWN0IHJhdGhlciB0aGFuIGFzIGEgc2ltcGxlIGVmZmVjdCdzIG1vZGVsLiBUaGlzIGlzIHdoeSB3ZSBoYXZlIHVzZWQgdGhlIHByZWRpY3RlZCAob3IgZml0dGVkKSB2YWx1ZXMgYXMgYWRqdXN0ZWQgYnkgb3VyIHN0YXRpc3RpY2FsIG1vZGVsOyB0aGUgcmVzdWx0cyBhcmUgdGhlIHNhbWUgaWYgd2Ugd2VyZSB0byB1c2UgdGhlICJhY3R1YWwiIHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhlIHByZWRpY3RlZCBvbmVzLiANCldlIHVzZWQgRkRSIChmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUpIGNvcnJlY3Rpb24gZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIGFzIHRoaXMgYWxsb3dlZCBmb3IgY29ycmVjdGluZyBmb3IgYmlhcyBpbiB0aGUgZGlmZmVyZW5jZXMgaW4gZG9pbmcgbXVsdGlwbGUgY29tcGFyaXNvbnMuIA0KDQpgYGB7cn0NCnBhaXJ3aXNlLnQudGVzdChnZW1pbmF0aW9uVjIkZml0dGVkX1YyaDFtbmgyT25zZXROb3JtLCBnZW1pbmF0aW9uVjIkc2luZ0dlbTpnZW1pbmF0aW9uVjIkdm9pY2VkLnVudm9pY2VkLCBwLmFkaiA9ICJmZHIiKQ0KYGBgDQoNCg==