comment: toc comand not working, need to repost with headings links for ease of navigation

General notes

This contained planed analyses as of 18.06.17 for data set which we will start to collect on 19/06/17. Plans may change as a result of statsitical consulation (we are currently seeking advice on some details)

The study is a training study to be conducted with year 3 (7-8 years) children with no previous knowledge of Mandarin or any tone language, training them on the four tones (6 tone contrasts) in Mandarin. There will intially be two conditions: (1) pictures-only: they are trained using a 2AFC task where they hear a (real) Mandarin word and identify which of two pictures it refers to (one correct, one a foil which differs only by tone); (2) pictures+diacritics - same task but the pictures are acompanied by pictures of the four diacritics. [If resources permit, we may later run a diacritics only condition]. Data will be collected both from training and from some tests conducted pre and post training.

Our main analyses will be Baysean and we will computing Bayes factors using the method advocated by Dienes, 2008 ;Dienes, 2015; we will also along side provide frequentist statistics. Frequentist statistics will computed using logistic mixed effect models, this method is used since in each case we have a dependent variable of correct/incorrect response. Note that although mixed models allow us to include both participants and items, we do not intend to include items in the analyses since power on this dimension will be low. (NB - it is not common for by items analyses to be included for work in this area; increasing the number of items in a learning study of this type with children is not feasible). We use full random slopes structure for predictors of interest (generally, condition, session/pre->post). Factors such as tone contrast for the trial are included as fixed factors and we will not include random slopes for these.

For the Bayesian analsyes, we will continue to work in log odds space (as for Frequentist) to meet assumptions of normality, using estimates and standard errors which come from the logistic mixed effects models. Following Dienes (2008) we will model H1 by using an estimate of the mean for theory (an estimate coming from either from logistic mixed effects models run over pilot data, or in some cases from elsewhere in the data) as the SD of a half normal (for one tailed) or full normal (for two tailed) distribution. We will say we have substantial evidence for H1 is BF>3 and BF<.33 accepted if BF>4

See: https://doi.org/10.1016/j.jml.2017.01.005 for published paper using this approach and Rscript http://rpubs.com/ewonnacott/242454.

Note that the pilot data referred to below comes from three students projects. None were exactly the same as the experiments planned here, but materials were very similar and in some cases similar questions were asked. The models of the pilot data presented below also serve to exemplify the approach to be taken with the current data.

Where possible, we conducted power analyses, although lme’s will be used for the actual analsyes, we conducted the analsyes as though for (near equivalent) t-tests over by subject propotions. This means that the values are only approximate, but since our main analsyes are BF factors our aim here is to get an idea of approximate suitable samples.

In addition to power analyses, where possible we also conducted Bayesian analsyes on relevant parts of the pilot data to see is we had a sufficient sample for BF>3 or BF<.33. We also look to see what size sample might be expected to give BF>3 or BF<.33, given that SE varues as squareroot(N).

The analyses below suggest that there are cases where a sample of 20 participants per condition could be sufficient to acheive 90% power. Intereactions with condition will be harder to power; as discussed below, there may be situations where there is evidence of H1 (ie. data reflecs learning) in condition1 but evidence for H0 (no evidence of learning in this dat) for condition2. If so, we wil deem this sufficient to draw conculsions about the different training methods.

Our policy wil be as follows: we will inspect the data after we have approx. 20 participants in each condition (Note: this is approximate since we aim to get this by the end of the academic year; if we don’t quite get this many children, we will still look at the sample we have). If results for key analsyes are inconclusive, resources permitting we will continue to test more participants, collecting 10 per condition at each step before inspecting the data again at each step. We will continue until N per condition =50, resources permitting.

Final note: we have designed the experiment to have four sessions as follows: session1 pre-tests: discrimination and wordrepetition training session2 training post-tests: discrimination and wordrepetition 2AFC pictest/ 2AFC tonetest session3 training

session4 training post-tests: discrimination and wordrepetition 2AFC pictest/ 2AFC tonetest

For our first inspection of the data, we will conduct analsyes both on day2 data and day4 data (both compared to relevant pre-tests; for training data itself, we will look at sessions1 and 2 versus session 1,2,3&4). If using data from session4 extra two sessions do not affect the key pattern of results, given the large expeniture of resources per participant, we will drop the final two sessions for ongoing participant collection.

Note that frequentist analsyes will not be valid at .05 level, due to stopping problem. Current plan is to nevertheless report with that caveat; BF will be considered the critical analyses.)

Data will be collected from children in year 3 (aged 7-8)

Load packages and helper functions

Packages

## Packages.  
rm(list=ls())
#suppressPackageStartupMessages(library(stringdist))
#library(languageR)
library(lattice)
suppressPackageStartupMessages(library(lme4))
library(plotrix)
#suppressPackageStartupMessages(library(irr))
library(plyr)
library(knitr)
library(ggplot2)    #for graphs
#library(reshape)
library(reshape2)
#library(reshape)
library(reshape2)
#library(reshape)
library(reshape2)
#library(lmerTest)
#library(simr)
library(lsr)

Helper Functions

SummarySE

This function can be found on the website “Cookbook for R”.

http://www.cookbook-r.com/Manipulating_data/Summarizing_data/

It summarizes data, giving count, mean, standard deviation, standard error of the mean, and confidence interval (default 95%).

  • data: a data frame.
  • measurevar: the name of a column that contains the variable to be summarized.
  • groupvars: a vector containing names of columns that contain grouping variables.
  • na.rm: a boolean that indicates whether to ignore NA’s.
  • conf.interval: the percent range of the confidence interval (default is 95%).
summarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE,
                      conf.interval=.95, .drop=TRUE) {
    require(plyr)
    # New version of length which can handle NA's: if na.rm==T, don't count them
    length2 <- function (x, na.rm=FALSE) {
        if (na.rm) sum(!is.na(x))
        else       length(x)
    }
    # This does the summary. For each group's data frame, return a vector with
    # N, mean, and sd
    datac <- ddply(data, groupvars, .drop=.drop,
      .fun = function(xx, col) {
        c(N    = length2(xx[[col]], na.rm=na.rm),
          mean = mean   (xx[[col]], na.rm=na.rm),
          sd   = sd     (xx[[col]], na.rm=na.rm)
        )
      },
      measurevar
    )
    # Rename the "mean" column    
    datac <- rename(datac, c("mean" = measurevar))
    datac$se <- datac$sd / sqrt(datac$N)  # Calculate standard error of the mean
    # Confidence interval multiplier for standard error
    # Calculate t-statistic for confidence interval: 
    # e.g., if conf.interval is .95, use .975 (above/below), and use df=N-1
    ciMult <- qt(conf.interval/2 + .5, datac$N-1)
    datac$ci <- datac$se * ciMult
    return(datac)
}

SummarySEwithin

This function can be found on the website “Cookbook for R”.

http://www.cookbook-r.com/Graphs/Plotting_means_and_error_bars_(ggplot2)/#Helper functions

From that website:

Summarizes data, handling within-subjects variables by removing inter-subject variability. It will still work if there are no within-S variables. Gives count, un-normed mean, normed mean (with same between-group mean), standard deviation, standard error of the mean, and confidence interval. If there are within-subject variables, calculate adjusted values using method from Morey (2008). data: a data frame.

measurevar: the name of a column that contains the variable to be summariezed betweenvars: a vector containing names of columns that are between-subjects variables withinvars: a vector containing names of columns that are within-subjects variables idvar: the name of a column that identifies each subject (or matched subjects) na.rm: a boolean that indicates whether to ignore NA’s conf.interval: the percent range of the confidence interval (default is 95%)

summarySEwithin <- function(data=NULL, measurevar, betweenvars=NULL, withinvars=NULL,
                            idvar=NULL, na.rm=FALSE, conf.interval=.95, .drop=TRUE) {
  # Ensure that the betweenvars and withinvars are factors
  factorvars <- vapply(data[, c(betweenvars, withinvars), drop=FALSE],
    FUN=is.factor, FUN.VALUE=logical(1))
  if (!all(factorvars)) {
    nonfactorvars <- names(factorvars)[!factorvars]
    message("Automatically converting the following non-factors to factors: ",
            paste(nonfactorvars, collapse = ", "))
    data[nonfactorvars] <- lapply(data[nonfactorvars], factor)
  }
  # Get the means from the un-normed data
  datac <- summarySE(data, measurevar, groupvars=c(betweenvars, withinvars),
                     na.rm=na.rm, conf.interval=conf.interval, .drop=.drop)
  # Drop all the unused columns (these will be calculated with normed data)
  datac$sd <- NULL
  datac$se <- NULL
  datac$ci <- NULL
  # Norm each subject's data
  ndata <- normDataWithin(data, idvar, measurevar, betweenvars, na.rm, .drop=.drop)
  # This is the name of the new column
  measurevar_n <- paste(measurevar, "_norm", sep="")
  # Collapse the normed data - now we can treat between and within vars the same
  ndatac <- summarySE(ndata, measurevar_n, groupvars=c(betweenvars, withinvars),
                      na.rm=na.rm, conf.interval=conf.interval, .drop=.drop)
  # Apply correction from Morey (2008) to the standard error and confidence interval
  #  Get the product of the number of conditions of within-S variables
  nWithinGroups    <- prod(vapply(ndatac[,withinvars, drop=FALSE], FUN=nlevels,
                           FUN.VALUE=numeric(1)))
  correctionFactor <- sqrt( nWithinGroups / (nWithinGroups-1) )
  # Apply the correction factor
  ndatac$sd <- ndatac$sd * correctionFactor
  ndatac$se <- ndatac$se * correctionFactor
  ndatac$ci <- ndatac$ci * correctionFactor
  # Combine the un-normed means with the normed results
  merge(datac, ndatac)
}

normDataWithin

This function is used by the SummarySEWithin fucntion above. It can be found on the website “Cookbook for R”.

http://www.cookbook-r.com/Graphs/Plotting_means_and_error_bars_(ggplot2)/#Helper functions

From that website:

Norms the data within specified groups in a data frame; it normalizes each subject (identified by idvar) so that they have the same mean, within each group specified by betweenvars. data: a data frame. idvar: the name of a column that identifies each subject (or matched subjects) measurevar: the name of a column that contains the variable to be summariezed betweenvars: a vector containing names of columns that are between-subjects variables na.rm: a boolean that indicates whether to ignore NA’s

normDataWithin <- function(data=NULL, idvar, measurevar, betweenvars=NULL,
                           na.rm=FALSE, .drop=TRUE) {
    #library(plyr)
    # Measure var on left, idvar + between vars on right of formula.
    data.subjMean <- ddply(data, c(idvar, betweenvars), .drop=.drop,
     .fun = function(xx, col, na.rm) {
        c(subjMean = mean(xx[,col], na.rm=na.rm))
      },
      measurevar,
      na.rm
    )
    # Put the subject means with original data
    data <- merge(data, data.subjMean)
    # Get the normalized data in a new column
    measureNormedVar <- paste(measurevar, "_norm", sep="")
    data[,measureNormedVar] <- data[,measurevar] - data[,"subjMean"] +
                               mean(data[,measurevar], na.rm=na.rm)
    # Remove this subject mean column
    data$subjMean <- NULL
    return(data)
}

myCenter

This function ouputs the centered values of an variable, which can be a numeric variable, a factor, or a data frame. It was taken from Florian Jaegers blog

https://hlplab.wordpress.com/2009/04/27/centering-several-variables/.

From his blog:

  • If the input is a numeric variable, the output is the centered variable.

  • If the input is a factor, the output is a numeric variable with centered factor level values. That is, the factor’s levels are converted into numerical values in their inherent order (if not specified otherwise, R defaults to alphanumerical order). More specifically, this centers any binary factor so that the value below 0 will be the 1st level of the original factor, and the value above 0 will be the 2nd level.

  • If the input is a data frame or matrix, the output is a new matrix of the same dimension and with the centered values and column names that correspond to the colnames() of the input preceded by “c” (e.g. “Variable1” will be “cVariable1”).

myCenter= function(x) {
  if (is.numeric(x)) { return(x - mean(x, na.rm=T)) }
    if (is.factor(x)) {
        x= as.numeric(x)
        return(x - mean(x, na.rm=T))
    }
    if (is.data.frame(x) || is.matrix(x)) {
        m= matrix(nrow=nrow(x), ncol=ncol(x))
        colnames(m)= paste("c", colnames(x), sep="")
    
        for (i in 1:ncol(x)) {
        
            m[,i]= myCenter(x[,i])
        }
        return(as.data.frame(m))
    }
}

lizCenter

This function provides a wrapper around myCenter allowing you to center a specific list of variables from a dataframe.

  • x: data frame
  • listfname: a list of the variables to be centered (e.g. list(variable1,variable2))

The output is a copy of the data frame with a column (always a numeric variable) added for each of the centered variables. These columns are labelled with the each column’s previous name, but with “.ct” appended (e.g., “variable1” will become “variable1.ct”).

lizCenter= function(x, listfname) 
{
    for (i in 1:length(listfname)) 
    {
        fname = as.character(listfname[i])
        x[paste(fname,".ct", sep="")] = myCenter(x[fname])
    }
        
    return(x)
}

get_coeffs

This function allows us to inspect particular coefficients from the output of an lme model by putting them in table.

  • x: the output returned when running lmer or glmer (i.e. an objet of type lmerMod or glmerMod)
  • list: a list of names of the coefficients to be extracted (e.g. c(“variable1”,“variable1:variable2”))
#get_coeffs <- function(x,list){(kable(as.data.frame(summary(x)$coefficients)[list,],digits=3))}
get_coeffs <- function(x,list){(as.data.frame(summary(x)$coefficients)[list,])}

Bf

This function is equivalent to the Dienes (2008) calculator which can be found here: http://www.lifesci.sussex.ac.uk/home/Zoltan_Dienes/inference/Bayes.htm.

The code was provided by Baguely and Kayne (2010) and can be found here: http://www.academia.edu/427288/Review_of_Understanding_psychology_as_a_science_An_introduction_to_scientific_and_statistical_inference

Bf<-function(sd, obtained, uniform, lower=0, upper=1, meanoftheory=0,sdtheory=1, tail=2){
 area <- 0
 if(identical(uniform, 1)){
  theta <- lower
  range <- upper - lower
  incr <- range / 2000
  for (A in -1000:1000){
     theta <- theta + incr
     dist_theta <- 1 / range
     height <- dist_theta * dnorm(obtained, theta, sd)
     area <- area + height * incr
  }
 }else
   {theta <- meanoftheory - 5 * sdtheory
    incr <- sdtheory / 200
    for (A in -1000:1000){
      theta <- theta + incr
      dist_theta <- dnorm(theta, meanoftheory, sdtheory)
      if(identical(tail, 1)){
        if (theta <= 0){
          dist_theta <- 0
        } else {
          dist_theta <- dist_theta * 2
        }
      }
      height <- dist_theta * dnorm(obtained, theta, sd)
      area <- area + height * incr
    }
 }
 LikelihoodTheory <- area
 Likelihoodnull <- dnorm(obtained, 0, sd)
 BayesFactor <- LikelihoodTheory / Likelihoodnull
 ret <- list("LikelihoodTheory" = LikelihoodTheory,"Likelihoodnull" = Likelihoodnull, "BayesFactor" = BayesFactor)
 ret
} 

Bf_powercalc

This works with the Bf funciton above. It requires the same values as that function (i.e. the obtained mean and SE for the current sample, a value for the predicted mean, which is set to be sdtheory (with meanoftheory=0), and the current number of participants N). However rather than return a BF for the current sample, it works out what the BF would be for a range of different subject numbers (assuming that the SE scales with sqrt(N)),

Bf_powercalc<-function(sd, obtained, uniform, lower=0, upper=1, meanoftheory=0, sdtheory=1, tail=2, N, min, max)
{
 
 x = c(0)
 y = c(0)
   # note: working out what the difference between N and df is (for the contrast between two groups, this is 2; for constraints where there is 4 groups this will be 3, etc.)  
 for(newN in min : max)
 {
  B = as.numeric(Bf(sd = sd*sqrt(N/newN), obtained, uniform, lower, upper, meanoftheory, sdtheory, tail)[3])
  x= append(x,newN)  
  y= append(y,B)
  output = cbind(x,y)
  
 } 
 output = output[-1,] 
 return(output) 
}

Training

DV: Each training trial produces a data point (did they pick the correct picture - 1/0; note they get feedback on this)

load up and run lmes on relevant pilot data

The child data below come from a two session study where they were trained on stimuli similar to the “picture-only” condition in the current study. We have data from both 7 year olds and 11 year olds; the 11 year old data here are relevant in providing an estimate that can be used to inform H1 in our BF example analyses.

The adult data below come from a two session study where there were two conditions: (1) trained on stimuli similar to the “picture-only” condition in the current study (2) trained on pictures JUST of the diacritics. This is useful for considering possible effects of condition in the data (though with the caveat that comparison is somewhat different).

Note: tonecontrast is fixed effect with 6 levels (six possible contrasts). It is expected to contribute to model and is thus included but isn’t of specific interest.

child.train = read.csv("kidstrain_clean.csv")
adult.train = read.csv ("adultstrain_clean.csv")
child.train$agegroup = relevel(child.train$agegroup, ref="7years")
adult.train$condition = relevel(adult.train$condition, ref="i")
child.train.7 = subset(child.train, agegroup == "7years")
child.train.7 <- lizCenter(child.train.7, list("session", "tonecontrast"))
child.train.7.mod  = glmer (result ~
                + session.ct 
                + tonecontrast.ct
                + (session.ct|subject),
                data = child.train.7,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(child.train.7.mod)$coefficients,3)
                Estimate Std. Error z value Pr(>|z|)
(Intercept)        0.157      0.059   2.659    0.008
session.ct         0.158      0.077   2.062    0.039
tonecontrast.ct   -0.026      0.022  -1.171    0.242
child.train.11 = subset(child.train, agegroup == "11years")
child.train.11 <- lizCenter(child.train.11, list("session", "tonecontrast"))
child.train.11.mod  = glmer (result ~
                + session.ct 
                + tonecontrast.ct
                + (session.ct|subject),
                data = child.train.11,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(child.train.11.mod)$coefficients,3)
                Estimate Std. Error z value Pr(>|z|)
(Intercept)        0.538      0.096   5.602    0.000
session.ct         0.301      0.085   3.538    0.000
tonecontrast.ct   -0.051      0.023  -2.233    0.026
adult.train <- lizCenter(adult.train, list("session", "tonecontrast","condition"))
adult.train.mod  = glmer (result ~
                + session.ct *condition.ct
                + tonecontrast.ct
                + (session.ct|subject),
                data = adult.train,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(adult.train.mod)$coefficients,3)
                        Estimate Std. Error z value Pr(>|z|)
(Intercept)                0.961      0.091  10.555    0.000
session.ct                 0.487      0.067   7.263    0.000
condition.ct               0.416      0.181   2.291    0.022
tonecontrast.ct            0.067      0.010   6.740    0.000
session.ct:condition.ct   -0.032      0.133  -0.241    0.809

Prediction1: Children will show overall above chance performance across training in both condition1 and condition2

Based on:

We saw this in the pilot data from seven year olds above, which was in a condition like the pictures-only condition. The pictures+tones condition contains the same information (plus some additional) so we predict (at least - see below) above chance here too.

mean: 53.9%; log odds (beta from lme): 0.1572362; odds (exp(beta)):1.1702719;

Planned Analyses: Frequentist

lme model similar to that on pilot data above but with data from both conditions; Fit separate intercepts for each condition and compare each to chance = 50 (i.e.default value returned). Note that since all predictors are centered intercept relfects overall average (rather than at baselevels of a factor).

We will do this both for a model with just first two sessions and for a model with all data (with session then having four possible values and coded as centered numerical factor).

Planned Analyses: BF

Summary of data for each condition: mean and se for interecpt from lme; value to inform H1: estimate from above pilot data for seven year olds 0.1579623

NOTE: If (e.g.) we find an effect for condition1, we can also use the estimate for intercept for that to inform H1 when looking at data from condition2; and vice versa. This is a better estimate since the conditions are more closely matched to each other than either is to the pilot data/

Required sample analyses

Frequentists power

Look at sample required to obtain different levels of power with pilot data with 7 year olds:

dataS=as.numeric(with(droplevels(child.train.7), tapply(result,list(subject), mean, na.rm=T)))
d= cohensD(x = dataS, mu=0.5)
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .9,  type = c("one.sample"), alternative = c( "greater"))

     One-sample t test power calculation 

              n = 20.5642
              d = 0.6690231
      sig.level = 0.05
          power = 0.9
    alternative = greater
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .8,  type = c("one.sample"), alternative = c( "greater"))

     One-sample t test power calculation 

              n = 15.26043
              d = 0.6690231
      sig.level = 0.05
          power = 0.8
    alternative = greater
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .7,  type = c("one.sample"), alternative = c( "greater"))

     One-sample t test power calculation 

              n = 11.97662
              d = 0.6690231
      sig.level = 0.05
          power = 0.7
    alternative = greater
rm(dataS)
rm(d)

Required sample for BF analyses:

Here, we look at the pilot data from seven year olds, using H1 informed by estimate for 11 year olds. In our actual analsyes with new data for 7 year olds will be using estimate from current pilot data with 7 year olds to inform H1

meanBF = summary(child.train.7.mod)$coefficients["(Intercept)" ,"Estimate"]
seBF = summary(child.train.7.mod)$coefficients["(Intercept)" ,"Std. Error"]
h1mean = summary(child.train.11.mod)$coefficients["(Intercept)" ,"Estimate"]
Bf(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean,tail=1)
$LikelihoodTheory
[1] 1.408113

$Likelihoodnull
[1] 0.1968384

$BayesFactor
[1] 7.153651
rm(meanBF)
rm(seBF)

We could reject H0 with the current sample of N=15.

Prediction2: Improvement with session in each condition

Based on:

We saw this in 7 year olds in previous study.

7 year olds means : 0.52, 0.56 7 year olds log odds (beta from lme): 0.1579623 7 year old odd (exp(beta))1.171122

Planned Analyses: Frequentist

lme model similar to that on pilot data above but with data from both conditions; Fit separate slopes for session for each condition. We will do this both for a model with just first two sessions and for a model with all data.

Planned Analyses: BF

Summary of data for each condition: mean and se for session.ct for each level of condition from lme value to inform H1: estimate from above pilot data for seven year olds 0.1579623

If it appears that one of the conditions (c1) shows a positive effect of session and one doesn’t (c2), we can also do BF analsyes for c2 data with H1 informed by estimate from c1 (this is a better estimate than the pilot since the conditions are more closely matched to each other than either is to the pilot data)

Required sample analyses

Frequentists power

dataS = with(droplevels(child.train.7), tapply(result,list(subject,session), mean, na.rm=T))
d= cohensD(x = dataS[,1], y = dataS[,2], method = "paired")
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .9,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 28.38133
              d = 0.5634754
      sig.level = 0.05
          power = 0.9
    alternative = greater

NOTE: n is number of *pairs*
rm(dataS)
rm(d)
dataS = with(droplevels(child.train.7), tapply(result,list(subject,session), mean, na.rm=T))
d= cohensD(x = dataS[,1], y = dataS[,2], method = "paired")
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .8,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 20.89366
              d = 0.5634754
      sig.level = 0.05
          power = 0.8
    alternative = greater

NOTE: n is number of *pairs*
rm(dataS)
rm(d)
dataS = with(droplevels(child.train.7), tapply(result,list(subject,session), mean, na.rm=T))
d= cohensD(x = dataS[,1], y = dataS[,2], method = "paired")
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .7,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 16.25431
              d = 0.5634754
      sig.level = 0.05
          power = 0.7
    alternative = greater

NOTE: n is number of *pairs*
rm(dataS)
rm(d)

Required sample for BF analyses:

As for prediction 1, we again look at the pilot data from seven year olds, using H1 informed by estimate for 11 year olds. In our actual analsyes will be using estimate from the pilot data to inform H1.

meanBF = summary(child.train.7.mod)$coefficients["session.ct" ,"Estimate"]
seBF = summary(child.train.7.mod)$coefficients["session.ct" ,"Std. Error"]
h1mean = summary(child.train.11.mod)$coefficients["session.ct" ,"Estimate"]
Bf(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean,tail=1)
$LikelihoodTheory
[1] 2.206111

$Likelihoodnull
[1] 0.6215463

$BayesFactor
[1] 3.549392
rm(meanBF)
rm(seBF)

We have sufficient evidence to accept H1 over H0 on basis of current sample.

Prediction3: Greater performance in picture+diacritic condition with just picture condition

Based on:

We don’t have any pilot data with this type of manipulation for children.

This prediction is made on the basis of a related effect seen in adult data: they showed greater overall performance in a condition where they saw just diacritic rather than just picture. Note that iconcity means you can potentially respond when they are present. It is possible that having the diacritics present will help children too; though (a) children could well be different (diactritics might be too abstract) (b) it could be that having the picture there changes things).

Means from the pilot:

adult means : 0.67, 0.75 adult log odds (beta from lme): 0.4156183 adult odd (exp(beta))1.626952

Planned Analyses: Frequentist

lme model similar to that on pilot data above but with data from both conditions; look for fixed effect of condition We will do this both for a model with just first two sessions and for a model with all data.

Planned Analyses: BF

Summary of data: mean and se for condition.ct value to inform H1: estimate from above ADULT pilot data 0.4156183

There is a caveat here since this value comes from adults and will likely overestimate any difference for children (making it a conservative estimate, biasing evidence for H0).

Required sample analyses

Frequentists power

NOTE: this is based on ADULT data. It likely underestimates the power required to see this difference.

dataS = with(droplevels(adult.train), tapply(result,list(subject,condition), mean, na.rm=T))
d= cohensD(x = dataS[,1], y = dataS[,2], method = "pooled")
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .9,  type = c("two.sample"), alternative = c( "greater"))

     Two-sample t test power calculation 

              n = 58.37074
              d = 0.5449171
      sig.level = 0.05
          power = 0.9
    alternative = greater

NOTE: n is number in *each* group
rm(dataS)
rm(d)
dataS = with(droplevels(adult.train), tapply(result,list(subject,condition), mean, na.rm=T))
d= cohensD(x = dataS[,1], y = dataS[,2], method = "pooled")
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .8,  type = c("two.sample"), alternative = c( "greater"))

     Two-sample t test power calculation 

              n = 42.3355
              d = 0.5449171
      sig.level = 0.05
          power = 0.8
    alternative = greater

NOTE: n is number in *each* group
rm(dataS)
rm(d)
dataS = with(droplevels(adult.train), tapply(result,list(subject,condition), mean, na.rm=T))
d= cohensD(x = dataS[,1], y = dataS[,2], method = "pooled")
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .7,  type = c("two.sample"), alternative = c( "greater"))

     Two-sample t test power calculation 

              n = 32.39217
              d = 0.5449171
      sig.level = 0.05
          power = 0.7
    alternative = greater

NOTE: n is number in *each* group
rm(dataS)
rm(d)

Suggests that for adults we would need 58 per condition to get 90% power. We would be likely to need more with children.

Given practical constraints, we are unlikely to obtain a sufficient sample for this. However this effect isn’t critical in terms of demonstrating what leads to greater learning. (It is therefore more important to demonstrate that they are above chance in each condition)/

Prediction 4: They will improve more in one condition than the other(no predicted direction)

Based on:

We don’t have any clear evidence to base this on. However it seems reasonable that the type of training will leed to different learning slopes. One possibility is that while they show greater learning in the condition with diacrtics, due to more information per trial. However it is also possible that they could show steeper learning in the other condition, due to needing to pay more attention to and remember individual stimuli. We saw means in this latter direction in the adult pilot data i.e. more improvement in the condition with pictures (labelled condition “i” for implicit) than with diacrticis (labelled “e” for explicit) (though conditions not exactly the same see above). though it wsn’t signficant.

adult means : 0.62, 0.71, 0.72, 0.79 beta: -0.0321743

Planned Analyses: Frequentist

lme model similar to that on pilot data above but with data from both conditions; look for fixed effect of condition.ct:session.ct We will do this both for a model with just first two sessions and for a model with all data.

Planned Analyses: BF

