knitr::opts_chunk$set(
    echo = TRUE,
    message = FALSE,
    warning = FALSE
)

Import údajov z otv. databáz

Import údajov z .csv alebo .xls

udaje <- read.csv2("population_data.csv",header=TRUE,sep=",",dec=".")
head(udaje)                                             # niekolko prvych riadkov
colnames(udaje)                                         # nazvy premennych

Grafy

library(dplyr)
library(ggplot2)

# zoradíme podľa populácie v roku 2025 a vyberieme top 5
top5 <- udaje %>%
  arrange(desc(Population.2025)) %>%
  slice_head(n = 5)

# vykreslenie grafu
ggplot(top5, aes(x = reorder(Country..or.dependency., Population.2025), 
                 y = Population.2025, 
                 fill = Country..or.dependency.)) +
  geom_col() +
  coord_flip() +  # otočí osi, aby sa krajiny lepšie čítali
  labs(
    title = "5 krajín s najväčšou populáciou (2025)",
    x = "Krajina",
    y = "Počet obyvateľov (v miliónoch)"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

ggplot2 - knižnica pre grafy

library(ggplot2)
library(dplyr)

# zoradíme a vyberieme top 5 krajín
top5 <- udaje %>%
  arrange(desc(Population.2025)) %>%
  slice_head(n = 5)

# vytvorenie pekného ggplot2 grafu
ggplot(top5, aes(
  x = reorder(Country..or.dependency., Population.2025),
  y = Population.2025,
  fill = Country..or.dependency.
)) +
  geom_bar(stat = "identity", width = 0.6, show.legend = FALSE) +
  geom_text(aes(label = round(Population.2025, 1)),
            hjust = -0.1, size = 4, color = "black") +
  coord_flip() +
  labs(
    title = "Top 5 krajín s najväčšou populáciou (2025)",
    x = "Krajina",
    y = "Populácia (v miliónoch)"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.y = element_text(face = "bold")
  )

Výber a následné triedenie

library(dplyr)

udaje_2025 <- udaje %>%
  select(Country..or.dependency., Population.2025)

head(udaje_2025)
library(tidyr)
library(dplyr)

udaje_long <- udaje %>%
  pivot_longer(
    cols = starts_with("Population."),
    names_to = "Year",
    values_to = "Population"
  ) %>%
  mutate(
    Year = as.numeric(gsub("Population\\.", "", Year))
  )

head(udaje_long)
library(dplyr)
library(ggplot2)

udaje %>%
  filter(Country..or.dependency. %in% c("China","India","United States")) %>%
  ggplot(aes(x = reorder(Country..or.dependency., Population.2025),
             y = Population.2025,
             fill = Country..or.dependency.)) +
  geom_col(width = 0.6, show.legend = FALSE) +
  geom_text(aes(label = format(Population.2025, big.mark = " ", scientific = FALSE)),
            hjust = -0.1, size = 4, color = "black") +
  coord_flip() +
  labs(title = "Populácia v roku 2025 (vybrané krajiny)",
       x = "Krajina",
       y = "Počet obyvateľov") +
  theme_minimal(base_size = 13)

Scatter plot


library(ggplot2)

ggplot(udaje, aes(x = Density..P.Km.., y = Population.2025)) +
  geom_point(color = "steelblue", size = 2, alpha = 0.7) +
  theme_minimal() +
  labs(
    title = "Vzťah medzi hustotou obyvateľstva a populáciou (2025)",
    x = "Hustota obyvateľstva (obyv./km²)",
    y = "Populácia (v miliónoch)"
  )

Boxplot

library(ggplot2)
library(dplyr)

# vyber 5 náhodných krajín
set.seed(123)  # pre opakovateľnosť výsledku
vyber <- sample(unique(udaje$Country..or.dependency.), 5)

# filtrovanie datasetu len na tieto krajiny
udaje_vyber <- udaje %>%
  filter(Country..or.dependency. %in% vyber)

# boxplot hustoty obyvateľstva pre vybrané krajiny
ggplot(udaje_vyber, aes(x = Country..or.dependency., y = Density..P.Km..)) +
  geom_boxplot(fill = "lightblue", color = "darkblue") +
  theme_minimal() +
  labs(
    title = "Hustota obyvateľstva v 5 náhodne vybraných krajinách",
    x = "Krajina",
    y = "Hustota obyvateľstva (obyv./km²)"
  )

Základné štatistiky.

knitr - tabuľka

library(dplyr)
library(knitr)

# Základné štatistiky pre Land Area
land.stats <- udaje %>%
  summarise(
    n = n(),
    mean = mean(Land.Area..Km.., na.rm = TRUE),
    sd = sd(Land.Area..Km.., na.rm = TRUE),
    min = min(Land.Area..Km.., na.rm = TRUE),
    q25 = quantile(Land.Area..Km.., 0.25, na.rm = TRUE),
    median = median(Land.Area..Km.., na.rm = TRUE),
    q75 = quantile(Land.Area..Km.., 0.75, na.rm = TRUE),
    max = max(Land.Area..Km.., na.rm = TRUE)
  )

# Výstup tabuľky s formátovaním
kable(
  land.stats %>%
    mutate(across(where(is.numeric), ~ format(., big.mark = " "))),
  caption = "Základné štatistiky rozlohy krajín (v km²)"
)

alebo krajšie tabuľky s pomocou .kableExtra.:

library(dplyr)
library(knitr)
library(kableExtra)

# Výpočet základných štatistík pre Land Area
land.stats <- udaje %>%
  summarise(
    n = n(),
    mean = mean(Land.Area..Km.., na.rm = TRUE),
    sd = sd(Land.Area..Km.., na.rm = TRUE),
    min = min(Land.Area..Km.., na.rm = TRUE),
    q25 = quantile(Land.Area..Km.., 0.25, na.rm = TRUE),
    median = median(Land.Area..Km.., na.rm = TRUE),
    q75 = quantile(Land.Area..Km.., 0.75, na.rm = TRUE),
    max = max(Land.Area..Km.., na.rm = TRUE)
  )

# Vytvorenie štýlovanej tabuľky
land.stats %>%
  mutate(across(where(is.numeric), ~ format(., big.mark = " "))) %>%
  kable(
    digits = 2,
    caption = "Základné štatistiky rozlohy krajín (Land Area, km²)"
  ) %>%
  kable_styling(
    full_width = FALSE,
    bootstrap_options = c("striped", "hover", "condensed")
  ) %>%
  row_spec(0, bold = TRUE, background = "#f2f2f2") %>%
  add_header_above(c(" " = 1, "Land Area Statistics" = 7))

Testovanie hypotéz

t-test: Rozdiel v priemernej hustote obyvateľstva

#Vytvoríme hypotézu
#H₀ (nulová hypotéza): priemerná hustota obyvateľstva v krajinách s malou a veľkou rozlohou je rovnaká
#H₁ (alternatívna hypotéza): priemerná hustota obyvateľstva sa líši medzi krajinami s malou a veľkou rozlohou
# vytvoríme dve skupiny krajín: malé a veľké podľa mediánu rozlohy
median_area <- median(udaje$Land.Area..Km.., na.rm = TRUE)

male_krajiny <- udaje %>%
  filter(Land.Area..Km.. <= median_area) %>%
  pull(Density..P.Km..)

velke_krajiny <- udaje %>%
  filter(Land.Area..Km.. > median_area) %>%
  pull(Density..P.Km..)

# t-test pre rozdiel priemerov hustoty obyvateľstva
t.test.result <- t.test(male_krajiny, velke_krajiny)

# výpis výsledku
print(t.test.result)

Zhrnutie:
Výsledok je štatisticky významný.
Malé krajiny majú v priemere vyššiu hustotu obyvateľstva.
T-test aj interpretácia sú urobené správne.

ANOVA:

library(dplyr)

# rozdelenie krajín do 3 kategórií podľa rozlohy (tercily)
udaje_anova <- udaje %>%
  mutate(
    Velkost_krajiny = cut(
      Land.Area..Km..,
      breaks = quantile(Land.Area..Km.., probs = c(0, 1/3, 2/3, 1), na.rm = TRUE),
      include.lowest = TRUE,
      labels = c("Malá", "Stredná", "Veľká")
    )
  )

# vykonanie ANOVA testu
anova.result <- aov(Density..P.Km.. ~ Velkost_krajiny, data = udaje_anova)

# výpis výsledkov
summary(anova.result)

Keďže p-hodnota (0.00405) < 0.05, zamietame nulovú hypotézu (H₀). To znamená, že existuje štatisticky významný rozdiel v priemernej hustote obyvateľstva medzi skupinami krajín rôznej veľkosti (malé, stredné, veľké).

Linear Regression:

#Skúsme analyzovať, ako rozloha krajiny ovplyvňuje hustotu obyvateľstva.
#H₀: Medzi rozlohou a hustotou obyvateľstva nie je lineárny vzťah.
#H₁: Hustota obyvateľstva sa mení v závislosti od rozlohy krajiny.

# lineárna regresia: hustota ~ rozloha
model <- lm(Density..P.Km.. ~ Land.Area..Km.., data = udaje)

# výpis výsledkov
summary(model)

Na základe výsledkov lineárnej regresie (F = 0,7855; p = 0,3764) môžeme konštatovať, že neexistuje štatisticky významný lineárny vzťah medzi rozlohou krajiny a hustotou obyvateľstva. Hodnota koeficientu determinácie (R² = 0,0034) naznačuje, že rozloha vysvetľuje iba zanedbateľnú časť variability hustoty obyvateľstva.

# install.packages(c("broom", "kableExtra", "dplyr", "stringr"))

library(broom)
library(dplyr)
library(kableExtra)
library(stringr)

# 1️⃣ Vytvorenie lineárneho modelu
model <- lm(Density..P.Km.. ~ Land.Area..Km.. + Population.2025, data = udaje)

# 2️⃣ Tabuľka koeficientov s významnosťou
coef.tbl <- tidy(model, conf.int = TRUE) %>%
  mutate(
    term = recode(term,
      "(Intercept)" = "Intercept",
      "Land.Area..Km2." = "Land Area (km²)",
      "Population.2025" = "Population 2025"
    ),
    stars = case_when(
      p.value < 0.001 ~ "***",
      p.value < 0.01 ~ "**",
      p.value < 0.05 ~ "*",
      p.value < 0.1 ~ ".",
      TRUE ~ ""
    )
  ) %>%
  transmute(
    Term = term,
    Estimate = round(estimate, 4),
    `Std. Error` = round(std.error, 4),
    `t value` = round(statistic, 3),
    `p value` = round(p.value, 4),
    `95% CI` = str_c("[", round(conf.low, 3), ", ", round(conf.high, 3), "]"),
    Sig = stars
  )

# 3️⃣ Zobrazenie tabuľky koeficientov
coef.tbl %>%
  kable(
    digits = 3,
    caption = "OLS Regression Coefficients (Density ~ Land Area + Population)"
  ) %>%
  kable_styling(
    full_width = FALSE,
    bootstrap_options = c("striped", "hover", "condensed")
  ) %>%
  column_spec(1, bold = TRUE) %>%
  row_spec(0, bold = TRUE, background = "#f2f2f2") %>%
  footnote(
    general = "Signif. codes: *** p<0.001, ** p<0.01, * p<0.05, . p<0.1",
    threeparttable = TRUE
  )

# 4️⃣ Štatistiky kvality modelu
fit.tbl <- glance(model) %>%
  transmute(
    `R-squared` = round(r.squared, 4),
    `Adj. R-squared` = round(adj.r.squared, 4),
    `F-statistic` = round(statistic, 3),
    `F p-value` = round(p.value, 4),
    `AIC` = round(AIC, 2),
    `BIC` = round(BIC, 2),
    `Num. obs.` = nobs
  )

fit.tbl %>%
  kable(
    digits = 3,
    caption = "Model Fit Statistics"
  ) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("condensed"))

