library(zoo)
library(tseries)
library(lmtest)
library(sandwich)
library(car)
rm(list=ls())

Moja databáza obsahuje záznamy o dopravných nehodách v Barcelone za rok 2017. Ide o kombináciu premenných týkajúcich sa miesta nehody (mestská štvrť, ulica), času (deň v týždni, hodina, časť dňa) a závažnosti nehody (počet zranených, počet obetí, počet zapojených vozidiel). Cieľom analýzy je pomocou viacnásobnej lineárnej regresie preskúmať, do akej miery sú počty obetí dopravných nehôd ovplyvnené vybranými časovými a kontextovými faktormi, konkrétne hodinou nehody (Hour.1), časťou dňa (Part.of.the.day) a počtom zapojených vozidiel (Vehicles.involved). Výsledkom je identifikácia premenných, ktoré štatisticky významne prispievajú k vysvetleniu závažnosti nehôd.

barc_data <- read.csv("barc_data.csv", sep=";", dec=",", header = TRUE)
head(udaje) 
udaje <- udaje[-27,]
udaje <- udaje[-2,]

udaje <- barc_data[, c("Victims", "Hour.1", "Part.of.the.day", "Vehicles.involved")]

udaje$Part.of.the.day <- as.factor(udaje$Part.of.the.day)

# Data imputation
# Compute column medians for numeric variables
column_medians <- sapply(udaje[, c("Victims", "Hour.1", "Vehicles.involved")], median, na.rm = TRUE)

# Impute missing values with column medians
udaje_imputed <- udaje
for (col in names(column_medians)) {
  udaje_imputed[[col]][is.na(udaje_imputed[[col]])] <- column_medians[col]
}

# Replace original data with imputed version
udaje <- udaje_imputed

# ZAKLADNA REGRESIA
attach(udaje)
model <- lm(Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved, data = udaje)
summary(model)

Call:
lm(formula = Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved, 
    data = udaje)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.6389 -0.5528 -0.2234  0.3994  3.9091 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)
(Intercept)             0.56205    0.78521   0.716    0.477
Hour.1                  0.01195    0.03267   0.366    0.716
Part.of.the.dayMorning -0.22459    0.35783  -0.628    0.533
Part.of.the.dayNight    0.66066    0.50874   1.299    0.199
Vehicles.involved       0.40421    0.24294   1.664    0.102

Residual standard error: 0.9391 on 55 degrees of freedom
Multiple R-squared:  0.1156,    Adjusted R-squared:  0.05129 
F-statistic: 1.797 on 4 and 55 DF,  p-value: 0.1425

Testovať, či je model v správnej funkčnej forme (t. j. či je lineárna špecifikácia vhodná, alebo či by ste mali transformovať premenné, napríklad pomocou logaritmov alebo mocninami), možno vykonať viacerými spôsobmi.

1. Test RESET (test chyby špecifikácie Ramseyho regresnej rovnice - Ramsey Reset Test)

Ide o najštandardnejší formálny test nesprávnej špecifikácie funkčnej formy ale dá sa použiť aj pre prípady, ak sme nešpecifikovali všetky vysvetľujúce premenné.

Myšlienka: Nech pôvodný model má tvar \[y_t = \beta_0 + \beta_1 x_{t10} + \dots +\beta_k x_{tk} + u_t\] Ak je váš model správne špecifikovaný, potom pridaním mocnín vyrovnaných hodnôt (napr. \(\hat y_t^2\), \(\hat{y}_t^3\)) by sa pôvodný model nemal podstatne zlepšiť, teda budeme testovať pôvodný model uvedený vyššie a model

\[y_t = \beta_0 + \beta_1 x_{t10} + \dots +\beta_k x_{tk} + \gamma_2\hat y_t^2 + \gamma_3\hat{y}_t^3 + u_t\]

Budeme testovať hypotézu

\(H_0:\) model je správne špecifikovaný (\(\gamma_2 = \gamma_3 = 0\))

oproti

\(H_1:\) model je nesprávne špecifikovaný (\(\gamma_2 \ne 0 \quad \text{alebo} \quad \gamma_3 \ne 0\))

# Suppose your model is:
model <- lm(Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved, data = udaje)

# RESET test from 'lmtest' package:
library(lmtest)
resettest(model)

    RESET test

data:  model
RESET = 0.11629, df1 = 2, df2 = 53, p-value = 0.8904

Na základe výsledkov RESET testu (p-hodnota: 0.8904 > 0.05) nezamietame nulovú hypotézu o správnej špecifikácii modelu. To naznačuje, že model pravdepodobne neobsahuje štrukturálnu chybu a zvolená lineárna forma je vhodná na vysvetlenie počtu obetí dopravných nehôd.

2. Grafická analýza

Graf Residuals vs. Fitted

Grafická analýza vzťahu medzi vyrovnanými hodnotami náhodnej premennej a rezíduami:

plot(model, which = 1)

Graf rezíduí voči vyrovnaným hodnotám naznačuje jemné zakrivenie, čo môže signalizovať, že model nezachytáva všetky vzťahy úplne presne. Mierna odchýlka od náhodnosti rezíduí môže poukazovať na nelineárny efekt alebo na chýbajúcu relevantnú premennú.

Grafy C+R **

Táto analýza nám môže pomôcť pri hľadaní odpovede na otázku, ktorú premennú by sme mali transfomovať pomocou nejakej známej funkcie. Vychádzajme z pôvodnej rovnice

\[y_t = \beta_0 + \beta_1 x_{t1} + \dots +\beta_k x_{tk} + u_t\] Túto rovnicu najprv odhadneme a potom vykresľujeme grafy, kde výraz component+residual (C+R) plot vykresľuje na zvislej osi \(\hat{\beta}_ix_{ti}+e_t\) a na vodorovnej osi vykresľuje hodnoty \(x_{ti}\)

Tieto grafy pomáhajú identifikovať nelineárne vzťahy pre každý regresor:

car::crPlots(model)

Component + Residual grafy ukazujú, že vzťah medzi počtom obetí a niektorými premennými nemusí byť úplne lineárny. Najväčší odklon od priamky vidno pri premenných Hour.1 a Vehicles.involved, čo naznačuje, že by mohlo byť vhodné zvážiť ich kvadratickú alebo inú funkčnú transformáciu.

3. Nelineárna špecifikácia

Častokrát môžeme aj zložitejšie nelineárne vzťahy modelovať s pomocou ich aproximácie s polynómom, teda v prípade kvadratických členov

\[y_t = \beta_0 + \beta_1 x_{t10} + \dots +\beta_k x_{tk} + \dots + \gamma_i\hat x_{ik}^2 + \dots + \gamma_j\hat x_{jk}^2 + \dots + u_t\] Príklad na túto modifikáciu uvidíme nižšie.

3. Porovnanie základného a modifikovaného modelu

Predpokladajme, že pri nelineárnych úpravách pôvodného modelu dopravných nehôd zavedieme kvadratické členy pre premenné Hour.1 a Vehicles.involved. K tomuto kroku nás motivuje Component + Residual graf, kde sa vyrovnaná krivka najviac odchyľuje od priamky práve pri týchto premenných.

