1 Model met interacties

  • Effect modificatie!

  • Associatie van een predictor en de respons variabele hangt van de waarde van een andere predictor.

1.1 Interactie tussen continue predictor variabele en een categorische predictor?

Om deze interactie of effectmodificatie tussen variabelen \(X_v\) en \(X_s\), en \(X_w\) en \(X_s\) statistisch te modelleren, kan men de producten van beide variabelen in kwestie aan het model toevoegen

\[ Y_i = \beta_0 + \beta_v x_{iv} + \beta_w x_{iw} +\beta_s x_{is} + \beta_{vs} x_{iv}x_{is} + \beta_{ws} x_{iw}x_{is} +\epsilon_i \]

Deze termen kwantificeren de interactie-effecten van respectievelijk de predictoren \(x_v\) en \(x_s\), en, \(x_v\) en \(x_s\) op de gemiddelde uitkomst.

In dit model worden de termen \(\beta_vx_{iv}\), \(\beta_wx_{iw}\) en \(\beta_s x_{is}\) de hoofdeffecten van de predictoren \(x_v\), \(x_w\) en \(x_s\) genoemd.

lmVWS_IntVS_WS <- lm(
  lpsa ~
    lcavol +
    lweight +
    svi +
    svi:lcavol +
    svi:lweight,
  data = prostate)

summary(lmVWS_IntVS_WS)
## 
## Call:
## lm(formula = lpsa ~ lcavol + lweight + svi + svi:lcavol + svi:lweight, 
##     data = prostate)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.50902 -0.44807  0.06455  0.45657  1.54354 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         -0.52642    0.56793  -0.927 0.356422    
## lcavol               0.54060    0.07821   6.912 6.38e-10 ***
## lweight              0.58292    0.15699   3.713 0.000353 ***
## sviinvasion          3.43653    1.93954   1.772 0.079771 .  
## lcavol:sviinvasion   0.13467    0.25550   0.527 0.599410    
## lweight:sviinvasion -0.82740    0.52224  -1.584 0.116592    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.7147 on 91 degrees of freedom
## Multiple R-squared:  0.6367, Adjusted R-squared:  0.6167 
## F-statistic: 31.89 on 5 and 91 DF,  p-value: < 2.2e-16

Omdat \(X_S\) een dummy variabele is, verkrijgen we verschillende regressievlakken:

  1. Model voor \(X_s=0\): \[Y=\beta_0+\beta_vX_v+\beta_wX_w + \epsilon\] waar de hoofdeffecten de hellingen voor lcavol en lweight zijn

  2. en het model voor \(X_s=1\): \[\begin{array}{lcl} Y&=&\beta_0+\beta_vX_v+\beta_s+\beta_wX_w+\beta_{vs}X_v + \beta_{ws}X_w +\epsilon\\ &=& (\beta_0+\beta_s)+(\beta_v+\beta_{vs})X_v+(\beta_w+\beta_{ws})X_w+\epsilon \end{array}\] met intercept \(\beta_0+\beta_s\) en hellingen \(\beta_v+\beta_{vs}\) en \(\beta_w+\beta_{ws}\)

  • De helling voor lcavol en lweight hangt af van de status van de zaadblaasjes!

1.2 Interactie tussen continue predictoren?

\[ Y_i = \beta_0 + \beta_v x_{iv} + \beta_w x_{iw} +\beta_s x_{is} + \beta_{vw} x_{iv}x_{iw} +\epsilon_i \]

Deze term kwantificeert het interactie-effect van de predictoren \(x_v\) en \(x_w\) op de gemiddelde uitkomst.


Het effect van een verschil in 1 eenheid in \(X_v\) op de gemiddelde uitkomst bedraagt nu:

\[ \begin{array}{l} E(Y | X_v=x_v +1, X_w=x_w, X_s=x_s) - E(Y | X_v=x_v, X_w=x_w, X_s=x_s) \\ \quad = \left[\beta_0 + \beta_v (x_{v}+1) + \beta_w x_w +\beta_s x_{s} + \beta_{vw} (x_{v}+1) x_w \right] - \left[\beta_0 + \beta_v x_{v} + \beta_w x_w + \beta_s x_{s} + \beta_{vw} (x_{v}) x_w \right]\\ \quad = \beta_v + \beta_{vw} x_w \end{array} \]

  • De helling voor lcavol hangt m.a.w. af van het log gewicht van de prostaat!

  • We kunnen hetzelfde doen voor lweight. Helling voor lweight hangt af van het log volume van de tumor!


lmVWS_IntVW <- lm(
  lpsa ~ lcavol +
    lweight +
    svi +
    lcavol:lweight,
  prostate)

summary(lmVWS_IntVW)
## 
## Call:
## lm(formula = lpsa ~ lcavol + lweight + svi + lcavol:lweight, 
##     data = prostate)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.65886 -0.44673  0.02082  0.50244  1.57457 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)   
## (Intercept)     -0.6430     0.7030  -0.915  0.36278   
## lcavol           1.0046     0.5427   1.851  0.06734 . 
## lweight          0.6146     0.1961   3.134  0.00232 **
## sviinvasion      0.6859     0.2114   3.244  0.00164 **
## lcavol:lweight  -0.1246     0.1478  -0.843  0.40156   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.7179 on 92 degrees of freedom
## Multiple R-squared:  0.6293, Adjusted R-squared:  0.6132 
## F-statistic: 39.05 on 4 and 92 DF,  p-value: < 2.2e-16

2 Anova tabel en aanvullende kwadratensommen?

Beschouw de volgende twee geneste regressiemodellen voor predictoren \(x_1, \ldots, x_{p-k}\) en \(x_1, \ldots, x_{p-1}\): \[ Y_i = \beta_0+\beta_1 x_{i1} + ... + \beta_{p-k} x_{ip-k} + \epsilon_i, \] met \(\epsilon_i\text{ iid } N(0,\sigma_1^{2})\), en \[ Y_i = \beta_0+\beta_1 x_{i1} + ... + \beta_{p-1} x_{ip-1} + \epsilon_i, \] met \(\epsilon_i\text{ iid } N(0,\sigma_2^{2})\).

Voor het eerste (gereduceerde) model geldt de decompositie \[ \text{SSTot} = \text{SSR}_1 + \text{SSE}_1 \] en voor het tweede (niet-gereduceerde) model \[ \text{SSTot} = \text{SSR}_2 + \text{SSE}_2 \] (SSTot is uiteraard dezelfde in beide modellen omdat dit niet afhangt van het regressiemodel).

\[ \text{SSTot} = \text{SSR}_{2 \mid 1} + \text{SSR}_1 + \text{SSE}_2 \]

\[ F = \frac{\text{SSR}_{2 \mid 1}}{\text{SSE}_2} \]

  • Testen voor alle niveaus van een factor simultaan: omnibus test.
  • Testen voor totale effect van een predictor: hoofdeffecten + interacties

3 Diagnostiek

3.1 Multicollineariteit

\[\textrm{VIF}_j=\left(1-R_j^2\right)^{-1}\]

3.1.1 Body fat voorbeeld

## 
## Call:
## lm(formula = Body_fat ~ Triceps + Thigh + Midarm, data = bodyfat)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.7263 -1.6111  0.3923  1.4656  4.1277 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept)  117.085     99.782   1.173    0.258
## Triceps        4.334      3.016   1.437    0.170
## Thigh         -2.857      2.582  -1.106    0.285
## Midarm        -2.186      1.595  -1.370    0.190
## 
## Residual standard error: 2.48 on 16 degrees of freedom
## Multiple R-squared:  0.8014, Adjusted R-squared:  0.7641 
## F-statistic: 21.52 on 3 and 16 DF,  p-value: 7.343e-06
vif(lmFat)
##  Triceps    Thigh   Midarm 
## 708.8429 564.3434 104.6060
## 
## Call:
## lm(formula = Midarm ~ Triceps + Thigh, data = bodyfat)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.58200 -0.30625  0.02592  0.29526  0.56102 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 62.33083    1.23934   50.29   <2e-16 ***
## Triceps      1.88089    0.04498   41.82   <2e-16 ***
## Thigh       -1.60850    0.04316  -37.26   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.377 on 17 degrees of freedom
## Multiple R-squared:  0.9904, Adjusted R-squared:  0.9893 
## F-statistic: 880.7 on 2 and 17 DF,  p-value: < 2.2e-16

3.2 Invloedrijke Observaties

3.2.1 Exploratief

  • Studentized residu’s om outliers op te sporen
  • leverage (invloed, hefboom) om observaties met extreem covariaatpatroon op te sporen. Extreme leverage: leverage waarde groter dan 2p/n
plot(lmVWS,5)

3.2.2 Cooks distance

\[D_i=\frac{\sum_{j=1}^n(\hat{Y}_j-\hat{Y}_{j(i)})^2}{p\textrm{MSE}}\]

  • Extreme Cook’s distance als het het 50% percentiel van de \(F_{p,n-p}\)-verdeling overschrijdt.
plot(lmVWS,4)

3.2.3 DFBETAS

\[\textrm{DFBETAS}_{j(i)}=\frac{\hat{\beta}_{j}-\hat{\beta}_{j(i)}}{\textrm{SD}(\hat{\beta}_{j})}\] - DFBETAS extreem is wanneer ze 1 overschrijdt in kleine tot middelgrote datasets en \(2/\sqrt{n}\) in grote datasets

4 Contrasten

4.1 Bloeddruk voorbeeld

library(NHANES)
bpData <- NHANES %>%
filter(
  Race1 =="White" &
    Age >= 18 &
    !is.na(BPSysAve)
    )

mBp1 <- lm(BPSysAve ~ Age*Gender, bpData)
par(mfrow = c(2,2))
plot(mBp1)

4.1.1 Remediering heteroscedasticiteit

Illustratie: Bij grote steekproeven kunnen we corrigeren voor heteroscedasticiteit.

mSd <- lm(mBp1$res %>% abs ~ mBp1$fitted)

We schatten het model nu opnieuw:

mBp3 <- lm(BPSysAve ~ Age*Gender, bpData, w = 1/mSd$fitted^2)

4.1.2 Besluitvorming

De onderzoeksvragen vertalen zich in de volgende nullhypotheses:

  1. Associatie tussen bloeddruk en leeftijd bij de vrouwen? \[H_0: \beta_\text{Age} = 0 \text{ vs } H_1: \beta_\text{Age} \neq 0 \]

  2. Associatie tussen bloeddruk en leeftijd bij de mannen? \[H_0: \beta_\text{Age} + \beta_\text{Age:Gendermale} = 0 \text{ vs } H_1: \beta_\text{Age} + \beta_\text{Age:Gendermale} \neq 0 \]

  3. Is de Associatie tussen bloeddruk en leeftijd verschillend bij mannen en vrouwen? \[H_0: \beta_\text{Age:Gendermale} = 0 \text{ vs } H_1: \beta_\text{Age:Gendermale} \neq 0 \]

  • We kunnen onderzoeksvraag 1 en 3 onmiddelijk toetsen o.b.v. de model output.

  • Onderzoeksvraag 2 is echter een lineaire combinatie van twee parameters.

\[ \begin{array}{lcl} L \boldsymbol{\beta} &=& 0\\\\ \left[\begin{array}{cccc} 0 &0& 1& 1\end{array} \right]\left[\begin{array}{c}\beta_0\\ \beta_g\\ \beta_a\\ \beta_{a:g}\end{array} \right] &=& 0\\\\ 0\beta_0 + 0 \beta_g + 1 \beta_a + 1\beta_{a:g} &=& 0\\\\ \beta_a + \beta_{a:g} &=&0 \end{array} \]

  • Bovendien is er ook het probleem dat we meerdere toetsen nodig hebben om de associaties te bestuderen.
  1. We toetsen eerste de omnibus hypothese dat er geen associatie is tussen leeftijd en de bloeddruk.

\[ H_0: \beta_\text{Age} = \beta_\text{Age} + \beta_\text{Age:Gendermale} = \beta_\text{Age:Gendermale} = 0 \]

  • Dat vereenvoudigt zich tot het toetsen dat \[ H_0: \beta_\text{Age} = \beta_\text{Age:Gendermale} = 0 \]

  • Wat we kunnen evalueren door twee modellen te vergelijken. Een model met enkel het gender effect en volledige model met Gender, Age en Gender x Age interactie.

  1. Als we deze hypothese kunnen verwerpen voeren we posthoc analyses uit voor elk van de 3 contrasten.
mBp0 <- lm(BPSysAve ~ Gender, bpData, w = 1/mSd$fitted^2)
anova(mBp0, mBp3)

De posthoc testen kunnen we opnieuw uitvoeren a.d.h.v. het multcomp pakket.

bpPosthoc <- glht(mBp3, linfct=c(
  "Age = 0",
  "Age + Age:Gendermale = 0",
  "Age:Gendermale = 0")
  )
bpPosthoc %>% summary
## 
##   Simultaneous Tests for General Linear Hypotheses
## 
## Fit: lm(formula = BPSysAve ~ Age * Gender, data = bpData, weights = 1/mSd$fitted^2)
## 
## Linear Hypotheses:
##                           Estimate Std. Error t value Pr(>|t|)    
## Age == 0                   0.43999    0.01511  29.127   <1e-10 ***
## Age + Age:Gendermale == 0  0.24840    0.01879  13.217   <1e-10 ***
## Age:Gendermale == 0       -0.19159    0.02411  -7.946   <1e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## (Adjusted p values reported -- single-step method)
bpPosthocBI <- bpPosthoc %>% confint
bpPosthocBI
## 
##   Simultaneous Confidence Intervals
## 
## Fit: lm(formula = BPSysAve ~ Age * Gender, data = bpData, weights = 1/mSd$fitted^2)
## 
## Quantile = 2.3161
## 95% family-wise confidence level
##  
## 
## Linear Hypotheses:
##                           Estimate lwr     upr    
## Age == 0                   0.4400   0.4050  0.4750
## Age + Age:Gendermale == 0  0.2484   0.2049  0.2919
## Age:Gendermale == 0       -0.1916  -0.2474 -0.1357

