Longitudinal Designs
- Longitudinal generally means you measure a person over time. Thus,
the person is the level 2 (the cluster) and Time is the level 1.
- At least 3 measurements for that person: Longitudinal can be defined
in seconds, minutes, days, weeks, years, or decades.
- Time is repeated measure on the subject, but you are interested in
charting how they change over time
Mixed Model framework for Longitudinal
- Mixed models have some major advantages over RM ANOVA approach to
dealing with time
- Intercept differences: do different treatments have different
baselines
- Slope differences between treatments
- Growth curves: Are slopes linear or curvilinear
- 3a) Each subject can have a different slope and slope shape
- Time measurements do not need to be the same for each subject:
Subject 1: Month 1,2,4,6, Subject 2: Month 2,3,5,7
- 4a) This because you can have missing data in your measurements:
in RM ANOVA this would mean you lose the whole subject
- You test for discontinuities in time: For example, treatment changes
during the measurements (think elbow shaped slope)
- Subjects have 3 baselines: Month 1, 2, 3 and at Month 4 they start
treatment, and you have two more measurements. Thus you want to see if
the slope during no treatment for that subject changes after
treatment
- We can measure Time Fixed Covariates: Covariate
does not change over the measurement period (DV = Depression score at
each treatment, Covariate = Trait Anxiety level)
- We can measure Time Variable Covariates: Covariate
that change over the measurement period (DV = Depression score at each
treatment, Covariate = State Anxiety level during a therapy
session)
- Interact Time Fixed and Time Variable covariates
- You can control the covariance structure and use autoregressive
structures (but not in lme4)
- Deal with nested forms of Time: For example, month to month change
in Anxiety levels, but you can also examine hour to hour Anxiety levels
(nested in the month they were collected)
Simplest Type of Longitudinal Model
Children with ASD typically have difficulty with motor skill and poor
interpersonal coordination. Their reduced ability to coordinate with
people maybe be causing them to be left out of play with other children
isolating them. Past efforts to improve their interpersonal coordination
have often failed because children with ASD are overwhelmed by people.
So training sessions often fail. However, children with ASD gravitate
towards electronics and have been observed to be interested and
comfortable with robots. Srinivasan et al., (2015) hypothesized that
children with ASD might be better at coordinating with robots because a)
children with ASD love robots, and b) robots are less threatening as
they convey less information (not overwhelming the child). Srinivasan et
al., (2015) found that having children “dance” with dancing robots
improved their interpersonal coordination ability.
Today we will examine a simulated study of interpersonal coordination
on 12 children with ASD. Each child underwent 6 training sessions
(including the baseline where they had an ASD assessment to see where
they were on the spectrum; Chlebowski et al. 2010). The children were
asked to “dance” with an instructor and their parent in each of the 6
sessions. In the last part of the session their degree of coordination
(from 0 - 1) with the new instructor who was in the room during the
session, but did not dance. For half the children the instructor was
human, and for the other half, the instructor was a robot.
Data
- As with all our other analysis, the data is in long format (for
Longitudinal you might see it called period-period data)
- Time is coded to start at 0 (baseline or first measurement).
- Instructor (0,1): 0: Human; 1: Robot
- Coordination (0-1): Degree of coordination (DV)
- ASD: ASD spectrum score (possible covariate)
- Download data
LongSim<-read.csv("Mixed/LongData1.csv")
Subject
|
Time
|
Instructor
|
Coordination
|
ASD
|
1
|
0
|
0
|
0.2220880
|
26.07486
|
1
|
1
|
0
|
0.2780595
|
26.07486
|
1
|
2
|
0
|
0.2701741
|
26.07486
|
1
|
3
|
0
|
0.1431913
|
26.07486
|
1
|
4
|
0
|
0.4037957
|
26.07486
|
1
|
5
|
0
|
0.3261772
|
26.07486
|
Coding
- Decisions have to be made about how to code Instructor
- Dummy or effects code it? For today lets just dummy code our
treatment
#Dummy
LongSim$Instructor.D<-factor(LongSim$Instructor,
levels = c(0,1),
labels = c("Human","Robot"))
- Decisions have to be made about how to code Time. Each
again will change how we interpret our model. We will code it out now
for later:
- We can leave Time as is: it starts at 0 and progresses in
the units of measurements
- Center time Time: So there are 6 sessions (0-5), thus
center is 2.5: So Session # - 2.5
- (Note: yes you can Zscore time or Zscore and NOT center as
well)
# Centered
LongSim$Time.C<-scale(LongSim$Time, scale=F, center=T)[,]
Spaghetti Plots
- Longitudinal Models are best assessed with spaghetti plots. When you
have a small number of subjects, you can plot it as “facets.”
- We will plot each person in a facet and add their linear model for
each subject
# Make sure that subject is a factor
LongSim$Subject<-as.factor(LongSim$Subject)
Speg.1<-ggplot(data = LongSim, aes(x=Time,y=Coordination))+
facet_wrap(~Subject)+
geom_point(aes(color=Instructor.D))+
geom_smooth(method='lm', se=FALSE,aes(color=Instructor.D))+
xlab("Time")+ylab("Coordination")+
theme_bw()+
theme(legend.position = "top")
Speg.1
- If you have too many subjects, you can plot the results like this
instead
- On the left, you can fit a regression per subject, on the right you
plot lines instead of the slope
theme_set(theme_bw(base_size = 7, base_family = ""))
Speg.2<-ggplot(data = LongSim, aes(x=Time,y=Coordination, group=Subject, color=Subject))+
facet_wrap(~Instructor.D)+
geom_point()+
geom_smooth(method='lm', se=FALSE)+
xlab("Time")+ylab("Coordination")+
theme(legend.position = "none")
Speg.2
Speg.3<-ggplot(data = LongSim, aes(x=Time,y=Coordination, group=Subject, color=Subject))+
facet_wrap(~Instructor.D)+
geom_point()+
geom_line()+
xlab("Time")+ylab("Coordination")+
theme(legend.position = "none")
Speg.3
Modeling to Examine Random Structure
- The subject is the Level 2 variable (just like in our repeated
measures mixed models)
- We can show that via our ICC analysis
Intercepts only model
Null<-lmer(Coordination ~ 1+(1|Subject), data=LongSim, REML=FALSE)
sjstats::icc(Null)
## # Intraclass Correlation Coefficient
##
## Adjusted ICC: 0.420
## Unadjusted ICC: 0.420
Intercepts only plot
- Predict out the model results
- Dots = Real data
- Line = Predicted result
theme_set(theme_bw(base_size = 7, base_family = ""))
LongSim$Null<-predict(Null, newdata=LongSim)
Speg.Null.1<-ggplot(data = LongSim)+
facet_wrap(~Subject)+
geom_point(aes(x=Time,y=Coordination,color=Instructor.D))+
geom_line(aes(x=Time,y=Null, color=Instructor.D))+
xlab("Time")+ylab("Coordination")+
theme(legend.position = "top")
Speg.Null.1
Speg.Null.2<-ggplot(data = LongSim)+
facet_wrap(~Instructor.D)+
geom_point(aes(x=Time,y=Coordination, group=Subject,color=Subject))+
geom_line(aes(x=Time,y=Null,group=Subject,color=Subject))+
xlab("Time")+ylab("Coordination")+
theme(legend.position = "none")
Speg.Null.2
- Notice that each subject has their own intercept, but no slope
Random Intercepts and Slopes Model
- We will let the intercept and Time vary relative to each subject:
(1+Time|Subject)
- Note you can block the correlation between the slope/intercept like
before if the correlation is -1/1:
(1+Time||Subject)
RISlope<-lmer(Coordination ~ 1+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(RISlope)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ 1 + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -102.0 -90.6 56.0 -112.0 67
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.21989 -0.52703 0.01245 0.55970 2.00199
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.004804 0.06931
## Time 0.004751 0.06893 0.42
## Residual 0.005488 0.07408
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.26005 0.02481 12.00035 10.48 2.15e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Random Intercept and Slopes Plot
- Predict out the model results
- Dots = Real data
- Line = Predicted result
theme_set(theme_bw(base_size = 7, base_family = ""))
LongSim$RISlope<-predict(RISlope, newdata=LongSim)
Speg.R.I.Slope.1<-ggplot(data = LongSim)+
facet_wrap(~Subject)+
geom_point(aes(x=Time,y=Coordination, color=Instructor.D))+
geom_line(aes(x=Time,y=RISlope, color=Instructor.D))+
xlab("Time")+ylab("Coordination")+
theme(legend.position = "top")
Speg.R.I.Slope.1
Speg.R.I.Slope.2<-ggplot(data = LongSim)+
facet_wrap(~Instructor.D)+
geom_point(aes(x=Time,y=Coordination, group=Subject,color=Subject))+
geom_line(aes(x=Time,y=RISlope,group=Subject,color=Subject))+
xlab("Time")+ylab("Coordination")+
theme(legend.position = "none")
Speg.R.I.Slope.2
Random Slopes Only Model
- It could be there is no random intercept, so you can remove it (but
you need to have a reason)
- We will let Time vary relative to each subject:
(0+Time|Subject)
RSlope<-lmer(Coordination ~ 1+(0+Time|Subject), data=LongSim, REML=FALSE)
summary(RSlope)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ 1 + (0 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -99.3 -92.5 52.6 -105.3 69
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.54802 -0.53178 -0.00811 0.59543 2.92944
##
## Random effects:
## Groups Name Variance Std.Dev.
## Subject Time 0.005376 0.07332
## Residual 0.007289 0.08538
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.28463 0.01739 65.05840 16.36 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Random Slopes Only Plot
- Predict out the model results
- Dots = Real data
- Line = Predicted result
theme_set(theme_bw(base_size = 7, base_family = ""))
LongSim$RSlope<-predict(RSlope, newdata=LongSim)
Speg.R.Slope.1<-ggplot(data = LongSim)+
facet_wrap(Instructor.D~Subject)+
geom_point(aes(x=Time,y=Coordination, color=Instructor.D))+
geom_line(aes(x=Time,y=RSlope, color=Instructor.D))+
xlab("Time")+ylab("Coordination")+
theme(legend.position = "top")
Speg.R.Slope.1
Speg.R.Slope.2<-ggplot(data = LongSim)+
facet_wrap(~Instructor.D)+
geom_point(aes(x=Time,y=Coordination, group=Subject,color=Subject))+
geom_line(aes(x=Time,y=RSlope,group=Subject,color=Subject))+
xlab("Time")+ylab("Coordination")+
theme(legend.position = "none")
Speg.R.Slope.2
- Note: The intercepts for each subject are the same.
- You can also guess that this model will not be a good fit as the
last one, which we can test:
anova(RSlope,RISlope)
## Data: LongSim
## Models:
## RSlope: Coordination ~ 1 + (0 + Time | Subject)
## RISlope: Coordination ~ 1 + (1 + Time | Subject)
## npar AIC BIC logLik deviance Chisq Df Pr(>Chisq)
## RSlope 3 -99.287 -92.457 52.643 -105.29
## RISlope 5 -102.000 -90.617 56.000 -112.00 6.7134 2 0.03485 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Modeling for Results
- The goal above was to understand the random effects. This is useful
if you want to understand your data, but when you move to modeling for
publication you will want to set your random effects and move
to fixed effect testing
- The most obvious structure for most longitudinal (2 level) data is
to use random slopes and intercepts (watch that correlation between
them)
- We will now also explore the different coding schemes to understand
the models
Non-Centered Time & Dummy coded Instructor
- Note: because Instructor is 0/1 coded you can also enter that into
the model instead of it as a factor (you will get the same answer)
Main effects
MainEffect.1<-lmer(Coordination ~ Time+Instructor.D+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(MainEffect.1, correlation=FALSE)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ Time + Instructor.D + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -113.8 -97.9 63.9 -127.8 65
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.15774 -0.56020 0.04558 0.61775 1.91569
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.003360 0.05796
## Time 0.001327 0.03642 0.15
## Residual 0.005488 0.07408
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.23232 0.03206 12.08500 7.247 9.8e-06 ***
## Time 0.05852 0.01169 11.99995 5.005 0.000307 ***
## Instructor.DRobot 0.08358 0.04509 11.99994 1.854 0.088498 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Interpretation
- Time: After each session, the kids get are better
at coordinating regardless of Instruction (the estimate is the
slope over sessions)
- Instructor.DRobot: t < 1.96 (so not
significant). Had it been significant it would mean that kids who had
the robot instructor had overall higher coordination [averaged
over all session] (the estimate reported is the difference
between human and robot)
Interaction
Interaction.1<-lmer(Coordination ~ Time*Instructor.D+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(Interaction.1, correlation=F)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ Time * Instructor.D + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -115.5 -97.3 65.7 -131.5 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.17344 -0.56178 0.04976 0.64212 2.08058
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.0033241 0.05766
## Time 0.0008965 0.02994 0.25
## Residual 0.0054877 0.07408
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.23829 0.03214 12.00007 7.414 8.12e-06 ***
## Time 0.03777 0.01420 11.99972 2.660 0.0208 *
## Instructor.DRobot 0.07163 0.04546 12.00007 1.576 0.1411
## Time:Instructor.DRobot 0.04148 0.02008 11.99972 2.065 0.0612 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Interpretation
- Time: slope over sessions for kids who had the
human instructor.
- Instructor.DRobot: It is the difference between
human and robot when Time = 0 [Baseline].
- To prove this we can fit the model and subtract the fitted values:
Robot @ Time 0 - Human @ Time 0
library(effects)
effect(c("Time*Instructor.D"),Interaction.1)
Time
|
Instructor.D
|
fit
|
se
|
lower
|
upper
|
0
|
Human
|
0.2383
|
0.0321
|
0.1742
|
0.3024
|
1
|
Human
|
0.2761
|
0.0334
|
0.2093
|
0.3428
|
2
|
Human
|
0.3138
|
0.0401
|
0.2338
|
0.3938
|
4
|
Human
|
0.3894
|
0.0616
|
0.2665
|
0.5123
|
5
|
Human
|
0.4272
|
0.0741
|
0.2793
|
0.5751
|
0
|
Robot
|
0.3099
|
0.0321
|
0.2458
|
0.3741
|
1
|
Robot
|
0.3892
|
0.0334
|
0.3224
|
0.4559
|
2
|
Robot
|
0.4684
|
0.0401
|
0.3884
|
0.5484
|
4
|
Robot
|
0.6269
|
0.0616
|
0.5040
|
0.7499
|
5
|
Robot
|
0.7062
|
0.0741
|
0.5583
|
0.8541
|
- Estimate of **Instructor.DRobot**: 0.3099211 - 0.2382928 = 0.0716283
- Note: *You are missing the simple effect of Human @ Time 0*. Relevel instructor to test if you need to know.
- Time:Instructor.DRobot: slope over sessions
difference = slope @ robot instructor - slope @ human
instructor
Centered Time & Dummy coded Instructor
- Note: Because Instructor is 0/1 coded you can also enter that into
the model instead of it as factor (you will get the same answer)
Main effects
MainEffect.2<-lmer(Coordination ~ Time.C+Instructor.D+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(MainEffect.2, correlation=F)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ Time.C + Instructor.D + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -113.8 -97.9 63.9 -127.8 65
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.15774 -0.56020 0.04558 0.61775 1.91569
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.003360 0.05796
## Time 0.001327 0.03642 0.15
## Residual 0.005488 0.07408
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.37861 0.04105 14.18874 9.223 2.26e-07 ***
## Time.C 0.05852 0.01169 11.99995 5.005 0.000307 ***
## Instructor.DRobot 0.08358 0.04509 11.99994 1.854 0.088498 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Interaction
- Now things will change because the zero-point in time is now the
middle of the session (not the baseline)
Interaction.2<-lmer(Coordination ~ Time.C*Instructor.D+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(Interaction.2, correlation=F)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ Time.C * Instructor.D + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -115.5 -97.3 65.7 -131.5 64
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.17344 -0.56178 0.04976 0.64212 2.08058
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.0033241 0.05766
## Time 0.0008965 0.02994 0.25
## Residual 0.0054877 0.07408
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.33273 0.04476 11.99999 7.434 7.9e-06 ***
## Time.C 0.03777 0.01420 11.99972 2.660 0.0208 *
## Instructor.DRobot 0.17533 0.06329 11.99999 2.770 0.0170 *
## Time.C:Instructor.DRobot 0.04148 0.02008 11.99972 2.065 0.0612 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Interpretation
- Time: slope for kids who had the human
instructor.
- Instructor.DRobot: It is the difference between
human and robot when Time = 0. But remember Time 0 equals
the Middle Session!
- To prove this, we can fit the model and subtract the fitted values:
Robot @ Time 0 - Human @ Time 0 [Middle
session]
effect(c("Time.C*Instructor.D"),Interaction.2)
Time.C
|
Instructor.D
|
fit
|
se
|
lower
|
upper
|
-2
|
Human
|
0.2572
|
0.0320
|
0.1933
|
0.3211
|
-1
|
Human
|
0.2950
|
0.0362
|
0.2227
|
0.3672
|
0
|
Human
|
0.3327
|
0.0448
|
0.2434
|
0.4220
|
1
|
Human
|
0.3705
|
0.0556
|
0.2595
|
0.4816
|
2
|
Human
|
0.4083
|
0.0678
|
0.2730
|
0.5435
|
-2
|
Robot
|
0.3495
|
0.0320
|
0.2857
|
0.4134
|
-1
|
Robot
|
0.4288
|
0.0362
|
0.3565
|
0.5011
|
0
|
Robot
|
0.5081
|
0.0448
|
0.4188
|
0.5974
|
1
|
Robot
|
0.5873
|
0.0556
|
0.4763
|
0.6984
|
2
|
Robot
|
0.6666
|
0.0678
|
0.5313
|
0.8018
|
- Estimate of **Instructor.DRobot**: 0.5080641 - 0.3327298 = 0.1753344
- Time:Instructor.DRobot: slope over sessions
difference = slope @ robot instructor - slope @ human
instructor
Summary
- To center time or not center time?
- This all depends on what story you need to tell
- In the interaction model:
- if you don’t center time, you are talking about the baseline. In
this case, it seems very useful to be able to say the kids with ASD
started out at the same level of coordination and over time their slopes
changed
- if you center time you are talking about the middle session, I find
this less useful for the question at hand, but keep it in mind that you
can examine it this way
Plot our Final Model
- We can use the effects package and ggplot to plot the fitted
model
library(effects)
Fitted.I1<-effect(c("Time*Instructor.D"),Interaction.1)
Fitted.I1<-as.data.frame(Fitted.I1)
Fitted.Plot<-ggplot(data = Fitted.I1, aes(x=Time,y=fit, group=Instructor.D))+
geom_line(aes(color=Instructor.D))+
geom_ribbon(aes(ymin=lower,ymax=upper,fill=Instructor.D),alpha=.2)+
xlab("Session")+ylab("Coordination")+
scale_y_continuous(lim=c(0,1),breaks = seq(0, 1,.2)) +
theme_bw()+
theme(legend.position = c(.85,.875),
legend.title = element_blank(),
panel.grid.major = element_line(linetype = "blank"),
panel.grid.minor = element_line(linetype = "blank"))
Fitted.Plot
Fixed Covariates
- We had a covariate: each kids autism spectrum score.
- We can simply add it to our model if we want to control for it, but
you really should center it so you intercept does not change.
LongSim$ASD.C<-scale(LongSim$ASD, scale=F, center=T)[,]
- You can add it to your model just as any regression
Cov1.Model<-lmer(Coordination ~ Time*Instructor.D+ASD.C
+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(Cov1.Model, correlation=F)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ Time * Instructor.D + ASD.C + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -125.0 -104.5 71.5 -143.0 63
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.13957 -0.60777 0.05259 0.66668 1.77972
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.001085 0.03294
## Time 0.001052 0.03244 1.00
## Residual 0.004844 0.06960
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.2739315 0.0261886 18.4814776 10.460 3.39e-09 ***
## Time 0.0377748 0.0148838 12.3504929 2.538 0.025558 *
## Instructor.DRobot 0.0003509 0.0391905 19.1578812 0.009 0.992948
## ASD.C -0.0657266 0.0167110 25.5959845 -3.933 0.000569 ***
## Time:Instructor.DRobot 0.0414824 0.0210488 12.3504929 1.971 0.071583 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
Note: the correlation between the intercept and slope = 1, so
we should block that moving forward and we would go back and block it in
prior models to they are all have the same random structure. For now we
will ignore it and move on
anova(Interaction.1,Cov1.Model)
## Data: LongSim
## Models:
## Interaction.1: Coordination ~ Time * Instructor.D + (1 + Time | Subject)
## Cov1.Model: Coordination ~ Time * Instructor.D + ASD.C + (1 + Time | Subject)
## npar AIC BIC logLik deviance Chisq Df Pr(>Chisq)
## Interaction.1 8 -115.48 -97.265 65.739 -131.48
## Cov1.Model 9 -124.95 -104.462 71.476 -142.95 11.474 1 0.0007059 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
- Our slope is no longer significant, meaning the covariate might be
explaining some of our interaction at the mean level of ASD score. This
is suggestive of 3-way interaction.
Cov2.Model<-lmer(Coordination ~ Time*Instructor.D*ASD.C
+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(Cov2.Model, correlation=F)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ Time * Instructor.D * ASD.C + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -127.7 -100.4 75.9 -151.7 60
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.25728 -0.53957 -0.00054 0.73048 1.68226
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.0005812 0.02411
## Time 0.0004871 0.02207 1.00
## Residual 0.0047984 0.06927
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.290973 0.027451 25.063026 10.600 9.49e-11
## Time 0.042820 0.013615 13.221798 3.145 0.00761
## Instructor.DRobot -0.005657 0.037056 25.063026 -0.153 0.87989
## ASD.C -0.097154 0.028438 25.063026 -3.416 0.00217
## Time:Instructor.DRobot 0.051314 0.018379 13.221798 2.792 0.01506
## Time:ASD.C -0.009305 0.014105 13.221798 -0.660 0.52075
## Instructor.DRobot:ASD.C 0.051776 0.034086 25.063026 1.519 0.14128
## Time:Instructor.DRobot:ASD.C 0.036742 0.016906 13.221798 2.173 0.04849
##
## (Intercept) ***
## Time **
## Instructor.DRobot
## ASD.C **
## Time:Instructor.DRobot *
## Time:ASD.C
## Instructor.DRobot:ASD.C
## Time:Instructor.DRobot:ASD.C *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
anova(Cov1.Model,Cov2.Model)
## Data: LongSim
## Models:
## Cov1.Model: Coordination ~ Time * Instructor.D + ASD.C + (1 + Time | Subject)
## Cov2.Model: Coordination ~ Time * Instructor.D * ASD.C + (1 + Time | Subject)
## npar AIC BIC logLik deviance Chisq Df Pr(>Chisq)
## Cov1.Model 9 -124.95 -104.46 71.476 -142.95
## Cov2.Model 12 -127.74 -100.42 75.872 -151.74 8.7914 3 0.0322 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
- The three way improved the model fit.
- Time:Instructor.DRobot: is the slope over sessions
difference = slope @ robot instructor - slope @ human
instructor [@ at the average ASD level]
- Time:Instructor.DRobot:ASD.C: is the slope over
sessions difference = slope @ robot instructor - slope @
human instructor [as a function of ASD score]
- So the slope difference between robot and human instructor is
getting larger as ASD level increases. See the plot below to understand
this:
Plot 3-Way
- We will plot it like any other interaction in a regression involving
two continuous variables
- We will need to find 1 SD above/below the mean of the covariate
(which was mean centered)
SDN1<- -sd(LongSim$ASD.C)
SDP1<- +sd(LongSim$ASD.C)
Fitted.Cov2<-effect(c("Time*Instructor.D*ASD.C"),Cov2.Model,
xlevel=list(Time=seq(0,5,1),
ASD.C=c(SDN1,0,SDP1)))
Fitted.Cov2<-as.data.frame(Fitted.Cov2)
Fitted.Cov2$ASD<-factor(Fitted.Cov2$ASD.C,
levels=c(SDN1,0,SDP1),
labels=c("-1 SD ASD","Mean ASD","+1 SD ASD"))
Fitted.Plot.2<-ggplot(data = Fitted.Cov2, aes(x=Time,y=fit, group=Instructor.D))+
facet_grid(~ASD)+
geom_line(aes(color=Instructor.D))+
geom_ribbon(aes(ymin=lower,ymax=upper,fill=Instructor.D),alpha=.2)+
xlab("Session")+ylab("Coordination")+
scale_y_continuous(lim=c(0,1),breaks = seq(0, 1,.2)) +
theme_bw()+
theme(legend.position = c(.15,.85),
legend.title = element_blank(),
panel.grid.major = element_line(linetype = "blank"),
panel.grid.minor = element_line(linetype = "blank"))
Fitted.Plot.2
Test of Simple Interactions
- If you want to know if the interaction is significant at each level
of ASD score, you simply have to re-center the ASD. We already know the
middle plot was significant. We are going to watch the
Time:Instructor.DRobot terms as we change the center
point at ASD.C
Test -1 SD of ASD
- We move the center to be -1 SD by adding 1 SD
LongSim$ASD.N1sd<-LongSim$ASD.C+sd(LongSim$ASD.C)
Cov2.Model.Simple.N1sd<-lmer(Coordination ~ Time*Instructor.D*ASD.N1sd
+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(Cov2.Model.Simple.N1sd, correlation=F)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ Time * Instructor.D * ASD.N1sd + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -127.7 -100.4 75.9 -151.7 60
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.25728 -0.53957 -0.00054 0.73048 1.68226
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.0005812 0.02411
## Time 0.0004871 0.02207 1.00
## Residual 0.0047984 0.06927
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.404358 0.053652 25.063026 7.537 6.74e-08
## Time 0.053680 0.026610 13.221798 2.017 0.06444
## Instructor.DRobot -0.066083 0.059432 25.063026 -1.112 0.27673
## ASD.N1sd -0.097154 0.028438 25.063026 -3.416 0.00217
## Time:Instructor.DRobot 0.008433 0.029477 13.221798 0.286 0.77924
## Time:ASD.N1sd -0.009305 0.014105 13.221798 -0.660 0.52075
## Instructor.DRobot:ASD.N1sd 0.051776 0.034086 25.063026 1.519 0.14128
## Time:Instructor.DRobot:ASD.N1sd 0.036742 0.016906 13.221798 2.173 0.04849
##
## (Intercept) ***
## Time .
## Instructor.DRobot
## ASD.N1sd **
## Time:Instructor.DRobot
## Time:ASD.N1sd
## Instructor.DRobot:ASD.N1sd
## Time:Instructor.DRobot:ASD.N1sd *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
- Time:Instructor.DRobot is not significant. So the
left panel is our graph is not an interaction
Test +1 SD of ASD
- We move the center to be +1 SD by subtracting 1 SD
LongSim$ASD.P1sd<-LongSim$ASD.C-sd(LongSim$ASD.C)
Cov2.Model.Simple.P1sd<-lmer(Coordination ~ Time*Instructor.D*ASD.P1sd
+(1+Time|Subject), data=LongSim, REML=FALSE)
summary(Cov2.Model.Simple.P1sd, correlation=F)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
## method [lmerModLmerTest]
## Formula: Coordination ~ Time * Instructor.D * ASD.P1sd + (1 + Time | Subject)
## Data: LongSim
##
## AIC BIC logLik deviance df.resid
## -127.7 -100.4 75.9 -151.7 60
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.25728 -0.53957 -0.00054 0.73048 1.68226
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## Subject (Intercept) 0.0005812 0.02411
## Time 0.0004871 0.02207 1.00
## Residual 0.0047984 0.06927
## Number of obs: 72, groups: Subject, 12
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 0.177587 0.028836 25.063027 6.159 1.92e-06
## Time 0.031961 0.014302 13.221798 2.235 0.04330
## Instructor.DRobot 0.054770 0.048776 25.063027 1.123 0.27213
## ASD.P1sd -0.097154 0.028438 25.063027 -3.416 0.00217
## Time:Instructor.DRobot 0.094195 0.024192 13.221798 3.894 0.00179
## Time:ASD.P1sd -0.009305 0.014105 13.221798 -0.660 0.52075
## Instructor.DRobot:ASD.P1sd 0.051776 0.034086 25.063027 1.519 0.14128
## Time:Instructor.DRobot:ASD.P1sd 0.036742 0.016906 13.221798 2.173 0.04849
##
## (Intercept) ***
## Time *
## Instructor.DRobot
## ASD.P1sd **
## Time:Instructor.DRobot **
## Time:ASD.P1sd
## Instructor.DRobot:ASD.P1sd
## Time:Instructor.DRobot:ASD.P1sd *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
- Time:Instructor.DRobot is significant (as it has to
be). So the right panel in our graph is an interaction.
- In summary, our two way interaction changes as function of ASD
score
References
Chlebowski, C., Green, J. A., Barton, M. L., & Fein, D. (2010).
Using the childhood autism rating scale to diagnose autism spectrum
disorders. Journal of autism and developmental disorders,
40(7), 787-799.
Srinivasan, S. M., Kaur, M., Park, I. K., Gifford, T. D., Marsh, K.
L., & Bhat, A. N. (2015). The effects of rhythm and robotic
interventions on the imitation/praxis, interpersonal synchrony, and
motor performance of children with autism spectrum disorder (ASD): a
pilot randomized controlled trial. Autism research and
treatment.
LS0tDQp0aXRsZTogJ0xvbmdpdHVkaW5hbCcNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBmb250c2l6ZTogOHB0DQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0aGVtZTogZmxhdGx5DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IG5vDQotLS0NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChjYWNoZSA9IFRSVUUpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEZBTFNFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmcgPSAgRkFMU0UpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTQuMjUpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLmhlaWdodD00LjApDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLmFsaWduPSdjZW50ZXInKSANCmtuaXRyOjpvcHRzX2NodW5rJHNldChyZXN1bHRzPSdob2xkJykgDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGxtZTQpDQpgYGANCg0KIyBMb25naXR1ZGluYWwgRGVzaWducw0KLSBMb25naXR1ZGluYWwgZ2VuZXJhbGx5IG1lYW5zIHlvdSBtZWFzdXJlIGEgcGVyc29uIG92ZXIgdGltZS4gVGh1cywgdGhlIHBlcnNvbiBpcyB0aGUgbGV2ZWwgMiAodGhlIGNsdXN0ZXIpIGFuZCBUaW1lIGlzIHRoZSBsZXZlbCAxLg0KICAgIC0gQXQgbGVhc3QgMyBtZWFzdXJlbWVudHMgZm9yIHRoYXQgcGVyc29uOiBMb25naXR1ZGluYWwgY2FuIGJlIGRlZmluZWQgaW4gc2Vjb25kcywgbWludXRlcywgZGF5cywgd2Vla3MsIHllYXJzLCBvciBkZWNhZGVzLg0KICAgIC0gVGltZSBpcyByZXBlYXRlZCBtZWFzdXJlIG9uIHRoZSBzdWJqZWN0LCBidXQgeW91IGFyZSBpbnRlcmVzdGVkIGluIGNoYXJ0aW5nIGhvdyB0aGV5IGNoYW5nZSBvdmVyIHRpbWUNCiAgICANCiMgTWl4ZWQgTW9kZWwgZnJhbWV3b3JrIGZvciBMb25naXR1ZGluYWwNCi0gTWl4ZWQgbW9kZWxzIGhhdmUgc29tZSBtYWpvciBhZHZhbnRhZ2VzIG92ZXIgUk0gQU5PVkEgYXBwcm9hY2ggdG8gZGVhbGluZyB3aXRoIHRpbWUNCiAgICAtIDEpIEludGVyY2VwdCBkaWZmZXJlbmNlczogZG8gZGlmZmVyZW50IHRyZWF0bWVudHMgaGF2ZSBkaWZmZXJlbnQgYmFzZWxpbmVzIA0KICAgIC0gMikgU2xvcGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0cmVhdG1lbnRzDQogICAgLSAzKSBHcm93dGggY3VydmVzOiBBcmUgc2xvcGVzIGxpbmVhciBvciBjdXJ2aWxpbmVhcg0KICAgICAgICAtIDNhKSBFYWNoIHN1YmplY3QgY2FuIGhhdmUgYSBkaWZmZXJlbnQgc2xvcGUgYW5kIHNsb3BlIHNoYXBlIA0KICAgIC0gNCkgVGltZSBtZWFzdXJlbWVudHMgZG8gbm90IG5lZWQgdG8gYmUgdGhlIHNhbWUgZm9yIGVhY2ggc3ViamVjdDogU3ViamVjdCAxOiBNb250aCAxLDIsNCw2LCBTdWJqZWN0IDI6IE1vbnRoIDIsMyw1LDcNCiAgICAgICAgLSA0YSkgKlRoaXMgYmVjYXVzZSB5b3UgY2FuIGhhdmUgbWlzc2luZyBkYXRhIGluIHlvdXIgbWVhc3VyZW1lbnRzOiBpbiBSTSBBTk9WQSB0aGlzIHdvdWxkIG1lYW4geW91IGxvc2UgdGhlIHdob2xlIHN1YmplY3QqIA0KICAgIC0gNSkgWW91IHRlc3QgZm9yIGRpc2NvbnRpbnVpdGllcyBpbiB0aW1lOiBGb3IgZXhhbXBsZSwgdHJlYXRtZW50IGNoYW5nZXMgZHVyaW5nIHRoZSBtZWFzdXJlbWVudHMgKHRoaW5rIGVsYm93IHNoYXBlZCBzbG9wZSkgDQogICAgICAgIC0gU3ViamVjdHMgaGF2ZSAzIGJhc2VsaW5lczogTW9udGggMSwgMiwgMyBhbmQgYXQgTW9udGggNCB0aGV5IHN0YXJ0IHRyZWF0bWVudCwgYW5kIHlvdSBoYXZlIHR3byBtb3JlIG1lYXN1cmVtZW50cy4gVGh1cyB5b3Ugd2FudCB0byBzZWUgaWYgdGhlIHNsb3BlIGR1cmluZyBubyB0cmVhdG1lbnQgZm9yIHRoYXQgc3ViamVjdCBjaGFuZ2VzIGFmdGVyIHRyZWF0bWVudCAgICAgICAgIA0KICAgIC0gNikgV2UgY2FuIG1lYXN1cmUgKipUaW1lIEZpeGVkIENvdmFyaWF0ZXMqKjogQ292YXJpYXRlIGRvZXMgbm90IGNoYW5nZSBvdmVyIHRoZSBtZWFzdXJlbWVudCBwZXJpb2QgKERWID0gRGVwcmVzc2lvbiBzY29yZSBhdCBlYWNoIHRyZWF0bWVudCwgQ292YXJpYXRlID0gVHJhaXQgQW54aWV0eSBsZXZlbCkNCiAgICAtIDcpIFdlIGNhbiBtZWFzdXJlICoqVGltZSBWYXJpYWJsZSBDb3ZhcmlhdGVzKio6IENvdmFyaWF0ZSB0aGF0IGNoYW5nZSBvdmVyIHRoZSBtZWFzdXJlbWVudCBwZXJpb2QgKERWID0gRGVwcmVzc2lvbiBzY29yZSBhdCBlYWNoIHRyZWF0bWVudCwgQ292YXJpYXRlID0gU3RhdGUgQW54aWV0eSBsZXZlbCBkdXJpbmcgYSB0aGVyYXB5IHNlc3Npb24pDQogICAgLSA4KSBJbnRlcmFjdCBUaW1lIEZpeGVkIGFuZCBUaW1lIFZhcmlhYmxlIGNvdmFyaWF0ZXMNCiAgICAtIDkpIFlvdSBjYW4gY29udHJvbCB0aGUgY292YXJpYW5jZSBzdHJ1Y3R1cmUgYW5kIHVzZSBhdXRvcmVncmVzc2l2ZSBzdHJ1Y3R1cmVzIChidXQgbm90IGluIGxtZTQpDQogICAgLSAxMCkgRGVhbCB3aXRoIG5lc3RlZCBmb3JtcyBvZiBUaW1lOiBGb3IgZXhhbXBsZSwgbW9udGggdG8gbW9udGggY2hhbmdlIGluIEFueGlldHkgbGV2ZWxzLCBidXQgeW91IGNhbiBhbHNvIGV4YW1pbmUgaG91ciB0byBob3VyIEFueGlldHkgbGV2ZWxzIChuZXN0ZWQgaW4gdGhlIG1vbnRoIHRoZXkgd2VyZSBjb2xsZWN0ZWQpICANCg0KIyBTaW1wbGVzdCBUeXBlIG9mIExvbmdpdHVkaW5hbCBNb2RlbA0KQ2hpbGRyZW4gd2l0aCBBU0QgdHlwaWNhbGx5IGhhdmUgZGlmZmljdWx0eSB3aXRoIG1vdG9yIHNraWxsIGFuZCBwb29yIGludGVycGVyc29uYWwgY29vcmRpbmF0aW9uLiBUaGVpciByZWR1Y2VkIGFiaWxpdHkgdG8gY29vcmRpbmF0ZSB3aXRoIHBlb3BsZSBtYXliZSBiZSBjYXVzaW5nIHRoZW0gdG8gYmUgbGVmdCBvdXQgb2YgcGxheSB3aXRoIG90aGVyIGNoaWxkcmVuIGlzb2xhdGluZyB0aGVtLiBQYXN0IGVmZm9ydHMgdG8gaW1wcm92ZSB0aGVpciBpbnRlcnBlcnNvbmFsIGNvb3JkaW5hdGlvbiBoYXZlIG9mdGVuIGZhaWxlZCBiZWNhdXNlIGNoaWxkcmVuIHdpdGggQVNEIGFyZSBvdmVyd2hlbG1lZCBieSBwZW9wbGUuIFNvIHRyYWluaW5nIHNlc3Npb25zIG9mdGVuIGZhaWwuIEhvd2V2ZXIsIGNoaWxkcmVuIHdpdGggQVNEIGdyYXZpdGF0ZSB0b3dhcmRzIGVsZWN0cm9uaWNzIGFuZCBoYXZlIGJlZW4gb2JzZXJ2ZWQgdG8gYmUgaW50ZXJlc3RlZCBhbmQgY29tZm9ydGFibGUgd2l0aCByb2JvdHMuIFNyaW5pdmFzYW4gZXQgYWwuLCAoMjAxNSkgaHlwb3RoZXNpemVkIHRoYXQgY2hpbGRyZW4gd2l0aCBBU0QgbWlnaHQgYmUgYmV0dGVyIGF0IGNvb3JkaW5hdGluZyB3aXRoIHJvYm90cyBiZWNhdXNlIGEpIGNoaWxkcmVuIHdpdGggQVNEIGxvdmUgcm9ib3RzLCBhbmQgYikgcm9ib3RzIGFyZSBsZXNzIHRocmVhdGVuaW5nIGFzIHRoZXkgY29udmV5IGxlc3MgaW5mb3JtYXRpb24gKG5vdCBvdmVyd2hlbG1pbmcgdGhlIGNoaWxkKS4gIFNyaW5pdmFzYW4gZXQgYWwuLCAoMjAxNSkgZm91bmQgdGhhdCBoYXZpbmcgY2hpbGRyZW4gImRhbmNlIiB3aXRoIGRhbmNpbmcgcm9ib3RzIGltcHJvdmVkIHRoZWlyIGludGVycGVyc29uYWwgY29vcmRpbmF0aW9uIGFiaWxpdHkuICANCg0KVG9kYXkgd2Ugd2lsbCBleGFtaW5lIGEgc2ltdWxhdGVkIHN0dWR5IG9mIGludGVycGVyc29uYWwgY29vcmRpbmF0aW9uIG9uIDEyIGNoaWxkcmVuIHdpdGggQVNELiBFYWNoIGNoaWxkIHVuZGVyd2VudCA2IHRyYWluaW5nIHNlc3Npb25zIChpbmNsdWRpbmcgdGhlIGJhc2VsaW5lIHdoZXJlIHRoZXkgaGFkIGFuIEFTRCBhc3Nlc3NtZW50IHRvIHNlZSB3aGVyZSB0aGV5IHdlcmUgb24gdGhlIHNwZWN0cnVtOyBDaGxlYm93c2tpIGV0IGFsLiAyMDEwKS4gVGhlIGNoaWxkcmVuIHdlcmUgYXNrZWQgdG8gImRhbmNlIiB3aXRoIGFuIGluc3RydWN0b3IgYW5kIHRoZWlyIHBhcmVudCBpbiBlYWNoIG9mIHRoZSA2IHNlc3Npb25zLiBJbiB0aGUgbGFzdCBwYXJ0IG9mIHRoZSBzZXNzaW9uIHRoZWlyIGRlZ3JlZSBvZiBjb29yZGluYXRpb24gKGZyb20gMCAtIDEpIHdpdGggdGhlIG5ldyBpbnN0cnVjdG9yIHdobyB3YXMgaW4gdGhlIHJvb20gZHVyaW5nIHRoZSBzZXNzaW9uLCBidXQgZGlkIG5vdCBkYW5jZS4gRm9yIGhhbGYgdGhlIGNoaWxkcmVuIHRoZSBpbnN0cnVjdG9yIHdhcyBodW1hbiwgYW5kIGZvciB0aGUgb3RoZXIgaGFsZiwgdGhlIGluc3RydWN0b3Igd2FzIGEgcm9ib3QuDQoNCiMjIERhdGENCi0gQXMgd2l0aCBhbGwgb3VyIG90aGVyIGFuYWx5c2lzLCB0aGUgZGF0YSBpcyBpbiBsb25nIGZvcm1hdCAoZm9yIExvbmdpdHVkaW5hbCB5b3UgbWlnaHQgc2VlIGl0IGNhbGxlZCBwZXJpb2QtcGVyaW9kIGRhdGEpDQogICAgLSBUaW1lIGlzIGNvZGVkIHRvIHN0YXJ0IGF0IDAgKGJhc2VsaW5lIG9yIGZpcnN0IG1lYXN1cmVtZW50KS4gDQogICAgLSBJbnN0cnVjdG9yICgwLDEpOiAwOiBIdW1hbjsgIDE6IFJvYm90IA0KICAgIC0gQ29vcmRpbmF0aW9uICgwLTEpOiBEZWdyZWUgb2YgY29vcmRpbmF0aW9uIChEVikNCiAgICAtIEFTRDogQVNEIHNwZWN0cnVtIHNjb3JlIChwb3NzaWJsZSBjb3ZhcmlhdGUpDQogICAgLSBbRG93bmxvYWQgZGF0YV0oL01peGVkL0xvbmdEYXRhMS5jc3YpDQogICAgDQpgYGB7cn0NCkxvbmdTaW08LXJlYWQuY3N2KCJNaXhlZC9Mb25nRGF0YTEuY3N2IikNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmxpYnJhcnkoa25pdHIpOyBsaWJyYXJ5KGthYmxlRXh0cmEpIA0Ka2FibGUoaGVhZChMb25nU2ltKSwgImh0bWwiLCBib29rdGFicyA9IFQpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRikNCmBgYA0KDQojIyMgQ29kaW5nDQotIERlY2lzaW9ucyBoYXZlIHRvIGJlIG1hZGUgYWJvdXQgaG93IHRvIGNvZGUgKkluc3RydWN0b3IqDQogICAgLSBEdW1teSBvciBlZmZlY3RzIGNvZGUgaXQ/IEZvciB0b2RheSBsZXRzIGp1c3QgZHVtbXkgY29kZSBvdXIgdHJlYXRtZW50DQogICAgDQpgYGB7cn0NCiNEdW1teQ0KTG9uZ1NpbSRJbnN0cnVjdG9yLkQ8LWZhY3RvcihMb25nU2ltJEluc3RydWN0b3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoMCwxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiSHVtYW4iLCJSb2JvdCIpKQ0KYGBgDQoNCi0gRGVjaXNpb25zIGhhdmUgdG8gYmUgbWFkZSBhYm91dCBob3cgdG8gY29kZSAqVGltZSouIEVhY2ggYWdhaW4gd2lsbCBjaGFuZ2UgaG93IHdlIGludGVycHJldCBvdXIgbW9kZWwuIFdlIHdpbGwgY29kZSBpdCBvdXQgbm93IGZvciBsYXRlcjoNCiAgICAtIFdlIGNhbiBsZWF2ZSAqVGltZSogYXMgaXM6IGl0IHN0YXJ0cyBhdCAwIGFuZCBwcm9ncmVzc2VzIGluIHRoZSB1bml0cyBvZiBtZWFzdXJlbWVudHMNCiAgICAtIENlbnRlciB0aW1lICpUaW1lKjogU28gdGhlcmUgYXJlIDYgc2Vzc2lvbnMgKDAtNSksIHRodXMgY2VudGVyIGlzIDIuNTogU28gU2Vzc2lvbiAjIC0gMi41DQogICAgLSAoTm90ZTogKnllcyB5b3UgY2FuIFpzY29yZSB0aW1lIG9yIFpzY29yZSBhbmQgTk9UIGNlbnRlciBhcyB3ZWxsKikNCg0KYGBge3J9DQojIENlbnRlcmVkDQpMb25nU2ltJFRpbWUuQzwtc2NhbGUoTG9uZ1NpbSRUaW1lLCBzY2FsZT1GLCBjZW50ZXI9VClbLF0NCmBgYCAgICAgICAgDQogIA0KIyMgU3BhZ2hldHRpIFBsb3RzDQotIExvbmdpdHVkaW5hbCBNb2RlbHMgYXJlIGJlc3QgYXNzZXNzZWQgd2l0aCBzcGFnaGV0dGkgcGxvdHMuIFdoZW4geW91IGhhdmUgYSBzbWFsbCBudW1iZXIgb2Ygc3ViamVjdHMsIHlvdSBjYW4gcGxvdCBpdCBhcyAiZmFjZXRzLiINCi0gV2Ugd2lsbCBwbG90IGVhY2ggcGVyc29uIGluIGEgZmFjZXQgYW5kIGFkZCB0aGVpciBsaW5lYXIgbW9kZWwgZm9yIGVhY2ggc3ViamVjdA0KYGBge3IsZmlnLndpZHRoPTMuNSwgZmlnLmhlaWdodD0zLjV9DQojIE1ha2Ugc3VyZSB0aGF0IHN1YmplY3QgaXMgYSBmYWN0b3INCkxvbmdTaW0kU3ViamVjdDwtYXMuZmFjdG9yKExvbmdTaW0kU3ViamVjdCkNCg0KU3BlZy4xPC1nZ3Bsb3QoZGF0YSA9IExvbmdTaW0sIGFlcyh4PVRpbWUseT1Db29yZGluYXRpb24pKSsNCiAgZmFjZXRfd3JhcCh+U3ViamVjdCkrDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yPUluc3RydWN0b3IuRCkpKw0KICBnZW9tX3Ntb290aChtZXRob2Q9J2xtJywgc2U9RkFMU0UsYWVzKGNvbG9yPUluc3RydWN0b3IuRCkpKw0KICB4bGFiKCJUaW1lIikreWxhYigiQ29vcmRpbmF0aW9uIikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQ0KU3BlZy4xDQpgYGANCg0KLSBJZiB5b3UgaGF2ZSB0b28gbWFueSBzdWJqZWN0cywgeW91IGNhbiBwbG90IHRoZSByZXN1bHRzIGxpa2UgdGhpcyBpbnN0ZWFkDQotIE9uIHRoZSBsZWZ0LCB5b3UgY2FuIGZpdCBhIHJlZ3Jlc3Npb24gcGVyIHN1YmplY3QsIG9uIHRoZSByaWdodCB5b3UgcGxvdCBsaW5lcyBpbnN0ZWFkIG9mIHRoZSBzbG9wZQ0KDQpgYGB7ciwgZWNobz1UUlVFLCBvdXQud2lkdGg9JzUwJScsIGZpZy5oZWlnaHQ9Mi41LGZpZy5zaG93PSdob2xkJyxmaWcuYWxpZ249J2NlbnRlcid9DQp0aGVtZV9zZXQodGhlbWVfYncoYmFzZV9zaXplID0gNywgYmFzZV9mYW1pbHkgPSAiIikpDQoNClNwZWcuMjwtZ2dwbG90KGRhdGEgPSBMb25nU2ltLCBhZXMoeD1UaW1lLHk9Q29vcmRpbmF0aW9uLCBncm91cD1TdWJqZWN0LCBjb2xvcj1TdWJqZWN0KSkrDQogIGZhY2V0X3dyYXAofkluc3RydWN0b3IuRCkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSdsbScsIHNlPUZBTFNFKSsNCiAgeGxhYigiVGltZSIpK3lsYWIoIkNvb3JkaW5hdGlvbiIpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpTcGVnLjINCg0KU3BlZy4zPC1nZ3Bsb3QoZGF0YSA9IExvbmdTaW0sIGFlcyh4PVRpbWUseT1Db29yZGluYXRpb24sIGdyb3VwPVN1YmplY3QsIGNvbG9yPVN1YmplY3QpKSsNCiAgZmFjZXRfd3JhcCh+SW5zdHJ1Y3Rvci5EKSsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX2xpbmUoKSsNCiAgeGxhYigiVGltZSIpK3lsYWIoIkNvb3JkaW5hdGlvbiIpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpTcGVnLjMNCmBgYA0KDQojIyBNb2RlbGluZyB0byBFeGFtaW5lIFJhbmRvbSBTdHJ1Y3R1cmUgDQotIFRoZSBzdWJqZWN0IGlzIHRoZSBMZXZlbCAyIHZhcmlhYmxlIChqdXN0IGxpa2UgaW4gb3VyIHJlcGVhdGVkIG1lYXN1cmVzIG1peGVkIG1vZGVscykNCi0gV2UgY2FuIHNob3cgdGhhdCB2aWEgb3VyIElDQyBhbmFseXNpcyANCg0KIyMjIEludGVyY2VwdHMgb25seSBtb2RlbCANCmBgYHtyfQ0KTnVsbDwtbG1lcihDb29yZGluYXRpb24gfiAxKygxfFN1YmplY3QpLCBkYXRhPUxvbmdTaW0sIFJFTUw9RkFMU0UpDQpzanN0YXRzOjppY2MoTnVsbCkNCmBgYA0KDQojIyMjIEludGVyY2VwdHMgb25seSBwbG90DQotIFByZWRpY3Qgb3V0IHRoZSBtb2RlbCByZXN1bHRzIA0KLSBEb3RzID0gUmVhbCBkYXRhDQotIExpbmUgPSBQcmVkaWN0ZWQgcmVzdWx0DQpgYGB7ciwgZWNobz1UUlVFLG91dC53aWR0aD0nNTAlJywgZmlnLmhlaWdodD0yLjUsZmlnLnNob3c9J2hvbGQnLGZpZy5hbGlnbj0nY2VudGVyJ30NCnRoZW1lX3NldCh0aGVtZV9idyhiYXNlX3NpemUgPSA3LCBiYXNlX2ZhbWlseSA9ICIiKSkNCg0KTG9uZ1NpbSROdWxsPC1wcmVkaWN0KE51bGwsIG5ld2RhdGE9TG9uZ1NpbSkNCg0KU3BlZy5OdWxsLjE8LWdncGxvdChkYXRhID0gTG9uZ1NpbSkrDQogIGZhY2V0X3dyYXAoflN1YmplY3QpKw0KICBnZW9tX3BvaW50KGFlcyh4PVRpbWUseT1Db29yZGluYXRpb24sY29sb3I9SW5zdHJ1Y3Rvci5EKSkrDQogIGdlb21fbGluZShhZXMoeD1UaW1lLHk9TnVsbCwgY29sb3I9SW5zdHJ1Y3Rvci5EKSkrDQogIHhsYWIoIlRpbWUiKSt5bGFiKCJDb29yZGluYXRpb24iKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpDQpTcGVnLk51bGwuMQ0KDQpTcGVnLk51bGwuMjwtZ2dwbG90KGRhdGEgPSBMb25nU2ltKSsNCiAgZmFjZXRfd3JhcCh+SW5zdHJ1Y3Rvci5EKSsNCiAgZ2VvbV9wb2ludChhZXMoeD1UaW1lLHk9Q29vcmRpbmF0aW9uLCBncm91cD1TdWJqZWN0LGNvbG9yPVN1YmplY3QpKSsNCiAgZ2VvbV9saW5lKGFlcyh4PVRpbWUseT1OdWxsLGdyb3VwPVN1YmplY3QsY29sb3I9U3ViamVjdCkpKw0KICB4bGFiKCJUaW1lIikreWxhYigiQ29vcmRpbmF0aW9uIikrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNClNwZWcuTnVsbC4yDQoNCmBgYA0KLSBOb3RpY2UgdGhhdCBlYWNoIHN1YmplY3QgaGFzIHRoZWlyIG93biBpbnRlcmNlcHQsIGJ1dCBubyBzbG9wZQ0KDQojIyMgUmFuZG9tIEludGVyY2VwdHMgYW5kIFNsb3BlcyBNb2RlbCANCi0gV2Ugd2lsbCBsZXQgdGhlIGludGVyY2VwdCBhbmQgVGltZSB2YXJ5IHJlbGF0aXZlIHRvIGVhY2ggc3ViamVjdDogYCgxK1RpbWV8U3ViamVjdClgDQogICAgLSBOb3RlIHlvdSBjYW4gYmxvY2sgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHNsb3BlL2ludGVyY2VwdCBsaWtlIGJlZm9yZSBpZiB0aGUgY29ycmVsYXRpb24gaXMgLTEvMTogYCgxK1RpbWV8fFN1YmplY3QpYA0KYGBge3J9DQpSSVNsb3BlPC1sbWVyKENvb3JkaW5hdGlvbiB+IDErKDErVGltZXxTdWJqZWN0KSwgZGF0YT1Mb25nU2ltLCBSRU1MPUZBTFNFKQ0Kc3VtbWFyeShSSVNsb3BlKQ0KYGBgDQoNCiMjIyMgUmFuZG9tIEludGVyY2VwdCBhbmQgU2xvcGVzIFBsb3QNCi0gUHJlZGljdCBvdXQgdGhlIG1vZGVsIHJlc3VsdHMgDQotIERvdHMgPSBSZWFsIGRhdGENCi0gTGluZSA9IFByZWRpY3RlZCByZXN1bHQNCg0KYGBge3IsIGVjaG89VFJVRSxvdXQud2lkdGg9JzUwJScsIGZpZy5oZWlnaHQ9Mi41LGZpZy5zaG93PSdob2xkJyxmaWcuYWxpZ249J2NlbnRlcid9DQp0aGVtZV9zZXQodGhlbWVfYncoYmFzZV9zaXplID0gNywgYmFzZV9mYW1pbHkgPSAiIikpDQoNCkxvbmdTaW0kUklTbG9wZTwtcHJlZGljdChSSVNsb3BlLCBuZXdkYXRhPUxvbmdTaW0pDQpTcGVnLlIuSS5TbG9wZS4xPC1nZ3Bsb3QoZGF0YSA9IExvbmdTaW0pKw0KICBmYWNldF93cmFwKH5TdWJqZWN0KSsNCiAgZ2VvbV9wb2ludChhZXMoeD1UaW1lLHk9Q29vcmRpbmF0aW9uLCBjb2xvcj1JbnN0cnVjdG9yLkQpKSsNCiAgZ2VvbV9saW5lKGFlcyh4PVRpbWUseT1SSVNsb3BlLCBjb2xvcj1JbnN0cnVjdG9yLkQpKSsNCiAgeGxhYigiVGltZSIpK3lsYWIoIkNvb3JkaW5hdGlvbiIpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikNClNwZWcuUi5JLlNsb3BlLjENCg0KU3BlZy5SLkkuU2xvcGUuMjwtZ2dwbG90KGRhdGEgPSBMb25nU2ltKSsNCiAgZmFjZXRfd3JhcCh+SW5zdHJ1Y3Rvci5EKSsNCiAgZ2VvbV9wb2ludChhZXMoeD1UaW1lLHk9Q29vcmRpbmF0aW9uLCBncm91cD1TdWJqZWN0LGNvbG9yPVN1YmplY3QpKSsNCiAgZ2VvbV9saW5lKGFlcyh4PVRpbWUseT1SSVNsb3BlLGdyb3VwPVN1YmplY3QsY29sb3I9U3ViamVjdCkpKw0KICB4bGFiKCJUaW1lIikreWxhYigiQ29vcmRpbmF0aW9uIikrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNClNwZWcuUi5JLlNsb3BlLjINCmBgYA0KDQojIyMgUmFuZG9tIFNsb3BlcyBPbmx5IE1vZGVsIA0KLSBJdCBjb3VsZCBiZSB0aGVyZSBpcyBubyByYW5kb20gaW50ZXJjZXB0LCBzbyB5b3UgY2FuIHJlbW92ZSBpdCAoYnV0IHlvdSBuZWVkIHRvIGhhdmUgYSByZWFzb24pDQotIFdlIHdpbGwgbGV0IFRpbWUgdmFyeSByZWxhdGl2ZSB0byBlYWNoIHN1YmplY3Q6IGAoMCtUaW1lfFN1YmplY3QpYA0KYGBge3J9DQpSU2xvcGU8LWxtZXIoQ29vcmRpbmF0aW9uIH4gMSsoMCtUaW1lfFN1YmplY3QpLCBkYXRhPUxvbmdTaW0sIFJFTUw9RkFMU0UpDQpzdW1tYXJ5KFJTbG9wZSkNCmBgYA0KDQojIyMjIFJhbmRvbSBTbG9wZXMgT25seSBQbG90DQotIFByZWRpY3Qgb3V0IHRoZSBtb2RlbCByZXN1bHRzIA0KLSBEb3RzID0gUmVhbCBkYXRhDQotIExpbmUgPSBQcmVkaWN0ZWQgcmVzdWx0DQoNCmBgYHtyLCBlY2hvPVRSVUUsb3V0LndpZHRoPSc1MCUnLCBmaWcuaGVpZ2h0PTIuNSxmaWcuc2hvdz0naG9sZCcsZmlnLmFsaWduPSdjZW50ZXInfQ0KdGhlbWVfc2V0KHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDcsIGJhc2VfZmFtaWx5ID0gIiIpKQ0KDQpMb25nU2ltJFJTbG9wZTwtcHJlZGljdChSU2xvcGUsIG5ld2RhdGE9TG9uZ1NpbSkNCg0KU3BlZy5SLlNsb3BlLjE8LWdncGxvdChkYXRhID0gTG9uZ1NpbSkrDQogIGZhY2V0X3dyYXAoSW5zdHJ1Y3Rvci5EflN1YmplY3QpKw0KICBnZW9tX3BvaW50KGFlcyh4PVRpbWUseT1Db29yZGluYXRpb24sIGNvbG9yPUluc3RydWN0b3IuRCkpKw0KICBnZW9tX2xpbmUoYWVzKHg9VGltZSx5PVJTbG9wZSwgY29sb3I9SW5zdHJ1Y3Rvci5EKSkrDQogIHhsYWIoIlRpbWUiKSt5bGFiKCJDb29yZGluYXRpb24iKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpDQpTcGVnLlIuU2xvcGUuMQ0KDQpTcGVnLlIuU2xvcGUuMjwtZ2dwbG90KGRhdGEgPSBMb25nU2ltKSsNCiAgZmFjZXRfd3JhcCh+SW5zdHJ1Y3Rvci5EKSsNCiAgZ2VvbV9wb2ludChhZXMoeD1UaW1lLHk9Q29vcmRpbmF0aW9uLCBncm91cD1TdWJqZWN0LGNvbG9yPVN1YmplY3QpKSsNCiAgZ2VvbV9saW5lKGFlcyh4PVRpbWUseT1SU2xvcGUsZ3JvdXA9U3ViamVjdCxjb2xvcj1TdWJqZWN0KSkrDQogIHhsYWIoIlRpbWUiKSt5bGFiKCJDb29yZGluYXRpb24iKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KU3BlZy5SLlNsb3BlLjINCmBgYA0KDQotIE5vdGU6IFRoZSBpbnRlcmNlcHRzIGZvciBlYWNoIHN1YmplY3QgYXJlIHRoZSBzYW1lLg0KLSBZb3UgY2FuIGFsc28gZ3Vlc3MgdGhhdCB0aGlzIG1vZGVsIHdpbGwgbm90IGJlIGEgZ29vZCBmaXQgYXMgdGhlIGxhc3Qgb25lLCB3aGljaCB3ZSBjYW4gdGVzdDogDQoNCmBgYHtyLCBldmFsPVRSVUV9DQphbm92YShSU2xvcGUsUklTbG9wZSkNCmBgYA0KDQojIyBNb2RlbGluZyBmb3IgUmVzdWx0cw0KLSBUaGUgZ29hbCBhYm92ZSB3YXMgdG8gdW5kZXJzdGFuZCB0aGUgcmFuZG9tIGVmZmVjdHMuIFRoaXMgaXMgdXNlZnVsIGlmIHlvdSB3YW50IHRvIHVuZGVyc3RhbmQgeW91ciBkYXRhLCBidXQgd2hlbiB5b3UgbW92ZSB0byBtb2RlbGluZyBmb3IgcHVibGljYXRpb24geW91IHdpbGwgd2FudCB0byAqc2V0KiB5b3VyIHJhbmRvbSBlZmZlY3RzIGFuZCBtb3ZlIHRvIGZpeGVkIGVmZmVjdCB0ZXN0aW5nDQotIFRoZSBtb3N0IG9idmlvdXMgc3RydWN0dXJlIGZvciBtb3N0IGxvbmdpdHVkaW5hbCAoMiBsZXZlbCkgZGF0YSBpcyB0byB1c2UgcmFuZG9tIHNsb3BlcyBhbmQgaW50ZXJjZXB0cyAod2F0Y2ggdGhhdCBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZW0pDQotIFdlIHdpbGwgbm93IGFsc28gZXhwbG9yZSB0aGUgZGlmZmVyZW50IGNvZGluZyBzY2hlbWVzIHRvIHVuZGVyc3RhbmQgdGhlIG1vZGVscw0KDQojIyMgTm9uLUNlbnRlcmVkIFRpbWUgJiBEdW1teSBjb2RlZCBJbnN0cnVjdG9yIA0KLSBOb3RlOiBiZWNhdXNlIEluc3RydWN0b3IgaXMgMC8xIGNvZGVkIHlvdSBjYW4gYWxzbyBlbnRlciB0aGF0IGludG8gdGhlIG1vZGVsIGluc3RlYWQgb2YgaXQgYXMgYSBmYWN0b3IgKHlvdSB3aWxsIGdldCB0aGUgc2FtZSBhbnN3ZXIpDQoNCiMjIyMgTWFpbiBlZmZlY3RzDQpgYGB7cn0NCk1haW5FZmZlY3QuMTwtbG1lcihDb29yZGluYXRpb24gfiBUaW1lK0luc3RydWN0b3IuRCsoMStUaW1lfFN1YmplY3QpLCBkYXRhPUxvbmdTaW0sIFJFTUw9RkFMU0UpDQpzdW1tYXJ5KE1haW5FZmZlY3QuMSwgY29ycmVsYXRpb249RkFMU0UpDQpgYGANCg0KIyMjIyMgSW50ZXJwcmV0YXRpb24NCi0gKipUaW1lKio6IEFmdGVyIGVhY2ggc2Vzc2lvbiwgdGhlIGtpZHMgZ2V0IGFyZSBiZXR0ZXIgYXQgY29vcmRpbmF0aW5nIF9yZWdhcmRsZXNzXyBvZiBJbnN0cnVjdGlvbiAodGhlIGVzdGltYXRlIGlzIHRoZSBzbG9wZSBvdmVyIHNlc3Npb25zKQ0KLSAqKkluc3RydWN0b3IuRFJvYm90Kio6IHQgPCAxLjk2IChzbyBub3Qgc2lnbmlmaWNhbnQpLiBIYWQgaXQgYmVlbiBzaWduaWZpY2FudCBpdCB3b3VsZCBtZWFuIHRoYXQga2lkcyB3aG8gaGFkIHRoZSByb2JvdCBpbnN0cnVjdG9yIGhhZCBvdmVyYWxsIGhpZ2hlciBjb29yZGluYXRpb24gWyoqYXZlcmFnZWQgb3ZlciBhbGwgc2Vzc2lvbioqXSAodGhlIGVzdGltYXRlIHJlcG9ydGVkIGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gaHVtYW4gYW5kIHJvYm90KQ0KDQojIyMjIEludGVyYWN0aW9uIA0KYGBge3J9DQpJbnRlcmFjdGlvbi4xPC1sbWVyKENvb3JkaW5hdGlvbiB+IFRpbWUqSW5zdHJ1Y3Rvci5EKygxK1RpbWV8U3ViamVjdCksIGRhdGE9TG9uZ1NpbSwgUkVNTD1GQUxTRSkNCnN1bW1hcnkoSW50ZXJhY3Rpb24uMSwgY29ycmVsYXRpb249RikNCmBgYA0KDQojIyMjIyBJbnRlcnByZXRhdGlvbg0KLSAqKlRpbWUqKjogc2xvcGUgb3ZlciBzZXNzaW9ucyBmb3Iga2lkcyB3aG8gaGFkIHRoZSAqaHVtYW4gaW5zdHJ1Y3RvciouICANCi0gKipJbnN0cnVjdG9yLkRSb2JvdCoqOiBJdCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGh1bWFuIGFuZCByb2JvdCB3aGVuIFRpbWUgPSAwIFsqKkJhc2VsaW5lKipdLiANCiAgICAtIFRvIHByb3ZlIHRoaXMgd2UgY2FuIGZpdCB0aGUgbW9kZWwgYW5kIHN1YnRyYWN0IHRoZSBmaXR0ZWQgdmFsdWVzOiAqUm9ib3QgQCBUaW1lIDAgLSBIdW1hbiBAIFRpbWUgMCAqDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KbGlicmFyeShlZmZlY3RzKQ0KZWZmZWN0KGMoIlRpbWUqSW5zdHJ1Y3Rvci5EIiksSW50ZXJhY3Rpb24uMSkNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmxpYnJhcnkoZWZmZWN0cykNCiMgRmFuY3kgdmVyc2lvbiBvZiBhYm92ZTogSWdub3JlIG1lIQ0Ka2FibGUoYXMuZGF0YS5mcmFtZShlZmZlY3QoYygiVGltZSpJbnN0cnVjdG9yLkQiKSxJbnRlcmFjdGlvbi4xKSksIGRpZ2l0cz00LCJodG1sIiwgYm9va3RhYnMgPSBUKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYpDQpJbnRlci4xLkVmZmVjdHM8LWFzLmRhdGEuZnJhbWUoZWZmZWN0KGMoIlRpbWUqSW5zdHJ1Y3Rvci5EIiksSW50ZXJhY3Rpb24uMSkpDQpgYGANCiAgICAtIEVzdGltYXRlIG9mICoqSW5zdHJ1Y3Rvci5EUm9ib3QqKjogYHIgSW50ZXIuMS5FZmZlY3RzJGZpdFs2XWAgLSBgciBJbnRlci4xLkVmZmVjdHMkZml0WzFdYCA9IGByIEludGVyLjEuRWZmZWN0cyRmaXRbNl0gLSBJbnRlci4xLkVmZmVjdHMkZml0WzFdYA0KICAgICAgICAtIE5vdGU6ICpZb3UgYXJlIG1pc3NpbmcgdGhlIHNpbXBsZSBlZmZlY3Qgb2YgSHVtYW4gQCBUaW1lIDAqLiBSZWxldmVsIGluc3RydWN0b3IgdG8gdGVzdCBpZiB5b3UgbmVlZCB0byBrbm93Lg0KLSAqKlRpbWU6SW5zdHJ1Y3Rvci5EUm9ib3QqKjogc2xvcGUgb3ZlciBzZXNzaW9ucyBkaWZmZXJlbmNlID0gIHNsb3BlIEAgKnJvYm90IGluc3RydWN0b3IqIC0gc2xvcGUgQCAqaHVtYW4gaW5zdHJ1Y3RvcioNCg0KIyMjIENlbnRlcmVkIFRpbWUgJiBEdW1teSBjb2RlZCBJbnN0cnVjdG9yIA0KLSBOb3RlOiBCZWNhdXNlIEluc3RydWN0b3IgaXMgMC8xIGNvZGVkIHlvdSBjYW4gYWxzbyBlbnRlciB0aGF0IGludG8gdGhlIG1vZGVsIGluc3RlYWQgb2YgaXQgYXMgZmFjdG9yICh5b3Ugd2lsbCBnZXQgdGhlIHNhbWUgYW5zd2VyKQ0KDQojIyMjIE1haW4gZWZmZWN0cw0KYGBge3J9DQpNYWluRWZmZWN0LjI8LWxtZXIoQ29vcmRpbmF0aW9uIH4gVGltZS5DK0luc3RydWN0b3IuRCsoMStUaW1lfFN1YmplY3QpLCBkYXRhPUxvbmdTaW0sIFJFTUw9RkFMU0UpDQpzdW1tYXJ5KE1haW5FZmZlY3QuMiwgY29ycmVsYXRpb249RikNCmBgYA0KDQojIyMjIyBJbnRlcnByZXRhdGlvbg0KLSBTYW1lIGFzIG5vbi1jZW50ZXJlZA0KDQojIyMjIEludGVyYWN0aW9uIA0KLSBOb3cgdGhpbmdzIHdpbGwgY2hhbmdlIGJlY2F1c2UgdGhlIHplcm8tcG9pbnQgaW4gdGltZSBpcyBub3cgdGhlIG1pZGRsZSBvZiB0aGUgc2Vzc2lvbiAobm90IHRoZSBiYXNlbGluZSkNCmBgYHtyfQ0KSW50ZXJhY3Rpb24uMjwtbG1lcihDb29yZGluYXRpb24gfiBUaW1lLkMqSW5zdHJ1Y3Rvci5EKygxK1RpbWV8U3ViamVjdCksIGRhdGE9TG9uZ1NpbSwgUkVNTD1GQUxTRSkNCnN1bW1hcnkoSW50ZXJhY3Rpb24uMiwgY29ycmVsYXRpb249RikNCmBgYA0KDQojIyMjIyBJbnRlcnByZXRhdGlvbg0KLSAqKlRpbWUqKjogc2xvcGUgZm9yIGtpZHMgd2hvIGhhZCB0aGUgaHVtYW4gaW5zdHJ1Y3Rvci4gIA0KLSAqKkluc3RydWN0b3IuRFJvYm90Kio6IEl0IGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gaHVtYW4gYW5kIHJvYm90IHdoZW4gVGltZSA9IDAuIF8qKkJ1dCByZW1lbWJlciBUaW1lIDAgZXF1YWxzIHRoZSBNaWRkbGUgU2Vzc2lvbiEqKl8gDQogICAgLSBUbyBwcm92ZSB0aGlzLCB3ZSBjYW4gZml0IHRoZSBtb2RlbCBhbmQgc3VidHJhY3QgdGhlIGZpdHRlZCB2YWx1ZXM6ICpSb2JvdCBAIFRpbWUgMCAtIEh1bWFuIEAgVGltZSAwKiBbKipNaWRkbGUgc2Vzc2lvbioqXQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmVmZmVjdChjKCJUaW1lLkMqSW5zdHJ1Y3Rvci5EIiksSW50ZXJhY3Rpb24uMikNCmBgYA0KYGBge3IsIGVjaG89RkFMU0V9DQojIEZhbmN5IHZlcnNpb24gb2YgYWJvdmU6IElnbm9yZSBtZSENCmthYmxlKGFzLmRhdGEuZnJhbWUoZWZmZWN0KGMoIlRpbWUuQypJbnN0cnVjdG9yLkQiKSxJbnRlcmFjdGlvbi4yKSksIGRpZ2l0cz00LCJodG1sIiwgYm9va3RhYnMgPSBUKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYpDQpJbnRlci4yLkVmZmVjdHM8LWFzLmRhdGEuZnJhbWUoZWZmZWN0KGMoIlRpbWUuQypJbnN0cnVjdG9yLkQiKSxJbnRlcmFjdGlvbi4yKSkNCmBgYA0KICAgIC0gRXN0aW1hdGUgb2YgKipJbnN0cnVjdG9yLkRSb2JvdCoqOiBgciBJbnRlci4yLkVmZmVjdHMkZml0WzhdYCAtIGByIEludGVyLjIuRWZmZWN0cyRmaXRbM11gID0gYHIgSW50ZXIuMi5FZmZlY3RzJGZpdFs4XSAtIEludGVyLjIuRWZmZWN0cyRmaXRbM11gDQotICoqVGltZTpJbnN0cnVjdG9yLkRSb2JvdCoqOiBzbG9wZSBvdmVyIHNlc3Npb25zIGRpZmZlcmVuY2UgPSAgc2xvcGUgQCAqcm9ib3QgaW5zdHJ1Y3RvciogLSBzbG9wZSBAICpodW1hbiBpbnN0cnVjdG9yKg0KDQoNCiMjIyBTdW1tYXJ5DQotIFRvIGNlbnRlciB0aW1lIG9yIG5vdCBjZW50ZXIgdGltZT8gDQotIFRoaXMgYWxsIGRlcGVuZHMgb24gd2hhdCBzdG9yeSB5b3UgbmVlZCB0byB0ZWxsDQotIEluIHRoZSBpbnRlcmFjdGlvbiBtb2RlbDoNCiAgICAtIGlmIHlvdSBkb24ndCBjZW50ZXIgdGltZSwgeW91IGFyZSB0YWxraW5nIGFib3V0IHRoZSBiYXNlbGluZS4gSW4gdGhpcyBjYXNlLCBpdCBzZWVtcyB2ZXJ5IHVzZWZ1bCB0byBiZSBhYmxlIHRvIHNheSB0aGUga2lkcyB3aXRoIEFTRCBzdGFydGVkIG91dCBhdCB0aGUgc2FtZSBsZXZlbCBvZiBjb29yZGluYXRpb24gYW5kIG92ZXIgdGltZSB0aGVpciBzbG9wZXMgY2hhbmdlZA0KICAgICAtIGlmIHlvdSBjZW50ZXIgdGltZSB5b3UgYXJlIHRhbGtpbmcgYWJvdXQgdGhlIG1pZGRsZSBzZXNzaW9uLCBJIGZpbmQgdGhpcyBsZXNzIHVzZWZ1bCBmb3IgdGhlIHF1ZXN0aW9uIGF0IGhhbmQsIGJ1dCBrZWVwIGl0IGluIG1pbmQgdGhhdCB5b3UgY2FuIGV4YW1pbmUgaXQgdGhpcyB3YXkNCiAgICAgDQogICAgIA0KIyBQbG90IG91ciBGaW5hbCBNb2RlbA0KLSBXZSBjYW4gdXNlIHRoZSBlZmZlY3RzIHBhY2thZ2UgYW5kIGdncGxvdCB0byBwbG90IHRoZSBmaXR0ZWQgbW9kZWwNCmBgYHtyLGZpZy53aWR0aD0zLjUsIGZpZy5oZWlnaHQ9My41fQ0KbGlicmFyeShlZmZlY3RzKQ0KRml0dGVkLkkxPC1lZmZlY3QoYygiVGltZSpJbnN0cnVjdG9yLkQiKSxJbnRlcmFjdGlvbi4xKQ0KRml0dGVkLkkxPC1hcy5kYXRhLmZyYW1lKEZpdHRlZC5JMSkNCg0KRml0dGVkLlBsb3Q8LWdncGxvdChkYXRhID0gRml0dGVkLkkxLCBhZXMoeD1UaW1lLHk9Zml0LCBncm91cD1JbnN0cnVjdG9yLkQpKSsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1JbnN0cnVjdG9yLkQpKSsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW49bG93ZXIseW1heD11cHBlcixmaWxsPUluc3RydWN0b3IuRCksYWxwaGE9LjIpKw0KICB4bGFiKCJTZXNzaW9uIikreWxhYigiQ29vcmRpbmF0aW9uIikrDQogIHNjYWxlX3lfY29udGludW91cyhsaW09YygwLDEpLGJyZWFrcyA9IHNlcSgwLCAxLC4yKSkgKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKC44NSwuODc1KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gImJsYW5rIiksDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSkNCkZpdHRlZC5QbG90DQpgYGANCg0KIyBGaXhlZCBDb3ZhcmlhdGVzDQotIFdlIGhhZCBhIGNvdmFyaWF0ZTogZWFjaCBraWRzIGF1dGlzbSBzcGVjdHJ1bSBzY29yZS4gDQotIFdlIGNhbiBzaW1wbHkgYWRkIGl0IHRvIG91ciBtb2RlbCBpZiB3ZSB3YW50IHRvIGNvbnRyb2wgZm9yIGl0LCBidXQgeW91IHJlYWxseSBzaG91bGQgY2VudGVyIGl0IHNvIHlvdSBpbnRlcmNlcHQgZG9lcyBub3QgY2hhbmdlLiANCg0KYGBge3J9DQpMb25nU2ltJEFTRC5DPC1zY2FsZShMb25nU2ltJEFTRCwgc2NhbGU9RiwgY2VudGVyPVQpWyxdDQpgYGANCg0KLSBZb3UgY2FuIGFkZCBpdCB0byB5b3VyIG1vZGVsIGp1c3QgYXMgYW55IHJlZ3Jlc3Npb24NCmBgYHtyfQ0KQ292MS5Nb2RlbDwtbG1lcihDb29yZGluYXRpb24gfiBUaW1lKkluc3RydWN0b3IuRCtBU0QuQw0KICAgICAgICAgICAgICAgICsoMStUaW1lfFN1YmplY3QpLCBkYXRhPUxvbmdTaW0sIFJFTUw9RkFMU0UpDQpzdW1tYXJ5KENvdjEuTW9kZWwsIGNvcnJlbGF0aW9uPUYpDQpgYGANCg0KKipOb3RlOiB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgaW50ZXJjZXB0IGFuZCBzbG9wZSA9IDEsIHNvIHdlIHNob3VsZCBibG9jayB0aGF0IG1vdmluZyBmb3J3YXJkIGFuZCB3ZSB3b3VsZCBnbyBiYWNrIGFuZCBibG9jayBpdCBpbiBwcmlvciBtb2RlbHMgdG8gdGhleSBhcmUgYWxsIGhhdmUgdGhlIHNhbWUgcmFuZG9tIHN0cnVjdHVyZS4gRm9yIG5vdyB3ZSB3aWxsIGlnbm9yZSBpdCBhbmQgbW92ZSBvbioqDQoNCmBgYHtyLCBldmFsPVRSVUV9DQphbm92YShJbnRlcmFjdGlvbi4xLENvdjEuTW9kZWwpDQpgYGANCg0KDQotIE91ciBzbG9wZSBpcyBubyBsb25nZXIgc2lnbmlmaWNhbnQsIG1lYW5pbmcgdGhlIGNvdmFyaWF0ZSBtaWdodCBiZSBleHBsYWluaW5nIHNvbWUgb2Ygb3VyIGludGVyYWN0aW9uIGF0IHRoZSBtZWFuIGxldmVsIG9mIEFTRCBzY29yZS4gVGhpcyBpcyBzdWdnZXN0aXZlIG9mIDMtd2F5IGludGVyYWN0aW9uLg0KDQpgYGB7cn0NCkNvdjIuTW9kZWw8LWxtZXIoQ29vcmRpbmF0aW9uIH4gVGltZSpJbnN0cnVjdG9yLkQqQVNELkMNCiAgICAgICAgICAgICAgICArKDErVGltZXxTdWJqZWN0KSwgZGF0YT1Mb25nU2ltLCBSRU1MPUZBTFNFKQ0Kc3VtbWFyeShDb3YyLk1vZGVsLCBjb3JyZWxhdGlvbj1GKQ0KYGBgDQoNCmBgYHtyfQ0KYW5vdmEoQ292MS5Nb2RlbCxDb3YyLk1vZGVsKQ0KYGBgDQoNCg0KLSBUaGUgdGhyZWUgd2F5IGltcHJvdmVkIHRoZSBtb2RlbCBmaXQuIA0KLSAqKlRpbWU6SW5zdHJ1Y3Rvci5EUm9ib3QqKjogaXMgdGhlIHNsb3BlIG92ZXIgc2Vzc2lvbnMgZGlmZmVyZW5jZSA9ICBzbG9wZSBAICpyb2JvdCBpbnN0cnVjdG9yKiAtIHNsb3BlIEAgKmh1bWFuIGluc3RydWN0b3IqIFtAIGF0IHRoZSBhdmVyYWdlIEFTRCBsZXZlbF0NCi0gKipUaW1lOkluc3RydWN0b3IuRFJvYm90OkFTRC5DKio6IGlzIHRoZSBzbG9wZSBvdmVyIHNlc3Npb25zIGRpZmZlcmVuY2UgPSAgc2xvcGUgQCAqcm9ib3QgaW5zdHJ1Y3RvciogLSBzbG9wZSBAICpodW1hbiBpbnN0cnVjdG9yKiBbYXMgYSBmdW5jdGlvbiBvZiBBU0Qgc2NvcmVdDQogICAgLSBTbyB0aGUgc2xvcGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHJvYm90IGFuZCBodW1hbiBpbnN0cnVjdG9yIGlzIGdldHRpbmcgbGFyZ2VyIGFzIEFTRCBsZXZlbCBpbmNyZWFzZXMuIFNlZSB0aGUgcGxvdCBiZWxvdyB0byB1bmRlcnN0YW5kIHRoaXM6IA0KDQojIyBQbG90IDMtV2F5DQotIFdlIHdpbGwgcGxvdCBpdCBsaWtlIGFueSBvdGhlciBpbnRlcmFjdGlvbiBpbiBhIHJlZ3Jlc3Npb24gaW52b2x2aW5nIHR3byBjb250aW51b3VzIHZhcmlhYmxlcw0KLSBXZSB3aWxsIG5lZWQgdG8gZmluZCAxIFNEIGFib3ZlL2JlbG93IHRoZSBtZWFuIG9mIHRoZSBjb3ZhcmlhdGUgKHdoaWNoIHdhcyBtZWFuIGNlbnRlcmVkKQ0KDQpgYGB7cixmaWcud2lkdGg9NS41LCBmaWcuaGVpZ2h0PTMuNX0NClNETjE8LSAtc2QoTG9uZ1NpbSRBU0QuQykNClNEUDE8LSArc2QoTG9uZ1NpbSRBU0QuQykNCg0KRml0dGVkLkNvdjI8LWVmZmVjdChjKCJUaW1lKkluc3RydWN0b3IuRCpBU0QuQyIpLENvdjIuTW9kZWwsIA0KICAgICAgICAgICAgICAgICAgICB4bGV2ZWw9bGlzdChUaW1lPXNlcSgwLDUsMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFTRC5DPWMoU0ROMSwwLFNEUDEpKSkNCkZpdHRlZC5Db3YyPC1hcy5kYXRhLmZyYW1lKEZpdHRlZC5Db3YyKQ0KDQpGaXR0ZWQuQ292MiRBU0Q8LWZhY3RvcihGaXR0ZWQuQ292MiRBU0QuQywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YyhTRE4xLDAsU0RQMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiLTEgU0QgQVNEIiwiTWVhbiBBU0QiLCIrMSBTRCBBU0QiKSkNCg0KRml0dGVkLlBsb3QuMjwtZ2dwbG90KGRhdGEgPSBGaXR0ZWQuQ292MiwgYWVzKHg9VGltZSx5PWZpdCwgZ3JvdXA9SW5zdHJ1Y3Rvci5EKSkrDQogIGZhY2V0X2dyaWQofkFTRCkrDQogIGdlb21fbGluZShhZXMoY29sb3I9SW5zdHJ1Y3Rvci5EKSkrDQogIGdlb21fcmliYm9uKGFlcyh5bWluPWxvd2VyLHltYXg9dXBwZXIsZmlsbD1JbnN0cnVjdG9yLkQpLGFscGhhPS4yKSsNCiAgeGxhYigiU2Vzc2lvbiIpK3lsYWIoIkNvb3JkaW5hdGlvbiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltPWMoMCwxKSxicmVha3MgPSBzZXEoMCwgMSwuMikpICsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYyguMTUsLjg1KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gImJsYW5rIiksDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSkNCkZpdHRlZC5QbG90LjINCmBgYA0KDQoNCiMjIFRlc3Qgb2YgU2ltcGxlIEludGVyYWN0aW9ucw0KLSBJZiB5b3Ugd2FudCB0byBrbm93IGlmIHRoZSBpbnRlcmFjdGlvbiBpcyBzaWduaWZpY2FudCBhdCBlYWNoIGxldmVsIG9mIEFTRCBzY29yZSwgeW91IHNpbXBseSBoYXZlIHRvIHJlLWNlbnRlciB0aGUgQVNELiAgV2UgYWxyZWFkeSBrbm93IHRoZSBtaWRkbGUgcGxvdCB3YXMgc2lnbmlmaWNhbnQuIFdlIGFyZSBnb2luZyB0byB3YXRjaCB0aGUgKipUaW1lOkluc3RydWN0b3IuRFJvYm90KiogdGVybXMgYXMgd2UgY2hhbmdlIHRoZSBjZW50ZXIgcG9pbnQgYXQgQVNELkMNCg0KIyMjIFRlc3QgLTEgU0Qgb2YgQVNEDQotIFdlIG1vdmUgdGhlIGNlbnRlciB0byBiZSAtMSBTRCBieSBhZGRpbmcgMSBTRA0KYGBge3J9DQpMb25nU2ltJEFTRC5OMXNkPC1Mb25nU2ltJEFTRC5DK3NkKExvbmdTaW0kQVNELkMpDQpDb3YyLk1vZGVsLlNpbXBsZS5OMXNkPC1sbWVyKENvb3JkaW5hdGlvbiB+IFRpbWUqSW5zdHJ1Y3Rvci5EKkFTRC5OMXNkDQogICAgICAgICAgICAgICAgKygxK1RpbWV8U3ViamVjdCksIGRhdGE9TG9uZ1NpbSwgUkVNTD1GQUxTRSkNCnN1bW1hcnkoQ292Mi5Nb2RlbC5TaW1wbGUuTjFzZCwgY29ycmVsYXRpb249RikNCmBgYA0KDQotICoqVGltZTpJbnN0cnVjdG9yLkRSb2JvdCoqIGlzIG5vdCBzaWduaWZpY2FudC4gU28gdGhlIGxlZnQgcGFuZWwgaXMgb3VyIGdyYXBoIGlzIG5vdCBhbiBpbnRlcmFjdGlvbg0KDQojIyMgVGVzdCArMSBTRCBvZiBBU0QNCi0gV2UgbW92ZSB0aGUgY2VudGVyIHRvIGJlICsxIFNEIGJ5IHN1YnRyYWN0aW5nIDEgU0QNCmBgYHtyfQ0KTG9uZ1NpbSRBU0QuUDFzZDwtTG9uZ1NpbSRBU0QuQy1zZChMb25nU2ltJEFTRC5DKQ0KQ292Mi5Nb2RlbC5TaW1wbGUuUDFzZDwtbG1lcihDb29yZGluYXRpb24gfiBUaW1lKkluc3RydWN0b3IuRCpBU0QuUDFzZA0KICAgICAgICAgICAgICAgICsoMStUaW1lfFN1YmplY3QpLCBkYXRhPUxvbmdTaW0sIFJFTUw9RkFMU0UpDQpzdW1tYXJ5KENvdjIuTW9kZWwuU2ltcGxlLlAxc2QsIGNvcnJlbGF0aW9uPUYpDQpgYGANCg0KLSAqKlRpbWU6SW5zdHJ1Y3Rvci5EUm9ib3QqKiBpcyBzaWduaWZpY2FudCAoYXMgaXQgaGFzIHRvIGJlKS4gU28gdGhlIHJpZ2h0IHBhbmVsIGluIG91ciBncmFwaCBpcyBhbiBpbnRlcmFjdGlvbi4gDQotIEluIHN1bW1hcnksIG91ciB0d28gd2F5IGludGVyYWN0aW9uIGNoYW5nZXMgYXMgZnVuY3Rpb24gb2YgQVNEIHNjb3JlDQoNCiMgUmVmZXJlbmNlcw0KQ2hsZWJvd3NraSwgQy4sIEdyZWVuLCBKLiBBLiwgQmFydG9uLCBNLiBMLiwgJiBGZWluLCBELiAoMjAxMCkuIFVzaW5nIHRoZSBjaGlsZGhvb2QgYXV0aXNtIHJhdGluZyBzY2FsZSB0byBkaWFnbm9zZSBhdXRpc20gc3BlY3RydW0gZGlzb3JkZXJzLiAqSm91cm5hbCBvZiBhdXRpc20gYW5kIGRldmVsb3BtZW50YWwgZGlzb3JkZXJzKiwgNDAoNyksIDc4Ny03OTkuDQoNClNyaW5pdmFzYW4sIFMuIE0uLCBLYXVyLCBNLiwgUGFyaywgSS4gSy4sIEdpZmZvcmQsIFQuIEQuLCBNYXJzaCwgSy4gTC4sICYgQmhhdCwgQS4gTi4gKDIwMTUpLiBUaGUgZWZmZWN0cyBvZiByaHl0aG0gYW5kIHJvYm90aWMgaW50ZXJ2ZW50aW9ucyBvbiB0aGUgaW1pdGF0aW9uL3ByYXhpcywgaW50ZXJwZXJzb25hbCBzeW5jaHJvbnksIGFuZCBtb3RvciBwZXJmb3JtYW5jZSBvZiBjaGlsZHJlbiB3aXRoIGF1dGlzbSBzcGVjdHJ1bSBkaXNvcmRlciAoQVNEKTogYSBwaWxvdCByYW5kb21pemVkIGNvbnRyb2xsZWQgdHJpYWwuICpBdXRpc20gcmVzZWFyY2ggYW5kIHRyZWF0bWVudCouDQoNCjxzY3JpcHQ+DQogIChmdW5jdGlvbihpLHMsbyxnLHIsYSxtKXtpWydHb29nbGVBbmFseXRpY3NPYmplY3QnXT1yO2lbcl09aVtyXXx8ZnVuY3Rpb24oKXsNCiAgKGlbcl0ucT1pW3JdLnF8fFtdKS5wdXNoKGFyZ3VtZW50cyl9LGlbcl0ubD0xKm5ldyBEYXRlKCk7YT1zLmNyZWF0ZUVsZW1lbnQobyksDQogIG09cy5nZXRFbGVtZW50c0J5VGFnTmFtZShvKVswXTthLmFzeW5jPTE7YS5zcmM9ZzttLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGEsbSkNCiAgfSkod2luZG93LGRvY3VtZW50LCdzY3JpcHQnLCdodHRwczovL3d3dy5nb29nbGUtYW5hbHl0aWNzLmNvbS9hbmFseXRpY3MuanMnLCdnYScpOw0KDQogIGdhKCdjcmVhdGUnLCAnVUEtOTA0MTUxNjAtMScsICdhdXRvJyk7DQogIGdhKCdzZW5kJywgJ3BhZ2V2aWV3Jyk7DQoNCjwvc2NyaXB0Pg0K