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

Ú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,]
colnames(udaje)
 [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)
par(mfrow = c(1, 1))

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)
par(mfrow = c(1, 1))

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