4.1.3 Conclusie

We kunnen besluiten dat er een extreem significante associatie is tussen leeftijd en de bloeddruk (p << 0.001). De bloeddruk bij twee vrouwen die in leeftijd verschillen is gemiddeld 0.44 mm Hg hoger per jaar leeftijdsverschil bij de oudste vrouw en dat verschil is extreem significant (p << 0.001, 95% BI [0.41, 0.47]). De bloeddruk bij mannen die in leeftijd verschillen is gemiddeld 0.25 mm Hg hoger per jaar leeftijdsverschil bij de oudere man. (p << 0.001, 95% BI [0.2, 0.29]). Het gemiddelde bloeddrukverschil tussen personen in leeftijd verschillen is gemiddeld 0.19 mm Hg/jaar lager bij mannen dan vrouwen (p << 0.001, 95% BI [-0.25, -0.14]).

4.2 Marginale effecten

Wat doen we als interacties niet significant zijn?

  • Conventionele aanpak: interacties uit model halen
  • Daarna schatten we de hoofdeffecten met vereenvoudigd model

Merk op dat

  1. We bij complexe modellen veel testen uitvoeren om tot het vereenvoudigd model te komen.
  2. Het aanvaarden van de nulhypotheses een zwakke conclusie is en dat er typisch weinig power is om een interactie op te pikken. Het is dus mogelijk dat het model zonder interacties toch het foutieve model is.
  3. Bij high troughput experimenten gaan we typisch inferentie doen voor alle genen/proteinen die we meten (vb. 40000 genen of 1000den proteïnen). Door grote correctie voor multiple testing kunnen we interactie termen niet weglaten want daar weten we zeker dat de power om interacties op te pikken zeer laag.

Omwille van deze redenen kunnen we ook de interacties in het model laten en inferentie doen over de marginale effecten.

  • De effecten waarbij we uitmiddelen over alle predictorwaarden van de andere predictoren.

  • In een gerandomiseerde observationele studie zullen we zo dus de assocatie schatten voor de gemiddelde patiënt in de populatie.

  • Zie oefeningen: vissen en kpna2

4.2.1 Testosteron concentratie bij volwassen mannen in de NHANES studie

Veronderstel dat we wensen te bestuderen of er een associatie is leeftijd en gewicht van volwassen mannen in de Amerikaanse populatie op de de testosteron concentratie.

modTes <- lm(formula = Testosterone ~ Age * Weight, data = NHANES %>% 
    filter(Age > 18 & Gender == "male" & !is.na(Testosterone) &!is.na(Weight) & !is.na(Age)))
plot(modTes)

summary(modTes)
## 
## Call:
## lm(formula = Testosterone ~ Age * Weight, data = NHANES %>% filter(Age > 
##     18 & Gender == "male" & !is.na(Testosterone) & !is.na(Weight) & 
##     !is.na(Age)))
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -443.32 -117.40  -14.48   92.81 1454.01 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 733.876732  54.785206  13.396  < 2e-16 ***
## Age          -1.272290   1.160246  -1.097    0.273    
## Weight       -3.143425   0.629743  -4.992  6.6e-07 ***
## Age:Weight    0.003199   0.013342   0.240    0.811    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 167.4 on 1699 degrees of freedom
## Multiple R-squared:  0.1158, Adjusted R-squared:  0.1143 
## F-statistic: 74.19 on 3 and 1699 DF,  p-value: < 2.2e-16
  • Er is geen significante interactie. Het aanvaarden van de nulhypothese is een zwakke conclusie. Daarom kunnen we opteren om de interactie in het model te laten.

  • Merk op dat de hoofdeffecten geen zinvolle interpretatie hebben!

  • Omdat er geen significante interactie is, is het zinvol om een uitspraak te doen over de associatie van gewicht en testosteron, en leeftijd en testosteron.

We kunnen hierover een uitspraak doen door te marginaliseren over alle leeftijden (gewichten) van de mannen in het experiment.

\[ \frac{\sum\limits_{i=1}^n (\beta_a + \beta_{w:a} X_{w})}{n}= \beta_a +\beta_{w:a} \bar{X}_w \]

\[ \frac{\sum\limits_{i=1}^n (\beta_w + \beta_{w:a} X_{a})}{n}= \beta_w +\beta_{w:a} \bar{X}_a \]

NHANES %>% 
  filter(Age > 18 & Gender == "male" & !is.na(Testosterone) &!is.na(Weight) & !is.na(Age))  %>% 
  pull(Weight) %>%
  mean %>% 
  round(.,1)
## [1] 88.9
NHANES %>% 
  filter(Age > 18 & Gender == "male" & !is.na(Testosterone) &!is.na(Weight) & !is.na(Age))  %>% 
  pull(Age) %>%
  mean %>% 
  round(.,1)
## [1] 46.4

We evalueren nu het contrast voor de marginale effecten:

marginalEffects <- glht(
  modTes, 
  linfct = c(
    "Age +88.9*Age:Weight= 0",
    "Weight +46.4*Age:Weight= 0"
    )
  )
summary(marginalEffects)
## 
##   Simultaneous Tests for General Linear Hypotheses
## 
## Fit: lm(formula = Testosterone ~ Age * Weight, data = NHANES %>% filter(Age > 
##     18 & Gender == "male" & !is.na(Testosterone) & !is.na(Weight) & 
##     !is.na(Age)))
## 
## Linear Hypotheses:
##                                 Estimate Std. Error t value Pr(>|t|)    
## Age + 88.9 * Age:Weight == 0     -0.9879     0.2487  -3.973 0.000148 ***
## Weight + 46.4 * Age:Weight == 0  -2.9950     0.2131 -14.055  < 1e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## (Adjusted p values reported -- single-step method)
confint(marginalEffects)
## 
##   Simultaneous Confidence Intervals
## 
## Fit: lm(formula = Testosterone ~ Age * Weight, data = NHANES %>% filter(Age > 
##     18 & Gender == "male" & !is.na(Testosterone) & !is.na(Weight) & 
##     !is.na(Age)))
## 
## Quantile = 2.2383
## 95% family-wise confidence level
##  
## 
## Linear Hypotheses:
##                                 Estimate lwr     upr    
## Age + 88.9 * Age:Weight == 0    -0.9879  -1.5446 -0.4313
## Weight + 46.4 * Age:Weight == 0 -2.9950  -3.4720 -2.5180

Dit heeft een interpretatie van het gemiddelde leeftijds- en de gemiddelde gewichtsassociatie in de populatie.

Volgens de conventionele aanpak hadden we de interactie uit het model verwijderd.

modAddTes <- lm(formula = Testosterone ~ Age + Weight, data = 
    NHANES %>% 
    filter(Age > 18 & Gender == "male" & !is.na(Testosterone) &!is.na(Weight) & !is.na(Age)))
summary(modAddTes)
## 
## Call:
## lm(formula = Testosterone ~ Age + Weight, data = NHANES %>% filter(Age > 
##     18 & Gender == "male" & !is.na(Testosterone) & !is.na(Weight) & 
##     !is.na(Age)))
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -442.64 -118.06  -14.12   92.67 1455.21 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 721.8444    21.9582  32.874  < 2e-16 ***
## Age          -1.0003     0.2432  -4.113 4.08e-05 ***
## Weight       -3.0012     0.2115 -14.193  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 167.3 on 1700 degrees of freedom
## Multiple R-squared:  0.1158, Adjusted R-squared:  0.1148 
## F-statistic: 111.3 on 2 and 1700 DF,  p-value: < 2.2e-16

Merk op dat de schattingen uit het additief model lichtjes verschillend zijn omdat de data niet gebalanceerd zijn, we hebben niet dezelfde gewichten voor alle leeftijden en niet dezelfde leeftijden voor alle gewichten.

NHANES %>% 
    filter(Age > 18 & Gender == "male" & !is.na(Testosterone) &!is.na(Weight) & !is.na(Age)) %>% 
  ggplot(aes(Age,Weight)) +
  geom_point()

5 Factoriële proeven

5.1 Data

48 ratten werden at random toegewezen aan

  • 3 giffen (I,II,III) and
  • 4 behandelingen (A,B,C,D),

en,

  • de overlevingstijd werd opgemeten (eenheid: 10 h)

We transformeren de data eerst naar uren

data(rats,package = "faraway")

rats <- rats %>% 
  mutate(time=time * 10)

rats %>% 
  ggpairs()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

rats %>%
  ggplot(aes(x=treat,y=time)) + 
  geom_boxplot(outlier.shape=NA) + 
  geom_jitter() +
  facet_wrap(~poison) +
  ylab("time (h)")

rats %>%
  ggplot(aes(x=treat,y=1/time)) + 
  geom_boxplot(outlier.shape=NA) + 
  geom_jitter() +
  facet_wrap(~poison) + 
  ylab ("rate of dying (1/h)")

rats3 <- lm(1/time~poison*treat, rats)

We modelleren de “snelheid van sterven” met een hoofdeffect voor gif en behandeling en een gif \(\times\) behandeling interactie.

\[ \begin{array}{lcl} y_i &=& \beta_0 + \\ &&\beta_{II} x_{iII} + \beta_{III} x_{iIII} + \\ && \beta_{B} x_{iB} + \beta_{C} x_{iC} + \beta_{D} x_{iD} + \\ &&\beta_{II:B}x_{iII}x_{iB} + \beta_{II:C}x_{iII}x_{iC} + \beta_{II:D}x_{iII}x_{iD} + \\ &&\beta_{III:B}x_{iIII}x_{iB} + \beta_{III:C}x_{iIII}x_{iC} + \beta_{III:D}x_{iIII}x_{iD} + \epsilon_i \end{array} \]

met \(i = 1, \ldots, n\), \(n=48\), en, \(x_{iII}\), \(x_{iIII}\), \(x_{iB}\), \(x_{iC}\) en \(x_{iD}\) dummy variabelen voor respectievelijk gif II, III, behandeling B, C, en D.

5.2 Inferentie

ExploreModelMatrix::VisualizeDesign(rats,~poison*treat)$plot
## [[1]]

Een interactie tussen gif en behandeling impliceert dat we het effect van het type gif afzonderlijk moeten bestuderen voor elke behandeling:

  1. Voor behandeling A moeten we dan volgende nulhypotheses toetsen:
  • II-I: \(H_0: \beta_{II}=0\)
  • III-I: \(H_0: \beta_{III}=0\)
  • III-II: \(H_0: \beta_{III}-\beta_{II}=0\)
  1. Voor behandeling B:
  • II-I: \(H_0: \beta_{II}+\beta_{II:B}=0\)
  • III-I: \(H_0: \beta_{III}+\beta_{III:B}=0\)
  • III-II: \(H_0: \beta_{III}+\beta_{III:B}-\beta_{II}-\beta_{II:B}=0\)
  1. Voor behandeling C:
  • II-I: \(H_0: \beta_{II}+\beta_{II:C}=0\)
  • III-I: \(H_0: \beta_{III}+\beta_{III:C}=0\)
  • III-II: \(H_0: \beta_{III}+\beta_{III:C}-\beta_{II}-\beta_{II:C}=0\)
  1. Voor behandeling D:
  • II-I: \(H_0: \beta_{II}+\beta_{II:D}=0\)
  • III-I: \(H_0: \beta_{III}+\beta_{III:D}=0\)
  • III-II: \(H_0: \beta_{III}+\beta_{III:D}-\beta_{II}-\beta_{II:D}=0\)

Hetzelfde geldt wanneer we het effect van de behandeling bestuderen:

  1. Voor gif I toetsen we dan nulhypothese
  • B-A: \(H_0: \beta_{B}=0\)
  • C-A: \(H_0: \beta_{C}=0\)
  • D-A: \(H_0: \beta_{D}=0\)
  • C-B: \(H_0: \beta_{C}-\beta_{B}=0\)
  • D-B: \(H_0: \beta_{D}-\beta_{B}=0\)
  • D-C: \(H_0: \beta_{D}-\beta_{C}=0\)
  1. Gif II
  • B-A: \(H_0: \beta_{B}+\beta_{II:B}=0\)
  • C-A: \(H_0: \beta_{C}+\beta_{II:C}=0\)
  • D-A: \(H_0: \beta_{D}+\beta_{II:D}=0\)
  • C-B: \(H_0: \beta_{C}+\beta_{II:C}-\beta_{B}-\beta_{II:B}=0\)
  • D-B: \(H_0: \beta_{D}+\beta_{II:D}-\beta_{B}-\beta_{II:B}=0\)
  • D-C: \(H_0: \beta_{D}+\beta_{II:D}-\beta_{C}-\beta_{II:C}=0\)
  1. Gif III
  • B-A: \(H_0: \beta_{B}+\beta_{III:B}=0\)
  • C-A: \(H_0: \beta_{C}+\beta_{III:C}=0\)
  • D-A: \(H_0: \beta_{D}+\beta_{II:D}=0\)
  • C-B: \(H_0: \beta_{C}+\beta_{III:C}-\beta_{B}-\beta_{III:B}=0\)
  • D-B: \(H_0: \beta_{D}+\beta_{III:D}-\beta_{B}-\beta_{III:B}=0\)
  • D-C: \(H_0: \beta_{D}+\beta_{III:D}-\beta_{C}-\beta_{III:C}=0\)
library(car)
Anova(rats3, type="III")

In onze studie was de interactie echter niet significant. Het effect van het gif (II-I, III-I en III- II) verandert dus niet significant volgens de behandeling (A, B, C, en D) en vice versa. Voor onze dataset lijkt het dus zinvol om

  1. de effectgrootte voor de pairsgewijze vergelijkingen tussen de verschillende giffen (II-I, III-I en III- II) te schatten door ze uit te middelen over alle behandelingen (A, B, C, en D), en,
  2. de effectgrootte voor de pairsgewijze vergelijkingen tussen de verschillende behandelingen (B-A, C-A, D-A, C-B, D-B en D-C) te schatten door ze uit te middelen over alle giffen (I, II, III).

