1. Inštalácia potrebných balíčkov
install.packages("zoo")
install.packages("tseries")
install.packages("lmtest")
install.packages("sandwich")
install.packages("car")
2. Načítanie knižníc
library(zoo)
library(tseries)
library(lmtest)
library(sandwich)
library(car)
3. Načítanie údajov (súbor musí byť v pracovnom priečinku Posit
Cloud)
udaje <- read.csv("economic_indicators_dataset_2010_2023.csv",
dec = ".", sep = ",", header = TRUE, stringsAsFactors = FALSE)
4. Kontrola názvov stĺpcov
print("Názvy stĺpcov:")
print(names(udaje))
5. Prevod Date na Date triedu a vytvorenie stĺpca Year
udaje$Date_parsed <- as.Date(udaje$Date, format = "%Y-%m-%d")
Teraz vytvoríme Year
udaje$Year <- as.numeric(format(udaje$Date_parsed, "%Y"))
Rýchla kontrola dostupných rokov
print("Dostupné roky v dátach:")
print(sort(unique(udaje$Year)))
6. Výber údajov pre rok 2015
udaje.2015 <- subset(udaje, Year == 2015)
7. Výber relevantných stĺpcov podľa tvojich názvov
# Definujeme názvy stĺpcov, ktoré nás zaujímajú
stock_col <- "Stock.Index.Value"
gdp_col <- "GDP.Growth.Rate...."
interest_col <- "Interest.Rate...."
infl_col <- "Inflation.Rate...."
# Overíme, ktoré stĺpce skutočne existujú v dátach
available_cols <- c(stock_col, gdp_col, interest_col, infl_col)
existing_cols <- available_cols[available_cols %in% names(udaje.2015)]
print("Použité stĺpce:")
[1] "Použité stĺpce:"
[1] "Stock.Index.Value" "GDP.Growth.Rate...."
[3] "Interest.Rate...." "Inflation.Rate...."
# Vytvoríme dataframe len s týmito stĺpcami
udaje.2015_sel <- udaje.2015[, existing_cols, drop = FALSE]
8. Prevod všetkých vybraných stĺpcov na numerické (ak ešte nie
sú)
# Konvertujeme každý stĺpec individuálne na numerický
for (col in existing_cols) {
udaje.2015_sel[[col]] <- as.numeric(as.character(udaje.2015_sel[[col]]))
}
9. Kontrola NA / prázdnych stĺpcov pred boxplotom
na_counts <- sapply(udaje.2015_sel, function(x) sum(is.na(x)))
non_na_counts <- sapply(udaje.2015_sel, function(x) sum(!is.na(x)))
print("Počet NA v každom stĺpci:")
[1] "Počet NA v každom stĺpci:"
Stock.Index.Value GDP.Growth.Rate.... Interest.Rate....
0 0 0
Inflation.Rate....
0
print("Počet nenulových hodnôt v každom stĺpci:")
[1] "Počet nenulových hodnôt v každom stĺpci:"
Stock.Index.Value GDP.Growth.Rate.... Interest.Rate....
32 32 32
Inflation.Rate....
32
# Ak niektorý stĺpec obsahuje len NA -> vylúčime ho z ďalších krokov
cols_with_data <- names(udaje.2015_sel)[non_na_counts > 0]
if (length(cols_with_data) == 0) {
stop("Všetky vybrané stĺpce pre vybraný rok sú NA. Skontroluj dáta.")
}
udaje.2015_sel <- udaje.2015_sel[, cols_with_data, drop = FALSE]
10. Doplnenie chýbajúcich hodnôt mediánom
for (col in names(udaje.2015_sel)) {
if (sum(!is.na(udaje.2015_sel[[col]])) > 0) { # kontrola, či sú nejaké non-NA hodnoty
med <- median(udaje.2015_sel[[col]], na.rm = TRUE)
udaje.2015_sel[[col]][is.na(udaje.2015_sel[[col]])] <- med
}
}
11. Boxploty
numeric_cols <- names(udaje.2015_sel)[sapply(udaje.2015_sel, is.numeric)]
if (length(numeric_cols) == 0) {
stop("Žiadne numerické stĺpce na vykreslenie.")
}
# Dynamicky nastaviť rozloženie grafov podľa počtu stĺpcov
plot_rows <- ceiling(length(numeric_cols) / 2)
par(mfrow = c(plot_rows, 2))
par(mar = c(4, 4, 2, 1))
for (col in numeric_cols) {
vals <- udaje.2015_sel[[col]]
if (all(is.finite(vals))) {
boxplot(vals, main = col, xlab = "Hodnota", col = "lightblue")
} else {
warning(paste("Stĺpec", col, "nemá konečné hodnoty. Preskakujem."))
}
}
mtext("Boxploty vybraných premenných (rok 2015)", outer = TRUE, line = -1, cex = 1.2, font = 2)

