S využitím databázy dopravných nehôd budem analyzovať faktory, ktoré súvisia s počtom zranených pri nehode.

Pri ďalšej práci budeme používať knižnice

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

V hlavnom menu som Session nastavila na Source File Location. Môžem to urobiť aj interaktívnym spôsobom - napísať dole do Console (alebo to zahrnúť priamo do skriptu) ako

setwd(“…”)

Organizácia priečinkov a podpriečinkov sa však môže líšiť v závislosti od projektu, preto cestu nezaraďujem do Chunk-u.

Údaje o dopravných nehodách sú usporiadané v súbore csv, stĺpce sú oddelené znakom “,” a používajú desatinnú bodku. V pracovnom priečinku mám uložený súbor s názvom premavka.csv.csv.

Nie všetky údaje budú použité, preto som vybrala len niektoré stĺpce pre neskoršie použitie.

Úvod do problému, stanovenie hypotéz

Rozhodla som sa modelovať počet zranených pri nehode injuries_total v závislosti od vysvetľujúcich premenných:

Naša pracovná hypotéza hovorí o štatisticky významnom vplyve vysvetľujúcich premenných na počet zranených, pričom očakávam, že:

Príprava databázy, čistenie a úprava údajov

Keďže niektoré údaje chýbajú, doplnila som ich mediánovými hodnotami premennej, ktorú zvažujem.


# Načítanie údajov o dopravných nehodách
udaje <- read.csv("premavka.csv.csv", dec=".", sep=",", header = TRUE)

# Vyberiem len premenné, ktoré budem používať v analýze
udaje.sub <- udaje[, c("injuries_total",
                       "num_units",
                       "crash_hour",
                       "crash_day_of_week",
                       "crash_month")]

# Doplnenie chýbajúcich hodnôt mediánom (imputácia)
column_medians <- sapply(udaje.sub, median, na.rm = TRUE)

udaje_imputed <- udaje.sub
for (col in names(udaje.sub)) {
  udaje_imputed[[col]][is.na(udaje_imputed[[col]])] <- column_medians[col]
}

udaje.sub <- udaje_imputed

Teraz chcem vizuálne preskúmať tvar jednotlivých premenných a overiť, či sa v údajoch nenachádzajú nezrovnalosti, napríklad extrémne alebo nulové hodnoty. Na tento účel využívam boxploty, ktoré umožňujú rýchlu identifikáciu odľahlých pozorovaní a základných charakteristík rozdelenia dát.


# Predpokladáme, že udaje.sub je dátový rámec s vybranými premennými

# Počet premenných
num_plots <- length(names(udaje.sub))

# Nastavenie rozloženia grafov: 2 x 2
par(mfrow = c(2, 2))
par(mar = c(4, 4, 2, 1))  # úprava okrajov

# Vykreslenie boxplotov pre každú premennú
for (col in names(udaje.sub)) {
  boxplot(udaje.sub[[col]],
          main = col,
          xlab = "Hodnota",
          col = "lightblue")
}


# Spoločný nadpis
mtext("Boxploty jednotlivých premenných", outer = TRUE, cex = 1.4, font = 2)

NA
NA

Lineárna regresia

Model odhadujem príkazom lm(). Vysvetľovanou premennou je počet zranených pri dopravnej nehode (injuries_total). Ako vysvetľujúce premenné som zvolila počet zapojených vozidiel (num_units) a časové charakteristiky nehody, konkrétne hodinu nehody (crash_hour), deň v týždni (crash_day_of_week) a mesiac nehody (crash_month).

model <- lm(
  injuries_total ~ +1 + num_units + crash_hour + crash_day_of_week + crash_month,
  data = udaje.sub
)
summary(model)

Call:
lm(formula = injuries_total ~ +1 + num_units + crash_hour + crash_day_of_week + 
    crash_month, data = udaje.sub)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.9330 -0.3719 -0.3518  0.3171 20.9325 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -0.2478411  0.0110628 -22.403  < 2e-16 ***
num_units          0.3233581  0.0043563  74.227  < 2e-16 ***
crash_hour        -0.0024418  0.0003085  -7.916 2.46e-15 ***
crash_day_of_week -0.0059035  0.0008787  -6.718 1.84e-11 ***
crash_month        0.0030261  0.0005033   6.013 1.82e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.7892 on 209301 degrees of freedom
Multiple R-squared:  0.02626,   Adjusted R-squared:  0.02624 
F-statistic:  1411 on 4 and 209301 DF,  p-value: < 2.2e-16

Objekt triedy lm() mi po odhadnutí modelu poskytuje viacero užitočných výstupov, ktoré môžem využiť pri interpretácii a diagnostike regresie:

  1. Vektor odhadnutých koeficientov model$coefficients – ukazuje odhadovaný vplyv premenných (num_units, crash_hour, crash_day_of_week, crash_month) na vysvetľovanú premennú injuries_total.
  2. Vektor rezíduí model$residuals – rozdiely medzi skutočnými hodnotami injuries_total a hodnotami predikovanými modelom.
  3. Vektor vyrovnaných hodnôt vysvetľovanej premennej model$fitted.values – modelom vypočítané (predikované) hodnoty počtu zranených pri nehode.
  4. Matica vysvetľujúcich premenných X model.matrix(model) – numerická matica premenných zahrnutých v modeli, ktorú regresia používa pri výpočtoch.

Prehľad základných výsledkov a štatistickej významnosti získam pomocou príkazu summary(model).

Keďže všetky potrebné informácie viem získať priamo z objektu model, môžem si ich v prípade potreby vypísať aj jednotlivo. Pre prehľadnosť však budem ďalej pracovať najmä so súhrnom modelu pomocou príkazu summary(model), ktorý obsahuje koeficienty, ich štatistickú významnosť, informácie o rezíduách aj celkové vlastnosti modelu.

#print("Odhadnuté regresné koeficienty sú: ")
#print(model$coefficients)

#print("Odhadnuté rezíduá sú: ")
#print(model$residuals)

#print("Vyrovnané (predikované) hodnoty vysvetľovanej premennej sú: ")
#print(model$fitted.values)

#print("Matica vysvetľujúcich premenných X (model.matrix) je: ")
#print(model.matrix(model))

# (voliteľné) diagnostika vplyvu pozorovaní – diagonála hat-matrix:
#X <- model.matrix(model)
#diag(X %*% solve(t(X) %*% X) %*% t(X))

summary(model)

Call:
lm(formula = injuries_total ~ +1 + num_units + crash_hour + crash_day_of_week + 
    crash_month, data = udaje.sub)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.9330 -0.3719 -0.3518  0.3171 20.9325 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -0.2478411  0.0110628 -22.403  < 2e-16 ***
num_units          0.3233581  0.0043563  74.227  < 2e-16 ***
crash_hour        -0.0024418  0.0003085  -7.916 2.46e-15 ***
crash_day_of_week -0.0059035  0.0008787  -6.718 1.84e-11 ***
crash_month        0.0030261  0.0005033   6.013 1.82e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.7892 on 209301 degrees of freedom
Multiple R-squared:  0.02626,   Adjusted R-squared:  0.02624 
F-statistic:  1411 on 4 and 209301 DF,  p-value: < 2.2e-16

Súhrn odhadovaného regresného modelu poskytuje súbor odhadnutých regresných koeficientov, ktorých znamienka a štatistická významnosť budú podrobnejšie interpretované v ďalšej časti analýzy. Ak sa však zameriame na vlastnosti modelu ako celku, je potrebné najskôr overiť, či sú splnené základné predpoklady lineárnej regresie.

Na tento účel využívam diagnostické grafy regresného modelu. Prostredníctvom Q–Q grafu posudzujem predpoklad normality rezíduí, zatiaľ čo ostatné diagnostické grafy mi umožňujú identifikovať prípadné problémy s heteroskedasticitou, nelinearitou alebo prítomnosťou vplyvných pozorovaní. Na základe týchto grafov si viem vytvoriť prvotný dojem o vhodnosti zvoleného modelu a o tom, či je možné jeho výsledky považovať za spoľahlivé.

par(mfrow = c(2, 2))
par(mar = c(4, 4, 2, 1))


# Vykresliť všetky 4 diagnostické grafy modelu
plot(model)

# Resetovať layout
par(mfrow = c(1, 1))

Residuals vs. Fitted

Interpretácia konkrétneho grafu

Centrovanie okolo nuly
Rezíduá kolíšu približne okolo hodnoty 0, čo je žiaduci stav. Naznačuje to, že model nemá systematickú tendenciu nadhodnocovať alebo podhodnocovať počet zranených pri dopravných nehodách.

Tvar vzťahu
Červená vyhladzovacia čiara (LOESS) vykazuje mierne zakrivenie, čo môže naznačovať slabú nelinearitu medzi vysvetľujúcimi premennými (najmä časovými charakteristikami nehody) a počtom zranených. Tento efekt však nie je výrazný a nepredstavuje zásadný problém pre interpretáciu modelu.

Rozptyl rezíduí
Vertikálny rozptyl rezíduí sa javí ako približne konštantný v celom rozsahu vyrovnaných hodnôt, čo naznačuje splnenie predpokladu homoskedasticity.

Odľahlé pozorovania
Niekoľko bodov sa nachádza ďalej od ostatných, čo môže predstavovať nehody s mimoriadne vysokým alebo nízkym počtom zranených. Tieto pozorovania je možné ďalej preskúmať pomocou testu outlierTest(model) z balíka car.

Q–Q Plot

Čo graf znázorňuje

  • Os X predstavuje teoretické kvantily normálneho rozdelenia.
  • Os Y zobrazuje štandardizované rezíduá modelu.
  • Prerušovaná diagonála predstavuje ideálny prípad, v ktorom by rezíduá mali normálne rozdelenie.

Interpretácia konkrétneho grafu

Celkový tvar rozdelenia
Väčšina bodov sa nachádza blízko referenčnej priamky, čo naznačuje, že rezíduá sú približne normálne rozložené.

Krajné hodnoty
Na oboch koncoch grafu dochádza k miernym odchýlkam od priamky, čo môže signalizovať prítomnosť extrémnych hodnôt – napríklad nehôd s neštandardným počtom zranených.

Stredná časť rozdelenia
V centrálnej oblasti grafu (okolo mediánu) rezíduá veľmi dobre kopírujú teoretickú priamku, čo znamená, že väčšina pozorovaní spĺňa predpoklad normality.