Dat zou ons gelijkaardige schattingen van de effectgroottes moeten geven als deze voor het additieve model waarbij we de interactie term uit het model hadden geweerd.

B.v. voor gif III vs gif II zou dat in volgende contrast resulteren:

  • III-II: \[H_0: \begin{array}{l} \frac{\beta_{III}-\beta_{II}}{4} + \\ \quad \frac{\beta_{III} + \beta_{III:B}-\beta_{II} - \beta_{II:B}}{4} + \\ \quad \quad \frac{\beta_{III} + \beta_{III:C}-\beta_{II} - \beta_{II:C}}{4} + \\ \quad \quad \quad \frac{\beta_{III} + \beta_{III:D}-\beta_{II} - \beta_{II:D}}{4}=0 \end{array} \] \[ H_0:\beta_{III} + \frac{1}{4} \times \beta_{III:B} + \frac{1}{4} \times\beta_{III:C} + \frac{1}{4} \times\beta_{III:D} -\beta_{II} - \frac{1}{4} \times\beta_{II:B} - \frac{1}{4} \times\beta_{II:C} - \frac{1}{4} \times\beta_{II:D}=0 \]

We schatten met onderstaande code alle gemiddelde contrasten a.d.h.v. het model met interactie.

contrasts <- c(
  "poisonII + 1/4*poisonII:treatB + 1/4*poisonII:treatC + 1/4*poisonII:treatD = 0",
  "poisonIII + 1/4*poisonIII:treatB + 1/4*poisonIII:treatC + 1/4*poisonIII:treatD= 0",
  "poisonIII + 1/4*poisonIII:treatB + 1/4*poisonIII:treatC + 1/4*poisonIII:treatD - poisonII - 1/4*poisonII:treatB - 1/4*poisonII:treatC - 1/4*poisonII:treatD = 0",
  "treatB + 1/3*poisonII:treatB + 1/3*poisonIII:treatB = 0",
  "treatC + 1/3*poisonII:treatC + 1/3*poisonIII:treatC = 0",
  "treatD + 1/3*poisonII:treatD + 1/3*poisonIII:treatD = 0",
  "treatC + 1/3*poisonII:treatC + 1/3*poisonIII:treatC - treatB - 1/3*poisonII:treatB - 1/3*poisonIII:treatB = 0",
  "treatD + 1/3*poisonII:treatD + 1/3*poisonIII:treatD  - treatB - 1/3*poisonII:treatB - 1/3*poisonIII:treatB = 0",
  "treatD + 1/3*poisonII:treatD + 1/3*poisonIII:treatD  - treatC - 1/3*poisonII:treatC - 1/3*poisonIII:treatC = 0") 


comparisonsInt2 <- glht(rats3, linfct = contrasts
)
plot(comparisonsInt2,yaxt="none")
contrastNames <- c("II-I","III-I","III-II","B-A","C-A","D-A","C-B","D-B","D-C")
axis(2,at=c(length(contrastNames):1), labels=contrastNames,las=2)

5.3 Conclusie

Er is een extreem significant effect van het type gif en de behandeling op de snelheid van sterven bij ratten (p << 0.001).

De interactie tussen gif en behandeling is niet significant (p = 0.387).

De snelheid van sterven is gemiddeld 0.2h\(^{-1}\) en 0.15h\(^{-1}\) hoger voor ratten die blootgesteld worden aan gif III dan aan respectievelijk gif I en II (beide p << 0.001, 95% BI III-I: [0.15, 0.25]h\(^{-1}\), 95% BI III-II: [0.1, 0.2]h\(^{-1}\)) De gemiddelde snelheid van sterven was niet significant verschillend tussen ratten die werden blootgesteld aan gif I en gif II (p=0.074).

De snelheid van sterven is gemiddeld 0.17h\(^{-1}\) en 0.14h\(^{-1}\) hoger na behandeling A dan na behandeling B en D (p << 0.001, 95% BI B-A: [-0.22, -0.11]h\(^{-1}\), 95% BI D-A: [-0.19, -0.08]h\(^{-1}\)). De snelheid van sterven is gemiddeld 0.11h\(^{-1}\) en 0.08h\(^{-1}\) hoger na behandeling C dan respectievelijk na behandeling B en D (C-B: p << 0.001, 95% CI [0.05, 0.17]h\(^{-1}\) , D-C: p = 0.003, 95% CI [-0.14, -0.02]h\(^{-1}\)). De gemiddelde snelheid van sterven is niet significant verschillend tussen ratten behandeld met behandeling C vs A, en D vs B (p- waarden respectievelijk p = 0.051 en p = 0.61).

Alle p-waarden werden gecorrigeerd voor meervoudig testen.