#Na základe výsledkov lineárnej regresie môžeme konštatovať, že model nevysvetľuje variabilitu hustoty obyvateľstva prostredníctvom rozlohy krajiny a počtu obyvateľov. Hodnota koeficientu determinácie (R² = 0,003) je veľmi nízka a p-hodnota (p = 0,677) naznačuje, že vzťah medzi premennými nie je štatisticky významný. Celkovo teda model nepreukázal žiadny významný vplyv rozlohy ani populácie na hustotu obyvateľstva.

##Heatmap

# install.packages(c("ggplot2", "reshape2", "dplyr"))

library(ggplot2)
library(reshape2)
library(dplyr)

# 1️⃣ Výber len numerických premenných
num_data <- udaje %>%
  select_if(is.numeric)

# 2️⃣ Výpočet korelačnej matice
corr_matrix <- cor(num_data, use = "complete.obs")

# 3️⃣ Transformácia pre ggplot (dlhý formát)
corr_melt <- melt(corr_matrix)

# 4️⃣ Vykreslenie heatmapy
ggplot(corr_melt, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile(color = "white") +
  scale_fill_gradient2(
    low = "darkred",
    mid = "white",
    high = "darkblue",
    midpoint = 0,
    limit = c(-1, 1),
    name = "Korelácia"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1, size = 9),
    axis.text.y = element_text(size = 9)
  ) +
  labs(
    title = "Korelačná matica numerických premenných",
    x = "",
    y = ""
  )