Na základe Q–Q grafu možno konštatovať, že predpoklad normality rezíduí je v prijateľnej miere splnený, aj keď s miernymi odchýlkami v extrémoch.

Scale–Location Plot

Čo graf znázorňuje

  • Os X predstavuje vyrovnané hodnoty závislej premennej (predikovaný počet zranených).
  • Os Y zobrazuje druhú odmocninu absolútnych štandardizovaných rezíduí.
  • Červená čiara predstavuje vyhladený trend (LOESS).

Interpretácia konkrétneho grafu

Homoskedasticita
Body sú rovnomerne rozptýlené pozdĺž osi X a nevytvárajú lievikovitý tvar. To naznačuje, že variancia rezíduí je približne konštantná.

Trend vyhladzovacej krivky
Červená LOESS krivka je takmer horizontálna, čo podporuje predpoklad, že rozptyl rezíduí sa nemení s rastúcimi vyrovnanými hodnotami.

Odľahlé hodnoty
Niekoľko bodov sa nachádza mierne vyššie, avšak nejde o extrémne pozorovania, ktoré by výrazne narušovali stabilitu modelu.

Residuals vs. Leverage

Čo graf znázorňuje

  • Os X predstavuje pákový efekt pozorovaní, ktorý vyjadruje, ako veľmi sa dané pozorovanie líši od ostatných z hľadiska vysvetľujúcich premenných.
  • Os Y zobrazuje štandardizované rezíduá.
  • Bodkované krivky znázorňujú kontúry Cookovej vzdialenosti, ktoré identifikujú potenciálne vplyvné pozorovania.

Interpretácia konkrétneho grafu

Rozloženie vplyvu
Väčšina pozorovaní má nízky pákový efekt, čo je typické pre dobre štruktúrované dáta o dopravných nehodách.

Veľkosť rezíduí
Štandardizované rezíduá sa prevažne pohybujú v intervale ⟨−2, 2⟩, čo naznačuje absenciu extrémnych chýb modelu.

Vplyvné pozorovania
Niektoré pozorovania sa nachádzajú bližšie ku kontúram Cookovej vzdialenosti, avšak žiadne z nich neprekračuje kritické hranice. Z toho vyplýva, že žiadna nehoda neovplyvňuje regresné koeficienty neprimerane.


# Test normality rezíduí
residuals <- residuals(model)
jb_test <- jarque.bera.test(residuals)
jb_test

    Jarque Bera Test

data:  residuals
X-squared = 4841155, df = 2, p-value < 2.2e-16
# Test odľahlých pozorovaní (Bonferroni)
outlier_test <- outlierTest(model)
outlier_test
NA

Na overenie predpokladu normality rezíduí som použila Jarque–Bera test. Nulová hypotéza testu predpokladá, že rezíduá majú normálne rozdelenie. Výsledky testu naznačujú, že rezíduá sa môžu odchyľovať od normálneho rozdelenia, čo je pri dátach o dopravných nehodách pomerne časté, keďže počet zranených môže nadobúdať extrémne hodnoty pri závažných nehodách.

Zároveň som pomocou funkcie outlierTest() identifikovala potenciálne odľahlé a vplyvné pozorovania. Výsledky testu poukazujú na existenciu niekoľkých pozorovaní, ktoré môžu mať neprimerane veľký vplyv na odhad regresných koeficientov. Ide najmä o nehody s mimoriadne vysokým počtom zranených, ktoré môžu narúšať splnenie predpokladov lineárnej regresie.

Na základe výsledkov týchto testov sa rozhodnem upraviť pôvodný model transformáciou vysvetľovanej premennej injuries_total, aby som znížila vplyv extrémnych hodnôt a zlepšila vlastnosti modelu.


udaje.sub$log_injuries <- log(udaje.sub$injuries_total + 1)
model2 <- lm(
  log_injuries ~ num_units + crash_hour + crash_day_of_week + crash_month,
  data = udaje.sub
)
summary(model2)

Call:
lm(formula = log_injuries ~ num_units + crash_hour + crash_day_of_week + 
    crash_month, data = udaje.sub)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.3932 -0.2191 -0.2080  0.3322  3.0102 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -0.0647948  0.0055820 -11.608  < 2e-16 ***
num_units          0.1484818  0.0021981  67.551  < 2e-16 ***
crash_hour        -0.0012759  0.0001556  -8.198 2.46e-16 ***
crash_day_of_week -0.0032113  0.0004434  -7.243 4.41e-13 ***
crash_month        0.0017661  0.0002539   6.955 3.53e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3982 on 209301 degrees of freedom
Multiple R-squared:  0.02207,   Adjusted R-squared:  0.02205 
F-statistic:  1181 on 4 and 209301 DF,  p-value: < 2.2e-16
# Nastaviť rozloženie 2 x 2
par(mfrow = c(2, 2))
par(mar = c(4, 4, 2, 1))  # ZMENŠÍ OKRAJE

# Vykresliť všetky 4 diagnostické grafy modelu
plot(model2)

# (Voliteľné) pridať spoločný nadpis
#mtext("Diagnostické grafy regresného modelu", outer = TRUE, cex = 1.2, font = 2)

# Resetovať layout
par(mfrow = c(1, 1))

# Test normality rezíduí (model2)
residuals <- residuals(model2)
jb_test <- jarque.bera.test(residuals)
jb_test

    Jarque Bera Test

data:  residuals
X-squared = 115371, df = 2, p-value < 2.2e-16
# Test odľahlých pozorovaní (Bonferroni korekcia)
outlier_test <- outlierTest(model2)
outlier_test

Záver o analýze odľahlých hodnôt

Na základe vykonanej analýzy môžem konštatovať, že vybrané vysvetľujúce premenné majú štatisticky významný vplyv na vysvetľovanú premennú súvisiacu s dopravnými nehodami. Niektoré premenné sa v pôvodnom modeli ukázali ako menej vhodné alebo ťažko interpretovateľné, a preto bol model v ďalšom kroku upravený.

Testy normality a diagnostické grafy naznačili prítomnosť odľahlých pozorovaní, ktoré sú typické pre dáta z oblasti dopravy, kde sa vyskytujú extrémne situácie (napr. nehody s vysokým počtom zranených). Z tohto dôvodu bola použitá logaritmická transformácia vysvetľovanej premenne,ktorá prispela k zmierneniu vplyvu extrémnych hodnôt.

V upravenom modeli sa nepreukázali výrazné vplyvné pozorovania ani závažné nelinearity. Na základe toho možno výsledky regresnej analýzy považovať za primerané a model za vhodný na ďalšiu interpretáciu.

Heteroskedasticita

Prítomnosť heteroskedasticity (nekonštantného rozptylu náhodnej zložky) môže viesť k nesprávnemu vyhodnocovaniu t-testov významnosti jednotlivých regresných koeficientov. Z tohto dôvodu je nevyhnutné heteroskedasticitu
- detekovať (vizuálne aj pomocou štatistických testov),
- a v prípade jej prítomnosti ju vhodným spôsobom eliminovať.

V prípade databázy dopravných nehôd je možné heteroskedasticitu očakávať, keďže počet nehôd a ich následky sa môžu výrazne líšiť v závislosti od času, dňa alebo iných charakteristík premávky. Aj preto som sa zamerala na jej posúdenie prostredníctvom diagnostických grafov.

Na tento účel budem porovnávať dva regresné modely – pôvodný model označený ako model a upravený model model2, v ktorom bola použitá logaritmická transformácia vysvetľovanej premennej. Cieľom tejto úpravy bolo zníženie vplyvu extrémnych hodnôt a stabilizácia rozptylu rezíduí.

library(ggplot2)
library(patchwork)

df_res <- model.frame(model2)
df_res$res2 <- resid(model2)^2

set.seed(123)
df_plot <- df_res[sample(nrow(df_res), min(3000, nrow(df_res))), ]

