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.
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.
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
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)
1 |
AB |
AB |
2 |
AB |
AB |
Counterbalanced:
(1+Condition|Subject) + (1+Condition|Item)
1 |
A |
B |
2 |
B |
A |
Subjects-within Condition:
(1|Subject) + (1+Condition|Item)
(subjects are nested in
condition)
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)
1 |
A |
B |
2 |
A |
B |
Items and subjects within condition:
(1|Subject) + (1|Item)
1 |
A |
|
2 |
|
B |
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
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
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)
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?
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%)
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
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
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
Convergence
Suggestions
- Barr et al., suggest you stepwise down the complexity of the random
effects until the model converges, for example:
- Maximal:
(1+cond|Subj)+(1+cond|Item)
(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
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)
Convergence
Suggestions
- Maximal:
(1+cond1*cond2|Subj)+(1+cond1*cond2|Item)
(1+cond1+cond2|Subj)+(1+cond1+cond2|Item)
: remove
interactions
(1+cond1+cond2||Subj)+(1+cond1+cond2||Item)
: remove
random correlations (one at a time)
(1+cond1+cond2||Subj)+(1+cond1||Item)
: remove random
slopes (try one at time) and/or also random correlations
- This is often trial and error as to which combination will work
- Again, Bates solution address some of these issues
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.
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=