Úvod do problému, stanovenie hypotéz
Rozhodla som sa modelovať počet obetí dopravných nehôd (Victims) v
závislosti od troch vysvetľujúcich premenných: počtu ľahko zranených
osôb (Mild.injuries), počtu ťažko zranených osôb (Serious.injuries) a
počtu zapojených vozidiel (Vehicles.involved). Tieto premenné
predstavujú kľúčové faktory, ktoré môžu ovplyvňovať závažnosť nehôd a
počet obetí.
Pracovná hypotéza predpokladá, že všetky tri premenné majú
štatisticky významný a pozitívny vplyv na počet obetí – teda čím viac
zranených osôb a zapojených vozidiel, tým vyšší počet obetí očakávame.
Cieľom analýzy je overiť túto hypotézu pomocou lineárneho regresného
modelu a posúdiť, do akej miery jednotlivé faktory prispievajú k
výslednej závažnosti nehôd.
Príprava databázy, čistenie a úprava údajov
udaje <- read.csv("barc_data.csv", sep=";", dec=",", header = TRUE)
head(udaje)
udaje <- udaje[-27,]
udaje <- udaje[-2,]
[1] "Id" "District.Name_prek." "District.Name"
[4] "Neighborhood.Name" "Street" "Weekday_prek."
[7] "Weekday" "Date" "Mesiace"
[10] "Part.of.the.day_prek." "Part.of.the.day" "Hour"
[13] "Mild.injuries" "Serious.injuries" "Victims"
[16] "Vehicles.involved" "Longitude" "Latitude"
[19] "Hour.1"
udaje_2017 <- udaje[, c("Mild.injuries", "Serious.injuries", "Victims", "Vehicles.involved")]
median_hodnoty <- sapply(udaje_2017, median, na.rm = TRUE)
udaje_imputed <- udaje_2017
for (col in names(udaje_2017)) {
udaje_imputed[[col]][is.na(udaje_2017[[col]])] <- median_hodnoty[col]
}
udaje_2017 <- udaje_imputed
num_plots <- length(names(udaje_2017))
par(mfrow = c(2, 2))
par(mar = c(4, 4, 2, 1)) # Adjust margins (optional)
for (col in names(udaje_2017)) {
boxplot(udaje_2017[[col]], main = col, xlab = "Value", col = "lightpink")
}
mtext("Boxploty jednotlivých premenných (2017)", outer = TRUE, cex = 1.4, font = 2)

Lineárna regresia
model <- lm(Victims ~ +1 + Mild.injuries + Serious.injuries + Vehicles.involved, data = udaje_2017)
#print("Odhadnuté koeficienty sú: ")
# print(model$coefficients)
#print("Odhadnuté rezíduá: ")
#print(model$residuals)
#print("Vyrovnané hodnoty vysvetľovanej premennej sú: ")
#print(model$fitted.values)
#print("matica model$xlevels: ")
#print(model.matrix(model))
#X <- model.matrix(model)
#diag(X %*% solve(t(X) %*% X) %*% t(X))
summary(model)
Call:
lm(formula = Victims ~ +1 + Mild.injuries + Serious.injuries +
Vehicles.involved, data = udaje_2017)
Residuals:
Min 1Q Median 3Q Max
-2.614e-15 -1.715e-17 4.005e-17 9.205e-17 7.486e-16
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.000e+00 1.974e-16 0.000e+00 1.00
Mild.injuries 1.000e+00 5.901e-17 1.695e+16 <2e-16 ***
Serious.injuries 1.000e+00 1.173e-16 8.523e+15 <2e-16 ***
Vehicles.involved -5.807e-17 1.016e-16 -5.710e-01 0.57
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 3.847e-16 on 54 degrees of freedom
Multiple R-squared: 1, Adjusted R-squared: 1
F-statistic: 1.176e+32 on 3 and 54 DF, p-value: < 2.2e-16
par(mfrow = c(2, 2))
plot(model)
mtext("Diagnostické grafy regresného modelu", outer = TRUE, cex = 1.2, font = 2)

