Mixed Design Factors

You want to show the effectiveness of CBT therapy against no therapy in reducing depression scores. You give clients (and controls) the Beck depression index (BDI at baseline, and every two weeks afterward for up to 6 Weeks. You assign 30 people to each between-subjects group (control or CBT) with varying levels of depression (from mild to severe; BDI of 20 to 50), and in total, you will collect 4 BDI scores for each person (within subject). You expect BDI scores to drop by the second BDI measurement and continue to decrease over sessions relative to control which should show no change. Keep in mind there is no intervention for the control group, and BDI score has a tendency to be unstable, so you are worried about assumption violations.

Plot of Simulation

Spaghetti Plot

Each line represents a person’s score across conditions

Means plot

Just like RM ANOVA, we will use Cousineau-Morey Corrected error bars which remove individual differences. The function will correct for the mixed design differences in the correction, just pass which variables are between below. Again, you can select between SE and CI (I plotted CI below).

source('HelperFunctions.R')

MeansforGGPlot <- summarySEwithin(data=DataSim2, "BDI", 
                                  withinvars=c("Time"),
                                  betweenvars=c("Group"),
                            idvar="ID", na.rm=FALSE, conf.interval=.95)

Means.Within.CI <-ggplot(data = MeansforGGPlot, aes(x = Time, y=BDI, group=Group))+
  scale_y_continuous(breaks = seq(0,40,5))+
  geom_line(aes(colour = Group), size=2)+
  geom_ribbon(aes(ymin=BDI-ci, ymax=BDI+ci,fill = Group), alpha=.5)+
  ylab("Mean BDI Score")+xlab("Time")+
  theme(legend.position = "right")
Means.Within.CI

For within error bars (Corrected) you can eye-ball significance (Cumming & Finch, 2005)

95% CIs:

  • \(p < .05\): when proportion overlap is about .50
  • \(p < .01\): when proportion overlap is about 0

Notice also you can see problems with the variance

2-Way Mixed ANOVA logic

Two-way Mixed ANOVA Table With the formulas (conceptually simplified)

Source SS DF MS F
\(Between\,Subject\) \(CSS_{row\,means}\) \(nK-1\) \(\frac{SS_{BS}}{df_{BS}}\)
\(Group\) \(CnSS_{Group\,means}\) \(K-1\) \(\frac{SS_{G}}{df_{G}}\) \(\frac{MS_{G}}{MS_{W_{G}}}\)
\(W_{G}\) \(SS_{BS} - SS_{G}\) \(K(n-1)\) \(\frac{SS_{W_{G}}}{df_{W_{G}}}\)
\(Within\,Subject\) \(SS_T-SS_{BS}\) \(nK(C-1)\) \(\frac{SS_w}{df_w}\)
\(\,RM\) \(KnSS_{RM\,means}\) \(C-1\) \(\frac{SS_{RM}}{df_{RM}}\) \(\frac{MS_{RM}}{MS_{SXRM}}\)
\(\,GXRM\) \(nSS_{Col\,means}-SS_G-SS_{RM}\) \((K-1)(C-1)\) \(\frac{SS_{GXRM}}{df_{GXRM}}\) \(\frac{MS_{GXRM}}{MS_{SXRM}}\)
\(\,Residual\,[Sub\,x\,RM]\) \(SS_{WS}-SS_{RM}-SS_{GXRM}\) \(K(n-1)(C-1)\) \(\frac{SS_{SXRM}}{df_{SXRM}}\)
Total \(SS_{scores}\) \(N-1\)

Notes:

  • \(SS_{T} = SS_{BS} +SS_{WS}\)
    • \(SS_{BS} = SS_{G} + SS_{W_{G}}\)
    • \(SS_{WS} = SS_{RM} +SS_{GXRM} + SS_{SXRM}\)
  • \(df_{T} = df_{BS} +df_{WS}\)
    • \(df_{BS} = df_{G} + df_{W_{G}}\)
    • \(df_{WS} = df_{RM} +df_{GXRM} + df_{SXRM}\)

Explained Terms

  • \(SS_{G}\) = caused by group
  • \(SS_{RM}\) = caused by treatment
  • \(SS_{GXRM}\) = caused by group x treatment

Unexplained Terms

  • \(SS_{W_{G}}\) = Noise due to group
  • \(SS_{SXRM}\) = Noise due to treatment

R ANOVA Calculations

R Defaults

  • afex calculates the RM ANOVA for us and it will automatically correct for sphericity violations.
  • Error(Subject ID/RM Factor): This tells the afex that subjects vary as function RM conditions.
  • It reports \(\eta_g^2\) assuming a manipulated group and treatment.
library(afex)
Mixed.1<-aov_car(BDI~ Time*Group + Error(ID/Time), 
        data = DataSim2)
Mixed.1
## Anova Table (Type 3 tests)
## 
## Response: BDI
##       Effect          df    MSE       F  ges p.value
## 1      Group       1, 38 115.22 7.52 ** .062    .009
## 2       Time 2.38, 90.46  95.35  2.52 + .042    .076
## 3 Group:Time 2.38, 90.46  95.35  4.45 * .072    .010
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
## 
## Sphericity correction method: GG

Assumptions

Sphericity

Same as RM ANOVA, except we should examine Mauchly’s test for Sphericity on each term (that has more than two levels)

summary(Mixed.1, return="univariate")
## 
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
## 
##             Sum Sq num Df Error SS den Df   F value    Pr(>F)    
## (Intercept) 150794      1   4378.3     38 1308.7751 < 2.2e-16 ***
## Group          866      1   4378.3     38    7.5159  0.009271 ** 
## Time           573      3   8625.1    114    2.5239  0.061195 .  
## Group:Time    1011      3   8625.1    114    4.4531  0.005363 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Mauchly Tests for Sphericity
## 
##            Test statistic   p-value
## Time              0.58306 0.0013626
## Group:Time        0.58306 0.0013626
## 
## 
## Greenhouse-Geisser and Huynh-Feldt Corrections
##  for Departure from Sphericity
## 
##             GG eps Pr(>F[GG])  
## Time       0.79352    0.07603 .
## Group:Time 0.79352    0.01005 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##               HF eps  Pr(>F[HF])
## Time       0.8501145 0.071636760
## Group:Time 0.8501145 0.008454026

Violations of Sphericity are more common in mixed designs, so be cautious

Covariance Matrix

We assume Compound Symmetry for each group:

\[ \mathbf{Cov} = \sigma^2\left[\begin{array} {rrrr} 1 & \rho & \rho & \rho \\ \rho & 1 & \rho & \rho \\ \rho & \rho & 1 & \rho \\ \rho & \rho & \rho & 1\\ \end{array}\right] \]

However, as in the case of the study that we examined today, we have two Covariance Matrices (one for each group: \(COV_1 = COV_2\)). So we must test to see if they are homogeneous. We can use Box’s M.

Box’s M

Box’s M tests to see if the covariance matrices are equal between groups (HOCV). This function in R requires we spread DV into columns based on the Within factor (we will use spread function in tidyr package: dataset %>% spread(Within factor, DV).

library(tidyr); library(dplyr)
#Box's M
data_wide <- DataSim2 %>% spread(Time, BDI)

Now the data is wide, we will index the columns of the DV (rows 3 to 6) We will send this result to boxM function in heplots and cut it buy group. We can view the covariance matrix for each group and also view the results of the test.

library(heplots)
BoxResult<-boxM(data_wide[,3:6],data_wide$Group)
BoxResult$cov
BoxResult
## $CBT
##           Baseline    2 Weeks   4 Weeks    6 Weeks
## Baseline 35.830484  10.082930 39.039303   4.564906
## 2 Weeks  10.082930  74.984873  2.848143 -14.474673
## 4 Weeks  39.039303   2.848143 52.237993   7.832589
## 6 Weeks   4.564906 -14.474673  7.832589  46.560581
## 
## $Control
##            Baseline    2 Weeks    4 Weeks    6 Weeks
## Baseline  63.826004   5.222681  43.836602 -41.487667
## 2 Weeks    5.222681 124.377804  28.686090  40.546881
## 4 Weeks   43.836602  28.686090 120.724050  -8.021894
## 6 Weeks  -41.487667  40.546881  -8.021894 165.847124
## 
## 
##  Box's M-test for Homogeneity of Covariance Matrices
## 
## data:  data_wide[, 3:6]
## Chi-Sq (approx.) = 32.502, df = 10, p-value = 0.0003301

Box’s M does not work well with small samples and becomes overly sensitive in large samples. We can set alpha here to be \(\alpha = .001\). If the result is significant, that means the covariance matrices are not equal which means we have a problem. This increases the rate of which we might commit a Type I error when examining the interaction: the treatment affected the covariance between trials by the group and not the just the means as we expected. So is the interaction due to mean differences or covariance differences?

HOV

Box’s M is not a great test, so its recommended you also check Levene’s test (center the data via mean) or Brown-Forsythe test (center the data via median) in the car package. Brown-Forsythe test is more robust to the violation of normality (Note: the output will still say Levene’s test when you center via median). Both these tests are sensitive to unequal sample sizes per group. We can test HOV of the groups and group*treatment. If the interaction HOV is violated it supports the conclusion of Box’s M.

library(car)
# Brown-Forsythe test on Group Only
leveneTest(BDI~ Group, data=DataSim2,center=median)

# Brown-Forsythe test on Group X Treatment Only
leveneTest(BDI~ Time*Group, data=DataSim2,center=median)
## Levene's Test for Homogeneity of Variance (center = median)
##        Df F value   Pr(>F)   
## group   1  7.7604 0.005994 **
##       158                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Levene's Test for Homogeneity of Variance (center = median)
##        Df F value   Pr(>F)   
## group   7   2.766 0.009832 **
##       152                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

In the case of this study, Box’s M and Brown-Forsythe test showed HOCV and HOV problems. So we are in trouble, what can we do?

Solution?: Cohen (2008) recommends that you do not do the mixed ANOVA, meaning you will be unable to test the interaction. You can only do one-way RMs for each group and do ANOVA or independent t-tests on the groups (collapsing over RM term). Is this extremely conservative approach is it justified?

Follow Up Testing

We have the same options as we did with RM ANOVA, but we have one extra assumption that will affect both the Modern Approach (using emmeans with error term from ANOVA and Satterthwaite’s DF) and the Multivariate approach.

Degree of the problem?

I ran a simulation (see MonteCarloMixed.R) on the Type I error rates give the violations. In this simulation (n = 1000) of 2 (between) x 4 (within) design with a sample size of 30. All the cells have mean of 0 and I let the covariance matrices for each group be random but different from each other.

Type I Levels:

  • Interaction term in the ANOVA (uncorrected) = .077
  • Univariate approach (uncorrected interaction error term + Satterthwaite’s DF)
    • Significant interactions Followed up within-subject Pair-wise comparisons (2 families with 6 tests each)
      • Tukey Corrected & Using the error term from the Interaction = .175
      • Bonferroni Corrected & Using the error term from the Interaction = .169
    • Significant interactions Followed up Between-subject Pair-wise comparisons (no correction as 1 per family)
      • Using the error term from the Interaction = .289
  • Multivariate approach (error term and DF from MANOVA)
    • Significant interactions Followed up within-subject Pair-wise comparisons (2 families with 6 tests each)
      • Tukey Corrected & Using the error term from the Interaction = .158
      • Bonferroni Corrected & Using the error term from the Interaction = .152
    • Significant interactions Followed up Between-subject Pair-wise comparisons (no correction as 1 per family)
      • Using the error term from the Interaction = .279

This is extremely high on the follow-ups testing and worse yet when you follow up between-subject way. This is the reason for Cohen suggestions not to test the interaction. In the wild no one does this in practice because usually the whole point of the study.

Recommendations

  • For Box’s M, set \(\alpha = .001\), double check Brown-Forsythe to be sure there is a problem, and examine Spaghetti plots when you have a small number of subjects.
  • When Box’s M & B-F are violated:
    • Follow it up from the within variable ONLY and the minimum number of tests possible to test your predicted hypothesis.
      • If you need to contrasts (using the error term of the ANOVA) do only the one you need and keep in mind you might be able to be replicated
      • If you only need pairwise tests, do NOT use the error term from the ANOVA (do paired sample t-tests and Bonferroni correct the hell out of it)
      • The multivariate approach will not help you here as you could see
    • DO NOT DO ANY EXPLORATORY ANALYSIS; these will be all type I error.
  • If you have designed your study well and had no violations, go ahead follow up the way you would follow up an RM ANOVA using emmeans, but try to follow it up only within-subject as you have higher power (and thus lower Type I risk)

Example of Follow up (assuming no violations)

Follow Up Interaction

Example using simple effects followed up by polynomial contrast

library(emmeans)
Time.by.Group<-emmeans(Mixed.1,~Time|Group)
test(pairs(Time.by.Group), joint=TRUE)
##  Group   df1 df2 F.ratio p.value note
##  CBT       3  38  13.063  <.0001  d  
##  Control   3  38   0.766  0.5199  d  
## 
## d: df1 reduced due to linear dependence

So changes over time in Control group which we can follow up with contrasts: polynomials, consecutive, or any custom contrast you want to test. [Note we can index 1:3 to see only the CBT results]

contrast(Time.by.Group, 'poly')[1:3]
##  contrast  Group estimate   SE df t.ratio p.value
##  linear    CBT     -34.14 8.97 38  -3.805  0.0005
##  quadratic CBT       6.72 3.26 38   2.061  0.0462
##  cubic     CBT      -8.65 9.66 38  -0.896  0.3759

References

Cousineau, D., & O’Brien, F. (2014). Error bars in within-subject designs: a comment on Baguley (2012). Behavior Research Methods, 46(4), 1149-1151.

LS0tDQp0aXRsZTogIk1peGVkIEFOT1ZBOiBUd28td2F5LCBHcmFwaGluZyAmIEZvbGxvdyB1cHMiDQpoZWFkZXItaW5jbHVkZXM6DQotIFx1c2VwYWNrYWdle2Ftc21hdGh9DQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgZm9udHNpemU6IDhwdA0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUNCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlPVRSVUUpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEZBTFNFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmcgPSAgRkFMU0UpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTQuMjUpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLmhlaWdodD00LjApDQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLmFsaWduPSdjZW50ZXInKSANCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcucG9zID0gJ0gnKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHJlc3VsdHM9J2hvbGQnKSANCmBgYA0KDQoNCiMgTWl4ZWQgRGVzaWduIEZhY3RvcnMNCj4gWW91IHdhbnQgdG8gc2hvdyB0aGUgZWZmZWN0aXZlbmVzcyBvZiBDQlQgdGhlcmFweSBhZ2FpbnN0IG5vIHRoZXJhcHkgaW4gcmVkdWNpbmcgZGVwcmVzc2lvbiBzY29yZXMuIFlvdSBnaXZlIGNsaWVudHMgKGFuZCBjb250cm9scykgdGhlIEJlY2sgZGVwcmVzc2lvbiBpbmRleCAoQkRJIGF0IGJhc2VsaW5lLCBhbmQgZXZlcnkgdHdvIHdlZWtzIGFmdGVyd2FyZCBmb3IgdXAgdG8gNiBXZWVrcy4gWW91IGFzc2lnbiAzMCBwZW9wbGUgdG8gZWFjaCBiZXR3ZWVuLXN1YmplY3RzIGdyb3VwIChjb250cm9sIG9yIENCVCkgd2l0aCB2YXJ5aW5nIGxldmVscyBvZiBkZXByZXNzaW9uIChmcm9tIG1pbGQgdG8gc2V2ZXJlOyBCREkgb2YgMjAgdG8gNTApLCBhbmQgaW4gdG90YWwsIHlvdSB3aWxsIGNvbGxlY3QgNCBCREkgc2NvcmVzIGZvciBlYWNoIHBlcnNvbiAod2l0aGluIHN1YmplY3QpLiAgWW91IGV4cGVjdCBCREkgc2NvcmVzIHRvIGRyb3AgYnkgdGhlIHNlY29uZCBCREkgbWVhc3VyZW1lbnQgYW5kIGNvbnRpbnVlIHRvIGRlY3JlYXNlIG92ZXIgc2Vzc2lvbnMgcmVsYXRpdmUgdG8gY29udHJvbCB3aGljaCBzaG91bGQgc2hvdyBubyBjaGFuZ2UuIEtlZXAgaW4gbWluZCB0aGVyZSBpcyBubyBpbnRlcnZlbnRpb24gZm9yIHRoZSBjb250cm9sIGdyb3VwLCBhbmQgQkRJIHNjb3JlIGhhcyBhIHRlbmRlbmN5IHRvIGJlIHVuc3RhYmxlLCBzbyB5b3UgYXJlIHdvcnJpZWQgYWJvdXQgYXNzdW1wdGlvbiB2aW9sYXRpb25zLiAgICAgIA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShNYXRyaXgpDQpzZXQuc2VlZCg0MikNCm4gPSAyMDsgDQojIyBtZWFucw0KTTFBPTM1OyBNMkE9MzA7IE0zQT0yNTsgTTRBPTI1DQpNMUI9MzU7IE0yQj0zNTsgTTNCPTM1OyBNNEI9MzUNCiMjIEdlbmVyYXRlIENvdiBtYXRyaXgNCiMgY3JlYXRlIGsgeCBrIG1hdHJpeCBwb3B1bGF0ZWQgd2l0aCBzaWdtYQ0Kc2lnbWExPTgNCnNpZ21hMj0xMg0KcjE9MDsNCnIyPTANCnNkLnI9LjMNClMxICA8LSBmb3JjZVN5bW1ldHJpYyhNYXRyaXgocm5vcm0oMTYsIG09c2lnbWExLHM9MSksIDQpKQ0KUmhvMTwtIGZvcmNlU3ltbWV0cmljKE1hdHJpeChybm9ybSgxNiwgbT1yMSxzPXNkLnIpLCA0KSkNClMyICA8LSBmb3JjZVN5bW1ldHJpYyhNYXRyaXgocm5vcm0oMTYsIG09c2lnbWEyLHM9MSksIDQpKQ0KUmhvMjwtIGZvcmNlU3ltbWV0cmljKE1hdHJpeChybm9ybSgxNiwgbT1yMixzPXNkLnIpLCA0KSkNCg0KIyBjb21wdXRlIGNvdmFyaWFuY2UgYmV0d2VlbiBtZWFzdXJlcw0KU2lnbWExIDwtIChTMV4yKSAqUmhvMQ0KU2lnbWEyIDwtIChTMl4yKSAqUmhvMg0KIyBwdXQgdGhlIHZhcmlhbmNlcyBvbiB0aGUgZGlhZ29uYWwgDQpkaWFnKFNpZ21hMSkgPC0gc2lnbWExXjIgIA0KZGlhZyhTaWdtYTIpIDwtIHNpZ21hMl4yIA0KDQojIEZpeGVkIHRoZW0gaWYgdGhleSBhcmUgbm90IFBEDQpTaWdtYTE8LW5lYXJQRChTaWdtYTEpDQpTaWdtYTI8LW5lYXJQRChTaWdtYTIpDQoNClNpbXVsYXRpb24xID0gbXZybm9ybShuPW4sIG11PWMoTTFBLE0yQSxNM0EsTTRBKSwgU2lnbWE9U2lnbWExJG1hdCwgZW1waXJpY2FsPUZBTFNFKQ0KU2ltdWxhdGlvbjIgPSBtdnJub3JtKG49biwgbXU9YyhNMUIsTTJCLE0zQixNNEIpLCBTaWdtYT1TaWdtYTIkbWF0LCBlbXBpcmljYWw9RkFMU0UpDQoNCkRhdGFTaW0xPC1kYXRhLmZyYW1lKHJiaW5kKFNpbXVsYXRpb24xLFNpbXVsYXRpb24yKSkNCkRhdGFTaW0xJElEPC1hcy5mYWN0b3IocmVwKHNlcSgxOihuKjIpKSkpDQpEYXRhU2ltMSRHcm91cDwtYXMuZmFjdG9yKGMocmVwKCJDQlQiLG4pLHJlcCgiQ29udHJvbCIsbikpKQ0KRGF0YVNpbTI8LWdhdGhlcihEYXRhU2ltMSxrZXkgPSAiVGltZSIsIHZhbHVlID0gIkJESSIsWDE6WDQpDQoNCkRhdGFTaW0yJFRpbWU8LWZhY3RvcihEYXRhU2ltMiRUaW1lLCANCiAgICAgICBsZXZlbHM9YygiWDEiLCAiWDIiLCJYMyIsIlg0IiksDQogICAgICAgbGFiZWxzPWMoIkJhc2VsaW5lIiwgIjIgV2Vla3MiLCI0IFdlZWtzIiwiNiBXZWVrcyIpKQ0KRGF0YVNpbTIkR3JvdXA8LWZhY3RvcihEYXRhU2ltMiRHcm91cCwgDQogICAgICAgbGV2ZWxzPWMoIkNCVCIsICJDb250cm9sIiksDQogICAgICAgbGFiZWxzPWMoIkNCVCIsICJDb250cm9sIikpDQpgYGANCg0KDQojIyBQbG90IG9mIFNpbXVsYXRpb24NCiMjIyBTcGFnaGV0dGkgUGxvdA0KRWFjaCBsaW5lIHJlcHJlc2VudHMgYSBwZXJzb24ncyBzY29yZSBhY3Jvc3MgY29uZGl0aW9ucw0KDQpgYGB7ciwgZWNobz1GQUxTRSxmaWcud2lkdGg9Nn0NCmxpYnJhcnkoZ2dwbG90MikNCnRoZW1lX3NldCh0aGVtZV9idyhiYXNlX3NpemUgPSAxMiwgYmFzZV9mYW1pbHkgPSAiIikpIA0KDQpTcGFnaGV0dGkuMSA8LWdncGxvdChkYXRhID0gRGF0YVNpbTIsIGFlcyh4ID0gVGltZSwgeT1CREksIGdyb3VwPUlEKSkrDQogIGZhY2V0X2dyaWQofkdyb3VwKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsNjApLGJyZWFrcyA9IHNlcSgwLDYwLDEwKSkrDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IElEKSkrDQogIGdlb21fbGluZShhZXMoY29sb3VyID0gSUQpKSsNCiAgeWxhYigiQkRJIFNjb3JlIikreGxhYigiVGltZSIpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpTcGFnaGV0dGkuMQ0KYGBgDQoNCiMjIyBNZWFucyBwbG90IA0KSnVzdCBsaWtlIFJNIEFOT1ZBLCB3ZSB3aWxsIHVzZSBDb3VzaW5lYXUtTW9yZXkgQ29ycmVjdGVkIGVycm9yIGJhcnMgd2hpY2ggcmVtb3ZlIGluZGl2aWR1YWwgZGlmZmVyZW5jZXMuIFRoZSBmdW5jdGlvbiB3aWxsIGNvcnJlY3QgZm9yIHRoZSBtaXhlZCBkZXNpZ24gZGlmZmVyZW5jZXMgaW4gdGhlIGNvcnJlY3Rpb24sIGp1c3QgcGFzcyB3aGljaCB2YXJpYWJsZXMgYXJlIGJldHdlZW4gYmVsb3cuIEFnYWluLCB5b3UgY2FuIHNlbGVjdCBiZXR3ZWVuIFNFIGFuZCBDSSAoSSBwbG90dGVkIENJIGJlbG93KS4NCg0KYGBge3IsZmlnLndpZHRoPTZ9DQpzb3VyY2UoJ0hlbHBlckZ1bmN0aW9ucy5SJykNCg0KTWVhbnNmb3JHR1Bsb3QgPC0gc3VtbWFyeVNFd2l0aGluKGRhdGE9RGF0YVNpbTIsICJCREkiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRoaW52YXJzPWMoIlRpbWUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZXR3ZWVudmFycz1jKCJHcm91cCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkdmFyPSJJRCIsIG5hLnJtPUZBTFNFLCBjb25mLmludGVydmFsPS45NSkNCg0KTWVhbnMuV2l0aGluLkNJIDwtZ2dwbG90KGRhdGEgPSBNZWFuc2ZvckdHUGxvdCwgYWVzKHggPSBUaW1lLCB5PUJESSwgZ3JvdXA9R3JvdXApKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDQwLDUpKSsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXIgPSBHcm91cCksIHNpemU9MikrDQogIGdlb21fcmliYm9uKGFlcyh5bWluPUJESS1jaSwgeW1heD1CREkrY2ksZmlsbCA9IEdyb3VwKSwgYWxwaGE9LjUpKw0KICB5bGFiKCJNZWFuIEJESSBTY29yZSIpK3hsYWIoIlRpbWUiKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikNCk1lYW5zLldpdGhpbi5DSQ0KYGBgDQoNCkZvciB3aXRoaW4gZXJyb3IgYmFycyAoQ29ycmVjdGVkKSB5b3UgY2FuIGV5ZS1iYWxsIHNpZ25pZmljYW5jZSAoQ3VtbWluZyAmIEZpbmNoLCAyMDA1KQ0KDQo5NSUgQ0lzOiANCg0KLSAgJHAgPCAuMDUkOiB3aGVuIHByb3BvcnRpb24gb3ZlcmxhcCBpcyBhYm91dCAuNTANCi0gICRwIDwgLjAxJDogd2hlbiBwcm9wb3J0aW9uIG92ZXJsYXAgaXMgYWJvdXQgMA0KDQoqTm90aWNlIGFsc28geW91IGNhbiBzZWUgcHJvYmxlbXMgd2l0aCB0aGUgdmFyaWFuY2UqDQoNCiMjIDItV2F5IE1peGVkIEFOT1ZBIGxvZ2ljDQoNClR3by13YXkgTWl4ZWQgQU5PVkEgVGFibGUgV2l0aCB0aGUgZm9ybXVsYXMgKGNvbmNlcHR1YWxseSBzaW1wbGlmaWVkKQ0KDQpTb3VyY2UgICAgICAgIHwgU1MgICAgICAgICAgICAgICAgICB8IERGICAgICAgICAgIHwgTVMgICB8IEYNCi0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tfC0tLS0tLXwtLS0NCiRCZXR3ZWVuXCxTdWJqZWN0JCB8ICRDU1Nfe3Jvd1wsbWVhbnN9JCAgICAgICAgICAgICAgICAgIHwgJG5LLTEkICAgICAgfCAkXGZyYWN7U1Nfe0JTfX17ZGZfe0JTfX0kICAgICAgIHwgDQokR3JvdXAkIHwgJENuU1Nfe0dyb3VwXCxtZWFuc30kICAgICAgICAgICAgICAgICAgICAgICAgICB8ICRLLTEkICAgICAgIHwgJFxmcmFje1NTX3tHfX17ZGZfe0d9fSQgICAgICAgICB8JFxmcmFje01TX3tHfX17TVNfe1dfe0d9fX0kDQokV197R30kIHwgJFNTX3tCU30gLSBTU197R30kICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICRLKG4tMSkkICAgIHwgJFxmcmFje1NTX3tXX3tHfX19e2RmX3tXX3tHfX19JCB8IA0KJFdpdGhpblwsU3ViamVjdCQgIHwgJFNTX1QtU1Nfe0JTfSQgICAgICAgICAgICAgICAgICAgICAgfCAkbksoQy0xKSQgICB8ICRcZnJhY3tTU193fXtkZl93fSQgICAgICAgICAgICAgfCAgIA0KJFwsUk0kICB8ICRLblNTX3tSTVwsbWVhbnN9JCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAkQy0xJCAgICAgICB8ICRcZnJhY3tTU197Uk19fXtkZl97Uk19fSQgICAgICAgfCAkXGZyYWN7TVNfe1JNfX17TVNfe1NYUk19fSQNCiRcLEdYUk0kICB8ICRuU1Nfe0NvbFwsbWVhbnN9LVNTX0ctU1Nfe1JNfSQgICAgICAgICAgICAgIHwgJChLLTEpKEMtMSkkfCAkXGZyYWN7U1Nfe0dYUk19fXtkZl97R1hSTX19JCAgIHwgJFxmcmFje01TX3tHWFJNfX17TVNfe1NYUk19fSQNCiRcLFJlc2lkdWFsXCxbU3ViXCx4XCxSTV0kIHwgJFNTX3tXU30tU1Nfe1JNfS1TU197R1hSTX0kIHwgJEsobi0xKShDLTEpJHwgJFxmcmFje1NTX3tTWFJNfX17ZGZfe1NYUk19fSQgIHwgDQpUb3RhbCAgIHwgJFNTX3tzY29yZXN9JCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICROLTEkIA0KDQpOb3RlczogDQoNCi0gJFNTX3tUfSA9IFNTX3tCU30gK1NTX3tXU30kIA0KICAgIC0gJFNTX3tCU30gPSBTU197R30gKyBTU197V197R319JA0KICAgIC0gJFNTX3tXU30gPSBTU197Uk19ICtTU197R1hSTX0gKyBTU197U1hSTX0kIA0KLSAkZGZfe1R9ID0gZGZfe0JTfSArZGZfe1dTfSQgDQogICAgLSAkZGZfe0JTfSA9IGRmX3tHfSArIGRmX3tXX3tHfX0kDQogICAgLSAkZGZfe1dTfSA9IGRmX3tSTX0gK2RmX3tHWFJNfSArIGRmX3tTWFJNfSQgDQoNCiMjIyBFeHBsYWluZWQgVGVybXMgDQoNCi0gJFNTX3tHfSQgPSBjYXVzZWQgYnkgZ3JvdXANCi0gJFNTX3tSTX0kID0gY2F1c2VkIGJ5IHRyZWF0bWVudA0KLSAkU1Nfe0dYUk19JCA9IGNhdXNlZCBieSBncm91cCB4IHRyZWF0bWVudCANCg0KIyMjIFVuZXhwbGFpbmVkIFRlcm1zIA0KDQotICRTU197V197R319JCA9IE5vaXNlIGR1ZSB0byBncm91cCAgDQotICRTU197U1hSTX0kID0gTm9pc2UgZHVlIHRvIHRyZWF0bWVudCAgDQoNCiMjIFIgQU5PVkEgQ2FsY3VsYXRpb25zDQojIyMgUiBEZWZhdWx0cw0KLSBgYWZleGAgY2FsY3VsYXRlcyB0aGUgUk0gQU5PVkEgZm9yIHVzIGFuZCBpdCB3aWxsIGF1dG9tYXRpY2FsbHkgY29ycmVjdCBmb3Igc3BoZXJpY2l0eSB2aW9sYXRpb25zLiANCi0gRXJyb3IoU3ViamVjdCBJRC9STSBGYWN0b3IpOiBUaGlzIHRlbGxzIHRoZSBhZmV4IHRoYXQgc3ViamVjdHMgdmFyeSBhcyBmdW5jdGlvbiBSTSBjb25kaXRpb25zLiAgDQotIEl0IHJlcG9ydHMgJFxldGFfZ14yJCBhc3N1bWluZyBhIG1hbmlwdWxhdGVkIGdyb3VwIGFuZCB0cmVhdG1lbnQuDQoNCmBgYHtyfQ0KbGlicmFyeShhZmV4KQ0KTWl4ZWQuMTwtYW92X2NhcihCREl+IFRpbWUqR3JvdXAgKyBFcnJvcihJRC9UaW1lKSwgDQogICAgICAgIGRhdGEgPSBEYXRhU2ltMikNCk1peGVkLjENCmBgYA0KDQojIyMgQXNzdW1wdGlvbnMNCiMjIyMgU3BoZXJpY2l0eQ0KU2FtZSBhcyBSTSBBTk9WQSwgZXhjZXB0IHdlIHNob3VsZCBleGFtaW5lIE1hdWNobHkncyB0ZXN0IGZvciBTcGhlcmljaXR5IG9uIGVhY2ggdGVybSAodGhhdCBoYXMgbW9yZSB0aGFuIHR3byBsZXZlbHMpDQoNCmBgYHtyfQ0Kc3VtbWFyeShNaXhlZC4xLCByZXR1cm49InVuaXZhcmlhdGUiKQ0KYGBgDQoNClZpb2xhdGlvbnMgb2YgU3BoZXJpY2l0eSBhcmUgbW9yZSBjb21tb24gaW4gbWl4ZWQgZGVzaWducywgc28gYmUgY2F1dGlvdXMNCg0KIyMjIyBDb3ZhcmlhbmNlIE1hdHJpeCANCg0KV2UgYXNzdW1lIENvbXBvdW5kIFN5bW1ldHJ5IGZvciBlYWNoIGdyb3VwOiANCg0KJCQNClxtYXRoYmZ7Q292fSA9IFxzaWdtYV4yXGxlZnRbXGJlZ2lue2FycmF5fQ0KICAgICAgICAgIHtycnJyfQ0KICAgICAgICAgIDEgJiBccmhvICYgXHJobyAmIFxyaG8gIFxcDQogICAgICAgICAgXHJobyAmIDEgJiBccmhvICYgXHJobyAgXFwNCiAgICAgICAgICBccmhvICYgXHJobyAmIDEgJiBccmhvICBcXA0KICAgICAgICAgIFxyaG8gJiBccmhvICYgXHJobyAmIDFcXA0KICAgICAgICAgIFxlbmR7YXJyYXl9XHJpZ2h0XQ0KJCQgDQoNCkhvd2V2ZXIsIGFzIGluIHRoZSBjYXNlIG9mIHRoZSBzdHVkeSB0aGF0IHdlIGV4YW1pbmVkIHRvZGF5LCB3ZSBoYXZlICoqdHdvKiogQ292YXJpYW5jZSBNYXRyaWNlcyAob25lIGZvciBlYWNoIGdyb3VwOiAkQ09WXzEgPSBDT1ZfMiQpLiBTbyB3ZSBtdXN0IHRlc3QgdG8gc2VlIGlmIHRoZXkgYXJlIGhvbW9nZW5lb3VzLiBXZSBjYW4gdXNlIEJveCdzIE0uDQoNCiMjIyMgQm94J3MgTQ0KDQpCb3gncyBNIHRlc3RzIHRvIHNlZSBpZiB0aGUgY292YXJpYW5jZSBtYXRyaWNlcyBhcmUgZXF1YWwgYmV0d2VlbiBncm91cHMgKCoqSE9DVioqKS4gVGhpcyBmdW5jdGlvbiBpbiBSIHJlcXVpcmVzIHdlIHNwcmVhZCBEViBpbnRvIGNvbHVtbnMgYmFzZWQgb24gdGhlIFdpdGhpbiBmYWN0b3IgKHdlIHdpbGwgdXNlIGBzcHJlYWRgIGZ1bmN0aW9uIGluIHRpZHlyIHBhY2thZ2U6IGBkYXRhc2V0ICU+JSBzcHJlYWQoV2l0aGluIGZhY3RvciwgRFYpYC4gDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5cik7IGxpYnJhcnkoZHBseXIpDQojQm94J3MgTQ0KZGF0YV93aWRlIDwtIERhdGFTaW0yICU+JSBzcHJlYWQoVGltZSwgQkRJKQ0KYGBgDQoNCk5vdyB0aGUgZGF0YSBpcyB3aWRlLCB3ZSB3aWxsIGluZGV4IHRoZSBjb2x1bW5zIG9mIHRoZSBEViAocm93cyAzIHRvIDYpIFdlIHdpbGwgc2VuZCB0aGlzIHJlc3VsdCB0byBib3hNIGZ1bmN0aW9uIGluIGBoZXBsb3RzYCBhbmQgY3V0IGl0IGJ1eSBncm91cC4gV2UgY2FuIHZpZXcgdGhlIGNvdmFyaWFuY2UgbWF0cml4IGZvciBlYWNoIGdyb3VwIGFuZCBhbHNvIHZpZXcgdGhlIHJlc3VsdHMgb2YgdGhlIHRlc3QuDQoNCmBgYHtyfQ0KbGlicmFyeShoZXBsb3RzKQ0KQm94UmVzdWx0PC1ib3hNKGRhdGFfd2lkZVssMzo2XSxkYXRhX3dpZGUkR3JvdXApDQpCb3hSZXN1bHQkY292DQpCb3hSZXN1bHQNCmBgYA0KDQpCb3gncyBNIGRvZXMgbm90IHdvcmsgd2VsbCB3aXRoIHNtYWxsIHNhbXBsZXMgYW5kIGJlY29tZXMgb3Zlcmx5IHNlbnNpdGl2ZSBpbiBsYXJnZSBzYW1wbGVzLiAgV2UgY2FuIHNldCBhbHBoYSBoZXJlIHRvIGJlICRcYWxwaGEgPSAuMDAxJC4gSWYgdGhlIHJlc3VsdCBpcyBzaWduaWZpY2FudCwgdGhhdCBtZWFucyB0aGUgY292YXJpYW5jZSBtYXRyaWNlcyBhcmUgbm90IGVxdWFsIHdoaWNoIG1lYW5zIHdlIGhhdmUgYSBwcm9ibGVtLiBUaGlzIGluY3JlYXNlcyB0aGUgcmF0ZSBvZiB3aGljaCB3ZSBtaWdodCBjb21taXQgYSBUeXBlIEkgZXJyb3Igd2hlbiBleGFtaW5pbmcgdGhlIGludGVyYWN0aW9uOiAgdGhlIHRyZWF0bWVudCBhZmZlY3RlZCB0aGUgY292YXJpYW5jZSBiZXR3ZWVuIHRyaWFscyBieSB0aGUgZ3JvdXAgYW5kIG5vdCB0aGUganVzdCB0aGUgbWVhbnMgYXMgd2UgZXhwZWN0ZWQuIFNvIGlzIHRoZSBpbnRlcmFjdGlvbiBkdWUgdG8gbWVhbiBkaWZmZXJlbmNlcyBvciBjb3ZhcmlhbmNlIGRpZmZlcmVuY2VzPyANCg0KIyMjIyBIT1YNCkJveCdzIE0gaXMgbm90IGEgZ3JlYXQgdGVzdCwgc28gaXRzIHJlY29tbWVuZGVkIHlvdSBhbHNvIGNoZWNrIExldmVuZSdzIHRlc3QgKGNlbnRlciB0aGUgZGF0YSB2aWEgbWVhbikgb3IgQnJvd24tRm9yc3l0aGUgdGVzdCAoY2VudGVyIHRoZSBkYXRhIHZpYSBtZWRpYW4pIGluIHRoZSBgY2FyYCBwYWNrYWdlLiAgQnJvd24tRm9yc3l0aGUgdGVzdCBpcyBtb3JlIHJvYnVzdCB0byB0aGUgdmlvbGF0aW9uIG9mIG5vcm1hbGl0eSAoTm90ZTogdGhlIG91dHB1dCB3aWxsIHN0aWxsIHNheSBMZXZlbmUncyB0ZXN0IHdoZW4geW91IGNlbnRlciB2aWEgbWVkaWFuKS4gIEJvdGggdGhlc2UgdGVzdHMgYXJlIHNlbnNpdGl2ZSB0byB1bmVxdWFsIHNhbXBsZSBzaXplcyBwZXIgZ3JvdXAuICBXZSBjYW4gdGVzdCBIT1Ygb2YgdGhlIGdyb3VwcyBhbmQgZ3JvdXAqdHJlYXRtZW50LiBJZiB0aGUgaW50ZXJhY3Rpb24gSE9WIGlzIHZpb2xhdGVkIGl0IHN1cHBvcnRzIHRoZSBjb25jbHVzaW9uIG9mIEJveCdzIE0uIA0KDQpgYGB7cn0NCmxpYnJhcnkoY2FyKQ0KIyBCcm93bi1Gb3JzeXRoZSB0ZXN0IG9uIEdyb3VwIE9ubHkNCmxldmVuZVRlc3QoQkRJfiBHcm91cCwgZGF0YT1EYXRhU2ltMixjZW50ZXI9bWVkaWFuKQ0KDQojIEJyb3duLUZvcnN5dGhlIHRlc3Qgb24gR3JvdXAgWCBUcmVhdG1lbnQgT25seQ0KbGV2ZW5lVGVzdChCREl+IFRpbWUqR3JvdXAsIGRhdGE9RGF0YVNpbTIsY2VudGVyPW1lZGlhbikNCmBgYA0KDQpJbiB0aGUgY2FzZSBvZiB0aGlzIHN0dWR5LCBCb3gncyBNIGFuZCBCcm93bi1Gb3JzeXRoZSB0ZXN0IHNob3dlZCAqKkhPQ1YqKiBhbmQgKipIT1YqKiBwcm9ibGVtcy4gU28gd2UgYXJlIGluIHRyb3VibGUsIHdoYXQgY2FuIHdlIGRvPyANCg0KKipTb2x1dGlvbj8qKjogQ29oZW4gKDIwMDgpIHJlY29tbWVuZHMgdGhhdCB5b3UgZG8gKipub3QqKiBkbyB0aGUgbWl4ZWQgQU5PVkEsIG1lYW5pbmcgeW91IHdpbGwgYmUgdW5hYmxlIHRvIHRlc3QgdGhlIGludGVyYWN0aW9uLiBZb3UgY2FuIG9ubHkgZG8gb25lLXdheSBSTXMgZm9yIGVhY2ggZ3JvdXAgYW5kIGRvIEFOT1ZBIG9yIGluZGVwZW5kZW50IHQtdGVzdHMgb24gdGhlIGdyb3VwcyAoY29sbGFwc2luZyBvdmVyIFJNIHRlcm0pLiBJcyB0aGlzIGV4dHJlbWVseSBjb25zZXJ2YXRpdmUgYXBwcm9hY2ggaXMgaXQganVzdGlmaWVkPyANCg0KIyBGb2xsb3cgVXAgVGVzdGluZw0KV2UgaGF2ZSB0aGUgc2FtZSBvcHRpb25zIGFzIHdlIGRpZCB3aXRoIFJNIEFOT1ZBLCBidXQgd2UgaGF2ZSBvbmUgZXh0cmEgYXNzdW1wdGlvbiB0aGF0IHdpbGwgYWZmZWN0IGJvdGggdGhlIE1vZGVybiBBcHByb2FjaCAodXNpbmcgYGVtbWVhbnNgIHdpdGggZXJyb3IgdGVybSBmcm9tIEFOT1ZBIGFuZCBTYXR0ZXJ0aHdhaXRlJ3MgREYpIGFuZCB0aGUgTXVsdGl2YXJpYXRlIGFwcHJvYWNoLiANCg0KDQojIyBEZWdyZWUgb2YgdGhlIHByb2JsZW0/DQpJIHJhbiBhIHNpbXVsYXRpb24gKHNlZSBgTW9udGVDYXJsb01peGVkLlJgKSBvbiB0aGUgVHlwZSBJIGVycm9yIHJhdGVzIGdpdmUgdGhlIHZpb2xhdGlvbnMuICBJbiB0aGlzIHNpbXVsYXRpb24gKG4gPSAxMDAwKSBvZiAyIChiZXR3ZWVuKSB4ICA0ICh3aXRoaW4pIGRlc2lnbiB3aXRoIGEgc2FtcGxlIHNpemUgb2YgMzAuIEFsbCB0aGUgY2VsbHMgaGF2ZSBtZWFuIG9mIDAgYW5kIEkgbGV0IHRoZSBjb3ZhcmlhbmNlIG1hdHJpY2VzIGZvciBlYWNoIGdyb3VwIGJlIHJhbmRvbSBidXQgZGlmZmVyZW50IGZyb20gZWFjaCBvdGhlci4gDQoNCioqVHlwZSBJIExldmVsczoqKg0KDQotIEludGVyYWN0aW9uIHRlcm0gaW4gdGhlIEFOT1ZBICh1bmNvcnJlY3RlZCkgPSAgKiouMDc3KiogDQotICoqVW5pdmFyaWF0ZSBhcHByb2FjaCoqICh1bmNvcnJlY3RlZCBpbnRlcmFjdGlvbiBlcnJvciB0ZXJtICsgU2F0dGVydGh3YWl0ZSdzIERGKQ0KICAgIC0gU2lnbmlmaWNhbnQgaW50ZXJhY3Rpb25zIEZvbGxvd2VkIHVwICoqd2l0aGluLXN1YmplY3QqKiBQYWlyLXdpc2UgY29tcGFyaXNvbnMgKDIgZmFtaWxpZXMgd2l0aCA2IHRlc3RzIGVhY2gpDQogICAgICAgIC0gVHVrZXkgQ29ycmVjdGVkICYgVXNpbmcgdGhlIGVycm9yIHRlcm0gZnJvbSB0aGUgSW50ZXJhY3Rpb24gPSAqKi4xNzUqKg0KICAgICAgICAtIEJvbmZlcnJvbmkgQ29ycmVjdGVkICYgVXNpbmcgdGhlIGVycm9yIHRlcm0gZnJvbSB0aGUgSW50ZXJhY3Rpb24gPSAqKi4xNjkqKg0KICAgIC0gU2lnbmlmaWNhbnQgaW50ZXJhY3Rpb25zIEZvbGxvd2VkIHVwICoqQmV0d2Vlbi1zdWJqZWN0KiogUGFpci13aXNlIGNvbXBhcmlzb25zIChubyBjb3JyZWN0aW9uIGFzIDEgcGVyIGZhbWlseSkNCiAgICAgICAgLSBVc2luZyB0aGUgZXJyb3IgdGVybSBmcm9tIHRoZSBJbnRlcmFjdGlvbiA9ICoqLjI4OSoqDQotICoqTXVsdGl2YXJpYXRlIGFwcHJvYWNoKiogKGVycm9yIHRlcm0gYW5kIERGIGZyb20gTUFOT1ZBKQ0KICAgIC0gU2lnbmlmaWNhbnQgaW50ZXJhY3Rpb25zIEZvbGxvd2VkIHVwICoqd2l0aGluLXN1YmplY3QqKiBQYWlyLXdpc2UgY29tcGFyaXNvbnMgKDIgZmFtaWxpZXMgd2l0aCA2IHRlc3RzIGVhY2gpDQogICAgICAgIC0gVHVrZXkgQ29ycmVjdGVkICYgVXNpbmcgdGhlIGVycm9yIHRlcm0gZnJvbSB0aGUgSW50ZXJhY3Rpb24gPSAqKi4xNTgqKg0KICAgICAgICAtIEJvbmZlcnJvbmkgQ29ycmVjdGVkICYgVXNpbmcgdGhlIGVycm9yIHRlcm0gZnJvbSB0aGUgSW50ZXJhY3Rpb24gPSAqKi4xNTIqKg0KICAgIC0gU2lnbmlmaWNhbnQgaW50ZXJhY3Rpb25zIEZvbGxvd2VkIHVwICoqQmV0d2Vlbi1zdWJqZWN0KiogUGFpci13aXNlIGNvbXBhcmlzb25zIChubyBjb3JyZWN0aW9uIGFzIDEgcGVyIGZhbWlseSkNCiAgICAgICAgLSBVc2luZyB0aGUgZXJyb3IgdGVybSBmcm9tIHRoZSBJbnRlcmFjdGlvbiA9ICoqLjI3OSoqDQogICAgICAgIA0KICAgICAgICANClRoaXMgaXMgZXh0cmVtZWx5IGhpZ2ggb24gdGhlIGZvbGxvdy11cHMgdGVzdGluZyBhbmQgd29yc2UgeWV0IHdoZW4geW91IGZvbGxvdyB1cCBiZXR3ZWVuLXN1YmplY3Qgd2F5LiAgVGhpcyBpcyB0aGUgcmVhc29uIGZvciBDb2hlbiBzdWdnZXN0aW9ucyBub3QgdG8gdGVzdCB0aGUgaW50ZXJhY3Rpb24uIEluIHRoZSB3aWxkIG5vIG9uZSBkb2VzIHRoaXMgaW4gcHJhY3RpY2UgYmVjYXVzZSB1c3VhbGx5IHRoZSB3aG9sZSBwb2ludCBvZiB0aGUgc3R1ZHkuDQoNCiMjIFJlY29tbWVuZGF0aW9ucw0KDQotIEZvciBCb3gncyBNLCBzZXQgJFxhbHBoYSA9IC4wMDEkLCBkb3VibGUgY2hlY2sgQnJvd24tRm9yc3l0aGUgdG8gYmUgc3VyZSB0aGVyZSBpcyBhIHByb2JsZW0sIGFuZCBleGFtaW5lIFNwYWdoZXR0aSBwbG90cyB3aGVuIHlvdSBoYXZlIGEgc21hbGwgbnVtYmVyIG9mIHN1YmplY3RzLiAgIA0KLSBXaGVuIEJveCdzIE0gJiBCLUYgYXJlIHZpb2xhdGVkOiAgDQogICAgLSBGb2xsb3cgaXQgdXAgZnJvbSB0aGUgd2l0aGluIHZhcmlhYmxlIE9OTFkgYW5kIHRoZSBtaW5pbXVtIG51bWJlciBvZiB0ZXN0cyBwb3NzaWJsZSB0byB0ZXN0IHlvdXIgcHJlZGljdGVkIGh5cG90aGVzaXMuDQogICAgICAgIC0gSWYgeW91IG5lZWQgdG8gY29udHJhc3RzICh1c2luZyB0aGUgZXJyb3IgdGVybSBvZiB0aGUgQU5PVkEpIGRvIG9ubHkgdGhlIG9uZSB5b3UgbmVlZCBhbmQga2VlcCBpbiBtaW5kIHlvdSBtaWdodCBiZSBhYmxlIHRvIGJlIHJlcGxpY2F0ZWQNCiAgICAgICAgLSBJZiB5b3Ugb25seSBuZWVkIHBhaXJ3aXNlIHRlc3RzLCBkbyBOT1QgdXNlIHRoZSBlcnJvciB0ZXJtIGZyb20gdGhlIEFOT1ZBIChkbyBwYWlyZWQgc2FtcGxlIHQtdGVzdHMgYW5kIEJvbmZlcnJvbmkgY29ycmVjdCB0aGUgaGVsbCBvdXQgb2YgaXQpDQogICAgICAgIC0gVGhlIG11bHRpdmFyaWF0ZSBhcHByb2FjaCB3aWxsIG5vdCBoZWxwIHlvdSBoZXJlIGFzIHlvdSBjb3VsZCBzZWUNCiAgICAtIERPIE5PVCBETyBBTlkgRVhQTE9SQVRPUlkgQU5BTFlTSVM7IHRoZXNlIHdpbGwgYmUgYWxsIHR5cGUgSSBlcnJvci4gICAgDQotIElmIHlvdSBoYXZlIGRlc2lnbmVkIHlvdXIgc3R1ZHkgd2VsbCBhbmQgaGFkIG5vIHZpb2xhdGlvbnMsIGdvIGFoZWFkIGZvbGxvdyB1cCB0aGUgd2F5IHlvdSB3b3VsZCBmb2xsb3cgdXAgYW4gUk0gQU5PVkEgdXNpbmcgZW1tZWFucywgYnV0IHRyeSB0byBmb2xsb3cgaXQgdXAgb25seSB3aXRoaW4tc3ViamVjdCBhcyB5b3UgaGF2ZSBoaWdoZXIgcG93ZXIgKGFuZCB0aHVzIGxvd2VyIFR5cGUgSSByaXNrKQ0KDQoNCiMjIyBFeGFtcGxlIG9mIEZvbGxvdyB1cCAoYXNzdW1pbmcgbm8gdmlvbGF0aW9ucykNCiMjIyMgRm9sbG93IFVwIEludGVyYWN0aW9uDQoNCkV4YW1wbGUgdXNpbmcgc2ltcGxlIGVmZmVjdHMgZm9sbG93ZWQgdXAgYnkgcG9seW5vbWlhbCBjb250cmFzdA0KDQpgYGB7cn0NCmxpYnJhcnkoZW1tZWFucykNClRpbWUuYnkuR3JvdXA8LWVtbWVhbnMoTWl4ZWQuMSx+VGltZXxHcm91cCkNCnRlc3QocGFpcnMoVGltZS5ieS5Hcm91cCksIGpvaW50PVRSVUUpDQpgYGANCg0KU28gY2hhbmdlcyBvdmVyIHRpbWUgaW4gQ29udHJvbCBncm91cCB3aGljaCB3ZSBjYW4gZm9sbG93IHVwIHdpdGggY29udHJhc3RzOiBwb2x5bm9taWFscywgY29uc2VjdXRpdmUsIG9yIGFueSBjdXN0b20gY29udHJhc3QgeW91IHdhbnQgdG8gdGVzdC4gW05vdGUgd2UgY2FuIGluZGV4IDE6MyB0byBzZWUgb25seSB0aGUgQ0JUIHJlc3VsdHNdDQoNCmBgYHtyfQ0KY29udHJhc3QoVGltZS5ieS5Hcm91cCwgJ3BvbHknKVsxOjNdDQpgYGANCg0KDQojIFJlZmVyZW5jZXMNCkNvdXNpbmVhdSwgRC4sICYgTydCcmllbiwgRi4gKDIwMTQpLiBFcnJvciBiYXJzIGluIHdpdGhpbi1zdWJqZWN0IGRlc2lnbnM6IGEgY29tbWVudCBvbiBCYWd1bGV5ICgyMDEyKS4gKkJlaGF2aW9yIFJlc2VhcmNoIE1ldGhvZHMqLCA0Nig0KSwgMTE0OS0xMTUxLg0KDQo=