1 Achtergrond

Resistentie tegen het gif EI-43,064 wordt getest bij 96 vissen (dojovissen (0), goudvissen (1) en zebravissen (2)). Elke vis wordt apart in een aquarium gestopt die een bepaalde dosis (in mg) van het gif bevat. Naast de overlevingstijd in minuten (de uitkomst, minsurv) werd ook het gewicht van de vis gemeten (in gram). De onderzoekers weten uit vorige experimenten dat de overlevingstijd vaak sterk afhangt van het gewicht en dat de resistentie dikwijls soortafhankelijk is. De onderzoekers wensen inzicht te krijgen in het effect van de dosis en het gewicht van de vis op de overlevingstijd en of resistentie tegen het gif verschillend is bij de verschillende soorten.

1.1 Laad de libraries

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
#install.packages("GGally")
library(GGally)
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
library(car)
## Loading required package: carData
## 
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
## 
##     recode
library(multcomp)
## Loading required package: mvtnorm
## Loading required package: survival
## Loading required package: TH.data
## Loading required package: MASS
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
## 
##     select
## 
## Attaching package: 'TH.data'
## The following object is masked from 'package:MASS':
## 
##     geyser

2 Data-exploratie

Lees de dataset poison.dat in via read.table. We zagen in de voorgaande practica al dat de overlevingstijd beter op log2-schaal wordt gemodelleerd.

poison <- read.table("https://raw.githubusercontent.com/statOmics/statistiekBasisCursusData/master/practicum8/poison.dat", sep="", header = TRUE)

# We vormen de vissoort om in een factor en log2 transformeren de overlevingstijd
poison <- poison %>%
  mutate(soort = as.factor(soort),
         log2minsurv = log2(minsurv))

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

  • De overlevingstijd lijkt geassocieerd met het gewicht, soort en de dosis.

  • We observeren een sterke positieve associatie tussen de log2-overlevingstijd en het gewicht.

  • Bij lage gewichten lijkt de log2-overlevingstijd wat af te vlakken.

  • Daarnaast zien we ook dat het gewicht niet gelijk verdeeld is binnen elke dosis.

  • Er lijkt ook een associatie tussen de gewicht en soort.

We bestuderen de effecten verder:

Geef een scatterplot voor de log2-overlevingstijd ten opzichte van de dosis, voor elke soort apart. Trek ook een best passende rechte door elke figuur. Wat kan je opmerken over de log2-overlevingstijd in functie van de dosis? Verschilt de invloed van de dosis op de log2-overlevingstijd tussen de soorten?

scatterplot1<-poison%>% ggplot(aes(x=dosis, y=log2minsurv))+
  geom_point()+
  stat_smooth(method="lm")+
  facet_wrap(~soort)
scatterplot1
## `geom_smooth()` using formula = 'y ~ x'

De plot toont geen sterk verschil van het effect van de dosis op de log2-overlevingstijd tussen de verschillende vissoorten. We zullen hiervoor tijdens de statistische inferentie een statistische test uitvoeren.

Geef een scatterplot voor de log2-overlevingstijd ten opzichte van het gewicht, voor elke soort apart. Trek ook een best passende rechte door elke figuur. Wat kan je opmerken over de log2-overlevingstijd in functie van het gewicht? Verschilt de invloed van het gewicht op de log2-overlevingstijd tussen de soorten?

scatterplot2<-poison%>% ggplot(aes(x=gewicht, y=log2minsurv))+
  geom_point()+
  stat_smooth(method="lm")+
  facet_wrap(~soort)
scatterplot2
## `geom_smooth()` using formula = 'y ~ x'

De plot suggereert een verschil in het effect van gewicht op de log2-overlevingstijd tussen de verschillende vissoorten. Opnieuw zullen we via een statistische test nagaan of dit verschil statistisch significant is.

Gezien de onderzoekers op basis van voorgaande studies vermoeden dat het effect van de dosis kan variƫren van soort tot soort zouden we in de modellen interacties moeten voorzien tussen dosis en soort, zodat elke soort een verschillende dosisrespons kan tonen. Aangezien we in de data ook zien dat de invloed van het gewicht op de log2-overlevingstijd lijkt te verschillen tussen de soorten voegen we deze ook toe aan het model. Ten slotte voegen we ook de interactie tussen gewicht en dosis toe.

We bekomen dus het onderstaande model: \[ y_i=\beta_0+\beta_d x_{id} + \beta_g x_{ig} +\beta_{sg} x_{isg} +\beta_{sz} x_{isz} + \beta_{d:sg} x_{id}x_{isg} + \beta_{d:sz} x_{id}x_{isz} + \beta_{g:sg} x_{ig}x_{isg} + \beta_{g:sz} x_{ig}x_{isz} + \beta_{d:g} x_{id}x_{ig} + \epsilon_i, \]

met \(y_i\) de log2 overlevingstijd, \(x_{id}\) de dosis en \(x_{ig}\) het gewicht van vis \(i\). \(x_{isg}\) is een dummy-variabele die aangeeft of vis \(i\) een goudvis is en \(x_{isz}\) een dummy-variabele die aangeeft of de vis een zebravis is. De referentieklasse is dus voor de soort dojovissen (als \(x_{isg}=0\) en \(x_{isz}=0\)). Verder is \(\epsilon_i \text{ i.i.d. } N(0,\sigma^2)\).

Modelleer de log2-overlevingstijd in functie van de soort, de dosis en het gewicht van de vis. Neem al de tweeweg-interacties mee in het model. Ga de voorwaarden van het lineaire model na.

lmInt <- lm(log2minsurv~ soort + dosis + gewicht + soort:dosis + soort:gewicht + 
              dosis:gewicht,
            data = poison)
plot(lmInt)

Zijn al de assumpties van het lineaire model voldaan?

De QQ-plot suggereert mogelijks lichte afwijkingen van normaliteit. Er zijn echter veel observaties waardoor we kunnen aannemen dat de gemiddelden approximatief normaal verdeeld zullen zijn. Bovendien zijn de afwijkingen symmetrisch. Voor symmetrische distributies convergeert de verdeling van de parameterschatters sneller naar de normale verdeling en kunnen we de centrale limietstelling sneller toepassen.

Verder tonen we via simulatie aan dat de afwijkingen in de QQ-plot vallen binnen hetgene we kunnen verwachten o.b.v. gegevens uit een normale verdeling. (Merk op dat orig slaat op de QQ-plot van de residuen voor het model met interacties)

set.seed(1025)
nobs <- nrow(poison)

data.frame(
  y = c(lmInt$res,
        rnorm(nobs*8,
              sd = sigma(lmInt)
             )
      ),
  label = rep(
              c("orig",
                paste0("sim",1:8)),
              each = nobs)) %>%
  ggplot(aes(sample = y)) +
  geom_qq() +
  geom_qq_line() +
  facet_wrap(~ label)

3 Model opstellen via de conventionele methode: testen van interacties en niet-significante interacties verwijderen uit het model

We testen nu via een anova-analyse met type III kwadratensommen of de interactietermen significant zijn. We verwijderen telkens de minst significante interactieterm zolang er niet-significante interactietermen zijn.