LS0tCnRpdGxlOiAiMTAuIFJlY2FwOiBBbGdlbWVlbiBMaW5lYWlyIE1vZGVsIC0gSW50ZXJhY3RpZXMgLSBEaWFnbm9zdGllayAtIENvbnRyYXN0ZW4gLSBEYWN0b3Jpw6tsZSBwcm9ldmVuIgphdXRob3I6ICJMaWV2ZW4gQ2xlbWVudCIKZGF0ZTogInN0YXRPbWljcywgR2hlbnQgVW5pdmVyc2l0eSAoaHR0cHM6Ly9zdGF0b21pY3MuZ2l0aHViLmlvKSIKb3V0cHV0OgogICAgaHRtbF9kb2N1bWVudDoKICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgICB0aGVtZTogY29zbW8KICAgICAgdG9jOiB0cnVlCiAgICAgIHRvY19mbG9hdDogdHJ1ZQogICAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgcGRmX2RvY3VtZW50OgogICAgICB0b2M6IHRydWUKICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleAotLS0KCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG11bHRjb21wKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeShjYXIpCnByb3N0YXRlIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdG9taWNzL3NiYzIwL21hc3Rlci9kYXRhL3Byb3N0YXRlLmNzdiIpCnByb3N0YXRlJHN2aSA8LSBhcy5mYWN0b3IocHJvc3RhdGUkc3ZpKQpsbVZXUyA8LSBsbShscHNhfmxjYXZvbCArIGx3ZWlnaHQgKyBzdmksIHByb3N0YXRlKQpgYGAKCiMgTW9kZWwgbWV0IGludGVyYWN0aWVzCgotIEVmZmVjdCBtb2RpZmljYXRpZSEKCi0gKipBc3NvY2lhdGllIHZhbiBlZW4gcHJlZGljdG9yIGVuIGRlIHJlc3BvbnMgdmFyaWFiZWxlKiogaGFuZ3QgdmFuIGRlIHdhYXJkZSB2YW4gZWVuICoqYW5kZXJlIHByZWRpY3RvcioqLgoKIyMgSW50ZXJhY3RpZSB0dXNzZW4gY29udGludWUgcHJlZGljdG9yIHZhcmlhYmVsZSBlbiBlZW4gY2F0ZWdvcmlzY2hlIHByZWRpY3Rvcj8KCk9tIGRlemUgKippbnRlcmFjdGllKiogb2YgKiplZmZlY3Rtb2RpZmljYXRpZSoqIHR1c3NlbiB2YXJpYWJlbGVuICRYX3YkIGVuICRYX3MkLCBlbiAkWF93JCBlbiAkWF9zJCBzdGF0aXN0aXNjaCB0ZSBtb2RlbGxlcmVuLCBrYW4gbWVuIGRlIHByb2R1Y3RlbiB2YW4gYmVpZGUgdmFyaWFiZWxlbiBpbiBrd2VzdGllIGFhbiBoZXQgbW9kZWwgdG9ldm9lZ2VuCgokJApZX2kgPSBcYmV0YV8wICsgXGJldGFfdiB4X3tpdn0gKyBcYmV0YV93IHhfe2l3fSArXGJldGFfcyB4X3tpc30gKyBcYmV0YV97dnN9IHhfe2l2fXhfe2lzfSArIFxiZXRhX3t3c30geF97aXd9eF97aXN9ICArXGVwc2lsb25faQokJAoKRGV6ZSB0ZXJtZW4ga3dhbnRpZmljZXJlbiBkZSAqaW50ZXJhY3RpZS1lZmZlY3RlbiogdmFuIHJlc3BlY3RpZXZlbGlqayBkZSBwcmVkaWN0b3JlbiAkeF92JCBlbiAkeF9zJCwgZW4sICR4X3YkIGVuICR4X3MkIG9wIGRlIGdlbWlkZGVsZGUgdWl0a29tc3QuCgpJbiBkaXQgbW9kZWwgd29yZGVuIGRlIHRlcm1lbiAkXGJldGFfdnhfe2l2fSQsICRcYmV0YV93eF97aXd9JCBlbiAkXGJldGFfcyB4X3tpc30kIGRlICpob29mZGVmZmVjdGVuKiB2YW4gZGUgcHJlZGljdG9yZW4gJHhfdiQsICR4X3ckIGVuICR4X3MkIGdlbm9lbWQuCgpgYGB7cn0KbG1WV1NfSW50VlNfV1MgPC0gbG0oCiAgbHBzYSB+CiAgICBsY2F2b2wgKwogICAgbHdlaWdodCArCiAgICBzdmkgKwogICAgc3ZpOmxjYXZvbCArCiAgICBzdmk6bHdlaWdodCwKICBkYXRhID0gcHJvc3RhdGUpCgpzdW1tYXJ5KGxtVldTX0ludFZTX1dTKQpgYGAKCgpPbWRhdCAkWF9TJCBlZW4gZHVtbXkgdmFyaWFiZWxlIGlzLCB2ZXJrcmlqZ2VuIHdlIHZlcnNjaGlsbGVuZGUgcmVncmVzc2lldmxha2tlbjoKCjEuIE1vZGVsIHZvb3IgJFhfcz0wJDogJCRZPVxiZXRhXzArXGJldGFfdlhfditcYmV0YV93WF93ICsgXGVwc2lsb24kJCB3YWFyIGRlIGhvb2ZkZWZmZWN0ZW4gZGUgaGVsbGluZ2VuIHZvb3IgbGNhdm9sIGVuIGx3ZWlnaHQgemlqbgoKMi4gZW4gaGV0IG1vZGVsIHZvb3IgJFhfcz0xJDoKICAgJCRcYmVnaW57YXJyYXl9e2xjbH0KICAgWSY9JlxiZXRhXzArXGJldGFfdlhfditcYmV0YV9zK1xiZXRhX3dYX3crXGJldGFfe3ZzfVhfdiArIFxiZXRhX3t3c31YX3cgK1xlcHNpbG9uXFwKICAmPSYgKFxiZXRhXzArXGJldGFfcykrKFxiZXRhX3YrXGJldGFfe3ZzfSlYX3YrKFxiZXRhX3crXGJldGFfe3dzfSlYX3crXGVwc2lsb24KICBcZW5ke2FycmF5fSQkCm1ldCBpbnRlcmNlcHQgJFxiZXRhXzArXGJldGFfcyQgZW4gaGVsbGluZ2VuICRcYmV0YV92K1xiZXRhX3t2c30kIGVuICRcYmV0YV93K1xiZXRhX3t3c30kCgotIERlIGhlbGxpbmcgdm9vciBsY2F2b2wgZW4gbHdlaWdodCBoYW5ndCBhZiB2YW4gZGUgc3RhdHVzIHZhbiBkZSB6YWFkYmxhYXNqZXMhCgpgYGB7ciBvdXQud2lkdGg9JzEwMCUnLCBmaWcuYXNwPS44LCBmaWcuYWxpZ249J2NlbnRlcicsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0KcGFyKG1mcm93PWMoMSwyKSkKbGlicmFyeShwbG90M0QpCmdyaWQubGluZXMgPSAxMAp4PC1wcm9zdGF0ZSRsY2F2b2wKeTwtcHJvc3RhdGUkbHdlaWdodAp6PC1wcm9zdGF0ZSRscHNhCmZpdDwtbG0oen54K3krc3ZpLGRhdGE9cHJvc3RhdGUpCngucHJlZCA8LSBzZXEobWluKHgpLCBtYXgoeCksIGxlbmd0aC5vdXQgPSBncmlkLmxpbmVzKQp5LnByZWQgPC0gc2VxKG1pbih5KSwgbWF4KHkpLCBsZW5ndGgub3V0ID0gZ3JpZC5saW5lcykKCiMgZml0dGVkIHBvaW50cyBmb3IgZHJvcGxpbmVzIHRvIHN1cmZhY2UKdGg9LTI1CnBoPTUKc2NhdHRlcjNEKHgsIHksIHosIHBjaCA9IDE2LGNvbD1jKCJkYXJrYmx1ZSIsInJlZCIpW2FzLmRvdWJsZShwcm9zdGF0ZSRzdmkpXSwgY2V4ID0gLjc1LAogICAgdGhldGEgPSB0aCwgcGhpID0gcGgsIHRpY2t0eXBlID0gImRldGFpbGVkIiwKICAgIHhsYWIgPSAibGNhdm9sIiwgeWxhYiA9ICJsd2VpZ2h0IiwgemxhYiA9ICJscHNhIiwgIAogICBjb2x2YXI9RkFMU0UsYnR5ID0gImciLG1haW49IkFkZGl0aXZlIG1vZGVsIikKCmZvciAoaSBpbiB3aGljaChwcm9zdGF0ZSRzdmk9PSJoZWFsdGh5IikpCmxpbmVzM0QoeD1yZXAocHJvc3RhdGUkbGNhdm9sW2ldLDIpLHk9cmVwKHByb3N0YXRlJGx3ZWlnaHRbaV0sMiksej1jKHByb3N0YXRlJGxwc2FbaV0sbG1WV1MkZml0W2ldKSxjb2w9YygiZGFya2JsdWUiLCJyZWQiKVthcy5kb3VibGUocHJvc3RhdGUkc3ZpKVtpXV0sYWRkPVRSVUUsbHR5PTIpCgp6LnByZWQzRCA8LSBvdXRlcih4LnByZWQsIHkucHJlZCwgZnVuY3Rpb24oeCx5KSB7bG1WV1MkY29lZlsxXStsbVZXUyRjb2VmWzJdKngrbG1WV1MkY29lZlszXSp5fSkKeC5wcmVkM0QgPC0gb3V0ZXIoeC5wcmVkLHkucHJlZCxmdW5jdGlvbih4LHkpIHgpCnkucHJlZDNEIDwtIG91dGVyKHgucHJlZCx5LnByZWQsZnVuY3Rpb24oeCx5KSB5KQpzdXJmM0QoeC5wcmVkM0QseS5wcmVkM0Qsei5wcmVkM0QsY29sPSJibHVlIixmYWNldHM9TkEsYWRkPVRSVUUpCnoyLnByZWQzRCA8LSBvdXRlcih4LnByZWQsIHkucHJlZCwgZnVuY3Rpb24oeCx5KSB7bG1WV1MkY29lZlsxXStsbVZXUyRjb2VmWzRdK2xtVldTJGNvZWZbMl0qeCtsbVZXUyRjb2VmWzNdKnl9KQpzdXJmM0QoeC5wcmVkM0QseS5wcmVkM0QsejIucHJlZDNELGNvbD0ib3JhbmdlIixmYWNldHM9TkEsYWRkPVRSVUUpCgoKc2NhdHRlcjNEKHgsIHksIHosIHBjaCA9IDE2LGNvbD1jKCJkYXJrYmx1ZSIsInJlZCIpW2FzLmRvdWJsZShwcm9zdGF0ZSRzdmkpXSwgY2V4ID0gLjc1LAogICAgdGhldGEgPSB0aCwgcGhpID0gcGgsIHRpY2t0eXBlID0gImRldGFpbGVkIiwKICAgIHhsYWIgPSAibGNhdm9sIiwgeWxhYiA9ICJsd2VpZ2h0IiwgemxhYiA9ICJscHNhIiwgIAogICBjb2x2YXI9RkFMU0UsYnR5ID0gImciLG1haW49Ik1vZGVsIG1ldCBsY2F2b2w6bHdlaWdodCBpbnRlcmFjdGllIikKCmZvciAoaSBpbiB3aGljaChwcm9zdGF0ZSRzdmk9PSJoZWFsdGh5IikpCmxpbmVzM0QoeD1yZXAocHJvc3RhdGUkbGNhdm9sW2ldLDIpLHk9cmVwKHByb3N0YXRlJGx3ZWlnaHRbaV0sMiksej1jKHByb3N0YXRlJGxwc2FbaV0sbG1WV1NfSW50VlNfV1MkZml0W2ldKSxjb2w9YygiZGFya2JsdWUiLCJyZWQiKVthcy5kb3VibGUocHJvc3RhdGUkc3ZpKVtpXV0sYWRkPVRSVUUsbHR5PTIpCgp6LnByZWQzRCA8LSBvdXRlcih4LnByZWQsIHkucHJlZCwgZnVuY3Rpb24oeCx5KSB7bG1WV1NfSW50VlNfV1MkY29lZlsxXStsbVZXU19JbnRWU19XUyRjb2VmWzJdKngrbG1WV1NfSW50VlNfV1MkY29lZlszXSp5fSkKeC5wcmVkM0QgPC0gb3V0ZXIoeC5wcmVkLHkucHJlZCxmdW5jdGlvbih4LHkpIHgpCnkucHJlZDNEIDwtIG91dGVyKHgucHJlZCx5LnByZWQsZnVuY3Rpb24oeCx5KSB5KQpzdXJmM0QoeC5wcmVkM0QseS5wcmVkM0Qsei5wcmVkM0QsY29sPSJibHVlIixmYWNldHM9TkEsYWRkPVRSVUUpCnoyLnByZWQzRCA8LSBvdXRlcih4LnByZWQsIHkucHJlZCwgZnVuY3Rpb24oeCx5KSB7bG1WV1NfSW50VlNfV1MkY29lZlsxXStsbVZXU19JbnRWU19XUyRjb2VmWzRdK2xtVldTX0ludFZTX1dTJGNvZWZbMl0qeCtsbVZXU19JbnRWU19XUyRjb2VmWzNdKnkrbG1WV1NfSW50VlNfV1MkY29lZls1XSp4K2xtVldTX0ludFZTX1dTJGNvZWZbNl0qeX0pCnN1cmYzRCh4LnByZWQzRCx5LnByZWQzRCx6Mi5wcmVkM0QsY29sPSJvcmFuZ2UiLGZhY2V0cz1OQSxhZGQ9VFJVRSkKYGBgCgoKIyMgSW50ZXJhY3RpZSB0dXNzZW4gY29udGludWUgcHJlZGljdG9yZW4/CgoKJCQKWV9pID0gXGJldGFfMCArIFxiZXRhX3YgeF97aXZ9ICsgXGJldGFfdyB4X3tpd30gK1xiZXRhX3MgeF97aXN9ICsgXGJldGFfe3Z3fSB4X3tpdn14X3tpd30gK1xlcHNpbG9uX2kKJCQKCkRlemUgdGVybSBrd2FudGlmaWNlZXJ0IGhldCAqaW50ZXJhY3RpZS1lZmZlY3QqIHZhbiBkZSBwcmVkaWN0b3JlbiAkeF92JCBlbiAkeF93JCBvcCBkZSBnZW1pZGRlbGRlIHVpdGtvbXN0LgoKLS0tCgpIZXQgZWZmZWN0IHZhbiBlZW4gdmVyc2NoaWwgaW4gMSBlZW5oZWlkIGluICRYX3YkIG9wIGRlIGdlbWlkZGVsZGUgdWl0a29tc3QgYmVkcmFhZ3QgbnU6CgokJApcYmVnaW57YXJyYXl9e2x9CkUoWSB8IFhfdj14X3YgKzEsIFhfdz14X3csIFhfcz14X3MpIC0gRShZIHwgWF92PXhfdiwgWF93PXhfdywgWF9zPXhfcykgXFwKXHF1YWQgPSBcbGVmdFtcYmV0YV8wICsgXGJldGFfdiAoeF97dn0rMSkgKyBcYmV0YV93IHhfdyArXGJldGFfcyB4X3tzfSArIFxiZXRhX3t2d30gKHhfe3Z9KzEpIHhfdyBccmlnaHRdIC0gXGxlZnRbXGJldGFfMCArIFxiZXRhX3YgeF97dn0gKyBcYmV0YV93IHhfdyAgKyBcYmV0YV9zIHhfe3N9ICsgXGJldGFfe3Z3fSAoeF97dn0pIHhfdyBccmlnaHRdXFwKXHF1YWQgPSBcYmV0YV92ICsgIFxiZXRhX3t2d30geF93CiBcZW5ke2FycmF5fQogJCQKCi0gRGUgaGVsbGluZyB2b29yIGxjYXZvbCBoYW5ndCBtLmEudy4gYWYgdmFuIGhldCBsb2cgZ2V3aWNodCB2YW4gZGUgcHJvc3RhYXQhCgotIFdlIGt1bm5lbiBoZXR6ZWxmZGUgZG9lbiB2b29yIGx3ZWlnaHQuIEhlbGxpbmcgdm9vciBsd2VpZ2h0IGhhbmd0IGFmIHZhbiBoZXQgbG9nIHZvbHVtZSB2YW4gZGUgdHVtb3IhICAKCi0tLQoKYGBge3J9CmxtVldTX0ludFZXIDwtIGxtKAogIGxwc2EgfiBsY2F2b2wgKwogICAgbHdlaWdodCArCiAgICBzdmkgKwogICAgbGNhdm9sOmx3ZWlnaHQsCiAgcHJvc3RhdGUpCgpzdW1tYXJ5KGxtVldTX0ludFZXKQpgYGAKCmBgYHtyIG91dC53aWR0aD0nMTAwJScsIGZpZy5hc3A9LjgsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQpwYXIobWZyb3c9YygxLDIpKQpsaWJyYXJ5KHBsb3QzRCkKZ3JpZC5saW5lcyA9IDEwCng8LXByb3N0YXRlJGxjYXZvbAp5PC1wcm9zdGF0ZSRsd2VpZ2h0Cno8LXByb3N0YXRlJGxwc2EKZml0PC1sbSh6fngreStzdmksZGF0YT1wcm9zdGF0ZSkKeC5wcmVkIDwtIHNlcShtaW4oeCksIG1heCh4KSwgbGVuZ3RoLm91dCA9IGdyaWQubGluZXMpCnkucHJlZCA8LSBzZXEobWluKHkpLCBtYXgoeSksIGxlbmd0aC5vdXQgPSBncmlkLmxpbmVzKQoKIyBmaXR0ZWQgcG9pbnRzIGZvciBkcm9wbGluZXMgdG8gc3VyZmFjZQp0aD0tMjUKcGg9NQpzY2F0dGVyM0QoeCwgeSwgeiwgcGNoID0gMTYsY29sPWMoImRhcmtibHVlIiwicmVkIilbYXMuZG91YmxlKHByb3N0YXRlJHN2aSldLCBjZXggPSAuNzUsCiAgICB0aGV0YSA9IHRoLCBwaGkgPSBwaCwgdGlja3R5cGUgPSAiZGV0YWlsZWQiLAogICAgeGxhYiA9ICJsY2F2b2wiLCB5bGFiID0gImx3ZWlnaHQiLCB6bGFiID0gImxwc2EiLCAgCiAgIGNvbHZhcj1GQUxTRSxidHkgPSAiZyIsbWFpbj0iQWRkaXRpdmUgbW9kZWwiKQoKZm9yIChpIGluIHdoaWNoKHByb3N0YXRlJHN2aT09ImhlYWx0aHkiKSkKbGluZXMzRCh4PXJlcChwcm9zdGF0ZSRsY2F2b2xbaV0sMikseT1yZXAocHJvc3RhdGUkbHdlaWdodFtpXSwyKSx6PWMocHJvc3RhdGUkbHBzYVtpXSxsbVZXUyRmaXRbaV0pLGNvbD1jKCJkYXJrYmx1ZSIsInJlZCIpW2FzLmRvdWJsZShwcm9zdGF0ZSRzdmkpW2ldXSxhZGQ9VFJVRSxsdHk9MikKCnoucHJlZDNEIDwtIG91dGVyKHgucHJlZCwgeS5wcmVkLCBmdW5jdGlvbih4LHkpIHtsbVZXUyRjb2VmWzFdK2xtVldTJGNvZWZbMl0qeCtsbVZXUyRjb2VmWzNdKnl9KQp4LnByZWQzRCA8LSBvdXRlcih4LnByZWQseS5wcmVkLGZ1bmN0aW9uKHgseSkgeCkKeS5wcmVkM0QgPC0gb3V0ZXIoeC5wcmVkLHkucHJlZCxmdW5jdGlvbih4LHkpIHkpCnN1cmYzRCh4LnByZWQzRCx5LnByZWQzRCx6LnByZWQzRCxjb2w9ImJsdWUiLGZhY2V0cz1OQSxhZGQ9VFJVRSkKCgpzY2F0dGVyM0QoeCwgeSwgeiwgcGNoID0gMTYsY29sPWMoImRhcmtibHVlIiwicmVkIilbYXMuZG91YmxlKHByb3N0YXRlJHN2aSldLCBjZXggPSAuNzUsCiAgICB0aGV0YSA9IHRoLCBwaGkgPSBwaCwgdGlja3R5cGUgPSAiZGV0YWlsZWQiLAogICAgeGxhYiA9ICJsY2F2b2wiLCB5bGFiID0gImx3ZWlnaHQiLCB6bGFiID0gImxwc2EiLCAgCiAgIGNvbHZhcj1GQUxTRSxidHkgPSAiZyIsbWFpbj0iTW9kZWwgbWV0IGxjYXZvbDpsd2VpZ2h0IGludGVyYWN0aWUiKQoKZm9yIChpIGluIHdoaWNoKHByb3N0YXRlJHN2aT09ImhlYWx0aHkiKSkKbGluZXMzRCh4PXJlcChwcm9zdGF0ZSRsY2F2b2xbaV0sMikseT1yZXAocHJvc3RhdGUkbHdlaWdodFtpXSwyKSx6PWMocHJvc3RhdGUkbHBzYVtpXSxsbVZXU19JbnRWVyRmaXRbaV0pLGNvbD1jKCJkYXJrYmx1ZSIsInJlZCIpW2FzLmRvdWJsZShwcm9zdGF0ZSRzdmkpW2ldXSxhZGQ9VFJVRSxsdHk9MikKCnoucHJlZDNEIDwtIG91dGVyKHgucHJlZCwgeS5wcmVkLCBmdW5jdGlvbih4LHkpIHtsbVZXU19JbnRWVyRjb2VmWzFdK2xtVldTX0ludFZXJGNvZWZbMl0qeCtsbVZXU19JbnRWVyRjb2VmWzNdKnkrbG1WV1NfSW50VlckY29lZls1XSp4Knl9KQp4LnByZWQzRCA8LSBvdXRlcih4LnByZWQseS5wcmVkLGZ1bmN0aW9uKHgseSkgeCkKeS5wcmVkM0QgPC0gb3V0ZXIoeC5wcmVkLHkucHJlZCxmdW5jdGlvbih4LHkpIHkpCnN1cmYzRCh4LnByZWQzRCx5LnByZWQzRCx6LnByZWQzRCxjb2w9ImJsdWUiLGZhY2V0cz1OQSxhZGQ9VFJVRSkKYGBgCgojIEFub3ZhIHRhYmVsIGVuIGFhbnZ1bGxlbmRlIGt3YWRyYXRlbnNvbW1lbj8KCkJlc2Nob3V3IGRlIHZvbGdlbmRlIHR3ZWUgKipnZW5lc3RlKiogcmVncmVzc2llbW9kZWxsZW4gdm9vciBwcmVkaWN0b3JlbiAkeF8xLCBcbGRvdHMsIHhfe3Ata30kIGVuICR4XzEsIFxsZG90cywgeF97cC0xfSQ6CiQkCiAgWV9pID0gXGJldGFfMCtcYmV0YV8xIHhfe2kxfSArIC4uLiArIFxiZXRhX3twLWt9IHhfe2lwLWt9ICArIFxlcHNpbG9uX2ksCiQkCm1ldCAkXGVwc2lsb25faVx0ZXh0eyBpaWQgfSBOKDAsXHNpZ21hXzFeezJ9KSQsIGVuCiQkCllfaSA9IFxiZXRhXzArXGJldGFfMSB4X3tpMX0gKyAuLi4gKyBcYmV0YV97cC0xfSB4X3tpcC0xfSAgKyBcZXBzaWxvbl9pLAokJAptZXQgJFxlcHNpbG9uX2lcdGV4dHsgaWlkIH0gTigwLFxzaWdtYV8yXnsyfSkkLgoKVm9vciBoZXQgZWVyc3RlIChnZXJlZHVjZWVyZGUpIG1vZGVsIGdlbGR0IGRlIGRlY29tcG9zaXRpZQpcWwogIFx0ZXh0e1NTVG90fSA9IFx0ZXh0e1NTUn1fMSArIFx0ZXh0e1NTRX1fMQpcXQplbiB2b29yIGhldCB0d2VlZGUgKG5pZXQtZ2VyZWR1Y2VlcmRlKSBtb2RlbApcWwogIFx0ZXh0e1NTVG90fSA9IFx0ZXh0e1NTUn1fMiArIFx0ZXh0e1NTRX1fMgpcXQooU1NUb3QgaXMgdWl0ZXJhYXJkIGRlemVsZmRlIGluIGJlaWRlIG1vZGVsbGVuIG9tZGF0IGRpdCBuaWV0IGFmaGFuZ3QgdmFuIGhldCByZWdyZXNzaWVtb2RlbCkuCgpcWwogIFx0ZXh0e1NTVG90fSA9IFx0ZXh0e1NTUn1fezIgXG1pZCAxfSArIFx0ZXh0e1NTUn1fMSArIFx0ZXh0e1NTRX1fMgpcXQoKXFsKRiA9IFxmcmFje1x0ZXh0e1NTUn1fezIgXG1pZCAxfX17XHRleHR7U1NFfV8yfQpcXQoKLSBUZXN0ZW4gdm9vciBhbGxlIG5pdmVhdXMgdmFuIGVlbiBmYWN0b3Igc2ltdWx0YWFuOiBvbW5pYnVzIHRlc3QuCi0gVGVzdGVuIHZvb3IgdG90YWxlIGVmZmVjdCB2YW4gZWVuIHByZWRpY3RvcjogaG9vZmRlZmZlY3RlbiArIGludGVyYWN0aWVzCi0gLi4uCgojIERpYWdub3N0aWVrCgojIyBNdWx0aWNvbGxpbmVhcml0ZWl0CgpcW1x0ZXh0cm17VklGfV9qPVxsZWZ0KDEtUl9qXjJccmlnaHQpXnstMX1cXQoKIyMjIEJvZHkgZmF0IHZvb3JiZWVsZAoKYGBge3Igb3V0LndpZHRoPSc5MCUnLCBmaWcuYXNwPS44LCBmaWcuYWxpZ249J2NlbnRlcicsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0KYm9keWZhdCA8LSByZWFkX2RlbGltKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdG9taWNzL3NiYzIwL21hc3Rlci9kYXRhL2JvZHlmYXQudHh0IixkZWxpbT0iICIpCmJvZHlmYXQgJT4lIGdncGFpcnMoKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CmxtRmF0IDwtIGxtKAogIEJvZHlfZmF0IH4KICAgIFRyaWNlcHMgKwogICAgVGhpZ2ggKwogICAgTWlkYXJtLAogIGRhdGEgPSBib2R5ZmF0KQoKc3VtbWFyeShsbUZhdCkKYGBgCgpgYGB7cn0KdmlmKGxtRmF0KQpgYGAKCgpgYGB7ciBlY2hvPUZBTFNFfQpsbU1pZGFybSA8LSBsbSgKICBNaWRhcm0gfgogICAgVHJpY2VwcyArCiAgICBUaGlnaCwKICAgIGRhdGEgPSBib2R5ZmF0KQoKc3VtbWFyeShsbU1pZGFybSkKYGBgCgojIyBJbnZsb2Vkcmlqa2UgT2JzZXJ2YXRpZXMKCiMjIyBFeHBsb3JhdGllZgoKLSAqU3R1ZGVudGl6ZWQgcmVzaWR1J3MqIG9tIG91dGxpZXJzIG9wIHRlIHNwb3JlbgotICpsZXZlcmFnZSAoaW52bG9lZCwgaGVmYm9vbSkqIG9tIG9ic2VydmF0aWVzIG1ldCBleHRyZWVtIGNvdmFyaWFhdHBhdHJvb24gb3AgdGUgc3BvcmVuLiBFeHRyZW1lIGxldmVyYWdlOiBsZXZlcmFnZSB3YWFyZGUgZ3JvdGVyIGRhbiAgMnAvbgoKYGBge3J9CnBsb3QobG1WV1MsNSkKYGBgCgojIyMgQ29va3MgZGlzdGFuY2UKClxbRF9pPVxmcmFje1xzdW1fe2o9MX1ebihcaGF0e1l9X2otXGhhdHtZfV97aihpKX0pXjJ9e3BcdGV4dHJte01TRX19XF0KCi0gRXh0cmVtZSBDb29rJ3MgZGlzdGFuY2UgYWxzIGhldCBoZXQgNTBcJSBwZXJjZW50aWVsIHZhbiBkZSAkRl97cCxuLXB9JC12ZXJkZWxpbmcgb3ZlcnNjaHJpamR0LgoKYGBge3J9CnBsb3QobG1WV1MsNCkKYGBgCgojIyMgREZCRVRBUwoKJCRcdGV4dHJte0RGQkVUQVN9X3tqKGkpfT1cZnJhY3tcaGF0e1xiZXRhfV97an0tXGhhdHtcYmV0YX1fe2ooaSl9fXtcdGV4dHJte1NEfShcaGF0e1xiZXRhfV97an0pfSQkCi0gIERGQkVUQVMgZXh0cmVlbSBpcyB3YW5uZWVyIHplIDEgb3ZlcnNjaHJpamR0IGluIGtsZWluZSB0b3QgbWlkZGVsZ3JvdGUgZGF0YXNldHMgZW4gJDIvXHNxcnR7bn0kIGluIGdyb3RlIGRhdGFzZXRzCgpgYGB7ciBvdXQud2lkdGg9JzkwJScsIGZpZy5hc3A9LjgsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0KcGFyKG1mcm93PWMoMiwyKSkKZGZiZXRhc1Bsb3RzKGxtVldTKQpgYGAKCgojIENvbnRyYXN0ZW4KCiMjIEJsb2VkZHJ1ayB2b29yYmVlbGQKCmBgYHtyfQpsaWJyYXJ5KE5IQU5FUykKYnBEYXRhIDwtIE5IQU5FUyAlPiUKZmlsdGVyKAogIFJhY2UxID09IldoaXRlIiAmCiAgICBBZ2UgPj0gMTggJgogICAgIWlzLm5hKEJQU3lzQXZlKQogICAgKQoKbUJwMSA8LSBsbShCUFN5c0F2ZSB+IEFnZSpHZW5kZXIsIGJwRGF0YSkKcGFyKG1mcm93ID0gYygyLDIpKQpwbG90KG1CcDEpCmBgYAoKIyMjIFJlbWVkaWVyaW5nIGhldGVyb3NjZWRhc3RpY2l0ZWl0CgpJbGx1c3RyYXRpZTogQmlqIGdyb3RlIHN0ZWVrcHJvZXZlbiBrdW5uZW4gd2UgY29ycmlnZXJlbiB2b29yIGhldGVyb3NjZWRhc3RpY2l0ZWl0LgoKYGBge3J9Cm1TZCA8LSBsbShtQnAxJHJlcyAlPiUgYWJzIH4gbUJwMSRmaXR0ZWQpCmBgYAoKV2Ugc2NoYXR0ZW4gaGV0IG1vZGVsIG51IG9wbmlldXc6CgpgYGB7cn0KbUJwMyA8LSBsbShCUFN5c0F2ZSB+IEFnZSpHZW5kZXIsIGJwRGF0YSwgdyA9IDEvbVNkJGZpdHRlZF4yKQpgYGAKCiMjIyBCZXNsdWl0dm9ybWluZwoKCkRlIG9uZGVyem9la3N2cmFnZW4gdmVydGFsZW4gemljaCBpbiBkZSB2b2xnZW5kZSBudWxsaHlwb3RoZXNlczoKCjEuIEFzc29jaWF0aWUgdHVzc2VuIGJsb2VkZHJ1ayBlbiBsZWVmdGlqZCBiaWogZGUgdnJvdXdlbj8gXFtIXzA6IFxiZXRhX1x0ZXh0e0FnZX0gPSAwIFx0ZXh0eyB2cyB9IEhfMTogXGJldGFfXHRleHR7QWdlfSBcbmVxIDAgXF0KCjIuIEFzc29jaWF0aWUgdHVzc2VuIGJsb2VkZHJ1ayBlbiBsZWVmdGlqZCBiaWogZGUgbWFubmVuPyBcW0hfMDogXGJldGFfXHRleHR7QWdlfSArIFxiZXRhX1x0ZXh0e0FnZTpHZW5kZXJtYWxlfSA9IDAgXHRleHR7IHZzIH0gSF8xOiBcYmV0YV9cdGV4dHtBZ2V9ICsgXGJldGFfXHRleHR7QWdlOkdlbmRlcm1hbGV9IFxuZXEgMCBcXQoKMy4gSXMgZGUgQXNzb2NpYXRpZSB0dXNzZW4gYmxvZWRkcnVrIGVuIGxlZWZ0aWpkIHZlcnNjaGlsbGVuZCBiaWogbWFubmVuIGVuIHZyb3V3ZW4/IFxbSF8wOiBcYmV0YV9cdGV4dHtBZ2U6R2VuZGVybWFsZX0gPSAwIFx0ZXh0eyB2cyB9IEhfMTogXGJldGFfXHRleHR7QWdlOkdlbmRlcm1hbGV9IFxuZXEgMCBcXQoKCi0gV2Uga3VubmVuIG9uZGVyem9la3N2cmFhZyAxIGVuIDMgb25taWRkZWxpamsgdG9ldHNlbiBvLmIudi4gZGUgbW9kZWwgb3V0cHV0LgoKLSBPbmRlcnpvZWtzdnJhYWcgMiBpcyBlY2h0ZXIgZWVuIGxpbmVhaXJlIGNvbWJpbmF0aWUgdmFuIHR3ZWUgcGFyYW1ldGVycy4KClxbClxiZWdpbnthcnJheX17bGNsfQpMIFxib2xkc3ltYm9se1xiZXRhfSAmPSYgMFxcXFwKXGxlZnRbXGJlZ2lue2FycmF5fXtjY2NjfSAwICYwJiAxJiAxXGVuZHthcnJheX0gXHJpZ2h0XVxsZWZ0W1xiZWdpbnthcnJheX17Y31cYmV0YV8wXFwKXGJldGFfZ1xcClxiZXRhX2FcXApcYmV0YV97YTpnfVxlbmR7YXJyYXl9ClxyaWdodF0gJj0mICAwXFxcXAowXGJldGFfMCArIDAgXGJldGFfZyArIDEgXGJldGFfYSArIDFcYmV0YV97YTpnfSAmPSYgMFxcXFwKXGJldGFfYSArIFxiZXRhX3thOmd9ICY9JjAKXGVuZHthcnJheX0KXF0KCi0gQm92ZW5kaWVuIGlzIGVyIG9vayBoZXQgcHJvYmxlZW0gZGF0IHdlIG1lZXJkZXJlIHRvZXRzZW4gbm9kaWcgaGViYmVuIG9tIGRlIGFzc29jaWF0aWVzIHRlIGJlc3R1ZGVyZW4uCgoKMS4gIFdlIHRvZXRzZW4gZWVyc3RlIGRlIG9tbmlidXMgaHlwb3RoZXNlIGRhdCBlciBnZWVuIGFzc29jaWF0aWUgaXMgdHVzc2VuIGxlZWZ0aWpkIGVuIGRlIGJsb2VkZHJ1ay4KCiQkCkhfMDogXGJldGFfXHRleHR7QWdlfSA9IFxiZXRhX1x0ZXh0e0FnZX0gKyBcYmV0YV9cdGV4dHtBZ2U6R2VuZGVybWFsZX0gPSBcYmV0YV9cdGV4dHtBZ2U6R2VuZGVybWFsZX0gPSAwCiQkCgogIC0gRGF0IHZlcmVlbnZvdWRpZ3QgemljaCB0b3QgaGV0IHRvZXRzZW4gZGF0CiQkIAogICAgSF8wOiBcYmV0YV9cdGV4dHtBZ2V9ID0gXGJldGFfXHRleHR7QWdlOkdlbmRlcm1hbGV9ID0gMAokJAogICAgCiAgLSBXYXQgd2Uga3VubmVuIGV2YWx1ZXJlbiBkb29yIHR3ZWUgbW9kZWxsZW4gdGUgdmVyZ2VsaWprZW4uIEVlbiBtb2RlbCBtZXQgZW5rZWwgaGV0IGdlbmRlciBlZmZlY3QgZW4gdm9sbGVkaWdlIG1vZGVsIG1ldCBHZW5kZXIsIEFnZSBlbiBHZW5kZXIgeCBBZ2UgaW50ZXJhY3RpZS4KCjIuIEFscyB3ZSBkZXplIGh5cG90aGVzZSBrdW5uZW4gdmVyd2VycGVuIHZvZXJlbiB3ZSBwb3N0aG9jIGFuYWx5c2VzIHVpdCB2b29yIGVsayB2YW4gZGUgMyBjb250cmFzdGVuLgoKCmBgYHtyfQptQnAwIDwtIGxtKEJQU3lzQXZlIH4gR2VuZGVyLCBicERhdGEsIHcgPSAxL21TZCRmaXR0ZWReMikKYW5vdmEobUJwMCwgbUJwMykKYGBgICAKCkRlIHBvc3Rob2MgdGVzdGVuIGt1bm5lbiB3ZSBvcG5pZXV3IHVpdHZvZXJlbiBhLmQuaC52LiBoZXQgbXVsdGNvbXAgcGFra2V0LgoKYGBge3J9CmJwUG9zdGhvYyA8LSBnbGh0KG1CcDMsIGxpbmZjdD1jKAogICJBZ2UgPSAwIiwKICAiQWdlICsgQWdlOkdlbmRlcm1hbGUgPSAwIiwKICAiQWdlOkdlbmRlcm1hbGUgPSAwIikKICApCmJwUG9zdGhvYyAlPiUgc3VtbWFyeQoKYnBQb3N0aG9jQkkgPC0gYnBQb3N0aG9jICU+JSBjb25maW50CmJwUG9zdGhvY0JJCmBgYAoKIyMjIENvbmNsdXNpZQoKV2Uga3VubmVuIGJlc2x1aXRlbiBkYXQgZXIgZWVuIGV4dHJlZW0gc2lnbmlmaWNhbnRlIGFzc29jaWF0aWUgaXMgdHVzc2VuIGxlZWZ0aWpkIGVuIGRlIGJsb2VkZHJ1ayAocCA8PCAwLjAwMSkuCkRlIGJsb2VkZHJ1ayBiaWogdHdlZSB2cm91d2VuIGRpZSBpbiBsZWVmdGlqZCB2ZXJzY2hpbGxlbiBpcyBnZW1pZGRlbGQgYHIgcm91bmQoYnBQb3N0aG9jQkkkY29uZmludFsxLDFdLDIpYCBtbSBIZyBob2dlciBwZXIgamFhciBsZWVmdGlqZHN2ZXJzY2hpbCBiaWogZGUgb3Vkc3RlIHZyb3V3IGVuIGRhdCB2ZXJzY2hpbCBpcyBleHRyZWVtIHNpZ25pZmljYW50IChwIDw8IDAuMDAxLCA5NSUgQkkgW2ByIHBhc3RlKHJvdW5kKGJwUG9zdGhvY0JJJGNvbmZpbnRbMSwtMV0sMiksY29sbGFwc2U9IiwgIilgXSkuCkRlIGJsb2VkZHJ1ayBiaWogbWFubmVuIGRpZSBpbiBsZWVmdGlqZCB2ZXJzY2hpbGxlbiBpcyBnZW1pZGRlbGQgYHIgcm91bmQoYnBQb3N0aG9jQkkkY29uZmludFsyLDFdLDIpYCBtbSBIZyBob2dlciBwZXIgamFhciBsZWVmdGlqZHN2ZXJzY2hpbCBiaWogZGUgb3VkZXJlIG1hbi4gKHAgPDwgMC4wMDEsIDk1JSBCSSBbYHIgcGFzdGUocm91bmQoYnBQb3N0aG9jQkkkY29uZmludFsyLC0xXSwyKSxjb2xsYXBzZT0iLCAiKWBdKS4KSGV0IGdlbWlkZGVsZGUgYmxvZWRkcnVrdmVyc2NoaWwgdHVzc2VuIHBlcnNvbmVuIGluIGxlZWZ0aWpkIHZlcnNjaGlsbGVuIGlzIGdlbWlkZGVsZCBgciBhYnMocm91bmQoYnBQb3N0aG9jQkkkY29uZmludFszLDFdLDIpKWAgbW0gSGcvamFhciBsYWdlciBiaWogbWFubmVuIGRhbiB2cm91d2VuIChwIDw8IDAuMDAxLCA5NSUgQkkgW2ByIHBhc3RlKHJvdW5kKGJwUG9zdGhvY0JJJGNvbmZpbnRbMywtMV0sMiksY29sbGFwc2U9IiwgIilgXSkuICAKCiMjIE1hcmdpbmFsZSBlZmZlY3RlbgoKV2F0IGRvZW4gd2UgYWxzIGludGVyYWN0aWVzIG5pZXQgc2lnbmlmaWNhbnQgemlqbj8KCi0gQ29udmVudGlvbmVsZSBhYW5wYWs6IGludGVyYWN0aWVzIHVpdCBtb2RlbCBoYWxlbgotIERhYXJuYSBzY2hhdHRlbiB3ZSBkZSBob29mZGVmZmVjdGVuIG1ldCB2ZXJlZW52b3VkaWdkIG1vZGVsCgpNZXJrIG9wIGRhdAoKMS4gV2UgYmlqIGNvbXBsZXhlIG1vZGVsbGVuIHZlZWwgdGVzdGVuIHVpdHZvZXJlbiBvbSB0b3QgaGV0IHZlcmVlbnZvdWRpZ2QgbW9kZWwgdGUga29tZW4uCjIuIEhldCBhYW52YWFyZGVuIHZhbiBkZSBudWxoeXBvdGhlc2VzIGVlbiB6d2Fra2UgY29uY2x1c2llIGlzIGVuIGRhdCBlciB0eXBpc2NoIHdlaW5pZyBwb3dlciBpcyBvbSBlZW4gaW50ZXJhY3RpZSBvcCB0ZSBwaWtrZW4uIEhldCBpcyBkdXMgbW9nZWxpamsgZGF0IGhldCBtb2RlbCB6b25kZXIgaW50ZXJhY3RpZXMgdG9jaCBoZXQgZm91dGlldmUgbW9kZWwgaXMuCjMuIEJpaiBoaWdoIHRyb3VnaHB1dCBleHBlcmltZW50ZW4gZ2FhbiB3ZSB0eXBpc2NoIGluZmVyZW50aWUgZG9lbiB2b29yIGFsbGUgZ2VuZW4vcHJvdGVpbmVuIGRpZSB3ZSBtZXRlbiAodmIuIDQwMDAwIGdlbmVuIG9mIDEwMDBkZW4gcHJvdGXDr25lbikuIERvb3IgZ3JvdGUgY29ycmVjdGllIHZvb3IgbXVsdGlwbGUgdGVzdGluZyBrdW5uZW4gd2UgaW50ZXJhY3RpZSB0ZXJtZW4gbmlldCB3ZWdsYXRlbiB3YW50IGRhYXIgd2V0ZW4gd2UgemVrZXIgZGF0IGRlIHBvd2VyIG9tIGludGVyYWN0aWVzIG9wIHRlIHBpa2tlbiB6ZWVyIGxhYWcuCgpPbXdpbGxlIHZhbiBkZXplIHJlZGVuZW4ga3VubmVuIHdlIG9vayBkZSBpbnRlcmFjdGllcyBpbiBoZXQgbW9kZWwgbGF0ZW4gZW4gaW5mZXJlbnRpZSBkb2VuIG92ZXIgZGUgbWFyZ2luYWxlIGVmZmVjdGVuLgoKLSBEZSBlZmZlY3RlbiB3YWFyYmlqIHdlIHVpdG1pZGRlbGVuIG92ZXIgYWxsZSBwcmVkaWN0b3J3YWFyZGVuIHZhbiBkZSBhbmRlcmUgcHJlZGljdG9yZW4uCi0gSW4gZWVuIGdlcmFuZG9taXNlZXJkZSBvYnNlcnZhdGlvbmVsZSBzdHVkaWUgenVsbGVuIHdlIHpvIGR1cyBkZSBhc3NvY2F0aWUgc2NoYXR0ZW4gdm9vciBkZSBnZW1pZGRlbGRlIHBhdGnDq250IGluIGRlIHBvcHVsYXRpZS4KCi0gWmllIG9lZmVuaW5nZW46IHZpc3NlbiBlbiBrcG5hMgoKCiMjIyBUZXN0b3N0ZXJvbiBjb25jZW50cmF0aWUgYmlqIHZvbHdhc3NlbiBtYW5uZW4gaW4gZGUgTkhBTkVTIHN0dWRpZQoKVmVyb25kZXJzdGVsIGRhdCB3ZSB3ZW5zZW4gdGUgYmVzdHVkZXJlbiBvZiBlciBlZW4gYXNzb2NpYXRpZSBpcyBsZWVmdGlqZCBlbiBnZXdpY2h0IHZhbiB2b2x3YXNzZW4gbWFubmVuIGluIGRlIEFtZXJpa2FhbnNlIHBvcHVsYXRpZSBvcCBkZSBkZSB0ZXN0b3N0ZXJvbiBjb25jZW50cmF0aWUuIAoKYGBge3J9Cm1vZFRlcyA8LSBsbShmb3JtdWxhID0gVGVzdG9zdGVyb25lIH4gQWdlICogV2VpZ2h0LCBkYXRhID0gTkhBTkVTICU+JSAKICAgIGZpbHRlcihBZ2UgPiAxOCAmIEdlbmRlciA9PSAibWFsZSIgJiAhaXMubmEoVGVzdG9zdGVyb25lKSAmIWlzLm5hKFdlaWdodCkgJiAhaXMubmEoQWdlKSkpCnBsb3QobW9kVGVzKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KG1vZFRlcykKYGBgCgotIEVyIGlzIGdlZW4gc2lnbmlmaWNhbnRlIGludGVyYWN0aWUuIEhldCBhYW52YWFyZGVuIHZhbiBkZSBudWxoeXBvdGhlc2UgaXMgZWVuIHp3YWtrZSBjb25jbHVzaWUuCkRhYXJvbSBrdW5uZW4gd2Ugb3B0ZXJlbiBvbSBkZSBpbnRlcmFjdGllIGluIGhldCBtb2RlbCB0ZSBsYXRlbi4KCi0gTWVyayBvcCBkYXQgZGUgaG9vZmRlZmZlY3RlbiBnZWVuIHppbnZvbGxlIGludGVycHJldGF0aWUgaGViYmVuIQoKLSBPbWRhdCBlciBnZWVuIHNpZ25pZmljYW50ZSBpbnRlcmFjdGllIGlzLCBpcyBoZXQgemludm9sIG9tIGVlbiB1aXRzcHJhYWsgdGUgZG9lbiBvdmVyIGRlIGFzc29jaWF0aWUgdmFuIGdld2ljaHQgZW4gdGVzdG9zdGVyb24sIGVuIGxlZWZ0aWpkIGVuIHRlc3Rvc3Rlcm9uLgoKV2Uga3VubmVuIGhpZXJvdmVyIGVlbiB1aXRzcHJhYWsgZG9lbiBkb29yIHRlIG1hcmdpbmFsaXNlcmVuIG92ZXIgYWxsZSBsZWVmdGlqZGVuIChnZXdpY2h0ZW4pIHZhbiBkZSBtYW5uZW4gaW4gaGV0IGV4cGVyaW1lbnQuCgokJApcZnJhY3tcc3VtXGxpbWl0c197aT0xfV5uIChcYmV0YV9hICsgXGJldGFfe3c6YX0gWF97d30pfXtufT0gXGJldGFfYSArXGJldGFfe3c6YX0gXGJhcntYfV93CiQkCgokJApcZnJhY3tcc3VtXGxpbWl0c197aT0xfV5uIChcYmV0YV93ICsgXGJldGFfe3c6YX0gWF97YX0pfXtufT0gXGJldGFfdyArXGJldGFfe3c6YX0gXGJhcntYfV9hCiQkCgoKCgpgYGB7cn0KTkhBTkVTICU+JSAKICBmaWx0ZXIoQWdlID4gMTggJiBHZW5kZXIgPT0gIm1hbGUiICYgIWlzLm5hKFRlc3Rvc3Rlcm9uZSkgJiFpcy5uYShXZWlnaHQpICYgIWlzLm5hKEFnZSkpICAlPiUgCiAgcHVsbChXZWlnaHQpICU+JQogIG1lYW4gJT4lIAogIHJvdW5kKC4sMSkKYGBgCgpgYGB7cn0KTkhBTkVTICU+JSAKICBmaWx0ZXIoQWdlID4gMTggJiBHZW5kZXIgPT0gIm1hbGUiICYgIWlzLm5hKFRlc3Rvc3Rlcm9uZSkgJiFpcy5uYShXZWlnaHQpICYgIWlzLm5hKEFnZSkpICAlPiUgCiAgcHVsbChBZ2UpICU+JQogIG1lYW4gJT4lIAogIHJvdW5kKC4sMSkKYGBgCgpXZSBldmFsdWVyZW4gbnUgaGV0IGNvbnRyYXN0IHZvb3IgZGUgbWFyZ2luYWxlIGVmZmVjdGVuOgoKYGBge3J9Cm1hcmdpbmFsRWZmZWN0cyA8LSBnbGh0KAogIG1vZFRlcywgCiAgbGluZmN0ID0gYygKICAgICJBZ2UgKzg4LjkqQWdlOldlaWdodD0gMCIsCiAgICAiV2VpZ2h0ICs0Ni40KkFnZTpXZWlnaHQ9IDAiCiAgICApCiAgKQpzdW1tYXJ5KG1hcmdpbmFsRWZmZWN0cykKY29uZmludChtYXJnaW5hbEVmZmVjdHMpCmBgYAoKCkRpdCBoZWVmdCBlZW4gaW50ZXJwcmV0YXRpZSB2YW4gaGV0IGdlbWlkZGVsZGUgbGVlZnRpamRzLSBlbiBkZSBnZW1pZGRlbGRlIGdld2ljaHRzYXNzb2NpYXRpZSBpbiBkZSBwb3B1bGF0aWUuIAoKVm9sZ2VucyBkZSBjb252ZW50aW9uZWxlIGFhbnBhayBoYWRkZW4gd2UgZGUgaW50ZXJhY3RpZSB1aXQgaGV0IG1vZGVsIHZlcndpamRlcmQuIAoKYGBge3J9Cm1vZEFkZFRlcyA8LSBsbShmb3JtdWxhID0gVGVzdG9zdGVyb25lIH4gQWdlICsgV2VpZ2h0LCBkYXRhID0gCiAgICBOSEFORVMgJT4lIAogICAgZmlsdGVyKEFnZSA+IDE4ICYgR2VuZGVyID09ICJtYWxlIiAmICFpcy5uYShUZXN0b3N0ZXJvbmUpICYhaXMubmEoV2VpZ2h0KSAmICFpcy5uYShBZ2UpKSkKc3VtbWFyeShtb2RBZGRUZXMpCmBgYAoKTWVyayBvcCBkYXQgZGUgc2NoYXR0aW5nZW4gdWl0IGhldCBhZGRpdGllZiBtb2RlbCBsaWNodGplcyB2ZXJzY2hpbGxlbmQgemlqbiBvbWRhdCBkZSBkYXRhIG5pZXQgZ2ViYWxhbmNlZXJkIHppam4sIHdlIGhlYmJlbiBuaWV0IGRlemVsZmRlIGdld2ljaHRlbiB2b29yIGFsbGUgbGVlZnRpamRlbiBlbiBuaWV0IGRlemVsZmRlIGxlZWZ0aWpkZW4gdm9vciBhbGxlIGdld2ljaHRlbi4KCmBgYHtyfQpOSEFORVMgJT4lIAogICAgZmlsdGVyKEFnZSA+IDE4ICYgR2VuZGVyID09ICJtYWxlIiAmICFpcy5uYShUZXN0b3N0ZXJvbmUpICYhaXMubmEoV2VpZ2h0KSAmICFpcy5uYShBZ2UpKSAlPiUgCiAgZ2dwbG90KGFlcyhBZ2UsV2VpZ2h0KSkgKwogIGdlb21fcG9pbnQoKQpgYGAKCiMgRmFjdG9yacOrbGUgcHJvZXZlbiAKCiMjIERhdGEgCgoKNDggcmF0dGVuIHdlcmRlbiBhdCByYW5kb20gdG9lZ2V3ZXplbiBhYW4KCi0gMyBnaWZmZW4gKEksSUksSUlJKSBhbmQgCi0gNCBiZWhhbmRlbGluZ2VuIChBLEIsQyxEKSwgCgplbiwgCgotIGRlIG92ZXJsZXZpbmdzdGlqZCB3ZXJkIG9wZ2VtZXRlbiAoZWVuaGVpZDogMTAgaCkKCldlIHRyYW5zZm9ybWVyZW4gZGUgZGF0YSBlZXJzdCBuYWFyIHVyZW4KCmBgYHtyfQpkYXRhKHJhdHMscGFja2FnZSA9ICJmYXJhd2F5IikKCnJhdHMgPC0gcmF0cyAlPiUgCiAgbXV0YXRlKHRpbWU9dGltZSAqIDEwKQoKcmF0cyAlPiUgCiAgZ2dwYWlycygpCmBgYAoKYGBge3J9CnJhdHMgJT4lCiAgZ2dwbG90KGFlcyh4PXRyZWF0LHk9dGltZSkpICsgCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGU9TkEpICsgCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZmFjZXRfd3JhcCh+cG9pc29uKSArCiAgeWxhYigidGltZSAoaCkiKQpgYGAKCmBgYHtyfQpyYXRzICU+JQogIGdncGxvdChhZXMoeD10cmVhdCx5PTEvdGltZSkpICsgCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGU9TkEpICsgCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZmFjZXRfd3JhcCh+cG9pc29uKSArIAogIHlsYWIgKCJyYXRlIG9mIGR5aW5nICgxL2gpIikKCnJhdHMzIDwtIGxtKDEvdGltZX5wb2lzb24qdHJlYXQsIHJhdHMpCmBgYAoKV2UgbW9kZWxsZXJlbiBkZSAic25lbGhlaWQgdmFuIHN0ZXJ2ZW4iIG1ldCBlZW4gaG9vZmRlZmZlY3Qgdm9vciBnaWYgZW4gYmVoYW5kZWxpbmcgZW4gZWVuIGdpZiAkXHRpbWVzJCBiZWhhbmRlbGluZyBpbnRlcmFjdGllLiAKCiQkClxiZWdpbnthcnJheX17bGNsfQp5X2kgJj0mIFxiZXRhXzAgICsgXFwKJiZcYmV0YV97SUl9IHhfe2lJSX0gKyBcYmV0YV97SUlJfSB4X3tpSUlJfSArIFxcCiYmIFxiZXRhX3tCfSB4X3tpQn0gICsgXGJldGFfe0N9IHhfe2lDfSArIFxiZXRhX3tEfSB4X3tpRH0gKyBcXAomJlxiZXRhX3tJSTpCfXhfe2lJSX14X3tpQn0gKyBcYmV0YV97SUk6Q314X3tpSUl9eF97aUN9ICArIFxiZXRhX3tJSTpEfXhfe2lJSX14X3tpRH0gKyBcXAomJlxiZXRhX3tJSUk6Qn14X3tpSUlJfXhfe2lCfSArIFxiZXRhX3tJSUk6Q314X3tpSUlJfXhfe2lDfSAgKyBcYmV0YV97SUlJOkR9eF97aUlJSX14X3tpRH0gKwpcZXBzaWxvbl9pClxlbmR7YXJyYXl9CiQkCgptZXQgJGkgPSAxLCBcbGRvdHMsIG4kLCAkbj00OCQsIGVuLCAkeF97aUlJfSQsICR4X3tpSUlJfSQsICR4X3tpQn0kLCAkeF97aUN9JCBlbiAkeF97aUR9JCBkdW1teSB2YXJpYWJlbGVuIHZvb3IgcmVzcGVjdGlldmVsaWprIGdpZiBJSSwgSUlJLCBiZWhhbmRlbGluZyBCLCBDLCBlbiBELgoKIyMgSW5mZXJlbnRpZQoKCmBgYHtyfSAKRXhwbG9yZU1vZGVsTWF0cml4OjpWaXN1YWxpemVEZXNpZ24ocmF0cyx+cG9pc29uKnRyZWF0KSRwbG90CmBgYAoKRWVuIGludGVyYWN0aWUgdHVzc2VuIGdpZiBlbiBiZWhhbmRlbGluZyBpbXBsaWNlZXJ0IGRhdCB3ZSBoZXQgZWZmZWN0IHZhbiBoZXQgdHlwZSBnaWYgYWZ6b25kZXJsaWprIG1vZXRlbiBiZXN0dWRlcmVuIHZvb3IgZWxrZSBiZWhhbmRlbGluZzogCgoxLiBWb29yIGJlaGFuZGVsaW5nIEEgbW9ldGVuIHdlIGRhbiB2b2xnZW5kZSBudWxoeXBvdGhlc2VzIHRvZXRzZW46CgotIElJLUk6ICRIXzA6IFxiZXRhX3tJSX09MCQKLSBJSUktSTogJEhfMDogXGJldGFfe0lJSX09MCQKLSBJSUktSUk6ICRIXzA6IFxiZXRhX3tJSUl9LVxiZXRhX3tJSX09MCQKCjIuIFZvb3IgYmVoYW5kZWxpbmcgQjoKCi0gSUktSTogJEhfMDogXGJldGFfe0lJfStcYmV0YV97SUk6Qn09MCQKLSBJSUktSTogJEhfMDogXGJldGFfe0lJSX0rXGJldGFfe0lJSTpCfT0wJAotIElJSS1JSTogJEhfMDogXGJldGFfe0lJSX0rXGJldGFfe0lJSTpCfS1cYmV0YV97SUl9LVxiZXRhX3tJSTpCfT0wJAoKMy4gVm9vciBiZWhhbmRlbGluZyBDOgoKLSBJSS1JOiAkSF8wOiBcYmV0YV97SUl9K1xiZXRhX3tJSTpDfT0wJAotIElJSS1JOiAkSF8wOiBcYmV0YV97SUlJfStcYmV0YV97SUlJOkN9PTAkCi0gSUlJLUlJOiAkSF8wOiBcYmV0YV97SUlJfStcYmV0YV97SUlJOkN9LVxiZXRhX3tJSX0tXGJldGFfe0lJOkN9PTAkCgo0LiBWb29yIGJlaGFuZGVsaW5nIEQ6CgotIElJLUk6ICRIXzA6IFxiZXRhX3tJSX0rXGJldGFfe0lJOkR9PTAkCi0gSUlJLUk6ICRIXzA6IFxiZXRhX3tJSUl9K1xiZXRhX3tJSUk6RH09MCQKLSBJSUktSUk6ICRIXzA6IFxiZXRhX3tJSUl9K1xiZXRhX3tJSUk6RH0tXGJldGFfe0lJfS1cYmV0YV97SUk6RH09MCQKCkhldHplbGZkZSBnZWxkdCB3YW5uZWVyIHdlIGhldCBlZmZlY3QgdmFuIGRlIGJlaGFuZGVsaW5nIGJlc3R1ZGVyZW46IAoKMS4gVm9vciBnaWYgSSB0b2V0c2VuIHdlIGRhbiBudWxoeXBvdGhlc2UKCi0gQi1BOiAkSF8wOiBcYmV0YV97Qn09MCQKLSBDLUE6ICRIXzA6IFxiZXRhX3tDfT0wJAotIEQtQTogJEhfMDogXGJldGFfe0R9PTAkCi0gQy1COiAkSF8wOiBcYmV0YV97Q30tXGJldGFfe0J9PTAkCi0gRC1COiAkSF8wOiBcYmV0YV97RH0tXGJldGFfe0J9PTAkCi0gRC1DOiAkSF8wOiBcYmV0YV97RH0tXGJldGFfe0N9PTAkCgoyLiBHaWYgSUkKCi0gQi1BOiAkSF8wOiBcYmV0YV97Qn0rXGJldGFfe0lJOkJ9PTAkCi0gQy1BOiAkSF8wOiBcYmV0YV97Q30rXGJldGFfe0lJOkN9PTAkCi0gRC1BOiAkSF8wOiBcYmV0YV97RH0rXGJldGFfe0lJOkR9PTAkCi0gQy1COiAkSF8wOiBcYmV0YV97Q30rXGJldGFfe0lJOkN9LVxiZXRhX3tCfS1cYmV0YV97SUk6Qn09MCQKLSBELUI6ICRIXzA6IFxiZXRhX3tEfStcYmV0YV97SUk6RH0tXGJldGFfe0J9LVxiZXRhX3tJSTpCfT0wJAotIEQtQzogJEhfMDogXGJldGFfe0R9K1xiZXRhX3tJSTpEfS1cYmV0YV97Q30tXGJldGFfe0lJOkN9PTAkCgozLiBHaWYgSUlJCgotIEItQTogJEhfMDogXGJldGFfe0J9K1xiZXRhX3tJSUk6Qn09MCQKLSBDLUE6ICRIXzA6IFxiZXRhX3tDfStcYmV0YV97SUlJOkN9PTAkCi0gRC1BOiAkSF8wOiBcYmV0YV97RH0rXGJldGFfe0lJOkR9PTAkCi0gQy1COiAkSF8wOiBcYmV0YV97Q30rXGJldGFfe0lJSTpDfS1cYmV0YV97Qn0tXGJldGFfe0lJSTpCfT0wJAotIEQtQjogJEhfMDogXGJldGFfe0R9K1xiZXRhX3tJSUk6RH0tXGJldGFfe0J9LVxiZXRhX3tJSUk6Qn09MCQKLSBELUM6ICRIXzA6IFxiZXRhX3tEfStcYmV0YV97SUlJOkR9LVxiZXRhX3tDfS1cYmV0YV97SUlJOkN9PTAkCgoKYGBge3J9CmxpYnJhcnkoY2FyKQpBbm92YShyYXRzMywgdHlwZT0iSUlJIikKYGBgCgpJbiBvbnplIHN0dWRpZSB3YXMgZGUgaW50ZXJhY3RpZSBlY2h0ZXIgbmlldCBzaWduaWZpY2FudC4gSGV0IGVmZmVjdCB2YW4gaGV0IGdpZiAoSUktSSwgSUlJLUkgZW4gSUlJLSBJSSkgdmVyYW5kZXJ0IGR1cyBuaWV0IHNpZ25pZmljYW50IHZvbGdlbnMgZGUgYmVoYW5kZWxpbmcgKEEsIEIsIEMsIGVuIEQpIGVuIHZpY2UgdmVyc2EuIFZvb3Igb256ZSBkYXRhc2V0IGxpamt0IGhldCBkdXMgemludm9sIG9tIAoKMS4gZGUgZWZmZWN0Z3Jvb3R0ZSB2b29yIGRlIHBhaXJzZ2V3aWp6ZSB2ZXJnZWxpamtpbmdlbiB0dXNzZW4gZGUgdmVyc2NoaWxsZW5kZSBnaWZmZW4gKElJLUksIElJSS1JIGVuIElJSS0gSUkpIHRlIHNjaGF0dGVuIGRvb3IgemUgdWl0IHRlIG1pZGRlbGVuIG92ZXIgYWxsZSBiZWhhbmRlbGluZ2VuIChBLCBCLCBDLCBlbiBEKSwgZW4sIAoyLiAgZGUgZWZmZWN0Z3Jvb3R0ZSB2b29yIGRlIHBhaXJzZ2V3aWp6ZSB2ZXJnZWxpamtpbmdlbiB0dXNzZW4gZGUgdmVyc2NoaWxsZW5kZSBiZWhhbmRlbGluZ2VuIChCLUEsIEMtQSwgRC1BLCBDLUIsIEQtQiBlbiBELUMpIHRlIHNjaGF0dGVuIGRvb3IgemUgdWl0IHRlIG1pZGRlbGVuIG92ZXIgYWxsZSBnaWZmZW4gKEksIElJLCBJSUkpLiAKCkRhdCB6b3Ugb25zIGdlbGlqa2FhcmRpZ2Ugc2NoYXR0aW5nZW4gdmFuIGRlIGVmZmVjdGdyb290dGVzIG1vZXRlbiBnZXZlbiBhbHMgZGV6ZSB2b29yIGhldCBhZGRpdGlldmUgbW9kZWwgd2FhcmJpaiB3ZSBkZSBpbnRlcmFjdGllIHRlcm0gdWl0IGhldCBtb2RlbCBoYWRkZW4gZ2V3ZWVyZC4gCgoKQi52LiB2b29yIGdpZiBJSUkgdnMgZ2lmIElJIHpvdSBkYXQgaW4gdm9sZ2VuZGUgY29udHJhc3QgcmVzdWx0ZXJlbjogCgotIElJSS1JSTogCiQkSF8wOiAKXGJlZ2lue2FycmF5fXtsfQpcZnJhY3tcYmV0YV97SUlJfS1cYmV0YV97SUl9fXs0fSArIFxcClxxdWFkIFxmcmFje1xiZXRhX3tJSUl9ICsgXGJldGFfe0lJSTpCfS1cYmV0YV97SUl9IC0gXGJldGFfe0lJOkJ9fXs0fSArIFxcClxxdWFkIFxxdWFkIFxmcmFje1xiZXRhX3tJSUl9ICsgXGJldGFfe0lJSTpDfS1cYmV0YV97SUl9IC0gXGJldGFfe0lJOkN9fXs0fSArIFxcClxxdWFkIFxxdWFkIFxxdWFkIFxmcmFje1xiZXRhX3tJSUl9ICsgXGJldGFfe0lJSTpEfS1cYmV0YV97SUl9IC0gXGJldGFfe0lJOkR9fXs0fT0wClxlbmR7YXJyYXl9CiQkCiQkCkhfMDpcYmV0YV97SUlJfSArIFxmcmFjezF9ezR9IFx0aW1lcyBcYmV0YV97SUlJOkJ9ICsgIFxmcmFjezF9ezR9IFx0aW1lc1xiZXRhX3tJSUk6Q30gKyAgXGZyYWN7MX17NH0gXHRpbWVzXGJldGFfe0lJSTpEfQotXGJldGFfe0lJfSAtIFxmcmFjezF9ezR9IFx0aW1lc1xiZXRhX3tJSTpCfSAtICBcZnJhY3sxfXs0fSBcdGltZXNcYmV0YV97SUk6Q30gIC0gXGZyYWN7MX17NH0gXHRpbWVzXGJldGFfe0lJOkR9PTAKJCQKCldlIHNjaGF0dGVuIG1ldCBvbmRlcnN0YWFuZGUgY29kZSBhbGxlIGdlbWlkZGVsZGUgY29udHJhc3RlbiBhLmQuaC52LiBoZXQgbW9kZWwgbWV0IGludGVyYWN0aWUuCgpgYGB7cn0KY29udHJhc3RzIDwtIGMoCiAgInBvaXNvbklJICsgMS80KnBvaXNvbklJOnRyZWF0QiArIDEvNCpwb2lzb25JSTp0cmVhdEMgKyAxLzQqcG9pc29uSUk6dHJlYXREID0gMCIsCiAgInBvaXNvbklJSSArIDEvNCpwb2lzb25JSUk6dHJlYXRCICsgMS80KnBvaXNvbklJSTp0cmVhdEMgKyAxLzQqcG9pc29uSUlJOnRyZWF0RD0gMCIsCiAgInBvaXNvbklJSSArIDEvNCpwb2lzb25JSUk6dHJlYXRCICsgMS80KnBvaXNvbklJSTp0cmVhdEMgKyAxLzQqcG9pc29uSUlJOnRyZWF0RCAtIHBvaXNvbklJIC0gMS80KnBvaXNvbklJOnRyZWF0QiAtIDEvNCpwb2lzb25JSTp0cmVhdEMgLSAxLzQqcG9pc29uSUk6dHJlYXREID0gMCIsCiAgInRyZWF0QiArIDEvMypwb2lzb25JSTp0cmVhdEIgKyAxLzMqcG9pc29uSUlJOnRyZWF0QiA9IDAiLAogICJ0cmVhdEMgKyAxLzMqcG9pc29uSUk6dHJlYXRDICsgMS8zKnBvaXNvbklJSTp0cmVhdEMgPSAwIiwKICAidHJlYXREICsgMS8zKnBvaXNvbklJOnRyZWF0RCArIDEvMypwb2lzb25JSUk6dHJlYXREID0gMCIsCiAgInRyZWF0QyArIDEvMypwb2lzb25JSTp0cmVhdEMgKyAxLzMqcG9pc29uSUlJOnRyZWF0QyAtIHRyZWF0QiAtIDEvMypwb2lzb25JSTp0cmVhdEIgLSAxLzMqcG9pc29uSUlJOnRyZWF0QiA9IDAiLAogICJ0cmVhdEQgKyAxLzMqcG9pc29uSUk6dHJlYXREICsgMS8zKnBvaXNvbklJSTp0cmVhdEQgIC0gdHJlYXRCIC0gMS8zKnBvaXNvbklJOnRyZWF0QiAtIDEvMypwb2lzb25JSUk6dHJlYXRCID0gMCIsCiAgInRyZWF0RCArIDEvMypwb2lzb25JSTp0cmVhdEQgKyAxLzMqcG9pc29uSUlJOnRyZWF0RCAgLSB0cmVhdEMgLSAxLzMqcG9pc29uSUk6dHJlYXRDIC0gMS8zKnBvaXNvbklJSTp0cmVhdEMgPSAwIikgCgoKY29tcGFyaXNvbnNJbnQyIDwtIGdsaHQocmF0czMsIGxpbmZjdCA9IGNvbnRyYXN0cwopCnBsb3QoY29tcGFyaXNvbnNJbnQyLHlheHQ9Im5vbmUiKQpjb250cmFzdE5hbWVzIDwtIGMoIklJLUkiLCJJSUktSSIsIklJSS1JSSIsIkItQSIsIkMtQSIsIkQtQSIsIkMtQiIsIkQtQiIsIkQtQyIpCmF4aXMoMixhdD1jKGxlbmd0aChjb250cmFzdE5hbWVzKToxKSwgbGFiZWxzPWNvbnRyYXN0TmFtZXMsbGFzPTIpCmBgYAoKCiMjIENvbmNsdXNpZSAKCkVyIGlzIGVlbiBleHRyZWVtIHNpZ25pZmljYW50IGVmZmVjdCB2YW4gaGV0IHR5cGUgZ2lmIGVuIGRlIGJlaGFuZGVsaW5nIG9wIGRlIHNuZWxoZWlkIHZhbiBzdGVydmVuIGJpaiByYXR0ZW4gKHAgPDwgMC4wMDEpLgoKRGUgaW50ZXJhY3RpZSB0dXNzZW4gZ2lmIGVuIGJlaGFuZGVsaW5nIGlzIG5pZXQgc2lnbmlmaWNhbnQgKHAgPSBgciAgQW5vdmEocmF0czMsdHlwZT0iSUlJIilbInBvaXNvbjp0cmVhdCIsIlByKD5GKSJdICU+JSByb3VuZCgzKWApLiAKCkRlIHNuZWxoZWlkIHZhbiBzdGVydmVuIGlzIGdlbWlkZGVsZCBgciBjb25maW50KGNvbXBhcmlzb25zSW50MikkY29uZmludFtjb250cmFzdE5hbWVzPT0iSUlJLUkiLDFdICU+JSByb3VuZCgyKWBoJF57LTF9JCAgZW4gYHIgY29uZmludChjb21wYXJpc29uc0ludDIpJGNvbmZpbnRbY29udHJhc3ROYW1lcz09IklJSS1JSSIsMV0gJT4lIHJvdW5kKDIpYGgkXnstMX0kIGhvZ2VyIHZvb3IgcmF0dGVuIGRpZSBibG9vdGdlc3RlbGQgd29yZGVuIGFhbiBnaWYgSUlJIGRhbiBhYW4gcmVzcGVjdGlldmVsaWprIGdpZiBJIGVuIElJIChiZWlkZSBwIDw8IDAuMDAxLCA5NSUgQkkgSUlJLUk6IFtgciBwYXN0ZShyb3VuZChjb25maW50KGNvbXBhcmlzb25zSW50MikkY29uZmludFtjb250cmFzdE5hbWVzPT0iSUlJLUkiLC0xXSwyKSxjb2xsYXBzZT0iLCAiKWBdaCReey0xfSQsIDk1JSBCSSBJSUktSUk6IFtgciBwYXN0ZShyb3VuZChjb25maW50KGNvbXBhcmlzb25zSW50MikkY29uZmludFtjb250cmFzdE5hbWVzPT0iSUlJLUlJIiwtMV0sMiksY29sbGFwc2U9IiwgIilgXWgkXnstMX0kKQpEZSBnZW1pZGRlbGRlIHNuZWxoZWlkIHZhbiBzdGVydmVuIHdhcyBuaWV0IHNpZ25pZmljYW50IHZlcnNjaGlsbGVuZCB0dXNzZW4gcmF0dGVuIGRpZSB3ZXJkZW4gYmxvb3RnZXN0ZWxkIGFhbiBnaWYgSSBlbiBnaWYgSUkgKHA9YHIgcm91bmQoc3VtbWFyeShjb21wYXJpc29uc0ludDIpJHRlc3QkcHZhbHVlc1tjb250cmFzdE5hbWVzPT0iSUktSSJdLDMpYCkuCgpEZSBzbmVsaGVpZCB2YW4gc3RlcnZlbiBpcyBnZW1pZGRlbGQgYHIgY29uZmludChjb21wYXJpc29uc0ludDIpJGNvbmZpbnRbY29udHJhc3ROYW1lcz09IkItQSIsMV0gJT4lIHJvdW5kKDIpICU+JSBhYnNgaCReey0xfSQgZW4gYHIgY29uZmludChjb21wYXJpc29uc0ludDIpJGNvbmZpbnRbY29udHJhc3ROYW1lcz09IkQtQSIsMV0gJT4lIHJvdW5kKDIpJT4lIGFic2BoJF57LTF9JCBob2dlciBuYSBiZWhhbmRlbGluZyBBIGRhbiBuYSBiZWhhbmRlbGluZyBCIGVuIEQgKHAgPDwgMC4wMDEsIDk1JSBCSSBCLUE6IFtgciBwYXN0ZShyb3VuZChjb25maW50KGNvbXBhcmlzb25zSW50MikkY29uZmludFtjb250cmFzdE5hbWVzPT0iQi1BIiwtMV0sMiksY29sbGFwc2U9IiwgIilgXWgkXnstMX0kLCA5NSUgQkkgRC1BOiBbYHIgcGFzdGUocm91bmQoY29uZmludChjb21wYXJpc29uc0ludDIpJGNvbmZpbnRbY29udHJhc3ROYW1lcz09IkQtQSIsLTFdLDIpLGNvbGxhcHNlPSIsICIpYF1oJF57LTF9JCkuIApEZSBzbmVsaGVpZCB2YW4gc3RlcnZlbiBpcyBnZW1pZGRlbGQgYHIgY29uZmludChjb21wYXJpc29uc0ludDIpJGNvbmZpbnRbY29udHJhc3ROYW1lcz09IkMtQiIsMV0gJT4lIHJvdW5kKDIpYGgkXnstMX0kIGVuIGByIGNvbmZpbnQoY29tcGFyaXNvbnNJbnQyKSRjb25maW50W2NvbnRyYXN0TmFtZXM9PSJELUMiLDFdICU+JSByb3VuZCgyKSAlPiUgYWJzYGgkXnstMX0kIGhvZ2VyIG5hIGJlaGFuZGVsaW5nIEMgZGFuIHJlc3BlY3RpZXZlbGlqayBuYSBiZWhhbmRlbGluZyBCIGVuIEQgKEMtQjogcCA8PCAwLjAwMSwgOTUlIENJIFtgciBwYXN0ZShyb3VuZChjb25maW50KGNvbXBhcmlzb25zSW50MikkY29uZmludFtjb250cmFzdE5hbWVzPT0iQy1CIiwtMV0sMiksY29sbGFwc2U9IiwgIilgXWgkXnstMX0kICwgRC1DOiBwID0gYHIgc3VtbWFyeShjb21wYXJpc29uc0ludDIpJHRlc3QkcHZhbHVlc1tjb250cmFzdE5hbWVzPT0iRC1DIl0gJT4lIHJvdW5kKDMpYCwgOTUlIENJIFtgciBwYXN0ZShyb3VuZChjb25maW50KGNvbXBhcmlzb25zSW50MikkY29uZmludFtjb250cmFzdE5hbWVzPT0iRC1DIiwtMV0sMiksY29sbGFwc2U9IiwgIilgXWgkXnstMX0kKS4gCkRlIGdlbWlkZGVsZGUgc25lbGhlaWQgdmFuIHN0ZXJ2ZW4gaXMgbmlldCBzaWduaWZpY2FudCB2ZXJzY2hpbGxlbmQgdHVzc2VuIHJhdHRlbiBiZWhhbmRlbGQgbWV0IGJlaGFuZGVsaW5nIEMgdnMgQSwgZW4gRCB2cyBCIChwLSB3YWFyZGVuIHJlc3BlY3RpZXZlbGlqayBwID0gYHIgc3VtbWFyeShjb21wYXJpc29uc0ludDIpJHRlc3QkcHZhbHVlc1tjb250cmFzdE5hbWVzPT0iQy1BIl0gJT4lIHJvdW5kKDMpYCBlbiBwID0gYHIgc3VtbWFyeShjb21wYXJpc29uc0ludDIpJHRlc3QkcHZhbHVlc1tjb250cmFzdE5hbWVzPT0iRC1CIl0gJT4lIHJvdW5kKDMpYCkuCgpBbGxlIHAtd2FhcmRlbiB3ZXJkZW4gZ2Vjb3JyaWdlZXJkIHZvb3IgbWVlcnZvdWRpZyB0ZXN0ZW4uIAo=