Ak má transformovaný model vyšší upravený koefcient determinácie \(R^2_{adj}\) a pri RESET test prijmeme alternatívnu hypotézu, odporúčame si výsledky potvrdiť s pomocou Anova testu oboch modelov a prípadne opakovaného Reset Testu uplatneneného na nelineárne transformovaný model

model <- lm(Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved)
model_kvadr <- lm(Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved + I(Hour.1^2) + I(Vehicles.involved^2), data = udaje)
summary(model_kvadr)

Call:
lm(formula = Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved + 
    I(Hour.1^2) + I(Vehicles.involved^2), data = udaje)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.5810 -0.4786 -0.1790  0.4468  3.1569 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)  
(Intercept)            -1.991820   1.349285  -1.476   0.1458  
Hour.1                  0.316196   0.160864   1.966   0.0546 .
Part.of.the.dayMorning -0.493600   0.365117  -1.352   0.1821  
Part.of.the.dayNight    1.640067   0.726676   2.257   0.0282 *
Vehicles.involved       1.797412   1.098365   1.636   0.1077  
I(Hour.1^2)            -0.012282   0.006349  -1.934   0.0584 .
I(Vehicles.involved^2) -0.418467   0.301140  -1.390   0.1705  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.91 on 53 degrees of freedom
Multiple R-squared:  0.1998,    Adjusted R-squared:  0.1092 
F-statistic: 2.206 on 6 and 53 DF,  p-value: 0.05666
anova(model, model_kvadr)
Analysis of Variance Table

Model 1: Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved
Model 2: Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved + 
    I(Hour.1^2) + I(Vehicles.involved^2)
  Res.Df    RSS Df Sum of Sq      F Pr(>F)  
1     55 48.509                             
2     53 43.889  2    4.6199 2.7894 0.0705 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
library(lmtest)
resettest(model_kvadr)

    RESET test

data:  model_kvadr
RESET = 5.9336, df1 = 2, df2 = 51, p-value = 0.004822

Rozšírený model, ktorý zahŕňa kvadratické členy premenných Hour.1 a Vehicles.involved, nepreukázal výrazné zlepšenie oproti pôvodnému lineárnemu modelu. Hoci niektoré koeficienty sa približujú k hranici štatistickej významnosti, väčšina z nich – vrátane novopridaných kvadratických členov – ostáva nevýznamná. Upravený koeficient determinácie (R²adj) sa síce mierne zvýšil, ale stále zostáva nízky, čo naznačuje, že model len slabo vysvetľuje variabilitu počtu obetí.

Porovnanie modelov pomocou ANOVA testu ukazuje, že rozdiel medzi základným a rozšíreným modelom nie je štatisticky významný (p ≈ 0.0705), teda pridanie kvadratických členov neviedlo k výrazne lepšiemu opisu dát. Naopak, RESET test aplikovaný na rozšírený model ukazuje p-hodnotu ≈ 0.0048, čo naznačuje, že aj tento model môže trpieť špecifikačnou chybou – napriek tomu, že som už zaviedla nelineárne prvky.

V tomto prípade teda kvadratické členy síce mierne upravili model, ale neodstránili podozrenie na nesprávnu špecifikáciu. To naznačuje, že problém nemusí byť len v linearite, ale možno chýba aj ďalšia relevantná premenná. Preto by bolo vhodné zvážiť doplnenie nových vysvetľujúcich premenných alebo iný typ transformácie. Samotné kvadratické rozšírenie však v tomto prípade neprinieslo jednoznačné zlepšenie.

6. Transformácia pomocou dummy premennej a lineárnej lomenej funkcie

Predpokladajme, že máme dummy premennú DUM, ktorá nadobúda hodnotu 0 alebo 1 podľa počtu zapojených vozidiel. Takáto premenná sa dá využiť modelovanie zlomov,, a to napr.

  1. zlom v autonómnom člene \(\beta_0\) a to nasledovnou špecifikáciou \[y_t = \beta_0 + \beta_D D+ \beta_1 x_{t1} + \dots +\beta_k x_{tk} + u_t\] čo interpretujeme ako posun regresnej priamky (regresnej nadroviny) o \(\beta_D\) jednotiek pozdĺž zvislej osi a to len v pozorovaniach, ak je splnená podmienka \(D_t = 1\)
  2. zlom v sklone regresnej priamky (nadroviny) a to len v pozorovaniach, ak je splnená podmienka \(D_t = 1\), čo dosiahneme nasledovnou špecifikáciou \[y_t = \beta_0 + \beta_1 x_{t1} + \dots + \beta_{i}x_{ti} + \beta_{Di}D_tx_{ti}+ \dots + \beta_k x_{tk} + u_t\] kde teda sklon priamky pozdĺž premenne \(x_{ti}\) je \(\beta_i\) ale len v prípade \(D_t=0\), inak je ten sklon rovný \(\beta_i+\beta_{D_i}\).

V našom prípade sa z grafov Component + Residual ukazuje, že vzťah medzi počtom obetí a premennou Vehicles.involved nemusí byť úplne lineárny. Krivka naznačuje zmenu smerovania približne pri hodnote 2 zapojených vozidiel.

Preto zavedieme dummy premennú DUM, ktorá vyjadruje, či sa nehody týkajú dvoch a viacerých vozidiel:

  • ak Vehicles.involved < 2 → DUM = 0

  • ak Vehicles.involved ≥ 2 → DUM = 1

# Vytvorenie dummy premennej: 0 ak počet vozidiel < 2, inak 1
udaje$DUM <- ifelse(udaje$Vehicles.involved < 2, 0, 1)

# Regresný model s dummy premennou
modelD_auto <- lm(Victims ~ +1 + DUM + Hour.1 + Part.of.the.day + Vehicles.involved, data = udaje)
summary(modelD_auto)

Call:
lm(formula = Victims ~ +1 + DUM + Hour.1 + Part.of.the.day + 
    Vehicles.involved, data = udaje)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.4926 -0.6605 -0.2038  0.3398  3.8296 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)
(Intercept)             1.05441    0.86426   1.220    0.228
DUM                     0.81615    0.61728   1.322    0.192
Hour.1                  0.01110    0.03245   0.342    0.734
Part.of.the.dayMorning -0.30113    0.36011  -0.836    0.407
Part.of.the.dayNight    0.60983    0.50678   1.203    0.234
Vehicles.involved      -0.18274    0.50527  -0.362    0.719

Residual standard error: 0.9328 on 54 degrees of freedom
Multiple R-squared:  0.1433,    Adjusted R-squared:  0.06402 
F-statistic: 1.807 on 5 and 54 DF,  p-value: 0.127

Na základe výsledkov regresného modelu, ktorý zahŕňa dummy premennú DUM rozlišujúcu nehody s jedným vozidlom od tých s dvoma a viacerými, sa nepreukázal žiadny štatisticky významný efekt. Koeficient pri DUM je síce kladný (0.81615), no jeho p-hodnota (0.192) je výrazne nad bežnou hladinou významnosti, čo znamená, že rozdiel v autonómnom člene medzi skupinami nie je preukázateľný. Rovnako ani ostatné premenné ako Hour.1, Part.of.the.dayMorning, Part.of.the.dayNight a Vehicles.involved nevykazujú štatistickú významnosť.

