S využitím databázy dopravných nehôd budeme analyzovať faktory, ktoré
súvisia s počtom zranených pri nehode.
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. lm
# Načítanie údajov o dopravných nehodách
udaje <- read.csv("premavka.csv.csv", dec = ".", sep = ",", header = TRUE)
# Výber relevantných premenných:
# injuries_total - počet zranených pri nehode
# num_units - počet vozidiel/jednotiek zapojených do nehody
# crash_hour - hodina nehody
# crash_day_of_week - deň v týždni
# crash_month - mesiac nehody
udaje.sub <- udaje[, c("injuries_total",
"num_units",
"crash_hour",
"crash_day_of_week",
"crash_month")]
# Nahradenie chýbajúcich hodnôt mediánom v každom stĺpci
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
.
# Tvar údajov – boxploty pre každú premennú
# Koľko premenných máme
num_plots <- length(names(udaje.sub))
# Rozloženie grafov: 2 riadky × 3 stĺpce
par(mfrow = c(2, 3))
par(mar = c(4, 4, 2, 1)) # okraje grafov
# Boxplot pre každý stĺpec
for (col in names(udaje.sub)) {
boxplot(udaje.sub[[col]],
main = col, # NÁZOV PREMENNEJ
xlab = "",
col = "lightblue")
}
# Spoločný nadpis
mtext("Boxploty jednotlivých premenných", outer = TRUE, cex = 1.4, font = 2)
# Reset rozloženia
par(mfrow = c(1, 1))

Lineárna regresia
Cieľom je analyzovať faktory, ktoré ovplyvňujú počet zranených pri
dopravnej nehode (injuries_total). Ako vysvetľujúce
premenné sme zvolili:
num_units – počet vozidiel zapojených do nehody,
crash_hour – hodina, v ktorej sa nehoda stala,
crash_day_of_week – deň v týždni,
crash_month – mesiac nehody.
Model je odhadnutý pomocou príkazu lm():
model <- lm(injuries_total ~ num_units + crash_hour + crash_day_of_week + crash_month,
data = udaje.sub)
summary(model)
Call:
lm(formula = injuries_total ~ 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() po odhadnutí modelu poskytuje viacero
užitočných komponentov:
- Odhadnuté koeficienty
(
model$coefficients), ktoré ukazujú vplyv jednotlivých
vysvetľujúcich premenných na vysvetľovanú premennú
(injuries_total).
- Rezíduá (
model$residuals), teda
rozdiely medzi skutočnými hodnotami a hodnotami predpovedanými
modelom.
- Vyrovnané hodnoty
(
model$fitted.values), čo sú predikované hodnoty počtu
zranených podľa modelu.
- Maticu vysvetľujúcich premenných X
(
model.matrix(model)), ktorá obsahuje všetky premenné
zahrnuté v modeli v numerickej podobe.
Keďže všetky tieto informácie sú obsiahnuté aj v príkaze
summary(model), prehľad základných výsledkov získame jeho
použitím:
summary(model)
Call:
lm(formula = injuries_total ~ 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
Diagnostika regresného modelu
Súhrn odhadnutého modelu nám poskytuje súbor odhadnutých regresných
koeficientov, ktorých znamienka budú rozoberané neskôr. Ak chceme
posúdiť vlastnosti modelu ako celku, musíme skontrolovať, či spĺňa
základné predpoklady lineárnej regresie. Na tento účel slúžia
diagnostické grafy. Na základe Q–Q grafu môžeme posúdiť normalitu
rezíduí, zatiaľ čo ostatné grafy poskytujú informácie o
heteroskedasticite, linearite a prípadných vplyvných pozorovaniach.
par(mar = c(4, 4, 2, 1))
par(mfrow = c(2, 2))
plot(model)
par(mfrow = c(1, 1))

Podrobná interpretácia diagnostických grafov
1. Residuals vs Fitted
Tento graf ukazuje, či sa model vhodne prispôsobil údajom a či sú
splnené predpoklady linearity a konštantného rozptylu rezíduí. Rezíduá
oscilujú okolo nuly bez jasného tvaru, čo naznačuje, že vzťah medzi
vysvetľujúcimi premennými a počtom zranených je približne lineárny.
Mierne zakrivenie hladkej červenej čiary môže naznačovať existenciu
určitej nelinearity, no nejde o výrazny problém. Rozptyl rezíduí sa javí
ako relatívne rovnomerný, takže sa neprejavuje heteroskedasticita
(nerovnakosť rozptylu). Niekoľko bodov ďalej od ostatných môže
predstavovať odľahlé pozorovania, ktoré je vhodné ďalej preskúmať.
2. Normal Q–Q Plot
Normal Q–Q graf porovnáva rozdelenie rezíduí s teoretickým normálnym
rozdelením. Väčšina bodov leží blízko referenčnej priamky, čo naznačuje,
že rezíduá sú približne normálne rozložené. Mierne odchýlky na koncoch
grafu sú bežné a zvyčajne nepredstavujú vážny problém. Tieto odchýlky
môžu signalizovať prítomnosť extrémnych hodnôt alebo ťažších chvostov
rozdelenia, no celkový tvar potvrdzuje, že predpoklad normality je
prijateľne splnený.
3. Scale–Location Plot
Scale–Location graf (Spread–Location) hodnotí, či je variabilita
rezíduí konštantná naprieč predikovanými hodnotami. V našom prípade je
rozloženie bodov pomerne rovnomerné a červená LOESS krivka je relatívne
plochá. To naznačuje, že predpoklad homoskedasticity je splnený –
rozptyl rezíduí sa výrazne nemení s úrovňou predpovedí. Niekoľko bodov
mierne odskočených od ostatných môže predstavovať menšie odľahlosti, ale
nejde o nič kritické.
4. Residuals vs Leverage
Graf Rezíduá vs. Pákový efekt pomáha identifikovať pozorovania, ktoré
by mohli mať výrazný vplyv na výsledky regresie. Väčšina pozorovaní má
nízky pákový efekt a nachádza sa v bezpečnej oblasti mimo kontúr
Cookovej vzdialenosti. Jedno až dve pozorovania sa síce nachádzajú
bližšie ku kontúram, ale nepresahujú kritické hranice. To znamená, že
žiadne pozorovanie pravdepodobne neovplyvňuje model neprimerane. Je však
vhodné tieto prípady pozorovať pri ďalšej analýze.
# 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
Keďže test normality naznačil možné odchýlky od normálneho rozdelenia
rezíduí a v údajoch sa môžu nachádzať odľahlé pozorovania, pokúsime sa
tieto vplyvy zmierniť transformáciou vysvetľovanej premennej
injuries_total. Na tento účel použijeme logaritmickú
transformáciu počtu zranených, ktorá často pomáha stabilizovať varianciu
a znižovať vplyv extrémnych hodnôt.
Nová regresia
Keďže testy naznačili porušenie normality rezíduí v pôvodnom modeli,
pokúsime sa model upraviť transformáciou vysvetľovanej premennej. Počet
zranených pri nehode transformujeme pomocou logaritmu, čím znížime vplyv
extrémnych hodnôt.
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))
# 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))