Štatistické hypotézy
Pre regresný model testujeme nasledovné štatistické hypotézy:
Hlavné hypotézy:
- Hypotéza o vplyve HDP na akciový index:
- H₀: β_GDP = 0 (Rast HDP nemá vplyv na akciový index)
- H₁: β_GDP ≠ 0 (Rast HDP má vplyv na akciový index)
- Hypotéza o vplyve úrokovej sadzby:
- H₀: β_Interest = 0 (Úroková sadzba nemá vplyv na akciový index)
- H₁: β_Interest ≠ 0 (Úroková sadzba má vplyv na akciový index)
- Hypotéza o vplyve inflácie:
- H₀: β_Inflation = 0 (Inflácia nemá vplyv na akciový index)
- H₁: β_Inflation ≠ 0 (Inflácia má vplyv na akciový index)
Celková hypotéza modelu: - H₀: β₁ = β₂ = β₃ = 0
(Žiadna z premenných nevysvetľuje variabilitu akciového indexu) - H₁:
Aspoň jeden β ≠ 0 (Asi jedna premenná vysvetľuje variabilitu akciového
indexu)
Očakávané smerové účinky: - GDP Growth: očakávame
pozitívny vplyv (+) - Interest Rate: očakávame negatívny vplyv (-) -
Inflation Rate: vplyv nejednoznačný (+/-) “)
12. Regresný model
# Skontrolujeme, či máme aspoň Stock Index a jednu vysvetľujúcu premennú
if (!("Stock.Index.Value" %in% names(udaje.2015_sel))) {
stop("Stĺpec 'Stock Index Value' nie je dostupný po filtrovaní.")
}
# Zostavíme formulu dynamicky len z dostupných vysvetľujúcich premenných
response <- "Stock.Index.Value"
predictors <- setdiff(names(udaje.2015_sel), response)
if (length(predictors) == 0) {
stop("Žiadne vysvetľujúce premenné dostupné pre regresiu.")
}
formula_text <- paste(response, "~", paste(predictors, collapse = " + "))
model <- lm(as.formula(formula_text), data = udaje.2015_sel)
print(summary(model))
Call:
lm(formula = as.formula(formula_text), data = udaje.2015_sel)
Residuals:
Min 1Q Median 3Q Max
-22884.0 -6508.6 -291.9 9787.0 17806.9
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 25760.4 5217.1 4.938 3.29e-05 ***
GDP.Growth.Rate.... 523.6 547.4 0.957 0.347
Interest.Rate.... -928.3 652.8 -1.422 0.166
Inflation.Rate.... 243.6 664.0 0.367 0.716
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 12040 on 28 degrees of freedom
Multiple R-squared: 0.09753, Adjusted R-squared: 0.00084
F-statistic: 1.009 on 3 and 28 DF, p-value: 0.4036
13. Diagnostické grafy
par(mfrow = c(2, 2))
plot(model)
par(mfrow = c(1, 1))

