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

Úvod do problému, stanovenie hypotéz

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

Pracovná hypotéza:

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

Údaje sú uložené v súbore .csv, stĺpce sú oddelené čiarkou (,) a používajú desatinnú bodku (.).

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:

  1. Odhadnuté koeficienty (model$coefficients), ktoré ukazujú vplyv jednotlivých vysvetľujúcich premenných na vysvetľovanú premennú (injuries_total).
  2. Rezíduá (model$residuals), teda rozdiely medzi skutočnými hodnotami a hodnotami predpovedanými modelom.
  3. Vyrovnané hodnoty (model$fitted.values), čo sú predikované hodnoty počtu zranených podľa modelu.
  4. 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=