Conclusion
Cieľom analýzy bolo preskúmať faktory ovplyvňujúce počet zranených
pri dopravných nehodách pomocou lineárnej regresie. Ako vysvetľujúce
premenné sme použili počet zapojených vozidiel (num_units),
hodinu nehody (crash_hour), deň v týždni
(crash_day_of_week) a mesiac nehody (crash_month).
Výsledky regresného modelu naznačujú, že počet zapojených vozidiel má
štatisticky významný vplyv na počet zranených, čo je v súlade s
očakávaniami – nehody s vyšším počtom vozidiel majú spravidla
závažnejšie následky. Ostatné časové premenné zachytávajú pravidelnosti
v dopravnej nehodovosti, ktoré môžu súvisieť s intenzitou premávky počas
dňa, týždňa alebo roka.
Diagnostické grafy a formálne testy poukázali na možné odchýlky od
predpokladu normality rezíduí. Z tohto dôvodu sme pristúpili k
logaritmickej transformácii vysvetľovanej premennej
injuries_total, čím sme znížili vplyv extrémnych hodnôt a
stabilizovali varianciu rezíduí. Nový regresný model vykazuje
priaznivejšie diagnostické vlastnosti a je vhodnejší na interpretáciu
vzťahov v dátach.
Celkovo možno konštatovať, že použitý regresný prístup poskytuje
zmysluplný pohľad na faktory ovplyvňujúce počet zranených pri dopravných
nehodách, pričom výsledky môžu slúžiť ako podklad pre ďalšiu analýzu
dopravnej bezpečnosti.
LS0tCnRpdGxlOiAiRWNvbm9tZXRyaWNzIGluIFIgLSBjdmnEjWVuaWUgNSIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogQmFyYm9yYSBLb3ByZG92YSAKLS0tClMgdnl1xb5pdMOtbSBkYXRhYsOhenkgZG9wcmF2bsO9Y2ggbmVow7RkIGJ1ZGVtZSBhbmFseXpvdmHFpSBmYWt0b3J5LCBrdG9yw6kgc8O6dmlzaWEgcyBwb8SNdG9tIHpyYW5lbsO9Y2ggcHJpIG5laG9kZS4KCiMjIMOadm9kIGRvIHByb2Jsw6ltdSwgc3Rhbm92ZW5pZSBoeXBvdMOpeiAKClJvemhvZGxhIHNvbSBzYSBtb2RlbG92YcWlIHBvxI1ldCB6cmFuZW7DvWNoIHByaSBuZWhvZGUgKCppbmp1cmllc190b3RhbCopIHYgesOhdmlzbG9zdGkgb2QgdHJvY2ggdHlwb3YgdnlzdmV0xL51asO6Y2ljaCBwcmVtZW5uw71jaDoKCi0gKipQb8SNZXQgdm96aWRpZWwgemFwb2plbsO9Y2ggZG8gbmVob2R5KiogKCpudW1fdW5pdHMqKSwgIAotICoqxI1hc292w6lobyBrb250ZXh0dSBuZWhvZHkqKiDigJMgaG9kaW5hIGTFiGEgKCpjcmFzaF9ob3VyKiksIGRlxYggdiB0w73FvmRuaSAoKmNyYXNoX2RheV9vZl93ZWVrKikgYSBtZXNpYWMgKCpjcmFzaF9tb250aCopLgoKUHJhY292bsOhIGh5cG90w6l6YToKCi0gcHJlZHBva2xhZMOhbSwgxb5lICoqdnnFocWhw60gcG/EjWV0IHphcG9qZW7DvWNoIHZvemlkaWVsIChudW1fdW5pdHMpKiogenZ5xaF1amUgcG/EjWV0IHpyYW5lbsO9Y2ggKCppbmp1cmllc190b3RhbCopLCAgCi0gcHJlZHBva2xhZMOhbSwgxb5lICoqxI1hc292w6kgcHJlbWVubmUqKiAoaG9kaW5hLCBkZcWIIHYgdMO9xb5kbmksIG1lc2lhYykgbcO0xb51IG92cGx5dsWIb3ZhxaUgesOhdmHFvm5vc8WlIG5laG9keSAobmFwci4gdmlhYyBuZWjDtGQgcyB2w6TEjcWhw61tIHBvxI10b20genJhbmVuw71jaCB2IMWhcGnEjWtlIGFsZWJvIGNleiB2w61rZW5kKS4KCmBgYHtyfQpsaWJyYXJ5KHpvbykKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGxtdGVzdCkKbGlicmFyeShzYW5kd2ljaCkKbGlicmFyeShjYXIpCnJtKGxpc3Q9bHMoKSkKYGBgCgrDmmRhamUgc8O6IHVsb8W+ZW7DqSB2IHPDumJvcmUgYC5jc3ZgLCBzdMS6cGNlIHPDuiBvZGRlbGVuw6kgxI1pYXJrb3UgKGAsYCkgYSBwb3XFvsOtdmFqw7ogZGVzYXRpbm7DuiBib2RrdSAoYC5gKS4KCgoKCgoKIyBQcsOtcHJhdmEgZGF0YWLDoXp5LCDEjWlzdGVuaWUgYSDDunByYXZhIMO6ZGFqb3YKCktlxI/FvmUgbmlla3RvcsOpIMO6ZGFqZSBjaMO9YmFqw7osIGRvcGxuaWxhIHNvbSBpY2ggbWVkacOhbm92w71taSBob2Rub3RhbWkgcHJlbWVubmVqLCBrdG9yw7ogenZhxb51amVtLiBsbQoKCmBgYHtyfQoKIyBOYcSNw610YW5pZSDDumRham92IG8gZG9wcmF2bsO9Y2ggbmVob2TDoWNoCnVkYWplIDwtIHJlYWQuY3N2KCJwcmVtYXZrYS5jc3YuY3N2IiwgZGVjID0gIi4iLCBzZXAgPSAiLCIsIGhlYWRlciA9IFRSVUUpCgojIFbDvWJlciByZWxldmFudG7DvWNoIHByZW1lbm7DvWNoOgojIGluanVyaWVzX3RvdGFsICAgICAgLSBwb8SNZXQgenJhbmVuw71jaCBwcmkgbmVob2RlCiMgbnVtX3VuaXRzICAgICAgICAgICAtIHBvxI1ldCB2b3ppZGllbC9qZWRub3RpZWsgemFwb2plbsO9Y2ggZG8gbmVob2R5CiMgY3Jhc2hfaG91ciAgICAgICAgICAtIGhvZGluYSBuZWhvZHkKIyBjcmFzaF9kYXlfb2Zfd2VlayAgIC0gZGXFiCB2IHTDvcW+ZG5pCiMgY3Jhc2hfbW9udGggICAgICAgICAtIG1lc2lhYyBuZWhvZHkKdWRhamUuc3ViIDwtIHVkYWplWywgYygiaW5qdXJpZXNfdG90YWwiLAogICAgICAgICAgICAgICAgICAgICAgICJudW1fdW5pdHMiLAogICAgICAgICAgICAgICAgICAgICAgICJjcmFzaF9ob3VyIiwKICAgICAgICAgICAgICAgICAgICAgICAiY3Jhc2hfZGF5X29mX3dlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICJjcmFzaF9tb250aCIpXQoKIyBOYWhyYWRlbmllIGNow71iYWrDumNpY2ggaG9kbsO0dCBtZWRpw6Fub20gdiBrYcW+ZG9tIHN0xLpwY2kKY29sdW1uX21lZGlhbnMgPC0gc2FwcGx5KHVkYWplLnN1YiwgbWVkaWFuLCBuYS5ybSA9IFRSVUUpCgp1ZGFqZV9pbXB1dGVkIDwtIHVkYWplLnN1Ygpmb3IgKGNvbCBpbiBuYW1lcyh1ZGFqZS5zdWIpKSB7CiAgdWRhamVfaW1wdXRlZFtbY29sXV1baXMubmEodWRhamVfaW1wdXRlZFtbY29sXV0pXSA8LSBjb2x1bW5fbWVkaWFuc1tjb2xdCn0KCnVkYWplLnN1YiA8LSB1ZGFqZV9pbXB1dGVkCgpgYGAKCi4KCmBgYHtyfQojIFR2YXIgw7pkYWpvdiDigJMgYm94cGxvdHkgcHJlIGthxb5kw7ogcHJlbWVubsO6CgojIEtvxL5rbyBwcmVtZW5uw71jaCBtw6FtZQpudW1fcGxvdHMgPC0gbGVuZ3RoKG5hbWVzKHVkYWplLnN1YikpCgojIFJvemxvxb5lbmllIGdyYWZvdjogMiByaWFka3kgw5cgMyBzdMS6cGNlCnBhcihtZnJvdyA9IGMoMiwgMykpCnBhcihtYXIgPSBjKDQsIDQsIDIsIDEpKSAgIyBva3JhamUgZ3JhZm92CgojIEJveHBsb3QgcHJlIGthxb5kw70gc3TEunBlYwpmb3IgKGNvbCBpbiBuYW1lcyh1ZGFqZS5zdWIpKSB7CiAgYm94cGxvdCh1ZGFqZS5zdWJbW2NvbF1dLAogICAgICAgICAgbWFpbiA9IGNvbCwgICAgICMgTsOBWk9WIFBSRU1FTk5FSgogICAgICAgICAgeGxhYiA9ICIiLAogICAgICAgICAgY29sID0gImxpZ2h0Ymx1ZSIpCn0KCiMgU3BvbG/EjW7DvSBuYWRwaXMKbXRleHQoIkJveHBsb3R5IGplZG5vdGxpdsO9Y2ggcHJlbWVubsO9Y2giLCBvdXRlciA9IFRSVUUsIGNleCA9IDEuNCwgZm9udCA9IDIpCgojIFJlc2V0IHJvemxvxb5lbmlhCnBhcihtZnJvdyA9IGMoMSwgMSkpCmBgYAojIyBMaW5lw6FybmEgcmVncmVzaWEKCkNpZcS+b20gamUgYW5hbHl6b3ZhxaUgZmFrdG9yeSwga3RvcsOpIG92cGx5dsWIdWrDuiBwb8SNZXQgenJhbmVuw71jaCBwcmkgZG9wcmF2bmVqIG5laG9kZSAoYGluanVyaWVzX3RvdGFsYCkuIEFrbyB2eXN2ZXTEvnVqw7pjZSBwcmVtZW5uw6kgc21lIHp2b2xpbGk6CgotIGBudW1fdW5pdHNgIOKAkyBwb8SNZXQgdm96aWRpZWwgemFwb2plbsO9Y2ggZG8gbmVob2R5LAotIGBjcmFzaF9ob3VyYCDigJMgaG9kaW5hLCB2IGt0b3JlaiBzYSBuZWhvZGEgc3RhbGEsCi0gYGNyYXNoX2RheV9vZl93ZWVrYCDigJMgZGXFiCB2IHTDvcW+ZG5pLAotIGBjcmFzaF9tb250aGAg4oCTIG1lc2lhYyBuZWhvZHkuCgpNb2RlbCBqZSBvZGhhZG51dMO9IHBvbW9jb3UgcHLDrWthenUgYGxtKClgOgoKYGBge3J9Cm1vZGVsIDwtIGxtKGluanVyaWVzX3RvdGFsIH4gbnVtX3VuaXRzICsgY3Jhc2hfaG91ciArIGNyYXNoX2RheV9vZl93ZWVrICsgY3Jhc2hfbW9udGgsCiAgICAgICAgICAgIGRhdGEgPSB1ZGFqZS5zdWIpCnN1bW1hcnkobW9kZWwpCgoKYGBgCk9iamVrdCB0cmllZHkgYGxtKClgIHBvIG9kaGFkbnV0w60gbW9kZWx1IHBvc2t5dHVqZSB2aWFjZXJvIHXFvml0b8SNbsO9Y2gga29tcG9uZW50b3Y6CgoxLiAqKk9kaGFkbnV0w6kga29lZmljaWVudHkqKiAoYG1vZGVsJGNvZWZmaWNpZW50c2ApLCBrdG9yw6kgdWthenVqw7ogdnBseXYgamVkbm90bGl2w71jaCB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoIG5hIHZ5c3ZldMS+b3ZhbsO6IHByZW1lbm7DuiAoYGluanVyaWVzX3RvdGFsYCkuCjIuICoqUmV6w61kdcOhKiogKGBtb2RlbCRyZXNpZHVhbHNgKSwgdGVkYSByb3pkaWVseSBtZWR6aSBza3V0b8SNbsO9bWkgaG9kbm90YW1pIGEgaG9kbm90YW1pIHByZWRwb3ZlZGFuw71taSBtb2RlbG9tLgozLiAqKlZ5cm92bmFuw6kgaG9kbm90eSoqIChgbW9kZWwkZml0dGVkLnZhbHVlc2ApLCDEjW8gc8O6IHByZWRpa292YW7DqSBob2Rub3R5IHBvxI10dSB6cmFuZW7DvWNoIHBvZMS+YSBtb2RlbHUuCjQuICoqTWF0aWN1IHZ5c3ZldMS+dWrDumNpY2ggcHJlbWVubsO9Y2ggWCoqIChgbW9kZWwubWF0cml4KG1vZGVsKWApLCBrdG9yw6Egb2JzYWh1amUgdsWhZXRreSBwcmVtZW5uw6kgemFocm51dMOpIHYgbW9kZWxpIHYgbnVtZXJpY2tlaiBwb2RvYmUuCgpLZcSPxb5lIHbFoWV0a3kgdGlldG8gaW5mb3Jtw6FjaWUgc8O6IG9ic2lhaG51dMOpIGFqIHYgcHLDrWthemUgYHN1bW1hcnkobW9kZWwpYCwgcHJlaMS+YWQgesOha2xhZG7DvWNoIHbDvXNsZWRrb3YgesOtc2thbWUgamVobyBwb3XFvml0w61tOgoKYGBge3J9CnN1bW1hcnkobW9kZWwpCgpgYGAKCiMjIERpYWdub3N0aWthIHJlZ3Jlc27DqWhvIG1vZGVsdQoKU8O6aHJuIG9kaGFkbnV0w6lobyBtb2RlbHUgbsOhbSBwb3NreXR1amUgc8O6Ym9yIG9kaGFkbnV0w71jaCByZWdyZXNuw71jaCBrb2VmaWNpZW50b3YsIGt0b3LDvWNoIHpuYW1pZW5rYSBidWTDuiByb3pvYmVyYW7DqSBuZXNrw7RyLiBBayBjaGNlbWUgcG9zw7pkacWlIHZsYXN0bm9zdGkgbW9kZWx1IGFrbyBjZWxrdSwgbXVzw61tZSBza29udHJvbG92YcWlLCDEjWkgc3DEusWIYSB6w6FrbGFkbsOpIHByZWRwb2tsYWR5IGxpbmXDoXJuZWogcmVncmVzaWUuIE5hIHRlbnRvIMO6xI1lbCBzbMO6xb5pYSBkaWFnbm9zdGlja8OpIGdyYWZ5LiBOYSB6w6FrbGFkZSBR4oCTUSBncmFmdSBtw7TFvmVtZSBwb3PDumRpxaUgbm9ybWFsaXR1IHJlesOtZHXDrSwgemF0aWHEviDEjW8gb3N0YXRuw6kgZ3JhZnkgcG9za3l0dWrDuiBpbmZvcm3DoWNpZSBvIGhldGVyb3NrZWRhc3RpY2l0ZSwgbGluZWFyaXRlIGEgcHLDrXBhZG7DvWNoIHZwbHl2bsO9Y2ggcG96b3JvdmFuaWFjaC4KCmBgYHtyIGRpYWdwbG90cywgZmlnLmNhcD0iRGlhZ25vc3RpY2vDqSBncmFmeSByZWdyZXNuw6lobyBtb2RlbHUifQpwYXIobWFyID0gYyg0LCA0LCAyLCAxKSkKcGFyKG1mcm93ID0gYygyLCAyKSkKcGxvdChtb2RlbCkKcGFyKG1mcm93ID0gYygxLCAxKSkKYGBgCgojIyMgUG9kcm9ibsOhIGludGVycHJldMOhY2lhIGRpYWdub3N0aWNrw71jaCBncmFmb3YKCiMjIyMgMS4gUmVzaWR1YWxzIHZzIEZpdHRlZApUZW50byBncmFmIHVrYXp1amUsIMSNaSBzYSBtb2RlbCB2aG9kbmUgcHJpc3DDtHNvYmlsIMO6ZGFqb20gYSDEjWkgc8O6IHNwbG5lbsOpIHByZWRwb2tsYWR5IGxpbmVhcml0eSBhIGtvbsWhdGFudG7DqWhvIHJvenB0eWx1IHJlesOtZHXDrS4gUmV6w61kdcOhIG9zY2lsdWrDuiBva29sbyBudWx5IGJleiBqYXNuw6lobyB0dmFydSwgxI1vIG5hem5hxI11amUsIMW+ZSB2esWlYWggbWVkemkgdnlzdmV0xL51asO6Y2ltaSBwcmVtZW5uw71taSBhIHBvxI10b20genJhbmVuw71jaCBqZSBwcmlibGnFvm5lIGxpbmXDoXJueS4gTWllcm5lIHpha3JpdmVuaWUgaGxhZGtlaiDEjWVydmVuZWogxI1pYXJ5IG3DtMW+ZSBuYXpuYcSNb3ZhxaUgZXhpc3RlbmNpdSB1csSNaXRlaiBuZWxpbmVhcml0eSwgbm8gbmVqZGUgbyB2w71yYXpueSBwcm9ibMOpbS4gUm96cHR5bCByZXrDrWR1w60gc2EgamF2w60gYWtvIHJlbGF0w612bmUgcm92bm9tZXJuw70sIHRha8W+ZSBzYSBuZXByZWphdnVqZSBoZXRlcm9za2VkYXN0aWNpdGEgKG5lcm92bmFrb3PFpSByb3pwdHlsdSkuIE5pZWtvxL5rbyBib2RvdiDEj2FsZWogb2Qgb3N0YXRuw71jaCBtw7TFvmUgcHJlZHN0YXZvdmHFpSBvZMS+YWhsw6kgcG96b3JvdmFuaWEsIGt0b3LDqSBqZSB2aG9kbsOpIMSPYWxlaiBwcmVza8O6bWHFpS4KCiMjIyMgMi4gTm9ybWFsIFHigJNRIFBsb3QKTm9ybWFsIFHigJNRIGdyYWYgcG9yb3Zuw6F2YSByb3pkZWxlbmllIHJlesOtZHXDrSBzIHRlb3JldGlja8O9bSBub3Jtw6FsbnltIHJvemRlbGVuw61tLiBWw6TEjcWhaW5hIGJvZG92IGxlxb7DrSBibMOtemtvIHJlZmVyZW7EjW5laiBwcmlhbWt5LCDEjW8gbmF6bmHEjXVqZSwgxb5lIHJlesOtZHXDoSBzw7ogcHJpYmxpxb5uZSBub3Jtw6FsbmUgcm96bG/FvmVuw6kuIE1pZXJuZSBvZGNow71sa3kgbmEga29uY29jaCBncmFmdSBzw7ogYmXFvm7DqSBhIHp2ecSNYWpuZSBuZXByZWRzdGF2dWrDuiB2w6HFvm55IHByb2Jsw6ltLiBUaWV0byBvZGNow71sa3kgbcO0xb51IHNpZ25hbGl6b3ZhxaUgcHLDrXRvbW5vc8WlIGV4dHLDqW1ueWNoIGhvZG7DtHQgYWxlYm8gxaVhxb7FocOtY2ggY2h2b3N0b3Ygcm96ZGVsZW5pYSwgbm8gY2Vsa292w70gdHZhciBwb3R2cmR6dWplLCDFvmUgcHJlZHBva2xhZCBub3JtYWxpdHkgamUgcHJpamF0ZcS+bmUgc3BsbmVuw70uCgojIyMjIDMuIFNjYWxl4oCTTG9jYXRpb24gUGxvdApTY2FsZeKAk0xvY2F0aW9uIGdyYWYgKFNwcmVhZOKAk0xvY2F0aW9uKSBob2Rub3TDrSwgxI1pIGplIHZhcmlhYmlsaXRhIHJlesOtZHXDrSBrb27FoXRhbnRuw6EgbmFwcmllxI0gcHJlZGlrb3ZhbsO9bWkgaG9kbm90YW1pLiBWIG5hxaFvbSBwcsOtcGFkZSBqZSByb3psb8W+ZW5pZSBib2RvdiBwb21lcm5lIHJvdm5vbWVybsOpIGEgxI1lcnZlbsOhIExPRVNTIGtyaXZrYSBqZSByZWxhdMOtdm5lIHBsb2Now6EuIFRvIG5hem5hxI11amUsIMW+ZSBwcmVkcG9rbGFkIGhvbW9za2VkYXN0aWNpdHkgamUgc3BsbmVuw70g4oCTIHJvenB0eWwgcmV6w61kdcOtIHNhIHbDvXJhem5lIG5lbWVuw60gcyDDunJvdsWIb3UgcHJlZHBvdmVkw60uIE5pZWtvxL5rbyBib2RvdiBtaWVybmUgb2Rza2/EjWVuw71jaCBvZCBvc3RhdG7DvWNoIG3DtMW+ZSBwcmVkc3Rhdm92YcWlIG1lbsWhaWUgb2TEvmFobG9zdGksIGFsZSBuZWpkZSBvIG5pxI0ga3JpdGlja8OpLgoKIyMjIyA0LiBSZXNpZHVhbHMgdnMgTGV2ZXJhZ2UKR3JhZiBSZXrDrWR1w6EgdnMuIFDDoWtvdsO9IGVmZWt0IHBvbcOhaGEgaWRlbnRpZmlrb3ZhxaUgcG96b3JvdmFuaWEsIGt0b3LDqSBieSBtb2hsaSBtYcWlIHbDvXJhem7DvSB2cGx5diBuYSB2w71zbGVka3kgcmVncmVzaWUuIFbDpMSNxaFpbmEgcG96b3JvdmFuw60gbcOhIG7DrXpreSBww6Frb3bDvSBlZmVrdCBhIG5hY2jDoWR6YSBzYSB2IGJlenBlxI1uZWogb2JsYXN0aSBtaW1vIGtvbnTDunIgQ29va292ZWogdnpkaWFsZW5vc3RpLiBKZWRubyBhxb4gZHZlIHBvem9yb3ZhbmlhIHNhIHPDrWNlIG5hY2jDoWR6YWrDuiBibGnFvsWhaWUga3Uga29udMO6cmFtLCBhbGUgbmVwcmVzYWh1asO6IGtyaXRpY2vDqSBocmFuaWNlLiBUbyB6bmFtZW7DoSwgxb5lIMW+aWFkbmUgcG96b3JvdmFuaWUgcHJhdmRlcG9kb2JuZSBuZW92cGx5dsWIdWplIG1vZGVsIG5lcHJpbWVyYW5lLiBKZSB2xaFhayB2aG9kbsOpIHRpZXRvIHByw61wYWR5IHBvem9yb3ZhxaUgcHJpIMSPYWzFoWVqIGFuYWzDvXplLgoKCmBgYHtyfQojIFRlc3Qgbm9ybWFsaXR5IHJlesOtZHXDrQpyZXNpZHVhbHMgPC0gcmVzaWR1YWxzKG1vZGVsKQpqYl90ZXN0IDwtIGphcnF1ZS5iZXJhLnRlc3QocmVzaWR1YWxzKQpqYl90ZXN0CgojIFRlc3Qgb2TEvmFobMO9Y2ggcG96b3JvdmFuw60gKEJvbmZlcnJvbmkpCm91dGxpZXJfdGVzdCA8LSBvdXRsaWVyVGVzdChtb2RlbCkKb3V0bGllcl90ZXN0CgpgYGAKS2XEj8W+ZSB0ZXN0IG5vcm1hbGl0eSBuYXpuYcSNaWwgbW/Fvm7DqSBvZGNow71sa3kgb2Qgbm9ybcOhbG5laG8gcm96ZGVsZW5pYSByZXrDrWR1w60gYSB2IMO6ZGFqb2NoIHNhIG3DtMW+dSBuYWNow6FkemHFpSBvZMS+YWhsw6kgcG96b3JvdmFuaWEsIHBva8O6c2ltZSBzYSB0aWV0byB2cGx5dnkgem1pZXJuacWlIHRyYW5zZm9ybcOhY2lvdSB2eXN2ZXTEvm92YW5laiBwcmVtZW5uZWogKmluanVyaWVzX3RvdGFsKi4gTmEgdGVudG8gw7rEjWVsIHBvdcW+aWplbWUgbG9nYXJpdG1pY2vDuiB0cmFuc2Zvcm3DoWNpdSBwb8SNdHUgenJhbmVuw71jaCwga3RvcsOhIMSNYXN0byBwb23DoWhhIHN0YWJpbGl6b3ZhxaUgdmFyaWFuY2l1IGEgem5pxb5vdmHFpSB2cGx5diBleHRyw6ltbnljaCBob2Ruw7R0LiAKCgoKIyMgTm92w6EgcmVncmVzaWEKCktlxI/FvmUgdGVzdHkgbmF6bmHEjWlsaSBwb3J1xaFlbmllIG5vcm1hbGl0eSByZXrDrWR1w60gdiBww7R2b2Rub20gbW9kZWxpLCBwb2vDunNpbWUgc2EgbW9kZWwgdXByYXZpxaUgdHJhbnNmb3Jtw6FjaW91IHZ5c3ZldMS+b3ZhbmVqIHByZW1lbm5lai4gUG/EjWV0IHpyYW5lbsO9Y2ggcHJpIG5laG9kZSB0cmFuc2Zvcm11amVtZSBwb21vY291IGxvZ2FyaXRtdSwgxI3DrW0gem7DrcW+aW1lIHZwbHl2IGV4dHLDqW1ueWNoIGhvZG7DtHQuCgpgYGB7cn0KdWRhamUuc3ViJGxvZ19pbmp1cmllcyA8LSBsb2codWRhamUuc3ViJGluanVyaWVzX3RvdGFsICsgMSkKCm1vZGVsMiA8LSBsbSgKICBsb2dfaW5qdXJpZXMgfiBudW1fdW5pdHMgKyBjcmFzaF9ob3VyICsgY3Jhc2hfZGF5X29mX3dlZWsgKyBjcmFzaF9tb250aCwKICBkYXRhID0gdWRhamUuc3ViCikKc3VtbWFyeShtb2RlbDIpCgoKYGBgCgoKCmBgYHtyIGRpYWdwbG90czIsIGZpZy5jYXA9IkRpYWdub3N0aWNrw6kgZ3JhZnkgcmVncmVzbsOpaG8gbW9kZWx1In0KIyBOYXN0YXZpxaUgcm96bG/FvmVuaWUgMiB4IDIKcGFyKG1mcm93ID0gYygyLCAyKSkKCiMgVnlrcmVzbGnFpSB2xaFldGt5IDQgZGlhZ25vc3RpY2vDqSBncmFmeSBtb2RlbHUKcGxvdChtb2RlbDIpCgojIChWb2xpdGXEvm7DqSkgcHJpZGHFpSBzcG9sb8SNbsO9IG5hZHBpcwojbXRleHQoIkRpYWdub3N0aWNrw6kgZ3JhZnkgcmVncmVzbsOpaG8gbW9kZWx1Iiwgb3V0ZXIgPSBUUlVFLCBjZXggPSAxLjIsIGZvbnQgPSAyKQoKIyBSZXNldG92YcWlIGxheW91dApwYXIobWZyb3cgPSBjKDEsIDEpKQpgYGAKCgoKIyMgQ29uY2x1c2lvbgoKQ2llxL5vbSBhbmFsw716eSBib2xvIHByZXNrw7ptYcWlIGZha3Rvcnkgb3ZwbHl2xYh1asO6Y2UgcG/EjWV0IHpyYW5lbsO9Y2ggcHJpIGRvcHJhdm7DvWNoIG5laG9kw6FjaCBwb21vY291IGxpbmXDoXJuZWogcmVncmVzaWUuIEFrbyB2eXN2ZXTEvnVqw7pjZSBwcmVtZW5uw6kgc21lIHBvdcW+aWxpIHBvxI1ldCB6YXBvamVuw71jaCB2b3ppZGllbCAoKm51bV91bml0cyopLCBob2RpbnUgbmVob2R5ICgqY3Jhc2hfaG91ciopLCBkZcWIIHYgdMO9xb5kbmkgKCpjcmFzaF9kYXlfb2Zfd2VlayopIGEgbWVzaWFjIG5laG9keSAoKmNyYXNoX21vbnRoKikuCgpWw71zbGVka3kgcmVncmVzbsOpaG8gbW9kZWx1IG5hem5hxI11asO6LCDFvmUgcG/EjWV0IHphcG9qZW7DvWNoIHZvemlkaWVsIG3DoSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSB2cGx5diBuYSBwb8SNZXQgenJhbmVuw71jaCwgxI1vIGplIHYgc8O6bGFkZSBzIG/EjWFrw6F2YW5pYW1pIOKAkyBuZWhvZHkgcyB2ecWhxaHDrW0gcG/EjXRvbSB2b3ppZGllbCBtYWrDuiBzcHJhdmlkbGEgesOhdmHFvm5lasWhaWUgbsOhc2xlZGt5LiBPc3RhdG7DqSDEjWFzb3bDqSBwcmVtZW5uw6kgemFjaHl0w6F2YWrDuiBwcmF2aWRlbG5vc3RpIHYgZG9wcmF2bmVqIG5laG9kb3Zvc3RpLCBrdG9yw6kgbcO0xb51IHPDunZpc2llxaUgcyBpbnRlbnppdG91IHByZW3DoXZreSBwb8SNYXMgZMWIYSwgdMO9xb5kxYhhIGFsZWJvIHJva2EuCgpEaWFnbm9zdGlja8OpIGdyYWZ5IGEgZm9ybcOhbG5lIHRlc3R5IHBvdWvDoXphbGkgbmEgbW/Fvm7DqSBvZGNow71sa3kgb2QgcHJlZHBva2xhZHUgbm9ybWFsaXR5IHJlesOtZHXDrS4gWiB0b2h0byBkw7R2b2R1IHNtZSBwcmlzdMO6cGlsaSBrIGxvZ2FyaXRtaWNrZWogdHJhbnNmb3Jtw6FjaWkgdnlzdmV0xL5vdmFuZWogcHJlbWVubmVqICppbmp1cmllc190b3RhbCosIMSNw61tIHNtZSB6bsOtxb5pbGkgdnBseXYgZXh0csOpbW55Y2ggaG9kbsO0dCBhIHN0YWJpbGl6b3ZhbGkgdmFyaWFuY2l1IHJlesOtZHXDrS4gTm92w70gcmVncmVzbsO9IG1vZGVsIHZ5a2F6dWplIHByaWF6bml2ZWrFoWllIGRpYWdub3N0aWNrw6kgdmxhc3Rub3N0aSBhIGplIHZob2RuZWrFocOtIG5hIGludGVycHJldMOhY2l1IHZ6xaVhaG92IHYgZMOhdGFjaC4KCkNlbGtvdm8gbW/Fvm5vIGtvbsWhdGF0b3ZhxaUsIMW+ZSBwb3XFvml0w70gcmVncmVzbsO9IHByw61zdHVwIHBvc2t5dHVqZSB6bXlzbHVwbG7DvSBwb2jEvmFkIG5hIGZha3Rvcnkgb3ZwbHl2xYh1asO6Y2UgcG/EjWV0IHpyYW5lbsO9Y2ggcHJpIGRvcHJhdm7DvWNoIG5laG9kw6FjaCwgcHJpxI1vbSB2w71zbGVka3kgbcO0xb51IHNsw7rFvmnFpSBha28gcG9ka2xhZCBwcmUgxI9hbMWhaXUgYW5hbMO9enUgZG9wcmF2bmVqIGJlenBlxI1ub3N0aS4KCgo=