Komentár k Heatmap

Na základe korelačnej matice môžeme pozorovať, že medzi jednotlivými numerickými premennými existujú viaceré vzťahy rôznej intenzity. Najsilnejšia pozitívna korelácia sa prejavuje medzi počtom obyvateľov (Population 2025) a rozlohou krajiny (Land Area), čo je logické – väčšie krajiny mávajú spravidla aj viac obyvateľov. Naopak, negatívna korelácia sa objavuje medzi mediánovým vekom (Median Age) a mierou plodnosti (Fertility Rate), čo naznačuje, že krajiny s vyšším priemerným vekom populácie majú nižšiu pôrodnosť. Ostatné vzťahy medzi premennými sú len slabé až mierne, čo naznačuje, že väčšina ukazovateľov je medzi sebou relatívne nezávislá.

LS0tCnRpdGxlOiAiUHLDoWNhIHMgZGF0YWLDoXpvdSAtIGltcG9ydCDDumRham92LCBncmFmeSwgxaF0YXRpc3Rpa3kiCmF1dGhvcjogIlJhZG92YW4gU3RhbsSNw61rICA8YnI+CihzIHZ5dcW+aXTDrW0gdmVyZWpuZSBkb3N0dXBuw71jaCBrw7Nkb3YgYSBDaGF0R1BUKSIKZGF0ZTogIk9rdMOzYmVyIDIwMjUiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0aGVtZTogZmxhdGx5CiAgICBoaWdobGlnaHQ6IHRhbmdvCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiA3MgotLS0KCmBgYHtyfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgICBlY2hvID0gVFJVRSwKICAgIG1lc3NhZ2UgPSBGQUxTRSwKICAgIHdhcm5pbmcgPSBGQUxTRQopCmBgYAoKIyBJbXBvcnQgw7pkYWpvdiB6IG90di4gZGF0YWLDoXoKIyMgSW1wb3J0IMO6ZGFqb3YgeiAuY3N2IGFsZWJvIC54bHMKCmBgYHtyfQp1ZGFqZSA8LSByZWFkLmNzdjIoInBvcHVsYXRpb25fZGF0YS5jc3YiLGhlYWRlcj1UUlVFLHNlcD0iLCIsZGVjPSIuIikKaGVhZCh1ZGFqZSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG5pZWtvbGtvIHBydnljaCByaWFka292CmNvbG5hbWVzKHVkYWplKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBuYXp2eSBwcmVtZW5ueWNoCmBgYAoKCiMgR3JhZnkKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgem9yYWTDrW1lIHBvZMS+YSBwb3B1bMOhY2llIHYgcm9rdSAyMDI1IGEgdnliZXJpZW1lIHRvcCA1CnRvcDUgPC0gdWRhamUgJT4lCiAgYXJyYW5nZShkZXNjKFBvcHVsYXRpb24uMjAyNSkpICU+JQogIHNsaWNlX2hlYWQobiA9IDUpCgojIHZ5a3Jlc2xlbmllIGdyYWZ1CmdncGxvdCh0b3A1LCBhZXMoeCA9IHJlb3JkZXIoQ291bnRyeS4ub3IuZGVwZW5kZW5jeS4sIFBvcHVsYXRpb24uMjAyNSksIAogICAgICAgICAgICAgICAgIHkgPSBQb3B1bGF0aW9uLjIwMjUsIAogICAgICAgICAgICAgICAgIGZpbGwgPSBDb3VudHJ5Li5vci5kZXBlbmRlbmN5LikpICsKICBnZW9tX2NvbCgpICsKICBjb29yZF9mbGlwKCkgKyAgIyBvdG/EjcOtIG9zaSwgYWJ5IHNhIGtyYWppbnkgbGVwxaFpZSDEjcOtdGFsaQogIGxhYnMoCiAgICB0aXRsZSA9ICI1IGtyYWrDrW4gcyBuYWp2w6TEjcWhb3UgcG9wdWzDoWNpb3UgKDIwMjUpIiwKICAgIHggPSAiS3JhamluYSIsCiAgICB5ID0gIlBvxI1ldCBvYnl2YXRlxL5vdiAodiBtaWxpw7Nub2NoKSIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgojIyMgZ2dwbG90MiAtIGtuacW+bmljYSBwcmUgZ3JhZnkKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKCiMgem9yYWTDrW1lIGEgdnliZXJpZW1lIHRvcCA1IGtyYWrDrW4KdG9wNSA8LSB1ZGFqZSAlPiUKICBhcnJhbmdlKGRlc2MoUG9wdWxhdGlvbi4yMDI1KSkgJT4lCiAgc2xpY2VfaGVhZChuID0gNSkKCiMgdnl0dm9yZW5pZSBwZWtuw6lobyBnZ3Bsb3QyIGdyYWZ1CmdncGxvdCh0b3A1LCBhZXMoCiAgeCA9IHJlb3JkZXIoQ291bnRyeS4ub3IuZGVwZW5kZW5jeS4sIFBvcHVsYXRpb24uMjAyNSksCiAgeSA9IFBvcHVsYXRpb24uMjAyNSwKICBmaWxsID0gQ291bnRyeS4ub3IuZGVwZW5kZW5jeS4KKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNiwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChQb3B1bGF0aW9uLjIwMjUsIDEpKSwKICAgICAgICAgICAgaGp1c3QgPSAtMC4xLCBzaXplID0gNCwgY29sb3IgPSAiYmxhY2siKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVG9wIDUga3JhasOtbiBzIG5hanbDpMSNxaFvdSBwb3B1bMOhY2lvdSAoMjAyNSkiLAogICAgeCA9ICJLcmFqaW5hIiwKICAgIHkgPSAiUG9wdWzDoWNpYSAodiBtaWxpw7Nub2NoKSIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpCiAgKQoKYGBgCgoKVsO9YmVyIGEgbsOhc2xlZG7DqSB0cmllZGVuaWUKYGBge3J9CmxpYnJhcnkoZHBseXIpCgp1ZGFqZV8yMDI1IDwtIHVkYWplICU+JQogIHNlbGVjdChDb3VudHJ5Li5vci5kZXBlbmRlbmN5LiwgUG9wdWxhdGlvbi4yMDI1KQoKaGVhZCh1ZGFqZV8yMDI1KQoKYGBgCgpgYGB7cn0KbGlicmFyeSh0aWR5cikKbGlicmFyeShkcGx5cikKCnVkYWplX2xvbmcgPC0gdWRhamUgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IHN0YXJ0c193aXRoKCJQb3B1bGF0aW9uLiIpLAogICAgbmFtZXNfdG8gPSAiWWVhciIsCiAgICB2YWx1ZXNfdG8gPSAiUG9wdWxhdGlvbiIKICApICU+JQogIG11dGF0ZSgKICAgIFllYXIgPSBhcy5udW1lcmljKGdzdWIoIlBvcHVsYXRpb25cXC4iLCAiIiwgWWVhcikpCiAgKQoKaGVhZCh1ZGFqZV9sb25nKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCgp1ZGFqZSAlPiUKICBmaWx0ZXIoQ291bnRyeS4ub3IuZGVwZW5kZW5jeS4gJWluJSBjKCJDaGluYSIsIkluZGlhIiwiVW5pdGVkIFN0YXRlcyIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKENvdW50cnkuLm9yLmRlcGVuZGVuY3kuLCBQb3B1bGF0aW9uLjIwMjUpLAogICAgICAgICAgICAgeSA9IFBvcHVsYXRpb24uMjAyNSwKICAgICAgICAgICAgIGZpbGwgPSBDb3VudHJ5Li5vci5kZXBlbmRlbmN5LikpICsKICBnZW9tX2NvbCh3aWR0aCA9IDAuNiwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBmb3JtYXQoUG9wdWxhdGlvbi4yMDI1LCBiaWcubWFyayA9ICIgIiwgc2NpZW50aWZpYyA9IEZBTFNFKSksCiAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgc2l6ZSA9IDQsIGNvbG9yID0gImJsYWNrIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh0aXRsZSA9ICJQb3B1bMOhY2lhIHYgcm9rdSAyMDI1ICh2eWJyYW7DqSBrcmFqaW55KSIsCiAgICAgICB4ID0gIktyYWppbmEiLAogICAgICAgeSA9ICJQb8SNZXQgb2J5dmF0ZcS+b3YiKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykKCmBgYAoKIyMjIyBTY2F0dGVyIHBsb3QKYGBge3Igc2NhdHRlcnBsb3QsIGVjaG89VFJVRX0KCmxpYnJhcnkoZ2dwbG90MikKCmdncGxvdCh1ZGFqZSwgYWVzKHggPSBEZW5zaXR5Li5QLkttLi4sIHkgPSBQb3B1bGF0aW9uLjIwMjUpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiLCBzaXplID0gMiwgYWxwaGEgPSAwLjcpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWesWlYWggbWVkemkgaHVzdG90b3Ugb2J5dmF0ZcS+c3R2YSBhIHBvcHVsw6FjaW91ICgyMDI1KSIsCiAgICB4ID0gIkh1c3RvdGEgb2J5dmF0ZcS+c3R2YSAob2J5di4va23CsikiLAogICAgeSA9ICJQb3B1bMOhY2lhICh2IG1pbGnDs25vY2gpIgogICkKCmBgYAoKIyMjIyBCb3hwbG90CmBgYHtyIGJveHBsb3QtcmFuZG9tLCBlY2hvPVRSVUV9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKCiMgdnliZXIgNSBuw6Fob2Ruw71jaCBrcmFqw61uCnNldC5zZWVkKDEyMykgICMgcHJlIG9wYWtvdmF0ZcS+bm9zxaUgdsO9c2xlZGt1CnZ5YmVyIDwtIHNhbXBsZSh1bmlxdWUodWRhamUkQ291bnRyeS4ub3IuZGVwZW5kZW5jeS4pLCA1KQoKIyBmaWx0cm92YW5pZSBkYXRhc2V0dSBsZW4gbmEgdGlldG8ga3JhamlueQp1ZGFqZV92eWJlciA8LSB1ZGFqZSAlPiUKICBmaWx0ZXIoQ291bnRyeS4ub3IuZGVwZW5kZW5jeS4gJWluJSB2eWJlcikKCiMgYm94cGxvdCBodXN0b3R5IG9ieXZhdGXEvnN0dmEgcHJlIHZ5YnJhbsOpIGtyYWppbnkKZ2dwbG90KHVkYWplX3Z5YmVyLCBhZXMoeCA9IENvdW50cnkuLm9yLmRlcGVuZGVuY3kuLCB5ID0gRGVuc2l0eS4uUC5LbS4uKSkgKwogIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImRhcmtibHVlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkh1c3RvdGEgb2J5dmF0ZcS+c3R2YSB2IDUgbsOhaG9kbmUgdnlicmFuw71jaCBrcmFqaW7DoWNoIiwKICAgIHggPSAiS3JhamluYSIsCiAgICB5ID0gIkh1c3RvdGEgb2J5dmF0ZcS+c3R2YSAob2J5di4va23CsikiCiAgKQoKYGBgCgojIFrDoWtsYWRuw6kgxaF0YXRpc3Rpa3kuIAojIyBrbml0ciAtIHRhYnXEvmthCmBgYHtyIHN1bW1hcnktbGFuZCwgZWNobz1UUlVFfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGtuaXRyKQoKIyBaw6FrbGFkbsOpIMWhdGF0aXN0aWt5IHByZSBMYW5kIEFyZWEKbGFuZC5zdGF0cyA8LSB1ZGFqZSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgbWVhbiA9IG1lYW4oTGFuZC5BcmVhLi5LbS4uLCBuYS5ybSA9IFRSVUUpLAogICAgc2QgPSBzZChMYW5kLkFyZWEuLkttLi4sIG5hLnJtID0gVFJVRSksCiAgICBtaW4gPSBtaW4oTGFuZC5BcmVhLi5LbS4uLCBuYS5ybSA9IFRSVUUpLAogICAgcTI1ID0gcXVhbnRpbGUoTGFuZC5BcmVhLi5LbS4uLCAwLjI1LCBuYS5ybSA9IFRSVUUpLAogICAgbWVkaWFuID0gbWVkaWFuKExhbmQuQXJlYS4uS20uLiwgbmEucm0gPSBUUlVFKSwKICAgIHE3NSA9IHF1YW50aWxlKExhbmQuQXJlYS4uS20uLiwgMC43NSwgbmEucm0gPSBUUlVFKSwKICAgIG1heCA9IG1heChMYW5kLkFyZWEuLkttLi4sIG5hLnJtID0gVFJVRSkKICApCgojIFbDvXN0dXAgdGFidcS+a3kgcyBmb3Jtw6F0b3ZhbsOtbQprYWJsZSgKICBsYW5kLnN0YXRzICU+JQogICAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBmb3JtYXQoLiwgYmlnLm1hcmsgPSAiICIpKSksCiAgY2FwdGlvbiA9ICJaw6FrbGFkbsOpIMWhdGF0aXN0aWt5IHJvemxvaHkga3JhasOtbiAodiBrbcKyKSIKKQoKYGBgCgphbGVibyBrcmFqxaFpZSB0YWJ1xL5reSBzIHBvbW9jb3UgLmthYmxlRXh0cmEuOgpgYGB7ciBzdHlsZWQtdGFibGUsIGVjaG89VFJVRX0KbGlicmFyeShkcGx5cikKbGlicmFyeShrbml0cikKbGlicmFyeShrYWJsZUV4dHJhKQoKIyBWw71wb8SNZXQgesOha2xhZG7DvWNoIMWhdGF0aXN0w61rIHByZSBMYW5kIEFyZWEKbGFuZC5zdGF0cyA8LSB1ZGFqZSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgbWVhbiA9IG1lYW4oTGFuZC5BcmVhLi5LbS4uLCBuYS5ybSA9IFRSVUUpLAogICAgc2QgPSBzZChMYW5kLkFyZWEuLkttLi4sIG5hLnJtID0gVFJVRSksCiAgICBtaW4gPSBtaW4oTGFuZC5BcmVhLi5LbS4uLCBuYS5ybSA9IFRSVUUpLAogICAgcTI1ID0gcXVhbnRpbGUoTGFuZC5BcmVhLi5LbS4uLCAwLjI1LCBuYS5ybSA9IFRSVUUpLAogICAgbWVkaWFuID0gbWVkaWFuKExhbmQuQXJlYS4uS20uLiwgbmEucm0gPSBUUlVFKSwKICAgIHE3NSA9IHF1YW50aWxlKExhbmQuQXJlYS4uS20uLiwgMC43NSwgbmEucm0gPSBUUlVFKSwKICAgIG1heCA9IG1heChMYW5kLkFyZWEuLkttLi4sIG5hLnJtID0gVFJVRSkKICApCgojIFZ5dHZvcmVuaWUgxaF0w71sb3ZhbmVqIHRhYnXEvmt5CmxhbmQuc3RhdHMgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiBmb3JtYXQoLiwgYmlnLm1hcmsgPSAiICIpKSkgJT4lCiAga2FibGUoCiAgICBkaWdpdHMgPSAyLAogICAgY2FwdGlvbiA9ICJaw6FrbGFkbsOpIMWhdGF0aXN0aWt5IHJvemxvaHkga3JhasOtbiAoTGFuZCBBcmVhLCBrbcKyKSIKICApICU+JQogIGthYmxlX3N0eWxpbmcoCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikKICApICU+JQogIHJvd19zcGVjKDAsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNmMmYyZjIiKSAlPiUKICBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiID0gMSwgIkxhbmQgQXJlYSBTdGF0aXN0aWNzIiA9IDcpKQoKYGBgCgoKIyBUZXN0b3ZhbmllIGh5cG90w6l6CgojIyMjIHQtdGVzdDogUm96ZGllbCB2IHByaWVtZXJuZWogaHVzdG90ZSBvYnl2YXRlxL5zdHZhCmBgYHtyIHQtdGVzdCwgZWNobz1UUlVFfQojVnl0dm9yw61tZSBoeXBvdMOpenUKI0jigoAgKG51bG92w6EgaHlwb3TDqXphKTogcHJpZW1lcm7DoSBodXN0b3RhIG9ieXZhdGXEvnN0dmEgdiBrcmFqaW7DoWNoIHMgbWFsb3UgYSB2ZcS+a291IHJvemxvaG91IGplIHJvdm5ha8OhCiNI4oKBIChhbHRlcm5hdMOtdm5hIGh5cG90w6l6YSk6IHByaWVtZXJuw6EgaHVzdG90YSBvYnl2YXRlxL5zdHZhIHNhIGzDrcWhaSBtZWR6aSBrcmFqaW5hbWkgcyBtYWxvdSBhIHZlxL5rb3Ugcm96bG9ob3UKIyB2eXR2b3LDrW1lIGR2ZSBza3VwaW55IGtyYWrDrW46IG1hbMOpIGEgdmXEvmvDqSBwb2TEvmEgbWVkacOhbnUgcm96bG9oeQptZWRpYW5fYXJlYSA8LSBtZWRpYW4odWRhamUkTGFuZC5BcmVhLi5LbS4uLCBuYS5ybSA9IFRSVUUpCgptYWxlX2tyYWppbnkgPC0gdWRhamUgJT4lCiAgZmlsdGVyKExhbmQuQXJlYS4uS20uLiA8PSBtZWRpYW5fYXJlYSkgJT4lCiAgcHVsbChEZW5zaXR5Li5QLkttLi4pCgp2ZWxrZV9rcmFqaW55IDwtIHVkYWplICU+JQogIGZpbHRlcihMYW5kLkFyZWEuLkttLi4gPiBtZWRpYW5fYXJlYSkgJT4lCiAgcHVsbChEZW5zaXR5Li5QLkttLi4pCgojIHQtdGVzdCBwcmUgcm96ZGllbCBwcmllbWVyb3YgaHVzdG90eSBvYnl2YXRlxL5zdHZhCnQudGVzdC5yZXN1bHQgPC0gdC50ZXN0KG1hbGVfa3JhamlueSwgdmVsa2Vfa3JhamlueSkKCiMgdsO9cGlzIHbDvXNsZWRrdQpwcmludCh0LnRlc3QucmVzdWx0KQoKYGBgCioqWmhybnV0aWU6KiogIApWw71zbGVkb2sgamUgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70uICAKTWFsw6kga3JhamlueSBtYWrDuiB2IHByaWVtZXJlIHZ5xaHFoWl1IGh1c3RvdHUgb2J5dmF0ZcS+c3R2YS4gIApULXRlc3QgYWogaW50ZXJwcmV0w6FjaWEgc8O6IHVyb2JlbsOpIHNwcsOhdm5lLgoKCiMjIyMgQU5PVkE6CmBgYHtyIGFub3ZhLXRlc3QsIGVjaG89VFJVRX0KbGlicmFyeShkcGx5cikKCiMgcm96ZGVsZW5pZSBrcmFqw61uIGRvIDMga2F0ZWfDs3Jpw60gcG9kxL5hIHJvemxvaHkgKHRlcmNpbHkpCnVkYWplX2Fub3ZhIDwtIHVkYWplICU+JQogIG11dGF0ZSgKICAgIFZlbGtvc3Rfa3JhamlueSA9IGN1dCgKICAgICAgTGFuZC5BcmVhLi5LbS4uLAogICAgICBicmVha3MgPSBxdWFudGlsZShMYW5kLkFyZWEuLkttLi4sIHByb2JzID0gYygwLCAxLzMsIDIvMywgMSksIG5hLnJtID0gVFJVRSksCiAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRSwKICAgICAgbGFiZWxzID0gYygiTWFsw6EiLCAiU3RyZWRuw6EiLCAiVmXEvmvDoSIpCiAgICApCiAgKQoKIyB2eWtvbmFuaWUgQU5PVkEgdGVzdHUKYW5vdmEucmVzdWx0IDwtIGFvdihEZW5zaXR5Li5QLkttLi4gfiBWZWxrb3N0X2tyYWppbnksIGRhdGEgPSB1ZGFqZV9hbm92YSkKCiMgdsO9cGlzIHbDvXNsZWRrb3YKc3VtbWFyeShhbm92YS5yZXN1bHQpCgpgYGAKS2XEj8W+ZSBwLWhvZG5vdGEgKDAuMDA0MDUpIDwgMC4wNSwgemFtaWV0YW1lIG51bG92w7ogaHlwb3TDqXp1IChI4oKAKS4KVG8gem5hbWVuw6EsIMW+ZSBleGlzdHVqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSByb3pkaWVsIHYgcHJpZW1lcm5laiBodXN0b3RlIG9ieXZhdGXEvnN0dmEgbWVkemkgc2t1cGluYW1pIGtyYWrDrW4gcsO0em5laiB2ZcS+a29zdGkgKG1hbMOpLCBzdHJlZG7DqSwgdmXEvmvDqSkuCgoKIyMjIyBMaW5lYXIgUmVncmVzc2lvbjoKYGBge3IgbGluZWFyLW1vZGVsLCBlY2hvPVRSVUV9CiNTa8O6c21lIGFuYWx5em92YcWlLCBha28gcm96bG9oYSBrcmFqaW55IG92cGx5dsWIdWplIGh1c3RvdHUgb2J5dmF0ZcS+c3R2YS4KI0jigoA6IE1lZHppIHJvemxvaG91IGEgaHVzdG90b3Ugb2J5dmF0ZcS+c3R2YSBuaWUgamUgbGluZcOhcm55IHZ6xaVhaC4KI0jigoE6IEh1c3RvdGEgb2J5dmF0ZcS+c3R2YSBzYSBtZW7DrSB2IHrDoXZpc2xvc3RpIG9kIHJvemxvaHkga3JhamlueS4KCiMgbGluZcOhcm5hIHJlZ3Jlc2lhOiBodXN0b3RhIH4gcm96bG9oYQptb2RlbCA8LSBsbShEZW5zaXR5Li5QLkttLi4gfiBMYW5kLkFyZWEuLkttLi4sIGRhdGEgPSB1ZGFqZSkKCiMgdsO9cGlzIHbDvXNsZWRrb3YKc3VtbWFyeShtb2RlbCkKCmBgYApOYSB6w6FrbGFkZSB2w71zbGVka292IGxpbmXDoXJuZWogcmVncmVzaWUgKEYgPSAwLDc4NTU7IHAgPSAwLDM3NjQpIG3DtMW+ZW1lIGtvbsWhdGF0b3ZhxaUsIMW+ZSBuZWV4aXN0dWplIMWhdGF0aXN0aWNreSB2w716bmFtbsO9IGxpbmXDoXJueSB2esWlYWggbWVkemkgcm96bG9ob3Uga3JhamlueSBhIGh1c3RvdG91IG9ieXZhdGXEvnN0dmEuIEhvZG5vdGEga29lZmljaWVudHUgZGV0ZXJtaW7DoWNpZSAoUsKyID0gMCwwMDM0KSBuYXpuYcSNdWplLCDFvmUgcm96bG9oYSB2eXN2ZXTEvnVqZSBpYmEgemFuZWRiYXRlxL5uw7ogxI1hc8WlIHZhcmlhYmlsaXR5IGh1c3RvdHkgb2J5dmF0ZcS+c3R2YS4KCgpgYGB7ciByZWdyZXNzaW9uLXRhYmxlLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIGluc3RhbGwucGFja2FnZXMoYygiYnJvb20iLCAia2FibGVFeHRyYSIsICJkcGx5ciIsICJzdHJpbmdyIikpCgpsaWJyYXJ5KGJyb29tKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoc3RyaW5ncikKCiMgMe+4j+KDoyBWeXR2b3JlbmllIGxpbmXDoXJuZWhvIG1vZGVsdQptb2RlbCA8LSBsbShEZW5zaXR5Li5QLkttLi4gfiBMYW5kLkFyZWEuLkttLi4gKyBQb3B1bGF0aW9uLjIwMjUsIGRhdGEgPSB1ZGFqZSkKCiMgMu+4j+KDoyBUYWJ1xL5rYSBrb2VmaWNpZW50b3YgcyB2w716bmFtbm9zxaVvdQpjb2VmLnRibCA8LSB0aWR5KG1vZGVsLCBjb25mLmludCA9IFRSVUUpICU+JQogIG11dGF0ZSgKICAgIHRlcm0gPSByZWNvZGUodGVybSwKICAgICAgIihJbnRlcmNlcHQpIiA9ICJJbnRlcmNlcHQiLAogICAgICAiTGFuZC5BcmVhLi5LbTIuIiA9ICJMYW5kIEFyZWEgKGttwrIpIiwKICAgICAgIlBvcHVsYXRpb24uMjAyNSIgPSAiUG9wdWxhdGlvbiAyMDI1IgogICAgKSwKICAgIHN0YXJzID0gY2FzZV93aGVuKAogICAgICBwLnZhbHVlIDwgMC4wMDEgfiAiKioqIiwKICAgICAgcC52YWx1ZSA8IDAuMDEgfiAiKioiLAogICAgICBwLnZhbHVlIDwgMC4wNSB+ICIqIiwKICAgICAgcC52YWx1ZSA8IDAuMSB+ICIuIiwKICAgICAgVFJVRSB+ICIiCiAgICApCiAgKSAlPiUKICB0cmFuc211dGUoCiAgICBUZXJtID0gdGVybSwKICAgIEVzdGltYXRlID0gcm91bmQoZXN0aW1hdGUsIDQpLAogICAgYFN0ZC4gRXJyb3JgID0gcm91bmQoc3RkLmVycm9yLCA0KSwKICAgIGB0IHZhbHVlYCA9IHJvdW5kKHN0YXRpc3RpYywgMyksCiAgICBgcCB2YWx1ZWAgPSByb3VuZChwLnZhbHVlLCA0KSwKICAgIGA5NSUgQ0lgID0gc3RyX2MoIlsiLCByb3VuZChjb25mLmxvdywgMyksICIsICIsIHJvdW5kKGNvbmYuaGlnaCwgMyksICJdIiksCiAgICBTaWcgPSBzdGFycwogICkKCiMgM++4j+KDoyBab2JyYXplbmllIHRhYnXEvmt5IGtvZWZpY2llbnRvdgpjb2VmLnRibCAlPiUKICBrYWJsZSgKICAgIGRpZ2l0cyA9IDMsCiAgICBjYXB0aW9uID0gIk9MUyBSZWdyZXNzaW9uIENvZWZmaWNpZW50cyAoRGVuc2l0eSB+IExhbmQgQXJlYSArIFBvcHVsYXRpb24pIgogICkgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKQogICkgJT4lCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUpICU+JQogIHJvd19zcGVjKDAsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNmMmYyZjIiKSAlPiUKICBmb290bm90ZSgKICAgIGdlbmVyYWwgPSAiU2lnbmlmLiBjb2RlczogKioqIHA8MC4wMDEsICoqIHA8MC4wMSwgKiBwPDAuMDUsIC4gcDwwLjEiLAogICAgdGhyZWVwYXJ0dGFibGUgPSBUUlVFCiAgKQoKIyA077iP4oOjIMWgdGF0aXN0aWt5IGt2YWxpdHkgbW9kZWx1CmZpdC50YmwgPC0gZ2xhbmNlKG1vZGVsKSAlPiUKICB0cmFuc211dGUoCiAgICBgUi1zcXVhcmVkYCA9IHJvdW5kKHIuc3F1YXJlZCwgNCksCiAgICBgQWRqLiBSLXNxdWFyZWRgID0gcm91bmQoYWRqLnIuc3F1YXJlZCwgNCksCiAgICBgRi1zdGF0aXN0aWNgID0gcm91bmQoc3RhdGlzdGljLCAzKSwKICAgIGBGIHAtdmFsdWVgID0gcm91bmQocC52YWx1ZSwgNCksCiAgICBgQUlDYCA9IHJvdW5kKEFJQywgMiksCiAgICBgQklDYCA9IHJvdW5kKEJJQywgMiksCiAgICBgTnVtLiBvYnMuYCA9IG5vYnMKICApCgpmaXQudGJsICU+JQogIGthYmxlKAogICAgZGlnaXRzID0gMywKICAgIGNhcHRpb24gPSAiTW9kZWwgRml0IFN0YXRpc3RpY3MiCiAgKSAlPiUKICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJjb25kZW5zZWQiKSkKCiNOYSB6w6FrbGFkZSB2w71zbGVka292IGxpbmXDoXJuZWogcmVncmVzaWUgbcO0xb5lbWUga29uxaF0YXRvdmHFpSwgxb5lIG1vZGVsIG5ldnlzdmV0xL51amUgdmFyaWFiaWxpdHUgaHVzdG90eSBvYnl2YXRlxL5zdHZhIHByb3N0cmVkbsOtY3R2b20gcm96bG9oeSBrcmFqaW55IGEgcG/EjXR1IG9ieXZhdGXEvm92LiBIb2Rub3RhIGtvZWZpY2llbnR1IGRldGVybWluw6FjaWUgKFLCsiA9IDAsMDAzKSBqZSB2ZcS+bWkgbsOtemthIGEgcC1ob2Rub3RhIChwID0gMCw2NzcpIG5hem5hxI11amUsIMW+ZSB2esWlYWggbWVkemkgcHJlbWVubsO9bWkgbmllIGplIMWhdGF0aXN0aWNreSB2w716bmFtbsO9LiBDZWxrb3ZvIHRlZGEgbW9kZWwgbmVwcmV1a8OhemFsIMW+aWFkbnkgdsO9em5hbW7DvSB2cGx5diByb3psb2h5IGFuaSBwb3B1bMOhY2llIG5hIGh1c3RvdHUgb2J5dmF0ZcS+c3R2YS4KYGBgCgojI0hlYXRtYXAKYGBge3Iga29yZWxhY25hLWhlYXRtYXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgaW5zdGFsbC5wYWNrYWdlcyhjKCJnZ3Bsb3QyIiwgInJlc2hhcGUyIiwgImRwbHlyIikpCgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoZHBseXIpCgojIDHvuI/ig6MgVsO9YmVyIGxlbiBudW1lcmlja8O9Y2ggcHJlbWVubsO9Y2gKbnVtX2RhdGEgPC0gdWRhamUgJT4lCiAgc2VsZWN0X2lmKGlzLm51bWVyaWMpCgojIDLvuI/ig6MgVsO9cG/EjWV0IGtvcmVsYcSNbmVqIG1hdGljZQpjb3JyX21hdHJpeCA8LSBjb3IobnVtX2RhdGEsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQoKIyAz77iP4oOjIFRyYW5zZm9ybcOhY2lhIHByZSBnZ3Bsb3QgKGRsaMO9IGZvcm3DoXQpCmNvcnJfbWVsdCA8LSBtZWx0KGNvcnJfbWF0cml4KQoKIyA077iP4oOjIFZ5a3Jlc2xlbmllIGhlYXRtYXB5CmdncGxvdChjb3JyX21lbHQsIGFlcyh4ID0gVmFyMSwgeSA9IFZhcjIsIGZpbGwgPSB2YWx1ZSkpICsKICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIoCiAgICBsb3cgPSAiZGFya3JlZCIsCiAgICBtaWQgPSAid2hpdGUiLAogICAgaGlnaCA9ICJkYXJrYmx1ZSIsCiAgICBtaWRwb2ludCA9IDAsCiAgICBsaW1pdCA9IGMoLTEsIDEpLAogICAgbmFtZSA9ICJLb3JlbMOhY2lhIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDEsIGhqdXN0ID0gMSwgc2l6ZSA9IDkpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIktvcmVsYcSNbsOhIG1hdGljYSBudW1lcmlja8O9Y2ggcHJlbWVubsO9Y2giLAogICAgeCA9ICIiLAogICAgeSA9ICIiCiAgKQpgYGAKCiMjIEtvbWVudMOhciBrIEhlYXRtYXAKTmEgesOha2xhZGUga29yZWxhxI1uZWogbWF0aWNlIG3DtMW+ZW1lIHBvem9yb3ZhxaUsIMW+ZSBtZWR6aSBqZWRub3RsaXbDvW1pIG51bWVyaWNrw71taSBwcmVtZW5uw71taSBleGlzdHVqw7ogdmlhY2Vyw6kgdnrFpWFoeSByw7R6bmVqIGludGVueml0eS4gTmFqc2lsbmVqxaFpYSBwb3ppdMOtdm5hIGtvcmVsw6FjaWEgc2EgcHJlamF2dWplIG1lZHppIHBvxI10b20gb2J5dmF0ZcS+b3YgKFBvcHVsYXRpb24gMjAyNSkgYSByb3psb2hvdSBrcmFqaW55IChMYW5kIEFyZWEpLCDEjW8gamUgbG9naWNrw6kg4oCTIHbDpMSNxaFpZSBrcmFqaW55IG3DoXZhasO6IHNwcmF2aWRsYSBhaiB2aWFjIG9ieXZhdGXEvm92LiBOYW9wYWssIG5lZ2F0w612bmEga29yZWzDoWNpYSBzYSBvYmphdnVqZSBtZWR6aSBtZWRpw6Fub3bDvW0gdmVrb20gKE1lZGlhbiBBZ2UpIGEgbWllcm91IHBsb2Rub3N0aSAoRmVydGlsaXR5IFJhdGUpLCDEjW8gbmF6bmHEjXVqZSwgxb5lIGtyYWppbnkgcyB2ecWhxaHDrW0gcHJpZW1lcm7DvW0gdmVrb20gcG9wdWzDoWNpZSBtYWrDuiBuacW+xaFpdSBww7Ryb2Rub3PFpS4gT3N0YXRuw6kgdnrFpWFoeSBtZWR6aSBwcmVtZW5uw71taSBzw7ogbGVuIHNsYWLDqSBhxb4gbWllcm5lLCDEjW8gbmF6bmHEjXVqZSwgxb5lIHbDpMSNxaFpbmEgdWthem92YXRlxL5vdiBqZSBtZWR6aSBzZWJvdSByZWxhdMOtdm5lIG5lesOhdmlzbMOhLgoKCgoKCg==