Waarom een niet-parametrische test?
Voor het project lossen jullie deze onderzoeksvraag op met behulp van parametrische ANOVA (de F-test). Dit is een geldige test als aan de assumpties voldaan wordt. Echter, hoe kleiner de dataset, hoe moeilijker het is om deze assumptie te controleren. Een mogelijke oplossing kan zijn om de Normaliteitsassumptie te checken op de volledige dataset aan de hand van een lineair model, zoals we hieronder doen.
#Lees de data in
dataset=read.csv("~/Dropbox/PhD/Onderwijs/Statistiek Biochemie/201819/dropboxStats1819/class6_nonPar/half/versgewicht_sla.txt",header=TRUE)
m <- lm(versgewicht ~ behandeling, data=dataset)
par(mfrow=c(2,2))
plot(m)
par(mfrow=c(1,1))

De QQ-plot is nogal twijfelachtig, en men zou beide kanten kunnen beargumenteren. Inderdaad, enerzijds kan men argumenteren dat de QQ-plot niet bijzonder sterk afwijkt van wat men zou verwachten op basis van een Normale distributie. Anderzijds, kan men argumenteren dat (i) de QQ-plot licht afwijkt, en (ii) we bovendien een Normale distributie moeten veronderstellen binnen elke groep, en de bovenstaande QQ-plot geen sluitend bewijs geeft. Zoals je ziet, is dit een dataset waarbij zowel de argumentatie voor een parametrische ANOVA test als de argumentatie voor een niet-parametrische Kruskal-Wallis test steek kan houden. De veilige optie is duidelijk de Kruskal-Wallis test, aangezien die geen parametrsiche assumpties veronderstelt. De enige veronderstelling is dat de data onafhankelijk zijn. Bovendien kan het, om een algemeen inzicht te verkrijgen, ook nuttig zijn om de resultaten te interpreteren in functie van de probabilistische index.
Stel dat de versgewichten van de planten geen Normale maar bvb een Gamma distributie volgen. Een gamma distributie heeft een aantal eigenschappen die ze een betere keuze zouden maken on gewichten te modelleren. Bijvoorbeeld, gewichten kunnen niet negatief zijn. Een normalie distributie kan negatief worden, maar een gamma distributie een ondergrens heeft bij nul.
x = seq(-1,10,.01)
ynorm = dnorm(x,2)
ygam = dgamma(x,5,2)
plot(x,ynorm,type = 'l')
lines(x,ygam,col = 'red')
abline(v = 0)
legend('topright',c('Normale', 'Gamma'),text.col = c('black','red'))
We zullen 9 samples van elk 7 datapunten genereren uit een normale distributie.
par(mfrow = c(3,3))
set.seed(11) ## zorgt ervoor dat bij herlopen van de code exact dezelfde 'random' waarden genereerd worden.
for(i in 1:9){
x = rnorm(7)
qqnorm(x, main = i)
qqline(x)
}
We zien in de QQ-plots dat de meeste samples normaal verdeeld lijken, terwijl sommigen toch niet-lineaire patronen vertonen (zoals QQ-plot 5) en dus misschien (incorrect) als niet normaal beoordeeld zouden worden.
We zullen nu 9 samples van elk 7 datapunten genereren uit een gamma distributie.
par(mfrow = c(3,3))
set.seed(11)
for(i in 1:9){
x = rgamma(7,5,2)
qqnorm(x, main = i)
qqline(x)
}
We zien in de QQ-plots (bijvoorbeeld QQ-plot 4) dat sommige stalen samples afwijken van een rechte wat correct tot de conlusie van niet-normaal verdeelde data zou leiden. Aan de andere kant hebben de datapunten in bvb QQ-plot 7 wel een linear verband en zou deze data incorrect wel als normaal verdeeld beschouwd kunnen worden.
Nu is de assumptie van normaliteit belangrijk bij ANOVA (en ook t-test) omdat men hier ervan uitgaat dat je steekproefgemiddelde normaal verdeeld is rond het populatiegemidelde. Als je data normaal verdeeld is, zal dit altijd het geval zijn. Als je data niet normaal verdeeld is, dan gaat dit alleen maar op als je dataset groot genoeg is (zie de Centrale Limietstelling in de cursus).
We illustreren dit met een simulatie. Een groot aantal datasets van elk 4 datapunten worden gegenereerd uit een normale verdeling. We bereken per dataset het gemiddelde en we construeren een QQ-plot van deze gemiddelden om te controleren of ze normaal verdeeld zijn. We herhalen dit, maar nu worden de 4 datapunten gegenereerd uit een Gamma distributie. Om het effect van dataset grootte te bestuderen zullen we ook datasets uit een Gamma distributie genereren van grootte 7 en 10.
set.seed(11)
samples_normaal = replicate(30000, mean(rnorm(4)))
samples_gamma_4 = replicate(30000, mean(rgamma(3,5,2)))
samples_gamma_7 = replicate(30000, mean(rgamma(7,5,2)))
samples_gamma_10 = replicate(30000, mean(rgamma(30,5,2)))
par(mfrow = c(2,2))
qqnorm(samples_normaal,pch = 20, main = 'normaal; n = 4')
qqline(samples_normaal, col = 'red')
qqnorm(samples_gamma_4, pch = 20, main = 'gamma; n = 4')
qqline(samples_gamma_4, col = 'red')
qqnorm(samples_gamma_7,pch = 20, main = 'gamma; n = 7')
qqline(samples_gamma_7, col = 'red')
qqnorm(samples_gamma_10,pch = 20, main = 'gamma; n = 30')
qqline(samples_gamma_10, col = 'red')
We zien in de QQ-plot linksboven dat de gemiddelden van de normaal verdeelde datasets inderdaad op een rechte liggen en dus normaal verdeeld lijken. Bij de gemiddelden van de gamma datasets met grootte 4 zien we duidelijke afwijken van de normaliteit (de distributie is scheef verdeeld naar links). Teststatistieken en p-waarden berekend met ANOVA en t-testen zijn in dat geval ongeldig.
In de onderste rij QQ-plots kan men zien dat hoe groter de steekproeven worden, hoe meer de gemiddelden een normale distributie benaderen. Bij grotere datasets zal dus men kunnen argumenteren dat het steekproefgemiddelde een normale verdeling volgt. Dit effect, waarbij de gemiddelden van een steekproef uit om het even welke distributie een normale distributie gaan benaderen als de steekproef maar groot genoeg is, noemt men de centrale limietstelling. Als je steekproef groot genoeg is, kan je dus de centrale limietstelling inroepen om de normaliteitsassumptie te aanvaarden.
Als er geen sterke argumenten om de normaliteitsassumptie te aanvaarden (bijvoorbeeld gelijkaardige grotere datasets in het verleden lijken normaal verdeeld), is het doorgaans veiliger om dit niet te doen en een niet-parametrische test te gebruiken.
Merk op: ook als de assumptie van homoscedasticiteit geschonden is of moeilijk kan worden nagegaan door een te kleine steekproef, zullen de teststatistieken en p-waarden vertekend zijn. Voor een t-test kan je nog gebruik maken van de Welch t-test, voor een ANOVA zal je bij zeer sterke afwijkingen van homoscedasticiteit ook een niet-parametrische test moeten gebruiken en je resulaten in termen van de probabilistische index moeten interpreteren.
Data analyse
We zullen nu de slaplanten dataset herevalueren en niet-parametrische testen overwegen.
#Lees de data in
dataset=read.csv("~/Dropbox/PhD/Onderwijs/Statistiek Biochemie/201819/dropboxStats1819/class6_nonPar/versgewicht_sla.txt",header=TRUE)
cannot open file '/Users/koenvandenberge/Dropbox/PhD/Onderwijs/Statistiek Biochemie/201819/dropboxStats1819/class6_nonPar/versgewicht_sla.txt': No such file or directoryError in file(file, "rt") : cannot open the connection
Dataverkenning
## Tel het aantal metingen per behandeling
table(dataset$behandeling)
Tabel 1: frequentietabel van het aantal observaties per behandelingsgroep.
boxplot(versgewicht~behandeling,dataset)
set.seed(10)
stripchart(versgewicht~behandeling, data = dataset,
vertical = TRUE, method = "jitter",
pch = 19, col =c("coral","steelblue","gold","aquamarine3"),
add = TRUE)
Figuur 1: Boxplot van het versgewicht in gram per behandelingsgroep. De punten zijn de individuele metingen.
In de frequentietabel (Tabel 1) zien we dat er slechts 7 observaties per groep zijn. De gemeten versgewichten binnen de refoak behandelingsgroep zijn zeer vergelijkbaar met die van de controlegroep. De gemeten versgewichten binnen de cobc en de compost behandelingsgroepen zijn merkelijk hoger dan die binnen de controlegroep. De gemeten versgewichten binnen de compost behandelingsgroep liggen gemiddeld gezien iets hoger dan die binnen in de cobc groep, maar er is een grote overlap tussen gemeten waardes. Geen enkele behandelingsgroep bevat uitschieters. De metingen binnen iedere behandelijksgroep lijkt symmetrisch verdeeld. De variantie van de metingen lijkt niet sterk af te wijken tussen de behandelingsgroepen. Het bereik en de spreiding van de waarden tussen de verschillende groepen is zeer vergelijkbaar.
Kruskal-Wallis Rank Test
Door de weinig datapunten is het moeilijk om de distributionele assumpties voor de parametrische ANOVA te controleren (normaliteit en gelijke variantie tussen de groepen). De Kruskal-Wallis Rank Test (KW-test) is een niet-parametrische variant van de ANOVA. Deze test laat ons toe om de distributionele assumpties te relaxeren. Let erop dat de assumptie van onafhankelijkheid tussen de observaties nog steeds moet opgaan!
Als we willen testen voor een verschil tussen de mediaan van de verschillende behandelingsgroepen, dan moeten we uitgaan van de locatie shift assumptie. Onder de locatie shift assumptie veronderstellen we dat de verschillende groepen onderling nog steeds dezelfde distributie volgen (dit hoeft uiteraard niet noodzakelijk een normale verdeling te zijn, elke verdeling is goed, zolang het maar in beide groepen dezelfde verdeling is).
Wanneer je kijkt naar de boxplots in Figuur 1, denk je dan dat de locatie shift assumptie aannemelijk is?
…
Wanneer we niet bereid zijn om de locatie shift assumptie te aanvaarden, dan kunnen we de distributionele assumpties nog verder relaxeren, en testen we in termen van probabilistische indexen. Hier testen we in het geval van twee groepen de kans dat een willekeurige meetwaarde uit de eerste groep komt groter of gelijk is dan een willekeurige meetwaarde uit de tweede groep.
Hypothese
Probeer nu eens de nulhypothese op te stellen in termen van de onderzoeksvraag?
…
Statistische test
Sinds we te maken hebben met een klein aantal observaties per groep is het niet aan te raden om de asymptotische KW-test te gebruiken om een p-waarde te berekenen. Deze stelt namelijk dat je teststatistiek onder de nulhypothese een \(\chi^2\) distributie volgt (de nuldistributie) wanneer het aantal oberservaties per groep naar oneindig neigt (dus voor een groot aantal observaties).
Wanneer je een beperkt aantal observaties hebt, is het beter de nuldistributie exact te berekenen via permutaties. Dit is uiteraard computationeel onmogelijk, want met 4 groepen van elk 7 observaties bestaan er 4.725183510^{14} mogelijke permutaties. Gelukkig is het meestal voldoende om de exacte nuldistributie te benaderen met een kleiner aantal permutaties.
Voer een KW test uit op de data met behulp van een groot aantal permutaties (bv. 10000). (Tip: zie cursus http://users.ugent.be/~lclement/statistiek/ voor code voorbeelden) Wat kan je besluiten uit dit resultaat?
library(coin)
…
Als we willen weten in welke soorten grond er nu juist een significant verschil in versgewicht optreed, zal men een post-hoc analyse moeten doen.
Post-hoc analyse
Zoals bij de parametrische ANOVA zal je ook bij na de niet-parametrische KW test paarsgewijze testen moeten uitvoeren om onderlinge verschillen in versgewicht tussen de slaplanten te detecteren. Dit zullen uiteraard ook niet-parametrische testen zijn zoals de Wilcoxon-Mann-Whitney Test (WMW test). Als je de keuze gemaakt hebt om bij de KW test om de locatie shift assumptie te verwerpen dan zal je dit hier terug doen en de resultaten in termen van de probabilistische index interpreteren.
Wat zal nu de nul en alternatieve hypothese zijn voor iedere paarsgewijze test?
…
Voer een WMW post-hoc analyse uit op de data.
library(coin)
…
Kun je nu ook aan de hand van de Mann-Whitney U1 statistiek een puntschatting geven van de Probabilistische index?
…
Hoe interpreteer je de resultaten van de WMW testen?
…
LS0tCnRpdGxlOiAiTmlldC1wYXJhbWV0cmlzY2hlIHRlc3RlbjogUGxhbnRlbmdyb2VpIGluIGJsYWRncm9lbnRlbiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBTaXR1ZXJpbmcKSW4gZGUgbGFuZGJvdXcgaXMgaGV0IGJlbGFuZ3Jpamsgb20gZWVuIGdvZWRlIHByb2R1Y3RpZSB2YW4gZ2V3YXNzZW4gdGUgYmVrb21lbi4gVm9vciBoZXQga3dla2VuIHZhbiBibGFkZ3JvZW50ZW4gem9hbHMgc2xhIGVuIHNwaW5hemllIGhvdWR0IGRpdCBpbiBvbSB6byBncm9vdCBtb2dlbGlqa2Uga3JvcHBlbiBvZiBibGFkZXJlbiB0ZSBiZWtvbWVuLiBEZSBjb25zdW1lbnQgemFsIG5hbWVsaWprIGVlcmRlciBraWV6ZW4gdm9vciBncm90ZSwgdm9sbGUga3JvcHBlbiBtZXQgdmVlbCBibGFkLgoKT20gZGl0IHRlIGJla29tZW4sIGdlYnJ1aWtlbiBib2VyZW4gdmFhayB2ZXJzY2hpbGxlbmRlIHR5cGVzIHZhbiBtZXN0LiBFciBpcyBtZWVyIGVuIG1lZXIgZWVuIHRlbmRlbnMgb20gb3ZlciB0ZSBzY2hha2VsZW4gdmFuIGt1bnN0bWVzdHN0b2ZmZW4gbmFhciBtZWVyIGR1dXJ6YW1lIG9yZ2FuaXNjaGUgbWVzdHN0b2ZmZW4uIERlIG1lZXN0IGdla2VuZGUgb3JnYW5pc2NoZSBtZXN0c3RvZiBpcyBjb21wb3N0LiBJbiBoZXQgSUxWTyB3b3JkZW4gZXIgZWNodGVyIG9vayBuaWV1d2UgdHlwZXMgdmFuIG9yZ2FuaXNjaGUgbWVzdHN0b2ZmZW4gZ2V0ZXN0LiDDicOpbiB2YW4gZGV6ZSBuaWV1d2Ugc3RvZmZlbiBpcyBiaW9jaGFyLiBCaW9jaGFyIHdvcmR0IGdldm9ybWQgdGlqZGVucyBlZW4gcHlyb2x5c2UgcHJvY2VzIHZhbiBiaW9tYXNzYSAoem9hbHMgYnYuIGhvdXRhZnZhbCkgd2FhcmJpaiBlbmVyZ2llIHdvcmR0IG9wZ2V3ZWt0LiBIZXQgcmVzdG1hdGVyaWFhbCB2YW4gZGUgcHlyb2x5c2Ugd29yZHQgZGUgYmlvY2hhciBnZW5vZW1kLCBlZW4gc3RvZiBkaWUgc3RlcmsgZ2VsaWprdCBvcCBob3V0c2tvb2wgbWFhciBudXR0aWdlIGVpZ2Vuc2NoYXBwZW4gaGVlZnQgem9hbHMgdmFzdGhvdWRlbiB2YW4gaGV0IHdhdGVyIGluIGRlIGJvZGVtIGVuIGhldCBiZcOvbnZsb2VkZW4gdmFuIGRlIG51dHRpZ2UgYmFjdGVyacOrbiBpbiBkZSBib2RlbS4KCiMgRGF0YQpEZSBvbmRlcnpvZWtlcnMgd2lsbGVuIG5hZ2FhbiBvZiAgYmlvY2hhciwgY29tcG9zdCBlbiBjb21wb3N0IGdlbWVuZ2QgbWV0IGJpb2NoYXIgaW52bG9lZCBoZWVmdCBvcCBkZSBncm9laSB2YW4gYmxhZGdyb2VudGVuLiBEYWFydm9vciBncm9laWRlbiB6ZSBzbGEgb3AgaW4gcG90dGVuIG1ldCB2ZWxkZ3JvbmQgaW4gZWVuIGdyb2Vpa2FtZXIuIEhldCB2ZXJzZ2V3aWNodCB2YW4gZGUgcGxhbnQgd2VyZCBuYSBhY2h0IHdla2VuIGdlbWV0ZW4uIFZlcnNnZXdpY2h0IHdvcmR0IGdlYnJ1aWt0IGFscyBlZW4gbWFhdCB2b29yIGRlIHBsYW50ZW5ncm9laS4gIERlIHBsYW50ZW4gemlqbiBpbiB2aWVyIHZlcnNjaGlsbGVuZGUgdHlwZXMgZ3JvbmQgb3BnZWdyb2VpZDoKIAoxLiBWZWxkZ3JvbmQgKGNvbnRyb2xlKSAKMi4gVmVsZGdyb25kIHdhYXJhYW4gYmlvY2hhciB3ZXJkIHRvZWdldm9lZ2QgKHJlZm9haykKMy4gVmVsZGdyb25kIHdhYXJhYW4gY29tcG9zdCB3ZXJkIHRvZWdldm9lZ2QgKGNvbXBvc3QpCjQuIFZlbGRncm9uZCB3YWFyYWFuIGNvbXBvc3QgZ2VtZW5nZCBtZXQgYmlvY2hhciB3ZXJkIHRvZWdldm9lZ2QgKGNvYmMpCgpIZXQgYmVzdGFuZGplICd2ZXJzZ2V3aWNodF9zbGEudHh0JyBiZXZhdCBoZXQgdmVyc2dld2ljaHQgaW4gZ3JhbSB2b29yIDI4IHNsYXBsYW50ZW4gZW4gd2Vsa2UgYmVoYW5kZWxpbmcgemUgb25kZXJnaW5nZW4uCgojIE9uZGVyem9la3N2cmFhZwpHYSBuYSBvZiBlciBlZW4gZWZmZWN0IGlzIGRlIHZlcnNjaGlsbGVuZGUgYmVoYW5kZWxpbmdlbiBvcCBkZSBwbGFudGVuZ3JvZWkgdmFuIGJsYWRncm9lbnRlbi4KSW5kaWVuIGRpdCB6byBpcywgd2Vsa2UgYmVoYW5kZWxpbmdlbiB6aWpuIGVmZmVjdGllZj8KCiMgV2Fhcm9tIGVlbiBuaWV0LXBhcmFtZXRyaXNjaGUgdGVzdD8KClZvb3IgaGV0IHByb2plY3QgbG9zc2VuIGp1bGxpZSBkZXplIG9uZGVyem9la3N2cmFhZyBvcCBtZXQgYmVodWxwIHZhbiBwYXJhbWV0cmlzY2hlIEFOT1ZBIChkZSBGLXRlc3QpLgpEaXQgaXMgZWVuIGdlbGRpZ2UgdGVzdCBhbHMgYWFuIGRlIGFzc3VtcHRpZXMgdm9sZGFhbiB3b3JkdC4KRWNodGVyLCBob2Uga2xlaW5lciBkZSBkYXRhc2V0LCBob2UgbW9laWxpamtlciBoZXQgaXMgb20gZGV6ZSBhc3N1bXB0aWUgdGUgY29udHJvbGVyZW4uCkVlbiBtb2dlbGlqa2Ugb3Bsb3NzaW5nIGthbiB6aWpuIG9tIGRlIE5vcm1hbGl0ZWl0c2Fzc3VtcHRpZSB0ZSBjaGVja2VuIG9wIGRlIHZvbGxlZGlnZSBkYXRhc2V0IGFhbiBkZSBoYW5kIHZhbiBlZW4gbGluZWFpciBtb2RlbCwgem9hbHMgd2UgaGllcm9uZGVyIGRvZW4uCgpgYGB7cn0KI0xlZXMgZGUgZGF0YSBpbgpkYXRhc2V0PXJlYWQuY3N2KCJ+L0Ryb3Bib3gvUGhEL09uZGVyd2lqcy9TdGF0aXN0aWVrIEJpb2NoZW1pZS8yMDE4MTkvZHJvcGJveFN0YXRzMTgxOS9jbGFzczZfbm9uUGFyL2hhbGYvdmVyc2dld2ljaHRfc2xhLnR4dCIsaGVhZGVyPVRSVUUpCm0gPC0gbG0odmVyc2dld2ljaHQgfiBiZWhhbmRlbGluZywgZGF0YT1kYXRhc2V0KQpwYXIobWZyb3c9YygyLDIpKQpwbG90KG0pCnBhcihtZnJvdz1jKDEsMSkpCmBgYAoKRGUgUVEtcGxvdCBpcyBub2dhbCB0d2lqZmVsYWNodGlnLCBlbiBtZW4gem91IGJlaWRlIGthbnRlbiBrdW5uZW4gYmVhcmd1bWVudGVyZW4uCkluZGVyZGFhZCwgZW5lcnppamRzIGthbiBtZW4gYXJndW1lbnRlcmVuIGRhdCBkZSBRUS1wbG90IG5pZXQgYmlqem9uZGVyIHN0ZXJrIGFmd2lqa3QgdmFuIHdhdCBtZW4gem91IHZlcndhY2h0ZW4gb3AgYmFzaXMgdmFuIGVlbiBOb3JtYWxlIGRpc3RyaWJ1dGllLgpBbmRlcnppamRzLCBrYW4gbWVuIGFyZ3VtZW50ZXJlbiBkYXQgKGkpIGRlIFFRLXBsb3QgbGljaHQgYWZ3aWprdCwgZW4gKGlpKSB3ZSBib3ZlbmRpZW4gZWVuIE5vcm1hbGUgZGlzdHJpYnV0aWUgbW9ldGVuIHZlcm9uZGVyc3RlbGxlbiAqKmJpbm5lbiBlbGtlIGdyb2VwKiosIGVuIGRlIGJvdmVuc3RhYW5kZSBRUS1wbG90IGdlZW4gc2x1aXRlbmQgYmV3aWpzIGdlZWZ0Lgpab2FscyBqZSB6aWV0LCBpcyBkaXQgZWVuIGRhdGFzZXQgd2FhcmJpaiB6b3dlbCBkZSBhcmd1bWVudGF0aWUgdm9vciBlZW4gcGFyYW1ldHJpc2NoZSBBTk9WQSB0ZXN0IGFscyBkZSBhcmd1bWVudGF0aWUgdm9vciBlZW4gbmlldC1wYXJhbWV0cmlzY2hlIEtydXNrYWwtV2FsbGlzIHRlc3Qgc3RlZWsga2FuIGhvdWRlbi4gRGUgdmVpbGlnZSBvcHRpZSBpcyBkdWlkZWxpamsgZGUgS3J1c2thbC1XYWxsaXMgdGVzdCwgYWFuZ2V6aWVuIGRpZSBnZWVuIHBhcmFtZXRyc2ljaGUgYXNzdW1wdGllcyB2ZXJvbmRlcnN0ZWx0LiBEZSBlbmlnZSB2ZXJvbmRlcnN0ZWxsaW5nIGlzIGRhdCBkZSBkYXRhIG9uYWZoYW5rZWxpamsgemlqbi4KQm92ZW5kaWVuIGthbiBoZXQsIG9tIGVlbiBhbGdlbWVlbiBpbnppY2h0IHRlIHZlcmtyaWpnZW4sIG9vayBudXR0aWcgemlqbiBvbSBkZSByZXN1bHRhdGVuIHRlIGludGVycHJldGVyZW4gaW4gZnVuY3RpZSB2YW4gZGUgcHJvYmFiaWxpc3Rpc2NoZSBpbmRleC4KCgpTdGVsIGRhdCBkZSB2ZXJzZ2V3aWNodGVuIHZhbiBkZSBwbGFudGVuIGdlZW4gTm9ybWFsZSBtYWFyIGJ2YiBlZW4gR2FtbWEgZGlzdHJpYnV0aWUgdm9sZ2VuLgpFZW4gZ2FtbWEgZGlzdHJpYnV0aWUgaGVlZnQgZWVuIGFhbnRhbCBlaWdlbnNjaGFwcGVuIGRpZSB6ZSBlZW4gYmV0ZXJlIGtldXplIHpvdWRlbiBtYWtlbiBvbiBnZXdpY2h0ZW4gdGUgbW9kZWxsZXJlbi4KQmlqdm9vcmJlZWxkLCBnZXdpY2h0ZW4ga3VubmVuIG5pZXQgbmVnYXRpZWYgemlqbi4gRWVuIG5vcm1hbGllIGRpc3RyaWJ1dGllIGthbiBuZWdhdGllZiB3b3JkZW4sIG1hYXIgZWVuIGdhbW1hIGRpc3RyaWJ1dGllIGVlbiBvbmRlcmdyZW5zIGhlZWZ0IGJpaiBudWwuCgpgYGB7cn0KeCA9IHNlcSgtMSwxMCwuMDEpCnlub3JtID0gZG5vcm0oeCwyKQp5Z2FtID0gZGdhbW1hKHgsNSwyKQpwbG90KHgseW5vcm0sdHlwZSA9ICdsJykKbGluZXMoeCx5Z2FtLGNvbCA9ICdyZWQnKQphYmxpbmUodiA9IDApCmxlZ2VuZCgndG9wcmlnaHQnLGMoJ05vcm1hbGUnLCAnR2FtbWEnKSx0ZXh0LmNvbCA9IGMoJ2JsYWNrJywncmVkJykpCmBgYAoKCgpXZSB6dWxsZW4gOSBzYW1wbGVzIHZhbiBlbGsgNyBkYXRhcHVudGVuIGdlbmVyZXJlbiB1aXQgZWVuICoqbm9ybWFsZSoqIGRpc3RyaWJ1dGllLgoKYGBge3J9CnBhcihtZnJvdyA9IGMoMywzKSkKc2V0LnNlZWQoMTEpICMjIHpvcmd0IGVydm9vciBkYXQgYmlqIGhlcmxvcGVuIHZhbiBkZSBjb2RlIGV4YWN0IGRlemVsZmRlICdyYW5kb20nIHdhYXJkZW4gZ2VuZXJlZXJkIHdvcmRlbi4KZm9yKGkgaW4gMTo5KXsKICB4ID0gcm5vcm0oNykKICBxcW5vcm0oeCwgbWFpbiA9IGkpCiAgcXFsaW5lKHgpCn0KYGBgCgpXZSB6aWVuIGluIGRlIFFRLXBsb3RzIGRhdCBkZSBtZWVzdGUgc2FtcGxlcyBub3JtYWFsIHZlcmRlZWxkIGxpamtlbiwgdGVyd2lqbCBzb21taWdlbiB0b2NoIG5pZXQtbGluZWFpcmUgcGF0cm9uZW4gdmVydG9uZW4gKHpvYWxzIFFRLXBsb3QgNSkgZW4gZHVzIG1pc3NjaGllbiAoaW5jb3JyZWN0KSBhbHMgbmlldCBub3JtYWFsIGJlb29yZGVlbGQgem91ZGVuIHdvcmRlbi4KCldlIHp1bGxlbiBudSA5IHNhbXBsZXMgdmFuIGVsayA3IGRhdGFwdW50ZW4gZ2VuZXJlcmVuIHVpdCBlZW4gKipnYW1tYSoqIGRpc3RyaWJ1dGllLgoKYGBge3J9CnBhcihtZnJvdyA9IGMoMywzKSkKc2V0LnNlZWQoMTEpCgpmb3IoaSBpbiAxOjkpewogIHggPSByZ2FtbWEoNyw1LDIpCiAgcXFub3JtKHgsIG1haW4gPSBpKQogIHFxbGluZSh4KQp9CmBgYAoKCldlIHppZW4gaW4gZGUgUVEtcGxvdHMgKGJpanZvb3JiZWVsZCBRUS1wbG90IDQpIGRhdCBzb21taWdlIHN0YWxlbiBzYW1wbGVzIGFmd2lqa2VuIHZhbiBlZW4gcmVjaHRlIHdhdCBjb3JyZWN0IHRvdCBkZSBjb25sdXNpZSB2YW4gbmlldC1ub3JtYWFsIHZlcmRlZWxkZSBkYXRhIHpvdSBsZWlkZW4uCkFhbiBkZSBhbmRlcmUga2FudCBoZWJiZW4gZGUgZGF0YXB1bnRlbiBpbiBidmIgUVEtcGxvdCA3IHdlbCBlZW4gbGluZWFyIHZlcmJhbmQgZW4gem91IGRlemUgZGF0YSBpbmNvcnJlY3Qgd2VsIGFscyBub3JtYWFsIHZlcmRlZWxkIGJlc2Nob3V3ZCBrdW5uZW4gd29yZGVuLgoKTnUgaXMgZGUgYXNzdW1wdGllIHZhbiBub3JtYWxpdGVpdCBiZWxhbmdyaWprIGJpaiBBTk9WQSAoZW4gb29rIHQtdGVzdCkgb21kYXQgbWVuIGhpZXIgZXJ2YW4gdWl0Z2FhdCBkYXQgamUgc3RlZWtwcm9lZmdlbWlkZGVsZGUgbm9ybWFhbCB2ZXJkZWVsZCBpcyByb25kIGhldCBwb3B1bGF0aWVnZW1pZGVsZGUuIApBbHMgamUgZGF0YSBub3JtYWFsIHZlcmRlZWxkIGlzLCB6YWwgZGl0IGFsdGlqZCBoZXQgZ2V2YWwgemlqbi4KQWxzIGplIGRhdGEgbmlldCBub3JtYWFsIHZlcmRlZWxkIGlzLCBkYW4gZ2FhdCBkaXQgYWxsZWVuIG1hYXIgb3AgYWxzIGplIGRhdGFzZXQgZ3Jvb3QgZ2Vub2VnIGlzICh6aWUgZGUgQ2VudHJhbGUgTGltaWV0c3RlbGxpbmcgaW4gZGUgY3Vyc3VzKS4KCldlIGlsbHVzdHJlcmVuIGRpdCBtZXQgZWVuIHNpbXVsYXRpZS4KRWVuIGdyb290IGFhbnRhbCBkYXRhc2V0cyB2YW4gZWxrIDQgZGF0YXB1bnRlbiB3b3JkZW4gZ2VnZW5lcmVlcmQgdWl0IGVlbiBub3JtYWxlIHZlcmRlbGluZy4KV2UgYmVyZWtlbiBwZXIgZGF0YXNldCBoZXQgZ2VtaWRkZWxkZSBlbiB3ZSBjb25zdHJ1ZXJlbiBlZW4gUVEtcGxvdCB2YW4gZGV6ZSBnZW1pZGRlbGRlbiBvbSB0ZSBjb250cm9sZXJlbiBvZiB6ZSBub3JtYWFsIHZlcmRlZWxkIHppam4uIApXZSBoZXJoYWxlbiBkaXQsIG1hYXIgbnUgd29yZGVuIGRlIDQgZGF0YXB1bnRlbiBnZWdlbmVyZWVyZCB1aXQgZWVuIEdhbW1hIGRpc3RyaWJ1dGllLgpPbSBoZXQgZWZmZWN0IHZhbiBkYXRhc2V0IGdyb290dGUgdGUgYmVzdHVkZXJlbiB6dWxsZW4gd2Ugb29rIGRhdGFzZXRzIHVpdCBlZW4gR2FtbWEgZGlzdHJpYnV0aWUgZ2VuZXJlcmVuIHZhbiBncm9vdHRlIDcgZW4gMTAuCgpgYGB7cn0Kc2V0LnNlZWQoMTEpCnNhbXBsZXNfbm9ybWFhbCA9IHJlcGxpY2F0ZSgzMDAwMCwgbWVhbihybm9ybSg0KSkpCnNhbXBsZXNfZ2FtbWFfNCA9IHJlcGxpY2F0ZSgzMDAwMCwgbWVhbihyZ2FtbWEoMyw1LDIpKSkKc2FtcGxlc19nYW1tYV83ID0gcmVwbGljYXRlKDMwMDAwLCBtZWFuKHJnYW1tYSg3LDUsMikpKQpzYW1wbGVzX2dhbW1hXzEwID0gcmVwbGljYXRlKDMwMDAwLCBtZWFuKHJnYW1tYSgzMCw1LDIpKSkKcGFyKG1mcm93ID0gYygyLDIpKQpxcW5vcm0oc2FtcGxlc19ub3JtYWFsLHBjaCA9IDIwLCBtYWluID0gJ25vcm1hYWw7IG4gPSA0JykKcXFsaW5lKHNhbXBsZXNfbm9ybWFhbCwgY29sID0gJ3JlZCcpCnFxbm9ybShzYW1wbGVzX2dhbW1hXzQsIHBjaCA9IDIwLCBtYWluID0gJ2dhbW1hOyBuID0gNCcpCnFxbGluZShzYW1wbGVzX2dhbW1hXzQsIGNvbCA9ICdyZWQnKQpxcW5vcm0oc2FtcGxlc19nYW1tYV83LHBjaCA9IDIwLCBtYWluID0gJ2dhbW1hOyBuID0gNycpCnFxbGluZShzYW1wbGVzX2dhbW1hXzcsIGNvbCA9ICdyZWQnKQpxcW5vcm0oc2FtcGxlc19nYW1tYV8xMCxwY2ggPSAyMCwgbWFpbiA9ICdnYW1tYTsgbiA9IDMwJykKcXFsaW5lKHNhbXBsZXNfZ2FtbWFfMTAsIGNvbCA9ICdyZWQnKQpgYGAKCgpXZSB6aWVuIGluIGRlIFFRLXBsb3QgbGlua3Nib3ZlbiBkYXQgZGUgZ2VtaWRkZWxkZW4gdmFuIGRlIG5vcm1hYWwgdmVyZGVlbGRlIGRhdGFzZXRzIGluZGVyZGFhZCBvcCBlZW4gcmVjaHRlIGxpZ2dlbiBlbiBkdXMgbm9ybWFhbCB2ZXJkZWVsZCBsaWprZW4uCkJpaiBkZSBnZW1pZGRlbGRlbiB2YW4gZGUgZ2FtbWEgZGF0YXNldHMgbWV0IGdyb290dGUgNCB6aWVuIHdlIGR1aWRlbGlqa2UgYWZ3aWprZW4gdmFuIGRlIG5vcm1hbGl0ZWl0IChkZSBkaXN0cmlidXRpZSBpcyBzY2hlZWYgdmVyZGVlbGQgbmFhciBsaW5rcykuIFRlc3RzdGF0aXN0aWVrZW4gZW4gcC13YWFyZGVuIGJlcmVrZW5kIG1ldCBBTk9WQSBlbiB0LXRlc3RlbiB6aWpuIGluIGRhdCBnZXZhbCBvbmdlbGRpZy4gCgpJbiBkZSBvbmRlcnN0ZSByaWogUVEtcGxvdHMga2FuIG1lbiB6aWVuIGRhdCBob2UgZ3JvdGVyIGRlIHN0ZWVrcHJvZXZlbiB3b3JkZW4sIGhvZSBtZWVyIGRlIGdlbWlkZGVsZGVuIGVlbiBub3JtYWxlIGRpc3RyaWJ1dGllIGJlbmFkZXJlbi4KQmlqIGdyb3RlcmUgZGF0YXNldHMgemFsIGR1cyBtZW4ga3VubmVuIGFyZ3VtZW50ZXJlbiBkYXQgKipoZXQgc3RlZWtwcm9lZmdlbWlkZGVsZGUqKiBlZW4gbm9ybWFsZSB2ZXJkZWxpbmcgdm9sZ3QuIERpdCBlZmZlY3QsIHdhYXJiaWogZGUgZ2VtaWRkZWxkZW4gdmFuIGVlbiBzdGVla3Byb2VmIHVpdCBvbSBoZXQgZXZlbiB3ZWxrZSBkaXN0cmlidXRpZSBlZW4gbm9ybWFsZSBkaXN0cmlidXRpZSBnYWFuIGJlbmFkZXJlbiBhbHMgZGUgc3RlZWtwcm9lZiBtYWFyIGdyb290IGdlbm9lZyBpcywgbm9lbXQgbWVuIGRlIGNlbnRyYWxlIGxpbWlldHN0ZWxsaW5nLiBBbHMgamUgc3RlZWtwcm9lZiBncm9vdCBnZW5vZWcgaXMsIGthbiBqZSBkdXMgZGUgY2VudHJhbGUgbGltaWV0c3RlbGxpbmcgaW5yb2VwZW4gb20gZGUgbm9ybWFsaXRlaXRzYXNzdW1wdGllIHRlIGFhbnZhYXJkZW4uCgpBbHMgZXIgZ2VlbiBzdGVya2UgYXJndW1lbnRlbiBvbSBkZSBub3JtYWxpdGVpdHNhc3N1bXB0aWUgdGUgYWFudmFhcmRlbiAoYmlqdm9vcmJlZWxkIGdlbGlqa2FhcmRpZ2UgZ3JvdGVyZSBkYXRhc2V0cyBpbiBoZXQgdmVybGVkZW4gbGlqa2VuIG5vcm1hYWwgdmVyZGVlbGQpLCBpcyBoZXQgZG9vcmdhYW5zIHZlaWxpZ2VyIG9tIGRpdCBuaWV0IHRlIGRvZW4gZW4gZWVuIG5pZXQtcGFyYW1ldHJpc2NoZSB0ZXN0IHRlIGdlYnJ1aWtlbi4KCioqTWVyayBvcDoqKiBvb2sgYWxzIGRlIGFzc3VtcHRpZSB2YW4gaG9tb3NjZWRhc3RpY2l0ZWl0IGdlc2Nob25kZW4gaXMgb2YgbW9laWxpamsga2FuIHdvcmRlbiBuYWdlZ2FhbiBkb29yIGVlbiB0ZSBrbGVpbmUgc3RlZWtwcm9lZiwgenVsbGVuIGRlIHRlc3RzdGF0aXN0aWVrZW4gZW4gcC13YWFyZGVuIHZlcnRla2VuZCB6aWpuLiBWb29yIGVlbiB0LXRlc3Qga2FuIGplIG5vZyBnZWJydWlrIG1ha2VuIHZhbiBkZSBXZWxjaCB0LXRlc3QsIHZvb3IgZWVuIEFOT1ZBIHphbCBqZSBiaWogemVlciBzdGVya2UgYWZ3aWpraW5nZW4gdmFuIGhvbW9zY2VkYXN0aWNpdGVpdCBvb2sgZWVuIG5pZXQtcGFyYW1ldHJpc2NoZSB0ZXN0IG1vZXRlbiBnZWJydWlrZW4gZW4gamUgcmVzdWxhdGVuIGluIHRlcm1lbiB2YW4gZGUgcHJvYmFiaWxpc3Rpc2NoZSBpbmRleCBtb2V0ZW4gaW50ZXJwcmV0ZXJlbi4KCiMgRGF0YSBhbmFseXNlCldlIHp1bGxlbiBudSBkZSBzbGFwbGFudGVuIGRhdGFzZXQgaGVyZXZhbHVlcmVuIGVuIG5pZXQtcGFyYW1ldHJpc2NoZSB0ZXN0ZW4gb3ZlcndlZ2VuLgoKYGBge3J9CiNMZWVzIGRlIGRhdGEgaW4KZGF0YXNldD1yZWFkLmNzdigifi9Ecm9wYm94L1BoRC9PbmRlcndpanMvU3RhdGlzdGllayBCaW9jaGVtaWUvMjAxODE5L2Ryb3Bib3hTdGF0czE4MTkvY2xhc3M2X25vblBhci9oYWxmL3ZlcnNnZXdpY2h0X3NsYS50eHQiLGhlYWRlcj1UUlVFKQpgYGAKCiMjIERhdGF2ZXJrZW5uaW5nCgpgYGB7cn0KIyMgVGVsIGhldCBhYW50YWwgbWV0aW5nZW4gcGVyIGJlaGFuZGVsaW5nCnRhYmxlKGRhdGFzZXQkYmVoYW5kZWxpbmcpCmBgYAoKKipUYWJlbCAxOioqIGZyZXF1ZW50aWV0YWJlbCB2YW4gaGV0IGFhbnRhbCBvYnNlcnZhdGllcyBwZXIgYmVoYW5kZWxpbmdzZ3JvZXAuCgpgYGB7cn0KYm94cGxvdCh2ZXJzZ2V3aWNodH5iZWhhbmRlbGluZyxkYXRhc2V0KQpzZXQuc2VlZCgxMCkKc3RyaXBjaGFydCh2ZXJzZ2V3aWNodH5iZWhhbmRlbGluZywgZGF0YSA9IGRhdGFzZXQsCiAgICAgICAgICAgIHZlcnRpY2FsID0gVFJVRSwgbWV0aG9kID0gImppdHRlciIsIAogICAgICAgICAgICBwY2ggPSAxOSwgY29sID1jKCJjb3JhbCIsInN0ZWVsYmx1ZSIsImdvbGQiLCJhcXVhbWFyaW5lMyIpLCAKICAgICAgICAgICAgYWRkID0gVFJVRSkKYGBgCgoqKkZpZ3V1ciAxOioqIEJveHBsb3QgdmFuIGhldCB2ZXJzZ2V3aWNodCBpbiBncmFtIHBlciBiZWhhbmRlbGluZ3Nncm9lcC4gRGUgcHVudGVuIHppam4gZGUgaW5kaXZpZHVlbGUgbWV0aW5nZW4uCgpJbiBkZSBmcmVxdWVudGlldGFiZWwgKFRhYmVsIDEpIHppZW4gd2UgZGF0IGVyIHNsZWNodHMgNyBvYnNlcnZhdGllcyBwZXIgZ3JvZXAgemlqbi4KRGUgZ2VtZXRlbiB2ZXJzZ2V3aWNodGVuIGJpbm5lbiBkZSByZWZvYWsgYmVoYW5kZWxpbmdzZ3JvZXAgemlqbiB6ZWVyIHZlcmdlbGlqa2JhYXIgbWV0IGRpZSB2YW4gZGUgY29udHJvbGVncm9lcC4KRGUgZ2VtZXRlbiB2ZXJzZ2V3aWNodGVuIGJpbm5lbiBkZSBjb2JjIGVuIGRlIGNvbXBvc3QgYmVoYW5kZWxpbmdzZ3JvZXBlbiB6aWpuIG1lcmtlbGlqayBob2dlciBkYW4gZGllIGJpbm5lbiBkZSBjb250cm9sZWdyb2VwLgpEZSBnZW1ldGVuIHZlcnNnZXdpY2h0ZW4gYmlubmVuIGRlIGNvbXBvc3QgYmVoYW5kZWxpbmdzZ3JvZXAgbGlnZ2VuIGdlbWlkZGVsZCBnZXppZW4gaWV0cyBob2dlciBkYW4gZGllIGJpbm5lbiBpbiBkZSBjb2JjIGdyb2VwLCBtYWFyIGVyIGlzIGVlbiBncm90ZSBvdmVybGFwIHR1c3NlbiBnZW1ldGVuIHdhYXJkZXMuCkdlZW4gZW5rZWxlIGJlaGFuZGVsaW5nc2dyb2VwIGJldmF0IHVpdHNjaGlldGVycy4KRGUgbWV0aW5nZW4gYmlubmVuIGllZGVyZSBiZWhhbmRlbGlqa3Nncm9lcCBsaWprdCBzeW1tZXRyaXNjaCB2ZXJkZWVsZC4KRGUgdmFyaWFudGllIHZhbiBkZSBtZXRpbmdlbiBsaWprdCBuaWV0IHN0ZXJrIGFmIHRlIHdpamtlbiB0dXNzZW4gZGUgYmVoYW5kZWxpbmdzZ3JvZXBlbi4KSGV0IGJlcmVpayBlbiBkZSBzcHJlaWRpbmcgdmFuIGRlIHdhYXJkZW4gdHVzc2VuIGRlIHZlcnNjaGlsbGVuZGUgZ3JvZXBlbiBpcyB6ZWVyIHZlcmdlbGlqa2JhYXIuCgojICBLcnVza2FsLVdhbGxpcyBSYW5rIFRlc3QKRG9vciBkZSB3ZWluaWcgZGF0YXB1bnRlbiBpcyBoZXQgbW9laWxpamsgb20gZGUgZGlzdHJpYnV0aW9uZWxlIGFzc3VtcHRpZXMgdm9vciBkZSBwYXJhbWV0cmlzY2hlIEFOT1ZBIHRlIGNvbnRyb2xlcmVuIChub3JtYWxpdGVpdCBlbiBnZWxpamtlIHZhcmlhbnRpZSB0dXNzZW4gZGUgZ3JvZXBlbikuCkRlIEtydXNrYWwtV2FsbGlzIFJhbmsgVGVzdCAoS1ctdGVzdCkgaXMgZWVuIG5pZXQtcGFyYW1ldHJpc2NoZSB2YXJpYW50IHZhbiBkZSBBTk9WQS4KRGV6ZSB0ZXN0IGxhYXQgb25zIHRvZSBvbSBkZSBkaXN0cmlidXRpb25lbGUgYXNzdW1wdGllcyB0ZSByZWxheGVyZW4uCioqTGV0IGVyb3AgZGF0IGRlIGFzc3VtcHRpZSB2YW4gb25hZmhhbmtlbGlqa2hlaWQgdHVzc2VuIGRlIG9ic2VydmF0aWVzIG5vZyBzdGVlZHMgbW9ldCBvcGdhYW4hKioKCkFscyB3ZSB3aWxsZW4gdGVzdGVuIHZvb3IgZWVuIHZlcnNjaGlsIHR1c3NlbiBkZSBtZWRpYWFuIHZhbiBkZSB2ZXJzY2hpbGxlbmRlIGJlaGFuZGVsaW5nc2dyb2VwZW4sIGRhbiBtb2V0ZW4gd2UgdWl0Z2FhbiB2YW4gZGUgbG9jYXRpZSBzaGlmdCBhc3N1bXB0aWUuCk9uZGVyIGRlIGxvY2F0aWUgc2hpZnQgYXNzdW1wdGllIHZlcm9uZGVyc3RlbGxlbiB3ZSBkYXQgZGUgdmVyc2NoaWxsZW5kZSBncm9lcGVuIG9uZGVybGluZyBub2cgc3RlZWRzIGRlemVsZmRlIGRpc3RyaWJ1dGllIHZvbGdlbiAoZGl0IGhvZWZ0IHVpdGVyYWFyZCBuaWV0IG5vb2R6YWtlbGlqayBlZW4gbm9ybWFsZSB2ZXJkZWxpbmcgdGUgemlqbiwgZWxrZSB2ZXJkZWxpbmcgaXMgZ29lZCwgem9sYW5nIGhldCBtYWFyIGluIGJlaWRlIGdyb2VwZW4gZGV6ZWxmZGUgdmVyZGVsaW5nIGlzKS4gCgoqKldhbm5lZXIgamUga2lqa3QgbmFhciBkZSBib3hwbG90cyBpbiBGaWd1dXIgMSwgZGVuayBqZSBkYW4gZGF0IGRlIGxvY2F0aWUgc2hpZnQgYXNzdW1wdGllIGFhbm5lbWVsaWprIGlzPyoqCgouLi4KCgpXYW5uZWVyIHdlIG5pZXQgYmVyZWlkIHppam4gb20gZGUgbG9jYXRpZSBzaGlmdCBhc3N1bXB0aWUgdGUgYWFudmFhcmRlbiwgZGFuIGt1bm5lbiB3ZSBkZSBkaXN0cmlidXRpb25lbGUgYXNzdW1wdGllcyBub2cgdmVyZGVyIHJlbGF4ZXJlbiwgZW4gdGVzdGVuIHdlIGluIHRlcm1lbiB2YW4gcHJvYmFiaWxpc3Rpc2NoZSBpbmRleGVuLgpIaWVyIHRlc3RlbiB3ZSBpbiBoZXQgZ2V2YWwgdmFuIHR3ZWUgZ3JvZXBlbiBkZSBrYW5zIGRhdCBlZW4gd2lsbGVrZXVyaWdlIG1lZXR3YWFyZGUgdWl0IGRlIGVlcnN0ZSBncm9lcCBrb210IGdyb3RlciBvZiBnZWxpamsgaXMgZGFuIGVlbiB3aWxsZWtldXJpZ2UgbWVldHdhYXJkZSB1aXQgZGUgdHdlZWRlIGdyb2VwLgoKIyMgSHlwb3RoZXNlCioqUHJvYmVlciBudSBlZW5zIGRlIG51bGh5cG90aGVzZSBvcCB0ZSBzdGVsbGVuIGluIHRlcm1lbiB2YW4gZGUgb25kZXJ6b2Vrc3ZyYWFnPyoqCgouLi4KCiMjIFN0YXRpc3Rpc2NoZSB0ZXN0CgpTaW5kcyB3ZSB0ZSBtYWtlbiBoZWJiZW4gbWV0IGVlbiBrbGVpbiBhYW50YWwgb2JzZXJ2YXRpZXMgcGVyIGdyb2VwIGlzIGhldCBuaWV0IGFhbiB0ZSByYWRlbiBvbSBkZSBhc3ltcHRvdGlzY2hlIEtXLXRlc3QgdGUgZ2VicnVpa2VuIG9tIGVlbiBwLXdhYXJkZSB0ZSBiZXJla2VuZW4uCkRlemUgc3RlbHQgbmFtZWxpamsgZGF0IGplIHRlc3RzdGF0aXN0aWVrIG9uZGVyIGRlIG51bGh5cG90aGVzZSBlZW4gJFxjaGleMiQgZGlzdHJpYnV0aWUgdm9sZ3QgKGRlIG51bGRpc3RyaWJ1dGllKSB3YW5uZWVyIGhldCBhYW50YWwgb2JlcnNlcnZhdGllcyBwZXIgZ3JvZXAgbmFhciBvbmVpbmRpZyBuZWlndCAoZHVzIHZvb3IgZWVuIGdyb290IGFhbnRhbCBvYnNlcnZhdGllcykuCgpXYW5uZWVyIGplIGVlbiBiZXBlcmt0IGFhbnRhbCBvYnNlcnZhdGllcyBoZWJ0LCBpcyBoZXQgYmV0ZXIgZGUgbnVsZGlzdHJpYnV0aWUgZXhhY3QgdGUgYmVyZWtlbmVuIHZpYSBwZXJtdXRhdGllcy4KRGl0IGlzIHVpdGVyYWFyZCBjb21wdXRhdGlvbmVlbCBvbm1vZ2VsaWprLCB3YW50IG1ldCA0IGdyb2VwZW4gdmFuIGVsayA3IG9ic2VydmF0aWVzIGJlc3RhYW4gZXIgYHIgZmFjdG9yaWFsKDI4KS8oZmFjdG9yaWFsKDcpXjQpYCBtb2dlbGlqa2UgcGVybXV0YXRpZXMuCkdlbHVra2lnIGlzIGhldCBtZWVzdGFsIHZvbGRvZW5kZSBvbSBkZSBleGFjdGUgbnVsZGlzdHJpYnV0aWUgdGUgYmVuYWRlcmVuIG1ldCBlZW4ga2xlaW5lciBhYW50YWwgcGVybXV0YXRpZXMuCgoqKlZvZXIgZWVuIEtXIHRlc3QgdWl0IG9wIGRlIGRhdGEgbWV0IGJlaHVscCB2YW4gZWVuIGdyb290IGFhbnRhbCBwZXJtdXRhdGllcyAoYnYuIDEwMDAwKS4qKgoqKihUaXA6IHppZSBjdXJzdXMgaHR0cDovL3VzZXJzLnVnZW50LmJlL35sY2xlbWVudC9zdGF0aXN0aWVrLyB2b29yIGNvZGUgdm9vcmJlZWxkZW4pKioKKipXYXQga2FuIGplIGJlc2x1aXRlbiB1aXQgZGl0IHJlc3VsdGFhdD8qKgoKYGBge3J9CmxpYnJhcnkoY29pbikKCmBgYAoKLi4uCgpBbHMgd2Ugd2lsbGVuIHdldGVuIGluIHdlbGtlIHNvb3J0ZW4gZ3JvbmQgZXIgbnUganVpc3QgZWVuIHNpZ25pZmljYW50IHZlcnNjaGlsIGluIHZlcnNnZXdpY2h0IG9wdHJlZWQsIHphbCBtZW4gZWVuIHBvc3QtaG9jIGFuYWx5c2UgbW9ldGVuIGRvZW4uCgojIyBQb3N0LWhvYyBhbmFseXNlClpvYWxzIGJpaiBkZSBwYXJhbWV0cmlzY2hlIEFOT1ZBIHphbCBqZSBvb2sgYmlqIG5hIGRlIG5pZXQtcGFyYW1ldHJpc2NoZSBLVyB0ZXN0IHBhYXJzZ2V3aWp6ZSB0ZXN0ZW4gbW9ldGVuIHVpdHZvZXJlbiBvbSBvbmRlcmxpbmdlIHZlcnNjaGlsbGVuIGluIHZlcnNnZXdpY2h0IHR1c3NlbiBkZSBzbGFwbGFudGVuIHRlIGRldGVjdGVyZW4uCkRpdCB6dWxsZW4gdWl0ZXJhYXJkIG9vayBuaWV0LXBhcmFtZXRyaXNjaGUgdGVzdGVuIHppam4gem9hbHMgZGUgV2lsY294b24tTWFubi1XaGl0bmV5IFRlc3QgKFdNVyB0ZXN0KS4KQWxzIGplIGRlIGtldXplIGdlbWFha3QgaGVidCBvbSBiaWogZGUgS1cgdGVzdCBvbSBkZSBsb2NhdGllIHNoaWZ0IGFzc3VtcHRpZSB0ZSB2ZXJ3ZXJwZW4gZGFuIHphbCBqZSBkaXQgaGllciB0ZXJ1ZyBkb2VuIGVuIGRlIHJlc3VsdGF0ZW4gaW4gdGVybWVuIHZhbiBkZSBwcm9iYWJpbGlzdGlzY2hlIGluZGV4IGludGVycHJldGVyZW4uCgoqKldhdCB6YWwgbnUgZGUgbnVsIGVuIGFsdGVybmF0aWV2ZSBoeXBvdGhlc2UgemlqbiB2b29yIGllZGVyZSBwYWFyc2dld2lqemUgdGVzdD8qKgoKLi4uCgoKKipWb2VyIGVlbiBXTVcgcG9zdC1ob2MgYW5hbHlzZSB1aXQgb3AgZGUgZGF0YS4qKgoKCj4gYGBge3J9CmxpYnJhcnkoY29pbikKCgpgYGAKCi4uLgoKKipLdW4gamUgbnUgb29rIGFhbiBkZSBoYW5kIHZhbiBkZSBNYW5uLVdoaXRuZXkgVTEgc3RhdGlzdGllayBlZW4gcHVudHNjaGF0dGluZyBnZXZlbiB2YW4gZGUgUHJvYmFiaWxpc3Rpc2NoZSBpbmRleD8qKgoKPiAgYGBge3J9CgoKYGBgCi4uLgoKKipIb2UgaW50ZXJwcmV0ZWVyIGplIGRlIHJlc3VsdGF0ZW4gdmFuIGRlIFdNVyB0ZXN0ZW4/KioKCi4uLgoKIyBDb25jbHVzaWUKCi4uLgo=