Merk op dat je nooit een hoofdeffect mag verwijderen zolang er interactietermen van dit hoofdeffect in het model zitten.

Merk verder op dat type III kwadratensommen niet kunnen verkregen worden via de standaard anova functie. De Anova functie uit het car package laat dat wel toe.

Anova(lmInt,type="III")

We zien dat zowel de interactie soort:dosis als dosis:gewicht niet significant zijn. We verwijderen eerst de minst significante interactieterm, namelijk soort:dosis.

Dit betekent dat het effect van de dosis op de log2-overlevingstijd (de helling) niet significant verschilt tussen de verschillende vissen. We voeren opnieuw een anova uit op het model zonder interactieterm soort:dosis.

lm_zonder_soort_dosis <- lm(log2minsurv~ soort + dosis + gewicht + soort:gewicht + dosis:gewicht ,data = poison)
Anova(lm_zonder_soort_dosis,type="III")

We zien dat de interactie tussen dosis en gewicht ook niet significant is. We verwijderen deze uit het model. Dit betekent dat het effect van de dosis (helling) op de log2-overlevingstijd niet significant verschilt bij een verschillend gewicht. We voeren opnieuw een anova uit op het resterende model.

lm_final <- lm(log2minsurv ~ soort + dosis + gewicht + soort:gewicht, data = poison)
Anova(lm_final,type="III")

We zien dat de interactieterm tussen soort en gewicht significant blijft. Dit komt overeen met wat we in de figuren bij de data exploratie hebben geobserveerd. Het effect van het gewicht (de helling) op de log2-overlevingstijd verschilt dus significant tussen de verschillende vissoorten op het 5% significantieniveau. We behouden deze interactieterm dus in het model. We bekomen dus het volgende model:

\[ y_i=\beta_0+\beta_d x_{id} + \beta_g x_{ig} +\beta_{sg} x_{isg} +\beta_{sz} x_{isz} + \beta_{g:sg} x_{ig}x_{isg} + \beta_{g:sz} x_{ig}x_{isz} + \epsilon_i \] Wat equivalent is aan \[ y_i=\beta_0 + \beta_{sg} x_{isg} +\beta_{sz} x_{isz} + \beta_d x_{id} + (\beta_g +\beta_{g:sg}x_{isg} + \beta_{g:sz}x_{isz})x_{ig} + \epsilon_i \]

Dit model zal eigenlijk drie regressievlakken opleveren: 1 voor dojovissen, 1 voor goudvissen en 1 voor zebravissen.

\[ \begin{array}{ll} \text{dojovis } (x_{isg}=0\text{ en }x_{isz}=0):&E[y\vert \text{dojovis}]=\beta_0 + \beta_d x_{id} + \beta_g x_{ig} \\ \text{goudvis } (x_{isg}=1\text{ en }x_{isz}=0):&E[y\vert \text{goudvis}]=\beta_0+\beta_{sg}+\beta_d x_{id} + (\beta_g+\beta_{g:sg}) x_{ig} \\ \text{zebravis } (x_{isg}=0\text{ en }x_{isz}=1):&E[y\vert \text{zebravis}]=\beta_0+\beta_{sz}+\beta_d x_{id} + (\beta_g+\beta_{g:sz}) x_{ig}\\ \end{array} \]

  • Het hoofdeffect voor soort zorgt dus dat elke soort een verschillend intercept van log2-overlevingstijd heeft (\(\beta_0\), \(\beta_0 + \beta_{sg}\), \(\beta_0+\beta_{sz}\) voor dojo-, goud- en zebravissen, respectievelijk).

  • De interactie tussen soort en gewicht zorgt ervoor dat het gewichtseffect (helling) verschillend kan zijn voor elke soort (\(\beta_g\), \(\beta_g+\beta_{g:sg}\), \(\beta_g+\beta_{g:sz}\) voor dojo-, goud- en zebravissen, respectievelijk).

  • Het dosiseffect (helling) blijft gelijk voor de verschillende vissen.

summary(lm_final)
## 
## Call:
## lm(formula = log2minsurv ~ soort + dosis + gewicht + soort:gewicht, 
##     data = poison)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.97719 -0.29105 -0.05937  0.29029  0.92184 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      0.6768     0.6130   1.104 0.272561    
## soort1          -0.3425     0.8390  -0.408 0.684099    
## soort2           1.6071     1.0055   1.598 0.113544    
## dosis           -0.8416     0.1215  -6.924 6.56e-10 ***
## gewicht          1.0657     0.2765   3.854 0.000219 ***
## soort1:gewicht   0.4844     0.3807   1.272 0.206550    
## soort2:gewicht  -0.9648     0.5505  -1.753 0.083108 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.4082 on 89 degrees of freedom
## Multiple R-squared:  0.7407, Adjusted R-squared:  0.7232 
## F-statistic: 42.37 on 6 and 89 DF,  p-value: < 2.2e-16

4 Testen van hypotheses

Ga met behulp van het opgestelde model volgende onderzoeksvragen na voor elke vissoort. Corrigeer hierbij voor multiple testing en controleer het experimentgewijs significantieniveau op 5%:

  • Is er een associatie tussen dosis en log2-overlevingstijd voor de verschillende vissoorten?
  • Is er een associatie tussen gewicht en log2-overlevingstijd voor de verschillende vissoorten?
  • Tussen welke vissoorten is er een verschil in associatie tussen dosis en log2-overlevingstijd?
  • Tussen welke vissoorten is er een verschil in associatie tussen gewicht en log2-overlevingstijd?
mcp <- glht(lm_final,linfct = c("dosis = 0", 
                                "gewicht = 0", 
                                "gewicht + soort1:gewicht = 0",
                                "gewicht + soort2:gewicht = 0",
                                "soort1:gewicht = 0",
                                "soort2:gewicht = 0",
                                "soort2:gewicht - soort1:gewicht = 0"))
