# 0) Balíčky (len ak chýbajú, doinštalujú sa)
needs <- c("dplyr","ggplot2","tseries","car")
to_install <- needs[!needs %in% rownames(installed.packages())]
if (length(to_install)) install.packages(to_install, quiet = TRUE)
lapply(needs, library, character.only = TRUE)
[[1]]
 [1] "car"       "carData"   "tseries"   "tidyr"     "dplyr"     "stats"    
 [7] "graphics"  "grDevices" "utils"     "datasets"  "methods"   "base"     

[[2]]
 [1] "ggplot2"   "car"       "carData"   "tseries"   "tidyr"     "dplyr"    
 [7] "stats"     "graphics"  "grDevices" "utils"     "datasets"  "methods"  
[13] "base"     

[[3]]
 [1] "ggplot2"   "car"       "carData"   "tseries"   "tidyr"     "dplyr"    
 [7] "stats"     "graphics"  "grDevices" "utils"     "datasets"  "methods"  
[13] "base"     

[[4]]
 [1] "ggplot2"   "car"       "carData"   "tseries"   "tidyr"     "dplyr"    
 [7] "stats"     "graphics"  "grDevices" "utils"     "datasets"  "methods"  
[13] "base"     
# 1) Robustné načítanie dát
safe_read <- function(path){
  df <- tryCatch(read.csv(path, header=TRUE, sep=";", dec=",",
                          check.names=FALSE, stringsAsFactors=FALSE), error=function(e) NULL)
  if (is.null(df) || ncol(df) == 1)
    df <- read.csv(path, header=TRUE, sep=",", dec=".",
                   check.names=FALSE, stringsAsFactors=FALSE)
  df
}
udaje <- safe_read("dataEKONOMETRIA.csv")
if (is.null(udaje)) stop("Súbor 'dataEKONOMETRIA.csv' sa nepodarilo načítať. Cesta: ", getwd())

cat("Nájdené stĺpce:\n"); print(colnames(udaje)); cat("\n")
Nájdené stĺpce:
[1] "Nazov"       "Kategoria"   "Forma"       "ROE"         "ROA"        
[6] "EBIT"        "EBITDAmarza" "M"           "Z"          
# 2) Mapovanie názvov stĺpcov (ak by sa volali trochu inak)
rename_if_exists <- function(df, old, new){ if (old %in% names(df)) names(df)[names(df)==old] <- new; df }
cand <- list(
  Nazov       = c("Nazov","Názov","Firma","Spolocnost","Spoločnosť"),
  Kategoria   = c("Kategoria","Kategória"),
  Forma       = c("Forma","PravnaForma","Právna forma","Pravna forma"),
  ROE         = c("ROE"),
  ROA         = c("ROA"),
  EBIT        = c("EBIT"),
  EBITDAmarza = c("EBITDAmarza","EBITDA%","EBITDA_marza","EBITDA"),
  M           = c("M","Muzi","Mužov","Pocet_muzov"),
  Z           = c("Z","Zeny","Žien","Pocet_zien")
)
for (nm in names(cand)) {
  hit <- cand[[nm]][cand[[nm]] %in% names(udaje)]
  if (length(hit)==1) udaje <- rename_if_exists(udaje, hit, nm)
}

# 3) Čistenie čísel (ak prišli ako texty)
clean_num <- function(x){
  if (is.numeric(x)) return(x)
  x <- gsub("\\s+", "", x)            # medzery
  x <- gsub("[^0-9,.-]", "", x)       # necháme čísla , . -
  x <- chartr(",", ".", x)            # des. čiarka -> bodka
  suppressWarnings(as.numeric(x))
}
num_cols <- c("ROE","ROA","EBIT","EBITDAmarza","M","Z")
for (nm in intersect(num_cols, names(udaje))) udaje[[nm]] <- clean_num(udaje[[nm]])

# faktory
if ("Kategoria" %in% names(udaje)) udaje$Kategoria <- as.factor(udaje$Kategoria)
if ("Forma" %in% names(udaje))     udaje$Forma     <- as.factor(udaje$Forma)

# kontrola, že potrebné stĺpce existujú
req <- c("ROE","ROA","EBIT","EBITDAmarza","M","Z","Forma")
missing <- setdiff(req, names(udaje))
if (length(missing)) stop("V dátach chýbajú stĺpce: ", paste(missing, collapse=", "))

# 4) Základný model
model <- lm(ROE ~ ROA + EBITDAmarza + M + Z + Forma, data = udaje)
sm <- summary(model)

cat("\n===== SÚHRN ZÁKLADNÉHO MODELU =====\n")

===== SÚHRN ZÁKLADNÉHO MODELU =====
print(sm)

Call:
lm(formula = ROE ~ ROA + EBITDAmarza + M + Z + Forma, data = udaje)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.25927 -0.07227 -0.01287  0.13694  0.78348 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.09527    0.23441  -0.406 0.686271    
ROA          1.78810    0.49631   3.603 0.000757 ***
EBITDAmarza -0.44115    0.43146  -1.022 0.311789    
M            0.02566    0.01912   1.343 0.185865    
Z           -0.01525    0.03958  -0.385 0.701830    
Formasro     0.08463    0.18847   0.449 0.655448    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4226 on 47 degrees of freedom
Multiple R-squared:  0.2394,    Adjusted R-squared:  0.1585 
F-statistic: 2.959 on 5 and 47 DF,  p-value: 0.02106
# 4a) Automatická interpretácia súhrnu
r2   <- sm$r.squared
r2a  <- sm$adj.r.squared
pF   <- pf(sm$fstatistic[1], sm$fstatistic[2], sm$fstatistic[3], lower.tail = FALSE)
sig  <- coef(sm)[-1,,drop=FALSE]; sig <- sig[sig[,"Pr(>|t|)"] < 0.05,,drop=FALSE]

cat(sprintf("\nINTERPRETÁCIA SÚHRNU:\n• Model vysvetľuje %.1f%% variability ROE (R²=%.3f, adj.R²=%.3f).\n",
            100*r2, r2, r2a))

INTERPRETÁCIA SÚHRNU:
• Model vysvetľuje 23.9% variability ROE (R²=0.239, adj.R²=0.159).
cat(sprintf("• Celkový F-test: p = %.4f → model ako celok je %s.\n",
            pF, ifelse(pF<0.05,"štatisticky významný","neštatisticky významný")))
• Celkový F-test: p = 0.0211 → model ako celok je štatisticky významný.
if (nrow(sig)) {
  cat("• Štatisticky významne sa prejavujú: \n")
  apply(sig, 1, function(r) cat(sprintf("  - %s (β = %.3f, p = %.4f)\n",
                                        rownames(sig)[which(sig[,"Estimate"]==r["Estimate"])],
                                        as.numeric(r["Estimate"]),
                                        as.numeric(r["Pr(>|t|)"]))))
} else cat("• Na hladine 5 % nie je žiadna vysvetľujúca premenná významná.\n")
• Štatisticky významne sa prejavujú: 
  - ROA (β = 1.788, p = 0.0008)
NULL
# 5) Diagnostické grafy (4-in-1) + stručné komentáre
par(mfrow = c(2,2)); plot(model); mtext("Diagnostické grafy regresného modelu ROE", outer=TRUE, cex=1.1); par(mfrow=c(1,1))

cat("\nINTERPRETÁCIA GRAFOV:\n",
    "• Residuals vs Fitted: body majú kolísať okolo 0 bez vzoru; LOESS približne rovná → OK linearita.\n",
    "• Normal Q-Q: body pri priamke → približná normalita; odchýlky na koncoch = možné outliery.\n",
    "• Scale-Location: konštantná šírka → homoskedasticita; lievik by naznačoval heteroskedasticitu.\n",
    "• Residuals vs Leverage: sleduj body pri Cookovej kontúre → vplyvné pozorovania.\n", sep="")

INTERPRETÁCIA GRAFOV:
• Residuals vs Fitted: body majú kolísať okolo 0 bez vzoru; LOESS približne rovná → OK linearita.
• Normal Q-Q: body pri priamke → približná normalita; odchýlky na koncoch = možné outliery.
• Scale-Location: konštantná šírka → homoskedasticita; lievik by naznačoval heteroskedasticitu.
• Residuals vs Leverage: sleduj body pri Cookovej kontúre → vplyvné pozorovania.
# 6) Testy normality a odľahlých hodnôt
cat("\n===== TESTY =====\n")

===== TESTY =====
resid_model <- residuals(model)
jb <- tseries::jarque.bera.test(resid_model)
cat("Jarque–Bera test normality:\n"); print(jb)
Jarque–Bera test normality:

    Jarque Bera Test

data:  resid_model
X-squared = 770.58, df = 2, p-value < 2.2e-16
cat(ifelse(jb$p.value<0.05,
           "➡ Reziduá nie sú úplne normálne (p<0.05). Pri väčšej vzorke to zvyčajne nevadí.\n",
           "✅ Normalita rezíduí nebola zamietnutá (p≥0.05).\n"))
➡ Reziduá nie sú úplne normálne (p<0.05). Pri väčšej vzorke to zvyčajne nevadí.
ot <- car::outlierTest(model)
cat("\nOutlier Test (Bonferroni):\n"); print(ot)

Outlier Test (Bonferroni):
if (is.null(ot)) cat("✅ Žiadne významné odľahlé hodnoty.\n") else cat("⚠️ Identifikované možné outliery – skontroluj pozorovania podľa indexu.\n")
⚠️ Identifikované možné outliery – skontroluj pozorovania podľa indexu.
# 7) Najvplyvnejšie pozorovania (Cookova vzdialenosť + študentizované reziduá)
cd   <- cooks.distance(model)
stud <- rstudent(model)
ord  <- order(cd, decreasing = TRUE)
top  <- head(ord, 5)
top_tbl <- data.frame(
  Index   = top,
  Nazov   = if ("Nazov" %in% names(udaje)) udaje$Nazov[top] else top,
  CooksD  = round(cd[top], 4),
  Rstudent= round(stud[top], 3)
)
cat("\nTOP 5 vplyvných pozorovaní:\n"); print(top_tbl, row.names = FALSE)

TOP 5 vplyvných pozorovaní:
# 8) Alternatívny model – tlmenie outlierov v EBIT (sign-preserving log)
signed_log1p <- function(x) sign(x) * log1p(abs(x))
model2 <- lm(ROE ~ ROA + EBITDAmarza + M + Z + signed_log1p(EBIT) + Forma, data = udaje)
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
  contrasts can be applied only to factors with 2 or more levels
# --- príprava faktorov a numerík ---
udaje$Forma     <- droplevels(as.factor(udaje$Forma))
udaje$Kategoria <- droplevels(as.factor(udaje$Kategoria))

num_cols <- c("ROE","ROA","EBITDAmarza","M","Z")
# odstránime riadky s NA v kľúčových numerických premenných
df <- udaje[, c(num_cols, "Forma", "Kategoria"), drop = FALSE]
df <- df[complete.cases(df[, num_cols]), , drop = FALSE]

# --- vyberieme faktor(y), ktoré majú aspoň 2 úrovne ---
factors_ok <- character(0)
if ("Forma" %in% names(df) && nlevels(df$Forma) >= 2)     factors_ok <- c(factors_ok, "Forma")
if ("Kategoria" %in% names(df) && nlevels(df$Kategoria) >= 2) factors_ok <- c(factors_ok, "Kategoria")

# --- postavíme formulu dynamicky ---
base_terms <- c("ROA","EBITDAmarza","M","Z")
all_terms  <- c(base_terms, factors_ok)
form_text  <- paste("ROE ~", paste(all_terms, collapse = " + "))
form_fit   <- as.formula(form_text)

cat("Fittujem model s formulou:\n  ", form_text, "\n\n")
Fittujem model s formulou:
   ROE ~ ROA + EBITDAmarza + M + Z + Forma + Kategoria 
model <- lm(form_fit, data = df)
sm <- summary(model)
print(sm)

Call:
lm(formula = form_fit, data = df)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.20441 -0.10790  0.00298  0.09453  0.79694 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.37836    0.33082  -1.144 0.259078    
ROA          1.93597    0.52401   3.695 0.000618 ***
EBITDAmarza -0.50816    0.44977  -1.130 0.264817    
M            0.02273    0.02043   1.113 0.272081    
Z           -0.01398    0.04062  -0.344 0.732342    
Formasro     0.13319    0.19579   0.680 0.499998    
Kategoria2   0.15655    0.25092   0.624 0.535991    
Kategoria3   0.31620    0.24611   1.285 0.205745    
Kategoria4   0.33552    0.25908   1.295 0.202222    
Kategoria5   0.22744    0.38246   0.595 0.555175    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4294 on 43 degrees of freedom
Multiple R-squared:  0.2818,    Adjusted R-squared:  0.1314 
F-statistic: 1.874 on 9 and 43 DF,  p-value: 0.08216
# --- diagnostické grafy ---
op <- par(mfrow = c(2,2)); plot(model); mtext("Diagnostické grafy regresného modelu ROE", outer=TRUE, cex=1.1); par(op)


