PC-les 4: Enkelvoudige lineaire regressie

Enkelvoudige lineaire regressie met een continue predictor

Een voorbeeld

We specifiëren ons model als volgt:

\(E[y_i] = \beta_0 + \beta_1 x_i\)

\(y_i = \beta_0 + \beta_1 dosis_i + \epsilon_i\)

met \(\epsilon_i \sim N(0,\sigma^2)\).

Laat ons eens data simuleren.

# Laat ons zeggen dat het intercept = 10 en het gemiddelde effect van de predictor op de uitkomst = 3
beta0 <- 10
beta1 <- 3
# Onze predictoren x hebben waarden van 1 tot 10
x <- 1:10
# Genereer de fouttermen met een standaardafwijking van 2
epsilon <- rnorm(10, sd = 2)
# Onze uitkomstwaarden zijn dan gelijk aan
y <- beta0 + beta1*x + epsilon

Nu fitten we ons lineair regressiemodel.

summary(lm(y~x))

Call:
lm(formula = y ~ x)

Residuals:
    Min      1Q  Median      3Q     Max 
-4.6455 -1.0194  0.0931  1.6805  3.3134 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  12.1509     1.7164   7.079 0.000104 ***
x             2.7075     0.2766   9.788 9.96e-06 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.513 on 8 degrees of freedom
Multiple R-squared:  0.9229,    Adjusted R-squared:  0.9133 
F-statistic:  95.8 on 1 and 8 DF,  p-value: 9.96e-06

De schattingen voor onze modelparameters liggen typisch in de buurt, maar zijn niet gelijk aan de werkelijke modelparameters. Ze zullen verschillen elke keer je nieuwe data simuleert. We krijgen wel een onzekerheid op elke parameterschatting. (Intercept) geeft \(\hat{\beta_0}\) weer, x geeft \(\hat{\beta_1}\) weer.

Overlevingstijd van vissen

Bij 96 vissen (dojovissen, goudvissen en zebravissen) werd de resistentie tegen het gif EI-43,064 getest door elke vis individueel in een vat met 2 liter water en een bepaalde dosis (in mg) van het vergif te steken. Naast de overlevingstijd in minuten (de uitkomst, minsurv) werd ook het gewicht van de vis gemeten (in gram). De onderzoeksvragen zijn: “Wat is de associatie tussen dosis en overlevingstijd?” en “Is er gemiddeld gezien een verschil in overlevingstijd tussen dojovissen, goudvissen en zebravissen?”

Lees de dataset poison.dat in via read.table. Verander de directory naar de folder waarin je de poision.dat file hebt opgeslaan.

poison <- read.table("/Users/lgoeminn/Dropbox/dropboxStats1819/class4/full/poison.dat", sep = "", header = TRUE)
# We gebruiken de volgende variabelen:
soort <- poison$soort
gewicht <- poison$gewicht
dosis <- poison$dosis
minsurv <- poison$minsurv
sum(soort == 0)
[1] 39
sum(soort == 1)
[1] 38
sum(soort == 2)
[1] 19

Eenvoudige lineaire regressie is een regressie waarbij de afhankelijke variabele gemodelleerd wordt in functie van slechts 1 onafhankelijke variabele, i.e. van de vorm \(E[Y_i] = \beta_0 + \beta_1X_i\) (waarbij de \(E\) staat voor de verwachte waarde.). Hierbij stelt \(Y\) de afhankelijke variabele (of responsvariabele) en \(X\) de onafhankelijke variabele (of predictorvariabele) voor.

In deze opgave zullen we een antwoord op de onderzoeksvraag “Wat is de associatie tussen dosis en overlevingstijd?” proberen te formuleren.

We gaan er voor deze oefening van uit dat, voor een gelijk gewicht en gelijke dosis, het effect van het vergif op elke vis over de drie vissoorten heen volledig gelijkaardig is (gelijke distributies van de overlevingstijden voor gelijk gewicht en dosis). Merk op dat deze aanname in de praktijk waarschijnlijk niet zo realistisch is.

1. Maak een gepaste grafiek om de associatie tussen de dosis en de overlevingstijd te bekijken.

Ga na of het realistisch is om een lineaire associatie tussen dosis en overlevingstijd te onderstellen door eerst eens de best passende kromme doorheen de puntenwolk te tekenen en ook eens de best passende rechte.

plot(x=dosis,y=minsurv, xlab="dosis", ylab="overlevingstijd")
# fit een kromme door de puntenwolk (volle lijn)
lines(lowess(dosis,minsurv), lty=1)  # lty=1 tekent een volle lijn
# fit een rechte door de puntenwolk aan de hand van de kleinstekwadratenmethode (gestippelde lijn)
abline(lsfit(dosis,minsurv), lty=2) # lty=2 tekent een stippellijn

De kromme benadert vrij goed een rechte. Op basis van de figuur kunnen we besluiten dat het realistisch is om een lineair verband tussen minsurv en dosis te veronderstellen.

2. Postuleer op basis van voorgaande grafiek een zinvol model voor de gemiddelde overlevingstijd in functie van de dosis.

Model: \(minsurv_i = \beta_0 + \beta_1 dosis_i + \epsilon_i\)

met \(\beta_0\) het (werkelijke) intercept,

\(\beta_1\) de werkelijke helling of meer specifiek het (werkelijk) effect van dosis op de gemiddelde overlevingstijd

en \(\epsilon_i\) een foutterm (“error term”)

We kunnen ook zeggen: \(E[minsurv_i] = \beta_0 + \beta_1 dosis_i\)

Waarbij de \(E\) staat voor de verwachte waarde.

3. Voer een lineaire-regressieanalyse uit om de parameters in het model te schatten.

#fit een lineair regressiemodel met 'minsurv' als afhankelijke en 'dosis' als onafhankelijke variabele
model1 <- lm(minsurv~dosis) 
model1

Call:
lm(formula = minsurv ~ dosis)

Coefficients:
(Intercept)        dosis  
      7.819       -2.267  
summaryM1 <- summary(model1)
summaryM1

Call:
lm(formula = minsurv ~ dosis)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.9857 -1.7536 -0.5846  1.2407  8.1620 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   7.8187     1.1231   6.961  4.5e-10 ***
dosis        -2.2672     0.7073  -3.206  0.00184 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.392 on 94 degrees of freedom
Multiple R-squared:  0.09854,   Adjusted R-squared:  0.08895 
F-statistic: 10.28 on 1 and 94 DF,  p-value: 0.001842

Belangrijk! Alvorens we het lineaire regressiemodel kunnen gebruiken om geldige conclusies te trekken, moeten we de voorwaarden nagaan die moeten voldaan zijn om deze analyse te mogen uitvoeren en de resultaten te mogen vertrouwen.

De assumpties van een lineaire-regressieanalyse zijn:

  1. Onafhankelijke gegevens
  2. Lineariteit tussen respons en predictor (impliceert dat residuen rond nul verdeeld zijn, zonder merkbaar resterend patroon tussen de residuen en de geschatte respons variabele)
  3. Normaal verdeelde residuen
  4. Homoscedasticiteit

Is er hier aan de voorwaarden voldaan?

  1. Onafhankelijkheid

Onafhankelijkheid van de observaties wil zeggen dat kennis over de responswaarde van 1 observatie geen informatie oplevert over de responswaarde van een andere variabele. Vanwege onze (onrealistische) aanname dat de vissoort, bij gelijk gewicht en gelijke dosis, geen informatie geeft over hoe een vis zal reageren op het gif, kunnen we onafhankelijkheid aannemen. Immers, de onderzoekers bestudeerden in hun steekproef 96 vissen door elke vis individueel in een vat met water en een bepaalde dosis vergif te steken. Als je ervan uitgaat dat de randomisatie correct gebeurde en het selecteren van de vissen willekeurig gebeurde, kun je in principe onafhankelijkheid aannemen omdat bij een goede randomisatie observaties onafhankelijk van elkaar worden gemeten.

  1. Lineariteit

De lineariteitsassumptie vereist een lineair verband tussen predictorvariabele en responsvariabele in het volledige bereik van het model. Dit impliceert dat de residuen willekeurig rond nul verdeeld zijn, onafhankelijk van waar we ons op de rechte bevinden (en dus onafhankelijk van de waarde van zowel predictor als respons). Om dit na te gaan, plotten we de waarden van de residuen in functie van de door het model geschatte waarden (fitted values) \(\widehat{minsurv}_i = \hat{\beta}_0 + \hat{\beta}_1 dosis_i\), dus de geschatte gemiddelde overlevingstijd voor elke geobserveerde dosis. We plotten ook de best passende smoother doorheen de punten. Als de assumptie van lineariteit opgaat, zullen de residuen over heel het bereik van de gefitte waarden rond 0 liggen en zal de smoother min of meer een rechte zijn en zeker geen duidelijke trends (zoals duidelijke minima of maxima) vertonen die kunnen wijzen op een kwadratisch of hogere-ordeverband dat niet in rekening werd genomen. Hier lijkt goed aan de lineariteitsassumptie voldaan te zijn, aangezien de residuen mooi rond nul liggen. De smoother ligt daarom ook dicht rond de nul-lijn zonder duidelijke trends.

Merk op: soms kunnen 1 of enkele punten aan het uiteinde van het bereik het verloop van de smoother sterk beinvloeden, vooral als er weinig datapunten zijn. Het criterium om te bepalen of de lineariteitsassumptie geschonden is, is echter dat de residuen over heel het bereik mooi rond nul moeten liggen. De smoother is hierbij (enkel) een hulpmiddel om eventuele trends duidelijker te zien.

# Lineariteit:
plot(fitted(model1),resid(model1))
# Best passende smoother:
lines(lowess(fitted(model1),resid(model1)))
# Best passende rechte in stippellijn:
abline(h=0,lty=2)

  1. Normaal verdeelde residuen

De residuen moeten normaal verdeeld zijn. De beste manier om dit na te gaan is aan de hand van een QQ-plot. Bij een QQ-plot worden percentielen die men heeft berekend voor de gegeven reeks observaties uitgezet t.o.v. de overeenkomstige percentielen die men verwacht op basis van de normale distributie Als de onderstelling correct is dat de gegevens normaal verdeeld zijn, dan komen beide percentielen telkens vrij goed met elkaar overeen en verwacht men bijgevolg een reeks punten min of meer op een rechte te zien. Systematische afwijkingen van een rechte wijzen op systematische afwijkingen van normaliteit. Lukrake afwijkingen van een rechte kunnen het gevolg zijn van sampling variabiliteit en/of toevallige biologische variatie en zijn daarom niet indicatief voor afwijkingen van normaliteit.

# Normaal verdeelde residuen:
qqnorm(resid(model1))
qqline(resid(model1)) #lange rechtse staart + korte linkse staart. Niet echt OK

De residuen hebben een scheef rechtse staart en een korte linkse staart. De normaliteitsassumptie lijkt geschonden. Je kan dit ook zien op het histogram van de residuen:

hist(resid(model1))

  1. Homoscedasticiteit

Homoscedasticiteit betekent “gelijkheid van varianties” (heteroscedasticiteit betekent dat de varianties niet gelijk zijn). Bij lineaire regressie wil de homoscedasticiteitsassumptie zeggen dat de variantie van de residuen onafhankelijk is van waar we ons op de rechte bevinden (dus onafhankelijk van de predictor- en responsvariabele). We plotten het kwadraat van de residuen in functie van de gefitte waarden. Als we hier een smoother door trekken, zou de smoother een horizontaal verloop moeten hebben.

Waarom plotten we het kwadraat van de residuen in functie van de gefitte waarden?

De residuele variantie wordt als volgt berekend: \(\frac{\sum{\hat{e}_i^2}}{n-2}\). Hier willen we kijken of de residuele variantie afhankelijk is van waar we ons op de rechte bevinden. We plotten dus de teller \(\sum{\hat{e}_i^2}\) in functie van de gefitte waarden.

Waarom staat er n-2 in de noemer?

We verliezen 2 vrijheidsgraden omdat we (1) het intercept schatten en (2) het effect voor de predictor dosis schatten.

Voor de studenten biochemie en biotechnologie en biomedische wetenschappen: wanneer we aan het hoofdstuk over multivariate lineaire regressie toekomen, zal dit \(n-p\) worden, met \(p\) het aantal parameters in het model.

# Homoscedasticiteit
plot(fitted(model1),resid(model1)^2)
lines(lowess(x=fitted(model1), y=resid(model1)^2), col="red")

Het nadeel van deze plot is dat het kwadraat van de residuen scheef verdeeld is, waardoor eventuele trends moeilijk te zien zijn (intuitief: als je waarden tussen -1 en 1 kwadrateert, worden ze nog kleiner, en hoe dichter bij 0, hoe kleiner ze worden. Waarden in absolute waarde groter dan 1: als je ze kwadrateert worden ze groter, en hoe groter ze zijn, hoe groter ze worden na kwadratering. Waarden die initieel standaard normaal verdeeld waren, zullen na kwadrateren dus scheef naar rechts verdeeld zijn (chi-kwadraatverdeling met 1 vrijheidsgraad).).

De vierkantswortel van de absolute waarde van de gestandaardiseerde residuen ligt bij homoscedasticiteit ook rond nul, maar is veel minder scheef verdeeld. Gestandaardiseerde residuen (“internally studentized residuals”) zijn een transformatie van de residuen, die een standaard normale distributie zouden vormen gegeven dat de werkelijke fouttermen een gelijke variantie hebben. Indien men dus de absolute waarde van deze residuen zou plotten in functie van de geschatte respons, dan zouden deze geen systematische afwijking van een horizontale lijn mogen volgen. Indien wel, bv. er is een systematische trend waarbij de gestandaardiseerde residuen hoger/lager worden naarmate de fitted values hoger/lager worden, dan betekent het dat de variantie van de residuen hoger/lager wordt naarmate de geschatte respons hoger/lager wordt.

# Gestandaardiseerde residuen
standardisedResiduals <- rstandard(model1)
# Plot de vierkantswortel van de absolute waarde van de gestandaardiseerde residuen in functie van de gefitte waarden
plot(x=fitted(model1), y=sqrt(abs(standardisedResiduals)))
# Teken een smoother door de puntenwolk
lines(lowess(x=fitted(model1), y=sqrt(abs(standardisedResiduals))), col="red")

Uit deze plot blijkt duidelijk dat de residuele variantie toeneemt naarmate de gefitte waarden toenemen. De homoscedasticiteitsassumptie lijkt dus twijfelachtig…

Conclusie: de residuen volgen geen normale verdeling en de assumptie van homoscedasticiteit is twijfelachtig. We kunnen eventueel beroep doen op een transformatie van de afhankelijke variabele om toch aan deze assumpties te voldoen. Dit zullen we verder behandelen in de aparte oefeningenlessen.

Je kan alle assumpties tegelijk checken voor een model. Gebruik hiervoor \(plot(model1)\). Merk op dat je de assumptie van homoscedasiticiteit ook kan nagaan op basis van de eerste plot (residuen vs. fitted values): als de spreiding hoger/lager wordt over de fitted values, is hieraan niet voldaan.

# Meerdere assumpties tegelijk checken
par(mfrow=c(2,2))
plot(model1)

De plot “Residuals vs Leverage” komt voor de studenten biochemie en biotechnologie later nog aan bod. Met \(par(mfrow=c(2,2))\) verdelen we het plotvenster in twee rijen en twee kolommen zodat er 4 plots in 1 venster passen. Om dit terug te zetten op 1 plot per venster, voer dit uit:

# 1 rij en 1 kolom => 1 plot per venster
par(mfrow=c(1,1))
plot(model1)

4. Schrijf het model neer voor de gemiddelde uitkomst met de geschatte regressiecoefficienten ingevuld. Geef de nul- en alternatieve hypothese voor de testen in de summary output. Interpreteer de geschatte regressiecoefficienten.

