Case study: Lengte van
mannen en vrouwen - Variabiliteit van steekproef tot steekproef
Om te begrijpen dat een steekproef random is zouden we hetzelfde
experiment veel keer moeten kunnen herhalen
(repeated sampling
).
Dan zouden we inzicht kunnen krijgen hoe de gegevens veranderen
van steekproef tot steekproef.
Om dit te illustreren zullen we gebruik maken van een hele grote
studie.
Uit die studie zullen we dan herhaaldelijk kleine steekproeven
trekken om te begrijpen hoe de gegevens en statistieken veranderen van
steekproef tot steekproef. Of om met andere woorden na te gaan wat de
variabiliteit is tussen steekproeven.
National Health And Nutrition Examination Study (NHANES)
- Sinds 1960 worden elk jaar mensen van alle leeftijden geïnterviewd
bij hen thuis.
- Er maakt ook een gezondheidsonderzoek deel uit van de study die in
een mobiel onderzoekscentrum wordt afgenomen.
- We zullen deze grote studie gebruiken om at random personen te
selecteren van de Amerikaanse populatie.
- Dat zal inzicht geven in hoe de gegevens en resultaten van een
analyse zullen variëren van steekproef tot steekproef.
- De data van deze studie is terug te vinden in het R pakket
NHANES
library(NHANES)
head(NHANES)
# A tibble: 6 × 76
ID SurveyYr Gender Age AgeDecade AgeMonths Race1 Race3 Education
<int> <fct> <fct> <int> <fct> <int> <fct> <fct> <fct>
1 51624 2009_10 male 34 " 30-39" 409 White <NA> High School
2 51624 2009_10 male 34 " 30-39" 409 White <NA> High School
3 51624 2009_10 male 34 " 30-39" 409 White <NA> High School
4 51625 2009_10 male 4 " 0-9" 49 Other <NA> <NA>
5 51630 2009_10 female 49 " 40-49" 596 White <NA> Some College
6 51638 2009_10 male 9 " 0-9" 115 White <NA> <NA>
# … with 67 more variables: MaritalStatus <fct>, HHIncome <fct>,
# HHIncomeMid <int>, Poverty <dbl>, HomeRooms <int>, HomeOwn <fct>,
# Work <fct>, Weight <dbl>, Length <dbl>, HeadCirc <dbl>, Height <dbl>,
# BMI <dbl>, BMICatUnder20yrs <fct>, BMI_WHO <fct>, Pulse <int>,
# BPSysAve <int>, BPDiaAve <int>, BPSys1 <int>, BPDia1 <int>, BPSys2 <int>,
# BPDia2 <int>, BPSys3 <int>, BPDia3 <int>, Testosterone <dbl>,
# DirectChol <dbl>, TotChol <dbl>, UrineVol1 <int>, UrineFlow1 <dbl>, …
Rows: 10,000
Columns: 76
$ ID <int> 51624, 51624, 51624, 51625, 51630, 51638, 51646, 5164…
$ SurveyYr <fct> 2009_10, 2009_10, 2009_10, 2009_10, 2009_10, 2009_10,…
$ Gender <fct> male, male, male, male, female, male, male, female, f…
$ Age <int> 34, 34, 34, 4, 49, 9, 8, 45, 45, 45, 66, 58, 54, 10, …
$ AgeDecade <fct> 30-39, 30-39, 30-39, 0-9, 40-49, 0-9, 0-9, 40…
$ AgeMonths <int> 409, 409, 409, 49, 596, 115, 101, 541, 541, 541, 795,…
$ Race1 <fct> White, White, White, Other, White, White, White, Whit…
$ Race3 <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ Education <fct> High School, High School, High School, NA, Some Colle…
$ MaritalStatus <fct> Married, Married, Married, NA, LivePartner, NA, NA, M…
$ HHIncome <fct> 25000-34999, 25000-34999, 25000-34999, 20000-24999, 3…
$ HHIncomeMid <int> 30000, 30000, 30000, 22500, 40000, 87500, 60000, 8750…
$ Poverty <dbl> 1.36, 1.36, 1.36, 1.07, 1.91, 1.84, 2.33, 5.00, 5.00,…
$ HomeRooms <int> 6, 6, 6, 9, 5, 6, 7, 6, 6, 6, 5, 10, 6, 10, 10, 4, 3,…
$ HomeOwn <fct> Own, Own, Own, Own, Rent, Rent, Own, Own, Own, Own, O…
$ Work <fct> NotWorking, NotWorking, NotWorking, NA, NotWorking, N…
$ Weight <dbl> 87.4, 87.4, 87.4, 17.0, 86.7, 29.8, 35.2, 75.7, 75.7,…
$ Length <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ HeadCirc <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ Height <dbl> 164.7, 164.7, 164.7, 105.4, 168.4, 133.1, 130.6, 166.…
$ BMI <dbl> 32.22, 32.22, 32.22, 15.30, 30.57, 16.82, 20.64, 27.2…
$ BMICatUnder20yrs <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ BMI_WHO <fct> 30.0_plus, 30.0_plus, 30.0_plus, 12.0_18.5, 30.0_plus…
$ Pulse <int> 70, 70, 70, NA, 86, 82, 72, 62, 62, 62, 60, 62, 76, 8…
$ BPSysAve <int> 113, 113, 113, NA, 112, 86, 107, 118, 118, 118, 111, …
$ BPDiaAve <int> 85, 85, 85, NA, 75, 47, 37, 64, 64, 64, 63, 74, 85, 6…
$ BPSys1 <int> 114, 114, 114, NA, 118, 84, 114, 106, 106, 106, 124, …
$ BPDia1 <int> 88, 88, 88, NA, 82, 50, 46, 62, 62, 62, 64, 76, 86, 6…
$ BPSys2 <int> 114, 114, 114, NA, 108, 84, 108, 118, 118, 118, 108, …
$ BPDia2 <int> 88, 88, 88, NA, 74, 50, 36, 68, 68, 68, 62, 72, 88, 6…
$ BPSys3 <int> 112, 112, 112, NA, 116, 88, 106, 118, 118, 118, 114, …
$ BPDia3 <int> 82, 82, 82, NA, 76, 44, 38, 60, 60, 60, 64, 76, 82, 7…
$ Testosterone <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ DirectChol <dbl> 1.29, 1.29, 1.29, NA, 1.16, 1.34, 1.55, 2.12, 2.12, 2…
$ TotChol <dbl> 3.49, 3.49, 3.49, NA, 6.70, 4.86, 4.09, 5.82, 5.82, 5…
$ UrineVol1 <int> 352, 352, 352, NA, 77, 123, 238, 106, 106, 106, 113, …
$ UrineFlow1 <dbl> NA, NA, NA, NA, 0.094, 1.538, 1.322, 1.116, 1.116, 1.…
$ UrineVol2 <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ UrineFlow2 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ Diabetes <fct> No, No, No, No, No, No, No, No, No, No, No, No, No, N…
$ DiabetesAge <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ HealthGen <fct> Good, Good, Good, NA, Good, NA, NA, Vgood, Vgood, Vgo…
$ DaysPhysHlthBad <int> 0, 0, 0, NA, 0, NA, NA, 0, 0, 0, 10, 0, 4, NA, NA, 0,…
$ DaysMentHlthBad <int> 15, 15, 15, NA, 10, NA, NA, 3, 3, 3, 0, 0, 0, NA, NA,…
$ LittleInterest <fct> Most, Most, Most, NA, Several, NA, NA, None, None, No…
$ Depressed <fct> Several, Several, Several, NA, Several, NA, NA, None,…
$ nPregnancies <int> NA, NA, NA, NA, 2, NA, NA, 1, 1, 1, NA, NA, NA, NA, N…
$ nBabies <int> NA, NA, NA, NA, 2, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Age1stBaby <int> NA, NA, NA, NA, 27, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ SleepHrsNight <int> 4, 4, 4, NA, 8, NA, NA, 8, 8, 8, 7, 5, 4, NA, 5, 7, N…
$ SleepTrouble <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, No, No, Y…
$ PhysActive <fct> No, No, No, NA, No, NA, NA, Yes, Yes, Yes, Yes, Yes, …
$ PhysActiveDays <int> NA, NA, NA, NA, NA, NA, NA, 5, 5, 5, 7, 5, 1, NA, 2, …
$ TVHrsDay <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ CompHrsDay <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ TVHrsDayChild <int> NA, NA, NA, 4, NA, 5, 1, NA, NA, NA, NA, NA, NA, 4, N…
$ CompHrsDayChild <int> NA, NA, NA, 1, NA, 0, 6, NA, NA, NA, NA, NA, NA, 3, N…
$ Alcohol12PlusYr <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, Yes, Y…
$ AlcoholDay <int> NA, NA, NA, NA, 2, NA, NA, 3, 3, 3, 1, 2, 6, NA, NA, …
$ AlcoholYear <int> 0, 0, 0, NA, 20, NA, NA, 52, 52, 52, 100, 104, 364, N…
$ SmokeNow <fct> No, No, No, NA, Yes, NA, NA, NA, NA, NA, No, NA, NA, …
$ Smoke100 <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, Yes, No, …
$ Smoke100n <fct> Smoker, Smoker, Smoker, NA, Smoker, NA, NA, Non-Smoke…
$ SmokeAge <int> 18, 18, 18, NA, 38, NA, NA, NA, NA, NA, 13, NA, NA, N…
$ Marijuana <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, NA, Ye…
$ AgeFirstMarij <int> 17, 17, 17, NA, 18, NA, NA, 13, 13, 13, NA, 19, 15, N…
$ RegularMarij <fct> No, No, No, NA, No, NA, NA, No, No, No, NA, Yes, Yes,…
$ AgeRegMarij <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 20, 15, N…
$ HardDrugs <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, No, Yes, …
$ SexEver <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, Yes, Y…
$ SexAge <int> 16, 16, 16, NA, 12, NA, NA, 13, 13, 13, 17, 22, 12, N…
$ SexNumPartnLife <int> 8, 8, 8, NA, 10, NA, NA, 20, 20, 20, 15, 7, 100, NA, …
$ SexNumPartYear <int> 1, 1, 1, NA, 1, NA, NA, 0, 0, 0, NA, 1, 1, NA, NA, 1,…
$ SameSex <fct> No, No, No, NA, Yes, NA, NA, Yes, Yes, Yes, No, No, N…
$ SexOrientation <fct> Heterosexual, Heterosexual, Heterosexual, NA, Heteros…
$ PregnantNow <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
Data exploratie
Onderzoeksvraag: hoe verschilt de lengte van volwassen mannen en
vrouwen.
- We pipen de dataset naar de function
filter
om de data
te filteren volgens leeftijd.
- We plotten de lengte metingen.
- We selecteren de data data met het commando
ggplot(aes(x=lengte))
- We voegen een histogram toe met het commando
geom_histogram()
- We maken twee vertikale panels met het commando
facet_grid(Gender~.)
- We veranderen het label van de x-as met de
xlab
functie.
NHANES%>%
filter(Age >= 18 & !is.na(Height)) %>%
ggplot(aes(x = Height))+
geom_histogram() +
facet_grid(Gender ~ .) +
xlab("Lengte (cm)")
We zien dat de data nu min of meer symmetrisch verdeeld zijn en een
klokvorm hebben.
Dat zal ons toe laten om de data verder samen te vatten door gebruik te
maken van twee statistieken: het gemiddelde en de standaard deviatie wat
een maat is voor de spreiding van de gegevens rond het gemiddelde.
We maken nu een subset van de data die we zullen gebruiken om aan te
tonen hoe de variabiliteit in kleine steekproeven kan variëren van
steekproef tot steekproef.
- We filteren op leeftijd en verwijderen ontbrekenden gegevens (NA,
Not Available).
- We selecteren enkel het geslacht en Lengte zodat de dataset geen
onnodige variabelen bevat.
nhanesSub <- NHANES %>%
filter(Age >= 18 & !is.na(Height)) %>%
select(c("Gender","Height"))
We berekenen het gemiddelde en de standaard deviatie voor de lengte
voor mannen en vrouwen in de grote dataset. We groeperen de data
hiervoor op basis van het geslacht (variable Gender).
HeightSum <- nhanesSub %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean = mean,
sd = sd)
)
knitr::kable(
HeightSum %>%
mutate_if(is.numeric, round, digits=1)
)
female |
162.1 |
7.3 |
male |
175.9 |
7.5 |
Experiment
Stel dat we geen toegang hebben tot de metingen van de NHANES
studie.
We zouden dan een experiment op moeten zetten om metingen bij
mannen en vrouwen te doen.
Veronderstel dat we budget hebben om metingen bij 5 mannen en 5
vrouwen te doen.
We zouden dan 5 mannen en 5 vrouwen boven de 18 jaar at random
selecteren uit de Amerikaanse populatie.
We kunnen dit experiment simuleren door 5 vrouwen en 5 mannen at
random te selecteren uit de NHANES studie.
set.seed(1023)
nSamp <- 5
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp1 <- rbind(fem,mal)
samp1
# A tibble: 10 × 2
Gender Height
<fct> <dbl>
1 female 164
2 female 160.
3 female 159
4 female 154.
5 female 156.
6 male 170.
7 male 183.
8 male 183.
9 male 185.
10 male 170.
Data Exploratie
samp1 %>%
ggplot(aes(x=Height)) +
geom_histogram() +
facet_grid(Gender~.) +
xlab("Lengte (cm)")
HeightSumExp1 <- samp1 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean = mean,
sd = sd)
)
HeightSumExp1
# A tibble: 2 × 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 159. 3.76
2 male 178. 7.55
Histogram is niet zinvol als we maar zo weinig datapunten hebben.
Boxplot is beter:
We voeren hier ook een t-test uit.
t.test(Height~Gender,data=samp1)
Welch Two Sample t-test
data: Height by Gender
t = -5.0783, df = 5.8695, p-value = 0.00242
alternative hypothesis: true difference in means between group female and group male is not equal to 0
95 percent confidence interval:
-28.441927 -9.878073
sample estimates:
mean in group female mean in group male
158.72 177.88
In het experiment zijn vrouwen gemiddeld 19.16 cm kleiner dan mannen.
En als we een statistische test uitvoeren (zie hoofdstuk 5: Statistische
besluitvorming) kunnen we besluiten dat dit verschil statistisch
significant is.
Herhaal het
experiment
Als we het experiment herhalen selecteren we andere mensen en
verkrijgen we andere resultaten.
set.seed(1024)
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp2 <- rbind(fem,mal)
HeightSumExp2 <- samp2 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean=mean,
sd=sd)
)
HeightSumExp2
# A tibble: 2 × 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 166. 9.89
2 male 170. 8.24
samp2 %>%
ggplot(aes(x = Gender,y = Height)) +
geom_boxplot(outlier.shape = NA) +
geom_point(position = "jitter") +
geom_point(
aes(x = 1, y = HeightSumExp2$mean[1]),
size = 3,
pch = 17,
color="darkred") +
geom_point(
aes(x = 2, y = HeightSumExp2$mean[2]),
size = 3,
pch = 17,
color = "darkred") +
ylab("Height (cm)")
t.test(Height ~ Gender, data=samp2)
Welch Two Sample t-test
data: Height by Gender
t = -0.7295, df = 7.747, p-value = 0.4872
alternative hypothesis: true difference in means between group female and group male is not equal to 0
95 percent confidence interval:
-17.552343 9.152343
sample estimates:
mean in group female mean in group male
166.26 170.46
In de nieuwe steekproef zijn vrouwen gemiddeld 4.2 cm kleiner dan
mannen. En dit verschil is statistisch niet significant
Herhaal het
experiment opnieuw
seed <- 88605
set.seed(seed)
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp3 <- rbind(fem,mal)
HeightSumExp3 <- samp3 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean=mean,
sd=sd)
)
HeightSumExp3
# A tibble: 2 × 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 173. 1.97
2 male 168. 2.84
samp3 %>%
ggplot(aes(x = Gender,y = Height)) +
geom_boxplot(outlier.shape = NA) +
geom_point(position = "jitter") +
geom_point(
aes(x = 1, y = HeightSumExp3$mean[1]),
size = 3,
pch = 17,
color="darkred") +
geom_point(
aes(x = 2, y = HeightSumExp3$mean[2]),
size = 3,
pch = 17,
color = "darkred") +
ylab("Height (cm)")
t.test(Height ~ Gender, data=samp3)
Welch Two Sample t-test
data: Height by Gender
t = 3.1182, df = 7.136, p-value = 0.01648
alternative hypothesis: true difference in means between group female and group male is not equal to 0
95 percent confidence interval:
1.178916 8.461084
sample estimates:
mean in group female mean in group male
172.60 167.78
In de nieuwe steekproef zijn vrouwen gemiddeld 4.82 cm groter dan
mannen. En dit verschil is statistisch significant
Samenvatting
We trokken at random andere proefpersonen in elke
steekproef
Hierdoor verschillen lengtemetingen van steekproef tot
steekproef.
Dus ook de geschatte gemiddeldes en standaard deviaties.
Bijgevolg zijn onze conclusies ook onzeker en kunnen deze
wijzigen van steekproef tot steekproef.
Voor het lengte voorbeeld zijn steekproeven waarbij het effect
tegengesteld is aan dat in de populatie en waarbij we besluiten dat het
verschil significant echter zeldzaam.
\(\rightarrow\) Met statistiek
controleren we de kans op het trekken foute conclusies.
Controle van
fouten
Hoe controleert statistiek de kans op het trekken van foute
conclusies?
- In onderstaande code trekken we 10000 herhaalde steekproeven van 5
vrouwen en 5 mannen uit de NHANES studie.
set.seed(15152)
# Aantal simulaties en steekproefgrootte per groep
nSim <- 10000
nSamp <- 5
# We filteren de data vooraf zodat we dit niet telkens opnieuw hoeven te doen
fem <- nhanesSub %>%
filter(Gender == "female")
mal <- nhanesSub %>%
filter(Gender == "male")
# Simulatie studie
# Om snelle functies te kunnen gebruiken nemen we eerst nSim steekproeven en berekenen we daarna alles.
femSamps <- malSamps <-matrix(NA, nrow=nSamp, ncol=nSim)
for (i in 1:nSim)
{
femSamps[,i] <- sample(fem$Height, nSamp)
malSamps[,i] <- sample(mal$Height, nSamp)
}
res <- data.frame(
verschil=colMeans(femSamps) - colMeans(malSamps),
Rfast::ttests(femSamps, malSamps)
)
sum(res$pvalue < 0.05 & res$verschil < 0)
[1] 7234
[1] 2766
sum(res$pvalue < 0.05 & res$verschil>0)
[1] 0
res %>%
ggplot(aes(x=verschil,y=-log10(pvalue),color=pvalue < 0.05)) +
geom_point() +
xlab("Gemiddeld Verschil (cm)") +
ylab("Statistische Significantie (-log10 p)")
res %>%
ggplot(aes(y = verschil)) +
geom_boxplot() +
ylab("Gemiddeld Verschil (cm)")
$x
[1] ""
attr(,"class")
[1] "labels"
Op basis van 10000 steekproeven van 5 mannen en 5 vrouwen zagen we
dat in 7234 steekproeven vrouwen gemiddeld significant kleiner zijn dan
mannen. In 2766 steekproeven besluiten we dat vrouwen en mannen
gemiddeld niet significant verschillen in lengte. En in 0 besluiten we
dat vrouwen gemiddeld significant groter zijn dan mannen.
- De steekproef die we toonden waaruit we zouden besluiten dat vrouwen
significant groter zijn dan mannen is heel onwaarschijnlijk. Er moesten
88605 steekproeven worden getrokken om deze extreme steekproef te
vinden.
Het feit dat we in veel steekproeven resultaten vinden die
statistisch niet significant zijn komt omdat de statistische toets een
te lage kracht heeft om het verschil te detecteren wanneer er maar 5
observaties zijn per groep.
Grotere
steekproef?
Wat gebeurt er als we de steekproef verhogen naar 50 observaties per
groep?
set.seed(11145)
# Aantal simulaties en steekproefgrootte per groep
nSim <- 10000
nSamp <- 50
# We filteren de data vooraf zodat we dit niet telkens opnieuw hoeven te doen
fem <- nhanesSub %>%
filter(Gender == "female")
mal <- nhanesSub %>%
filter(Gender == "male")
# Simulatie studie
# Om snelle functies te kunnen gebruiken nemen we eerst nSim steekproeven en berekenen we daarna alles.
femSamps <- malSamps <- matrix(NA, nrow = nSamp, ncol = nSim)
for (i in 1:nSim)
{
femSamps[,i] <- sample(fem$Height, nSamp)
malSamps[,i] <- sample(mal$Height, nSamp)
}
res <- data.frame(
verschil = colMeans(femSamps) - colMeans(malSamps),
Rfast::ttests(femSamps, malSamps)
)
sum(res$pvalue < 0.05 & res$verschil < 0)
[1] 10000
[1] 0
sum(res$pvalue < 0.05 & res$verschil > 0)
[1] 0
res %>%
ggplot(aes(x=verschil,y=-log10(pvalue),color=pvalue<0.05)) +
geom_point() +
xlab("Gemiddeld Verschil (cm)") +
ylab("Statistische Significantie (-log10 p)")
res %>%
ggplot(aes(y=verschil)) +
geom_boxplot() +
ylab("Gemiddeld Verschil (cm)")
$x
[1] ""
attr(,"class")
[1] "labels"
We zien dus dat we de kans om een verschil te vinden als er in
werkelijkheid een verschil is in de populatie kunnen beïnvloeden in de
design fase: aan de hand van de steekproefgrootte.
Hoe meer gegevens hoe makkelijker we het werkelijk verschil
oppikken in de steekproef.
Controle van vals
positieven
Wat gebeurt er als er geen verschil is tussen beide groepen?
We moeten hiervoor experimenten simuleren waarbij de groepen
gelijk zijn.
Hiervoor zullen we twee groepen vergelijken waarvoor de lengte
gemiddeld niet verschillend is.
Dat kunnen we doen door een steekproef te trekken waarbij we voor
beide groepen at random subjecten trekken uit de subset van vrouwen in
de NHANES studie.
We doen dit opnieuw voor een steekproef met 5 subjecten per
groep
set.seed(13245)
# Aantal simulaties en steekproefgrootte per groep
nSim <- 10000
nSamp <- 5
# We filteren de data vooraf zodat we dit niet telkens opnieuw hoeven te doen
fem <- nhanesSub %>%
filter(Gender == "female")
# Simulatie studie
# Om snelle functies te kunnen gebruiken nemen we eerst nSim steekproeven en berekenen we daarna alles.
femSamps <- femSamps2 <-matrix(NA, nrow=nSamp, ncol=nSim)
for (i in 1:nSim)
{
femSamps[,i] <- sample(fem$Height, nSamp)
femSamps2[,i] <- sample(fem$Height, nSamp)
}
res <- data.frame(
verschil=colMeans(femSamps) - colMeans(femSamps2),
Rfast::ttests(femSamps, femSamps2)
)
sum(res$pvalue < 0.05 & res$verschil < 0)
[1] 213
[1] 9558
sum(res$pvalue < 0.05 & res$verschil>0)
[1] 229
res %>%
ggplot(aes(x=verschil,y=-log10(pvalue),color=pvalue < 0.05)) +
geom_point() +
xlab("Gemiddeld Verschil (cm)") +
ylab("Statistische Significantie (-log10 p)")
res %>%
ggplot(aes(y = verschil)) +
geom_boxplot() +
ylab("Gemiddeld Verschil (cm)")
$x
[1] ""
attr(,"class")
[1] "labels"
Op basis van 10000 steekproeven zien we dat we in 442 steekproeven
ten onrechte besluiten dat er een verschil is in gemiddelde lengte
tussen twee groepen vrouwen.
Met de statistische analyse controleren we dus het aantal vals
positieve resultaten correct op 5%.
Wat gebeurt er als we het aantal observaties verhogen?
We simuleren opnieuw experimenten met 50 subjecten per groep maar we
trekken de subjecten opnieuw telkens uit de populatie van vrouwen.
set.seed(1345)
# Aantal simulaties en steekproefgrootte per groep
nSim <- 10000
nSamp <- 50
# We filteren de data vooraf zodat we dit niet telkens opnieuw hoeven te doen
fem <- nhanesSub %>%
filter(Gender == "female")
# Simulatie studie
# Om snelle functies te kunnen gebruiken nemen we eerst nSim steekproeven en berekenen we daarna alles.
femSamps <- femSamps2 <-matrix(NA, nrow=nSamp, ncol=nSim)
for (i in 1:nSim)
{
femSamps[,i] <- sample(fem$Height, nSamp)
femSamps2[,i] <- sample(fem$Height, nSamp)
}
res <- data.frame(
verschil=colMeans(femSamps) - colMeans(femSamps2),
Rfast::ttests(femSamps, femSamps2)
)
sum(res$pvalue < 0.05 & res$verschil < 0)
[1] 271
[1] 9501
sum(res$pvalue < 0.05 & res$verschil>0)
[1] 228
res %>%
ggplot(aes(x=verschil,y=-log10(pvalue),color=pvalue < 0.05)) +
geom_point() +
xlab("Gemiddeld Verschil (cm)") +
ylab("Statistische Significantie (-log10 p)")
res %>%
ggplot(aes(y = verschil)) +
geom_boxplot() +
ylab("Gemiddeld Verschil (cm)")
$x
[1] ""
attr(,"class")
[1] "labels"
Op basis van 10000 steekproeven zien we dat we in 499 steekproeven
ten onrechte besluiten dat er een verschil is in gemiddelde lengte
tussen twee groepen vrouwen.
Met de statistische analyse controleren we dus ook bij het nemen van
een grote steekproef het aantal vals positieve resultaten correct op 5%
(Vals positief: Op basis van de steekproef besluiten dat er gemiddeld
een verschil is in lengte tussen beide groepen terwijl er in
werkelijkheid geen verschil is in de populatie.)
Conclusies
De statistische analyse controleert steeds de kans op het nemen
van een vals positieve conclusie.
De statistische analysis controleert de kans op het nemen van een
vals negatieve conclusies niet, maar in de design fase kunnen we deze
kans beïnvloeden ondermeer d.m.v. de steekproefgrootte.
#Case study: Salk vaccin
- In 1916, brak de eerste grote polio epidemie uit in de USA.
- Begin de jaren 50 ontwikkelde John Salk een vaccin met belovende
resultaten in het lab.
- In 1954, heeft de National Foundation for Infantile Paralysis (NFIP)
een grote studie opgezet om de effectiviteit van het Salk vaccin na te
gaan.
- Veronderstel dat de NFIP in 1954 een groot aantal kinderen zou
hebben gevaccineerd, wat zouden ze dan kunnen besluiten als de polio
incidentie in 1954 lager was dan in 1953?
NFIP Study
Design
- Grote simultane studie met gevaccineerde kinderen (cases) en
ongevaccineerde kinderen (controles).
- In scholen van districten met hoge polio incidentie.
- Cases: kinderen van de tweede graad van het lager onderwijs waarvan
de ouders toestemden met vaccinatie.
- Controles: kinderen van de eerste en derde graad.
Data
nfip <- tibble(
group=c("cases","controls","noConcent"),
grade=c("g2","g1g3","g2"),
vaccin=c("yes","no","no"),
total=c(221998,725173,123605),
polio=c(54,391,56)
) %>%
mutate(noPolio = total - polio)
knitr::kable(nfip)
cases |
g2 |
yes |
221998 |
54 |
221944 |
controls |
g1g3 |
no |
725173 |
391 |
724782 |
noConcent |
g2 |
no |
123605 |
56 |
123549 |
Vergelijk de polio incidentie?
nfip <- nfip %>%
mutate(incidencePM = round(nfip$polio/nfip$total*1e6,0))
knitr::kable(nfip)
cases |
g2 |
yes |
221998 |
54 |
221944 |
243 |
controls |
g1g3 |
no |
725173 |
391 |
724782 |
539 |
noConcent |
g2 |
no |
123605 |
56 |
123549 |
453 |
Wat kunnen we concluderen?
Confounding
We observeren een lagere polio (P) incidentie voor kinderen bij
wie de ouders geen toestemming gaven dan in de controle groep.
Toestemming voor vaccinatie (V) is geassocieerd met de
socio-economische status (S).
Kinderen van lagere socio-economische status zijn meer resistent
tegen de ziekte.
De groepen van cases en controles zijn niet vergelijkbaar
- verschil in leeftijd
- verschil in socio-economische status en
- verschil in vatbaarheid voor de ziekte.
Salk Study
Design
Een nieuwe studie werd uitgevoerd: dubbel blinde gerandomiseerde
studie.
- Kinderen worden at random toegewezen aan controle of case arm van
het experiment nadat de ouders toestemden met vaccinatie.
- Controle: vaccinatie met placebo
- Treatment: vaccinatie met vaccin
- Double blinding:
- ouders en kinderen weten niet of ze werden gevaccineerd of niet
- medische staf en onderzoekers weten niet of het kind het vaccin of
de placebo kreeg
Data
salk <- data.frame(
group=c("cases","control","noConcent"),
treatment=c("vaccine","placebo","none"),
total=c(200745,201229, 338778),polio=c(57,142,157)
) %>%
mutate(
noPolio = total-polio,
incidencePM = round(polio/total*1e6,0)
)
knitr::kable(salk)
cases |
vaccine |
200745 |
57 |
200688 |
284 |
control |
placebo |
201229 |
142 |
201087 |
706 |
noConcent |
none |
338778 |
157 |
338621 |
463 |
We observeren een veel groter effect nu dat cases en controles
vergelijkbaar zijn, incidentie van respectievelijk 284 and 706 per
miljoen.
De polio incidentie voor kinderen die geen toestemming geven
blijft vergelijkbaar 453 and 463 per miljoen respectievelijk in the NFIP
and Salk study.
LS0tCnRpdGxlOiAiMS4gSW5sZWlkaW5nOiBXYWFyb20gU3RhdGlzdGllaz8iCmF1dGhvcjogIkxpZXZlbiBDbGVtZW50IgpkYXRlOiAic3RhdE9taWNzLCBHaGVudCBVbml2ZXJzaXR5IChodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8pIgpvdXRwdXQ6CiAgICBodG1sX2RvY3VtZW50OgogICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlICAgIAogICAgICB0aGVtZTogY29zbW8KICAgICAgdG9jOiB0cnVlCiAgICAgIHRvY19mbG9hdDogdHJ1ZQogICAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQotLS0KCiMgSW50cm9kdWN0aWUKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgotIFdlIGxldmVuIGluIGhldCBiaWcgZGF0YSBlcmEKLSBHZWdldmVucyBvdmVyIGxvY2F0aWUsIHN1cmZnZWRyYWcsIGFhbmtvb3BnZWRyYWcsIHNvY2lhbGUgbWVkaWEKLSBXZXRlbnNjaGFwOiBleHByZXNzaWUgbWV0ZW4gdmFuIGR1aXplbmRlbiBnZW5lbiwgZWl3aXR0ZW4sLi4uIHZvb3IgZWxrIHN1YmplY3QKLSBDaGVtaXNjaGUgcHJvY2VzIGNvbnRyb2xlOiBncm9vdCBhYW50YWwgc2Vuc29yZW4gZGllIGNvbnRpbnUgZWVuIHByb2NlcyBtZXRlbiB6b2RhdCBoZXQgcHJvY2VzIGthbiB3b3JkZW4gYmlqZ2VzdHV1cmQKLSBEYXRhIGRyaXZlbiBqb3VybmFsaXNtCi0gLi4uCgpTdGF0aXN0aWVrIGlzIGRlIHdldGVuc2NoYXAgb20gdGUgbGVyZW4gdWl0IGVtcGlyaXNjaGUgZ2VnZXZlbnMKClN0YXRpc3Rpc2NoZSBnZWxldHRlcmRoZWlkIGlzIGNydWNpYWFsIG9tIHJlc3VsdGF0ZW4gZW4gcHVibGljYXRpZXMga3JpdGlzY2ggdGUga3VubmVuIGludGVycHJldGVyZW4uCgotLS0KCiMgQ2FzZSBzdHVkeTogb2tzZWwgbWljcm9iaW9tZQoKCiFbXShodHRwczovL2ltYWdlcy52cnQuYmUvd2lkdGgxMjgwLzIwMTgvMDYvMjcvNGU3MjA5OGQtN2EwZC0xMWU4LWFiY2MtMDJiN2I3NmJmNDdmLmpwZyl7d2lkdGg9NzAlfQoKLSBodHRwczovL3d3dy52cnQuYmUvdnJ0bndzL25sLzIwMTgvMTAvMjIvZ2V6b2NodC1tZW5zZW4tbWV0LXBlbmV0cmFudGUtbGlqZmdldXItb20tcHJvYmlvdGlzY2hlLWRlb2Rvci8KLSBodHRwczovL3lvdXR1LmJlLzlSSUZ5cUxYZFZ3CgotLS0KCi0gT2tzZWxnZXVyIHdvcmR0IG5pZXQgdmVyb29yemFha3QgZG9vciBoZXQgendlZXQgemVsZi4gRGUgZ2V1ciBpcyBhZmtvbXN0aWcgdmFuIHNwZWNpZmljaWVrIG1pY3JvLW9yZ2FuaXNtZW4gdmFuIGRlIGdyb2VwICpDb3J5bmViYWN0ZXJpdW0gc3BwLiogZGllIGhldCB6d2VldCBtZXRhYm9saXNlcmVuLiAqU3RhcGh5bG9jb2NjdXMgc3BwLiogemlqbiBlZW4gYW5kZXJlIGdyb2VwIGJhY3RlcmnDq24gZGllIG9vayBhYnVuZGFudCB6aWpuIGluIGhldCBtaWNyb2Jpb21lIHZhbiBkZSBva3NlbCBkaWUgendlZXQgbWV0YWJvbGlzZXJlbiBuYWFyIG1ldGFib2xpZXRlbiBkaWUgbmlldCBzdGlua2VuLgoKLSBEZSBDTUVULWdyb2VwIGFhbiBVR0VOVCBkb2V0IG9uZGVyem9layBuYWFyIGhldCB0cmFuc3BsYW50ZXJlbiB2YW4gZGUgbWljcm9iacOrbGUgZ2VtZWVuc2NoYXAsIGhldCBtaWNyb2Jpb21lLCBvbSBtZW5zZW4gdmFuIGdldXJlbmRlIG9rc2VscyBhZiB0ZSBoZWxwZW4uICAKCi0gVm9vcmdlc3RlbGRlIHRoZXJhcGllCiAgCTEuIFZlcndpamRlciBoZXQgb2tzZWwgbWljcm9iaW9tZSBtZXQgYW50aWJpb3RpY2EKICAgIDIuIEJlw69udmxvZWQgaGV0IG9rc2VsIG1pY3JvYmlvbWUgZG9vciBtaWNyb2Jpb21lIHRlIHRyYW5zcGxhbnRlcmVuIHZhbiBlZW4gaW5kaXZpZHVlIGRpZSBnZWVuIGdldXJlbmRlIG9rc2VscyBoZWVmdCAoaHR0cHM6Ly95b3V0dS5iZS85UklGeXFMWGRWdykKCgotLS0KCiMjIFByb2Vmb3B6ZXQgKGV4cGVyaW1lbnRhbCBkZXNpZ24pCgpgYGB7ciBvdXQud2lkdGg9JzgwJScsZmlnLmFzcD0uOCwgZmlnLmFsaWduPSdjZW50ZXInLGVjaG89RkFMU0V9CmlmICgicGkiJWluJWxzKCkpIHJtKCJwaSIpCmtvcHZvZXRlcjwtZnVuY3Rpb24oeCx5LGFuZ2xlPTAsbD0uMixjZXguZG90PS41LHBjaD0xOSxjb2w9ImJsYWNrIikKewphbmdsZT1hbmdsZS8xODAqcGkKcG9pbnRzKHgseSxjZXg9Y2V4LmRvdCxwY2g9cGNoLGNvbD1jb2wpCmxpbmVzKGMoeCx4K2wqY29zKC1waS8yK2FuZ2xlKSksYyh5LHkrbCpzaW4oLXBpLzIrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKGFuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihhbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MocGkrYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKHBpK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yK3BpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzIrcGkvNCthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMi1waS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yLXBpLzQrYW5nbGUpKSxjb2w9Y29sKQp9CgpwYXIobWFyPWMoMCwwLDAsMCksbWFpPWMoMCwwLDAsMCkpCnBsb3QoMCwwLHhsYWI9IiIseWxhYj0iIix4bGltPWMoMCwxMCkseWxpbT1jKDAsMTApLGNvbD0wLHhheHQ9Im5vbmUiLHlheHQ9Im5vbmUiLGF4ZXM9RkFMU0UpCnJlY3QoMCw2LDEwLDEwLGJvcmRlcj0icmVkIixsd2Q9MikKdGV4dCguNSw4LCJwb3B1bGF0aW9uIixzcnQ9OTAsY29sPSJyZWQiLGNleD0yKQpzeW1ib2xzICgzLCA4LCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJyZWQiLGluY2hlcz1GQUxTRSxsd2Q9MikKc2V0LnNlZWQoMzMwKQpncmlkPXNlcSgwLDEuMywuMDEpCgpmb3IgKGkgaW4gMTo1MCkKewoJYW5nbGUxPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJYW5nbGUyPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJcmFkaXVzPXNhbXBsZShncmlkLHByb2I9Z3JpZF4yKnBpL3N1bShncmlkXjIqcGkpLHNpemU9MSkKCWtvcHZvZXRlcigzK3JhZGl1cypjb3MoYW5nbGUxLzE4MCpwaSksOCtyYWRpdXMqc2luKGFuZ2xlMS8xODAqcGkpLGFuZ2xlPWFuZ2xlMikKfQp0ZXh0KDcuNSw4LCJNaWNyb2Jpb21lIGluIHBvcHVsYXRpb24iLGNvbD0icmVkIixjZXg9MS4yKQpgYGAKCi0tLQoKCmBgYHtyIG91dC53aWR0aD0nODAlJyxmaWcuYXNwPS44LCBmaWcuYWxpZ249J2NlbnRlcicsZWNobz1GQUxTRX0KaWYgKCJwaSIlaW4lbHMoKSkgcm0oInBpIikKa29wdm9ldGVyPC1mdW5jdGlvbih4LHksYW5nbGU9MCxsPS4yLGNleC5kb3Q9LjUscGNoPTE5LGNvbD0iYmxhY2siKQp7CmFuZ2xlPWFuZ2xlLzE4MCpwaQpwb2ludHMoeCx5LGNleD1jZXguZG90LHBjaD1wY2gsY29sPWNvbCkKbGluZXMoYyh4LHgrbCpjb3MoLXBpLzIrYW5nbGUpKSxjKHkseStsKnNpbigtcGkvMithbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MoYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKGFuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wvMipjb3MoLXBpLzIrYW5nbGUpLHgrbC8yKmNvcygtcGkvMithbmdsZSkrbC80KmNvcyhwaSthbmdsZSkpLGMoeStsLzIqc2luKC1waS8yK2FuZ2xlKSx5K2wvMipzaW4oLXBpLzIrYW5nbGUpK2wvNCpzaW4ocGkrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbCpjb3MoLXBpLzIrYW5nbGUpLHgrbCpjb3MoLXBpLzIrYW5nbGUpK2wvMipjb3MoLXBpLzIrcGkvNCthbmdsZSkpLGMoeStsKnNpbigtcGkvMithbmdsZSkseStsKnNpbigtcGkvMithbmdsZSkrbC8yKnNpbigtcGkvMitwaS80K2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yLXBpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzItcGkvNCthbmdsZSkpLGNvbD1jb2wpCn0KCnBhcihtYXI9YygwLDAsMCwwKSxtYWk9YygwLDAsMCwwKSkKcGxvdCgwLDAseGxhYj0iIix5bGFiPSIiLHhsaW09YygwLDEwKSx5bGltPWMoMCwxMCksY29sPTAseGF4dD0ibm9uZSIseWF4dD0ibm9uZSIsYXhlcz1GQUxTRSkKcmVjdCgwLDYsMTAsMTAsYm9yZGVyPSJyZWQiLGx3ZD0yKQp0ZXh0KC41LDgsInBvcHVsYXRpb24iLHNydD05MCxjb2w9InJlZCIsY2V4PTIpCnN5bWJvbHMgKDMsIDgsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9InJlZCIsaW5jaGVzPUZBTFNFLGx3ZD0yKQpzZXQuc2VlZCgzMzApCmdyaWQ9c2VxKDAsMS4zLC4wMSkKCmZvciAoaSBpbiAxOjUwKQp7CglhbmdsZTE9cnVuaWYobj0xLG1pbj0wLG1heD0zNjApCglhbmdsZTI9cnVuaWYobj0xLG1pbj0wLG1heD0zNjApCglyYWRpdXM9c2FtcGxlKGdyaWQscHJvYj1ncmlkXjIqcGkvc3VtKGdyaWReMipwaSksc2l6ZT0xKQoJa29wdm9ldGVyKDMrcmFkaXVzKmNvcyhhbmdsZTEvMTgwKnBpKSw4K3JhZGl1cypzaW4oYW5nbGUxLzE4MCpwaSksYW5nbGU9YW5nbGUyKQp9CnRleHQoNy41LDgsIk1pY3JvYmlvbWUgaW4gcG9wdWxhdGlvbiIsY29sPSJyZWQiLGNleD0xLjIpCgpyZWN0KDAsMCwxMCw0LGJvcmRlcj0iYmx1ZSIsbHdkPTIpCnRleHQoLjUsMiwic2FtcGxlIixzcnQ9OTAsY29sPSJibHVlIixjZXg9MikKc3ltYm9scyAoMywgMiwgY2lyY2xlcz0xLjUsIGNvbD0icmVkIixhZGQ9VFJVRSxmZz0iYmx1ZSIsaW5jaGVzPUZBTFNFLGx3ZD0yKQpmb3IgKGkgaW4gMDoxKQoJZm9yIChqIGluIDA6NCkKewoKCWtvcHZvZXRlcigyLjEraiooMy45LTIuMSkvNCwxLjEraS8yLGNvbD0iYmxhY2siKQp9CmZvciAoaSBpbiAyOjMpCglmb3IgKGogaW4gMDo0KQp7CgoJa29wdm9ldGVyKDIuMStqKigzLjktMi4xKS80LDEuNitpLzIsY29sPSJibGFjayIpCn0KdGV4dCg3LjUsMiwiTWljcm9iaW9tZSBpbiBzYW1wbGUiLGNvbD0iYmx1ZSIsY2V4PTEuMikKCmFycm93cygzLDUuOSwzLDQuMSxjb2w9ImJsYWNrIixsd2Q9MykKdGV4dCgxLjUsNSwiRVhQLiBERVNJR04gKDEpIixjb2w9ImJsYWNrIixjZXg9MS4yKQpgYGAKCi0tLQoKLSBFeHBlcmltZW50OgoKICAgIC0gMjAgcGVyc29uZW4gd29yZGVuIGF0IHJhbmRvbSB1aXQgZGUgcG9wdWxhdGllIGdldHJva2tlbiB2YW4gcGVyc29uZW4gbWV0IGVlbiBva3NlbGdldXI6IHN0ZWVrcHJvZWYgcmVwcmVzZW50YXRpZWYgdm9vciBwb3B1bGF0aWUhCgogICAgLSBkZSBwZXJzb25lbiB3b3JkZW4gYXQgcmFuZG9tIHZlcmRlZWxkIG92ZXIgdHdlZSBiZWhhbmRlbGluZ3Nncm9lcGVuOgoKICAgICAgICAtIHBsYWNlYm8gKGVua2VsIGFudGliaW90aWNhKQogICAgICAgIC0gdHJhbnNwbGFudGllIChhbnRpYmlvdGljYSBlbiBtaWNyb2Jpw6tsZSB0cmFuc3BsYW50YXRpZSkuCiAgICAgICAgLSBSYW5kb21pc2F0aWUgaXMgYmVsYW5ncmlqayBvbSBlcnZvb3IgdGUgem9yZ2VuIGRhdCBkZSBncm9lcGVuIHZlcmdlbGlqa2JhYXIgemlqbi4KCiAgICAtIEhldCBtaWNyb2Jpb21lIHdvcmR0IGJlbW9uc3RlcmQgNiB3ZWtlbiBuYSBkZSBiZWhhbmRlbGluZy4KICAgIC0gVGhlIHJlbGF0aXZlIGFidW5kYW50aWUgdmFuICpTdGFwaHlsb2NvY2N1cyBzcHAuKiBvcCAqQ29yeW5lYmFjdGVyaXVtIHNwcC4qICsgKlN0YXBoeWxvY29jY3VzIHNwcC4qIGluIGhldCBtaWNyb2Jpb21lIHdvcmR0IGdlbWV0ZW4gdmlhIERHR0UgKCpEZW5hdHVyaW5nIEdyYWRpZW50IEdlbCBFbGVjdHJvcGhvcmVzaXMqKS4KCi0tLQoKREdHRQoKIVtdKGh0dHBzOi8vam91cm5hbHMucGxvcy5vcmcvcGxvc29uZS9hcnRpY2xlL2ZpZ3VyZS9pbWFnZT9zaXplPWxhcmdlJmRvd25sb2FkPSZpZD0xMC4xMzcxL2pvdXJuYWwucG9uZS4wMDcwNTM4LmcwMDEpe3dpZHRoPTcwJX0KCmh0dHBzOi8vZG9pLm9yZy8xMC4xMzcxL2pvdXJuYWwucG9uZS4wMDcwNTM4CgotLS0KClZlcnRhYWwgb25kZXJ6b2Vrc3ZyYWFnIG5hYXIgaWV0cyB3YXQgd2Uga3VubmVuIHF1YW50aWZpY2VyZW46IElzIGVyIGVlbiB2ZXJzY2hpbCBpbiByZWxhdGlldmUgYWJ1bmRhbnRpZSB2YW4gKlN0YXBoeWxvY29jY3VzIHNwcC4qIGluIGhldCBtaWNyb2Jpb21lIHZhbiBkZSBwbGFjZWJvIGdyb2VwIGVuIGRlIHRyYW5zcGxhbnRhdGllCgotLS0KCmBgYHtyIG91dC53aWR0aD0nODAlJyxmaWcuYXNwPS44LCBmaWcuYWxpZ249J2NlbnRlcicsZWNobz1GQUxTRX0KaWYgKCJwaSIlaW4lbHMoKSkgcm0oInBpIikKa29wdm9ldGVyPC1mdW5jdGlvbih4LHksYW5nbGU9MCxsPS4yLGNleC5kb3Q9LjUscGNoPTE5LGNvbD0iYmxhY2siKQp7CmFuZ2xlPWFuZ2xlLzE4MCpwaQpwb2ludHMoeCx5LGNleD1jZXguZG90LHBjaD1wY2gsY29sPWNvbCkKbGluZXMoYyh4LHgrbCpjb3MoLXBpLzIrYW5nbGUpKSxjKHkseStsKnNpbigtcGkvMithbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MoYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKGFuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wvMipjb3MoLXBpLzIrYW5nbGUpLHgrbC8yKmNvcygtcGkvMithbmdsZSkrbC80KmNvcyhwaSthbmdsZSkpLGMoeStsLzIqc2luKC1waS8yK2FuZ2xlKSx5K2wvMipzaW4oLXBpLzIrYW5nbGUpK2wvNCpzaW4ocGkrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbCpjb3MoLXBpLzIrYW5nbGUpLHgrbCpjb3MoLXBpLzIrYW5nbGUpK2wvMipjb3MoLXBpLzIrcGkvNCthbmdsZSkpLGMoeStsKnNpbigtcGkvMithbmdsZSkseStsKnNpbigtcGkvMithbmdsZSkrbC8yKnNpbigtcGkvMitwaS80K2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yLXBpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzItcGkvNCthbmdsZSkpLGNvbD1jb2wpCn0KCnBhcihtYXI9YygwLDAsMCwwKSxtYWk9YygwLDAsMCwwKSkKcGxvdCgwLDAseGxhYj0iIix5bGFiPSIiLHhsaW09YygwLDEwKSx5bGltPWMoMCwxMCksY29sPTAseGF4dD0ibm9uZSIseWF4dD0ibm9uZSIsYXhlcz1GQUxTRSkKcmVjdCgwLDYsMTAsMTAsYm9yZGVyPSJyZWQiLGx3ZD0yKQp0ZXh0KC41LDgsInBvcHVsYXRpb24iLHNydD05MCxjb2w9InJlZCIsY2V4PTIpCnN5bWJvbHMgKDMsIDgsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9InJlZCIsaW5jaGVzPUZBTFNFLGx3ZD0yKQpzZXQuc2VlZCgzMzApCmdyaWQ9c2VxKDAsMS4zLC4wMSkKCmZvciAoaSBpbiAxOjUwKQp7CglhbmdsZTE9cnVuaWYobj0xLG1pbj0wLG1heD0zNjApCglhbmdsZTI9cnVuaWYobj0xLG1pbj0wLG1heD0zNjApCglyYWRpdXM9c2FtcGxlKGdyaWQscHJvYj1ncmlkXjIqcGkvc3VtKGdyaWReMipwaSksc2l6ZT0xKQoJa29wdm9ldGVyKDMrcmFkaXVzKmNvcyhhbmdsZTEvMTgwKnBpKSw4K3JhZGl1cypzaW4oYW5nbGUxLzE4MCpwaSksYW5nbGU9YW5nbGUyKQp9CnRleHQoNy41LDgsIk1pY3JvYmlvbWUgaW4gcG9wdWxhdGlvbiIsY29sPSJyZWQiLGNleD0xLjIpCgpyZWN0KDAsMCwxMCw0LGJvcmRlcj0iYmx1ZSIsbHdkPTIpCnRleHQoLjUsMiwic2FtcGxlIixzcnQ9OTAsY29sPSJibHVlIixjZXg9MikKc3ltYm9scyAoMywgMiwgY2lyY2xlcz0xLjUsIGNvbD0icmVkIixhZGQ9VFJVRSxmZz0iYmx1ZSIsaW5jaGVzPUZBTFNFLGx3ZD0yKQpmb3IgKGkgaW4gMDoxKQoJZm9yIChqIGluIDA6NCkKewoKCWtvcHZvZXRlcigyLjEraiooMy45LTIuMSkvNCwxLjEraS8yLGNvbD0icHVycGxlIikKfQpmb3IgKGkgaW4gMjozKQoJZm9yIChqIGluIDA6NCkKewoKCWtvcHZvZXRlcigyLjEraiooMy45LTIuMSkvNCwxLjYraS8yLGNvbD0ib3JhbmdlIikKfQp0ZXh0KDcuNSwyLCJNaWNyb2Jpb21lIGluIHNhbXBsZSIsY29sPSJibHVlIixjZXg9MS4yKQoKYXJyb3dzKDMsNS45LDMsNC4xLGNvbD0iYmxhY2siLGx3ZD0zKQp0ZXh0KDEuNSw1LCJFWFAuIERFU0lHTiAoMSkiLGNvbD0iYmxhY2siLGNleD0xLjIpCnRleHQoNy41LC41LCJEQVRBIEVYUExPUkFUSU9OICZcbkRFU0NSSVBUSVZFIFNUQVRJU1RJQ1MgKDIpIixjb2w9ImJsYWNrIixjZXg9MS4yKQpgYGAKCi0tLQoKIyMgRGF0YSBFeHBsb3JhdGllIGVuIGJlc2NocmlqdmVuZGUgc3RhdGlzdGllawoKCi0gRGF0YSBleHBsb3JhdGllIGlzIGhlZWwgYmVsYW5ncmlqayBvbSBpbnppY2h0IHRlIGtyaWpnZW4gaW4gZGUgZGF0YSBlbiBpcyBlZW4gZXNzZW50acOrbGUgZWVyc3RlIHN0YXAgb20gdGUgbGVyZW4gdWl0IGRhdGEuCi0gSGV0IHdvcmR0IHZhYWsgb25kZXJnZXdhYXJkZWVyZCBvZiBvdmVyIGhldCBob29mZCBnZXppZW4uCgotLS0KCiMjIyBJbXBvcnRlZXIgZGUgZGF0YQoKLSBEYXRhIGluIGRlemUgY3Vyc3VzIHdvcmR0IHZlcndlcmt0IHZpYSBoZXQgc3RhdGlzdGlzY2ggc29mdHdhcmUgcGFra2V0IFIuCi0gRGl0IHBha2tldCBsYWF0IHRvZSBvbSB0ZSBsZXJlbiB1aXQgZGF0YS4KLSBJbiBkZXplIGN1cnN1cyBnYWFuIHdlIGRhdGEgZWVyc3QgZXhwbG9yZXJlbiBvbSBpbnppY2h0IHRlIHZlcndlcnZlbiBpbiBkZSBnZWdldmVucyBvbSBkaWUgdmVydm9sZ2VucyBzdGF0aXN0aXNjaCB0ZSB2ZXJ3ZXJrZW4uCi0gVm9vcmFsZWVyIHdlIGhpZXJtZWUgdmFuIHN0YXJ0IGt1bm5lbiBnYWFuIG1vZXRlbiB3ZSBkZSBkYXRhIGVlcnN0IGltcG9ydGVyZW4gaW4gUi4KCi0gVmlhIGhldCB2b2xnZW5kZSBjb21tYW5kbyBrdW5uZW4gd2UgZW5rZWxlIHJlZ2VscyB2YW4gZWVuIGRhdGEgYmVzdGFuZCBpbmxlemVuIG9tIGRlIHN0cnVjdHV1ciB2YW4gaGV0IGRhdGEgYmVzdGFuZCB0ZSB3ZXRlbiB0ZSBrb21lbi4KCmBgYHtyfQpyZWFkX2xpbmVzKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdE9taWNzL3NiYzIwL21hc3Rlci9kYXRhL2FybXBpdC5jc3YiKQpgYGAKCi0gR2VnZXZlbnMgaW4gaGV0IGJlc3RhbmQgemlqbiBkb29yIGNvbW1hJ3MgZ2VzY2hlaWRlbi4KLSBFbGtlIHJpaiBiZXZhdCBkZSBnZWdldmVucyB2b29yIDEgcHJvZWZwZXJzb29uCi0gVmVyc2NoaWxsZW5kZSB2YXJpYWJlbGVuIHdvcmRlbiBnZW1ldGVuIHBlciBwZXJzb29uIGVuIHppam4gdmFuIGVsa2FhciBnZXNjaGVpZGVuIGRvb3IgZWVuIGNvbW1hLiBIZXQgYmVzdGFuZCBpcyBjc3YgZm9ybWFhdDogImNvbW1hIHNlcGFyYXRlZCB2YWx1ZXMiLgotIFdlIGt1bm5lbiBiZXN0YW5kZW4gbWV0IGRpdCBmb3JtYWF0IGlubGV6ZW4gUiB2aWEgaGV0IGNvbW1hbmRvIHJlYWRfY3N2LgotIFdlIHNsYWFuIGRlIGRhdGEgb3AgaW4gUiBpbiBoZXQgb2JqZWN0IG1ldCBuYWFtIGFwLiBIaWVydm9vciBnZWJydWlrZW4gd2UgZGUgYDwtYCBvcGVyYXRvci4KLSBXZSBnZXZlbiBkZSBkYXRhIHRhYmVsIHRlcnVnIGRvb3IgaGV0IG9iamVjdCBhYW4gdGUgcm9lcGVuIGRvb3IgemlqbiBuYWFtIHRlIHR5cGVuLgoKYGBge3J9CmFwIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdE9taWNzL3NiYzIwL21hc3Rlci9kYXRhL2FybXBpdC5jc3YiKQphcApgYGAKCi0tLQoKIyMjIEJlc2NocmlqdmVuZGUgc3RhdGlzdGllawoKLSBJbiBhcnRpa2VscyBlbiBkZSBtZWRpYSB3b3JkZW4gcmVzdWx0YXRlbiB1aXQgZWVuIHN0ZWVrcHJvZWYgdmFhayBnZXJhcHBvcnRlZXJkIGEuZC5oLnYuIGdlbWlkZGVsZGUgZW4gZGUgc3RhbmRhYXJkYWZ3aWpraW5nCgotIFdlIHZhdHRlbiBkZSBkYXRhIGVlcnN0IHNhbWVuLiBXZSBiZXJla2VuZW4gaGV0IGdlbWlkZGVsZGUgZW4gZGUgc3RhbmRhYXJkIGRldmlhdGllIChlZW4gbWFhdCB2b29yIGRlIHNwcmVpZGluZywgemllIHZvbGdlbmRlIGhvb2Zkc3R1a2tlbikuCldlIHNsYWFuIGhldCByZXN1bHRhYXQgaGllcnZhbiBvcCBpbiBoZXQgb2JqZWN0IGFwUmVsU3VtIHZpYSBgYXBSZWxTdW0gPC1gLgoKMS4gV2UgcGlwZW4gKHZpYSBgJT4lYCkgaGV0IGBhcGAgZGF0YWZyYW1lIG5hYXIgZGUgYGdyb3VwX2J5YCBmdW5jdGllIG9tIGRlIGRhdGEgdGUgZ3JvZXBlcmVuIHBlciB0cmVhdG1lbnQgdHJ0OiBgZ3JvdXBfYnkodHJ0KWAuCgoyLiBXZSBwaXBlbiBoZXQgcmVzdWx0YWF0IG5hYXIgZGUgYHN1bW1hcml6ZV9hdGAgZnVuY3Rpb24gb20gZGUgInJlbCIgdmFyaWFibGUgc2FtZW4gdGUgdmF0dGVuIGVuIGJlcmVrZW5lbiBoaWVyYmlqIGhldCBnZW1pZGRlbGRlIGVuIHN0YW5kYWFyZGFmd2lqa2luZy4gT21kYXQgd2UgZGUgZGF0YSBlZXJzdCBoZWJiZW4gZ2Vncm9lcGVlcmQgenVsbGVuIHdlIGhldCBnZW1pZGRlbGRlIGVuIGRlIHN0YW5kYWFyZCBkZXZpYXRpZSBiZXJla2VuZW4gcGVyIGdyb2VwLgoKCgpgYGB7cn0KYXBSZWxTdW0gPC0gYXAgJT4lCiAgZ3JvdXBfYnkodHJ0KSAlPiUKICBzdW1tYXJpemVfYXQoInJlbCIsCiAgICAgICAgICAgICAgIGxpc3QobWVhbj1tZWFuLAogICAgICAgICAgICAgICAgICAgIHNkPXNkCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKQpgYGAKCldlIHRvbmVuIHZlcnZvbGdlbnMgaGV0IHJlc3VsdGFhdCBkb29yIGhldCBvYmplY3QgYXBSZWxTdW0gYWFuIHRlIHJvZXBlbgoKYGBge3J9CmFwUmVsU3VtCmBgYAoKV2Uga3VubmVuIG9vayBlZW4gdGFiZWwgaW4gZGUgd2VicGFnaW5hIG9mIGhldCBwZGYgYmVzdGFuZCBpbnRlZ3JlcmVuIHZpYSBoZXQgY29tbWFuZG8ga2FibGUgdmFuIGhldCBrbml0ciBwYWtrZXQ6CgpgYGB7cn0Ka25pdHI6OmthYmxlKGFwUmVsU3VtKQpgYGAKCi0tLQoKIyMjIEdyYWZpZWtlbgoKV2UgbWFrZW4gaW4gZGV6ZSBjdXJzdXMgZ2VicnVpayB2YW4gaGV0IHBha2tldCBgZ2dwbG90MmAgb20gZ3JhZmlla2VuIHRlIG1ha2VuLiAgCk1ldCBkZSBnZ3Bsb3QyIGJpYmxpb3RoZWVrIGt1bm5lbiB3ZSBnZW1ha2tlbGlqayBncmFmaWVrZW4gb3Bib3V3ZW4gaW4gbGFnZW4gKGxheWVycykuCkhpZXJkb29yIGxlZXN0IGRlIGNvZGUgdmVlbCBtYWtrZWxpamtlci4KCiMjIyMgYmFycGxvdAoKQmFyIHBsb3RzIHdvcmRlbiBoZWVsIHZlZWwgZ2VicnVpa3QgaW4gYXJ0aWtlbHMgb20gcmVzdWx0YXRlbiB3ZWVyIHRlIGdldmVuLgoKMS4gV2UgcGlwZW4gZGUgc2FtZW5nZXZhdHRlIGRhdGEgbmFhciBkZSBmdW5jdGllIGBnZ3Bsb3RgLiBEYXQgaXMgZGUgYmFzaXMgdmFuIGVsa2UgZ2dwbG90LiAgV2Ugc2VsZWN0ZXJlbiBkZSB2YXJpYWJlbGUgbWV0IGRlIGJlaGFuZGVsaW5nIHRydCBhbHMgeCB2YXJpYWJlbGUgZW4gZGUgdmFyaWFiZWxlIG1ldCBuYWFtIG1lYW4gYWxzIHktdmFyaWFiZWxlIHZvb3IgZGUgcGxvdC4KV2UgZG9lbiBkaXQgc3RlZWRzIHZpYSBkZSBhZXN0ZXRpY3MgYGFlc2AgZnVuY3RpZS4gICBgYWVzKHg9dHJ0LHk9bWVhbilgCgoyLiBXZSBtYWtlbiBlZW4gYmFycGxvdCBkb29yIGVlbiBsYWFnIHRvZSB0ZSB2b2VnZW4gdmlhIGRlICBgZ2VvbV9iYXJgIGZ1bmN0aW9uLiBEZSBzdGF0aXN0aWVrIGlzIGBzdGF0PSJpZGVudGl0eSJgIG9tZGF0IGRlIGhvb2d0ZSB2YW4gZGUgYmFyIGdlbGlqayBpcyBhYW4gZGUgd2FhcmRlIHZvb3IgeSAoaGllciBoZXQgZ2VtaWRkZWxkZSB2b29yIGRlIHJlbGF0aWV2ZSBhYnVuZGFudGllKS4KCjMuIFdlIHZvZWdlbiBmb3V0ZW52bGFnZ2VuIHRvZSBvbSBkZSBvbnpla2VyaGVpZCBvcCBoZXQgZ2VtaWRkZWxkZSB3ZWVyIHRlIGdldmVuLiAgV2UgZG9lbiBkaXQgdmlhIGRlIGBnZW9tX2Vycm9yYmFyYCBmdW5jdGllIGVuIHNwZWNpZmnDq3JlbiBoZXQgbWluaW11bSBlbiBtYXhpbXVtIHZhbiBkZSBlcnJvciBiYXIuIEhldCBgd2lkdGhgIGFyZ3VtZW50IHdvcmR0IGdlYnJ1aWt0IG9tIGRlIGJyZWVkdGUgdmFuIGRlIGVycm9yIGJhciBzbWFsbGVyIHRlIG1ha2VuIGRhdCBkZXplIHZhbiBkZSBiYXIuCgpgYGB7cn0KYXBSZWxTdW0gJT4lCiAgZ2dwbG90KGFlcyh4PXRydCx5PW1lYW4pKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1tZWFuLXNkLHltYXg9bWVhbitzZCksd2lkdGg9LjIpCmBgYAoKLSBJcyBkZXplIHBsb3QgaW5mb3JtYXRpZWY/PwoKLS0tCgojIyMjIGJveHBsb3RzCgpCYXJwbG90cyB6aWpuIGdlZW4gZ29lZGUgZ3JhZmlla2VuOgoKLSBaZSB6aWpuIG5pZXQgaW5mb3JtYXRpZWYKCi0gWmUgdmlzdWxhcmlzZXJlbiBlZW4gc2FtZW52YXR0aW5nIHZhbiBkZSBkYXRhIGRvb3IgdHdlZSBwdW50ZW46IGB0d28gcG9pbnQgc3VtbWFyeWA6IGdlbWlkZGVsZGUgZW4gZGUgc3RhbmRhYXJkIGRldmlhdGllIGhpZXJvcCBlbiBrdW5uZW4gYmV0ZXIgaW4gZWVuIHRhYmVsIHdvcmRlbiBvcGdlbm9tZW4uCgotIFplIGxhdGVuIG5pZXQgdG9lIG9tIGFub21hbGllw6tuIGluIGRlIGRhdGEgem9hbHMgbWVldGZvdXRlbiBvcCB0ZSBzcG9yZW4uCgotIFplIHZlcmJydWlrZW4gdmVlbCBydWltdGUsIGIudi4gdmFuIG51bCB0b3QgZGUga2xlaW5zdGUgd2FhcmRlIHZvb3IgZGUgcmVsYXRpZXZlIGFidW5kYW50aWUpIHdhYXIgZ2VlbiBkYXRhIGluIGxpZ3QuCgpIZXQgaXMgYmV0ZXIgb20gZGUgZGF0YSB6byBydXcgbW9nZWxpamsgdm9vciB0ZSBzdGVsbGVuIHpvZGF0IHdlIGluemljaHQga3JpamdlbiBpbiBkZSB2ZXJkZWxpbmcgdmFuIGRlIGdlZ2V2ZW5zLgpIaWVydm9vciB6dWxsZW4gd2Ugb25kZXJtZWVyIGJveHBsb3RzIGdlYnJ1aWtlbi4KCi0tLQoKV2UgbWFrZW4gbnUgZWVuIGJveHBsb3Qgdm9vciBkZSBhcCBkYXRhCgoxLiBXZSBwaXBlbiBoZXQgYGFwYCBkYXRhZnJhbWUgbmFhciBgZ2dwbG90YAoyLiBXZSBzZWxlY3RlcmVuIGRlIGRhdGEgdm9vciBkZSBwbG90IHZpYSBgZ2dwbG90KGFlcyh4PXRydCx5PXJlbCkpYAozLiBXZSB2b2VnZW4gbGFhZyB0b2Ugdm9vciBkZSBib3hwbG90IGRtdiBkZSBmdW5jdGllIGBnZW9tX2JveHBsb3QoKWAKCmBgYHtyfQphcCAlPiUgIAogIGdncGxvdChhZXMoeD10cnQseT1yZWwpKSArCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgotLS0KCk1lcmsgb3AgZGF0IHdlIGRlIHBsb3Qgb29rIG9wIGt1bm5lbiBzbGFhbiBhbHMgZWVuIG9iamVjdC4KCmBgYHtyfQphcEJveHBsb3QgPC0gYXAgJT4lICAKICBnZ3Bsb3QoYWVzKHg9dHJ0LHk9cmVsKSkgKwogIGdlb21fYm94cGxvdCgpCmBgYAoKRGUgcGxvdCB3b3JkdCBkYW4gbmlldCBnZW1hYWt0LgoKT20gZGUgcGxvdCB3ZWVyIHRlIGdldmVuIGt1bm5lbiB3ZSBoZXQgb2JqZWN0IGFhbnJvZXBlbgoKYGBge3J9CmFwQm94cGxvdApgYGAKCi0tLQoKLSBNZXJrIG9wIGRhdCB3ZSBuaWV0IHpvdmVlbCBnZWdldmVucyBoZWJiZW4uIEVua2VsIDEwIHBlciBncm9lcC4KCi0gSGV0IGlzIGFsdGlqZCBiZXRlciBvbSBkZSBkYXRhIHpvIHJ1dyBtb2dlbGlqayB0ZSB0b25lbiEKCk9tZGF0IGVyIG5pZXQgem92ZWVsIGdlZ2V2ZW5zIHppam4ga3VubmVuIHdlIGRlIGRhdGEgdG9ldm9lZ2VuIGFhbiBkZSBwbG90IHpvbmRlciBkYXQgZGllIHRlIGRydWsgd29yZHQuCgotIE1lcmsgb3AgZGF0IHdlIGhldCBhcmd1bWVudCBgb3V0bGllci5zaGFwZWAgb3AgTkEgKG5vdCBhdmFpbGFibGUpIHpldHRlbiBgb3V0bGllci5zaGFwZT1OQWAgaW4gdGhlIGBnZW9tX2JveHBsb3RgIGZ1bmN0aWUgb21kYXQgd2UgYW5kZXJzIG91dGxpZXJzIHR3ZWUga2VlciB3ZWVyIHp1bGxlbiBnZXZlbi4gRWVyc3QgdmlhIGRlIGJveHBsb3QgbGFhZyBlbiBkYWFybmEgb21kYXQgd2UgZWVuIGxhYWcgbWV0IGFsbGUgcnV3ZSBkYXRhIHRvZXZvZWdlbiBhYW4gZGUgcGxvdC4KLSBXZSBnZXZlbiBkZSBydXdlIGRhdGEgd2VlciB2aWEgZGUgIGBnZW9tX3BvaW50KHBvc2l0aW9uPSJqaXR0ZXIiKWAgZnVuY3RpZS4gV2UgZ2VicnVpa2VuIGhpZXJiaWogaGV0IGFyZ3VtZW50IHBvc2l0aW9uPSdqaXR0ZXInIHpvZGF0IHdlIHdhdCByYW5kb20gcnVpcyB0b2V2b2VnZW4gYWFuIGRlIHgtY29yZGluYWF0IHpvZGF0IGRlIGdlZ2V2ZW5zIGVsa2FhciBuaWV0IG92ZXJsYXBwZW4uCgpgYGB7cn0KYXAgJT4lICAKICBnZ3Bsb3QoYWVzKHg9dHJ0LHk9cmVsKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlPU5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIikKYGBgCgpEaXQgaXMgZWVuIGluZm9ybWF0aWV2ZSBwbG90IQoKLS0tCgpBYW5nZXppZW4gd2UgZGUgcGxvdCBvb2sgaGViYmVuIG9wZ2VzbGFnZW4ga29uZGVuIHdlIGRpdCBvb2sgZG9lbiBkb29yIGRlIHBsb3Qgb3AgdGUgcm9lcGVuIGVuIG5vZyBlZW4gbGFhZyB0b2UgdGUgdm9lZ2VuLgoKYGBge3J9CmFwQm94cGxvdCArCiAgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIikKYGBgCgpXZSBoYWRkZW4gaGV0IHJlc3VsdGFhdCBvb2sgb3BuaWV1dyBvcCBrdW5uZW4gc2xhYW4gdm9vciBsYXRlciBoZXJnZWJydWlrLgoKYGBge3J9CmFwQm94cGxvdCA8LSBhcEJveHBsb3QgKwogIGdlb21fcG9pbnQocG9zaXRpb249ImppdHRlciIpCmBgYAoKLS0tCgotIFdlIHphZ2VuIGR1aWRlbGlqayBlZW4gZWZmZWN0IHZhbiBkZSB0cmFuc3BsYW50YXRpZSBvcCBkZSByZWxhdGlldmUgYWJ1bmRhbnRpZSB2YW4gU3RhcGh5bG9jb2NjdXMuCgotIElzIGRhdCBlZmZlY3QgbnUgZ3Jvb3QgZ2Vub2VnIG9tIHRlIGt1bm5lbiBjb25jbHVkZXJlbiBkYXQgZGUgYmVoYW5kZWxpbmcgd2Vya3Q/CgotLS0KCmBgYHtyIG91dC53aWR0aD0nODAlJyxmaWcuYXNwPS44LCBmaWcuYWxpZ249J2NlbnRlcicsZWNobz1GQUxTRX0KaWYgKCJwaSIlaW4lbHMoKSkgcm0oInBpIikKa29wdm9ldGVyPC1mdW5jdGlvbih4LHksYW5nbGU9MCxsPS4yLGNleC5kb3Q9LjUscGNoPTE5LGNvbD0iYmxhY2siKQp7CmFuZ2xlPWFuZ2xlLzE4MCpwaQpwb2ludHMoeCx5LGNleD1jZXguZG90LHBjaD1wY2gsY29sPWNvbCkKbGluZXMoYyh4LHgrbCpjb3MoLXBpLzIrYW5nbGUpKSxjKHkseStsKnNpbigtcGkvMithbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MoYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKGFuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wvMipjb3MoLXBpLzIrYW5nbGUpLHgrbC8yKmNvcygtcGkvMithbmdsZSkrbC80KmNvcyhwaSthbmdsZSkpLGMoeStsLzIqc2luKC1waS8yK2FuZ2xlKSx5K2wvMipzaW4oLXBpLzIrYW5nbGUpK2wvNCpzaW4ocGkrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbCpjb3MoLXBpLzIrYW5nbGUpLHgrbCpjb3MoLXBpLzIrYW5nbGUpK2wvMipjb3MoLXBpLzIrcGkvNCthbmdsZSkpLGMoeStsKnNpbigtcGkvMithbmdsZSkseStsKnNpbigtcGkvMithbmdsZSkrbC8yKnNpbigtcGkvMitwaS80K2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yLXBpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzItcGkvNCthbmdsZSkpLGNvbD1jb2wpCn0KCnBhcihtYXI9YygwLDAsMCwwKSxtYWk9YygwLDAsMCwwKSkKcGxvdCgwLDAseGxhYj0iIix5bGFiPSIiLHhsaW09YygwLDEwKSx5bGltPWMoMCwxMCksY29sPTAseGF4dD0ibm9uZSIseWF4dD0ibm9uZSIsYXhlcz1GQUxTRSkKcmVjdCgwLDYsMTAsMTAsYm9yZGVyPSJyZWQiLGx3ZD0yKQp0ZXh0KC41LDgsInBvcHVsYXRpb24iLHNydD05MCxjb2w9InJlZCIsY2V4PTIpCnN5bWJvbHMgKDMsIDgsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9InJlZCIsaW5jaGVzPUZBTFNFLGx3ZD0yKQpzZXQuc2VlZCgzMzApCmdyaWQ9c2VxKDAsMS4zLC4wMSkKCmZvciAoaSBpbiAxOjUwKQp7CglhbmdsZTE9cnVuaWYobj0xLG1pbj0wLG1heD0zNjApCglhbmdsZTI9cnVuaWYobj0xLG1pbj0wLG1heD0zNjApCglyYWRpdXM9c2FtcGxlKGdyaWQscHJvYj1ncmlkXjIqcGkvc3VtKGdyaWReMipwaSksc2l6ZT0xKQoJa29wdm9ldGVyKDMrcmFkaXVzKmNvcyhhbmdsZTEvMTgwKnBpKSw4K3JhZGl1cypzaW4oYW5nbGUxLzE4MCpwaSksYW5nbGU9YW5nbGUyKQp9CnRleHQoNy41LDgsIk1pY3JvYmlvbWUgaW4gcG9wdWxhdGlvbiIsY29sPSJyZWQiLGNleD0xLjIpCgpyZWN0KDAsMCwxMCw0LGJvcmRlcj0iYmx1ZSIsbHdkPTIpCnRleHQoLjUsMiwic2FtcGxlIixzcnQ9OTAsY29sPSJibHVlIixjZXg9MikKc3ltYm9scyAoMywgMiwgY2lyY2xlcz0xLjUsIGNvbD0icmVkIixhZGQ9VFJVRSxmZz0iYmx1ZSIsaW5jaGVzPUZBTFNFLGx3ZD0yKQpmb3IgKGkgaW4gMDoxKQoJZm9yIChqIGluIDA6NCkKewoKCWtvcHZvZXRlcigyLjEraiooMy45LTIuMSkvNCwxLjEraS8yLGNvbD0icHVycGxlIikKfQpmb3IgKGkgaW4gMjozKQoJZm9yIChqIGluIDA6NCkKewoKCWtvcHZvZXRlcigyLjEraiooMy45LTIuMSkvNCwxLjYraS8yLGNvbD0ib3JhbmdlIikKfQp0ZXh0KDcuNSwyLCJNaWNyb2Jpb21lIGluIHNhbXBsZSIsY29sPSJibHVlIixjZXg9MS4yKQoKYXJyb3dzKDMsNS45LDMsNC4xLGNvbD0iYmxhY2siLGx3ZD0zKQp0ZXh0KDEuNSw1LCJFWFAuIERFU0lHTiAoMSkiLGNvbD0iYmxhY2siLGNleD0xLjIpCnRleHQoNy41LC41LCJEQVRBIEVYUExPUkFUSU9OICZcbkRFU0NSSVBUSVZFIFNUQVRJU1RJQ1MgKDIpIixjb2w9ImJsYWNrIixjZXg9MS4yKQphcnJvd3MoNyw0LjEsNyw1LjksY29sPSJibGFjayIsbHdkPTMpCnRleHQoOC41LDUsIkVTVElNQVRJT04gJlxuSU5GRVJFTkNFICgzKSIsY29sPSJibGFjayIsY2V4PTEuMikKYGBgCgotLS0KCi0gSW5kdWN0aWU6IERvb3IgbWlkZGVsIHZhbiBzdGF0aXN0aXNjaGUgYmVzbHVpdHZvcm1pbmcgKGluZmVyZW5jZSkga3VubmVuIHdlIHVpdHNwcmFrZW4gZG9lbiBvdmVyIGRlIHBvcHVsYXRpZSBvcCBiYXNpcyB2YW4gZWVuIHN0ZWVrcHJvZWYuCgotIERlIHByaWpzIGRpZSB3ZSBoaWVydm9vciBiZXRhbGVuIGlzIG9uemVrZXJoZWlkIQoKLSBXZSBrdW5uZW4gb3AgYmFzaXMgdmFuIGVlbiBzdGVla3Byb2VmIG5vb2l0IGFic29sdXV0IHpla2VyIHppam4gdmFuIG9uemUgY29uY2x1c2llcy4KCi0tLQoKLSBNZXQgZGF0YSBrdW5uZW4gd2UgbmlldCBiZXdpanplbiBkYXQgZWVuIGJlaGFuZGVsaW5nIHdlcmt0LgoKLSBGYWxzaWZpY2F0aWUgcHJpbmNpcGUgdmFuIFBvcHBlcjogRGF0YSBrdW5uZW4gZW5rZWwgZWVuIGh5cG90aGVzZSBvZiBlZW4gdGhlb3JpZSBvbnRrcmFjaHRlbi4KCi0gTWV0IHN0YXRpc3RpZWsga3VubmVuIHdlIGR1cyBuaWV0IGFhbnRvbmVuIGRhdCBkZSBiZWhhbmRlbGluZyB3ZXJrdC4KCi0gU3RhdGlzdGllayB6YWwgb25zIHdlbCB0b2VsYXRlbiBvbSBoZXQgb21nZWtlZXJkZSB0ZSBmYWxzaWZpw6tyZW46IGFscyB3ZSB2ZXJvbmRlcnN0ZWxsZW4gZGF0IGVyIGdlZW4gZWZmZWN0IHZhbiBkZSBiZWhhbmRlbGluZywgc3ByZWVrdCBkZSBkYXRhIGluIGRlIHN0ZWVrcHJvZWYgZGl0IHRlZ2VuPwoKLSBNZXQgc3RhdGlzdGllayBrdW5uZW4gd2UgYmVyZWtlbmVuIGhvZSB3YWFyc2NoaWpubGlqayBoZXQgaXMgb20gaW4gZWVuIHJhbmRvbSBzdGVla3Byb2VmICh3YW5uZWVyIHdlIGhldCBleHBlcmltZW50IGR1cyBvcG5pZXV3IHVpdCB6b3VkZW4gdm9lcmVuKSBlZW4gZ2VtaWRkZWxkIHZlcnNjaGlsIGluIHJlbGF0aWV2ZSBhYnVuZGFudGllIHRlIHppZW4gdHVzc2VuIHBsYWNlYm8gZW4gdHJhbnNwbGFudGF0aWVncm9lcCBkYXQgbWluc3RlbnMgem8gZ3Jvb3QgaXMgYWxzIGluIG9uemUgc3RlZWtwcm9lZiBhbHMgZGUgYmVoYW5kZWxpbmcgZ2VlbiBlZmZlY3Qgem91IGhlYmJlbi4KCi0gRGllIGthbnMgd29yZHQgZWVuIHAtd2FhcmRlIGdlbm9lbWQuCgotIEFscyBwIGhlZWwga2xlaW4gaXMsIGRhbiBpcyBoZXQgaGVlbCBvbndhYXJzY2hpam5saWprIG9tIGVlbiBkZXJnZWxpamsgZWZmZWN0IHRlIG9ic2VydmVyZW4gaW4gZWVuIHN0ZWVrcHJvZWYgZG9vciB0b2V2YWwuCgotIHAgd29yZHQgbWVlc3RhbCB2ZXJnZWxla2VuIG1ldCA1JS4gQWxzIGVyIGdlZW4gZWZmZWN0IGlzIHZhbiBkZSBiZWhhbmRlbGluZyBkYW4gdG9sZXJlcmVuIDUlIHZhbHMgcG9zaXRpZXZlIGNvbmNsdXNpZXMuCgotIE9tIGRlIGthbnMgcCB0ZSBiZXJla2VuZW4gaXMgaGV0IG5vZGlnIG9tIGRlIGRhdGEgdGUgbW9kZWxsZXJlbiBtZXQgc3RhdGlzdGlzY2hlIG1vZGVsbGVuLgoKLS0tCgpJbiBsYXRlcmUgaG9vZmRzdHVra2VuIHp1bGxlbiB3ZSB6aWVuIGRhdCB3ZSB0LXRlc3Qga3VubmVuIGdlYnJ1aWtlbiBvbSBoZXRnZWVuIHdlIG9ic2VydmVyZW4gaW4gZGUgbWljcm9iaW9tZSBkYXRhc2V0IHRlIHZlcmFsZ2VtZW5lbiBuYWFyIGRlIHBvcHVsYXRpZS4KCmBgYHtyfQp0LnRlc3QocmVsfnRydCxkYXRhPWFwKQpgYGAKCkNvbmNsdXNpZToKR2VtaWRkZWxkIGlzIGRlIHJlbGF0aWV2ZSBhYnVuZGFudGllIHZhbiBTdGFwaHlsb2NvY2N1cyBpbiBoZXQgbWljcm9iaW9tZSB2YW4gcGVyc29uZW4gbWV0IGVlbiB6d2VldGdldXIgYHIgZm9ybWF0KGFwUmVsU3VtJG1lYW5bMl0tYXBSZWxTdW0kbWVhblsxXSxkaWdpdHM9MylgJSBob2dlciBuYSBkZSB0cmFuc3BsYW50aWUgZGFuIG5hIGRlIHBsYWNlYm8gYmVoYW5kZWxpbmcuCgotLS0KCiMjIFJhbmRvbWlzYXRpZQoKLSBXYXQgd29yZHQgemlqbiBkZSBjb25zZXF1ZW50aWVzIHZhbiBoZXQgZ2VicnVpayB2YW4gZWVuIHN0ZWVrcHJvZWYgZW4gdmFuIHJhbmRvbWlzYXRpZT8KCi0gUmFuZG9taXNhdGllIGlzIHN0ZXJrIGdlcmVsYXRlZXJkIG1ldCBoZXQgY29uY2VwdCB2YW4gZGUgcG9wdWxhdGllIGVuIHNjb3BlIHZhbiBkZSBzdHVkaWUuICAKCi0gRGUgc2NvcGUgdmFuIGRlIHN0dWRpZSBtb2V0IGdvZWQgd29yZGVuIG9tc2NocmV2ZW4gdm9vciBkZSBzdGFydCB2YW4gaGV0IGV4cGVyaW1lbnQuCgotIE9tZGF0IGRlIHN0YXRpc3Rpc2NoZSBhbmFseXNlIHZhbGlkZSB6b3UgemlqbiBpcyBoZXQgbm9vZHpha2VsaWprIGRhdCBkZSBzdWJqZWN0ZW4gdm9sbGVkaWcgcmFuZG9tIHdvcmRlbiBnZXRyb2trZW4gdWl0IGRlIHBvcHVsYXRpZSBuYWFyIHdhYXIgd2Ugb256ZSBjb25jbHVzaWVzIHdlbnNlbiB0ZSB2ZXJhbGdlbWVuZW4uCgotIFZvbGxlZGlnIHJhbmRvbSB0cmVra2VuIHZhbiBkZSBwb3B1bGF0aWUgaW1wbGljZWVydCBkYXQ6CgogICAgLSBhbGxlIHN1YmplY3RlbiB2YW4gZGUgcG9wdWxhdGllIGV2ZW52ZWVsIGthbnMgaGViYmVuIG9tIGluIGRlIHN0ZWVrcHJvZWYgdGUgd29yZGVuIG9wZ2Vub21lbgogICAgLSBkZSBzZWxlY3RpZSB2YW4gZWVuIHN1YmplY3Qgb25hZmhhbmtlbGlqayBpcyB2YW4gZGUgYW5kZXJlIHN1YmplY3RlbiBpbiBkZSBzdGVla3Byb2VmLgoKCi0gRGUgc3RlZWtwcm9lZiBpcyBkYW4gcmVwcmVzZW50YXRpZWYgdm9vciBkZSBwb3B1bGF0aWUsIG1hYXIgaXMgbm9nIHN0ZWVkcyByYW5kb20uCgotIFdhdCBiZXRla2VudCBkaXQ/CgotLS0KCiMgQ2FzZSBzdHVkeTogTGVuZ3RlIHZhbiBtYW5uZW4gZW4gdnJvdXdlbiBcLSBWYXJpYWJpbGl0ZWl0IHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmCgotIE9tIHRlIGJlZ3JpanBlbiBkYXQgZWVuIHN0ZWVrcHJvZWYgcmFuZG9tIGlzIHpvdWRlbiB3ZSBoZXR6ZWxmZGUgZXhwZXJpbWVudCB2ZWVsIGtlZXIgbW9ldGVuIGt1bm5lbiBoZXJoYWxlbiAoYHJlcGVhdGVkIHNhbXBsaW5nYCkuCgotIERhbiB6b3VkZW4gd2UgaW56aWNodCBrdW5uZW4ga3JpamdlbiBob2UgZGUgZ2VnZXZlbnMgdmVyYW5kZXJlbiB2YW4gc3RlZWtwcm9lZiB0b3Qgc3RlZWtwcm9lZi4KCi0gT20gZGl0IHRlIGlsbHVzdHJlcmVuIHp1bGxlbiB3ZSBnZWJydWlrIG1ha2VuIHZhbiBlZW4gaGVsZSBncm90ZSBzdHVkaWUuCgotIFVpdCBkaWUgc3R1ZGllIHp1bGxlbiB3ZSBkYW4gaGVyaGFhbGRlbGlqayBrbGVpbmUgc3RlZWtwcm9ldmVuIHRyZWtrZW4gb20gdGUgYmVncmlqcGVuIGhvZSBkZSBnZWdldmVucyBlbiBzdGF0aXN0aWVrZW4gdmVyYW5kZXJlbiB2YW4gc3RlZWtwcm9lZiB0b3Qgc3RlZWtwcm9lZi4gT2Ygb20gbWV0IGFuZGVyZSB3b29yZGVuIG5hIHRlIGdhYW4gd2F0IGRlIHZhcmlhYmlsaXRlaXQgaXMgdHVzc2VuIHN0ZWVrcHJvZXZlbi4KCi0tLQoKTmF0aW9uYWwgSGVhbHRoIEFuZCBOdXRyaXRpb24gRXhhbWluYXRpb24gU3R1ZHkgKE5IQU5FUykKCiAgLSBTaW5kcyAxOTYwIHdvcmRlbiBlbGsgamFhciBtZW5zZW4gdmFuIGFsbGUgbGVlZnRpamRlbiBnZcOvbnRlcnZpZXdkIGJpaiBoZW4gdGh1aXMuCiAgLSBFciBtYWFrdCBvb2sgZWVuIGdlem9uZGhlaWRzb25kZXJ6b2VrIGRlZWwgdWl0IHZhbiBkZSBzdHVkeSBkaWUgaW4gZWVuIG1vYmllbCBvbmRlcnpvZWtzY2VudHJ1bSB3b3JkdCBhZmdlbm9tZW4uCiAgLSBXZSB6dWxsZW4gZGV6ZSBncm90ZSBzdHVkaWUgZ2VicnVpa2VuIG9tIGF0IHJhbmRvbSBwZXJzb25lbiB0ZSBzZWxlY3RlcmVuIHZhbiBkZSBBbWVyaWthYW5zZSBwb3B1bGF0aWUuCiAgLSBEYXQgemFsIGluemljaHQgZ2V2ZW4gaW4gaG9lIGRlIGdlZ2V2ZW5zIGVuIHJlc3VsdGF0ZW4gdmFuIGVlbiBhbmFseXNlIHp1bGxlbiB2YXJpw6tyZW4gdmFuIHN0ZWVrcHJvZWYgdG90IHN0ZWVrcHJvZWYuCiAgLSBEZSBkYXRhIHZhbiBkZXplIHN0dWRpZSBpcyB0ZXJ1ZyB0ZSB2aW5kZW4gaW4gaGV0IFIgcGFra2V0IGBOSEFORVNgCgotLS0KCmBgYHtyfQpsaWJyYXJ5KE5IQU5FUykKaGVhZChOSEFORVMpCmdsaW1wc2UoTkhBTkVTKQpgYGAKCi0tLQoKIyMgRGF0YSBleHBsb3JhdGllCgoKCk9uZGVyem9la3N2cmFhZzogaG9lIHZlcnNjaGlsdCBkZSBsZW5ndGUgdmFuIHZvbHdhc3NlbiBtYW5uZW4gZW4gdnJvdXdlbi4KCjEuIFdlIHBpcGVuIGRlIGRhdGFzZXQgbmFhciBkZSBmdW5jdGlvbiBgZmlsdGVyYCBvbSBkZSBkYXRhIHRlIGZpbHRlcmVuIHZvbGdlbnMgbGVlZnRpamQuICAKMi4gV2UgcGxvdHRlbiBkZSBsZW5ndGUgbWV0aW5nZW4uCiAgICAtIFdlIHNlbGVjdGVyZW4gZGUgZGF0YSBkYXRhIG1ldCBoZXQgY29tbWFuZG8gYGdncGxvdChhZXMoeD1sZW5ndGUpKWAKICAgIC0gV2Ugdm9lZ2VuIGVlbiBoaXN0b2dyYW0gdG9lIG1ldCBoZXQgY29tbWFuZG8gYGdlb21faGlzdG9ncmFtKClgCiAgICAtIFdlIG1ha2VuIHR3ZWUgdmVydGlrYWxlIHBhbmVscyBtZXQgaGV0IGNvbW1hbmRvIGBmYWNldF9ncmlkKEdlbmRlcn4uKWAKICAgIC0gV2UgdmVyYW5kZXJlbiBoZXQgbGFiZWwgdmFuIGRlIHgtYXMgbWV0IGRlIGB4bGFiYCBmdW5jdGllLgoKYGBge3J9Ck5IQU5FUyU+JSAgCiAgZmlsdGVyKEFnZSA+PSAxOCAmICFpcy5uYShIZWlnaHQpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBIZWlnaHQpKSsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBmYWNldF9ncmlkKEdlbmRlciB+IC4pICsKICB4bGFiKCJMZW5ndGUgKGNtKSIpCmBgYAoKLS0tCgpXZSB6aWVuIGRhdCBkZSBkYXRhIG51IG1pbiBvZiBtZWVyIHN5bW1ldHJpc2NoIHZlcmRlZWxkIHppam4gZW4gZWVuIGtsb2t2b3JtIGhlYmJlbi4gIApEYXQgemFsIG9ucyB0b2UgbGF0ZW4gb20gZGUgZGF0YSB2ZXJkZXIgc2FtZW4gdGUgdmF0dGVuIGRvb3IgZ2VicnVpayB0ZSBtYWtlbiB2YW4gdHdlZSBzdGF0aXN0aWVrZW46IGhldCBnZW1pZGRlbGRlIGVuIGRlIHN0YW5kYWFyZCBkZXZpYXRpZSB3YXQgZWVuIG1hYXQgaXMgdm9vciBkZSBzcHJlaWRpbmcgdmFuIGRlIGdlZ2V2ZW5zIHJvbmQgaGV0IGdlbWlkZGVsZGUuCgotLS0KCldlIG1ha2VuIG51IGVlbiBzdWJzZXQgdmFuIGRlIGRhdGEgZGllIHdlIHp1bGxlbiBnZWJydWlrZW4gb20gYWFuIHRlIHRvbmVuIGhvZSBkZSB2YXJpYWJpbGl0ZWl0IGluIGtsZWluZSBzdGVla3Byb2V2ZW4ga2FuIHZhcmnDq3JlbiB2YW4gc3RlZWtwcm9lZiB0b3Qgc3RlZWtwcm9lZi4KCiAgMS4gV2UgZmlsdGVyZW4gb3AgbGVlZnRpamQgZW4gdmVyd2lqZGVyZW4gb250YnJla2VuZGVuIGdlZ2V2ZW5zIChOQSwgTm90IEF2YWlsYWJsZSkuCiAgMi4gV2Ugc2VsZWN0ZXJlbiBlbmtlbCBoZXQgZ2VzbGFjaHQgZW4gTGVuZ3RlIHpvZGF0IGRlIGRhdGFzZXQgZ2VlbiBvbm5vZGlnZSB2YXJpYWJlbGVuIGJldmF0LgoKYGBge3J9Cm5oYW5lc1N1YiA8LSBOSEFORVMgJT4lCiAgZmlsdGVyKEFnZSA+PSAxOCAmICFpcy5uYShIZWlnaHQpKSAlPiUKICBzZWxlY3QoYygiR2VuZGVyIiwiSGVpZ2h0IikpCmBgYAoKLS0tCgpXZSBiZXJla2VuZW4gaGV0IGdlbWlkZGVsZGUgZW4gZGUgc3RhbmRhYXJkIGRldmlhdGllIHZvb3IgZGUgbGVuZ3RlIHZvb3IgbWFubmVuIGVuIHZyb3V3ZW4gaW4gZGUgZ3JvdGUgZGF0YXNldC4KV2UgZ3JvZXBlcmVuIGRlIGRhdGEgaGllcnZvb3Igb3AgYmFzaXMgdmFuIGhldCBnZXNsYWNodCAodmFyaWFibGUgR2VuZGVyKS4KCgpgYGB7cn0KCkhlaWdodFN1bSA8LSBuaGFuZXNTdWIgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemVfYXQoIkhlaWdodCIsCiAgICAgICAgICAgICAgIGxpc3QobWVhbiA9IG1lYW4sCiAgICAgICAgICAgICAgIHNkID0gc2QpCiAgICAgICAgICAgICAgKQoKa25pdHI6OmthYmxlKAogIEhlaWdodFN1bSAlPiUKICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIGRpZ2l0cz0xKQogICkKYGBgCgotLS0KCiMjIEV4cGVyaW1lbnQKCi0gU3RlbCBkYXQgd2UgZ2VlbiB0b2VnYW5nIGhlYmJlbiB0b3QgZGUgbWV0aW5nZW4gdmFuIGRlIE5IQU5FUyBzdHVkaWUuCgotIFdlIHpvdWRlbiBkYW4gZWVuIGV4cGVyaW1lbnQgb3AgbW9ldGVuIHpldHRlbiBvbSBtZXRpbmdlbiBiaWogbWFubmVuIGVuIHZyb3V3ZW4gdGUgZG9lbi4KCi0gVmVyb25kZXJzdGVsIGRhdCB3ZSBidWRnZXQgaGViYmVuIG9tIG1ldGluZ2VuIGJpaiA1IG1hbm5lbiBlbiA1IHZyb3V3ZW4gdGUgZG9lbi4KCi0gV2Ugem91ZGVuIGRhbiA1IG1hbm5lbiBlbiA1IHZyb3V3ZW4gYm92ZW4gZGUgMTggamFhciBhdCByYW5kb20gc2VsZWN0ZXJlbiB1aXQgZGUgQW1lcmlrYWFuc2UgcG9wdWxhdGllLgoKLSBXZSBrdW5uZW4gZGl0IGV4cGVyaW1lbnQgc2ltdWxlcmVuIGRvb3IgNSB2cm91d2VuIGVuIDUgbWFubmVuIGF0IHJhbmRvbSB0ZSBzZWxlY3RlcmVuIHVpdCBkZSBOSEFORVMgc3R1ZGllLgoKLS0tCgpgYGB7cn0Kc2V0LnNlZWQoMTAyMykKblNhbXAgPC0gNQpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXI9PSJmZW1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplPTUpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXI9PSJtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZT01KQoKc2FtcDEgPC0gcmJpbmQoZmVtLG1hbCkKCnNhbXAxCmBgYAoKLS0tCgpEYXRhIEV4cGxvcmF0aWUKCmBgYHtyfQpzYW1wMSAlPiUKICBnZ3Bsb3QoYWVzKHg9SGVpZ2h0KSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIGZhY2V0X2dyaWQoR2VuZGVyfi4pICsKICB4bGFiKCJMZW5ndGUgKGNtKSIpCgpIZWlnaHRTdW1FeHAxIDwtIHNhbXAxICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplX2F0KCJIZWlnaHQiLAogICAgICAgICAgICAgICBsaXN0KG1lYW4gPSBtZWFuLAogICAgICAgICAgICAgICAgICAgICAgc2QgPSBzZCkKICAgICAgICAgICAgICAgICAgKQpIZWlnaHRTdW1FeHAxCmBgYAoKSGlzdG9ncmFtIGlzIG5pZXQgemludm9sIGFscyB3ZSBtYWFyIHpvIHdlaW5pZyBkYXRhcHVudGVuIGhlYmJlbi4KCi0tLQoKCkJveHBsb3QgaXMgYmV0ZXI6CgpgYGB7ciBlY2hvPUZBTFNFfQpzYW1wMSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIseSA9IEhlaWdodCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9ICJqaXR0ZXIiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyh4ID0gMSwgeSA9IEhlaWdodFN1bUV4cDEkbWVhblsxXSksCiAgICBzaXplID0gMywKICAgIHBjaCA9IDE3LAogICAgY29sb3I9ImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyh4ID0gMiwgeSA9IEhlaWdodFN1bUV4cDEkbWVhblsyXSksCiAgICBzaXplID0gMywKICAgIHBjaCA9IDE3LAogICAgY29sb3IgPSAiZGFya3JlZCIpICsKICB5bGFiKCJIZWlnaHQgKGNtKSIpCmBgYAoKLS0tCgpXZSB2b2VyZW4gaGllciBvb2sgZWVuIHQtdGVzdCB1aXQuCgpgYGB7cn0KdC50ZXN0KEhlaWdodH5HZW5kZXIsZGF0YT1zYW1wMSkKYGBgCgpJbiBoZXQgZXhwZXJpbWVudCB6aWpuIHZyb3V3ZW4gZ2VtaWRkZWxkIGByIHJvdW5kKGFicyhIZWlnaHRTdW1FeHAxJG1lYW5bMV0tSGVpZ2h0U3VtRXhwMSRtZWFuWzJdKSwyKWAgY20gYHIgaWZlbHNlKEhlaWdodFN1bUV4cDEkbWVhblsxXT5IZWlnaHRTdW1FeHAxJG1lYW5bMl0sImdyb3RlciIsImtsZWluZXIiKWAgZGFuIG1hbm5lbi4gRW4gYWxzIHdlIGVlbiBzdGF0aXN0aXNjaGUgdGVzdCB1aXR2b2VyZW4gKHppZSBob29mZHN0dWsgNTogU3RhdGlzdGlzY2hlIGJlc2x1aXR2b3JtaW5nKSBrdW5uZW4gd2UgYmVzbHVpdGVuIGRhdCBkaXQgdmVyc2NoaWwgc3RhdGlzdGlzY2ggYHIgaWZlbHNlKHQudGVzdChIZWlnaHR+R2VuZGVyLHNhbXAxKSRwLnZhbHVlIDwgMC4wNSwic2lnbmlmaWNhbnQiLCJuaWV0IHNpZ25pZmljYW50IilgIGlzLgoKLS0tCgojIyBIZXJoYWFsIGhldCBleHBlcmltZW50CgpBbHMgd2UgaGV0IGV4cGVyaW1lbnQgaGVyaGFsZW4gc2VsZWN0ZXJlbiB3ZSBhbmRlcmUgbWVuc2VuIGVuIHZlcmtyaWpnZW4gd2UgYW5kZXJlIHJlc3VsdGF0ZW4uCgoKYGBge3J9CnNldC5zZWVkKDEwMjQpCmZlbSA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlcj09ImZlbWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemU9NSkKCm1hbCA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlcj09Im1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplPTUpCgpzYW1wMiA8LSByYmluZChmZW0sbWFsKQoKSGVpZ2h0U3VtRXhwMiA8LSBzYW1wMiAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZV9hdCgiSGVpZ2h0IiwKICAgICAgICAgICAgICAgbGlzdChtZWFuPW1lYW4sCiAgICAgICAgICAgICAgICAgICAgc2Q9c2QpCiAgICAgICAgICAgICAgKQpIZWlnaHRTdW1FeHAyCgpzYW1wMiAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIseSA9IEhlaWdodCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9ICJqaXR0ZXIiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyh4ID0gMSwgeSA9IEhlaWdodFN1bUV4cDIkbWVhblsxXSksCiAgICBzaXplID0gMywKICAgIHBjaCA9IDE3LAogICAgY29sb3I9ImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyh4ID0gMiwgeSA9IEhlaWdodFN1bUV4cDIkbWVhblsyXSksCiAgICBzaXplID0gMywKICAgIHBjaCA9IDE3LAogICAgY29sb3IgPSAiZGFya3JlZCIpICsKICB5bGFiKCJIZWlnaHQgKGNtKSIpCgp0LnRlc3QoSGVpZ2h0IH4gR2VuZGVyLCBkYXRhPXNhbXAyKQpgYGAKCgpJbiBkZSBuaWV1d2Ugc3RlZWtwcm9lZiB6aWpuIHZyb3V3ZW4gZ2VtaWRkZWxkIGByIHJvdW5kKGFicyhIZWlnaHRTdW1FeHAyJG1lYW5bMV0tSGVpZ2h0U3VtRXhwMiRtZWFuWzJdKSwyKWAgY20gYHIgaWZlbHNlKEhlaWdodFN1bUV4cDIkbWVhblsxXT5IZWlnaHRTdW1FeHAyJG1lYW5bMl0sImdyb3RlciIsImtsZWluZXIiKWAgZGFuIG1hbm5lbi4gRW4gZGl0IHZlcnNjaGlsIGlzIHN0YXRpc3Rpc2NoIGByIGlmZWxzZSh0LnRlc3QoSGVpZ2h0fkdlbmRlcixzYW1wMix2YXIuZXF1YWw9VFJVRSkkcC52YWx1ZSA8IDAuMDUsInNpZ25pZmljYW50IiwibmlldCBzaWduaWZpY2FudCIpYAoKCi0tLQoKIyMgSGVyaGFhbCBoZXQgZXhwZXJpbWVudCBvcG5pZXV3CgpgYGB7cn0Kc2VlZCA8LSA4ODYwNQpzZXQuc2VlZChzZWVkKQpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXI9PSJmZW1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplPTUpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXI9PSJtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZT01KQoKc2FtcDMgPC0gcmJpbmQoZmVtLG1hbCkKCkhlaWdodFN1bUV4cDMgPC0gc2FtcDMgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemVfYXQoIkhlaWdodCIsCiAgICAgICAgICAgICAgIGxpc3QobWVhbj1tZWFuLAogICAgICAgICAgICAgICAgICAgIHNkPXNkKQogICAgICAgICAgICAgICkKSGVpZ2h0U3VtRXhwMwoKc2FtcDMgJT4lCiAgZ2dwbG90KGFlcyh4ID0gR2VuZGVyLHkgPSBIZWlnaHQpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSAiaml0dGVyIikgKwogIGdlb21fcG9pbnQoCiAgICBhZXMoeCA9IDEsIHkgPSBIZWlnaHRTdW1FeHAzJG1lYW5bMV0pLAogICAgc2l6ZSA9IDMsCiAgICBwY2ggPSAxNywKICAgIGNvbG9yPSJkYXJrcmVkIikgKwogIGdlb21fcG9pbnQoCiAgICBhZXMoeCA9IDIsIHkgPSBIZWlnaHRTdW1FeHAzJG1lYW5bMl0pLAogICAgc2l6ZSA9IDMsCiAgICBwY2ggPSAxNywKICAgIGNvbG9yID0gImRhcmtyZWQiKSArCiAgeWxhYigiSGVpZ2h0IChjbSkiKQoKdC50ZXN0KEhlaWdodCB+IEdlbmRlciwgZGF0YT1zYW1wMykKYGBgCgpJbiBkZSBuaWV1d2Ugc3RlZWtwcm9lZiB6aWpuIHZyb3V3ZW4gZ2VtaWRkZWxkIGByIHJvdW5kKGFicyhIZWlnaHRTdW1FeHAzJG1lYW5bMV0tSGVpZ2h0U3VtRXhwMyRtZWFuWzJdKSwyKWAgY20gYHIgaWZlbHNlKEhlaWdodFN1bUV4cDMkbWVhblsxXT5IZWlnaHRTdW1FeHAzJG1lYW5bMl0sImdyb3RlciIsImtsZWluZXIiKWAgZGFuIG1hbm5lbi4gRW4gZGl0IHZlcnNjaGlsIGlzIHN0YXRpc3Rpc2NoIGByIGlmZWxzZSh0LnRlc3QoSGVpZ2h0fkdlbmRlcixzYW1wMyx2YXIuZXF1YWw9VFJVRSkkcC52YWx1ZSA8IDAuMDUsInNpZ25pZmljYW50IiwibmlldCBzaWduaWZpY2FudCIpYAoKLS0tCgojIyBTYW1lbnZhdHRpbmcKCi0gV2UgdHJva2tlbiBhdCByYW5kb20gYW5kZXJlIHByb2VmcGVyc29uZW4gaW4gZWxrZSBzdGVla3Byb2VmCgotIEhpZXJkb29yIHZlcnNjaGlsbGVuIGxlbmd0ZW1ldGluZ2VuIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmLgoKLSBEdXMgb29rIGRlIGdlc2NoYXR0ZSBnZW1pZGRlbGRlcyBlbiBzdGFuZGFhcmQgZGV2aWF0aWVzLgoKLSBCaWpnZXZvbGcgemlqbiBvbnplIGNvbmNsdXNpZXMgb29rIG9uemVrZXIgZW4ga3VubmVuIGRlemUgd2lqemlnZW4gdmFuIHN0ZWVrcHJvZWYgdG90IHN0ZWVrcHJvZWYuCgotIFZvb3IgaGV0IGxlbmd0ZSB2b29yYmVlbGQgemlqbiBzdGVla3Byb2V2ZW4gd2FhcmJpaiBoZXQgZWZmZWN0IHRlZ2VuZ2VzdGVsZCBpcyBhYW4gZGF0IGluIGRlIHBvcHVsYXRpZSBlbiB3YWFyYmlqIHdlIGJlc2x1aXRlbiBkYXQgaGV0IHZlcnNjaGlsIHNpZ25pZmljYW50IGVjaHRlciB6ZWxkemFhbS4KCiRccmlnaHRhcnJvdyQgTWV0IHN0YXRpc3RpZWsgY29udHJvbGVyZW4gd2UgZGUga2FucyBvcCBoZXQgdHJla2tlbiBmb3V0ZSBjb25jbHVzaWVzLgoKIyMgQ29udHJvbGUgdmFuIGZvdXRlbgoKSG9lIGNvbnRyb2xlZXJ0IHN0YXRpc3RpZWsgZGUga2FucyBvcCBoZXQgdHJla2tlbiB2YW4gZm91dGUgY29uY2x1c2llcz8KCi0gSW4gb25kZXJzdGFhbmRlIGNvZGUgdHJla2tlbiB3ZSAxMDAwMCBoZXJoYWFsZGUgc3RlZWtwcm9ldmVuIHZhbiA1IHZyb3V3ZW4gZW4gNSBtYW5uZW4gdWl0IGRlIE5IQU5FUyBzdHVkaWUuCgpgYGB7cn0Kc2V0LnNlZWQoMTUxNTIpCiMgQWFudGFsIHNpbXVsYXRpZXMgZW4gc3RlZWtwcm9lZmdyb290dGUgcGVyIGdyb2VwCm5TaW0gPC0gMTAwMDAKblNhbXAgPC0gNQoKIyBXZSBmaWx0ZXJlbiBkZSBkYXRhIHZvb3JhZiB6b2RhdCB3ZSBkaXQgbmlldCB0ZWxrZW5zIG9wbmlldXcgaG9ldmVuIHRlIGRvZW4KZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJmZW1hbGUiKQoKbWFsIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJtYWxlIikKCiMgU2ltdWxhdGllIHN0dWRpZQojIE9tIHNuZWxsZSBmdW5jdGllcyB0ZSBrdW5uZW4gZ2VicnVpa2VuIG5lbWVuIHdlIGVlcnN0IG5TaW0gc3RlZWtwcm9ldmVuIGVuIGJlcmVrZW5lbiB3ZSBkYWFybmEgYWxsZXMuCgpmZW1TYW1wcyA8LSBtYWxTYW1wcyA8LW1hdHJpeChOQSwgbnJvdz1uU2FtcCwgbmNvbD1uU2ltKQpmb3IgKGkgaW4gMTpuU2ltKQp7CiAgZmVtU2FtcHNbLGldIDwtIHNhbXBsZShmZW0kSGVpZ2h0LCBuU2FtcCkKICBtYWxTYW1wc1ssaV0gPC0gc2FtcGxlKG1hbCRIZWlnaHQsIG5TYW1wKQp9CgpyZXMgPC0gZGF0YS5mcmFtZSgKICB2ZXJzY2hpbD1jb2xNZWFucyhmZW1TYW1wcykgLSBjb2xNZWFucyhtYWxTYW1wcyksCiAgUmZhc3Q6OnR0ZXN0cyhmZW1TYW1wcywgbWFsU2FtcHMpCiAgKQoKc3VtKHJlcyRwdmFsdWUgPCAwLjA1ICYgcmVzJHZlcnNjaGlsIDwgMCkKc3VtKHJlcyRwdmFsdWUgPj0gMC4wNSkKc3VtKHJlcyRwdmFsdWUgPCAwLjA1ICYgcmVzJHZlcnNjaGlsPjApCgpyZXMgJT4lCiAgZ2dwbG90KGFlcyh4PXZlcnNjaGlsLHk9LWxvZzEwKHB2YWx1ZSksY29sb3I9cHZhbHVlIDwgMC4wNSkpICsKICBnZW9tX3BvaW50KCkgKwogIHhsYWIoIkdlbWlkZGVsZCBWZXJzY2hpbCAoY20pIikgKwogIHlsYWIoIlN0YXRpc3Rpc2NoZSBTaWduaWZpY2FudGllICgtbG9nMTAgcCkiKQoKcmVzICU+JQogIGdncGxvdChhZXMoeSA9IHZlcnNjaGlsKSkgKwogIGdlb21fYm94cGxvdCgpICsKICB5bGFiKCJHZW1pZGRlbGQgVmVyc2NoaWwgKGNtKSIpCiAgeGxhYigiIikKYGBgCgpPcCBiYXNpcyB2YW4gMTAwMDAgc3RlZWtwcm9ldmVuIHZhbiA1IG1hbm5lbiBlbiA1IHZyb3V3ZW4gemFnZW4gd2UgZGF0IGluIGByIHN1bShyZXMkcHZhbHVlPDAuMDUmcmVzJHZlcnNjaGlsPDApYCBzdGVla3Byb2V2ZW4gdnJvdXdlbiBnZW1pZGRlbGQgc2lnbmlmaWNhbnQga2xlaW5lciB6aWpuIGRhbiBtYW5uZW4uIEluIGByIHN1bShyZXMkcHZhbHVlPj0wLjA1KWAgc3RlZWtwcm9ldmVuIGJlc2x1aXRlbiB3ZSBkYXQgdnJvdXdlbiBlbiBtYW5uZW4gZ2VtaWRkZWxkIG5pZXQgc2lnbmlmaWNhbnQgdmVyc2NoaWxsZW4gaW4gbGVuZ3RlLiBFbiBpbiBgciBzdW0ocmVzJHB2YWx1ZTwwLjA1JnJlcyR2ZXJzY2hpbD4wKWAgYmVzbHVpdGVuIHdlIGRhdCB2cm91d2VuIGdlbWlkZGVsZCBzaWduaWZpY2FudCBncm90ZXIgemlqbiBkYW4gbWFubmVuLgoKLSBEZSBzdGVla3Byb2VmIGRpZSB3ZSB0b29uZGVuIHdhYXJ1aXQgd2Ugem91ZGVuIGJlc2x1aXRlbiBkYXQgdnJvdXdlbiBzaWduaWZpY2FudCBncm90ZXIgemlqbiBkYW4gbWFubmVuIGlzIGhlZWwgb253YWFyc2NoaWpubGlqay4gRXIgbW9lc3RlbiBgciBwYXN0ZShzZWVkKWAgc3RlZWtwcm9ldmVuIHdvcmRlbiBnZXRyb2trZW4gb20gZGV6ZSBleHRyZW1lIHN0ZWVrcHJvZWYgdGUgdmluZGVuLgoKSGV0IGZlaXQgZGF0IHdlIGluIHZlZWwgc3RlZWtwcm9ldmVuIHJlc3VsdGF0ZW4gdmluZGVuIGRpZSBzdGF0aXN0aXNjaCBuaWV0IHNpZ25pZmljYW50IHppam4ga29tdCBvbWRhdCBkZSBzdGF0aXN0aXNjaGUgdG9ldHMgZWVuIHRlIGxhZ2Uga3JhY2h0IGhlZWZ0IG9tIGhldCB2ZXJzY2hpbCB0ZSBkZXRlY3RlcmVuIHdhbm5lZXIgZXIgbWFhciA1IG9ic2VydmF0aWVzIHppam4gcGVyIGdyb2VwLgoKLS0tCgojIyMgR3JvdGVyZSBzdGVla3Byb2VmPwoKV2F0IGdlYmV1cnQgZXIgYWxzIHdlIGRlIHN0ZWVrcHJvZWYgdmVyaG9nZW4gbmFhciA1MCBvYnNlcnZhdGllcyBwZXIgZ3JvZXA/CgoKYGBge3J9CnNldC5zZWVkKDExMTQ1KQojIEFhbnRhbCBzaW11bGF0aWVzIGVuIHN0ZWVrcHJvZWZncm9vdHRlIHBlciBncm9lcApuU2ltIDwtIDEwMDAwCm5TYW1wIDwtIDUwCgojIFdlIGZpbHRlcmVuIGRlIGRhdGEgdm9vcmFmIHpvZGF0IHdlIGRpdCBuaWV0IHRlbGtlbnMgb3BuaWV1dyBob2V2ZW4gdGUgZG9lbgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIm1hbGUiKQoKIyBTaW11bGF0aWUgc3R1ZGllCiMgT20gc25lbGxlIGZ1bmN0aWVzIHRlIGt1bm5lbiBnZWJydWlrZW4gbmVtZW4gd2UgZWVyc3QgblNpbSBzdGVla3Byb2V2ZW4gZW4gYmVyZWtlbmVuIHdlIGRhYXJuYSBhbGxlcy4KCmZlbVNhbXBzIDwtIG1hbFNhbXBzIDwtIG1hdHJpeChOQSwgbnJvdyA9IG5TYW1wLCBuY29sID0gblNpbSkKZm9yIChpIGluIDE6blNpbSkKewogIGZlbVNhbXBzWyxpXSA8LSBzYW1wbGUoZmVtJEhlaWdodCwgblNhbXApCiAgbWFsU2FtcHNbLGldIDwtIHNhbXBsZShtYWwkSGVpZ2h0LCBuU2FtcCkKfQoKcmVzIDwtIGRhdGEuZnJhbWUoCiAgdmVyc2NoaWwgPSBjb2xNZWFucyhmZW1TYW1wcykgLSBjb2xNZWFucyhtYWxTYW1wcyksCiAgUmZhc3Q6OnR0ZXN0cyhmZW1TYW1wcywgbWFsU2FtcHMpCiAgKQoKc3VtKHJlcyRwdmFsdWUgPCAwLjA1ICYgcmVzJHZlcnNjaGlsIDwgMCkKc3VtKHJlcyRwdmFsdWUgPj0gMC4wNSkKc3VtKHJlcyRwdmFsdWUgPCAwLjA1ICYgcmVzJHZlcnNjaGlsID4gMCkKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHg9dmVyc2NoaWwseT0tbG9nMTAocHZhbHVlKSxjb2xvcj1wdmFsdWU8MC4wNSkpICsKICBnZW9tX3BvaW50KCkgKwogIHhsYWIoIkdlbWlkZGVsZCBWZXJzY2hpbCAoY20pIikgKwogIHlsYWIoIlN0YXRpc3Rpc2NoZSBTaWduaWZpY2FudGllICgtbG9nMTAgcCkiKQoKcmVzICU+JQogIGdncGxvdChhZXMoeT12ZXJzY2hpbCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgeWxhYigiR2VtaWRkZWxkIFZlcnNjaGlsIChjbSkiKQogIHhsYWIoIiIpCmBgYAoKLSBXZSB6aWVuIGR1cyBkYXQgd2UgZGUga2FucyBvbSBlZW4gdmVyc2NoaWwgdGUgdmluZGVuIGFscyBlciBpbiB3ZXJrZWxpamtoZWlkIGVlbiB2ZXJzY2hpbCBpcyBpbiBkZSBwb3B1bGF0aWUga3VubmVuIGJlw69udmxvZWRlbiBpbiBkZSBkZXNpZ24gZmFzZTogYWFuIGRlIGhhbmQgdmFuIGRlIHN0ZWVrcHJvZWZncm9vdHRlLgoKLSBIb2UgbWVlciBnZWdldmVucyBob2UgbWFra2VsaWprZXIgd2UgaGV0IHdlcmtlbGlqayB2ZXJzY2hpbCBvcHBpa2tlbiBpbiBkZSBzdGVla3Byb2VmLgoKCiMjIyBDb250cm9sZSB2YW4gdmFscyBwb3NpdGlldmVuCgpXYXQgZ2ViZXVydCBlciBhbHMgZXIgZ2VlbiB2ZXJzY2hpbCBpcyB0dXNzZW4gYmVpZGUgZ3JvZXBlbj8KCi0gV2UgbW9ldGVuIGhpZXJ2b29yIGV4cGVyaW1lbnRlbiBzaW11bGVyZW4gd2FhcmJpaiBkZSBncm9lcGVuIGdlbGlqayB6aWpuLiAgCgotIEhpZXJ2b29yIHp1bGxlbiB3ZSB0d2VlIGdyb2VwZW4gdmVyZ2VsaWprZW4gd2FhcnZvb3IgZGUgbGVuZ3RlIGdlbWlkZGVsZCBuaWV0IHZlcnNjaGlsbGVuZCBpcy4KCi0gRGF0IGt1bm5lbiB3ZSBkb2VuIGRvb3IgZWVuIHN0ZWVrcHJvZWYgdGUgdHJla2tlbiB3YWFyYmlqIHdlIHZvb3IgYmVpZGUgZ3JvZXBlbiBhdCByYW5kb20gc3ViamVjdGVuIHRyZWtrZW4gdWl0IGRlIHN1YnNldCB2YW4gdnJvdXdlbiBpbiBkZSBOSEFORVMgc3R1ZGllLgoKLSBXZSBkb2VuIGRpdCBvcG5pZXV3IHZvb3IgZWVuIHN0ZWVrcHJvZWYgbWV0IDUgc3ViamVjdGVuIHBlciBncm9lcAoKCmBgYHtyfQpzZXQuc2VlZCgxMzI0NSkKIyBBYW50YWwgc2ltdWxhdGllcyBlbiBzdGVla3Byb2VmZ3Jvb3R0ZSBwZXIgZ3JvZXAKblNpbSA8LSAxMDAwMApuU2FtcCA8LSA1CgojIFdlIGZpbHRlcmVuIGRlIGRhdGEgdm9vcmFmIHpvZGF0IHdlIGRpdCBuaWV0IHRlbGtlbnMgb3BuaWV1dyBob2V2ZW4gdGUgZG9lbgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpCgojIFNpbXVsYXRpZSBzdHVkaWUKIyBPbSBzbmVsbGUgZnVuY3RpZXMgdGUga3VubmVuIGdlYnJ1aWtlbiBuZW1lbiB3ZSBlZXJzdCBuU2ltIHN0ZWVrcHJvZXZlbiBlbiBiZXJla2VuZW4gd2UgZGFhcm5hIGFsbGVzLgoKZmVtU2FtcHMgPC0gZmVtU2FtcHMyIDwtbWF0cml4KE5BLCBucm93PW5TYW1wLCBuY29sPW5TaW0pCmZvciAoaSBpbiAxOm5TaW0pCnsKICBmZW1TYW1wc1ssaV0gPC0gc2FtcGxlKGZlbSRIZWlnaHQsIG5TYW1wKQogIGZlbVNhbXBzMlssaV0gPC0gc2FtcGxlKGZlbSRIZWlnaHQsIG5TYW1wKQp9CgpyZXMgPC0gZGF0YS5mcmFtZSgKICB2ZXJzY2hpbD1jb2xNZWFucyhmZW1TYW1wcykgLSBjb2xNZWFucyhmZW1TYW1wczIpLAogIFJmYXN0Ojp0dGVzdHMoZmVtU2FtcHMsIGZlbVNhbXBzMikKICApCgpzdW0ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWwgPCAwKQpzdW0ocmVzJHB2YWx1ZSA+PSAwLjA1KQpzdW0ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWw+MCkKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHg9dmVyc2NoaWwseT0tbG9nMTAocHZhbHVlKSxjb2xvcj1wdmFsdWUgPCAwLjA1KSkgKwogIGdlb21fcG9pbnQoKSArCiAgeGxhYigiR2VtaWRkZWxkIFZlcnNjaGlsIChjbSkiKSArCiAgeWxhYigiU3RhdGlzdGlzY2hlIFNpZ25pZmljYW50aWUgKC1sb2cxMCBwKSIpCgpyZXMgJT4lCiAgZ2dwbG90KGFlcyh5ID0gdmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkdlbWlkZGVsZCBWZXJzY2hpbCAoY20pIikKICB4bGFiKCIiKQpgYGAKCk9wIGJhc2lzIHZhbiAxMDAwMCBzdGVla3Byb2V2ZW4gemllbiB3ZSBkYXQgd2UgaW4gYHIgc3VtKHJlcyRwdmFsdWU8MC4wNSlgIHN0ZWVrcHJvZXZlbiB0ZW4gb25yZWNodGUgYmVzbHVpdGVuIGRhdCBlciBlZW4gdmVyc2NoaWwgaXMgaW4gZ2VtaWRkZWxkZSBsZW5ndGUgdHVzc2VuIHR3ZWUgZ3JvZXBlbiB2cm91d2VuLgoKTWV0IGRlIHN0YXRpc3Rpc2NoZSBhbmFseXNlIGNvbnRyb2xlcmVuIHdlIGR1cyBoZXQgYWFudGFsIHZhbHMgcG9zaXRpZXZlIHJlc3VsdGF0ZW4gY29ycmVjdCBvcCA1JS4KCipXYXQgZ2ViZXVydCBlciBhbHMgd2UgaGV0IGFhbnRhbCBvYnNlcnZhdGllcyB2ZXJob2dlbj8qCgpXZSBzaW11bGVyZW4gb3BuaWV1dyBleHBlcmltZW50ZW4gbWV0IDUwIHN1YmplY3RlbiBwZXIgZ3JvZXAgbWFhciB3ZSB0cmVra2VuIGRlIHN1YmplY3RlbiBvcG5pZXV3IHRlbGtlbnMgdWl0IGRlIHBvcHVsYXRpZSB2YW4gdnJvdXdlbi4KCmBgYHtyfQpzZXQuc2VlZCgxMzQ1KQojIEFhbnRhbCBzaW11bGF0aWVzIGVuIHN0ZWVrcHJvZWZncm9vdHRlIHBlciBncm9lcApuU2ltIDwtIDEwMDAwCm5TYW1wIDwtIDUwCgojIFdlIGZpbHRlcmVuIGRlIGRhdGEgdm9vcmFmIHpvZGF0IHdlIGRpdCBuaWV0IHRlbGtlbnMgb3BuaWV1dyBob2V2ZW4gdGUgZG9lbgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpCgojIFNpbXVsYXRpZSBzdHVkaWUKIyBPbSBzbmVsbGUgZnVuY3RpZXMgdGUga3VubmVuIGdlYnJ1aWtlbiBuZW1lbiB3ZSBlZXJzdCBuU2ltIHN0ZWVrcHJvZXZlbiBlbiBiZXJla2VuZW4gd2UgZGFhcm5hIGFsbGVzLgoKZmVtU2FtcHMgPC0gZmVtU2FtcHMyIDwtbWF0cml4KE5BLCBucm93PW5TYW1wLCBuY29sPW5TaW0pCmZvciAoaSBpbiAxOm5TaW0pCnsKICBmZW1TYW1wc1ssaV0gPC0gc2FtcGxlKGZlbSRIZWlnaHQsIG5TYW1wKQogIGZlbVNhbXBzMlssaV0gPC0gc2FtcGxlKGZlbSRIZWlnaHQsIG5TYW1wKQp9CgpyZXMgPC0gZGF0YS5mcmFtZSgKICB2ZXJzY2hpbD1jb2xNZWFucyhmZW1TYW1wcykgLSBjb2xNZWFucyhmZW1TYW1wczIpLAogIFJmYXN0Ojp0dGVzdHMoZmVtU2FtcHMsIGZlbVNhbXBzMikKICApCgpzdW0ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWwgPCAwKQpzdW0ocmVzJHB2YWx1ZSA+PSAwLjA1KQpzdW0ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWw+MCkKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHg9dmVyc2NoaWwseT0tbG9nMTAocHZhbHVlKSxjb2xvcj1wdmFsdWUgPCAwLjA1KSkgKwogIGdlb21fcG9pbnQoKSArCiAgeGxhYigiR2VtaWRkZWxkIFZlcnNjaGlsIChjbSkiKSArCiAgeWxhYigiU3RhdGlzdGlzY2hlIFNpZ25pZmljYW50aWUgKC1sb2cxMCBwKSIpCgpyZXMgJT4lCiAgZ2dwbG90KGFlcyh5ID0gdmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkdlbWlkZGVsZCBWZXJzY2hpbCAoY20pIikKICB4bGFiKCIiKQpgYGAKCgpPcCBiYXNpcyB2YW4gMTAwMDAgc3RlZWtwcm9ldmVuIHppZW4gd2UgZGF0IHdlIGluIGByIHN1bShyZXMkcHZhbHVlPDAuMDUpYCBzdGVla3Byb2V2ZW4gdGVuIG9ucmVjaHRlIGJlc2x1aXRlbiBkYXQgZXIgZWVuIHZlcnNjaGlsIGlzIGluIGdlbWlkZGVsZGUgbGVuZ3RlIHR1c3NlbiB0d2VlIGdyb2VwZW4gdnJvdXdlbi4KCk1ldCBkZSBzdGF0aXN0aXNjaGUgYW5hbHlzZSBjb250cm9sZXJlbiB3ZSBkdXMgb29rIGJpaiBoZXQgbmVtZW4gdmFuIGVlbiBncm90ZSBzdGVla3Byb2VmIGhldCBhYW50YWwgdmFscyBwb3NpdGlldmUgcmVzdWx0YXRlbiBjb3JyZWN0IG9wIDUlIChWYWxzIHBvc2l0aWVmOiBPcCBiYXNpcyB2YW4gZGUgc3RlZWtwcm9lZiBiZXNsdWl0ZW4gZGF0IGVyIGdlbWlkZGVsZCBlZW4gdmVyc2NoaWwgaXMgaW4gbGVuZ3RlIHR1c3NlbiBiZWlkZSBncm9lcGVuIHRlcndpamwgZXIgaW4gd2Vya2VsaWpraGVpZCBnZWVuIHZlcnNjaGlsIGlzIGluIGRlIHBvcHVsYXRpZS4pCgojIyMgQ29uY2x1c2llcwoKIC0gRGUgc3RhdGlzdGlzY2hlIGFuYWx5c2UgY29udHJvbGVlcnQgc3RlZWRzIGRlIGthbnMgb3AgaGV0IG5lbWVuIHZhbiBlZW4gdmFscyBwb3NpdGlldmUgY29uY2x1c2llLgoKIC0gRGUgc3RhdGlzdGlzY2hlIGFuYWx5c2lzIGNvbnRyb2xlZXJ0IGRlIGthbnMgb3AgaGV0IG5lbWVuIHZhbiBlZW4gdmFscyBuZWdhdGlldmUgY29uY2x1c2llcyBuaWV0LCBtYWFyIGluIGRlIGRlc2lnbiBmYXNlIGt1bm5lbiB3ZSBkZXplIGthbnMgYmXDr252bG9lZGVuIG9uZGVybWVlciBkLm0udi4gZGUgc3RlZWtwcm9lZmdyb290dGUuCgotLS0KCiNDYXNlIHN0dWR5OiBTYWxrIHZhY2NpbgoKLSBJbiAxOTE2LCBicmFrIGRlIGVlcnN0ZSBncm90ZSBwb2xpbyBlcGlkZW1pZSB1aXQgaW4gZGUgVVNBLgotIEJlZ2luIGRlIGphcmVuIDUwIG9udHdpa2tlbGRlIEpvaG4gU2FsayBlZW4gdmFjY2luIG1ldCBiZWxvdmVuZGUgcmVzdWx0YXRlbiBpbiBoZXQgbGFiLgotIEluIDE5NTQsIGhlZWZ0IGRlIE5hdGlvbmFsIEZvdW5kYXRpb24KZm9yIEluZmFudGlsZSBQYXJhbHlzaXMgKE5GSVApIGVlbiBncm90ZSBzdHVkaWUgb3BnZXpldCBvbSBkZSBlZmZlY3Rpdml0ZWl0IHZhbiBoZXQgU2FsayB2YWNjaW4gbmEgdGUgZ2Fhbi4KLSBWZXJvbmRlcnN0ZWwgZGF0IGRlIE5GSVAgaW4gMTk1NCBlZW4gZ3Jvb3QgYWFudGFsIGtpbmRlcmVuIHpvdSBoZWJiZW4gZ2V2YWNjaW5lZXJkLCB3YXQgem91ZGVuIHplIGRhbiBrdW5uZW4gYmVzbHVpdGVuIGFscyBkZSBwb2xpbyBpbmNpZGVudGllIGluIDE5NTQgbGFnZXIgd2FzIGRhbiBpbiAxOTUzPwoKLS0tCgojIyBORklQIFN0dWR5CiMjIyBEZXNpZ24KCi0gR3JvdGUgc2ltdWx0YW5lIHN0dWRpZSBtZXQgZ2V2YWNjaW5lZXJkZSBraW5kZXJlbiAoY2FzZXMpIGVuIG9uZ2V2YWNjaW5lZXJkZSBraW5kZXJlbiAoY29udHJvbGVzKS4KLSBJbiBzY2hvbGVuIHZhbiBkaXN0cmljdGVuIG1ldCBob2dlIHBvbGlvIGluY2lkZW50aWUuCi0gQ2FzZXM6IGtpbmRlcmVuIHZhbiBkZSB0d2VlZGUgZ3JhYWQgdmFuIGhldCBsYWdlciBvbmRlcndpanMgd2FhcnZhbiBkZSBvdWRlcnMgdG9lc3RlbWRlbiBtZXQgdmFjY2luYXRpZS4KLSBDb250cm9sZXM6IGtpbmRlcmVuIHZhbiBkZSBlZXJzdGUgZW4gZGVyZGUgZ3JhYWQuCgojIyMgRGF0YQpgYGB7cn0KbmZpcCA8LSB0aWJibGUoCiAgZ3JvdXA9YygiY2FzZXMiLCJjb250cm9scyIsIm5vQ29uY2VudCIpLAogIGdyYWRlPWMoImcyIiwiZzFnMyIsImcyIiksCiAgdmFjY2luPWMoInllcyIsIm5vIiwibm8iKSwKICB0b3RhbD1jKDIyMTk5OCw3MjUxNzMsMTIzNjA1KSwKICBwb2xpbz1jKDU0LDM5MSw1NikKICApICU+JQogIG11dGF0ZShub1BvbGlvID0gdG90YWwgLSBwb2xpbykKa25pdHI6OmthYmxlKG5maXApCmBgYAoKVmVyZ2VsaWprIGRlIHBvbGlvIGluY2lkZW50aWU/CgotLS0KCmBgYHtyfQpuZmlwIDwtIG5maXAgJT4lCiAgbXV0YXRlKGluY2lkZW5jZVBNID0gcm91bmQobmZpcCRwb2xpby9uZmlwJHRvdGFsKjFlNiwwKSkKa25pdHI6OmthYmxlKG5maXApCmBgYAoKV2F0IGt1bm5lbiB3ZSBjb25jbHVkZXJlbj8KCi0tLQoKIyMgQ29uZm91bmRpbmcKCgpgYGB7cixlY2hvPUZBTFNFLCBmaWcuYWxpZ24gPSAiY2VudGVyIixvdXQud2lkdGggPSAnNTAlJ30KcGxvdChjKDAsMCwxKSxjKC0yLDIsMCkscGNoPWMoIlMiLCJWIiwiUCIpLHhheHQ9Im5vbmUiLHlheHQ9Im5vbmUiLGF4ZXM9RkFMU0UseGxhYj0iIix5bGFiPSIiLGNleD00LHlsaW09YygtMi4yLDIuMikpCmFycm93cyh4MD0wLjEseDE9LjkseTA9MS44LHkxPTAuMSxsd2Q9NCkKYXJyb3dzKHgwPTAuMSx4MT0uOSx5MD0tMS44LHkxPS0wLjIsbHdkPTQpCmFycm93cyh4MD0wLHgxPTAseTA9LTEuNCx5MT0xLjQsbHdkPTQpCmBgYAoKCi0gV2Ugb2JzZXJ2ZXJlbiBlZW4gbGFnZXJlIHBvbGlvIChQKSBpbmNpZGVudGllIHZvb3Iga2luZGVyZW4gYmlqIHdpZSBkZSBvdWRlcnMgZ2VlbiB0b2VzdGVtbWluZyBnYXZlbiBkYW4gaW4gZGUgY29udHJvbGUgZ3JvZXAuICAKCi0gVG9lc3RlbW1pbmcgdm9vciB2YWNjaW5hdGllIChWKSBpcyBnZWFzc29jaWVlcmQgbWV0IGRlIHNvY2lvLWVjb25vbWlzY2hlIHN0YXR1cyAoUykuCgotIEtpbmRlcmVuIHZhbiBsYWdlcmUgc29jaW8tZWNvbm9taXNjaGUgc3RhdHVzIHppam4gbWVlciByZXNpc3RlbnQgdGVnZW4gZGUgemlla3RlLgoKLSBEZSBncm9lcGVuIHZhbiBjYXNlcyBlbiBjb250cm9sZXMgemlqbiBuaWV0IHZlcmdlbGlqa2JhYXIKICAgIC0gdmVyc2NoaWwgaW4gbGVlZnRpamQKICAgIC0gdmVyc2NoaWwgaW4gc29jaW8tZWNvbm9taXNjaGUgc3RhdHVzIGVuCiAgICAtIHZlcnNjaGlsIGluIHZhdGJhYXJoZWlkIHZvb3IgZGUgemlla3RlLgoKLS0tCgojIyBTYWxrIFN0dWR5CgojIyMgRGVzaWduCkVlbiBuaWV1d2Ugc3R1ZGllIHdlcmQgdWl0Z2V2b2VyZDogZHViYmVsIGJsaW5kZSBnZXJhbmRvbWlzZWVyZGUgc3R1ZGllLgoKICAtIEtpbmRlcmVuIHdvcmRlbiBhdCByYW5kb20gdG9lZ2V3ZXplbiBhYW4gY29udHJvbGUgb2YgY2FzZSBhcm0gdmFuIGhldCBleHBlcmltZW50IG5hZGF0IGRlIG91ZGVycyB0b2VzdGVtZGVuIG1ldCB2YWNjaW5hdGllLgogIC0gQ29udHJvbGU6IHZhY2NpbmF0aWUgbWV0IHBsYWNlYm8KICAtIFRyZWF0bWVudDogdmFjY2luYXRpZSBtZXQgdmFjY2luCiAgLSBEb3VibGUgYmxpbmRpbmc6CiAgICAtIG91ZGVycyBlbiBraW5kZXJlbiB3ZXRlbiBuaWV0IG9mIHplIHdlcmRlbiBnZXZhY2NpbmVlcmQgb2YgbmlldAogICAgLSBtZWRpc2NoZSBzdGFmIGVuIG9uZGVyem9la2VycyB3ZXRlbiBuaWV0IG9mIGhldCBraW5kIGhldCB2YWNjaW4gb2YgZGUgcGxhY2VibyBrcmVlZwoKLS0tCgojIyMgRGF0YQoKYGBge3J9CnNhbGsgPC0gZGF0YS5mcmFtZSgKICBncm91cD1jKCJjYXNlcyIsImNvbnRyb2wiLCJub0NvbmNlbnQiKSwKICB0cmVhdG1lbnQ9YygidmFjY2luZSIsInBsYWNlYm8iLCJub25lIiksCiAgdG90YWw9YygyMDA3NDUsMjAxMjI5LCAzMzg3NzgpLHBvbGlvPWMoNTcsMTQyLDE1NykKICApICU+JQogIG11dGF0ZSgKICAgIG5vUG9saW8gPSB0b3RhbC1wb2xpbywKICAgIGluY2lkZW5jZVBNID0gcm91bmQocG9saW8vdG90YWwqMWU2LDApCiAgICApCmtuaXRyOjprYWJsZShzYWxrKQpgYGAKCi0gV2Ugb2JzZXJ2ZXJlbiBlZW4gdmVlbCBncm90ZXIgZWZmZWN0IG51IGRhdCBjYXNlcyBlbiBjb250cm9sZXMgdmVyZ2VsaWprYmFhciB6aWpuLCBpbmNpZGVudGllIHZhbiByZXNwZWN0aWV2ZWxpamsgYHIgc2FsayRpbmNpZGVuY2VQTVsxXWAgIGFuZCBgciBzYWxrJGluY2lkZW5jZVBNWzJdYCBwZXIgbWlsam9lbi4KCi0gRGUgcG9saW8gaW5jaWRlbnRpZSB2b29yIGtpbmRlcmVuIGRpZSBnZWVuIHRvZXN0ZW1taW5nIGdldmVuIGJsaWpmdCB2ZXJnZWxpamtiYWFyICBgciBuZmlwJGluY2lkZW5jZVBNWzNdYCBhbmQgYHIgc2FsayRpbmNpZGVuY2VQTVszXWAgcGVyIG1pbGpvZW4gcmVzcGVjdGlldmVsaWprIGluIHRoZSBORklQIGFuZCBTYWxrIHN0dWR5LgoKLS0tCgojIFJvbCB2YW4gU3RhdGlzdGllawoKLSBXZSBoZWJiZW4gZ2V6aWVuIGRhdAogICAgLSBoZXQgYmVsYW5ncmlqayBpcyBvbSBkZSBzY29wZSB2YW4gZGUgc3R1ZGllIGdvZWQgdGUgc3BlY2lmacOrcmVuIHZvb3IgZGUgc3RhcnQgdmFuIGhldCBleHBlcmltZW50CiAgICAtIHJhbmRvbWlzYXRpZSBub2RpZyBpcyBvbSBlZW4gcmVwcmVzZW50YXRpZXZlIHN0ZWVrcHJvZWYgdGUgbmVtZW4KICAgIC0gc3RlZWtwcm9lZiBncm9vdHRlIGlzIGhlZWwgYmVsYW5ncmlqawogICAgLSB3ZSBtb2V0ZW4gb25zIGJld3VzdCB6aWpuIHZhbiBDb25mb3VuZGluZwogICAgLSBlZW4gZ29lZGUgY29udHJvbGUgaXMgYmVsYW5ncmlqawoKCiRccmlnaHRhcnJvdyQgR29lZGUgcHJvZWZvcHpldCBpcyBjcnVjaWFhbCEKCi0tLQoKLSBXZSBoZWJiZW4gb29rIGdlb2JzZXJ2ZWVyZCBkYXQgZXIgdmFyaWFiaWxpdGVpdCBpcyBpbiBkZSBwb3B1bGF0aWUKLSBXZSBrdW5uZW4gbWFhciBlZW4gYmVwZXJrdGUgc3RlZWtwcm9lZiBuZW1lbiB1aXQgZGUgcG9wdWxhdGllCgokXHJpZ2h0YXJyb3ckIG9uemVrZXJoZWlkIGluIGRlIHJlc3VsdGF0ZW4KJFxyaWdodGFycm93JCBvbnpla2VyaGVpZCBpbiBkZSBjb25jbHVzaWVzCgoKLS0tCgotIFN0YXRpc3RpZWsgaXMgZGUgd2V0ZW5zY2hhcCB2b29yIGhldAogICAgMS4gdmVyemFtZWxlbiAoZXhwZXJpbWVudGVlbCBkZXNpZ24pLAogICAgMi4gZXhwbG9yZW4gKGRhdGEgZXhwbG9yYXRpb24pIGVuCiAgICAzLiBsZXJlbiB2YW4gZGF0YSB6b2RhdCB3ZSBoZXRnZWVuIHdlIG9ic2VydmVyZW4gaW4gZGUgc3RlZWtwcm9lZiB6b3VkZW4ga3VubmVuIHZlcmFsZ2VtZW5lbiBuYWFyIGRlIHBvcHVsYXRpZSB0ZXJ3aWpsIHdlIGRlIG9uemVrZXJoZWlkIHF1YW50aWZpY2VyZW4sIGNvbnRyb2xlcmVuIGVuIHJhcHBvcnRlcmVuIChzdGF0aXN0aXNjaCBtb2RlbGxlcmVuIGVuIHN0YXRpc3Rpc2NoZSBiZXNsdWl0dm9ybWluZykuCgotIFN0YXRpc3RpZWsgc3BlZWx0IGRhYXJvbSBlZW4gaGVlbCBiZWxhbmdyaWprZSByb2wgaW4gem93YXQgYWxsZSB3ZXRlbnNjaGFwcGVuCgoKIyBbSG9tZV0oaHR0cHM6Ly9zdGF0b21pY3MuZ2l0aHViLmlvL3NiYzIwKSB7LX0K