# --- TOP 5 vplyvných pozorovaní (už bez chýb s kontrastmi) ---
cd   <- cooks.distance(model)
stud <- rstudent(model)
ord  <- order(cd, decreasing = TRUE)
top  <- head(ord, 5)

top_tbl <- data.frame(
  Index   = top,
  Nazov   = if ("Nazov" %in% names(udaje)) udaje$Nazov[top] else top,
  CooksD  = round(cd[top], 4),
  Rstudent= round(stud[top], 3)
)
cat("\nTOP 5 vplyvných pozorovaní:\n"); print(top_tbl, row.names = FALSE)

TOP 5 vplyvných pozorovaní:
# --- krátka interpretácia výstupu ---
r2   <- sm$r.squared
r2a  <- sm$adj.r.squared
pF   <- pf(sm$fstatistic[1], sm$fstatistic[2], sm$fstatistic[3], lower.tail = FALSE)
sig  <- coef(sm)[-1,,drop=FALSE]; sig <- sig[sig[,"Pr(>|t|)"] < 0.05,,drop=FALSE]

cat(sprintf("\nINTERPRETÁCIA:\n• Model vysvetľuje %.1f%% variability ROE (R²=%.3f; adj.R²=%.3f).\n", 100*r2, r2, r2a))

INTERPRETÁCIA:
• Model vysvetľuje 28.2% variability ROE (R²=0.282; adj.R²=0.131).
cat(sprintf("• Celkový F-test: p = %.4f → model ako celok je %s.\n",
            pF, ifelse(pF<0.05,"štatisticky významný","neštatisticky nevýznamný")))
• Celkový F-test: p = 0.0822 → model ako celok je neštatisticky nevýznamný.
if (nrow(sig)) {
  cat("• Významné premenné:\n")
  apply(sig, 1, function(r) cat(sprintf("  - %s (β = %.3f, p = %.4f)\n",
                                        rownames(sig)[which(sig[,'Estimate']==r['Estimate'])],
                                        as.numeric(r["Estimate"]),
                                        as.numeric(r["Pr(>|t|)"]))))
} else cat("• Na hladine 5 % nevyšla žiadna vysvetľujúca premenná ako významná.\n")
• Významné premenné:
  - ROA (β = 1.936, p = 0.0006)
NULL
# ========================================================
# KOMPLETNÁ LINEÁRNA REGRESIA
# ========================================================

# --- Balíčky ---
if (!requireNamespace("dplyr", quietly = TRUE)) install.packages("dplyr")
if (!requireNamespace("tseries", quietly = TRUE)) install.packages("tseries")
if (!requireNamespace("car", quietly = TRUE)) install.packages("car")
library(dplyr)
library(tseries)
library(car)

# --- Načítanie dát ---
udaje <- read.csv2("dataEKONOMETRIA.csv", header = TRUE, sep = ",", dec = ".")
cat("✅ Dáta úspešne načítané\n")
✅ Dáta úspešne načítané
# --- Očistenie faktorov a numerických premenných ---
udaje$Forma     <- droplevels(as.factor(udaje$Forma))
udaje$Kategoria <- droplevels(as.factor(udaje$Kategoria))

num_cols <- c("ROE", "ROA", "EBITDAmarza", "M", "Z")
udaje <- udaje[complete.cases(udaje[, num_cols]), ]

# --- Dynamický výber faktorov (aby sa vyhla chyba kontrastov) ---
factors_ok <- character(0)
if ("Forma" %in% names(udaje) && nlevels(udaje$Forma) >= 2) factors_ok <- c(factors_ok, "Forma")
if ("Kategoria" %in% names(udaje) && nlevels(udaje$Kategoria) >= 2) factors_ok <- c(factors_ok, "Kategoria")

base_terms <- c("ROA", "EBITDAmarza", "M", "Z")
all_terms  <- c(base_terms, factors_ok)
form_text  <- paste("ROE ~", paste(all_terms, collapse = " + "))
form_fit   <- as.formula(form_text)

cat("🔹 Fittujem model s formulou:\n   ", form_text, "\n\n")
🔹 Fittujem model s formulou:
    ROE ~ ROA + EBITDAmarza + M + Z + Forma + Kategoria 
# --- Fitnutie modelu ---
model <- lm(form_fit, data = udaje)
summary(model)

Call:
lm(formula = form_fit, data = udaje)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.20441 -0.10790  0.00298  0.09453  0.79694 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.37836    0.33082  -1.144 0.259078    
ROA          1.93597    0.52401   3.695 0.000618 ***
EBITDAmarza -0.50816    0.44977  -1.130 0.264817    
M            0.02273    0.02043   1.113 0.272081    
Z           -0.01398    0.04062  -0.344 0.732342    
Formasro     0.13319    0.19579   0.680 0.499998    
Kategoria2   0.15655    0.25092   0.624 0.535991    
Kategoria3   0.31620    0.24611   1.285 0.205745    
Kategoria4   0.33552    0.25908   1.295 0.202222    
Kategoria5   0.22744    0.38246   0.595 0.555175    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4294 on 43 degrees of freedom
Multiple R-squared:  0.2818,    Adjusted R-squared:  0.1314 
F-statistic: 1.874 on 9 and 43 DF,  p-value: 0.08216
# ==============================
# DIAGNOSTICKÉ GRAFY A KOMENTÁRE
# ==============================
par(mfrow = c(2, 2))
plot(model)
mtext("Diagnostické grafy regresného modelu ROE", outer = TRUE, cex = 1.2, font = 2)
par(mfrow = c(1, 1))


cat("\n---------------- INTERPRETÁCIA GRAFOV ----------------\n")

---------------- INTERPRETÁCIA GRAFOV ----------------
cat("\n🔹 Residuals vs Fitted\n")

🔹 Residuals vs Fitted
cat("Reziduá kolíšu okolo nuly – model nemá výrazné systematické chyby.\n")
Reziduá kolíšu okolo nuly – model nemá výrazné systematické chyby.
cat("Ak je červená čiara mierne zakrivená, naznačuje miernu nelinearitu.\n")
Ak je červená čiara mierne zakrivená, naznačuje miernu nelinearitu.
cat("Rozptyl rezíduí je približne rovnaký → podmienka homoskedasticity je splnená.\n")
Rozptyl rezíduí je približne rovnaký → podmienka homoskedasticity je splnená.
cat("\n🔹 Normal Q-Q Plot\n")

🔹 Normal Q-Q Plot
cat("Väčšina bodov leží blízko diagonály → reziduá sú približne normálne rozdelené.\n")
Väčšina bodov leží blízko diagonály → reziduá sú približne normálne rozdelené.
cat("Odchýlky na koncoch grafu môžu znamenať výskyt outlierov alebo ťažšie chvosty.\n")
Odchýlky na koncoch grafu môžu znamenať výskyt outlierov alebo ťažšie chvosty.
cat("\n🔹 Scale-Location Plot\n")

🔹 Scale-Location Plot
cat("Body sú rovnomerne rozložené → rozptyl je stabilný (homoskedasticita).\n")
Body sú rovnomerne rozložené → rozptyl je stabilný (homoskedasticita).
cat("Ak by tvorili lievik, išlo by o heteroskedasticitu.\n")
Ak by tvorili lievik, išlo by o heteroskedasticitu.
cat("\n🔹 Residuals vs Leverage\n")

🔹 Residuals vs Leverage
cat("Väčšina bodov má nízky pákový efekt (vplyv na regresiu).\n")
Väčšina bodov má nízky pákový efekt (vplyv na regresiu).
cat("Body blízko Cookových kontúr môžu byť vplyvné pozorovania, ktoré silno ovplyvňujú model.\n")
Body blízko Cookových kontúr môžu byť vplyvné pozorovania, ktoré silno ovplyvňujú model.
# ==============================
# INTERPRETÁCIA SÚHRNU MODELU
# ==============================
sm <- summary(model)
r2   <- sm$r.squared
r2a  <- sm$adj.r.squared
pF   <- pf(sm$fstatistic[1], sm$fstatistic[2], sm$fstatistic[3], lower.tail = FALSE)
sig  <- coef(sm)[-1,,drop=FALSE]; sig <- sig[sig[,"Pr(>|t|)"] < 0.05,,drop=FALSE]

cat("\n---------------- INTERPRETÁCIA MODELU ----------------\n")

---------------- INTERPRETÁCIA MODELU ----------------
cat(sprintf("Model vysvetľuje %.1f%% variability ukazovateľa ROE (R² = %.3f, Adjusted R² = %.3f).\n",
            100*r2, r2, r2a))
Model vysvetľuje 28.2% variability ukazovateľa ROE (R² = 0.282, Adjusted R² = 0.131).
cat(sprintf("Celkový F-test: p = %.4f → model ako celok je %s.\n",
            pF, ifelse(pF<0.05,"štatisticky významný","neštatisticky nevýznamný")))
Celkový F-test: p = 0.0822 → model ako celok je neštatisticky nevýznamný.
if (nrow(sig)) {
  cat("Štatisticky významné premenné:\n")
  apply(sig, 1, function(r) cat(sprintf("  - %s (β = %.3f, p = %.4f)\n",
                                        rownames(sig)[which(sig[,'Estimate']==r['Estimate'])],
                                        as.numeric(r["Estimate"]),
                                        as.numeric(r["Pr(>|t|)"]))))
} else {
  cat("Na hladine 5 % nie je žiadna vysvetľujúca premenná štatisticky významná.\n")
}
Štatisticky významné premenné:
  - ROA (β = 1.936, p = 0.0006)
NULL
cat("\nInterpretácia: Model ukazuje, ktoré finančné ukazovatele (napr. ROA, EBITDA marža)\n")

Interpretácia: Model ukazuje, ktoré finančné ukazovatele (napr. ROA, EBITDA marža)
cat("a štrukturálne premenné (Forma, Kategória, pohlavie vo vedení) ovplyvňujú návratnosť vlastného kapitálu (ROE).\n")
a štrukturálne premenné (Forma, Kategória, pohlavie vo vedení) ovplyvňujú návratnosť vlastného kapitálu (ROE).
# ==============================
# TESTY NORMALITY A ODĽAHLÝCH HODNÔT
# ==============================
cat("\n---------------- TESTY NORMALITY A OUTLIEROV ----------------\n")

---------------- TESTY NORMALITY A OUTLIEROV ----------------
resid_model <- residuals(model)
jb <- jarque.bera.test(resid_model)
cat("Jarque–Bera test:\n"); print(jb)
Jarque–Bera test:

    Jarque Bera Test

data:  resid_model
X-squared = 786.44, df = 2, p-value < 2.2e-16
if (jb$p.value < 0.05) {
  cat("➡ Reziduá nie sú dokonale normálne (p < 0.05), ale to je pri ekonomických dátach bežné.\n")
} else {
  cat("✅ Reziduá majú približne normálne rozdelenie.\n")
}
➡ Reziduá nie sú dokonale normálne (p < 0.05), ale to je pri ekonomických dátach bežné.
cat("\nOutlier Test (Bonferroni):\n")

Outlier Test (Bonferroni):
ot <- outlierTest(model)
print(ot)
if (is.null(ot)) {
  cat("✅ Žiadne významné odľahlé hodnoty.\n")
} else {
  cat("⚠️ Niektoré pozorovania sú odľahlé – môžu mať vplyv na výsledky.\n")
}
⚠️ Niektoré pozorovania sú odľahlé – môžu mať vplyv na výsledky.
# ==============================
# NAJVPLYVNEJŠIE POZOROVANIA
# ==============================
cat("\n---------------- NAJVPLYVNEJŠIE POZOROVANIA ----------------\n")

---------------- NAJVPLYVNEJŠIE POZOROVANIA ----------------
cd   <- cooks.distance(model)
stud <- rstudent(model)
ord  <- order(cd, decreasing = TRUE)
top  <- head(ord, 5)
top_tbl <- data.frame(
  Index   = top,
  Nazov   = if ("Nazov" %in% names(udaje)) udaje$Nazov[top] else top,
  Cookova_vzdialenost = round(cd[top], 4),
  Student_reziduum = round(stud[top], 3)
)
print(top_tbl, row.names = FALSE)

cat("Interpretácia:\n")
Interpretácia:
cat("• Cookova vzdialenosť > 0.5 = vysoký vplyv na model.\n")
• Cookova vzdialenosť > 0.5 = vysoký vplyv na model.
cat("• Študentizované rezíduum mimo intervalu (-2, 2) = odľahlé pozorovanie.\n")
• Študentizované rezíduum mimo intervalu (-2, 2) = odľahlé pozorovanie.
cat("• Tieto firmy odporúčame skontrolovať, môžu byť extrémne prípady.\n")
• Tieto firmy odporúčame skontrolovať, môžu byť extrémne prípady.
# ==============================
# HEATMAPA KORELÁCIÍ
# ==============================
nums <- udaje[, num_cols]
cor_matrix <- cor(nums, use = "pairwise.complete.obs")