Summary of data: mean and se for interaction session and condition (session.ct by conditoin.ct) value to inform H1: estimate of session from the same model model (e.g. summary(model.newdata)$coefficients[“session.ct” ,“Estimate”]`.

This will provide a relatively high estiamte of likely effect of interaction (if one is present) given the actual data set (so again, a conservative estimate)

[Note: are checking this with stats consultant]

Note this is exemplified below in sample size analysis using the current data from adults:

Required sample analyses

Frequentist power

Nothing to base power analysis on here (as was no effect in original data).

Required sample for BF analyses:

Note this is with adult data - it exemplifies the process we will actually use to conduct power analyses on actual data

meanBF = summary(adult.train.mod)$coefficients["session.ct:condition.ct","Estimate"]
seBF = summary(adult.train.mod)$coefficients["session.ct:condition.ct","Std. Error"]
h1mean = summary(adult.train.mod)$coefficients["session.ct","Estimate"]
Bf(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean,tail=2)
$LikelihoodTheory
[1] 0.7889355

$Likelihoodnull
[1] 2.905926

$BayesFactor
[1] 0.271492
rm(meanBF)
rm(seBF)

Note: we use tail =2 as don’t have a clear direction for this hypothesis

So note, with adult pilot data we do have evidence in favor of H0 from the current data set.

One possibility with children is that we will not be able to obtain a large enough sample to provide evidence for/against the hypothesis that there is more learning in one direction, but we may find evidence for the H1 that there is an effect of session in one condition but for the H0 that there is not and effect of session in the other condition. If so, we will deem this sufficient to address this prediciton.

2AFC picture and 2AFC diacritic

These two tests are very similar to training but with either just pictures or just diacritics. The tests are only done as post tests, not as pre-tests (unlike all of the tests discussed after this one)

Children in the pictures+diacritics condition will get the 2AFC pictures test followed by the 2AFC diacritics test; children in the picturesonly test will get just 2AFC pictures but will get it twice (so that total exposure doesn’t differ across conditions).

Where we just look a conditions separately, for the just pictures test, we will look at all of the data (i.e. for the pictures only condition, from both parts of the repeated test). Where we compare conditions, we will look only use data from the first 2AFC test.

Note: unlike for all the tests that follow, there is no pre-test.

run lmes on relevant pilot data

We didn’t do this test in the pilot, however the test is rather similar to training test so we use model based on just last 24 sessions of training for informing power decisions.

child.train.7.s2.24 = droplevels(subset(child.train, agegroup == "7years" & session =="session2" & order>72))
child.train.7.s2.24 = lizCenter(child.train.7.s2.24, c("tonecontrast"))
child.train.7.s2.s4.mod = glmer (result ~
                 1+ tonecontrast.ct
                + (1|subject),
                data = child.train.7.s2.24,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(child.train.7.s2.s4.mod)$coefficients,3)
                Estimate Std. Error z value Pr(>|z|)
(Intercept)        0.201      0.106   1.894    0.058
tonecontrast.ct    0.008      0.062   0.124    0.901
child.train.11.s2.24 = droplevels(subset(child.train, agegroup == "11years" & session =="session2" & order>72))
child.train.11.s2.24 = lizCenter(child.train.11.s2.24, c("tonecontrast"))
child.train.11.s2.s4.mod = glmer (result ~
                 1+ tonecontrast.ct
                + (1|subject),
                data = child.train.11.s2.24,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(child.train.11.s2.s4.mod)$coefficients,3)
                Estimate Std. Error z value Pr(>|z|)
(Intercept)        0.686      0.117   5.839    0.000
tonecontrast.ct   -0.075      0.066  -1.144    0.253
adult.train.s2.24 = subset(adult.train, session =="session2" & order>264)
adult.train.s2.24 = lizCenter(adult.train.s2.24, list("tonecontrast"))
adult.train.s2.24.mod = glmer (result ~
                 1+ tonecontrast.ct
                + (1|subject),
                data = adult.train.s2.24,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(adult.train.s2.24.mod)$coefficients,3)
                Estimate Std. Error z value Pr(>|z|)
(Intercept)        1.284      0.136   9.428        0
tonecontrast.ct    0.218      0.055   3.977        0

Prediction1: Performance will above chance in each test in each condition.

Based on:

Training data in pilot (see above) ### Planned Analyses: Frequentist

lme model similar to that for training data. Again fit separate intercepts for each condition and compare each to chance = 50 (i.e.default value returned). Note that since all predictors are centered, the intercept relfects overall average (rather than at baselevels of a factor).

(We will do this both for a model with just day2 test and day4 test; as discussed above, we will use the full double data set for the 2AFC picture test for the participants in the picture+diacritic condition).

Planned Analyses: BF test

Summary of data for each condition: mean and se for interecpt from lme

value to inform H1: assuming they show learning, estimate from the equivalent lme for training data from current data set (NOT from pilot data - unless the intercept from training set didn’t suggest above chance peformance). Again note that if we find an effect for condition1, we can also use the estimate for intercept for that to inform H1 when looking at data from condition2; and vice versa. This is a better estimate since the conditions are more closely matched to each other than either is to the pilot data.

Required sample analyses

Frequentist power

Here we look at power using the values from the subset of training data from the above

dataS=as.numeric(with(droplevels(child.train.7.s2.24), tapply(result,list(subject), mean, na.rm=T)))
d= cohensD(x = dataS, mu=0.5)
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .9,  type = c("one.sample"), alternative = c( "greater"))

     One-sample t test power calculation 

              n = 20.29292
              d = 0.6738353
      sig.level = 0.05
          power = 0.9
    alternative = greater
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .8,  type = c("one.sample"), alternative = c( "greater"))

     One-sample t test power calculation 

              n = 15.06511
              d = 0.6738353
      sig.level = 0.05
          power = 0.8
    alternative = greater
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .7,  type = c("one.sample"), alternative = c( "greater"))

     One-sample t test power calculation 

              n = 11.82842
              d = 0.6738353
      sig.level = 0.05
          power = 0.7
    alternative = greater
rm(dataS)
rm(d)

This suggests a sample of 21 is sufficient for 90% power.

Required sample for BF analyses:

Here we use the subset of pilot data with 7 year olds and an H1 informed by estimate from 11 year olds whole training data set (note: in actual analyses H1 will be informed by estimate from model of the current training data with 7 year olds )

meanBF = summary(child.train.7.s2.s4.mod)$coefficients["(Intercept)" ,"Estimate"]
seBF = summary(child.train.7.s2.s4.mod)$coefficients["(Intercept)" ,"Std. Error"]
h1mean = summary(child.train.11.mod)$coefficients["(Intercept)" ,"Estimate"]
Bf(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean,tail=1)
$LikelihoodTheory
[1] 1.319399

$Likelihoodnull
[1] 0.6261729

$BayesFactor
[1] 2.107085
Bf_powercalc(seBF, meanBF,  uniform =0,meanoftheory=0,N=15, min=15, max=20,sdtheory=h1mean,tail=1)
      x        y
[1,] 15 2.107085
[2,] 16 2.311559
[3,] 17 2.538967
[4,] 18 2.791849
[5,] 19 3.073052
[6,] 20 3.385763
rm(meanBF)
rm(seBF)

Suggests don’t currently have sufficient sample to get reliable evidence for H1, but could do with 19 participants.

Prediction 2: For picture-only test, there will be greater performance in the picture-only condition

based on

Children in the condition where diacritics are present might have become overly reliant on them during training and thus unable to do the test when they are absent. Don’t currently have specific data to base this on.

Planned Analyses: Frequentist

lme model on 7 year olds data, look at effect of condition.

(We will do this both for a model with just day2 test and day4 test; as discussed above, we will only ue the half set for the 2AFC picture test for the participants in the picture+diacritic condition).

Planned Analyses: BF test

Summary of data for each condition: mean and se for condition from lme value to inform H1: assuming they show learning, estimate of intercept from the current model (note other values are centered, so this is equivlaent to grand mean; it will be conservative)

(Am seeking statistical advice to confirm that this is a reasonable, if conservative, estimate for H1)

Required sample analyses

Nothing we can really base analyses on here (comparison of condition in previous adult data is too dissimilar).

Note that it may prove difficult to obtaina sufficient sample to gain evidence for H1 or h0. However it may be that we see above chance performance only for the picture-only condition. In that case, we may be look to the previous analyses (Prediction 1) and be able to show that there is evidence for H1 over H0 in one condition, but for H0 over H1 in the other. If so, we will be able to say that there is evidence of learning in one condition and not the other, and this will be deemed sufficient to address this hypothesis.

Discrimination

This test will be given pre and post. Children will hear three frogs each produce a Mandarin word. One produces the target and the other two each produce the same foil word, which will be a word differeing from the target only in tone.

Each of the 6 one contrasts are tested. We put tonecontrast into the model, since it is likely to have an effect, but don’t have specific hypotheses of interest here. There are four talkers, 3f 1m. Trials in which the m is the odd one out are known to be easiest and those where one of the speakers is m but it is not the odd one out are eaisest. THere are an equal number of each trial type and we put trial type into the model as a factor; though again it isn’t a question for which we have predictions.

For the intial data set collected, we will consider both pre-test -> posttest1 and pre-test -> post-test2 (if equivlaent results obtaned, subsequenting testing will drop final two sessions - see note above)

load up and run lmes on relevant pilot data

The pilot child data below come from same 2-session study as pilot traning data (recall they were trained on stimuli similar to the “picture-only” condition in the current study.)

The adult data below come from a different two- session study where there were two condition (1) trained on stimuli similar to the “picture-only” condition in the current study (2) trained on pictures JUST of the diacritics. This is useful for considering possible effects of condition in the data (though with the caveat that comparison is somewhat different).

Note that for both adults and children in the pilot experiemnt we had both trained and untrained items. For this experiment we use only untrained items in this test so we remove the untrained items from the analyses below.

Note: tonecontrast is fixed effect with 6 levels (six possible contrasts). It is expected to contribute to model and is thus included but isn’t of specific interest.

child.discrim = read.csv("kidsdiscrim_clean.csv")
adult.discrim = read.csv ("adultsdiscrim_clean.csv")
child.discrim$pre_post = relevel(child.discrim$pre_post, ref="pre")
child.discrim$agegroup = as.factor(child.discrim$agegroup)
adult.discrim$pre_post = relevel(adult.discrim$pre_post, ref="pre")
adult.discrim$condition = relevel(adult.discrim$condition, ref="i")
child.discrim$pre_post = relevel(child.discrim$pre_post, ref="pre")
adult.discrim<- droplevels(subset(adult.discrim, neworold == "newword"))
child.discrim<- droplevels(subset(child.discrim, neworold == "newword"))
adult.discrim <- lizCenter(adult.discrim, list("pre_post","trialtype", "condition", "tonecontrast"))
adult.discrim.mod = glmer (correct ~
                + condition.ct * pre_post.ct
                + trialtype.ct 
                + tonecontrast.ct
                + (pre_post.ct|participantnumber),
                  data = adult.discrim,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(adult.discrim.mod)$coefficients, 3)
                         Estimate Std. Error z value Pr(>|z|)
(Intercept)                 0.345      0.075   4.615    0.000
condition.ct               -0.147      0.149  -0.984    0.325
pre_post.ct                 0.287      0.099   2.897    0.004
trialtype.ct                0.066      0.054   1.232    0.218
tonecontrast.ct             0.041      0.013   3.251    0.001
condition.ct:pre_post.ct   -0.071      0.198  -0.360    0.719
child.discrim.7 = droplevels(subset(child.discrim, agegroup == "7"))
child.discrim.7 <- lizCenter(child.discrim.7, list("pre_post","trialtype", "condition", "tonecontrast"))
child.discrim.7.mod = glmer (correct ~
                + pre_post.ct
                + trialtype.ct 
                + tonecontrast.ct
                + (pre_post.ct|participantnumber),
                  data = child.discrim.7,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(child.discrim.7.mod)$coefficients, 3)
                Estimate Std. Error z value Pr(>|z|)
(Intercept)       -0.445      0.128  -3.472    0.001
pre_post.ct       -0.365      0.228  -1.604    0.109
trialtype.ct      -0.252      0.139  -1.815    0.070
tonecontrast.ct    0.115      0.033   3.504    0.000

Prediction1: Improvement from pre-post test in each each condition

Based on

In the pilot data, adults show improvement with session but neither 7 year olds didn’t (nb nor did 11 year olds)

means : 0.55, 0.61; log odds (beta from lme): 0.2868916; odd (exp(beta))1.3322798

7year olds (don’t show this- in fact means reversed )

means : 0.44, 0.36; log odds (beta from lme): -0.3652203; odd (exp(beta))0.6940437

Planned Analyses: Frequentist

lme model similar to that on pilot data above but with data from both conditions; Fit separate slopes for pre-post in each condition

For the intial data set collected we will do this both to compare pre test to post-test 1 and pre-test to post-test2 (see notes above).

Planned Analyses: BF

Summary of data for each condition: mean and se for pre-post from lme value to inform H1: estimate from above pilot data for adults i.e. 0.2868916

Note: this adult value will likely overestimate the means. A better value would come from the new data from children themselves - therefore, if they show learing in one condition we will use that to inform BF for the other condition (and if both show learning we will use to inform BF for each other).

Required sample analyses

Frequentist Power

Note: this analysis included for completeness but is not really relevant since it is based on adult data. If children do show an effect, it is likely smaller and they will have larger SE

dataS=with(droplevels(adult.discrim), tapply(correct,list(participantnumber, pre_post), mean, na.rm=T))
d = cohensD(x = as.numeric(dataS[,1]),y = as.numeric(dataS[,2]), method = "paired")
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .9,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 31.24664
              d = 0.5356902
      sig.level = 0.05
          power = 0.9
    alternative = greater

NOTE: n is number of *pairs*
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .8,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 22.95973
              d = 0.5356902
      sig.level = 0.05
          power = 0.8
    alternative = greater

NOTE: n is number of *pairs*
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .7,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 17.82436
              d = 0.5356902
      sig.level = 0.05
          power = 0.7
    alternative = greater

NOTE: n is number of *pairs*
rm(d)
rm(dataS)

Required sample for BF analyses from pilot data

Here we look at data from 7 year olds in pilot and

meanBF = summary(child.discrim.7.mod)$coefficients["pre_post.ct" ,"Estimate"]
seBF = summary(child.discrim.7.mod)$coefficients["pre_post.ct" ,"Std. Error"]
h1mean = summary(adult.discrim.mod)$coefficients["pre_post.ct" ,"Estimate"]
Bf(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean,tail=1)
$LikelihoodTheory
[1] 0.1393478

$Likelihoodnull
[1] 0.4839102

$BayesFactor
[1] 0.2879621
rm(meanBF)
rm(seBF)
rm(h1mean)

Have evidence for the null from just 15 participants. Note however, that we are relatively high estimate for H1, which may make it easier to find evidence for the null.

Prediction2: More improvement in one condition than the other

Based on

We don’t have any specific evidence to base this on. The closest contrasts was in the adult pilot experiment (comparing condition with picture only training versus diacritic only training) where they showed numerically more improvement in the implicit condition, but the difference was NS.

means : 0.56, 0.63, 0.54, 0.59 log odds (beta from lme): -0.0711115 odd (exp(beta))0.931358

For the intial data set collected Ww will do this both to compare pre test to post-test 1 and pre-test to post-test2 (see notes above).

Planned Analyses: Frequentist

lme model similar to that on pilot data above but with data from both conditions; look for interaction between pre-post and condition.

Planned Ananlyses: BF

Summary of data for each condition: mean and se for pre-post*condition from lme value to inform H1: estimate for session from the current model (i.e. summary(new.data)$coefficients[“pre_post.ct” ,“Estimate”]`

Note: we only do this if we have evidence of an effect of pre-post in at least one of the conditions. If they don’t learn in either condition then this test is inappropriate.

Also note that this will be relatively conservative estimate for a large difference in how much the conditions lead to a change pre to post. (again will seek statistial advice here)

Required sample estimates

Frequentist Power

We have no data to look at this (since was no sig. difference in data collected)

Required sample for BF analyses from pilot data

Here we are looking at this with adult data.

meanBF = summary(adult.discrim.mod)$coefficients["condition.ct:pre_post.ct" ,"Estimate"]
seBF = summary(adult.discrim.mod)$coefficients["condition.ct:pre_post.ct" ,"Std. Error"]
h1mean = summary(adult.discrim.mod)$coefficients["pre_post.ct" ,"Estimate"]
Bf(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean,tail=2)
$LikelihoodTheory
[1] 1.121749

$Likelihoodnull
[1] 1.89307

$BayesFactor
[1] 0.5925559
plot(Bf_powercalc(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean, N=15, min=900, max = 50, tail=2))
abline(h=3)

Bf_powercalc(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean, N=15, min=811, max = 815, tail=2)
       x        y
[1,] 811 3.007075
[2,] 812 3.018251
[3,] 813 3.029471
[4,] 814 3.040735
[5,] 815 3.052043
rm(meanBF)
rm(seBF)
rm(h1mean)

General note: this analysis suggestst that even for adults, wouldn’t need a sample of over 800 participants per condition to see this interaction. This is implausible (though may be partly because are basing on over conservative value for h1).

However this analysis suggests it will be difficult to gain power for this interaction. On the other hand, previous analyses may make it clear that there is no improvement on this test in EITHER condition (see Prediction 1 above). In that that it may be very difficult to power this. One possibility is that we won’t have power for the interaction but will have power to say we have evidence for learning in one condition, but for the other there is more evidence for the null than for H1 based on that condition.

Word repetition

This test is given pre and post. Children hear a word and copy it back. We look to see if they repeat back the tone correctly (they will be coded by native speakers who blind as to both condition and what the target word is; the tone of the transcribed word will compared to tone of target and thus coded as correct/incorrect).

There are equal number of words for each of the four tones.

For the intial data set collected, will consider both pre-test -> posttest1 and pre-test -> post-test2 (if equivalent results obtaned, subsequenting testing will drop final two sessions - see note above)

load up and run lmes on pilot data

The child data below come from same two session study as pilot traning data/discrim data (i.e where they were trained on stimuli similar to the “picture-only” condition in the current study.)

The adult data below do not come from the same two day pilot study as the other adult data used above (that student project didn’t include this test), but instead from a much longer 9 session experiment conducted by current PhD student. There was no contrast of condition of the type relevant to the current study in that data.

Note that for both adults and children in pilot experiments using this test we had both trained and untrained items. For this experiment we use only untrained items in thiis test so we remove the untrained items from the analyses below.

child.wr = read.csv("kidswordrep_clean.csv")
adult.wr = read.csv("adultswordrep_clean.csv")
child.wr = droplevels(subset(child.wr, wordtype == "new"))
adult.wr = droplevels(subset(adult.wr, wordtype == "Untrained"))
child.wr$pre_post = relevel(child.wr$pre_post, ref = "pre")
adult.wr$pre_post = relevel(adult.wr$pre_post, ref = "pre")
child.wr.7 = droplevels(subset(child.wr, Age=="young"))
child.wr.7 <- lizCenter(child.wr.7, list("Age", "pre_post","correcttone"))
child.wr.7.mod = glmer (resulttone ~
                + pre_post.ct 
                + correcttone.ct
                + (pre_post.ct|participantname),
                  data = child.wr.7,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(child.wr.7.mod)$coefficients,3)
               Estimate Std. Error z value Pr(>|z|)
(Intercept)       0.553      0.147   3.764    0.000
pre_post.ct       0.309      0.141   2.183    0.029
correcttone.ct    0.066      0.043   1.537    0.124
adult.wr <- lizCenter(adult.wr, list( "pre_post","correcttone"))
adult.wr.mod = glmer (resulttone ~
                + pre_post.ct 
                + correcttone.ct
                + (pre_post.ct|participantname),
                  data = adult.wr,  family = binomial, control=glmerControl(optimizer = "bobyqa"))
round(summary(adult.wr.mod)$coefficients,3)
               Estimate Std. Error z value Pr(>|z|)
(Intercept)       1.110      0.077  14.321        0
pre_post.ct       0.412      0.118   3.491        0
correcttone.ct   -0.142      0.032  -4.409        0

Prediction1: Improvement from pre-post test in each each condition

Based on

Both adults and children showed this in the relevant pilot studies

adult mean : 0.7, 0.77; adult log odds (beta from lme): 0.4117959; adult odd (exp(beta))1.5095264

7year mean :0.59, 0.65; 7year log odds (beta from lme): 0.3085348; 7year odd (exp(beta))1.3614289

Planned Analyses: Frequentist

lme model similar to that on pilot data above but with data from both conditions; Fit separate slopes for pre-post in each condition

For the intial data set collected We will do this both to compare pre test to post-test 1 and pre-test to post-test2 (see notes above).

Planned Analyses: BF

Summary of data for each condition: mean and se for pre-post from lme value to inform H1: estimate from above pilot data for children i.e. 0.3085348

NOTE: If (e.g.) we find an effect for condition1, we can also use the estimate for session for that to inform H1 when looking at data from condition2; and vice versa. This is a better estimate since the conditions are more closely matched to each other than either is to the pilot data/

Required sample analyses

Frequentist Power

Note: this analysis included for completeness but is not really relevant since it is based on adult data. If children do show an effect, it is likely smaller and they will have larger SE

7

dataS = with(droplevels(child.wr.7), tapply(resulttone,list(participantname,pre_post), mean, na.rm=T))
d= cohensD(x = dataS[,1], y = dataS[,2], method = "paired")
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .9,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 32.46102
              d = 0.5250962
      sig.level = 0.05
          power = 0.9
    alternative = greater

NOTE: n is number of *pairs*
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .8,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 23.83549
              d = 0.5250962
      sig.level = 0.05
          power = 0.8
    alternative = greater

NOTE: n is number of *pairs*
pwr.t.test(n = NULL, d = d, sig.level = 0.05, power = .7,  type = c("paired"), alternative = c( "greater"))

     Paired t test power calculation 

              n = 18.48998
              d = 0.5250962
      sig.level = 0.05
          power = 0.7
    alternative = greater

NOTE: n is number of *pairs*
rm(dataS)
rm(d)

Sample estimation suggests that N=33 per condition for 90% power.

Required sample for BF analyses from pilot data

Note that here we use the mean from the adult pilot data adults to inform H1 (whereas for actual analyses we will be using value from pilot data with 7 year olds to inform H1)

meanBF = summary(child.wr.7.mod)$coefficients["pre_post.ct" ,"Estimate"]
seBF = summary(child.wr.7.mod)$coefficients["pre_post.ct" ,"Std. Error"]
h1mean = summary(adult.wr.mod)$coefficients["pre_post.ct" ,"Estimate"]
Bf(seBF, meanBF,  uniform =0,meanoftheory=0,sdtheory=h1mean,tail=1)
$LikelihoodTheory
[1] 1.398479

$Likelihoodnull
[1] 0.2603624

$BayesFactor
[1] 5.371278
rm(meanBF)
rm(seBF)

We have sufficient evidence from the sample of N=15 children for H1.

Prediction 2: There will be more improvement in one condition by pre-post

Based on

We have no data to base this on as we haven’t previously used this test in an experiment contrasting these (or similar) conditions.

If the presence of the diacritics boosts learning, children may improve more in the diacrticis+picture condition.

Planned Analyses: Frequentist

lme model similar to that on pilot data above but with data from both conditions; look for interaction of pre-post and condition

For the intial data set collected Ww will do this both to compare pre test to post-test 1 and pre-test to post-test2 (see notes above).

Planned Ananlyses: BF

Summary of data for each condition: mean and se for pre-post*condition from lme value to inform H1: estimate for session from the model with the new data (i.e. summary(new.data)$coefficients[“pre_post.ct” ,“Estimate”]`

Note: we only do this if we have evidence of an effect of pre-post in at least one of the conditions. If they don’t learn in either condition then this test is inappropriate.

Also note that this will be relatively conservative estimate for a large difference in how much the conditions lead to a change pre to post.

Required sample analyses

We have no relevant data to can base this on for either frequentist or BF analyses. One possibility is that we won’t be able to get a sufficiently large sample to have power for this interaction. As for other tests, here we may have to draw whatever conculsionsare possible based on which of the conditions individually provides evidence for H1/H0.

LS0tDQp0aXRsZTogJ1BsYW4gZm9yIHRlc3RpbmcgeWVhciAzIG9uIHBpY3R1cmVzLW9ubHkgdmVyc3VzIHBpY3R1cmVzK3RvbmVzJw0KYXV0aG9yOiAiRWxpemFiZXRoIFdvbm5hY290dCINCmRhdGU6ICIxOC4wNi4xNyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgdG9jOiB0cnVlDQptYXgtd2lkdGg6IDMwMA0KDQotLS0NCg0KY29tbWVudDogdG9jIGNvbWFuZCBub3Qgd29ya2luZywgbmVlZCB0byByZXBvc3Qgd2l0aCBoZWFkaW5ncyBsaW5rcyBmb3IgZWFzZSBvZiBuYXZpZ2F0aW9uICANCg0KIyBHZW5lcmFsIG5vdGVzDQoNClRoaXMgY29udGFpbmVkIHBsYW5lZCBhbmFseXNlcyBhcyBvZiAxOC4wNi4xNyBmb3IgZGF0YSBzZXQgd2hpY2ggd2Ugd2lsbCBzdGFydCB0byBjb2xsZWN0IG9uIDE5LzA2LzE3Lg0KUGxhbnMgbWF5IGNoYW5nZSBhcyBhIHJlc3VsdCBvZiBzdGF0c2l0aWNhbCBjb25zdWxhdGlvbiAod2UgYXJlIGN1cnJlbnRseSBzZWVraW5nIGFkdmljZSBvbiBzb21lIGRldGFpbHMpDQoNClRoZSBzdHVkeSBpcyBhIHRyYWluaW5nIHN0dWR5IHRvIGJlIGNvbmR1Y3RlZCB3aXRoIHllYXIgMyAoNy04IHllYXJzKSBjaGlsZHJlbiB3aXRoIG5vIHByZXZpb3VzIGtub3dsZWRnZSBvZiBNYW5kYXJpbiBvciBhbnkgdG9uZSBsYW5ndWFnZSwgdHJhaW5pbmcgdGhlbSBvbiB0aGUgZm91ciB0b25lcyAoNiB0b25lIGNvbnRyYXN0cykgaW4gTWFuZGFyaW4uICBUaGVyZSB3aWxsIGludGlhbGx5IGJlIHR3byBjb25kaXRpb25zOiAoMSkgcGljdHVyZXMtb25seTogdGhleSBhcmUgdHJhaW5lZCB1c2luZyBhIDJBRkMgdGFzayB3aGVyZSB0aGV5IGhlYXIgYSAocmVhbCkgTWFuZGFyaW4gd29yZCBhbmQgaWRlbnRpZnkgd2hpY2ggb2YgdHdvIHBpY3R1cmVzIGl0IHJlZmVycyB0byAob25lIGNvcnJlY3QsIG9uZSBhIGZvaWwgd2hpY2ggZGlmZmVycyBvbmx5IGJ5IHRvbmUpOyAoMikgcGljdHVyZXMrZGlhY3JpdGljcyAtIHNhbWUgdGFzayBidXQgdGhlIHBpY3R1cmVzIGFyZSBhY29tcGFuaWVkIGJ5IHBpY3R1cmVzIG9mIHRoZSBmb3VyIGRpYWNyaXRpY3MuIFtJZiByZXNvdXJjZXMgcGVybWl0LCB3ZSBtYXkgbGF0ZXIgcnVuIGEgZGlhY3JpdGljcyBvbmx5IGNvbmRpdGlvbl0uIERhdGEgd2lsbCBiZSAgY29sbGVjdGVkIGJvdGggZnJvbSB0cmFpbmluZyBhbmQgZnJvbSBzb21lIHRlc3RzIGNvbmR1Y3RlZCBwcmUgYW5kIHBvc3QgdHJhaW5pbmcuDQogDQpPdXIgbWFpbiBhbmFseXNlcyB3aWxsIGJlIEJheXNlYW4gYW5kIHdlIHdpbGwgY29tcHV0aW5nIEJheWVzIGZhY3RvcnMgdXNpbmcgdGhlIG1ldGhvZCBhZHZvY2F0ZWQgYnkgRGllbmVzLCAyMDA4IDtEaWVuZXMsIDIwMTU7IHdlIHdpbGwgYWxzbyBhbG9uZyBzaWRlIHByb3ZpZGUgZnJlcXVlbnRpc3Qgc3RhdGlzdGljcy4gRnJlcXVlbnRpc3Qgc3RhdGlzdGljcyB3aWxsIGNvbXB1dGVkIHVzaW5nIGxvZ2lzdGljIG1peGVkIGVmZmVjdCBtb2RlbHMsIHRoaXMgbWV0aG9kIGlzIHVzZWQgc2luY2UgaW4gZWFjaCBjYXNlIHdlIGhhdmUgYSBkZXBlbmRlbnQgdmFyaWFibGUgb2YgY29ycmVjdC9pbmNvcnJlY3QgcmVzcG9uc2UuIE5vdGUgdGhhdCBhbHRob3VnaCBtaXhlZCBtb2RlbHMgYWxsb3cgdXMgdG8gaW5jbHVkZSBib3RoIHBhcnRpY2lwYW50cyBhbmQgaXRlbXMsIHdlIGRvIG5vdCBpbnRlbmQgdG8gaW5jbHVkZSBpdGVtcyBpbiB0aGUgYW5hbHlzZXMgc2luY2UgcG93ZXIgb24gdGhpcyBkaW1lbnNpb24gd2lsbCBiZSBsb3cuIChOQiAtIGl0IGlzIG5vdCBjb21tb24gZm9yIGJ5IGl0ZW1zIGFuYWx5c2VzIHRvIGJlIGluY2x1ZGVkIGZvciB3b3JrIGluIHRoaXMgYXJlYTsgaW5jcmVhc2luZyB0aGUgbnVtYmVyIG9mIGl0ZW1zIGluIGEgbGVhcm5pbmcgc3R1ZHkgb2YgdGhpcyB0eXBlIHdpdGggY2hpbGRyZW4gaXMgbm90IGZlYXNpYmxlKS4gV2UgdXNlIGZ1bGwgcmFuZG9tIHNsb3BlcyBzdHJ1Y3R1cmUgZm9yIHByZWRpY3RvcnMgb2YgaW50ZXJlc3QgKGdlbmVyYWxseSwgY29uZGl0aW9uLCBzZXNzaW9uL3ByZS0+cG9zdCkuIEZhY3RvcnMgc3VjaCBhcyB0b25lIGNvbnRyYXN0IGZvciB0aGUgdHJpYWwgYXJlIGluY2x1ZGVkIGFzIGZpeGVkIGZhY3RvcnMgYW5kIHdlIHdpbGwgbm90IGluY2x1ZGUgcmFuZG9tIHNsb3BlcyAgZm9yIHRoZXNlLg0KDQpGb3IgdGhlIEJheWVzaWFuIGFuYWxzeWVzLCB3ZSB3aWxsIGNvbnRpbnVlIHRvIHdvcmsgaW4gbG9nIG9kZHMgc3BhY2UgKGFzIGZvciBGcmVxdWVudGlzdCkgdG8gbWVldCBhc3N1bXB0aW9ucyBvZiBub3JtYWxpdHksIHVzaW5nIGVzdGltYXRlcyBhbmQgc3RhbmRhcmQgZXJyb3JzIHdoaWNoIGNvbWUgZnJvbSB0aGUgbG9naXN0aWMgbWl4ZWQgZWZmZWN0cyBtb2RlbHMuIEZvbGxvd2luZyBEaWVuZXMgKDIwMDgpIHdlIHdpbGwgbW9kZWwgSDEgYnkgdXNpbmcgYW4gZXN0aW1hdGUgb2YgdGhlIG1lYW4gZm9yIHRoZW9yeSAoYW4gZXN0aW1hdGUgY29taW5nIGZyb20gZWl0aGVyIGZyb20gbG9naXN0aWMgbWl4ZWQgZWZmZWN0cyBtb2RlbHMgcnVuIG92ZXIgcGlsb3QgZGF0YSwgb3IgaW4gc29tZSBjYXNlcyBmcm9tIGVsc2V3aGVyZSBpbiB0aGUgZGF0YSkgYXMgdGhlIFNEIG9mIGEgaGFsZiBub3JtYWwgKGZvciBvbmUgdGFpbGVkKSBvciBmdWxsIG5vcm1hbCAoZm9yIHR3byB0YWlsZWQpIGRpc3RyaWJ1dGlvbi4gV2Ugd2lsbCBzYXkgd2UgaGF2ZSBzdWJzdGFudGlhbCBldmlkZW5jZSBmb3IgSDEgaXMgQkY+MyBhbmQgQkY8LjMzIGFjY2VwdGVkIGlmIEJGPjQgDQoNClNlZTogaHR0cHM6Ly9kb2kub3JnLzEwLjEwMTYvai5qbWwuMjAxNy4wMS4wMDUgZm9yIHB1Ymxpc2hlZCBwYXBlciB1c2luZyB0aGlzIGFwcHJvYWNoIGFuZCBSc2NyaXB0IGh0dHA6Ly9ycHVicy5jb20vZXdvbm5hY290dC8yNDI0NTQuIA0KDQoNCk5vdGUgdGhhdCB0aGUgcGlsb3QgZGF0YSByZWZlcnJlZCB0byBiZWxvdyBjb21lcyBmcm9tIHRocmVlIHN0dWRlbnRzIHByb2plY3RzLiBOb25lIHdlcmUgZXhhY3RseSB0aGUgc2FtZSBhcyB0aGUgZXhwZXJpbWVudHMgcGxhbm5lZCBoZXJlLCBidXQgbWF0ZXJpYWxzIHdlcmUgdmVyeSAgc2ltaWxhciBhbmQgaW4gc29tZSBjYXNlcyBzaW1pbGFyIHF1ZXN0aW9ucyB3ZXJlIGFza2VkLiBUaGUgbW9kZWxzIG9mIHRoZSBwaWxvdCBkYXRhIHByZXNlbnRlZCBiZWxvdyBhbHNvIHNlcnZlIHRvIGV4ZW1wbGlmeSB0aGUgYXBwcm9hY2ggdG8gYmUgdGFrZW4gd2l0aCB0aGUgY3VycmVudCBkYXRhLg0KDQpXaGVyZSBwb3NzaWJsZSwgd2UgY29uZHVjdGVkIHBvd2VyIGFuYWx5c2VzLCBhbHRob3VnaCBsbWUncyB3aWxsIGJlIHVzZWQgZm9yIHRoZSBhY3R1YWwgYW5hbHN5ZXMsIHdlIGNvbmR1Y3RlZCB0aGUgYW5hbHN5ZXMgYXMgdGhvdWdoIGZvciAobmVhciBlcXVpdmFsZW50KSB0LXRlc3RzIG92ZXIgYnkgc3ViamVjdCBwcm9wb3Rpb25zLiBUaGlzIG1lYW5zIHRoYXQgdGhlIHZhbHVlcyBhcmUgb25seSBhcHByb3hpbWF0ZSwgYnV0IHNpbmNlIG91ciBtYWluIGFuYWxzeWVzIGFyZSBCRiBmYWN0b3JzIG91ciBhaW0gaGVyZSBpcyB0byBnZXQgYW4gaWRlYSBvZiBhcHByb3hpbWF0ZSBzdWl0YWJsZSBzYW1wbGVzLg0KDQpJbiBhZGRpdGlvbiB0byBwb3dlciBhbmFseXNlcywgd2hlcmUgcG9zc2libGUgd2UgYWxzbyBjb25kdWN0ZWQgQmF5ZXNpYW4gYW5hbHN5ZXMgb24gcmVsZXZhbnQgcGFydHMgb2YgdGhlIHBpbG90IGRhdGEgdG8gc2VlIGlzIHdlIGhhZCBhIHN1ZmZpY2llbnQgc2FtcGxlIGZvciBCRj4zIG9yIEJGPC4zMy4gV2UgYWxzbyBsb29rIHRvIHNlZSB3aGF0IHNpemUgc2FtcGxlIG1pZ2h0IGJlIGV4cGVjdGVkIHRvIGdpdmUgQkY+MyBvciBCRjwuMzMsIGdpdmVuIHRoYXQgICBTRSB2YXJ1ZXMgYXMgc3F1YXJlcm9vdChOKS4NCg0KVGhlIGFuYWx5c2VzIGJlbG93IHN1Z2dlc3QgdGhhdCB0aGVyZSBhcmUgY2FzZXMgd2hlcmUgYSBzYW1wbGUgb2YgMjAgcGFydGljaXBhbnRzIHBlciBjb25kaXRpb24gY291bGQgYmUgc3VmZmljaWVudCB0byBhY2hlaXZlIDkwJSBwb3dlci4gSW50ZXJlYWN0aW9ucyB3aXRoIGNvbmRpdGlvbiB3aWxsIGJlIGhhcmRlciB0byBwb3dlcjsgYXMgZGlzY3Vzc2VkIGJlbG93LCB0aGVyZSBtYXkgYmUgc2l0dWF0aW9ucyB3aGVyZSB0aGVyZSBpcyBldmlkZW5jZSBvZiBIMSAoaWUuIGRhdGEgcmVmbGVjcyBsZWFybmluZykgaW4gY29uZGl0aW9uMSBidXQgZXZpZGVuY2UgZm9yIEgwIChubyBldmlkZW5jZSBvZiBsZWFybmluZyBpbiB0aGlzIGRhdCkgZm9yIGNvbmRpdGlvbjIuIElmIHNvLCB3ZSB3aWwgZGVlbSB0aGlzIHN1ZmZpY2llbnQgdG8gZHJhdyBjb25jdWxzaW9ucyBhYm91dCB0aGUgZGlmZmVyZW50IHRyYWluaW5nIG1ldGhvZHMuDQoNCk91ciBwb2xpY3kgd2lsIGJlIGFzIGZvbGxvd3M6IHdlIHdpbGwgaW5zcGVjdCB0aGUgZGF0YSBhZnRlciB3ZSBoYXZlIGFwcHJveC4gMjAgcGFydGljaXBhbnRzIGluIGVhY2ggY29uZGl0aW9uIChOb3RlOiB0aGlzIGlzIGFwcHJveGltYXRlIHNpbmNlIHdlIGFpbSAgdG8gZ2V0IHRoaXMgYnkgdGhlIGVuZCBvZiB0aGUgYWNhZGVtaWMgeWVhcjsgaWYgd2UgZG9uJ3QgcXVpdGUgZ2V0IHRoaXMgbWFueSBjaGlsZHJlbiwgd2Ugd2lsbCBzdGlsbCBsb29rIGF0IHRoZSBzYW1wbGUgd2UgaGF2ZSkuIElmIHJlc3VsdHMgZm9yIGtleSBhbmFsc3llcyBhcmUgaW5jb25jbHVzaXZlLCByZXNvdXJjZXMgcGVybWl0dGluZyB3ZSB3aWxsIGNvbnRpbnVlIHRvIHRlc3QgIG1vcmUgcGFydGljaXBhbnRzLCBjb2xsZWN0aW5nIDEwIHBlciBjb25kaXRpb24gYXQgZWFjaCBzdGVwIGJlZm9yZSBpbnNwZWN0aW5nIHRoZSBkYXRhIGFnYWluIGF0IGVhY2ggc3RlcC4gV2Ugd2lsbCBjb250aW51ZSB1bnRpbCBOIHBlciBjb25kaXRpb24gPTUwLCByZXNvdXJjZXMgcGVybWl0dGluZy4gIA0KICANCkZpbmFsIG5vdGU6IHdlIGhhdmUgZGVzaWduZWQgdGhlIGV4cGVyaW1lbnQgdG8gaGF2ZSBmb3VyIHNlc3Npb25zIGFzIGZvbGxvd3M6DQpzZXNzaW9uMSBwcmUtdGVzdHM6IGRpc2NyaW1pbmF0aW9uIGFuZCAgd29yZHJlcGV0aXRpb24gDQogICAgICAgICB0cmFpbmluZw0Kc2Vzc2lvbjIgdHJhaW5pbmcNCiAgICAgICAgIHBvc3QtdGVzdHM6IGRpc2NyaW1pbmF0aW9uIGFuZCAgd29yZHJlcGV0aXRpb24gDQogICAgICAgICAgICAgICAgICAgICAyQUZDIHBpY3Rlc3QvIDJBRkMgdG9uZXRlc3QNCnNlc3Npb24zIHRyYWluaW5nDQogICAgICAgDQpzZXNzaW9uNCB0cmFpbmluZw0KICAgICAgICAgcG9zdC10ZXN0czogZGlzY3JpbWluYXRpb24gYW5kICB3b3JkcmVwZXRpdGlvbiANCiAgICAgICAgICAgICAgICAgICAgIDJBRkMgcGljdGVzdC8gMkFGQyB0b25ldGVzdA0KICAgICAgICAgICAgICAgICAgICAgDQpGb3Igb3VyIGZpcnN0IGluc3BlY3Rpb24gb2YgdGhlIGRhdGEsIHdlIHdpbGwgY29uZHVjdCBhbmFsc3llcyBib3RoIG9uIGRheTIgZGF0YSBhbmQgZGF5NCBkYXRhIChib3RoIGNvbXBhcmVkIHRvIHJlbGV2YW50IHByZS10ZXN0czsgZm9yIHRyYWluaW5nIGRhdGEgaXRzZWxmLCB3ZSB3aWxsIGxvb2sgYXQgc2Vzc2lvbnMxIGFuZCAyIHZlcnN1cyBzZXNzaW9uIDEsMiwzJjQpLiAgSWYgdXNpbmcgZGF0YSBmcm9tIHNlc3Npb240IGV4dHJhIHR3byBzZXNzaW9ucyBkbyBub3QgYWZmZWN0IHRoZSBrZXkgcGF0dGVybiBvZiByZXN1bHRzLCBnaXZlbiB0aGUgbGFyZ2UgZXhwZW5pdHVyZSBvZiByZXNvdXJjZXMgcGVyIHBhcnRpY2lwYW50LCB3ZSB3aWxsIGRyb3AgdGhlIGZpbmFsIHR3byBzZXNzaW9ucyBmb3Igb25nb2luZyAgcGFydGljaXBhbnQgY29sbGVjdGlvbi4NCg0KTm90ZSB0aGF0IGZyZXF1ZW50aXN0IGFuYWxzeWVzIHdpbGwgbm90IGJlIHZhbGlkIGF0IC4wNSBsZXZlbCwgZHVlIHRvIHN0b3BwaW5nIHByb2JsZW0uIEN1cnJlbnQgcGxhbiBpcyB0byBuZXZlcnRoZWxlc3MgcmVwb3J0IHdpdGggdGhhdCBjYXZlYXQ7IEJGIHdpbGwgYmUgY29uc2lkZXJlZCB0aGUgIGNyaXRpY2FsIGFuYWx5c2VzLikNCg0KRGF0YSB3aWxsIGJlIGNvbGxlY3RlZCBmcm9tIGNoaWxkcmVuIGluIHllYXIgMyAoYWdlZCA3LTgpDQoNCiMgTG9hZCBwYWNrYWdlcyBhbmQgaGVscGVyIGZ1bmN0aW9ucw0KIyMgUGFja2FnZXMNCg0KYGBge3J9DQojIyBQYWNrYWdlcy4gIA0Kcm0obGlzdD1scygpKQ0KI3N1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KHN0cmluZ2Rpc3QpKQ0KI2xpYnJhcnkobGFuZ3VhZ2VSKQ0KbGlicmFyeShsYXR0aWNlKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkobG1lNCkpDQpsaWJyYXJ5KHBsb3RyaXgpDQojc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoaXJyKSkNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGdncGxvdDIpCSNmb3IgZ3JhcGhzDQojbGlicmFyeShyZXNoYXBlKQ0KbGlicmFyeShyZXNoYXBlMikNCg0KI2xpYnJhcnkocmVzaGFwZSkNCmxpYnJhcnkocmVzaGFwZTIpDQojbGlicmFyeShyZXNoYXBlKQ0KbGlicmFyeShyZXNoYXBlMikNCiNsaWJyYXJ5KGxtZXJUZXN0KQ0KI2xpYnJhcnkoc2ltcikNCmxpYnJhcnkobHNyKQ0KYGBgDQoNCg0KIyBIZWxwZXIgRnVuY3Rpb25zDQoNCiMjIyBTdW1tYXJ5U0UNCg0KVGhpcyBmdW5jdGlvbiBjYW4gYmUgZm91bmQgb24gdGhlICB3ZWJzaXRlICJDb29rYm9vayBmb3IgUiIuDQoNCmh0dHA6Ly93d3cuY29va2Jvb2stci5jb20vTWFuaXB1bGF0aW5nX2RhdGEvU3VtbWFyaXppbmdfZGF0YS8NCg0KSXQgc3VtbWFyaXplcyBkYXRhLCBnaXZpbmcgY291bnQsIG1lYW4sIHN0YW5kYXJkIGRldmlhdGlvbiwgc3RhbmRhcmQgZXJyb3Igb2YgdGhlIG1lYW4sIGFuZCBjb25maWRlbmNlIGludGVydmFsIChkZWZhdWx0IDk1JSkuDQoNCi0gZGF0YTogYSBkYXRhIGZyYW1lLiANCi0gbWVhc3VyZXZhcjogdGhlIG5hbWUgb2YgYSBjb2x1bW4gdGhhdCBjb250YWlucyB0aGUgdmFyaWFibGUgdG8gYmUgc3VtbWFyaXplZC4NCi0gZ3JvdXB2YXJzOiBhIHZlY3RvciBjb250YWluaW5nIG5hbWVzIG9mIGNvbHVtbnMgdGhhdCBjb250YWluIGdyb3VwaW5nIHZhcmlhYmxlcy4NCi0gbmEucm06IGEgYm9vbGVhbiB0aGF0IGluZGljYXRlcyB3aGV0aGVyIHRvIGlnbm9yZSBOQSdzLg0KLSBjb25mLmludGVydmFsOiB0aGUgcGVyY2VudCByYW5nZSBvZiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCAoZGVmYXVsdCBpcyA5NSUpLg0KDQpgYGB7cn0NCnN1bW1hcnlTRSA8LSBmdW5jdGlvbihkYXRhPU5VTEwsIG1lYXN1cmV2YXIsIGdyb3VwdmFycz1OVUxMLCBuYS5ybT1GQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb25mLmludGVydmFsPS45NSwgLmRyb3A9VFJVRSkgew0KICAgIHJlcXVpcmUocGx5cikNCg0KICAgICMgTmV3IHZlcnNpb24gb2YgbGVuZ3RoIHdoaWNoIGNhbiBoYW5kbGUgTkEnczogaWYgbmEucm09PVQsIGRvbid0IGNvdW50IHRoZW0NCiAgICBsZW5ndGgyIDwtIGZ1bmN0aW9uICh4LCBuYS5ybT1GQUxTRSkgew0KICAgICAgICBpZiAobmEucm0pIHN1bSghaXMubmEoeCkpDQogICAgICAgIGVsc2UgICAgICAgbGVuZ3RoKHgpDQogICAgfQ0KDQogICAgIyBUaGlzIGRvZXMgdGhlIHN1bW1hcnkuIEZvciBlYWNoIGdyb3VwJ3MgZGF0YSBmcmFtZSwgcmV0dXJuIGEgdmVjdG9yIHdpdGgNCiAgICAjIE4sIG1lYW4sIGFuZCBzZA0KICAgIGRhdGFjIDwtIGRkcGx5KGRhdGEsIGdyb3VwdmFycywgLmRyb3A9LmRyb3AsDQogICAgICAuZnVuID0gZnVuY3Rpb24oeHgsIGNvbCkgew0KICAgICAgICBjKE4gICAgPSBsZW5ndGgyKHh4W1tjb2xdXSwgbmEucm09bmEucm0pLA0KICAgICAgICAgIG1lYW4gPSBtZWFuICAgKHh4W1tjb2xdXSwgbmEucm09bmEucm0pLA0KICAgICAgICAgIHNkICAgPSBzZCAgICAgKHh4W1tjb2xdXSwgbmEucm09bmEucm0pDQogICAgICAgICkNCiAgICAgIH0sDQogICAgICBtZWFzdXJldmFyDQogICAgKQ0KDQogICAgIyBSZW5hbWUgdGhlICJtZWFuIiBjb2x1bW4gICAgDQogICAgZGF0YWMgPC0gcmVuYW1lKGRhdGFjLCBjKCJtZWFuIiA9IG1lYXN1cmV2YXIpKQ0KDQogICAgZGF0YWMkc2UgPC0gZGF0YWMkc2QgLyBzcXJ0KGRhdGFjJE4pICAjIENhbGN1bGF0ZSBzdGFuZGFyZCBlcnJvciBvZiB0aGUgbWVhbg0KDQogICAgIyBDb25maWRlbmNlIGludGVydmFsIG11bHRpcGxpZXIgZm9yIHN0YW5kYXJkIGVycm9yDQogICAgIyBDYWxjdWxhdGUgdC1zdGF0aXN0aWMgZm9yIGNvbmZpZGVuY2UgaW50ZXJ2YWw6IA0KICAgICMgZS5nLiwgaWYgY29uZi5pbnRlcnZhbCBpcyAuOTUsIHVzZSAuOTc1IChhYm92ZS9iZWxvdyksIGFuZCB1c2UgZGY9Ti0xDQogICAgY2lNdWx0IDwtIHF0KGNvbmYuaW50ZXJ2YWwvMiArIC41LCBkYXRhYyROLTEpDQogICAgZGF0YWMkY2kgPC0gZGF0YWMkc2UgKiBjaU11bHQNCg0KICAgIHJldHVybihkYXRhYykNCn0NCmBgYA0KDQojIyMgU3VtbWFyeVNFd2l0aGluDQoNClRoaXMgZnVuY3Rpb24gY2FuIGJlIGZvdW5kIG9uIHRoZSAgd2Vic2l0ZSAiQ29va2Jvb2sgZm9yIFIiLg0KDQpodHRwOi8vd3d3LmNvb2tib29rLXIuY29tL0dyYXBocy9QbG90dGluZ19tZWFuc19hbmRfZXJyb3JfYmFyc18oZ2dwbG90MikvI0hlbHBlciBmdW5jdGlvbnMNCg0KRnJvbSB0aGF0IHdlYnNpdGU6DQoNClN1bW1hcml6ZXMgZGF0YSwgaGFuZGxpbmcgd2l0aGluLXN1YmplY3RzIHZhcmlhYmxlcyBieSByZW1vdmluZyBpbnRlci1zdWJqZWN0IHZhcmlhYmlsaXR5Lg0KSXQgd2lsbCBzdGlsbCB3b3JrIGlmIHRoZXJlIGFyZSBubyB3aXRoaW4tUyB2YXJpYWJsZXMuDQpHaXZlcyBjb3VudCwgdW4tbm9ybWVkIG1lYW4sIG5vcm1lZCBtZWFuICh3aXRoIHNhbWUgYmV0d2Vlbi1ncm91cCBtZWFuKSwNCnN0YW5kYXJkIGRldmlhdGlvbiwgc3RhbmRhcmQgZXJyb3Igb2YgdGhlIG1lYW4sIGFuZCBjb25maWRlbmNlIGludGVydmFsLg0KSWYgdGhlcmUgYXJlIHdpdGhpbi1zdWJqZWN0IHZhcmlhYmxlcywgY2FsY3VsYXRlIGFkanVzdGVkIHZhbHVlcyB1c2luZyBtZXRob2QgZnJvbSBNb3JleSAoMjAwOCkuDQpkYXRhOiBhIGRhdGEgZnJhbWUuDQoNCm1lYXN1cmV2YXI6IHRoZSBuYW1lIG9mIGEgY29sdW1uIHRoYXQgY29udGFpbnMgdGhlIHZhcmlhYmxlIHRvIGJlIHN1bW1hcmllemVkDQpiZXR3ZWVudmFyczogYSB2ZWN0b3IgY29udGFpbmluZyBuYW1lcyBvZiBjb2x1bW5zIHRoYXQgYXJlIGJldHdlZW4tc3ViamVjdHMgdmFyaWFibGVzDQp3aXRoaW52YXJzOiBhIHZlY3RvciBjb250YWluaW5nIG5hbWVzIG9mIGNvbHVtbnMgdGhhdCBhcmUgd2l0aGluLXN1YmplY3RzIHZhcmlhYmxlcw0KaWR2YXI6IHRoZSBuYW1lIG9mIGEgY29sdW1uIHRoYXQgaWRlbnRpZmllcyBlYWNoIHN1YmplY3QgKG9yIG1hdGNoZWQgc3ViamVjdHMpDQpuYS5ybTogYSBib29sZWFuIHRoYXQgaW5kaWNhdGVzIHdoZXRoZXIgdG8gaWdub3JlIE5BJ3MNCmNvbmYuaW50ZXJ2YWw6IHRoZSBwZXJjZW50IHJhbmdlIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFsIChkZWZhdWx0IGlzIDk1JSkNCg0KYGBge3J9DQpzdW1tYXJ5U0V3aXRoaW4gPC0gZnVuY3Rpb24oZGF0YT1OVUxMLCBtZWFzdXJldmFyLCBiZXR3ZWVudmFycz1OVUxMLCB3aXRoaW52YXJzPU5VTEwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWR2YXI9TlVMTCwgbmEucm09RkFMU0UsIGNvbmYuaW50ZXJ2YWw9Ljk1LCAuZHJvcD1UUlVFKSB7DQoNCiAgIyBFbnN1cmUgdGhhdCB0aGUgYmV0d2VlbnZhcnMgYW5kIHdpdGhpbnZhcnMgYXJlIGZhY3RvcnMNCiAgZmFjdG9ydmFycyA8LSB2YXBwbHkoZGF0YVssIGMoYmV0d2VlbnZhcnMsIHdpdGhpbnZhcnMpLCBkcm9wPUZBTFNFXSwNCiAgICBGVU49aXMuZmFjdG9yLCBGVU4uVkFMVUU9bG9naWNhbCgxKSkNCg0KICBpZiAoIWFsbChmYWN0b3J2YXJzKSkgew0KICAgIG5vbmZhY3RvcnZhcnMgPC0gbmFtZXMoZmFjdG9ydmFycylbIWZhY3RvcnZhcnNdDQogICAgbWVzc2FnZSgiQXV0b21hdGljYWxseSBjb252ZXJ0aW5nIHRoZSBmb2xsb3dpbmcgbm9uLWZhY3RvcnMgdG8gZmFjdG9yczogIiwNCiAgICAgICAgICAgIHBhc3RlKG5vbmZhY3RvcnZhcnMsIGNvbGxhcHNlID0gIiwgIikpDQogICAgZGF0YVtub25mYWN0b3J2YXJzXSA8LSBsYXBwbHkoZGF0YVtub25mYWN0b3J2YXJzXSwgZmFjdG9yKQ0KICB9DQoNCiAgIyBHZXQgdGhlIG1lYW5zIGZyb20gdGhlIHVuLW5vcm1lZCBkYXRhDQogIGRhdGFjIDwtIHN1bW1hcnlTRShkYXRhLCBtZWFzdXJldmFyLCBncm91cHZhcnM9YyhiZXR3ZWVudmFycywgd2l0aGludmFycyksDQogICAgICAgICAgICAgICAgICAgICBuYS5ybT1uYS5ybSwgY29uZi5pbnRlcnZhbD1jb25mLmludGVydmFsLCAuZHJvcD0uZHJvcCkNCg0KICAjIERyb3AgYWxsIHRoZSB1bnVzZWQgY29sdW1ucyAodGhlc2Ugd2lsbCBiZSBjYWxjdWxhdGVkIHdpdGggbm9ybWVkIGRhdGEpDQogIGRhdGFjJHNkIDwtIE5VTEwNCiAgZGF0YWMkc2UgPC0gTlVMTA0KICBkYXRhYyRjaSA8LSBOVUxMDQoNCiAgIyBOb3JtIGVhY2ggc3ViamVjdCdzIGRhdGENCiAgbmRhdGEgPC0gbm9ybURhdGFXaXRoaW4oZGF0YSwgaWR2YXIsIG1lYXN1cmV2YXIsIGJldHdlZW52YXJzLCBuYS5ybSwgLmRyb3A9LmRyb3ApDQoNCiAgIyBUaGlzIGlzIHRoZSBuYW1lIG9mIHRoZSBuZXcgY29sdW1uDQogIG1lYXN1cmV2YXJfbiA8LSBwYXN0ZShtZWFzdXJldmFyLCAiX25vcm0iLCBzZXA9IiIpDQoNCiAgIyBDb2xsYXBzZSB0aGUgbm9ybWVkIGRhdGEgLSBub3cgd2UgY2FuIHRyZWF0IGJldHdlZW4gYW5kIHdpdGhpbiB2YXJzIHRoZSBzYW1lDQogIG5kYXRhYyA8LSBzdW1tYXJ5U0UobmRhdGEsIG1lYXN1cmV2YXJfbiwgZ3JvdXB2YXJzPWMoYmV0d2VlbnZhcnMsIHdpdGhpbnZhcnMpLA0KICAgICAgICAgICAgICAgICAgICAgIG5hLnJtPW5hLnJtLCBjb25mLmludGVydmFsPWNvbmYuaW50ZXJ2YWwsIC5kcm9wPS5kcm9wKQ0KDQogICMgQXBwbHkgY29ycmVjdGlvbiBmcm9tIE1vcmV5ICgyMDA4KSB0byB0aGUgc3RhbmRhcmQgZXJyb3IgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwNCiAgIyAgR2V0IHRoZSBwcm9kdWN0IG9mIHRoZSBudW1iZXIgb2YgY29uZGl0aW9ucyBvZiB3aXRoaW4tUyB2YXJpYWJsZXMNCiAgbldpdGhpbkdyb3VwcyAgICA8LSBwcm9kKHZhcHBseShuZGF0YWNbLHdpdGhpbnZhcnMsIGRyb3A9RkFMU0VdLCBGVU49bmxldmVscywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTi5WQUxVRT1udW1lcmljKDEpKSkNCiAgY29ycmVjdGlvbkZhY3RvciA8LSBzcXJ0KCBuV2l0aGluR3JvdXBzIC8gKG5XaXRoaW5Hcm91cHMtMSkgKQ0KDQogICMgQXBwbHkgdGhlIGNvcnJlY3Rpb24gZmFjdG9yDQogIG5kYXRhYyRzZCA8LSBuZGF0YWMkc2QgKiBjb3JyZWN0aW9uRmFjdG9yDQogIG5kYXRhYyRzZSA8LSBuZGF0YWMkc2UgKiBjb3JyZWN0aW9uRmFjdG9yDQogIG5kYXRhYyRjaSA8LSBuZGF0YWMkY2kgKiBjb3JyZWN0aW9uRmFjdG9yDQoNCiAgIyBDb21iaW5lIHRoZSB1bi1ub3JtZWQgbWVhbnMgd2l0aCB0aGUgbm9ybWVkIHJlc3VsdHMNCiAgbWVyZ2UoZGF0YWMsIG5kYXRhYykNCn0NCmBgYA0KDQojIyMgbm9ybURhdGFXaXRoaW4NCg0KVGhpcyBmdW5jdGlvbiBpcyB1c2VkIGJ5IHRoZSBTdW1tYXJ5U0VXaXRoaW4gZnVjbnRpb24gYWJvdmUuIEl0IGNhbiBiZSBmb3VuZCBvbiB0aGUgIHdlYnNpdGUgIkNvb2tib29rIGZvciBSIi4NCg0KaHR0cDovL3d3dy5jb29rYm9vay1yLmNvbS9HcmFwaHMvUGxvdHRpbmdfbWVhbnNfYW5kX2Vycm9yX2JhcnNfKGdncGxvdDIpLyNIZWxwZXIgZnVuY3Rpb25zDQoNCkZyb20gdGhhdCB3ZWJzaXRlOg0KDQpOb3JtcyB0aGUgZGF0YSB3aXRoaW4gc3BlY2lmaWVkIGdyb3VwcyBpbiBhIGRhdGEgZnJhbWU7IGl0IG5vcm1hbGl6ZXMgZWFjaA0Kc3ViamVjdCAoaWRlbnRpZmllZCBieSBpZHZhcikgc28gdGhhdCB0aGV5IGhhdmUgdGhlIHNhbWUgbWVhbiwgd2l0aGluIGVhY2ggZ3JvdXANCnNwZWNpZmllZCBieSBiZXR3ZWVudmFycy4NCmRhdGE6IGEgZGF0YSBmcmFtZS4NCmlkdmFyOiB0aGUgbmFtZSBvZiBhIGNvbHVtbiB0aGF0IGlkZW50aWZpZXMgZWFjaCBzdWJqZWN0IChvciBtYXRjaGVkIHN1YmplY3RzKQ0KbWVhc3VyZXZhcjogdGhlIG5hbWUgb2YgYSBjb2x1bW4gdGhhdCBjb250YWlucyB0aGUgdmFyaWFibGUgdG8gYmUgc3VtbWFyaWV6ZWQNCmJldHdlZW52YXJzOiBhIHZlY3RvciBjb250YWluaW5nIG5hbWVzIG9mIGNvbHVtbnMgdGhhdCBhcmUgYmV0d2Vlbi1zdWJqZWN0cyB2YXJpYWJsZXMNCm5hLnJtOiBhIGJvb2xlYW4gdGhhdCBpbmRpY2F0ZXMgd2hldGhlciB0byBpZ25vcmUgTkEncw0KDQoNCmBgYHtyfQ0Kbm9ybURhdGFXaXRoaW4gPC0gZnVuY3Rpb24oZGF0YT1OVUxMLCBpZHZhciwgbWVhc3VyZXZhciwgYmV0d2VlbnZhcnM9TlVMTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtPUZBTFNFLCAuZHJvcD1UUlVFKSB7DQogICAgI2xpYnJhcnkocGx5cikNCg0KICAgICMgTWVhc3VyZSB2YXIgb24gbGVmdCwgaWR2YXIgKyBiZXR3ZWVuIHZhcnMgb24gcmlnaHQgb2YgZm9ybXVsYS4NCiAgICBkYXRhLnN1YmpNZWFuIDwtIGRkcGx5KGRhdGEsIGMoaWR2YXIsIGJldHdlZW52YXJzKSwgLmRyb3A9LmRyb3AsDQogICAgIC5mdW4gPSBmdW5jdGlvbih4eCwgY29sLCBuYS5ybSkgew0KICAgICAgICBjKHN1YmpNZWFuID0gbWVhbih4eFssY29sXSwgbmEucm09bmEucm0pKQ0KICAgICAgfSwNCiAgICAgIG1lYXN1cmV2YXIsDQogICAgICBuYS5ybQ0KICAgICkNCg0KICAgICMgUHV0IHRoZSBzdWJqZWN0IG1lYW5zIHdpdGggb3JpZ2luYWwgZGF0YQ0KICAgIGRhdGEgPC0gbWVyZ2UoZGF0YSwgZGF0YS5zdWJqTWVhbikNCg0KICAgICMgR2V0IHRoZSBub3JtYWxpemVkIGRhdGEgaW4gYSBuZXcgY29sdW1uDQogICAgbWVhc3VyZU5vcm1lZFZhciA8LSBwYXN0ZShtZWFzdXJldmFyLCAiX25vcm0iLCBzZXA9IiIpDQogICAgZGF0YVssbWVhc3VyZU5vcm1lZFZhcl0gPC0gZGF0YVssbWVhc3VyZXZhcl0gLSBkYXRhWywic3Viak1lYW4iXSArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbihkYXRhWyxtZWFzdXJldmFyXSwgbmEucm09bmEucm0pDQoNCiAgICAjIFJlbW92ZSB0aGlzIHN1YmplY3QgbWVhbiBjb2x1bW4NCiAgICBkYXRhJHN1YmpNZWFuIDwtIE5VTEwNCg0KICAgIHJldHVybihkYXRhKQ0KfQ0KDQpgYGANCg0KDQojIyMgbXlDZW50ZXINCg0KVGhpcyBmdW5jdGlvbiBvdXB1dHMgdGhlIGNlbnRlcmVkIHZhbHVlcyBvZiBhbiB2YXJpYWJsZSwgd2hpY2ggY2FuIGJlIGEgbnVtZXJpYyB2YXJpYWJsZSwgYSBmYWN0b3IsIG9yIGEgZGF0YSBmcmFtZS4gSXQgd2FzIHRha2VuIGZyb20gRmxvcmlhbiBKYWVnZXJzIGJsb2cgDQoNCmh0dHBzOi8vaGxwbGFiLndvcmRwcmVzcy5jb20vMjAwOS8wNC8yNy9jZW50ZXJpbmctc2V2ZXJhbC12YXJpYWJsZXMvLg0KDQpGcm9tIGhpcyBibG9nOg0KDQotIElmIHRoZSBpbnB1dCBpcyBhIG51bWVyaWMgdmFyaWFibGUsIHRoZSBvdXRwdXQgaXMgdGhlIGNlbnRlcmVkIHZhcmlhYmxlLg0KDQotIElmIHRoZSBpbnB1dCBpcyBhIGZhY3RvciwgdGhlIG91dHB1dCBpcyBhIG51bWVyaWMgdmFyaWFibGUgd2l0aCBjZW50ZXJlZCBmYWN0b3IgbGV2ZWwgdmFsdWVzLiBUaGF0IGlzLCB0aGUgZmFjdG9yJ3MgbGV2ZWxzIGFyZSBjb252ZXJ0ZWQgaW50byBudW1lcmljYWwgdmFsdWVzIGluIHRoZWlyIGluaGVyZW50IG9yZGVyIChpZiBub3Qgc3BlY2lmaWVkIG90aGVyd2lzZSwgIFIgZGVmYXVsdHMgdG8gYWxwaGFudW1lcmljYWwgb3JkZXIpLiBNb3JlIHNwZWNpZmljYWxseSwgdGhpcyBjZW50ZXJzIGFueSBiaW5hcnkgZmFjdG9yIHNvIHRoYXQgdGhlIHZhbHVlIGJlbG93IDAgd2lsbCBiZSB0aGUgMXN0IGxldmVsIG9mIHRoZSBvcmlnaW5hbCBmYWN0b3IsIGFuZCB0aGUgdmFsdWUgYWJvdmUgMCB3aWxsIGJlIHRoZSAybmQgbGV2ZWwuDQoNCi0gSWYgdGhlIGlucHV0IGlzIGEgZGF0YSBmcmFtZSBvciBtYXRyaXgsIHRoZSBvdXRwdXQgaXMgYSBuZXcgbWF0cml4IG9mIHRoZSBzYW1lIGRpbWVuc2lvbiBhbmQgd2l0aCB0aGUgY2VudGVyZWQgdmFsdWVzIGFuZCBjb2x1bW4gbmFtZXMgdGhhdCBjb3JyZXNwb25kIHRvIHRoZSBjb2xuYW1lcygpIG9mIHRoZSBpbnB1dCBwcmVjZWRlZCBieSAiYyIgKGUuZy4gIlZhcmlhYmxlMSIgd2lsbCBiZSAiY1ZhcmlhYmxlMSIpLg0KDQpgYGB7cn0NCm15Q2VudGVyPSBmdW5jdGlvbih4KSB7DQogIGlmIChpcy5udW1lcmljKHgpKSB7IHJldHVybih4IC0gbWVhbih4LCBuYS5ybT1UKSkgfQ0KCWlmIChpcy5mYWN0b3IoeCkpIHsNCgkJeD0gYXMubnVtZXJpYyh4KQ0KCQlyZXR1cm4oeCAtIG1lYW4oeCwgbmEucm09VCkpDQoJfQ0KCWlmIChpcy5kYXRhLmZyYW1lKHgpIHx8IGlzLm1hdHJpeCh4KSkgew0KCQltPSBtYXRyaXgobnJvdz1ucm93KHgpLCBuY29sPW5jb2woeCkpDQoJCWNvbG5hbWVzKG0pPSBwYXN0ZSgiYyIsIGNvbG5hbWVzKHgpLCBzZXA9IiIpDQoJDQoJCWZvciAoaSBpbiAxOm5jb2woeCkpIHsNCgkJDQoJCQltWyxpXT0gbXlDZW50ZXIoeFssaV0pDQoJCX0NCgkJcmV0dXJuKGFzLmRhdGEuZnJhbWUobSkpDQoJfQ0KfQ0KYGBgDQoNCiMjIyBsaXpDZW50ZXINCg0KVGhpcyBmdW5jdGlvbiBwcm92aWRlcyBhIHdyYXBwZXIgYXJvdW5kIG15Q2VudGVyIGFsbG93aW5nIHlvdSB0byBjZW50ZXIgYSBzcGVjaWZpYyBsaXN0IG9mIHZhcmlhYmxlcyBmcm9tIGEgZGF0YWZyYW1lLiANCg0KLSB4OiBkYXRhIGZyYW1lDQotIGxpc3RmbmFtZTogYSBsaXN0IG9mIHRoZSB2YXJpYWJsZXMgdG8gYmUgY2VudGVyZWQgKGUuZy4gbGlzdCh2YXJpYWJsZTEsdmFyaWFibGUyKSkNCg0KVGhlIG91dHB1dCBpcyBhIGNvcHkgb2YgdGhlIGRhdGEgZnJhbWUgd2l0aCBhIGNvbHVtbiAoYWx3YXlzIGEgbnVtZXJpYyB2YXJpYWJsZSkgYWRkZWQgZm9yIGVhY2ggb2YgdGhlIGNlbnRlcmVkIHZhcmlhYmxlcy4gVGhlc2UgY29sdW1ucyBhcmUgbGFiZWxsZWQgd2l0aCB0aGUgZWFjaCBjb2x1bW4ncyBwcmV2aW91cyBuYW1lLCBidXQgd2l0aCAiLmN0IiBhcHBlbmRlZCAoZS5nLiwgInZhcmlhYmxlMSIgd2lsbCBiZWNvbWUgInZhcmlhYmxlMS5jdCIpLg0KDQoNCmBgYHtyfQ0KbGl6Q2VudGVyPSBmdW5jdGlvbih4LCBsaXN0Zm5hbWUpIA0Kew0KCWZvciAoaSBpbiAxOmxlbmd0aChsaXN0Zm5hbWUpKSANCgl7DQoJCWZuYW1lID0gYXMuY2hhcmFjdGVyKGxpc3RmbmFtZVtpXSkNCgkJeFtwYXN0ZShmbmFtZSwiLmN0Iiwgc2VwPSIiKV0gPSBteUNlbnRlcih4W2ZuYW1lXSkNCgl9DQoJCQ0KCXJldHVybih4KQ0KfQ0KYGBgCQ0KDQoNCiAgDQoNCiMjIyBnZXRfY29lZmZzDQoNClRoaXMgZnVuY3Rpb24gYWxsb3dzIHVzIHRvIGluc3BlY3QgcGFydGljdWxhciBjb2VmZmljaWVudHMgZnJvbSB0aGUgb3V0cHV0IG9mIGFuIGxtZSBtb2RlbCBieSBwdXR0aW5nIHRoZW0gaW4gdGFibGUuDQoNCi0geDogdGhlIG91dHB1dCByZXR1cm5lZCB3aGVuIHJ1bm5pbmcgbG1lciBvciBnbG1lciAoaS5lLiBhbiBvYmpldCBvZiB0eXBlIGxtZXJNb2Qgb3IgZ2xtZXJNb2QpDQotIGxpc3Q6IGEgbGlzdCBvZiBuYW1lcyBvZiB0aGUgY29lZmZpY2llbnRzIHRvIGJlIGV4dHJhY3RlZCAoZS5nLiBjKCJ2YXJpYWJsZTEiLCJ2YXJpYWJsZTE6dmFyaWFibGUyIikpDQoNCmBgYHtyfQ0KI2dldF9jb2VmZnMgPC0gZnVuY3Rpb24oeCxsaXN0KXsoa2FibGUoYXMuZGF0YS5mcmFtZShzdW1tYXJ5KHgpJGNvZWZmaWNpZW50cylbbGlzdCxdLGRpZ2l0cz0zKSl9DQpnZXRfY29lZmZzIDwtIGZ1bmN0aW9uKHgsbGlzdCl7KGFzLmRhdGEuZnJhbWUoc3VtbWFyeSh4KSRjb2VmZmljaWVudHMpW2xpc3QsXSl9DQpgYGAgIA0KDQojIyMgQmYNCg0KVGhpcyBmdW5jdGlvbiBpcyBlcXVpdmFsZW50IHRvIHRoZSBEaWVuZXMgKDIwMDgpIGNhbGN1bGF0b3Igd2hpY2ggY2FuIGJlIGZvdW5kIGhlcmU6IGh0dHA6Ly93d3cubGlmZXNjaS5zdXNzZXguYWMudWsvaG9tZS9ab2x0YW5fRGllbmVzL2luZmVyZW5jZS9CYXllcy5odG0uDQoNClRoZSBjb2RlIHdhcyBwcm92aWRlZCBieSBCYWd1ZWx5IGFuZCBLYXluZSAoMjAxMCkgYW5kIGNhbiBiZSBmb3VuZCBoZXJlOiBodHRwOi8vd3d3LmFjYWRlbWlhLmVkdS80MjcyODgvUmV2aWV3X29mX1VuZGVyc3RhbmRpbmdfcHN5Y2hvbG9neV9hc19hX3NjaWVuY2VfQW5faW50cm9kdWN0aW9uX3RvX3NjaWVudGlmaWNfYW5kX3N0YXRpc3RpY2FsX2luZmVyZW5jZQ0KDQpgYGB7cn0NCkJmPC1mdW5jdGlvbihzZCwgb2J0YWluZWQsIHVuaWZvcm0sIGxvd2VyPTAsIHVwcGVyPTEsIG1lYW5vZnRoZW9yeT0wLHNkdGhlb3J5PTEsIHRhaWw9Mil7DQogYXJlYSA8LSAwDQogaWYoaWRlbnRpY2FsKHVuaWZvcm0sIDEpKXsNCiAgdGhldGEgPC0gbG93ZXINCiAgcmFuZ2UgPC0gdXBwZXIgLSBsb3dlcg0KICBpbmNyIDwtIHJhbmdlIC8gMjAwMA0KICBmb3IgKEEgaW4gLTEwMDA6MTAwMCl7DQogICAgIHRoZXRhIDwtIHRoZXRhICsgaW5jcg0KICAgICBkaXN0X3RoZXRhIDwtIDEgLyByYW5nZQ0KICAgICBoZWlnaHQgPC0gZGlzdF90aGV0YSAqIGRub3JtKG9idGFpbmVkLCB0aGV0YSwgc2QpDQogICAgIGFyZWEgPC0gYXJlYSArIGhlaWdodCAqIGluY3INCiAgfQ0KIH1lbHNlDQogICB7dGhldGEgPC0gbWVhbm9mdGhlb3J5IC0gNSAqIHNkdGhlb3J5DQogICAgaW5jciA8LSBzZHRoZW9yeSAvIDIwMA0KICAgIGZvciAoQSBpbiAtMTAwMDoxMDAwKXsNCiAgICAgIHRoZXRhIDwtIHRoZXRhICsgaW5jcg0KICAgICAgZGlzdF90aGV0YSA8LSBkbm9ybSh0aGV0YSwgbWVhbm9mdGhlb3J5LCBzZHRoZW9yeSkNCiAgICAgIGlmKGlkZW50aWNhbCh0YWlsLCAxKSl7DQogICAgICAgIGlmICh0aGV0YSA8PSAwKXsNCiAgICAgICAgICBkaXN0X3RoZXRhIDwtIDANCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBkaXN0X3RoZXRhIDwtIGRpc3RfdGhldGEgKiAyDQogICAgICAgIH0NCiAgICAgIH0NCiAgICAgIGhlaWdodCA8LSBkaXN0X3RoZXRhICogZG5vcm0ob2J0YWluZWQsIHRoZXRhLCBzZCkNCiAgICAgIGFyZWEgPC0gYXJlYSArIGhlaWdodCAqIGluY3INCiAgICB9DQogfQ0KIExpa2VsaWhvb2RUaGVvcnkgPC0gYXJlYQ0KIExpa2VsaWhvb2RudWxsIDwtIGRub3JtKG9idGFpbmVkLCAwLCBzZCkNCiBCYXllc0ZhY3RvciA8LSBMaWtlbGlob29kVGhlb3J5IC8gTGlrZWxpaG9vZG51bGwNCiByZXQgPC0gbGlzdCgiTGlrZWxpaG9vZFRoZW9yeSIgPSBMaWtlbGlob29kVGhlb3J5LCJMaWtlbGlob29kbnVsbCIgPSBMaWtlbGlob29kbnVsbCwgIkJheWVzRmFjdG9yIiA9IEJheWVzRmFjdG9yKQ0KIHJldA0KfSANCmBgYA0KDQojIyMgQmZfcG93ZXJjYWxjDQoNClRoaXMgd29ya3Mgd2l0aCB0aGUgQmYgZnVuY2l0b24gYWJvdmUuIEl0IHJlcXVpcmVzIHRoZSBzYW1lIHZhbHVlcyBhcyB0aGF0IGZ1bmN0aW9uIChpLmUuIHRoZSBvYnRhaW5lZCBtZWFuIGFuZCBTRSBmb3IgdGhlIGN1cnJlbnQgc2FtcGxlLCBhIHZhbHVlIGZvciB0aGUgcHJlZGljdGVkIG1lYW4sIHdoaWNoIGlzIHNldCB0byBiZSBzZHRoZW9yeSAod2l0aCBtZWFub2Z0aGVvcnk9MCksIGFuZCB0aGUgY3VycmVudCBudW1iZXIgb2YgcGFydGljaXBhbnRzIE4pLiBIb3dldmVyIHJhdGhlciB0aGFuIHJldHVybiBhIEJGIGZvciB0aGUgY3VycmVudCBzYW1wbGUsIGl0IHdvcmtzIG91dCB3aGF0IHRoZSBCRiB3b3VsZCBiZSBmb3IgYSByYW5nZSBvZiBkaWZmZXJlbnQgc3ViamVjdCBudW1iZXJzIChhc3N1bWluZyB0aGF0IHRoZSBTRSBzY2FsZXMgd2l0aCBzcXJ0KE4pKSwgDQoNCmBgYHtyfQ0KQmZfcG93ZXJjYWxjPC1mdW5jdGlvbihzZCwgb2J0YWluZWQsIHVuaWZvcm0sIGxvd2VyPTAsIHVwcGVyPTEsIG1lYW5vZnRoZW9yeT0wLCBzZHRoZW9yeT0xLCB0YWlsPTIsIE4sIG1pbiwgbWF4KQ0Kew0KIA0KIHggPSBjKDApDQogeSA9IGMoMCkNCiAgICMgbm90ZTogd29ya2luZyBvdXQgd2hhdCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIE4gYW5kIGRmIGlzIChmb3IgdGhlIGNvbnRyYXN0IGJldHdlZW4gdHdvIGdyb3VwcywgdGhpcyBpcyAyOyBmb3IgY29uc3RyYWludHMgd2hlcmUgdGhlcmUgaXMgNCBncm91cHMgdGhpcyB3aWxsIGJlIDMsIGV0Yy4pICANCg0KIGZvcihuZXdOIGluIG1pbiA6IG1heCkNCiB7DQogIEIgPSBhcy5udW1lcmljKEJmKHNkID0gc2Qqc3FydChOL25ld04pLCBvYnRhaW5lZCwgdW5pZm9ybSwgbG93ZXIsIHVwcGVyLCBtZWFub2Z0aGVvcnksIHNkdGhlb3J5LCB0YWlsKVszXSkNCiAgeD0gYXBwZW5kKHgsbmV3TikgIA0KICB5PSBhcHBlbmQoeSxCKQ0KICBvdXRwdXQgPSBjYmluZCh4LHkpDQogIA0KIH0gDQogb3V0cHV0ID0gb3V0cHV0Wy0xLF0gDQogcmV0dXJuKG91dHB1dCkgDQp9DQpgYGANCg0KDQoNCg0KDQoNCiMgVHJhaW5pbmcNCg0KRFY6IEVhY2ggdHJhaW5pbmcgdHJpYWwgcHJvZHVjZXMgYSBkYXRhIHBvaW50IChkaWQgdGhleSBwaWNrIHRoZSBjb3JyZWN0IHBpY3R1cmUgLSAxLzA7IG5vdGUgdGhleSBnZXQgZmVlZGJhY2sgb24gdGhpcykgDQoNCiMjIGxvYWQgdXAgYW5kIHJ1biBsbWVzIG9uIHJlbGV2YW50IHBpbG90IGRhdGENCg0KVGhlIGNoaWxkIGRhdGEgYmVsb3cgY29tZSBmcm9tIGEgdHdvIHNlc3Npb24gc3R1ZHkgd2hlcmUgdGhleSB3ZXJlIHRyYWluZWQgb24gc3RpbXVsaSBzaW1pbGFyIHRvIHRoZSAicGljdHVyZS1vbmx5IiBjb25kaXRpb24gaW4gdGhlIGN1cnJlbnQgc3R1ZHkuDQpXZSBoYXZlIGRhdGEgZnJvbSBib3RoIDcgeWVhciBvbGRzIGFuZCAxMSB5ZWFyIG9sZHM7IHRoZSAxMSB5ZWFyIG9sZCBkYXRhIGhlcmUgYXJlIHJlbGV2YW50IGluIHByb3ZpZGluZyBhbiBlc3RpbWF0ZSB0aGF0IGNhbiBiZSB1c2VkIHRvIGluZm9ybSBIMSBpbiBvdXIgQkYgZXhhbXBsZSBhbmFseXNlcy4NCg0KVGhlIGFkdWx0ICBkYXRhIGJlbG93IGNvbWUgZnJvbSBhIHR3byBzZXNzaW9uIHN0dWR5IHdoZXJlIHRoZXJlIHdlcmUgdHdvIGNvbmRpdGlvbnM6ICgxKSB0cmFpbmVkIG9uIHN0aW11bGkgc2ltaWxhciB0byB0aGUgInBpY3R1cmUtb25seSIgY29uZGl0aW9uIGluIHRoZSBjdXJyZW50IHN0dWR5ICgyKSB0cmFpbmVkIG9uIHBpY3R1cmVzIEpVU1Qgb2YgdGhlIGRpYWNyaXRpY3MuIFRoaXMgaXMgdXNlZnVsIGZvciBjb25zaWRlcmluZyBwb3NzaWJsZSBlZmZlY3RzIG9mIGNvbmRpdGlvbiBpbiB0aGUgZGF0YSAodGhvdWdoIHdpdGggdGhlIGNhdmVhdCB0aGF0IGNvbXBhcmlzb24gaXMgc29tZXdoYXQgZGlmZmVyZW50KS4NCg0KTm90ZTogdG9uZWNvbnRyYXN0IGlzIGZpeGVkIGVmZmVjdCB3aXRoIDYgbGV2ZWxzIChzaXggcG9zc2libGUgY29udHJhc3RzKS4gSXQgaXMgZXhwZWN0ZWQgdG8gY29udHJpYnV0ZSB0byBtb2RlbCBhbmQgaXMgdGh1cyBpbmNsdWRlZCBidXQgaXNuJ3Qgb2Ygc3BlY2lmaWMgaW50ZXJlc3QuDQoNCmBgYHtyfQ0KY2hpbGQudHJhaW4gPSByZWFkLmNzdigia2lkc3RyYWluX2NsZWFuLmNzdiIpDQphZHVsdC50cmFpbiA9IHJlYWQuY3N2ICgiYWR1bHRzdHJhaW5fY2xlYW4uY3N2IikNCmNoaWxkLnRyYWluJGFnZWdyb3VwID0gcmVsZXZlbChjaGlsZC50cmFpbiRhZ2Vncm91cCwgcmVmPSI3eWVhcnMiKQ0KYWR1bHQudHJhaW4kY29uZGl0aW9uID0gcmVsZXZlbChhZHVsdC50cmFpbiRjb25kaXRpb24sIHJlZj0iaSIpDQpgYGANCg0KYGBge3J9DQoNCmNoaWxkLnRyYWluLjcgPSBzdWJzZXQoY2hpbGQudHJhaW4sIGFnZWdyb3VwID09ICI3eWVhcnMiKQ0KY2hpbGQudHJhaW4uNyA8LSBsaXpDZW50ZXIoY2hpbGQudHJhaW4uNywgbGlzdCgic2Vzc2lvbiIsICJ0b25lY29udHJhc3QiKSkNCg0KY2hpbGQudHJhaW4uNy5tb2QgID0gZ2xtZXIgKHJlc3VsdCB+DQogICAgICAgICAgICAgICAgKyBzZXNzaW9uLmN0IA0KICAgICAgICAgICAgICAgICsgdG9uZWNvbnRyYXN0LmN0DQogICAgICAgICAgICAgICAgKyAoc2Vzc2lvbi5jdHxzdWJqZWN0KSwNCiAgICAgICAgICAgICAgICBkYXRhID0gY2hpbGQudHJhaW4uNywgIGZhbWlseSA9IGJpbm9taWFsLCBjb250cm9sPWdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIikpDQoNCg0Kcm91bmQoc3VtbWFyeShjaGlsZC50cmFpbi43Lm1vZCkkY29lZmZpY2llbnRzLDMpDQpgYGANCg0KDQpgYGB7cn0NCg0KY2hpbGQudHJhaW4uMTEgPSBzdWJzZXQoY2hpbGQudHJhaW4sIGFnZWdyb3VwID09ICIxMXllYXJzIikNCmNoaWxkLnRyYWluLjExIDwtIGxpekNlbnRlcihjaGlsZC50cmFpbi4xMSwgbGlzdCgic2Vzc2lvbiIsICJ0b25lY29udHJhc3QiKSkNCg0KY2hpbGQudHJhaW4uMTEubW9kICA9IGdsbWVyIChyZXN1bHQgfg0KICAgICAgICAgICAgICAgICsgc2Vzc2lvbi5jdCANCiAgICAgICAgICAgICAgICArIHRvbmVjb250cmFzdC5jdA0KICAgICAgICAgICAgICAgICsgKHNlc3Npb24uY3R8c3ViamVjdCksDQogICAgICAgICAgICAgICAgZGF0YSA9IGNoaWxkLnRyYWluLjExLCAgZmFtaWx5ID0gYmlub21pYWwsIGNvbnRyb2w9Z2xtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiKSkNCg0KDQpyb3VuZChzdW1tYXJ5KGNoaWxkLnRyYWluLjExLm1vZCkkY29lZmZpY2llbnRzLDMpDQpgYGANCg0KDQpgYGB7cn0NCg0KYWR1bHQudHJhaW4gPC0gbGl6Q2VudGVyKGFkdWx0LnRyYWluLCBsaXN0KCJzZXNzaW9uIiwgInRvbmVjb250cmFzdCIsImNvbmRpdGlvbiIpKQ0KDQphZHVsdC50cmFpbi5tb2QgID0gZ2xtZXIgKHJlc3VsdCB+DQogICAgICAgICAgICAgICAgKyBzZXNzaW9uLmN0ICpjb25kaXRpb24uY3QNCiAgICAgICAgICAgICAgICArIHRvbmVjb250cmFzdC5jdA0KICAgICAgICAgICAgICAgICsgKHNlc3Npb24uY3R8c3ViamVjdCksDQogICAgICAgICAgICAgICAgZGF0YSA9IGFkdWx0LnRyYWluLCAgZmFtaWx5ID0gYmlub21pYWwsIGNvbnRyb2w9Z2xtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiKSkNCg0KDQpyb3VuZChzdW1tYXJ5KGFkdWx0LnRyYWluLm1vZCkkY29lZmZpY2llbnRzLDMpDQpgYGANCg0KIyMgUHJlZGljdGlvbjE6IENoaWxkcmVuIHdpbGwgc2hvdyBvdmVyYWxsIGFib3ZlIGNoYW5jZSBwZXJmb3JtYW5jZSBhY3Jvc3MgdHJhaW5pbmcgaW4gYm90aCBjb25kaXRpb24xIGFuZCBjb25kaXRpb24yDQojIyMgQmFzZWQgb246IA0KDQpXZSBzYXcgdGhpcyBpbiB0aGUgcGlsb3QgZGF0YSBmcm9tIHNldmVuIHllYXIgb2xkcyBhYm92ZSwgd2hpY2ggd2FzIGluIGEgY29uZGl0aW9uIGxpa2UgdGhlIHBpY3R1cmVzLW9ubHkgY29uZGl0aW9uLg0KVGhlIHBpY3R1cmVzK3RvbmVzIGNvbmRpdGlvbiBjb250YWlucyB0aGUgc2FtZSBpbmZvcm1hdGlvbiAocGx1cyBzb21lIGFkZGl0aW9uYWwpIHNvIHdlIHByZWRpY3QgKGF0IGxlYXN0IC0gc2VlIGJlbG93KSBhYm92ZSBjaGFuY2UgaGVyZSB0b28uIA0KDQptZWFuOiBgciBwYXN0ZShyb3VuZChtZWFuKGNoaWxkLnRyYWluLjckcmVzdWx0KSwzKSAqMTAwLCAiJSIsIHNlcD0iIilgOw0KbG9nIG9kZHMgKGJldGEgZnJvbSBsbWUpOiBgciBzdW1tYXJ5KGNoaWxkLnRyYWluLjcubW9kKSRjb2VmZmljaWVudHNbIihJbnRlcmNlcHQpIiAsIkVzdGltYXRlIl1gOw0Kb2RkcyAgKGV4cChiZXRhKSk6YHIgZXhwKHN1bW1hcnkoY2hpbGQudHJhaW4uNy5tb2QpJGNvZWZmaWNpZW50c1siKEludGVyY2VwdCkiICwiRXN0aW1hdGUiXSlgOw0KDQojIyMgUGxhbm5lZCBBbmFseXNlczogRnJlcXVlbnRpc3QgDQoNCmxtZSBtb2RlbCBzaW1pbGFyIHRvIHRoYXQgb24gcGlsb3QgZGF0YSBhYm92ZSBidXQgd2l0aCBkYXRhIGZyb20gYm90aCBjb25kaXRpb25zOyBGaXQgc2VwYXJhdGUgaW50ZXJjZXB0cyBmb3IgZWFjaCBjb25kaXRpb24gYW5kIGNvbXBhcmUgZWFjaCB0byBjaGFuY2UgPSA1MCAoaS5lLmRlZmF1bHQgdmFsdWUgcmV0dXJuZWQpLiBOb3RlIHRoYXQgc2luY2UgYWxsIHByZWRpY3RvcnMgYXJlIGNlbnRlcmVkIGludGVyY2VwdCByZWxmZWN0cyBvdmVyYWxsIGF2ZXJhZ2UgKHJhdGhlciB0aGFuIGF0IGJhc2VsZXZlbHMgb2YgYSBmYWN0b3IpLiANCg0KV2Ugd2lsbCBkbyB0aGlzIGJvdGggZm9yIGEgbW9kZWwgd2l0aCBqdXN0IGZpcnN0IHR3byBzZXNzaW9ucyBhbmQgZm9yIGEgbW9kZWwgd2l0aCBhbGwgZGF0YSAod2l0aCBzZXNzaW9uIHRoZW4gaGF2aW5nIGZvdXIgcG9zc2libGUgdmFsdWVzIGFuZCBjb2RlZCBhcyBjZW50ZXJlZCBudW1lcmljYWwgZmFjdG9yKS4NCg0KIyMjIFBsYW5uZWQgQW5hbHlzZXM6IEJGIA0KDQpTdW1tYXJ5IG9mIGRhdGEgZm9yIGVhY2ggY29uZGl0aW9uOiBtZWFuIGFuZCBzZSBmb3IgaW50ZXJlY3B0IGZyb20gbG1lOw0KdmFsdWUgdG8gaW5mb3JtIEgxOiBlc3RpbWF0ZSBmcm9tIGFib3ZlIHBpbG90IGRhdGEgZm9yIHNldmVuIHllYXIgb2xkcyAgYHIgc3VtbWFyeShjaGlsZC50cmFpbi43Lm1vZCkkY29lZmZpY2llbnRzWyJzZXNzaW9uLmN0IiAsIkVzdGltYXRlIl1gDQoNCk5PVEU6IElmIChlLmcuKSB3ZSBmaW5kIGFuIGVmZmVjdCBmb3IgY29uZGl0aW9uMSwgd2UgY2FuIGFsc28gdXNlIHRoZSBlc3RpbWF0ZSBmb3IgaW50ZXJjZXB0IGZvciB0aGF0IHRvIGluZm9ybSBIMSB3aGVuIGxvb2tpbmcgYXQgZGF0YSBmcm9tIGNvbmRpdGlvbjI7IGFuZCB2aWNlIHZlcnNhLiBUaGlzIGlzIGEgYmV0dGVyIGVzdGltYXRlIHNpbmNlIHRoZSBjb25kaXRpb25zIGFyZSBtb3JlIGNsb3NlbHkgbWF0Y2hlZCB0byBlYWNoIG90aGVyIHRoYW4gZWl0aGVyIGlzIHRvIHRoZSBwaWxvdCBkYXRhLw0KDQojIyMgUmVxdWlyZWQgc2FtcGxlIGFuYWx5c2VzDQojIyMjIEZyZXF1ZW50aXN0cyBwb3dlcg0KDQpMb29rIGF0IHNhbXBsZSByZXF1aXJlZCB0byBvYnRhaW4gZGlmZmVyZW50IGxldmVscyBvZiBwb3dlciB3aXRoIHBpbG90IGRhdGEgd2l0aCA3IHllYXIgb2xkczogDQoNCg0KYGBge3J9DQpkYXRhUz1hcy5udW1lcmljKHdpdGgoZHJvcGxldmVscyhjaGlsZC50cmFpbi43KSwgdGFwcGx5KHJlc3VsdCxsaXN0KHN1YmplY3QpLCBtZWFuLCBuYS5ybT1UKSkpDQpkPSBjb2hlbnNEKHggPSBkYXRhUywgbXU9MC41KQ0KDQpwd3IudC50ZXN0KG4gPSBOVUxMLCBkID0gZCwgc2lnLmxldmVsID0gMC4wNSwgcG93ZXIgPSAuOSwgIHR5cGUgPSBjKCJvbmUuc2FtcGxlIiksIGFsdGVybmF0aXZlID0gYyggImdyZWF0ZXIiKSkNCnB3ci50LnRlc3QobiA9IE5VTEwsIGQgPSBkLCBzaWcubGV2ZWwgPSAwLjA1LCBwb3dlciA9IC44LCAgdHlwZSA9IGMoIm9uZS5zYW1wbGUiKSwgYWx0ZXJuYXRpdmUgPSBjKCAiZ3JlYXRlciIpKQ0KcHdyLnQudGVzdChuID0gTlVMTCwgZCA9IGQsIHNpZy5sZXZlbCA9IDAuMDUsIHBvd2VyID0gLjcsICB0eXBlID0gYygib25lLnNhbXBsZSIpLCBhbHRlcm5hdGl2ZSA9IGMoICJncmVhdGVyIikpDQpybShkYXRhUykNCnJtKGQpDQpgYGANCg0KDQoNCiMjIyMgUmVxdWlyZWQgc2FtcGxlIGZvciBCRiBhbmFseXNlczogDQoNCkhlcmUsIHdlIGxvb2sgYXQgdGhlIHBpbG90IGRhdGEgZnJvbSBzZXZlbiB5ZWFyIG9sZHMsIHVzaW5nIEgxIGluZm9ybWVkIGJ5IGVzdGltYXRlIGZvciAxMSB5ZWFyIG9sZHMuIEluIG91ciBhY3R1YWwgYW5hbHN5ZXMgd2l0aCBuZXcgZGF0YSBmb3IgNyB5ZWFyIG9sZHMgd2lsbCBiZSB1c2luZyBlc3RpbWF0ZSBmcm9tIGN1cnJlbnQgcGlsb3QgZGF0YSB3aXRoIDcgeWVhciBvbGRzICB0byBpbmZvcm0gSDENCg0KYGBge3J9DQoNCm1lYW5CRiA9IHN1bW1hcnkoY2hpbGQudHJhaW4uNy5tb2QpJGNvZWZmaWNpZW50c1siKEludGVyY2VwdCkiICwiRXN0aW1hdGUiXQ0Kc2VCRiA9IHN1bW1hcnkoY2hpbGQudHJhaW4uNy5tb2QpJGNvZWZmaWNpZW50c1siKEludGVyY2VwdCkiICwiU3RkLiBFcnJvciJdDQpoMW1lYW4gPSBzdW1tYXJ5KGNoaWxkLnRyYWluLjExLm1vZCkkY29lZmZpY2llbnRzWyIoSW50ZXJjZXB0KSIgLCJFc3RpbWF0ZSJdDQoNCkJmKHNlQkYsIG1lYW5CRiwgIHVuaWZvcm0gPTAsbWVhbm9mdGhlb3J5PTAsc2R0aGVvcnk9aDFtZWFuLHRhaWw9MSkNCg0Kcm0obWVhbkJGKQ0Kcm0oc2VCRikNCg0KYGBgDQoNCldlIGNvdWxkIHJlamVjdCBIMCB3aXRoIHRoZSBjdXJyZW50IHNhbXBsZSBvZiBOPTE1Lg0KDQojIyBQcmVkaWN0aW9uMjogSW1wcm92ZW1lbnQgd2l0aCBzZXNzaW9uIGluIGVhY2ggY29uZGl0aW9uDQojIyMgQmFzZWQgb246IA0KDQpXZSBzYXcgdGhpcyBpbiA3IHllYXIgb2xkcyBpbiBwcmV2aW91cyBzdHVkeS4NCg0KNyB5ZWFyIG9sZHMgbWVhbnMgOiBgciByb3VuZCggd2l0aChjaGlsZC50cmFpbi43LCB0YXBwbHkocmVzdWx0LCBzZXNzaW9uLCBtZWFuLCBuYS5ybT1UKSkgLDIpYA0KNyB5ZWFyIG9sZHMgbG9nIG9kZHMgKGJldGEgZnJvbSBsbWUpOiBgciBzdW1tYXJ5KGNoaWxkLnRyYWluLjcubW9kKSRjb2VmZmljaWVudHNbInNlc3Npb24uY3QiICwiRXN0aW1hdGUiXWANCjcgeWVhciBvbGQgb2RkICAoZXhwKGJldGEpKWByIGV4cChzdW1tYXJ5KGNoaWxkLnRyYWluLjcubW9kKSRjb2VmZmljaWVudHNbInNlc3Npb24uY3QiICwiRXN0aW1hdGUiXSlgDQoNCiMjIyBQbGFubmVkIEFuYWx5c2VzOiBGcmVxdWVudGlzdCANCg0KbG1lIG1vZGVsIHNpbWlsYXIgdG8gdGhhdCBvbiBwaWxvdCBkYXRhIGFib3ZlIGJ1dCB3aXRoIGRhdGEgZnJvbSBib3RoIGNvbmRpdGlvbnM7IEZpdCBzZXBhcmF0ZSBzbG9wZXMgZm9yIHNlc3Npb24gZm9yIGVhY2ggY29uZGl0aW9uLiANCldlIHdpbGwgZG8gdGhpcyBib3RoIGZvciBhIG1vZGVsIHdpdGgganVzdCBmaXJzdCB0d28gc2Vzc2lvbnMgYW5kIGZvciBhIG1vZGVsIHdpdGggYWxsIGRhdGEuDQoNCiMjIyBQbGFubmVkIEFuYWx5c2VzOiBCRiANCg0KU3VtbWFyeSBvZiBkYXRhIGZvciBlYWNoIGNvbmRpdGlvbjogbWVhbiBhbmQgc2UgZm9yIHNlc3Npb24uY3QgZm9yIGVhY2ggbGV2ZWwgb2YgY29uZGl0aW9uIGZyb20gbG1lDQp2YWx1ZSB0byBpbmZvcm0gSDE6IGVzdGltYXRlIGZyb20gYWJvdmUgcGlsb3QgZGF0YSBmb3Igc2V2ZW4geWVhciBvbGRzICBgciBzdW1tYXJ5KGNoaWxkLnRyYWluLjcubW9kKSRjb2VmZmljaWVudHNbInNlc3Npb24uY3QiICwiRXN0aW1hdGUiXWANCg0KSWYgaXQgYXBwZWFycyB0aGF0ICBvbmUgb2YgdGhlIGNvbmRpdGlvbnMgKGMxKSBzaG93cyBhIHBvc2l0aXZlIGVmZmVjdCBvZiBzZXNzaW9uIGFuZCBvbmUgZG9lc24ndCAoYzIpLCB3ZSBjYW4gYWxzbyBkbyBCRiBhbmFsc3llcyBmb3IgYzIgZGF0YSB3aXRoICBIMSBpbmZvcm1lZCBieSBlc3RpbWF0ZSBmcm9tICBjMSAodGhpcyBpcyBhIGJldHRlciBlc3RpbWF0ZSB0aGFuIHRoZSBwaWxvdCBzaW5jZSB0aGUgY29uZGl0aW9ucyBhcmUgbW9yZSBjbG9zZWx5IG1hdGNoZWQgdG8gZWFjaCBvdGhlciB0aGFuIGVpdGhlciBpcyB0byB0aGUgcGlsb3QgZGF0YSkNCg0KDQoNCiMjIyBSZXF1aXJlZCBzYW1wbGUgYW5hbHlzZXMNCiMjIyMgRnJlcXVlbnRpc3RzIHBvd2VyDQoNCmBgYHtyfQ0KZGF0YVMgPSB3aXRoKGRyb3BsZXZlbHMoY2hpbGQudHJhaW4uNyksIHRhcHBseShyZXN1bHQsbGlzdChzdWJqZWN0LHNlc3Npb24pLCBtZWFuLCBuYS5ybT1UKSkNCmQ9IGNvaGVuc0QoeCA9IGRhdGFTWywxXSwgeSA9IGRhdGFTWywyXSwgbWV0aG9kID0gInBhaXJlZCIpDQoNCnB3ci50LnRlc3QobiA9IE5VTEwsIGQgPSBkLCBzaWcubGV2ZWwgPSAwLjA1LCBwb3dlciA9IC45LCAgdHlwZSA9IGMoInBhaXJlZCIpLCBhbHRlcm5hdGl2ZSA9IGMoICJncmVhdGVyIikpDQoNCnJtKGRhdGFTKQ0Kcm0oZCkNCmBgYA0KDQpgYGB7cn0NCmRhdGFTID0gd2l0aChkcm9wbGV2ZWxzKGNoaWxkLnRyYWluLjcpLCB0YXBwbHkocmVzdWx0LGxpc3Qoc3ViamVjdCxzZXNzaW9uKSwgbWVhbiwgbmEucm09VCkpDQpkPSBjb2hlbnNEKHggPSBkYXRhU1ssMV0sIHkgPSBkYXRhU1ssMl0sIG1ldGhvZCA9ICJwYWlyZWQiKQ0KDQpwd3IudC50ZXN0KG4gPSBOVUxMLCBkID0gZCwgc2lnLmxldmVsID0gMC4wNSwgcG93ZXIgPSAuOCwgIHR5cGUgPSBjKCJwYWlyZWQiKSwgYWx0ZXJuYXRpdmUgPSBjKCAiZ3JlYXRlciIpKQ0KDQpybShkYXRhUykNCnJtKGQpDQpgYGANCg0KYGBge3J9DQpkYXRhUyA9IHdpdGgoZHJvcGxldmVscyhjaGlsZC50cmFpbi43KSwgdGFwcGx5KHJlc3VsdCxsaXN0KHN1YmplY3Qsc2Vzc2lvbiksIG1lYW4sIG5hLnJtPVQpKQ0KZD0gY29oZW5zRCh4ID0gZGF0YVNbLDFdLCB5ID0gZGF0YVNbLDJdLCBtZXRob2QgPSAicGFpcmVkIikNCg0KcHdyLnQudGVzdChuID0gTlVMTCwgZCA9IGQsIHNpZy5sZXZlbCA9IDAuMDUsIHBvd2VyID0gLjcsICB0eXBlID0gYygicGFpcmVkIiksIGFsdGVybmF0aXZlID0gYyggImdyZWF0ZXIiKSkNCg0Kcm0oZGF0YVMpDQpybShkKQ0KYGBgDQoNCg0KDQojIyMjIFJlcXVpcmVkIHNhbXBsZSBmb3IgQkYgYW5hbHlzZXM6IA0KDQpBcyBmb3IgcHJlZGljdGlvbiAxLCB3ZSBhZ2FpbiBsb29rIGF0IHRoZSBwaWxvdCBkYXRhIGZyb20gc2V2ZW4geWVhciBvbGRzLCB1c2luZyBIMSBpbmZvcm1lZCBieSBlc3RpbWF0ZSBmb3IgMTEgeWVhciBvbGRzLiBJbiBvdXIgYWN0dWFsIGFuYWxzeWVzIHdpbGwgYmUgdXNpbmcgZXN0aW1hdGUgZnJvbSB0aGUgcGlsb3QgIGRhdGEgdG8gaW5mb3JtIEgxLg0KDQoNCmBgYHtyfQ0KDQptZWFuQkYgPSBzdW1tYXJ5KGNoaWxkLnRyYWluLjcubW9kKSRjb2VmZmljaWVudHNbInNlc3Npb24uY3QiICwiRXN0aW1hdGUiXQ0Kc2VCRiA9IHN1bW1hcnkoY2hpbGQudHJhaW4uNy5tb2QpJGNvZWZmaWNpZW50c1sic2Vzc2lvbi5jdCIgLCJTdGQuIEVycm9yIl0NCmgxbWVhbiA9IHN1bW1hcnkoY2hpbGQudHJhaW4uMTEubW9kKSRjb2VmZmljaWVudHNbInNlc3Npb24uY3QiICwiRXN0aW1hdGUiXQ0KDQpCZihzZUJGLCBtZWFuQkYsICB1bmlmb3JtID0wLG1lYW5vZnRoZW9yeT0wLHNkdGhlb3J5PWgxbWVhbix0YWlsPTEpDQoNCnJtKG1lYW5CRikNCnJtKHNlQkYpDQoNCmBgYA0KDQpXZSBoYXZlIHN1ZmZpY2llbnQgZXZpZGVuY2UgdG8gYWNjZXB0IEgxIG92ZXIgSDAgb24gYmFzaXMgb2YgY3VycmVudCBzYW1wbGUuDQoNCg0KIyMgUHJlZGljdGlvbjM6IEdyZWF0ZXIgcGVyZm9ybWFuY2UgaW4gcGljdHVyZStkaWFjcml0aWMgY29uZGl0aW9uIHdpdGgganVzdCBwaWN0dXJlIGNvbmRpdGlvbg0KIyMjIEJhc2VkIG9uOiANCg0KV2UgZG9uJ3QgaGF2ZSBhbnkgcGlsb3QgZGF0YSB3aXRoIHRoaXMgdHlwZSBvZiBtYW5pcHVsYXRpb24gZm9yIGNoaWxkcmVuLiANCg0KVGhpcyBwcmVkaWN0aW9uIGlzIG1hZGUgb24gdGhlIGJhc2lzIG9mIGEgcmVsYXRlZCBlZmZlY3Qgc2VlbiBpbiBhZHVsdCBkYXRhOiB0aGV5IHNob3dlZCBncmVhdGVyIG92ZXJhbGwgcGVyZm9ybWFuY2UgaW4gYSBjb25kaXRpb24gd2hlcmUgdGhleSBzYXcganVzdCBkaWFjcml0aWMgcmF0aGVyIHRoYW4ganVzdCBwaWN0dXJlLiBOb3RlIHRoYXQgaWNvbmNpdHkgbWVhbnMgeW91IGNhbiBwb3RlbnRpYWxseSByZXNwb25kIHdoZW4gdGhleSBhcmUgcHJlc2VudC4gSXQgaXMgcG9zc2libGUgdGhhdCAgaGF2aW5nIHRoZSBkaWFjcml0aWNzIHByZXNlbnQgd2lsbCBoZWxwIGNoaWxkcmVuIHRvbzsgdGhvdWdoIChhKSBjaGlsZHJlbiBjb3VsZCB3ZWxsIGJlIGRpZmZlcmVudCAoZGlhY3RyaXRpY3MgbWlnaHQgYmUgdG9vIGFic3RyYWN0KSAoYikgaXQgY291bGQgYmUgdGhhdCBoYXZpbmcgdGhlIHBpY3R1cmUgdGhlcmUgY2hhbmdlcyB0aGluZ3MpLiANCg0KTWVhbnMgZnJvbSB0aGUgcGlsb3Q6DQoNCmFkdWx0ICBtZWFucyA6IGByIHJvdW5kKCB3aXRoKGFkdWx0LnRyYWluLCB0YXBwbHkocmVzdWx0LCBjb25kaXRpb24sIG1lYW4sIG5hLnJtPVQpKSAsMilgDQphZHVsdCAgbG9nIG9kZHMgKGJldGEgZnJvbSBsbWUpOiBgciBzdW1tYXJ5KGFkdWx0LnRyYWluLm1vZCkkY29lZmZpY2llbnRzWyJjb25kaXRpb24uY3QiICwiRXN0aW1hdGUiXWANCmFkdWx0ICBvZGQgIChleHAoYmV0YSkpYHIgZXhwKHN1bW1hcnkoYWR1bHQudHJhaW4ubW9kKSRjb2VmZmljaWVudHNbInNlc3Npb24uY3QiICwiRXN0aW1hdGUiXSlgDQoNCg0KIyMjIFBsYW5uZWQgQW5hbHlzZXM6IEZyZXF1ZW50aXN0IA0KDQpsbWUgbW9kZWwgc2ltaWxhciB0byB0aGF0IG9uIHBpbG90IGRhdGEgYWJvdmUgYnV0IHdpdGggZGF0YSBmcm9tIGJvdGggY29uZGl0aW9uczsgbG9vayBmb3IgZml4ZWQgZWZmZWN0IG9mIGNvbmRpdGlvbg0KV2Ugd2lsbCBkbyB0aGlzIGJvdGggZm9yIGEgbW9kZWwgd2l0aCBqdXN0IGZpcnN0IHR3byBzZXNzaW9ucyBhbmQgZm9yIGEgbW9kZWwgd2l0aCBhbGwgZGF0YS4NCg0KIyMjIFBsYW5uZWQgQW5hbHlzZXM6IEJGIA0KDQpTdW1tYXJ5IG9mIGRhdGE6IG1lYW4gYW5kIHNlIGZvciBjb25kaXRpb24uY3QNCnZhbHVlIHRvIGluZm9ybSBIMTogZXN0aW1hdGUgZnJvbSBhYm92ZSBBRFVMVCBwaWxvdCBkYXRhICAgYHIgc3VtbWFyeShhZHVsdC50cmFpbi5tb2QpJGNvZWZmaWNpZW50c1siY29uZGl0aW9uLmN0IiAsIkVzdGltYXRlIl1gDQoNClRoZXJlIGlzIGEgY2F2ZWF0IGhlcmUgc2luY2UgdGhpcyB2YWx1ZSBjb21lcyBmcm9tIGFkdWx0cyBhbmQgd2lsbCBsaWtlbHkgb3ZlcmVzdGltYXRlIGFueSBkaWZmZXJlbmNlIGZvciBjaGlsZHJlbiAobWFraW5nIGl0IGEgY29uc2VydmF0aXZlIGVzdGltYXRlLCBiaWFzaW5nIGV2aWRlbmNlIGZvciBIMCkuIA0KDQojIyMgUmVxdWlyZWQgc2FtcGxlIGFuYWx5c2VzDQojIyMjIEZyZXF1ZW50aXN0cyBwb3dlcg0KDQpOT1RFOiB0aGlzIGlzIGJhc2VkIG9uIEFEVUxUIGRhdGEuIEl0IGxpa2VseSB1bmRlcmVzdGltYXRlcyB0aGUgcG93ZXIgcmVxdWlyZWQgdG8gc2VlIHRoaXMgZGlmZmVyZW5jZS4NCmBgYHtyfQ0KDQpkYXRhUyA9IHdpdGgoZHJvcGxldmVscyhhZHVsdC50cmFpbiksIHRhcHBseShyZXN1bHQsbGlzdChzdWJqZWN0LGNvbmRpdGlvbiksIG1lYW4sIG5hLnJtPVQpKQ0KZD0gY29oZW5zRCh4ID0gZGF0YVNbLDFdLCB5ID0gZGF0YVNbLDJdLCBtZXRob2QgPSAicG9vbGVkIikNCg0KcHdyLnQudGVzdChuID0gTlVMTCwgZCA9IGQsIHNpZy5sZXZlbCA9IDAuMDUsIHBvd2VyID0gLjksICB0eXBlID0gYygidHdvLnNhbXBsZSIpLCBhbHRlcm5hdGl2ZSA9IGMoICJncmVhdGVyIikpDQpybShkYXRhUykNCnJtKGQpDQpgYGANCg0KDQpgYGB7cn0NCg0KZGF0YVMgPSB3aXRoKGRyb3BsZXZlbHMoYWR1bHQudHJhaW4pLCB0YXBwbHkocmVzdWx0LGxpc3Qoc3ViamVjdCxjb25kaXRpb24pLCBtZWFuLCBuYS5ybT1UKSkNCmQ9IGNvaGVuc0QoeCA9IGRhdGFTWywxXSwgeSA9IGRhdGFTWywyXSwgbWV0aG9kID0gInBvb2xlZCIpDQoNCnB3ci50LnRlc3QobiA9IE5VTEwsIGQgPSBkLCBzaWcubGV2ZWwgPSAwLjA1LCBwb3dlciA9IC44LCAgdHlwZSA9IGMoInR3by5zYW1wbGUiKSwgYWx0ZXJuYXRpdmUgPSBjKCAiZ3JlYXRlciIpKQ0Kcm0oZGF0YVMpDQpybShkKQ0KYGBgDQoNCmBgYHtyfQ0KZGF0YVMgPSB3aXRoKGRyb3BsZXZlbHMoYWR1bHQudHJhaW4pLCB0YXBwbHkocmVzdWx0LGxpc3Qoc3ViamVjdCxjb25kaXRpb24pLCBtZWFuLCBuYS5ybT1UKSkNCmQ9IGNvaGVuc0QoeCA9IGRhdGFTWywxXSwgeSA9IGRhdGFTWywyXSwgbWV0aG9kID0gInBvb2xlZCIpDQoNCnB3ci50LnRlc3QobiA9IE5VTEwsIGQgPSBkLCBzaWcubGV2ZWwgPSAwLjA1LCBwb3dlciA9IC43LCAgdHlwZSA9IGMoInR3by5zYW1wbGUiKSwgYWx0ZXJuYXRpdmUgPSBjKCAiZ3JlYXRlciIpKQ0Kcm0oZGF0YVMpDQpybShkKQ0KYGBgDQoNClN1Z2dlc3RzIHRoYXQgZm9yIGFkdWx0cyB3ZSB3b3VsZCBuZWVkIDU4IHBlciBjb25kaXRpb24gdG8gZ2V0IDkwJSBwb3dlci4gV2Ugd291bGQgYmUgbGlrZWx5IHRvIG5lZWQgbW9yZSB3aXRoIGNoaWxkcmVuLg0KDQpHaXZlbiBwcmFjdGljYWwgY29uc3RyYWludHMsIHdlIGFyZSB1bmxpa2VseSB0byBvYnRhaW4gYSBzdWZmaWNpZW50IHNhbXBsZSBmb3IgdGhpcy4gSG93ZXZlciB0aGlzIGVmZmVjdCBpc24ndCBjcml0aWNhbCBpbiB0ZXJtcyBvZiBkZW1vbnN0cmF0aW5nIHdoYXQgbGVhZHMgdG8gZ3JlYXRlciBsZWFybmluZy4gKEl0IGlzIHRoZXJlZm9yZSBtb3JlIGltcG9ydGFudCB0byBkZW1vbnN0cmF0ZSB0aGF0IHRoZXkgYXJlIGFib3ZlIGNoYW5jZSBpbiBlYWNoIGNvbmRpdGlvbikvDQoNCiMjIFByZWRpY3Rpb24gNDogVGhleSB3aWxsIGltcHJvdmUgbW9yZSBpbiBvbmUgY29uZGl0aW9uIHRoYW4gdGhlIG90aGVyKG5vIHByZWRpY3RlZCBkaXJlY3Rpb24pDQojIyMgQmFzZWQgb246DQoNCldlIGRvbid0IGhhdmUgYW55IGNsZWFyIGV2aWRlbmNlIHRvIGJhc2UgdGhpcyBvbi4gSG93ZXZlciBpdCBzZWVtcyByZWFzb25hYmxlIHRoYXQgdGhlIHR5cGUgb2YgdHJhaW5pbmcgd2lsbCBsZWVkIHRvIGRpZmZlcmVudCBsZWFybmluZyBzbG9wZXMuIE9uZSBwb3NzaWJpbGl0eSBpcyB0aGF0IHdoaWxlIHRoZXkgc2hvdyBncmVhdGVyIGxlYXJuaW5nIGluIHRoZSBjb25kaXRpb24gd2l0aCBkaWFjcnRpY3MsIGR1ZSB0byBtb3JlIGluZm9ybWF0aW9uIHBlciB0cmlhbC4gSG93ZXZlciBpdCBpcyBhbHNvIHBvc3NpYmxlIHRoYXQgdGhleSBjb3VsZCBzaG93IHN0ZWVwZXIgbGVhcm5pbmcgaW4gdGhlIG90aGVyIGNvbmRpdGlvbiwgZHVlIHRvIG5lZWRpbmcgdG8gcGF5IG1vcmUgYXR0ZW50aW9uIHRvIGFuZCByZW1lbWJlciBpbmRpdmlkdWFsIHN0aW11bGkuIFdlIHNhdyBtZWFucyBpbiB0aGlzIGxhdHRlciBkaXJlY3Rpb24gaW4gdGhlIGFkdWx0IHBpbG90IGRhdGEgaS5lLiBtb3JlIGltcHJvdmVtZW50IGluIHRoZSBjb25kaXRpb24gd2l0aCBwaWN0dXJlcyAobGFiZWxsZWQgY29uZGl0aW9uICJpIiBmb3IgaW1wbGljaXQpIHRoYW4gd2l0aCBkaWFjcnRpY2lzIChsYWJlbGxlZCAiZSIgZm9yIGV4cGxpY2l0KSAodGhvdWdoIGNvbmRpdGlvbnMgbm90IGV4YWN0bHkgdGhlIHNhbWUgc2VlIGFib3ZlKS4gdGhvdWdoIGl0IHdzbid0IHNpZ25maWNhbnQuDQoNCmFkdWx0ICBtZWFucyA6IGByIHJvdW5kKHdpdGgoYWR1bHQudHJhaW4sIHRhcHBseShyZXN1bHQsIGxpc3QoY29uZGl0aW9uLCBzZXNzaW9uKSwgbWVhbiwgbmEucm09VCkpICwyKWANCiAgICAgICBiZXRhOiBgciBzdW1tYXJ5KGFkdWx0LnRyYWluLm1vZCkkY29lZmZpY2llbnRzWyJzZXNzaW9uLmN0OmNvbmRpdGlvbi5jdCIsIkVzdGltYXRlIiBdYA0KDQojIyMgUGxhbm5lZCBBbmFseXNlczogRnJlcXVlbnRpc3QgDQoNCmxtZSBtb2RlbCBzaW1pbGFyIHRvIHRoYXQgb24gcGlsb3QgZGF0YSBhYm92ZSBidXQgd2l0aCBkYXRhIGZyb20gYm90aCBjb25kaXRpb25zOyBsb29rIGZvciBmaXhlZCBlZmZlY3Qgb2YgY29uZGl0aW9uLmN0OnNlc3Npb24uY3QNCldlIHdpbGwgZG8gdGhpcyBib3RoIGZvciBhIG1vZGVsIHdpdGgganVzdCBmaXJzdCB0d28gc2Vzc2lvbnMgYW5kIGZvciBhIG1vZGVsIHdpdGggYWxsIGRhdGEuDQoNCiMjIyBQbGFubmVkIEFuYWx5c2VzOiBCRiANCg0KU3VtbWFyeSBvZiBkYXRhOiBtZWFuIGFuZCBzZSBmb3IgaW50ZXJhY3Rpb24gc2Vzc2lvbiBhbmQgY29uZGl0aW9uIChzZXNzaW9uLmN0IGJ5IGNvbmRpdG9pbi5jdCkgDQp2YWx1ZSB0byBpbmZvcm0gSDE6IGVzdGltYXRlIG9mIHNlc3Npb24gZnJvbSB0aGUgc2FtZSBtb2RlbCBtb2RlbCAoZS5nLiBzdW1tYXJ5KG1vZGVsLm5ld2RhdGEpJGNvZWZmaWNpZW50c1sic2Vzc2lvbi5jdCIgLCJFc3RpbWF0ZSJdYC4gDQoNClRoaXMgd2lsbCBwcm92aWRlIGEgcmVsYXRpdmVseSBoaWdoIGVzdGlhbXRlIG9mIGxpa2VseSBlZmZlY3Qgb2YgaW50ZXJhY3Rpb24gKGlmIG9uZSBpcyBwcmVzZW50KSBnaXZlbiB0aGUgYWN0dWFsIGRhdGEgc2V0IChzbyBhZ2FpbiwgYSBjb25zZXJ2YXRpdmUgZXN0aW1hdGUpICANCg0KW05vdGU6IGFyZSBjaGVja2luZyB0aGlzIHdpdGggc3RhdHMgY29uc3VsdGFudF0NCg0KTm90ZSB0aGlzIGlzIGV4ZW1wbGlmaWVkIGJlbG93IGluIHNhbXBsZSBzaXplIGFuYWx5c2lzIHVzaW5nIHRoZSBjdXJyZW50IGRhdGEgZnJvbSBhZHVsdHM6DQoNCg0KIyMjIFJlcXVpcmVkIHNhbXBsZSBhbmFseXNlcw0KDQojIyMjIEZyZXF1ZW50aXN0IHBvd2VyDQpOb3RoaW5nIHRvIGJhc2UgcG93ZXIgYW5hbHlzaXMgb24gaGVyZSAoYXMgd2FzIG5vIGVmZmVjdCBpbiBvcmlnaW5hbCBkYXRhKS4NCg0KIyMjIyBSZXF1aXJlZCBzYW1wbGUgZm9yIEJGIGFuYWx5c2VzOiANCg0KTm90ZSB0aGlzIGlzIHdpdGggYWR1bHQgZGF0YSAtIGl0IGV4ZW1wbGlmaWVzIHRoZSBwcm9jZXNzIHdlIHdpbGwgYWN0dWFsbHkgdXNlIHRvIGNvbmR1Y3QgcG93ZXIgYW5hbHlzZXMgb24gYWN0dWFsIGRhdGEgDQpgYGB7cn0NCg0KbWVhbkJGID0gc3VtbWFyeShhZHVsdC50cmFpbi5tb2QpJGNvZWZmaWNpZW50c1sic2Vzc2lvbi5jdDpjb25kaXRpb24uY3QiLCJFc3RpbWF0ZSJdDQpzZUJGID0gc3VtbWFyeShhZHVsdC50cmFpbi5tb2QpJGNvZWZmaWNpZW50c1sic2Vzc2lvbi5jdDpjb25kaXRpb24uY3QiLCJTdGQuIEVycm9yIl0NCmgxbWVhbiA9IHN1bW1hcnkoYWR1bHQudHJhaW4ubW9kKSRjb2VmZmljaWVudHNbInNlc3Npb24uY3QiLCJFc3RpbWF0ZSJdDQpCZihzZUJGLCBtZWFuQkYsICB1bmlmb3JtID0wLG1lYW5vZnRoZW9yeT0wLHNkdGhlb3J5PWgxbWVhbix0YWlsPTIpDQoNCnJtKG1lYW5CRikNCnJtKHNlQkYpDQoNCmBgYA0KTm90ZTogd2UgdXNlIHRhaWwgPTIgYXMgZG9uJ3QgaGF2ZSBhIGNsZWFyIGRpcmVjdGlvbiBmb3IgdGhpcyBoeXBvdGhlc2lzDQoNClNvIG5vdGUsIHdpdGggYWR1bHQgcGlsb3QgZGF0YSB3ZSBkbyBoYXZlIGV2aWRlbmNlIGluIGZhdm9yIG9mIEgwIGZyb20gdGhlIGN1cnJlbnQgZGF0YSBzZXQuIA0KDQoNCk9uZSBwb3NzaWJpbGl0eSB3aXRoIGNoaWxkcmVuIGlzIHRoYXQgd2Ugd2lsbCBub3QgYmUgYWJsZSB0byBvYnRhaW4gYSBsYXJnZSBlbm91Z2ggc2FtcGxlIHRvIHByb3ZpZGUgZXZpZGVuY2UgZm9yL2FnYWluc3QgdGhlIGh5cG90aGVzaXMgdGhhdCB0aGVyZSBpcyBtb3JlIGxlYXJuaW5nIGluIG9uZSBkaXJlY3Rpb24sIGJ1dCB3ZSBtYXkgZmluZCBldmlkZW5jZSBmb3IgdGhlIEgxIHRoYXQgdGhlcmUgKmlzKiBhbiBlZmZlY3Qgb2Ygc2Vzc2lvbiBpbiBvbmUgY29uZGl0aW9uIGJ1dCBmb3IgdGhlIEgwIHRoYXQgdGhlcmUgaXMgKm5vdCogYW5kIGVmZmVjdCBvZiBzZXNzaW9uIGluIHRoZSBvdGhlciBjb25kaXRpb24uIElmIHNvLCB3ZSB3aWxsIGRlZW0gdGhpcyBzdWZmaWNpZW50IHRvIGFkZHJlc3MgdGhpcyBwcmVkaWNpdG9uLg0KDQoNCg0KIyAyQUZDIHBpY3R1cmUgYW5kIDJBRkMgZGlhY3JpdGljDQoNClRoZXNlIHR3byB0ZXN0cyBhcmUgdmVyeSBzaW1pbGFyIHRvIHRyYWluaW5nIGJ1dCB3aXRoIGVpdGhlciBqdXN0IHBpY3R1cmVzIG9yIGp1c3QgZGlhY3JpdGljcy4gVGhlIHRlc3RzIGFyZSBvbmx5IGRvbmUgYXMgcG9zdCB0ZXN0cywgbm90IGFzIHByZS10ZXN0cyAodW5saWtlIGFsbCBvZiB0aGUgdGVzdHMgZGlzY3Vzc2VkIGFmdGVyIHRoaXMgb25lKQ0KDQpDaGlsZHJlbiBpbiB0aGUgcGljdHVyZXMrZGlhY3JpdGljcyBjb25kaXRpb24gd2lsbCBnZXQgdGhlIDJBRkMgcGljdHVyZXMgdGVzdCBmb2xsb3dlZCBieSB0aGUgMkFGQyBkaWFjcml0aWNzIHRlc3Q7IGNoaWxkcmVuIGluIHRoZSBwaWN0dXJlc29ubHkgdGVzdCB3aWxsIGdldCBqdXN0IDJBRkMgcGljdHVyZXMgYnV0IHdpbGwgZ2V0IGl0IHR3aWNlIChzbyB0aGF0IHRvdGFsIGV4cG9zdXJlIGRvZXNuJ3QgZGlmZmVyIGFjcm9zcyBjb25kaXRpb25zKS4NCg0KV2hlcmUgd2UganVzdCBsb29rIGEgY29uZGl0aW9ucyBzZXBhcmF0ZWx5LCBmb3IgdGhlIGp1c3QgcGljdHVyZXMgdGVzdCwgd2Ugd2lsbCBsb29rIGF0IGFsbCBvZiB0aGUgZGF0YSAoaS5lLiBmb3IgdGhlIHBpY3R1cmVzIG9ubHkgY29uZGl0aW9uLCBmcm9tIGJvdGggcGFydHMgb2YgdGhlIHJlcGVhdGVkIHRlc3QpLiBXaGVyZSB3ZSBjb21wYXJlIGNvbmRpdGlvbnMsIHdlIHdpbGwgbG9vayBvbmx5IHVzZSBkYXRhIGZyb20gdGhlIGZpcnN0IDJBRkMgdGVzdC4gDQoNCk5vdGU6IHVubGlrZSBmb3IgYWxsIHRoZSB0ZXN0cyB0aGF0IGZvbGxvdywgdGhlcmUgaXMgbm8gcHJlLXRlc3QuDQoNCiMjIHJ1biBsbWVzIG9uIHJlbGV2YW50IHBpbG90IGRhdGENCg0KV2UgZGlkbid0IGRvIHRoaXMgdGVzdCBpbiB0aGUgcGlsb3QsIGhvd2V2ZXIgdGhlIHRlc3QgaXMgcmF0aGVyIHNpbWlsYXIgdG8gdHJhaW5pbmcgdGVzdCBzbyB3ZSB1c2UgbW9kZWwgYmFzZWQgb24ganVzdCBsYXN0IDI0IHNlc3Npb25zIG9mIHRyYWluaW5nIGZvciBpbmZvcm1pbmcgcG93ZXIgZGVjaXNpb25zLiANCg0KYGBge3J9DQpjaGlsZC50cmFpbi43LnMyLjI0ID0gZHJvcGxldmVscyhzdWJzZXQoY2hpbGQudHJhaW4sIGFnZWdyb3VwID09ICI3eWVhcnMiICYgc2Vzc2lvbiA9PSJzZXNzaW9uMiIgJiBvcmRlcj43MikpDQpjaGlsZC50cmFpbi43LnMyLjI0ID0gbGl6Q2VudGVyKGNoaWxkLnRyYWluLjcuczIuMjQsIGMoInRvbmVjb250cmFzdCIpKQ0KY2hpbGQudHJhaW4uNy5zMi5zNC5tb2QgPSBnbG1lciAocmVzdWx0IH4NCiAgICAgICAgICAgICAgICAgMSsgdG9uZWNvbnRyYXN0LmN0DQogICAgICAgICAgICAgICAgKyAoMXxzdWJqZWN0KSwNCiAgICAgICAgICAgICAgICBkYXRhID0gY2hpbGQudHJhaW4uNy5zMi4yNCwgIGZhbWlseSA9IGJpbm9taWFsLCBjb250cm9sPWdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIikpDQoNCnJvdW5kKHN1bW1hcnkoY2hpbGQudHJhaW4uNy5zMi5zNC5tb2QpJGNvZWZmaWNpZW50cywzKQ0KYGBgDQoNCmBgYHtyfQ0KDQpjaGlsZC50cmFpbi4xMS5zMi4yNCA9IGRyb3BsZXZlbHMoc3Vic2V0KGNoaWxkLnRyYWluLCBhZ2Vncm91cCA9PSAiMTF5ZWFycyIgJiBzZXNzaW9uID09InNlc3Npb24yIiAmIG9yZGVyPjcyKSkNCmNoaWxkLnRyYWluLjExLnMyLjI0ID0gbGl6Q2VudGVyKGNoaWxkLnRyYWluLjExLnMyLjI0LCBjKCJ0b25lY29udHJhc3QiKSkNCmNoaWxkLnRyYWluLjExLnMyLnM0Lm1vZCA9IGdsbWVyIChyZXN1bHQgfg0KICAgICAgICAgICAgICAgICAxKyB0b25lY29udHJhc3QuY3QNCiAgICAgICAgICAgICAgICArICgxfHN1YmplY3QpLA0KICAgICAgICAgICAgICAgIGRhdGEgPSBjaGlsZC50cmFpbi4xMS5zMi4yNCwgIGZhbWlseSA9IGJpbm9taWFsLCBjb250cm9sPWdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIikpDQoNCnJvdW5kKHN1bW1hcnkoY2hpbGQudHJhaW4uMTEuczIuczQubW9kKSRjb2VmZmljaWVudHMsMykNCmBgYA0KDQoNCmBgYHtyfQ0KYWR1bHQudHJhaW4uczIuMjQgPSBzdWJzZXQoYWR1bHQudHJhaW4sIHNlc3Npb24gPT0ic2Vzc2lvbjIiICYgb3JkZXI+MjY0KQ0KYWR1bHQudHJhaW4uczIuMjQgPSBsaXpDZW50ZXIoYWR1bHQudHJhaW4uczIuMjQsIGxpc3QoInRvbmVjb250cmFzdCIpKQ0KDQphZHVsdC50cmFpbi5zMi4yNC5tb2QgPSBnbG1lciAocmVzdWx0IH4NCiAgICAgICAgICAgICAgICAgMSsgdG9uZWNvbnRyYXN0LmN0DQogICAgICAgICAgICAgICAgKyAoMXxzdWJqZWN0KSwNCiAgICAgICAgICAgICAgICBkYXRhID0gYWR1bHQudHJhaW4uczIuMjQsICBmYW1pbHkgPSBiaW5vbWlhbCwgY29udHJvbD1nbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIpKQ0KDQpyb3VuZChzdW1tYXJ5KGFkdWx0LnRyYWluLnMyLjI0Lm1vZCkkY29lZmZpY2llbnRzLDMpDQpgYGANCg0KIyMgUHJlZGljdGlvbjE6IFBlcmZvcm1hbmNlIHdpbGwgYWJvdmUgY2hhbmNlIGluIGVhY2ggdGVzdCBpbiBlYWNoIGNvbmRpdGlvbi4NCiMjIyBCYXNlZCBvbjoNClRyYWluaW5nIGRhdGEgaW4gcGlsb3QgKHNlZSBhYm92ZSkNCiMjIyBQbGFubmVkIEFuYWx5c2VzOiBGcmVxdWVudGlzdCANCg0KbG1lIG1vZGVsIHNpbWlsYXIgdG8gdGhhdCBmb3IgdHJhaW5pbmcgZGF0YS4gQWdhaW4gZml0IHNlcGFyYXRlIGludGVyY2VwdHMgZm9yIGVhY2ggY29uZGl0aW9uIGFuZCBjb21wYXJlIGVhY2ggdG8gY2hhbmNlID0gNTAgKGkuZS5kZWZhdWx0IHZhbHVlIHJldHVybmVkKS4gTm90ZSB0aGF0IHNpbmNlIGFsbCBwcmVkaWN0b3JzIGFyZSBjZW50ZXJlZCwgdGhlIGludGVyY2VwdCByZWxmZWN0cyBvdmVyYWxsIGF2ZXJhZ2UgKHJhdGhlciB0aGFuIGF0IGJhc2VsZXZlbHMgb2YgYSBmYWN0b3IpLiANCg0KKFdlIHdpbGwgZG8gdGhpcyBib3RoIGZvciBhIG1vZGVsIHdpdGgganVzdCBkYXkyIHRlc3QgYW5kIGRheTQgdGVzdDsgYXMgZGlzY3Vzc2VkIGFib3ZlLCB3ZSB3aWxsIHVzZSB0aGUgZnVsbCBkb3VibGUgZGF0YSBzZXQgZm9yIHRoZSAyQUZDIHBpY3R1cmUgdGVzdCBmb3IgdGhlIHBhcnRpY2lwYW50cyBpbiB0aGUgcGljdHVyZStkaWFjcml0aWMgY29uZGl0aW9uKS4NCg0KIyMjIFBsYW5uZWQgQW5hbHlzZXM6IEJGIHRlc3QgDQoNClN1bW1hcnkgb2YgZGF0YSBmb3IgZWFjaCBjb25kaXRpb246IG1lYW4gYW5kIHNlIGZvciBpbnRlcmVjcHQgZnJvbSBsbWUNCg0KdmFsdWUgdG8gaW5mb3JtIEgxOiBhc3N1bWluZyB0aGV5IHNob3cgbGVhcm5pbmcsIGVzdGltYXRlIGZyb20gdGhlIGVxdWl2YWxlbnQgbG1lIGZvciB0cmFpbmluZyBkYXRhIGZyb20gY3VycmVudCBkYXRhIHNldCAoTk9UIGZyb20gcGlsb3QgZGF0YSAtICp1bmxlc3MqIHRoZSBpbnRlcmNlcHQgZnJvbSB0cmFpbmluZyBzZXQgZGlkbid0IHN1Z2dlc3QgYWJvdmUgY2hhbmNlIHBlZm9ybWFuY2UpLiBBZ2FpbiBub3RlIHRoYXQgaWYgd2UgZmluZCBhbiBlZmZlY3QgZm9yIGNvbmRpdGlvbjEsIHdlIGNhbiBhbHNvIHVzZSB0aGUgZXN0aW1hdGUgZm9yIGludGVyY2VwdCBmb3IgdGhhdCB0byBpbmZvcm0gSDEgd2hlbiBsb29raW5nIGF0IGRhdGEgZnJvbSBjb25kaXRpb24yOyBhbmQgdmljZSB2ZXJzYS4gVGhpcyBpcyBhIGJldHRlciBlc3RpbWF0ZSBzaW5jZSB0aGUgY29uZGl0aW9ucyBhcmUgbW9yZSBjbG9zZWx5IG1hdGNoZWQgdG8gZWFjaCBvdGhlciB0aGFuIGVpdGhlciBpcyB0byB0aGUgcGlsb3QgZGF0YS4NCg0KIyMjIFJlcXVpcmVkIHNhbXBsZSBhbmFseXNlcw0KIyMjIyBGcmVxdWVudGlzdCBwb3dlcg0KDQpIZXJlIHdlIGxvb2sgYXQgcG93ZXIgdXNpbmcgdGhlIHZhbHVlcyBmcm9tIHRoZSBzdWJzZXQgb2YgdHJhaW5pbmcgZGF0YSBmcm9tIHRoZSBhYm92ZQ0KDQpgYGB7cn0gICAgICAgICAgICAgICAgIA0KDQpkYXRhUz1hcy5udW1lcmljKHdpdGgoZHJvcGxldmVscyhjaGlsZC50cmFpbi43LnMyLjI0KSwgdGFwcGx5KHJlc3VsdCxsaXN0KHN1YmplY3QpLCBtZWFuLCBuYS5ybT1UKSkpDQpkPSBjb2hlbnNEKHggPSBkYXRhUywgbXU9MC41KQ0KcHdyLnQudGVzdChuID0gTlVMTCwgZCA9IGQsIHNpZy5sZXZlbCA9IDAuMDUsIHBvd2VyID0gLjksICB0eXBlID0gYygib25lLnNhbXBsZSIpLCBhbHRlcm5hdGl2ZSA9IGMoICJncmVhdGVyIikpDQpwd3IudC50ZXN0KG4gPSBOVUxMLCBkID0gZCwgc2lnLmxldmVsID0gMC4wNSwgcG93ZXIgPSAuOCwgIHR5cGUgPSBjKCJvbmUuc2FtcGxlIiksIGFsdGVybmF0aXZlID0gYyggImdyZWF0ZXIiKSkNCnB3ci50LnRlc3QobiA9IE5VTEwsIGQgPSBkLCBzaWcubGV2ZWwgPSAwLjA1LCBwb3dlciA9IC43LCAgdHlwZSA9IGMoIm9uZS5zYW1wbGUiKSwgYWx0ZXJuYXRpdmUgPSBjKCAiZ3JlYXRlciIpKQ0Kcm0oZGF0YVMpDQpybShkKQ0KYGBgDQoNClRoaXMgc3VnZ2VzdHMgYSBzYW1wbGUgb2YgMjEgaXMgc3VmZmljaWVudCBmb3IgOTAlIHBvd2VyLg0KDQojIyMjIFJlcXVpcmVkIHNhbXBsZSBmb3IgQkYgYW5hbHlzZXM6IA0KDQpIZXJlIHdlIHVzZSB0aGUgc3Vic2V0IG9mIHBpbG90IGRhdGEgd2l0aCA3IHllYXIgb2xkcyBhbmQgYW4gSDEgaW5mb3JtZWQgYnkgZXN0aW1hdGUgZnJvbSAxMSB5ZWFyIG9sZHMgd2hvbGUgdHJhaW5pbmcgZGF0YSBzZXQgKG5vdGU6IGluIGFjdHVhbCBhbmFseXNlcyBIMSB3aWxsIGJlIGluZm9ybWVkIGJ5IGVzdGltYXRlIGZyb20gbW9kZWwgb2YgdGhlIGN1cnJlbnQgdHJhaW5pbmcgZGF0YSB3aXRoIDcgeWVhciBvbGRzICkNCg0KYGBge3J9DQoNCm1lYW5CRiA9IHN1bW1hcnkoY2hpbGQudHJhaW4uNy5zMi5zNC5tb2QpJGNvZWZmaWNpZW50c1siKEludGVyY2VwdCkiICwiRXN0aW1hdGUiXQ0Kc2VCRiA9IHN1bW1hcnkoY2hpbGQudHJhaW4uNy5zMi5zNC5tb2QpJGNvZWZmaWNpZW50c1siKEludGVyY2VwdCkiICwiU3RkLiBFcnJvciJdDQpoMW1lYW4gPSBzdW1tYXJ5KGNoaWxkLnRyYWluLjExLm1vZCkkY29lZmZpY2llbnRzWyIoSW50ZXJjZXB0KSIgLCJFc3RpbWF0ZSJdDQoNCkJmKHNlQkYsIG1lYW5CRiwgIHVuaWZvcm0gPTAsbWVhbm9mdGhlb3J5PTAsc2R0aGVvcnk9aDFtZWFuLHRhaWw9MSkNCkJmX3Bvd2VyY2FsYyhzZUJGLCBtZWFuQkYsICB1bmlmb3JtID0wLG1lYW5vZnRoZW9yeT0wLE49MTUsIG1pbj0xNSwgbWF4PTIwLHNkdGhlb3J5PWgxbWVhbix0YWlsPTEpDQoNCnJtKG1lYW5CRikNCnJtKHNlQkYpDQoNCmBgYA0KDQpTdWdnZXN0cyBkb24ndCBjdXJyZW50bHkgaGF2ZSBzdWZmaWNpZW50IHNhbXBsZSB0byBnZXQgcmVsaWFibGUgZXZpZGVuY2UgZm9yIEgxLCBidXQgY291bGQgZG8gd2l0aCAxOSBwYXJ0aWNpcGFudHMuDQoNCiMjIFByZWRpY3Rpb24gMjogRm9yIHBpY3R1cmUtb25seSB0ZXN0LCB0aGVyZSB3aWxsIGJlIGdyZWF0ZXIgcGVyZm9ybWFuY2UgaW4gdGhlIHBpY3R1cmUtb25seSBjb25kaXRpb24NCiMjIyBiYXNlZCBvbg0KQ2hpbGRyZW4gaW4gdGhlIGNvbmRpdGlvbiB3aGVyZSBkaWFjcml0aWNzIGFyZSBwcmVzZW50IG1pZ2h0IGhhdmUgYmVjb21lIG92ZXJseSByZWxpYW50IG9uIHRoZW0gZHVyaW5nIHRyYWluaW5nIGFuZCB0aHVzIHVuYWJsZSB0byBkbyB0aGUgdGVzdCB3aGVuIHRoZXkgYXJlIGFic2VudC4NCkRvbid0IGN1cnJlbnRseSBoYXZlIHNwZWNpZmljIGRhdGEgdG8gYmFzZSB0aGlzIG9uLg0KDQojIyMgUGxhbm5lZCBBbmFseXNlczogRnJlcXVlbnRpc3QgDQpsbWUgbW9kZWwgb24gNyB5ZWFyIG9sZHMgZGF0YSwgbG9vayBhdCBlZmZlY3Qgb2YgY29uZGl0aW9uLg0KDQooV2Ugd2lsbCBkbyB0aGlzIGJvdGggZm9yIGEgbW9kZWwgd2l0aCBqdXN0IGRheTIgdGVzdCBhbmQgZGF5NCB0ZXN0OyBhcyBkaXNjdXNzZWQgYWJvdmUsIHdlIHdpbGwgb25seSB1ZSB0aGUgaGFsZiBzZXQgZm9yIHRoZSAyQUZDIHBpY3R1cmUgdGVzdCBmb3IgdGhlIHBhcnRpY2lwYW50cyBpbiB0aGUgcGljdHVyZStkaWFjcml0aWMgY29uZGl0aW9uKS4NCg0KIyMjIFBsYW5uZWQgQW5hbHlzZXM6IEJGIHRlc3QgDQoNClN1bW1hcnkgb2YgZGF0YSBmb3IgZWFjaCBjb25kaXRpb246IG1lYW4gYW5kIHNlIGZvciBjb25kaXRpb24gZnJvbSBsbWUNCnZhbHVlIHRvIGluZm9ybSBIMTogYXNzdW1pbmcgdGhleSBzaG93IGxlYXJuaW5nLCBlc3RpbWF0ZSBvZiBpbnRlcmNlcHQgZnJvbSB0aGUgY3VycmVudCBtb2RlbCAobm90ZSBvdGhlciB2YWx1ZXMgYXJlIGNlbnRlcmVkLCBzbyB0aGlzIGlzIGVxdWl2bGFlbnQgdG8gZ3JhbmQgbWVhbjsgaXQgd2lsbCBiZSBjb25zZXJ2YXRpdmUpDQoNCihBbSBzZWVraW5nIHN0YXRpc3RpY2FsIGFkdmljZSB0byBjb25maXJtIHRoYXQgdGhpcyBpcyBhIHJlYXNvbmFibGUsIGlmIGNvbnNlcnZhdGl2ZSwgZXN0aW1hdGUgZm9yIEgxKQ0KDQojIyMgUmVxdWlyZWQgc2FtcGxlIGFuYWx5c2VzDQoNCk5vdGhpbmcgd2UgY2FuIHJlYWxseSBiYXNlIGFuYWx5c2VzIG9uIGhlcmUgKGNvbXBhcmlzb24gb2YgY29uZGl0aW9uIGluIHByZXZpb3VzIGFkdWx0IGRhdGEgaXMgdG9vIGRpc3NpbWlsYXIpLg0KDQpOb3RlIHRoYXQgaXQgbWF5IHByb3ZlIGRpZmZpY3VsdCB0byBvYnRhaW5hIHN1ZmZpY2llbnQgc2FtcGxlIHRvIGdhaW4gZXZpZGVuY2UgZm9yIEgxIG9yIGgwLiAgSG93ZXZlciBpdCBtYXkgYmUgdGhhdCB3ZSBzZWUgYWJvdmUgY2hhbmNlIHBlcmZvcm1hbmNlIG9ubHkgZm9yIHRoZSBwaWN0dXJlLW9ubHkgY29uZGl0aW9uLiBJbiB0aGF0IGNhc2UsIHdlIG1heSBiZSBsb29rIHRvIHRoZSBwcmV2aW91cyBhbmFseXNlcyAoUHJlZGljdGlvbiAxKSBhbmQgYmUgYWJsZSB0byBzaG93IHRoYXQgdGhlcmUgaXMgZXZpZGVuY2UgZm9yIEgxIG92ZXIgSDAgaW4gb25lIGNvbmRpdGlvbiwgYnV0IGZvciBIMCBvdmVyIEgxIGluIHRoZSBvdGhlci4gSWYgc28sIHdlIHdpbGwgYmUgYWJsZSB0byBzYXkgdGhhdCB0aGVyZSBpcyBldmlkZW5jZSBvZiBsZWFybmluZyBpbiBvbmUgY29uZGl0aW9uIGFuZCBub3QgdGhlIG90aGVyLCBhbmQgdGhpcyB3aWxsIGJlIGRlZW1lZCBzdWZmaWNpZW50IHRvIGFkZHJlc3MgdGhpcyBoeXBvdGhlc2lzLiAgDQoNCiMgRGlzY3JpbWluYXRpb24NClRoaXMgdGVzdCB3aWxsIGJlIGdpdmVuIHByZSBhbmQgcG9zdC4gQ2hpbGRyZW4gd2lsbCBoZWFyIHRocmVlIGZyb2dzIGVhY2ggcHJvZHVjZSBhIE1hbmRhcmluIHdvcmQuIE9uZSBwcm9kdWNlcyB0aGUgdGFyZ2V0IGFuZCB0aGUgb3RoZXIgdHdvIGVhY2ggcHJvZHVjZSB0aGUgc2FtZSBmb2lsIHdvcmQsIHdoaWNoIHdpbGwgYmUgYSB3b3JkIGRpZmZlcmVpbmcgZnJvbSB0aGUgdGFyZ2V0IG9ubHkgaW4gdG9uZS4gDQoNCkVhY2ggb2YgdGhlIDYgb25lIGNvbnRyYXN0cyBhcmUgdGVzdGVkLiBXZSBwdXQgdG9uZWNvbnRyYXN0IGludG8gdGhlIG1vZGVsLCBzaW5jZSBpdCBpcyBsaWtlbHkgdG8gaGF2ZSBhbiBlZmZlY3QsIGJ1dCBkb24ndCBoYXZlIHNwZWNpZmljIGh5cG90aGVzZXMgb2YgaW50ZXJlc3QgaGVyZS4gVGhlcmUgYXJlIGZvdXIgdGFsa2VycywgM2YgMW0uIFRyaWFscyBpbiB3aGljaCB0aGUgbSBpcyB0aGUgb2RkIG9uZSBvdXQgYXJlIGtub3duIHRvIGJlIGVhc2llc3QgYW5kIHRob3NlIHdoZXJlIG9uZSBvZiB0aGUgc3BlYWtlcnMgaXMgbSBidXQgaXQgaXMgbm90IHRoZSBvZGQgb25lIG91dCBhcmUgZWFpc2VzdC4gVEhlcmUgYXJlIGFuIGVxdWFsIG51bWJlciBvZiBlYWNoIHRyaWFsIHR5cGUgYW5kIHdlIHB1dCAgdHJpYWwgdHlwZSBpbnRvIHRoZSBtb2RlbCBhcyBhIGZhY3RvcjsgdGhvdWdoIGFnYWluIGl0IGlzbid0IGEgcXVlc3Rpb24gZm9yIHdoaWNoIHdlIGhhdmUgcHJlZGljdGlvbnMuDQoNCkZvciB0aGUgaW50aWFsIGRhdGEgc2V0IGNvbGxlY3RlZCwgd2Ugd2lsbCBjb25zaWRlciBib3RoIHByZS10ZXN0IC0+IHBvc3R0ZXN0MSBhbmQgcHJlLXRlc3QgLT4gcG9zdC10ZXN0MiAoaWYgZXF1aXZsYWVudCByZXN1bHRzIG9idGFuZWQsIHN1YnNlcXVlbnRpbmcgdGVzdGluZyB3aWxsIGRyb3AgZmluYWwgdHdvIHNlc3Npb25zIC0gc2VlIG5vdGUgYWJvdmUpDQoNCiMjIGxvYWQgdXAgYW5kIHJ1biBsbWVzIG9uIHJlbGV2YW50IHBpbG90IGRhdGENCg0KVGhlIHBpbG90IGNoaWxkIGRhdGEgYmVsb3cgY29tZSBmcm9tIHNhbWUgMi1zZXNzaW9uIHN0dWR5IGFzIHBpbG90IHRyYW5pbmcgZGF0YSAocmVjYWxsIHRoZXkgd2VyZSB0cmFpbmVkIG9uIHN0aW11bGkgc2ltaWxhciB0byB0aGUgInBpY3R1cmUtb25seSIgY29uZGl0aW9uIGluIHRoZSBjdXJyZW50IHN0dWR5LikNCg0KVGhlIGFkdWx0ICBkYXRhIGJlbG93IGNvbWUgZnJvbSBhIGRpZmZlcmVudCB0d28tIHNlc3Npb24gc3R1ZHkgd2hlcmUgdGhlcmUgd2VyZSB0d28gY29uZGl0aW9uICgxKSB0cmFpbmVkIG9uIHN0aW11bGkgc2ltaWxhciB0byB0aGUgInBpY3R1cmUtb25seSIgY29uZGl0aW9uIGluIHRoZSBjdXJyZW50IHN0dWR5ICgyKSB0cmFpbmVkIG9uIHBpY3R1cmVzIEpVU1Qgb2YgdGhlIGRpYWNyaXRpY3MuIFRoaXMgaXMgdXNlZnVsIGZvciBjb25zaWRlcmluZyBwb3NzaWJsZSBlZmZlY3RzIG9mIGNvbmRpdGlvbiBpbiB0aGUgZGF0YSAodGhvdWdoIHdpdGggdGhlIGNhdmVhdCB0aGF0IGNvbXBhcmlzb24gaXMgc29tZXdoYXQgZGlmZmVyZW50KS4NCg0KTm90ZSB0aGF0IGZvciBib3RoIGFkdWx0cyBhbmQgY2hpbGRyZW4gaW4gdGhlIHBpbG90IGV4cGVyaWVtbnQgd2UgaGFkIGJvdGggdHJhaW5lZCBhbmQgdW50cmFpbmVkIGl0ZW1zLiBGb3IgdGhpcyBleHBlcmltZW50IHdlIHVzZSBvbmx5IHVudHJhaW5lZCBpdGVtcyBpbiB0aGlzIHRlc3Qgc28gd2UgcmVtb3ZlIHRoZSB1bnRyYWluZWQgaXRlbXMgZnJvbSB0aGUgYW5hbHlzZXMgYmVsb3cuDQoNCk5vdGU6IHRvbmVjb250cmFzdCBpcyBmaXhlZCBlZmZlY3Qgd2l0aCA2IGxldmVscyAoc2l4IHBvc3NpYmxlIGNvbnRyYXN0cykuIEl0IGlzIGV4cGVjdGVkIHRvIGNvbnRyaWJ1dGUgdG8gbW9kZWwgYW5kIGlzIHRodXMgaW5jbHVkZWQgYnV0IGlzbid0IG9mIHNwZWNpZmljIGludGVyZXN0Lg0KYGBge3J9DQpjaGlsZC5kaXNjcmltID0gcmVhZC5jc3YoImtpZHNkaXNjcmltX2NsZWFuLmNzdiIpDQphZHVsdC5kaXNjcmltID0gcmVhZC5jc3YgKCJhZHVsdHNkaXNjcmltX2NsZWFuLmNzdiIpDQpjaGlsZC5kaXNjcmltJHByZV9wb3N0ID0gcmVsZXZlbChjaGlsZC5kaXNjcmltJHByZV9wb3N0LCByZWY9InByZSIpDQpjaGlsZC5kaXNjcmltJGFnZWdyb3VwID0gYXMuZmFjdG9yKGNoaWxkLmRpc2NyaW0kYWdlZ3JvdXApDQoNCmFkdWx0LmRpc2NyaW0kcHJlX3Bvc3QgPSByZWxldmVsKGFkdWx0LmRpc2NyaW0kcHJlX3Bvc3QsIHJlZj0icHJlIikNCmFkdWx0LmRpc2NyaW0kY29uZGl0aW9uID0gcmVsZXZlbChhZHVsdC5kaXNjcmltJGNvbmRpdGlvbiwgcmVmPSJpIikNCg0KY2hpbGQuZGlzY3JpbSRwcmVfcG9zdCA9IHJlbGV2ZWwoY2hpbGQuZGlzY3JpbSRwcmVfcG9zdCwgcmVmPSJwcmUiKQ0KDQphZHVsdC5kaXNjcmltPC0gZHJvcGxldmVscyhzdWJzZXQoYWR1bHQuZGlzY3JpbSwgbmV3b3JvbGQgPT0gIm5ld3dvcmQiKSkNCmNoaWxkLmRpc2NyaW08LSBkcm9wbGV2ZWxzKHN1YnNldChjaGlsZC5kaXNjcmltLCBuZXdvcm9sZCA9PSAibmV3d29yZCIpKQ0KYGBgDQoNCg0KYGBge3J9DQphZHVsdC5kaXNjcmltIDwtIGxpekNlbnRlcihhZHVsdC5kaXNjcmltLCBsaXN0KCJwcmVfcG9zdCIsInRyaWFsdHlwZSIsICJjb25kaXRpb24iLCAidG9uZWNvbnRyYXN0IikpDQoNCmFkdWx0LmRpc2NyaW0ubW9kID0gZ2xtZXIgKGNvcnJlY3Qgfg0KICAgICAgICAgICAgICAgICsgY29uZGl0aW9uLmN0ICogcHJlX3Bvc3QuY3QNCiAgICAgICAgICAgICAgICArIHRyaWFsdHlwZS5jdCANCiAgICAgICAgICAgICAgICArIHRvbmVjb250cmFzdC5jdA0KICAgICAgICAgICAgICAgICsgKHByZV9wb3N0LmN0fHBhcnRpY2lwYW50bnVtYmVyKSwNCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBhZHVsdC5kaXNjcmltLCAgZmFtaWx5ID0gYmlub21pYWwsIGNvbnRyb2w9Z2xtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiKSkNCg0Kcm91bmQoc3VtbWFyeShhZHVsdC5kaXNjcmltLm1vZCkkY29lZmZpY2llbnRzLCAzKQ0KDQoNCmBgYA0KDQpgYGB7cn0NCmNoaWxkLmRpc2NyaW0uNyA9IGRyb3BsZXZlbHMoc3Vic2V0KGNoaWxkLmRpc2NyaW0sIGFnZWdyb3VwID09ICI3IikpDQoNCmNoaWxkLmRpc2NyaW0uNyA8LSBsaXpDZW50ZXIoY2hpbGQuZGlzY3JpbS43LCBsaXN0KCJwcmVfcG9zdCIsInRyaWFsdHlwZSIsICJjb25kaXRpb24iLCAidG9uZWNvbnRyYXN0IikpDQoNCmNoaWxkLmRpc2NyaW0uNy5tb2QgPSBnbG1lciAoY29ycmVjdCB+DQogICAgICAgICAgICAgICAgKyBwcmVfcG9zdC5jdA0KICAgICAgICAgICAgICAgICsgdHJpYWx0eXBlLmN0IA0KICAgICAgICAgICAgICAgICsgdG9uZWNvbnRyYXN0LmN0DQogICAgICAgICAgICAgICAgKyAocHJlX3Bvc3QuY3R8cGFydGljaXBhbnRudW1iZXIpLA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IGNoaWxkLmRpc2NyaW0uNywgIGZhbWlseSA9IGJpbm9taWFsLCBjb250cm9sPWdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIikpDQoNCnJvdW5kKHN1bW1hcnkoY2hpbGQuZGlzY3JpbS43Lm1vZCkkY29lZmZpY2llbnRzLCAzKQ0KDQoNCmBgYA0KDQoNCg0KIyMgUHJlZGljdGlvbjE6IEltcHJvdmVtZW50IGZyb20gcHJlLXBvc3QgdGVzdCBpbiBlYWNoICBlYWNoIGNvbmRpdGlvbg0KIyMjIEJhc2VkIG9uDQoNCkluIHRoZSBwaWxvdCBkYXRhLCBhZHVsdHMgc2hvdyBpbXByb3ZlbWVudCB3aXRoIHNlc3Npb24gYnV0IG5laXRoZXIgNyB5ZWFyIG9sZHMgZGlkbid0IChuYiBub3IgZGlkIDExIHllYXIgb2xkcykNCg0KbWVhbnMgOiBgciByb3VuZCggd2l0aChhZHVsdC5kaXNjcmltLCB0YXBwbHkoY29ycmVjdCwgcHJlX3Bvc3QsIG1lYW4sIG5hLnJtPVQpKSAsMilgOw0KbG9nIG9kZHMgKGJldGEgZnJvbSBsbWUpOiBgciBzdW1tYXJ5KGFkdWx0LmRpc2NyaW0ubW9kKSRjb2VmZmljaWVudHNbInByZV9wb3N0LmN0IiAsIkVzdGltYXRlIl1gOw0Kb2RkICAoZXhwKGJldGEpKWByIGV4cChzdW1tYXJ5KGFkdWx0LmRpc2NyaW0ubW9kKSRjb2VmZmljaWVudHNbInByZV9wb3N0LmN0IiAsIkVzdGltYXRlIl0pYA0KDQo3eWVhciBvbGRzIChkb24ndCBzaG93IHRoaXMtIGluIGZhY3QgbWVhbnMgcmV2ZXJzZWQgKQ0KDQptZWFucyA6IGByIHJvdW5kKCB3aXRoKGNoaWxkLmRpc2NyaW0uNywgdGFwcGx5KGNvcnJlY3QsIHByZV9wb3N0LCBtZWFuLCBuYS5ybT1UKSkgLDIpYDsNCmxvZyBvZGRzIChiZXRhIGZyb20gbG1lKTogYHIgc3VtbWFyeShjaGlsZC5kaXNjcmltLjcubW9kKSRjb2VmZmljaWVudHNbInByZV9wb3N0LmN0IiAsIkVzdGltYXRlIl1gOw0Kb2RkICAoZXhwKGJldGEpKWByIGV4cChzdW1tYXJ5KGNoaWxkLmRpc2NyaW0uNy5tb2QpJGNvZWZmaWNpZW50c1sicHJlX3Bvc3QuY3QiICwiRXN0aW1hdGUiXSlgDQoNCiMjIyBQbGFubmVkIEFuYWx5c2VzOiBGcmVxdWVudGlzdCANCmxtZSBtb2RlbCBzaW1pbGFyIHRvIHRoYXQgb24gcGlsb3QgZGF0YSBhYm92ZSBidXQgd2l0aCBkYXRhIGZyb20gYm90aCBjb25kaXRpb25zOyBGaXQgc2VwYXJhdGUgc2xvcGVzIGZvciBwcmUtcG9zdCBpbiBlYWNoIGNvbmRpdGlvbiANCg0KRm9yIHRoZSBpbnRpYWwgZGF0YSBzZXQgY29sbGVjdGVkIHdlIHdpbGwgZG8gdGhpcyBib3RoIHRvIGNvbXBhcmUgcHJlIHRlc3QgdG8gcG9zdC10ZXN0IDEgYW5kIHByZS10ZXN0IHRvIHBvc3QtdGVzdDIgKHNlZSBub3RlcyBhYm92ZSkuDQoNCiMjIyBQbGFubmVkIEFuYWx5c2VzOiBCRiANCg0KU3VtbWFyeSBvZiBkYXRhIGZvciBlYWNoIGNvbmRpdGlvbjogbWVhbiBhbmQgc2UgZm9yIHByZS1wb3N0IGZyb20gbG1lDQp2YWx1ZSB0byBpbmZvcm0gSDE6IGVzdGltYXRlIGZyb20gYWJvdmUgcGlsb3QgZGF0YSBmb3IgYWR1bHRzIGkuZS4gYHIgc3VtbWFyeShhZHVsdC5kaXNjcmltLm1vZCkkY29lZmZpY2llbnRzWyJwcmVfcG9zdC5jdCIgLCJFc3RpbWF0ZSJdYA0KDQpOb3RlOiB0aGlzIGFkdWx0IHZhbHVlIHdpbGwgbGlrZWx5IG92ZXJlc3RpbWF0ZSB0aGUgbWVhbnMuIEEgYmV0dGVyIHZhbHVlIHdvdWxkIGNvbWUgZnJvbSB0aGUgbmV3IGRhdGEgZnJvbSBjaGlsZHJlbiB0aGVtc2VsdmVzIC0gdGhlcmVmb3JlLCBpZiB0aGV5IHNob3cgbGVhcmluZyBpbiBvbmUgY29uZGl0aW9uIHdlIHdpbGwgdXNlIHRoYXQgdG8gaW5mb3JtIEJGIGZvciB0aGUgb3RoZXIgY29uZGl0aW9uIChhbmQgaWYgYm90aCBzaG93IGxlYXJuaW5nIHdlIHdpbGwgdXNlIHRvIGluZm9ybSBCRiBmb3IgZWFjaCBvdGhlcikuIA0KDQoNCg0KDQojIyMgUmVxdWlyZWQgc2FtcGxlIGFuYWx5c2VzDQojIyMjIEZyZXF1ZW50aXN0IFBvd2VyDQoNCk5vdGU6IHRoaXMgYW5hbHlzaXMgaW5jbHVkZWQgZm9yIGNvbXBsZXRlbmVzcyBidXQgaXMgbm90IHJlYWxseSByZWxldmFudCBzaW5jZSBpdCBpcyBiYXNlZCBvbiBhZHVsdCBkYXRhLiBJZiBjaGlsZHJlbiBkbyBzaG93IGFuIGVmZmVjdCwgaXQgaXMgbGlrZWx5IHNtYWxsZXIgYW5kIHRoZXkgd2lsbCBoYXZlIGxhcmdlciBTRSAgDQoNCmBgYHtyfQ0KZGF0YVM9d2l0aChkcm9wbGV2ZWxzKGFkdWx0LmRpc2NyaW0pLCB0YXBwbHkoY29ycmVjdCxsaXN0KHBhcnRpY2lwYW50bnVtYmVyLCBwcmVfcG9zdCksIG1lYW4sIG5hLnJtPVQpKQ0KZCA9IGNvaGVuc0QoeCA9IGFzLm51bWVyaWMoZGF0YVNbLDFdKSx5ID0gYXMubnVtZXJpYyhkYXRhU1ssMl0pLCBtZXRob2QgPSAicGFpcmVkIikNCnB3ci50LnRlc3QobiA9IE5VTEwsIGQgPSBkLCBzaWcubGV2ZWwgPSAwLjA1LCBwb3dlciA9IC45LCAgdHlwZSA9IGMoInBhaXJlZCIpLCBhbHRlcm5hdGl2ZSA9IGMoICJncmVhdGVyIikpDQpwd3IudC50ZXN0KG4gPSBOVUxMLCBkID0gZCwgc2lnLmxldmVsID0gMC4wNSwgcG93ZXIgPSAuOCwgIHR5cGUgPSBjKCJwYWlyZWQiKSwgYWx0ZXJuYXRpdmUgPSBjKCAiZ3JlYXRlciIpKQ0KcHdyLnQudGVzdChuID0gTlVMTCwgZCA9IGQsIHNpZy5sZXZlbCA9IDAuMDUsIHBvd2VyID0gLjcsICB0eXBlID0gYygicGFpcmVkIiksIGFsdGVybmF0aXZlID0gYyggImdyZWF0ZXIiKSkNCg0Kcm0oZCkNCnJtKGRhdGFTKQ0KYGBgDQoNCg0KIyMjIyBSZXF1aXJlZCBzYW1wbGUgZm9yIEJGIGFuYWx5c2VzIGZyb20gcGlsb3QgZGF0YQ0KDQpIZXJlIHdlIGxvb2sgYXQgZGF0YSBmcm9tIDcgeWVhciBvbGRzIGluIHBpbG90ICBhbmQgDQpgYGB7cn0NCm1lYW5CRiA9IHN1bW1hcnkoY2hpbGQuZGlzY3JpbS43Lm1vZCkkY29lZmZpY2llbnRzWyJwcmVfcG9zdC5jdCIgLCJFc3RpbWF0ZSJdDQpzZUJGID0gc3VtbWFyeShjaGlsZC5kaXNjcmltLjcubW9kKSRjb2VmZmljaWVudHNbInByZV9wb3N0LmN0IiAsIlN0ZC4gRXJyb3IiXQ0KaDFtZWFuID0gc3VtbWFyeShhZHVsdC5kaXNjcmltLm1vZCkkY29lZmZpY2llbnRzWyJwcmVfcG9zdC5jdCIgLCJFc3RpbWF0ZSJdDQoNCkJmKHNlQkYsIG1lYW5CRiwgIHVuaWZvcm0gPTAsbWVhbm9mdGhlb3J5PTAsc2R0aGVvcnk9aDFtZWFuLHRhaWw9MSkNCg0Kcm0obWVhbkJGKQ0Kcm0oc2VCRikNCnJtKGgxbWVhbikNCmBgYA0KSGF2ZSBldmlkZW5jZSBmb3IgdGhlIG51bGwgZnJvbSBqdXN0IDE1IHBhcnRpY2lwYW50cy4gTm90ZSBob3dldmVyLCB0aGF0IHdlIGFyZSByZWxhdGl2ZWx5IGhpZ2ggZXN0aW1hdGUgZm9yIEgxLCB3aGljaCBtYXkgbWFrZSBpdCBlYXNpZXIgdG8gZmluZCBldmlkZW5jZSBmb3IgdGhlIG51bGwuDQoNCg0KIyMgUHJlZGljdGlvbjI6IE1vcmUgaW1wcm92ZW1lbnQgaW4gb25lIGNvbmRpdGlvbiB0aGFuIHRoZSBvdGhlcg0KDQojIyMgQmFzZWQgb24NCg0KV2UgZG9uJ3QgaGF2ZSBhbnkgc3BlY2lmaWMgZXZpZGVuY2UgdG8gYmFzZSB0aGlzIG9uLiBUaGUgY2xvc2VzdCBjb250cmFzdHMgd2FzIGluIHRoZSBhZHVsdCBwaWxvdCBleHBlcmltZW50IChjb21wYXJpbmcgY29uZGl0aW9uIHdpdGggcGljdHVyZSBvbmx5IHRyYWluaW5nIHZlcnN1cyBkaWFjcml0aWMgb25seSB0cmFpbmluZykgd2hlcmUgdGhleSBzaG93ZWQgbnVtZXJpY2FsbHkgbW9yZSBpbXByb3ZlbWVudCBpbiB0aGUgaW1wbGljaXQgY29uZGl0aW9uLCBidXQgdGhlIGRpZmZlcmVuY2Ugd2FzIE5TLg0KDQptZWFucyA6IGByIHJvdW5kKCB3aXRoKGFkdWx0LmRpc2NyaW0sIHRhcHBseShjb3JyZWN0LCBsaXN0KHByZV9wb3N0LCBjb25kaXRpb24pLCBtZWFuLCBuYS5ybT1UKSkgLDIpYA0KbG9nIG9kZHMgKGJldGEgZnJvbSBsbWUpOiBgciBzdW1tYXJ5KGFkdWx0LmRpc2NyaW0ubW9kKSRjb2VmZmljaWVudHNbImNvbmRpdGlvbi5jdDpwcmVfcG9zdC5jdCIgLCJFc3RpbWF0ZSJdYA0Kb2RkICAoZXhwKGJldGEpKWByIGV4cChzdW1tYXJ5KGFkdWx0LmRpc2NyaW0ubW9kKSRjb2VmZmljaWVudHNbImNvbmRpdGlvbi5jdDpwcmVfcG9zdC5jdCIgLCJFc3RpbWF0ZSJdKWANCg0KDQpGb3IgdGhlIGludGlhbCBkYXRhIHNldCBjb2xsZWN0ZWQgV3cgd2lsbCBkbyB0aGlzIGJvdGggdG8gY29tcGFyZSBwcmUgdGVzdCB0byBwb3N0LXRlc3QgMSBhbmQgcHJlLXRlc3QgdG8gcG9zdC10ZXN0MiAoc2VlIG5vdGVzIGFib3ZlKS4NCg0KIyMjIFBsYW5uZWQgQW5hbHlzZXM6IEZyZXF1ZW50aXN0DQoNCmxtZSBtb2RlbCBzaW1pbGFyIHRvIHRoYXQgb24gcGlsb3QgZGF0YSBhYm92ZSBidXQgd2l0aCBkYXRhIGZyb20gYm90aCBjb25kaXRpb25zOyBsb29rIGZvciBpbnRlcmFjdGlvbiBiZXR3ZWVuIHByZS1wb3N0IGFuZCBjb25kaXRpb24uDQoNCiMjIyBQbGFubmVkIEFuYW5seXNlczogQkYNClN1bW1hcnkgb2YgZGF0YSBmb3IgZWFjaCBjb25kaXRpb246IG1lYW4gYW5kIHNlIGZvciBwcmUtcG9zdCpjb25kaXRpb24gZnJvbSBsbWUNCnZhbHVlIHRvIGluZm9ybSBIMTogZXN0aW1hdGUgZm9yIHNlc3Npb24gZnJvbSB0aGUgY3VycmVudCBtb2RlbCAgIChpLmUuIHN1bW1hcnkobmV3LmRhdGEpJGNvZWZmaWNpZW50c1sicHJlX3Bvc3QuY3QiICwiRXN0aW1hdGUiXWANCg0KTm90ZTogd2Ugb25seSBkbyB0aGlzIGlmIHdlIGhhdmUgZXZpZGVuY2Ugb2YgYW4gZWZmZWN0IG9mIHByZS1wb3N0IGluIGF0IGxlYXN0IG9uZSBvZiB0aGUgY29uZGl0aW9ucy4gSWYgdGhleSBkb24ndCBsZWFybiBpbiBlaXRoZXIgY29uZGl0aW9uIHRoZW4gdGhpcyB0ZXN0IGlzIGluYXBwcm9wcmlhdGUuDQoNCkFsc28gbm90ZSB0aGF0IHRoaXMgd2lsbCBiZSByZWxhdGl2ZWx5IGNvbnNlcnZhdGl2ZSBlc3RpbWF0ZSBmb3IgYSBsYXJnZSBkaWZmZXJlbmNlIGluIGhvdyBtdWNoIHRoZSBjb25kaXRpb25zIGxlYWQgdG8gYSBjaGFuZ2UgcHJlIHRvIHBvc3QuIA0KKGFnYWluIHdpbGwgc2VlayBzdGF0aXN0aWFsIGFkdmljZSBoZXJlKQ0KDQojIyMgUmVxdWlyZWQgc2FtcGxlIGVzdGltYXRlcw0KIyMjIyBGcmVxdWVudGlzdCBQb3dlcg0KV2UgaGF2ZSBubyBkYXRhIHRvIGxvb2sgYXQgdGhpcyAoc2luY2Ugd2FzIG5vIHNpZy4gZGlmZmVyZW5jZSBpbiBkYXRhIGNvbGxlY3RlZCkNCg0KIyMjIyBSZXF1aXJlZCBzYW1wbGUgZm9yIEJGIGFuYWx5c2VzIGZyb20gcGlsb3QgZGF0YQ0KDQpIZXJlIHdlIGFyZSBsb29raW5nIGF0IHRoaXMgd2l0aCBhZHVsdCBkYXRhLg0KDQpgYGB7cn0NCm1lYW5CRiA9IHN1bW1hcnkoYWR1bHQuZGlzY3JpbS5tb2QpJGNvZWZmaWNpZW50c1siY29uZGl0aW9uLmN0OnByZV9wb3N0LmN0IiAsIkVzdGltYXRlIl0NCnNlQkYgPSBzdW1tYXJ5KGFkdWx0LmRpc2NyaW0ubW9kKSRjb2VmZmljaWVudHNbImNvbmRpdGlvbi5jdDpwcmVfcG9zdC5jdCIgLCJTdGQuIEVycm9yIl0NCmgxbWVhbiA9IHN1bW1hcnkoYWR1bHQuZGlzY3JpbS5tb2QpJGNvZWZmaWNpZW50c1sicHJlX3Bvc3QuY3QiICwiRXN0aW1hdGUiXQ0KDQpCZihzZUJGLCBtZWFuQkYsICB1bmlmb3JtID0wLG1lYW5vZnRoZW9yeT0wLHNkdGhlb3J5PWgxbWVhbix0YWlsPTIpDQpwbG90KEJmX3Bvd2VyY2FsYyhzZUJGLCBtZWFuQkYsICB1bmlmb3JtID0wLG1lYW5vZnRoZW9yeT0wLHNkdGhlb3J5PWgxbWVhbiwgTj0xNSwgbWluPTkwMCwgbWF4ID0gNTAsIHRhaWw9MikpDQphYmxpbmUoaD0zKQ0KQmZfcG93ZXJjYWxjKHNlQkYsIG1lYW5CRiwgIHVuaWZvcm0gPTAsbWVhbm9mdGhlb3J5PTAsc2R0aGVvcnk9aDFtZWFuLCBOPTE1LCBtaW49ODExLCBtYXggPSA4MTUsIHRhaWw9MikNCg0Kcm0obWVhbkJGKQ0Kcm0oc2VCRikNCnJtKGgxbWVhbikNCmBgYA0KDQpHZW5lcmFsIG5vdGU6IHRoaXMgYW5hbHlzaXMgc3VnZ2VzdHN0IHRoYXQgZXZlbiBmb3IgYWR1bHRzLCB3b3VsZG4ndCBuZWVkIGEgc2FtcGxlIG9mIG92ZXIgODAwIHBhcnRpY2lwYW50cyBwZXIgY29uZGl0aW9uIHRvIHNlZSB0aGlzIGludGVyYWN0aW9uLiBUaGlzIGlzIGltcGxhdXNpYmxlICh0aG91Z2ggbWF5IGJlIHBhcnRseSBiZWNhdXNlIGFyZSBiYXNpbmcgb24gb3ZlciBjb25zZXJ2YXRpdmUgdmFsdWUgZm9yIGgxKS4NCg0KSG93ZXZlciB0aGlzIGFuYWx5c2lzIHN1Z2dlc3RzIGl0IHdpbGwgYmUgZGlmZmljdWx0IHRvIGdhaW4gcG93ZXIgZm9yIHRoaXMgaW50ZXJhY3Rpb24uIE9uIHRoZSBvdGhlciBoYW5kLCBwcmV2aW91cyBhbmFseXNlcyBtYXkgbWFrZSBpdCBjbGVhciB0aGF0IHRoZXJlIGlzIG5vIGltcHJvdmVtZW50IG9uIHRoaXMgdGVzdCBpbiBFSVRIRVIgY29uZGl0aW9uIChzZWUgUHJlZGljdGlvbiAxIGFib3ZlKS4gSW4gdGhhdCB0aGF0IGl0IG1heSBiZSB2ZXJ5IGRpZmZpY3VsdCB0byBwb3dlciB0aGlzLiBPbmUgcG9zc2liaWxpdHkgaXMgdGhhdCB3ZSB3b24ndCBoYXZlIHBvd2VyIGZvciB0aGUgaW50ZXJhY3Rpb24gYnV0IHdpbGwgaGF2ZSBwb3dlciB0byBzYXkgd2UgaGF2ZSAgZXZpZGVuY2UgZm9yIGxlYXJuaW5nIGluIG9uZSBjb25kaXRpb24sIGJ1dCBmb3IgdGhlIG90aGVyIHRoZXJlIGlzIG1vcmUgZXZpZGVuY2UgZm9yIHRoZSBudWxsIHRoYW4gZm9yIEgxIGJhc2VkIG9uIHRoYXQgY29uZGl0aW9uLiANCg0KDQojIFdvcmQgcmVwZXRpdGlvbg0KDQpUaGlzIHRlc3QgaXMgZ2l2ZW4gcHJlIGFuZCBwb3N0LiBDaGlsZHJlbiBoZWFyIGEgd29yZCBhbmQgY29weSBpdCBiYWNrLiBXZSBsb29rIHRvIHNlZSBpZiB0aGV5IHJlcGVhdCBiYWNrIHRoZSB0b25lIGNvcnJlY3RseSAodGhleSB3aWxsIGJlIGNvZGVkIGJ5IG5hdGl2ZSBzcGVha2VycyB3aG8gYmxpbmQgYXMgdG8gYm90aCBjb25kaXRpb24gYW5kIHdoYXQgdGhlIHRhcmdldCB3b3JkIGlzOyAgdGhlIHRvbmUgb2YgdGhlIHRyYW5zY3JpYmVkIHdvcmQgd2lsbCBjb21wYXJlZCB0byB0b25lIG9mIHRhcmdldCBhbmQgdGh1cyBjb2RlZCBhcyBjb3JyZWN0L2luY29ycmVjdCkuDQoNClRoZXJlIGFyZSBlcXVhbCBudW1iZXIgb2Ygd29yZHMgZm9yIGVhY2ggb2YgdGhlIGZvdXIgdG9uZXMuDQoNCkZvciB0aGUgaW50aWFsIGRhdGEgc2V0IGNvbGxlY3RlZCwgd2lsbCBjb25zaWRlciBib3RoIHByZS10ZXN0IC0+IHBvc3R0ZXN0MSBhbmQgcHJlLXRlc3QgLT4gcG9zdC10ZXN0MiAoaWYgZXF1aXZhbGVudCByZXN1bHRzIG9idGFuZWQsIHN1YnNlcXVlbnRpbmcgdGVzdGluZyB3aWxsIGRyb3AgZmluYWwgdHdvIHNlc3Npb25zIC0gc2VlIG5vdGUgYWJvdmUpDQoNCg0KIyMgbG9hZCB1cCBhbmQgcnVuIGxtZXMgb24gcGlsb3QgZGF0YQ0KDQpUaGUgY2hpbGQgZGF0YSBiZWxvdyBjb21lIGZyb20gc2FtZSB0d28gc2Vzc2lvbiBzdHVkeSBhcyBwaWxvdCB0cmFuaW5nIGRhdGEvZGlzY3JpbSBkYXRhIChpLmUgIHdoZXJlIHRoZXkgd2VyZSB0cmFpbmVkIG9uIHN0aW11bGkgc2ltaWxhciB0byB0aGUgInBpY3R1cmUtb25seSIgY29uZGl0aW9uIGluIHRoZSBjdXJyZW50IHN0dWR5LikNCg0KDQpUaGUgYWR1bHQgZGF0YSBiZWxvdyBkbyBub3QgY29tZSBmcm9tIHRoZSBzYW1lIHR3byBkYXkgcGlsb3Qgc3R1ZHkgYXMgdGhlIG90aGVyIGFkdWx0IGRhdGEgdXNlZCBhYm92ZSAodGhhdCBzdHVkZW50IHByb2plY3QgZGlkbid0IGluY2x1ZGUgdGhpcyB0ZXN0KSwgYnV0IGluc3RlYWQgZnJvbSBhIG11Y2ggbG9uZ2VyIDkgc2Vzc2lvbiBleHBlcmltZW50IGNvbmR1Y3RlZCBieSBjdXJyZW50IFBoRCBzdHVkZW50LiBUaGVyZSB3YXMgbm8gY29udHJhc3Qgb2YgY29uZGl0aW9uIG9mIHRoZSB0eXBlIHJlbGV2YW50IHRvIHRoZSBjdXJyZW50IHN0dWR5IGluIHRoYXQgZGF0YS4gDQoNCk5vdGUgdGhhdCBmb3IgYm90aCBhZHVsdHMgYW5kIGNoaWxkcmVuIGluIHBpbG90IGV4cGVyaW1lbnRzIHVzaW5nIHRoaXMgdGVzdCAgd2UgaGFkIGJvdGggdHJhaW5lZCBhbmQgdW50cmFpbmVkIGl0ZW1zLiBGb3IgdGhpcyBleHBlcmltZW50IHdlIHVzZSBvbmx5IHVudHJhaW5lZCBpdGVtcyBpbiB0aGlpcyB0ZXN0IHNvIHdlIHJlbW92ZSB0aGUgdW50cmFpbmVkIGl0ZW1zIGZyb20gdGhlIGFuYWx5c2VzIGJlbG93Lg0KDQoNCmBgYHtyfQ0KDQpjaGlsZC53ciA9IHJlYWQuY3N2KCJraWRzd29yZHJlcF9jbGVhbi5jc3YiKQ0KYWR1bHQud3IgPSByZWFkLmNzdigiYWR1bHRzd29yZHJlcF9jbGVhbi5jc3YiKQ0KDQpjaGlsZC53ciA9IGRyb3BsZXZlbHMoc3Vic2V0KGNoaWxkLndyLCB3b3JkdHlwZSA9PSAibmV3IikpDQoNCmFkdWx0LndyID0gZHJvcGxldmVscyhzdWJzZXQoYWR1bHQud3IsIHdvcmR0eXBlID09ICJVbnRyYWluZWQiKSkNCg0KY2hpbGQud3IkcHJlX3Bvc3QgPSByZWxldmVsKGNoaWxkLndyJHByZV9wb3N0LCByZWYgPSAicHJlIikNCmFkdWx0LndyJHByZV9wb3N0ID0gcmVsZXZlbChhZHVsdC53ciRwcmVfcG9zdCwgcmVmID0gInByZSIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpjaGlsZC53ci43ID0gZHJvcGxldmVscyhzdWJzZXQoY2hpbGQud3IsIEFnZT09InlvdW5nIikpDQoNCmNoaWxkLndyLjcgPC0gbGl6Q2VudGVyKGNoaWxkLndyLjcsIGxpc3QoIkFnZSIsICJwcmVfcG9zdCIsImNvcnJlY3R0b25lIikpDQoNCmNoaWxkLndyLjcubW9kID0gZ2xtZXIgKHJlc3VsdHRvbmUgfg0KICAgICAgICAgICAgICAgICsgcHJlX3Bvc3QuY3QgDQogICAgICAgICAgICAgICAgKyBjb3JyZWN0dG9uZS5jdA0KICAgICAgICAgICAgICAgICsgKHByZV9wb3N0LmN0fHBhcnRpY2lwYW50bmFtZSksDQogICAgICAgICAgICAgICAgICBkYXRhID0gY2hpbGQud3IuNywgIGZhbWlseSA9IGJpbm9taWFsLCBjb250cm9sPWdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIikpDQoNCg0Kcm91bmQoc3VtbWFyeShjaGlsZC53ci43Lm1vZCkkY29lZmZpY2llbnRzLDMpDQoNCg0KYGBgDQoNCg0KDQoNCg0KYGBge3J9DQoNCmFkdWx0LndyIDwtIGxpekNlbnRlcihhZHVsdC53ciwgbGlzdCggInByZV9wb3N0IiwiY29ycmVjdHRvbmUiKSkNCg0KYWR1bHQud3IubW9kID0gZ2xtZXIgKHJlc3VsdHRvbmUgfg0KICAgICAgICAgICAgICAgICsgcHJlX3Bvc3QuY3QgDQogICAgICAgICAgICAgICAgKyBjb3JyZWN0dG9uZS5jdA0KICAgICAgICAgICAgICAgICsgKHByZV9wb3N0LmN0fHBhcnRpY2lwYW50bmFtZSksDQogICAgICAgICAgICAgICAgICBkYXRhID0gYWR1bHQud3IsICBmYW1pbHkgPSBiaW5vbWlhbCwgY29udHJvbD1nbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIpKQ0KDQoNCnJvdW5kKHN1bW1hcnkoYWR1bHQud3IubW9kKSRjb2VmZmljaWVudHMsMykNCg0KDQpgYGANCiMjIFByZWRpY3Rpb24xOiBJbXByb3ZlbWVudCBmcm9tIHByZS1wb3N0IHRlc3QgaW4gZWFjaCAgZWFjaCBjb25kaXRpb24NCg0KIyMjIEJhc2VkIG9uIA0KDQpCb3RoIGFkdWx0cyBhbmQgY2hpbGRyZW4gc2hvd2VkIHRoaXMgaW4gdGhlIHJlbGV2YW50IHBpbG90IHN0dWRpZXMNCg0KYWR1bHQgbWVhbiA6IGByIHJvdW5kKCB3aXRoKGFkdWx0LndyLCB0YXBwbHkocmVzdWx0dG9uZSwgbGlzdChwcmVfcG9zdCksIG1lYW4sIG5hLnJtPVQpKSAsMilgOw0KYWR1bHQgIGxvZyBvZGRzIChiZXRhIGZyb20gbG1lKTogYHIgc3VtbWFyeShhZHVsdC53ci5tb2QpJGNvZWZmaWNpZW50c1sicHJlX3Bvc3QuY3QiICwiRXN0aW1hdGUiXWA7DQphZHVsdCAgb2RkICAoZXhwKGJldGEpKWByIGV4cChzdW1tYXJ5KGFkdWx0LndyLm1vZCkkY29lZmZpY2llbnRzWyJwcmVfcG9zdC5jdCIgLCJFc3RpbWF0ZSJdKWANCg0KN3llYXIgbWVhbiA6YHIgcm91bmQoIHdpdGgoY2hpbGQud3IuNywgdGFwcGx5KHJlc3VsdHRvbmUsIGxpc3QocHJlX3Bvc3QpLCBtZWFuLCBuYS5ybT1UKSkgLDIpYDsNCjd5ZWFyICBsb2cgb2RkcyAoYmV0YSBmcm9tIGxtZSk6IGByIHN1bW1hcnkoY2hpbGQud3IuNy5tb2QpJGNvZWZmaWNpZW50c1sicHJlX3Bvc3QuY3QiICwiRXN0aW1hdGUiXWA7DQo3eWVhciAgb2RkICAoZXhwKGJldGEpKWByIGV4cChzdW1tYXJ5KGNoaWxkLndyLjcubW9kKSRjb2VmZmljaWVudHNbInByZV9wb3N0LmN0IiAsIkVzdGltYXRlIl0pYA0KDQojIyMgUGxhbm5lZCBBbmFseXNlczogRnJlcXVlbnRpc3QgDQpsbWUgbW9kZWwgc2ltaWxhciB0byB0aGF0IG9uIHBpbG90IGRhdGEgYWJvdmUgYnV0IHdpdGggZGF0YSBmcm9tIGJvdGggY29uZGl0aW9uczsgRml0IHNlcGFyYXRlIHNsb3BlcyBmb3IgcHJlLXBvc3QgaW4gZWFjaCBjb25kaXRpb24gDQoNCkZvciB0aGUgaW50aWFsIGRhdGEgc2V0IGNvbGxlY3RlZCBXZSB3aWxsIGRvIHRoaXMgYm90aCB0byBjb21wYXJlIHByZSB0ZXN0IHRvIHBvc3QtdGVzdCAxIGFuZCBwcmUtdGVzdCB0byBwb3N0LXRlc3QyIChzZWUgbm90ZXMgYWJvdmUpLg0KDQojIyMgUGxhbm5lZCBBbmFseXNlczogQkYgDQpTdW1tYXJ5IG9mIGRhdGEgZm9yIGVhY2ggY29uZGl0aW9uOiBtZWFuIGFuZCBzZSBmb3IgcHJlLXBvc3QgZnJvbSBsbWUNCnZhbHVlIHRvIGluZm9ybSBIMTogZXN0aW1hdGUgZnJvbSBhYm92ZSBwaWxvdCBkYXRhIGZvciBjaGlsZHJlbiBpLmUuIGByIHN1bW1hcnkoY2hpbGQud3IuNy5tb2QpJGNvZWZmaWNpZW50c1sicHJlX3Bvc3QuY3QiICwiRXN0aW1hdGUiXWANCg0KTk9URTogSWYgKGUuZy4pIHdlIGZpbmQgYW4gZWZmZWN0IGZvciBjb25kaXRpb24xLCB3ZSBjYW4gYWxzbyB1c2UgdGhlIGVzdGltYXRlIGZvciBzZXNzaW9uIGZvciB0aGF0IHRvIGluZm9ybSBIMSB3aGVuIGxvb2tpbmcgYXQgZGF0YSBmcm9tIGNvbmRpdGlvbjI7IGFuZCB2aWNlIHZlcnNhLiBUaGlzIGlzIGEgYmV0dGVyIGVzdGltYXRlIHNpbmNlIHRoZSBjb25kaXRpb25zIGFyZSBtb3JlIGNsb3NlbHkgbWF0Y2hlZCB0byBlYWNoIG90aGVyIHRoYW4gZWl0aGVyIGlzIHRvIHRoZSBwaWxvdCBkYXRhLw0KDQojIyMgUmVxdWlyZWQgc2FtcGxlIGFuYWx5c2VzDQojIyMjIEZyZXF1ZW50aXN0IFBvd2VyDQoNCk5vdGU6IHRoaXMgYW5hbHlzaXMgaW5jbHVkZWQgZm9yIGNvbXBsZXRlbmVzcyBidXQgaXMgbm90IHJlYWxseSByZWxldmFudCBzaW5jZSBpdCBpcyBiYXNlZCBvbiBhZHVsdCBkYXRhLiBJZiBjaGlsZHJlbiBkbyBzaG93IGFuIGVmZmVjdCwgaXQgaXMgbGlrZWx5IHNtYWxsZXIgYW5kIHRoZXkgd2lsbCBoYXZlIGxhcmdlciBTRSAgDQoNCjcNCmBgYHtyfQ0KZGF0YVMgPSB3aXRoKGRyb3BsZXZlbHMoY2hpbGQud3IuNyksIHRhcHBseShyZXN1bHR0b25lLGxpc3QocGFydGljaXBhbnRuYW1lLHByZV9wb3N0KSwgbWVhbiwgbmEucm09VCkpDQpkPSBjb2hlbnNEKHggPSBkYXRhU1ssMV0sIHkgPSBkYXRhU1ssMl0sIG1ldGhvZCA9ICJwYWlyZWQiKQ0KcHdyLnQudGVzdChuID0gTlVMTCwgZCA9IGQsIHNpZy5sZXZlbCA9IDAuMDUsIHBvd2VyID0gLjksICB0eXBlID0gYygicGFpcmVkIiksIGFsdGVybmF0aXZlID0gYyggImdyZWF0ZXIiKSkNCnB3ci50LnRlc3QobiA9IE5VTEwsIGQgPSBkLCBzaWcubGV2ZWwgPSAwLjA1LCBwb3dlciA9IC44LCAgdHlwZSA9IGMoInBhaXJlZCIpLCBhbHRlcm5hdGl2ZSA9IGMoICJncmVhdGVyIikpDQpwd3IudC50ZXN0KG4gPSBOVUxMLCBkID0gZCwgc2lnLmxldmVsID0gMC4wNSwgcG93ZXIgPSAuNywgIHR5cGUgPSBjKCJwYWlyZWQiKSwgYWx0ZXJuYXRpdmUgPSBjKCAiZ3JlYXRlciIpKQ0KDQpybShkYXRhUykNCnJtKGQpDQpgYGANCg0KU2FtcGxlIGVzdGltYXRpb24gc3VnZ2VzdHMgdGhhdCBOPTMzIHBlciBjb25kaXRpb24gZm9yIDkwJSBwb3dlci4NCg0KIyMjIyBSZXF1aXJlZCBzYW1wbGUgZm9yIEJGIGFuYWx5c2VzIGZyb20gcGlsb3QgZGF0YQ0KDQpOb3RlIHRoYXQgaGVyZSB3ZSB1c2UgdGhlIG1lYW4gZnJvbSB0aGUgYWR1bHQgcGlsb3QgZGF0YSBhZHVsdHMgdG8gaW5mb3JtIEgxICh3aGVyZWFzIGZvciBhY3R1YWwgYW5hbHlzZXMgd2Ugd2lsbCBiZSB1c2luZyB2YWx1ZSBmcm9tIHBpbG90IGRhdGEgd2l0aCA3IHllYXIgb2xkcyB0byBpbmZvcm0gSDEpDQpgYGB7cn0NCg0KbWVhbkJGID0gc3VtbWFyeShjaGlsZC53ci43Lm1vZCkkY29lZmZpY2llbnRzWyJwcmVfcG9zdC5jdCIgLCJFc3RpbWF0ZSJdDQpzZUJGID0gc3VtbWFyeShjaGlsZC53ci43Lm1vZCkkY29lZmZpY2llbnRzWyJwcmVfcG9zdC5jdCIgLCJTdGQuIEVycm9yIl0NCmgxbWVhbiA9IHN1bW1hcnkoYWR1bHQud3IubW9kKSRjb2VmZmljaWVudHNbInByZV9wb3N0LmN0IiAsIkVzdGltYXRlIl0NCg0KQmYoc2VCRiwgbWVhbkJGLCAgdW5pZm9ybSA9MCxtZWFub2Z0aGVvcnk9MCxzZHRoZW9yeT1oMW1lYW4sdGFpbD0xKQ0KDQoNCnJtKG1lYW5CRikNCnJtKHNlQkYpDQoNCmBgYA0KDQpXZSBoYXZlIHN1ZmZpY2llbnQgZXZpZGVuY2UgZnJvbSB0aGUgc2FtcGxlIG9mIE49MTUgY2hpbGRyZW4gZm9yIEgxLiANCg0KIyMgUHJlZGljdGlvbiAyOiBUaGVyZSB3aWxsIGJlIG1vcmUgaW1wcm92ZW1lbnQgaW4gb25lICBjb25kaXRpb24gYnkgcHJlLXBvc3QNCiMjIEJhc2VkIG9uIA0KV2UgaGF2ZSBubyBkYXRhIHRvIGJhc2UgdGhpcyBvbiBhcyB3ZSBoYXZlbid0IHByZXZpb3VzbHkgdXNlZCB0aGlzIHRlc3QgaW4gYW4gZXhwZXJpbWVudCBjb250cmFzdGluZyB0aGVzZSAob3Igc2ltaWxhcikgY29uZGl0aW9ucy4NCg0KSWYgdGhlIHByZXNlbmNlIG9mIHRoZSBkaWFjcml0aWNzIGJvb3N0cyBsZWFybmluZywgY2hpbGRyZW4gbWF5IGltcHJvdmUgbW9yZSBpbiB0aGUgZGlhY3J0aWNpcytwaWN0dXJlIGNvbmRpdGlvbi4NCg0KDQojIyMgUGxhbm5lZCBBbmFseXNlczogRnJlcXVlbnRpc3QgDQpsbWUgbW9kZWwgc2ltaWxhciB0byB0aGF0IG9uIHBpbG90IGRhdGEgYWJvdmUgYnV0IHdpdGggZGF0YSBmcm9tIGJvdGggY29uZGl0aW9uczsgbG9vayBmb3IgaW50ZXJhY3Rpb24gb2YgcHJlLXBvc3QgYW5kIGNvbmRpdGlvbg0KDQpGb3IgdGhlIGludGlhbCBkYXRhIHNldCBjb2xsZWN0ZWQgV3cgd2lsbCBkbyB0aGlzIGJvdGggdG8gY29tcGFyZSBwcmUgdGVzdCB0byBwb3N0LXRlc3QgMSBhbmQgcHJlLXRlc3QgdG8gcG9zdC10ZXN0MiAoc2VlIG5vdGVzIGFib3ZlKS4NCg0KIyMjIFBsYW5uZWQgQW5hbmx5c2VzOiBCRg0KU3VtbWFyeSBvZiBkYXRhIGZvciBlYWNoIGNvbmRpdGlvbjogbWVhbiBhbmQgc2UgZm9yIHByZS1wb3N0KmNvbmRpdGlvbiBmcm9tIGxtZQ0KdmFsdWUgdG8gaW5mb3JtIEgxOiBlc3RpbWF0ZSBmb3Igc2Vzc2lvbiBmcm9tIHRoZSBtb2RlbCB3aXRoIHRoZSBuZXcgZGF0YSAgKGkuZS4gc3VtbWFyeShuZXcuZGF0YSkkY29lZmZpY2llbnRzWyJwcmVfcG9zdC5jdCIgLCJFc3RpbWF0ZSJdYA0KDQpOb3RlOiB3ZSBvbmx5IGRvIHRoaXMgaWYgd2UgaGF2ZSBldmlkZW5jZSBvZiBhbiBlZmZlY3Qgb2YgcHJlLXBvc3QgaW4gYXQgbGVhc3Qgb25lIG9mIHRoZSBjb25kaXRpb25zLiBJZiB0aGV5IGRvbid0IGxlYXJuIGluIGVpdGhlciBjb25kaXRpb24gdGhlbiB0aGlzIHRlc3QgaXMgaW5hcHByb3ByaWF0ZS4NCg0KQWxzbyBub3RlIHRoYXQgdGhpcyB3aWxsIGJlIHJlbGF0aXZlbHkgY29uc2VydmF0aXZlIGVzdGltYXRlIGZvciBhIGxhcmdlIGRpZmZlcmVuY2UgaW4gaG93IG11Y2ggdGhlIGNvbmRpdGlvbnMgbGVhZCB0byBhIGNoYW5nZSBwcmUgdG8gcG9zdC4gDQoNCg0KIyMjIFJlcXVpcmVkIHNhbXBsZSBhbmFseXNlcw0KV2UgaGF2ZSBubyByZWxldmFudCBkYXRhIHRvIGNhbiBiYXNlIHRoaXMgb24gZm9yIGVpdGhlciBmcmVxdWVudGlzdCBvciBCRiBhbmFseXNlcy4gT25lIHBvc3NpYmlsaXR5IGlzIHRoYXQgd2Ugd29uJ3QgYmUgYWJsZSB0byBnZXQgYSBzdWZmaWNpZW50bHkgbGFyZ2Ugc2FtcGxlIHRvIGhhdmUgIHBvd2VyIGZvciB0aGlzIGludGVyYWN0aW9uLiBBcyBmb3Igb3RoZXIgdGVzdHMsIGhlcmUgd2UgbWF5IGhhdmUgdG8gZHJhdyB3aGF0ZXZlciBjb25jdWxzaW9uc2FyZSBwb3NzaWJsZSBiYXNlZCBvbiB3aGljaCBvZiB0aGUgY29uZGl0aW9ucyBpbmRpdmlkdWFsbHkgcHJvdmlkZXMgZXZpZGVuY2UgZm9yIEgxL0gwLg0K