Opgelet: de assumpties van normaliteit en homoscedasticiteit zijn niet voldaan! De assumpties van onafhankelijkheid en lineariteit lijken niet geschonden. Dit laatste betekent dat de schattingen van de effectgroottes correct zullen zijn. Echter: doordat de normaliteits- en/of homoscedasticiteitsassumptie geschonden zijn, zal onze besluitvorming (m.b.t. significantie) mogelijks incorrect zijn doordat onze teststatistiek niet langer een t-verdeling zal volgen (zie cursus onder “5.5. Nagaan van modelveronderstellingen”). We werken de oefening hier uit ter illustratie, maar hou dit in uw achterhoofd!

summaryM1

Call:
lm(formula = minsurv ~ dosis)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.9857 -1.7536 -0.5846  1.2407  8.1620 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   7.8187     1.1231   6.961  4.5e-10 ***
dosis        -2.2672     0.7073  -3.206  0.00184 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.392 on 94 degrees of freedom
Multiple R-squared:  0.09854,   Adjusted R-squared:  0.08895 
F-statistic: 10.28 on 1 and 94 DF,  p-value: 0.001842

Ons model is als volgt gespecifieerd:

\(E[minsurv_i] = \beta_0 + \beta_1 dosis_i\)

Hierbij is \(E[minsurv_i]\) de verwachte (gemiddelde) overlevingstijd bij een dosis \(dosis_i\).

We hebben ons model zodanig geschat zodat:

\(minsurv_i = \hat{\beta}_0 + \hat{\beta}_1 dosis_i + e_i\)

Hierbij zijn \(e_i\) de residuen. We hebben de residuen zodanig gekozen dat de som van hun kwadraten zo klein mogelijk is (kleinstekwadratenschatter). Hieruit volgt dat de som van de residuen nul is. In ons geval bekomen we hetvolgende:

\(minsurv_i = 7.8187 - 2.2672 * dosis_i + e_i\)

De geschatte gemiddelde overlevingstijd \(\widehat{minsurv_i}\) gegeven een bepaalde dosis \(dosis_i\) is gelijk aan:

\(\widehat{minsurv_i} = 7.8187 - 2.2672 * dosis_i\)

1. Nulhypothese, alternatieve hypothese en interpretatie van het intercept \(\hat{\beta}_0\):

Wat gebeurt er als \(dosis_i\) = 0? Dan krijgen we dit:

\(\widehat{minsurv_i} = \hat{\beta}_0\)

Hieraan zie je dat het intercept dient geïnterpreteerd te worden als de gemiddelde waarde van de responsvariabele gegeven dat de predictorvariabele gelijk is aan nul. We spreken steeds over de gemiddelde waarde van de responsvariabele omdat we de gemiddelde waarde van de responsvariabele hebben gemodelleerd in functie van de predictor.

Intuïtief: herinner u de definitie van het intercept van een rechte: het is de waarde waar de rechte de y-as snijdt (dus waar x = 0). In de summary output wordt een t-test uitgevoerd om na te gaan of het werkelijke intercept verschilt van nul.

De nulhypothese voor deze test in ons voorbeeld luidt: de gemiddelde overlevingstijd van vissen bij een dosis van 0 mg is gelijk aan 0 minuten.

De alternatieve hypothese is: de gemiddelde overlevingstijd van vissen bij een dosis van 0 mg verschilt van 0 minuten.

In ons voorbeeld luidt de correcte interpretatie van het intercept als volgt:

De gemiddelde overlevingstijd van vissen bij een dosis van 0 mg is gelijk aan 7,8 minuten. De p-waarde is gelijk aan 4,5e-10. Het intercept is dus extreem significant verschillend van 0 minuten op het 5%-significantieniveau.

Merk op dat deze schatting niet realistisch is: vissen die geen vergif krijgen, zouden volgens het model gemiddeld gezien na 7,8 minuten spontaan sterven. Dit komt omdat een dosis van 0 mg ver buiten het bereik van ons model ligt. In de realiteit is het veronderstelde lineair verband tussen predictor- en responsvariabele bijna altijd slechts geldig in een beperkt bereik, het bereik van de verklarende variabelen die we gemeten hebben (ook al omdat bv. veel variabelen in de praktijk niet negatief kunnen worden). We kunnen het model dus niet gebruiken om schattingen te maken buiten het bereik! Je kan dit ook zien op onderstaande figuur. Het intercept is in het rood aangeduid. Hierdoor is een nuttige biologische interpretatie van het intercept niet steeds voorhanden.

plot(x=dosis,y=minsurv, xlab="dosis", ylab="overlevingstijd", xlim=c(0,2.2))
#fit een rechte door de puntenwolk aan de hand van de kleinstekwadratenmethode (gestippelde lijn)
abline(lsfit(dosis,minsurv), lty=2) #lty=2 tekent een stippellijn
#duid het intercept aan (rood punt)
points(0,summaryM1$coefficients["(Intercept)","Estimate"],col="red", pch=16)

2. Nulhypothese, alternatieve hypothese en interpretatie van de predictorvariabele \(\hat{\beta}_1\):

Vertrek opnieuw van deze vergelijking:

\(\widehat{minsurv_i} = \hat{\beta}_0 + \hat{\beta}_1 dosis_i\)

Wat gebeurt er als we een nieuwe \(dosis_j\) definiëren die één eenheid hoger ligt? Dan krijgen we dit:

\(\widehat{minsurv_j} = \hat{\beta}_0 + \hat{\beta}_1 dosis_j\)

Aangezien \(j\) één eenheid hoger ligt dan \(i\), kunnen we dit ook als volgt schrijven:

\(\widehat{minsurv_j} = \hat{\beta}_0 + \hat{\beta}_1 * (dosis_i+1)\)

Als we nu \(\widehat{minsurv_i}\) aftrekken van \(\widehat{minsurv_j}\), dan bekomen we exact \(\hat{\beta}_1\).

Dit betekent dat \(\hat{\beta}_1\) gelijk is aan de gemiddelde toename van de repsonsvariabele gegeven dat de predictorvariabele met één eenheid toeneemt. Intuïtief: herinner u de definitie van de richtingscoëfficiënt van een rechte: als de waarde op de x-as met één eenheid toeneemt, neemt de overeenkomstige waarde op de y-as met \(\hat{\beta}_1\) eenheden toe. In de summary output wordt een t-test uitgevoerd om na te gaan of de werkelijke \(\beta_1\) verschilt van nul.

De nulhypothese voor deze test in ons voorbeeld luidt: er is geen verband tussen de dosis vergif en de gemiddelde overlevingstijd van vissen.

De alternatieve hypothese is: er is een lineair effect van de dosis op de gemiddelde overlevingstijd van vissen.

In ons voorbeeld luidt de correcte interpretatie van de predictorvariabele \(\hat{\beta}_1\) als volgt:

Vissen die 1 miligram vergif meer toegediend krijgen, leven gemiddeld gezien 2,26 minuten minder lang dan vissen die die extra miligram vergif niet toegediend kregen. Dit effect is sterk significant verschillend van 0 minuten op het 5%-significantieniveau (p = 0,0018).

Aangezien we hier met een experimentele studie te maken hebben, kunnen we dit ook causaal interpreteren binnen het bereik van het model:

Elke extra 1 miligram vergif die vissen toegediend krijgen, leidt tot een gemiddelde afname in overlevingstijd van 2,26 minuten. Dit effect is sterk significant verschillend van nul op het 5%-significantieniveau (p = 0,0018).

Merk op dat deze laatste interpretatie enkel kan bij experimentele studies en niet bij observationele studies. Als je bv. een lineair verbandt vindt tussen het BBP van een land en het aantal tv’s per inwoner, kan je niet zeggen dat een toename van 1 tv per gezin “leidt tot” een toename in het BBP.

Merk ook op dat de assumpties van normaliteit en homoscedasticiteit geschonden waren! Hierdoor volgt onze teststatistiek geen t-verdeling meer en zijn de bekomen p-waarden onnauwkeurig!

5. Schat de gemiddelde overlevingstijd voor vissen die een dosis van 2 mg kregen en geef een bijhorend 95%-betrouwbaarheidsinterval.

predict(model1, newdata=data.frame(dosis=2), interval="confidence")
       fit      lwr      upr
1 3.284209 2.487741 4.080676

De geschatte overlevingstijd van vissen die een dosis vergif van 2 mg kregen is gelijk aan 3,28 minuten.

Interpretatie van het 95%-betrouwbaarheidsinterval:

Met een waarschijnlijkheid van 95% zal het interval 2,48 tot 4,08 de werkelijke gemiddelde overlevingstijd omvatten voor vissen die een dosis van 2 mg vergif toegediend kregen.

6. Interpreteer de determinatiecoëfficiënt.

summary(model1)

Call:
lm(formula = minsurv ~ dosis)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.9857 -1.7536 -0.5846  1.2407  8.1620 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   7.8187     1.1231   6.961  4.5e-10 ***
dosis        -2.2672     0.7073  -3.206  0.00184 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.392 on 94 degrees of freedom
Multiple R-squared:  0.09854,   Adjusted R-squared:  0.08895 
F-statistic: 10.28 on 1 and 94 DF,  p-value: 0.001842

In het finale model is de determinatiecoëfficiënt gelijk aan 0.09854. Wat betekent dit? Wat zegt dit over de kwaliteit van het model?

In het finale model is de determinatiecoëfficiënt gelijk aan 0,099. Dit betekent dat 9,9% van de variatie in de responsvariabele overlevingstijd wordt verklaard door zijn associatie met de verklarende variabele (= predictorvariabele) dosis. Het model heeft geen sterke voorspellende waarde. Dit zegt echter niets over de kwaliteit van het model!

Enkelvoudige lineaire regressie met een categorische predictor

We focussen ons nu op de tweede onderzoeksvraag: Is er gemiddeld gezien een verschil in overlevingstijd tussen dojovissen, goudvissen en zebravissen? We gaan ervan uit dat dojovissen gecodeerd zijn als “0”, goudvissen als “1” en zebravissen als “2”.

Wegens beperkte tijd gaan we de assumpties voor de volgende modellen hier niet nagaan. Dit is analoog aan wat we voor model1 getoond hebben. Dit is echter wel zeer belangrijk wanneer je zelf een lineaire regressie uitvoert!

Merk op dat als er niets gegeven is, we er normaal gezien van uitgaan dat de gegevens in elke groep willekeurig verzameld zijn (dus ook willekeurig over de relevante gewichten in elke groep). Als er niets gegeven is dat op het tegendeel wijst, gaan we ervan uit dat de randomisatie goed gebeurd is en dat er aan de onafhankelijkheidsassumptie voldaan is.

1. Fit een lineair regressiemodel voor de gemiddelde overlevingstijd in functie van de soort.

model2 <- lm(minsurv ~ soort)
summary(model2)

Call:
lm(formula = minsurv ~ soort)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.9333 -1.7172 -0.8608  1.1298  8.9653 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  4.34165    0.37418  11.603   <2e-16 ***
soort       -0.04698    0.34337  -0.137    0.891    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.519 on 94 degrees of freedom
Multiple R-squared:  0.0001991, Adjusted R-squared:  -0.01044 
F-statistic: 0.01872 on 1 and 94 DF,  p-value: 0.8915

Wat is het gemiddelde verschil in overlevingstijd tussen goudvissen en dojovissen?

De gemiddelde overlevingstijd voor goudvissen ligt 0,05 minuten lager dan de gemiddelde overlevingstijd voor dojovissen. De p-waarde bedraagt 0,89. Het effect van soort op de overlevingstijd is dus niet significant verschillend van nul op het 5%-significantieniveau.

Wat is het gemiddelde verschil in overlevingstijd tussen zebravissen en goudvissen?

De gemiddelde overlevingstijd voor zebravissen ligt 0,05 minuten lager dan de gemiddelde overlevingstijd voor goudvissen. De p-waarde bedraagt 0,89. Het effect van soort op de overlevingstijd is dus niet significant verschillend van nul op het 5%-significantieniveau.

Wat is het gemiddelde verschil in overlevingstijd tussen zebravissen en dojovissen?

De gemiddelde overlevingstijd voor zebravissen ligt 0,04698*2 = 0,09 minuten lager dan de gemiddelde overlevingstijd voor dojovissen. De p-waarde bedraagt 0,89. Het effect van soort op de overlevingstijd is dus niet significant verschillend van nul op het 5%-significantieniveau.

Is deze codering zinvol? Waarom wel/niet?

Deze codering is weinig zinvol, dit model onderstelt impliciet dat het verschil in responsvariabele dosis 2 keer groter is tussen zebravissen en dojovissen dan tussen goudvissen en dojovissen, omdat het de variabele soort aanziet als een numerieke variabele. We zien dit in door het model grafisch voor te stellen:

plot(minsurv~soort)
abline(lm(minsurv~soort),col=2)

2. Maak nu eerst 2 dummyvariabelen. Fit dit model in R en interpreteer de coefficienten.

Oplossing: dummy-variabelen:

  • variabele \(soortgoud\) is 1 als de observatie overeenkomt met een goudvis en nul anders.
  • variabele \(soortzebra\) is 1 als de observatie overeenkomt met een zebravis en nul anders.

We kunnen nu afstappen van de onderstelling dat de overlevingstijd lineair is in het soort vis door een model te fitten met als verklarende variabelen deze twee nieuwe variabelen.

Merk op dat we met telkens werken met k-1 dummy-variabelen waarbij k het aantal niveaus is van de oorspronkelijke factor-variabele. Het resterende niveau wordt dan gerepresenteerd door het intercept. Elk niveau van de categorische variabele is eenduidig gedefinieerd door een combinatie van de dummies:

Tabel 1. Waarden van de dummyvariabelen “soortgoud” en “soortzebra” voor elk level van de factorvariabele “soort”.

Soort soortgoud soortzebra
dojovis 0 0
goudvis 1 0
zebravis 0 1
soortgoud <- ifelse(soort==1,1,0) # soortgoud is 1 als soort==1 en anders 0
soortzebra <- ifelse(soort==2,1,0) # soortzebra is 1 als soort==2 en anders 0
model3 <- lm(minsurv ~ soortgoud + soortzebra)
summary(model3)

Call:
lm(formula = minsurv ~ soortgoud + soortzebra)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.5720 -0.9903 -0.3546  0.7366  7.1103 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   3.4379     0.3188  10.784  < 2e-16 ***
soortgoud     2.7117     0.4538   5.975 4.19e-08 ***
soortzebra   -1.0452     0.5570  -1.877   0.0637 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 1.991 on 93 degrees of freedom
Multiple R-squared:  0.3823,    Adjusted R-squared:  0.369 
F-statistic: 28.77 on 2 and 93 DF,  p-value: 1.873e-10

Bovenstaande aanpak kan vrij inefficiënt zijn als je veel levels hebt (veel vissoorten in dit voorbeeld), omdat je zelf voor ieder level een nieuwe variabele moet aanmaken. Een efficiëntere manier is om soort als een (discrete!) factorvariabele te definiëren en dit mee te nemen in het model. Je vertelt R op deze manier dat soort een factorvariabele is (en geen numerieke variabele). Wanneer je je regressiemodel fit, zal R automatisch een dummycodering gebruiken om om je model te fitten. Vergelijk de parameterschattingen!

fSoort <- factor(soort)
fmodel <- lm(minsurv ~ fSoort)
summary(fmodel)

Call:
lm(formula = minsurv ~ fSoort)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.5720 -0.9903 -0.3546  0.7366  7.1103 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   3.4379     0.3188  10.784  < 2e-16 ***
fSoort1       2.7117     0.4538   5.975 4.19e-08 ***
fSoort2      -1.0452     0.5570  -1.877   0.0637 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 1.991 on 93 degrees of freedom
Multiple R-squared:  0.3823,    Adjusted R-squared:  0.369 
F-statistic: 28.77 on 2 and 93 DF,  p-value: 1.873e-10

We zien dat het model nu drie parameters heeft geschat; waarin de gemiddelde overlevingstijd voor de drie vissoorte in vervat zitten.

beta=coef(fmodel) # geschatte regressiecoefficienten
plot(minsurv~soort)
points(x=0, y=beta[1], pch=17, cex=3/2, col="red") # intercept: dojovis
points(x=1, y=beta[1]+beta[2], pch=17, cex=3/2, col="red") # intercept + fsoort1: goudvis
points(x=2, y=beta[1]+beta[3], pch=17, cex=3/2, col="red") # intercept + fsoort2: zebravis
legend("topright",c("data","geschatte gemiddelde"),pch=c(1,17), col=1:2, bty="n", cex=2/3)