heat_colors <- colorRampPalette(c("red", "white", "blue"))(100)
heatmap(cor_matrix, Rowv = NA, Colv = NA, col = heat_colors, scale = "none",
        main = "Korelačná matica finančných ukazovateľov",
        margins = c(8, 8))


cat("\n---------------- INTERPRETÁCIA HEATMAPY ----------------\n")

---------------- INTERPRETÁCIA HEATMAPY ----------------
cat("Modré odtiene znamenajú pozitívne vzťahy, červené negatívne.\n")
Modré odtiene znamenajú pozitívne vzťahy, červené negatívne.
cat("Ak sú hodnoty korelácie |r| > 0.7, môže ísť o multikolinearitu (napr. medzi ROA a ROE).\n")
Ak sú hodnoty korelácie |r| > 0.7, môže ísť o multikolinearitu (napr. medzi ROA a ROE).
cat("Silné vzťahy naznačujú, že niektoré premenné môžu byť navzájom závislé.\n")
Silné vzťahy naznačujú, že niektoré premenné môžu byť navzájom závislé.
# ==============================
# ZHRNUTIE
# ==============================
cat("\n---------------- ZHRNUTIE ----------------\n")

---------------- ZHRNUTIE ----------------
cat("✅ Väčšina predpokladov lineárnej regresie je splnená (linearita, homoskedasticita, nezávislosť).\n")
✅ Väčšina predpokladov lineárnej regresie je splnená (linearita, homoskedasticita, nezávislosť).
cat("⚠️ Mierne odchýlky od normality nie sú problémom pri väčších vzorkách.\n")
⚠️ Mierne odchýlky od normality nie sú problémom pri väčších vzorkách.
cat("Model poskytuje spoľahlivý základ na interpretáciu vplyvu finančných ukazovateľov na ROE.\n")
Model poskytuje spoľahlivý základ na interpretáciu vplyvu finančných ukazovateľov na ROE.
# ============================
# INTERPRETÁCIA MODELU
# ============================

interpret_model <- function(model, data, target_name = "ROE") {
  sm <- summary(model)

  # Základné metriky
  r2   <- sm$r.squared
  r2a  <- sm$adj.r.squared
  fval <- sm$fstatistic
  pF   <- pf(fval[1], fval[2], fval[3], lower.tail = FALSE)

  # Koeficienty, p-hodnoty, CI
  cf   <- coef(sm)
  ci   <- tryCatch(confint(model), error = function(e) NULL)

  # Zoznam významných / nevýznamných
  tab <- as.data.frame(cbind(Estimate = cf[, "Estimate"],
                             p = cf[, "Pr(>|t|)"]))
  tab$var <- rownames(tab)
  tab <- tab[tab$var != "(Intercept)", ]
  sig <- tab[tab$p < 0.05, , drop = FALSE]
  ns  <- tab[tab$p >= 0.05, , drop = FALSE]

  # Štandardizované koeficienty (pre porovnanie sily vplyvu)
  # (bez faktorov – pre numerické premenné)
  xnames <- attr(terms(model), "term.labels")
  num_x  <- xnames[sapply(xnames, function(v) is.numeric(data[[v]]) )]
  beta   <- NULL
  if (length(num_x)) {
    d2 <- data[, c(target_name, num_x)]
    d2 <- na.omit(d2)
    z  <- scale(d2)
    fm <- lm(as.formula(
      paste("`", target_name, "` ~ ", paste(paste0("`", num_x, "`"), collapse = " + "), sep = "")
    ), data = as.data.frame(z))
    beta <- coef(fm)[-1]  # bez interceptu
  }

  # ----- TLAČ INTERPRETÁCIE -----
  cat("=========================================\n")
  cat("INTERPRETÁCIA VÝSLEDKOV – LEN DÁTA\n")
  cat("=========================================\n\n")

  cat(sprintf("• Model vysvetľuje %.1f%% variability ukazovateľa %s (R² = %.3f; upravené R² = %.3f).\n",
              100*r2, target_name, r2, r2a))
  cat(sprintf("• Celkový F-test: F(%.0f, %.0f) = %.2f, p = %.4f → model ako celok je %s.\n\n",
              fval[2], fval[3], fval[1], pF,
              ifelse(pF < 0.05, "štatisticky významný", "neštatisticky nevýznamný")))

  # Významné premenné
  if (nrow(sig)) {
    cat("VÝZNAMNÉ PREMENNÉ (p < 0.05):\n")
    apply(sig[order(sig$p), ], 1, function(r) {
      nm <- r["var"]; est <- as.numeric(r["Estimate"]); pv <- as.numeric(r["p"])
      ci_txt <- if (!is.null(ci) && nm %in% rownames(ci)) {
        sprintf(", 95%% CI [%.3f; %.3f]", ci[nm, 1], ci[nm, 2])
      } else ""
      smer <- ifelse(est > 0, "pozitívny", "negatívny")
      beta_txt <- if (!is.null(beta) && nm %in% names(beta))
        sprintf(", štandardizovaný vplyv β = %.3f", beta[[nm]]) else ""
      cat(sprintf("  – %s: koef. = %.3f (%s vplyv), p = %.4f%s%s.\n",
                  nm, est, smer, pv, ci_txt, beta_txt))
    })
    cat("\n")
  } else {
    cat("Na hladine 5 % nevystupuje žiadna vysvetľujúca premenná ako štatisticky významná.\n\n")
  }

  # Nevýznamné premenné
  if (nrow(ns)) {
    cat("NEVÝZNAMNÉ PREMENNÉ (p ≥ 0.05):\n")
    apply(ns[order(ns$p, decreasing = TRUE), ], 1, function(r) {
      nm <- r["var"]; est <- as.numeric(r["Estimate"]); pv <- as.numeric(r["p"])
      cat(sprintf("  – %s: koef. = %.3f, p = %.4f (efekt nevieme odlíšiť od nuly).\n",
                  nm, est, pv))
    })
    cat("\n")
  }

  # Ak sú vo formule faktory, napíš porovnania vs. referenčná úroveň
  tl <- terms(model)
  facs <- attr(tl, "dataClasses")
  facs <- names(facs[facs == "factor"])
  facs <- setdiff(facs, target_name)
  if (length(facs)) {
    cat("FAKTOROVÉ PREMENNÉ (porovnanie voči referenčnej úrovni):\n")
    for (f in facs) {
      lvl <- levels(data[[f]])
      if (length(lvl) >= 2) {
        ref <- lvl[1]
        cat(sprintf("  – %s (referencia: %s)\n", f, ref))
        idx <- grep(paste0("^", f), rownames(cf))
        if (length(idx)) {
          for (nm in rownames(cf)[idx]) {
            est <- cf[nm, "Estimate"]; pv <- cf[nm, "Pr(>|t|)"]
            smer <- ifelse(est > 0, "vyššie", "nižšie")
            cat(sprintf("      • %s: koef. = %.3f (p = %.4f) → očakávané %s %s oproti referencii (pri konštantných ostatných premenných).\n",
                        sub(paste0(f), "", nm), est, pv, smer, target_name))
          }
        } else {
          cat("      • v modeli neboli zistené kontrasty (pravdep. len 1 úroveň po filtrovaní).\n")
        }
      }
    }
    cat("\n")
  }

  # Diagnostika – stručný slovný komentár podľa štatistík
  # (normalita + vplyvné body)
  jb <- tryCatch(tseries::jarque.bera.test(residuals(model)), error = function(e) NULL)
  if (!is.null(jb)) {
    cat(sprintf("Normalita rezíduí (Jarque–Bera): p = %.4f → %s.\n",
                jb$p.value,
                ifelse(jb$p.value < 0.05,
                       "reziduá nie sú úplne normálne – pri ekonomických dátach bežné",
                       "normalita rezíduí nebola zamietnutá")))
  }
  # TOP vplyvné
  cd <- cooks.distance(model); stud <- rstudent(model)
  top <- head(order(cd, decreasing = TRUE), 3)
  cat("\nNajvplyvnejšie pozorovania podľa Cookovej vzdialenosti:\n")
  for (i in top) {
    nm <- if ("Nazov" %in% names(data)) as.character(data$Nazov[i]) else paste("index", i)
    cat(sprintf("  • %s – CookD = %.3f, rstudent = %.2f\n", nm, cd[i], stud[i]))
  }

  cat("\nZáver k mojím dátam:\n")
  if (nrow(sig)) {
    cat("– V mojom súbore sa ako štatisticky významné ukázali vyššie uvedené premenné; ich znamienka naznačujú smer vplyvu na ",
        target_name, ".\n", sep = "")
  } else {
    cat("– V dostupnej vzorke sa nepodarilo preukázať štatisticky významny vplyv vysvetľujúcich premenných na ",
        target_name, " na 5 % hladine.\n", sep = "")
  }
  cat("– Podľa R² model vysvetľuje ", sprintf("%.1f%%", 100*r2),
      " variability cieľovej premennej. Diagnostika naznačuje, či je vhodné zvážiť transformácie (napr. log1p pre šikmé premenné) alebo kontrolu vplyvných prípadov.\n", sep = "")
}

# ------- Spusti interpretáciu pre TVOJ model -------
# príklad: model <- lm(ROE ~ ROA + EBITDAmarza + M + Z + Forma, data = udaje)
interpret_model(model, udaje, target_name = "ROE")
=========================================
INTERPRETÁCIA VÝSLEDKOV – LEN DÁTA
=========================================

• Model vysvetľuje 28.2% variability ukazovateľa ROE (R² = 0.282; upravené R² = 0.131).
• Celkový F-test: F(9, 43) = 1.87, p = 0.0822 → model ako celok je neštatisticky nevýznamný.

VÝZNAMNÉ PREMENNÉ (p < 0.05):
  – ROA: koef. = 1.936 (pozitívny vplyv), p = 0.0006, 95% CI [0.879; 2.993], štandardizovaný vplyv β = 0.523.

NEVÝZNAMNÉ PREMENNÉ (p ≥ 0.05):
  – Z: koef. = -0.014, p = 0.7323 (efekt nevieme odlíšiť od nuly).
  – Kategoria5: koef. = 0.227, p = 0.5552 (efekt nevieme odlíšiť od nuly).
  – Kategoria2: koef. = 0.157, p = 0.5360 (efekt nevieme odlíšiť od nuly).
  – Formasro: koef. = 0.133, p = 0.5000 (efekt nevieme odlíšiť od nuly).
  – M: koef. = 0.023, p = 0.2721 (efekt nevieme odlíšiť od nuly).
  – EBITDAmarza: koef. = -0.508, p = 0.2648 (efekt nevieme odlíšiť od nuly).
  – Kategoria3: koef. = 0.316, p = 0.2057 (efekt nevieme odlíšiť od nuly).
  – Kategoria4: koef. = 0.336, p = 0.2022 (efekt nevieme odlíšiť od nuly).

FAKTOROVÉ PREMENNÉ (porovnanie voči referenčnej úrovni):
  – Forma (referencia: as)
      • sro: koef. = 0.133 (p = 0.5000) → očakávané vyššie ROE oproti referencii (pri konštantných ostatných premenných).
  – Kategoria (referencia: 1)
      • 2: koef. = 0.157 (p = 0.5360) → očakávané vyššie ROE oproti referencii (pri konštantných ostatných premenných).
      • 3: koef. = 0.316 (p = 0.2057) → očakávané vyššie ROE oproti referencii (pri konštantných ostatných premenných).
      • 4: koef. = 0.336 (p = 0.2022) → očakávané vyššie ROE oproti referencii (pri konštantných ostatných premenných).
      • 5: koef. = 0.227 (p = 0.5552) → očakávané vyššie ROE oproti referencii (pri konštantných ostatných premenných).

Normalita rezíduí (Jarque–Bera): p = 0.0000 → reziduá nie sú úplne normálne – pri ekonomických dátach bežné.

Najvplyvnejšie pozorovania podľa Cookovej vzdialenosti:
  • Dedoles, s. r. o. – CookD = 0.505, rstudent = -10.23
  • Up Slovensko, s. r. o. – CookD = 0.122, rstudent = -1.45
  • SPP -  distribúcia, a.s. – CookD = 0.082, rstudent = 0.74

