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:"
print(existing_cols)
[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:"
print(na_counts)
  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:"
print(non_na_counts)
  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)
par(mfrow = c(1, 1))

Štatistické hypotézy

Pre regresný model testujeme nasledovné štatistické hypotézy:

Hlavné hypotézy:

  1. 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)
  2. 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)
  3. 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