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.
Laad de
libraries
##
## 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
## Loading required package: carData
##
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
##
## recode
## 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
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)
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.
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.
##
## 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
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
## 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
## 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
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