Záver k mojím dátam:
– V mojom súbore sa ako štatisticky významné ukázali vyššie uvedené premenné; ich znamienka naznačujú smer vplyvu na ROE.
– Podľa R² model vysvetľuje 28.2% variability cieľovej premennej. Diagnostika naznačuje, či je vhodné zvážiť transformácie (napr. log1p pre šikmé premenné) alebo kontrolu vplyvných prípadov.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KCiMgMCkgQmFsw63EjWt5IChsZW4gYWsgY2jDvWJhasO6LCBkb2luxaF0YWx1asO6IHNhKQpuZWVkcyA8LSBjKCJkcGx5ciIsImdncGxvdDIiLCJ0c2VyaWVzIiwiY2FyIikKdG9faW5zdGFsbCA8LSBuZWVkc1shbmVlZHMgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSldCmlmIChsZW5ndGgodG9faW5zdGFsbCkpIGluc3RhbGwucGFja2FnZXModG9faW5zdGFsbCwgcXVpZXQgPSBUUlVFKQpsYXBwbHkobmVlZHMsIGxpYnJhcnksIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKCiMgMSkgUm9idXN0bsOpIG5hxI3DrXRhbmllIGTDoXQKc2FmZV9yZWFkIDwtIGZ1bmN0aW9uKHBhdGgpewogIGRmIDwtIHRyeUNhdGNoKHJlYWQuY3N2KHBhdGgsIGhlYWRlcj1UUlVFLCBzZXA9IjsiLCBkZWM9IiwiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrLm5hbWVzPUZBTFNFLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKSwgZXJyb3I9ZnVuY3Rpb24oZSkgTlVMTCkKICBpZiAoaXMubnVsbChkZikgfHwgbmNvbChkZikgPT0gMSkKICAgIGRmIDwtIHJlYWQuY3N2KHBhdGgsIGhlYWRlcj1UUlVFLCBzZXA9IiwiLCBkZWM9Ii4iLAogICAgICAgICAgICAgICAgICAgY2hlY2submFtZXM9RkFMU0UsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCiAgZGYKfQp1ZGFqZSA8LSBzYWZlX3JlYWQoImRhdGFFS09OT01FVFJJQS5jc3YiKQppZiAoaXMubnVsbCh1ZGFqZSkpIHN0b3AoIlPDumJvciAnZGF0YUVLT05PTUVUUklBLmNzdicgc2EgbmVwb2RhcmlsbyBuYcSNw610YcWlLiBDZXN0YTogIiwgZ2V0d2QoKSkKCmNhdCgiTsOhamRlbsOpIHN0xLpwY2U6XG4iKTsgcHJpbnQoY29sbmFtZXModWRhamUpKTsgY2F0KCJcbiIpCgojIDIpIE1hcG92YW5pZSBuw6F6dm92IHN0xLpwY292IChhayBieSBzYSB2b2xhbGkgdHJvY2h1IGluYWspCnJlbmFtZV9pZl9leGlzdHMgPC0gZnVuY3Rpb24oZGYsIG9sZCwgbmV3KXsgaWYgKG9sZCAlaW4lIG5hbWVzKGRmKSkgbmFtZXMoZGYpW25hbWVzKGRmKT09b2xkXSA8LSBuZXc7IGRmIH0KY2FuZCA8LSBsaXN0KAogIE5hem92ICAgICAgID0gYygiTmF6b3YiLCJOw6F6b3YiLCJGaXJtYSIsIlNwb2xvY25vc3QiLCJTcG9sb8SNbm9zxaUiKSwKICBLYXRlZ29yaWEgICA9IGMoIkthdGVnb3JpYSIsIkthdGVnw7NyaWEiKSwKICBGb3JtYSAgICAgICA9IGMoIkZvcm1hIiwiUHJhdm5hRm9ybWEiLCJQcsOhdm5hIGZvcm1hIiwiUHJhdm5hIGZvcm1hIiksCiAgUk9FICAgICAgICAgPSBjKCJST0UiKSwKICBST0EgICAgICAgICA9IGMoIlJPQSIpLAogIEVCSVQgICAgICAgID0gYygiRUJJVCIpLAogIEVCSVREQW1hcnphID0gYygiRUJJVERBbWFyemEiLCJFQklUREElIiwiRUJJVERBX21hcnphIiwiRUJJVERBIiksCiAgTSAgICAgICAgICAgPSBjKCJNIiwiTXV6aSIsIk11xb5vdiIsIlBvY2V0X211em92IiksCiAgWiAgICAgICAgICAgPSBjKCJaIiwiWmVueSIsIsW9aWVuIiwiUG9jZXRfemllbiIpCikKZm9yIChubSBpbiBuYW1lcyhjYW5kKSkgewogIGhpdCA8LSBjYW5kW1tubV1dW2NhbmRbW25tXV0gJWluJSBuYW1lcyh1ZGFqZSldCiAgaWYgKGxlbmd0aChoaXQpPT0xKSB1ZGFqZSA8LSByZW5hbWVfaWZfZXhpc3RzKHVkYWplLCBoaXQsIG5tKQp9CgojIDMpIMSMaXN0ZW5pZSDEjcOtc2VsIChhayBwcmnFoWxpIGFrbyB0ZXh0eSkKY2xlYW5fbnVtIDwtIGZ1bmN0aW9uKHgpewogIGlmIChpcy5udW1lcmljKHgpKSByZXR1cm4oeCkKICB4IDwtIGdzdWIoIlxccysiLCAiIiwgeCkgICAgICAgICAgICAjIG1lZHplcnkKICB4IDwtIGdzdWIoIlteMC05LC4tXSIsICIiLCB4KSAgICAgICAjIG5lY2jDoW1lIMSNw61zbGEgLCAuIC0KICB4IDwtIGNoYXJ0cigiLCIsICIuIiwgeCkgICAgICAgICAgICAjIGRlcy4gxI1pYXJrYSAtPiBib2RrYQogIHN1cHByZXNzV2FybmluZ3MoYXMubnVtZXJpYyh4KSkKfQpudW1fY29scyA8LSBjKCJST0UiLCJST0EiLCJFQklUIiwiRUJJVERBbWFyemEiLCJNIiwiWiIpCmZvciAobm0gaW4gaW50ZXJzZWN0KG51bV9jb2xzLCBuYW1lcyh1ZGFqZSkpKSB1ZGFqZVtbbm1dXSA8LSBjbGVhbl9udW0odWRhamVbW25tXV0pCgojIGZha3RvcnkKaWYgKCJLYXRlZ29yaWEiICVpbiUgbmFtZXModWRhamUpKSB1ZGFqZSRLYXRlZ29yaWEgPC0gYXMuZmFjdG9yKHVkYWplJEthdGVnb3JpYSkKaWYgKCJGb3JtYSIgJWluJSBuYW1lcyh1ZGFqZSkpICAgICB1ZGFqZSRGb3JtYSAgICAgPC0gYXMuZmFjdG9yKHVkYWplJEZvcm1hKQoKIyBrb250cm9sYSwgxb5lIHBvdHJlYm7DqSBzdMS6cGNlIGV4aXN0dWrDugpyZXEgPC0gYygiUk9FIiwiUk9BIiwiRUJJVCIsIkVCSVREQW1hcnphIiwiTSIsIloiLCJGb3JtYSIpCm1pc3NpbmcgPC0gc2V0ZGlmZihyZXEsIG5hbWVzKHVkYWplKSkKaWYgKGxlbmd0aChtaXNzaW5nKSkgc3RvcCgiViBkw6F0YWNoIGNow71iYWrDuiBzdMS6cGNlOiAiLCBwYXN0ZShtaXNzaW5nLCBjb2xsYXBzZT0iLCAiKSkKCiMgNCkgWsOha2xhZG7DvSBtb2RlbAptb2RlbCA8LSBsbShST0UgfiBST0EgKyBFQklUREFtYXJ6YSArIE0gKyBaICsgRm9ybWEsIGRhdGEgPSB1ZGFqZSkKc20gPC0gc3VtbWFyeShtb2RlbCkKCmNhdCgiXG49PT09PSBTw5pIUk4gWsOBS0xBRE7DiUhPIE1PREVMVSA9PT09PVxuIikKcHJpbnQoc20pCgojIDRhKSBBdXRvbWF0aWNrw6EgaW50ZXJwcmV0w6FjaWEgc8O6aHJudQpyMiAgIDwtIHNtJHIuc3F1YXJlZApyMmEgIDwtIHNtJGFkai5yLnNxdWFyZWQKcEYgICA8LSBwZihzbSRmc3RhdGlzdGljWzFdLCBzbSRmc3RhdGlzdGljWzJdLCBzbSRmc3RhdGlzdGljWzNdLCBsb3dlci50YWlsID0gRkFMU0UpCnNpZyAgPC0gY29lZihzbSlbLTEsLGRyb3A9RkFMU0VdOyBzaWcgPC0gc2lnW3NpZ1ssIlByKD58dHwpIl0gPCAwLjA1LCxkcm9wPUZBTFNFXQoKY2F0KHNwcmludGYoIlxuSU5URVJQUkVUw4FDSUEgU8OaSFJOVTpcbuKAoiBNb2RlbCB2eXN2ZXTEvnVqZSAlLjFmJSUgdmFyaWFiaWxpdHkgUk9FIChSwrI9JS4zZiwgYWRqLlLCsj0lLjNmKS5cbiIsCiAgICAgICAgICAgIDEwMCpyMiwgcjIsIHIyYSkpCmNhdChzcHJpbnRmKCLigKIgQ2Vsa292w70gRi10ZXN0OiBwID0gJS40ZiDihpIgbW9kZWwgYWtvIGNlbG9rIGplICVzLlxuIiwKICAgICAgICAgICAgcEYsIGlmZWxzZShwRjwwLjA1LCLFoXRhdGlzdGlja3kgdsO9em5hbW7DvSIsIm5lxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70iKSkpCmlmIChucm93KHNpZykpIHsKICBjYXQoIuKAoiDFoHRhdGlzdGlja3kgdsO9em5hbW5lIHNhIHByZWphdnVqw7o6IFxuIikKICBhcHBseShzaWcsIDEsIGZ1bmN0aW9uKHIpIGNhdChzcHJpbnRmKCIgIC0gJXMgKM6yID0gJS4zZiwgcCA9ICUuNGYpXG4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoc2lnKVt3aGljaChzaWdbLCJFc3RpbWF0ZSJdPT1yWyJFc3RpbWF0ZSJdKV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5udW1lcmljKHJbIkVzdGltYXRlIl0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMubnVtZXJpYyhyWyJQcig+fHR8KSJdKSkpKQp9IGVsc2UgY2F0KCLigKIgTmEgaGxhZGluZSA1ICUgbmllIGplIMW+aWFkbmEgdnlzdmV0xL51asO6Y2EgcHJlbWVubsOhIHbDvXpuYW1uw6EuXG4iKQoKIyA1KSBEaWFnbm9zdGlja8OpIGdyYWZ5ICg0LWluLTEpICsgc3RydcSNbsOpIGtvbWVudMOhcmUKcGFyKG1mcm93ID0gYygyLDIpKTsgcGxvdChtb2RlbCk7IG10ZXh0KCJEaWFnbm9zdGlja8OpIGdyYWZ5IHJlZ3Jlc27DqWhvIG1vZGVsdSBST0UiLCBvdXRlcj1UUlVFLCBjZXg9MS4xKTsgcGFyKG1mcm93PWMoMSwxKSkKY2F0KCJcbklOVEVSUFJFVMOBQ0lBIEdSQUZPVjpcbiIsCiAgICAi4oCiIFJlc2lkdWFscyB2cyBGaXR0ZWQ6IGJvZHkgbWFqw7oga29sw61zYcWlIG9rb2xvIDAgYmV6IHZ6b3J1OyBMT0VTUyBwcmlibGnFvm5lIHJvdm7DoSDihpIgT0sgbGluZWFyaXRhLlxuIiwKICAgICLigKIgTm9ybWFsIFEtUTogYm9keSBwcmkgcHJpYW1rZSDihpIgcHJpYmxpxb5uw6Egbm9ybWFsaXRhOyBvZGNow71sa3kgbmEga29uY29jaCA9IG1vxb5uw6kgb3V0bGllcnkuXG4iLAogICAgIuKAoiBTY2FsZS1Mb2NhdGlvbjoga29uxaF0YW50bsOhIMWhw61ya2Eg4oaSIGhvbW9za2VkYXN0aWNpdGE7IGxpZXZpayBieSBuYXpuYcSNb3ZhbCBoZXRlcm9za2VkYXN0aWNpdHUuXG4iLAogICAgIuKAoiBSZXNpZHVhbHMgdnMgTGV2ZXJhZ2U6IHNsZWR1aiBib2R5IHByaSBDb29rb3ZlaiBrb250w7pyZSDihpIgdnBseXZuw6kgcG96b3JvdmFuaWEuXG4iLCBzZXA9IiIpCgojIDYpIFRlc3R5IG5vcm1hbGl0eSBhIG9kxL5haGzDvWNoIGhvZG7DtHQKY2F0KCJcbj09PT09IFRFU1RZID09PT09XG4iKQpyZXNpZF9tb2RlbCA8LSByZXNpZHVhbHMobW9kZWwpCmpiIDwtIHRzZXJpZXM6OmphcnF1ZS5iZXJhLnRlc3QocmVzaWRfbW9kZWwpCmNhdCgiSmFycXVl4oCTQmVyYSB0ZXN0IG5vcm1hbGl0eTpcbiIpOyBwcmludChqYikKY2F0KGlmZWxzZShqYiRwLnZhbHVlPDAuMDUsCiAgICAgICAgICAgIuKeoSBSZXppZHXDoSBuaWUgc8O6IMO6cGxuZSBub3Jtw6FsbmUgKHA8MC4wNSkuIFByaSB2w6TEjcWhZWogdnpvcmtlIHRvIHp2ecSNYWpuZSBuZXZhZMOtLlxuIiwKICAgICAgICAgICAi4pyFIE5vcm1hbGl0YSByZXrDrWR1w60gbmVib2xhIHphbWlldG51dMOhIChw4omlMC4wNSkuXG4iKSkKCm90IDwtIGNhcjo6b3V0bGllclRlc3QobW9kZWwpCmNhdCgiXG5PdXRsaWVyIFRlc3QgKEJvbmZlcnJvbmkpOlxuIik7IHByaW50KG90KQppZiAoaXMubnVsbChvdCkpIGNhdCgi4pyFIMW9aWFkbmUgdsO9em5hbW7DqSBvZMS+YWhsw6kgaG9kbm90eS5cbiIpIGVsc2UgY2F0KCLimqDvuI8gSWRlbnRpZmlrb3ZhbsOpIG1vxb5uw6kgb3V0bGllcnkg4oCTIHNrb250cm9sdWogcG96b3JvdmFuaWEgcG9kxL5hIGluZGV4dS5cbiIpCgojIDcpIE5hanZwbHl2bmVqxaFpZSBwb3pvcm92YW5pYSAoQ29va292YSB2emRpYWxlbm9zxaUgKyDFoXR1ZGVudGl6b3ZhbsOpIHJlemlkdcOhKQpjZCAgIDwtIGNvb2tzLmRpc3RhbmNlKG1vZGVsKQpzdHVkIDwtIHJzdHVkZW50KG1vZGVsKQpvcmQgIDwtIG9yZGVyKGNkLCBkZWNyZWFzaW5nID0gVFJVRSkKdG9wICA8LSBoZWFkKG9yZCwgNSkKdG9wX3RibCA8LSBkYXRhLmZyYW1lKAogIEluZGV4ICAgPSB0b3AsCiAgTmF6b3YgICA9IGlmICgiTmF6b3YiICVpbiUgbmFtZXModWRhamUpKSB1ZGFqZSROYXpvdlt0b3BdIGVsc2UgdG9wLAogIENvb2tzRCAgPSByb3VuZChjZFt0b3BdLCA0KSwKICBSc3R1ZGVudD0gcm91bmQoc3R1ZFt0b3BdLCAzKQopCmNhdCgiXG5UT1AgNSB2cGx5dm7DvWNoIHBvem9yb3ZhbsOtOlxuIik7IHByaW50KHRvcF90YmwsIHJvdy5uYW1lcyA9IEZBTFNFKQoKIyA4KSBBbHRlcm5hdMOtdm55IG1vZGVsIOKAkyB0bG1lbmllIG91dGxpZXJvdiB2IEVCSVQgKHNpZ24tcHJlc2VydmluZyBsb2cpCnNpZ25lZF9sb2cxcCA8LSBmdW5jdGlvbih4KSBzaWduKHgpICogbG9nMXAoYWJzKHgpKQptb2RlbDIgPC0gbG0oUk9FIH4gUk9BICsgRUJJVERBbWFyemEgKyBNICsgWiArIHNpZ25lZF9sb2cxcChFQklUKSArIEZvcm1hLCBkYXRhID0gdWRhamUpCnNtMiA8LSBzdW1tYXJ5KG1vZGVsMikKY2F0KCJcbj09PT09IEFMVEVSTkFUw41WTlkgTU9ERUwgKGxvZzFwKEVCSVQpKSA9PT09PVxuIik7IHByaW50KHNtMikKCiMgcG9yb3ZuYW5pZSBtb2RlbG92CmNtcCA8LSBkYXRhLmZyYW1lKAogIE1vZGVsID0gYygiWsOha2xhZG7DvSIsIkFsdGVybmF0w612bnkgKGxvZzFwKEVCSVQpKSIpLAogIFIyICAgID0gYyhzbSRyLnNxdWFyZWQsIHNtMiRyLnNxdWFyZWQpLAogIEFkalIyID0gYyhzbSRhZGouci5zcXVhcmVkLCBzbTIkYWRqLnIuc3F1YXJlZCksCiAgQUlDICAgPSBjKEFJQyhtb2RlbCksIEFJQyhtb2RlbDIpKQopCmNhdCgiXG5Qb3Jvdm5hbmllIG1vZGVsb3YgKHZ5xaHFoWllIFLCsiBhIG5pxb7FocOtIEFJQyBqZSBsZXDFoWllKTpcbiIpOyBwcmludChjbXAsIHJvdy5uYW1lcyA9IEZBTFNFKQoKIyA5KSAoQm9udXMpIEtvcmVsYcSNbsOhIGhlYXRtYXBhIG51bWVyaWNrw71jaCBwcmVtZW5uw71jaCDigJMgYmV6IGV4dHJhIGJhbMOta292Cm51bXMgPC0gdWRhamVbLCBpbnRlcnNlY3QobnVtX2NvbHMsIG5hbWVzKHVkYWplKSksIGRyb3A9RkFMU0VdCmNtIDwtIGNvcihudW1zLCB1c2U9InBhaXJ3aXNlLmNvbXBsZXRlLm9icyIpCnBhbCA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsIndoaXRlIiwiYmx1ZSIpKSgxMDApCm9wIDwtIHBhcihtYXI9Yyg4LDgsMiwyKSk7IGhlYXRtYXAoY20sIFJvd3Y9TkEsIENvbHY9TkEsIHNjYWxlPSJub25lIiwgY29sPXBhbCwgbWFyZ2lucz1jKDgsOCkpCm10ZXh0KCJLb3JlbGHEjW7DoSBtYXRpY2EgbnVtZXJpY2vDvWNoIHVrYXpvdmF0ZcS+b3YiLCBvdXRlcj1UUlVFLCBjZXg9MS4wKQpwYXIob3ApCgpjYXQoIlxuSU5URVJQUkVUw4FDSUEgSEVBVE1BUFk6XG4iLAogICAgIuKAoiBUbWF2byBtb2Ryw6kgPSBzaWxuw6EgcG96aXTDrXZuYSBrb3JlbMOhY2lhLCB0bWF2byDEjWVydmVuw6kgPSBzaWxuw6EgbmVnYXTDrXZuYS5cbiIsCiAgICAi4oCiIFNsZWR1aiBobGF2bmUgcMOhcnkgcyB8cnwgPiAwLjcg4oCTIG3DtMW+dSBzcMO0c29ib3ZhxaUgbXVsdGlrb2xpbmVhcml0dSB2IHJlZ3Jlc2lpLlxuIiwgc2VwPSIiKQoKYGBgCmBgYHtyfQojIC0tLSBwcsOtcHJhdmEgZmFrdG9yb3YgYSBudW1lcsOtayAtLS0KdWRhamUkRm9ybWEgICAgIDwtIGRyb3BsZXZlbHMoYXMuZmFjdG9yKHVkYWplJEZvcm1hKSkKdWRhamUkS2F0ZWdvcmlhIDwtIGRyb3BsZXZlbHMoYXMuZmFjdG9yKHVkYWplJEthdGVnb3JpYSkpCgpudW1fY29scyA8LSBjKCJST0UiLCJST0EiLCJFQklUREFtYXJ6YSIsIk0iLCJaIikKIyBvZHN0csOhbmltZSByaWFka3kgcyBOQSB2IGvEvsO6xI1vdsO9Y2ggbnVtZXJpY2vDvWNoIHByZW1lbm7DvWNoCmRmIDwtIHVkYWplWywgYyhudW1fY29scywgIkZvcm1hIiwgIkthdGVnb3JpYSIpLCBkcm9wID0gRkFMU0VdCmRmIDwtIGRmW2NvbXBsZXRlLmNhc2VzKGRmWywgbnVtX2NvbHNdKSwgLCBkcm9wID0gRkFMU0VdCgojIC0tLSB2eWJlcmllbWUgZmFrdG9yKHkpLCBrdG9yw6kgbWFqw7ogYXNwb8WIIDIgw7pyb3ZuZSAtLS0KZmFjdG9yc19vayA8LSBjaGFyYWN0ZXIoMCkKaWYgKCJGb3JtYSIgJWluJSBuYW1lcyhkZikgJiYgbmxldmVscyhkZiRGb3JtYSkgPj0gMikgICAgIGZhY3RvcnNfb2sgPC0gYyhmYWN0b3JzX29rLCAiRm9ybWEiKQppZiAoIkthdGVnb3JpYSIgJWluJSBuYW1lcyhkZikgJiYgbmxldmVscyhkZiRLYXRlZ29yaWEpID49IDIpIGZhY3RvcnNfb2sgPC0gYyhmYWN0b3JzX29rLCAiS2F0ZWdvcmlhIikKCiMgLS0tIHBvc3RhdsOtbWUgZm9ybXVsdSBkeW5hbWlja3kgLS0tCmJhc2VfdGVybXMgPC0gYygiUk9BIiwiRUJJVERBbWFyemEiLCJNIiwiWiIpCmFsbF90ZXJtcyAgPC0gYyhiYXNlX3Rlcm1zLCBmYWN0b3JzX29rKQpmb3JtX3RleHQgIDwtIHBhc3RlKCJST0UgfiIsIHBhc3RlKGFsbF90ZXJtcywgY29sbGFwc2UgPSAiICsgIikpCmZvcm1fZml0ICAgPC0gYXMuZm9ybXVsYShmb3JtX3RleHQpCgpjYXQoIkZpdHR1amVtIG1vZGVsIHMgZm9ybXVsb3U6XG4gICIsIGZvcm1fdGV4dCwgIlxuXG4iKQptb2RlbCA8LSBsbShmb3JtX2ZpdCwgZGF0YSA9IGRmKQpzbSA8LSBzdW1tYXJ5KG1vZGVsKQpwcmludChzbSkKCiMgLS0tIGRpYWdub3N0aWNrw6kgZ3JhZnkgLS0tCm9wIDwtIHBhcihtZnJvdyA9IGMoMiwyKSk7IHBsb3QobW9kZWwpOyBtdGV4dCgiRGlhZ25vc3RpY2vDqSBncmFmeSByZWdyZXNuw6lobyBtb2RlbHUgUk9FIiwgb3V0ZXI9VFJVRSwgY2V4PTEuMSk7IHBhcihvcCkKCiMgLS0tIFRPUCA1IHZwbHl2bsO9Y2ggcG96b3JvdmFuw60gKHXFviBiZXogY2jDvWIgcyBrb250cmFzdG1pKSAtLS0KY2QgICA8LSBjb29rcy5kaXN0YW5jZShtb2RlbCkKc3R1ZCA8LSByc3R1ZGVudChtb2RlbCkKb3JkICA8LSBvcmRlcihjZCwgZGVjcmVhc2luZyA9IFRSVUUpCnRvcCAgPC0gaGVhZChvcmQsIDUpCgp0b3BfdGJsIDwtIGRhdGEuZnJhbWUoCiAgSW5kZXggICA9IHRvcCwKICBOYXpvdiAgID0gaWYgKCJOYXpvdiIgJWluJSBuYW1lcyh1ZGFqZSkpIHVkYWplJE5hem92W3RvcF0gZWxzZSB0b3AsCiAgQ29va3NEICA9IHJvdW5kKGNkW3RvcF0sIDQpLAogIFJzdHVkZW50PSByb3VuZChzdHVkW3RvcF0sIDMpCikKY2F0KCJcblRPUCA1IHZwbHl2bsO9Y2ggcG96b3JvdmFuw606XG4iKTsgcHJpbnQodG9wX3RibCwgcm93Lm5hbWVzID0gRkFMU0UpCgojIC0tLSBrcsOhdGthIGludGVycHJldMOhY2lhIHbDvXN0dXB1IC0tLQpyMiAgIDwtIHNtJHIuc3F1YXJlZApyMmEgIDwtIHNtJGFkai5yLnNxdWFyZWQKcEYgICA8LSBwZihzbSRmc3RhdGlzdGljWzFdLCBzbSRmc3RhdGlzdGljWzJdLCBzbSRmc3RhdGlzdGljWzNdLCBsb3dlci50YWlsID0gRkFMU0UpCnNpZyAgPC0gY29lZihzbSlbLTEsLGRyb3A9RkFMU0VdOyBzaWcgPC0gc2lnW3NpZ1ssIlByKD58dHwpIl0gPCAwLjA1LCxkcm9wPUZBTFNFXQoKY2F0KHNwcmludGYoIlxuSU5URVJQUkVUw4FDSUE6XG7igKIgTW9kZWwgdnlzdmV0xL51amUgJS4xZiUlIHZhcmlhYmlsaXR5IFJPRSAoUsKyPSUuM2Y7IGFkai5SwrI9JS4zZikuXG4iLCAxMDAqcjIsIHIyLCByMmEpKQpjYXQoc3ByaW50Zigi4oCiIENlbGtvdsO9IEYtdGVzdDogcCA9ICUuNGYg4oaSIG1vZGVsIGFrbyBjZWxvayBqZSAlcy5cbiIsCiAgICAgICAgICAgIHBGLCBpZmVsc2UocEY8MC4wNSwixaF0YXRpc3RpY2t5IHbDvXpuYW1uw70iLCJuZcWhdGF0aXN0aWNreSBuZXbDvXpuYW1uw70iKSkpCmlmIChucm93KHNpZykpIHsKICBjYXQoIuKAoiBWw716bmFtbsOpIHByZW1lbm7DqTpcbiIpCiAgYXBwbHkoc2lnLCAxLCBmdW5jdGlvbihyKSBjYXQoc3ByaW50ZigiICAtICVzICjOsiA9ICUuM2YsIHAgPSAlLjRmKVxuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKHNpZylbd2hpY2goc2lnWywnRXN0aW1hdGUnXT09clsnRXN0aW1hdGUnXSldLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMubnVtZXJpYyhyWyJFc3RpbWF0ZSJdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm51bWVyaWMoclsiUHIoPnx0fCkiXSkpKSkKfSBlbHNlIGNhdCgi4oCiIE5hIGhsYWRpbmUgNSAlIG5ldnnFoWxhIMW+aWFkbmEgdnlzdmV0xL51asO6Y2EgcHJlbWVubsOhIGFrbyB2w716bmFtbsOhLlxuIikKCmBgYApgYGB7cn0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIEtPTVBMRVROw4EgTElORcOBUk5BIFJFR1JFU0lBCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiMgLS0tIEJhbMOtxI1reSAtLS0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJkcGx5ciIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoInRzZXJpZXMiLCBxdWlldGx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMoInRzZXJpZXMiKQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImNhciIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygiY2FyIikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGNhcikKCiMgLS0tIE5hxI3DrXRhbmllIGTDoXQgLS0tCnVkYWplIDwtIHJlYWQuY3N2MigiZGF0YUVLT05PTUVUUklBLmNzdiIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIiwgZGVjID0gIi4iKQpjYXQoIuKchSBEw6F0YSDDunNwZcWhbmUgbmHEjcOtdGFuw6lcbiIpCgojIC0tLSBPxI1pc3RlbmllIGZha3Rvcm92IGEgbnVtZXJpY2vDvWNoIHByZW1lbm7DvWNoIC0tLQp1ZGFqZSRGb3JtYSAgICAgPC0gZHJvcGxldmVscyhhcy5mYWN0b3IodWRhamUkRm9ybWEpKQp1ZGFqZSRLYXRlZ29yaWEgPC0gZHJvcGxldmVscyhhcy5mYWN0b3IodWRhamUkS2F0ZWdvcmlhKSkKCm51bV9jb2xzIDwtIGMoIlJPRSIsICJST0EiLCAiRUJJVERBbWFyemEiLCAiTSIsICJaIikKdWRhamUgPC0gdWRhamVbY29tcGxldGUuY2FzZXModWRhamVbLCBudW1fY29sc10pLCBdCgojIC0tLSBEeW5hbWlja8O9IHbDvWJlciBmYWt0b3JvdiAoYWJ5IHNhIHZ5aGxhIGNoeWJhIGtvbnRyYXN0b3YpIC0tLQpmYWN0b3JzX29rIDwtIGNoYXJhY3RlcigwKQppZiAoIkZvcm1hIiAlaW4lIG5hbWVzKHVkYWplKSAmJiBubGV2ZWxzKHVkYWplJEZvcm1hKSA+PSAyKSBmYWN0b3JzX29rIDwtIGMoZmFjdG9yc19vaywgIkZvcm1hIikKaWYgKCJLYXRlZ29yaWEiICVpbiUgbmFtZXModWRhamUpICYmIG5sZXZlbHModWRhamUkS2F0ZWdvcmlhKSA+PSAyKSBmYWN0b3JzX29rIDwtIGMoZmFjdG9yc19vaywgIkthdGVnb3JpYSIpCgpiYXNlX3Rlcm1zIDwtIGMoIlJPQSIsICJFQklUREFtYXJ6YSIsICJNIiwgIloiKQphbGxfdGVybXMgIDwtIGMoYmFzZV90ZXJtcywgZmFjdG9yc19vaykKZm9ybV90ZXh0ICA8LSBwYXN0ZSgiUk9FIH4iLCBwYXN0ZShhbGxfdGVybXMsIGNvbGxhcHNlID0gIiArICIpKQpmb3JtX2ZpdCAgIDwtIGFzLmZvcm11bGEoZm9ybV90ZXh0KQoKY2F0KCLwn5S5IEZpdHR1amVtIG1vZGVsIHMgZm9ybXVsb3U6XG4gICAiLCBmb3JtX3RleHQsICJcblxuIikKCiMgLS0tIEZpdG51dGllIG1vZGVsdSAtLS0KbW9kZWwgPC0gbG0oZm9ybV9maXQsIGRhdGEgPSB1ZGFqZSkKc3VtbWFyeShtb2RlbCkKCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgRElBR05PU1RJQ0vDiSBHUkFGWSBBIEtPTUVOVMOBUkUKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KcGFyKG1mcm93ID0gYygyLCAyKSkKcGxvdChtb2RlbCkKbXRleHQoIkRpYWdub3N0aWNrw6kgZ3JhZnkgcmVncmVzbsOpaG8gbW9kZWx1IFJPRSIsIG91dGVyID0gVFJVRSwgY2V4ID0gMS4yLCBmb250ID0gMikKcGFyKG1mcm93ID0gYygxLCAxKSkKCmNhdCgiXG4tLS0tLS0tLS0tLS0tLS0tIElOVEVSUFJFVMOBQ0lBIEdSQUZPViAtLS0tLS0tLS0tLS0tLS0tXG4iKQoKY2F0KCJcbvCflLkgUmVzaWR1YWxzIHZzIEZpdHRlZFxuIikKY2F0KCJSZXppZHXDoSBrb2zDrcWhdSBva29sbyBudWx5IOKAkyBtb2RlbCBuZW3DoSB2w71yYXpuw6kgc3lzdGVtYXRpY2vDqSBjaHlieS5cbiIpCmNhdCgiQWsgamUgxI1lcnZlbsOhIMSNaWFyYSBtaWVybmUgemFrcml2ZW7DoSwgbmF6bmHEjXVqZSBtaWVybnUgbmVsaW5lYXJpdHUuXG4iKQpjYXQoIlJvenB0eWwgcmV6w61kdcOtIGplIHByaWJsacW+bmUgcm92bmFrw70g4oaSIHBvZG1pZW5rYSBob21vc2tlZGFzdGljaXR5IGplIHNwbG5lbsOhLlxuIikKCmNhdCgiXG7wn5S5IE5vcm1hbCBRLVEgUGxvdFxuIikKY2F0KCJWw6TEjcWhaW5hIGJvZG92IGxlxb7DrSBibMOtemtvIGRpYWdvbsOhbHkg4oaSIHJlemlkdcOhIHPDuiBwcmlibGnFvm5lIG5vcm3DoWxuZSByb3pkZWxlbsOpLlxuIikKY2F0KCJPZGNow71sa3kgbmEga29uY29jaCBncmFmdSBtw7TFvnUgem5hbWVuYcWlIHbDvXNreXQgb3V0bGllcm92IGFsZWJvIMWlYcW+xaFpZSBjaHZvc3R5LlxuIikKCmNhdCgiXG7wn5S5IFNjYWxlLUxvY2F0aW9uIFBsb3RcbiIpCmNhdCgiQm9keSBzw7ogcm92bm9tZXJuZSByb3psb8W+ZW7DqSDihpIgcm96cHR5bCBqZSBzdGFiaWxuw70gKGhvbW9za2VkYXN0aWNpdGEpLlxuIikKY2F0KCJBayBieSB0dm9yaWxpIGxpZXZpaywgacWhbG8gYnkgbyBoZXRlcm9za2VkYXN0aWNpdHUuXG4iKQoKY2F0KCJcbvCflLkgUmVzaWR1YWxzIHZzIExldmVyYWdlXG4iKQpjYXQoIlbDpMSNxaFpbmEgYm9kb3YgbcOhIG7DrXpreSBww6Frb3bDvSBlZmVrdCAodnBseXYgbmEgcmVncmVzaXUpLlxuIikKY2F0KCJCb2R5IGJsw616a28gQ29va292w71jaCBrb250w7pyIG3DtMW+dSBiecWlIHZwbHl2bsOpIHBvem9yb3ZhbmlhLCBrdG9yw6kgc2lsbm8gb3ZwbHl2xYh1asO6IG1vZGVsLlxuIikKCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgSU5URVJQUkVUw4FDSUEgU8OaSFJOVSBNT0RFTFUKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0Kc20gPC0gc3VtbWFyeShtb2RlbCkKcjIgICA8LSBzbSRyLnNxdWFyZWQKcjJhICA8LSBzbSRhZGouci5zcXVhcmVkCnBGICAgPC0gcGYoc20kZnN0YXRpc3RpY1sxXSwgc20kZnN0YXRpc3RpY1syXSwgc20kZnN0YXRpc3RpY1szXSwgbG93ZXIudGFpbCA9IEZBTFNFKQpzaWcgIDwtIGNvZWYoc20pWy0xLCxkcm9wPUZBTFNFXTsgc2lnIDwtIHNpZ1tzaWdbLCJQcig+fHR8KSJdIDwgMC4wNSwsZHJvcD1GQUxTRV0KCmNhdCgiXG4tLS0tLS0tLS0tLS0tLS0tIElOVEVSUFJFVMOBQ0lBIE1PREVMVSAtLS0tLS0tLS0tLS0tLS0tXG4iKQoKY2F0KHNwcmludGYoIk1vZGVsIHZ5c3ZldMS+dWplICUuMWYlJSB2YXJpYWJpbGl0eSB1a2F6b3ZhdGXEvmEgUk9FIChSwrIgPSAlLjNmLCBBZGp1c3RlZCBSwrIgPSAlLjNmKS5cbiIsCiAgICAgICAgICAgIDEwMCpyMiwgcjIsIHIyYSkpCmNhdChzcHJpbnRmKCJDZWxrb3bDvSBGLXRlc3Q6IHAgPSAlLjRmIOKGkiBtb2RlbCBha28gY2Vsb2sgamUgJXMuXG4iLAogICAgICAgICAgICBwRiwgaWZlbHNlKHBGPDAuMDUsIsWhdGF0aXN0aWNreSB2w716bmFtbsO9IiwibmXFoXRhdGlzdGlja3kgbmV2w716bmFtbsO9IikpKQoKaWYgKG5yb3coc2lnKSkgewogIGNhdCgixaB0YXRpc3RpY2t5IHbDvXpuYW1uw6kgcHJlbWVubsOpOlxuIikKICBhcHBseShzaWcsIDEsIGZ1bmN0aW9uKHIpIGNhdChzcHJpbnRmKCIgIC0gJXMgKM6yID0gJS4zZiwgcCA9ICUuNGYpXG4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoc2lnKVt3aGljaChzaWdbLCdFc3RpbWF0ZSddPT1yWydFc3RpbWF0ZSddKV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5udW1lcmljKHJbIkVzdGltYXRlIl0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMubnVtZXJpYyhyWyJQcig+fHR8KSJdKSkpKQp9IGVsc2UgewogIGNhdCgiTmEgaGxhZGluZSA1ICUgbmllIGplIMW+aWFkbmEgdnlzdmV0xL51asO6Y2EgcHJlbWVubsOhIMWhdGF0aXN0aWNreSB2w716bmFtbsOhLlxuIikKfQoKY2F0KCJcbkludGVycHJldMOhY2lhOiBNb2RlbCB1a2F6dWplLCBrdG9yw6kgZmluYW7EjW7DqSB1a2F6b3ZhdGVsZSAobmFwci4gUk9BLCBFQklUREEgbWFyxb5hKVxuIikKY2F0KCJhIMWhdHJ1a3R1csOhbG5lIHByZW1lbm7DqSAoRm9ybWEsIEthdGVnw7NyaWEsIHBvaGxhdmllIHZvIHZlZGVuw60pIG92cGx5dsWIdWrDuiBuw6F2cmF0bm9zxaUgdmxhc3Ruw6lobyBrYXBpdMOhbHUgKFJPRSkuXG4iKQoKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyBURVNUWSBOT1JNQUxJVFkgQSBPRMS9QUhMw51DSCBIT0ROw5RUCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CmNhdCgiXG4tLS0tLS0tLS0tLS0tLS0tIFRFU1RZIE5PUk1BTElUWSBBIE9VVExJRVJPViAtLS0tLS0tLS0tLS0tLS0tXG4iKQoKcmVzaWRfbW9kZWwgPC0gcmVzaWR1YWxzKG1vZGVsKQpqYiA8LSBqYXJxdWUuYmVyYS50ZXN0KHJlc2lkX21vZGVsKQpjYXQoIkphcnF1ZeKAk0JlcmEgdGVzdDpcbiIpOyBwcmludChqYikKaWYgKGpiJHAudmFsdWUgPCAwLjA1KSB7CiAgY2F0KCLinqEgUmV6aWR1w6EgbmllIHPDuiBkb2tvbmFsZSBub3Jtw6FsbmUgKHAgPCAwLjA1KSwgYWxlIHRvIGplIHByaSBla29ub21pY2vDvWNoIGTDoXRhY2ggYmXFvm7DqS5cbiIpCn0gZWxzZSB7CiAgY2F0KCLinIUgUmV6aWR1w6EgbWFqw7ogcHJpYmxpxb5uZSBub3Jtw6FsbmUgcm96ZGVsZW5pZS5cbiIpCn0KCmNhdCgiXG5PdXRsaWVyIFRlc3QgKEJvbmZlcnJvbmkpOlxuIikKb3QgPC0gb3V0bGllclRlc3QobW9kZWwpCnByaW50KG90KQppZiAoaXMubnVsbChvdCkpIHsKICBjYXQoIuKchSDFvWlhZG5lIHbDvXpuYW1uw6kgb2TEvmFobMOpIGhvZG5vdHkuXG4iKQp9IGVsc2UgewogIGNhdCgi4pqg77iPIE5pZWt0b3LDqSBwb3pvcm92YW5pYSBzw7ogb2TEvmFobMOpIOKAkyBtw7TFvnUgbWHFpSB2cGx5diBuYSB2w71zbGVka3kuXG4iKQp9CgojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIE5BSlZQTFlWTkVKxaBJRSBQT1pPUk9WQU5JQQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpjYXQoIlxuLS0tLS0tLS0tLS0tLS0tLSBOQUpWUExZVk5FSsWgSUUgUE9aT1JPVkFOSUEgLS0tLS0tLS0tLS0tLS0tLVxuIikKCmNkICAgPC0gY29va3MuZGlzdGFuY2UobW9kZWwpCnN0dWQgPC0gcnN0dWRlbnQobW9kZWwpCm9yZCAgPC0gb3JkZXIoY2QsIGRlY3JlYXNpbmcgPSBUUlVFKQp0b3AgIDwtIGhlYWQob3JkLCA1KQp0b3BfdGJsIDwtIGRhdGEuZnJhbWUoCiAgSW5kZXggICA9IHRvcCwKICBOYXpvdiAgID0gaWYgKCJOYXpvdiIgJWluJSBuYW1lcyh1ZGFqZSkpIHVkYWplJE5hem92W3RvcF0gZWxzZSB0b3AsCiAgQ29va292YV92emRpYWxlbm9zdCA9IHJvdW5kKGNkW3RvcF0sIDQpLAogIFN0dWRlbnRfcmV6aWR1dW0gPSByb3VuZChzdHVkW3RvcF0sIDMpCikKcHJpbnQodG9wX3RibCwgcm93Lm5hbWVzID0gRkFMU0UpCgpjYXQoIkludGVycHJldMOhY2lhOlxuIikKY2F0KCLigKIgQ29va292YSB2emRpYWxlbm9zxaUgPiAwLjUgPSB2eXNva8O9IHZwbHl2IG5hIG1vZGVsLlxuIikKY2F0KCLigKIgxaB0dWRlbnRpem92YW7DqSByZXrDrWR1dW0gbWltbyBpbnRlcnZhbHUgKC0yLCAyKSA9IG9kxL5haGzDqSBwb3pvcm92YW5pZS5cbiIpCmNhdCgi4oCiIFRpZXRvIGZpcm15IG9kcG9yw7rEjWFtZSBza29udHJvbG92YcWlLCBtw7TFvnUgYnnFpSBleHRyw6ltbmUgcHLDrXBhZHkuXG4iKQoKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyBIRUFUTUFQQSBLT1JFTMOBQ0nDjQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpudW1zIDwtIHVkYWplWywgbnVtX2NvbHNdCmNvcl9tYXRyaXggPC0gY29yKG51bXMsIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQoKaGVhdF9jb2xvcnMgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJyZWQiLCAid2hpdGUiLCAiYmx1ZSIpKSgxMDApCmhlYXRtYXAoY29yX21hdHJpeCwgUm93diA9IE5BLCBDb2x2ID0gTkEsIGNvbCA9IGhlYXRfY29sb3JzLCBzY2FsZSA9ICJub25lIiwKICAgICAgICBtYWluID0gIktvcmVsYcSNbsOhIG1hdGljYSBmaW5hbsSNbsO9Y2ggdWthem92YXRlxL5vdiIsCiAgICAgICAgbWFyZ2lucyA9IGMoOCwgOCkpCgpjYXQoIlxuLS0tLS0tLS0tLS0tLS0tLSBJTlRFUlBSRVTDgUNJQSBIRUFUTUFQWSAtLS0tLS0tLS0tLS0tLS0tXG4iKQpjYXQoIk1vZHLDqSBvZHRpZW5lIHpuYW1lbmFqw7ogcG96aXTDrXZuZSB2esWlYWh5LCDEjWVydmVuw6kgbmVnYXTDrXZuZS5cbiIpCmNhdCgiQWsgc8O6IGhvZG5vdHkga29yZWzDoWNpZSB8cnwgPiAwLjcsIG3DtMW+ZSDDrXPFpSBvIG11bHRpa29saW5lYXJpdHUgKG5hcHIuIG1lZHppIFJPQSBhIFJPRSkuXG4iKQpjYXQoIlNpbG7DqSB2esWlYWh5IG5hem5hxI11asO6LCDFvmUgbmlla3RvcsOpIHByZW1lbm7DqSBtw7TFvnUgYnnFpSBuYXZ6w6Fqb20gesOhdmlzbMOpLlxuIikKCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgWkhSTlVUSUUKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KY2F0KCJcbi0tLS0tLS0tLS0tLS0tLS0gWkhSTlVUSUUgLS0tLS0tLS0tLS0tLS0tLVxuIikKY2F0KCLinIUgVsOkxI3FoWluYSBwcmVkcG9rbGFkb3YgbGluZcOhcm5laiByZWdyZXNpZSBqZSBzcGxuZW7DoSAobGluZWFyaXRhLCBob21vc2tlZGFzdGljaXRhLCBuZXrDoXZpc2xvc8WlKS5cbiIpCmNhdCgi4pqg77iPIE1pZXJuZSBvZGNow71sa3kgb2Qgbm9ybWFsaXR5IG5pZSBzw7ogcHJvYmzDqW1vbSBwcmkgdsOkxI3FocOtY2ggdnpvcmvDoWNoLlxuIikKY2F0KCJNb2RlbCBwb3NreXR1amUgc3BvxL5haGxpdsO9IHrDoWtsYWQgbmEgaW50ZXJwcmV0w6FjaXUgdnBseXZ1IGZpbmFuxI1uw71jaCB1a2F6b3ZhdGXEvm92IG5hIFJPRS5cbiIpCgpgYGAKYGBge3J9CiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIElOVEVSUFJFVMOBQ0lBIE1PREVMVQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmludGVycHJldF9tb2RlbCA8LSBmdW5jdGlvbihtb2RlbCwgZGF0YSwgdGFyZ2V0X25hbWUgPSAiUk9FIikgewogIHNtIDwtIHN1bW1hcnkobW9kZWwpCgogICMgWsOha2xhZG7DqSBtZXRyaWt5CiAgcjIgICA8LSBzbSRyLnNxdWFyZWQKICByMmEgIDwtIHNtJGFkai5yLnNxdWFyZWQKICBmdmFsIDwtIHNtJGZzdGF0aXN0aWMKICBwRiAgIDwtIHBmKGZ2YWxbMV0sIGZ2YWxbMl0sIGZ2YWxbM10sIGxvd2VyLnRhaWwgPSBGQUxTRSkKCiAgIyBLb2VmaWNpZW50eSwgcC1ob2Rub3R5LCBDSQogIGNmICAgPC0gY29lZihzbSkKICBjaSAgIDwtIHRyeUNhdGNoKGNvbmZpbnQobW9kZWwpLCBlcnJvciA9IGZ1bmN0aW9uKGUpIE5VTEwpCgogICMgWm96bmFtIHbDvXpuYW1uw71jaCAvIG5ldsO9em5hbW7DvWNoCiAgdGFiIDwtIGFzLmRhdGEuZnJhbWUoY2JpbmQoRXN0aW1hdGUgPSBjZlssICJFc3RpbWF0ZSJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAgPSBjZlssICJQcig+fHR8KSJdKSkKICB0YWIkdmFyIDwtIHJvd25hbWVzKHRhYikKICB0YWIgPC0gdGFiW3RhYiR2YXIgIT0gIihJbnRlcmNlcHQpIiwgXQogIHNpZyA8LSB0YWJbdGFiJHAgPCAwLjA1LCAsIGRyb3AgPSBGQUxTRV0KICBucyAgPC0gdGFiW3RhYiRwID49IDAuMDUsICwgZHJvcCA9IEZBTFNFXQoKICAjIMWgdGFuZGFyZGl6b3ZhbsOpIGtvZWZpY2llbnR5IChwcmUgcG9yb3ZuYW5pZSBzaWx5IHZwbHl2dSkKICAjIChiZXogZmFrdG9yb3Yg4oCTIHByZSBudW1lcmlja8OpIHByZW1lbm7DqSkKICB4bmFtZXMgPC0gYXR0cih0ZXJtcyhtb2RlbCksICJ0ZXJtLmxhYmVscyIpCiAgbnVtX3ggIDwtIHhuYW1lc1tzYXBwbHkoeG5hbWVzLCBmdW5jdGlvbih2KSBpcy5udW1lcmljKGRhdGFbW3ZdXSkgKV0KICBiZXRhICAgPC0gTlVMTAogIGlmIChsZW5ndGgobnVtX3gpKSB7CiAgICBkMiA8LSBkYXRhWywgYyh0YXJnZXRfbmFtZSwgbnVtX3gpXQogICAgZDIgPC0gbmEub21pdChkMikKICAgIHogIDwtIHNjYWxlKGQyKQogICAgZm0gPC0gbG0oYXMuZm9ybXVsYSgKICAgICAgcGFzdGUoImAiLCB0YXJnZXRfbmFtZSwgImAgfiAiLCBwYXN0ZShwYXN0ZTAoImAiLCBudW1feCwgImAiKSwgY29sbGFwc2UgPSAiICsgIiksIHNlcCA9ICIiKQogICAgKSwgZGF0YSA9IGFzLmRhdGEuZnJhbWUoeikpCiAgICBiZXRhIDwtIGNvZWYoZm0pWy0xXSAgIyBiZXogaW50ZXJjZXB0dQogIH0KCiAgIyAtLS0tLSBUTEHEjCBJTlRFUlBSRVTDgUNJRSAtLS0tLQogIGNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIpCiAgY2F0KCJJTlRFUlBSRVTDgUNJQSBWw51TTEVES09WIOKAkyBMRU4gRMOBVEFcbiIpCiAgY2F0KCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4iKQoKICBjYXQoc3ByaW50Zigi4oCiIE1vZGVsIHZ5c3ZldMS+dWplICUuMWYlJSB2YXJpYWJpbGl0eSB1a2F6b3ZhdGXEvmEgJXMgKFLCsiA9ICUuM2Y7IHVwcmF2ZW7DqSBSwrIgPSAlLjNmKS5cbiIsCiAgICAgICAgICAgICAgMTAwKnIyLCB0YXJnZXRfbmFtZSwgcjIsIHIyYSkpCiAgY2F0KHNwcmludGYoIuKAoiBDZWxrb3bDvSBGLXRlc3Q6IEYoJS4wZiwgJS4wZikgPSAlLjJmLCBwID0gJS40ZiDihpIgbW9kZWwgYWtvIGNlbG9rIGplICVzLlxuXG4iLAogICAgICAgICAgICAgIGZ2YWxbMl0sIGZ2YWxbM10sIGZ2YWxbMV0sIHBGLAogICAgICAgICAgICAgIGlmZWxzZShwRiA8IDAuMDUsICLFoXRhdGlzdGlja3kgdsO9em5hbW7DvSIsICJuZcWhdGF0aXN0aWNreSBuZXbDvXpuYW1uw70iKSkpCgogICMgVsO9em5hbW7DqSBwcmVtZW5uw6kKICBpZiAobnJvdyhzaWcpKSB7CiAgICBjYXQoIlbDnVpOQU1Ow4kgUFJFTUVOTsOJIChwIDwgMC4wNSk6XG4iKQogICAgYXBwbHkoc2lnW29yZGVyKHNpZyRwKSwgXSwgMSwgZnVuY3Rpb24ocikgewogICAgICBubSA8LSByWyJ2YXIiXTsgZXN0IDwtIGFzLm51bWVyaWMoclsiRXN0aW1hdGUiXSk7IHB2IDwtIGFzLm51bWVyaWMoclsicCJdKQogICAgICBjaV90eHQgPC0gaWYgKCFpcy5udWxsKGNpKSAmJiBubSAlaW4lIHJvd25hbWVzKGNpKSkgewogICAgICAgIHNwcmludGYoIiwgOTUlJSBDSSBbJS4zZjsgJS4zZl0iLCBjaVtubSwgMV0sIGNpW25tLCAyXSkKICAgICAgfSBlbHNlICIiCiAgICAgIHNtZXIgPC0gaWZlbHNlKGVzdCA+IDAsICJwb3ppdMOtdm55IiwgIm5lZ2F0w612bnkiKQogICAgICBiZXRhX3R4dCA8LSBpZiAoIWlzLm51bGwoYmV0YSkgJiYgbm0gJWluJSBuYW1lcyhiZXRhKSkKICAgICAgICBzcHJpbnRmKCIsIMWhdGFuZGFyZGl6b3ZhbsO9IHZwbHl2IM6yID0gJS4zZiIsIGJldGFbW25tXV0pIGVsc2UgIiIKICAgICAgY2F0KHNwcmludGYoIiAg4oCTICVzOiBrb2VmLiA9ICUuM2YgKCVzIHZwbHl2KSwgcCA9ICUuNGYlcyVzLlxuIiwKICAgICAgICAgICAgICAgICAgbm0sIGVzdCwgc21lciwgcHYsIGNpX3R4dCwgYmV0YV90eHQpKQogICAgfSkKICAgIGNhdCgiXG4iKQogIH0gZWxzZSB7CiAgICBjYXQoIk5hIGhsYWRpbmUgNSAlIG5ldnlzdHVwdWplIMW+aWFkbmEgdnlzdmV0xL51asO6Y2EgcHJlbWVubsOhIGFrbyDFoXRhdGlzdGlja3kgdsO9em5hbW7DoS5cblxuIikKICB9CgogICMgTmV2w716bmFtbsOpIHByZW1lbm7DqQogIGlmIChucm93KG5zKSkgewogICAgY2F0KCJORVbDnVpOQU1Ow4kgUFJFTUVOTsOJIChwIOKJpSAwLjA1KTpcbiIpCiAgICBhcHBseShuc1tvcmRlcihucyRwLCBkZWNyZWFzaW5nID0gVFJVRSksIF0sIDEsIGZ1bmN0aW9uKHIpIHsKICAgICAgbm0gPC0gclsidmFyIl07IGVzdCA8LSBhcy5udW1lcmljKHJbIkVzdGltYXRlIl0pOyBwdiA8LSBhcy5udW1lcmljKHJbInAiXSkKICAgICAgY2F0KHNwcmludGYoIiAg4oCTICVzOiBrb2VmLiA9ICUuM2YsIHAgPSAlLjRmIChlZmVrdCBuZXZpZW1lIG9kbMOtxaFpxaUgb2QgbnVseSkuXG4iLAogICAgICAgICAgICAgICAgICBubSwgZXN0LCBwdikpCiAgICB9KQogICAgY2F0KCJcbiIpCiAgfQoKICAjIEFrIHPDuiB2byBmb3JtdWxlIGZha3RvcnksIG5hcMOtxaEgcG9yb3ZuYW5pYSB2cy4gcmVmZXJlbsSNbsOhIMO6cm92ZcWICiAgdGwgPC0gdGVybXMobW9kZWwpCiAgZmFjcyA8LSBhdHRyKHRsLCAiZGF0YUNsYXNzZXMiKQogIGZhY3MgPC0gbmFtZXMoZmFjc1tmYWNzID09ICJmYWN0b3IiXSkKICBmYWNzIDwtIHNldGRpZmYoZmFjcywgdGFyZ2V0X25hbWUpCiAgaWYgKGxlbmd0aChmYWNzKSkgewogICAgY2F0KCJGQUtUT1JPVsOJIFBSRU1FTk7DiSAocG9yb3ZuYW5pZSB2b8SNaSByZWZlcmVuxI1uZWogw7pyb3ZuaSk6XG4iKQogICAgZm9yIChmIGluIGZhY3MpIHsKICAgICAgbHZsIDwtIGxldmVscyhkYXRhW1tmXV0pCiAgICAgIGlmIChsZW5ndGgobHZsKSA+PSAyKSB7CiAgICAgICAgcmVmIDwtIGx2bFsxXQogICAgICAgIGNhdChzcHJpbnRmKCIgIOKAkyAlcyAocmVmZXJlbmNpYTogJXMpXG4iLCBmLCByZWYpKQogICAgICAgIGlkeCA8LSBncmVwKHBhc3RlMCgiXiIsIGYpLCByb3duYW1lcyhjZikpCiAgICAgICAgaWYgKGxlbmd0aChpZHgpKSB7CiAgICAgICAgICBmb3IgKG5tIGluIHJvd25hbWVzKGNmKVtpZHhdKSB7CiAgICAgICAgICAgIGVzdCA8LSBjZltubSwgIkVzdGltYXRlIl07IHB2IDwtIGNmW25tLCAiUHIoPnx0fCkiXQogICAgICAgICAgICBzbWVyIDwtIGlmZWxzZShlc3QgPiAwLCAidnnFocWhaWUiLCAibmnFvsWhaWUiKQogICAgICAgICAgICBjYXQoc3ByaW50ZigiICAgICAg4oCiICVzOiBrb2VmLiA9ICUuM2YgKHAgPSAlLjRmKSDihpIgb8SNYWvDoXZhbsOpICVzICVzIG9wcm90aSByZWZlcmVuY2lpIChwcmkga29uxaF0YW50bsO9Y2ggb3N0YXRuw71jaCBwcmVtZW5uw71jaCkuXG4iLAogICAgICAgICAgICAgICAgICAgICAgICBzdWIocGFzdGUwKGYpLCAiIiwgbm0pLCBlc3QsIHB2LCBzbWVyLCB0YXJnZXRfbmFtZSkpCiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNhdCgiICAgICAg4oCiIHYgbW9kZWxpIG5lYm9saSB6aXN0ZW7DqSBrb250cmFzdHkgKHByYXZkZXAuIGxlbiAxIMO6cm92ZcWIIHBvIGZpbHRyb3ZhbsOtKS5cbiIpCiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBjYXQoIlxuIikKICB9CgogICMgRGlhZ25vc3Rpa2Eg4oCTIHN0cnXEjW7DvSBzbG92bsO9IGtvbWVudMOhciBwb2TEvmEgxaF0YXRpc3TDrWsKICAjIChub3JtYWxpdGEgKyB2cGx5dm7DqSBib2R5KQogIGpiIDwtIHRyeUNhdGNoKHRzZXJpZXM6OmphcnF1ZS5iZXJhLnRlc3QocmVzaWR1YWxzKG1vZGVsKSksIGVycm9yID0gZnVuY3Rpb24oZSkgTlVMTCkKICBpZiAoIWlzLm51bGwoamIpKSB7CiAgICBjYXQoc3ByaW50ZigiTm9ybWFsaXRhIHJlesOtZHXDrSAoSmFycXVl4oCTQmVyYSk6IHAgPSAlLjRmIOKGkiAlcy5cbiIsCiAgICAgICAgICAgICAgICBqYiRwLnZhbHVlLAogICAgICAgICAgICAgICAgaWZlbHNlKGpiJHAudmFsdWUgPCAwLjA1LAogICAgICAgICAgICAgICAgICAgICAgICJyZXppZHXDoSBuaWUgc8O6IMO6cGxuZSBub3Jtw6FsbmUg4oCTIHByaSBla29ub21pY2vDvWNoIGTDoXRhY2ggYmXFvm7DqSIsCiAgICAgICAgICAgICAgICAgICAgICAgIm5vcm1hbGl0YSByZXrDrWR1w60gbmVib2xhIHphbWlldG51dMOhIikpKQogIH0KICAjIFRPUCB2cGx5dm7DqQogIGNkIDwtIGNvb2tzLmRpc3RhbmNlKG1vZGVsKTsgc3R1ZCA8LSByc3R1ZGVudChtb2RlbCkKICB0b3AgPC0gaGVhZChvcmRlcihjZCwgZGVjcmVhc2luZyA9IFRSVUUpLCAzKQogIGNhdCgiXG5OYWp2cGx5dm5lasWhaWUgcG96b3JvdmFuaWEgcG9kxL5hIENvb2tvdmVqIHZ6ZGlhbGVub3N0aTpcbiIpCiAgZm9yIChpIGluIHRvcCkgewogICAgbm0gPC0gaWYgKCJOYXpvdiIgJWluJSBuYW1lcyhkYXRhKSkgYXMuY2hhcmFjdGVyKGRhdGEkTmF6b3ZbaV0pIGVsc2UgcGFzdGUoImluZGV4IiwgaSkKICAgIGNhdChzcHJpbnRmKCIgIOKAoiAlcyDigJMgQ29va0QgPSAlLjNmLCByc3R1ZGVudCA9ICUuMmZcbiIsIG5tLCBjZFtpXSwgc3R1ZFtpXSkpCiAgfQoKICBjYXQoIlxuWsOhdmVyIGsgbW9qw61tIGTDoXRhbTpcbiIpCiAgaWYgKG5yb3coc2lnKSkgewogICAgY2F0KCLigJMgViBtb2pvbSBzw7pib3JlIHNhIGFrbyDFoXRhdGlzdGlja3kgdsO9em5hbW7DqSB1a8OhemFsaSB2ecWhxaFpZSB1dmVkZW7DqSBwcmVtZW5uw6k7IGljaCB6bmFtaWVua2EgbmF6bmHEjXVqw7ogc21lciB2cGx5dnUgbmEgIiwKICAgICAgICB0YXJnZXRfbmFtZSwgIi5cbiIsIHNlcCA9ICIiKQogIH0gZWxzZSB7CiAgICBjYXQoIuKAkyBWIGRvc3R1cG5laiB2em9ya2Ugc2EgbmVwb2RhcmlsbyBwcmV1a8OhemHFpSDFoXRhdGlzdGlja3kgdsO9em5hbW55IHZwbHl2IHZ5c3ZldMS+dWrDumNpY2ggcHJlbWVubsO9Y2ggbmEgIiwKICAgICAgICB0YXJnZXRfbmFtZSwgIiBuYSA1ICUgaGxhZGluZS5cbiIsIHNlcCA9ICIiKQogIH0KICBjYXQoIuKAkyBQb2TEvmEgUsKyIG1vZGVsIHZ5c3ZldMS+dWplICIsIHNwcmludGYoIiUuMWYlJSIsIDEwMCpyMiksCiAgICAgICIgdmFyaWFiaWxpdHkgY2llxL5vdmVqIHByZW1lbm5lai4gRGlhZ25vc3Rpa2EgbmF6bmHEjXVqZSwgxI1pIGplIHZob2Ruw6kgenbDocW+acWlIHRyYW5zZm9ybcOhY2llIChuYXByLiBsb2cxcCBwcmUgxaFpa23DqSBwcmVtZW5uw6kpIGFsZWJvIGtvbnRyb2x1IHZwbHl2bsO9Y2ggcHLDrXBhZG92LlxuIiwgc2VwID0gIiIpCn0KCiMgLS0tLS0tLSBTcHVzdGkgaW50ZXJwcmV0w6FjaXUgcHJlIFRWT0ogbW9kZWwgLS0tLS0tLQojIHByw61rbGFkOiBtb2RlbCA8LSBsbShST0UgfiBST0EgKyBFQklUREFtYXJ6YSArIE0gKyBaICsgRm9ybWEsIGRhdGEgPSB1ZGFqZSkKaW50ZXJwcmV0X21vZGVsKG1vZGVsLCB1ZGFqZSwgdGFyZ2V0X25hbWUgPSAiUk9FIikKCmBgYAoK