14. Testy rezíduí a odľahlých hodnôt
jb_test <- jarque.bera.test(residuals(model))
print(jb_test)
Jarque Bera Test
data: residuals(model)
X-squared = 1.9994, df = 2, p-value = 0.368
print(outlierTest(model))
No Studentized residuals with Bonferroni p < 0.05
Largest |rstudent|:
15. Alternatívny model
# Skúsime model bez krajných hodnôt
if (nrow(udaje.2015_sel) > 10) { # len ak máme dostatok dát
# Odstránime vplyvné body
cooks_dist <- cooks.distance(model)
influential <- cooks_dist > (4 / nrow(udaje.2015_sel))
if (sum(influential) > 0) {
udaje.2015_clean <- udaje.2015_sel[!influential, ]
model_clean <- lm(as.formula(formula_text), data = udaje.2015_clean)
print("Model po odstránení vplyvných pozorovaní:")
print(summary(model_clean))
}
}
[1] "Model po odstránení vplyvných pozorovaní:"
Call:
lm(formula = as.formula(formula_text), data = udaje.2015_clean)
Residuals:
Min 1Q Median 3Q Max
-20974 -4867 -1410 8841 16668
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 27477.5 4934.4 5.569 6.64e-06 ***
GDP.Growth.Rate.... 915.6 540.4 1.694 0.1017
Interest.Rate.... -1228.9 624.5 -1.968 0.0594 .
Inflation.Rate.... 206.7 620.7 0.333 0.7417
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 11250 on 27 degrees of freedom
Multiple R-squared: 0.1944, Adjusted R-squared: 0.1048
F-statistic: 2.171 on 3 and 27 DF, p-value: 0.1146
Správa z analýzy (rok 2015)
Cieľom analýzy bolo preskúmať vplyv makroekonomických premenných na
hodnotu akciového indexu. Použité premenné: Stock Index Value (závislá),
GDP Growth Rate (%), Interest Rate (%), Inflation Rate (%).
Doplnenie chýbajúcich hodnôt: medián príslušnej premennej. Regresný
model: pozri vyššie výpis summary().
Interpretácia: - Ak je koeficient pri raste HDP pozitívny a
štatisticky významný -> rast HDP zvyšuje akciový index. - Ak je
koeficient pri úrokovej sadzbe negatívny -> vyššie úrokové sadzby
znižujú hodnotu akcií. - Inflácia často má slabší alebo nejednoznačný
vplyv.
LS0tDQp0aXRsZTogIlVsb2hhIDUiDQphdXRob3I6ICJZdWxpaWEgTHlzeXRzaWEiDQpkYXRlOiAiT2t0b2JlciAyMDI1Ig0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICB0aGVtZTogdW5pdGVkDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KZWRpdG9yX29wdGlvbnM6IA0KICBtYXJrZG93bjogDQogICAgd3JhcDogNzINCi0tLQ0KDQojIDEuIEluxaF0YWzDoWNpYSBwb3RyZWJuw71jaCBiYWzDrcSNa292IA0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCJ6b28iKQ0KaW5zdGFsbC5wYWNrYWdlcygidHNlcmllcyIpDQppbnN0YWxsLnBhY2thZ2VzKCJsbXRlc3QiKQ0KaW5zdGFsbC5wYWNrYWdlcygic2FuZHdpY2giKQ0KaW5zdGFsbC5wYWNrYWdlcygiY2FyIikNCmBgYA0KDQojIDIuIE5hxI3DrXRhbmllIGtuacW+bsOtYw0KYGBge3J9DQpsaWJyYXJ5KHpvbykNCmxpYnJhcnkodHNlcmllcykNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShzYW5kd2ljaCkNCmxpYnJhcnkoY2FyKQ0KYGBgDQoNCg0KDQojIDMuIE5hxI3DrXRhbmllIMO6ZGFqb3YgKHPDumJvciBtdXPDrSBiecWlIHYgcHJhY292bm9tIHByaWXEjWlua3UgUG9zaXQgQ2xvdWQpDQoNCmBgYHtyfQ0KdWRhamUgPC0gcmVhZC5jc3YoImVjb25vbWljX2luZGljYXRvcnNfZGF0YXNldF8yMDEwXzIwMjMuY3N2IiwNCiAgICAgICAgICAgICAgICAgIGRlYyA9ICIuIiwgc2VwID0gIiwiLCBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpgYGANCg0KDQojIDQuIEtvbnRyb2xhIG7DoXp2b3Ygc3TEunBjb3YNCmBgYHtyfQ0KcHJpbnQoIk7DoXp2eSBzdMS6cGNvdjoiKQ0KcHJpbnQobmFtZXModWRhamUpKQ0KYGBgDQoNCg0KIyA1LiBQcmV2b2QgRGF0ZSBuYSBEYXRlIHRyaWVkdSBhIHZ5dHZvcmVuaWUgc3TEunBjYSBZZWFyDQpgYGB7cn0NCnVkYWplJERhdGVfcGFyc2VkIDwtIGFzLkRhdGUodWRhamUkRGF0ZSwgZm9ybWF0ID0gIiVZLSVtLSVkIikNCmBgYA0KDQoNCiMgVGVyYXogdnl0dm9yw61tZSBZZWFyDQpgYGB7cn0NCnVkYWplJFllYXIgPC0gYXMubnVtZXJpYyhmb3JtYXQodWRhamUkRGF0ZV9wYXJzZWQsICIlWSIpKQ0KYGBgDQoNCg0KIyBSw71jaGxhIGtvbnRyb2xhIGRvc3R1cG7DvWNoIHJva292DQpgYGB7cn0NCnByaW50KCJEb3N0dXBuw6kgcm9reSB2IGTDoXRhY2g6IikNCnByaW50KHNvcnQodW5pcXVlKHVkYWplJFllYXIpKSkNCmBgYA0KDQojIDYuIFbDvWJlciDDumRham92IHByZSByb2sgMjAxNSANCmBgYHtyfQ0KdWRhamUuMjAxNSA8LSBzdWJzZXQodWRhamUsIFllYXIgPT0gMjAxNSkNCg0KYGBgDQoNCg0KIyA3LiBWw71iZXIgcmVsZXZhbnRuw71jaCBzdMS6cGNvdiBwb2TEvmEgdHZvamljaCBuw6F6dm92DQpgYGB7cn0NCiMgRGVmaW51amVtZSBuw6F6dnkgc3TEunBjb3YsIGt0b3LDqSBuw6FzIHphdWrDrW1hasO6DQpzdG9ja19jb2wgPC0gIlN0b2NrLkluZGV4LlZhbHVlIg0KZ2RwX2NvbCA8LSAiR0RQLkdyb3d0aC5SYXRlLi4uLiINCmludGVyZXN0X2NvbCA8LSAiSW50ZXJlc3QuUmF0ZS4uLi4iDQppbmZsX2NvbCA8LSAiSW5mbGF0aW9uLlJhdGUuLi4uIg0KDQojIE92ZXLDrW1lLCBrdG9yw6kgc3TEunBjZSBza3V0b8SNbmUgZXhpc3R1asO6IHYgZMOhdGFjaA0KYXZhaWxhYmxlX2NvbHMgPC0gYyhzdG9ja19jb2wsIGdkcF9jb2wsIGludGVyZXN0X2NvbCwgaW5mbF9jb2wpDQpleGlzdGluZ19jb2xzIDwtIGF2YWlsYWJsZV9jb2xzW2F2YWlsYWJsZV9jb2xzICVpbiUgbmFtZXModWRhamUuMjAxNSldDQoNCnByaW50KCJQb3XFvml0w6kgc3TEunBjZToiKQ0KcHJpbnQoZXhpc3RpbmdfY29scykNCg0KIyBWeXR2b3LDrW1lIGRhdGFmcmFtZSBsZW4gcyB0w71taXRvIHN0xLpwY2FtaQ0KdWRhamUuMjAxNV9zZWwgPC0gdWRhamUuMjAxNVssIGV4aXN0aW5nX2NvbHMsIGRyb3AgPSBGQUxTRV0NCg0KYGBgDQoNCiMgOC4gUHJldm9kIHbFoWV0a8O9Y2ggdnlicmFuw71jaCBzdMS6cGNvdiBuYSBudW1lcmlja8OpIChhayBlxaF0ZSBuaWUgc8O6KQ0KYGBge3J9DQojIEtvbnZlcnR1amVtZSBrYcW+ZMO9IHN0xLpwZWMgaW5kaXZpZHXDoWxuZSBuYSBudW1lcmlja8O9DQpmb3IgKGNvbCBpbiBleGlzdGluZ19jb2xzKSB7DQogIHVkYWplLjIwMTVfc2VsW1tjb2xdXSA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih1ZGFqZS4yMDE1X3NlbFtbY29sXV0pKQ0KfQ0KYGBgDQoNCg0KIyA5LiBLb250cm9sYSBOQSAvIHByw6F6ZG55Y2ggc3TEunBjb3YgcHJlZCBib3hwbG90b20gDQpgYGB7cn0NCm5hX2NvdW50cyA8LSBzYXBwbHkodWRhamUuMjAxNV9zZWwsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpDQpub25fbmFfY291bnRzIDwtIHNhcHBseSh1ZGFqZS4yMDE1X3NlbCwgZnVuY3Rpb24oeCkgc3VtKCFpcy5uYSh4KSkpDQpwcmludCgiUG/EjWV0IE5BIHYga2HFvmRvbSBzdMS6cGNpOiIpDQpwcmludChuYV9jb3VudHMpDQpwcmludCgiUG/EjWV0IG5lbnVsb3bDvWNoIGhvZG7DtHQgdiBrYcW+ZG9tIHN0xLpwY2k6IikNCnByaW50KG5vbl9uYV9jb3VudHMpDQoNCiMgQWsgbmlla3RvcsO9IHN0xLpwZWMgb2JzYWh1amUgbGVuIE5BIC0+IHZ5bMO6xI1pbWUgaG8geiDEj2FsxaHDrWNoIGtyb2tvdg0KY29sc193aXRoX2RhdGEgPC0gbmFtZXModWRhamUuMjAxNV9zZWwpW25vbl9uYV9jb3VudHMgPiAwXQ0KaWYgKGxlbmd0aChjb2xzX3dpdGhfZGF0YSkgPT0gMCkgew0KICBzdG9wKCJWxaFldGt5IHZ5YnJhbsOpIHN0xLpwY2UgcHJlIHZ5YnJhbsO9IHJvayBzw7ogTkEuIFNrb250cm9sdWogZMOhdGEuIikNCn0NCnVkYWplLjIwMTVfc2VsIDwtIHVkYWplLjIwMTVfc2VsWywgY29sc193aXRoX2RhdGEsIGRyb3AgPSBGQUxTRV0NCg0KYGBgDQoNCiMgMTAuIERvcGxuZW5pZSBjaMO9YmFqw7pjaWNoIGhvZG7DtHQgbWVkacOhbm9tIA0KYGBge3J9DQpmb3IgKGNvbCBpbiBuYW1lcyh1ZGFqZS4yMDE1X3NlbCkpIHsNCiAgaWYgKHN1bSghaXMubmEodWRhamUuMjAxNV9zZWxbW2NvbF1dKSkgPiAwKSB7ICAjIGtvbnRyb2xhLCDEjWkgc8O6IG5lamFrw6kgbm9uLU5BIGhvZG5vdHkNCiAgICBtZWQgPC0gbWVkaWFuKHVkYWplLjIwMTVfc2VsW1tjb2xdXSwgbmEucm0gPSBUUlVFKQ0KICAgIHVkYWplLjIwMTVfc2VsW1tjb2xdXVtpcy5uYSh1ZGFqZS4yMDE1X3NlbFtbY29sXV0pXSA8LSBtZWQNCiAgfQ0KfQ0KDQpgYGANCg0KIyAxMS4gQm94cGxvdHkgDQpgYGB7cn0NCm51bWVyaWNfY29scyA8LSBuYW1lcyh1ZGFqZS4yMDE1X3NlbClbc2FwcGx5KHVkYWplLjIwMTVfc2VsLCBpcy5udW1lcmljKV0NCmlmIChsZW5ndGgobnVtZXJpY19jb2xzKSA9PSAwKSB7DQogIHN0b3AoIsW9aWFkbmUgbnVtZXJpY2vDqSBzdMS6cGNlIG5hIHZ5a3Jlc2xlbmllLiIpDQp9DQoNCiMgRHluYW1pY2t5IG5hc3RhdmnFpSByb3psb8W+ZW5pZSBncmFmb3YgcG9kxL5hIHBvxI10dSBzdMS6cGNvdg0KcGxvdF9yb3dzIDwtIGNlaWxpbmcobGVuZ3RoKG51bWVyaWNfY29scykgLyAyKQ0KcGFyKG1mcm93ID0gYyhwbG90X3Jvd3MsIDIpKQ0KcGFyKG1hciA9IGMoNCwgNCwgMiwgMSkpDQoNCmZvciAoY29sIGluIG51bWVyaWNfY29scykgew0KICB2YWxzIDwtIHVkYWplLjIwMTVfc2VsW1tjb2xdXQ0KICBpZiAoYWxsKGlzLmZpbml0ZSh2YWxzKSkpIHsNCiAgICBib3hwbG90KHZhbHMsIG1haW4gPSBjb2wsIHhsYWIgPSAiSG9kbm90YSIsIGNvbCA9ICJsaWdodGJsdWUiKQ0KICB9IGVsc2Ugew0KICAgIHdhcm5pbmcocGFzdGUoIlN0xLpwZWMiLCBjb2wsICJuZW3DoSBrb25lxI1uw6kgaG9kbm90eS4gUHJlc2tha3VqZW0uIikpDQogIH0NCn0NCg0KbXRleHQoIkJveHBsb3R5IHZ5YnJhbsO9Y2ggcHJlbWVubsO9Y2ggKHJvayAyMDE1KSIsIG91dGVyID0gVFJVRSwgbGluZSA9IC0xLCBjZXggPSAxLjIsIGZvbnQgPSAyKQ0KcGFyKG1mcm93ID0gYygxLCAxKSkNCmBgYA0KDQojIyMgxaB0YXRpc3RpY2vDqSBoeXBvdMOpenkNCg0KUHJlIHJlZ3Jlc27DvSBtb2RlbCB0ZXN0dWplbWUgbmFzbGVkb3Zuw6kgxaF0YXRpc3RpY2vDqSBoeXBvdMOpenk6DQoNCioqSGxhdm7DqSBoeXBvdMOpenk6KioNCg0KMS4gKipIeXBvdMOpemEgbyB2cGx5dmUgSERQIG5hIGFrY2lvdsO9IGluZGV4OioqDQogICAtIEjigoA6IM6yX0dEUCA9IDAgKFJhc3QgSERQIG5lbcOhIHZwbHl2IG5hIGFrY2lvdsO9IGluZGV4KQ0KICAgLSBI4oKBOiDOsl9HRFAg4omgIDAgKFJhc3QgSERQIG3DoSB2cGx5diBuYSBha2Npb3bDvSBpbmRleCkNCg0KMi4gKipIeXBvdMOpemEgbyB2cGx5dmUgw7pyb2tvdmVqIHNhZHpieToqKg0KICAgLSBI4oKAOiDOsl9JbnRlcmVzdCA9IDAgKMOacm9rb3bDoSBzYWR6YmEgbmVtw6EgdnBseXYgbmEgYWtjaW92w70gaW5kZXgpDQogICAtIEjigoE6IM6yX0ludGVyZXN0IOKJoCAwICjDmnJva292w6Egc2FkemJhIG3DoSB2cGx5diBuYSBha2Npb3bDvSBpbmRleCkNCg0KMy4gKipIeXBvdMOpemEgbyB2cGx5dmUgaW5mbMOhY2llOioqDQogICAtIEjigoA6IM6yX0luZmxhdGlvbiA9IDAgKEluZmzDoWNpYSBuZW3DoSB2cGx5diBuYSBha2Npb3bDvSBpbmRleCkNCiAgIC0gSOKCgTogzrJfSW5mbGF0aW9uIOKJoCAwIChJbmZsw6FjaWEgbcOhIHZwbHl2IG5hIGFrY2lvdsO9IGluZGV4KQ0KDQoqKkNlbGtvdsOhIGh5cG90w6l6YSBtb2RlbHU6KioNCi0gSOKCgDogzrLigoEgPSDOsuKCgiA9IM6y4oKDID0gMCAoxb1pYWRuYSB6IHByZW1lbm7DvWNoIG5ldnlzdmV0xL51amUgdmFyaWFiaWxpdHUgYWtjaW92w6lobyBpbmRleHUpDQotIEjigoE6IEFzcG/FiCBqZWRlbiDOsiDiiaAgMCAoQXNpIGplZG5hIHByZW1lbm7DoSB2eXN2ZXTEvnVqZSB2YXJpYWJpbGl0dSBha2Npb3bDqWhvIGluZGV4dSkNCg0KKipPxI1ha8OhdmFuw6kgc21lcm92w6kgw7rEjWlua3k6KioNCi0gR0RQIEdyb3d0aDogb8SNYWvDoXZhbWUgcG96aXTDrXZueSB2cGx5diAoKykNCi0gSW50ZXJlc3QgUmF0ZTogb8SNYWvDoXZhbWUgbmVnYXTDrXZueSB2cGx5diAoLSkNCi0gSW5mbGF0aW9uIFJhdGU6IHZwbHl2IG5lamVkbm96bmHEjW7DvSAoKy8tKQ0KIikNCg0KIyAxMi4gUmVncmVzbsO9IG1vZGVsDQoNCmBgYHtyfQ0KDQojIFNrb250cm9sdWplbWUsIMSNaSBtw6FtZSBhc3BvxYggU3RvY2sgSW5kZXggYSBqZWRudSB2eXN2ZXTEvnVqw7pjdSBwcmVtZW5uw7oNCmlmICghKCJTdG9jay5JbmRleC5WYWx1ZSIgJWluJSBuYW1lcyh1ZGFqZS4yMDE1X3NlbCkpKSB7DQogIHN0b3AoIlN0xLpwZWMgJ1N0b2NrIEluZGV4IFZhbHVlJyBuaWUgamUgZG9zdHVwbsO9IHBvIGZpbHRyb3ZhbsOtLiIpDQp9DQoNCiMgWm9zdGF2w61tZSBmb3JtdWx1IGR5bmFtaWNreSBsZW4geiBkb3N0dXBuw71jaCB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoDQpyZXNwb25zZSA8LSAiU3RvY2suSW5kZXguVmFsdWUiDQpwcmVkaWN0b3JzIDwtIHNldGRpZmYobmFtZXModWRhamUuMjAxNV9zZWwpLCByZXNwb25zZSkNCg0KaWYgKGxlbmd0aChwcmVkaWN0b3JzKSA9PSAwKSB7DQogIHN0b3AoIsW9aWFkbmUgdnlzdmV0xL51asO6Y2UgcHJlbWVubsOpIGRvc3R1cG7DqSBwcmUgcmVncmVzaXUuIikNCn0NCg0KZm9ybXVsYV90ZXh0IDwtIHBhc3RlKHJlc3BvbnNlLCAifiIsIHBhc3RlKHByZWRpY3RvcnMsIGNvbGxhcHNlID0gIiArICIpKQ0KbW9kZWwgPC0gbG0oYXMuZm9ybXVsYShmb3JtdWxhX3RleHQpLCBkYXRhID0gdWRhamUuMjAxNV9zZWwpDQpwcmludChzdW1tYXJ5KG1vZGVsKSkNCg0KYGBgDQoNCiMgMTMuIERpYWdub3N0aWNrw6kgZ3JhZnkNCg0KYGBge3J9DQoNCnBhcihtZnJvdyA9IGMoMiwgMikpDQpwbG90KG1vZGVsKQ0KcGFyKG1mcm93ID0gYygxLCAxKSkNCg0KYGBgDQoNCg0KIyAxNC4gVGVzdHkgcmV6w61kdcOtIGEgb2TEvmFobMO9Y2ggaG9kbsO0dA0KDQpgYGB7cn0NCg0KamJfdGVzdCA8LSBqYXJxdWUuYmVyYS50ZXN0KHJlc2lkdWFscyhtb2RlbCkpDQpwcmludChqYl90ZXN0KQ0KcHJpbnQob3V0bGllclRlc3QobW9kZWwpKQ0KDQpgYGANCg0KIyAxNS4gQWx0ZXJuYXTDrXZueSBtb2RlbCANCg0KYGBge3J9DQojIFNrw7pzaW1lIG1vZGVsIGJleiBrcmFqbsO9Y2ggaG9kbsO0dA0KaWYgKG5yb3codWRhamUuMjAxNV9zZWwpID4gMTApIHsgIA0KICAjIE9kc3Ryw6FuaW1lIHZwbHl2bsOpIGJvZHkNCiAgY29va3NfZGlzdCA8LSBjb29rcy5kaXN0YW5jZShtb2RlbCkNCiAgaW5mbHVlbnRpYWwgPC0gY29va3NfZGlzdCA+ICg0IC8gbnJvdyh1ZGFqZS4yMDE1X3NlbCkpDQogIA0KICBpZiAoc3VtKGluZmx1ZW50aWFsKSA+IDApIHsNCiAgICB1ZGFqZS4yMDE1X2NsZWFuIDwtIHVkYWplLjIwMTVfc2VsWyFpbmZsdWVudGlhbCwgXQ0KICAgIG1vZGVsX2NsZWFuIDwtIGxtKGFzLmZvcm11bGEoZm9ybXVsYV90ZXh0KSwgZGF0YSA9IHVkYWplLjIwMTVfY2xlYW4pDQogICAgcHJpbnQoIk1vZGVsIHBvIG9kc3Ryw6FuZW7DrSB2cGx5dm7DvWNoIHBvem9yb3ZhbsOtOiIpDQogICAgcHJpbnQoc3VtbWFyeShtb2RlbF9jbGVhbikpDQogIH0NCn0NCmBgYA0KDQojIyMgU3Byw6F2YSB6IGFuYWzDvXp5IChyb2sgMjAxNSkNCg0KQ2llxL5vbSBhbmFsw716eSBib2xvIHByZXNrw7ptYcWlIHZwbHl2IG1ha3JvZWtvbm9taWNrw71jaCBwcmVtZW5uw71jaCBuYSBob2Rub3R1IGFrY2lvdsOpaG8gaW5kZXh1Lg0KUG91xb5pdMOpIHByZW1lbm7DqTogU3RvY2sgSW5kZXggVmFsdWUgKHrDoXZpc2zDoSksIEdEUCBHcm93dGggUmF0ZSAoJSksIEludGVyZXN0IFJhdGUgKCUpLCBJbmZsYXRpb24gUmF0ZSAoJSkuDQoNCkRvcGxuZW5pZSBjaMO9YmFqw7pjaWNoIGhvZG7DtHQ6IG1lZGnDoW4gcHLDrXNsdcWhbmVqIHByZW1lbm5lai4NClJlZ3Jlc27DvSBtb2RlbDogcG96cmkgdnnFocWhaWUgdsO9cGlzIHN1bW1hcnkoKS4NCg0KSW50ZXJwcmV0w6FjaWE6DQotIEFrIGplIGtvZWZpY2llbnQgcHJpIHJhc3RlIEhEUCBwb3ppdMOtdm55IGEgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70gLT4gcmFzdCBIRFAgenZ5xaF1amUgYWtjaW92w70gaW5kZXguDQotIEFrIGplIGtvZWZpY2llbnQgcHJpIMO6cm9rb3ZlaiBzYWR6YmUgbmVnYXTDrXZueSAtPiB2ecWhxaFpZSDDunJva292w6kgc2FkemJ5IHpuacW+dWrDuiBob2Rub3R1IGFrY2nDrS4NCi0gSW5mbMOhY2lhIMSNYXN0byBtw6Egc2xhYsWhw60gYWxlYm8gbmVqZWRub3puYcSNbsO9IHZwbHl2Lg0KDQoNCg0KDQoNCg0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg