Naturalistic Designs

The inevitable challenge when dealing with longitudinal designs is when to measure the participant and how to represent time in the model. In addition, because time is passing, you cannot guarantee that there are no time-variant predictors that you will have to deal with or with missingness. To understand this problem, let’s work through an example.

You have come up with your own modified protocol of CBT treat generalized anxiety disorder. While you are interested in the effectiveness of this new treatment, you cannot run a double-blind clinical study with the control group because you lack those particular resources. Instead, you already have a large number of undergraduates (N = 45) interested in coming to the clinic to reduce their generalized anxiety. Therefore you are interested in whether the students feel that their anxiety is decreasing over the course of treatment. The treatment will occur in eight sessions over the course of approximately 18 weeks, with a somewhat exponential cadence. Meaning that the students will first show up often at the beginning of the study and then the time between sessions will be stretched out [weeks: 0, 1, 2.8, 5.2, 8.0, 11.2, 14.7, 18.5]. You record from the students at each session how anxious they have felt in general over the course of the previous week. At the beginning of the study, you have recorded their Beck Depression Index score (as it is often highly correlated with anxiety). You also record when subjects do not show up for therapy sessions, but still emailed them asking them for their anxiety scores when they do not show up. Some are responsive and reply, but many do not. You open enrollment for a three-month period, record when they show up and set an approximate schedule for their visits following the general protocol of visits.

Visualize The data

  • We self-report of Anxiety score (0 = Low to 10 High) at each Week (0-18) or Session (0-7). We have their BDI at the start of the study; we know which Therapy sessions they attended. Download Data
AxSim<-read.csv("Mixed/AnxietySim.csv")
AxSim$Subject<-as.factor(AxSim$Subject)
AxSim$Attend<-factor(AxSim$Therapy,
                     levels=c(0,1),
                     labels=c("No Show","Show"))

Speg.1<-ggplot(data = AxSim, aes(x=Enrollment,y=AnxietyScore, group=Subject, color=Attend))+
  geom_point()+
  geom_line()+
  ylab("Self Report of Anxiety")+xlab("Enrollment/Treatment Weeks")+
  ggtitle("By Subject") +
  theme(legend.position = "right")+theme_bw()
Speg.1

Limit to a few subjects

SS_select=c("1","5","10","15","20","25","30","35","40")

Speg.2<-ggplot(data = subset(AxSim, Subject %in% SS_select), 
               aes(x=Enrollment,y=AnxietyScore, color=Attend))+
  facet_wrap(~Subject)+
  geom_point()+
  geom_line()+
  ylab("Self Report of Anxiety")+xlab("Enrollment/Treatment Weeks")+
  ggtitle("By Subject") +
  theme(legend.position = "right")+theme_bw()
Speg.2

Coding Time

  • Do we use time from enrollment?
    • Enrollment has the slight differences in when sessions were started, but people can start apart by 3 months making time hard to deal with
    • We can fix it by making a new variable called Week
      • Enrollment - Enrollment start date [per subject]
library(dplyr)
AxSim<-
  AxSim %>% 
  group_by(Subject)%>% 
  mutate(EnrollmentStart=Enrollment[1]) %>%
  mutate(Week = Enrollment - EnrollmentStart)
Enrollment Week
0.700000 0.000000
1.712855 1.012855
3.475186 2.775186
5.829432 5.129432
8.763547 8.063547
11.801827 11.101827
15.329693 14.629693
19.109640 18.409640
  • We can code Session instead of the Week, but the cadence is different

Cadence Differences

  • Here is plot of Session number by Week.
SS_select=c("1")

CadencePlot<-ggplot(data = subset(AxSim, Subject %in% SS_select), 
               aes(x=Session,y=Week))+
  geom_point()+
  geom_line()+
  scale_y_continuous(breaks = seq(0, 19, by = 1))+
  scale_x_continuous(breaks = seq(0, 7, by = 1)) +
  xlab("Session Number")+ylab("Treatment Weeks")+
  theme(legend.position = "right")+theme_bw()
CadencePlot 

  • Notice the slopes are different and thus it will affect the slope estimate

Modeling Cadence

  • Compare Week Model vs Session Model
  • We will ignore the other predictors for now

Week Model Fixed Effects:

Week.Model<-lmer(AnxietyScore ~ Week+ 
           (1+Week|Subject), 
         data=AxSim, REML=FALSE)
effect term estimate std.error statistic df p.value
fixed (Intercept) 8.4518133 0.0820153 103.05163 45.34254 0
fixed Week -0.1612106 0.0151390 -10.64871 47.51626 0

Session Model Fixed Effects:

Session.Model<-lmer(AnxietyScore ~ Session+ 
           (1+Session|Subject), 
         data=AxSim, REML=FALSE)
effect term estimate std.error statistic df p.value
fixed (Intercept) 8.7575107 0.0759658 115.28226 45.41633 0
fixed Session -0.4413921 0.0407728 -10.82564 46.96877 0
  • Note the slope is different between the two different terms. Which is more logical?
AxSim$WeekM<-predict(Week.Model, newdata=AxSim)
AxSim$SessionM<-predict(Session.Model, newdata=AxSim)

AxSimPredict<- AxSim %>% 
  dplyr::group_by(Session)%>% 
  dplyr::summarise(ASMean=mean(AnxietyScore,na.rm = TRUE),
            ModelW=mean(WeekM,na.rm=TRUE),
            ModelS=mean(SessionM,na.rm=TRUE))

ggplot(data = AxSimPredict)+
  geom_line(aes(x=Session,y=ASMean,color='black'), size=2)+
  geom_line(aes(x=Session,y=ModelW,color='blue'), size=2,alpha=.2)+
  geom_line(aes(x=Session,y=ModelS,color='red'), size=2,alpha=.2)+
  scale_x_continuous(breaks = seq(0, 7, by = 1)) +
 scale_colour_manual(name = 'Data Source', 
         values =c('black'='black','red'='red','blue'='blue'), labels = c('Raw','Week',"Session"))+
  ylab("Mean of Self Report of Anxiety")+xlab("Sesssion")+
  theme(legend.position = "top")+theme_bw()

  • Remember, Weeks was not linear so when we try to predict down to a linear scale its shows a curve.
    • We can also go back and look at the AIC/Deviance: Note these are NOT nested models (so the pvalues is meaningless, but we can see the AIC and deviance is lower on session models)
anova(Week.Model,Session.Model)
## Data: AxSim
## Models:
## Week.Model: AnxietyScore ~ Week + (1 + Week | Subject)
## Session.Model: AnxietyScore ~ Session + (1 + Session | Subject)
##               npar    AIC    BIC  logLik deviance  Chisq Df Pr(>Chisq)
## Week.Model       6 753.61 775.67 -370.80   741.61                     
## Session.Model    6 721.16 743.22 -354.58   709.16 32.443  0
  • The results are not different in terms of the story we might tell, but we are doing linear modeling and Weeks is not linear variable.

  • MCAR (Missing Completely At Random): “There’s no relationship between whether a data point is missing and any values in the data set, missing or observed.”

    • This is rarely the case in longitudinal data.
  • MAR (Missing At Random): “means the propensity for a data point to be missing is not related to the missing data, but it is related to some of the observed data”. In other words, the subject does not show up to the session and does not respond to your data, and you are missing your DV.

    • This is very common and not really a major problem
  • MNAR (Missing Not At Random): “means the propensity for a data point to be missing is related to the missing data”. You have no idea why the response/question is missing. Thus you cannot infer it.

MissingAttend<-
  AxSim %>% 
  group_by(Attend)%>% 
  summarise(NA_Percent = round(sum(!is.na(AnxietyScore))/length(AnxietyScore),4)*100)
Attend NA_Percent
No Show 53.1
Show 100.0
  • Yikes 53% of the time subjects did not show up they did not give a self-report
MissingSession<- AxSim %>% 
  group_by(Session)%>% 
  summarise(NA_Percent = round(sum(!is.na(AnxietyScore))/length(AnxietyScore),4)*100)
Session NA_Percent
0 100.00
1 95.56
2 95.56
3 84.44
4 66.67
5 68.89
6 73.33
7 64.44
  • Logically the percentage of missing DV over time increases.
  • The mixed model will take what data it has and still be able to make predictions, but you have to assume the data is MAR

Time-Variant Predictors

  • Attendance varied with time: Clients always started by coming to sessions and then they missed a few in between or stopped coming. What is important here is that no one dropped out at session 0 and very few at session 1-2.

Modeling

Main Effects Model

  • We will start with the Main Effects Model, but let’s work with continuously coded Therapy instead of the dummy coded Attend.
Main.Model<-lmer(AnxietyScore ~ Session+Therapy+
           (1+Session|Subject), 
         data=AxSim, REML=FALSE)
summary(Main.Model ,correlation=FALSE)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: AnxietyScore ~ Session + Therapy + (1 + Session | Subject)
##    Data: AxSim
## 
##      AIC      BIC   logLik deviance df.resid 
##    651.9    677.6   -319.0    637.9      285 
## 
## Scaled residuals: 
##      Min       1Q   Median       3Q      Max 
## -2.62417 -0.50908 -0.00069  0.64319  2.06493 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev. Corr
##  Subject  (Intercept) 0.11373  0.3372       
##           Session     0.04693  0.2166   0.71
##  Residual             0.30919  0.5561       
## Number of obs: 292, groups:  Subject, 45
## 
## Fixed effects:
##              Estimate Std. Error        df t value Pr(>|t|)    
## (Intercept)   9.64463    0.12129 169.64364  79.517   <2e-16 ***
## Session      -0.51921    0.03657  51.45408 -14.197   <2e-16 ***
## Therapy      -0.92132    0.09937 260.11487  -9.271   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Plot Main effects

library(effects)
Results.Main<-Effect(c("Session","Therapy"),Main.Model,
                        xlevels=list(Session=seq(0,7,1),Therapy=c(0,1)))

Results.Main<-as.data.frame(Results.Main)
Results.Main$Therapy<-factor(Results.Main$Therapy,
                     levels=c(0,1),
                     labels=c("No Show","Show"))

Main.Plot <-ggplot(data = Results.Main, 
                            aes(x = Session, y =fit))+
  geom_line(aes(color=Therapy),size=1)+
  coord_cartesian(ylim = c(0, 10))+ 
  geom_ribbon(aes(ymin=lower, ymax=upper,fill=Therapy),alpha=.2)+
    scale_x_continuous(breaks = seq(0, 7, by = 1)) +
  ylab("Self Report of Anxiety")+xlab("Session")+
    ggtitle("Main Effects") +
  theme(legend.position = "right")+theme_bw()
Main.Plot

Interpretation

This model is saying even people who do not come to therapy get better over time. Does that make sense? Also, the model predicts those who do show up to therapy have lower anxiety overall. But does the model reflect the data?

Interaction Model

  • Add the interaction between session and therapy.
Inter.Model<-lmer(AnxietyScore ~ Session*Therapy+
           (1+Session|Subject), 
         data=AxSim, REML=FALSE)
summary(Inter.Model ,correlation=FALSE)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: AnxietyScore ~ Session * Therapy + (1 + Session | Subject)
##    Data: AxSim
## 
##      AIC      BIC   logLik deviance df.resid 
##    605.3    634.7   -294.7    589.3      284 
## 
## Scaled residuals: 
##      Min       1Q   Median       3Q      Max 
## -2.78935 -0.59059 -0.05999  0.60910  2.72489 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev. Corr
##  Subject  (Intercept) 0.07147  0.2673       
##           Session     0.04793  0.2189   0.92
##  Residual             0.26233  0.5122       
## Number of obs: 292, groups:  Subject, 45
## 
## Fixed effects:
##                  Estimate Std. Error        df t value Pr(>|t|)    
## (Intercept)       8.51534    0.18711 230.89499  45.509  < 2e-16 ***
## Session          -0.24648    0.05172 152.91554  -4.765 4.35e-06 ***
## Therapy           0.35221    0.19436 242.40109   1.812   0.0712 .  
## Session:Therapy  -0.34141    0.04624 237.23090  -7.383 2.60e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Plot Interaction

Results.Inter1<-Effect(c("Session","Therapy"),Inter.Model,
                        xlevels=list(Session=seq(0,7,1),Therapy=c(0,1)))

Results.Inter1<-as.data.frame(Results.Inter1)
Results.Inter1$Therapy<-factor(Results.Inter1$Therapy,
                     levels=c(0,1),
                     labels=c("No Show","Show"))

Inter1.Plot <-ggplot(data = Results.Inter1, 
                            aes(x = Session, y =fit))+
  geom_line(aes(color=Therapy),size=1)+
  coord_cartesian(ylim = c(0, 10))+ 
  geom_ribbon(aes(ymin=lower, ymax=upper,fill=Therapy),alpha=.2)+
    scale_x_continuous(breaks = seq(0, 7, by = 1)) +
  ylab("Self Report of Anxiety")+xlab("Session")+
    ggtitle("Interaction Effects") +
  theme(legend.position = "right")+theme_bw()
Inter1.Plot

Test Improvement?

anova(Main.Model,Inter.Model)
## Data: AxSim
## Models:
## Main.Model: AnxietyScore ~ Session + Therapy + (1 + Session | Subject)
## Inter.Model: AnxietyScore ~ Session * Therapy + (1 + Session | Subject)
##             npar    AIC    BIC  logLik deviance  Chisq Df Pr(>Chisq)    
## Main.Model     7 651.90 677.64 -318.95   637.90                         
## Inter.Model    8 605.32 634.74 -294.66   589.32 48.582  1  3.168e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  • Yes, the interaction model is better.

Interpretation

Again, this model is saying even people who do not come to therapy get better over time (Session Term). But the model does show an an interaction: those who go to therapy do report less anxiety over the sessions!

Random effect of Time-Variant Predictor?

We have allowed each participant to have their own slope relative to the sessions; meaning that each participant can respond to the therapy sessions in their own way. As we saw in the initial spaghetti plot, this was probably a good idea. However, could it be that those who actually show up to therapy sessions versus drop out might have different slopes? The interaction suggest there’s an overall effect, however, could it be that there are individual slopes for each participant relative to whether they did or did not attend therapy sessions? In other words, should we control for whether they show up to the therapy sessions as a random effect? The short answer is no because that is a between-subject effect and does not vary as a function of the level 2 variable (i.e., the subject). The longer answer is that it depends! Case in point below.

True Main effects?

In our previous modeling, we noticed both the consistent main effect of sessions and the simple effect of those who did were no-shows at therapy, still showing lower self-reports of anxiety over time. From a theoretical perspective this does not quite make sense, in that how do people reduce their overall anxiety levels by never having gone to therapy? If time heals all wounds then why are there therapists? Remember, in our data all subjects started in therapy and attended at least one or two sessions. Therefore any main effect/simple effect of no-shows improving on anxiety could be that they learn the techniques they needed in the first few sessions and continue to improve steadily once they had a kickstart. Therefore an alternative method in which to model the data may seem a little odd from a regression perspective but makes sense in the context of this particular data set. What we’re going to do is remove the main effect of sessions. In other words, were only going to test the interaction between sessions and therapy attendance as well as the main effect of therapy, given that we know people came in and out of therapy sessions. By removing the main effect of time, we will be creating a theoretical control group of those individuals who never attended a therapy session, but we also want to control for the random effect of that interaction. This allows us to remove the main effect that is not logical (as random) and see the results we would have expected.

Inter.Model.3<-lmer(AnxietyScore ~ Therapy+Session:Therapy+
           (1+Therapy+Session:Therapy|Subject), 
         data=AxSim, REML=FALSE)
summary(Inter.Model.3 ,correlation=FALSE)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: 
## AnxietyScore ~ Therapy + Session:Therapy + (1 + Therapy + Session:Therapy |  
##     Subject)
##    Data: AxSim
## 
##      AIC      BIC   logLik deviance df.resid 
##    637.3    674.1   -308.6    617.3      282 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -4.0061 -0.5087 -0.0255  0.5806  2.7752 
## 
## Random effects:
##  Groups   Name            Variance Std.Dev. Corr       
##  Subject  (Intercept)     0.60441  0.7774              
##           Therapy         0.28246  0.5315   -1.00      
##           Therapy:Session 0.07572  0.2752    0.96 -0.94
##  Residual                 0.29604  0.5441              
## Number of obs: 292, groups:  Subject, 45
## 
## Fixed effects:
##                 Estimate Std. Error       df t value Pr(>|t|)    
## (Intercept)      7.37884    0.13525 38.85585   54.56   <2e-16 ***
## Therapy          1.50092    0.12076 49.09602   12.43   <2e-16 ***
## Therapy:Session -0.59409    0.04657 47.14372  -12.76   <2e-16 ***
## ---
## 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 is having some issues with our random correlations, let’s remove them:
Inter.Model.3a<-lmer(AnxietyScore ~ Therapy+Session:Therapy+
           (1+Therapy+Session:Therapy||Subject), 
         data=AxSim, REML=FALSE)
summary(Inter.Model.3a ,correlation=FALSE)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: 
## AnxietyScore ~ Therapy + Session:Therapy + (1 + Therapy + Session:Therapy ||  
##     Subject)
##    Data: AxSim
## 
##      AIC      BIC   logLik deviance df.resid 
##    676.6    702.3   -331.3    662.6      285 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -4.2102 -0.4737  0.0183  0.5406  2.5074 
## 
## Random effects:
##  Groups    Name            Variance  Std.Dev. 
##  Subject   (Intercept)     2.616e-01 5.114e-01
##  Subject.1 Therapy         3.484e-10 1.866e-05
##  Subject.2 Therapy:Session 6.798e-02 2.607e-01
##  Residual                  3.304e-01 5.748e-01
## Number of obs: 292, groups:  Subject, 45
## 
## Fixed effects:
##                  Estimate Std. Error        df t value Pr(>|t|)    
## (Intercept)       7.33648    0.10538  79.36444   69.62  < 2e-16 ***
## Therapy           1.51811    0.09896 253.01179   15.34  < 2e-16 ***
## Therapy:Session  -0.57147    0.04798  45.15198  -11.91 1.57e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')

Plot Interaction

Results.Inter3<-Effect(c("Session","Therapy"),Inter.Model.3a,
                        xlevels=list(Session=seq(0,7,1),Therapy=c(0,1)))

Results.Inter3<-as.data.frame(Results.Inter3)
Results.Inter3$Therapy<-factor(Results.Inter3$Therapy,
                     levels=c(0,1),
                     labels=c("No Show","Show"))

Inter3.Plot <-ggplot(data = Results.Inter3, 
                            aes(x = Session, y =fit))+
  geom_line(aes(color=Therapy),size=1)+
  coord_cartesian(ylim = c(0, 10))+ 
  geom_ribbon(aes(ymin=lower, ymax=upper,fill=Therapy),alpha=.2)+
    scale_x_continuous(breaks = seq(0, 7, by = 1)) +
  ylab("Self Report of Anxiety")+xlab("Session")+
    ggtitle("Interaction Effects") +
  theme(legend.position = "right")+theme_bw()
Inter3.Plot

Interpretation

The results of this model make much more theoretical sense. Those who never show up to therapy never improve, while those who did show up to therapy steadily showed improvement over time. The main effect term for therapy is necessary for interpreting the final result of the model, but in itself is not meaningful. It is the intercept difference between the no-show and shows conditions at session 0. In other words, as you can clearly see the no-show group had a lower intercept than the show group. But remember, the no-show group, in this case, is somewhat a theoretical condition. However, the slope that we are now predicting is likely more accurate for those individuals who actually would have attended all therapy sessions from beginning to end.

Test Improvement?

We cannot really test the difference. First, we took away a fixed effect and removed the random correlations and added more term. However again remember that model fit is not always the end goal. Sometimes the goal is to fit the data to the theory best. Model 3a is more logical theoretically, while the interaction model (2) was just going to be a better fit but more difficult to interpret because the data that is fitting and interpreting is not always real. It is the goal of the modeler to select the “best fit” and what they define as best fit is up to them.

Notes

Centering Session

  • To change the meaning the main effect of therapy, we would need to center time
AxSim$Session.C<-AxSim$Session-3.5
Inter.Model.3b<-lmer(AnxietyScore ~ Therapy+Session.C:Therapy+
           (1+Therapy+Session.C:Therapy||Subject), 
         data=AxSim, REML=FALSE)
summary(Inter.Model.3b ,correlation=FALSE)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: 
## AnxietyScore ~ Therapy + Session.C:Therapy + (1 + Therapy + Session.C:Therapy ||  
##     Subject)
##    Data: AxSim
## 
##      AIC      BIC   logLik deviance df.resid 
##    729.7    755.5   -357.9    715.7      285 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.8960 -0.4641  0.0383  0.5254  2.6457 
## 
## Random effects:
##  Groups    Name              Variance Std.Dev.
##  Subject   (Intercept)       0.82340  0.9074  
##  Subject.1 Therapy           0.22109  0.4702  
##  Subject.2 Therapy:Session.C 0.05781  0.2404  
##  Residual                    0.31794  0.5639  
## Number of obs: 292, groups:  Subject, 45
## 
## Fixed effects:
##                   Estimate Std. Error       df t value Pr(>|t|)    
## (Intercept)        7.37389    0.15595 47.35328  47.284  < 2e-16 ***
## Therapy           -0.54004    0.12627 43.97852  -4.277 0.000101 ***
## Therapy:Session.C -0.58098    0.04276 52.79677 -13.587  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  • Here we can see the main effect term makes more sense now (those with more attendance have lower anxiety)

Plot Interaction

Results.Inter4<-Effect(c("Session.C","Therapy"),Inter.Model.3b,
                        xlevels=list(Session.C=seq(-3.5,3.5,.5),Therapy=c(0,1)))

Results.Inter4<-as.data.frame(Results.Inter4)
Results.Inter4$Therapy<-factor(Results.Inter4$Therapy,
                     levels=c(0,1),
                     labels=c("No Show","Show"))

Inter4.Plot <-ggplot(data = Results.Inter4, 
                            aes(x = Session.C, y =fit))+
  geom_line(aes(color=Therapy),size=1)+
  coord_cartesian(ylim = c(0, 10))+ 
  geom_ribbon(aes(ymin=lower, ymax=upper,fill=Therapy),alpha=.2)+
    scale_x_continuous(breaks = seq(-3, 3, by = 1)) +
  ylab("Self Report of Anxiety")+xlab("Session")+
    ggtitle("Interaction Effects") +
  theme(legend.position = "right")+theme_bw()
Inter4.Plot

Missing vs. Full data

  • Did all that missing data change our story?
  • Since the data was simulated let’s compare to the complete dataset (we will compare to model 2)
Inter.Model.ALL<-lmer(AnxietyScore_True ~ Session*Therapy+
           (1+Session|Subject), 
         data=AxSim, REML=FALSE)

Plot Interaction

Results.Inter5<-Effect(c("Session","Therapy"),Inter.Model.ALL,
                        xlevels=list(Session=seq(0,7,1),Therapy=c(0,1)))

Results.Inter5<-as.data.frame(Results.Inter5)
Results.Inter5$Therapy<-factor(Results.Inter5$Therapy,
                     levels=c(0,1),
                     labels=c("No Show","Show"))

Inter5.Plot <-ggplot(data = Results.Inter5, 
                            aes(x = Session, y =fit))+
  geom_line(aes(color=Therapy),size=1)+
  coord_cartesian(ylim = c(0, 10))+ 
  geom_ribbon(aes(ymin=lower, ymax=upper,fill=Therapy),alpha=.2)+
    scale_x_continuous(breaks = seq(0, 7, by = 1)) +
  ylab("Self Report of Anxiety")+xlab("Session")+
    ggtitle("Interaction Effects") +
  theme(legend.position = "right")+theme_bw()
Inter5.Plot

Interpretation

  • Looks the Same as model 2.

Final Notes about Missing

  • Do we need to remove the missing values before we run our model? NO! Again you will notice the missing data did not change the result by much (when compared side by side)
AxSim.NoNA<-AxSim[is.na(AxSim$AnxietyScore)==FALSE,]
Inter.Model.2.Missing<-lmer(AnxietyScore ~ Session*Therapy+
           (1+Session|Subject), 
         data=AxSim.NoNA, REML=FALSE)
Statistical models
  Model 1 Model 2 Model 3
(Intercept) 8.30 (0.15)*** 8.52 (0.19)*** 8.52 (0.19)***
Session -0.21 (0.04)*** -0.25 (0.05)*** -0.25 (0.05)***
Therapy 0.57 (0.15)*** 0.35 (0.19) 0.35 (0.19)
Session:Therapy -0.37 (0.04)*** -0.34 (0.05)*** -0.34 (0.05)***
AIC 720.12 605.32 605.32
BIC 751.21 634.74 634.74
Log Likelihood -352.06 -294.66 -294.66
Num. obs. 360 292 292
Num. groups: Subject 45 45 45
Var: Subject (Intercept) 0.10 0.07 0.07
Var: Subject Session 0.05 0.05 0.05
Cov: Subject (Intercept) Session 0.04 0.05 0.05
Var: Residual 0.25 0.26 0.26
***p < 0.001; **p < 0.01; *p < 0.05

Time-Invarient Predictor

  • We can add BDI
AxSim$BDI.Z<-scale(AxSim$BDI)
Inter.Model.C<-lmer(AnxietyScore ~ Session*Therapy+BDI.Z+
           (1+Session|Subject), 
         data=AxSim, REML=FALSE)
summary(Inter.Model.C ,correlation=FALSE)
## Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
##   method [lmerModLmerTest]
## Formula: AnxietyScore ~ Session * Therapy + BDI.Z + (1 + Session | Subject)
##    Data: AxSim
## 
##      AIC      BIC   logLik deviance df.resid 
##    596.8    629.9   -289.4    578.8      283 
## 
## Scaled residuals: 
##      Min       1Q   Median       3Q      Max 
## -2.99012 -0.59482 -0.03139  0.62407  2.53065 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev. Corr
##  Subject  (Intercept) 0.03075  0.1754       
##           Session     0.04840  0.2200   1.00
##  Residual             0.25951  0.5094       
## Number of obs: 292, groups:  Subject, 45
## 
## Fixed effects:
##                  Estimate Std. Error        df t value Pr(>|t|)    
## (Intercept)       8.52976    0.18291 259.28508  46.634  < 2e-16 ***
## Session          -0.25004    0.05166 154.08073  -4.840 3.12e-06 ***
## Therapy           0.33505    0.19238 252.92381   1.742 0.082799 .  
## BDI.Z             0.15767    0.04426 241.42458   3.563 0.000442 ***
## Session:Therapy  -0.33503    0.04616 247.00196  -7.258 5.07e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
  • Notice our random correlation

Test Improvement?

anova(Inter.Model,Inter.Model.C)
## Data: AxSim
## Models:
## Inter.Model: AnxietyScore ~ Session * Therapy + (1 + Session | Subject)
## Inter.Model.C: AnxietyScore ~ Session * Therapy + BDI.Z + (1 + Session | Subject)
##               npar    AIC    BIC  logLik deviance  Chisq Df Pr(>Chisq)   
## Inter.Model      8 605.32 634.74 -294.66   589.32                        
## Inter.Model.C    9 596.77 629.86 -289.38   578.77 10.552  1    0.00116 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Interpretation

  • Adding BDI improves fit and is positive, as expected. It does not change our other result