Residuals vs. fitted
Interpretácia vášho konkrétneho grafu
Graf ukazuje, že väčšina reziduí sa drží blízko nulovej osi, čo
naznačuje, že model nepredpovedá systematicky zle. Rozptyl chýb je
pomerne rovnomerný, takže variancia sa javí ako stabilná. Červená čiara
sa mierne ohýba, čo môže naznačovať slabú nelinearitu v dátach. Niektoré
body sú ďalej od ostatných, ale nevyzerajú extrémne. Ich správanie
nenaznačuje, že by výrazne ovplyvňovali výsledky. Môžu byť len
prirodzenou súčasťou variability v dátach.
Q-Q plot
Čo ukazuje
Q-Q graf ukazuje, že rozdelenie reziduí je vo všeobecnosti blízke
normálnemu. Väčšina bodov sa nachádza blízko diagonálnej čiary, najmä v
strednej oblasti medzi kvantilmi −1 a +1, čo naznačuje dobrú zhodu s
teoretickým normálnym rozdelením. Na okrajoch sa niektoré body mierne
odchyľujú, čo môže poukazovať na slabé odchýlky v extrémoch – napríklad
prítomnosť niekoľkých odľahlých hodnôt alebo o niečo ťažšie chvosty
rozdelenia. Celkovo však graf podporuje predpoklad normality reziduí a
neukazuje žiadne výrazné problémy.
Scale location plot
Scale-Location graf naznačuje, že rozptyl reziduí je približne
konštantný pri rôznych predikovaných hodnotách. Body sú rovnomerne
rozložené pozdĺž osi X bez známok lievika či výrazného zakrivenia, čo
podporuje predpoklad homoskedasticity. Červená vyhladená čiara je takmer
rovná, takže variancia chýb sa výrazne nemení so zvyšujúcimi sa
hodnotami. Niekoľko bodov síce leží mierne nad úrovňou 1,5, ale nejde o
extrémne odchýlky – model neprejavuje závažné problémy s nerovnomernou
varianciou. Celkovo graf potvrdzuje, že rozptyl chýb je stabilný.
residuals vs leverage
Residuals vs Leverage graf ukazuje, že väčšina pozorovaní má nízky
pákový efekt a štandardizované reziduá sa pohybujú v rozmedzí približne
−2 až +2, čo je dobré znamenie. Niekoľko bodov má vyššiu páku (napr.
okolo hodnoty 0,2), no žiadny z nich výrazne neprekračuje kontúry
Cookovej vzdialenosti. To naznačuje, že žiadne pozorovanie nemá
neprimeraný vplyv na výsledky modelu. Celkovo graf nepoukazuje na
závažné problémy s vplyvnými bodmi.
residuals <- residuals(model)
jb_test <- jarque.bera.test(residuals)
jb_test
Jarque Bera Test
data: residuals
X-squared = 4152.9, df = 2, p-value < 2.2e-16
outlier_test <- outlierTest(model)
outlier_test
Heteroskedasticita
Heteroskedasticita znamená, že rozptyl náhodnej zložky nie je
konštantný, čo môže viesť k nespoľahlivým výsledkom t-testov pri
hodnotení významnosti regresných koeficientov. Preto je dôležité
heteroskedasticitu najprv zistiť, a ak sa v modeli vyskytuje, pokúsiť sa
ju odstrániť. V našom prípade sa zameriame na grafické znázornenie
štvorcov rezíduí vo vzťahu k vysvetľujúcim premenným, ktoré by mohli
heteroskedasticitu spôsobovať. Porovnávame dva modely – pôvodný model
(model) a upravený model (model2), v ktorom je premenná
Vehicles.involved logaritmicky transformovaná s cieľom znížiť vplyv
odľahlých hodnôt a možnú heteroskedasticitu.
library(ggplot2)
library(patchwork)
# Načítanie údajov
barc_data <- read.csv("barc_data.csv", sep=";", encoding = "latin1")
# Lineárny model: počet obetí (Victims) ~ počet zapojených vozidiel + časť dňa
model <- lm(Victims ~ Vehicles.involved + Mild.injuries, data = barc_data)
# Skúmanie heteroskedasticity pomocou štvorcov reziduí
p1 <- ggplot(barc_data, aes(x = Vehicles.involved, y = resid(model)^2)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "loess", se = FALSE, color = "lightpink") +
labs(x = "Počet zapojených vozidiel",
y = "Štvorce reziduí",
title = "Štvorce reziduí vs Počet vozidiel") +
theme_minimal()
p2 <- ggplot(barc_data, aes(x = Mild.injuries, y = resid(model)^2)) +
geom_jitter(width = 0.2, alpha = 0.6) +
geom_boxplot(alpha = 0.2, color = "lightpink", outlier.shape = NA) +
labs(x = "Počet ľahkých zranení",
y = "Štvorce reziduí",
title = "Štvorce reziduí vs Počet ľahkých zranení") +
theme_minimal()
# Spojenie grafov vedľa seba
p1 + p2

Na grafoch Štvorce reziduí vs Počet vozidiel a Štvorce reziduí vs
Počet ľahkých zranení môžeme pozorovať, že ružová vyhladená krivka
zostáva relatívne plochá a rozptyl reziduí sa s hodnotami premenných
výrazne nemení. Menšie kolísanie naznačuje len slabé náznaky
heteroskedasticity, ktoré však nie sú výrazné. Celkovo možno teda
usúdiť, že v modeli sa heteroskedasticita výrazne nevyskytuje a rozptyl
náhodnej zložky zostáva približne konštantný.
a teraz model so zlogaritmizovanou premennou
Vehicles.involved.
library(ggplot2)
library(patchwork) # install.packages("patchwork")
# Načítanie údajov
barc_data <- read.csv("barc_data.csv", encoding = "latin1", sep = ";")
# Lineárny model č.2: počet obetí podľa počtu vozidiel a miernych zranení
model2 <- lm(Victims ~ Vehicles.involved + Mild.injuries, data = barc_data)
# Graf 1 – log(počet vozidiel) vs štvorce reziduí
p1 <- ggplot(barc_data, aes(x = log(Vehicles.involved + 1), y = resid(model2)^2)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "loess", se = FALSE, color = "lightpink") +
labs(x = "log(Počet zapojených vozidiel)",
y = "Štvorce reziduí",
title = "Reziduá vs log(Počet vozidiel)") +
theme_minimal()
# Graf 2 – mierne zranenia vs štvorce reziduí
p2 <- ggplot(barc_data, aes(x = Mild.injuries, y = resid(model2)^2)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "loess", se = FALSE, color = "lightpink") +
labs(x = "Mierne zranenia",
y = "Štvorce reziduí",
title = "Reziduá vs Mierne zranenia") +
theme_minimal()
# Spojenie grafov vedľa seba
p1 + p2