1. Interpretatie van het intercept

Zoals voorheen moet het intercept geinterpreteerd worden als de gemiddelde respons wanneer de predictoren gelijk zijn aan nul. Uit tabel 1 blijkt dat dit overeenkomt met dojovissen. Het intercept moet dus als volgt geinterpreteerd worden:

De gemiddelde overlevingstijd van dojovissen is gelijk aan 3,4 minuten. Dit effect is extreem significant verschillend van nul (p < 2e-16).

2. Interpretatie van “fSoort1” (of “soortgoud”)

We weten dat dojovissen voorgesteld worden door het intercept, en dat soort==1 voor goudvissen. De parameter die R fSoort1 noemt, slaat dus op de goudvissen. R zal in de output voor een factor variabele in een lineair model namelijk steeds de naam van de variabele gebruiken gevolgd door het niveau dat de parameter voorstelt. Je kon dit ook bekijken via de tabel hierboven: Als we dojovissen met goudvissen vergelijken, zien we dat de enige variabele die verandert soortgoud is. Deze variabele moet dus als volgt geinterpreteerd worden:

De gemiddelde overlevingstijd voor goudvissen ligt 2,7 minuten hoger dan de gemiddelde overlevingstijd voor dojovissen. Dit effect is extreem significant op het 5%-significantieniveau (p = 4,2e-08).

Merk op dat we deze parameter enkel kunnen interpreteren ten opzichte van de referentieklasse, namelijk het intercept.

3. Interpretatie van “fSoort2” (of “soortzebra”)

Analoog als hierboven weten we dat dojovissen voorgesteld worden door het intercept, en dat soort==2 voor zebravissen. Deze variabele moet dus als volgt geïnterpreteerd worden:

De gemiddelde overlevingstijd voor zebravissen ligt 1,0 minuten lager dan de gemiddelde overlevingstijd voor dojovissen. Dit effect is niet significant maar echter wel suggestief op het 5%-significantieniveau (p = 0,06).

Wat als we de gemiddelde overlevingstijd van zebravissen willen vergelijken met goudvissen?

Er is geen parameter in het model die het verschil in gemiddelde overlevingstijd tussen zebravissen en goudvissen aangeeft. We kunnen uiteraard wel de grootte van dit effect berekenen via: -1,0452 - 2,7117 = -3,8. De gemiddelde overlevingstijd voor zebravissen ligt dus 3,8 minuten lager dan de gemiddelde overlevingstijd voor goudvissen. Om echter statistische inferentie te kunnen doen op dit effect, moeten we een combinatie van modelparameters testen, wat volgende week aan bod komt in het practicum ANOVA.

Een andere oplossing om wel inferentie te kunnen doen op dit effect, is je dummyvariabelen anders te coderen, waarbij we “goudvis” als referentieklasse nemen. Dit kan als volgt:

fSoortB <- relevel(fSoort, ref="1") # 1 staat voor "goudvis", dit wordt nu de nieuwe referentieklasse
fmodel2 <- lm(minsurv ~ fSoortB)
summary(fmodel2)

Call:
lm(formula = minsurv ~ fSoortB)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.5720 -0.9903 -0.3546  0.7366  7.1103 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   6.1497     0.3230  19.041  < 2e-16 ***
fSoortB0     -2.7117     0.4538  -5.975 4.19e-08 ***
fSoortB2     -3.7570     0.5594  -6.716 1.46e-09 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 1.991 on 93 degrees of freedom
Multiple R-squared:  0.3823,    Adjusted R-squared:  0.369 
F-statistic: 28.77 on 2 and 93 DF,  p-value: 1.873e-10

fSoortB0 moet nu geinterpreteerd worden als het verschil in gemiddelde overlevingstijd van dojovissen t.o.v. goudvissen. fSoortB2 is dan het verschil in gemiddelde overlevingstijd van zebravissen t.o.v. goudvissen. Dit laatste effect is uiteraard exact gelijk aan de -3,8 die we op basis van fmodel berekenden.

Merk op: We willen hier eigenlijk drie nulhypothesen testen (verschil in gemiddelde overlevingstijd tussen goudvissen en dojovissen, tussen zebravissen en dojovissen, en tussen zebravissen en goudvissen). Hoewel elke test hier apart op het 5%-significantieniveau gecontroleerd is, is de kans om minstens één nulhypothese onterecht te verwerpen, gegeven dat er geen verschil is tussen de drie vissoorten, groter dan 5%. Om hieraan tegemoet te komen, verwijzen we opnieuw naar het volgende practicum: ANOVA.