LS0tDQp0aXRsZTogJ0RlYWxpbmcgd2l0aCBUaW1lJw0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGZvbnRzaXplOiA4cHQNCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCi0tLQ0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlID0gVFJVRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRkFMU0UpDQprbml0cjo6b3B0c19jaHVuayRzZXQod2FybmluZyA9ICBGQUxTRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGg9NC4yNSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcuaGVpZ2h0PTQuMCkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcuYWxpZ249J2NlbnRlcicpIA0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHJlc3VsdHM9J2hvbGQnKSANCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobG1lNCkNCnRoZW1lX3NldCh0aGVtZV9idygpKQ0KYGBgDQoNCg0KIyBOYXR1cmFsaXN0aWMgRGVzaWducw0KVGhlIGluZXZpdGFibGUgY2hhbGxlbmdlIHdoZW4gZGVhbGluZyB3aXRoIGxvbmdpdHVkaW5hbCBkZXNpZ25zIGlzIHdoZW4gdG8gbWVhc3VyZSB0aGUgcGFydGljaXBhbnQgYW5kIGhvdyB0byByZXByZXNlbnQgdGltZSBpbiB0aGUgbW9kZWwuIEluIGFkZGl0aW9uLCBiZWNhdXNlIHRpbWUgaXMgcGFzc2luZywgeW91IGNhbm5vdCBndWFyYW50ZWUgdGhhdCB0aGVyZSBhcmUgbm8gdGltZS12YXJpYW50IHByZWRpY3RvcnMgdGhhdCB5b3Ugd2lsbCBoYXZlIHRvIGRlYWwgd2l0aCBvciB3aXRoIG1pc3NpbmduZXNzLiAgVG8gdW5kZXJzdGFuZCB0aGlzIHByb2JsZW0sIGxldCdzIHdvcmsgdGhyb3VnaCBhbiBleGFtcGxlLg0KDQo+IFlvdSBoYXZlIGNvbWUgdXAgd2l0aCB5b3VyIG93biBtb2RpZmllZCBwcm90b2NvbCBvZiBDQlQgdHJlYXQgZ2VuZXJhbGl6ZWQgYW54aWV0eSBkaXNvcmRlci4gV2hpbGUgeW91IGFyZSBpbnRlcmVzdGVkIGluIHRoZSBlZmZlY3RpdmVuZXNzIG9mIHRoaXMgbmV3IHRyZWF0bWVudCwgeW91IGNhbm5vdCBydW4gYSBkb3VibGUtYmxpbmQgY2xpbmljYWwgc3R1ZHkgd2l0aCB0aGUgY29udHJvbCBncm91cCBiZWNhdXNlIHlvdSBsYWNrIHRob3NlIHBhcnRpY3VsYXIgcmVzb3VyY2VzLiBJbnN0ZWFkLCB5b3UgYWxyZWFkeSBoYXZlIGEgbGFyZ2UgbnVtYmVyIG9mIHVuZGVyZ3JhZHVhdGVzIChOID0gNDUpIGludGVyZXN0ZWQgaW4gY29taW5nIHRvIHRoZSBjbGluaWMgdG8gcmVkdWNlIHRoZWlyIGdlbmVyYWxpemVkIGFueGlldHkuIFRoZXJlZm9yZSB5b3UgYXJlIGludGVyZXN0ZWQgaW4gd2hldGhlciB0aGUgc3R1ZGVudHMgZmVlbCB0aGF0IHRoZWlyIGFueGlldHkgaXMgZGVjcmVhc2luZyBvdmVyIHRoZSBjb3Vyc2Ugb2YgdHJlYXRtZW50LiBUaGUgdHJlYXRtZW50IHdpbGwgb2NjdXIgaW4gZWlnaHQgc2Vzc2lvbnMgb3ZlciB0aGUgY291cnNlIG9mIGFwcHJveGltYXRlbHkgMTggd2Vla3MsIHdpdGggYSBzb21ld2hhdCBleHBvbmVudGlhbCAqY2FkZW5jZSouIE1lYW5pbmcgdGhhdCB0aGUgc3R1ZGVudHMgd2lsbCBmaXJzdCBzaG93IHVwIG9mdGVuIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHN0dWR5IGFuZCB0aGVuIHRoZSB0aW1lIGJldHdlZW4gc2Vzc2lvbnMgd2lsbCBiZSBzdHJldGNoZWQgb3V0IFt3ZWVrczogMCwgMSwgMi44LCA1LjIsIDguMCwgMTEuMiwgMTQuNywgMTguNV0uIFlvdSByZWNvcmQgZnJvbSB0aGUgc3R1ZGVudHMgYXQgZWFjaCBzZXNzaW9uIGhvdyBhbnhpb3VzIHRoZXkgaGF2ZSBmZWx0IGluIGdlbmVyYWwgb3ZlciB0aGUgY291cnNlIG9mIHRoZSBwcmV2aW91cyB3ZWVrLiBBdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzdHVkeSwgeW91IGhhdmUgcmVjb3JkZWQgdGhlaXIgQmVjayBEZXByZXNzaW9uIEluZGV4IHNjb3JlIChhcyBpdCBpcyBvZnRlbiBoaWdobHkgY29ycmVsYXRlZCB3aXRoIGFueGlldHkpLiBZb3UgYWxzbyByZWNvcmQgd2hlbiBzdWJqZWN0cyBkbyBub3Qgc2hvdyB1cCBmb3IgdGhlcmFweSBzZXNzaW9ucywgYnV0IHN0aWxsIGVtYWlsZWQgdGhlbSBhc2tpbmcgdGhlbSBmb3IgdGhlaXIgYW54aWV0eSBzY29yZXMgd2hlbiB0aGV5IGRvIG5vdCBzaG93IHVwLiBTb21lIGFyZSByZXNwb25zaXZlIGFuZCByZXBseSwgYnV0IG1hbnkgZG8gbm90LiBZb3Ugb3BlbiBlbnJvbGxtZW50IGZvciBhIHRocmVlLW1vbnRoIHBlcmlvZCwgcmVjb3JkIHdoZW4gdGhleSBzaG93IHVwIGFuZCBzZXQgYW4gYXBwcm94aW1hdGUgc2NoZWR1bGUgZm9yIHRoZWlyIHZpc2l0cyBmb2xsb3dpbmcgdGhlIGdlbmVyYWwgcHJvdG9jb2wgb2YgdmlzaXRzLiAgDQoNCiMjIFZpc3VhbGl6ZSBUaGUgZGF0YQ0KDQotIFdlIHNlbGYtcmVwb3J0IG9mICoqQW54aWV0eSBzY29yZSoqICgwID0gTG93IHRvIDEwIEhpZ2gpIGF0IGVhY2ggKipXZWVrKiogKDAtMTgpIG9yICoqU2Vzc2lvbioqICgwLTcpLiBXZSBoYXZlIHRoZWlyIEJESSBhdCB0aGUgc3RhcnQgb2YgdGhlIHN0dWR5OyB3ZSBrbm93IHdoaWNoICoqVGhlcmFweSoqIHNlc3Npb25zIHRoZXkgYXR0ZW5kZWQuIFtEb3dubG9hZCBEYXRhXSgvTWl4ZWQvQW54aWV0eVNpbS5jc3YpDQoNCmBgYHtyLCBmaWcud2lkdGg9Ni4yNSxmaWcuaGVpZ2h0PTQuMH0NCkF4U2ltPC1yZWFkLmNzdigiTWl4ZWQvQW54aWV0eVNpbS5jc3YiKQ0KQXhTaW0kU3ViamVjdDwtYXMuZmFjdG9yKEF4U2ltJFN1YmplY3QpDQpBeFNpbSRBdHRlbmQ8LWZhY3RvcihBeFNpbSRUaGVyYXB5LA0KICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPWMoMCwxKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJObyBTaG93IiwiU2hvdyIpKQ0KDQpTcGVnLjE8LWdncGxvdChkYXRhID0gQXhTaW0sIGFlcyh4PUVucm9sbG1lbnQseT1BbnhpZXR5U2NvcmUsIGdyb3VwPVN1YmplY3QsIGNvbG9yPUF0dGVuZCkpKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fbGluZSgpKw0KICB5bGFiKCJTZWxmIFJlcG9ydCBvZiBBbnhpZXR5IikreGxhYigiRW5yb2xsbWVudC9UcmVhdG1lbnQgV2Vla3MiKSsNCiAgZ2d0aXRsZSgiQnkgU3ViamVjdCIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikrdGhlbWVfYncoKQ0KU3BlZy4xDQpgYGANCg0KTGltaXQgdG8gYSBmZXcgc3ViamVjdHMNCg0KYGBge3IsIGZpZy53aWR0aD02LjI1LGZpZy5oZWlnaHQ9NC4wfQ0KU1Nfc2VsZWN0PWMoIjEiLCI1IiwiMTAiLCIxNSIsIjIwIiwiMjUiLCIzMCIsIjM1IiwiNDAiKQ0KDQpTcGVnLjI8LWdncGxvdChkYXRhID0gc3Vic2V0KEF4U2ltLCBTdWJqZWN0ICVpbiUgU1Nfc2VsZWN0KSwgDQogICAgICAgICAgICAgICBhZXMoeD1FbnJvbGxtZW50LHk9QW54aWV0eVNjb3JlLCBjb2xvcj1BdHRlbmQpKSsNCiAgZmFjZXRfd3JhcCh+U3ViamVjdCkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9saW5lKCkrDQogIHlsYWIoIlNlbGYgUmVwb3J0IG9mIEFueGlldHkiKSt4bGFiKCJFbnJvbGxtZW50L1RyZWF0bWVudCBXZWVrcyIpKw0KICBnZ3RpdGxlKCJCeSBTdWJqZWN0IikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSt0aGVtZV9idygpDQpTcGVnLjINCmBgYA0KDQojIENvZGluZyBUaW1lDQotIERvIHdlIHVzZSB0aW1lIGZyb20gKmVucm9sbG1lbnQqPw0KICAgIC0gRW5yb2xsbWVudCBoYXMgdGhlIHNsaWdodCBkaWZmZXJlbmNlcyBpbiB3aGVuIHNlc3Npb25zIHdlcmUgc3RhcnRlZCwgYnV0IHBlb3BsZSBjYW4gc3RhcnQgYXBhcnQgYnkgMyBtb250aHMgbWFraW5nIHRpbWUgaGFyZCB0byBkZWFsIHdpdGgNCiAgICAtIFdlIGNhbiBmaXggaXQgYnkgbWFraW5nIGEgbmV3IHZhcmlhYmxlIGNhbGxlZCAqV2VlayoNCiAgICAgICAgLSBFbnJvbGxtZW50IC0gRW5yb2xsbWVudCBzdGFydCBkYXRlIFtwZXIgc3ViamVjdF0NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KQXhTaW08LQ0KICBBeFNpbSAlPiUgDQogIGdyb3VwX2J5KFN1YmplY3QpJT4lIA0KICBtdXRhdGUoRW5yb2xsbWVudFN0YXJ0PUVucm9sbG1lbnRbMV0pICU+JQ0KICBtdXRhdGUoV2VlayA9IEVucm9sbG1lbnQgLSBFbnJvbGxtZW50U3RhcnQpDQpgYGANCg0KYGBge3IsZWNobz1GQUxTRX0NCmxpYnJhcnkoa2FibGVFeHRyYSkNCmthYmxlKHN1YnNldChBeFNpbSwgU3ViamVjdCAlaW4lICIxIiwgc2VsZWN0PWMoIkVucm9sbG1lbnQiLCJXZWVrIikpKQ0KYGBgDQoNCi0gV2UgY2FuIGNvZGUgKlNlc3Npb24qIGluc3RlYWQgb2YgdGhlICpXZWVrKiwgYnV0IHRoZSBjYWRlbmNlIGlzIGRpZmZlcmVudA0KDQojIyBDYWRlbmNlIERpZmZlcmVuY2VzDQotIEhlcmUgaXMgcGxvdCBvZiBTZXNzaW9uIG51bWJlciBieSBXZWVrLiANCmBgYHtyIHNlcywgZmlnLndpZHRoPTYuMCxmaWcuaGVpZ2h0PTMuMH0NClNTX3NlbGVjdD1jKCIxIikNCg0KQ2FkZW5jZVBsb3Q8LWdncGxvdChkYXRhID0gc3Vic2V0KEF4U2ltLCBTdWJqZWN0ICVpbiUgU1Nfc2VsZWN0KSwgDQogICAgICAgICAgICAgICBhZXMoeD1TZXNzaW9uLHk9V2VlaykpKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fbGluZSgpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDE5LCBieSA9IDEpKSsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA3LCBieSA9IDEpKSArDQogIHhsYWIoIlNlc3Npb24gTnVtYmVyIikreWxhYigiVHJlYXRtZW50IFdlZWtzIikrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpK3RoZW1lX2J3KCkNCkNhZGVuY2VQbG90IA0KYGBgDQogDQotIE5vdGljZSB0aGUgc2xvcGVzIGFyZSBkaWZmZXJlbnQgYW5kIHRodXMgaXQgd2lsbCBhZmZlY3QgdGhlIHNsb3BlIGVzdGltYXRlDQoNCiMjIyBNb2RlbGluZyBDYWRlbmNlDQotIENvbXBhcmUgKldlZWsqIE1vZGVsIHZzICpTZXNzaW9uKiBNb2RlbA0KLSBXZSB3aWxsIGlnbm9yZSB0aGUgb3RoZXIgcHJlZGljdG9ycyBmb3Igbm93DQoNCldlZWsgTW9kZWwgRml4ZWQgRWZmZWN0czoNCmBgYHtyfQ0KV2Vlay5Nb2RlbDwtbG1lcihBbnhpZXR5U2NvcmUgfiBXZWVrKyANCiAgICAgICAgICAgKDErV2Vla3xTdWJqZWN0KSwgDQogICAgICAgICBkYXRhPUF4U2ltLCBSRU1MPUZBTFNFKQ0KYGBgDQoNCmBgYHtyLGVjaG89RkFMU0V9DQpsaWJyYXJ5KGJyb29tLm1peGVkKQ0Ka2FibGUodGlkeShXZWVrLk1vZGVsLGVmZmVjdHMgPSBjKCJmaXhlZCIpKSkNCmBgYA0KDQpTZXNzaW9uIE1vZGVsIEZpeGVkIEVmZmVjdHM6DQpgYGB7cn0NClNlc3Npb24uTW9kZWw8LWxtZXIoQW54aWV0eVNjb3JlIH4gU2Vzc2lvbisgDQogICAgICAgICAgICgxK1Nlc3Npb258U3ViamVjdCksIA0KICAgICAgICAgZGF0YT1BeFNpbSwgUkVNTD1GQUxTRSkNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmthYmxlKHRpZHkoU2Vzc2lvbi5Nb2RlbCxlZmZlY3RzID0gYygiZml4ZWQiKSksICJodG1sIiwgYm9va3RhYnMgPSBUKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYpDQpgYGANCg0KLSBOb3RlIHRoZSBzbG9wZSBpcyBkaWZmZXJlbnQgYmV0d2VlbiB0aGUgdHdvIGRpZmZlcmVudCB0ZXJtcy4gV2hpY2ggaXMgbW9yZSBsb2dpY2FsPyANCg0KYGBge3IgcHJlZHBsb3R9DQpBeFNpbSRXZWVrTTwtcHJlZGljdChXZWVrLk1vZGVsLCBuZXdkYXRhPUF4U2ltKQ0KQXhTaW0kU2Vzc2lvbk08LXByZWRpY3QoU2Vzc2lvbi5Nb2RlbCwgbmV3ZGF0YT1BeFNpbSkNCg0KQXhTaW1QcmVkaWN0PC0gQXhTaW0gJT4lIA0KICBkcGx5cjo6Z3JvdXBfYnkoU2Vzc2lvbiklPiUgDQogIGRwbHlyOjpzdW1tYXJpc2UoQVNNZWFuPW1lYW4oQW54aWV0eVNjb3JlLG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBNb2RlbFc9bWVhbihXZWVrTSxuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIE1vZGVsUz1tZWFuKFNlc3Npb25NLG5hLnJtPVRSVUUpKQ0KDQpnZ3Bsb3QoZGF0YSA9IEF4U2ltUHJlZGljdCkrDQogIGdlb21fbGluZShhZXMoeD1TZXNzaW9uLHk9QVNNZWFuLGNvbG9yPSdibGFjaycpLCBzaXplPTIpKw0KICBnZW9tX2xpbmUoYWVzKHg9U2Vzc2lvbix5PU1vZGVsVyxjb2xvcj0nYmx1ZScpLCBzaXplPTIsYWxwaGE9LjIpKw0KICBnZW9tX2xpbmUoYWVzKHg9U2Vzc2lvbix5PU1vZGVsUyxjb2xvcj0ncmVkJyksIHNpemU9MixhbHBoYT0uMikrDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNywgYnkgPSAxKSkgKw0KIHNjYWxlX2NvbG91cl9tYW51YWwobmFtZSA9ICdEYXRhIFNvdXJjZScsIA0KICAgICAgICAgdmFsdWVzID1jKCdibGFjayc9J2JsYWNrJywncmVkJz0ncmVkJywnYmx1ZSc9J2JsdWUnKSwgbGFiZWxzID0gYygnUmF3JywnV2VlaycsIlNlc3Npb24iKSkrDQogIHlsYWIoIk1lYW4gb2YgU2VsZiBSZXBvcnQgb2YgQW54aWV0eSIpK3hsYWIoIlNlc3NzaW9uIikrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSt0aGVtZV9idygpDQpgYGANCg0KLSBSZW1lbWJlciwgV2Vla3Mgd2FzIG5vdCBsaW5lYXIgc28gd2hlbiB3ZSB0cnkgdG8gcHJlZGljdCBkb3duIHRvIGEgbGluZWFyIHNjYWxlIGl0cyBzaG93cyBhIGN1cnZlLiANCiAgICAtIFdlIGNhbiBhbHNvIGdvIGJhY2sgYW5kIGxvb2sgYXQgdGhlIEFJQy9EZXZpYW5jZTogTm90ZSB0aGVzZSBhcmUgTk9UIG5lc3RlZCBtb2RlbHMgKHNvIHRoZSBwdmFsdWVzIGlzIG1lYW5pbmdsZXNzLCBidXQgd2UgY2FuIHNlZSB0aGUgQUlDIGFuZCBkZXZpYW5jZSBpcyBsb3dlciBvbiBzZXNzaW9uIG1vZGVscykNCmBgYHtyfQ0KYW5vdmEoV2Vlay5Nb2RlbCxTZXNzaW9uLk1vZGVsKQ0KDQpgYGANCg0KLSBUaGUgcmVzdWx0cyBhcmUgbm90IGRpZmZlcmVudCBpbiB0ZXJtcyBvZiB0aGUgc3Rvcnkgd2UgbWlnaHQgdGVsbCwgYnV0IHdlIGFyZSBkb2luZyBsaW5lYXIgbW9kZWxpbmcgYW5kICpXZWVrcyogaXMgbm90IGxpbmVhciB2YXJpYWJsZS4gDQoNCi0gTUNBUiAoTWlzc2luZyBDb21wbGV0ZWx5IEF0IFJhbmRvbSk6ICAiVGhlcmUncyBubyByZWxhdGlvbnNoaXAgYmV0d2VlbiB3aGV0aGVyIGEgZGF0YSBwb2ludCBpcyBtaXNzaW5nIGFuZCBhbnkgdmFsdWVzIGluIHRoZSBkYXRhIHNldCwgbWlzc2luZyBvciBvYnNlcnZlZC4iIA0KICAgIC0gKipUaGlzIGlzIHJhcmVseSB0aGUgY2FzZSBpbiBsb25naXR1ZGluYWwgZGF0YS4qKg0KDQotIE1BUiAoTWlzc2luZyBBdCBSYW5kb20pOiAibWVhbnMgdGhlIHByb3BlbnNpdHkgZm9yIGEgZGF0YSBwb2ludCB0byBiZSBtaXNzaW5nIGlzIG5vdCByZWxhdGVkIHRvIHRoZSBtaXNzaW5nIGRhdGEsIGJ1dCBpdCBpcyByZWxhdGVkIHRvIHNvbWUgb2YgdGhlIG9ic2VydmVkIGRhdGEiLiBJbiBvdGhlciB3b3JkcywgdGhlIHN1YmplY3QgZG9lcyBub3Qgc2hvdyB1cCB0byB0aGUgc2Vzc2lvbiBhbmQgZG9lcyBub3QgcmVzcG9uZCB0byB5b3VyIGRhdGEsIGFuZCB5b3UgYXJlIG1pc3NpbmcgeW91ciBEVi4gDQogICAgLSAqKlRoaXMgaXMgdmVyeSBjb21tb24gYW5kIG5vdCByZWFsbHkgYSBtYWpvciBwcm9ibGVtKioNCiAgICANCi0gTU5BUiAoTWlzc2luZyBOb3QgQXQgUmFuZG9tKTogIm1lYW5zIHRoZSBwcm9wZW5zaXR5IGZvciBhIGRhdGEgcG9pbnQgdG8gYmUgbWlzc2luZyBpcyByZWxhdGVkIHRvIHRoZSBtaXNzaW5nIGRhdGEiLiBZb3UgaGF2ZSBubyBpZGVhIHdoeSB0aGUgcmVzcG9uc2UvcXVlc3Rpb24gaXMgbWlzc2luZy4gVGh1cyB5b3UgY2Fubm90IGluZmVyIGl0LiANCiAgICAtICoqVGhpcyBpcyBhIHByb2JsZW0uIEZvciBleGFtcGxlLCB5b3VyIGNsaWVudCBzdG9wIHNob3dpbmcgdXAgYmVjYXVzZSBvZiBzb21ldGhpbmcgaW4gdGhlIGxhc3Qgc2Vzc2lvbiBhbmQgeW91IHdpbGwgbmV2ZXIga25vdyB3aHkqKg0KICAgICAgICAtIFNlZTogaHR0cDovL3d3dy50aGVhbmFseXNpc2ZhY3Rvci5jb20vbWFyLWFuZC1tY2FyLW1pc3NpbmctZGF0YS8NCg0KYGBge3J9DQpNaXNzaW5nQXR0ZW5kPC0NCiAgQXhTaW0gJT4lIA0KICBncm91cF9ieShBdHRlbmQpJT4lIA0KICBzdW1tYXJpc2UoTkFfUGVyY2VudCA9IHJvdW5kKHN1bSghaXMubmEoQW54aWV0eVNjb3JlKSkvbGVuZ3RoKEFueGlldHlTY29yZSksNCkqMTAwKQ0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0Ka2FibGUoTWlzc2luZ0F0dGVuZCwiaHRtbCIsIGJvb2t0YWJzID0gVCkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBGKQ0KYGBgDQoNCi0gWWlrZXMgNTMlIG9mIHRoZSB0aW1lIHN1YmplY3RzIGRpZCBub3Qgc2hvdyB1cCB0aGV5IGRpZCBub3QgZ2l2ZSBhIHNlbGYtcmVwb3J0IA0KDQpgYGB7cn0NCk1pc3NpbmdTZXNzaW9uPC0gQXhTaW0gJT4lIA0KICBncm91cF9ieShTZXNzaW9uKSU+JSANCiAgc3VtbWFyaXNlKE5BX1BlcmNlbnQgPSByb3VuZChzdW0oIWlzLm5hKEFueGlldHlTY29yZSkpL2xlbmd0aChBbnhpZXR5U2NvcmUpLDQpKjEwMCkNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmthYmxlKE1pc3NpbmdTZXNzaW9uLCJodG1sIiwgYm9va3RhYnMgPSBUKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYpDQpgYGANCg0KLSBMb2dpY2FsbHkgdGhlIHBlcmNlbnRhZ2Ugb2YgbWlzc2luZyBEViBvdmVyIHRpbWUgaW5jcmVhc2VzLiANCi0gVGhlIG1peGVkIG1vZGVsIHdpbGwgdGFrZSB3aGF0IGRhdGEgaXQgaGFzIGFuZCBzdGlsbCBiZSBhYmxlIHRvIG1ha2UgcHJlZGljdGlvbnMsIGJ1dCB5b3UgaGF2ZSB0byBhc3N1bWUgdGhlIGRhdGEgaXMgTUFSDQoNCiMgVGltZS1WYXJpYW50IFByZWRpY3RvcnMNCi0gQXR0ZW5kYW5jZSB2YXJpZWQgd2l0aCB0aW1lOiBDbGllbnRzIGFsd2F5cyBzdGFydGVkIGJ5IGNvbWluZyB0byBzZXNzaW9ucyBhbmQgdGhlbiB0aGV5IG1pc3NlZCBhIGZldyBpbiBiZXR3ZWVuIG9yIHN0b3BwZWQgY29taW5nLiAgV2hhdCBpcyBpbXBvcnRhbnQgaGVyZSBpcyB0aGF0IG5vIG9uZSBkcm9wcGVkIG91dCBhdCBzZXNzaW9uIDAgYW5kIHZlcnkgZmV3IGF0IHNlc3Npb24gMS0yLiAgDQoNCiMjIE1vZGVsaW5nDQoNCiMjIyBNYWluIEVmZmVjdHMgTW9kZWwgDQotIFdlIHdpbGwgc3RhcnQgd2l0aCB0aGUgTWFpbiBFZmZlY3RzIE1vZGVsLCBidXQgbGV0J3Mgd29yayB3aXRoIGNvbnRpbnVvdXNseSBjb2RlZCBUaGVyYXB5IGluc3RlYWQgb2YgdGhlIGR1bW15IGNvZGVkIEF0dGVuZC4gDQoNCmBgYHtyfQ0KTWFpbi5Nb2RlbDwtbG1lcihBbnhpZXR5U2NvcmUgfiBTZXNzaW9uK1RoZXJhcHkrDQogICAgICAgICAgICgxK1Nlc3Npb258U3ViamVjdCksIA0KICAgICAgICAgZGF0YT1BeFNpbSwgUkVNTD1GQUxTRSkNCnN1bW1hcnkoTWFpbi5Nb2RlbCAsY29ycmVsYXRpb249RkFMU0UpDQpgYGANCg0KIyMjIyBQbG90IE1haW4gZWZmZWN0cw0KYGBge3IsIGZpZy53aWR0aD01LjAsZmlnLmhlaWdodD0zLjB9DQpsaWJyYXJ5KGVmZmVjdHMpDQpSZXN1bHRzLk1haW48LUVmZmVjdChjKCJTZXNzaW9uIiwiVGhlcmFweSIpLE1haW4uTW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICB4bGV2ZWxzPWxpc3QoU2Vzc2lvbj1zZXEoMCw3LDEpLFRoZXJhcHk9YygwLDEpKSkNCg0KUmVzdWx0cy5NYWluPC1hcy5kYXRhLmZyYW1lKFJlc3VsdHMuTWFpbikNClJlc3VsdHMuTWFpbiRUaGVyYXB5PC1mYWN0b3IoUmVzdWx0cy5NYWluJFRoZXJhcHksDQogICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygwLDEpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk5vIFNob3ciLCJTaG93IikpDQoNCk1haW4uUGxvdCA8LWdncGxvdChkYXRhID0gUmVzdWx0cy5NYWluLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFNlc3Npb24sIHkgPWZpdCkpKw0KICBnZW9tX2xpbmUoYWVzKGNvbG9yPVRoZXJhcHkpLHNpemU9MSkrDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAxMCkpKyANCiAgZ2VvbV9yaWJib24oYWVzKHltaW49bG93ZXIsIHltYXg9dXBwZXIsZmlsbD1UaGVyYXB5KSxhbHBoYT0uMikrDQogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA3LCBieSA9IDEpKSArDQogIHlsYWIoIlNlbGYgUmVwb3J0IG9mIEFueGlldHkiKSt4bGFiKCJTZXNzaW9uIikrDQogICAgZ2d0aXRsZSgiTWFpbiBFZmZlY3RzIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSt0aGVtZV9idygpDQpNYWluLlBsb3QNCmBgYA0KDQojIyMjIEludGVycHJldGF0aW9uDQpUaGlzIG1vZGVsIGlzIHNheWluZyBldmVuIHBlb3BsZSB3aG8gZG8gbm90IGNvbWUgdG8gdGhlcmFweSBnZXQgYmV0dGVyIG92ZXIgdGltZS4gRG9lcyB0aGF0IG1ha2Ugc2Vuc2U/IEFsc28sIHRoZSBtb2RlbCBwcmVkaWN0cyB0aG9zZSB3aG8gZG8gc2hvdyB1cCB0byB0aGVyYXB5IGhhdmUgbG93ZXIgYW54aWV0eSBvdmVyYWxsLiBCdXQgZG9lcyB0aGUgbW9kZWwgcmVmbGVjdCB0aGUgZGF0YT8NCg0KDQojIyMgSW50ZXJhY3Rpb24gTW9kZWwNCi0gQWRkIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNlc3Npb24gYW5kIHRoZXJhcHkuDQoNCmBgYHtyfQ0KSW50ZXIuTW9kZWw8LWxtZXIoQW54aWV0eVNjb3JlIH4gU2Vzc2lvbipUaGVyYXB5Kw0KICAgICAgICAgICAoMStTZXNzaW9ufFN1YmplY3QpLCANCiAgICAgICAgIGRhdGE9QXhTaW0sIFJFTUw9RkFMU0UpDQpzdW1tYXJ5KEludGVyLk1vZGVsICxjb3JyZWxhdGlvbj1GQUxTRSkNCmBgYA0KDQojIyMjIFBsb3QgSW50ZXJhY3Rpb24NCmBgYHtyLCBmaWcud2lkdGg9NS4wLGZpZy5oZWlnaHQ9My4wfQ0KUmVzdWx0cy5JbnRlcjE8LUVmZmVjdChjKCJTZXNzaW9uIiwiVGhlcmFweSIpLEludGVyLk1vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgeGxldmVscz1saXN0KFNlc3Npb249c2VxKDAsNywxKSxUaGVyYXB5PWMoMCwxKSkpDQoNClJlc3VsdHMuSW50ZXIxPC1hcy5kYXRhLmZyYW1lKFJlc3VsdHMuSW50ZXIxKQ0KUmVzdWx0cy5JbnRlcjEkVGhlcmFweTwtZmFjdG9yKFJlc3VsdHMuSW50ZXIxJFRoZXJhcHksDQogICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygwLDEpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk5vIFNob3ciLCJTaG93IikpDQoNCkludGVyMS5QbG90IDwtZ2dwbG90KGRhdGEgPSBSZXN1bHRzLkludGVyMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBTZXNzaW9uLCB5ID1maXQpKSsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1UaGVyYXB5KSxzaXplPTEpKw0KICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTApKSsgDQogIGdlb21fcmliYm9uKGFlcyh5bWluPWxvd2VyLCB5bWF4PXVwcGVyLGZpbGw9VGhlcmFweSksYWxwaGE9LjIpKw0KICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNywgYnkgPSAxKSkgKw0KICB5bGFiKCJTZWxmIFJlcG9ydCBvZiBBbnhpZXR5IikreGxhYigiU2Vzc2lvbiIpKw0KICAgIGdndGl0bGUoIkludGVyYWN0aW9uIEVmZmVjdHMiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpK3RoZW1lX2J3KCkNCkludGVyMS5QbG90DQpgYGANCg0KIyMjIyBUZXN0IEltcHJvdmVtZW50Pw0KDQpgYGB7cn0NCmFub3ZhKE1haW4uTW9kZWwsSW50ZXIuTW9kZWwpDQpgYGANCg0KLSBZZXMsIHRoZSBpbnRlcmFjdGlvbiBtb2RlbCBpcyBiZXR0ZXIuDQoNCiMjIyMgSW50ZXJwcmV0YXRpb24NCkFnYWluLCB0aGlzIG1vZGVsIGlzIHNheWluZyBldmVuIHBlb3BsZSB3aG8gZG8gbm90IGNvbWUgdG8gdGhlcmFweSBnZXQgYmV0dGVyIG92ZXIgdGltZSAoU2Vzc2lvbiBUZXJtKS4gQnV0IHRoZSBtb2RlbCBkb2VzIHNob3cgYW4gYW4gaW50ZXJhY3Rpb246IHRob3NlIHdobyBnbyB0byB0aGVyYXB5IGRvIHJlcG9ydCBsZXNzIGFueGlldHkgb3ZlciB0aGUgc2Vzc2lvbnMhIA0KDQojIyBSYW5kb20gZWZmZWN0IG9mIFRpbWUtVmFyaWFudCBQcmVkaWN0b3I/DQpXZSBoYXZlIGFsbG93ZWQgZWFjaCBwYXJ0aWNpcGFudCB0byBoYXZlIHRoZWlyIG93biBzbG9wZSByZWxhdGl2ZSB0byB0aGUgc2Vzc2lvbnM7ICBtZWFuaW5nIHRoYXQgZWFjaCBwYXJ0aWNpcGFudCBjYW4gcmVzcG9uZCB0byB0aGUgdGhlcmFweSBzZXNzaW9ucyBpbiB0aGVpciBvd24gd2F5LiBBcyB3ZSBzYXcgaW4gdGhlIGluaXRpYWwgc3BhZ2hldHRpIHBsb3QsIHRoaXMgd2FzIHByb2JhYmx5IGEgZ29vZCBpZGVhLiBIb3dldmVyLCBjb3VsZCBpdCBiZSB0aGF0IHRob3NlIHdobyBhY3R1YWxseSBzaG93IHVwIHRvIHRoZXJhcHkgc2Vzc2lvbnMgdmVyc3VzIGRyb3Agb3V0IG1pZ2h0IGhhdmUgZGlmZmVyZW50IHNsb3Blcz8gVGhlIGludGVyYWN0aW9uIHN1Z2dlc3QgdGhlcmUncyBhbiBvdmVyYWxsIGVmZmVjdCwgaG93ZXZlciwgY291bGQgaXQgYmUgdGhhdCB0aGVyZSBhcmUgaW5kaXZpZHVhbCBzbG9wZXMgZm9yIGVhY2ggcGFydGljaXBhbnQgcmVsYXRpdmUgdG8gd2hldGhlciB0aGV5IGRpZCBvciBkaWQgbm90IGF0dGVuZCB0aGVyYXB5IHNlc3Npb25zPyBJbiBvdGhlciB3b3Jkcywgc2hvdWxkIHdlIGNvbnRyb2wgZm9yIHdoZXRoZXIgdGhleSBzaG93IHVwIHRvIHRoZSB0aGVyYXB5IHNlc3Npb25zIGFzIGEgcmFuZG9tIGVmZmVjdD8gVGhlIHNob3J0IGFuc3dlciBpcyBubyBiZWNhdXNlIHRoYXQgaXMgYSBiZXR3ZWVuLXN1YmplY3QgZWZmZWN0IGFuZCBkb2VzIG5vdCB2YXJ5IGFzIGEgZnVuY3Rpb24gb2YgdGhlIGxldmVsIDIgdmFyaWFibGUgKGkuZS4sIHRoZSBzdWJqZWN0KS4gKlRoZSBsb25nZXIgYW5zd2VyIGlzIHRoYXQgaXQgZGVwZW5kcyEgQ2FzZSBpbiBwb2ludCBiZWxvdy4qDQoNCiMjIyBUcnVlIE1haW4gZWZmZWN0cz8NCg0KSW4gb3VyIHByZXZpb3VzIG1vZGVsaW5nLCB3ZSBub3RpY2VkIGJvdGggdGhlIGNvbnNpc3RlbnQgbWFpbiBlZmZlY3Qgb2Ygc2Vzc2lvbnMgYW5kIHRoZSBzaW1wbGUgZWZmZWN0IG9mIHRob3NlIHdobyBkaWQgd2VyZSBuby1zaG93cyBhdCB0aGVyYXB5LCBzdGlsbCBzaG93aW5nIGxvd2VyIHNlbGYtcmVwb3J0cyBvZiBhbnhpZXR5IG92ZXIgdGltZS4gRnJvbSBhIHRoZW9yZXRpY2FsIHBlcnNwZWN0aXZlIHRoaXMgZG9lcyBub3QgcXVpdGUgbWFrZSBzZW5zZSwgaW4gdGhhdCBob3cgZG8gcGVvcGxlIHJlZHVjZSB0aGVpciBvdmVyYWxsIGFueGlldHkgbGV2ZWxzIGJ5IG5ldmVyIGhhdmluZyBnb25lIHRvIHRoZXJhcHk/IElmIHRpbWUgaGVhbHMgYWxsIHdvdW5kcyB0aGVuIHdoeSBhcmUgdGhlcmUgdGhlcmFwaXN0cz8gUmVtZW1iZXIsIGluIG91ciBkYXRhIGFsbCBzdWJqZWN0cyBzdGFydGVkIGluIHRoZXJhcHkgYW5kIGF0dGVuZGVkIGF0IGxlYXN0IG9uZSBvciB0d28gc2Vzc2lvbnMuIFRoZXJlZm9yZSBhbnkgbWFpbiBlZmZlY3Qvc2ltcGxlIGVmZmVjdCBvZiBuby1zaG93cyBpbXByb3Zpbmcgb24gYW54aWV0eSBjb3VsZCBiZSB0aGF0IHRoZXkgbGVhcm4gdGhlIHRlY2huaXF1ZXMgdGhleSBuZWVkZWQgaW4gdGhlIGZpcnN0IGZldyBzZXNzaW9ucyBhbmQgY29udGludWUgdG8gaW1wcm92ZSBzdGVhZGlseSBvbmNlIHRoZXkgaGFkIGEga2lja3N0YXJ0LiBUaGVyZWZvcmUgYW4gYWx0ZXJuYXRpdmUgbWV0aG9kIGluIHdoaWNoIHRvIG1vZGVsIHRoZSBkYXRhIG1heSBzZWVtIGEgbGl0dGxlIG9kZCBmcm9tIGEgcmVncmVzc2lvbiBwZXJzcGVjdGl2ZSBidXQgbWFrZXMgc2Vuc2UgaW4gdGhlIGNvbnRleHQgb2YgdGhpcyBwYXJ0aWN1bGFyIGRhdGEgc2V0LiBXaGF0IHdlJ3JlIGdvaW5nIHRvIGRvIGlzIHJlbW92ZSB0aGUgbWFpbiBlZmZlY3Qgb2Ygc2Vzc2lvbnMuIEluIG90aGVyIHdvcmRzLCB3ZXJlIG9ubHkgZ29pbmcgdG8gdGVzdCB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiBzZXNzaW9ucyBhbmQgdGhlcmFweSBhdHRlbmRhbmNlIGFzIHdlbGwgYXMgdGhlIG1haW4gZWZmZWN0IG9mIHRoZXJhcHksIGdpdmVuIHRoYXQgd2Uga25vdyBwZW9wbGUgY2FtZSBpbiBhbmQgb3V0IG9mIHRoZXJhcHkgc2Vzc2lvbnMuIEJ5IHJlbW92aW5nIHRoZSBtYWluIGVmZmVjdCBvZiB0aW1lLCB3ZSB3aWxsIGJlIGNyZWF0aW5nIGEgdGhlb3JldGljYWwgY29udHJvbCBncm91cCBvZiB0aG9zZSBpbmRpdmlkdWFscyB3aG8gbmV2ZXIgYXR0ZW5kZWQgYSB0aGVyYXB5IHNlc3Npb24sICpidXQgd2UgYWxzbyB3YW50IHRvIGNvbnRyb2wgZm9yIHRoZSByYW5kb20gZWZmZWN0IG9mIHRoYXQgaW50ZXJhY3Rpb24qLiBUaGlzIGFsbG93cyB1cyB0byByZW1vdmUgdGhlIG1haW4gZWZmZWN0IHRoYXQgaXMgbm90IGxvZ2ljYWwgKGFzIHJhbmRvbSkgYW5kIHNlZSB0aGUgcmVzdWx0cyB3ZSB3b3VsZCBoYXZlIGV4cGVjdGVkLiANCg0KYGBge3J9DQpJbnRlci5Nb2RlbC4zPC1sbWVyKEFueGlldHlTY29yZSB+IFRoZXJhcHkrU2Vzc2lvbjpUaGVyYXB5Kw0KICAgICAgICAgICAoMStUaGVyYXB5K1Nlc3Npb246VGhlcmFweXxTdWJqZWN0KSwgDQogICAgICAgICBkYXRhPUF4U2ltLCBSRU1MPUZBTFNFKQ0Kc3VtbWFyeShJbnRlci5Nb2RlbC4zICxjb3JyZWxhdGlvbj1GQUxTRSkNCmBgYA0KDQotIE5vdGUgaXMgaGF2aW5nIHNvbWUgaXNzdWVzIHdpdGggb3VyIHJhbmRvbSBjb3JyZWxhdGlvbnMsIGxldCdzIHJlbW92ZSB0aGVtOg0KDQpgYGB7cn0NCkludGVyLk1vZGVsLjNhPC1sbWVyKEFueGlldHlTY29yZSB+IFRoZXJhcHkrU2Vzc2lvbjpUaGVyYXB5Kw0KICAgICAgICAgICAoMStUaGVyYXB5K1Nlc3Npb246VGhlcmFweXx8U3ViamVjdCksIA0KICAgICAgICAgZGF0YT1BeFNpbSwgUkVNTD1GQUxTRSkNCnN1bW1hcnkoSW50ZXIuTW9kZWwuM2EgLGNvcnJlbGF0aW9uPUZBTFNFKQ0KYGBgDQoNCiMjIyMgUGxvdCBJbnRlcmFjdGlvbg0KYGBge3IsIGZpZy53aWR0aD01LjAsZmlnLmhlaWdodD0zLjB9DQpSZXN1bHRzLkludGVyMzwtRWZmZWN0KGMoIlNlc3Npb24iLCJUaGVyYXB5IiksSW50ZXIuTW9kZWwuM2EsDQogICAgICAgICAgICAgICAgICAgICAgICB4bGV2ZWxzPWxpc3QoU2Vzc2lvbj1zZXEoMCw3LDEpLFRoZXJhcHk9YygwLDEpKSkNCg0KUmVzdWx0cy5JbnRlcjM8LWFzLmRhdGEuZnJhbWUoUmVzdWx0cy5JbnRlcjMpDQpSZXN1bHRzLkludGVyMyRUaGVyYXB5PC1mYWN0b3IoUmVzdWx0cy5JbnRlcjMkVGhlcmFweSwNCiAgICAgICAgICAgICAgICAgICAgIGxldmVscz1jKDAsMSksDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiTm8gU2hvdyIsIlNob3ciKSkNCg0KSW50ZXIzLlBsb3QgPC1nZ3Bsb3QoZGF0YSA9IFJlc3VsdHMuSW50ZXIzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFNlc3Npb24sIHkgPWZpdCkpKw0KICBnZW9tX2xpbmUoYWVzKGNvbG9yPVRoZXJhcHkpLHNpemU9MSkrDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAxMCkpKyANCiAgZ2VvbV9yaWJib24oYWVzKHltaW49bG93ZXIsIHltYXg9dXBwZXIsZmlsbD1UaGVyYXB5KSxhbHBoYT0uMikrDQogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA3LCBieSA9IDEpKSArDQogIHlsYWIoIlNlbGYgUmVwb3J0IG9mIEFueGlldHkiKSt4bGFiKCJTZXNzaW9uIikrDQogICAgZ2d0aXRsZSgiSW50ZXJhY3Rpb24gRWZmZWN0cyIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikrdGhlbWVfYncoKQ0KSW50ZXIzLlBsb3QNCmBgYA0KDQojIyMjIEludGVycHJldGF0aW9uDQpUaGUgcmVzdWx0cyBvZiB0aGlzIG1vZGVsIG1ha2UgbXVjaCBtb3JlIHRoZW9yZXRpY2FsIHNlbnNlLiBUaG9zZSB3aG8gbmV2ZXIgc2hvdyB1cCB0byB0aGVyYXB5IG5ldmVyIGltcHJvdmUsIHdoaWxlIHRob3NlIHdobyBkaWQgc2hvdyB1cCB0byB0aGVyYXB5IHN0ZWFkaWx5IHNob3dlZCBpbXByb3ZlbWVudCBvdmVyIHRpbWUuICBUaGUgbWFpbiBlZmZlY3QgdGVybSBmb3IgdGhlcmFweSBpcyBuZWNlc3NhcnkgZm9yIGludGVycHJldGluZyB0aGUgZmluYWwgcmVzdWx0IG9mIHRoZSBtb2RlbCwgYnV0IGluIGl0c2VsZiBpcyBub3QgbWVhbmluZ2Z1bC4gSXQgaXMgdGhlIGludGVyY2VwdCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG5vLXNob3cgYW5kIHNob3dzIGNvbmRpdGlvbnMgYXQgc2Vzc2lvbiAwLiBJbiBvdGhlciB3b3JkcywgYXMgeW91IGNhbiBjbGVhcmx5IHNlZSB0aGUgbm8tc2hvdyBncm91cCBoYWQgYSBsb3dlciBpbnRlcmNlcHQgdGhhbiB0aGUgc2hvdyBncm91cC4gQnV0IHJlbWVtYmVyLCB0aGUgbm8tc2hvdyBncm91cCwgaW4gdGhpcyBjYXNlLCBpcyBzb21ld2hhdCBhIHRoZW9yZXRpY2FsIGNvbmRpdGlvbi4gIEhvd2V2ZXIsIHRoZSBzbG9wZSB0aGF0IHdlIGFyZSBub3cgcHJlZGljdGluZyBpcyBsaWtlbHkgbW9yZSBhY2N1cmF0ZSBmb3IgdGhvc2UgaW5kaXZpZHVhbHMgd2hvIGFjdHVhbGx5IHdvdWxkIGhhdmUgYXR0ZW5kZWQgYWxsIHRoZXJhcHkgc2Vzc2lvbnMgZnJvbSBiZWdpbm5pbmcgdG8gZW5kLg0KDQojIyMjIFRlc3QgSW1wcm92ZW1lbnQ/DQoNCldlIGNhbm5vdCByZWFsbHkgdGVzdCB0aGUgZGlmZmVyZW5jZS4gRmlyc3QsIHdlIHRvb2sgYXdheSBhIGZpeGVkIGVmZmVjdCBhbmQgcmVtb3ZlZCB0aGUgcmFuZG9tIGNvcnJlbGF0aW9ucyBhbmQgYWRkZWQgbW9yZSB0ZXJtLiBIb3dldmVyIGFnYWluIHJlbWVtYmVyIHRoYXQgbW9kZWwgZml0IGlzIG5vdCBhbHdheXMgdGhlIGVuZCBnb2FsLiBTb21ldGltZXMgdGhlIGdvYWwgaXMgdG8gZml0IHRoZSBkYXRhIHRvIHRoZSB0aGVvcnkgYmVzdC4gTW9kZWwgM2EgaXMgbW9yZSBsb2dpY2FsIHRoZW9yZXRpY2FsbHksIHdoaWxlIHRoZSBpbnRlcmFjdGlvbiBtb2RlbCAoMikgd2FzIGp1c3QgZ29pbmcgdG8gYmUgYSBiZXR0ZXIgZml0IGJ1dCBtb3JlIGRpZmZpY3VsdCB0byBpbnRlcnByZXQgYmVjYXVzZSB0aGUgZGF0YSB0aGF0IGlzIGZpdHRpbmcgYW5kIGludGVycHJldGluZyBpcyBub3QgYWx3YXlzIHJlYWwuIEl0IGlzIHRoZSBnb2FsIG9mIHRoZSBtb2RlbGVyIHRvIHNlbGVjdCB0aGUgImJlc3QgZml0IiBhbmQgd2hhdCB0aGV5IGRlZmluZSBhcyBiZXN0IGZpdCBpcyB1cCB0byB0aGVtLg0KDQojIE5vdGVzDQojIyBDZW50ZXJpbmcgU2Vzc2lvbg0KLSBUbyBjaGFuZ2UgdGhlIG1lYW5pbmcgdGhlIG1haW4gZWZmZWN0IG9mIHRoZXJhcHksIHdlIHdvdWxkIG5lZWQgdG8gY2VudGVyIHRpbWUNCg0KYGBge3J9DQpBeFNpbSRTZXNzaW9uLkM8LUF4U2ltJFNlc3Npb24tMy41DQpJbnRlci5Nb2RlbC4zYjwtbG1lcihBbnhpZXR5U2NvcmUgfiBUaGVyYXB5K1Nlc3Npb24uQzpUaGVyYXB5Kw0KICAgICAgICAgICAoMStUaGVyYXB5K1Nlc3Npb24uQzpUaGVyYXB5fHxTdWJqZWN0KSwgDQogICAgICAgICBkYXRhPUF4U2ltLCBSRU1MPUZBTFNFKQ0Kc3VtbWFyeShJbnRlci5Nb2RlbC4zYiAsY29ycmVsYXRpb249RkFMU0UpDQpgYGANCg0KLSBIZXJlIHdlIGNhbiAgc2VlIHRoZSBtYWluIGVmZmVjdCB0ZXJtIG1ha2VzIG1vcmUgc2Vuc2Ugbm93ICh0aG9zZSB3aXRoIG1vcmUgYXR0ZW5kYW5jZSBoYXZlIGxvd2VyIGFueGlldHkpIA0KDQojIyMgUGxvdCBJbnRlcmFjdGlvbg0KYGBge3IsIGZpZy53aWR0aD01LjAsZmlnLmhlaWdodD0zLjB9DQpSZXN1bHRzLkludGVyNDwtRWZmZWN0KGMoIlNlc3Npb24uQyIsIlRoZXJhcHkiKSxJbnRlci5Nb2RlbC4zYiwNCiAgICAgICAgICAgICAgICAgICAgICAgIHhsZXZlbHM9bGlzdChTZXNzaW9uLkM9c2VxKC0zLjUsMy41LC41KSxUaGVyYXB5PWMoMCwxKSkpDQoNClJlc3VsdHMuSW50ZXI0PC1hcy5kYXRhLmZyYW1lKFJlc3VsdHMuSW50ZXI0KQ0KUmVzdWx0cy5JbnRlcjQkVGhlcmFweTwtZmFjdG9yKFJlc3VsdHMuSW50ZXI0JFRoZXJhcHksDQogICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygwLDEpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk5vIFNob3ciLCJTaG93IikpDQoNCkludGVyNC5QbG90IDwtZ2dwbG90KGRhdGEgPSBSZXN1bHRzLkludGVyNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBTZXNzaW9uLkMsIHkgPWZpdCkpKw0KICBnZW9tX2xpbmUoYWVzKGNvbG9yPVRoZXJhcHkpLHNpemU9MSkrDQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAxMCkpKyANCiAgZ2VvbV9yaWJib24oYWVzKHltaW49bG93ZXIsIHltYXg9dXBwZXIsZmlsbD1UaGVyYXB5KSxhbHBoYT0uMikrDQogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMywgMywgYnkgPSAxKSkgKw0KICB5bGFiKCJTZWxmIFJlcG9ydCBvZiBBbnhpZXR5IikreGxhYigiU2Vzc2lvbiIpKw0KICAgIGdndGl0bGUoIkludGVyYWN0aW9uIEVmZmVjdHMiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpK3RoZW1lX2J3KCkNCkludGVyNC5QbG90DQpgYGANCg0KIyMgTWlzc2luZyB2cy4gRnVsbCBkYXRhDQotIERpZCBhbGwgdGhhdCBtaXNzaW5nIGRhdGEgY2hhbmdlIG91ciBzdG9yeT8NCi0gU2luY2UgdGhlIGRhdGEgd2FzIHNpbXVsYXRlZCBsZXQncyBjb21wYXJlIHRvIHRoZSBjb21wbGV0ZSBkYXRhc2V0ICh3ZSB3aWxsIGNvbXBhcmUgdG8gbW9kZWwgMikNCg0KYGBge3J9DQpJbnRlci5Nb2RlbC5BTEw8LWxtZXIoQW54aWV0eVNjb3JlX1RydWUgfiBTZXNzaW9uKlRoZXJhcHkrDQogICAgICAgICAgICgxK1Nlc3Npb258U3ViamVjdCksIA0KICAgICAgICAgZGF0YT1BeFNpbSwgUkVNTD1GQUxTRSkNCmBgYA0KDQojIyMgUGxvdCBJbnRlcmFjdGlvbg0KYGBge3IsIGZpZy53aWR0aD01LjAsZmlnLmhlaWdodD0zLjB9DQpSZXN1bHRzLkludGVyNTwtRWZmZWN0KGMoIlNlc3Npb24iLCJUaGVyYXB5IiksSW50ZXIuTW9kZWwuQUxMLA0KICAgICAgICAgICAgICAgICAgICAgICAgeGxldmVscz1saXN0KFNlc3Npb249c2VxKDAsNywxKSxUaGVyYXB5PWMoMCwxKSkpDQoNClJlc3VsdHMuSW50ZXI1PC1hcy5kYXRhLmZyYW1lKFJlc3VsdHMuSW50ZXI1KQ0KUmVzdWx0cy5JbnRlcjUkVGhlcmFweTwtZmFjdG9yKFJlc3VsdHMuSW50ZXI1JFRoZXJhcHksDQogICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygwLDEpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk5vIFNob3ciLCJTaG93IikpDQoNCkludGVyNS5QbG90IDwtZ2dwbG90KGRhdGEgPSBSZXN1bHRzLkludGVyNSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBTZXNzaW9uLCB5ID1maXQpKSsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1UaGVyYXB5KSxzaXplPTEpKw0KICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTApKSsgDQogIGdlb21fcmliYm9uKGFlcyh5bWluPWxvd2VyLCB5bWF4PXVwcGVyLGZpbGw9VGhlcmFweSksYWxwaGE9LjIpKw0KICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNywgYnkgPSAxKSkgKw0KICB5bGFiKCJTZWxmIFJlcG9ydCBvZiBBbnhpZXR5IikreGxhYigiU2Vzc2lvbiIpKw0KICAgIGdndGl0bGUoIkludGVyYWN0aW9uIEVmZmVjdHMiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpK3RoZW1lX2J3KCkNCkludGVyNS5QbG90DQpgYGANCiANCiMjIEludGVycHJldGF0aW9uDQotIExvb2tzIHRoZSBTYW1lIGFzIG1vZGVsIDIuICANCg0KDQojIyBGaW5hbCBOb3RlcyBhYm91dCBNaXNzaW5nDQotIERvIHdlIG5lZWQgdG8gcmVtb3ZlIHRoZSBtaXNzaW5nIHZhbHVlcyBiZWZvcmUgd2UgcnVuIG91ciBtb2RlbD8gTk8hIEFnYWluIHlvdSB3aWxsIG5vdGljZSB0aGUgbWlzc2luZyBkYXRhIGRpZCBub3QgY2hhbmdlIHRoZSByZXN1bHQgYnkgbXVjaCAod2hlbiBjb21wYXJlZCBzaWRlIGJ5IHNpZGUpDQpgYGB7ciBjaGVjfQ0KQXhTaW0uTm9OQTwtQXhTaW1baXMubmEoQXhTaW0kQW54aWV0eVNjb3JlKT09RkFMU0UsXQ0KSW50ZXIuTW9kZWwuMi5NaXNzaW5nPC1sbWVyKEFueGlldHlTY29yZSB+IFNlc3Npb24qVGhlcmFweSsNCiAgICAgICAgICAgKDErU2Vzc2lvbnxTdWJqZWN0KSwgDQogICAgICAgICBkYXRhPUF4U2ltLk5vTkEsIFJFTUw9RkFMU0UpDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0KbGlicmFyeSh0ZXhyZWcpDQpodG1scmVnKGxpc3QoSW50ZXIuTW9kZWwuQUxMLCBJbnRlci5Nb2RlbCxJbnRlci5Nb2RlbC4yLk1pc3NpbmcpLA0KICAgICAgICAgIGNvbHVtbi5sYWJlbHMgPSBjKCJBbGwgRGF0YSIsICJNaXNzaW5nIExlZnQiLCAiTWlzc2luZyBSZW1vdmVkIiksDQogICAgICAgICAgc2luZ2xlLnJvdz1UUlVFKQ0KYGBgDQoNCg0KDQojIyBUaW1lLUludmFyaWVudCBQcmVkaWN0b3INCi0gV2UgY2FuIGFkZCBCREkgDQoNCmBgYHtyfQ0KQXhTaW0kQkRJLlo8LXNjYWxlKEF4U2ltJEJESSkNCkludGVyLk1vZGVsLkM8LWxtZXIoQW54aWV0eVNjb3JlIH4gU2Vzc2lvbipUaGVyYXB5K0JESS5aKw0KICAgICAgICAgICAoMStTZXNzaW9ufFN1YmplY3QpLCANCiAgICAgICAgIGRhdGE9QXhTaW0sIFJFTUw9RkFMU0UpDQpzdW1tYXJ5KEludGVyLk1vZGVsLkMgLGNvcnJlbGF0aW9uPUZBTFNFKQ0KYGBgDQotIE5vdGljZSBvdXIgcmFuZG9tIGNvcnJlbGF0aW9uIA0KDQojIyMgVGVzdCBJbXByb3ZlbWVudD8NCg0KYGBge3J9DQphbm92YShJbnRlci5Nb2RlbCxJbnRlci5Nb2RlbC5DKQ0KYGBgDQoNCg0KIyMjIEludGVycHJldGF0aW9uDQotIEFkZGluZyBCREkgaW1wcm92ZXMgZml0IGFuZCBpcyBwb3NpdGl2ZSwgYXMgZXhwZWN0ZWQuIEl0IGRvZXMgbm90IGNoYW5nZSBvdXIgb3RoZXIgcmVzdWx0IA0KDQo8c2NyaXB0Pg0KICAoZnVuY3Rpb24oaSxzLG8sZyxyLGEsbSl7aVsnR29vZ2xlQW5hbHl0aWNzT2JqZWN0J109cjtpW3JdPWlbcl18fGZ1bmN0aW9uKCl7DQogIChpW3JdLnE9aVtyXS5xfHxbXSkucHVzaChhcmd1bWVudHMpfSxpW3JdLmw9MSpuZXcgRGF0ZSgpO2E9cy5jcmVhdGVFbGVtZW50KG8pLA0KICBtPXMuZ2V0RWxlbWVudHNCeVRhZ05hbWUobylbMF07YS5hc3luYz0xO2Euc3JjPWc7bS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShhLG0pDQogIH0pKHdpbmRvdyxkb2N1bWVudCwnc2NyaXB0JywnaHR0cHM6Ly93d3cuZ29vZ2xlLWFuYWx5dGljcy5jb20vYW5hbHl0aWNzLmpzJywnZ2EnKTsNCg0KICBnYSgnY3JlYXRlJywgJ1VBLTkwNDE1MTYwLTEnLCAnYXV0bycpOw0KICBnYSgnc2VuZCcsICdwYWdldmlldycpOw0KDQo8L3NjcmlwdD4NCg==