Situering

In de landbouw is het belangrijk om een goede productie van gewassen te bekomen. Voor het kweken van bladgroenten zoals sla en spinazie houdt dit in om zo groot mogelijke kroppen of bladeren te bekomen. De consument zal namelijk eerder kiezen voor grote, volle kroppen met veel blad.

Om dit te bekomen, gebruiken boeren vaak verschillende types van mest. Er is meer en meer een tendens om over te schakelen van kunstmeststoffen naar meer duurzame organische meststoffen. De meest gekende organische meststof is compost. In het ILVO worden er echter ook nieuwe types van organische meststoffen getest. Één van deze nieuwe stoffen is biochar. Biochar wordt gevormd tijdens een pyrolyse proces van biomassa (zoals bv. houtafval) waarbij energie wordt opgewekt. Het restmateriaal van de pyrolyse wordt de biochar genoemd, een stof die sterk gelijkt op houtskool maar nuttige eigenschappen heeft zoals vasthouden van het water in de bodem en het beïnvloeden van de nuttige bacteriën in de bodem.

Data

De onderzoekers willen nagaan of biochar, compost en compost gemengd met biochar invloed heeft op de groei van bladgroenten. Daarvoor groeiden ze sla op in potten met veldgrond in een groeikamer. Het versgewicht van de plant werd na acht weken gemeten. Versgewicht wordt gebruikt als een maat voor de plantengroei. De planten zijn in vier verschillende types grond opgegroeid:

  1. Veldgrond (controle)
  2. Veldgrond waaraan biochar werd toegevoegd (refoak)
  3. Veldgrond waaraan compost werd toegevoegd (compost)
  4. Veldgrond waaraan compost gemengd met biochar werd toegevoegd (cobc)

Het bestandje ‘versgewicht_sla.txt’ bevat het versgewicht in gram voor 28 slaplanten en welke behandeling ze ondergingen.

Onderzoeksvraag

Ga na of er een effect is de verschillende behandelingen op de plantengroei van bladgroenten. Indien dit zo is, welke behandelingen zijn effectief?

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?

Conclusie

