1 Random Items (Stimulus)

Imagine you are running a study on attentional blink and you want to see if disturbing images cause a longer attentional blink depending on whether you warn the subjects of what they are about to see (A: Few Details, B: Many Details). You select a bunch of disturbing images, but the problem is that not all image types have the same effect. The multiple images within each condition, for whatever reason, yield a noisy response. For example, images of people eating bugs vs. people swimming in sewage maybe have the same mean rating of grossness in your norming study (asking lots of people to rate the items), but there is variance around those items. What happens if different levels of warnings influence the specific types of items? If we counterbalance our design, we can measure the effect of the condition on the items and subjects. The goal is to know that our condition is causing an effect on our subjects (not our items). We want to make sure our experiment generalizes over both subjects and items!

Barr et al., 2013 summarizes the ANOVA approach to detailing with subject and items. Items are not independent measures of the effect (like with subjects). Thus we violate independence (inflate Type 1 error). The solution was to run \(F_1\) ANOVA, where the random term was the subject and \(F_2\) where the random term was the items. You want a significant effect of your condition on both \(F_1\) and \(F_2\) ANOVA (Note, however: the more the effect varies across items/subjects the higher the risk of type I error). The solution to reducing Barr et al., 2013 proposed to reduce the type I error rate and increase the power (and run one analysis) is to use the maximal random structure.

2 Subjects and Items Maximal Structure

Counterbalanced Designs - All subjects saw all experimental conditions (A & B), and Items (1:6) but balanced across condition. Subjects saw condition A and B 3 times each.
Subject Items 1 Items 2 Items 3 Items 4 Items 5 Items 6
1 A B A B A B
2 B A B A B A
3 A B A B A B
4 B A B A B A
5 A B A B A B
6 B A B A B A
  • With this many repeats of the conditions, we can estimate the random effects around the items
  • For this type of design the maximal structure is (1+Condition|Subject) + (1+Condition|Item)
    • Crossed random effects
    • We will estimate the random slopes of condition per subject and per item

2.1 Applicable Designs

Random slopes per item only makes sense in specific designs (see Westfall et al., 2014)

Fully crossed: (1+Condition|Subject) + (1+Condition|Item) + (1|Subject:Item)
Subject Stimuli 1 Stimuli 2
1 AB AB
2 AB AB
Counterbalanced: (1+Condition|Subject) + (1+Condition|Item)
Subject Stimuli 1 Stimuli 2
1 A B
2 B A
Subjects-within Condition: (1|Subject) + (1+Condition|Item) (subjects are nested in condition)
Subject Stimuli 1 Stimuli 2
1 A A
2 B B

But not in these designs (as conditions are nested in items)

Items-within condition: (1+Condition|Subject) + (1|Item) (subjects are crossed with condition, but not items)
Subject Stimuli 1 Stimuli 2
1 A B
2 A B
Items and subjects within condition: (1|Subject) + (1|Item)
Subject Stimuli 1 Stimuli 2
1 A
2 B

2.2 Simulation

  • Simulate (using RePsychLing package functions Bates et al., 2015) where we set the \(H_0\) to be FALSE
  • We will examine the results By Subject and By Item for a Counterbalanced Design with 6 subjects and 6 items.
  • Simulation results in Download Data
  • Check our design
DataSim6<-read.csv("Mixed/DataSim6.csv")
mytable <- table(DataSim6$subj,DataSim6$item,DataSim6$cond) # A will be rows, B will be

  • It easier to see the variance per subject and per item sometimes as boxplots

2.2.1 Random Subjects

  • Fit only random intercepts of Subjects and random slopes of condition (1+cond|subj)
  • We will examine the ICC to see what subjects (level 2) capture
  • We will also predict model results and visually examine our fit
library(lme4)

Sub.Only.Fit<-lmer(resp~cond+(1+cond|subj),data=DataSim6,REML=FALSE)
sjstats::icc(Sub.Only.Fit)
DataSim6$S.Fitted<-predict(Sub.Only.Fit, newdata=DataSim6)
## [1] NA
  • Subjects alone is not doing a good job
  • Let’s see what the model predicts for subjects

  • Let’s see what the model predicts for items

  • Examine the model results

summary(Sub.Only.Fit)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: resp ~ cond + (1 + cond | subj)
##    Data: DataSim6
## 
##      AIC      BIC   logLik deviance df.resid 
##    148.6    157.7    -68.3    136.6       28 
## 
## Scaled residuals: 
##      Min       1Q   Median       3Q      Max 
## -1.72830 -0.60114 -0.01594  0.33334  2.35492 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev. Corr
##  subj     (Intercept) 0.000    0.000        
##           condB       1.529    1.237     NaN
##  Residual             2.755    1.660        
## Number of obs: 34, groups:  subj, 6
## 
## Fixed effects:
##             Estimate Std. Error      df t value Pr(>|t|)    
## (Intercept)   1.3007     0.4025 27.1785   3.231  0.00322 ** 
## condB        -3.9262     0.7622  9.1582  -5.151  0.00057 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Correlation of Fixed Effects:
##       (Intr)
## condB -0.528
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
  • We can see significant result on the fixed effect, but problems with the random correlations (which we will ignore for now)

2.2.2 Random Subjects & Items

  • Fit only random intercepts of Subjects & Items and random slopes of condition (1+cond|subj)+(1+cond|item)
  • We will examine the ICC to see what subjects & Items (level 2) captures
  • We will also predict model results and visually examine our fit
Sub.Items.Fit<-lmer(resp~cond+(1+cond|subj)+(1+cond|item),data=DataSim6,REML=FALSE)
sjstats::icc(Sub.Items.Fit)
DataSim6$SI.Fitted<-predict(Sub.Items.Fit, newdata=DataSim6)
## # Intraclass Correlation Coefficient
## 
##     Adjusted ICC: 0.782
##   Unadjusted ICC: 0.404
  • Subjects & Items are picking variance now
  • Let’s see what the model predicts for subjects

  • Let’s see what the model predicts for items

  • Examine the model results
summary(Sub.Items.Fit)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: resp ~ cond + (1 + cond | subj) + (1 + cond | item)
##    Data: DataSim6
## 
##      AIC      BIC   logLik deviance df.resid 
##    141.3    155.0    -61.6    123.3       25 
## 
## Scaled residuals: 
##      Min       1Q   Median       3Q      Max 
## -1.40501 -0.48644 -0.02899  0.53637  1.71396 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev. Corr 
##  subj     (Intercept) 0.3646   0.6039        
##           condB       0.6507   0.8067   0.60 
##  item     (Intercept) 1.1097   1.0534        
##           condB       3.2387   1.7996   -0.41
##  Residual             0.8199   0.9055        
## Number of obs: 34, groups:  subj, 6; item, 6
## 
## Fixed effects:
##             Estimate Std. Error      df t value Pr(>|t|)   
## (Intercept)   1.2363     0.5433  6.6570   2.275  0.05892 . 
## condB        -3.6968     0.8645  6.7724  -4.276  0.00396 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Correlation of Fixed Effects:
##       (Intr)
## condB -0.275
  • We see a drop in the t-value from the subjects only model

2.3 Maximal Random Structure vs Simpler Random effects (Counterbalanced Designs)

  • Question is all this complexity needed? Can’t we do an intercepts only model, ignore items, or simply go back to our ANOVA?