LS0tCnRpdGxlOiAiRW5rZWx2b3VkaWdlIGxpbmVhaXJlIHJlZ3Jlc3NpZSIKYXV0aG9yOiAiTHVkZ2VyIEdvZW1pbm5lICYgS29lbiBWYW4gZGVuIEJlcmdlIgpkYXRlOiAiMTcvMTEvMjAxNyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBQQy1sZXMgNDogRW5rZWx2b3VkaWdlIGxpbmVhaXJlIHJlZ3Jlc3NpZQoKIyMgRW5rZWx2b3VkaWdlIGxpbmVhaXJlIHJlZ3Jlc3NpZSBtZXQgZWVuIGNvbnRpbnVlIHByZWRpY3RvcgoKIyMjIEVlbiB2b29yYmVlbGQKCldlIHNwZWNpZmnrcmVuIG9ucyBtb2RlbCBhbHMgdm9sZ3Q6CgokRVt5X2ldID0gXGJldGFfMCArIFxiZXRhXzEgeF9pJAoKJHlfaSA9IFxiZXRhXzAgKyBcYmV0YV8xIGRvc2lzX2kgKyBcZXBzaWxvbl9pJAoKbWV0ICRcZXBzaWxvbl9pIFxzaW0gTigwLFxzaWdtYV4yKSQuCgpMYWF0IG9ucyBlZW5zIGRhdGEgc2ltdWxlcmVuLgoKYGBge3J9CiMgTGFhdCBvbnMgemVnZ2VuIGRhdCBoZXQgaW50ZXJjZXB0ID0gMTAgZW4gaGV0IGdlbWlkZGVsZGUgZWZmZWN0IHZhbiBkZSBwcmVkaWN0b3Igb3AgZGUgdWl0a29tc3QgPSAzCmJldGEwIDwtIDEwCmJldGExIDwtIDMKIyBPbnplIHByZWRpY3RvcmVuIHggaGViYmVuIHdhYXJkZW4gdmFuIDEgdG90IDEwCnggPC0gMToxMAojIEdlbmVyZWVyIGRlIGZvdXR0ZXJtZW4gbWV0IGVlbiBzdGFuZGFhcmRhZndpamtpbmcgdmFuIDIKZXBzaWxvbiA8LSBybm9ybSgxMCwgc2QgPSAyKQoKIyBPbnplIHVpdGtvbXN0d2FhcmRlbiB6aWpuIGRhbiBnZWxpamsgYWFuCnkgPC0gYmV0YTAgKyBiZXRhMSp4ICsgZXBzaWxvbgpgYGAKCk51IGZpdHRlbiB3ZSBvbnMgbGluZWFpciByZWdyZXNzaWVtb2RlbC4KCmBgYHtyfQpzdW1tYXJ5KGxtKHl+eCkpCmBgYAoKRGUgc2NoYXR0aW5nZW4gdm9vciBvbnplIG1vZGVscGFyYW1ldGVycyBsaWdnZW4gdHlwaXNjaCBpbiBkZSBidXVydCwgbWFhciB6aWpuIG5pZXQgZ2VsaWprIGFhbiBkZSB3ZXJrZWxpamtlIG1vZGVscGFyYW1ldGVycy4gWmUgenVsbGVuIHZlcnNjaGlsbGVuIGVsa2Uga2VlciBqZSBuaWV1d2UgZGF0YSBzaW11bGVlcnQuIFdlIGtyaWpnZW4gd2VsIGVlbiBvbnpla2VyaGVpZCBvcCBlbGtlIHBhcmFtZXRlcnNjaGF0dGluZy4gYChJbnRlcmNlcHQpYCBnZWVmdCAkXGhhdHtcYmV0YV8wfSQgd2VlciwgYHhgIGdlZWZ0ICRcaGF0e1xiZXRhXzF9JCB3ZWVyLgoKIyMjIE92ZXJsZXZpbmdzdGlqZCB2YW4gdmlzc2VuCgpCaWogOTYgdmlzc2VuIChkb2pvdmlzc2VuLCBnb3Vkdmlzc2VuIGVuIHplYnJhdmlzc2VuKSB3ZXJkIGRlIHJlc2lzdGVudGllIHRlZ2VuIGhldCBnaWYgRUktNDMsMDY0IGdldGVzdCBkb29yIGVsa2UgdmlzIGluZGl2aWR1ZWVsIGluIGVlbiB2YXQgbWV0IDIgbGl0ZXIgd2F0ZXIgZW4gZWVuIGJlcGFhbGRlIGBkb3Npc2AgKGluIG1nKSB2YW4gaGV0IHZlcmdpZiB0ZSBzdGVrZW4uIE5hYXN0IGRlIG92ZXJsZXZpbmdzdGlqZCBpbiBtaW51dGVuIChkZSB1aXRrb21zdCwgYG1pbnN1cnZgKSB3ZXJkIG9vayBoZXQgYGdld2ljaHRgIHZhbiBkZSB2aXMgZ2VtZXRlbiAoaW4gZ3JhbSkuIERlIG9uZGVyem9la3N2cmFnZW4gemlqbjogIldhdCBpcyBkZSBhc3NvY2lhdGllIHR1c3NlbiBkb3NpcyBlbiBvdmVybGV2aW5nc3RpamQ/IiBlbiAiSXMgZXIgZ2VtaWRkZWxkIGdlemllbiBlZW4gdmVyc2NoaWwgaW4gb3ZlcmxldmluZ3N0aWpkIHR1c3NlbiBkb2pvdmlzc2VuLCBnb3Vkdmlzc2VuIGVuIHplYnJhdmlzc2VuPyIKCkxlZXMgZGUgZGF0YXNldCBwb2lzb24uZGF0IGluIHZpYSBgcmVhZC50YWJsZWAuIFZlcmFuZGVyIGRlIGRpcmVjdG9yeSBuYWFyIGRlIGZvbGRlciB3YWFyaW4gamUgZGUgYHBvaXNpb24uZGF0YCBmaWxlIGhlYnQgb3BnZXNsYWFuLgoKYGBge3J9CnBvaXNvbiA8LSByZWFkLnRhYmxlKCIvVXNlcnMvbGdvZW1pbm4vRHJvcGJveC9kcm9wYm94U3RhdHMxODE5L2NsYXNzNC9mdWxsL3BvaXNvbi5kYXQiLCBzZXAgPSAiIiwgaGVhZGVyID0gVFJVRSkKCiMgV2UgZ2VicnVpa2VuIGRlIHZvbGdlbmRlIHZhcmlhYmVsZW46CnNvb3J0IDwtIHBvaXNvbiRzb29ydApnZXdpY2h0IDwtIHBvaXNvbiRnZXdpY2h0CmRvc2lzIDwtIHBvaXNvbiRkb3NpcwptaW5zdXJ2IDwtIHBvaXNvbiRtaW5zdXJ2CgpzdW0oc29vcnQgPT0gMCkKc3VtKHNvb3J0ID09IDEpCnN1bShzb29ydCA9PSAyKQpgYGAKCkVlbnZvdWRpZ2UgbGluZWFpcmUgcmVncmVzc2llIGlzIGVlbiByZWdyZXNzaWUgd2FhcmJpaiBkZSBhZmhhbmtlbGlqa2UgdmFyaWFiZWxlIGdlbW9kZWxsZWVyZCB3b3JkdCBpbiBmdW5jdGllIHZhbiBzbGVjaHRzIDEgb25hZmhhbmtlbGlqa2UgdmFyaWFiZWxlLCBpLmUuIHZhbiBkZSB2b3JtICRFW1lfaV0gPSBcYmV0YV8wICsgXGJldGFfMVhfaSQgKHdhYXJiaWogZGUgJEUkIHN0YWF0IHZvb3IgZGUgdmVyd2FjaHRlIHdhYXJkZS4pLiBIaWVyYmlqIHN0ZWx0ICRZJCBkZSBhZmhhbmtlbGlqa2UgdmFyaWFiZWxlIChvZiByZXNwb25zdmFyaWFiZWxlKSBlbiAkWCQgZGUgb25hZmhhbmtlbGlqa2UgdmFyaWFiZWxlIChvZiBwcmVkaWN0b3J2YXJpYWJlbGUpIHZvb3IuCgpJbiBkZXplIG9wZ2F2ZSB6dWxsZW4gd2UgZWVuIGFudHdvb3JkIG9wIGRlIG9uZGVyem9la3N2cmFhZyAqKiJXYXQgaXMgZGUgYXNzb2NpYXRpZSB0dXNzZW4gZG9zaXMgZW4gb3ZlcmxldmluZ3N0aWpkPyIqKiBwcm9iZXJlbiB0ZSBmb3JtdWxlcmVuLgoKV2UgZ2FhbiBlciB2b29yIGRlemUgb2VmZW5pbmcgdmFuIHVpdCBkYXQsIHZvb3IgZWVuIGdlbGlqayBnZXdpY2h0IGVuIGdlbGlqa2UgZG9zaXMsIGhldCBlZmZlY3QgdmFuIGhldCB2ZXJnaWYgb3AgZWxrZSB2aXMgb3ZlciBkZSBkcmllIHZpc3Nvb3J0ZW4gaGVlbiB2b2xsZWRpZyBnZWxpamthYXJkaWcgaXMgKGdlbGlqa2UgZGlzdHJpYnV0aWVzIHZhbiBkZSBvdmVybGV2aW5nc3RpamRlbiB2b29yIGdlbGlqayBnZXdpY2h0IGVuIGRvc2lzKS4gTWVyayBvcCBkYXQgZGV6ZSBhYW5uYW1lIGluIGRlIHByYWt0aWprIHdhYXJzY2hpam5saWprIG5pZXQgem8gcmVhbGlzdGlzY2ggaXMuCgojIyMgMS4gTWFhayBlZW4gZ2VwYXN0ZSBncmFmaWVrIG9tIGRlIGFzc29jaWF0aWUgdHVzc2VuIGRlIGRvc2lzIGVuIGRlIG92ZXJsZXZpbmdzdGlqZCB0ZSBiZWtpamtlbi4KCkdhIG5hIG9mIGhldCByZWFsaXN0aXNjaCBpcyBvbSBlZW4gbGluZWFpcmUgYXNzb2NpYXRpZSB0dXNzZW4gZG9zaXMgZW4gb3ZlcmxldmluZ3N0aWpkIHRlIG9uZGVyc3RlbGxlbiBkb29yIGVlcnN0IGVlbnMgZGUgYmVzdCBwYXNzZW5kZSBrcm9tbWUgZG9vcmhlZW4gZGUgcHVudGVud29sayB0ZSB0ZWtlbmVuIGVuIG9vayBlZW5zIGRlIGJlc3QgcGFzc2VuZGUgcmVjaHRlLgoKYGBge3J9CnBsb3QoeD1kb3Npcyx5PW1pbnN1cnYsIHhsYWI9ImRvc2lzIiwgeWxhYj0ib3ZlcmxldmluZ3N0aWpkIikKCiMgZml0IGVlbiBrcm9tbWUgZG9vciBkZSBwdW50ZW53b2xrICh2b2xsZSBsaWpuKQoKbGluZXMobG93ZXNzKGRvc2lzLG1pbnN1cnYpLCBsdHk9MSkgICMgbHR5PTEgdGVrZW50IGVlbiB2b2xsZSBsaWpuCiMgZml0IGVlbiByZWNodGUgZG9vciBkZSBwdW50ZW53b2xrIGFhbiBkZSBoYW5kIHZhbiBkZSBrbGVpbnN0ZWt3YWRyYXRlbm1ldGhvZGUgKGdlc3RpcHBlbGRlIGxpam4pCgphYmxpbmUobHNmaXQoZG9zaXMsbWluc3VydiksIGx0eT0yKSAjIGx0eT0yIHRla2VudCBlZW4gc3RpcHBlbGxpam4KYGBgCgpEZSBrcm9tbWUgYmVuYWRlcnQgdnJpaiBnb2VkIGVlbiByZWNodGUuIE9wIGJhc2lzIHZhbiBkZSBmaWd1dXIga3VubmVuIHdlIGJlc2x1aXRlbiBkYXQgaGV0IHJlYWxpc3Rpc2NoIGlzIG9tIGVlbiBsaW5lYWlyIHZlcmJhbmQgdHVzc2VuIGBtaW5zdXJ2YCBlbiBgZG9zaXNgIHRlIHZlcm9uZGVyc3RlbGxlbi4KCiMjIyAyLiBQb3N0dWxlZXIgb3AgYmFzaXMgdmFuIHZvb3JnYWFuZGUgZ3JhZmllayBlZW4gemludm9sIG1vZGVsIHZvb3IgZGUgZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgaW4gZnVuY3RpZSB2YW4gZGUgZG9zaXMuCgpNb2RlbDoKJG1pbnN1cnZfaSA9IFxiZXRhXzAgKyBcYmV0YV8xIGRvc2lzX2kgKyBcZXBzaWxvbl9pJAoKbWV0ICRcYmV0YV8wJCBoZXQgKHdlcmtlbGlqa2UpICoqaW50ZXJjZXB0KiosCgokXGJldGFfMSQgZGUgd2Vya2VsaWprZSAqKmhlbGxpbmcqKiBvZiBtZWVyIHNwZWNpZmllayBoZXQgKHdlcmtlbGlqaykgKiplZmZlY3QgdmFuIGRvc2lzIG9wIGRlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkKioKCmVuICRcZXBzaWxvbl9pJCBlZW4gZm91dHRlcm0gKCJlcnJvciB0ZXJtIikKCldlIGt1bm5lbiBvb2sgemVnZ2VuOgokRVttaW5zdXJ2X2ldID0gXGJldGFfMCArIFxiZXRhXzEgZG9zaXNfaSQKCldhYXJiaWogZGUgJEUkIHN0YWF0IHZvb3IgZGUgdmVyd2FjaHRlIHdhYXJkZS4KCiMjIyAzLiBWb2VyIGVlbiBsaW5lYWlyZS1yZWdyZXNzaWVhbmFseXNlIHVpdCBvbSBkZSBwYXJhbWV0ZXJzIGluIGhldCBtb2RlbCB0ZSBzY2hhdHRlbi4KCmBgYHtyfQojZml0IGVlbiBsaW5lYWlyIHJlZ3Jlc3NpZW1vZGVsIG1ldCAnbWluc3VydicgYWxzIGFmaGFua2VsaWprZSBlbiAnZG9zaXMnIGFscyBvbmFmaGFua2VsaWprZSB2YXJpYWJlbGUKbW9kZWwxIDwtIGxtKG1pbnN1cnZ+ZG9zaXMpIAptb2RlbDEKc3VtbWFyeU0xIDwtIHN1bW1hcnkobW9kZWwxKQpzdW1tYXJ5TTEKYGBgIAoKQmVsYW5ncmlqayEgQWx2b3JlbnMgd2UgaGV0IGxpbmVhaXJlIHJlZ3Jlc3NpZW1vZGVsIGt1bm5lbiBnZWJydWlrZW4gb20gZ2VsZGlnZSBjb25jbHVzaWVzIHRlIHRyZWtrZW4sIG1vZXRlbiB3ZSBkZSB2b29yd2FhcmRlbiBuYWdhYW4gZGllIG1vZXRlbiB2b2xkYWFuIHppam4gb20gZGV6ZSBhbmFseXNlIHRlIG1vZ2VuIHVpdHZvZXJlbiBlbiBkZSByZXN1bHRhdGVuIHRlIG1vZ2VuIHZlcnRyb3V3ZW4uCgoqKkRlIGFzc3VtcHRpZXMgdmFuIGVlbiBsaW5lYWlyZS1yZWdyZXNzaWVhbmFseXNlIHppam46KioKCiAxLiBPbmFmaGFua2VsaWprZSBnZWdldmVucwogMi4gTGluZWFyaXRlaXQgdHVzc2VuIHJlc3BvbnMgZW4gcHJlZGljdG9yIChpbXBsaWNlZXJ0IGRhdCByZXNpZHVlbiByb25kIG51bCB2ZXJkZWVsZCB6aWpuLCB6b25kZXIgbWVya2JhYXIgcmVzdGVyZW5kIHBhdHJvb24gdHVzc2VuIGRlIHJlc2lkdWVuIGVuIGRlIGdlc2NoYXR0ZSByZXNwb25zIHZhcmlhYmVsZSkKIDMuIE5vcm1hYWwgdmVyZGVlbGRlIHJlc2lkdWVuCiA0LiBIb21vc2NlZGFzdGljaXRlaXQKCklzIGVyIGhpZXIgYWFuIGRlIHZvb3J3YWFyZGVuIHZvbGRhYW4/CgoxLiBPbmFmaGFua2VsaWpraGVpZAoKT25hZmhhbmtlbGlqa2hlaWQgdmFuIGRlIG9ic2VydmF0aWVzIHdpbCB6ZWdnZW4gZGF0IGtlbm5pcyBvdmVyIGRlIHJlc3BvbnN3YWFyZGUgdmFuIDEgb2JzZXJ2YXRpZSBnZWVuIGluZm9ybWF0aWUgb3BsZXZlcnQgb3ZlciBkZSByZXNwb25zd2FhcmRlIHZhbiBlZW4gYW5kZXJlIHZhcmlhYmVsZS4gVmFud2VnZSBvbnplIChvbnJlYWxpc3Rpc2NoZSkgYWFubmFtZSBkYXQgZGUgdmlzc29vcnQsIGJpaiBnZWxpamsgZ2V3aWNodCBlbiBnZWxpamtlIGRvc2lzLCBnZWVuIGluZm9ybWF0aWUgZ2VlZnQgb3ZlciBob2UgZWVuIHZpcyB6YWwgcmVhZ2VyZW4gb3AgaGV0IGdpZiwga3VubmVuIHdlIG9uYWZoYW5rZWxpamtoZWlkIGFhbm5lbWVuLiBJbW1lcnMsIGRlIG9uZGVyem9la2VycyBiZXN0dWRlZXJkZW4gaW4gaHVuIHN0ZWVrcHJvZWYgOTYgdmlzc2VuIGRvb3IgZWxrZSB2aXMgaW5kaXZpZHVlZWwgaW4gZWVuIHZhdCBtZXQgd2F0ZXIgZW4gZWVuIGJlcGFhbGRlIGRvc2lzIHZlcmdpZiB0ZSBzdGVrZW4uIEFscyBqZSBlcnZhbiB1aXRnYWF0IGRhdCBkZSByYW5kb21pc2F0aWUgY29ycmVjdCBnZWJldXJkZSBlbiBoZXQgc2VsZWN0ZXJlbiB2YW4gZGUgdmlzc2VuIHdpbGxla2V1cmlnIGdlYmV1cmRlLCBrdW4gamUgaW4gcHJpbmNpcGUgb25hZmhhbmtlbGlqa2hlaWQgYWFubmVtZW4gb21kYXQgYmlqIGVlbiBnb2VkZSByYW5kb21pc2F0aWUgb2JzZXJ2YXRpZXMgb25hZmhhbmtlbGlqayB2YW4gZWxrYWFyIHdvcmRlbiBnZW1ldGVuLgoKMi4gTGluZWFyaXRlaXQKCkRlIGxpbmVhcml0ZWl0c2Fzc3VtcHRpZSB2ZXJlaXN0IGVlbiBsaW5lYWlyIHZlcmJhbmQgdHVzc2VuIHByZWRpY3RvcnZhcmlhYmVsZSBlbiByZXNwb25zdmFyaWFiZWxlIGluIGhldCB2b2xsZWRpZ2UgYmVyZWlrIHZhbiBoZXQgbW9kZWwuIERpdCBpbXBsaWNlZXJ0IGRhdCBkZSByZXNpZHVlbiB3aWxsZWtldXJpZyByb25kIG51bCB2ZXJkZWVsZCB6aWpuLCBvbmFmaGFua2VsaWprIHZhbiB3YWFyIHdlIG9ucyBvcCBkZSByZWNodGUgYmV2aW5kZW4gKGVuIGR1cyBvbmFmaGFua2VsaWprIHZhbiBkZSB3YWFyZGUgdmFuIHpvd2VsIHByZWRpY3RvciBhbHMgcmVzcG9ucykuIE9tIGRpdCBuYSB0ZSBnYWFuLCBwbG90dGVuIHdlIGRlIHdhYXJkZW4gdmFuIGRlIHJlc2lkdWVuIGluIGZ1bmN0aWUgdmFuIGRlIGRvb3IgaGV0IG1vZGVsIGdlc2NoYXR0ZSB3YWFyZGVuICgqZml0dGVkIHZhbHVlcyopICRcd2lkZWhhdHttaW5zdXJ2fV9pID0gXGhhdHtcYmV0YX1fMCArIFxoYXR7XGJldGF9XzEgZG9zaXNfaSQsIGR1cyBkZSBnZXNjaGF0dGUgZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgdm9vciBlbGtlIGdlb2JzZXJ2ZWVyZGUgZG9zaXMuIFdlIHBsb3R0ZW4gb29rIGRlIGJlc3QgcGFzc2VuZGUgc21vb3RoZXIgZG9vcmhlZW4gZGUgcHVudGVuLiBBbHMgZGUgYXNzdW1wdGllIHZhbiBsaW5lYXJpdGVpdCBvcGdhYXQsIHp1bGxlbiBkZSByZXNpZHVlbiBvdmVyIGhlZWwgaGV0IGJlcmVpayB2YW4gZGUgZ2VmaXR0ZSB3YWFyZGVuIHJvbmQgMCBsaWdnZW4gZW4gemFsIGRlIHNtb290aGVyIG1pbiBvZiBtZWVyIGVlbiByZWNodGUgemlqbiBlbiB6ZWtlciBnZWVuIGR1aWRlbGlqa2UgdHJlbmRzICh6b2FscyBkdWlkZWxpamtlIG1pbmltYSBvZiBtYXhpbWEpIHZlcnRvbmVuIGRpZSBrdW5uZW4gd2lqemVuIG9wIGVlbiBrd2FkcmF0aXNjaCBvZiBob2dlcmUtb3JkZXZlcmJhbmQgZGF0IG5pZXQgaW4gcmVrZW5pbmcgd2VyZCBnZW5vbWVuLiBIaWVyIGxpamt0IGdvZWQgYWFuIGRlIGxpbmVhcml0ZWl0c2Fzc3VtcHRpZSB2b2xkYWFuIHRlIHppam4sIGFhbmdlemllbiBkZSByZXNpZHVlbiBtb29pIHJvbmQgbnVsIGxpZ2dlbi4gRGUgc21vb3RoZXIgbGlndCBkYWFyb20gb29rIGRpY2h0IHJvbmQgZGUgbnVsLWxpam4gem9uZGVyIGR1aWRlbGlqa2UgdHJlbmRzLgoKKipNZXJrIG9wOioqIHNvbXMga3VubmVuIDEgb2YgZW5rZWxlIHB1bnRlbiBhYW4gaGV0IHVpdGVpbmRlIHZhbiBoZXQgYmVyZWlrIGhldCB2ZXJsb29wIHZhbiBkZSBzbW9vdGhlciBzdGVyayBiZWludmxvZWRlbiwgdm9vcmFsIGFscyBlciB3ZWluaWcgZGF0YXB1bnRlbiB6aWpuLiBIZXQgY3JpdGVyaXVtIG9tIHRlIGJlcGFsZW4gb2YgZGUgbGluZWFyaXRlaXRzYXNzdW1wdGllIGdlc2Nob25kZW4gaXMsIGlzIGVjaHRlciBkYXQgZGUgcmVzaWR1ZW4gb3ZlciBoZWVsIGhldCBiZXJlaWsgbW9vaSByb25kIG51bCBtb2V0ZW4gbGlnZ2VuLiBEZSBzbW9vdGhlciBpcyBoaWVyYmlqIChlbmtlbCkgZWVuIGh1bHBtaWRkZWwgb20gZXZlbnR1ZWxlIHRyZW5kcyBkdWlkZWxpamtlciB0ZSB6aWVuLgoKYGBge3J9CiMgTGluZWFyaXRlaXQ6CnBsb3QoZml0dGVkKG1vZGVsMSkscmVzaWQobW9kZWwxKSkKIyBCZXN0IHBhc3NlbmRlIHNtb290aGVyOgpsaW5lcyhsb3dlc3MoZml0dGVkKG1vZGVsMSkscmVzaWQobW9kZWwxKSkpCiMgQmVzdCBwYXNzZW5kZSByZWNodGUgaW4gc3RpcHBlbGxpam46CmFibGluZShoPTAsbHR5PTIpCmBgYCAKCjMuIE5vcm1hYWwgdmVyZGVlbGRlIHJlc2lkdWVuCgpEZSByZXNpZHVlbiBtb2V0ZW4gbm9ybWFhbCB2ZXJkZWVsZCB6aWpuLiBEZSBiZXN0ZSBtYW5pZXIgb20gZGl0IG5hIHRlIGdhYW4gaXMgYWFuIGRlIGhhbmQgdmFuIGVlbiBRUS1wbG90LiBCaWogZWVuIFFRLXBsb3Qgd29yZGVuIHBlcmNlbnRpZWxlbiBkaWUgbWVuIGhlZWZ0IGJlcmVrZW5kIHZvb3IgZGUgZ2VnZXZlbiByZWVrcyBvYnNlcnZhdGllcyB1aXRnZXpldCB0Lm8udi4gZGUgb3ZlcmVlbmtvbXN0aWdlIHBlcmNlbnRpZWxlbiBkaWUgbWVuIHZlcndhY2h0IG9wIGJhc2lzIHZhbiBkZSBub3JtYWxlIGRpc3RyaWJ1dGllIEFscyBkZSBvbmRlcnN0ZWxsaW5nIGNvcnJlY3QgaXMgZGF0IGRlIGdlZ2V2ZW5zIG5vcm1hYWwgdmVyZGVlbGQgemlqbiwgZGFuIGtvbWVuIGJlaWRlIHBlcmNlbnRpZWxlbiB0ZWxrZW5zIHZyaWogZ29lZCBtZXQgZWxrYWFyIG92ZXJlZW4gZW4gdmVyd2FjaHQgbWVuIGJpamdldm9sZyBlZW4gcmVla3MgcHVudGVuIG1pbiBvZiBtZWVyIG9wIGVlbiByZWNodGUgdGUgemllbi4gU3lzdGVtYXRpc2NoZSBhZndpamtpbmdlbiB2YW4gZWVuIHJlY2h0ZSB3aWp6ZW4gb3Agc3lzdGVtYXRpc2NoZSBhZndpamtpbmdlbiB2YW4gbm9ybWFsaXRlaXQuIEx1a3Jha2UgYWZ3aWpraW5nZW4gdmFuIGVlbiByZWNodGUga3VubmVuIGhldCBnZXZvbGcgemlqbiB2YW4gc2FtcGxpbmcgdmFyaWFiaWxpdGVpdCBlbi9vZiB0b2V2YWxsaWdlIGJpb2xvZ2lzY2hlIHZhcmlhdGllIGVuIHppam4gZGFhcm9tIG5pZXQgaW5kaWNhdGllZiB2b29yIGFmd2lqa2luZ2VuIHZhbiBub3JtYWxpdGVpdC4KCmBgYHtyfQojIE5vcm1hYWwgdmVyZGVlbGRlIHJlc2lkdWVuOgpxcW5vcm0ocmVzaWQobW9kZWwxKSkKcXFsaW5lKHJlc2lkKG1vZGVsMSkpICNsYW5nZSByZWNodHNlIHN0YWFydCArIGtvcnRlIGxpbmtzZSBzdGFhcnQuIE5pZXQgZWNodCBPSwpgYGAgCgpEZSByZXNpZHVlbiBoZWJiZW4gZWVuIHNjaGVlZiByZWNodHNlIHN0YWFydCBlbiBlZW4ga29ydGUgbGlua3NlIHN0YWFydC4gRGUgbm9ybWFsaXRlaXRzYXNzdW1wdGllIGxpamt0IGdlc2Nob25kZW4uIEplIGthbiBkaXQgb29rIHppZW4gb3AgaGV0IGhpc3RvZ3JhbSB2YW4gZGUgcmVzaWR1ZW46CgpgYGB7cn0KaGlzdChyZXNpZChtb2RlbDEpKQpgYGAKCjQuIEhvbW9zY2VkYXN0aWNpdGVpdAoKSG9tb3NjZWRhc3RpY2l0ZWl0IGJldGVrZW50ICJnZWxpamtoZWlkIHZhbiB2YXJpYW50aWVzIiAoaGV0ZXJvc2NlZGFzdGljaXRlaXQgYmV0ZWtlbnQgZGF0IGRlIHZhcmlhbnRpZXMgbmlldCBnZWxpamsgemlqbikuIEJpaiBsaW5lYWlyZSByZWdyZXNzaWUgd2lsIGRlIGhvbW9zY2VkYXN0aWNpdGVpdHNhc3N1bXB0aWUgemVnZ2VuIGRhdCBkZSB2YXJpYW50aWUgdmFuIGRlIHJlc2lkdWVuIG9uYWZoYW5rZWxpamsgaXMgdmFuIHdhYXIgd2Ugb25zIG9wIGRlIHJlY2h0ZSBiZXZpbmRlbiAoZHVzIG9uYWZoYW5rZWxpamsgdmFuIGRlIHByZWRpY3Rvci0gZW4gcmVzcG9uc3ZhcmlhYmVsZSkuIFdlIHBsb3R0ZW4gaGV0IGt3YWRyYWF0IHZhbiBkZSByZXNpZHVlbiBpbiBmdW5jdGllIHZhbiBkZSBnZWZpdHRlIHdhYXJkZW4uIEFscyB3ZSBoaWVyIGVlbiBzbW9vdGhlciBkb29yIHRyZWtrZW4sIHpvdSBkZSBzbW9vdGhlciBlZW4gaG9yaXpvbnRhYWwgdmVybG9vcCBtb2V0ZW4gaGViYmVuLgoKKipXYWFyb20gcGxvdHRlbiB3ZSBoZXQga3dhZHJhYXQgdmFuIGRlIHJlc2lkdWVuIGluIGZ1bmN0aWUgdmFuIGRlIGdlZml0dGUgd2FhcmRlbj8qKgoKRGUgcmVzaWR1ZWxlIHZhcmlhbnRpZSB3b3JkdCBhbHMgdm9sZ3QgYmVyZWtlbmQ6ICRcZnJhY3tcc3Vte1xoYXR7ZX1faV4yfX17bi0yfSQuIEhpZXIgd2lsbGVuIHdlIGtpamtlbiBvZiBkZSByZXNpZHVlbGUgdmFyaWFudGllIGFmaGFua2VsaWprIGlzIHZhbiB3YWFyIHdlIG9ucyBvcCBkZSByZWNodGUgYmV2aW5kZW4uIFdlIHBsb3R0ZW4gZHVzIGRlIHRlbGxlciAkXHN1bXtcaGF0e2V9X2leMn0kIGluIGZ1bmN0aWUgdmFuIGRlIGdlZml0dGUgd2FhcmRlbi4KCioqV2Fhcm9tIHN0YWF0IGVyIG4tMiBpbiBkZSBub2VtZXI/KioKCldlIHZlcmxpZXplbiAyIHZyaWpoZWlkc2dyYWRlbiBvbWRhdCB3ZSAoMSkgaGV0IGludGVyY2VwdCBzY2hhdHRlbiBlbiAoMikgaGV0IGVmZmVjdCB2b29yIGRlIHByZWRpY3RvciBgZG9zaXNgIHNjaGF0dGVuLgoKVm9vciBkZSBzdHVkZW50ZW4gYmlvY2hlbWllIGVuIGJpb3RlY2hub2xvZ2llIGVuIGJpb21lZGlzY2hlIHdldGVuc2NoYXBwZW46IHdhbm5lZXIgd2UgYWFuIGhldCBob29mZHN0dWsgb3ZlciBtdWx0aXZhcmlhdGUgbGluZWFpcmUgcmVncmVzc2llIHRvZWtvbWVuLCB6YWwgZGl0ICRuLXAkIHdvcmRlbiwgbWV0ICRwJCBoZXQgYWFudGFsIHBhcmFtZXRlcnMgaW4gaGV0IG1vZGVsLgoKYGBge3J9CiMgSG9tb3NjZWRhc3RpY2l0ZWl0CnBsb3QoZml0dGVkKG1vZGVsMSkscmVzaWQobW9kZWwxKV4yKQpsaW5lcyhsb3dlc3MoeD1maXR0ZWQobW9kZWwxKSwgeT1yZXNpZChtb2RlbDEpXjIpLCBjb2w9InJlZCIpCmBgYCAKCkhldCBuYWRlZWwgdmFuIGRlemUgcGxvdCBpcyBkYXQgaGV0IGt3YWRyYWF0IHZhbiBkZSByZXNpZHVlbiBzY2hlZWYgdmVyZGVlbGQgaXMsIHdhYXJkb29yIGV2ZW50dWVsZSB0cmVuZHMgbW9laWxpamsgdGUgemllbiB6aWpuIChpbnR1aXRpZWY6IGFscyBqZSB3YWFyZGVuIHR1c3NlbiAtMSBlbiAxIGt3YWRyYXRlZXJ0LCB3b3JkZW4gemUgbm9nIGtsZWluZXIsIGVuIGhvZSBkaWNodGVyIGJpaiAwLCBob2Uga2xlaW5lciB6ZSB3b3JkZW4uIFdhYXJkZW4gaW4gYWJzb2x1dGUgd2FhcmRlIGdyb3RlciBkYW4gMTogYWxzIGplIHplIGt3YWRyYXRlZXJ0IHdvcmRlbiB6ZSBncm90ZXIsIGVuIGhvZSBncm90ZXIgemUgemlqbiwgaG9lIGdyb3RlciB6ZSB3b3JkZW4gbmEga3dhZHJhdGVyaW5nLiBXYWFyZGVuIGRpZSBpbml0aWVlbCBzdGFuZGFhcmQgbm9ybWFhbCB2ZXJkZWVsZCB3YXJlbiwgenVsbGVuIG5hIGt3YWRyYXRlcmVuIGR1cyBzY2hlZWYgbmFhciByZWNodHMgdmVyZGVlbGQgemlqbiAoY2hpLWt3YWRyYWF0dmVyZGVsaW5nIG1ldCAxIHZyaWpoZWlkc2dyYWFkKS4pLgoKRGUgKip2aWVya2FudHN3b3J0ZWwgdmFuIGRlIGFic29sdXRlIHdhYXJkZSoqIHZhbiBkZSBnZXN0YW5kYWFyZGlzZWVyZGUgcmVzaWR1ZW4gbGlndCBiaWogaG9tb3NjZWRhc3RpY2l0ZWl0IG9vayByb25kIG51bCwgbWFhciBpcyB2ZWVsIG1pbmRlciBzY2hlZWYgdmVyZGVlbGQuICoqR2VzdGFuZGFhcmRpc2VlcmRlIHJlc2lkdWVuKiogKCJpbnRlcm5hbGx5IHN0dWRlbnRpemVkIHJlc2lkdWFscyIpIHppam4gZWVuIHRyYW5zZm9ybWF0aWUgdmFuIGRlIHJlc2lkdWVuLCBkaWUgZWVuIHN0YW5kYWFyZCBub3JtYWxlIGRpc3RyaWJ1dGllIHpvdWRlbiB2b3JtZW4gZ2VnZXZlbiBkYXQgZGUgd2Vya2VsaWprZSBmb3V0dGVybWVuIGVlbiBnZWxpamtlIHZhcmlhbnRpZSBoZWJiZW4uIEluZGllbiBtZW4gZHVzIGRlIGFic29sdXRlIHdhYXJkZSB2YW4gZGV6ZSByZXNpZHVlbiB6b3UgcGxvdHRlbiBpbiBmdW5jdGllIHZhbiBkZSBnZXNjaGF0dGUgcmVzcG9ucywgZGFuIHpvdWRlbiBkZXplIGdlZW4gc3lzdGVtYXRpc2NoZSBhZndpamtpbmcgdmFuIGVlbiBob3Jpem9udGFsZSBsaWpuIG1vZ2VuIHZvbGdlbi4gSW5kaWVuIHdlbCwgYnYuIGVyIGlzIGVlbiBzeXN0ZW1hdGlzY2hlIHRyZW5kIHdhYXJiaWogZGUgZ2VzdGFuZGFhcmRpc2VlcmRlIHJlc2lkdWVuIGhvZ2VyL2xhZ2VyIHdvcmRlbiBuYWFybWF0ZSBkZSAqZml0dGVkIHZhbHVlcyogaG9nZXIvbGFnZXIgd29yZGVuLCBkYW4gYmV0ZWtlbnQgaGV0IGRhdCBkZSB2YXJpYW50aWUgdmFuIGRlIHJlc2lkdWVuIGhvZ2VyL2xhZ2VyIHdvcmR0IG5hYXJtYXRlIGRlIGdlc2NoYXR0ZSByZXNwb25zIGhvZ2VyL2xhZ2VyIHdvcmR0LgoKYGBge3J9CiMgR2VzdGFuZGFhcmRpc2VlcmRlIHJlc2lkdWVuCnN0YW5kYXJkaXNlZFJlc2lkdWFscyA8LSByc3RhbmRhcmQobW9kZWwxKQojIFBsb3QgZGUgdmllcmthbnRzd29ydGVsIHZhbiBkZSBhYnNvbHV0ZSB3YWFyZGUgdmFuIGRlIGdlc3RhbmRhYXJkaXNlZXJkZSByZXNpZHVlbiBpbiBmdW5jdGllIHZhbiBkZSBnZWZpdHRlIHdhYXJkZW4KcGxvdCh4PWZpdHRlZChtb2RlbDEpLCB5PXNxcnQoYWJzKHN0YW5kYXJkaXNlZFJlc2lkdWFscykpKQojIFRla2VuIGVlbiBzbW9vdGhlciBkb29yIGRlIHB1bnRlbndvbGsKbGluZXMobG93ZXNzKHg9Zml0dGVkKG1vZGVsMSksIHk9c3FydChhYnMoc3RhbmRhcmRpc2VkUmVzaWR1YWxzKSkpLCBjb2w9InJlZCIpCmBgYCAKClVpdCBkZXplIHBsb3QgYmxpamt0IGR1aWRlbGlqayBkYXQgZGUgcmVzaWR1ZWxlIHZhcmlhbnRpZSB0b2VuZWVtdCBuYWFybWF0ZSBkZSBnZWZpdHRlIHdhYXJkZW4gdG9lbmVtZW4uIERlIGhvbW9zY2VkYXN0aWNpdGVpdHNhc3N1bXB0aWUgbGlqa3QgZHVzIHR3aWpmZWxhY2h0aWcuLi4KCioqQ29uY2x1c2llOioqIGRlIHJlc2lkdWVuIHZvbGdlbiBnZWVuIG5vcm1hbGUgdmVyZGVsaW5nIGVuIGRlIGFzc3VtcHRpZSB2YW4gaG9tb3NjZWRhc3RpY2l0ZWl0IGlzIHR3aWpmZWxhY2h0aWcuIFdlIGt1bm5lbiBldmVudHVlZWwgYmVyb2VwIGRvZW4gb3AgZWVuIHRyYW5zZm9ybWF0aWUgdmFuIGRlIGFmaGFua2VsaWprZSB2YXJpYWJlbGUgb20gdG9jaCBhYW4gZGV6ZSBhc3N1bXB0aWVzIHRlIHZvbGRvZW4uIERpdCB6dWxsZW4gd2UgdmVyZGVyIGJlaGFuZGVsZW4gaW4gZGUgYXBhcnRlIG9lZmVuaW5nZW5sZXNzZW4uCgpKZSBrYW4gYWxsZSBhc3N1bXB0aWVzIHRlZ2VsaWprIGNoZWNrZW4gdm9vciBlZW4gbW9kZWwuIEdlYnJ1aWsgaGllcnZvb3IgJHBsb3QobW9kZWwxKSQuIE1lcmsgb3AgZGF0IGplIGRlIGFzc3VtcHRpZSB2YW4gaG9tb3NjZWRhc2l0aWNpdGVpdCBvb2sga2FuIG5hZ2FhbiBvcCBiYXNpcyB2YW4gZGUgZWVyc3RlIHBsb3QgKHJlc2lkdWVuIHZzLiBmaXR0ZWQgdmFsdWVzKTogYWxzIGRlIHNwcmVpZGluZyBob2dlci9sYWdlciB3b3JkdCBvdmVyIGRlIGZpdHRlZCB2YWx1ZXMsIGlzIGhpZXJhYW4gbmlldCB2b2xkYWFuLgoKYGBge3J9CiMgTWVlcmRlcmUgYXNzdW1wdGllcyB0ZWdlbGlqayBjaGVja2VuCnBhcihtZnJvdz1jKDIsMikpCnBsb3QobW9kZWwxKQpgYGAgCgpEZSBwbG90ICJSZXNpZHVhbHMgdnMgTGV2ZXJhZ2UiIGtvbXQgdm9vciBkZSBzdHVkZW50ZW4gYmlvY2hlbWllIGVuIGJpb3RlY2hub2xvZ2llIGxhdGVyIG5vZyBhYW4gYm9kLiBNZXQgJHBhcihtZnJvdz1jKDIsMikpJCB2ZXJkZWxlbiB3ZSBoZXQgcGxvdHZlbnN0ZXIgaW4gdHdlZSByaWplbiBlbiB0d2VlIGtvbG9tbWVuIHpvZGF0IGVyIDQgcGxvdHMgaW4gMSB2ZW5zdGVyIHBhc3Nlbi4gT20gZGl0IHRlcnVnIHRlIHpldHRlbiBvcCAxIHBsb3QgcGVyIHZlbnN0ZXIsIHZvZXIgZGl0IHVpdDoKCmBgYHtyfQojIDEgcmlqIGVuIDEga29sb20gPT4gMSBwbG90IHBlciB2ZW5zdGVyCnBhcihtZnJvdz1jKDEsMSkpCnBsb3QobW9kZWwxKQpgYGAKCiMjIyA0LiBTY2hyaWpmIGhldCBtb2RlbCBuZWVyIHZvb3IgZGUgZ2VtaWRkZWxkZSB1aXRrb21zdCBtZXQgZGUgZ2VzY2hhdHRlIHJlZ3Jlc3NpZWNvZWZmaWNpZW50ZW4gaW5nZXZ1bGQuIEdlZWYgZGUgbnVsLSBlbiBhbHRlcm5hdGlldmUgaHlwb3RoZXNlIHZvb3IgZGUgdGVzdGVuIGluIGRlIHN1bW1hcnkgb3V0cHV0LiBJbnRlcnByZXRlZXIgZGUgZ2VzY2hhdHRlIHJlZ3Jlc3NpZWNvZWZmaWNpZW50ZW4uCgoqKk9wZ2VsZXQ6IGRlIGFzc3VtcHRpZXMgdmFuIG5vcm1hbGl0ZWl0IGVuIGhvbW9zY2VkYXN0aWNpdGVpdCB6aWpuIG5pZXQgdm9sZGFhbiEqKiBEZSBhc3N1bXB0aWVzIHZhbiBvbmFmaGFua2VsaWpraGVpZCBlbiBsaW5lYXJpdGVpdCBsaWprZW4gbmlldCBnZXNjaG9uZGVuLiBEaXQgbGFhdHN0ZSBiZXRla2VudCBkYXQgZGUgc2NoYXR0aW5nZW4gdmFuIGRlIGVmZmVjdGdyb290dGVzIGNvcnJlY3QgenVsbGVuIHppam4uIEVjaHRlcjogZG9vcmRhdCBkZSBub3JtYWxpdGVpdHMtIGVuL29mIGhvbW9zY2VkYXN0aWNpdGVpdHNhc3N1bXB0aWUgZ2VzY2hvbmRlbiB6aWpuLCB6YWwgb256ZSBiZXNsdWl0dm9ybWluZyAobS5iLnQuIHNpZ25pZmljYW50aWUpIG1vZ2VsaWprcyBpbmNvcnJlY3QgemlqbiBkb29yZGF0IG9uemUgdGVzdHN0YXRpc3RpZWsgbmlldCBsYW5nZXIgZWVuIHQtdmVyZGVsaW5nIHphbCB2b2xnZW4gKHppZSBjdXJzdXMgb25kZXIgIjUuNS4gTmFnYWFuIHZhbiBtb2RlbHZlcm9uZGVyc3RlbGxpbmdlbiIpLiBXZSB3ZXJrZW4gZGUgb2VmZW5pbmcgaGllciB1aXQgdGVyIGlsbHVzdHJhdGllLCBtYWFyIGhvdSBkaXQgaW4gdXcgYWNodGVyaG9vZmQhCgpgYGB7cn0Kc3VtbWFyeU0xCmBgYApPbnMgbW9kZWwgaXMgYWxzIHZvbGd0IGdlc3BlY2lmaWVlcmQ6CgokRVttaW5zdXJ2X2ldID0gXGJldGFfMCArIFxiZXRhXzEgZG9zaXNfaSQKCkhpZXJiaWogaXMgJEVbbWluc3Vydl9pXSQgZGUgdmVyd2FjaHRlIChnZW1pZGRlbGRlKSBvdmVybGV2aW5nc3RpamQgYmlqIGVlbiBkb3NpcyAkZG9zaXNfaSQuCgpXZSBoZWJiZW4gb25zIG1vZGVsIHpvZGFuaWcgZ2VzY2hhdCB6b2RhdDoKCiRtaW5zdXJ2X2kgPSBcaGF0e1xiZXRhfV8wICsgXGhhdHtcYmV0YX1fMSBkb3Npc19pICsgZV9pJAoKSGllcmJpaiB6aWpuICRlX2kkIGRlIHJlc2lkdWVuLiBXZSBoZWJiZW4gZGUgcmVzaWR1ZW4gem9kYW5pZyBnZWtvemVuIGRhdCBkZSBzb20gdmFuIGh1biBrd2FkcmF0ZW4gem8ga2xlaW4gbW9nZWxpamsgaXMgKGtsZWluc3Rla3dhZHJhdGVuc2NoYXR0ZXIpLiBIaWVydWl0IHZvbGd0IGRhdCBkZSBzb20gdmFuIGRlIHJlc2lkdWVuIG51bCBpcy4gSW4gb25zIGdldmFsIGJla29tZW4gd2UgaGV0dm9sZ2VuZGU6CgokbWluc3Vydl9pID0gNy44MTg3IC0gMi4yNjcyICogZG9zaXNfaSArIGVfaSQKCkRlIGdlc2NoYXR0ZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCAkXHdpZGVoYXR7bWluc3Vydl9pfSQgZ2VnZXZlbiBlZW4gYmVwYWFsZGUgZG9zaXMgJGRvc2lzX2kkIGlzIGdlbGlqayBhYW46CgokXHdpZGVoYXR7bWluc3Vydl9pfSA9IDcuODE4NyAtIDIuMjY3MiAqIGRvc2lzX2kkCgojIyMjIDEuIE51bGh5cG90aGVzZSwgYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSBlbiBpbnRlcnByZXRhdGllIHZhbiBoZXQgaW50ZXJjZXB0ICRcaGF0e1xiZXRhfV8wJDoKCldhdCBnZWJldXJ0IGVyIGFscyAkZG9zaXNfaSQgPSAwPyBEYW4ga3JpamdlbiB3ZSBkaXQ6CgokXHdpZGVoYXR7bWluc3Vydl9pfSA9IFxoYXR7XGJldGF9XzAkCgpIaWVyYWFuIHppZSBqZSBkYXQgaGV0IGludGVyY2VwdCBkaWVudCBnZe9udGVycHJldGVlcmQgdGUgd29yZGVuIGFscyBkZSBnZW1pZGRlbGRlIHdhYXJkZSB2YW4gZGUgcmVzcG9uc3ZhcmlhYmVsZSBnZWdldmVuIGRhdCBkZSBwcmVkaWN0b3J2YXJpYWJlbGUgZ2VsaWprIGlzIGFhbiBudWwuIFdlIHNwcmVrZW4gc3RlZWRzIG92ZXIgZGUgKipnZW1pZGRlbGRlIHdhYXJkZSoqIHZhbiBkZSByZXNwb25zdmFyaWFiZWxlIG9tZGF0IHdlIGRlIGdlbWlkZGVsZGUgd2FhcmRlIHZhbiBkZSByZXNwb25zdmFyaWFiZWxlIGhlYmJlbiBnZW1vZGVsbGVlcmQgaW4gZnVuY3RpZSB2YW4gZGUgcHJlZGljdG9yLgoKSW50de90aWVmOiBoZXJpbm5lciB1IGRlIGRlZmluaXRpZSB2YW4gaGV0IGludGVyY2VwdCB2YW4gZWVuIHJlY2h0ZTogaGV0IGlzIGRlIHdhYXJkZSB3YWFyIGRlIHJlY2h0ZSBkZSB5LWFzIHNuaWpkdCAoZHVzIHdhYXIgeCA9IDApLiBJbiBkZSBzdW1tYXJ5IG91dHB1dCB3b3JkdCBlZW4gdC10ZXN0IHVpdGdldm9lcmQgb20gbmEgdGUgZ2FhbiBvZiBoZXQgd2Vya2VsaWprZSBpbnRlcmNlcHQgdmVyc2NoaWx0IHZhbiBudWwuCgpEZSAqKm51bGh5cG90aGVzZSoqIHZvb3IgZGV6ZSB0ZXN0IGluIG9ucyB2b29yYmVlbGQgbHVpZHQ6IGRlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIHZhbiB2aXNzZW4gYmlqIGVlbiBkb3NpcyB2YW4gMCBtZyBpcyBnZWxpamsgYWFuIDAgbWludXRlbi4KCkRlICoqYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSoqIGlzOiBkZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2YW4gdmlzc2VuIGJpaiBlZW4gZG9zaXMgdmFuIDAgbWcgdmVyc2NoaWx0IHZhbiAwIG1pbnV0ZW4uCgpJbiBvbnMgdm9vcmJlZWxkIGx1aWR0IGRlIGNvcnJlY3RlICoqaW50ZXJwcmV0YXRpZSB2YW4gaGV0IGludGVyY2VwdCoqIGFscyB2b2xndDoKCioqRGUgZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgdmFuIHZpc3NlbiBiaWogZWVuIGRvc2lzIHZhbiAwIG1nIGlzIGdlbGlqayBhYW4gNyw4IG1pbnV0ZW4uIERlIHAtd2FhcmRlIGlzIGdlbGlqayBhYW4gNCw1ZS0xMC4gSGV0IGludGVyY2VwdCBpcyBkdXMgZXh0cmVlbSBzaWduaWZpY2FudCB2ZXJzY2hpbGxlbmQgdmFuIDAgbWludXRlbiBvcCBoZXQgNSUtc2lnbmlmaWNhbnRpZW5pdmVhdS4qKgoKTWVyayBvcCBkYXQgZGV6ZSBzY2hhdHRpbmcgbmlldCByZWFsaXN0aXNjaCBpczogdmlzc2VuIGRpZSBnZWVuIHZlcmdpZiBrcmlqZ2VuLCB6b3VkZW4gIHZvbGdlbnMgaGV0IG1vZGVsIGdlbWlkZGVsZCBnZXppZW4gbmEgNyw4IG1pbnV0ZW4gc3BvbnRhYW4gc3RlcnZlbi4gRGl0IGtvbXQgb21kYXQgZWVuIGRvc2lzIHZhbiAwIG1nIHZlciBidWl0ZW4gaGV0IGJlcmVpayB2YW4gb25zIG1vZGVsIGxpZ3QuIEluIGRlIHJlYWxpdGVpdCBpcyBoZXQgdmVyb25kZXJzdGVsZGUgbGluZWFpciB2ZXJiYW5kIHR1c3NlbiBwcmVkaWN0b3ItIGVuIHJlc3BvbnN2YXJpYWJlbGUgYmlqbmEgYWx0aWpkIHNsZWNodHMgZ2VsZGlnIGluIGVlbiBiZXBlcmt0IGJlcmVpaywgaGV0IGJlcmVpayB2YW4gZGUgdmVya2xhcmVuZGUgdmFyaWFiZWxlbiBkaWUgd2UgZ2VtZXRlbiBoZWJiZW4gKG9vayBhbCBvbWRhdCBidi4gdmVlbCB2YXJpYWJlbGVuIGluIGRlIHByYWt0aWprIG5pZXQgbmVnYXRpZWYga3VubmVuIHdvcmRlbikuIFdlIGt1bm5lbiBoZXQgbW9kZWwgZHVzIG5pZXQgZ2VicnVpa2VuIG9tIHNjaGF0dGluZ2VuIHRlIG1ha2VuIGJ1aXRlbiBoZXQgYmVyZWlrISBKZSBrYW4gZGl0IG9vayB6aWVuIG9wIG9uZGVyc3RhYW5kZSBmaWd1dXIuIEhldCBpbnRlcmNlcHQgaXMgaW4gaGV0IHJvb2QgYWFuZ2VkdWlkLiBIaWVyZG9vciBpcyBlZW4gbnV0dGlnZSBiaW9sb2dpc2NoZSBpbnRlcnByZXRhdGllIHZhbiBoZXQgaW50ZXJjZXB0IG5pZXQgc3RlZWRzIHZvb3JoYW5kZW4uCgpgYGB7cn0KcGxvdCh4PWRvc2lzLHk9bWluc3VydiwgeGxhYj0iZG9zaXMiLCB5bGFiPSJvdmVybGV2aW5nc3RpamQiLCB4bGltPWMoMCwyLjIpKQojZml0IGVlbiByZWNodGUgZG9vciBkZSBwdW50ZW53b2xrIGFhbiBkZSBoYW5kIHZhbiBkZSBrbGVpbnN0ZWt3YWRyYXRlbm1ldGhvZGUgKGdlc3RpcHBlbGRlIGxpam4pCmFibGluZShsc2ZpdChkb3NpcyxtaW5zdXJ2KSwgbHR5PTIpICNsdHk9MiB0ZWtlbnQgZWVuIHN0aXBwZWxsaWpuCiNkdWlkIGhldCBpbnRlcmNlcHQgYWFuIChyb29kIHB1bnQpCnBvaW50cygwLHN1bW1hcnlNMSRjb2VmZmljaWVudHNbIihJbnRlcmNlcHQpIiwiRXN0aW1hdGUiXSxjb2w9InJlZCIsIHBjaD0xNikKYGBgCgojIyMjIDIuIE51bGh5cG90aGVzZSwgYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSBlbiBpbnRlcnByZXRhdGllIHZhbiBkZSBwcmVkaWN0b3J2YXJpYWJlbGUgJFxoYXR7XGJldGF9XzEkOgoKVmVydHJlayBvcG5pZXV3IHZhbiBkZXplIHZlcmdlbGlqa2luZzoKCiRcd2lkZWhhdHttaW5zdXJ2X2l9ID0gXGhhdHtcYmV0YX1fMCArIFxoYXR7XGJldGF9XzEgZG9zaXNfaSQKCldhdCBnZWJldXJ0IGVyIGFscyB3ZSBlZW4gbmlldXdlICRkb3Npc19qJCBkZWZpbmnrcmVuIGRpZSDp6W4gZWVuaGVpZCBob2dlciBsaWd0PyBEYW4ga3JpamdlbiB3ZSBkaXQ6CgokXHdpZGVoYXR7bWluc3Vydl9qfSA9IFxoYXR7XGJldGF9XzAgKyBcaGF0e1xiZXRhfV8xIGRvc2lzX2okCgpBYW5nZXppZW4gJGokIOnpbiBlZW5oZWlkIGhvZ2VyIGxpZ3QgZGFuICRpJCwga3VubmVuIHdlIGRpdCBvb2sgYWxzIHZvbGd0IHNjaHJpanZlbjoKCiRcd2lkZWhhdHttaW5zdXJ2X2p9ID0gXGhhdHtcYmV0YX1fMCArIFxoYXR7XGJldGF9XzEgKiAoZG9zaXNfaSsxKSQKCkFscyB3ZSBudSAkXHdpZGVoYXR7bWluc3Vydl9pfSQgYWZ0cmVra2VuIHZhbiAkXHdpZGVoYXR7bWluc3Vydl9qfSQsIGRhbiBiZWtvbWVuIHdlIGV4YWN0ICRcaGF0e1xiZXRhfV8xJC4KCkRpdCBiZXRla2VudCBkYXQgJFxoYXR7XGJldGF9XzEkIGdlbGlqayBpcyBhYW4gZGUgKipnZW1pZGRlbGRlIHRvZW5hbWUqKiB2YW4gZGUgcmVwc29uc3ZhcmlhYmVsZSBnZWdldmVuIGRhdCBkZSBwcmVkaWN0b3J2YXJpYWJlbGUgbWV0IOnpbiBlZW5oZWlkIHRvZW5lZW10LiBJbnR173RpZWY6IGhlcmlubmVyIHUgZGUgZGVmaW5pdGllIHZhbiBkZSByaWNodGluZ3Njb+tmZmljaetudCB2YW4gZWVuIHJlY2h0ZTogYWxzIGRlIHdhYXJkZSBvcCBkZSB4LWFzIG1ldCDp6W4gZWVuaGVpZCB0b2VuZWVtdCwgbmVlbXQgZGUgb3ZlcmVlbmtvbXN0aWdlIHdhYXJkZSBvcCBkZSB5LWFzIG1ldCAkXGhhdHtcYmV0YX1fMSQgZWVuaGVkZW4gdG9lLiBJbiBkZSBzdW1tYXJ5IG91dHB1dCB3b3JkdCBlZW4gdC10ZXN0IHVpdGdldm9lcmQgb20gbmEgdGUgZ2FhbiBvZiBkZSB3ZXJrZWxpamtlICRcYmV0YV8xJCB2ZXJzY2hpbHQgdmFuIG51bC4KCkRlICoqbnVsaHlwb3RoZXNlKiogdm9vciBkZXplIHRlc3QgaW4gb25zIHZvb3JiZWVsZCBsdWlkdDogZXIgaXMgZ2VlbiB2ZXJiYW5kIHR1c3NlbiBkZSBkb3NpcyB2ZXJnaWYgZW4gZGUgZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgdmFuIHZpc3Nlbi4KCkRlICoqYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSoqIGlzOiBlciBpcyBlZW4gbGluZWFpciBlZmZlY3QgdmFuIGRlIGRvc2lzIG9wIGRlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIHZhbiB2aXNzZW4uCgpJbiBvbnMgdm9vcmJlZWxkIGx1aWR0IGRlIGNvcnJlY3RlICoqaW50ZXJwcmV0YXRpZSB2YW4gZGUgcHJlZGljdG9ydmFyaWFiZWxlICRcaGF0e1xiZXRhfV8xJCoqIGFscyB2b2xndDoKCioqVmlzc2VuIGRpZSAxIG1pbGlncmFtIHZlcmdpZiBtZWVyIHRvZWdlZGllbmQga3JpamdlbiwgbGV2ZW4gZ2VtaWRkZWxkIGdlemllbiAyLDI2IG1pbnV0ZW4gbWluZGVyIGxhbmcgZGFuIHZpc3NlbiBkaWUgZGllIGV4dHJhIG1pbGlncmFtIHZlcmdpZiBuaWV0IHRvZWdlZGllbmQga3JlZ2VuLiBEaXQgZWZmZWN0IGlzIHN0ZXJrIHNpZ25pZmljYW50IHZlcnNjaGlsbGVuZCB2YW4gMCBtaW51dGVuIG9wIGhldCA1JS1zaWduaWZpY2FudGllbml2ZWF1IChwID0gMCwwMDE4KS4qKgoKQWFuZ2V6aWVuIHdlIGhpZXIgbWV0IGVlbiAqKmV4cGVyaW1lbnRlbGUgc3R1ZGllKiogdGUgbWFrZW4gaGViYmVuLCBrdW5uZW4gd2UgZGl0IG9vayAqKmNhdXNhYWwqKiBpbnRlcnByZXRlcmVuIGJpbm5lbiBoZXQgYmVyZWlrIHZhbiBoZXQgbW9kZWw6CgoqKkVsa2UgZXh0cmEgMSBtaWxpZ3JhbSB2ZXJnaWYgZGllIHZpc3NlbiB0b2VnZWRpZW5kIGtyaWpnZW4sIGxlaWR0IHRvdCBlZW4gZ2VtaWRkZWxkZSBhZm5hbWUgaW4gb3ZlcmxldmluZ3N0aWpkIHZhbiAyLDI2IG1pbnV0ZW4uIERpdCBlZmZlY3QgaXMgc3Rlcmsgc2lnbmlmaWNhbnQgdmVyc2NoaWxsZW5kIHZhbiBudWwgb3AgaGV0IDUlLXNpZ25pZmljYW50aWVuaXZlYXUgKHAgPSAwLDAwMTgpLioqCgpNZXJrIG9wIGRhdCBkZXplIGxhYXRzdGUgaW50ZXJwcmV0YXRpZSBlbmtlbCBrYW4gYmlqICoqZXhwZXJpbWVudGVsZSBzdHVkaWVzKiogZW4gbmlldCBiaWogb2JzZXJ2YXRpb25lbGUgc3R1ZGllcy4gQWxzIGplIGJ2LiBlZW4gbGluZWFpciB2ZXJiYW5kdCB2aW5kdCB0dXNzZW4gaGV0IEJCUCB2YW4gZWVuIGxhbmQgZW4gaGV0IGFhbnRhbCB0didzIHBlciBpbndvbmVyLCBrYW4gamUgbmlldCB6ZWdnZW4gZGF0IGVlbiB0b2VuYW1lIHZhbiAxIHR2IHBlciBnZXppbiAibGVpZHQgdG90IiBlZW4gdG9lbmFtZSBpbiBoZXQgQkJQLgoKTWVyayBvb2sgb3AgZGF0IGRlIGFzc3VtcHRpZXMgdmFuIG5vcm1hbGl0ZWl0IGVuIGhvbW9zY2VkYXN0aWNpdGVpdCBnZXNjaG9uZGVuIHdhcmVuISBIaWVyZG9vciB2b2xndCBvbnplIHRlc3RzdGF0aXN0aWVrIGdlZW4gdC12ZXJkZWxpbmcgbWVlciBlbiB6aWpuIGRlIGJla29tZW4gcC13YWFyZGVuIG9ubmF1d2tldXJpZyEKCiMjIzUuIFNjaGF0IGRlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIHZvb3Igdmlzc2VuIGRpZSBlZW4gZG9zaXMgdmFuIDIgbWcga3JlZ2VuIGVuIGdlZWYgZWVuIGJpamhvcmVuZCA5NSUtYmV0cm91d2JhYXJoZWlkc2ludGVydmFsLgoKYGBge3J9CnByZWRpY3QobW9kZWwxLCBuZXdkYXRhPWRhdGEuZnJhbWUoZG9zaXM9MiksIGludGVydmFsPSJjb25maWRlbmNlIikKYGBgCgpEZSBnZXNjaGF0dGUgb3ZlcmxldmluZ3N0aWpkIHZhbiB2aXNzZW4gZGllIGVlbiBkb3NpcyB2ZXJnaWYgdmFuIDIgbWcga3JlZ2VuIGlzIGdlbGlqayBhYW4gMywyOCBtaW51dGVuLgoKKipJbnRlcnByZXRhdGllIHZhbiBoZXQgOTUlLWJldHJvdXdiYWFyaGVpZHNpbnRlcnZhbDoqKgoKTWV0IGVlbiB3YWFyc2NoaWpubGlqa2hlaWQgdmFuIDk1JSB6YWwgaGV0IGludGVydmFsIDIsNDggdG90IDQsMDggZGUgd2Vya2VsaWprZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCBvbXZhdHRlbiB2b29yIHZpc3NlbiBkaWUgZWVuIGRvc2lzIHZhbiAyIG1nIHZlcmdpZiB0b2VnZWRpZW5kIGtyZWdlbi4KCiMjIzYuIEludGVycHJldGVlciBkZSBkZXRlcm1pbmF0aWVjb+tmZmljaetudC4KCmBgYHtyfQpzdW1tYXJ5KG1vZGVsMSkKYGBgCgoqKkluIGhldCBmaW5hbGUgbW9kZWwgaXMgZGUgZGV0ZXJtaW5hdGllY2/rZmZpY2nrbnQgZ2VsaWprIGFhbiBgMC4wOTg1NGAuIFdhdCBiZXRla2VudCBkaXQ/IFdhdCB6ZWd0IGRpdCBvdmVyIGRlIGt3YWxpdGVpdCB2YW4gaGV0IG1vZGVsPyoqCgpJbiBoZXQgZmluYWxlIG1vZGVsIGlzIGRlIGRldGVybWluYXRpZWNv62ZmaWNp6250IGdlbGlqayBhYW4gMCwwOTkuIERpdCBiZXRla2VudCBkYXQgOSw5JSB2YW4gZGUgdmFyaWF0aWUgaW4gZGUgcmVzcG9uc3ZhcmlhYmVsZSBvdmVybGV2aW5nc3RpamQgd29yZHQgdmVya2xhYXJkIGRvb3IgemlqbiBhc3NvY2lhdGllIG1ldCBkZSB2ZXJrbGFyZW5kZSB2YXJpYWJlbGUgKD0gcHJlZGljdG9ydmFyaWFiZWxlKSBkb3Npcy4gSGV0IG1vZGVsIGhlZWZ0IGdlZW4gc3RlcmtlIHZvb3JzcGVsbGVuZGUgd2FhcmRlLiBEaXQgemVndCBlY2h0ZXIgbmlldHMgb3ZlciBkZSBrd2FsaXRlaXQgdmFuIGhldCBtb2RlbCEKCgojIyBFbmtlbHZvdWRpZ2UgbGluZWFpcmUgcmVncmVzc2llIG1ldCBlZW4gY2F0ZWdvcmlzY2hlIHByZWRpY3RvcgoKV2UgZm9jdXNzZW4gb25zIG51IG9wIGRlIHR3ZWVkZSBvbmRlcnpvZWtzdnJhYWc6ICoqSXMgZXIgZ2VtaWRkZWxkIGdlemllbiBlZW4gdmVyc2NoaWwgaW4gb3ZlcmxldmluZ3N0aWpkIHR1c3NlbiBkb2pvdmlzc2VuLCBnb3Vkdmlzc2VuIGVuIHplYnJhdmlzc2VuPyoqIFdlIGdhYW4gZXJ2YW4gdWl0IGRhdCBkb2pvdmlzc2VuIGdlY29kZWVyZCB6aWpuIGFscyAiMCIsIGdvdWR2aXNzZW4gYWxzICIxIiBlbiB6ZWJyYXZpc3NlbiBhbHMgIjIiLgoKV2VnZW5zIGJlcGVya3RlIHRpamQgZ2FhbiB3ZSBkZSBhc3N1bXB0aWVzIHZvb3IgZGUgdm9sZ2VuZGUgbW9kZWxsZW4gaGllciBuaWV0IG5hZ2Fhbi4gRGl0IGlzIGFuYWxvb2cgYWFuIHdhdCB3ZSB2b29yIGBtb2RlbDFgIGdldG9vbmQgaGViYmVuLiBEaXQgaXMgZWNodGVyIHdlbCB6ZWVyIGJlbGFuZ3Jpamsgd2FubmVlciBqZSB6ZWxmIGVlbiBsaW5lYWlyZSByZWdyZXNzaWUgdWl0dm9lcnQhCgpNZXJrIG9wIGRhdCBhbHMgZXIgbmlldHMgZ2VnZXZlbiBpcywgd2UgZXIgbm9ybWFhbCBnZXppZW4gdmFuIHVpdGdhYW4gZGF0IGRlIGdlZ2V2ZW5zIGluIGVsa2UgZ3JvZXAgd2lsbGVrZXVyaWcgdmVyemFtZWxkIHppam4gKGR1cyBvb2sgd2lsbGVrZXVyaWcgb3ZlciBkZSByZWxldmFudGUgZ2V3aWNodGVuIGluIGVsa2UgZ3JvZXApLiBBbHMgZXIgbmlldHMgZ2VnZXZlbiBpcyBkYXQgb3AgaGV0IHRlZ2VuZGVlbCB3aWpzdCwgZ2FhbiB3ZSBlcnZhbiB1aXQgZGF0IGRlIHJhbmRvbWlzYXRpZSBnb2VkIGdlYmV1cmQgaXMgZW4gZGF0IGVyIGFhbiBkZSBvbmFmaGFua2VsaWpraGVpZHNhc3N1bXB0aWUgdm9sZGFhbiBpcy4KCiMjIzEuIEZpdCBlZW4gbGluZWFpciByZWdyZXNzaWVtb2RlbCB2b29yIGRlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIGluIGZ1bmN0aWUgdmFuIGRlIHNvb3J0LgoKYGBge3J9Cm1vZGVsMiA8LSBsbShtaW5zdXJ2IH4gc29vcnQpCnN1bW1hcnkobW9kZWwyKQpgYGAKCioqV2F0IGlzIGhldCBnZW1pZGRlbGRlIHZlcnNjaGlsIGluIG92ZXJsZXZpbmdzdGlqZCB0dXNzZW4gZ291ZHZpc3NlbiBlbiBkb2pvdmlzc2VuPyoqCgpEZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2b29yIGdvdWR2aXNzZW4gbGlndCAwLDA1IG1pbnV0ZW4gbGFnZXIgZGFuIGRlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIHZvb3IgZG9qb3Zpc3Nlbi4gIERlIHAtd2FhcmRlIGJlZHJhYWd0IDAsODkuIEhldCBlZmZlY3QgdmFuIHNvb3J0IG9wIGRlIG92ZXJsZXZpbmdzdGlqZCBpcyBkdXMgbmlldCBzaWduaWZpY2FudCB2ZXJzY2hpbGxlbmQgdmFuIG51bCBvcCBoZXQgNSUtc2lnbmlmaWNhbnRpZW5pdmVhdS4KCioqV2F0IGlzIGhldCBnZW1pZGRlbGRlIHZlcnNjaGlsIGluIG92ZXJsZXZpbmdzdGlqZCB0dXNzZW4gemVicmF2aXNzZW4gZW4gZ291ZHZpc3Nlbj8qKgoKRGUgZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgdm9vciB6ZWJyYXZpc3NlbiBsaWd0IDAsMDUgbWludXRlbiBsYWdlciBkYW4gZGUgZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgdm9vciBnb3Vkdmlzc2VuLiAgRGUgcC13YWFyZGUgYmVkcmFhZ3QgMCw4OS4gSGV0IGVmZmVjdCB2YW4gc29vcnQgb3AgZGUgb3ZlcmxldmluZ3N0aWpkIGlzIGR1cyBuaWV0IHNpZ25pZmljYW50IHZlcnNjaGlsbGVuZCB2YW4gbnVsIG9wIGhldCA1JS1zaWduaWZpY2FudGllbml2ZWF1LgoKKipXYXQgaXMgaGV0IGdlbWlkZGVsZGUgdmVyc2NoaWwgaW4gb3ZlcmxldmluZ3N0aWpkIHR1c3NlbiB6ZWJyYXZpc3NlbiBlbiBkb2pvdmlzc2VuPyoqCgpEZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2b29yIHplYnJhdmlzc2VuIGxpZ3QgMCwwNDY5OCoyID0gMCwwOSBtaW51dGVuIGxhZ2VyIGRhbiBkZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2b29yIGRvam92aXNzZW4uICBEZSBwLXdhYXJkZSBiZWRyYWFndCAwLDg5LiBIZXQgZWZmZWN0IHZhbiBzb29ydCBvcCBkZSBvdmVybGV2aW5nc3RpamQgaXMgZHVzIG5pZXQgc2lnbmlmaWNhbnQgdmVyc2NoaWxsZW5kIHZhbiBudWwgb3AgaGV0IDUlLXNpZ25pZmljYW50aWVuaXZlYXUuCgoqKklzIGRlemUgY29kZXJpbmcgemludm9sPyBXYWFyb20gd2VsL25pZXQ/KioKCkRlemUgY29kZXJpbmcgaXMgd2VpbmlnIHppbnZvbCwgZGl0IG1vZGVsIG9uZGVyc3RlbHQgaW1wbGljaWV0IGRhdCBoZXQgdmVyc2NoaWwgaW4gcmVzcG9uc3ZhcmlhYmVsZSBkb3NpcyAyIGtlZXIgZ3JvdGVyIGlzIHR1c3NlbiB6ZWJyYXZpc3NlbiBlbiBkb2pvdmlzc2VuIGRhbiB0dXNzZW4gZ291ZHZpc3NlbiBlbiBkb2pvdmlzc2VuLCBvbWRhdCBoZXQgZGUgdmFyaWFiZWxlIGBzb29ydGAgYWFuemlldCBhbHMgZWVuIG51bWVyaWVrZSB2YXJpYWJlbGUuCldlIHppZW4gZGl0IGluIGRvb3IgaGV0IG1vZGVsIGdyYWZpc2NoIHZvb3IgdGUgc3RlbGxlbjoKCmBgYHtyfQpwbG90KG1pbnN1cnZ+c29vcnQpCmFibGluZShsbShtaW5zdXJ2fnNvb3J0KSxjb2w9MikKYGBgCgojIyMyLiBNYWFrIG51IGVlcnN0IDIgZHVtbXl2YXJpYWJlbGVuLiBGaXQgZGl0IG1vZGVsIGluIFIgZW4gaW50ZXJwcmV0ZWVyIGRlIGNvZWZmaWNpZW50ZW4uCgpPcGxvc3Npbmc6IGR1bW15LXZhcmlhYmVsZW46CgogLSB2YXJpYWJlbGUgJHNvb3J0Z291ZCQgaXMgMSBhbHMgZGUgb2JzZXJ2YXRpZSBvdmVyZWVua29tdCBtZXQgZWVuIGdvdWR2aXMgZW4gbnVsIGFuZGVycy4KIC0gdmFyaWFiZWxlICRzb29ydHplYnJhJCBpcyAxIGFscyBkZSBvYnNlcnZhdGllIG92ZXJlZW5rb210IG1ldCBlZW4gemVicmF2aXMgZW4gbnVsIGFuZGVycy4KCldlIGt1bm5lbiBudSBhZnN0YXBwZW4gdmFuIGRlIG9uZGVyc3RlbGxpbmcgZGF0IGRlIG92ZXJsZXZpbmdzdGlqZCBsaW5lYWlyIGlzIGluIGhldCBzb29ydCB2aXMgZG9vciBlZW4gbW9kZWwgdGUgZml0dGVuIG1ldCBhbHMgdmVya2xhcmVuZGUgdmFyaWFiZWxlbiBkZXplIHR3ZWUgbmlldXdlIHZhcmlhYmVsZW4uCgpNZXJrIG9wIGRhdCB3ZSBtZXQgdGVsa2VucyB3ZXJrZW4gbWV0ICprKi0xIGR1bW15LXZhcmlhYmVsZW4gd2FhcmJpaiAqayogaGV0IGFhbnRhbCBuaXZlYXVzIGlzIHZhbiBkZSBvb3JzcHJvbmtlbGlqa2UgZmFjdG9yLXZhcmlhYmVsZS4gSGV0IHJlc3RlcmVuZGUgbml2ZWF1IHdvcmR0IGRhbiBnZXJlcHJlc2VudGVlcmQgZG9vciBoZXQgaW50ZXJjZXB0LiBFbGsgbml2ZWF1IHZhbiBkZSBjYXRlZ29yaXNjaGUgdmFyaWFiZWxlIGlzIGVlbmR1aWRpZyBnZWRlZmluaWVlcmQgZG9vciBlZW4gY29tYmluYXRpZSB2YW4gZGUgZHVtbWllczoKCgoqKlRhYmVsIDEuKiogV2FhcmRlbiB2YW4gZGUgZHVtbXl2YXJpYWJlbGVuICJzb29ydGdvdWQiIGVuICJzb29ydHplYnJhIiB2b29yIGVsayBsZXZlbCB2YW4gZGUgZmFjdG9ydmFyaWFiZWxlICJzb29ydCIuCgogU29vcnQgICAgIHNvb3J0Z291ZCBzb29ydHplYnJhCiAtLS0tLS0tLS0gLS0tLS0tLS0tIC0tLS0tLS0tLS0KIGRvam92aXMgICAwICAgICAgICAgMAogZ291ZHZpcyAgIDEgICAgICAgICAwCiB6ZWJyYXZpcyAgMCAgICAgICAgIDEKCmBgYHtyfQpzb29ydGdvdWQgPC0gaWZlbHNlKHNvb3J0PT0xLDEsMCkgIyBzb29ydGdvdWQgaXMgMSBhbHMgc29vcnQ9PTEgZW4gYW5kZXJzIDAKc29vcnR6ZWJyYSA8LSBpZmVsc2Uoc29vcnQ9PTIsMSwwKSAjIHNvb3J0emVicmEgaXMgMSBhbHMgc29vcnQ9PTIgZW4gYW5kZXJzIDAKCm1vZGVsMyA8LSBsbShtaW5zdXJ2IH4gc29vcnRnb3VkICsgc29vcnR6ZWJyYSkKc3VtbWFyeShtb2RlbDMpCmBgYAoKQm92ZW5zdGFhbmRlIGFhbnBhayBrYW4gdnJpaiBpbmVmZmljaetudCB6aWpuIGFscyBqZSB2ZWVsIGxldmVscyBoZWJ0ICh2ZWVsIHZpc3Nvb3J0ZW4gaW4gZGl0IHZvb3JiZWVsZCksIG9tZGF0IGplIHplbGYgdm9vciBpZWRlciBsZXZlbCBlZW4gbmlldXdlIHZhcmlhYmVsZSBtb2V0IGFhbm1ha2VuLiBFZW4gZWZmaWNp6250ZXJlIG1hbmllciBpcyBvbSBzb29ydCBhbHMgZWVuIChkaXNjcmV0ZSEpICoqZmFjdG9ydmFyaWFiZWxlKiogdGUgZGVmaW5p63JlbiBlbiBkaXQgbWVlIHRlIG5lbWVuIGluIGhldCBtb2RlbC4gSmUgdmVydGVsdCBSIG9wIGRlemUgbWFuaWVyIGRhdCBzb29ydCBlZW4gZmFjdG9ydmFyaWFiZWxlIGlzIChlbiBnZWVuIG51bWVyaWVrZSB2YXJpYWJlbGUpLiBXYW5uZWVyIGplIGplIHJlZ3Jlc3NpZW1vZGVsIGZpdCwgemFsIFIgYXV0b21hdGlzY2ggZWVuIGR1bW15Y29kZXJpbmcgZ2VicnVpa2VuIG9tIG9tIGplIG1vZGVsIHRlIGZpdHRlbi4gVmVyZ2VsaWprIGRlIHBhcmFtZXRlcnNjaGF0dGluZ2VuIQoKYGBge3J9CmZTb29ydCA8LSBmYWN0b3Ioc29vcnQpCmZtb2RlbCA8LSBsbShtaW5zdXJ2IH4gZlNvb3J0KQpzdW1tYXJ5KGZtb2RlbCkKYGBgCgpXZSB6aWVuIGRhdCBoZXQgbW9kZWwgbnUgZHJpZSBwYXJhbWV0ZXJzIGhlZWZ0IGdlc2NoYXQ7IHdhYXJpbiBkZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2b29yIGRlIGRyaWUgdmlzc29vcnRlIGluIHZlcnZhdCB6aXR0ZW4uCgpgYGB7cn0KYmV0YT1jb2VmKGZtb2RlbCkgIyBnZXNjaGF0dGUgcmVncmVzc2llY29lZmZpY2llbnRlbgpwbG90KG1pbnN1cnZ+c29vcnQpCnBvaW50cyh4PTAsIHk9YmV0YVsxXSwgcGNoPTE3LCBjZXg9My8yLCBjb2w9InJlZCIpICMgaW50ZXJjZXB0OiBkb2pvdmlzCnBvaW50cyh4PTEsIHk9YmV0YVsxXStiZXRhWzJdLCBwY2g9MTcsIGNleD0zLzIsIGNvbD0icmVkIikgIyBpbnRlcmNlcHQgKyBmc29vcnQxOiBnb3VkdmlzCnBvaW50cyh4PTIsIHk9YmV0YVsxXStiZXRhWzNdLCBwY2g9MTcsIGNleD0zLzIsIGNvbD0icmVkIikgIyBpbnRlcmNlcHQgKyBmc29vcnQyOiB6ZWJyYXZpcwpsZWdlbmQoInRvcHJpZ2h0IixjKCJkYXRhIiwiZ2VzY2hhdHRlIGdlbWlkZGVsZGUiKSxwY2g9YygxLDE3KSwgY29sPTE6MiwgYnR5PSJuIiwgY2V4PTIvMykKYGBgCgoKIyMjIyAxLiBJbnRlcnByZXRhdGllIHZhbiBoZXQgaW50ZXJjZXB0Cgpab2FscyB2b29yaGVlbiBtb2V0IGhldCBpbnRlcmNlcHQgZ2VpbnRlcnByZXRlZXJkIHdvcmRlbiBhbHMgZGUgZ2VtaWRkZWxkZSByZXNwb25zIHdhbm5lZXIgZGUgcHJlZGljdG9yZW4gZ2VsaWprIHppam4gYWFuIG51bC4gVWl0IHRhYmVsIDEgYmxpamt0IGRhdCBkaXQgb3ZlcmVlbmtvbXQgbWV0IGRvam92aXNzZW4uIEhldCBpbnRlcmNlcHQgbW9ldCBkdXMgYWxzIHZvbGd0IGdlaW50ZXJwcmV0ZWVyZCB3b3JkZW46CgoqKkRlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIHZhbiBkb2pvdmlzc2VuIGlzIGdlbGlqayBhYW4gMyw0IG1pbnV0ZW4uIERpdCBlZmZlY3QgaXMgZXh0cmVlbSBzaWduaWZpY2FudCB2ZXJzY2hpbGxlbmQgdmFuIG51bCAocCA8IDJlLTE2KS4qKgoKIyMjIyAyLiBJbnRlcnByZXRhdGllIHZhbiAiZlNvb3J0MSIgKG9mICJzb29ydGdvdWQiKQoKV2Ugd2V0ZW4gZGF0IGRvam92aXNzZW4gdm9vcmdlc3RlbGQgd29yZGVuIGRvb3IgaGV0IGludGVyY2VwdCwgZW4gZGF0IGBzb29ydD09MWAgdm9vciBnb3Vkdmlzc2VuLiBEZSBwYXJhbWV0ZXIgZGllIGBSYCBgZlNvb3J0MWAgbm9lbXQsIHNsYWF0IGR1cyBvcCBkZSBnb3Vkdmlzc2VuLiBgUmAgemFsIGluIGRlIG91dHB1dCB2b29yIGVlbiBmYWN0b3IgdmFyaWFiZWxlIGluIGVlbiBsaW5lYWlyIG1vZGVsIG5hbWVsaWprIHN0ZWVkcyBkZSBuYWFtIHZhbiBkZSB2YXJpYWJlbGUgZ2VicnVpa2VuIGdldm9sZ2QgZG9vciBoZXQgbml2ZWF1IGRhdCBkZSBwYXJhbWV0ZXIgdm9vcnN0ZWx0LiBKZSBrb24gZGl0IG9vayBiZWtpamtlbiB2aWEgZGUgdGFiZWwgaGllcmJvdmVuOiBBbHMgd2UgZG9qb3Zpc3NlbiBtZXQgZ291ZHZpc3NlbiB2ZXJnZWxpamtlbiwgemllbiB3ZSBkYXQgZGUgZW5pZ2UgdmFyaWFiZWxlIGRpZSB2ZXJhbmRlcnQgYHNvb3J0Z291ZGAgaXMuIERlemUgdmFyaWFiZWxlIG1vZXQgZHVzIGFscyB2b2xndCBnZWludGVycHJldGVlcmQgd29yZGVuOgoKKipEZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2b29yIGdvdWR2aXNzZW4gbGlndCAyLDcgbWludXRlbiBob2dlciBkYW4gZGUgZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgdm9vciBkb2pvdmlzc2VuLiBEaXQgZWZmZWN0IGlzIGV4dHJlZW0gc2lnbmlmaWNhbnQgb3AgaGV0IDUlLXNpZ25pZmljYW50aWVuaXZlYXUgKHAgPSA0LDJlLTA4KS4qKgoKTWVyayBvcCBkYXQgd2UgZGV6ZSBwYXJhbWV0ZXIgZW5rZWwga3VubmVuIGludGVycHJldGVyZW4gdGVuIG9wemljaHRlIHZhbiBkZSByZWZlcmVudGlla2xhc3NlLCBuYW1lbGlqayBoZXQgaW50ZXJjZXB0LgoKIyMjIyAzLiBJbnRlcnByZXRhdGllIHZhbiAiZlNvb3J0MiIgKG9mICJzb29ydHplYnJhIikKCkFuYWxvb2cgYWxzIGhpZXJib3ZlbiB3ZXRlbiB3ZSBkYXQgZG9qb3Zpc3NlbiB2b29yZ2VzdGVsZCB3b3JkZW4gZG9vciBoZXQgaW50ZXJjZXB0LCBlbiBkYXQgYHNvb3J0PT0yYCB2b29yIHplYnJhdmlzc2VuLiBEZXplIHZhcmlhYmVsZSBtb2V0IGR1cyBhbHMgdm9sZ3QgZ2XvbnRlcnByZXRlZXJkIHdvcmRlbjoKCioqRGUgZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgdm9vciB6ZWJyYXZpc3NlbiBsaWd0IDEsMCBtaW51dGVuIGxhZ2VyIGRhbiBkZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2b29yIGRvam92aXNzZW4uIERpdCBlZmZlY3QgaXMgbmlldCBzaWduaWZpY2FudCBtYWFyIGVjaHRlciB3ZWwgc3VnZ2VzdGllZiBvcCBoZXQgNSUtc2lnbmlmaWNhbnRpZW5pdmVhdSAocCA9IDAsMDYpLioqCgojIyMjV2F0IGFscyB3ZSBkZSBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2YW4gemVicmF2aXNzZW4gd2lsbGVuIHZlcmdlbGlqa2VuIG1ldCBnb3Vkdmlzc2VuPwoKRXIgaXMgZ2VlbiBwYXJhbWV0ZXIgaW4gaGV0IG1vZGVsIGRpZSBoZXQgdmVyc2NoaWwgaW4gZ2VtaWRkZWxkZSBvdmVybGV2aW5nc3RpamQgdHVzc2VuIHplYnJhdmlzc2VuIGVuIGdvdWR2aXNzZW4gYWFuZ2VlZnQuIFdlIGt1bm5lbiB1aXRlcmFhcmQgd2VsIGRlIGdyb290dGUgdmFuIGRpdCBlZmZlY3QgYmVyZWtlbmVuIHZpYTogLTEsMDQ1MiAtIDIsNzExNyA9IC0zLDguIERlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIHZvb3IgemVicmF2aXNzZW4gbGlndCBkdXMgMyw4IG1pbnV0ZW4gbGFnZXIgZGFuIGRlIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIHZvb3IgZ291ZHZpc3Nlbi4gT20gZWNodGVyIHN0YXRpc3Rpc2NoZSBpbmZlcmVudGllIHRlIGt1bm5lbiBkb2VuIG9wIGRpdCBlZmZlY3QsIG1vZXRlbiB3ZSBlZW4gY29tYmluYXRpZSB2YW4gbW9kZWxwYXJhbWV0ZXJzIHRlc3Rlbiwgd2F0IHZvbGdlbmRlIHdlZWsgYWFuIGJvZCBrb210IGluIGhldCBwcmFjdGljdW0gQU5PVkEuCgpFZW4gYW5kZXJlIG9wbG9zc2luZyBvbSB3ZWwgaW5mZXJlbnRpZSB0ZSBrdW5uZW4gZG9lbiBvcCBkaXQgZWZmZWN0LCBpcyBqZSBkdW1teXZhcmlhYmVsZW4gYW5kZXJzIHRlIGNvZGVyZW4sIHdhYXJiaWogd2UgImdvdWR2aXMiIGFscyByZWZlcmVudGlla2xhc3NlIG5lbWVuLiBEaXQga2FuIGFscyB2b2xndDoKCmBgYHtyfQpmU29vcnRCIDwtIHJlbGV2ZWwoZlNvb3J0LCByZWY9IjEiKSAjIDEgc3RhYXQgdm9vciAiZ291ZHZpcyIsIGRpdCB3b3JkdCBudSBkZSBuaWV1d2UgcmVmZXJlbnRpZWtsYXNzZQpmbW9kZWwyIDwtIGxtKG1pbnN1cnYgfiBmU29vcnRCKQpzdW1tYXJ5KGZtb2RlbDIpCmBgYAoKYGZTb29ydEIwYCBtb2V0IG51IGdlaW50ZXJwcmV0ZWVyZCB3b3JkZW4gYWxzIGhldCB2ZXJzY2hpbCBpbiBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB2YW4gZG9qb3Zpc3NlbiB0Lm8udi4gZ291ZHZpc3Nlbi4gYGZTb29ydEIyYCBpcyBkYW4gaGV0IHZlcnNjaGlsIGluIGdlbWlkZGVsZGUgb3ZlcmxldmluZ3N0aWpkIHZhbiB6ZWJyYXZpc3NlbiB0Lm8udi4gZ291ZHZpc3Nlbi4gRGl0IGxhYXRzdGUgZWZmZWN0IGlzIHVpdGVyYWFyZCBleGFjdCBnZWxpamsgYWFuIGRlIC0zLDggZGllIHdlIG9wIGJhc2lzIHZhbiBgZm1vZGVsYCBiZXJla2VuZGVuLgoKKipNZXJrIG9wOioqIFdlIHdpbGxlbiBoaWVyIGVpZ2VubGlqayBkcmllIG51bGh5cG90aGVzZW4gdGVzdGVuICh2ZXJzY2hpbCBpbiBnZW1pZGRlbGRlIG92ZXJsZXZpbmdzdGlqZCB0dXNzZW4gZ291ZHZpc3NlbiBlbiBkb2pvdmlzc2VuLCB0dXNzZW4gemVicmF2aXNzZW4gZW4gZG9qb3Zpc3NlbiwgZW4gdHVzc2VuIHplYnJhdmlzc2VuIGVuIGdvdWR2aXNzZW4pLiBIb2V3ZWwgZWxrZSB0ZXN0IGhpZXIgYXBhcnQgb3AgaGV0IDVcJS1zaWduaWZpY2FudGllbml2ZWF1IGdlY29udHJvbGVlcmQgaXMsIGlzIGRlIGthbnMgb20gbWluc3RlbnMg6eluIG51bGh5cG90aGVzZSBvbnRlcmVjaHQgdGUgdmVyd2VycGVuLCBnZWdldmVuIGRhdCBlciBnZWVuIHZlcnNjaGlsIGlzIHR1c3NlbiBkZSBkcmllIHZpc3Nvb3J0ZW4sIGdyb3RlciBkYW4gNVwlLiBPbSBoaWVyYWFuIHRlZ2Vtb2V0IHRlIGtvbWVuLCB2ZXJ3aWp6ZW4gd2Ugb3BuaWV1dyBuYWFyIGhldCB2b2xnZW5kZSBwcmFjdGljdW06IEFOT1ZBLgoKCgo=