LS0tCnRpdGxlOiAiTmlldC1wYXJhbWV0cmlzY2hlIHRlc3RlbjogUGxhbnRlbmdyb2VpIGluIGJsYWRncm9lbnRlbiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBTaXR1ZXJpbmcKSW4gZGUgbGFuZGJvdXcgaXMgaGV0IGJlbGFuZ3Jpamsgb20gZWVuIGdvZWRlIHByb2R1Y3RpZSB2YW4gZ2V3YXNzZW4gdGUgYmVrb21lbi4gVm9vciBoZXQga3dla2VuIHZhbiBibGFkZ3JvZW50ZW4gem9hbHMgc2xhIGVuIHNwaW5hemllIGhvdWR0IGRpdCBpbiBvbSB6byBncm9vdCBtb2dlbGlqa2Uga3JvcHBlbiBvZiBibGFkZXJlbiB0ZSBiZWtvbWVuLiBEZSBjb25zdW1lbnQgemFsIG5hbWVsaWprIGVlcmRlciBraWV6ZW4gdm9vciBncm90ZSwgdm9sbGUga3JvcHBlbiBtZXQgdmVlbCBibGFkLgoKT20gZGl0IHRlIGJla29tZW4sIGdlYnJ1aWtlbiBib2VyZW4gdmFhayB2ZXJzY2hpbGxlbmRlIHR5cGVzIHZhbiBtZXN0LiBFciBpcyBtZWVyIGVuIG1lZXIgZWVuIHRlbmRlbnMgb20gb3ZlciB0ZSBzY2hha2VsZW4gdmFuIGt1bnN0bWVzdHN0b2ZmZW4gbmFhciBtZWVyIGR1dXJ6YW1lIG9yZ2FuaXNjaGUgbWVzdHN0b2ZmZW4uIERlIG1lZXN0IGdla2VuZGUgb3JnYW5pc2NoZSBtZXN0c3RvZiBpcyBjb21wb3N0LiBJbiBoZXQgSUxWTyB3b3JkZW4gZXIgZWNodGVyIG9vayBuaWV1d2UgdHlwZXMgdmFuIG9yZ2FuaXNjaGUgbWVzdHN0b2ZmZW4gZ2V0ZXN0LiDDicOpbiB2YW4gZGV6ZSBuaWV1d2Ugc3RvZmZlbiBpcyBiaW9jaGFyLiBCaW9jaGFyIHdvcmR0IGdldm9ybWQgdGlqZGVucyBlZW4gcHlyb2x5c2UgcHJvY2VzIHZhbiBiaW9tYXNzYSAoem9hbHMgYnYuIGhvdXRhZnZhbCkgd2FhcmJpaiBlbmVyZ2llIHdvcmR0IG9wZ2V3ZWt0LiBIZXQgcmVzdG1hdGVyaWFhbCB2YW4gZGUgcHlyb2x5c2Ugd29yZHQgZGUgYmlvY2hhciBnZW5vZW1kLCBlZW4gc3RvZiBkaWUgc3RlcmsgZ2VsaWprdCBvcCBob3V0c2tvb2wgbWFhciBudXR0aWdlIGVpZ2Vuc2NoYXBwZW4gaGVlZnQgem9hbHMgdmFzdGhvdWRlbiB2YW4gaGV0IHdhdGVyIGluIGRlIGJvZGVtIGVuIGhldCBiZcOvbnZsb2VkZW4gdmFuIGRlIG51dHRpZ2UgYmFjdGVyacOrbiBpbiBkZSBib2RlbS4KCiMgRGF0YQpEZSBvbmRlcnpvZWtlcnMgd2lsbGVuIG5hZ2FhbiBvZiAgYmlvY2hhciwgY29tcG9zdCBlbiBjb21wb3N0IGdlbWVuZ2QgbWV0IGJpb2NoYXIgaW52bG9lZCBoZWVmdCBvcCBkZSBncm9laSB2YW4gYmxhZGdyb2VudGVuLiBEYWFydm9vciBncm9laWRlbiB6ZSBzbGEgb3AgaW4gcG90dGVuIG1ldCB2ZWxkZ3JvbmQgaW4gZWVuIGdyb2Vpa2FtZXIuIEhldCB2ZXJzZ2V3aWNodCB2YW4gZGUgcGxhbnQgd2VyZCBuYSBhY2h0IHdla2VuIGdlbWV0ZW4uIFZlcnNnZXdpY2h0IHdvcmR0IGdlYnJ1aWt0IGFscyBlZW4gbWFhdCB2b29yIGRlIHBsYW50ZW5ncm9laS4gIERlIHBsYW50ZW4gemlqbiBpbiB2aWVyIHZlcnNjaGlsbGVuZGUgdHlwZXMgZ3JvbmQgb3BnZWdyb2VpZDoKIAoxLiBWZWxkZ3JvbmQgKGNvbnRyb2xlKSAKMi4gVmVsZGdyb25kIHdhYXJhYW4gYmlvY2hhciB3ZXJkIHRvZWdldm9lZ2QgKHJlZm9haykKMy4gVmVsZGdyb25kIHdhYXJhYW4gY29tcG9zdCB3ZXJkIHRvZWdldm9lZ2QgKGNvbXBvc3QpCjQuIFZlbGRncm9uZCB3YWFyYWFuIGNvbXBvc3QgZ2VtZW5nZCBtZXQgYmlvY2hhciB3ZXJkIHRvZWdldm9lZ2QgKGNvYmMpCgpIZXQgYmVzdGFuZGplICd2ZXJzZ2V3aWNodF9zbGEudHh0JyBiZXZhdCBoZXQgdmVyc2dld2ljaHQgaW4gZ3JhbSB2b29yIDI4IHNsYXBsYW50ZW4gZW4gd2Vsa2UgYmVoYW5kZWxpbmcgemUgb25kZXJnaW5nZW4uCgojIE9uZGVyem9la3N2cmFhZwpHYSBuYSBvZiBlciBlZW4gZWZmZWN0IGlzIGRlIHZlcnNjaGlsbGVuZGUgYmVoYW5kZWxpbmdlbiBvcCBkZSBwbGFudGVuZ3JvZWkgdmFuIGJsYWRncm9lbnRlbi4KSW5kaWVuIGRpdCB6byBpcywgd2Vsa2UgYmVoYW5kZWxpbmdlbiB6aWpuIGVmZmVjdGllZj8KCiMgV2Fhcm9tIGVlbiBuaWV0LXBhcmFtZXRyaXNjaGUgdGVzdD8KClZvb3IgaGV0IHByb2plY3QgbG9zc2VuIGp1bGxpZSBkZXplIG9uZGVyem9la3N2cmFhZyBvcCBtZXQgYmVodWxwIHZhbiBwYXJhbWV0cmlzY2hlIEFOT1ZBIChkZSBGLXRlc3QpLgpEaXQgaXMgZWVuIGdlbGRpZ2UgdGVzdCBhbHMgYWFuIGRlIGFzc3VtcHRpZXMgdm9sZGFhbiB3b3JkdC4KRWNodGVyLCBob2Uga2xlaW5lciBkZSBkYXRhc2V0LCBob2UgbW9laWxpamtlciBoZXQgaXMgb20gZGV6ZSBhc3N1bXB0aWUgdGUgY29udHJvbGVyZW4uCkVlbiBtb2dlbGlqa2Ugb3Bsb3NzaW5nIGthbiB6aWpuIG9tIGRlIE5vcm1hbGl0ZWl0c2Fzc3VtcHRpZSB0ZSBjaGVja2VuIG9wIGRlIHZvbGxlZGlnZSBkYXRhc2V0IGFhbiBkZSBoYW5kIHZhbiBlZW4gbGluZWFpciBtb2RlbCwgem9hbHMgd2UgaGllcm9uZGVyIGRvZW4uCgpgYGB7cn0KI0xlZXMgZGUgZGF0YSBpbgpkYXRhc2V0PXJlYWQuY3N2KCJ+L0Ryb3Bib3gvUGhEL09uZGVyd2lqcy9TdGF0aXN0aWVrIEJpb2NoZW1pZS8yMDE4MTkvZHJvcGJveFN0YXRzMTgxOS9jbGFzczZfbm9uUGFyL2hhbGYvdmVyc2dld2ljaHRfc2xhLnR4dCIsaGVhZGVyPVRSVUUpCm0gPC0gbG0odmVyc2dld2ljaHQgfiBiZWhhbmRlbGluZywgZGF0YT1kYXRhc2V0KQpwYXIobWZyb3c9YygyLDIpKQpwbG90KG0pCnBhcihtZnJvdz1jKDEsMSkpCmBgYAoKRGUgUVEtcGxvdCBpcyBub2dhbCB0d2lqZmVsYWNodGlnLCBlbiBtZW4gem91IGJlaWRlIGthbnRlbiBrdW5uZW4gYmVhcmd1bWVudGVyZW4uCkluZGVyZGFhZCwgZW5lcnppamRzIGthbiBtZW4gYXJndW1lbnRlcmVuIGRhdCBkZSBRUS1wbG90IG5pZXQgYmlqem9uZGVyIHN0ZXJrIGFmd2lqa3QgdmFuIHdhdCBtZW4gem91IHZlcndhY2h0ZW4gb3AgYmFzaXMgdmFuIGVlbiBOb3JtYWxlIGRpc3RyaWJ1dGllLgpBbmRlcnppamRzLCBrYW4gbWVuIGFyZ3VtZW50ZXJlbiBkYXQgKGkpIGRlIFFRLXBsb3QgbGljaHQgYWZ3aWprdCwgZW4gKGlpKSB3ZSBib3ZlbmRpZW4gZWVuIE5vcm1hbGUgZGlzdHJpYnV0aWUgbW9ldGVuIHZlcm9uZGVyc3RlbGxlbiAqKmJpbm5lbiBlbGtlIGdyb2VwKiosIGVuIGRlIGJvdmVuc3RhYW5kZSBRUS1wbG90IGdlZW4gc2x1aXRlbmQgYmV3aWpzIGdlZWZ0Lgpab2FscyBqZSB6aWV0LCBpcyBkaXQgZWVuIGRhdGFzZXQgd2FhcmJpaiB6b3dlbCBkZSBhcmd1bWVudGF0aWUgdm9vciBlZW4gcGFyYW1ldHJpc2NoZSBBTk9WQSB0ZXN0IGFscyBkZSBhcmd1bWVudGF0aWUgdm9vciBlZW4gbmlldC1wYXJhbWV0cmlzY2hlIEtydXNrYWwtV2FsbGlzIHRlc3Qgc3RlZWsga2FuIGhvdWRlbi4gRGUgdmVpbGlnZSBvcHRpZSBpcyBkdWlkZWxpamsgZGUgS3J1c2thbC1XYWxsaXMgdGVzdCwgYWFuZ2V6aWVuIGRpZSBnZWVuIHBhcmFtZXRyc2ljaGUgYXNzdW1wdGllcyB2ZXJvbmRlcnN0ZWx0LiBEZSBlbmlnZSB2ZXJvbmRlcnN0ZWxsaW5nIGlzIGRhdCBkZSBkYXRhIG9uYWZoYW5rZWxpamsgemlqbi4KQm92ZW5kaWVuIGthbiBoZXQsIG9tIGVlbiBhbGdlbWVlbiBpbnppY2h0IHRlIHZlcmtyaWpnZW4sIG9vayBudXR0aWcgemlqbiBvbSBkZSByZXN1bHRhdGVuIHRlIGludGVycHJldGVyZW4gaW4gZnVuY3RpZSB2YW4gZGUgcHJvYmFiaWxpc3Rpc2NoZSBpbmRleC4KCgpTdGVsIGRhdCBkZSB2ZXJzZ2V3aWNodGVuIHZhbiBkZSBwbGFudGVuIGdlZW4gTm9ybWFsZSBtYWFyIGJ2YiBlZW4gR2FtbWEgZGlzdHJpYnV0aWUgdm9sZ2VuLgpFZW4gZ2FtbWEgZGlzdHJpYnV0aWUgaGVlZnQgZWVuIGFhbnRhbCBlaWdlbnNjaGFwcGVuIGRpZSB6ZSBlZW4gYmV0ZXJlIGtldXplIHpvdWRlbiBtYWtlbiBvbiBnZXdpY2h0ZW4gdGUgbW9kZWxsZXJlbi4KQmlqdm9vcmJlZWxkLCBnZXdpY2h0ZW4ga3VubmVuIG5pZXQgbmVnYXRpZWYgemlqbi4gRWVuIG5vcm1hbGllIGRpc3RyaWJ1dGllIGthbiBuZWdhdGllZiB3b3JkZW4sIG1hYXIgZWVuIGdhbW1hIGRpc3RyaWJ1dGllIGVlbiBvbmRlcmdyZW5zIGhlZWZ0IGJpaiBudWwuCgpgYGB7cn0KeCA9IHNlcSgtMSwxMCwuMDEpCnlub3JtID0gZG5vcm0oeCwyKQp5Z2FtID0gZGdhbW1hKHgsNSwyKQpwbG90KHgseW5vcm0sdHlwZSA9ICdsJykKbGluZXMoeCx5Z2FtLGNvbCA9ICdyZWQnKQphYmxpbmUodiA9IDApCmxlZ2VuZCgndG9wcmlnaHQnLGMoJ05vcm1hbGUnLCAnR2FtbWEnKSx0ZXh0LmNvbCA9IGMoJ2JsYWNrJywncmVkJykpCmBgYAoKCgpXZSB6dWxsZW4gOSBzYW1wbGVzIHZhbiBlbGsgNyBkYXRhcHVudGVuIGdlbmVyZXJlbiB1aXQgZWVuICoqbm9ybWFsZSoqIGRpc3RyaWJ1dGllLgoKYGBge3J9CnBhcihtZnJvdyA9IGMoMywzKSkKc2V0LnNlZWQoMTEpICMjIHpvcmd0IGVydm9vciBkYXQgYmlqIGhlcmxvcGVuIHZhbiBkZSBjb2RlIGV4YWN0IGRlemVsZmRlICdyYW5kb20nIHdhYXJkZW4gZ2VuZXJlZXJkIHdvcmRlbi4KZm9yKGkgaW4gMTo5KXsKICB4ID0gcm5vcm0oNykKICBxcW5vcm0oeCwgbWFpbiA9IGkpCiAgcXFsaW5lKHgpCn0KYGBgCgpXZSB6aWVuIGluIGRlIFFRLXBsb3RzIGRhdCBkZSBtZWVzdGUgc2FtcGxlcyBub3JtYWFsIHZlcmRlZWxkIGxpamtlbiwgdGVyd2lqbCBzb21taWdlbiB0b2NoIG5pZXQtbGluZWFpcmUgcGF0cm9uZW4gdmVydG9uZW4gKHpvYWxzIFFRLXBsb3QgNSkgZW4gZHVzIG1pc3NjaGllbiAoaW5jb3JyZWN0KSBhbHMgbmlldCBub3JtYWFsIGJlb29yZGVlbGQgem91ZGVuIHdvcmRlbi4KCldlIHp1bGxlbiBudSA5IHNhbXBsZXMgdmFuIGVsayA3IGRhdGFwdW50ZW4gZ2VuZXJlcmVuIHVpdCBlZW4gKipnYW1tYSoqIGRpc3RyaWJ1dGllLgoKYGBge3J9CnBhcihtZnJvdyA9IGMoMywzKSkKc2V0LnNlZWQoMTEpCgpmb3IoaSBpbiAxOjkpewogIHggPSByZ2FtbWEoNyw1LDIpCiAgcXFub3JtKHgsIG1haW4gPSBpKQogIHFxbGluZSh4KQp9CmBgYAoKCldlIHppZW4gaW4gZGUgUVEtcGxvdHMgKGJpanZvb3JiZWVsZCBRUS1wbG90IDQpIGRhdCBzb21taWdlIHN0YWxlbiBzYW1wbGVzIGFmd2lqa2VuIHZhbiBlZW4gcmVjaHRlIHdhdCBjb3JyZWN0IHRvdCBkZSBjb25sdXNpZSB2YW4gbmlldC1ub3JtYWFsIHZlcmRlZWxkZSBkYXRhIHpvdSBsZWlkZW4uCkFhbiBkZSBhbmRlcmUga2FudCBoZWJiZW4gZGUgZGF0YXB1bnRlbiBpbiBidmIgUVEtcGxvdCA3IHdlbCBlZW4gbGluZWFyIHZlcmJhbmQgZW4gem91IGRlemUgZGF0YSBpbmNvcnJlY3Qgd2VsIGFscyBub3JtYWFsIHZlcmRlZWxkIGJlc2Nob3V3ZCBrdW5uZW4gd29yZGVuLgoKTnUgaXMgZGUgYXNzdW1wdGllIHZhbiBub3JtYWxpdGVpdCBiZWxhbmdyaWprIGJpaiBBTk9WQSAoZW4gb29rIHQtdGVzdCkgb21kYXQgbWVuIGhpZXIgZXJ2YW4gdWl0Z2FhdCBkYXQgamUgc3RlZWtwcm9lZmdlbWlkZGVsZGUgbm9ybWFhbCB2ZXJkZWVsZCBpcyByb25kIGhldCBwb3B1bGF0aWVnZW1pZGVsZGUuIApBbHMgamUgZGF0YSBub3JtYWFsIHZlcmRlZWxkIGlzLCB6YWwgZGl0IGFsdGlqZCBoZXQgZ2V2YWwgemlqbi4KQWxzIGplIGRhdGEgbmlldCBub3JtYWFsIHZlcmRlZWxkIGlzLCBkYW4gZ2FhdCBkaXQgYWxsZWVuIG1hYXIgb3AgYWxzIGplIGRhdGFzZXQgZ3Jvb3QgZ2Vub2VnIGlzICh6aWUgZGUgQ2VudHJhbGUgTGltaWV0c3RlbGxpbmcgaW4gZGUgY3Vyc3VzKS4KCldlIGlsbHVzdHJlcmVuIGRpdCBtZXQgZWVuIHNpbXVsYXRpZS4KRWVuIGdyb290IGFhbnRhbCBkYXRhc2V0cyB2YW4gZWxrIDQgZGF0YXB1bnRlbiB3b3JkZW4gZ2VnZW5lcmVlcmQgdWl0IGVlbiBub3JtYWxlIHZlcmRlbGluZy4KV2UgYmVyZWtlbiBwZXIgZGF0YXNldCBoZXQgZ2VtaWRkZWxkZSBlbiB3ZSBjb25zdHJ1ZXJlbiBlZW4gUVEtcGxvdCB2YW4gZGV6ZSBnZW1pZGRlbGRlbiBvbSB0ZSBjb250cm9sZXJlbiBvZiB6ZSBub3JtYWFsIHZlcmRlZWxkIHppam4uIApXZSBoZXJoYWxlbiBkaXQsIG1hYXIgbnUgd29yZGVuIGRlIDQgZGF0YXB1bnRlbiBnZWdlbmVyZWVyZCB1aXQgZWVuIEdhbW1hIGRpc3RyaWJ1dGllLgpPbSBoZXQgZWZmZWN0IHZhbiBkYXRhc2V0IGdyb290dGUgdGUgYmVzdHVkZXJlbiB6dWxsZW4gd2Ugb29rIGRhdGFzZXRzIHVpdCBlZW4gR2FtbWEgZGlzdHJpYnV0aWUgZ2VuZXJlcmVuIHZhbiBncm9vdHRlIDcgZW4gMTAuCgpgYGB7cn0Kc2V0LnNlZWQoMTEpCnNhbXBsZXNfbm9ybWFhbCA9IHJlcGxpY2F0ZSgzMDAwMCwgbWVhbihybm9ybSg0KSkpCnNhbXBsZXNfZ2FtbWFfNCA9IHJlcGxpY2F0ZSgzMDAwMCwgbWVhbihyZ2FtbWEoMyw1LDIpKSkKc2FtcGxlc19nYW1tYV83ID0gcmVwbGljYXRlKDMwMDAwLCBtZWFuKHJnYW1tYSg3LDUsMikpKQpzYW1wbGVzX2dhbW1hXzEwID0gcmVwbGljYXRlKDMwMDAwLCBtZWFuKHJnYW1tYSgzMCw1LDIpKSkKcGFyKG1mcm93ID0gYygyLDIpKQpxcW5vcm0oc2FtcGxlc19ub3JtYWFsLHBjaCA9IDIwLCBtYWluID0gJ25vcm1hYWw7IG4gPSA0JykKcXFsaW5lKHNhbXBsZXNfbm9ybWFhbCwgY29sID0gJ3JlZCcpCnFxbm9ybShzYW1wbGVzX2dhbW1hXzQsIHBjaCA9IDIwLCBtYWluID0gJ2dhbW1hOyBuID0gNCcpCnFxbGluZShzYW1wbGVzX2dhbW1hXzQsIGNvbCA9ICdyZWQnKQpxcW5vcm0oc2FtcGxlc19nYW1tYV83LHBjaCA9IDIwLCBtYWluID0gJ2dhbW1hOyBuID0gNycpCnFxbGluZShzYW1wbGVzX2dhbW1hXzcsIGNvbCA9ICdyZWQnKQpxcW5vcm0oc2FtcGxlc19nYW1tYV8xMCxwY2ggPSAyMCwgbWFpbiA9ICdnYW1tYTsgbiA9IDMwJykKcXFsaW5lKHNhbXBsZXNfZ2FtbWFfMTAsIGNvbCA9ICdyZWQnKQpgYGAKCgpXZSB6aWVuIGluIGRlIFFRLXBsb3QgbGlua3Nib3ZlbiBkYXQgZGUgZ2VtaWRkZWxkZW4gdmFuIGRlIG5vcm1hYWwgdmVyZGVlbGRlIGRhdGFzZXRzIGluZGVyZGFhZCBvcCBlZW4gcmVjaHRlIGxpZ2dlbiBlbiBkdXMgbm9ybWFhbCB2ZXJkZWVsZCBsaWprZW4uCkJpaiBkZSBnZW1pZGRlbGRlbiB2YW4gZGUgZ2FtbWEgZGF0YXNldHMgbWV0IGdyb290dGUgNCB6aWVuIHdlIGR1aWRlbGlqa2UgYWZ3aWprZW4gdmFuIGRlIG5vcm1hbGl0ZWl0IChkZSBkaXN0cmlidXRpZSBpcyBzY2hlZWYgdmVyZGVlbGQgbmFhciBsaW5rcykuIFRlc3RzdGF0aXN0aWVrZW4gZW4gcC13YWFyZGVuIGJlcmVrZW5kIG1ldCBBTk9WQSBlbiB0LXRlc3RlbiB6aWpuIGluIGRhdCBnZXZhbCBvbmdlbGRpZy4gCgpJbiBkZSBvbmRlcnN0ZSByaWogUVEtcGxvdHMga2FuIG1lbiB6aWVuIGRhdCBob2UgZ3JvdGVyIGRlIHN0ZWVrcHJvZXZlbiB3b3JkZW4sIGhvZSBtZWVyIGRlIGdlbWlkZGVsZGVuIGVlbiBub3JtYWxlIGRpc3RyaWJ1dGllIGJlbmFkZXJlbi4KQmlqIGdyb3RlcmUgZGF0YXNldHMgemFsIGR1cyBtZW4ga3VubmVuIGFyZ3VtZW50ZXJlbiBkYXQgKipoZXQgc3RlZWtwcm9lZmdlbWlkZGVsZGUqKiBlZW4gbm9ybWFsZSB2ZXJkZWxpbmcgdm9sZ3QuIERpdCBlZmZlY3QsIHdhYXJiaWogZGUgZ2VtaWRkZWxkZW4gdmFuIGVlbiBzdGVla3Byb2VmIHVpdCBvbSBoZXQgZXZlbiB3ZWxrZSBkaXN0cmlidXRpZSBlZW4gbm9ybWFsZSBkaXN0cmlidXRpZSBnYWFuIGJlbmFkZXJlbiBhbHMgZGUgc3RlZWtwcm9lZiBtYWFyIGdyb290IGdlbm9lZyBpcywgbm9lbXQgbWVuIGRlIGNlbnRyYWxlIGxpbWlldHN0ZWxsaW5nLiBBbHMgamUgc3RlZWtwcm9lZiBncm9vdCBnZW5vZWcgaXMsIGthbiBqZSBkdXMgZGUgY2VudHJhbGUgbGltaWV0c3RlbGxpbmcgaW5yb2VwZW4gb20gZGUgbm9ybWFsaXRlaXRzYXNzdW1wdGllIHRlIGFhbnZhYXJkZW4uCgpBbHMgZXIgZ2VlbiBzdGVya2UgYXJndW1lbnRlbiBvbSBkZSBub3JtYWxpdGVpdHNhc3N1bXB0aWUgdGUgYWFudmFhcmRlbiAoYmlqdm9vcmJlZWxkIGdlbGlqa2FhcmRpZ2UgZ3JvdGVyZSBkYXRhc2V0cyBpbiBoZXQgdmVybGVkZW4gbGlqa2VuIG5vcm1hYWwgdmVyZGVlbGQpLCBpcyBoZXQgZG9vcmdhYW5zIHZlaWxpZ2VyIG9tIGRpdCBuaWV0IHRlIGRvZW4gZW4gZWVuIG5pZXQtcGFyYW1ldHJpc2NoZSB0ZXN0IHRlIGdlYnJ1aWtlbi4KCioqTWVyayBvcDoqKiBvb2sgYWxzIGRlIGFzc3VtcHRpZSB2YW4gaG9tb3NjZWRhc3RpY2l0ZWl0IGdlc2Nob25kZW4gaXMgb2YgbW9laWxpamsga2FuIHdvcmRlbiBuYWdlZ2FhbiBkb29yIGVlbiB0ZSBrbGVpbmUgc3RlZWtwcm9lZiwgenVsbGVuIGRlIHRlc3RzdGF0aXN0aWVrZW4gZW4gcC13YWFyZGVuIHZlcnRla2VuZCB6aWpuLiBWb29yIGVlbiB0LXRlc3Qga2FuIGplIG5vZyBnZWJydWlrIG1ha2VuIHZhbiBkZSBXZWxjaCB0LXRlc3QsIHZvb3IgZWVuIEFOT1ZBIHphbCBqZSBiaWogemVlciBzdGVya2UgYWZ3aWpraW5nZW4gdmFuIGhvbW9zY2VkYXN0aWNpdGVpdCBvb2sgZWVuIG5pZXQtcGFyYW1ldHJpc2NoZSB0ZXN0IG1vZXRlbiBnZWJydWlrZW4gZW4gamUgcmVzdWxhdGVuIGluIHRlcm1lbiB2YW4gZGUgcHJvYmFiaWxpc3Rpc2NoZSBpbmRleCBtb2V0ZW4gaW50ZXJwcmV0ZXJlbi4KCiMgRGF0YSBhbmFseXNlCldlIHp1bGxlbiBudSBkZSBzbGFwbGFudGVuIGRhdGFzZXQgaGVyZXZhbHVlcmVuIGVuIG5pZXQtcGFyYW1ldHJpc2NoZSB0ZXN0ZW4gb3ZlcndlZ2VuLgoKYGBge3J9CiNMZWVzIGRlIGRhdGEgaW4KZGF0YXNldD1yZWFkLmNzdigifi9Ecm9wYm94L1BoRC9PbmRlcndpanMvU3RhdGlzdGllayBCaW9jaGVtaWUvMjAxODE5L2Ryb3Bib3hTdGF0czE4MTkvY2xhc3M2X25vblBhci9oYWxmL3ZlcnNnZXdpY2h0X3NsYS50eHQiLGhlYWRlcj1UUlVFKQpgYGAKCiMjIERhdGF2ZXJrZW5uaW5nCgpgYGB7cn0KIyMgVGVsIGhldCBhYW50YWwgbWV0aW5nZW4gcGVyIGJlaGFuZGVsaW5nCnRhYmxlKGRhdGFzZXQkYmVoYW5kZWxpbmcpCmBgYAoKKipUYWJlbCAxOioqIGZyZXF1ZW50aWV0YWJlbCB2YW4gaGV0IGFhbnRhbCBvYnNlcnZhdGllcyBwZXIgYmVoYW5kZWxpbmdzZ3JvZXAuCgpgYGB7cn0KYm94cGxvdCh2ZXJzZ2V3aWNodH5iZWhhbmRlbGluZyxkYXRhc2V0KQpzZXQuc2VlZCgxMCkKc3RyaXBjaGFydCh2ZXJzZ2V3aWNodH5iZWhhbmRlbGluZywgZGF0YSA9IGRhdGFzZXQsCiAgICAgICAgICAgIHZlcnRpY2FsID0gVFJVRSwgbWV0aG9kID0gImppdHRlciIsIAogICAgICAgICAgICBwY2ggPSAxOSwgY29sID1jKCJjb3JhbCIsInN0ZWVsYmx1ZSIsImdvbGQiLCJhcXVhbWFyaW5lMyIpLCAKICAgICAgICAgICAgYWRkID0gVFJVRSkKYGBgCgoqKkZpZ3V1ciAxOioqIEJveHBsb3QgdmFuIGhldCB2ZXJzZ2V3aWNodCBpbiBncmFtIHBlciBiZWhhbmRlbGluZ3Nncm9lcC4gRGUgcHVudGVuIHppam4gZGUgaW5kaXZpZHVlbGUgbWV0aW5nZW4uCgpJbiBkZSBmcmVxdWVudGlldGFiZWwgKFRhYmVsIDEpIHppZW4gd2UgZGF0IGVyIHNsZWNodHMgNyBvYnNlcnZhdGllcyBwZXIgZ3JvZXAgemlqbi4KRGUgZ2VtZXRlbiB2ZXJzZ2V3aWNodGVuIGJpbm5lbiBkZSByZWZvYWsgYmVoYW5kZWxpbmdzZ3JvZXAgemlqbiB6ZWVyIHZlcmdlbGlqa2JhYXIgbWV0IGRpZSB2YW4gZGUgY29udHJvbGVncm9lcC4KRGUgZ2VtZXRlbiB2ZXJzZ2V3aWNodGVuIGJpbm5lbiBkZSBjb2JjIGVuIGRlIGNvbXBvc3QgYmVoYW5kZWxpbmdzZ3JvZXBlbiB6aWpuIG1lcmtlbGlqayBob2dlciBkYW4gZGllIGJpbm5lbiBkZSBjb250cm9sZWdyb2VwLgpEZSBnZW1ldGVuIHZlcnNnZXdpY2h0ZW4gYmlubmVuIGRlIGNvbXBvc3QgYmVoYW5kZWxpbmdzZ3JvZXAgbGlnZ2VuIGdlbWlkZGVsZCBnZXppZW4gaWV0cyBob2dlciBkYW4gZGllIGJpbm5lbiBpbiBkZSBjb2JjIGdyb2VwLCBtYWFyIGVyIGlzIGVlbiBncm90ZSBvdmVybGFwIHR1c3NlbiBnZW1ldGVuIHdhYXJkZXMuCkdlZW4gZW5rZWxlIGJlaGFuZGVsaW5nc2dyb2VwIGJldmF0IHVpdHNjaGlldGVycy4KRGUgbWV0aW5nZW4gYmlubmVuIGllZGVyZSBiZWhhbmRlbGlqa3Nncm9lcCBsaWprdCBzeW1tZXRyaXNjaCB2ZXJkZWVsZC4KRGUgdmFyaWFudGllIHZhbiBkZSBtZXRpbmdlbiBsaWprdCBuaWV0IHN0ZXJrIGFmIHRlIHdpamtlbiB0dXNzZW4gZGUgYmVoYW5kZWxpbmdzZ3JvZXBlbi4KSGV0IGJlcmVpayBlbiBkZSBzcHJlaWRpbmcgdmFuIGRlIHdhYXJkZW4gdHVzc2VuIGRlIHZlcnNjaGlsbGVuZGUgZ3JvZXBlbiBpcyB6ZWVyIHZlcmdlbGlqa2JhYXIuCgojICBLcnVza2FsLVdhbGxpcyBSYW5rIFRlc3QKRG9vciBkZSB3ZWluaWcgZGF0YXB1bnRlbiBpcyBoZXQgbW9laWxpamsgb20gZGUgZGlzdHJpYnV0aW9uZWxlIGFzc3VtcHRpZXMgdm9vciBkZSBwYXJhbWV0cmlzY2hlIEFOT1ZBIHRlIGNvbnRyb2xlcmVuIChub3JtYWxpdGVpdCBlbiBnZWxpamtlIHZhcmlhbnRpZSB0dXNzZW4gZGUgZ3JvZXBlbikuCkRlIEtydXNrYWwtV2FsbGlzIFJhbmsgVGVzdCAoS1ctdGVzdCkgaXMgZWVuIG5pZXQtcGFyYW1ldHJpc2NoZSB2YXJpYW50IHZhbiBkZSBBTk9WQS4KRGV6ZSB0ZXN0IGxhYXQgb25zIHRvZSBvbSBkZSBkaXN0cmlidXRpb25lbGUgYXNzdW1wdGllcyB0ZSByZWxheGVyZW4uCioqTGV0IGVyb3AgZGF0IGRlIGFzc3VtcHRpZSB2YW4gb25hZmhhbmtlbGlqa2hlaWQgdHVzc2VuIGRlIG9ic2VydmF0aWVzIG5vZyBzdGVlZHMgbW9ldCBvcGdhYW4hKioKCkFscyB3ZSB3aWxsZW4gdGVzdGVuIHZvb3IgZWVuIHZlcnNjaGlsIHR1c3NlbiBkZSBtZWRpYWFuIHZhbiBkZSB2ZXJzY2hpbGxlbmRlIGJlaGFuZGVsaW5nc2dyb2VwZW4sIGRhbiBtb2V0ZW4gd2UgdWl0Z2FhbiB2YW4gZGUgbG9jYXRpZSBzaGlmdCBhc3N1bXB0aWUuCk9uZGVyIGRlIGxvY2F0aWUgc2hpZnQgYXNzdW1wdGllIHZlcm9uZGVyc3RlbGxlbiB3ZSBkYXQgZGUgdmVyc2NoaWxsZW5kZSBncm9lcGVuIG9uZGVybGluZyBub2cgc3RlZWRzIGRlemVsZmRlIGRpc3RyaWJ1dGllIHZvbGdlbiAoZGl0IGhvZWZ0IHVpdGVyYWFyZCBuaWV0IG5vb2R6YWtlbGlqayBlZW4gbm9ybWFsZSB2ZXJkZWxpbmcgdGUgemlqbiwgZWxrZSB2ZXJkZWxpbmcgaXMgZ29lZCwgem9sYW5nIGhldCBtYWFyIGluIGJlaWRlIGdyb2VwZW4gZGV6ZWxmZGUgdmVyZGVsaW5nIGlzKS4gCgoqKldhbm5lZXIgamUga2lqa3QgbmFhciBkZSBib3hwbG90cyBpbiBGaWd1dXIgMSwgZGVuayBqZSBkYW4gZGF0IGRlIGxvY2F0aWUgc2hpZnQgYXNzdW1wdGllIGFhbm5lbWVsaWprIGlzPyoqCgouLi4KCgpXYW5uZWVyIHdlIG5pZXQgYmVyZWlkIHppam4gb20gZGUgbG9jYXRpZSBzaGlmdCBhc3N1bXB0aWUgdGUgYWFudmFhcmRlbiwgZGFuIGt1bm5lbiB3ZSBkZSBkaXN0cmlidXRpb25lbGUgYXNzdW1wdGllcyBub2cgdmVyZGVyIHJlbGF4ZXJlbiwgZW4gdGVzdGVuIHdlIGluIHRlcm1lbiB2YW4gcHJvYmFiaWxpc3Rpc2NoZSBpbmRleGVuLgpIaWVyIHRlc3RlbiB3ZSBpbiBoZXQgZ2V2YWwgdmFuIHR3ZWUgZ3JvZXBlbiBkZSBrYW5zIGRhdCBlZW4gd2lsbGVrZXVyaWdlIG1lZXR3YWFyZGUgdWl0IGRlIGVlcnN0ZSBncm9lcCBrb210IGdyb3RlciBvZiBnZWxpamsgaXMgZGFuIGVlbiB3aWxsZWtldXJpZ2UgbWVldHdhYXJkZSB1aXQgZGUgdHdlZWRlIGdyb2VwLgoKIyMgSHlwb3RoZXNlCioqUHJvYmVlciBudSBlZW5zIGRlIG51bGh5cG90aGVzZSBvcCB0ZSBzdGVsbGVuIGluIHRlcm1lbiB2YW4gZGUgb25kZXJ6b2Vrc3ZyYWFnPyoqCgouLi4KCiMjIFN0YXRpc3Rpc2NoZSB0ZXN0CgpTaW5kcyB3ZSB0ZSBtYWtlbiBoZWJiZW4gbWV0IGVlbiBrbGVpbiBhYW50YWwgb2JzZXJ2YXRpZXMgcGVyIGdyb2VwIGlzIGhldCBuaWV0IGFhbiB0ZSByYWRlbiBvbSBkZSBhc3ltcHRvdGlzY2hlIEtXLXRlc3QgdGUgZ2VicnVpa2VuIG9tIGVlbiBwLXdhYXJkZSB0ZSBiZXJla2VuZW4uCkRlemUgc3RlbHQgbmFtZWxpamsgZGF0IGplIHRlc3RzdGF0aXN0aWVrIG9uZGVyIGRlIG51bGh5cG90aGVzZSBlZW4gJFxjaGleMiQgZGlzdHJpYnV0aWUgdm9sZ3QgKGRlIG51bGRpc3RyaWJ1dGllKSB3YW5uZWVyIGhldCBhYW50YWwgb2JlcnNlcnZhdGllcyBwZXIgZ3JvZXAgbmFhciBvbmVpbmRpZyBuZWlndCAoZHVzIHZvb3IgZWVuIGdyb290IGFhbnRhbCBvYnNlcnZhdGllcykuCgpXYW5uZWVyIGplIGVlbiBiZXBlcmt0IGFhbnRhbCBvYnNlcnZhdGllcyBoZWJ0LCBpcyBoZXQgYmV0ZXIgZGUgbnVsZGlzdHJpYnV0aWUgZXhhY3QgdGUgYmVyZWtlbmVuIHZpYSBwZXJtdXRhdGllcy4KRGl0IGlzIHVpdGVyYWFyZCBjb21wdXRhdGlvbmVlbCBvbm1vZ2VsaWprLCB3YW50IG1ldCA0IGdyb2VwZW4gdmFuIGVsayA3IG9ic2VydmF0aWVzIGJlc3RhYW4gZXIgYHIgZmFjdG9yaWFsKDI4KS8oZmFjdG9yaWFsKDcpXjQpYCBtb2dlbGlqa2UgcGVybXV0YXRpZXMuCkdlbHVra2lnIGlzIGhldCBtZWVzdGFsIHZvbGRvZW5kZSBvbSBkZSBleGFjdGUgbnVsZGlzdHJpYnV0aWUgdGUgYmVuYWRlcmVuIG1ldCBlZW4ga2xlaW5lciBhYW50YWwgcGVybXV0YXRpZXMuCgoqKlZvZXIgZWVuIEtXIHRlc3QgdWl0IG9wIGRlIGRhdGEgbWV0IGJlaHVscCB2YW4gZWVuIGdyb290IGFhbnRhbCBwZXJtdXRhdGllcyAoYnYuIDEwMDAwKS4qKgoqKihUaXA6IHppZSBjdXJzdXMgaHR0cDovL3VzZXJzLnVnZW50LmJlL35sY2xlbWVudC9zdGF0aXN0aWVrLyB2b29yIGNvZGUgdm9vcmJlZWxkZW4pKioKKipXYXQga2FuIGplIGJlc2x1aXRlbiB1aXQgZGl0IHJlc3VsdGFhdD8qKgoKYGBge3J9CmxpYnJhcnkoY29pbikKCmBgYAoKLi4uCgpBbHMgd2Ugd2lsbGVuIHdldGVuIGluIHdlbGtlIHNvb3J0ZW4gZ3JvbmQgZXIgbnUganVpc3QgZWVuIHNpZ25pZmljYW50IHZlcnNjaGlsIGluIHZlcnNnZXdpY2h0IG9wdHJlZWQsIHphbCBtZW4gZWVuIHBvc3QtaG9jIGFuYWx5c2UgbW9ldGVuIGRvZW4uCgojIyBQb3N0LWhvYyBhbmFseXNlClpvYWxzIGJpaiBkZSBwYXJhbWV0cmlzY2hlIEFOT1ZBIHphbCBqZSBvb2sgYmlqIG5hIGRlIG5pZXQtcGFyYW1ldHJpc2NoZSBLVyB0ZXN0IHBhYXJzZ2V3aWp6ZSB0ZXN0ZW4gbW9ldGVuIHVpdHZvZXJlbiBvbSBvbmRlcmxpbmdlIHZlcnNjaGlsbGVuIGluIHZlcnNnZXdpY2h0IHR1c3NlbiBkZSBzbGFwbGFudGVuIHRlIGRldGVjdGVyZW4uCkRpdCB6dWxsZW4gdWl0ZXJhYXJkIG9vayBuaWV0LXBhcmFtZXRyaXNjaGUgdGVzdGVuIHppam4gem9hbHMgZGUgV2lsY294b24tTWFubi1XaGl0bmV5IFRlc3QgKFdNVyB0ZXN0KS4KQWxzIGplIGRlIGtldXplIGdlbWFha3QgaGVidCBvbSBiaWogZGUgS1cgdGVzdCBvbSBkZSBsb2NhdGllIHNoaWZ0IGFzc3VtcHRpZSB0ZSB2ZXJ3ZXJwZW4gZGFuIHphbCBqZSBkaXQgaGllciB0ZXJ1ZyBkb2VuIGVuIGRlIHJlc3VsdGF0ZW4gaW4gdGVybWVuIHZhbiBkZSBwcm9iYWJpbGlzdGlzY2hlIGluZGV4IGludGVycHJldGVyZW4uCgoqKldhdCB6YWwgbnUgZGUgbnVsIGVuIGFsdGVybmF0aWV2ZSBoeXBvdGhlc2UgemlqbiB2b29yIGllZGVyZSBwYWFyc2dld2lqemUgdGVzdD8qKgoKLi4uCgoKKipWb2VyIGVlbiBXTVcgcG9zdC1ob2MgYW5hbHlzZSB1aXQgb3AgZGUgZGF0YS4qKgoKCj4gYGBge3J9CmxpYnJhcnkoY29pbikKCgpgYGAKCi4uLgoKKipLdW4gamUgbnUgb29rIGFhbiBkZSBoYW5kIHZhbiBkZSBNYW5uLVdoaXRuZXkgVTEgc3RhdGlzdGllayBlZW4gcHVudHNjaGF0dGluZyBnZXZlbiB2YW4gZGUgUHJvYmFiaWxpc3Rpc2NoZSBpbmRleD8qKgoKPiAgYGBge3J9CgoKYGBgCi4uLgoKKipIb2UgaW50ZXJwcmV0ZWVyIGplIGRlIHJlc3VsdGF0ZW4gdmFuIGRlIFdNVyB0ZXN0ZW4/KioKCi4uLgoKIyBDb25jbHVzaWUKCi4uLgo=