p1 <- ggplot(df_plot, aes(x = num_units, y = res2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE) +
  labs(
    x = "Počet zúčastnených vozidiel",
    y = "Štvorce rezíduí",
    title = "Štvorce rezíduí vs. počet vozidiel"
  ) +
  theme_minimal()

p2 <- ggplot(df_plot, aes(x = crash_hour, y = res2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE) +
  labs(
    x = "Hodina nehody",
    y = "Štvorce rezíduí",
    title = "Štvorce rezíduí vs. hodina nehody"
  ) +
  theme_minimal()

print(p1 + p2)

NA
NA

a teraz model so zlogaritmizovanou premennou num_units.

library(ggplot2)
library(patchwork)

df_res <- model.frame(model2)
df_res$res2 <- resid(model2)^2

df_res <- df_res[
  is.finite(df_res$res2) &
    !is.na(df_res$num_units) &
    !is.na(df_res$crash_hour),
]

set.seed(123)
df_plot <- df_res[sample(nrow(df_res), min(3000, nrow(df_res))), ]

p1 <- ggplot(df_plot, aes(x = log(num_units + 1), y = res2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE) +
  labs(x = "log(num_units + 1)",
       y = "Squared Residuals",
       title = "Residuals vs log(num_units + 1)") +
  theme_minimal()

p2 <- ggplot(df_plot, aes(x = crash_hour, y = res2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE) +
  labs(x = "crash_hour",
       y = "Squared Residuals",
       title = "Residuals vs crash_hour") +
  theme_minimal()

p1 + p2

NA
NA

Na tomto obrázku podľa vyhladených hodnôt štvorcov rezíduí (vyhladená krivka v grafe) môžem konštatovať, že nevidím výrazný rast ani pokles rozptylu rezíduí v závislosti od vysvetľujúcich premenných.

V grafe Residuals vs log(num_units + 1) je väčšina bodov sústredená pri nižších hodnotách počtu zúčastnených vozidiel a vyhladená krivka nevykazuje jasný trend, ktorý by naznačoval systematické zvyšovanie variability.

V grafe Residuals vs crash_hour sa takisto neukazuje jednoznačný vývoj rozptylu rezíduí v priebehu dňa – vyhladená krivka je len mierne rastúca, čo môže naznačovať slabý efekt, ale nie výraznú heteroskedasticitu.

Preto na základe vizuálneho posúdenia nevidím silný dôkaz heteroskedasticity. Tento záver však následne overím formálnym testom (napr. Breusch–Pagan testom).

Testovanie prítomnosti heteroskedasticity

# Install (if not yet installed)
# install.packages("lmtest")

# Load the package
library(lmtest)

# Run the Breusch–Pagan test
bptest(model)

    studentized Breusch-Pagan test

data:  model
BP = 1823, df = 4, p-value < 2.2e-16
# Install (if not yet installed)
# install.packages("lmtest")

# Load the package
library(lmtest)

# Run the Breusch–Pagan test
bptest(model2)

    studentized Breusch-Pagan test

data:  model2
BP = 2957.9, df = 4, p-value < 2.2e-16

Na základe Breusch–Paganovho testu môžeme konštatovať, že heteroskedasticita rezíduí je prítomná v pôvodnom modeli (model) aj v upravenom modeli (model2), keďže v oboch prípadoch bola nulová hypotéza o konštantnom rozptyle zamietnutá (p-hodnota < 0,05).

Logaritmická transformácia vysvetľovanej premennej síce zlepšila tvar rezíduí a ich vizuálne správanie, avšak heteroskedasticitu sa tým nepodarilo úplne odstrániť. V ďalšej analýze je preto vhodné pracovať s robustnými (heteroskedasticity-consistent) odhadmi rozptylov regresných koeficientov, aby boli výsledky testov štatistickej významnosti spoľahlivé.

#install.packages("sandwich")
#install.packages("lmtest")
library(sandwich)
library(lmtest)
coeftest(model, vcov = vcovHC(model))

t test of coefficients:

                     Estimate  Std. Error  t value  Pr(>|t|)    
(Intercept)       -0.24784106  0.01823464 -13.5918 < 2.2e-16 ***
num_units          0.32335812  0.00826524  39.1226 < 2.2e-16 ***
crash_hour        -0.00244183  0.00034277  -7.1238 1.053e-12 ***
crash_day_of_week -0.00590350  0.00091434  -6.4565 1.074e-10 ***
crash_month        0.00302614  0.00048532   6.2353 4.517e-10 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Všimnime si, že po použití heteroskedasticity-robustných (White) odhadov rozptylov zostávajú všetky vysvetľujúce premenné štatisticky významné. To znamená, že aj po korekcii na heteroskedasticitu sú vzťahy zachytené modelom stabilné a výsledky testov štatistickej významnosti možno považovať za spoľahlivé.

Použitie tejto metódy je vhodné najmä pri väčšom počte pozorovaní, čo je v prípade databázy dopravných nehôd splnené. Alternatívnym riešením heteroskedasticity by bola transformácia alebo škálovanie niektorých premenných (napr. prepočet na mieru na jednotku času alebo vozidlo), avšak takéto úpravy by mohli znížiť interpretačnú prehľadnosť modelu. Z tohto dôvodu považujem použitie robustných odhadov za primerané riešenie v rámci tejto analýzy.

LS0tCnRpdGxlOiAiRWNvbm9tZXRyaWNzIGluIFIgLSBjdmnEjWVuaWUgNiIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogQmFyYm9yYSBLb3ByZG92YQotLS0KClMgdnl1xb5pdMOtbSBkYXRhYsOhenkgZG9wcmF2bsO9Y2ggbmVow7RkIGJ1ZGVtIGFuYWx5em92YcWlIGZha3RvcnksIGt0b3LDqSBzw7p2aXNpYSBzIHBvxI10b20genJhbmVuw71jaCBwcmkgbmVob2RlLgoKUHJpIMSPYWzFoWVqIHByw6FjaSBidWRlbWUgcG91xb7DrXZhxaUga25pxb5uaWNlCgpgYGB7cn0KbGlicmFyeSh6b28pCmxpYnJhcnkodHNlcmllcykKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkoc2FuZHdpY2gpCmxpYnJhcnkoY2FyKQpybShsaXN0PWxzKCkpCmBgYAoKCgpWICpobGF2bm9tIG1lbnUqIHNvbSAqU2Vzc2lvbiogbmFzdGF2aWxhIG5hICpTb3VyY2UgRmlsZSBMb2NhdGlvbiouIE3DtMW+ZW0gdG8gdXJvYmnFpSBhaiBpbnRlcmFrdMOtdm55bSBzcMO0c29ib20gLSBuYXDDrXNhxaUgZG9sZSBkbyBDb25zb2xlIChhbGVibyB0byB6YWhybsO6xaUgcHJpYW1vIGRvIHNrcmlwdHUpIGFrbyAKCiAqKnNldHdkKCIuLi4iKSoqCgpPcmdhbml6w6FjaWEgcHJpZcSNaW5rb3YgYSBwb2RwcmllxI1pbmtvdiBzYSB2xaFhayBtw7TFvmUgbMOtxaFpxaUgdiB6w6F2aXNsb3N0aSBvZCBwcm9qZWt0dSwgcHJldG8gY2VzdHUgbmV6YXJhxI91amVtIGRvIENodW5rLXUuCgrDmmRhamUgbyBkb3ByYXZuw71jaCBuZWhvZMOhY2ggc8O6IHVzcG9yaWFkYW7DqSB2IHPDumJvcmUgKmNzdiosIHN0xLpwY2Ugc8O6IG9kZGVsZW7DqSB6bmFrb20gIiwiIGEgcG91xb7DrXZhasO6IGRlc2F0aW5uw7ogYm9ka3UuIFYgcHJhY292bm9tIHByaWXEjWlua3UgbcOhbSB1bG/FvmVuw70gc8O6Ym9yIHMgbsOhenZvbSAqcHJlbWF2a2EuY3N2LmNzdiouCgpOaWUgdsWhZXRreSDDumRhamUgYnVkw7ogcG91xb5pdMOpLCBwcmV0byBzb20gdnlicmFsYSBsZW4gbmlla3RvcsOpIHN0xLpwY2UgcHJlIG5lc2tvcsWhaWUgcG91xb5pdGllLgoKIyDDmnZvZCBkbyBwcm9ibMOpbXUsIHN0YW5vdmVuaWUgaHlwb3TDqXogCgpSb3pob2RsYSBzb20gc2EgbW9kZWxvdmHFpSBwb8SNZXQgenJhbmVuw71jaCBwcmkgbmVob2RlICppbmp1cmllc190b3RhbCogdiB6w6F2aXNsb3N0aSBvZCB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoOgoKLSBwb8SNZXQgdm96aWRpZWwgemFwb2plbsO9Y2ggZG8gbmVob2R5ICpudW1fdW5pdHMqLAotIGhvZGluYSBuZWhvZHkgKmNyYXNoX2hvdXIqLAotIGRlxYggdiB0w73FvmRuaSAqY3Jhc2hfZGF5X29mX3dlZWsqLAotIG1lc2lhYyBuZWhvZHkgKmNyYXNoX21vbnRoKi4KCk5hxaFhIHByYWNvdm7DoSBoeXBvdMOpemEgaG92b3LDrSBvIMWhdGF0aXN0aWNreSB2w716bmFtbm9tIHZwbHl2ZSB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoIG5hIHBvxI1ldCB6cmFuZW7DvWNoLCBwcmnEjW9tIG/EjWFrw6F2YW0sIMW+ZToKCi0gdnnFocWhw60gcG/EjWV0IHZvemlkaWVsICgqbnVtX3VuaXRzKikgYnVkZSBzw7p2aXNpZcWlIHMgdnnFocWhw61tIHBvxI10b20genJhbmVuw71jaCAoKmluanVyaWVzX3RvdGFsKiksCi0gxI1hc292w6kgcHJlbWVubsOpICgqY3Jhc2hfaG91ciosICpjcmFzaF9kYXlfb2Zfd2VlayosICpjcmFzaF9tb250aCopIG3DtMW+dSB6YWNoeXTDoXZhxaUgcm96ZGllbHkgdiB6w6F2YcW+bm9zdGkgbmVow7RkIHBvxI1hcyBkxYhhLCB0w73FvmTFiGEgYSByb2thLgoKIyBQcsOtcHJhdmEgZGF0YWLDoXp5LCDEjWlzdGVuaWUgYSDDunByYXZhIMO6ZGFqb3YKCktlxI/FvmUgbmlla3RvcsOpIMO6ZGFqZSBjaMO9YmFqw7osIGRvcGxuaWxhIHNvbSBpY2ggbWVkacOhbm92w71taSBob2Rub3RhbWkgcHJlbWVubmVqLCBrdG9yw7ogenZhxb51amVtLgoKCgoKYGBge3J9CgojIE5hxI3DrXRhbmllIMO6ZGFqb3YgbyBkb3ByYXZuw71jaCBuZWhvZMOhY2gKdWRhamUgPC0gcmVhZC5jc3YoInByZW1hdmthLmNzdi5jc3YiLCBkZWM9Ii4iLCBzZXA9IiwiLCBoZWFkZXIgPSBUUlVFKQoKIyBWeWJlcmllbSBsZW4gcHJlbWVubsOpLCBrdG9yw6kgYnVkZW0gcG91xb7DrXZhxaUgdiBhbmFsw716ZQp1ZGFqZS5zdWIgPC0gdWRhamVbLCBjKCJpbmp1cmllc190b3RhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgIm51bV91bml0cyIsCiAgICAgICAgICAgICAgICAgICAgICAgImNyYXNoX2hvdXIiLAogICAgICAgICAgICAgICAgICAgICAgICJjcmFzaF9kYXlfb2Zfd2VlayIsCiAgICAgICAgICAgICAgICAgICAgICAgImNyYXNoX21vbnRoIildCgojIERvcGxuZW5pZSBjaMO9YmFqw7pjaWNoIGhvZG7DtHQgbWVkacOhbm9tIChpbXB1dMOhY2lhKQpjb2x1bW5fbWVkaWFucyA8LSBzYXBwbHkodWRhamUuc3ViLCBtZWRpYW4sIG5hLnJtID0gVFJVRSkKCnVkYWplX2ltcHV0ZWQgPC0gdWRhamUuc3ViCmZvciAoY29sIGluIG5hbWVzKHVkYWplLnN1YikpIHsKICB1ZGFqZV9pbXB1dGVkW1tjb2xdXVtpcy5uYSh1ZGFqZV9pbXB1dGVkW1tjb2xdXSldIDwtIGNvbHVtbl9tZWRpYW5zW2NvbF0KfQoKdWRhamUuc3ViIDwtIHVkYWplX2ltcHV0ZWQKCgpgYGAKCgpUZXJheiBjaGNlbSB2aXp1w6FsbmUgcHJlc2vDum1hxaUgdHZhciBqZWRub3RsaXbDvWNoIHByZW1lbm7DvWNoIGEgb3ZlcmnFpSwgxI1pIHNhIHYgw7pkYWpvY2ggbmVuYWNow6FkemFqw7ogbmV6cm92bmFsb3N0aSwgbmFwcsOta2xhZCBleHRyw6ltbmUgYWxlYm8gbnVsb3bDqSBob2Rub3R5LgpOYSB0ZW50byDDusSNZWwgdnl1xb7DrXZhbSBib3hwbG90eSwga3RvcsOpIHVtb8W+xYh1asO6IHLDvWNobHUgaWRlbnRpZmlrw6FjaXUgb2TEvmFobMO9Y2ggcG96b3JvdmFuw60gYSB6w6FrbGFkbsO9Y2ggY2hhcmFrdGVyaXN0w61rIHJvemRlbGVuaWEgZMOhdC4KCmBgYHtyfQoKIyBQcmVkcG9rbGFkw6FtZSwgxb5lIHVkYWplLnN1YiBqZSBkw6F0b3bDvSByw6FtZWMgcyB2eWJyYW7DvW1pIHByZW1lbm7DvW1pCgojIFBvxI1ldCBwcmVtZW5uw71jaApudW1fcGxvdHMgPC0gbGVuZ3RoKG5hbWVzKHVkYWplLnN1YikpCgojIE5hc3RhdmVuaWUgcm96bG/FvmVuaWEgZ3JhZm92OiAyIHggMgpwYXIobWZyb3cgPSBjKDIsIDIpKQpwYXIobWFyID0gYyg0LCA0LCAyLCAxKSkgICMgw7pwcmF2YSBva3Jham92CgojIFZ5a3Jlc2xlbmllIGJveHBsb3RvdiBwcmUga2HFvmTDuiBwcmVtZW5uw7oKZm9yIChjb2wgaW4gbmFtZXModWRhamUuc3ViKSkgewogIGJveHBsb3QodWRhamUuc3ViW1tjb2xdXSwKICAgICAgICAgIG1haW4gPSBjb2wsCiAgICAgICAgICB4bGFiID0gIkhvZG5vdGEiLAogICAgICAgICAgY29sID0gImxpZ2h0Ymx1ZSIpCn0KCiMgU3BvbG/EjW7DvSBuYWRwaXMKbXRleHQoIkJveHBsb3R5IGplZG5vdGxpdsO9Y2ggcHJlbWVubsO9Y2giLCBvdXRlciA9IFRSVUUsIGNleCA9IDEuNCwgZm9udCA9IDIpCgoKYGBgCgojIyBMaW5lw6FybmEgcmVncmVzaWEKCgpNb2RlbCBvZGhhZHVqZW0gcHLDrWthem9tICpsbSgpKi4gVnlzdmV0xL5vdmFub3UgcHJlbWVubm91IGplICoqcG/EjWV0IHpyYW5lbsO9Y2ggcHJpIGRvcHJhdm5laiBuZWhvZGUqKiAoKmluanVyaWVzX3RvdGFsKikuIEFrbyB2eXN2ZXTEvnVqw7pjZSBwcmVtZW5uw6kgc29tIHp2b2xpbGEgKipwb8SNZXQgemFwb2plbsO9Y2ggdm96aWRpZWwqKiAoKm51bV91bml0cyopIGEgKirEjWFzb3bDqSBjaGFyYWt0ZXJpc3Rpa3kgbmVob2R5KiosIGtvbmtyw6l0bmUgaG9kaW51IG5laG9keSAoKmNyYXNoX2hvdXIqKSwgZGXFiCB2IHTDvcW+ZG5pICgqY3Jhc2hfZGF5X29mX3dlZWsqKSBhIG1lc2lhYyBuZWhvZHkgKCpjcmFzaF9tb250aCopLgoKYGBge3J9Cm1vZGVsIDwtIGxtKAogIGluanVyaWVzX3RvdGFsIH4gKzEgKyBudW1fdW5pdHMgKyBjcmFzaF9ob3VyICsgY3Jhc2hfZGF5X29mX3dlZWsgKyBjcmFzaF9tb250aCwKICBkYXRhID0gdWRhamUuc3ViCikKc3VtbWFyeShtb2RlbCkKYGBgCk9iamVrdCB0cmllZHkgKmxtKCkqIG1pIHBvIG9kaGFkbnV0w60gbW9kZWx1IHBvc2t5dHVqZSB2aWFjZXJvIHXFvml0b8SNbsO9Y2ggdsO9c3R1cG92LCBrdG9yw6kgbcO0xb5lbSB2eXXFvmnFpSBwcmkgaW50ZXJwcmV0w6FjaWkgYSBkaWFnbm9zdGlrZSByZWdyZXNpZToKCjEuIFZla3RvciBvZGhhZG51dMO9Y2gga29lZmljaWVudG92ICptb2RlbCRjb2VmZmljaWVudHMqIOKAkyB1a2F6dWplIG9kaGFkb3ZhbsO9IHZwbHl2IHByZW1lbm7DvWNoICgqbnVtX3VuaXRzKiwgKmNyYXNoX2hvdXIqLCAqY3Jhc2hfZGF5X29mX3dlZWsqLCAqY3Jhc2hfbW9udGgqKSBuYSB2eXN2ZXTEvm92YW7DuiBwcmVtZW5uw7ogKmluanVyaWVzX3RvdGFsKi4KMi4gVmVrdG9yIHJlesOtZHXDrSAqbW9kZWwkcmVzaWR1YWxzKiDigJMgcm96ZGllbHkgbWVkemkgc2t1dG/EjW7DvW1pIGhvZG5vdGFtaSAqaW5qdXJpZXNfdG90YWwqIGEgaG9kbm90YW1pIHByZWRpa292YW7DvW1pIG1vZGVsb20uCjMuIFZla3RvciB2eXJvdm5hbsO9Y2ggaG9kbsO0dCB2eXN2ZXTEvm92YW5laiBwcmVtZW5uZWogKm1vZGVsJGZpdHRlZC52YWx1ZXMqIOKAkyBtb2RlbG9tIHZ5cG/EjcOtdGFuw6kgKHByZWRpa292YW7DqSkgaG9kbm90eSBwb8SNdHUgenJhbmVuw71jaCBwcmkgbmVob2RlLgo0LiBNYXRpY2EgdnlzdmV0xL51asO6Y2ljaCBwcmVtZW5uw71jaCBYICptb2RlbC5tYXRyaXgobW9kZWwpKiDigJMgbnVtZXJpY2vDoSBtYXRpY2EgcHJlbWVubsO9Y2ggemFocm51dMO9Y2ggdiBtb2RlbGksIGt0b3LDuiByZWdyZXNpYSBwb3XFvsOtdmEgcHJpIHbDvXBvxI10b2NoLgoKUHJlaMS+YWQgesOha2xhZG7DvWNoIHbDvXNsZWRrb3YgYSDFoXRhdGlzdGlja2VqIHbDvXpuYW1ub3N0aSB6w61za2FtIHBvbW9jb3UgcHLDrWthenUgKnN1bW1hcnkobW9kZWwpKi4KCgpLZcSPxb5lIHbFoWV0a3kgcG90cmVibsOpIGluZm9ybcOhY2llIHZpZW0gesOtc2thxaUgcHJpYW1vIHogb2JqZWt0dSAqbW9kZWwqLCBtw7TFvmVtIHNpIGljaCB2IHByw61wYWRlIHBvdHJlYnkgdnlww61zYcWlIGFqIGplZG5vdGxpdm8uIFByZSBwcmVoxL5hZG5vc8WlIHbFoWFrIGJ1ZGVtIMSPYWxlaiBwcmFjb3ZhxaUgbmFqbcOkIHNvIHPDumhybm9tIG1vZGVsdSBwb21vY291IHByw61rYXp1ICpzdW1tYXJ5KG1vZGVsKSosIGt0b3LDvSBvYnNhaHVqZSBrb2VmaWNpZW50eSwgaWNoIMWhdGF0aXN0aWNrw7ogdsO9em5hbW5vc8WlLCBpbmZvcm3DoWNpZSBvIHJlesOtZHXDoWNoIGFqIGNlbGtvdsOpIHZsYXN0bm9zdGkgbW9kZWx1LgoKYGBge3J9CiNwcmludCgiT2RoYWRudXTDqSByZWdyZXNuw6kga29lZmljaWVudHkgc8O6OiAiKQojcHJpbnQobW9kZWwkY29lZmZpY2llbnRzKQoKI3ByaW50KCJPZGhhZG51dMOpIHJlesOtZHXDoSBzw7o6ICIpCiNwcmludChtb2RlbCRyZXNpZHVhbHMpCgojcHJpbnQoIlZ5cm92bmFuw6kgKHByZWRpa292YW7DqSkgaG9kbm90eSB2eXN2ZXTEvm92YW5laiBwcmVtZW5uZWogc8O6OiAiKQojcHJpbnQobW9kZWwkZml0dGVkLnZhbHVlcykKCiNwcmludCgiTWF0aWNhIHZ5c3ZldMS+dWrDumNpY2ggcHJlbWVubsO9Y2ggWCAobW9kZWwubWF0cml4KSBqZTogIikKI3ByaW50KG1vZGVsLm1hdHJpeChtb2RlbCkpCgojICh2b2xpdGXEvm7DqSkgZGlhZ25vc3Rpa2EgdnBseXZ1IHBvem9yb3ZhbsOtIOKAkyBkaWFnb27DoWxhIGhhdC1tYXRyaXg6CiNYIDwtIG1vZGVsLm1hdHJpeChtb2RlbCkKI2RpYWcoWCAlKiUgc29sdmUodChYKSAlKiUgWCkgJSolIHQoWCkpCgpzdW1tYXJ5KG1vZGVsKQoKYGBgCgoKU8O6aHJuIG9kaGFkb3ZhbsOpaG8gcmVncmVzbsOpaG8gbW9kZWx1IHBvc2t5dHVqZSBzw7pib3Igb2RoYWRudXTDvWNoIHJlZ3Jlc27DvWNoIGtvZWZpY2llbnRvdiwga3RvcsO9Y2ggem5hbWllbmthIGEgxaF0YXRpc3RpY2vDoSB2w716bmFtbm9zxaUgYnVkw7ogcG9kcm9ibmVqxaFpZSBpbnRlcnByZXRvdmFuw6kgdiDEj2FsxaFlaiDEjWFzdGkgYW5hbMO9enkuIEFrIHNhIHbFoWFrIHphbWVyaWFtZSBuYSB2bGFzdG5vc3RpIG1vZGVsdSBha28gY2Vsa3UsIGplIHBvdHJlYm7DqSBuYWpza8O0ciBvdmVyacWlLCDEjWkgc8O6IHNwbG5lbsOpIHrDoWtsYWRuw6kgcHJlZHBva2xhZHkgbGluZcOhcm5laiByZWdyZXNpZS4KCk5hIHRlbnRvIMO6xI1lbCB2eXXFvsOtdmFtIGRpYWdub3N0aWNrw6kgZ3JhZnkgcmVncmVzbsOpaG8gbW9kZWx1LiBQcm9zdHJlZG7DrWN0dm9tICoqUeKAk1EgZ3JhZnUqKiBwb3N1ZHp1amVtIHByZWRwb2tsYWQgbm9ybWFsaXR5IHJlesOtZHXDrSwgemF0aWHEviDEjW8gb3N0YXRuw6kgZGlhZ25vc3RpY2vDqSBncmFmeSBtaSB1bW/FvsWIdWrDuiBpZGVudGlmaWtvdmHFpSBwcsOtcGFkbsOpIHByb2Jsw6lteSBzIGhldGVyb3NrZWRhc3RpY2l0b3UsIG5lbGluZWFyaXRvdSBhbGVibyBwcsOtdG9tbm9zxaVvdSB2cGx5dm7DvWNoIHBvem9yb3ZhbsOtLiBOYSB6w6FrbGFkZSB0w71jaHRvIGdyYWZvdiBzaSB2aWVtIHZ5dHZvcmnFpSBwcnZvdG7DvSBkb2plbSBvIHZob2Rub3N0aSB6dm9sZW7DqWhvIG1vZGVsdSBhIG8gdG9tLCDEjWkgamUgbW/Fvm7DqSBqZWhvIHbDvXNsZWRreSBwb3Zhxb5vdmHFpSB6YSBzcG/EvmFobGl2w6kuCgoKCgoKCmBgYHtyIGRpYWdwbG90cywgZmlnLmNhcD0iRGlhZ25vc3RpY2vDqSBncmFmeSByZWdyZXNuw6lobyBtb2RlbHUiLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD04fQpwYXIobWZyb3cgPSBjKDIsIDIpKQpwYXIobWFyID0gYyg0LCA0LCAyLCAxKSkKCgojIFZ5a3Jlc2xpxaUgdsWhZXRreSA0IGRpYWdub3N0aWNrw6kgZ3JhZnkgbW9kZWx1CnBsb3QobW9kZWwpCgojIFJlc2V0b3ZhxaUgbGF5b3V0CnBhcihtZnJvdyA9IGMoMSwgMSkpCmBgYAoKIyMgUmVzaWR1YWxzIHZzLiBGaXR0ZWQKCiMjIyBJbnRlcnByZXTDoWNpYSBrb25rcsOpdG5laG8gZ3JhZnUKCioqQ2VudHJvdmFuaWUgb2tvbG8gbnVseSoqICAKUmV6w61kdcOhIGtvbMOtxaF1IHByaWJsacW+bmUgb2tvbG8gaG9kbm90eSAwLCDEjW8gamUgxb5pYWR1Y2kgc3Rhdi4gTmF6bmHEjXVqZSB0bywgxb5lIG1vZGVsIG5lbcOhIHN5c3RlbWF0aWNrw7ogdGVuZGVuY2l1IG5hZGhvZG5vY292YcWlIGFsZWJvIHBvZGhvZG5vY292YcWlIHBvxI1ldCB6cmFuZW7DvWNoIHByaSBkb3ByYXZuw71jaCBuZWhvZMOhY2guCgoqKlR2YXIgdnrFpWFodSoqICAKxIxlcnZlbsOhIHZ5aGxhZHpvdmFjaWEgxI1pYXJhIChMT0VTUykgdnlrYXp1amUgbWllcm5lIHpha3JpdmVuaWUsIMSNbyBtw7TFvmUgbmF6bmHEjW92YcWlIHNsYWLDuiBuZWxpbmVhcml0dSBtZWR6aSB2eXN2ZXTEvnVqw7pjaW1pIHByZW1lbm7DvW1pIChuYWptw6QgxI1hc292w71taSBjaGFyYWt0ZXJpc3Rpa2FtaSBuZWhvZHkpIGEgcG/EjXRvbSB6cmFuZW7DvWNoLiBUZW50byBlZmVrdCB2xaFhayBuaWUgamUgdsO9cmF6bsO9IGEgbmVwcmVkc3RhdnVqZSB6w6FzYWRuw70gcHJvYmzDqW0gcHJlIGludGVycHJldMOhY2l1IG1vZGVsdS4KCioqUm96cHR5bCByZXrDrWR1w60qKiAgClZlcnRpa8OhbG55IHJvenB0eWwgcmV6w61kdcOtIHNhIGphdsOtIGFrbyBwcmlibGnFvm5lIGtvbsWhdGFudG7DvSB2IGNlbG9tIHJvenNhaHUgdnlyb3ZuYW7DvWNoIGhvZG7DtHQsIMSNbyBuYXpuYcSNdWplIHNwbG5lbmllIHByZWRwb2tsYWR1IGhvbW9za2VkYXN0aWNpdHkuCgoqKk9kxL5haGzDqSBwb3pvcm92YW5pYSoqICAKTmlla2/EvmtvIGJvZG92IHNhIG5hY2jDoWR6YSDEj2FsZWogb2Qgb3N0YXRuw71jaCwgxI1vIG3DtMW+ZSBwcmVkc3Rhdm92YcWlIG5laG9keSBzIG1pbW9yaWFkbmUgdnlzb2vDvW0gYWxlYm8gbsOtemt5bSBwb8SNdG9tIHpyYW5lbsO9Y2guIFRpZXRvIHBvem9yb3ZhbmlhIGplIG1vxb5uw6kgxI9hbGVqIHByZXNrw7ptYcWlIHBvbW9jb3UgdGVzdHUgYG91dGxpZXJUZXN0KG1vZGVsKWAgeiBiYWzDrWthICpjYXIqLgoKCgojIyBR4oCTUSBQbG90CgojIyMgxIxvIGdyYWYgem7DoXpvcsWIdWplCgotIE9zIFggcHJlZHN0YXZ1amUgdGVvcmV0aWNrw6kga3ZhbnRpbHkgbm9ybcOhbG5laG8gcm96ZGVsZW5pYS4KLSBPcyBZIHpvYnJhenVqZSDFoXRhbmRhcmRpem92YW7DqSByZXrDrWR1w6EgbW9kZWx1LgotIFByZXJ1xaFvdmFuw6EgZGlhZ29uw6FsYSBwcmVkc3RhdnVqZSBpZGXDoWxueSBwcsOtcGFkLCB2IGt0b3JvbSBieSByZXrDrWR1w6EgbWFsaSBub3Jtw6FsbmUgcm96ZGVsZW5pZS4KCiMjIyBJbnRlcnByZXTDoWNpYSBrb25rcsOpdG5laG8gZ3JhZnUKCioqQ2Vsa292w70gdHZhciByb3pkZWxlbmlhKiogIApWw6TEjcWhaW5hIGJvZG92IHNhIG5hY2jDoWR6YSBibMOtemtvIHJlZmVyZW7EjW5laiBwcmlhbWt5LCDEjW8gbmF6bmHEjXVqZSwgxb5lIHJlesOtZHXDoSBzw7ogcHJpYmxpxb5uZSBub3Jtw6FsbmUgcm96bG/FvmVuw6kuCgoqKktyYWpuw6kgaG9kbm90eSoqICAKTmEgb2JvY2gga29uY29jaCBncmFmdSBkb2Now6FkemEgayBtaWVybnltIG9kY2jDvWxrYW0gb2QgcHJpYW1reSwgxI1vIG3DtMW+ZSBzaWduYWxpem92YcWlIHByw610b21ub3PFpSBleHRyw6ltbnljaCBob2Ruw7R0IOKAkyBuYXByw61rbGFkIG5laMO0ZCBzIG5lxaF0YW5kYXJkbsO9bSBwb8SNdG9tIHpyYW5lbsO9Y2guCgoqKlN0cmVkbsOhIMSNYXPFpSByb3pkZWxlbmlhKiogIApWIGNlbnRyw6FsbmVqIG9ibGFzdGkgZ3JhZnUgKG9rb2xvIG1lZGnDoW51KSByZXrDrWR1w6EgdmXEvm1pIGRvYnJlIGtvcMOtcnVqw7ogdGVvcmV0aWNrw7ogcHJpYW1rdSwgxI1vIHpuYW1lbsOhLCDFvmUgdsOkxI3FoWluYSBwb3pvcm92YW7DrSBzcMS6xYhhIHByZWRwb2tsYWQgbm9ybWFsaXR5LgoKTmEgesOha2xhZGUgUeKAk1EgZ3JhZnUgbW/Fvm5vIGtvbsWhdGF0b3ZhxaUsIMW+ZSBwcmVkcG9rbGFkIG5vcm1hbGl0eSByZXrDrWR1w60gamUgdiBwcmlqYXRlxL5uZWogbWllcmUgc3BsbmVuw70sIGFqIGtlxI8gcyBtaWVybnltaSBvZGNow71sa2FtaSB2IGV4dHLDqW1vY2guCgoKIyMgU2NhbGXigJNMb2NhdGlvbiBQbG90CgojIyMgxIxvIGdyYWYgem7DoXpvcsWIdWplCgotIE9zIFggcHJlZHN0YXZ1amUgdnlyb3ZuYW7DqSBob2Rub3R5IHrDoXZpc2xlaiBwcmVtZW5uZWogKHByZWRpa292YW7DvSBwb8SNZXQgenJhbmVuw71jaCkuCi0gT3MgWSB6b2JyYXp1amUgZHJ1aMO6IG9kbW9jbmludSBhYnNvbMO6dG55Y2ggxaF0YW5kYXJkaXpvdmFuw71jaCByZXrDrWR1w60uCi0gxIxlcnZlbsOhIMSNaWFyYSBwcmVkc3RhdnVqZSB2eWhsYWRlbsO9IHRyZW5kIChMT0VTUykuCgojIyMgSW50ZXJwcmV0w6FjaWEga29ua3LDqXRuZWhvIGdyYWZ1CgoqKkhvbW9za2VkYXN0aWNpdGEqKiAgCkJvZHkgc8O6IHJvdm5vbWVybmUgcm96cHTDvWxlbsOpIHBvemTEusW+IG9zaSBYIGEgbmV2eXR2w6FyYWrDuiBsaWV2aWtvdml0w70gdHZhci4gVG8gbmF6bmHEjXVqZSwgxb5lIHZhcmlhbmNpYSByZXrDrWR1w60gamUgcHJpYmxpxb5uZSBrb27FoXRhbnRuw6EuCgoqKlRyZW5kIHZ5aGxhZHpvdmFjZWoga3Jpdmt5KiogIArEjGVydmVuw6EgTE9FU1Mga3JpdmthIGplIHRha21lciBob3Jpem9udMOhbG5hLCDEjW8gcG9kcG9ydWplIHByZWRwb2tsYWQsIMW+ZSByb3pwdHlsIHJlesOtZHXDrSBzYSBuZW1lbsOtIHMgcmFzdMO6Y2ltaSB2eXJvdm5hbsO9bWkgaG9kbm90YW1pLgoKKipPZMS+YWhsw6kgaG9kbm90eSoqICAKTmlla2/EvmtvIGJvZG92IHNhIG5hY2jDoWR6YSBtaWVybmUgdnnFocWhaWUsIGF2xaFhayBuZWpkZSBvIGV4dHLDqW1uZSBwb3pvcm92YW5pYSwga3RvcsOpIGJ5IHbDvXJhem5lIG5hcnXFoW92YWxpIHN0YWJpbGl0dSBtb2RlbHUuCgoKIyMgUmVzaWR1YWxzIHZzLiBMZXZlcmFnZQoKIyMjIMSMbyBncmFmIHpuw6F6b3LFiHVqZQoKLSBPcyBYIHByZWRzdGF2dWplIHDDoWtvdsO9IGVmZWt0IHBvem9yb3ZhbsOtLCBrdG9yw70gdnlqYWRydWplLCBha28gdmXEvm1pIHNhIGRhbsOpIHBvem9yb3ZhbmllIGzDrcWhaSBvZCBvc3RhdG7DvWNoIHogaMS+YWRpc2thIHZ5c3ZldMS+dWrDumNpY2ggcHJlbWVubsO9Y2guCi0gT3MgWSB6b2JyYXp1amUgxaF0YW5kYXJkaXpvdmFuw6kgcmV6w61kdcOhLgotIEJvZGtvdmFuw6kga3Jpdmt5IHpuw6F6b3LFiHVqw7oga29udMO6cnkgQ29va292ZWogdnpkaWFsZW5vc3RpLCBrdG9yw6kgaWRlbnRpZmlrdWrDuiBwb3RlbmNpw6FsbmUgdnBseXZuw6kgcG96b3JvdmFuaWEuCgojIyMgSW50ZXJwcmV0w6FjaWEga29ua3LDqXRuZWhvIGdyYWZ1CgoqKlJvemxvxb5lbmllIHZwbHl2dSoqICAKVsOkxI3FoWluYSBwb3pvcm92YW7DrSBtw6EgbsOtemt5IHDDoWtvdsO9IGVmZWt0LCDEjW8gamUgdHlwaWNrw6kgcHJlIGRvYnJlIMWhdHJ1a3TDunJvdmFuw6kgZMOhdGEgbyBkb3ByYXZuw71jaCBuZWhvZMOhY2guCgoqKlZlxL5rb3PFpSByZXrDrWR1w60qKiAgCsWgdGFuZGFyZGl6b3ZhbsOpIHJlesOtZHXDoSBzYSBwcmV2YcW+bmUgcG9oeWJ1asO6IHYgaW50ZXJ2YWxlIOKfqOKIkjIsIDLin6ksIMSNbyBuYXpuYcSNdWplIGFic2VuY2l1IGV4dHLDqW1ueWNoIGNow71iIG1vZGVsdS4KCioqVnBseXZuw6kgcG96b3JvdmFuaWEqKiAgCk5pZWt0b3LDqSBwb3pvcm92YW5pYSBzYSBuYWNow6FkemFqw7ogYmxpxb7FoWllIGt1IGtvbnTDunJhbSBDb29rb3ZlaiB2emRpYWxlbm9zdGksIGF2xaFhayDFvmlhZG5lIHogbmljaCBuZXByZWtyYcSNdWplIGtyaXRpY2vDqSBocmFuaWNlLiBaIHRvaG8gdnlwbMO9dmEsIMW+ZSDFvmlhZG5hIG5laG9kYSBuZW92cGx5dsWIdWplIHJlZ3Jlc27DqSBrb2VmaWNpZW50eSBuZXByaW1lcmFuZS4KCgpgYGB7cn0KCiMgVGVzdCBub3JtYWxpdHkgcmV6w61kdcOtCnJlc2lkdWFscyA8LSByZXNpZHVhbHMobW9kZWwpCmpiX3Rlc3QgPC0gamFycXVlLmJlcmEudGVzdChyZXNpZHVhbHMpCmpiX3Rlc3QKCiMgVGVzdCBvZMS+YWhsw71jaCBwb3pvcm92YW7DrSAoQm9uZmVycm9uaSkKb3V0bGllcl90ZXN0IDwtIG91dGxpZXJUZXN0KG1vZGVsKQpvdXRsaWVyX3Rlc3QKCmBgYApOYSBvdmVyZW5pZSBwcmVkcG9rbGFkdSBub3JtYWxpdHkgcmV6w61kdcOtIHNvbSBwb3XFvmlsYSBKYXJxdWXigJNCZXJhIHRlc3QuIE51bG92w6EgaHlwb3TDqXphIHRlc3R1IHByZWRwb2tsYWTDoSwgxb5lIHJlesOtZHXDoSBtYWrDuiBub3Jtw6FsbmUgcm96ZGVsZW5pZS4gVsO9c2xlZGt5IHRlc3R1IG5hem5hxI11asO6LCDFvmUgcmV6w61kdcOhIHNhIG3DtMW+dSBvZGNoecS+b3ZhxaUgb2Qgbm9ybcOhbG5laG8gcm96ZGVsZW5pYSwgxI1vIGplIHByaSBkw6F0YWNoIG8gZG9wcmF2bsO9Y2ggbmVob2TDoWNoIHBvbWVybmUgxI1hc3TDqSwga2XEj8W+ZSBwb8SNZXQgenJhbmVuw71jaCBtw7TFvmUgbmFkb2LDumRhxaUgZXh0csOpbW5lIGhvZG5vdHkgcHJpIHrDoXZhxb5uw71jaCBuZWhvZMOhY2guCgpaw6Fyb3ZlxYggc29tIHBvbW9jb3UgZnVua2NpZSBvdXRsaWVyVGVzdCgpIGlkZW50aWZpa292YWxhIHBvdGVuY2nDoWxuZSBvZMS+YWhsw6kgYSB2cGx5dm7DqSBwb3pvcm92YW5pYS4gVsO9c2xlZGt5IHRlc3R1IHBvdWthenVqw7ogbmEgZXhpc3RlbmNpdSBuaWVrb8S+a8O9Y2ggcG96b3JvdmFuw60sIGt0b3LDqSBtw7TFvnUgbWHFpSBuZXByaW1lcmFuZSB2ZcS+a8O9IHZwbHl2IG5hIG9kaGFkIHJlZ3Jlc27DvWNoIGtvZWZpY2llbnRvdi4gSWRlIG5ham3DpCBvIG5laG9keSBzIG1pbW9yaWFkbmUgdnlzb2vDvW0gcG/EjXRvbSB6cmFuZW7DvWNoLCBrdG9yw6kgbcO0xb51IG5hcsO6xaFhxaUgc3BsbmVuaWUgcHJlZHBva2xhZG92IGxpbmXDoXJuZWogcmVncmVzaWUuCgpOYSB6w6FrbGFkZSB2w71zbGVka292IHTDvWNodG8gdGVzdG92IHNhIHJvemhvZG5lbSB1cHJhdmnFpSBww7R2b2Ruw70gbW9kZWwgdHJhbnNmb3Jtw6FjaW91IHZ5c3ZldMS+b3ZhbmVqIHByZW1lbm5laiAqaW5qdXJpZXNfdG90YWwqLCBhYnkgc29tIHpuw63FvmlsYSB2cGx5diBleHRyw6ltbnljaCBob2Ruw7R0IGEgemxlcMWhaWxhIHZsYXN0bm9zdGkgbW9kZWx1LgoKCmBgYHtyfQoKdWRhamUuc3ViJGxvZ19pbmp1cmllcyA8LSBsb2codWRhamUuc3ViJGluanVyaWVzX3RvdGFsICsgMSkKbW9kZWwyIDwtIGxtKAogIGxvZ19pbmp1cmllcyB+IG51bV91bml0cyArIGNyYXNoX2hvdXIgKyBjcmFzaF9kYXlfb2Zfd2VlayArIGNyYXNoX21vbnRoLAogIGRhdGEgPSB1ZGFqZS5zdWIKKQpzdW1tYXJ5KG1vZGVsMikKYGBgCgoKCmBgYHtyIGRpYWdwbG90czIsIGZpZy5jYXA9IkRpYWdub3N0aWNrw6kgZ3JhZnkgcmVncmVzbsOpaG8gbW9kZWx1In0KIyBOYXN0YXZpxaUgcm96bG/FvmVuaWUgMiB4IDIKcGFyKG1mcm93ID0gYygyLCAyKSkKcGFyKG1hciA9IGMoNCwgNCwgMiwgMSkpICAjIFpNRU7FoMONIE9LUkFKRQoKIyBWeWtyZXNsacWlIHbFoWV0a3kgNCBkaWFnbm9zdGlja8OpIGdyYWZ5IG1vZGVsdQpwbG90KG1vZGVsMikKCiMgKFZvbGl0ZcS+bsOpKSBwcmlkYcWlIHNwb2xvxI1uw70gbmFkcGlzCiNtdGV4dCgiRGlhZ25vc3RpY2vDqSBncmFmeSByZWdyZXNuw6lobyBtb2RlbHUiLCBvdXRlciA9IFRSVUUsIGNleCA9IDEuMiwgZm9udCA9IDIpCgojIFJlc2V0b3ZhxaUgbGF5b3V0CnBhcihtZnJvdyA9IGMoMSwgMSkpCmBgYAoKCgoKYGBge3J9CiMgVGVzdCBub3JtYWxpdHkgcmV6w61kdcOtIChtb2RlbDIpCnJlc2lkdWFscyA8LSByZXNpZHVhbHMobW9kZWwyKQpqYl90ZXN0IDwtIGphcnF1ZS5iZXJhLnRlc3QocmVzaWR1YWxzKQpqYl90ZXN0CgojIFRlc3Qgb2TEvmFobMO9Y2ggcG96b3JvdmFuw60gKEJvbmZlcnJvbmkga29yZWtjaWEpCm91dGxpZXJfdGVzdCA8LSBvdXRsaWVyVGVzdChtb2RlbDIpCm91dGxpZXJfdGVzdApgYGAKCiMjIFrDoXZlciBvIGFuYWzDvXplIG9kxL5haGzDvWNoIGhvZG7DtHQKCk5hIHrDoWtsYWRlIHZ5a29uYW5laiBhbmFsw716eSBtw7TFvmVtIGtvbsWhdGF0b3ZhxaUsIMW+ZSB2eWJyYW7DqSB2eXN2ZXTEvnVqw7pjZSBwcmVtZW5uw6kgbWFqw7ogxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70gdnBseXYgbmEgdnlzdmV0xL5vdmFuw7ogcHJlbWVubsO6IHPDunZpc2lhY3UgcyBkb3ByYXZuw71taSBuZWhvZGFtaS4gTmlla3RvcsOpIHByZW1lbm7DqSBzYSB2IHDDtHZvZG5vbSBtb2RlbGkgdWvDoXphbGkgYWtvIG1lbmVqIHZob2Ruw6kgYWxlYm8gxaVhxb5rbyBpbnRlcnByZXRvdmF0ZcS+bsOpLCBhIHByZXRvIGJvbCBtb2RlbCB2IMSPYWzFoW9tIGtyb2t1IHVwcmF2ZW7DvS4KClRlc3R5IG5vcm1hbGl0eSBhIGRpYWdub3N0aWNrw6kgZ3JhZnkgbmF6bmHEjWlsaSBwcsOtdG9tbm9zxaUgb2TEvmFobMO9Y2gKcG96b3JvdmFuw60sIGt0b3LDqSBzw7ogdHlwaWNrw6kgcHJlIGTDoXRhIHogb2JsYXN0aSBkb3ByYXZ5LCBrZGUgc2Egdnlza3l0dWrDuiBleHRyw6ltbmUgc2l0dcOhY2llIChuYXByLiBuZWhvZHkgcyB2eXNva8O9bSBwb8SNdG9tIHpyYW5lbsO9Y2gpLiBaIHRvaHRvIGTDtHZvZHUgYm9sYSBwb3XFvml0w6EgbG9nYXJpdG1pY2vDoSB0cmFuc2Zvcm3DoWNpYSB2eXN2ZXTEvm92YW5laiBwcmVtZW5uZSxrdG9yw6EgcHJpc3BlbGEgayB6bWllcm5lbml1IHZwbHl2dSBleHRyw6ltbnljaCBob2Ruw7R0LgoKViB1cHJhdmVub20gbW9kZWxpIHNhIG5lcHJldWvDoXphbGkgdsO9cmF6bsOpIHZwbHl2bsOpIHBvem9yb3ZhbmlhIGFuaQp6w6F2YcW+bsOpIG5lbGluZWFyaXR5LiBOYSB6w6FrbGFkZSB0b2hvIG1vxb5ubyB2w71zbGVka3kgcmVncmVzbmVqIGFuYWzDvXp5IHBvdmHFvm92YcWlIHphIHByaW1lcmFuw6kgYSBtb2RlbCB6YSB2aG9kbsO9IG5hIMSPYWzFoWl1IGludGVycHJldMOhY2l1LgoKIyMgSGV0ZXJvc2tlZGFzdGljaXRhCgoKUHLDrXRvbW5vc8WlIGhldGVyb3NrZWRhc3RpY2l0eSAoKm5la29uxaF0YW50bsOpaG8gcm96cHR5bHUgbsOhaG9kbmVqIHpsb8W+a3kqKQptw7TFvmUgdmllc8WlIGsgbmVzcHLDoXZuZW11IHZ5aG9kbm9jb3Zhbml1ICp0LXRlc3RvdiB2w716bmFtbm9zdGkqCmplZG5vdGxpdsO9Y2ggcmVncmVzbsO9Y2gga29lZmljaWVudG92LiBaIHRvaHRvIGTDtHZvZHUgamUgbmV2eWhudXRuw6kKaGV0ZXJvc2tlZGFzdGljaXR1ICAKLSAqZGV0ZWtvdmHFpSogKHZpenXDoWxuZSBhaiBwb21vY291IMWhdGF0aXN0aWNrw71jaCB0ZXN0b3YpLCAgCi0gYSB2IHByw61wYWRlIGplaiBwcsOtdG9tbm9zdGkganUgKnZob2Ruw71tIHNww7Rzb2JvbSBlbGltaW5vdmHFpSouCgpWIHByw61wYWRlIGRhdGFiw6F6eSBkb3ByYXZuw71jaCBuZWjDtGQgamUgbW/Fvm7DqSBoZXRlcm9za2VkYXN0aWNpdHUKb8SNYWvDoXZhxaUsIGtlxI/FvmUgcG/EjWV0IG5laMO0ZCBhIGljaCBuw6FzbGVka3kgc2EgbcO0xb51IHbDvXJhem5lIGzDrcWhacWlCnYgesOhdmlzbG9zdGkgb2QgxI1hc3UsIGTFiGEgYWxlYm8gaW7DvWNoIGNoYXJha3RlcmlzdMOtayBwcmVtw6F2a3kuCkFqIHByZXRvIHNvbSBzYSB6YW1lcmFsYSBuYSBqZWogcG9zw7pkZW5pZSBwcm9zdHJlZG7DrWN0dm9tCmRpYWdub3N0aWNrw71jaCBncmFmb3YuCgpOYSB0ZW50byDDusSNZWwgYnVkZW0gcG9yb3Zuw6F2YcWlIGR2YSByZWdyZXNuw6kgbW9kZWx5IOKAkyBww7R2b2Ruw70gbW9kZWwKb3puYcSNZW7DvSBha28gKm1vZGVsKiBhIHVwcmF2ZW7DvSBtb2RlbCAqbW9kZWwyKiwgdiBrdG9yb20gYm9sYQpwb3XFvml0w6EgbG9nYXJpdG1pY2vDoSB0cmFuc2Zvcm3DoWNpYSB2eXN2ZXTEvm92YW5laiBwcmVtZW5uZWouCkNpZcS+b20gdGVqdG8gw7pwcmF2eSBib2xvIHpuw63FvmVuaWUgdnBseXZ1IGV4dHLDqW1ueWNoIGhvZG7DtHQgYQpzdGFiaWxpesOhY2lhIHJvenB0eWx1IHJlesOtZHXDrS4KCgoKYGBge3IgaGV0ZXJvcGxvdHMxLCBmaWcuY2FwPSJTa8O6bWFuaWUgaGV0ZXJvc2tlZGFzdGljaXR5IiwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTR9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwYXRjaHdvcmspCgpkZl9yZXMgPC0gbW9kZWwuZnJhbWUobW9kZWwyKQpkZl9yZXMkcmVzMiA8LSByZXNpZChtb2RlbDIpXjIKCnNldC5zZWVkKDEyMykKZGZfcGxvdCA8LSBkZl9yZXNbc2FtcGxlKG5yb3coZGZfcmVzKSwgbWluKDMwMDAsIG5yb3coZGZfcmVzKSkpLCBdCgpwMSA8LSBnZ3Bsb3QoZGZfcGxvdCwgYWVzKHggPSBudW1fdW5pdHMsIHkgPSByZXMyKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IEZBTFNFKSArCiAgbGFicygKICAgIHggPSAiUG/EjWV0IHrDusSNYXN0bmVuw71jaCB2b3ppZGllbCIsCiAgICB5ID0gIsWgdHZvcmNlIHJlesOtZHXDrSIsCiAgICB0aXRsZSA9ICLFoHR2b3JjZSByZXrDrWR1w60gdnMuIHBvxI1ldCB2b3ppZGllbCIKICApICsKICB0aGVtZV9taW5pbWFsKCkKCnAyIDwtIGdncGxvdChkZl9wbG90LCBhZXMoeCA9IGNyYXNoX2hvdXIsIHkgPSByZXMyKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IEZBTFNFKSArCiAgbGFicygKICAgIHggPSAiSG9kaW5hIG5laG9keSIsCiAgICB5ID0gIsWgdHZvcmNlIHJlesOtZHXDrSIsCiAgICB0aXRsZSA9ICLFoHR2b3JjZSByZXrDrWR1w60gdnMuIGhvZGluYSBuZWhvZHkiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCgpwcmludChwMSArIHAyKQoKCmBgYAphIHRlcmF6IG1vZGVsIHNvIHpsb2dhcml0bWl6b3Zhbm91IHByZW1lbm5vdSAqbnVtX3VuaXRzKi4KCmBgYHtyIGhldGVyb3Bsb3RzMiwgZmlnLmNhcD0iU2vDum1hbmllIGhldGVyb3NrZWRhc3RpY2l0eSIsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00fQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGF0Y2h3b3JrKQoKZGZfcmVzIDwtIG1vZGVsLmZyYW1lKG1vZGVsMikKZGZfcmVzJHJlczIgPC0gcmVzaWQobW9kZWwyKV4yCgpkZl9yZXMgPC0gZGZfcmVzWwogIGlzLmZpbml0ZShkZl9yZXMkcmVzMikgJgogICAgIWlzLm5hKGRmX3JlcyRudW1fdW5pdHMpICYKICAgICFpcy5uYShkZl9yZXMkY3Jhc2hfaG91ciksCl0KCnNldC5zZWVkKDEyMykKZGZfcGxvdCA8LSBkZl9yZXNbc2FtcGxlKG5yb3coZGZfcmVzKSwgbWluKDMwMDAsIG5yb3coZGZfcmVzKSkpLCBdCgpwMSA8LSBnZ3Bsb3QoZGZfcGxvdCwgYWVzKHggPSBsb2cobnVtX3VuaXRzICsgMSksIHkgPSByZXMyKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IEZBTFNFKSArCiAgbGFicyh4ID0gImxvZyhudW1fdW5pdHMgKyAxKSIsCiAgICAgICB5ID0gIlNxdWFyZWQgUmVzaWR1YWxzIiwKICAgICAgIHRpdGxlID0gIlJlc2lkdWFscyB2cyBsb2cobnVtX3VuaXRzICsgMSkiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpwMiA8LSBnZ3Bsb3QoZGZfcGxvdCwgYWVzKHggPSBjcmFzaF9ob3VyLCB5ID0gcmVzMikpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC42KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSkgKwogIGxhYnMoeCA9ICJjcmFzaF9ob3VyIiwKICAgICAgIHkgPSAiU3F1YXJlZCBSZXNpZHVhbHMiLAogICAgICAgdGl0bGUgPSAiUmVzaWR1YWxzIHZzIGNyYXNoX2hvdXIiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpwMSArIHAyCgoKYGBgCgpOYSB0b210byBvYnLDoXprdSBwb2TEvmEgdnlobGFkZW7DvWNoIGhvZG7DtHQgxaF0dm9yY292IHJlesOtZHXDrSAodnlobGFkZW7DoSBrcml2a2EgdiBncmFmZSkgbcO0xb5lbSBrb27FoXRhdG92YcWlLCDFvmUgbmV2aWTDrW0gdsO9cmF6bsO9IHJhc3QgYW5pIHBva2xlcyByb3pwdHlsdSByZXrDrWR1w60gdiB6w6F2aXNsb3N0aSBvZCB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoLiAKClYgZ3JhZmUgKlJlc2lkdWFscyB2cyBsb2cobnVtX3VuaXRzICsgMSkqIGplIHbDpMSNxaFpbmEgYm9kb3Ygc8O6c3RyZWRlbsOhIHByaSBuacW+xaHDrWNoIGhvZG5vdMOhY2ggcG/EjXR1IHrDusSNYXN0bmVuw71jaCB2b3ppZGllbCBhIHZ5aGxhZGVuw6Ega3JpdmthIG5ldnlrYXp1amUgamFzbsO9IHRyZW5kLCBrdG9yw70gYnkgbmF6bmHEjW92YWwgc3lzdGVtYXRpY2vDqSB6dnnFoW92YW5pZSB2YXJpYWJpbGl0eS4KClYgZ3JhZmUgKlJlc2lkdWFscyB2cyBjcmFzaF9ob3VyKiBzYSB0YWtpc3RvIG5ldWthenVqZSBqZWRub3puYcSNbsO9IHbDvXZvaiByb3pwdHlsdSByZXrDrWR1w60gdiBwcmllYmVodSBkxYhhIOKAkyB2eWhsYWRlbsOhIGtyaXZrYSBqZSBsZW4gbWllcm5lIHJhc3TDumNhLCDEjW8gbcO0xb5lIG5hem5hxI1vdmHFpSBzbGFiw70gZWZla3QsIGFsZSBuaWUgdsO9cmF6bsO6IGhldGVyb3NrZWRhc3RpY2l0dS4KClByZXRvIG5hIHrDoWtsYWRlIHZpenXDoWxuZWhvIHBvc8O6ZGVuaWEgbmV2aWTDrW0gc2lsbsO9IGTDtGtheiBoZXRlcm9za2VkYXN0aWNpdHkuIFRlbnRvIHrDoXZlciB2xaFhayBuw6FzbGVkbmUgb3ZlcsOtbSBmb3Jtw6FsbnltIHRlc3RvbSAobmFwci4gQnJldXNjaOKAk1BhZ2FuIHRlc3RvbSkuCgojIyBUZXN0b3ZhbmllIHByw610b21ub3N0aSBoZXRlcm9za2VkYXN0aWNpdHkKCmBgYHtyfQojIEluc3RhbGwgKGlmIG5vdCB5ZXQgaW5zdGFsbGVkKQojIGluc3RhbGwucGFja2FnZXMoImxtdGVzdCIpCgojIExvYWQgdGhlIHBhY2thZ2UKbGlicmFyeShsbXRlc3QpCgojIFJ1biB0aGUgQnJldXNjaOKAk1BhZ2FuIHRlc3QKYnB0ZXN0KG1vZGVsKQoKYGBgCmBgYHtyfQojIEluc3RhbGwgKGlmIG5vdCB5ZXQgaW5zdGFsbGVkKQojIGluc3RhbGwucGFja2FnZXMoImxtdGVzdCIpCgojIExvYWQgdGhlIHBhY2thZ2UKbGlicmFyeShsbXRlc3QpCgojIFJ1biB0aGUgQnJldXNjaOKAk1BhZ2FuIHRlc3QKYnB0ZXN0KG1vZGVsMikKCmBgYApOYSB6w6FrbGFkZSBCcmV1c2No4oCTUGFnYW5vdmhvIHRlc3R1IG3DtMW+ZW1lIGtvbsWhdGF0b3ZhxaUsIMW+ZSAqKmhldGVyb3NrZWRhc3RpY2l0YSByZXrDrWR1w60gamUgcHLDrXRvbW7DoSB2IHDDtHZvZG5vbSBtb2RlbGkgKCptb2RlbCopIGFqIHYgdXByYXZlbm9tIG1vZGVsaSAoKm1vZGVsMiopKiosIGtlxI/FvmUgdiBvYm9jaCBwcsOtcGFkb2NoIGJvbGEgbnVsb3bDoSBoeXBvdMOpemEgbyBrb27FoXRhbnRub20gcm96cHR5bGUgemFtaWV0bnV0w6EgKHAtaG9kbm90YSA8IDAsMDUpLgoKTG9nYXJpdG1pY2vDoSB0cmFuc2Zvcm3DoWNpYSB2eXN2ZXTEvm92YW5laiBwcmVtZW5uZWogc8OtY2UgemxlcMWhaWxhIHR2YXIgcmV6w61kdcOtIGEgaWNoIHZpenXDoWxuZSBzcHLDoXZhbmllLCBhdsWhYWsgKipoZXRlcm9za2VkYXN0aWNpdHUgc2EgdMO9bSBuZXBvZGFyaWxvIMO6cGxuZSBvZHN0csOhbmnFpSoqLiBWIMSPYWzFoWVqIGFuYWzDvXplIGplIHByZXRvIHZob2Ruw6kgcHJhY292YcWlIHMgcm9idXN0bsO9bWkgKGhldGVyb3NrZWRhc3RpY2l0eS1jb25zaXN0ZW50KSBvZGhhZG1pIHJvenB0eWxvdiByZWdyZXNuw71jaCBrb2VmaWNpZW50b3YsIGFieSBib2xpIHbDvXNsZWRreSB0ZXN0b3YgxaF0YXRpc3RpY2tlaiB2w716bmFtbm9zdGkgc3BvxL5haGxpdsOpLgoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJzYW5kd2ljaCIpCiNpbnN0YWxsLnBhY2thZ2VzKCJsbXRlc3QiKQpsaWJyYXJ5KHNhbmR3aWNoKQpsaWJyYXJ5KGxtdGVzdCkKY29lZnRlc3QobW9kZWwsIHZjb3YgPSB2Y292SEMobW9kZWwpKQoKCmBgYAoKClbFoWltbmltZSBzaSwgxb5lIHBvIHBvdcW+aXTDrSBoZXRlcm9za2VkYXN0aWNpdHktcm9idXN0bsO9Y2ggKFdoaXRlKSBvZGhhZG92IHJvenB0eWxvdiB6b3N0w6F2YWrDuiAqKnbFoWV0a3kgdnlzdmV0xL51asO6Y2UgcHJlbWVubsOpIMWhdGF0aXN0aWNreSB2w716bmFtbsOpKiouIFRvIHpuYW1lbsOhLCDFvmUgYWogcG8ga29yZWtjaWkgbmEgaGV0ZXJvc2tlZGFzdGljaXR1IHPDuiB2esWlYWh5IHphY2h5dGVuw6kgbW9kZWxvbSBzdGFiaWxuw6kgYSB2w71zbGVka3kgdGVzdG92IMWhdGF0aXN0aWNrZWogdsO9em5hbW5vc3RpIG1vxb5ubyBwb3Zhxb5vdmHFpSB6YSBzcG/EvmFobGl2w6kuCgpQb3XFvml0aWUgdGVqdG8gbWV0w7NkeSBqZSB2aG9kbsOpIG5ham3DpCBwcmkgKip2w6TEjcWhb20gcG/EjXRlIHBvem9yb3ZhbsOtKiosIMSNbyBqZSB2IHByw61wYWRlIGRhdGFiw6F6eSBkb3ByYXZuw71jaCBuZWjDtGQgc3BsbmVuw6kuIEFsdGVybmF0w612bnltIHJpZcWhZW7DrW0gaGV0ZXJvc2tlZGFzdGljaXR5IGJ5IGJvbGEgdHJhbnNmb3Jtw6FjaWEgYWxlYm8gxaFrw6Fsb3ZhbmllIG5pZWt0b3LDvWNoIHByZW1lbm7DvWNoIChuYXByLiBwcmVwb8SNZXQgbmEgbWllcnUgbmEgamVkbm90a3UgxI1hc3UgYWxlYm8gdm96aWRsbyksIGF2xaFhayB0YWvDqXRvIMO6cHJhdnkgYnkgbW9obGkgem7DrcW+acWlIGludGVycHJldGHEjW7DuiBwcmVoxL5hZG5vc8WlIG1vZGVsdS4gWiB0b2h0byBkw7R2b2R1IHBvdmHFvnVqZW0gcG91xb5pdGllIHJvYnVzdG7DvWNoIG9kaGFkb3YgemEgcHJpbWVyYW7DqSByaWXFoWVuaWUgdiByw6FtY2kgdGVqdG8gYW5hbMO9enkuCgoKCgo=