summary(mcp)
## 
##   Simultaneous Tests for General Linear Hypotheses
## 
## Fit: lm(formula = log2minsurv ~ soort + dosis + gewicht + soort:gewicht, 
##     data = poison)
## 
## Linear Hypotheses:
##                                      Estimate Std. Error t value Pr(>|t|)    
## dosis == 0                            -0.8416     0.1215  -6.924  < 0.001 ***
## gewicht == 0                           1.0657     0.2765   3.854  0.00135 ** 
## gewicht + soort1:gewicht == 0          1.5501     0.2609   5.940  < 0.001 ***
## gewicht + soort2:gewicht == 0          0.1009     0.4767   0.212  0.99935    
## soort1:gewicht == 0                    0.4844     0.3807   1.272  0.64379    
## soort2:gewicht == 0                   -0.9648     0.5505  -1.753  0.33657    
## soort2:gewicht - soort1:gewicht == 0  -1.4492     0.5440  -2.664  0.04799 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## (Adjusted p values reported -- single-step method)
confints <- confint(mcp)
confints
## 
##   Simultaneous Confidence Intervals
## 
## Fit: lm(formula = log2minsurv ~ soort + dosis + gewicht + soort:gewicht, 
##     data = poison)
## 
## Quantile = 2.6488
## 95% family-wise confidence level
##  
## 
## Linear Hypotheses:
##                                      Estimate  lwr       upr      
## dosis == 0                           -0.841627 -1.163575 -0.519680
## gewicht == 0                          1.065692  0.333234  1.798150
## gewicht + soort1:gewicht == 0         1.550072  0.858873  2.241271
## gewicht + soort2:gewicht == 0         0.100860 -1.161748  1.363468
## soort1:gewicht == 0                   0.484380 -0.523979  1.492739
## soort2:gewicht == 0                  -0.964832 -2.422998  0.493334
## soort2:gewicht - soort1:gewicht == 0 -1.449212 -2.890275 -0.008149
2^confints$confint
##                                  Estimate       lwr       upr
## dosis                           0.5580138 0.4464051 0.6975266
## gewicht                         2.0931741 1.2598347 3.4777404
## gewicht + soort1:gewicht        2.9283180 1.8136212 4.7281352
## gewicht + soort2:gewicht        1.0724126 0.4469706 2.5730300
## soort1:gewicht                  1.3989844 0.6954512 2.8142268
## soort2:gewicht                  0.5123380 0.1864682 1.4076941
## soort2:gewicht - soort1:gewicht 0.3662214 0.1348778 0.9943675
## attr(,"conf.level")
## [1] 0.95
## attr(,"calpha")
## [1] 2.648792
2^-confints$confint
##                                  Estimate       lwr       upr
## dosis                           1.7920704 2.2401178 1.4336372
## gewicht                         0.4777433 0.7937550 0.2875430
## gewicht + soort1:gewicht        0.3414930 0.5513831 0.2114999
## gewicht + soort2:gewicht        0.9324769 2.2372835 0.3886468
## soort1:gewicht                  0.7148042 1.4379154 0.3553374
## soort2:gewicht                  1.9518365 5.3628443 0.7103816
## soort2:gewicht - soort1:gewicht 2.7305889 7.4141194 1.0056644
## attr(,"conf.level")
## [1] 0.95
## attr(,"calpha")
## [1] 2.648792

5 Conclusie

Er is een extreem significant effect van de dosis op de overlevingstijd (p << 0.001). De overlevingstijd van vissen die aan een hogere dosis van het gif worden blootgesteld neemt gemiddeld met een factor1.8 af per mg extra gif die wordt toegediend (95% BI [1.4, 2.2]). Het dosiseffect verschilt niet significant tussen de verschillende vissoorten op het 5% significantie-niveau.

Verder is er een sterk significante associatie is tussen gewicht en overlevingstijd bij zowel de dojovissen (contrast: gewicht == 0, p = 0.001) als de goudvissen (contrast: gewicht + soort1:gewicht == 0, p << 0.001). Voor vissen met een verschillend lichaamsgewicht is de overlevingstijd gemiddeld een factor 2.1 en 2.9 per gram lichaamsgewicht hoger voor de zwaardere vis bij respectievelijk dojo- en goudvissen (95% BI [1.3, 3.5] en [1.8, 4.7], respectievelijk). Voor de zebravissen (contrast: gewicht + soort2:gewicht == 0, p = 0.999) is er geen significante associatie tussen gewicht en overlevingstijd.

De associatie van gewicht en de log2-overlevingstijd is significant verschillend tussen zebravissen en goudvissen (contrast: soort2:gewicht - soort1:gewicht == 0, p= 0.0483). Bij zebravissen stijgt de overlevingstijd per gram extra gewicht met een factor 2.7 minder dan bij goudvissen (95% BI [1, 7.4]). De associatie van gewicht en de log2-overlevingstijd is niet significant verschillend tussen goudvissen en dojovissen (contrast: soort1:gewicht == 0, p = 0.64) en tussen zebravissen en dojovissen (contrast: soort2:gewicht == 0, p=0.34).