2.3.1 Type I Error

  • Barr et al, 2013 have found that type I error is extremely high when we ignore maximal structure
  • To show this, I simulated a larger design (24 subjects and 24 items in a 2 level counterbalanced design) 1K times with \(H_0\) = TRUE. This means we can estimate the type I error rate of different types of fit. [Using RePsychLing Functions]
    • 5% of the data was allowed to be missing at random
  • See the results below read in from the Type1.csv file
    • When you set an intercept-only model (subject and/or items) your Type I error rate was nearly 60%
    • When you set a random slope & intercept model but only for subject or items your Type I error rate was nearly 20%
    • F1xF2 ANOVA was about 4.1% (with F1 or F2 alone being 11-14%)
    • The maximal model (1+cond|Subj+(1+cond|Item) yielded an acceptable Type 1 error rate of 5.9%, simply using the anticonservative method of |t| > 2 as the threshold for significance (more conservative methods for Pvalues will probably bring it below 5%)

2.3.2 Power Level

  • How does this complexity impact our power?
  • Barr et al, 2013 have found that power is reduced by having this complex structure, but in general is better than F1xF2 ANOVA
  • Same simulation as above, but this time \(H_0\) = FALSE. So we can calculate the number of times we get a significant effect
    • 5% of the data could be missing at random
  • See the results below read in from the Power.csv file
    • When you set an intercepts only model (subject and/or items) your power was nearly 96%
    • When you set random slopes & intercept model but only for subject or items your power was nearly 80%
    • F1xF2 ANOVA was about 41% (with F1 or F2 alone being 55-60%)
    • The maximal model (1+cond|Subj+(1+cond|Item) yielded a power of 63%, using |t| > 2 as the threshold for significance

  • All things being equal the Mixed Model > F1xF2 ANOVA (less Type 1 & Higher Power)
  • The mixed model will allow for more complex designs than ANOVA

2.4 Convergence & Optimation

  • Maximal modeling is the most complex random structure that you can apply to the data and it assumes that there is sufficient variance at the subjects and items (and for random slopes at both subjects and items) to sustain this model
    • In this case, your model will fail to converge: meaning it cannot estimate random effects (you will see lots of warning messages)
      • Usually, the problem is the random structure is too complex for the data
    • Sometimes this is optimization issue (the functions used to estimate model parameters) and not a problem with the random structure: https://github.com/lme4/lme4/issues/98
      • The functions can be changed and the models can be refit (but in my experience this often fails)
      • Optimization Options: There are options, but details are beyond are scope today, but here is an example of how to change them:
#https://github.com/lme4/lme4/issues/98
library(nloptr)
defaultControl <- list(algorithm="NLOPT_LN_BOBYQA",xtol_rel=1e-6,maxeval=1e5)
nloptwrap2 <- function(fn,par,lower,upper,control=list(),...) {
    for (n in names(defaultControl)) 
      if (is.null(control[[n]])) control[[n]] <- defaultControl[[n]]
    res <- nloptr(x0=par,eval_f=fn,lb=lower,ub=upper,opts=control,...)
    with(res,list(par=solution,
                  fval=objective,
                  feval=iterations,
                  conv=if (status>0) 0 else status,
                  message=message))
}
Sub.Items.Fit.N <- update(Sub.Items.Fit,control=lmerControl(optimizer="nloptwrap2"))
deviance(Sub.Items.Fit)-deviance(Sub.Items.Fit.N)
## [1] 6.150186e-08
  • another option:
library("optimx")
Sub.Items.Fit.O <-lmer(resp~cond+(1+cond|subj)+(1+cond|item),data=DataSim6,REML=FALSE,
     control = lmerControl(optimizer = "optimx", 
                           optCtrl = list(method = "nlminb",
                                          starttests = FALSE, kkt = FALSE)))
deviance(Sub.Items.Fit)-deviance(Sub.Items.Fit.O)
## [1] 6.150155e-08
  • In both cases, the fit has not improved

2.4.1 Convergence Suggestions

  • Barr et al., suggest you stepwise down the complexity of the random effects until the model converges, for example:
  1. Maximal: (1+cond|Subj)+(1+cond|Item)
  2. (1+cond||Subj)+(1+cond||Item): remove random correlations (try one at time) 3.(1+cond|Subj+(1|Item): remove random slopes (try one at time) and/or also random correlations 4.(1|Subj+(1|Item): remove all slopes (but Type I error galore!?)
  • We will return next week to Bates et al. criticisms of the Maximal approach and their solutions to keeping the random structure as complex as it needs to be

2.5 Maximal Structure for Multiple Repeated Factors

  • If you had multiple repeated factors, they need to be treated as random slopes as well:
    • (1+cond1*cond2|Subj)+(1+cond1*cond2|Item)
      • This means we will estimate 3 random slopes per subject and 3 more per item (and random correlations between them)
  • Everyone I have talked too finds this rarely converges
    • Also, this can be very slow (as you add more and more random effects the slower it will get)

2.5.1 Convergence Suggestions

  1. Maximal: (1+cond1*cond2|Subj)+(1+cond1*cond2|Item)
  2. (1+cond1+cond2|Subj)+(1+cond1+cond2|Item): remove interactions
  3. (1+cond1+cond2||Subj)+(1+cond1+cond2||Item): remove random correlations (one at a time)
  4. (1+cond1+cond2||Subj)+(1+cond1||Item): remove random slopes (try one at time) and/or also random correlations
  5. This is often trial and error as to which combination will work
  • Again, Bates solution address some of these issues

2.6 Maximal Structure & Non-Gaussian Distributions

If you use Logistic or Poisson you will encounter serious convergence issues, if a) you sample size is small or b) the number of items you have is small. Rarely do I find that maximal model fits. However, I also find the I must try many different optimizers.

3 Coding Types

Problem with categorical data is that how you code it affects your random effect estimation. The best suggestion is when you work with 2 level factors, convert them to -.5 and .5 and treat them like slopes! They are easiest to work with. Dummy coding can work equally as well, but you have to code it more carefully. We will go over that in the in-class assignment. See here for more details click here

LS0tDQp0aXRsZTogJ1N1YmplY3RzICYgSXRlbXM6IE1heGltYWwnDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgZm9udHNpemU6IDhwdA0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChjYWNoZT1UUlVFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gIEZBTFNFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy53aWR0aD00LjI1KQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5oZWlnaHQ9NC4wKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5hbGlnbj0nY2VudGVyJykgDQprbml0cjo6b3B0c19jaHVuayRzZXQocmVzdWx0cz0naG9sZCcpIA0KYGBgDQoNCiMgUmFuZG9tIEl0ZW1zIChTdGltdWx1cykNCkltYWdpbmUgeW91IGFyZSBydW5uaW5nIGEgc3R1ZHkgb24gYXR0ZW50aW9uYWwgYmxpbmsgYW5kIHlvdSB3YW50IHRvIHNlZSBpZiBkaXN0dXJiaW5nIGltYWdlcyBjYXVzZSBhIGxvbmdlciBhdHRlbnRpb25hbCBibGluayBkZXBlbmRpbmcgb24gd2hldGhlciB5b3Ugd2FybiB0aGUgc3ViamVjdHMgb2Ygd2hhdCB0aGV5IGFyZSBhYm91dCB0byBzZWUgKEE6IEZldyBEZXRhaWxzLCBCOiBNYW55IERldGFpbHMpLiBZb3Ugc2VsZWN0IGEgYnVuY2ggb2YgZGlzdHVyYmluZyBpbWFnZXMsIGJ1dCB0aGUgcHJvYmxlbSBpcyB0aGF0IG5vdCBhbGwgaW1hZ2UgdHlwZXMgaGF2ZSB0aGUgc2FtZSBlZmZlY3QuIFRoZSBtdWx0aXBsZSBpbWFnZXMgd2l0aGluIGVhY2ggY29uZGl0aW9uLCBmb3Igd2hhdGV2ZXIgcmVhc29uLCB5aWVsZCBhIG5vaXN5IHJlc3BvbnNlLiBGb3IgZXhhbXBsZSwgaW1hZ2VzIG9mIHBlb3BsZSBlYXRpbmcgYnVncyB2cy4gcGVvcGxlIHN3aW1taW5nIGluIHNld2FnZSBtYXliZSBoYXZlIHRoZSBzYW1lIG1lYW4gcmF0aW5nIG9mICpncm9zc25lc3MqIGluIHlvdXIgbm9ybWluZyBzdHVkeSAoYXNraW5nIGxvdHMgb2YgcGVvcGxlIHRvIHJhdGUgdGhlIGl0ZW1zKSwgYnV0IHRoZXJlIGlzIHZhcmlhbmNlIGFyb3VuZCB0aG9zZSBpdGVtcy4gV2hhdCBoYXBwZW5zIGlmIGRpZmZlcmVudCAqbGV2ZWxzIG9mIHdhcm5pbmdzKiBpbmZsdWVuY2UgdGhlIHNwZWNpZmljIHR5cGVzIG9mIGl0ZW1zPyBJZiB3ZSAqKmNvdW50ZXJiYWxhbmNlKiogb3VyIGRlc2lnbiwgd2UgY2FuIG1lYXN1cmUgdGhlIGVmZmVjdCBvZiB0aGUgY29uZGl0aW9uIG9uIHRoZSBpdGVtcyBhbmQgc3ViamVjdHMuIFRoZSBnb2FsIGlzIHRvIGtub3cgdGhhdCBvdXIgY29uZGl0aW9uIGlzIGNhdXNpbmcgYW4gZWZmZWN0IG9uIG91ciBzdWJqZWN0cyAobm90IG91ciBpdGVtcykuIFdlIHdhbnQgdG8gbWFrZSBzdXJlIG91ciBleHBlcmltZW50IGdlbmVyYWxpemVzIG92ZXIgYm90aCBzdWJqZWN0cyBhbmQgaXRlbXMhIA0KDQpCYXJyIGV0IGFsLiwgMjAxMyBzdW1tYXJpemVzIHRoZSBBTk9WQSBhcHByb2FjaCB0byBkZXRhaWxpbmcgd2l0aCBzdWJqZWN0IGFuZCBpdGVtcy4gSXRlbXMgYXJlIG5vdCBpbmRlcGVuZGVudCBtZWFzdXJlcyBvZiB0aGUgZWZmZWN0IChsaWtlIHdpdGggc3ViamVjdHMpLiBUaHVzIHdlIHZpb2xhdGUgaW5kZXBlbmRlbmNlIChpbmZsYXRlIFR5cGUgMSBlcnJvcikuIFRoZSBzb2x1dGlvbiB3YXMgdG8gcnVuICRGXzEkIEFOT1ZBLCB3aGVyZSB0aGUgcmFuZG9tIHRlcm0gd2FzIHRoZSBzdWJqZWN0IGFuZCAkRl8yJCB3aGVyZSB0aGUgcmFuZG9tIHRlcm0gd2FzIHRoZSBpdGVtcy4gWW91IHdhbnQgYSBzaWduaWZpY2FudCBlZmZlY3Qgb2YgeW91ciBjb25kaXRpb24gb24gKipib3RoKiogJEZfMSQgYW5kICRGXzIkIEFOT1ZBIChOb3RlLCBob3dldmVyOiB0aGUgbW9yZSB0aGUgZWZmZWN0IHZhcmllcyBhY3Jvc3MgaXRlbXMvc3ViamVjdHMgdGhlIGhpZ2hlciB0aGUgcmlzayBvZiB0eXBlIEkgZXJyb3IpLiAgIFRoZSBzb2x1dGlvbiB0byByZWR1Y2luZyBCYXJyIGV0IGFsLiwgMjAxMyBwcm9wb3NlZCB0byByZWR1Y2UgdGhlIHR5cGUgSSBlcnJvciByYXRlIGFuZCBpbmNyZWFzZSB0aGUgcG93ZXIgKGFuZCBydW4gb25lIGFuYWx5c2lzKSBpcyB0byB1c2UgdGhlICptYXhpbWFsIHJhbmRvbSBzdHJ1Y3R1cmUqLiANCg0KIyAgU3ViamVjdHMgYW5kIEl0ZW1zIE1heGltYWwgU3RydWN0dXJlDQoNCjogKipDb3VudGVyYmFsYW5jZWQgRGVzaWducyoqIC0gQWxsIHN1YmplY3RzIHNhdyBhbGwgZXhwZXJpbWVudGFsIGNvbmRpdGlvbnMgKEEgJiBCKSwgYW5kIEl0ZW1zICgxOjYpIGJ1dCBiYWxhbmNlZCBhY3Jvc3MgY29uZGl0aW9uLiBTdWJqZWN0cyBzYXcgY29uZGl0aW9uIEEgYW5kIEIgMyB0aW1lcyBlYWNoLiANCg0KU3ViamVjdCB8IEl0ZW1zIDEgIHwgSXRlbXMgMiAgIHwgSXRlbXMgMyAgIHwgSXRlbXMgNCAgIHwgSXRlbXMgNSAgIHwgSXRlbXMgNiANCi0tLS0tLS0gfCAtLS0tLS0tLSB8IC0tLS0tLS0tLSB8IC0tLS0tLS0tLSB8IC0tLS0tLS0tLSB8IC0tLS0tLS0tLSB8IC0tLS0tLS0tLQ0KMSAgICAgICB8IEEgICAgICAgIHwgQiAgICAgICAgIHwgQSAgICAgICAgIHwgQiAgICAgICAgIHwgIEEgICAgICAgIHwgQiAgICAgICAgICANCjIgICAgICAgfCBCICAgICAgICB8IEEgICAgICAgICB8IEIgICAgICAgICB8IEEgICAgICAgICB8ICBCICAgICAgICB8IEENCjMgICAgICAgfCBBICAgICAgICB8IEIgICAgICAgICB8IEEgICAgICAgICB8IEIgICAgICAgICB8ICBBICAgICAgICB8IEIgICAgICAgICANCjQgICAgICAgfCBCICAgICAgICB8IEEgICAgICAgICB8IEIgICAgICAgICB8IEEgICAgICAgICB8ICBCICAgICAgICB8IEENCjUgICAgICAgfCBBICAgICAgICB8IEIgICAgICAgICB8IEEgICAgICAgICB8IEIgICAgICAgICB8ICBBICAgICAgICB8IEIgICAgICAgICANCjYgICAgICAgfCBCICAgICAgICB8IEEgICAgICAgICB8IEIgICAgICAgICB8IEEgICAgICAgICB8ICBCICAgICAgICB8IEENCg0KDQotIFdpdGggdGhpcyBtYW55IHJlcGVhdHMgb2YgdGhlIGNvbmRpdGlvbnMsIHdlIGNhbiBlc3RpbWF0ZSB0aGUgcmFuZG9tIGVmZmVjdHMgYXJvdW5kIHRoZSBpdGVtcw0KLSBGb3IgdGhpcyB0eXBlIG9mIGRlc2lnbiB0aGUgbWF4aW1hbCBzdHJ1Y3R1cmUgaXMgYCgxK0NvbmRpdGlvbnxTdWJqZWN0KSArICgxK0NvbmRpdGlvbnxJdGVtKWANCiAgICAtIENyb3NzZWQgcmFuZG9tIGVmZmVjdHMNCiAgICAtIFdlIHdpbGwgZXN0aW1hdGUgdGhlIHJhbmRvbSBzbG9wZXMgb2YgY29uZGl0aW9uIHBlciBzdWJqZWN0IGFuZCBwZXIgaXRlbQ0KICAgIA0KIyMgQXBwbGljYWJsZSBEZXNpZ25zDQpSYW5kb20gc2xvcGVzIHBlciBpdGVtIG9ubHkgbWFrZXMgc2Vuc2UgaW4gc3BlY2lmaWMgZGVzaWducyAoc2VlICoqV2VzdGZhbGwgZXQgYWwuLCAyMDE0KiopDQoNCjogRnVsbHkgY3Jvc3NlZDogYCgxK0NvbmRpdGlvbnxTdWJqZWN0KSArICgxK0NvbmRpdGlvbnxJdGVtKSArICgxfFN1YmplY3Q6SXRlbSlgDQoNClN1YmplY3QgfCBTdGltdWxpIDF8IFN0aW11bGkgMg0KLS0tLS0tLSB8IC0tLS0tLS0tIHwgLS0tLS0tLS0NCjEgICAgICAgfCBBQiAgICAgICB8IEFCDQoyICAgICAgIHwgQUIgICAgICAgfCBBQg0KDQo6IENvdW50ZXJiYWxhbmNlZDogIGAoMStDb25kaXRpb258U3ViamVjdCkgKyAoMStDb25kaXRpb258SXRlbSlgDQoNClN1YmplY3QgfCBTdGltdWxpIDF8IFN0aW11bGkgMg0KLS0tLS0tLSB8IC0tLS0tLS0tIHwgLS0tLS0tLS0NCjEgICAgICAgfCBBICAgICAgICB8IEINCjIgICAgICAgfCBCICAgICAgICB8IEENCg0KOiBTdWJqZWN0cy13aXRoaW4gQ29uZGl0aW9uOiBgKDF8U3ViamVjdCkgKyAoMStDb25kaXRpb258SXRlbSlgIChzdWJqZWN0cyBhcmUgbmVzdGVkIGluIGNvbmRpdGlvbikNCg0KU3ViamVjdCB8IFN0aW11bGkgMXwgU3RpbXVsaSAyDQotLS0tLS0tIHwgLS0tLS0tLS0gfCAtLS0tLS0tLQ0KMSAgICAgICB8IEEgICAgICAgIHwgQQ0KMiAgICAgICB8IEIgICAgICAgIHwgQg0KDQoNCkJ1dCBub3QgaW4gdGhlc2UgZGVzaWducyAoYXMgY29uZGl0aW9ucyBhcmUgbmVzdGVkIGluIGl0ZW1zKQ0KDQo6IEl0ZW1zLXdpdGhpbiBjb25kaXRpb246IGAoMStDb25kaXRpb258U3ViamVjdCkgKyAoMXxJdGVtKWAgKHN1YmplY3RzIGFyZSBjcm9zc2VkIHdpdGggY29uZGl0aW9uLCBidXQgbm90IGl0ZW1zKQ0KDQpTdWJqZWN0IHwgU3RpbXVsaSAxfCBTdGltdWxpIDINCi0tLS0tLS0gfCAtLS0tLS0tLSB8IC0tLS0tLS0tDQoxICAgICAgIHwgQSAgICAgICAgfCBCDQoyICAgICAgIHwgQSAgICAgICAgfCBCDQoNCjogSXRlbXMgYW5kIHN1YmplY3RzIHdpdGhpbiBjb25kaXRpb246IGAoMXxTdWJqZWN0KSArICgxfEl0ZW0pYA0KDQpTdWJqZWN0IHwgU3RpbXVsaSAxfCBTdGltdWxpIDINCi0tLS0tLS0gfCAtLS0tLS0tLSB8IC0tLS0tLS0tDQoxICAgICAgIHwgQSAgICAgICAgfCANCjIgICAgICAgfCAgICAgICAgICB8IEINCg0KDQojIyBTaW11bGF0aW9uDQotIFNpbXVsYXRlICh1c2luZyBgUmVQc3ljaExpbmdgIHBhY2thZ2UgZnVuY3Rpb25zIEJhdGVzIGV0IGFsLiwgMjAxNSkgd2hlcmUgd2Ugc2V0IHRoZSAkSF8wJCB0byBiZSBGQUxTRQ0KLSBXZSB3aWxsIGV4YW1pbmUgdGhlIHJlc3VsdHMgKipCeSBTdWJqZWN0KiogYW5kICoqQnkgSXRlbSoqIGZvciBhIENvdW50ZXJiYWxhbmNlZCBEZXNpZ24gd2l0aCA2IHN1YmplY3RzIGFuZCA2IGl0ZW1zLiANCi0gU2ltdWxhdGlvbiByZXN1bHRzIGluIFtEb3dubG9hZCBEYXRhXSgvTWl4ZWQvRGF0YVNpbTYuY3N2KQ0KLSBDaGVjayBvdXIgZGVzaWduDQpgYGB7cn0NCkRhdGFTaW02PC1yZWFkLmNzdigiTWl4ZWQvRGF0YVNpbTYuY3N2IikNCm15dGFibGUgPC0gdGFibGUoRGF0YVNpbTYkc3ViaixEYXRhU2ltNiRpdGVtLERhdGFTaW02JGNvbmQpICMgQSB3aWxsIGJlIHJvd3MsIEIgd2lsbCBiZQ0KYGBgDQoNCg0KDQpgYGB7ciwgZWNobz1GQUxTRSxvdXQud2lkdGg9JzUwJScsIGZpZy5oZWlnaHQ9Mi41LGZpZy5zaG93PSdob2xkJyxmaWcuYWxpZ249J2NlbnRlcid9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCnRoZW1lX3NldCh0aGVtZV9idyhiYXNlX3NpemUgPSAxMiwgYmFzZV9mYW1pbHkgPSAiIikpIA0KYnlTdWJqZWN0IDwtZ2dwbG90KGRhdGEgPSBEYXRhU2ltNiwgYWVzKHggPSBjb25kLCB5PXJlc3ApKSsNCiAgZmFjZXRfd3JhcCh+c3ViaikrDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHN1Ymosc2hhcGUgPSBzdWJqKSkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGFlcyhncm91cD1zdWJqLGNvbG91ciA9IHN1YmopKSsNCiAgeWxhYigiUmVzcG9uc2UiKSt4bGFiKCJDb25kaXRpb24iKSsNCiAgIGdndGl0bGUoIkJ5IFN1YmplY3QiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmJ5U3ViamVjdA0KDQpieUl0ZW0gPC1nZ3Bsb3QoZGF0YSA9IERhdGFTaW02LCBhZXMoeCA9IGNvbmQsIHk9cmVzcCkpKw0KICBmYWNldF93cmFwKH5pdGVtKSsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gaXRlbSxzaGFwZSA9IGl0ZW0pKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgYWVzKGdyb3VwPWl0ZW0sY29sb3VyID0gaXRlbSkpKw0KICB5bGFiKCJSZXNwb25zZSIpK3hsYWIoIkNvbmRpdGlvbiIpKw0KICAgZ2d0aXRsZSgiQnkgSXRlbSIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYnlJdGVtDQpgYGANCg0KLSBJdCBlYXNpZXIgdG8gc2VlIHRoZSB2YXJpYW5jZSBwZXIgc3ViamVjdCBhbmQgcGVyIGl0ZW0gc29tZXRpbWVzIGFzIGJveHBsb3RzDQoNCmBgYHtyLCBlY2hvPUZBTFNFLG91dC53aWR0aD0nNTAlJywgZmlnLmhlaWdodD0yLjUsZmlnLnNob3c9J2hvbGQnLGZpZy5hbGlnbj0nY2VudGVyJ30NCg0KYnlTdWIuQm94IDwtZ2dwbG90KGRhdGEgPSBEYXRhU2ltNiwgYWVzKHggPSBzdWJqLCB5PXJlc3ApKSsNCiAgZ2VvbV9ib3hwbG90KGFlcyhmaWxsPWNvbmQpKSsNCiAgeWxhYigiUmVzcG9uc2UiKSt4bGFiKCJDb25kaXRpb24iKSsNCiAgIGdndGl0bGUoIkJ5IFN1YmplY3QiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpDQpieVN1Yi5Cb3gNCg0KYnlJdGVtLkJveCA8LWdncGxvdChkYXRhID0gRGF0YVNpbTYsIGFlcyh4ID0gaXRlbSwgeT1yZXNwKSkrDQogIGdlb21fYm94cGxvdChhZXMoZmlsbD1jb25kKSkrDQogIHlsYWIoIlJlc3BvbnNlIikreGxhYigiQ29uZGl0aW9uIikrDQogICBnZ3RpdGxlKCJCeSBJdGVtIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQ0KYnlJdGVtLkJveA0KYGBgDQoNCiMjIyBSYW5kb20gU3ViamVjdHMgDQotIEZpdCBvbmx5IHJhbmRvbSBpbnRlcmNlcHRzIG9mIFN1YmplY3RzIGFuZCByYW5kb20gc2xvcGVzIG9mIGNvbmRpdGlvbiBgKDErY29uZHxzdWJqKWANCi0gV2Ugd2lsbCBleGFtaW5lIHRoZSBJQ0MgdG8gc2VlIHdoYXQgc3ViamVjdHMgKGxldmVsIDIpIGNhcHR1cmUNCi0gV2Ugd2lsbCBhbHNvIHByZWRpY3QgbW9kZWwgcmVzdWx0cyBhbmQgdmlzdWFsbHkgZXhhbWluZSBvdXIgZml0DQoNCmBgYHtyfQ0KbGlicmFyeShsbWU0KQ0KDQpTdWIuT25seS5GaXQ8LWxtZXIocmVzcH5jb25kKygxK2NvbmR8c3ViaiksZGF0YT1EYXRhU2ltNixSRU1MPUZBTFNFKQ0Kc2pzdGF0czo6aWNjKFN1Yi5Pbmx5LkZpdCkNCkRhdGFTaW02JFMuRml0dGVkPC1wcmVkaWN0KFN1Yi5Pbmx5LkZpdCwgbmV3ZGF0YT1EYXRhU2ltNikNCmBgYA0KDQotIFN1YmplY3RzIGFsb25lIGlzIG5vdCBkb2luZyBhIGdvb2Qgam9iDQotIExldCdzIHNlZSB3aGF0IHRoZSBtb2RlbCBwcmVkaWN0cyBmb3Igc3ViamVjdHMNCg0KYGBge3IsIGVjaG89RkFMU0Usb3V0LndpZHRoPSc1MCUnLCBmaWcuaGVpZ2h0PTIuNSxmaWcuc2hvdz0naG9sZCcsZmlnLmFsaWduPSdjZW50ZXInfQ0KYnlTdWJqZWN0IDwtZ2dwbG90KGRhdGEgPSBEYXRhU2ltNiwgYWVzKHggPSBjb25kLCB5PXJlc3ApKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC02LDMpKSsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gc3ViaixzaGFwZSA9IHN1YmopKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgYWVzKGdyb3VwPXN1YmosY29sb3VyID0gc3ViaikpKw0KICB5bGFiKCJSZXNwb25zZSIpK3hsYWIoIkNvbmRpdGlvbiIpKw0KICAgIGdndGl0bGUoIlJhdyBNZWFucyIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYnlTdWJqZWN0DQoNCmJ5U3ViamVjdC5GaXQxIDwtZ2dwbG90KGRhdGEgPSBEYXRhU2ltNiwgYWVzKHggPSBjb25kLCB5PVMuRml0dGVkKSkrDQogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoLTYsMykpKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzdWJqLHNoYXBlID0gc3ViaikpKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBhZXMoZ3JvdXA9c3Viaixjb2xvdXIgPSBzdWJqKSkrDQogIHlsYWIoIk1vZGVsIFByZWRpY3RlZDogUmVzcG9uc2UiKSt4bGFiKCJDb25kaXRpb24iKSsNCiAgZ2d0aXRsZSgiUmFuZG9tOiAoMStjb25kfHN1YmopIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpieVN1YmplY3QuRml0MQ0KYGBgDQoNCi0gTGV0J3Mgc2VlIHdoYXQgdGhlIG1vZGVsIHByZWRpY3RzIGZvciBpdGVtcw0KYGBge3IsIGVjaG89RkFMU0Usb3V0LndpZHRoPSc1MCUnLCBmaWcuaGVpZ2h0PTIuNSxmaWcuc2hvdz0naG9sZCcsZmlnLmFsaWduPSdjZW50ZXInfQ0KYnlJdGVtPC1nZ3Bsb3QoZGF0YSA9IERhdGFTaW02LCBhZXMoeCA9IGNvbmQsIHk9cmVzcCkpKw0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoLTYsNCkpKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBpdGVtLHNoYXBlID0gaXRlbSkpKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBhZXMoZ3JvdXA9aXRlbSxjb2xvdXIgPSBpdGVtKSkrDQogIHlsYWIoIlJlc3BvbnNlIikreGxhYigiQ29uZGl0aW9uIikrDQogICAgZ2d0aXRsZSgiUmF3IE1lYW5zIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpieVN1YmplY3QNCg0KYnlJdGVtLkZpdDEgPC1nZ3Bsb3QoZGF0YSA9IERhdGFTaW02LCBhZXMoeCA9IGNvbmQsIHk9Uy5GaXR0ZWQpKSsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygtNiw0KSkrDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IGl0ZW0sc2hhcGUgPSBpdGVtKSkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGFlcyhncm91cD1pdGVtLGNvbG91ciA9IGl0ZW0pKSsNCiAgeWxhYigiTW9kZWwgUHJlZGljdGVkOiBSZXNwb25zZSIpK3hsYWIoIkNvbmRpdGlvbiIpKw0KICBnZ3RpdGxlKCJSYW5kb206KDErY29uZHxzdWJqKSIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYnlJdGVtLkZpdDENCmBgYA0KDQotIEV4YW1pbmUgdGhlIG1vZGVsIHJlc3VsdHMNCmBgYHtyfQ0Kc3VtbWFyeShTdWIuT25seS5GaXQpDQpgYGANCg0KLSBXZSBjYW4gc2VlIHNpZ25pZmljYW50IHJlc3VsdCBvbiB0aGUgZml4ZWQgZWZmZWN0LCBidXQgcHJvYmxlbXMgd2l0aCB0aGUgcmFuZG9tIGNvcnJlbGF0aW9ucyAod2hpY2ggd2Ugd2lsbCBpZ25vcmUgZm9yIG5vdykgDQoNCiMjIyBSYW5kb20gU3ViamVjdHMgJiBJdGVtcw0KLSBGaXQgb25seSByYW5kb20gaW50ZXJjZXB0cyBvZiBTdWJqZWN0cyAmIEl0ZW1zIGFuZCByYW5kb20gc2xvcGVzIG9mIGNvbmRpdGlvbiBgKDErY29uZHxzdWJqKSsoMStjb25kfGl0ZW0pYA0KLSBXZSB3aWxsIGV4YW1pbmUgdGhlIElDQyB0byBzZWUgd2hhdCBzdWJqZWN0cyAmIEl0ZW1zIChsZXZlbCAyKSBjYXB0dXJlcw0KLSBXZSB3aWxsIGFsc28gcHJlZGljdCBtb2RlbCByZXN1bHRzIGFuZCB2aXN1YWxseSBleGFtaW5lIG91ciBmaXQNCg0KYGBge3J9DQpTdWIuSXRlbXMuRml0PC1sbWVyKHJlc3B+Y29uZCsoMStjb25kfHN1YmopKygxK2NvbmR8aXRlbSksZGF0YT1EYXRhU2ltNixSRU1MPUZBTFNFKQ0Kc2pzdGF0czo6aWNjKFN1Yi5JdGVtcy5GaXQpDQpEYXRhU2ltNiRTSS5GaXR0ZWQ8LXByZWRpY3QoU3ViLkl0ZW1zLkZpdCwgbmV3ZGF0YT1EYXRhU2ltNikNCmBgYA0KDQotIFN1YmplY3RzICYgSXRlbXMgYXJlIHBpY2tpbmcgdmFyaWFuY2Ugbm93IA0KLSBMZXQncyBzZWUgd2hhdCB0aGUgbW9kZWwgcHJlZGljdHMgZm9yIHN1YmplY3RzDQoNCmBgYHtyLCBlY2hvPUZBTFNFLG91dC53aWR0aD0nNTAlJywgZmlnLmhlaWdodD0yLjUsZmlnLnNob3c9J2hvbGQnLGZpZy5hbGlnbj0nY2VudGVyJ30NCmJ5U3ViamVjdDwtZ2dwbG90KGRhdGEgPSBEYXRhU2ltNiwgYWVzKHggPSBjb25kLCB5PXJlc3ApKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC02LDQpKSsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gc3ViaixzaGFwZSA9IHN1YmopKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgYWVzKGdyb3VwPXN1YmosY29sb3VyID0gc3ViaikpKw0KICB5bGFiKCJSZXNwb25zZSIpK3hsYWIoIkNvbmRpdGlvbiIpKw0KICAgIGdndGl0bGUoIlJhdyBNZWFuc1xuIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpieVN1YmplY3QNCg0KYnlTdWJqZWN0LkZpdDI8LWdncGxvdChkYXRhID0gRGF0YVNpbTYsIGFlcyh4ID0gY29uZCwgeT1TSS5GaXR0ZWQpKSsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygtNiw0KSkrDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHN1Ymosc2hhcGUgPSBzdWJqKSkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGFlcyhncm91cD1zdWJqLGNvbG91ciA9IHN1YmopKSsNCiAgeWxhYigiTW9kZWwgUHJlZGljdGVkOiBSZXNwb25zZSIpK3hsYWIoIkNvbmRpdGlvbiIpKw0KICBnZ3RpdGxlKCJSYW5kb206KDErY29uZHxzdWJqKVxuKygxK2NvbmR8aXRlbXMpIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpieVN1YmplY3QuRml0Mg0KYGBgDQoNCi0gTGV0J3Mgc2VlIHdoYXQgdGhlIG1vZGVsIHByZWRpY3RzIGZvciBpdGVtcw0KDQpgYGB7ciwgZWNobz1GQUxTRSxvdXQud2lkdGg9JzUwJScsIGZpZy5oZWlnaHQ9Mi41LGZpZy5zaG93PSdob2xkJyxmaWcuYWxpZ249J2NlbnRlcid9DQpieUl0ZW08LWdncGxvdChkYXRhID0gRGF0YVNpbTYsIGFlcyh4ID0gY29uZCwgeT1yZXNwKSkrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW09YygtNiw0KSkrDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IGl0ZW0sc2hhcGUgPSBpdGVtKSkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGFlcyhncm91cD1pdGVtLGNvbG91ciA9IGl0ZW0pKSsNCiAgeWxhYigiUmVzcG9uc2UiKSt4bGFiKCJDb25kaXRpb24iKSsNCiAgICBnZ3RpdGxlKCJSYXcgTWVhbnNcbiIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYnlTdWJqZWN0DQoNCmJ5SXRlbS5GaXQyIDwtZ2dwbG90KGRhdGEgPSBEYXRhU2ltNiwgYWVzKHggPSBjb25kLCB5PVNJLkZpdHRlZCkpKw0KICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC02LDQpKSsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gaXRlbSxzaGFwZSA9IGl0ZW0pKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgYWVzKGdyb3VwPWl0ZW0sY29sb3VyID0gaXRlbSkpKw0KICB5bGFiKCJNb2RlbCBQcmVkaWN0ZWQ6IFJlc3BvbnNlIikreGxhYigiQ29uZGl0aW9uIikrDQogIGdndGl0bGUoIlJhbmRvbTooMStjb25kfHN1YmopXG4rKDErY29uZHxpdGVtcykiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmJ5SXRlbS5GaXQyDQpgYGANCg0KLSBFeGFtaW5lIHRoZSBtb2RlbCByZXN1bHRzDQoNCmBgYHtyfQ0Kc3VtbWFyeShTdWIuSXRlbXMuRml0KQ0KYGBgDQoNCi0gV2Ugc2VlIGEgZHJvcCBpbiB0aGUgdC12YWx1ZSBmcm9tIHRoZSBzdWJqZWN0cyBvbmx5IG1vZGVsDQoNCiMjIE1heGltYWwgUmFuZG9tIFN0cnVjdHVyZSB2cyBTaW1wbGVyIFJhbmRvbSBlZmZlY3RzIChDb3VudGVyYmFsYW5jZWQgRGVzaWducykNCi0gUXVlc3Rpb24gaXMgYWxsIHRoaXMgY29tcGxleGl0eSBuZWVkZWQ/IENhbid0IHdlIGRvIGFuIGludGVyY2VwdHMgb25seSBtb2RlbCwgaWdub3JlIGl0ZW1zLCBvciBzaW1wbHkgZ28gYmFjayB0byBvdXIgQU5PVkE/DQoNCiMjIyBUeXBlIEkgRXJyb3IgDQotIEJhcnIgZXQgYWwsIDIwMTMgaGF2ZSBmb3VuZCB0aGF0IHR5cGUgSSBlcnJvciBpcyBleHRyZW1lbHkgaGlnaCB3aGVuIHdlIGlnbm9yZSBtYXhpbWFsIHN0cnVjdHVyZQ0KLSBUbyBzaG93IHRoaXMsIEkgc2ltdWxhdGVkIGEgbGFyZ2VyIGRlc2lnbiAoMjQgc3ViamVjdHMgYW5kIDI0IGl0ZW1zIGluIGEgMiBsZXZlbCBjb3VudGVyYmFsYW5jZWQgZGVzaWduKSAxSyB0aW1lcyB3aXRoICAkSF8wJCA9IFRSVUUuIFRoaXMgbWVhbnMgd2UgY2FuIGVzdGltYXRlIHRoZSB0eXBlIEkgZXJyb3IgcmF0ZSBvZiBkaWZmZXJlbnQgdHlwZXMgb2YgZml0LiBbVXNpbmcgUmVQc3ljaExpbmcgRnVuY3Rpb25zXQ0KICAgIC0gNSUgb2YgdGhlIGRhdGEgd2FzIGFsbG93ZWQgdG8gYmUgbWlzc2luZyBhdCByYW5kb20gIA0KLSBTZWUgdGhlIHJlc3VsdHMgYmVsb3cgcmVhZCBpbiBmcm9tIHRoZSBgVHlwZTEuY3N2YCBmaWxlDQogICAgLSBXaGVuIHlvdSBzZXQgYW4gaW50ZXJjZXB0LW9ubHkgbW9kZWwgKHN1YmplY3QgYW5kL29yIGl0ZW1zKSB5b3VyIFR5cGUgSSBlcnJvciByYXRlIHdhcyBuZWFybHkgNjAlDQogICAgLSBXaGVuIHlvdSBzZXQgYSByYW5kb20gc2xvcGUgJiBpbnRlcmNlcHQgbW9kZWwgYnV0IG9ubHkgZm9yIHN1YmplY3Qgb3IgaXRlbXMgeW91ciBUeXBlIEkgZXJyb3IgcmF0ZSB3YXMgbmVhcmx5IDIwJQ0KICAgIC0gRjF4RjIgQU5PVkEgd2FzIGFib3V0IDQuMSUgKHdpdGggRjEgb3IgRjIgYWxvbmUgYmVpbmcgMTEtMTQlKQ0KICAgIC0gVGhlIG1heGltYWwgbW9kZWwgYCgxK2NvbmR8U3ViaisoMStjb25kfEl0ZW0pYCB5aWVsZGVkIGFuIGFjY2VwdGFibGUgVHlwZSAxIGVycm9yIHJhdGUgb2YgNS45JSwgc2ltcGx5IHVzaW5nIHRoZSBhbnRpY29uc2VydmF0aXZlIG1ldGhvZCBvZiB8KnQqfCA+IDIgYXMgdGhlIHRocmVzaG9sZCBmb3Igc2lnbmlmaWNhbmNlIChtb3JlIGNvbnNlcnZhdGl2ZSBtZXRob2RzIGZvciBQdmFsdWVzIHdpbGwgcHJvYmFibHkgYnJpbmcgaXQgYmVsb3cgNSUpDQogICAgDQoNCmBgYHtyLCBlY2hvPUZBTFNFLG91dC53aWR0aD0nNTAlJywgZmlnLmhlaWdodD0yLjUsZmlnLnNob3c9J2hvbGQnLGZpZy5hbGlnbj0nY2VudGVyJ30NCnRoZW1lX3NldCh0aGVtZV9idyhiYXNlX3NpemUgPSA5LCBiYXNlX2ZhbWlseSA9ICIiKSkNClR5cGUxPC1yZWFkLmNzdigiTWl4ZWQvVHlwZTFTdW1tYXJ5LmNzdiIpDQoNCk9yZGVyczwtYygiKDF8U3ViaikiLCIoMXxJdGVtKSIsIigxfFN1YmopXG4rKDF8SXRlbSkiLA0KICAgICAgICAgICAgICAgICAgICAgICIoMStjb25kfFN1YmopIiwiKDErY29uZHxJdGVtKSIsIigxK2NvbmR8U3ViailcbisoMXxJdGVtKSIsDQogICAgICAgICAgICAgICAgICAgICAgIigxfFN1YmopXG4rKDErY29uZHxJdGVtKSIsDQogICAgICAgICAgICAgICAgICAgICAgIigxK2NvbmR8U3ViailcbisoMStjb25kfEl0ZW0pIiwiRjFcbkFOT1ZBIiwiRjJcbkFOT1ZBIiwiRjF4RjJcbkFOT1ZBIikNCg0KVHlwZTEkUmFuZG9tRjwtZmFjdG9yKFR5cGUxJFJhbmRvbUYsIGxldmVscz1PcmRlcnMsbGFiZWxzPU9yZGVycykNCg0KZ2dwbG90KGRhdGEgPSBUeXBlMSxhZXMoUmFuZG9tRiwgbWVhblQpKSArDQogIGdlb21fY29sKGZpbGw9YyhyZXAoImdyZXk1MCIsNyksICJyZWQiLCAiZ3JleTUwIiwgImdyZXk1MCIsJ2JsdWUnKSkgKw0KICBnZ3RpdGxlKCJCYXIgUGxvdCBvZiAxSyBTaW11bGF0aW9uIG9mIEgwIikgKw0KICB4bGFiKCJSYW5kb20gRWZmZWN0cyIpICsNCiAgeWxhYigiVHlwZSBJIEVycm9yIFJhdGUiKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLjA1KQ0KDQpgYGANCg0KIyMjIFBvd2VyIExldmVsDQotIEhvdyBkb2VzIHRoaXMgY29tcGxleGl0eSBpbXBhY3Qgb3VyIHBvd2VyPw0KLSBCYXJyIGV0IGFsLCAyMDEzIGhhdmUgZm91bmQgdGhhdCBwb3dlciBpcyByZWR1Y2VkIGJ5IGhhdmluZyB0aGlzIGNvbXBsZXggc3RydWN0dXJlLCBidXQgaW4gZ2VuZXJhbCBpcyBiZXR0ZXIgdGhhbiBGMXhGMiBBTk9WQQ0KLSBTYW1lIHNpbXVsYXRpb24gYXMgYWJvdmUsIGJ1dCB0aGlzIHRpbWUgJEhfMCQgPSBGQUxTRS4gU28gd2UgY2FuIGNhbGN1bGF0ZSB0aGUgbnVtYmVyIG9mIHRpbWVzIHdlIGdldCBhIHNpZ25pZmljYW50IGVmZmVjdA0KICAgIC0gNSUgb2YgdGhlIGRhdGEgY291bGQgYmUgbWlzc2luZyBhdCByYW5kb20gIA0KLSBTZWUgdGhlIHJlc3VsdHMgYmVsb3cgcmVhZCBpbiBmcm9tIHRoZSBgUG93ZXIuY3N2YCBmaWxlDQogICAgLSBXaGVuIHlvdSBzZXQgYW4gaW50ZXJjZXB0cyBvbmx5IG1vZGVsIChzdWJqZWN0IGFuZC9vciBpdGVtcykgeW91ciBwb3dlciB3YXMgbmVhcmx5IDk2JQ0KICAgIC0gV2hlbiB5b3Ugc2V0IHJhbmRvbSBzbG9wZXMgJiBpbnRlcmNlcHQgbW9kZWwgYnV0IG9ubHkgZm9yIHN1YmplY3Qgb3IgaXRlbXMgeW91ciBwb3dlciB3YXMgbmVhcmx5IDgwJQ0KICAgIC0gRjF4RjIgQU5PVkEgd2FzIGFib3V0IDQxJSAod2l0aCBGMSBvciBGMiBhbG9uZSBiZWluZyA1NS02MCUpDQogICAgLSBUaGUgbWF4aW1hbCBtb2RlbCBgKDErY29uZHxTdWJqKygxK2NvbmR8SXRlbSlgIHlpZWxkZWQgYSBwb3dlciBvZiA2MyUsIHVzaW5nIHwqdCp8ID4gMiBhcyB0aGUgdGhyZXNob2xkIGZvciBzaWduaWZpY2FuY2UNCiAgDQoNCmBgYHtyLCBlY2hvPUZBTFNFLG91dC53aWR0aD0nNTAlJywgZmlnLmhlaWdodD0yLjUsZmlnLnNob3c9J2hvbGQnLGZpZy5hbGlnbj0nY2VudGVyJ30NClBvd2VyU2ltPC1yZWFkLmNzdigiTWl4ZWQvUG93ZXJTdW1tYXJ5LmNzdiIpDQpQb3dlclNpbSRSYW5kb21GPC1mYWN0b3IoUG93ZXJTaW0kUmFuZG9tRiwgbGV2ZWxzPU9yZGVycywgIGxhYmVscz1PcmRlcnMpDQpnZ3Bsb3QoZGF0YSA9IFBvd2VyU2ltLCBhZXMoUmFuZG9tRiwgbWVhblApKSArDQogIGdlb21fY29sKGZpbGw9YyhyZXAoImdyZXk1MCIsNyksICJyZWQiLCAiZ3JleTUwIiwgImdyZXk1MCIsJ2JsdWUnKSkgKw0KICBnZ3RpdGxlKCJCYXIgUGxvdCBvZiAxSyBTaW11bGF0aW9uIG9mIEgxIikgKw0KICB4bGFiKCJSYW5kb20gRWZmZWN0cyIpICsNCiAgeWxhYigiUG93ZXIiKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLjgwKSt0aGVtZV9idygpDQpgYGANCg0KLSBBbGwgdGhpbmdzIGJlaW5nIGVxdWFsIHRoZSBNaXhlZCBNb2RlbCA+IEYxeEYyIEFOT1ZBIChsZXNzIFR5cGUgMSAmIEhpZ2hlciBQb3dlcikNCi0gVGhlIG1peGVkIG1vZGVsIHdpbGwgYWxsb3cgZm9yIG1vcmUgY29tcGxleCBkZXNpZ25zIHRoYW4gQU5PVkENCiAgICAtIEZvciBhZGRpdGlvbmFsIHNpbXVsYXRpb24gc2VlIGh0dHA6Ly90YWxrbGFiLnBzeS5nbGEuYWMudWsvc2ltZ2VuLy4gDQogICAgLSBUaGV5IHByb3ZpZGUgZXh0ZW5zaXZlIHNpbXVsYXRpb24gd29yaw0KDQojIyBDb252ZXJnZW5jZSAmIE9wdGltYXRpb24NCi0gTWF4aW1hbCBtb2RlbGluZyBpcyB0aGUgbW9zdCBjb21wbGV4IHJhbmRvbSBzdHJ1Y3R1cmUgdGhhdCB5b3UgY2FuIGFwcGx5IHRvIHRoZSBkYXRhIGFuZCBpdCBhc3N1bWVzIHRoYXQgdGhlcmUgaXMgc3VmZmljaWVudCB2YXJpYW5jZSBhdCB0aGUgc3ViamVjdHMgYW5kIGl0ZW1zIChhbmQgZm9yIHJhbmRvbSBzbG9wZXMgYXQgYm90aCBzdWJqZWN0cyBhbmQgaXRlbXMpIHRvIHN1c3RhaW4gdGhpcyBtb2RlbA0KICAgIC0gSW4gdGhpcyBjYXNlLCB5b3VyIG1vZGVsIHdpbGwgZmFpbCB0byBjb252ZXJnZTogbWVhbmluZyBpdCBjYW5ub3QgZXN0aW1hdGUgcmFuZG9tIGVmZmVjdHMgKHlvdSB3aWxsIHNlZSBsb3RzIG9mIHdhcm5pbmcgbWVzc2FnZXMpDQogICAgICAgIC0gVXN1YWxseSwgdGhlIHByb2JsZW0gaXMgdGhlIHJhbmRvbSBzdHJ1Y3R1cmUgaXMgdG9vIGNvbXBsZXggZm9yIHRoZSBkYXRhDQogICAgLSBTb21ldGltZXMgdGhpcyBpcyBvcHRpbWl6YXRpb24gaXNzdWUgKHRoZSBmdW5jdGlvbnMgdXNlZCB0byBlc3RpbWF0ZSBtb2RlbCBwYXJhbWV0ZXJzKSBhbmQgbm90IGEgcHJvYmxlbSB3aXRoIHRoZSByYW5kb20gc3RydWN0dXJlOiBodHRwczovL2dpdGh1Yi5jb20vbG1lNC9sbWU0L2lzc3Vlcy85OA0KICAgICAgICAtICBUaGUgZnVuY3Rpb25zIGNhbiBiZSBjaGFuZ2VkIGFuZCB0aGUgbW9kZWxzIGNhbiBiZSByZWZpdCAoYnV0IGluIG15IGV4cGVyaWVuY2UgdGhpcyBvZnRlbiBmYWlscykNCiAgICAgICAgLSBPcHRpbWl6YXRpb24gT3B0aW9uczogVGhlcmUgYXJlIG9wdGlvbnMsIGJ1dCBkZXRhaWxzIGFyZSBiZXlvbmQgYXJlIHNjb3BlIHRvZGF5LCBidXQgaGVyZSBpcyBhbiBleGFtcGxlIG9mIGhvdyB0byBjaGFuZ2UgdGhlbTogDQoNCmBgYHtyfQ0KI2h0dHBzOi8vZ2l0aHViLmNvbS9sbWU0L2xtZTQvaXNzdWVzLzk4DQpsaWJyYXJ5KG5sb3B0cikNCmRlZmF1bHRDb250cm9sIDwtIGxpc3QoYWxnb3JpdGhtPSJOTE9QVF9MTl9CT0JZUUEiLHh0b2xfcmVsPTFlLTYsbWF4ZXZhbD0xZTUpDQpubG9wdHdyYXAyIDwtIGZ1bmN0aW9uKGZuLHBhcixsb3dlcix1cHBlcixjb250cm9sPWxpc3QoKSwuLi4pIHsNCiAgICBmb3IgKG4gaW4gbmFtZXMoZGVmYXVsdENvbnRyb2wpKSANCiAgICAgIGlmIChpcy5udWxsKGNvbnRyb2xbW25dXSkpIGNvbnRyb2xbW25dXSA8LSBkZWZhdWx0Q29udHJvbFtbbl1dDQogICAgcmVzIDwtIG5sb3B0cih4MD1wYXIsZXZhbF9mPWZuLGxiPWxvd2VyLHViPXVwcGVyLG9wdHM9Y29udHJvbCwuLi4pDQogICAgd2l0aChyZXMsbGlzdChwYXI9c29sdXRpb24sDQogICAgICAgICAgICAgICAgICBmdmFsPW9iamVjdGl2ZSwNCiAgICAgICAgICAgICAgICAgIGZldmFsPWl0ZXJhdGlvbnMsDQogICAgICAgICAgICAgICAgICBjb252PWlmIChzdGF0dXM+MCkgMCBlbHNlIHN0YXR1cywNCiAgICAgICAgICAgICAgICAgIG1lc3NhZ2U9bWVzc2FnZSkpDQp9DQpTdWIuSXRlbXMuRml0Lk4gPC0gdXBkYXRlKFN1Yi5JdGVtcy5GaXQsY29udHJvbD1sbWVyQ29udHJvbChvcHRpbWl6ZXI9Im5sb3B0d3JhcDIiKSkNCmRldmlhbmNlKFN1Yi5JdGVtcy5GaXQpLWRldmlhbmNlKFN1Yi5JdGVtcy5GaXQuTikNCmBgYA0KDQotIGFub3RoZXIgb3B0aW9uOg0KDQpgYGB7cn0NCmxpYnJhcnkoIm9wdGlteCIpDQpTdWIuSXRlbXMuRml0Lk8gPC1sbWVyKHJlc3B+Y29uZCsoMStjb25kfHN1YmopKygxK2NvbmR8aXRlbSksZGF0YT1EYXRhU2ltNixSRU1MPUZBTFNFLA0KICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gIm9wdGlteCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0Q3RybCA9IGxpc3QobWV0aG9kID0gIm5sbWluYiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydHRlc3RzID0gRkFMU0UsIGtrdCA9IEZBTFNFKSkpDQpkZXZpYW5jZShTdWIuSXRlbXMuRml0KS1kZXZpYW5jZShTdWIuSXRlbXMuRml0Lk8pDQpgYGANCg0KLSBJbiBib3RoIGNhc2VzLCB0aGUgZml0IGhhcyBub3QgaW1wcm92ZWQNCg0KIyMjIENvbnZlcmdlbmNlIFN1Z2dlc3Rpb25zDQotIEJhcnIgZXQgYWwuLCBzdWdnZXN0IHlvdSBzdGVwd2lzZSBkb3duIHRoZSBjb21wbGV4aXR5IG9mIHRoZSByYW5kb20gZWZmZWN0cyB1bnRpbCB0aGUgbW9kZWwgY29udmVyZ2VzLCBmb3IgZXhhbXBsZTogDQoNCjEuIE1heGltYWw6IGAoMStjb25kfFN1YmopKygxK2NvbmR8SXRlbSlgDQoyLiBgKDErY29uZHx8U3ViaikrKDErY29uZHx8SXRlbSlgOiByZW1vdmUgcmFuZG9tIGNvcnJlbGF0aW9ucyAodHJ5IG9uZSBhdCB0aW1lKQ0KMy5gKDErY29uZHxTdWJqKygxfEl0ZW0pYDogcmVtb3ZlIHJhbmRvbSBzbG9wZXMgKHRyeSBvbmUgYXQgdGltZSkgYW5kL29yIGFsc28gcmFuZG9tIGNvcnJlbGF0aW9ucw0KNC5gKDF8U3ViaisoMXxJdGVtKWA6IHJlbW92ZSBhbGwgc2xvcGVzIChidXQgVHlwZSBJIGVycm9yIGdhbG9yZSE/KQ0KDQotIFdlIHdpbGwgcmV0dXJuIG5leHQgd2VlayB0byBCYXRlcyBldCBhbC4gY3JpdGljaXNtcyBvZiB0aGUgTWF4aW1hbCBhcHByb2FjaCBhbmQgdGhlaXIgc29sdXRpb25zIHRvIGtlZXBpbmcgdGhlIHJhbmRvbSBzdHJ1Y3R1cmUgYXMgY29tcGxleCBhcyBpdCBuZWVkcyB0byBiZQ0KDQoNCiMjIE1heGltYWwgU3RydWN0dXJlIGZvciBNdWx0aXBsZSBSZXBlYXRlZCBGYWN0b3JzDQotIElmIHlvdSBoYWQgbXVsdGlwbGUgcmVwZWF0ZWQgZmFjdG9ycywgdGhleSBuZWVkIHRvIGJlIHRyZWF0ZWQgYXMgcmFuZG9tIHNsb3BlcyBhcyB3ZWxsOiAgIA0KICAgIC0gYCgxK2NvbmQxKmNvbmQyfFN1YmopKygxK2NvbmQxKmNvbmQyfEl0ZW0pYA0KICAgICAgICAtIFRoaXMgbWVhbnMgd2Ugd2lsbCBlc3RpbWF0ZSAzIHJhbmRvbSBzbG9wZXMgcGVyIHN1YmplY3QgYW5kIDMgbW9yZSBwZXIgaXRlbSAoYW5kIHJhbmRvbSBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0aGVtKQ0KLSBFdmVyeW9uZSBJIGhhdmUgdGFsa2VkIHRvbyBmaW5kcyAqKnRoaXMgcmFyZWx5IGNvbnZlcmdlcyoqDQogICAgLSBBbHNvLCB0aGlzIGNhbiBiZSB2ZXJ5IHNsb3cgKGFzIHlvdSBhZGQgbW9yZSBhbmQgbW9yZSByYW5kb20gZWZmZWN0cyB0aGUgc2xvd2VyIGl0IHdpbGwgZ2V0KSANCg0KIyMjIENvbnZlcmdlbmNlIFN1Z2dlc3Rpb25zDQoxLiBNYXhpbWFsOiBgKDErY29uZDEqY29uZDJ8U3ViaikrKDErY29uZDEqY29uZDJ8SXRlbSlgDQoyLiBgKDErY29uZDErY29uZDJ8U3ViaikrKDErY29uZDErY29uZDJ8SXRlbSlgOiByZW1vdmUgaW50ZXJhY3Rpb25zIA0KMy4gYCgxK2NvbmQxK2NvbmQyfHxTdWJqKSsoMStjb25kMStjb25kMnx8SXRlbSlgOiByZW1vdmUgcmFuZG9tIGNvcnJlbGF0aW9ucyAob25lIGF0IGEgdGltZSkNCjQuIGAoMStjb25kMStjb25kMnx8U3ViaikrKDErY29uZDF8fEl0ZW0pYDogcmVtb3ZlIHJhbmRvbSBzbG9wZXMgKHRyeSBvbmUgYXQgdGltZSkgYW5kL29yIGFsc28gcmFuZG9tIGNvcnJlbGF0aW9ucw0KNS4gVGhpcyBpcyBvZnRlbiB0cmlhbCBhbmQgZXJyb3IgYXMgdG8gd2hpY2ggY29tYmluYXRpb24gd2lsbCB3b3JrDQoNCi0gQWdhaW4sIEJhdGVzIHNvbHV0aW9uIGFkZHJlc3Mgc29tZSBvZiB0aGVzZSBpc3N1ZXMNCg0KIyMgTWF4aW1hbCBTdHJ1Y3R1cmUgJiBOb24tR2F1c3NpYW4gRGlzdHJpYnV0aW9ucw0KSWYgeW91IHVzZSBMb2dpc3RpYyBvciBQb2lzc29uIHlvdSB3aWxsIGVuY291bnRlciBzZXJpb3VzIGNvbnZlcmdlbmNlIGlzc3VlcywgaWYgYSkgeW91IHNhbXBsZSBzaXplIGlzIHNtYWxsIG9yIGIpIHRoZSBudW1iZXIgb2YgaXRlbXMgeW91IGhhdmUgaXMgc21hbGwuIFJhcmVseSBkbyBJIGZpbmQgdGhhdCBtYXhpbWFsIG1vZGVsIGZpdHMuIEhvd2V2ZXIsIEkgYWxzbyBmaW5kIHRoZSBJIG11c3QgdHJ5IG1hbnkgZGlmZmVyZW50IG9wdGltaXplcnMuICANCg0KDQoNCiMgQ29kaW5nIFR5cGVzDQpQcm9ibGVtIHdpdGggY2F0ZWdvcmljYWwgZGF0YSBpcyB0aGF0IGhvdyB5b3UgY29kZSBpdCBhZmZlY3RzIHlvdXIgcmFuZG9tIGVmZmVjdCBlc3RpbWF0aW9uLiBUaGUgYmVzdCBzdWdnZXN0aW9uIGlzIHdoZW4geW91IHdvcmsgd2l0aCAyIGxldmVsIGZhY3RvcnMsIGNvbnZlcnQgdGhlbSB0byAtLjUgYW5kIC41IGFuZCB0cmVhdCB0aGVtIGxpa2Ugc2xvcGVzISBUaGV5IGFyZSBlYXNpZXN0IHRvIHdvcmsgd2l0aC4gIER1bW15IGNvZGluZyBjYW4gd29yayBlcXVhbGx5IGFzIHdlbGwsIGJ1dCB5b3UgaGF2ZSB0byBjb2RlIGl0IG1vcmUgY2FyZWZ1bGx5LiBXZSB3aWxsIGdvIG92ZXIgdGhhdCBpbiB0aGUgaW4tY2xhc3MgYXNzaWdubWVudC4gU2VlIGhlcmUgZm9yIG1vcmUgZGV0YWlscyBbY2xpY2sgaGVyZV0od3d3LmFsZXhhbmRlcmRlbW9zLm9yZy9DbGFzczguaHRtbCkNCg0KDQo8c2NyaXB0Pg0KICAoZnVuY3Rpb24oaSxzLG8sZyxyLGEsbSl7aVsnR29vZ2xlQW5hbHl0aWNzT2JqZWN0J109cjtpW3JdPWlbcl18fGZ1bmN0aW9uKCl7DQogIChpW3JdLnE9aVtyXS5xfHxbXSkucHVzaChhcmd1bWVudHMpfSxpW3JdLmw9MSpuZXcgRGF0ZSgpO2E9cy5jcmVhdGVFbGVtZW50KG8pLA0KICBtPXMuZ2V0RWxlbWVudHNCeVRhZ05hbWUobylbMF07YS5hc3luYz0xO2Euc3JjPWc7bS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShhLG0pDQogIH0pKHdpbmRvdyxkb2N1bWVudCwnc2NyaXB0JywnaHR0cHM6Ly93d3cuZ29vZ2xlLWFuYWx5dGljcy5jb20vYW5hbHl0aWNzLmpzJywnZ2EnKTsNCg0KICBnYSgnY3JlYXRlJywgJ1VBLTkwNDE1MTYwLTEnLCAnYXV0bycpOw0KICBnYSgnc2VuZCcsICdwYWdldmlldycpOw0KDQo8L3NjcmlwdD4NCg0KDQo=