Po logaritmickej transformácii premennej Počet zapojených vozidiel sa
ružová krivka vyrovnala a rozptyl reziduí sa stal rovnomernejším, čo
naznačuje, že transformácia znížila heteroskedasticitu. Premenná Mierne
zranenia nevykazuje viditeľné známky heteroskedasticity, takže celkovo
možno povedať, že nový model má stabilnejší rozptyl reziduí a lepšiu
štruktúru ako pôvodný.
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 = 1.04, df = 2, p-value = 0.5945
# 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 = 1.04, df = 2, p-value = 0.5945
Keďže p-hodnota Breusch–Paganovho testu (0.5945) výrazne presahuje
bežnú hladinu významnosti (napr. 0.05), nezamietame nulovú hypotézu,
ktorá predpokladá homoskedasticitu – teda konštantný rozptyl rezíduí bez
systematických zmien v závislosti od vysvetľujúcich premenných.
Na základe výsledku testu možno konštatovať, že v rezíduách modelu
model2 nie je prítomná heteroskedasticita. Rozptyl sa javí ako stabilný,
a preto nie je potrebné aplikovať Whiteovu korekciu ani ďalšie úpravy
modelu.
LS0tCnRpdGxlOiAiRWNvbm9tZXRyaWNzIGluIFItIGN2acSNZW5pZSA1LTYiCmF1dGhvcjogIk1vbmlrYSBTesWxY3NvdsOhIChzIHZ5dcW+aXTDrW0gdmVyZWpuZSBkb3N0dXBuw71jaCBrw7Nkb3YgYSBDaGF0R1BUKSIKZGF0ZTogIk5vdmVtYmVyIDIwMjUiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRoZW1lOiB1bml0ZWQKICAgIGhpZ2hsaWdodDogdGFuZ28KICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKZWRpdG9yX29wdGlvbnM6CiAgbWFya2Rvd246CiAgICB3cmFwOiA3MgotLS0KCmBgYHtyfQpsaWJyYXJ5KHpvbykKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGxtdGVzdCkKbGlicmFyeShzYW5kd2ljaCkKbGlicmFyeShjYXIpCnJtKGxpc3Q9bHMoKSkKYGBgCgoKIyDDmnZvZCBkbyBwcm9ibMOpbXUsIHN0YW5vdmVuaWUgaHlwb3TDqXogCgpSb3pob2RsYSBzb20gc2EgbW9kZWxvdmHFpSBwb8SNZXQgb2JldMOtIGRvcHJhdm7DvWNoIG5laMO0ZCAoVmljdGltcykgdiB6w6F2aXNsb3N0aSBvZCB0cm9jaCB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoOiBwb8SNdHUgxL5haGtvIHpyYW5lbsO9Y2ggb3PDtGIgKE1pbGQuaW5qdXJpZXMpLCBwb8SNdHUgxaVhxb5rbyB6cmFuZW7DvWNoIG9zw7RiIChTZXJpb3VzLmluanVyaWVzKSBhIHBvxI10dSB6YXBvamVuw71jaCB2b3ppZGllbCAoVmVoaWNsZXMuaW52b2x2ZWQpLiBUaWV0byBwcmVtZW5uw6kgcHJlZHN0YXZ1asO6IGvEvsO6xI1vdsOpIGZha3RvcnksIGt0b3LDqSBtw7TFvnUgb3ZwbHl2xYhvdmHFpSB6w6F2YcW+bm9zxaUgbmVow7RkIGEgcG/EjWV0IG9iZXTDrS4KClByYWNvdm7DoSBoeXBvdMOpemEgcHJlZHBva2xhZMOhLCDFvmUgdsWhZXRreSB0cmkgcHJlbWVubsOpIG1hasO6IMWhdGF0aXN0aWNreSB2w716bmFtbsO9IGEgcG96aXTDrXZueSB2cGx5diBuYSBwb8SNZXQgb2JldMOtIOKAkyB0ZWRhIMSNw61tIHZpYWMgenJhbmVuw71jaCBvc8O0YiBhIHphcG9qZW7DvWNoIHZvemlkaWVsLCB0w71tIHZ5xaHFocOtIHBvxI1ldCBvYmV0w60gb8SNYWvDoXZhbWUuIENpZcS+b20gYW5hbMO9enkgamUgb3ZlcmnFpSB0w7p0byBoeXBvdMOpenUgcG9tb2NvdSBsaW5lw6FybmVobyByZWdyZXNuw6lobyBtb2RlbHUgYSBwb3PDumRpxaUsIGRvIGFrZWogbWllcnkgamVkbm90bGl2w6kgZmFrdG9yeSBwcmlzcGlldmFqw7ogayB2w71zbGVkbmVqIHrDoXZhxb5ub3N0aSBuZWjDtGQuCgojIFByw61wcmF2YSBkYXRhYsOhenksIMSNaXN0ZW5pZSBhIMO6cHJhdmEgw7pkYWpvdgoKCmBgYHtyfQp1ZGFqZSA8LSByZWFkLmNzdigiYmFyY19kYXRhLmNzdiIsIHNlcD0iOyIsIGRlYz0iLCIsIGhlYWRlciA9IFRSVUUpCmhlYWQodWRhamUpIAp1ZGFqZSA8LSB1ZGFqZVstMjcsXQp1ZGFqZSA8LSB1ZGFqZVstMixdCmBgYApgYGB7cn0KY29sbmFtZXModWRhamUpCmBgYApgYGB7cn0KdWRhamVfMjAxNyA8LSB1ZGFqZVssIGMoIk1pbGQuaW5qdXJpZXMiLCAiU2VyaW91cy5pbmp1cmllcyIsICJWaWN0aW1zIiwgIlZlaGljbGVzLmludm9sdmVkIildCgptZWRpYW5faG9kbm90eSA8LSBzYXBwbHkodWRhamVfMjAxNywgbWVkaWFuLCBuYS5ybSA9IFRSVUUpCgp1ZGFqZV9pbXB1dGVkIDwtIHVkYWplXzIwMTcKZm9yIChjb2wgaW4gbmFtZXModWRhamVfMjAxNykpIHsKICB1ZGFqZV9pbXB1dGVkW1tjb2xdXVtpcy5uYSh1ZGFqZV8yMDE3W1tjb2xdXSldIDwtIG1lZGlhbl9ob2Rub3R5W2NvbF0KfQoKdWRhamVfMjAxNyA8LSB1ZGFqZV9pbXB1dGVkCmBgYAoKCmBgYHtyfQpudW1fcGxvdHMgPC0gbGVuZ3RoKG5hbWVzKHVkYWplXzIwMTcpKQoKcGFyKG1mcm93ID0gYygyLCAyKSkKcGFyKG1hciA9IGMoNCwgNCwgMiwgMSkpICAjIEFkanVzdCBtYXJnaW5zIChvcHRpb25hbCkKCmZvciAoY29sIGluIG5hbWVzKHVkYWplXzIwMTcpKSB7CiAgYm94cGxvdCh1ZGFqZV8yMDE3W1tjb2xdXSwgbWFpbiA9IGNvbCwgeGxhYiA9ICJWYWx1ZSIsIGNvbCA9ICJsaWdodHBpbmsiKQp9CgptdGV4dCgiQm94cGxvdHkgamVkbm90bGl2w71jaCBwcmVtZW5uw71jaCAoMjAxNykiLCBvdXRlciA9IFRSVUUsIGNleCA9IDEuNCwgZm9udCA9IDIpCnBhcihtZnJvdyA9IGMoMSwgMSkpCmBgYAojIyBMaW5lw6FybmEgcmVncmVzaWEKCmBgYHtyfQptb2RlbCA8LSBsbShWaWN0aW1zIH4gKzEgKyBNaWxkLmluanVyaWVzICsgU2VyaW91cy5pbmp1cmllcyArIFZlaGljbGVzLmludm9sdmVkLCBkYXRhID0gdWRhamVfMjAxNykKYGBgCgoKYGBge3J9CiNwcmludCgiT2RoYWRudXTDqSBrb2VmaWNpZW50eSBzw7o6ICIpCiMgICAgICBwcmludChtb2RlbCRjb2VmZmljaWVudHMpCiNwcmludCgiT2RoYWRudXTDqSByZXrDrWR1w6E6ICIpCiNwcmludChtb2RlbCRyZXNpZHVhbHMpCiNwcmludCgiVnlyb3ZuYW7DqSBob2Rub3R5IHZ5c3ZldMS+b3ZhbmVqIHByZW1lbm5laiBzw7o6ICIpCiNwcmludChtb2RlbCRmaXR0ZWQudmFsdWVzKQojcHJpbnQoIm1hdGljYSBtb2RlbCR4bGV2ZWxzOiAiKQojcHJpbnQobW9kZWwubWF0cml4KG1vZGVsKSkKI1ggPC0gbW9kZWwubWF0cml4KG1vZGVsKQojZGlhZyhYICUqJSBzb2x2ZSh0KFgpICUqJSBYKSAlKiUgdChYKSkKCnN1bW1hcnkobW9kZWwpCmBgYAoKYGBge3IgZGlhZ3Bsb3RzLCBmaWcuY2FwPSJEaWFnbm9zdGlja8OpIGdyYWZ5IHJlZ3Jlc27DqWhvIG1vZGVsdSJ9CnBhcihtZnJvdyA9IGMoMiwgMikpCnBsb3QobW9kZWwpCm10ZXh0KCJEaWFnbm9zdGlja8OpIGdyYWZ5IHJlZ3Jlc27DqWhvIG1vZGVsdSIsIG91dGVyID0gVFJVRSwgY2V4ID0gMS4yLCBmb250ID0gMikKcGFyKG1mcm93ID0gYygxLCAxKSkKYGBgCgojIyBSZXNpZHVhbHMgdnMuIGZpdHRlZAoKIyMjIEludGVycHJldMOhY2lhIHbDocWhaG8ga29ua3LDqXRuZWhvIGdyYWZ1CgpHcmFmIHVrYXp1amUsIMW+ZSB2w6TEjcWhaW5hIHJlemlkdcOtIHNhIGRyxb7DrSBibMOtemtvIG51bG92ZWogb3NpLCDEjW8gbmF6bmHEjXVqZSwgxb5lIG1vZGVsIG5lcHJlZHBvdmVkw6Egc3lzdGVtYXRpY2t5IHpsZS4gUm96cHR5bCBjaMO9YiBqZSBwb21lcm5lIHJvdm5vbWVybsO9LCB0YWvFvmUgdmFyaWFuY2lhIHNhIGphdsOtIGFrbyBzdGFiaWxuw6EuIMSMZXJ2ZW7DoSDEjWlhcmEgc2EgbWllcm5lIG9ow71iYSwgxI1vIG3DtMW+ZSBuYXpuYcSNb3ZhxaUgc2xhYsO6IG5lbGluZWFyaXR1IHYgZMOhdGFjaC4gTmlla3RvcsOpIGJvZHkgc8O6IMSPYWxlaiBvZCBvc3RhdG7DvWNoLCBhbGUgbmV2eXplcmFqw7ogZXh0csOpbW5lLiBJY2ggc3Byw6F2YW5pZSBuZW5hem5hxI11amUsIMW+ZSBieSB2w71yYXpuZSBvdnBseXbFiG92YWxpIHbDvXNsZWRreS4gTcO0xb51IGJ5xaUgbGVuIHByaXJvZHplbm91IHPDusSNYXPFpW91IHZhcmlhYmlsaXR5IHYgZMOhdGFjaC4KCiMjIFEtUSBwbG90CgojIyMgxIxvIHVrYXp1amUKClEtUSBncmFmIHVrYXp1amUsIMW+ZSByb3pkZWxlbmllIHJlemlkdcOtIGplIHZvIHbFoWVvYmVjbm9zdGkgYmzDrXprZSBub3Jtw6FsbmVtdS4gVsOkxI3FoWluYSBib2RvdiBzYSBuYWNow6FkemEgYmzDrXprbyBkaWFnb27DoWxuZWogxI1pYXJ5LCBuYWptw6QgdiBzdHJlZG5laiBvYmxhc3RpIG1lZHppIGt2YW50aWxtaSDiiJIxIGEgKzEsIMSNbyBuYXpuYcSNdWplIGRvYnLDuiB6aG9kdSBzIHRlb3JldGlja8O9bSBub3Jtw6FsbnltIHJvemRlbGVuw61tLiBOYSBva3Jham9jaCBzYSBuaWVrdG9yw6kgYm9keSBtaWVybmUgb2RjaHnEvnVqw7osIMSNbyBtw7TFvmUgcG91a2F6b3ZhxaUgbmEgc2xhYsOpIG9kY2jDvWxreSB2IGV4dHLDqW1vY2gg4oCTIG5hcHLDrWtsYWQgcHLDrXRvbW5vc8WlIG5pZWtvxL5rw71jaCBvZMS+YWhsw71jaCBob2Ruw7R0IGFsZWJvIG8gbmllxI1vIMWlYcW+xaFpZSBjaHZvc3R5IHJvemRlbGVuaWEuIENlbGtvdm8gdsWhYWsgZ3JhZiBwb2Rwb3J1amUgcHJlZHBva2xhZCBub3JtYWxpdHkgcmV6aWR1w60gYSBuZXVrYXp1amUgxb5pYWRuZSB2w71yYXpuw6kgcHJvYmzDqW15LgoKIyMgU2NhbGUgbG9jYXRpb24gcGxvdAoKU2NhbGUtTG9jYXRpb24gZ3JhZiBuYXpuYcSNdWplLCDFvmUgcm96cHR5bCByZXppZHXDrSBqZSBwcmlibGnFvm5lIGtvbsWhdGFudG7DvSBwcmkgcsO0em55Y2ggcHJlZGlrb3ZhbsO9Y2ggaG9kbm90w6FjaC4gQm9keSBzw7ogcm92bm9tZXJuZSByb3psb8W+ZW7DqSBwb3pkxLrFviBvc2kgWCBiZXogem7DoW1vayBsaWV2aWthIMSNaSB2w71yYXpuw6lobyB6YWtyaXZlbmlhLCDEjW8gcG9kcG9ydWplIHByZWRwb2tsYWQgaG9tb3NrZWRhc3RpY2l0eS4gxIxlcnZlbsOhIHZ5aGxhZGVuw6EgxI1pYXJhIGplIHRha21lciByb3Zuw6EsIHRha8W+ZSB2YXJpYW5jaWEgY2jDvWIgc2EgdsO9cmF6bmUgbmVtZW7DrSBzbyB6dnnFoXVqw7pjaW1pIHNhIGhvZG5vdGFtaS4gTmlla2/EvmtvIGJvZG92IHPDrWNlIGxlxb7DrSBtaWVybmUgbmFkIMO6cm92xYhvdSAxLDUsIGFsZSBuZWpkZSBvIGV4dHLDqW1uZSBvZGNow71sa3kg4oCTIG1vZGVsIG5lcHJlamF2dWplIHrDoXZhxb5uw6kgcHJvYmzDqW15IHMgbmVyb3Zub21lcm5vdSB2YXJpYW5jaW91LiBDZWxrb3ZvIGdyYWYgcG90dnJkenVqZSwgxb5lIHJvenB0eWwgY2jDvWIgamUgc3RhYmlsbsO9LgoKIyMgcmVzaWR1YWxzIHZzIGxldmVyYWdlCgpSZXNpZHVhbHMgdnMgTGV2ZXJhZ2UgZ3JhZiB1a2F6dWplLCDFvmUgdsOkxI3FoWluYSBwb3pvcm92YW7DrSBtw6EgbsOtemt5IHDDoWtvdsO9IGVmZWt0IGEgxaF0YW5kYXJkaXpvdmFuw6kgcmV6aWR1w6Egc2EgcG9oeWJ1asO6IHYgcm96bWVkesOtIHByaWJsacW+bmUg4oiSMiBhxb4gKzIsIMSNbyBqZSBkb2Jyw6kgem5hbWVuaWUuIE5pZWtvxL5rbyBib2RvdiBtw6EgdnnFocWhaXUgcMOha3UgKG5hcHIuIG9rb2xvIGhvZG5vdHkgMCwyKSwgbm8gxb5pYWRueSB6IG5pY2ggdsO9cmF6bmUgbmVwcmVrcmHEjXVqZSBrb250w7pyeSBDb29rb3ZlaiB2emRpYWxlbm9zdGkuIFRvIG5hem5hxI11amUsIMW+ZSDFvmlhZG5lIHBvem9yb3ZhbmllIG5lbcOhIG5lcHJpbWVyYW7DvSB2cGx5diBuYSB2w71zbGVka3kgbW9kZWx1LiBDZWxrb3ZvIGdyYWYgbmVwb3VrYXp1amUgbmEgesOhdmHFvm7DqSBwcm9ibMOpbXkgcyB2cGx5dm7DvW1pIGJvZG1pLgoKCgpgYGB7cn0KcmVzaWR1YWxzIDwtIHJlc2lkdWFscyhtb2RlbCkKamJfdGVzdCA8LSBqYXJxdWUuYmVyYS50ZXN0KHJlc2lkdWFscykKamJfdGVzdAoKb3V0bGllcl90ZXN0IDwtIG91dGxpZXJUZXN0KG1vZGVsKQpvdXRsaWVyX3Rlc3QKYGBgCgojIyBIZXRlcm9za2VkYXN0aWNpdGEKCkhldGVyb3NrZWRhc3RpY2l0YSB6bmFtZW7DoSwgxb5lIHJvenB0eWwgbsOhaG9kbmVqIHpsb8W+a3kgbmllIGplIGtvbsWhdGFudG7DvSwgxI1vIG3DtMW+ZSB2aWVzxaUgayBuZXNwb8S+YWhsaXbDvW0gdsO9c2xlZGtvbSB0LXRlc3RvdiBwcmkgaG9kbm90ZW7DrSB2w716bmFtbm9zdGkgcmVncmVzbsO9Y2gga29lZmljaWVudG92LiBQcmV0byBqZSBkw7RsZcW+aXTDqSBoZXRlcm9za2VkYXN0aWNpdHUgbmFqcHJ2IHppc3RpxaUsIGEgYWsgc2EgdiBtb2RlbGkgdnlza3l0dWplLCBwb2vDunNpxaUgc2EganUgb2RzdHLDoW5pxaUuIFYgbmHFoW9tIHByw61wYWRlIHNhIHphbWVyaWFtZSBuYSBncmFmaWNrw6kgem7DoXpvcm5lbmllIMWhdHZvcmNvdiByZXrDrWR1w60gdm8gdnrFpWFodSBrIHZ5c3ZldMS+dWrDumNpbSBwcmVtZW5uw71tLCBrdG9yw6kgYnkgbW9obGkgaGV0ZXJvc2tlZGFzdGljaXR1IHNww7Rzb2JvdmHFpS4gUG9yb3Zuw6F2YW1lIGR2YSBtb2RlbHkg4oCTIHDDtHZvZG7DvSBtb2RlbCAobW9kZWwpIGEgdXByYXZlbsO9IG1vZGVsIChtb2RlbDIpLCB2IGt0b3JvbSBqZSBwcmVtZW5uw6EgVmVoaWNsZXMuaW52b2x2ZWQgbG9nYXJpdG1pY2t5IHRyYW5zZm9ybW92YW7DoSBzIGNpZcS+b20gem7DrcW+acWlIHZwbHl2IG9kxL5haGzDvWNoIGhvZG7DtHQgYSBtb8W+bsO6IGhldGVyb3NrZWRhc3RpY2l0dS4KCgpgYGB7ciBoZXRlcm9wbG90c19iY24sIGZpZy5jYXA9IlNrw7ptYW5pZSBoZXRlcm9za2VkYXN0aWNpdHkgbmEgw7pkYWpvY2ggbyBuZWhvZMOhY2ggdiBCYXJjZWxvbmUiLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NH0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBhdGNod29yaykKCiMgTmHEjcOtdGFuaWUgw7pkYWpvdgpiYXJjX2RhdGEgPC0gcmVhZC5jc3YoImJhcmNfZGF0YS5jc3YiLCBzZXA9IjsiLCBlbmNvZGluZyA9ICJsYXRpbjEiKQoKIyBMaW5lw6FybnkgbW9kZWw6IHBvxI1ldCBvYmV0w60gKFZpY3RpbXMpIH4gcG/EjWV0IHphcG9qZW7DvWNoIHZvemlkaWVsICsgxI1hc8WlIGTFiGEKbW9kZWwgPC0gbG0oVmljdGltcyB+IFZlaGljbGVzLmludm9sdmVkICsgTWlsZC5pbmp1cmllcywgZGF0YSA9IGJhcmNfZGF0YSkKCiMgU2vDum1hbmllIGhldGVyb3NrZWRhc3RpY2l0eSBwb21vY291IMWhdHZvcmNvdiByZXppZHXDrQpwMSA8LSBnZ3Bsb3QoYmFyY19kYXRhLCBhZXMoeCA9IFZlaGljbGVzLmludm9sdmVkLCB5ID0gcmVzaWQobW9kZWwpXjIpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gRkFMU0UsIGNvbG9yID0gImxpZ2h0cGluayIpICsKICBsYWJzKHggPSAiUG/EjWV0IHphcG9qZW7DvWNoIHZvemlkaWVsIiwKICAgICAgIHkgPSAixaB0dm9yY2UgcmV6aWR1w60iLAogICAgICAgdGl0bGUgPSAixaB0dm9yY2UgcmV6aWR1w60gdnMgUG/EjWV0IHZvemlkaWVsIikgKwogIHRoZW1lX21pbmltYWwoKQoKcDIgPC0gZ2dwbG90KGJhcmNfZGF0YSwgYWVzKHggPSBNaWxkLmluanVyaWVzLCB5ID0gcmVzaWQobW9kZWwpXjIpKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIGFscGhhID0gMC42KSArCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC4yLCBjb2xvciA9ICJsaWdodHBpbmsiLCBvdXRsaWVyLnNoYXBlID0gTkEpICsKICBsYWJzKHggPSAiUG/EjWV0IMS+YWhrw71jaCB6cmFuZW7DrSIsCiAgICAgICB5ID0gIsWgdHZvcmNlIHJlemlkdcOtIiwKICAgICAgIHRpdGxlID0gIsWgdHZvcmNlIHJlemlkdcOtIHZzIFBvxI1ldCDEvmFoa8O9Y2ggenJhbmVuw60iKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIFNwb2plbmllIGdyYWZvdiB2ZWTEvmEgc2ViYQpwMSArIHAyCmBgYAoKTmEgZ3JhZm9jaCDFoHR2b3JjZSByZXppZHXDrSB2cyBQb8SNZXQgdm96aWRpZWwgYSDFoHR2b3JjZSByZXppZHXDrSB2cyBQb8SNZXQgxL5haGvDvWNoIHpyYW5lbsOtIG3DtMW+ZW1lIHBvem9yb3ZhxaUsIMW+ZSBydcW+b3bDoSB2eWhsYWRlbsOhIGtyaXZrYSB6b3N0w6F2YSByZWxhdMOtdm5lIHBsb2Now6EgYSByb3pwdHlsIHJlemlkdcOtIHNhIHMgaG9kbm90YW1pIHByZW1lbm7DvWNoIHbDvXJhem5lIG5lbWVuw60uIE1lbsWhaWUga29sw61zYW5pZSBuYXpuYcSNdWplIGxlbiBzbGFiw6kgbsOhem5ha3kgaGV0ZXJvc2tlZGFzdGljaXR5LCBrdG9yw6kgdsWhYWsgbmllIHPDuiB2w71yYXpuw6kuIENlbGtvdm8gbW/Fvm5vIHRlZGEgdXPDumRpxaUsIMW+ZSB2IG1vZGVsaSBzYSBoZXRlcm9za2VkYXN0aWNpdGEgdsO9cmF6bmUgbmV2eXNreXR1amUgYSByb3pwdHlsIG7DoWhvZG5laiB6bG/Fvmt5IHpvc3TDoXZhIHByaWJsacW+bmUga29uxaF0YW50bsO9LgoKYSB0ZXJheiBtb2RlbCBzbyB6bG9nYXJpdG1pem92YW5vdSBwcmVtZW5ub3UgKlZlaGljbGVzLmludm9sdmVkKi4KCmBgYHtyIGhldGVyb3Bsb3RzX2JjbjIsIGZpZy5jYXA9IlNrw7ptYW5pZSBoZXRlcm9za2VkYXN0aWNpdHkg4oCTIGRvcHJhdm7DqSBuZWhvZHkgdiBCYXJjZWxvbmUiLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NH0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBhdGNod29yaykgICMgaW5zdGFsbC5wYWNrYWdlcygicGF0Y2h3b3JrIikKCiMgTmHEjcOtdGFuaWUgw7pkYWpvdgpiYXJjX2RhdGEgPC0gcmVhZC5jc3YoImJhcmNfZGF0YS5jc3YiLCBlbmNvZGluZyA9ICJsYXRpbjEiLCBzZXAgPSAiOyIpCgojIExpbmXDoXJueSBtb2RlbCDEjS4yOiBwb8SNZXQgb2JldMOtIHBvZMS+YSBwb8SNdHUgdm96aWRpZWwgYSBtaWVybnljaCB6cmFuZW7DrQptb2RlbDIgPC0gbG0oVmljdGltcyB+IFZlaGljbGVzLmludm9sdmVkICsgTWlsZC5pbmp1cmllcywgZGF0YSA9IGJhcmNfZGF0YSkKCiMgR3JhZiAxIOKAkyBsb2cocG/EjWV0IHZvemlkaWVsKSB2cyDFoXR2b3JjZSByZXppZHXDrQpwMSA8LSBnZ3Bsb3QoYmFyY19kYXRhLCBhZXMoeCA9IGxvZyhWZWhpY2xlcy5pbnZvbHZlZCArIDEpLCB5ID0gcmVzaWQobW9kZWwyKV4yKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJsaWdodHBpbmsiKSArCiAgbGFicyh4ID0gImxvZyhQb8SNZXQgemFwb2plbsO9Y2ggdm96aWRpZWwpIiwKICAgICAgIHkgPSAixaB0dm9yY2UgcmV6aWR1w60iLAogICAgICAgdGl0bGUgPSAiUmV6aWR1w6EgdnMgbG9nKFBvxI1ldCB2b3ppZGllbCkiKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIEdyYWYgMiDigJMgbWllcm5lIHpyYW5lbmlhIHZzIMWhdHZvcmNlIHJlemlkdcOtCnAyIDwtIGdncGxvdChiYXJjX2RhdGEsIGFlcyh4ID0gTWlsZC5pbmp1cmllcywgeSA9IHJlc2lkKG1vZGVsMileMikpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC42KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAibGlnaHRwaW5rIikgKwogIGxhYnMoeCA9ICJNaWVybmUgenJhbmVuaWEiLAogICAgICAgeSA9ICLFoHR2b3JjZSByZXppZHXDrSIsCiAgICAgICB0aXRsZSA9ICJSZXppZHXDoSB2cyBNaWVybmUgenJhbmVuaWEiKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIFNwb2plbmllIGdyYWZvdiB2ZWTEvmEgc2ViYQpwMSArIHAyCmBgYAoKUG8gbG9nYXJpdG1pY2tlaiB0cmFuc2Zvcm3DoWNpaSBwcmVtZW5uZWogUG/EjWV0IHphcG9qZW7DvWNoIHZvemlkaWVsIHNhIHJ1xb5vdsOhIGtyaXZrYSB2eXJvdm5hbGEgYSByb3pwdHlsIHJlemlkdcOtIHNhIHN0YWwgcm92bm9tZXJuZWrFocOtbSwgxI1vIG5hem5hxI11amUsIMW+ZSB0cmFuc2Zvcm3DoWNpYSB6bsOtxb5pbGEgaGV0ZXJvc2tlZGFzdGljaXR1LiBQcmVtZW5uw6EgTWllcm5lIHpyYW5lbmlhIG5ldnlrYXp1amUgdmlkaXRlxL5uw6kgem7DoW1reSBoZXRlcm9za2VkYXN0aWNpdHksIHRha8W+ZSBjZWxrb3ZvIG1vxb5ubyBwb3ZlZGHFpSwgxb5lIG5vdsO9IG1vZGVsIG3DoSBzdGFiaWxuZWrFocOtIHJvenB0eWwgcmV6aWR1w60gYSBsZXDFoWl1IMWhdHJ1a3TDunJ1IGFrbyBww7R2b2Ruw70uCgoKIyMgVGVzdG92YW5pZSBwcsOtdG9tbm9zdGkgaGV0ZXJvc2tlZGFzdGljaXR5CgpgYGB7cn0KIyBJbnN0YWxsIChpZiBub3QgeWV0IGluc3RhbGxlZCkKIyBpbnN0YWxsLnBhY2thZ2VzKCJsbXRlc3QiKQoKIyBMb2FkIHRoZSBwYWNrYWdlCmxpYnJhcnkobG10ZXN0KQoKIyBSdW4gdGhlIEJyZXVzY2jigJNQYWdhbiB0ZXN0CmJwdGVzdChtb2RlbCkKCmBgYAoKCmBgYHtyfQojIEluc3RhbGwgKGlmIG5vdCB5ZXQgaW5zdGFsbGVkKQojIGluc3RhbGwucGFja2FnZXMoImxtdGVzdCIpCgojIExvYWQgdGhlIHBhY2thZ2UKbGlicmFyeShsbXRlc3QpCgojIFJ1biB0aGUgQnJldXNjaOKAk1BhZ2FuIHRlc3QKYnB0ZXN0KG1vZGVsMikKCmBgYAoKS2XEj8W+ZSBwLWhvZG5vdGEgQnJldXNjaOKAk1BhZ2Fub3ZobyB0ZXN0dSAoMC41OTQ1KSB2w71yYXpuZSBwcmVzYWh1amUgYmXFvm7DuiBobGFkaW51IHbDvXpuYW1ub3N0aSAobmFwci4gMC4wNSksIG5lemFtaWV0YW1lIG51bG92w7ogaHlwb3TDqXp1LCBrdG9yw6EgcHJlZHBva2xhZMOhIGhvbW9za2VkYXN0aWNpdHUg4oCTIHRlZGEga29uxaF0YW50bsO9IHJvenB0eWwgcmV6w61kdcOtIGJleiBzeXN0ZW1hdGlja8O9Y2ggem1pZW4gdiB6w6F2aXNsb3N0aSBvZCB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoLgoKTmEgesOha2xhZGUgdsO9c2xlZGt1IHRlc3R1IG1vxb5ubyBrb27FoXRhdG92YcWlLCDFvmUgdiByZXrDrWR1w6FjaCBtb2RlbHUgbW9kZWwyIG5pZSBqZSBwcsOtdG9tbsOhIGhldGVyb3NrZWRhc3RpY2l0YS4gUm96cHR5bCBzYSBqYXbDrSBha28gc3RhYmlsbsO9LCBhIHByZXRvIG5pZSBqZSBwb3RyZWJuw6kgYXBsaWtvdmHFpSBXaGl0ZW92dSBrb3Jla2NpdSBhbmkgxI9hbMWhaWUgw7pwcmF2eSBtb2RlbHUuCgoK