Celková vysvetľovacia schopnosť modelu je slabá – R² dosahuje hodnotu 0.1433 a upravené R² len 0.06402. Tieto výsledky naznačujú, že zavedenie dummy premennej nezlepšilo kvalitu modelu a neodhalilo žiadne výrazné rozdiely v počte obetí medzi nehodami s rôznym počtom zapojených vozidiel. Model teda neodporúča rozlišovať tieto skupiny pomocou DUM.


modelD_sklon <- lm(Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved + I(DUM * Vehicles.involved),data=udaje ) 
summary(modelD_sklon)

Call:
lm(formula = Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved + 
    I(DUM * Vehicles.involved), data = udaje)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.4926 -0.6605 -0.2038  0.3398  3.8296 

Coefficients:
                           Estimate Std. Error t value Pr(>|t|)
(Intercept)                 1.87056    1.26005   1.485    0.143
Hour.1                      0.01110    0.03245   0.342    0.734
Part.of.the.dayMorning     -0.30113    0.36011  -0.836    0.407
Part.of.the.dayNight        0.60983    0.50678   1.203    0.234
Vehicles.involved          -0.99889    1.08830  -0.918    0.363
I(DUM * Vehicles.involved)  0.81615    0.61728   1.322    0.192

Residual standard error: 0.9328 on 54 degrees of freedom
Multiple R-squared:  0.1433,    Adjusted R-squared:  0.06402 
F-statistic: 1.807 on 5 and 54 DF,  p-value: 0.127

V tomto modeli som pridala interakčný člen I(DUM * Vehicles.involved), aby som zistila, či sa vplyv počtu vozidiel na počet obetí líši medzi nehodami s jedným vozidlom a tými, kde bolo zapojených viac vozidiel.

Výsledky však ukazujú, že ani samotný počet vozidiel (p = 0.363), ani interakcia s dummy premennou (p = 0.192) nie sú štatisticky významné. To znamená, že sklon regresnej priamky sa medzi týmito skupinami nehôd výrazne nelíši.

Upravené R² má hodnotu len 0.06402, takže model má slabú vysvetľovaciu schopnosť. Intercept je jediný parameter, ktorý sa približuje k významnosti, ale ani ten nie je jednoznačne preukázateľný (p = 0.143). Celkový F-test (p = 0.127) naznačuje, že model ako celok nie je štatisticky významný.

Zavedenie interakčného člena teda neprinieslo zlepšenie a neviedlo k identifikácii rozdielneho vplyvu počtu vozidiel na počet obetí. Model ostáva slabý a interakcia sa neukázala ako užitočná.

Porovnanie pôvodného modelu a modelu s premenlivým sklonom nadroviny vykonáme s pomocou anova testu:

anova(model, modelD_sklon)
Analysis of Variance Table

Model 1: Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved
Model 2: Victims ~ +1 + Hour.1 + Part.of.the.day + Vehicles.involved + 
    I(DUM * Vehicles.involved)
  Res.Df    RSS Df Sum of Sq      F Pr(>F)
1     55 48.509                           
2     54 46.988  1    1.5211 1.7481 0.1917
resettest(modelD_sklon)

    RESET test

data:  modelD_sklon
RESET = 0.21684, df1 = 2, df2 = 52, p-value = 0.8058

Porovnanie modelov pomocou ANOVA testu ukázalo, že pridanie interakčného členu I(DUM * Vehicles.involved) nezlepšilo výkonnosť modelu – p-hodnota 0.1917 naznačuje, že rozdiel medzi pôvodným a rozšíreným modelom nie je štatisticky významný.

RESET test s p-hodnotou 0.8058 takisto neukazuje žiadnu výraznú chybu v špecifikácii modelu. To znamená, že aktuálna forma modelu je z hľadiska funkčnej štruktúry postačujúca.

Celkovo sa interakčný člen neukázal ako prínosný a jeho zahrnutie do modelu nevedie k lepšiemu vysvetleniu počtu obetí. Model sa po tejto úprave nezlepšil.