LS0tCnRpdGxlOiAiQWxnZW1lZW4gTGluZWFpciBNb2RlbDogbmlldC1hZGRpdGllZiBtZWVydm91ZGlnIGxpbmVhaXIgcmVncmVzc2llIG1vZGVsIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgICB0b2M6IHRydWUKICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleAogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwotLS0KCiMgQWNodGVyZ3JvbmQKClJlc2lzdGVudGllIHRlZ2VuIGhldCBnaWYgRUktNDMsMDY0IHdvcmR0IGdldGVzdCBiaWogOTYgdmlzc2VuIChkb2pvdmlzc2VuICgwKSwgZ291ZHZpc3NlbiAoMSkgZW4gemVicmF2aXNzZW4gKDIpKS4KRWxrZSB2aXMgd29yZHQgYXBhcnQgaW4gZWVuIGFxdWFyaXVtIGdlc3RvcHQgZGllIGVlbiBiZXBhYWxkZSBgZG9zaXNgIChpbiBtZykgdmFuIGhldCBnaWYgYmV2YXQuCk5hYXN0IGRlIG92ZXJsZXZpbmdzdGlqZCBpbiBtaW51dGVuIChkZSB1aXRrb21zdCwgYG1pbnN1cnZgKSB3ZXJkIG9vayBoZXQgYGdld2ljaHRgIHZhbiBkZSB2aXMgZ2VtZXRlbiAoaW4gZ3JhbSkuCkRlIG9uZGVyem9la2VycyB3ZXRlbiB1aXQgdm9yaWdlIGV4cGVyaW1lbnRlbiBkYXQgZGUgb3ZlcmxldmluZ3N0aWpkIHZhYWsgc3RlcmsgYWZoYW5ndCB2YW4gaGV0IGdld2ljaHQgZW4gZGF0IGRlIHJlc2lzdGVudGllIGRpa3dpamxzIHNvb3J0YWZoYW5rZWxpamsgaXMuCkRlIG9uZGVyem9la2VycyB3ZW5zZW4gaW56aWNodCB0ZSBrcmlqZ2VuIGluIGhldCBlZmZlY3QgdmFuIGRlIGRvc2lzIGVuIGhldCBnZXdpY2h0IHZhbiBkZSB2aXMgb3AgZGUgb3ZlcmxldmluZ3N0aWpkIGVuIG9mIHJlc2lzdGVudGllIHRlZ2VuIGhldCBnaWYgdmVyc2NoaWxsZW5kIGlzIGJpaiBkZSB2ZXJzY2hpbGxlbmRlIHNvb3J0ZW4uCgojIyBMYWFkIGRlIGxpYnJhcmllcwoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKI2luc3RhbGwucGFja2FnZXMoIkdHYWxseSIpCmxpYnJhcnkoR0dhbGx5KQpsaWJyYXJ5KGNhcikKbGlicmFyeShtdWx0Y29tcCkKYGBgCgojIERhdGEtZXhwbG9yYXRpZQoKTGVlcyBkZSBkYXRhc2V0IHBvaXNvbi5kYXQgaW4gdmlhIGByZWFkLnRhYmxlYC4KV2UgemFnZW4gaW4gZGUgdm9vcmdhYW5kZSBwcmFjdGljYSBhbCBkYXQgZGUgb3ZlcmxldmluZ3N0aWpkIGJldGVyIG9wIGxvZzItc2NoYWFsIHdvcmR0IGdlbW9kZWxsZWVyZC4KCmBgYHtyfQpwb2lzb24gPC0gcmVhZC50YWJsZSgiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3N0YXRPbWljcy9zdGF0aXN0aWVrQmFzaXNDdXJzdXNEYXRhL21hc3Rlci9wcmFjdGljdW04L3BvaXNvbi5kYXQiLCBzZXA9IiIsIGhlYWRlciA9IFRSVUUpCgojIFdlIHZvcm1lbiBkZSB2aXNzb29ydCBvbSBpbiBlZW4gZmFjdG9yIGVuIGxvZzIgdHJhbnNmb3JtZXJlbiBkZSBvdmVybGV2aW5nc3RpamQKcG9pc29uIDwtIHBvaXNvbiAlPiUKICBtdXRhdGUoc29vcnQgPSBhcy5mYWN0b3Ioc29vcnQpLAogICAgICAgICBsb2cybWluc3VydiA9IGxvZzIobWluc3VydikpCgpwb2lzb24gJT4lCiAgZ2dwYWlycwpgYGAKCi0gRGUgb3ZlcmxldmluZ3N0aWpkIGxpamt0IGdlYXNzb2NpZWVyZCBtZXQgaGV0IGdld2ljaHQsIHNvb3J0IGVuIGRlIGRvc2lzLgoKLSBXZSBvYnNlcnZlcmVuIGVlbiBzdGVya2UgcG9zaXRpZXZlIGFzc29jaWF0aWUgdHVzc2VuIGRlIGxvZzItb3ZlcmxldmluZ3N0aWpkIGVuIGhldCBnZXdpY2h0LgoKLSBCaWogbGFnZSBnZXdpY2h0ZW4gbGlqa3QgZGUgbG9nMi1vdmVybGV2aW5nc3RpamQgd2F0IGFmIHRlIHZsYWtrZW4uCgotIERhYXJuYWFzdCB6aWVuIHdlIG9vayBkYXQgaGV0IGdld2ljaHQgbmlldCBnZWxpamsgdmVyZGVlbGQgaXMgYmlubmVuIGVsa2UgZG9zaXMuCgotIEVyIGxpamt0IG9vayBlZW4gYXNzb2NpYXRpZSB0dXNzZW4gZGUgZ2V3aWNodCBlbiBzb29ydC4KCldlIGJlc3R1ZGVyZW4gZGUgZWZmZWN0ZW4gdmVyZGVyOgoKR2VlZiBlZW4gc2NhdHRlcnBsb3Qgdm9vciBkZSBsb2cyLW92ZXJsZXZpbmdzdGlqZCB0ZW4gb3B6aWNodGUgdmFuIGRlIGRvc2lzLCB2b29yIGVsa2Ugc29vcnQgYXBhcnQuIFRyZWsgb29rIGVlbiBiZXN0IHBhc3NlbmRlIHJlY2h0ZSBkb29yIGVsa2UgZmlndXVyLiBXYXQga2FuIGplIG9wbWVya2VuIG92ZXIgZGUgbG9nMi1vdmVybGV2aW5nc3RpamQgaW4gZnVuY3RpZSB2YW4gZGUgZG9zaXM/IFZlcnNjaGlsdCBkZSBpbnZsb2VkIHZhbiBkZSBkb3NpcyBvcCBkZSBsb2cyLW92ZXJsZXZpbmdzdGlqZCB0dXNzZW4gZGUgc29vcnRlbj8KCgpgYGB7cn0Kc2NhdHRlcnBsb3QxPC1wb2lzb24lPiUgZ2dwbG90KGFlcyh4PWRvc2lzLCB5PWxvZzJtaW5zdXJ2KSkrCiAgZ2VvbV9wb2ludCgpKwogIHN0YXRfc21vb3RoKG1ldGhvZD0ibG0iKSsKICBmYWNldF93cmFwKH5zb29ydCkKc2NhdHRlcnBsb3QxCmBgYAoKRGUgcGxvdCB0b29udCBnZWVuIHN0ZXJrIHZlcnNjaGlsIHZhbiBoZXQgZWZmZWN0IHZhbiBkZSBkb3NpcyBvcCBkZSBsb2cyLW92ZXJsZXZpbmdzdGlqZCAgdHVzc2VuIGRlIHZlcnNjaGlsbGVuZGUgdmlzc29vcnRlbi4gV2UgenVsbGVuIGhpZXJ2b29yIHRpamRlbnMgZGUgc3RhdGlzdGlzY2hlIGluZmVyZW50aWUgZWVuIHN0YXRpc3Rpc2NoZSB0ZXN0IHVpdHZvZXJlbi4KCkdlZWYgZWVuIHNjYXR0ZXJwbG90IHZvb3IgZGUgbG9nMi1vdmVybGV2aW5nc3RpamQgdGVuIG9wemljaHRlIHZhbiBoZXQgZ2V3aWNodCwgdm9vciBlbGtlIHNvb3J0IGFwYXJ0LiBUcmVrIG9vayBlZW4gYmVzdCBwYXNzZW5kZSByZWNodGUgZG9vciBlbGtlIGZpZ3V1ci4gV2F0IGthbiBqZSBvcG1lcmtlbiBvdmVyIGRlIGxvZzItb3ZlcmxldmluZ3N0aWpkIGluIGZ1bmN0aWUgdmFuIGhldCBnZXdpY2h0PyBWZXJzY2hpbHQgZGUgaW52bG9lZCB2YW4gaGV0IGdld2ljaHQgb3AgZGUgbG9nMi1vdmVybGV2aW5nc3RpamQgdHVzc2VuIGRlIHNvb3J0ZW4/CgpgYGB7cn0Kc2NhdHRlcnBsb3QyPC1wb2lzb24lPiUgZ2dwbG90KGFlcyh4PWdld2ljaHQsIHk9bG9nMm1pbnN1cnYpKSsKICBnZW9tX3BvaW50KCkrCiAgc3RhdF9zbW9vdGgobWV0aG9kPSJsbSIpKwogIGZhY2V0X3dyYXAofnNvb3J0KQpzY2F0dGVycGxvdDIKYGBgCgpEZSBwbG90IHN1Z2dlcmVlcnQgZWVuIHZlcnNjaGlsIGluIGhldCBlZmZlY3QgdmFuIGdld2ljaHQgb3AgZGUgbG9nMi1vdmVybGV2aW5nc3RpamQgdHVzc2VuIGRlIHZlcnNjaGlsbGVuZGUgdmlzc29vcnRlbi4gT3BuaWV1dyB6dWxsZW4gd2UgdmlhIGVlbiBzdGF0aXN0aXNjaGUgdGVzdCBuYWdhYW4gb2YgZGl0IHZlcnNjaGlsIHN0YXRpc3Rpc2NoIHNpZ25pZmljYW50IGlzLgoKR2V6aWVuIGRlIG9uZGVyem9la2VycyBvcCBiYXNpcyB2YW4gdm9vcmdhYW5kZSBzdHVkaWVzIHZlcm1vZWRlbiBkYXQgaGV0IGVmZmVjdCB2YW4gZGUgZG9zaXMga2FuIHZhcmnDq3JlbiB2YW4gc29vcnQgdG90IHNvb3J0IHpvdWRlbiB3ZSBpbiBkZSBtb2RlbGxlbiBpbnRlcmFjdGllcyBtb2V0ZW4gdm9vcnppZW4gdHVzc2VuIGRvc2lzIGVuIHNvb3J0LCB6b2RhdCBlbGtlIHNvb3J0IGVlbiB2ZXJzY2hpbGxlbmRlIGRvc2lzcmVzcG9ucyBrYW4gdG9uZW4uIEFhbmdlemllbiB3ZSBpbiBkZSBkYXRhIG9vayB6aWVuIGRhdCBkZSBpbnZsb2VkIHZhbiBoZXQgZ2V3aWNodCBvcCBkZSBsb2cyLW92ZXJsZXZpbmdzdGlqZCBsaWprdCB0ZSB2ZXJzY2hpbGxlbiB0dXNzZW4gZGUgc29vcnRlbiB2b2VnZW4gd2UgZGV6ZSBvb2sgdG9lIGFhbiBoZXQgbW9kZWwuIFRlbiBzbG90dGUgdm9lZ2VuIHdlIG9vayBkZSBpbnRlcmFjdGllIHR1c3NlbiBnZXdpY2h0IGVuIGRvc2lzIHRvZS4gCgpXZSBiZWtvbWVuIGR1cyBoZXQgb25kZXJzdGFhbmRlIG1vZGVsOgokJAp5X2k9XGJldGFfMCtcYmV0YV9kIHhfe2lkfSArIFxiZXRhX2cgeF97aWd9ICtcYmV0YV97c2d9IHhfe2lzZ30gK1xiZXRhX3tzen0geF97aXN6fSArIFxiZXRhX3tkOnNnfSB4X3tpZH14X3tpc2d9ICsgXGJldGFfe2Q6c3p9IHhfe2lkfXhfe2lzen0gKyBcYmV0YV97ZzpzZ30geF97aWd9eF97aXNnfSArIFxiZXRhX3tnOnN6fSB4X3tpZ314X3tpc3p9ICsgXGJldGFfe2Q6Z30geF97aWR9eF97aWd9ICsgXGVwc2lsb25faSwKJCQKCgptZXQgJHlfaSQgZGUgbG9nMiBvdmVybGV2aW5nc3RpamQsICR4X3tpZH0kIGRlIGRvc2lzIGVuICR4X3tpZ30kIGhldCBnZXdpY2h0IHZhbiB2aXMgJGkkLiAkeF97aXNnfSQgaXMgZWVuIGR1bW15LXZhcmlhYmVsZSBkaWUgYWFuZ2VlZnQgb2YgdmlzICRpJCBlZW4gZ291ZHZpcyBpcyBlbiAkeF97aXN6fSQgZWVuIGR1bW15LXZhcmlhYmVsZSBkaWUgYWFuZ2VlZnQgb2YgZGUgdmlzIGVlbiB6ZWJyYXZpcyBpcy4KRGUgcmVmZXJlbnRpZWtsYXNzZSBpcyBkdXMgdm9vciBkZSBzb29ydCBkb2pvdmlzc2VuIChhbHMgICR4X3tpc2d9PTAkIGVuICR4X3tpc3p9PTAkKS4KVmVyZGVyIGlzICRcZXBzaWxvbl9pIFx0ZXh0eyBpLmkuZC4gfSBOKDAsXHNpZ21hXjIpJC4KCgoKCk1vZGVsbGVlciBkZSBsb2cyLW92ZXJsZXZpbmdzdGlqZCBpbiBmdW5jdGllIHZhbiBkZSBzb29ydCwgZGUgZG9zaXMgZW4gaGV0IGdld2ljaHQgdmFuIGRlIHZpcy4gTmVlbSBhbCBkZSB0d2Vld2VnLWludGVyYWN0aWVzIG1lZSBpbiBoZXQgbW9kZWwuIEdhIGRlIHZvb3J3YWFyZGVuIHZhbiBoZXQgbGluZWFpcmUgbW9kZWwgbmEuCgoKYGBge3J9CgpsbUludCA8LSBsbShsb2cybWluc3Vydn4gc29vcnQgKyBkb3NpcyArIGdld2ljaHQgKyBzb29ydDpkb3NpcyArIHNvb3J0Omdld2ljaHQgKyAKICAgICAgICAgICAgICBkb3NpczpnZXdpY2h0LAogICAgICAgICAgICBkYXRhID0gcG9pc29uKQpwbG90KGxtSW50KQpgYGAKClppam4gYWwgZGUgYXNzdW1wdGllcyB2YW4gaGV0IGxpbmVhaXJlIG1vZGVsIHZvbGRhYW4/CgpEZSBRUS1wbG90IHN1Z2dlcmVlcnQgbW9nZWxpamtzIGxpY2h0ZSBhZndpamtpbmdlbiB2YW4gbm9ybWFsaXRlaXQuIEVyIHppam4gZWNodGVyIHZlZWwgb2JzZXJ2YXRpZXMgd2FhcmRvb3Igd2Uga3VubmVuIGFhbm5lbWVuIGRhdCBkZSBnZW1pZGRlbGRlbiBhcHByb3hpbWF0aWVmIG5vcm1hYWwgdmVyZGVlbGQgenVsbGVuIHppam4uIEJvdmVuZGllbiB6aWpuIGRlIGFmd2lqa2luZ2VuIHN5bW1ldHJpc2NoLiBWb29yIHN5bW1ldHJpc2NoZSBkaXN0cmlidXRpZXMgY29udmVyZ2VlcnQgZGUgdmVyZGVsaW5nIHZhbiBkZSBwYXJhbWV0ZXJzY2hhdHRlcnMgc25lbGxlciBuYWFyIGRlIG5vcm1hbGUgdmVyZGVsaW5nIGVuIGt1bm5lbiB3ZSBkZSBjZW50cmFsZSBsaW1pZXRzdGVsbGluZyBzbmVsbGVyIHRvZXBhc3Nlbi4KClZlcmRlciB0b25lbiB3ZSB2aWEgc2ltdWxhdGllIGFhbiBkYXQgZGUgYWZ3aWpraW5nZW4gaW4gZGUgUVEtcGxvdCB2YWxsZW4gYmlubmVuIGhldGdlbmUgd2Uga3VubmVuIHZlcndhY2h0ZW4gby5iLnYuIGdlZ2V2ZW5zIHVpdCBlZW4gbm9ybWFsZSB2ZXJkZWxpbmcuIChNZXJrIG9wIGRhdCBvcmlnIHNsYWF0IG9wIGRlIFFRLXBsb3QgdmFuIGRlIHJlc2lkdWVuIHZvb3IgaGV0IG1vZGVsIG1ldCBpbnRlcmFjdGllcykKCmBgYHtyfQpzZXQuc2VlZCgxMDI1KQpub2JzIDwtIG5yb3cocG9pc29uKQoKZGF0YS5mcmFtZSgKICB5ID0gYyhsbUludCRyZXMsCiAgICAgICAgcm5vcm0obm9icyo4LAogICAgICAgICAgICAgIHNkID0gc2lnbWEobG1JbnQpCiAgICAgICAgICAgICApCiAgICAgICksCiAgbGFiZWwgPSByZXAoCiAgICAgICAgICAgICAgYygib3JpZyIsCiAgICAgICAgICAgICAgICBwYXN0ZTAoInNpbSIsMTo4KSksCiAgICAgICAgICAgICAgZWFjaCA9IG5vYnMpKSAlPiUKICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHkpKSArCiAgZ2VvbV9xcSgpICsKICBnZW9tX3FxX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+IGxhYmVsKQpgYGAKCiMgTW9kZWwgb3BzdGVsbGVuIHZpYSBkZSBjb252ZW50aW9uZWxlIG1ldGhvZGU6IHRlc3RlbiB2YW4gaW50ZXJhY3RpZXMgZW4gbmlldC1zaWduaWZpY2FudGUgaW50ZXJhY3RpZXMgdmVyd2lqZGVyZW4gdWl0IGhldCBtb2RlbAoKV2UgdGVzdGVuIG51IHZpYSBlZW4gYW5vdmEtYW5hbHlzZSBtZXQgdHlwZSBJSUkga3dhZHJhdGVuc29tbWVuIG9mIGRlIGludGVyYWN0aWV0ZXJtZW4gc2lnbmlmaWNhbnQgemlqbi4gV2UgdmVyd2lqZGVyZW4gdGVsa2VucyBkZSBtaW5zdCBzaWduaWZpY2FudGUgaW50ZXJhY3RpZXRlcm0gem9sYW5nIGVyIG5pZXQtc2lnbmlmaWNhbnRlIGludGVyYWN0aWV0ZXJtZW4gemlqbi4gCgpNZXJrIG9wIGRhdCBqZSBub29pdCBlZW4gaG9vZmRlZmZlY3QgbWFnIHZlcndpamRlcmVuIHpvbGFuZyBlciBpbnRlcmFjdGlldGVybWVuIHZhbiBkaXQgaG9vZmRlZmZlY3QgaW4gaGV0IG1vZGVsIHppdHRlbi4gCgpNZXJrIHZlcmRlciBvcCBkYXQgdHlwZSBJSUkga3dhZHJhdGVuc29tbWVuIG5pZXQga3VubmVuIHZlcmtyZWdlbiB3b3JkZW4gdmlhIGRlIHN0YW5kYWFyZCBhbm92YSBmdW5jdGllLiBEZSBBbm92YSBmdW5jdGllIHVpdCBoZXQgY2FyIHBhY2thZ2UgbGFhdCBkYXQgd2VsIHRvZS4KCmBgYHtyfQpBbm92YShsbUludCx0eXBlPSJJSUkiKQpgYGAKCldlIHppZW4gZGF0IHpvd2VsIGRlIGludGVyYWN0aWUgc29vcnQ6ZG9zaXMgYWxzIGRvc2lzOmdld2ljaHQgbmlldCBzaWduaWZpY2FudCB6aWpuLiBXZSB2ZXJ3aWpkZXJlbiBlZXJzdCBkZSBtaW5zdCBzaWduaWZpY2FudGUgaW50ZXJhY3RpZXRlcm0sIG5hbWVsaWprIHNvb3J0OmRvc2lzLiAKCkRpdCBiZXRla2VudCBkYXQgaGV0IGVmZmVjdCB2YW4gZGUgZG9zaXMgb3AgZGUgbG9nMi1vdmVybGV2aW5nc3RpamQgKGRlIGhlbGxpbmcpIG5pZXQgc2lnbmlmaWNhbnQgdmVyc2NoaWx0IHR1c3NlbiBkZSB2ZXJzY2hpbGxlbmRlIHZpc3Nlbi4gV2Ugdm9lcmVuIG9wbmlldXcgZWVuIGFub3ZhIHVpdCBvcCBoZXQgbW9kZWwgem9uZGVyIGludGVyYWN0aWV0ZXJtIHNvb3J0OmRvc2lzLgoKYGBge3J9CmxtX3pvbmRlcl9zb29ydF9kb3NpcyA8LSBsbShsb2cybWluc3Vydn4gc29vcnQgKyBkb3NpcyArIGdld2ljaHQgKyBzb29ydDpnZXdpY2h0ICsgZG9zaXM6Z2V3aWNodCAsZGF0YSA9IHBvaXNvbikKQW5vdmEobG1fem9uZGVyX3Nvb3J0X2Rvc2lzLHR5cGU9IklJSSIpCmBgYAoKV2UgemllbiBkYXQgZGUgaW50ZXJhY3RpZSB0dXNzZW4gZG9zaXMgZW4gZ2V3aWNodCBvb2sgbmlldCBzaWduaWZpY2FudCBpcy4gV2UgdmVyd2lqZGVyZW4gZGV6ZSB1aXQgaGV0IG1vZGVsLiBEaXQgYmV0ZWtlbnQgZGF0IGhldCBlZmZlY3QgdmFuIGRlIGRvc2lzIChoZWxsaW5nKSBvcCBkZSBsb2cyLW92ZXJsZXZpbmdzdGlqZCBuaWV0IHNpZ25pZmljYW50IHZlcnNjaGlsdCBiaWogZWVuIHZlcnNjaGlsbGVuZCBnZXdpY2h0LiBXZSB2b2VyZW4gb3BuaWV1dyBlZW4gYW5vdmEgdWl0IG9wIGhldCByZXN0ZXJlbmRlIG1vZGVsLgoKYGBge3J9CmxtX2ZpbmFsIDwtIGxtKGxvZzJtaW5zdXJ2IH4gc29vcnQgKyBkb3NpcyArIGdld2ljaHQgKyBzb29ydDpnZXdpY2h0LCBkYXRhID0gcG9pc29uKQpBbm92YShsbV9maW5hbCx0eXBlPSJJSUkiKQpgYGAKCgpXZSB6aWVuIGRhdCBkZSBpbnRlcmFjdGlldGVybSB0dXNzZW4gc29vcnQgZW4gZ2V3aWNodCBzaWduaWZpY2FudCBibGlqZnQuIERpdCBrb210IG92ZXJlZW4gbWV0IHdhdCB3ZSBpbiBkZSBmaWd1cmVuIGJpaiBkZSBkYXRhIGV4cGxvcmF0aWUgaGViYmVuIGdlb2JzZXJ2ZWVyZC4gSGV0IGVmZmVjdCB2YW4gaGV0IGdld2ljaHQgKGRlIGhlbGxpbmcpIG9wIGRlIGxvZzItb3ZlcmxldmluZ3N0aWpkIHZlcnNjaGlsdCBkdXMgc2lnbmlmaWNhbnQgdHVzc2VuIGRlIHZlcnNjaGlsbGVuZGUgdmlzc29vcnRlbiBvcCBoZXQgNSUgc2lnbmlmaWNhbnRpZW5pdmVhdS4gV2UgYmVob3VkZW4gZGV6ZSBpbnRlcmFjdGlldGVybSBkdXMgaW4gaGV0IG1vZGVsLiBXZSBiZWtvbWVuIGR1cyBoZXQgdm9sZ2VuZGUgbW9kZWw6CgokJAp5X2k9XGJldGFfMCtcYmV0YV9kIHhfe2lkfSArIFxiZXRhX2cgeF97aWd9ICtcYmV0YV97c2d9IHhfe2lzZ30gK1xiZXRhX3tzen0geF97aXN6fSArIFxiZXRhX3tnOnNnfSB4X3tpZ314X3tpc2d9ICsgXGJldGFfe2c6c3p9IHhfe2lnfXhfe2lzen0gKyBcZXBzaWxvbl9pCiQkCldhdCBlcXVpdmFsZW50IGlzIGFhbgokJAp5X2k9XGJldGFfMCArIFxiZXRhX3tzZ30geF97aXNnfSArXGJldGFfe3N6fSB4X3tpc3p9ICsgXGJldGFfZCB4X3tpZH0gKyAoXGJldGFfZyArXGJldGFfe2c6c2d9eF97aXNnfSArIFxiZXRhX3tnOnN6fXhfe2lzen0peF97aWd9ICAgKyBcZXBzaWxvbl9pCiQkCgpEaXQgbW9kZWwgemFsIGVpZ2VubGlqayBkcmllIHJlZ3Jlc3NpZXZsYWtrZW4gb3BsZXZlcmVuOiAxIHZvb3IgZG9qb3Zpc3NlbiwgMSB2b29yIGdvdWR2aXNzZW4gZW4gMSB2b29yIHplYnJhdmlzc2VuLgoKJCQKXGJlZ2lue2FycmF5fXtsbH0KXHRleHR7ZG9qb3ZpcyB9ICh4X3tpc2d9PTBcdGV4dHsgZW4gfXhfe2lzen09MCk6JkVbeVx2ZXJ0IFx0ZXh0e2Rvam92aXN9XT1cYmV0YV8wICsgXGJldGFfZCB4X3tpZH0gKyBcYmV0YV9nIHhfe2lnfSBcXApcdGV4dHtnb3VkdmlzIH0gICh4X3tpc2d9PTFcdGV4dHsgZW4gfXhfe2lzen09MCk6JkVbeVx2ZXJ0IFx0ZXh0e2dvdWR2aXN9XT1cYmV0YV8wK1xiZXRhX3tzZ30rXGJldGFfZCB4X3tpZH0gKyAoXGJldGFfZytcYmV0YV97ZzpzZ30pIHhfe2lnfSBcXApcdGV4dHt6ZWJyYXZpcyB9ICAoeF97aXNnfT0wXHRleHR7IGVuIH14X3tpc3p9PTEpOiZFW3lcdmVydCBcdGV4dHt6ZWJyYXZpc31dPVxiZXRhXzArXGJldGFfe3N6fStcYmV0YV9kIHhfe2lkfSArIChcYmV0YV9nK1xiZXRhX3tnOnN6fSkgeF97aWd9XFwKXGVuZHthcnJheX0KJCQKCgoKLSBIZXQgaG9vZmRlZmZlY3Qgdm9vciBzb29ydCB6b3JndCBkdXMgZGF0IGVsa2Ugc29vcnQgZWVuIHZlcnNjaGlsbGVuZCBpbnRlcmNlcHQgdmFuIGxvZzItb3ZlcmxldmluZ3N0aWpkIGhlZWZ0ICgkXGJldGFfMCQsICRcYmV0YV8wICsgXGJldGFfe3NnfSQsICRcYmV0YV8wK1xiZXRhX3tzen0kIHZvb3IgZG9qby0sIGdvdWQtIGVuIHplYnJhdmlzc2VuLCByZXNwZWN0aWV2ZWxpamspLgoKLSBEZSBpbnRlcmFjdGllIHR1c3NlbiBzb29ydCBlbiBnZXdpY2h0IHpvcmd0IGVydm9vciBkYXQgaGV0IGdld2ljaHRzZWZmZWN0IChoZWxsaW5nKSB2ZXJzY2hpbGxlbmQga2FuIHppam4gdm9vciBlbGtlIHNvb3J0ICgkXGJldGFfZyQsICRcYmV0YV9nK1xiZXRhX3tnOnNnfSQsICRcYmV0YV9nK1xiZXRhX3tnOnN6fSQgdm9vciBkb2pvLSwgZ291ZC0gZW4gemVicmF2aXNzZW4sIHJlc3BlY3RpZXZlbGlqaykuIAoKLSBIZXQgZG9zaXNlZmZlY3QgKGhlbGxpbmcpIGJsaWpmdCBnZWxpamsgdm9vciBkZSB2ZXJzY2hpbGxlbmRlIHZpc3Nlbi4KCgpgYGB7cn0Kc3VtbWFyeShsbV9maW5hbCkKYGBgCgojIFRlc3RlbiB2YW4gaHlwb3RoZXNlcwoKR2EgbWV0IGJlaHVscCB2YW4gaGV0IG9wZ2VzdGVsZGUgbW9kZWwgdm9sZ2VuZGUgb25kZXJ6b2Vrc3ZyYWdlbiBuYSB2b29yIGVsa2Ugdmlzc29vcnQuIENvcnJpZ2VlciBoaWVyYmlqIHZvb3IgbXVsdGlwbGUgdGVzdGluZyBlbiBjb250cm9sZWVyIGhldCBleHBlcmltZW50Z2V3aWpzIHNpZ25pZmljYW50aWVuaXZlYXUgb3AgNSU6CgotIElzIGVyIGVlbiBhc3NvY2lhdGllIHR1c3NlbiBkb3NpcyBlbiBsb2cyLW92ZXJsZXZpbmdzdGlqZCB2b29yIGRlIHZlcnNjaGlsbGVuZGUgdmlzc29vcnRlbj8KLSBJcyBlciBlZW4gYXNzb2NpYXRpZSB0dXNzZW4gZ2V3aWNodCBlbiBsb2cyLW92ZXJsZXZpbmdzdGlqZCB2b29yIGRlIHZlcnNjaGlsbGVuZGUgdmlzc29vcnRlbj8KLSBUdXNzZW4gd2Vsa2Ugdmlzc29vcnRlbiBpcyBlciBlZW4gdmVyc2NoaWwgaW4gYXNzb2NpYXRpZSB0dXNzZW4gZG9zaXMgZW4gbG9nMi1vdmVybGV2aW5nc3RpamQ/Ci0gVHVzc2VuIHdlbGtlIHZpc3Nvb3J0ZW4gaXMgZXIgZWVuIHZlcnNjaGlsIGluIGFzc29jaWF0aWUgdHVzc2VuIGdld2ljaHQgZW4gbG9nMi1vdmVybGV2aW5nc3RpamQ/CgpgYGB7cn0KbWNwIDwtIGdsaHQobG1fZmluYWwsbGluZmN0ID0gYygiZG9zaXMgPSAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImdld2ljaHQgPSAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImdld2ljaHQgKyBzb29ydDE6Z2V3aWNodCA9IDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJnZXdpY2h0ICsgc29vcnQyOmdld2ljaHQgPSAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic29vcnQxOmdld2ljaHQgPSAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic29vcnQyOmdld2ljaHQgPSAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic29vcnQyOmdld2ljaHQgLSBzb29ydDE6Z2V3aWNodCA9IDAiKSkKc3VtbWFyeShtY3ApCmBgYAoKYGBge3J9CmNvbmZpbnRzIDwtIGNvbmZpbnQobWNwKQpjb25maW50cwoyXmNvbmZpbnRzJGNvbmZpbnQKMl4tY29uZmludHMkY29uZmludApgYGAKCgojIENvbmNsdXNpZQoKRXIgaXMgZWVuIGV4dHJlZW0gc2lnbmlmaWNhbnQgZWZmZWN0IHZhbiBkZSBkb3NpcyBvcCBkZSBvdmVybGV2aW5nc3RpamQgKHAgPDwgMC4wMDEpLgpEZSBvdmVybGV2aW5nc3RpamQgdmFuIHZpc3NlbiBkaWUgYWFuIGVlbiBob2dlcmUgZG9zaXMgdmFuIGhldCBnaWYgd29yZGVuIGJsb290Z2VzdGVsZCBuZWVtdCBnZW1pZGRlbGQgbWV0IGVlbiBmYWN0b3JgciAyXmFicyhjb25maW50cyRjb25maW50WyJkb3NpcyIsMV0pICAlPiUgcm91bmQoLiwxKWAgYWYgcGVyIG1nIGV4dHJhIGdpZiBkaWUgd29yZHQgdG9lZ2VkaWVuZCAoOTUlIEJJIFtgciAyXmFicyhjb25maW50cyRjb25maW50WyJkb3NpcyIsLTFdKSAgJT4lIHJvdW5kKC4sMSklPiUgc29ydGBdKS4gIEhldCBkb3Npc2VmZmVjdCB2ZXJzY2hpbHQgbmlldCBzaWduaWZpY2FudCB0dXNzZW4gZGUgdmVyc2NoaWxsZW5kZSB2aXNzb29ydGVuIG9wIGhldCA1JSBzaWduaWZpY2FudGllLW5pdmVhdS4gCgpWZXJkZXIgaXMgZXIgZWVuIHN0ZXJrIHNpZ25pZmljYW50ZSBhc3NvY2lhdGllIGlzIHR1c3NlbiBnZXdpY2h0IGVuIG92ZXJsZXZpbmdzdGlqZCBiaWogem93ZWwgZGUgZG9qb3Zpc3NlbiAoY29udHJhc3Q6IGdld2ljaHQgPT0gMCwgcCA9IDAuMDAxKSBhbHMgZGUgZ291ZHZpc3NlbiAoY29udHJhc3Q6IGdld2ljaHQgKyBzb29ydDE6Z2V3aWNodCA9PSAwLCBwIDw8IDAuMDAxKS4gVm9vciB2aXNzZW4gbWV0IGVlbiB2ZXJzY2hpbGxlbmQgbGljaGFhbXNnZXdpY2h0IGlzIGRlIG92ZXJsZXZpbmdzdGlqZCBnZW1pZGRlbGQgZWVuIGZhY3RvciBgciAyXmFicyhjb25maW50cyRjb25maW50WyJnZXdpY2h0IiwxXSkgICU+JSByb3VuZCguLDEpYCBlbiBgciAyXmFicyhjb25maW50cyRjb25maW50WyJnZXdpY2h0ICsgc29vcnQxOmdld2ljaHQiLDFdKSAgJT4lIHJvdW5kKC4sMSlgIHBlciBncmFtIGxpY2hhYW1zZ2V3aWNodCBob2dlciB2b29yIGRlIHp3YWFyZGVyZSB2aXMgYmlqIHJlc3BlY3RpZXZlbGlqayBkb2pvLSBlbiBnb3Vkdmlzc2VuICg5NSUgQkkgW2ByIDJeYWJzKGNvbmZpbnRzJGNvbmZpbnRbImdld2ljaHQiLC0xXSkgICU+JSByb3VuZCguLDEpJT4lIHNvcnRgXSBlbiBbYHIgMl5hYnMoY29uZmludHMkY29uZmludFsiZ2V3aWNodCArIHNvb3J0MTpnZXdpY2h0IiwtMV0pICAlPiUgcm91bmQoLiwxKSU+JSBzb3J0YF0sIHJlc3BlY3RpZXZlbGlqaykuIApWb29yIGRlIHplYnJhdmlzc2VuIChjb250cmFzdDogZ2V3aWNodCArIHNvb3J0MjpnZXdpY2h0ID09IDAsIHAgPSAwLjk5OSkgaXMgZXIgZ2VlbiBzaWduaWZpY2FudGUgYXNzb2NpYXRpZSB0dXNzZW4gZ2V3aWNodCBlbiBvdmVybGV2aW5nc3RpamQuCgpEZSBhc3NvY2lhdGllIHZhbiBnZXdpY2h0IGVuIGRlIGxvZzItb3ZlcmxldmluZ3N0aWpkIGlzIHNpZ25pZmljYW50IHZlcnNjaGlsbGVuZCB0dXNzZW4gemVicmF2aXNzZW4gZW4gZ291ZHZpc3NlbiAoY29udHJhc3Q6IHNvb3J0MjpnZXdpY2h0IC0gc29vcnQxOmdld2ljaHQgPT0gMCwgcD0gMC4wNDgzKS4gQmlqIHplYnJhdmlzc2VuIHN0aWpndCBkZSBvdmVybGV2aW5nc3RpamQgcGVyIGdyYW0gZXh0cmEgZ2V3aWNodCBtZXQgZWVuIGZhY3RvciBgciAyXmFicyhjb25maW50cyRjb25maW50WyJzb29ydDI6Z2V3aWNodCAtIHNvb3J0MTpnZXdpY2h0IiwxXSkgICU+JSByb3VuZCguLDEpYCBtaW5kZXIgZGFuIGJpaiBnb3Vkdmlzc2VuICg5NSUgQkkgW2ByIDJeYWJzKGNvbmZpbnRzJGNvbmZpbnRbInNvb3J0MjpnZXdpY2h0IC0gc29vcnQxOmdld2ljaHQiLC0xXSkgICU+JSByb3VuZCguLDEpJT4lIHNvcnRgXSkuIApEZSBhc3NvY2lhdGllIHZhbiBnZXdpY2h0IGVuIGRlIGxvZzItb3ZlcmxldmluZ3N0aWpkIGlzIG5pZXQgc2lnbmlmaWNhbnQgdmVyc2NoaWxsZW5kIHR1c3NlbiBnb3Vkdmlzc2VuIGVuIGRvam92aXNzZW4gKGNvbnRyYXN0OiBzb29ydDE6Z2V3aWNodCA9PSAwLCBwID0gMC42NCkgZW4gdHVzc2VuIHplYnJhdmlzc2VuIGVuIGRvam92aXNzZW4gKGNvbnRyYXN0OiBzb29ydDI6Z2V3aWNodCA9PSAwLCBwPTAuMzQpLiAK