LS0tCnRpdGxlOiAixaBwZWNpZmlrw6FjaWEgbW9kZWx1IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKYXV0aG9yOiBNb25pa2EgU3rFsWNzb3bDoQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKYGBge3J9CmxpYnJhcnkoem9vKQpsaWJyYXJ5KHRzZXJpZXMpCmxpYnJhcnkobG10ZXN0KQpsaWJyYXJ5KHNhbmR3aWNoKQpsaWJyYXJ5KGNhcikKcm0obGlzdD1scygpKQpgYGAKCk1vamEgZGF0YWLDoXphIG9ic2FodWplIHrDoXpuYW15IG8gZG9wcmF2bsO9Y2ggbmVob2TDoWNoIHYgQmFyY2Vsb25lIHphIHJvayAyMDE3LiBJZGUgbyBrb21iaW7DoWNpdSBwcmVtZW5uw71jaCB0w71rYWrDumNpY2ggc2EgbWllc3RhIG5laG9keSAobWVzdHNrw6EgxaF0dnLFpSwgdWxpY2EpLCDEjWFzdSAoZGXFiCB2IHTDvcW+ZG5pLCBob2RpbmEsIMSNYXPFpSBkxYhhKSBhIHrDoXZhxb5ub3N0aSBuZWhvZHkgKHBvxI1ldCB6cmFuZW7DvWNoLCBwb8SNZXQgb2JldMOtLCBwb8SNZXQgemFwb2plbsO9Y2ggdm96aWRpZWwpLiBDaWXEvm9tIGFuYWzDvXp5IGplIHBvbW9jb3UgdmlhY27DoXNvYm5laiBsaW5lw6FybmVqIHJlZ3Jlc2llIHByZXNrw7ptYcWlLCBkbyBha2VqIG1pZXJ5IHPDuiBwb8SNdHkgb2JldMOtIGRvcHJhdm7DvWNoIG5laMO0ZCBvdnBseXZuZW7DqSB2eWJyYW7DvW1pIMSNYXNvdsO9bWkgYSBrb250ZXh0b3bDvW1pIGZha3Rvcm1pLCBrb25rcsOpdG5lIGhvZGlub3UgbmVob2R5IChIb3VyLjEpLCDEjWFzxaVvdSBkxYhhIChQYXJ0Lm9mLnRoZS5kYXkpIGEgcG/EjXRvbSB6YXBvamVuw71jaCB2b3ppZGllbCAoVmVoaWNsZXMuaW52b2x2ZWQpLiBWw71zbGVka29tIGplIGlkZW50aWZpa8OhY2lhIHByZW1lbm7DvWNoLCBrdG9yw6kgxaF0YXRpc3RpY2t5IHbDvXpuYW1uZSBwcmlzcGlldmFqw7ogayB2eXN2ZXRsZW5pdSB6w6F2YcW+bm9zdGkgbmVow7RkLgoKYGBge3J9CmJhcmNfZGF0YSA8LSByZWFkLmNzdigiYmFyY19kYXRhLmNzdiIsIHNlcD0iOyIsIGRlYz0iLCIsIGhlYWRlciA9IFRSVUUpCmhlYWQodWRhamUpIAp1ZGFqZSA8LSB1ZGFqZVstMjcsXQp1ZGFqZSA8LSB1ZGFqZVstMixdCgp1ZGFqZSA8LSBiYXJjX2RhdGFbLCBjKCJWaWN0aW1zIiwgIkhvdXIuMSIsICJQYXJ0Lm9mLnRoZS5kYXkiLCAiVmVoaWNsZXMuaW52b2x2ZWQiKV0KCnVkYWplJFBhcnQub2YudGhlLmRheSA8LSBhcy5mYWN0b3IodWRhamUkUGFydC5vZi50aGUuZGF5KQoKIyBEYXRhIGltcHV0YXRpb24KIyBDb21wdXRlIGNvbHVtbiBtZWRpYW5zIGZvciBudW1lcmljIHZhcmlhYmxlcwpjb2x1bW5fbWVkaWFucyA8LSBzYXBwbHkodWRhamVbLCBjKCJWaWN0aW1zIiwgIkhvdXIuMSIsICJWZWhpY2xlcy5pbnZvbHZlZCIpXSwgbWVkaWFuLCBuYS5ybSA9IFRSVUUpCgojIEltcHV0ZSBtaXNzaW5nIHZhbHVlcyB3aXRoIGNvbHVtbiBtZWRpYW5zCnVkYWplX2ltcHV0ZWQgPC0gdWRhamUKZm9yIChjb2wgaW4gbmFtZXMoY29sdW1uX21lZGlhbnMpKSB7CiAgdWRhamVfaW1wdXRlZFtbY29sXV1baXMubmEodWRhamVfaW1wdXRlZFtbY29sXV0pXSA8LSBjb2x1bW5fbWVkaWFuc1tjb2xdCn0KCiMgUmVwbGFjZSBvcmlnaW5hbCBkYXRhIHdpdGggaW1wdXRlZCB2ZXJzaW9uCnVkYWplIDwtIHVkYWplX2ltcHV0ZWQKCiMgWkFLTEFETkEgUkVHUkVTSUEKYXR0YWNoKHVkYWplKQptb2RlbCA8LSBsbShWaWN0aW1zIH4gKzEgKyBIb3VyLjEgKyBQYXJ0Lm9mLnRoZS5kYXkgKyBWZWhpY2xlcy5pbnZvbHZlZCwgZGF0YSA9IHVkYWplKQpzdW1tYXJ5KG1vZGVsKQpgYGAKClRlc3RvdmHFpSwgxI1pIGplIG1vZGVsIHYgc3Byw6F2bmVqIGZ1bmvEjW5laiBmb3JtZSAodC4gai4gxI1pIGplIGxpbmXDoXJuYSDFoXBlY2lmaWvDoWNpYSB2aG9kbsOhLCBhbGVibyDEjWkgYnkgc3RlIG1hbGkgdHJhbnNmb3Jtb3ZhxaUgcHJlbWVubsOpLCBuYXByw61rbGFkIHBvbW9jb3UgbG9nYXJpdG1vdiBhbGVibyBtb2NuaW5hbWkpLCBtb8W+bm8gdnlrb25hxaUgdmlhY2Vyw71taSBzcMO0c29ibWkuCgojIyMgMS4gVGVzdCBSRVNFVCAodGVzdCBjaHlieSDFoXBlY2lmaWvDoWNpZSBSYW1zZXlobyByZWdyZXNuZWogcm92bmljZSAtIFJhbXNleSBSZXNldCBUZXN0KQoKSWRlIG8gbmFqxaF0YW5kYXJkbmVqxaHDrSBmb3Jtw6FsbnkgdGVzdCBuZXNwcsOhdm5laiDFoXBlY2lmaWvDoWNpZSBmdW5rxI1uZWogZm9ybXkgYWxlIGTDoSBzYSBwb3XFvmnFpSBhaiBwcmUgcHLDrXBhZHksIGFrIHNtZSBuZcWhcGVjaWZpa292YWxpIHbFoWV0a3kgdnlzdmV0xL51asO6Y2UgcHJlbWVubsOpLgoKTXnFoWxpZW5rYTogTmVjaCBww7R2b2Ruw70gbW9kZWwgbcOhIHR2YXIKJCR5X3QgPSBcYmV0YV8wICsgXGJldGFfMSB4X3t0MTB9ICsgXGRvdHMgK1xiZXRhX2sgeF97dGt9ICsgdV90JCQKQWsgamUgdsOhxaEgbW9kZWwgc3Byw6F2bmUgxaFwZWNpZmlrb3ZhbsO9LCBwb3RvbSBwcmlkYW7DrW0gbW9jbsOtbiB2eXJvdm5hbsO9Y2ggaG9kbsO0dCAobmFwci4gJFxoYXQgeV90XjIkLCAkXGhhdHt5fV90XjMkKSBieSBzYSBww7R2b2Ruw70gbW9kZWwgbmVtYWwgcG9kc3RhdG5lIHpsZXDFoWnFpSwgdGVkYSBidWRlbWUgdGVzdG92YcWlIHDDtHZvZG7DvSBtb2RlbCB1dmVkZW7DvSB2ecWhxaFpZSBhIG1vZGVsCgokJHlfdCA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfe3QxMH0gKyBcZG90cyArXGJldGFfayB4X3t0a30gKyBcZ2FtbWFfMlxoYXQgeV90XjIgKyBcZ2FtbWFfM1xoYXR7eX1fdF4zICsgdV90JCQKCkJ1ZGVtZSB0ZXN0b3ZhxaUgaHlwb3TDqXp1IAoKJEhfMDokIG1vZGVsIGplIHNwcsOhdm5lIMWhcGVjaWZpa292YW7DvSAoJFxnYW1tYV8yID0gXGdhbW1hXzMgPSAwJCkKCm9wcm90aQoKJEhfMTokIG1vZGVsIGplIG5lc3Byw6F2bmUgxaFwZWNpZmlrb3ZhbsO9ICgkXGdhbW1hXzIgXG5lIDAgIFxxdWFkIFx0ZXh0e2FsZWJvfSAgXHF1YWQgXGdhbW1hXzMgXG5lIDAkKQoKYGBge3J9CiMgU3VwcG9zZSB5b3VyIG1vZGVsIGlzOgptb2RlbCA8LSBsbShWaWN0aW1zIH4gKzEgKyBIb3VyLjEgKyBQYXJ0Lm9mLnRoZS5kYXkgKyBWZWhpY2xlcy5pbnZvbHZlZCwgZGF0YSA9IHVkYWplKQoKIyBSRVNFVCB0ZXN0IGZyb20gJ2xtdGVzdCcgcGFja2FnZToKbGlicmFyeShsbXRlc3QpCnJlc2V0dGVzdChtb2RlbCkKCmBgYAoKTmEgesOha2xhZGUgdsO9c2xlZGtvdiBSRVNFVCB0ZXN0dSAocC1ob2Rub3RhOiAwLjg5MDQgPiAwLjA1KSBuZXphbWlldGFtZSBudWxvdsO6IGh5cG90w6l6dSBvIHNwcsOhdm5laiDFoXBlY2lmaWvDoWNpaSBtb2RlbHUuIFRvIG5hem5hxI11amUsIMW+ZSBtb2RlbCBwcmF2ZGVwb2RvYm5lIG5lb2JzYWh1amUgxaF0cnVrdHVyw6FsbnUgY2h5YnUgYSB6dm9sZW7DoSBsaW5lw6FybmEgZm9ybWEgamUgdmhvZG7DoSBuYSB2eXN2ZXRsZW5pZSBwb8SNdHUgb2JldMOtIGRvcHJhdm7DvWNoIG5laMO0ZC4KCiMjIyAyLiBHcmFmaWNrw6EgYW5hbMO9emEKCiMjIyMgR3JhZiAqUmVzaWR1YWxzIHZzLiBGaXR0ZWQqCgpHcmFmaWNrw6EgYW5hbMO9emEgdnrFpWFodSBtZWR6aSB2eXJvdm5hbsO9bWkgaG9kbm90YW1pIG7DoWhvZG5laiBwcmVtZW5uZWogYSByZXrDrWR1YW1pOgoKYGBge3J9CnBsb3QobW9kZWwsIHdoaWNoID0gMSkKYGBgCgpHcmFmIHJlesOtZHXDrSB2b8SNaSB2eXJvdm5hbsO9bSBob2Rub3TDoW0gbmF6bmHEjXVqZSBqZW1uw6kgemFrcml2ZW5pZSwgxI1vIG3DtMW+ZSBzaWduYWxpem92YcWlLCDFvmUgbW9kZWwgbmV6YWNoeXTDoXZhIHbFoWV0a3kgdnrFpWFoeSDDunBsbmUgcHJlc25lLiBNaWVybmEgb2RjaMO9bGthIG9kIG7DoWhvZG5vc3RpIHJlesOtZHXDrSBtw7TFvmUgcG91a2F6b3ZhxaUgbmEgbmVsaW5lw6FybnkgZWZla3QgYWxlYm8gbmEgY2jDvWJhasO6Y3UgcmVsZXZhbnRuw7ogcHJlbWVubsO6LgoKIyMjIyBHcmFmeSBDK1IgKioKClTDoXRvIGFuYWzDvXphIG7DoW0gbcO0xb5lIHBvbcO0Y8WlIHByaSBoxL5hZGFuw60gb2Rwb3ZlZGUgbmEgb3TDoXprdSwga3RvcsO6IHByZW1lbm7DuiBieSBzbWUgbWFsaSB0cmFuc2ZvbW92YcWlIHBvbW9jb3UgbmVqYWtlaiB6bsOhbWVqIGZ1bmtjaWUuIFZ5Y2jDoWR6YWptZSB6IHDDtHZvZG5laiByb3ZuaWNlCgokJHlfdCA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfe3QxfSArIFxkb3RzICtcYmV0YV9rIHhfe3RrfSArIHVfdCQkClTDunRvIHJvdm5pY3UgbmFqcHJ2IG9kaGFkbmVtZSBhIHBvdG9tIHZ5a3Jlc8S+dWplbWUgZ3JhZnksIGtkZSB2w71yYXogY29tcG9uZW50K3Jlc2lkdWFsIChDK1IpIHBsb3QgdnlrcmVzxL51amUgbmEgenZpc2xlaiBvc2kgJFxoYXR7XGJldGF9X2l4X3t0aX0rZV90JCBhIG5hIHZvZG9yb3ZuZWogb3NpIHZ5a3Jlc8S+dWplIGhvZG5vdHkgJHhfe3RpfSQKClRpZXRvIGdyYWZ5IHBvbcOhaGFqw7ogaWRlbnRpZmlrb3ZhxaUgbmVsaW5lw6FybmUgdnrFpWFoeSBwcmUga2HFvmTDvSByZWdyZXNvcjoKCmBgYHtyfQpjYXI6OmNyUGxvdHMobW9kZWwpCgpgYGAKQ29tcG9uZW50ICsgUmVzaWR1YWwgZ3JhZnkgdWthenVqw7osIMW+ZSB2esWlYWggbWVkemkgcG/EjXRvbSBvYmV0w60gYSBuaWVrdG9yw71taSBwcmVtZW5uw71taSBuZW11c8OtIGJ5xaUgw7pwbG5lIGxpbmXDoXJueS4gTmFqdsOkxI3FocOtIG9ka2xvbiBvZCBwcmlhbWt5IHZpZG5vIHByaSBwcmVtZW5uw71jaCBIb3VyLjEgYSBWZWhpY2xlcy5pbnZvbHZlZCwgxI1vIG5hem5hxI11amUsIMW+ZSBieSBtb2hsbyBiecWlIHZob2Ruw6kgenbDocW+acWlIGljaCBrdmFkcmF0aWNrw7ogYWxlYm8gaW7DuiBmdW5rxI1uw7ogdHJhbnNmb3Jtw6FjaXUuCgojIyAzLiBOZWxpbmXDoXJuYSDFoXBlY2lmaWvDoWNpYQoKxIxhc3Rva3LDoXQgbcO0xb5lbWUgYWogemxvxb5pdGVqxaFpZSBuZWxpbmXDoXJuZSB2esWlYWh5IG1vZGVsb3ZhxaUgcyBwb21vY291IGljaCBhcHJveGltw6FjaWUgcyBwb2x5bsOzbW9tLCB0ZWRhIHYgcHLDrXBhZGUga3ZhZHJhdGlja8O9Y2ggxI1sZW5vdgoKJCR5X3QgPSBcYmV0YV8wICsgXGJldGFfMSB4X3t0MTB9ICsgXGRvdHMgK1xiZXRhX2sgeF97dGt9ICsgXGRvdHMgKyBcZ2FtbWFfaVxoYXQgeF97aWt9XjIgKyBcZG90cyArIFxnYW1tYV9qXGhhdCB4X3tqa31eMiArIFxkb3RzICsgdV90JCQKUHLDrWtsYWQgbmEgdMO6dG8gbW9kaWZpa8OhY2l1IHV2aWTDrW1lIG5pxb7FoWllLgoKIyMgMy4gUG9yb3ZuYW5pZSB6w6FrbGFkbsOpaG8gYSBtb2RpZmlrb3ZhbsOpaG8gbW9kZWx1CgpQcmVkcG9rbGFkYWptZSwgxb5lIHByaSBuZWxpbmXDoXJueWNoIMO6cHJhdsOhY2ggcMO0dm9kbsOpaG8gbW9kZWx1IGRvcHJhdm7DvWNoIG5laMO0ZCB6YXZlZGllbWUga3ZhZHJhdGlja8OpIMSNbGVueSBwcmUgcHJlbWVubsOpIEhvdXIuMSBhIFZlaGljbGVzLmludm9sdmVkLiBLIHRvbXV0byBrcm9rdSBuw6FzIG1vdGl2dWplIENvbXBvbmVudCArIFJlc2lkdWFsIGdyYWYsIGtkZSBzYSB2eXJvdm5hbsOhIGtyaXZrYSBuYWp2aWFjIG9kY2h5xL51amUgb2QgcHJpYW1reSBwcsOhdmUgcHJpIHTDvWNodG8gcHJlbWVubsO9Y2guCgpBayBtw6EgdHJhbnNmb3Jtb3ZhbsO9IG1vZGVsIHZ5xaHFocOtIHVwcmF2ZW7DvSBrb2VmY2llbnQgZGV0ZXJtaW7DoWNpZSAkUl4yX3thZGp9JCBhIHByaSBSRVNFVCB0ZXN0IHByaWptZW1lIGFsdGVybmF0w612bnUgaHlwb3TDqXp1LCBvZHBvcsO6xI1hbWUgc2kgdsO9c2xlZGt5IHBvdHZyZGnFpSBzIHBvbW9jb3UgQW5vdmEgdGVzdHUgb2JvY2ggbW9kZWxvdiBhIHByw61wYWRuZSBvcGFrb3ZhbsOpaG8gUmVzZXQgVGVzdHUgdXBsYXRuZW5lbsOpaG8gbmEgbmVsaW5lw6FybmUgdHJhbnNmb3Jtb3ZhbsO9IG1vZGVsCgoKYGBge3J9Cm1vZGVsIDwtIGxtKFZpY3RpbXMgfiArMSArIEhvdXIuMSArIFBhcnQub2YudGhlLmRheSArIFZlaGljbGVzLmludm9sdmVkKQptb2RlbF9rdmFkciA8LSBsbShWaWN0aW1zIH4gKzEgKyBIb3VyLjEgKyBQYXJ0Lm9mLnRoZS5kYXkgKyBWZWhpY2xlcy5pbnZvbHZlZCArIEkoSG91ci4xXjIpICsgSShWZWhpY2xlcy5pbnZvbHZlZF4yKSwgZGF0YSA9IHVkYWplKQpzdW1tYXJ5KG1vZGVsX2t2YWRyKQphbm92YShtb2RlbCwgbW9kZWxfa3ZhZHIpCmxpYnJhcnkobG10ZXN0KQpyZXNldHRlc3QobW9kZWxfa3ZhZHIpCmBgYAoKUm96xaHDrXJlbsO9IG1vZGVsLCBrdG9yw70gemFoxZXFiGEga3ZhZHJhdGlja8OpIMSNbGVueSBwcmVtZW5uw71jaCBIb3VyLjEgYSBWZWhpY2xlcy5pbnZvbHZlZCwgbmVwcmV1a8OhemFsIHbDvXJhem7DqSB6bGVwxaFlbmllIG9wcm90aSBww7R2b2Ruw6ltdSBsaW5lw6FybmVtdSBtb2RlbHUuIEhvY2kgbmlla3RvcsOpIGtvZWZpY2llbnR5IHNhIHByaWJsacW+dWrDuiBrIGhyYW5pY2kgxaF0YXRpc3RpY2tlaiB2w716bmFtbm9zdGksIHbDpMSNxaFpbmEgeiBuaWNoIOKAkyB2csOhdGFuZSBub3ZvcHJpZGFuw71jaCBrdmFkcmF0aWNrw71jaCDEjWxlbm92IOKAkyBvc3TDoXZhIG5ldsO9em5hbW7DoS4gVXByYXZlbsO9IGtvZWZpY2llbnQgZGV0ZXJtaW7DoWNpZSAoUsKyYWRqKSBzYSBzw61jZSBtaWVybmUgenbDvcWhaWwsIGFsZSBzdMOhbGUgem9zdMOhdmEgbsOtemt5LCDEjW8gbmF6bmHEjXVqZSwgxb5lIG1vZGVsIGxlbiBzbGFibyB2eXN2ZXTEvnVqZSB2YXJpYWJpbGl0dSBwb8SNdHUgb2JldMOtLgoKUG9yb3ZuYW5pZSBtb2RlbG92IHBvbW9jb3UgQU5PVkEgdGVzdHUgdWthenVqZSwgxb5lIHJvemRpZWwgbWVkemkgesOha2xhZG7DvW0gYSByb3rFocOtcmVuw71tIG1vZGVsb20gbmllIGplIMWhdGF0aXN0aWNreSB2w716bmFtbsO9IChwIOKJiCAwLjA3MDUpLCB0ZWRhIHByaWRhbmllIGt2YWRyYXRpY2vDvWNoIMSNbGVub3YgbmV2aWVkbG8gayB2w71yYXpuZSBsZXDFoWllbXUgb3Bpc3UgZMOhdC4gTmFvcGFrLCBSRVNFVCB0ZXN0IGFwbGlrb3ZhbsO9IG5hIHJvesWhw61yZW7DvSBtb2RlbCB1a2F6dWplIHAtaG9kbm90dSDiiYggMC4wMDQ4LCDEjW8gbmF6bmHEjXVqZSwgxb5lIGFqIHRlbnRvIG1vZGVsIG3DtMW+ZSB0cnBpZcWlIMWhcGVjaWZpa2HEjW5vdSBjaHlib3Ug4oCTIG5hcHJpZWsgdG9tdSwgxb5lIHNvbSB1xb4gemF2aWVkbGEgbmVsaW5lw6FybmUgcHJ2a3kuCgpWIHRvbXRvIHByw61wYWRlIHRlZGEga3ZhZHJhdGlja8OpIMSNbGVueSBzw61jZSBtaWVybmUgdXByYXZpbGkgbW9kZWwsIGFsZSBuZW9kc3Ryw6FuaWxpIHBvZG96cmVuaWUgbmEgbmVzcHLDoXZudSDFoXBlY2lmaWvDoWNpdS4gVG8gbmF6bmHEjXVqZSwgxb5lIHByb2Jsw6ltIG5lbXVzw60gYnnFpSBsZW4gdiBsaW5lYXJpdGUsIGFsZSBtb8W+bm8gY2jDvWJhIGFqIMSPYWzFoWlhIHJlbGV2YW50bsOhIHByZW1lbm7DoS4gUHJldG8gYnkgYm9sbyB2aG9kbsOpIHp2w6HFvmnFpSBkb3BsbmVuaWUgbm92w71jaCB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoIGFsZWJvIGluw70gdHlwIHRyYW5zZm9ybcOhY2llLiBTYW1vdG7DqSBrdmFkcmF0aWNrw6kgcm96xaHDrXJlbmllIHbFoWFrIHYgdG9tdG8gcHLDrXBhZGUgbmVwcmluaWVzbG8gamVkbm96bmHEjW7DqSB6bGVwxaFlbmllLgoKIyMjIDYuIFRyYW5zZm9ybcOhY2lhIHBvbW9jb3UgZHVtbXkgcHJlbWVubmVqIGEgbGluZcOhcm5laiBsb21lbmVqIGZ1bmtjaWUKClByZWRwb2tsYWRham1lLCDFvmUgbcOhbWUgZHVtbXkgcHJlbWVubsO6IERVTSwga3RvcsOhIG5hZG9iw7pkYSBob2Rub3R1IDAgYWxlYm8gMSBwb2TEvmEgcG/EjXR1IHphcG9qZW7DvWNoIHZvemlkaWVsLiBUYWvDoXRvIHByZW1lbm7DoSBzYSBkw6Egdnl1xb5pxaUgbW9kZWxvdmFuaWUgemxvbW92LCwgYSB0byBuYXByLgoKMS4gemxvbSB2IGF1dG9uw7Ntbm9tIMSNbGVuZSAkXGJldGFfMCQgYSB0byBuYXNsZWRvdm5vdSDFoXBlY2lmaWvDoWNpb3UKJCR5X3QgPSBcYmV0YV8wICsgXGJldGFfRCBEKyBcYmV0YV8xIHhfe3QxfSArIFxkb3RzICtcYmV0YV9rIHhfe3RrfSArIHVfdCQkCsSNbyBpbnRlcnByZXR1amVtZSBha28gcG9zdW4gcmVncmVzbmVqIHByaWFta3kgKHJlZ3Jlc25laiBuYWRyb3ZpbnkpIG8gJFxiZXRhX0QkIGplZG5vdGllayBwb3pkxLrFviB6dmlzbGVqIG9zaSBhIHRvIGxlbiB2IHBvem9yb3ZhbmlhY2gsIGFrIGplIHNwbG5lbsOhIHBvZG1pZW5rYSAkRF90ID0gMSQKMi4gemxvbSB2IHNrbG9uZSByZWdyZXNuZWogcHJpYW1reSAobmFkcm92aW55KSBhIHRvIGxlbiB2IHBvem9yb3ZhbmlhY2gsIGFrIGplIHNwbG5lbsOhIHBvZG1pZW5rYSAkRF90ID0gMSQsIMSNbyBkb3NpYWhuZW1lIG5hc2xlZG92bm91IMWhcGVjaWZpa8OhY2lvdQokJHlfdCA9IFxiZXRhXzAgKyAgXGJldGFfMSB4X3t0MX0gKyBcZG90cyArIFxiZXRhX3tpfXhfe3RpfSArIFxiZXRhX3tEaX1EX3R4X3t0aX0rIFxkb3RzICsgXGJldGFfayB4X3t0a30gKyB1X3QkJAprZGUgdGVkYSBza2xvbiBwcmlhbWt5IHBvemTEusW+IHByZW1lbm5lICR4X3t0aX0kIGplICRcYmV0YV9pJCBhbGUgbGVuIHYgcHLDrXBhZGUgJERfdD0wJCwgaW5hayBqZSB0ZW4gc2tsb24gcm92bsO9ICRcYmV0YV9pK1xiZXRhX3tEX2l9JC4KClYgbmHFoW9tIHByw61wYWRlIHNhIHogZ3JhZm92IENvbXBvbmVudCArIFJlc2lkdWFsIHVrYXp1amUsIMW+ZSB2esWlYWggbWVkemkgcG/EjXRvbSBvYmV0w60gYSBwcmVtZW5ub3UgVmVoaWNsZXMuaW52b2x2ZWQgbmVtdXPDrSBiecWlIMO6cGxuZSBsaW5lw6FybnkuIEtyaXZrYSBuYXpuYcSNdWplIHptZW51IHNtZXJvdmFuaWEgcHJpYmxpxb5uZSBwcmkgaG9kbm90ZSAyIHphcG9qZW7DvWNoIHZvemlkaWVsLgoKUHJldG8gemF2ZWRpZW1lIGR1bW15IHByZW1lbm7DuiBEVU0sIGt0b3LDoSB2eWphZHJ1amUsIMSNaSBzYSBuZWhvZHkgdMO9a2Fqw7ogZHZvY2ggYSB2aWFjZXLDvWNoIHZvemlkaWVsOgoKLSBhayBWZWhpY2xlcy5pbnZvbHZlZCA8IDIg4oaSIERVTSA9IDAKCi0gYWsgVmVoaWNsZXMuaW52b2x2ZWQg4omlIDIg4oaSIERVTSA9IDEKCgpgYGB7cn0KIyBWeXR2b3JlbmllIGR1bW15IHByZW1lbm5lajogMCBhayBwb8SNZXQgdm96aWRpZWwgPCAyLCBpbmFrIDEKdWRhamUkRFVNIDwtIGlmZWxzZSh1ZGFqZSRWZWhpY2xlcy5pbnZvbHZlZCA8IDIsIDAsIDEpCgojIFJlZ3Jlc27DvSBtb2RlbCBzIGR1bW15IHByZW1lbm5vdQptb2RlbERfYXV0byA8LSBsbShWaWN0aW1zIH4gKzEgKyBEVU0gKyBIb3VyLjEgKyBQYXJ0Lm9mLnRoZS5kYXkgKyBWZWhpY2xlcy5pbnZvbHZlZCwgZGF0YSA9IHVkYWplKQpzdW1tYXJ5KG1vZGVsRF9hdXRvKQpgYGAKCk5hIHrDoWtsYWRlIHbDvXNsZWRrb3YgcmVncmVzbsOpaG8gbW9kZWx1LCBrdG9yw70gemFoxZXFiGEgZHVtbXkgcHJlbWVubsO6IERVTSByb3psacWhdWrDumN1IG5laG9keSBzIGplZG7DvW0gdm96aWRsb20gb2QgdMO9Y2ggcyBkdm9tYSBhIHZpYWNlcsO9bWksIHNhIG5lcHJldWvDoXphbCDFvmlhZG55IMWhdGF0aXN0aWNreSB2w716bmFtbsO9IGVmZWt0LiBLb2VmaWNpZW50IHByaSBEVU0gamUgc8OtY2Uga2xhZG7DvSAoMC44MTYxNSksIG5vIGplaG8gcC1ob2Rub3RhICgwLjE5MikgamUgdsO9cmF6bmUgbmFkIGJlxb5ub3UgaGxhZGlub3UgdsO9em5hbW5vc3RpLCDEjW8gem5hbWVuw6EsIMW+ZSByb3pkaWVsIHYgYXV0b27Ds21ub20gxI1sZW5lIG1lZHppIHNrdXBpbmFtaSBuaWUgamUgcHJldWvDoXphdGXEvm7DvS4gUm92bmFrbyBhbmkgb3N0YXRuw6kgcHJlbWVubsOpIGFrbyBIb3VyLjEsIFBhcnQub2YudGhlLmRheU1vcm5pbmcsIFBhcnQub2YudGhlLmRheU5pZ2h0IGEgVmVoaWNsZXMuaW52b2x2ZWQgbmV2eWthenVqw7ogxaF0YXRpc3RpY2vDuiB2w716bmFtbm9zxaUuIAoKQ2Vsa292w6EgdnlzdmV0xL5vdmFjaWEgc2Nob3Bub3PFpSBtb2RlbHUgamUgc2xhYsOhIOKAkyBSwrIgZG9zYWh1amUgaG9kbm90dSAwLjE0MzMgYSB1cHJhdmVuw6kgUsKyIGxlbiAwLjA2NDAyLiBUaWV0byB2w71zbGVka3kgbmF6bmHEjXVqw7osIMW+ZSB6YXZlZGVuaWUgZHVtbXkgcHJlbWVubmVqIG5lemxlcMWhaWxvIGt2YWxpdHUgbW9kZWx1IGEgbmVvZGhhbGlsbyDFvmlhZG5lIHbDvXJhem7DqSByb3pkaWVseSB2IHBvxI10ZSBvYmV0w60gbWVkemkgbmVob2RhbWkgcyByw7R6bnltIHBvxI10b20gemFwb2plbsO9Y2ggdm96aWRpZWwuIE1vZGVsIHRlZGEgbmVvZHBvcsO6xI1hIHJvemxpxaFvdmHFpSB0aWV0byBza3VwaW55IHBvbW9jb3UgRFVNLgoKCmBgYHtyfQoKbW9kZWxEX3NrbG9uIDwtIGxtKFZpY3RpbXMgfiArMSArIEhvdXIuMSArIFBhcnQub2YudGhlLmRheSArIFZlaGljbGVzLmludm9sdmVkICsgSShEVU0gKiBWZWhpY2xlcy5pbnZvbHZlZCksZGF0YT11ZGFqZSApIApzdW1tYXJ5KG1vZGVsRF9za2xvbikKYGBgCgpWIHRvbXRvIG1vZGVsaSBzb20gcHJpZGFsYSBpbnRlcmFrxI1uw70gxI1sZW4gSShEVU0gKiBWZWhpY2xlcy5pbnZvbHZlZCksIGFieSBzb20gemlzdGlsYSwgxI1pIHNhIHZwbHl2IHBvxI10dSB2b3ppZGllbCBuYSBwb8SNZXQgb2JldMOtIGzDrcWhaSBtZWR6aSBuZWhvZGFtaSBzIGplZG7DvW0gdm96aWRsb20gYSB0w71taSwga2RlIGJvbG8gemFwb2plbsO9Y2ggdmlhYyB2b3ppZGllbC4KClbDvXNsZWRreSB2xaFhayB1a2F6dWrDuiwgxb5lIGFuaSBzYW1vdG7DvSBwb8SNZXQgdm96aWRpZWwgKHAgPSAwLjM2MyksIGFuaSBpbnRlcmFrY2lhIHMgZHVtbXkgcHJlbWVubm91IChwID0gMC4xOTIpIG5pZSBzw7ogxaF0YXRpc3RpY2t5IHbDvXpuYW1uw6kuIFRvIHpuYW1lbsOhLCDFvmUgc2tsb24gcmVncmVzbmVqIHByaWFta3kgc2EgbWVkemkgdMO9bWl0byBza3VwaW5hbWkgbmVow7RkIHbDvXJhem5lIG5lbMOtxaFpLgoKVXByYXZlbsOpIFLCsiBtw6EgaG9kbm90dSBsZW4gMC4wNjQwMiwgdGFrxb5lIG1vZGVsIG3DoSBzbGFiw7ogdnlzdmV0xL5vdmFjaXUgc2Nob3Bub3PFpS4gSW50ZXJjZXB0IGplIGplZGluw70gcGFyYW1ldGVyLCBrdG9yw70gc2EgcHJpYmxpxb51amUgayB2w716bmFtbm9zdGksIGFsZSBhbmkgdGVuIG5pZSBqZSBqZWRub3puYcSNbmUgcHJldWvDoXphdGXEvm7DvSAocCA9IDAuMTQzKS4gQ2Vsa292w70gRi10ZXN0IChwID0gMC4xMjcpIG5hem5hxI11amUsIMW+ZSBtb2RlbCBha28gY2Vsb2sgbmllIGplIMWhdGF0aXN0aWNreSB2w716bmFtbsO9LgoKWmF2ZWRlbmllIGludGVyYWvEjW7DqWhvIMSNbGVuYSB0ZWRhIG5lcHJpbmllc2xvIHpsZXDFoWVuaWUgYSBuZXZpZWRsbyBrIGlkZW50aWZpa8OhY2lpIHJvemRpZWxuZWhvIHZwbHl2dSBwb8SNdHUgdm96aWRpZWwgbmEgcG/EjWV0IG9iZXTDrS4gTW9kZWwgb3N0w6F2YSBzbGFiw70gYSBpbnRlcmFrY2lhIHNhIG5ldWvDoXphbGEgYWtvIHXFvml0b8SNbsOhLgoKClBvcm92bmFuaWUgcMO0dm9kbsOpaG8gbW9kZWx1IGEgbW9kZWx1IHMgcHJlbWVubGl2w71tIHNrbG9ub20gbmFkcm92aW55IHZ5a29uw6FtZSBzIHBvbW9jb3UgYW5vdmEgdGVzdHU6CgpgYGB7cn0KYW5vdmEobW9kZWwsIG1vZGVsRF9za2xvbikKcmVzZXR0ZXN0KG1vZGVsRF9za2xvbikKYGBgClBvcm92bmFuaWUgbW9kZWxvdiBwb21vY291IEFOT1ZBIHRlc3R1IHVrw6F6YWxvLCDFvmUgcHJpZGFuaWUgaW50ZXJha8SNbsOpaG8gxI1sZW51IEkoRFVNICogVmVoaWNsZXMuaW52b2x2ZWQpIG5lemxlcMWhaWxvIHbDvWtvbm5vc8WlIG1vZGVsdSDigJMgcC1ob2Rub3RhIDAuMTkxNyBuYXpuYcSNdWplLCDFvmUgcm96ZGllbCBtZWR6aSBww7R2b2Ruw71tIGEgcm96xaHDrXJlbsO9bSBtb2RlbG9tIG5pZSBqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvS4KClJFU0VUIHRlc3QgcyBwLWhvZG5vdG91IDAuODA1OCB0YWtpc3RvIG5ldWthenVqZSDFvmlhZG51IHbDvXJhem7DuiBjaHlidSB2IMWhcGVjaWZpa8OhY2lpIG1vZGVsdS4gVG8gem5hbWVuw6EsIMW+ZSBha3R1w6FsbmEgZm9ybWEgbW9kZWx1IGplIHogaMS+YWRpc2thIGZ1bmvEjW5laiDFoXRydWt0w7pyeSBwb3N0YcSNdWrDumNhLgoKQ2Vsa292byBzYSBpbnRlcmFrxI1uw70gxI1sZW4gbmV1a8OhemFsIGFrbyBwcsOtbm9zbsO9IGEgamVobyB6YWhybnV0aWUgZG8gbW9kZWx1IG5ldmVkaWUgayBsZXDFoWllbXUgdnlzdmV0bGVuaXUgcG/EjXR1IG9iZXTDrS4gTW9kZWwgc2EgcG8gdGVqdG8gw7pwcmF2ZSBuZXpsZXDFoWlsLgoK