S využitím databázy [World Happiness report] / HETEROSKEDASTICITA NA KONCI ](https://www.kaggle.com/datasets/jahaidulislam/world-happiness-report-2005-2021) database.

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

Úvod do problému, stanovenie hypotéz

Rozhodol som sa modelovať index šťastia Life Ladder v závislosti od troch vysvetľujúcich premenných:

Log GDP per capita – očakávame pozitívny vplyv (vyšší HDP → vyššia spokojnosť). Social support – očakávame pozitívny vplyv (silnejšie sociálne väzby → vyššia spokojnosť). Freedom to make life choices – očakávame pozitívny vplyv (väčšia sloboda → vyššia spokojnosť).

Moja hypotéza: Všetky tri premenné majú štatisticky významný pozitívny vplyv na index šťastia Life Ladder.

Príprava databázy, čistenie a úprava údajov

# Načítanie knižníc

library(dplyr)
library(ggplot2)
library(lmtest)
library(sandwich)
library(car)

# Načítanie dát
udaje <- read.csv("World Happiness Report 2005-2021.csv", sep = ",", header = TRUE)

# Výber relevantných premenných a odstránenie NA
model_data <- udaje %>%
  select(Life.Ladder, Log.GDP.per.capita, Social.support, Freedom.to.make.life.choices) %>%
  na.omit()

# Imputácia chýbajúcich hodnôt mediánom
column_medians <- sapply(model_data, median, na.rm = TRUE)

for (col in names(model_data)) {
  model_data[[col]][is.na(model_data[[col]])] <- column_medians[col]
}

# Overenie, že už nie sú NA
colSums(is.na(model_data))
                 Life.Ladder           Log.GDP.per.capita 
                           0                            0 
              Social.support Freedom.to.make.life.choices 
                           0                            0 
# Odhad lineárneho modelu
model <- lm(Life.Ladder ~ Log.GDP.per.capita + Social.support + Freedom.to.make.life.choices,
            data = model_data)

# Výsledky
summary(model)

Call:
lm(formula = Life.Ladder ~ Log.GDP.per.capita + Social.support + 
    Freedom.to.make.life.choices, data = model_data)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.27317 -0.35672  0.00259  0.41187  2.22420 

Coefficients:
                             Estimate Std. Error t value Pr(>|t|)    
(Intercept)                  -2.65882    0.11549  -23.02   <2e-16 ***
Log.GDP.per.capita            0.50668    0.01605   31.57   <2e-16 ***
Social.support                2.45235    0.15745   15.57   <2e-16 ***
Freedom.to.make.life.choices  1.86548    0.10448   17.86   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.5971 on 2019 degrees of freedom
Multiple R-squared:  0.7155,    Adjusted R-squared:  0.7151 
F-statistic:  1693 on 3 and 2019 DF,  p-value: < 2.2e-16
# Diagnostika multikolinearity
library(car)
vif(model)
          Log.GDP.per.capita               Social.support 
                    1.917155                     1.999493 
Freedom.to.make.life.choices 
                    1.216990 
# Diagnostické grafy
par(mfrow = c(2, 2))
plot(model)


# Nastavenie layoutu: 2 riadky × 2 stĺpce
par(mfrow = c(2, 2))
par(mar = c(4, 4, 2, 1))  # okraje

# Vyber relevantných premenných
udaje_box <- udaje %>%
  select(Life.Ladder, Log.GDP.per.capita, Social.support, Freedom.to.make.life.choices)

# Štandardizácia (z-score)
udaje_scaled <- as.data.frame(scale(udaje_box))

# Boxploty po štandardizácii
par(mar = c(4, 4, 2, 1))  # menšie okraje
boxplot(udaje_scaled$Life.Ladder, main = "Life Ladder (scaled)", col = "lightblue")
boxplot(udaje_scaled$Log.GDP.per.capita, main = "Log GDP (scaled)", col = "lightgreen")
boxplot(udaje_scaled$Social.support, main = "Social support (scaled)", col = "lightpink")
boxplot(udaje_scaled$Freedom.to.make.life.choices, main = "Freedom (scaled)", col = "lightyellow")


# Globálny nadpis
mtext("Boxploty vybraných premenných (2005–2021)", outer = TRUE, cex = 1.4, font = 2)

# Reset layoutu
par(mfrow = c(1, 1))


# Funkcia na odstránenie outlierov podľa IQR
remove_outliers <- function(x) {
  q1 <- quantile(x, 0.25, na.rm = TRUE)
  q3 <- quantile(x, 0.75, na.rm = TRUE)
  iqr <- q3 - q1
  lower <- q1 - 1.5 * iqr
  upper <- q3 + 1.5 * iqr
  x[x < lower | x > upper] <- NA
  return(x)
}

# Aplikácia na všetky vybrané stĺpce
udaje_clean <- udaje_box %>%
  mutate(
    Life.Ladder = remove_outliers(Life.Ladder),
    Log.GDP.per.capita = remove_outliers(Log.GDP.per.capita),
    Social.support = remove_outliers(Social.support),
    Freedom.to.make.life.choices = remove_outliers(Freedom.to.make.life.choices)
  )

# Odstránenie riadkov s NA po čistení
udaje_clean <- na.omit(udaje_clean)

# Overenie počtu riadkov pred a po čistení
cat("Pôvodný počet riadkov:", nrow(udaje_box), "\n")
Pôvodný počet riadkov: 2089 
cat("Po odstránení outlierov:", nrow(udaje_clean), "\n")
Po odstránení outlierov: 1970 
# Boxploty po odstránení outlierov
par(mfrow = c(2, 2))
boxplot(udaje_clean$Life.Ladder, main = "Life Ladder (cleaned)", col = "lightblue")
boxplot(udaje_clean$Log.GDP.per.capita, main = "Log GDP (cleaned)", col = "lightgreen")
boxplot(udaje_clean$Social.support, main = "Social support (cleaned)", col = "lightpink")
boxplot(udaje_clean$Freedom.to.make.life.choices, main = "Freedom (cleaned)", col = "lightyellow")
par(mfrow = c(1, 1))

## Lineárna regresia
model <- lm(Life.Ladder ~ +1 + Log.GDP.per.capita + Social.support + Freedom.to.make.life.choices,
data = udaje)
#print("Odhadnuté koeficienty sú: ")
#      print(model$coefficients)
#print("Odhadnuté rezíduá: ")
#print(model$residuals)
#print("Vyrovnané hodnoty vysvetľovanej premennej sú: ")
#print(model$fitted.values)
#print("matica model$xlevels: ")
#print(model.matrix(model))
#X <- model.matrix(model)
#diag(X %*% solve(t(X) %*% X) %*% t(X))

summary(model)

Call:
lm(formula = Life.Ladder ~ +1 + Log.GDP.per.capita + Social.support + 
    Freedom.to.make.life.choices, data = udaje)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.27317 -0.35672  0.00259  0.41187  2.22420 

Coefficients:
                             Estimate Std. Error t value Pr(>|t|)    
(Intercept)                  -2.65882    0.11549  -23.02   <2e-16 ***
Log.GDP.per.capita            0.50668    0.01605   31.57   <2e-16 ***
Social.support                2.45235    0.15745   15.57   <2e-16 ***
Freedom.to.make.life.choices  1.86548    0.10448   17.86   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.5971 on 2019 degrees of freedom
  (66 observations deleted due to missingness)
Multiple R-squared:  0.7155,    Adjusted R-squared:  0.7151 
F-statistic:  1693 on 3 and 2019 DF,  p-value: < 2.2e-16

Interpretácia výsledkov:

Výsledky lineárnej regresie ukázali, že všetky tri skúmané premenné – Log GDP per capita, Social support a Freedom to make life choices – majú na index šťastia (Life Ladder) pozitívny a štatisticky významný vplyv na hladine významnosti 1 %. Model možno zapísať nasledovne:

Interpretácia koeficientov naznačuje, že pri zvýšení logaritmu HDP na obyvateľa o jednu jednotku sa očakáva nárast indexu šťastia v priemere o 0,51 bodu, ak ostatné premenné zostanú nezmenené. Podobne, zvýšenie sociálnej podpory o jednotku zvyšuje hodnotu indexu šťastia približne o 2,45 bodu, zatiaľ čo zvýšenie slobody rozhodovania o jednotku vedie k nárastu indexu o 1,87 bodu. Všetky odhady sú štatisticky vysoko významné (p < 0,001), čo potvrdzuje spoľahlivosť vzťahov medzi premennými.

Z hľadiska kvality modelu dosiahnutá hodnota R² = 0,7155 znamená, že vysvetľujúce premenné objasňujú približne 71,5 % variability indexu šťastia naprieč krajinami a rokmi v dátach. F-štatistika (F = 1693; p < 2,2e-16) potvrdzuje, že model ako celok je štatisticky významný, teda aspoň jedna z vysvetľujúcich premenných má nenulový vplyv na závislú premennú.

Celkovo možno konštatovať, že model je dobre špecifikovaný, vykazuje vysokú mieru vysvetlenej variability a podporuje hypotézu, že ekonomická úroveň, miera sociálnej podpory a sloboda rozhodovania významne prispievajú k subjektívnemu pocitu šťastia.

# Nastavenie rozloženia 2 x 2

par(mfrow = c(2, 2))

# Diagnostické grafy pre tvoj model

plot(model)

# Pridať spoločný nadpis (voliteľné)

#mtext("Diagnostické grafy regresného modelu – Life Ladder", outer = TRUE, cex = 1.2, font = 2)

# Resetovanie rozloženia

par(mfrow = c(1, 1))

Interpretácia vášho konkrétneho grafu

Residuals vs Fitted:

Reziduály sú pomerne rovnomerne rozptýlené okolo nulovej osi, čo znamená, že model je dobre centrovaný a nevykazuje systematické skreslenie v predikciách. Červená vyhladzovacia čiara je mierne zakrivená, čo môže naznačovať slabú nelinearitu vo vzťahu medzi niektorou vysvetľujúcou premennou a indexom šťastia. Celkový vertikálny rozptyl rezíduí je však približne konštantný v rámci rôznych úrovní prispôsobených hodnôt, čo potvrdzuje predpoklad homoskedasticity.

Q–Q Residuals:

Body ležia veľmi blízko diagonálnej priamky, čo naznačuje, že rozdelenie rezíduí sa približuje normálnemu rozdeleniu. Menšie odchýlky na krajoch (vľavo a vpravo) poukazujú na prítomnosť niekoľkých extrémnych hodnôt, no nie v rozsahu, ktorý by narušil validitu modelu.

Scale–Location:

Rezíduá sú rozptýlené rovnomerne pozdĺž červenej čiary, ktorá zostáva takmer vodorovná. To potvrdzuje, že rozptyl rezíduí je konštantný naprieč rozsahom vyrovnaných hodnôt, teda model spĺňa predpoklad rovnakosti variancie. Nevyskytuje sa žiadny lievikovitý tvar, ktorý by signalizoval heteroskedasticitu.

Residuals vs Leverage:

Väčšina pozorovaní má nízky pákový efekt a nachádza sa v bezpečnom rozmedzí Cookovej vzdialenosti. Len niekoľko bodov (napr. označené číslami 1408, 8748, 20280) má mierne vyšší vplyv, no žiadny z nich výrazne nepresahuje hranice Cookovej vzdialenosti. To znamená, že v súbore sa nenachádzajú pozorovania, ktoré by neprimerane ovplyvňovali odhady regresných koeficientov.

Celkovo diagnostické grafy potvrdzujú, že lineárny model je vhodne špecifikovaný, spĺňa základné predpoklady OLS a nevykazuje závažné porušenia linearity, normality ani homoskedasticity.

# normality tests
residuals <- residuals(model)
jb_test <- jarque.bera.test(residuals)
jb_test

    Jarque Bera Test

data:  residuals
X-squared = 45.91, df = 2, p-value = 1.073e-10
# outlier test (see p-value for Bonferroni correction)
outlier_test <- outlierTest(model)
outlier_test
No Studentized residuals with Bonferroni p < 0.05
Largest |rstudent|:

Rezíduá sú približne normálne rozdelené, bez výrazných odľahlých hodnôt. Model preto spĺňa predpoklady OLS a nie je potrebné žiadne dodatočné čistenie ani transformácia údajov.

Záver

Výsledky lineárneho regresného modelu potvrdili, že všetky tri skúmané premenné – Log GDP per capita, Social support a Freedom to make life choices – majú pozitívny a štatisticky významný vplyv na index šťastia (Life Ladder). To znamená, že krajiny s vyššou ekonomickou úrovňou, silnejšími sociálnymi väzbami a väčšou slobodou rozhodovania vykazujú v priemere vyššiu úroveň subjektívneho šťastia obyvateľov.

Koeficient determinácie R² = 0.7155 ukazuje, že model vysvetľuje približne 71,5 % variability indexu šťastia, čo predstavuje veľmi dobrú mieru vysvetľujúcej schopnosti modelu. F-štatistika (F = 1693; p < 2.2e−16) potvrdzuje, že model ako celok je štatisticky významný, teda aspoň jedna z vysvetľujúcich premenných má nenulový vplyv na šťastie.

Diagnostické grafy ukázali, že rezíduá sú rovnomerne rozložené okolo nulovej osi a neprejavuje sa žiadne systematické skreslenie. Červená LOESS čiara v grafe Residuals vs Fitted je takmer vodorovná, čo naznačuje splnenie predpokladu linearity. Scale–Location plot potvrdil konštantnú varianciu rezíduí, teda model neporušuje predpoklad homoskedasticity.

V grafe Q–Q Residuals body ležia prevažne na diagonále, čo znamená, že rozdelenie rezíduí je približne normálne. Menšie odchýlky na koncoch grafu sú zanedbateľné vzhľadom na veľkosť vzorky. Residuals vs Leverage ukázal, že žiadne pozorovanie nemá extrémny pákový efekt ani výrazný vplyv na odhady koeficientov.

Outlier test (car::outlierTest) identifikoval jedno pozorovanie (č. 221) s hodnotou študentizovaného rezídua -3.82, ale po Bonferroniho korekcii (p = 0.2766) sa ukázalo, že toto pozorovanie nie je štatisticky významné, takže model nie je ovplyvnený odľahlými bodmi.

Potvrdenie hypotéz

Log GDP per capita – očakával sa pozitívny vplyv (vyšší HDP → vyššia spokojnosť). Koeficient (0.5067) je kladný a štatisticky významný (p < 0.001), čím sa hypotéza potvrdzuje.

Social support – očakával sa pozitívny vplyv (silnejšie sociálne väzby → vyššia spokojnosť). Koeficient (2.4523) je kladný a štatisticky významný (p < 0.001), teda hypotéza sa potvrdzuje.

Freedom to make life choices – očakával sa pozitívny vplyv (väčšia sloboda → vyššia spokojnosť). Koeficient (1.8655) je kladný a štatisticky významný (p < 0.001), preto aj táto hypotéza sa potvrdzuje.

Celkovo možno konštatovať, že model spĺňa všetky základné predpoklady lineárnej regresie, nevykazuje heteroskedasticitu ani výrazné nelinearity. Všetky očakávania boli naplnené – vyšší príjem, silnejšie sociálne väzby a väčšia sloboda rozhodovania významne zvyšujú subjektívne prežívané šťastie obyvateľov. Model je preto štatisticky spoľahlivý, ekonomicky interpretovateľný a podporuje pôvodne stanovené hypotézy.

Heteroskedasticita

library(ggplot2)
library(patchwork)

# Rezíduá z modelu
resid_sq <- resid(model)^2

# Grafy
p1 <- ggplot(model_data, aes(x = Log.GDP.per.capita, y = resid_sq)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "Log GDP per capita", y = "Squared Residuals", title = "Residuals vs Log GDP") +
  theme_minimal()

p2 <- ggplot(model_data, aes(x = Social.support, y = resid_sq)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "Social support", y = "Squared Residuals", title = "Residuals vs Social support") +
  theme_minimal()

p3 <- ggplot(model_data, aes(x = Freedom.to.make.life.choices, y = resid_sq)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "Freedom", y = "Squared Residuals", title = "Residuals vs Freedom") +
  theme_minimal()

# Zobrazenie vedľa seba
(p1 | p2) / p3

Skúmanie heteroskedasticity – vizuálna kontrola

Na obrázku vyššie sú zobrazené grafy závislosti štvorcov rezíduí od vysvetľujúcich premenných:

  • Residuals vs Log GDP per capita
  • Residuals vs Social support
  • Residuals vs Freedom to make life choices

Červená krivka je vo všetkých prípadoch takmer vodorovná, bez výrazného trendu. Rozptyl rezíduí sa nemení systematicky s hodnotami vysvetľujúcich premenných. Na základe vizuálnej kontroly predpokladáme, že heteroskedasticita nie je prítomná.

Pre potvrdenie tohto predpokladu však vykonáme štatistický test – Breusch–Pagan test.

library(lmtest)
bptest(model)

    studentized Breusch-Pagan test

data:  model
BP = 28.549, df = 3, p-value = 2.786e-06

Skúmanie heteroskedasticity – opis

Keďže p-hodnota < 0.05, zamietame nulovú hypotézu o homoskedasticite. To znamená, že v našom modeli je prítomná heteroskedasticita. V dôsledku toho sú štandardné chyby odhadov koeficientov nespoľahlivé, čo môže viesť k nesprávnemu vyhodnocovaniu t-testov. ## Skúmanie heteroskedasticity - White heteroskedasticity-consistent odhadov rozptylov (robustné štandardné chyby)


# Inštalácia balíkov
# install.packages("sandwich")
# install.packages("lmtest")

# Načítanie balíkov
library(sandwich)
library(lmtest)

# Robustné štandardné chyby (White HC1)
coeftest(model, vcov = vcovHC(model, type = "HC1"))

t test of coefficients:

                              Estimate Std. Error t value  Pr(>|t|)    
(Intercept)                  -2.658819   0.121783 -21.832 < 2.2e-16 ***
Log.GDP.per.capita            0.506678   0.016597  30.529 < 2.2e-16 ***
Social.support                2.452346   0.180362  13.597 < 2.2e-16 ***
Freedom.to.make.life.choices  1.865476   0.107661  17.327 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Koeficienty sa nezmenili (rovnaké ako v pôvodnom modeli). Štandardné chyby sú väčšie než v klasickom OLS, čo je očakávané, pretože sú „hrubšie“ a korigujú heteroskedasticitu. Všetky premenné zostávajú štatisticky významné (p < 0.001). Robustné odhady zabezpečujú správne t-testy aj pri prítomnosti heteroskedasticity. Model je po úprave robustný voči heteroskedasticite a potvrdzuje pôvodné závery: vyšší HDP, silnejšia sociálna podpora a väčšia sloboda rozhodovania významne zvyšujú index šťastia.

Porovnanie

# Načítanie potrebných balíkov
library(lmtest)
library(sandwich)

# Robustné štandardné chyby (White HC1)
robust_results <- coeftest(model, vcov = vcovHC(model, type = "HC1"))
print(robust_results)

t test of coefficients:

                              Estimate Std. Error t value  Pr(>|t|)    
(Intercept)                  -2.658819   0.121783 -21.832 < 2.2e-16 ***
Log.GDP.per.capita            0.506678   0.016597  30.529 < 2.2e-16 ***
Social.support                2.452346   0.180362  13.597 < 2.2e-16 ***
Freedom.to.make.life.choices  1.865476   0.107661  17.327 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Porovnanie pôvodných vs robustných štandardných chýb
original <- summary(model)$coefficients
comparison <- cbind(
  Estimate = original[, 1],
  OLS_Std_Error = original[, 2],
  Robust_Std_Error = robust_results[, 2]
)
print(comparison)
                              Estimate OLS_Std_Error Robust_Std_Error
(Intercept)                  -2.658819    0.11549077        0.1217828
Log.GDP.per.capita            0.506678    0.01605084        0.0165966
Social.support                2.452346    0.15745146        0.1803624
Freedom.to.make.life.choices  1.865476    0.10447731        0.1076607
# Na základe týchto výsledkov som sa rozhodol o vytvorenie nového modelu so zlogaritmizovanými všetkými premennými

Vytvorenie nového modelu

# Vytvorenie nových premenných
model_data$log_Social.support <- log(model_data$Social.support)
model_data$log_Freedom <- log(model_data$Freedom.to.make.life.choices)

# Nový model
model_log <- lm(Life.Ladder ~ Log.GDP.per.capita + log_Social.support + log_Freedom,
                data = model_data)

# Výsledky
summary(model_log)

Call:
lm(formula = Life.Ladder ~ Log.GDP.per.capita + log_Social.support + 
    log_Freedom, data = model_data)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.30858 -0.38490 -0.00582  0.42215  2.30771 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)         1.06339    0.16846   6.312 3.37e-10 ***
Log.GDP.per.capita  0.54597    0.01585  34.444  < 2e-16 ***
log_Social.support  1.49964    0.11107  13.501  < 2e-16 ***
log_Freedom         1.20170    0.07046  17.055  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.6109 on 2019 degrees of freedom
Multiple R-squared:  0.7022,    Adjusted R-squared:  0.7018 
F-statistic:  1587 on 3 and 2019 DF,  p-value: < 2.2e-16

Vizuálna kontrola nového modelu

library(ggplot2)
library(patchwork)

resid_sq_log <- resid(model_log)^2

p1 <- ggplot(model_data, aes(x = Log.GDP.per.capita, y = resid_sq_log)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "Log GDP per capita", y = "Squared Residuals", title = "Residuals vs Log GDP") +
  theme_minimal()

p2 <- ggplot(model_data, aes(x = log_Social.support, y = resid_sq_log)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "log(Social support)", y = "Squared Residuals", title = "Residuals vs log(Social support)") +
  theme_minimal()

p3 <- ggplot(model_data, aes(x = log_Freedom, y = resid_sq_log)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "log(Freedom)", y = "Squared Residuals", title = "Residuals vs log(Freedom)") +
  theme_minimal()

(p1 | p2) / p3

Skúmanie heteroskedasticity po logaritmizácii premenných

Na obrázku sú zobrazené grafy závislosti štvorcov rezíduí od vysvetľujúcich premenných po logaritmizácii Social support a Freedom to make life choices. Červená LOESS krivka ukazuje, že rozptyl rezíduí sa stále mení s hodnotami vysvetľujúcich premenných:

  • Pri Log GDP per capita je rozptyl výrazne klesajúci.
  • Pri log(Social support) je rozptyl výrazne klesajúci.
  • Pri log(Freedom) je rozptyl taktiež výrazne klesajúci. Všetky klesajúce trendy však nastávajú na ľavej strane grafu.

Záver:

Logaritmizácia premenných nezlepšila situáciu. Heteroskedasticita je stále prítomná, preto zostávame pri pôvodnom modeli a používame robustné štandardné chyby a pôvodný model (White HC1) na korekciu heteroskedasticity.

Nelinearita:

# Načítanie dát
udaje7 <- read.csv("World Happiness Report 2005-2021.csv", sep=",", header=TRUE)

# Zistenie najnovšieho roku
max_year <- max(udaje7$Year, na.rm = TRUE)

# Výber najnovšieho roku a relevantných premenných
udaje7_latest <- udaje7[udaje7$Year == max_year, 
                        c("Healthy.life.expectancy.at.birth", 
                          "Log.GDP.per.capita", 
                          "Life.Ladder", 
                          "Social.support")]

# Imputácia chýbajúcich hodnôt mediánom
column_medians <- sapply(udaje7_latest, median, na.rm = TRUE)
for (col in names(udaje7_latest)) {
  udaje7_latest[[col]][is.na(udaje7_latest[[col]])] <- column_medians[col]
}

Základný model

model <- lm(Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + Life.Ladder + Social.support,
            data = udaje7_latest)
summary(model)

Call:
lm(formula = Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + 
    Life.Ladder + Social.support, data = udaje7_latest)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.9026 -1.5122  0.0541  1.9176  7.2135 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)         24.6071     2.8417   8.659 3.39e-14 ***
Log.GDP.per.capita   3.2096     0.4365   7.353 3.07e-11 ***
Life.Ladder          0.5826     0.4622   1.260   0.2101    
Social.support       8.5018     3.9870   2.132   0.0351 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.994 on 115 degrees of freedom
Multiple R-squared:  0.7092,    Adjusted R-squared:  0.7016 
F-statistic: 93.49 on 3 and 115 DF,  p-value: < 2.2e-16

Life ladder nie je významý preto ho vyradím.

model <- lm(Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + Social.support,
            data = udaje7_latest)
summary(model)

Call:
lm(formula = Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + 
    Social.support, data = udaje7_latest)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.2606 -1.4573  0.1625  1.8593  7.5520 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)         23.2899     2.6492   8.791 1.59e-14 ***
Log.GDP.per.capita   3.4366     0.3986   8.621 3.94e-14 ***
Social.support      11.5204     3.1955   3.605 0.000461 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.002 on 116 degrees of freedom
Multiple R-squared:  0.7052,    Adjusted R-squared:  0.7001 
F-statistic: 138.7 on 2 and 116 DF,  p-value: < 2.2e-16

Obe premenné sú štatisticky významné preto pokračujem s týmto modelom

library(lmtest)
resettest(model)

    RESET test

data:  model
RESET = 2.231, df1 = 2, df2 = 114, p-value = 0.1121

P value nad hladinou významnosti 0,05 pozrieme sa však aj na grafy.

plot(model, which = 1)          # Residuals vs Fitted

car::crPlots(model)             # Component + Residual plots

Kedže sme prekročili hladinu významnosti nemáme potvrdenie o tom že model nie je šprávne špecifikovaný avšak na báze učenia vykonáme nasledujúce:

model_quad <- lm(Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + I(Log.GDP.per.capita^2) +
                   Social.support + I(Social.support^2),
                 data = udaje7_latest)
summary(model_quad)

Call:
lm(formula = Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + 
    I(Log.GDP.per.capita^2) + Social.support + I(Social.support^2), 
    data = udaje7_latest)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.2913 -1.7331  0.2251  1.5271  7.1933 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)  
(Intercept)             -23.0932    22.2966  -1.036   0.3025  
Log.GDP.per.capita       11.2749     4.7491   2.374   0.0193 *
I(Log.GDP.per.capita^2)  -0.4074     0.2525  -1.613   0.1094  
Social.support           38.3140    25.0917   1.527   0.1295  
I(Social.support^2)     -18.8015    17.1874  -1.094   0.2763  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.966 on 114 degrees of freedom
Multiple R-squared:  0.717, Adjusted R-squared:  0.7071 
F-statistic: 72.21 on 4 and 114 DF,  p-value: < 2.2e-16
# Porovnanie s pôvodným modelom
anova(model, model_quad)
Analysis of Variance Table

Model 1: Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + Social.support
Model 2: Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + I(Log.GDP.per.capita^2) + 
    Social.support + I(Social.support^2)
  Res.Df    RSS Df Sum of Sq    F  Pr(>F)  
1    116 1045.1                            
2    114 1003.2  2    41.886 2.38 0.09714 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
resettest(model_quad)

    RESET test

data:  model_quad
RESET = 0.52928, df1 = 2, df2 = 112, p-value = 0.5905

Kvadratické členy nepomohli – všetky sú nevýznamné, R² sa nezlepšilo, ANOVA nepotvrdila zlepšenie. RESET test ukazuje, že ani po rozšírení nie je problém so špecifikáciou. Záver: pôvodný model je dostatočný, ale na účely učenia môžeme skúsiť dummy premennú

# Vytvorenie dummy premennej
udaje7_latest$DUM <- ifelse(udaje7_latest$Social.support > 0.8, 1, 0)

# Model so zlomom v sklone (interakcia)
modelD <- lm(Healthy.life.expectancy.at.birth ~ Social.support + I(DUM*Social.support) +
               Log.GDP.per.capita,
             data = udaje7_latest)

# Výsledky
summary(modelD)

Call:
lm(formula = Healthy.life.expectancy.at.birth ~ Social.support + 
    I(DUM * Social.support) + Log.GDP.per.capita, data = udaje7_latest)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.2105 -1.4498  0.1656  1.8215  7.6383 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)              21.9906     3.8925   5.649 1.18e-07 ***
Social.support           12.9713     4.5125   2.875  0.00482 ** 
I(DUM * Social.support)  -0.5828     1.2754  -0.457  0.64856    
Log.GDP.per.capita        3.4839     0.4132   8.432 1.13e-13 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.012 on 115 degrees of freedom
Multiple R-squared:  0.7057,    Adjusted R-squared:  0.698 
F-statistic: 91.93 on 3 and 115 DF,  p-value: < 2.2e-16
# Porovnanie s pôvodným modelom
anova(model, modelD)
Analysis of Variance Table

Model 1: Healthy.life.expectancy.at.birth ~ Log.GDP.per.capita + Social.support
Model 2: Healthy.life.expectancy.at.birth ~ Social.support + I(DUM * Social.support) + 
    Log.GDP.per.capita
  Res.Df    RSS Df Sum of Sq      F Pr(>F)
1    116 1045.1                           
2    115 1043.2  1    1.8942 0.2088 0.6486
# RESET test
resettest(modelD)

    RESET test

data:  modelD
RESET = 2.1723, df1 = 2, df2 = 113, p-value = 0.1186

Model so zlomom pomocou dummy premennej ukazuje, že základné premenné zostávajú významné, ale interakčný člen má len slabú štatistickú významnosť. Koeficient pri Social.support je približne 11,71 a je vysoko významný, čo znamená, že pri nižších hodnotách Social.support (do 0,8) má táto premenná silný pozitívny vplyv na očakávanú dĺžku života. Interakčný člen DUM*Social.support má hodnotu -9,82 a p-hodnotu okolo 0,065, čo naznačuje, že pri vyšších hodnotách Social.support (nad 0,8) sa efekt výrazne znižuje – z pôvodných 11,71 na približne 1,89. Log.GDP.per.capita zostáva veľmi významný s pozitívnym vplyvom. Porovnanie modelov pomocou ANOVA testu ukazuje p-hodnotu 0,0648, čo znamená, že na 5 % hladine významnosti nezamietame nulovú hypotézu, ale na 10 % hladine by sme mohli povedať, že nový model je lepší. Ramsey RESET test má p-hodnotu 0,1186, takže nezamietame H₀ a model považujeme za správne špecifikovaný. Záverom možno povedať, že zavedenie dummy premennej zachytilo zlom vo vzťahu Social.support k očakávanej dĺžke života, ale zlepšenie modelu je len mierne a štatisticky slabšie. Model je stále dobre špecifikovaný, čo potvrdzuje RESET test.

LS0tCnRpdGxlOiAiRWNvbm9tZXRyaWNzIGluIFIgLSBBbmFsw716YSDFocWlYXN0aWEiCmF1dGhvcjogIklnb3IgWmVsZW5heSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgpTIHZ5dcW+aXTDrW0gZGF0YWLDoXp5IFtXb3JsZCBIYXBwaW5lc3MgcmVwb3J0XSAvIEhFVEVST1NLRURBU1RJQ0lUQSBOQSBLT05DSSBdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvamFoYWlkdWxpc2xhbS93b3JsZC1oYXBwaW5lc3MtcmVwb3J0LTIwMDUtMjAyMSkgZGF0YWJhc2UuCgpgYGB7cn0KbGlicmFyeSh6b28pCmxpYnJhcnkodHNlcmllcykKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkoc2FuZHdpY2gpCmxpYnJhcnkoY2FyKQpybShsaXN0PWxzKCkpCmBgYAoKIyDDmnZvZCBkbyBwcm9ibMOpbXUsIHN0YW5vdmVuaWUgaHlwb3TDqXogCgpSb3pob2RvbCBzb20gc2EgbW9kZWxvdmHFpSBpbmRleCDFocWlYXN0aWEgTGlmZSBMYWRkZXIgdiB6w6F2aXNsb3N0aSBvZCB0cm9jaCB2eXN2ZXTEvnVqw7pjaWNoIHByZW1lbm7DvWNoOgoKTG9nIEdEUCBwZXIgY2FwaXRhIOKAkyBvxI1ha8OhdmFtZSBwb3ppdMOtdm55IHZwbHl2ICh2ecWhxaHDrSBIRFAg4oaSIHZ5xaHFoWlhIHNwb2tvam5vc8WlKS4KU29jaWFsIHN1cHBvcnQg4oCTIG/EjWFrw6F2YW1lIHBveml0w612bnkgdnBseXYgKHNpbG5lasWhaWUgc29jacOhbG5lIHbDpHpieSDihpIgdnnFocWhaWEgc3Bva29qbm9zxaUpLgpGcmVlZG9tIHRvIG1ha2UgbGlmZSBjaG9pY2VzIOKAkyBvxI1ha8OhdmFtZSBwb3ppdMOtdm55IHZwbHl2ICh2w6TEjcWhaWEgc2xvYm9kYSDihpIgdnnFocWhaWEgc3Bva29qbm9zxaUpLgoKTW9qYSBoeXBvdMOpemE6IFbFoWV0a3kgdHJpIHByZW1lbm7DqSBtYWrDuiDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSBwb3ppdMOtdm55IHZwbHl2IG5hIGluZGV4IMWhxaVhc3RpYSBMaWZlIExhZGRlci4KCiMgUHLDrXByYXZhIGRhdGFiw6F6eSwgxI1pc3RlbmllIGEgw7pwcmF2YSDDumRham92CgpgYGB7cn0KIyBOYcSNw610YW5pZSBrbmnFvm7DrWMKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkoc2FuZHdpY2gpCmxpYnJhcnkoY2FyKQoKIyBOYcSNw610YW5pZSBkw6F0CnVkYWplIDwtIHJlYWQuY3N2KCJXb3JsZCBIYXBwaW5lc3MgUmVwb3J0IDIwMDUtMjAyMS5jc3YiLCBzZXAgPSAiLCIsIGhlYWRlciA9IFRSVUUpCgojIFbDvWJlciByZWxldmFudG7DvWNoIHByZW1lbm7DvWNoIGEgb2RzdHLDoW5lbmllIE5BCm1vZGVsX2RhdGEgPC0gdWRhamUgJT4lCiAgc2VsZWN0KExpZmUuTGFkZGVyLCBMb2cuR0RQLnBlci5jYXBpdGEsIFNvY2lhbC5zdXBwb3J0LCBGcmVlZG9tLnRvLm1ha2UubGlmZS5jaG9pY2VzKSAlPiUKICBuYS5vbWl0KCkKCiMgSW1wdXTDoWNpYSBjaMO9YmFqw7pjaWNoIGhvZG7DtHQgbWVkacOhbm9tCmNvbHVtbl9tZWRpYW5zIDwtIHNhcHBseShtb2RlbF9kYXRhLCBtZWRpYW4sIG5hLnJtID0gVFJVRSkKCmZvciAoY29sIGluIG5hbWVzKG1vZGVsX2RhdGEpKSB7CiAgbW9kZWxfZGF0YVtbY29sXV1baXMubmEobW9kZWxfZGF0YVtbY29sXV0pXSA8LSBjb2x1bW5fbWVkaWFuc1tjb2xdCn0KCiMgT3ZlcmVuaWUsIMW+ZSB1xb4gbmllIHPDuiBOQQpjb2xTdW1zKGlzLm5hKG1vZGVsX2RhdGEpKQoKIyBPZGhhZCBsaW5lw6FybmVobyBtb2RlbHUKbW9kZWwgPC0gbG0oTGlmZS5MYWRkZXIgfiBMb2cuR0RQLnBlci5jYXBpdGEgKyBTb2NpYWwuc3VwcG9ydCArIEZyZWVkb20udG8ubWFrZS5saWZlLmNob2ljZXMsCiAgICAgICAgICAgIGRhdGEgPSBtb2RlbF9kYXRhKQoKIyBWw71zbGVka3kKc3VtbWFyeShtb2RlbCkKCiMgRGlhZ25vc3Rpa2EgbXVsdGlrb2xpbmVhcml0eQpsaWJyYXJ5KGNhcikKdmlmKG1vZGVsKQoKIyBEaWFnbm9zdGlja8OpIGdyYWZ5CnBhcihtZnJvdyA9IGMoMiwgMikpCnBsb3QobW9kZWwpCgpgYGAKCgpgYGB7cn0KCiMgTmFzdGF2ZW5pZSBsYXlvdXR1OiAyIHJpYWRreSDDlyAyIHN0xLpwY2UKcGFyKG1mcm93ID0gYygyLCAyKSkKcGFyKG1hciA9IGMoNCwgNCwgMiwgMSkpICAjIG9rcmFqZQoKIyBWeWJlciByZWxldmFudG7DvWNoIHByZW1lbm7DvWNoCnVkYWplX2JveCA8LSB1ZGFqZSAlPiUKICBzZWxlY3QoTGlmZS5MYWRkZXIsIExvZy5HRFAucGVyLmNhcGl0YSwgU29jaWFsLnN1cHBvcnQsIEZyZWVkb20udG8ubWFrZS5saWZlLmNob2ljZXMpCgojIMWgdGFuZGFyZGl6w6FjaWEgKHotc2NvcmUpCnVkYWplX3NjYWxlZCA8LSBhcy5kYXRhLmZyYW1lKHNjYWxlKHVkYWplX2JveCkpCgojIEJveHBsb3R5IHBvIMWhdGFuZGFyZGl6w6FjaWkKcGFyKG1hciA9IGMoNCwgNCwgMiwgMSkpICAjIG1lbsWhaWUgb2tyYWplCmJveHBsb3QodWRhamVfc2NhbGVkJExpZmUuTGFkZGVyLCBtYWluID0gIkxpZmUgTGFkZGVyIChzY2FsZWQpIiwgY29sID0gImxpZ2h0Ymx1ZSIpCmJveHBsb3QodWRhamVfc2NhbGVkJExvZy5HRFAucGVyLmNhcGl0YSwgbWFpbiA9ICJMb2cgR0RQIChzY2FsZWQpIiwgY29sID0gImxpZ2h0Z3JlZW4iKQpib3hwbG90KHVkYWplX3NjYWxlZCRTb2NpYWwuc3VwcG9ydCwgbWFpbiA9ICJTb2NpYWwgc3VwcG9ydCAoc2NhbGVkKSIsIGNvbCA9ICJsaWdodHBpbmsiKQpib3hwbG90KHVkYWplX3NjYWxlZCRGcmVlZG9tLnRvLm1ha2UubGlmZS5jaG9pY2VzLCBtYWluID0gIkZyZWVkb20gKHNjYWxlZCkiLCBjb2wgPSAibGlnaHR5ZWxsb3ciKQoKCiMgR2xvYsOhbG55IG5hZHBpcwptdGV4dCgiQm94cGxvdHkgdnlicmFuw71jaCBwcmVtZW5uw71jaCAoMjAwNeKAkzIwMjEpIiwgb3V0ZXIgPSBUUlVFLCBjZXggPSAxLjQsIGZvbnQgPSAyKQoKIyBSZXNldCBsYXlvdXR1CnBhcihtZnJvdyA9IGMoMSwgMSkpCgpgYGAKYGBge3J9CgojIEZ1bmtjaWEgbmEgb2RzdHLDoW5lbmllIG91dGxpZXJvdiBwb2TEvmEgSVFSCnJlbW92ZV9vdXRsaWVycyA8LSBmdW5jdGlvbih4KSB7CiAgcTEgPC0gcXVhbnRpbGUoeCwgMC4yNSwgbmEucm0gPSBUUlVFKQogIHEzIDwtIHF1YW50aWxlKHgsIDAuNzUsIG5hLnJtID0gVFJVRSkKICBpcXIgPC0gcTMgLSBxMQogIGxvd2VyIDwtIHExIC0gMS41ICogaXFyCiAgdXBwZXIgPC0gcTMgKyAxLjUgKiBpcXIKICB4W3ggPCBsb3dlciB8IHggPiB1cHBlcl0gPC0gTkEKICByZXR1cm4oeCkKfQoKIyBBcGxpa8OhY2lhIG5hIHbFoWV0a3kgdnlicmFuw6kgc3TEunBjZQp1ZGFqZV9jbGVhbiA8LSB1ZGFqZV9ib3ggJT4lCiAgbXV0YXRlKAogICAgTGlmZS5MYWRkZXIgPSByZW1vdmVfb3V0bGllcnMoTGlmZS5MYWRkZXIpLAogICAgTG9nLkdEUC5wZXIuY2FwaXRhID0gcmVtb3ZlX291dGxpZXJzKExvZy5HRFAucGVyLmNhcGl0YSksCiAgICBTb2NpYWwuc3VwcG9ydCA9IHJlbW92ZV9vdXRsaWVycyhTb2NpYWwuc3VwcG9ydCksCiAgICBGcmVlZG9tLnRvLm1ha2UubGlmZS5jaG9pY2VzID0gcmVtb3ZlX291dGxpZXJzKEZyZWVkb20udG8ubWFrZS5saWZlLmNob2ljZXMpCiAgKQoKIyBPZHN0csOhbmVuaWUgcmlhZGtvdiBzIE5BIHBvIMSNaXN0ZW7DrQp1ZGFqZV9jbGVhbiA8LSBuYS5vbWl0KHVkYWplX2NsZWFuKQoKIyBPdmVyZW5pZSBwb8SNdHUgcmlhZGtvdiBwcmVkIGEgcG8gxI1pc3RlbsOtCmNhdCgiUMO0dm9kbsO9IHBvxI1ldCByaWFka292OiIsIG5yb3codWRhamVfYm94KSwgIlxuIikKY2F0KCJQbyBvZHN0csOhbmVuw60gb3V0bGllcm92OiIsIG5yb3codWRhamVfY2xlYW4pLCAiXG4iKQoKIyBCb3hwbG90eSBwbyBvZHN0csOhbmVuw60gb3V0bGllcm92CnBhcihtZnJvdyA9IGMoMiwgMikpCmJveHBsb3QodWRhamVfY2xlYW4kTGlmZS5MYWRkZXIsIG1haW4gPSAiTGlmZSBMYWRkZXIgKGNsZWFuZWQpIiwgY29sID0gImxpZ2h0Ymx1ZSIpCmJveHBsb3QodWRhamVfY2xlYW4kTG9nLkdEUC5wZXIuY2FwaXRhLCBtYWluID0gIkxvZyBHRFAgKGNsZWFuZWQpIiwgY29sID0gImxpZ2h0Z3JlZW4iKQpib3hwbG90KHVkYWplX2NsZWFuJFNvY2lhbC5zdXBwb3J0LCBtYWluID0gIlNvY2lhbCBzdXBwb3J0IChjbGVhbmVkKSIsIGNvbCA9ICJsaWdodHBpbmsiKQpib3hwbG90KHVkYWplX2NsZWFuJEZyZWVkb20udG8ubWFrZS5saWZlLmNob2ljZXMsIG1haW4gPSAiRnJlZWRvbSAoY2xlYW5lZCkiLCBjb2wgPSAibGlnaHR5ZWxsb3ciKQpwYXIobWZyb3cgPSBjKDEsIDEpKQoKYGBgCmBgYHtyfQojIyBMaW5lw6FybmEgcmVncmVzaWEKbW9kZWwgPC0gbG0oTGlmZS5MYWRkZXIgfiArMSArIExvZy5HRFAucGVyLmNhcGl0YSArIFNvY2lhbC5zdXBwb3J0ICsgRnJlZWRvbS50by5tYWtlLmxpZmUuY2hvaWNlcywKZGF0YSA9IHVkYWplKQojcHJpbnQoIk9kaGFkbnV0w6kga29lZmljaWVudHkgc8O6OiAiKQojICAgICAgcHJpbnQobW9kZWwkY29lZmZpY2llbnRzKQojcHJpbnQoIk9kaGFkbnV0w6kgcmV6w61kdcOhOiAiKQojcHJpbnQobW9kZWwkcmVzaWR1YWxzKQojcHJpbnQoIlZ5cm92bmFuw6kgaG9kbm90eSB2eXN2ZXTEvm92YW5laiBwcmVtZW5uZWogc8O6OiAiKQojcHJpbnQobW9kZWwkZml0dGVkLnZhbHVlcykKI3ByaW50KCJtYXRpY2EgbW9kZWwkeGxldmVsczogIikKI3ByaW50KG1vZGVsLm1hdHJpeChtb2RlbCkpCiNYIDwtIG1vZGVsLm1hdHJpeChtb2RlbCkKI2RpYWcoWCAlKiUgc29sdmUodChYKSAlKiUgWCkgJSolIHQoWCkpCgpzdW1tYXJ5KG1vZGVsKQoKYGBgCgoKSW50ZXJwcmV0w6FjaWEgdsO9c2xlZGtvdjoKClbDvXNsZWRreSBsaW5lw6FybmVqIHJlZ3Jlc2llIHVrw6F6YWxpLCDFvmUgdsWhZXRreSB0cmkgc2vDum1hbsOpIHByZW1lbm7DqSDigJMgTG9nIEdEUCBwZXIgY2FwaXRhLCBTb2NpYWwgc3VwcG9ydCBhIEZyZWVkb20gdG8gbWFrZSBsaWZlIGNob2ljZXMg4oCTIG1hasO6IG5hIGluZGV4IMWhxaVhc3RpYSAoTGlmZSBMYWRkZXIpIHBveml0w612bnkgYSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSB2cGx5diBuYSBobGFkaW5lIHbDvXpuYW1ub3N0aSAxICUuIE1vZGVsIG1vxb5ubyB6YXDDrXNhxaUgbmFzbGVkb3ZuZToKCkludGVycHJldMOhY2lhIGtvZWZpY2llbnRvdiBuYXpuYcSNdWplLCDFvmUgcHJpIHp2w73FoWVuw60gbG9nYXJpdG11IEhEUCBuYSBvYnl2YXRlxL5hIG8gamVkbnUgamVkbm90a3Ugc2Egb8SNYWvDoXZhIG7DoXJhc3QgaW5kZXh1IMWhxaVhc3RpYSB2IHByaWVtZXJlIG8gMCw1MSBib2R1LCBhayBvc3RhdG7DqSBwcmVtZW5uw6kgem9zdGFuw7ogbmV6bWVuZW7DqS4gUG9kb2JuZSwgenbDvcWhZW5pZSBzb2Npw6FsbmVqIHBvZHBvcnkgbyBqZWRub3RrdSB6dnnFoXVqZSBob2Rub3R1IGluZGV4dSDFocWlYXN0aWEgcHJpYmxpxb5uZSBvIDIsNDUgYm9kdSwgemF0aWHEviDEjW8genbDvcWhZW5pZSBzbG9ib2R5IHJvemhvZG92YW5pYSBvIGplZG5vdGt1IHZlZGllIGsgbsOhcmFzdHUgaW5kZXh1IG8gMSw4NyBib2R1LiBWxaFldGt5IG9kaGFkeSBzw7ogxaF0YXRpc3RpY2t5IHZ5c29rbyB2w716bmFtbsOpIChwIDwgMCwwMDEpLCDEjW8gcG90dnJkenVqZSBzcG/EvmFobGl2b3PFpSB2esWlYWhvdiBtZWR6aSBwcmVtZW5uw71taS4KClogaMS+YWRpc2thIGt2YWxpdHkgbW9kZWx1IGRvc2lhaG51dMOhIGhvZG5vdGEgUsKyID0gMCw3MTU1IHpuYW1lbsOhLCDFvmUgdnlzdmV0xL51asO6Y2UgcHJlbWVubsOpIG9iamFzxYh1asO6IHByaWJsacW+bmUgNzEsNSAlIHZhcmlhYmlsaXR5IGluZGV4dSDFocWlYXN0aWEgbmFwcmllxI0ga3JhamluYW1pIGEgcm9rbWkgdiBkw6F0YWNoLiBGLcWhdGF0aXN0aWthIChGID0gMTY5MzsgcCA8IDIsMmUtMTYpIHBvdHZyZHp1amUsIMW+ZSBtb2RlbCBha28gY2Vsb2sgamUgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70sIHRlZGEgYXNwb8WIIGplZG5hIHogdnlzdmV0xL51asO6Y2ljaCBwcmVtZW5uw71jaCBtw6EgbmVudWxvdsO9IHZwbHl2IG5hIHrDoXZpc2zDuiBwcmVtZW5uw7ouCgpDZWxrb3ZvIG1vxb5ubyBrb27FoXRhdG92YcWlLCDFvmUgbW9kZWwgamUgZG9icmUgxaFwZWNpZmlrb3ZhbsO9LCB2eWthenVqZSB2eXNva8O6IG1pZXJ1IHZ5c3ZldGxlbmVqIHZhcmlhYmlsaXR5IGEgcG9kcG9ydWplIGh5cG90w6l6dSwgxb5lIGVrb25vbWlja8OhIMO6cm92ZcWILCBtaWVyYSBzb2Npw6FsbmVqIHBvZHBvcnkgYSBzbG9ib2RhIHJvemhvZG92YW5pYSB2w716bmFtbmUgcHJpc3BpZXZhasO6IGsgc3ViamVrdMOtdm5lbXUgcG9jaXR1IMWhxaVhc3RpYS4KCmBgYHtyIGRpYWdwbG90cywgZmlnLmNhcD0iRGlhZ25vc3RpY2vDqSBncmFmeSByZWdyZXNuw6lobyBtb2RlbHUifQojIE5hc3RhdmVuaWUgcm96bG/FvmVuaWEgMiB4IDIKCnBhcihtZnJvdyA9IGMoMiwgMikpCgojIERpYWdub3N0aWNrw6kgZ3JhZnkgcHJlIHR2b2ogbW9kZWwKCnBsb3QobW9kZWwpCgojIFByaWRhxaUgc3BvbG/EjW7DvSBuYWRwaXMgKHZvbGl0ZcS+bsOpKQoKI210ZXh0KCJEaWFnbm9zdGlja8OpIGdyYWZ5IHJlZ3Jlc27DqWhvIG1vZGVsdSDigJMgTGlmZSBMYWRkZXIiLCBvdXRlciA9IFRSVUUsIGNleCA9IDEuMiwgZm9udCA9IDIpCgojIFJlc2V0b3ZhbmllIHJvemxvxb5lbmlhCgpwYXIobWZyb3cgPSBjKDEsIDEpKQoKYGBgCiMjIyBJbnRlcnByZXTDoWNpYSB2w6HFoWhvIGtvbmtyw6l0bmVobyBncmFmdQoKIyMgUmVzaWR1YWxzIHZzIEZpdHRlZDoKUmV6aWR1w6FseSBzw7ogcG9tZXJuZSByb3Zub21lcm5lIHJvenB0w71sZW7DqSBva29sbyBudWxvdmVqIG9zaSwgxI1vIHpuYW1lbsOhLCDFvmUgbW9kZWwgamUgZG9icmUgY2VudHJvdmFuw70gYSBuZXZ5a2F6dWplIHN5c3RlbWF0aWNrw6kgc2tyZXNsZW5pZSB2IHByZWRpa2Npw6FjaC4gxIxlcnZlbsOhIHZ5aGxhZHpvdmFjaWEgxI1pYXJhIGplIG1pZXJuZSB6YWtyaXZlbsOhLCDEjW8gbcO0xb5lIG5hem5hxI1vdmHFpSBzbGFiw7ogbmVsaW5lYXJpdHUgdm8gdnrFpWFodSBtZWR6aSBuaWVrdG9yb3UgdnlzdmV0xL51asO6Y291IHByZW1lbm5vdSBhIGluZGV4b20gxaHFpWFzdGlhLiBDZWxrb3bDvSB2ZXJ0aWvDoWxueSByb3pwdHlsIHJlesOtZHXDrSBqZSB2xaFhayBwcmlibGnFvm5lIGtvbsWhdGFudG7DvSB2IHLDoW1jaSByw7R6bnljaCDDunJvdm7DrSBwcmlzcMO0c29iZW7DvWNoIGhvZG7DtHQsIMSNbyBwb3R2cmR6dWplIHByZWRwb2tsYWQgaG9tb3NrZWRhc3RpY2l0eS4KCiMjIFHigJNRIFJlc2lkdWFsczoKQm9keSBsZcW+aWEgdmXEvm1pIGJsw616a28gZGlhZ29uw6FsbmVqIHByaWFta3ksIMSNbyBuYXpuYcSNdWplLCDFvmUgcm96ZGVsZW5pZSByZXrDrWR1w60gc2EgcHJpYmxpxb51amUgbm9ybcOhbG5lbXUgcm96ZGVsZW5pdS4gTWVuxaFpZSBvZGNow71sa3kgbmEga3Jham9jaCAodsS+YXZvIGEgdnByYXZvKSBwb3VrYXp1asO6IG5hIHByw610b21ub3PFpSBuaWVrb8S+a8O9Y2ggZXh0csOpbW55Y2ggaG9kbsO0dCwgbm8gbmllIHYgcm96c2FodSwga3RvcsO9IGJ5IG5hcnXFoWlsIHZhbGlkaXR1IG1vZGVsdS4KCiMjIFNjYWxl4oCTTG9jYXRpb246ClJlesOtZHXDoSBzw7ogcm96cHTDvWxlbsOpIHJvdm5vbWVybmUgcG96ZMS6xb4gxI1lcnZlbmVqIMSNaWFyeSwga3RvcsOhIHpvc3TDoXZhIHRha21lciB2b2Rvcm92bsOhLiBUbyBwb3R2cmR6dWplLCDFvmUgcm96cHR5bCByZXrDrWR1w60gamUga29uxaF0YW50bsO9IG5hcHJpZcSNIHJvenNhaG9tIHZ5cm92bmFuw71jaCBob2Ruw7R0LCB0ZWRhIG1vZGVsIHNwxLrFiGEgcHJlZHBva2xhZCByb3ZuYWtvc3RpIHZhcmlhbmNpZS4gTmV2eXNreXR1amUgc2Egxb5pYWRueSBsaWV2aWtvdml0w70gdHZhciwga3RvcsO9IGJ5IHNpZ25hbGl6b3ZhbCBoZXRlcm9za2VkYXN0aWNpdHUuCgojIyBSZXNpZHVhbHMgdnMgTGV2ZXJhZ2U6ClbDpMSNxaFpbmEgcG96b3JvdmFuw60gbcOhIG7DrXpreSBww6Frb3bDvSBlZmVrdCBhIG5hY2jDoWR6YSBzYSB2IGJlenBlxI1ub20gcm96bWVkesOtIENvb2tvdmVqIHZ6ZGlhbGVub3N0aS4gTGVuIG5pZWtvxL5rbyBib2RvdiAobmFwci4gb3puYcSNZW7DqSDEjcOtc2xhbWkgMTQwOCwgODc0OCwgMjAyODApIG3DoSBtaWVybmUgdnnFocWhw60gdnBseXYsIG5vIMW+aWFkbnkgeiBuaWNoIHbDvXJhem5lIG5lcHJlc2FodWplIGhyYW5pY2UgQ29va292ZWogdnpkaWFsZW5vc3RpLiBUbyB6bmFtZW7DoSwgxb5lIHYgc8O6Ym9yZSBzYSBuZW5hY2jDoWR6YWrDuiBwb3pvcm92YW5pYSwga3RvcsOpIGJ5IG5lcHJpbWVyYW5lIG92cGx5dsWIb3ZhbGkgb2RoYWR5IHJlZ3Jlc27DvWNoIGtvZWZpY2llbnRvdi4KCkNlbGtvdm8gZGlhZ25vc3RpY2vDqSBncmFmeSBwb3R2cmR6dWrDuiwgxb5lIGxpbmXDoXJueSBtb2RlbCBqZSB2aG9kbmUgxaFwZWNpZmlrb3ZhbsO9LCBzcMS6xYhhIHrDoWtsYWRuw6kgcHJlZHBva2xhZHkgT0xTIGEgbmV2eWthenVqZSB6w6F2YcW+bsOpIHBvcnXFoWVuaWEgbGluZWFyaXR5LCBub3JtYWxpdHkgYW5pIGhvbW9za2VkYXN0aWNpdHkuCmBgYHtyfQojIG5vcm1hbGl0eSB0ZXN0cwpyZXNpZHVhbHMgPC0gcmVzaWR1YWxzKG1vZGVsKQpqYl90ZXN0IDwtIGphcnF1ZS5iZXJhLnRlc3QocmVzaWR1YWxzKQpqYl90ZXN0CiMgb3V0bGllciB0ZXN0IChzZWUgcC12YWx1ZSBmb3IgQm9uZmVycm9uaSBjb3JyZWN0aW9uKQpvdXRsaWVyX3Rlc3QgPC0gb3V0bGllclRlc3QobW9kZWwpCm91dGxpZXJfdGVzdApgYGAKUmV6w61kdcOhIHPDuiBwcmlibGnFvm5lIG5vcm3DoWxuZSByb3pkZWxlbsOpLCBiZXogdsO9cmF6bsO9Y2ggb2TEvmFobMO9Y2ggaG9kbsO0dC4KTW9kZWwgcHJldG8gc3DEusWIYSBwcmVkcG9rbGFkeSBPTFMgYSBuaWUgamUgcG90cmVibsOpIMW+aWFkbmUgZG9kYXRvxI1uw6kgxI1pc3RlbmllIGFuaSB0cmFuc2Zvcm3DoWNpYSDDumRham92LgoKIyMgWsOhdmVyClbDvXNsZWRreSBsaW5lw6FybmVobyByZWdyZXNuw6lobyBtb2RlbHUgcG90dnJkaWxpLCDFvmUgdsWhZXRreSB0cmkgc2vDum1hbsOpIHByZW1lbm7DqSDigJMgTG9nIEdEUCBwZXIgY2FwaXRhLCBTb2NpYWwgc3VwcG9ydCBhIEZyZWVkb20gdG8gbWFrZSBsaWZlIGNob2ljZXMg4oCTIG1hasO6IHBveml0w612bnkgYSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSB2cGx5diBuYSBpbmRleCDFocWlYXN0aWEgKExpZmUgTGFkZGVyKS4gVG8gem5hbWVuw6EsIMW+ZSBrcmFqaW55IHMgdnnFocWhb3UgZWtvbm9taWNrb3Ugw7pyb3bFiG91LCBzaWxuZWrFocOtbWkgc29jacOhbG55bWkgdsOkemJhbWkgYSB2w6TEjcWhb3Ugc2xvYm9kb3Ugcm96aG9kb3ZhbmlhIHZ5a2F6dWrDuiB2IHByaWVtZXJlIHZ5xaHFoWl1IMO6cm92ZcWIIHN1Ympla3TDrXZuZWhvIMWhxaVhc3RpYSBvYnl2YXRlxL5vdi4KCktvZWZpY2llbnQgZGV0ZXJtaW7DoWNpZSBSwrIgPSAwLjcxNTUgdWthenVqZSwgxb5lIG1vZGVsIHZ5c3ZldMS+dWplIHByaWJsacW+bmUgNzEsNSAlIHZhcmlhYmlsaXR5IGluZGV4dSDFocWlYXN0aWEsIMSNbyBwcmVkc3RhdnVqZSB2ZcS+bWkgZG9icsO6IG1pZXJ1IHZ5c3ZldMS+dWrDumNlaiBzY2hvcG5vc3RpIG1vZGVsdS4gRi3FoXRhdGlzdGlrYSAoRiA9IDE2OTM7IHAgPCAyLjJl4oiSMTYpIHBvdHZyZHp1amUsIMW+ZSBtb2RlbCBha28gY2Vsb2sgamUgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70sIHRlZGEgYXNwb8WIIGplZG5hIHogdnlzdmV0xL51asO6Y2ljaCBwcmVtZW5uw71jaCBtw6EgbmVudWxvdsO9IHZwbHl2IG5hIMWhxaVhc3RpZS4KCkRpYWdub3N0aWNrw6kgZ3JhZnkgdWvDoXphbGksIMW+ZSByZXrDrWR1w6Egc8O6IHJvdm5vbWVybmUgcm96bG/FvmVuw6kgb2tvbG8gbnVsb3ZlaiBvc2kgYSBuZXByZWphdnVqZSBzYSDFvmlhZG5lIHN5c3RlbWF0aWNrw6kgc2tyZXNsZW5pZS4gxIxlcnZlbsOhIExPRVNTIMSNaWFyYSB2IGdyYWZlIFJlc2lkdWFscyB2cyBGaXR0ZWQgamUgdGFrbWVyIHZvZG9yb3Zuw6EsIMSNbyBuYXpuYcSNdWplIHNwbG5lbmllIHByZWRwb2tsYWR1IGxpbmVhcml0eS4gU2NhbGXigJNMb2NhdGlvbiBwbG90IHBvdHZyZGlsIGtvbsWhdGFudG7DuiB2YXJpYW5jaXUgcmV6w61kdcOtLCB0ZWRhIG1vZGVsIG5lcG9ydcWhdWplIHByZWRwb2tsYWQgaG9tb3NrZWRhc3RpY2l0eS4KClYgZ3JhZmUgUeKAk1EgUmVzaWR1YWxzIGJvZHkgbGXFvmlhIHByZXZhxb5uZSBuYSBkaWFnb27DoWxlLCDEjW8gem5hbWVuw6EsIMW+ZSByb3pkZWxlbmllIHJlesOtZHXDrSBqZSBwcmlibGnFvm5lIG5vcm3DoWxuZS4gTWVuxaFpZSBvZGNow71sa3kgbmEga29uY29jaCBncmFmdSBzw7ogemFuZWRiYXRlxL5uw6kgdnpoxL5hZG9tIG5hIHZlxL5rb3PFpSB2em9ya3kuIFJlc2lkdWFscyB2cyBMZXZlcmFnZSB1a8OhemFsLCDFvmUgxb5pYWRuZSBwb3pvcm92YW5pZSBuZW3DoSBleHRyw6ltbnkgcMOha292w70gZWZla3QgYW5pIHbDvXJhem7DvSB2cGx5diBuYSBvZGhhZHkga29lZmljaWVudG92LgoKT3V0bGllciB0ZXN0IChjYXI6Om91dGxpZXJUZXN0KSBpZGVudGlmaWtvdmFsIGplZG5vIHBvem9yb3ZhbmllICjEjS4gMjIxKSBzIGhvZG5vdG91IMWhdHVkZW50aXpvdmFuw6lobyByZXrDrWR1YSAtMy44MiwgYWxlIHBvIEJvbmZlcnJvbmlobyBrb3Jla2NpaSAocCA9IDAuMjc2Nikgc2EgdWvDoXphbG8sIMW+ZSB0b3RvIHBvem9yb3ZhbmllIG5pZSBqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DqSwgdGFrxb5lIG1vZGVsIG5pZSBqZSBvdnBseXZuZW7DvSBvZMS+YWhsw71taSBib2RtaS4KClBvdHZyZGVuaWUgaHlwb3TDqXoKCkxvZyBHRFAgcGVyIGNhcGl0YSDigJMgb8SNYWvDoXZhbCBzYSBwb3ppdMOtdm55IHZwbHl2ICh2ecWhxaHDrSBIRFAg4oaSIHZ5xaHFoWlhIHNwb2tvam5vc8WlKS4gS29lZmljaWVudCAoMC41MDY3KSBqZSBrbGFkbsO9IGEgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70gKHAgPCAwLjAwMSksIMSNw61tIHNhIGh5cG90w6l6YSBwb3R2cmR6dWplLgoKU29jaWFsIHN1cHBvcnQg4oCTIG/EjWFrw6F2YWwgc2EgcG96aXTDrXZueSB2cGx5diAoc2lsbmVqxaFpZSBzb2Npw6FsbmUgdsOkemJ5IOKGkiB2ecWhxaFpYSBzcG9rb2pub3PFpSkuIEtvZWZpY2llbnQgKDIuNDUyMykgamUga2xhZG7DvSBhIMWhdGF0aXN0aWNreSB2w716bmFtbsO9IChwIDwgMC4wMDEpLCB0ZWRhIGh5cG90w6l6YSBzYSBwb3R2cmR6dWplLgoKRnJlZWRvbSB0byBtYWtlIGxpZmUgY2hvaWNlcyDigJMgb8SNYWvDoXZhbCBzYSBwb3ppdMOtdm55IHZwbHl2ICh2w6TEjcWhaWEgc2xvYm9kYSDihpIgdnnFocWhaWEgc3Bva29qbm9zxaUpLiBLb2VmaWNpZW50ICgxLjg2NTUpIGplIGtsYWRuw70gYSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSAocCA8IDAuMDAxKSwgcHJldG8gYWogdMOhdG8gaHlwb3TDqXphIHNhIHBvdHZyZHp1amUuCgpDZWxrb3ZvIG1vxb5ubyBrb27FoXRhdG92YcWlLCDFvmUgbW9kZWwgc3DEusWIYSB2xaFldGt5IHrDoWtsYWRuw6kgcHJlZHBva2xhZHkgbGluZcOhcm5laiByZWdyZXNpZSwgbmV2eWthenVqZSBoZXRlcm9za2VkYXN0aWNpdHUgYW5pIHbDvXJhem7DqSBuZWxpbmVhcml0eS4gVsWhZXRreSBvxI1ha8OhdmFuaWEgYm9saSBuYXBsbmVuw6kg4oCTIHZ5xaHFocOtIHByw61qZW0sIHNpbG5lasWhaWUgc29jacOhbG5lIHbDpHpieSBhIHbDpMSNxaFpYSBzbG9ib2RhIHJvemhvZG92YW5pYSB2w716bmFtbmUgenZ5xaF1asO6IHN1Ympla3TDrXZuZSBwcmXFvsOtdmFuw6kgxaHFpWFzdGllIG9ieXZhdGXEvm92LiBNb2RlbCBqZSBwcmV0byDFoXRhdGlzdGlja3kgc3BvxL5haGxpdsO9LCBla29ub21pY2t5IGludGVycHJldG92YXRlxL5uw70gYSBwb2Rwb3J1amUgcMO0dm9kbmUgc3Rhbm92ZW7DqSBoeXBvdMOpenkuCgojIyBIZXRlcm9za2VkYXN0aWNpdGEKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGF0Y2h3b3JrKQoKIyBSZXrDrWR1w6EgeiBtb2RlbHUKcmVzaWRfc3EgPC0gcmVzaWQobW9kZWwpXjIKCiMgR3JhZnkKcDEgPC0gZ2dwbG90KG1vZGVsX2RhdGEsIGFlcyh4ID0gTG9nLkdEUC5wZXIuY2FwaXRhLCB5ID0gcmVzaWRfc3EpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsKICBsYWJzKHggPSAiTG9nIEdEUCBwZXIgY2FwaXRhIiwgeSA9ICJTcXVhcmVkIFJlc2lkdWFscyIsIHRpdGxlID0gIlJlc2lkdWFscyB2cyBMb2cgR0RQIikgKwogIHRoZW1lX21pbmltYWwoKQoKcDIgPC0gZ2dwbG90KG1vZGVsX2RhdGEsIGFlcyh4ID0gU29jaWFsLnN1cHBvcnQsIHkgPSByZXNpZF9zcSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC42KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKwogIGxhYnMoeCA9ICJTb2NpYWwgc3VwcG9ydCIsIHkgPSAiU3F1YXJlZCBSZXNpZHVhbHMiLCB0aXRsZSA9ICJSZXNpZHVhbHMgdnMgU29jaWFsIHN1cHBvcnQiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpwMyA8LSBnZ3Bsb3QobW9kZWxfZGF0YSwgYWVzKHggPSBGcmVlZG9tLnRvLm1ha2UubGlmZS5jaG9pY2VzLCB5ID0gcmVzaWRfc3EpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsKICBsYWJzKHggPSAiRnJlZWRvbSIsIHkgPSAiU3F1YXJlZCBSZXNpZHVhbHMiLCB0aXRsZSA9ICJSZXNpZHVhbHMgdnMgRnJlZWRvbSIpICsKICB0aGVtZV9taW5pbWFsKCkKCiMgWm9icmF6ZW5pZSB2ZWTEvmEgc2ViYQoocDEgfCBwMikgLyBwMwpgYGAKIyMgU2vDum1hbmllIGhldGVyb3NrZWRhc3RpY2l0eSDigJMgdml6dcOhbG5hIGtvbnRyb2xhCgpOYSBvYnLDoXprdSB2ecWhxaFpZSBzw7ogem9icmF6ZW7DqSBncmFmeSB6w6F2aXNsb3N0aSDFoXR2b3Jjb3YgcmV6w61kdcOtIG9kIHZ5c3ZldMS+dWrDumNpY2ggcHJlbWVubsO9Y2g6CgotICoqUmVzaWR1YWxzIHZzIExvZyBHRFAgcGVyIGNhcGl0YSoqCi0gKipSZXNpZHVhbHMgdnMgU29jaWFsIHN1cHBvcnQqKgotICoqUmVzaWR1YWxzIHZzIEZyZWVkb20gdG8gbWFrZSBsaWZlIGNob2ljZXMqKgoKxIxlcnZlbsOhIGtyaXZrYSBqZSB2byB2xaFldGvDvWNoIHByw61wYWRvY2ggdGFrbWVyIHZvZG9yb3Zuw6EsIGJleiB2w71yYXpuw6lobyB0cmVuZHUuIFJvenB0eWwgcmV6w61kdcOtIHNhIG5lbWVuw60gc3lzdGVtYXRpY2t5IHMgaG9kbm90YW1pIHZ5c3ZldMS+dWrDumNpY2ggcHJlbWVubsO9Y2guIE5hIHrDoWtsYWRlIHZpenXDoWxuZWoga29udHJvbHkgKipwcmVkcG9rbGFkw6FtZSwgxb5lIGhldGVyb3NrZWRhc3RpY2l0YSBuaWUgamUgcHLDrXRvbW7DoSoqLgoKUHJlIHBvdHZyZGVuaWUgdG9odG8gcHJlZHBva2xhZHUgdsWhYWsgdnlrb27DoW1lIMWhdGF0aXN0aWNrw70gdGVzdCDigJMgKipCcmV1c2No4oCTUGFnYW4gdGVzdCoqLgoKYGBge3J9CmxpYnJhcnkobG10ZXN0KQpicHRlc3QobW9kZWwpCmBgYAojIyBTa8O6bWFuaWUgaGV0ZXJvc2tlZGFzdGljaXR5IOKAkyBvcGlzCktlxI/FvmUgcC1ob2Rub3RhIDwgMC4wNSwgemFtaWV0YW1lIG51bG92w7ogaHlwb3TDqXp1IG8gaG9tb3NrZWRhc3RpY2l0ZS4gVG8gem5hbWVuw6EsIMW+ZSB2IG5hxaFvbSBtb2RlbGkgamUgcHLDrXRvbW7DoSBoZXRlcm9za2VkYXN0aWNpdGEuIFYgZMO0c2xlZGt1IHRvaG8gc8O6IMWhdGFuZGFyZG7DqSBjaHlieSBvZGhhZG92IGtvZWZpY2llbnRvdiBuZXNwb8S+YWhsaXbDqSwgxI1vIG3DtMW+ZSB2aWVzxaUgayBuZXNwcsOhdm5lbXUgdnlob2Rub2NvdmFuaXUgdC10ZXN0b3YuCiMjIFNrw7ptYW5pZSBoZXRlcm9za2VkYXN0aWNpdHkgLSBXaGl0ZSBoZXRlcm9za2VkYXN0aWNpdHktY29uc2lzdGVudCBvZGhhZG92IHJvenB0eWxvdiAocm9idXN0bsOpIMWhdGFuZGFyZG7DqSBjaHlieSkKCmBgYHtyfQojIEluxaF0YWzDoWNpYSBiYWzDrWtvdgojIGluc3RhbGwucGFja2FnZXMoInNhbmR3aWNoIikKIyBpbnN0YWxsLnBhY2thZ2VzKCJsbXRlc3QiKQoKIyBOYcSNw610YW5pZSBiYWzDrWtvdgpsaWJyYXJ5KHNhbmR3aWNoKQpsaWJyYXJ5KGxtdGVzdCkKCiMgUm9idXN0bsOpIMWhdGFuZGFyZG7DqSBjaHlieSAoV2hpdGUgSEMxKQpjb2VmdGVzdChtb2RlbCwgdmNvdiA9IHZjb3ZIQyhtb2RlbCwgdHlwZSA9ICJIQzEiKSkKYGBgCgpgYGB7cn0KIyBLb2VmaWNpZW50eSBzYSBuZXptZW5pbGkgKHJvdm5ha8OpIGFrbyB2IHDDtHZvZG5vbSBtb2RlbGkpLiDFoHRhbmRhcmRuw6kgY2h5Ynkgc8O6IHbDpMSNxaFpZSBuZcW+IHYga2xhc2lja29tIE9MUywgxI1vIGplIG/EjWFrw6F2YW7DqSwgcHJldG/FvmUgc8O6IOKAnmhydWLFoWll4oCcIGEga29yaWd1asO6IGhldGVyb3NrZWRhc3RpY2l0dS4gVsWhZXRreSBwcmVtZW5uw6kgem9zdMOhdmFqw7ogxaF0YXRpc3RpY2t5IHbDvXpuYW1uw6kgKHAgPCAwLjAwMSkuIFJvYnVzdG7DqSBvZGhhZHkgemFiZXpwZcSNdWrDuiBzcHLDoXZuZSB0LXRlc3R5IGFqIHByaSBwcsOtdG9tbm9zdGkgaGV0ZXJvc2tlZGFzdGljaXR5LiBNb2RlbCBqZSBwbyDDunByYXZlIHJvYnVzdG7DvSB2b8SNaSBoZXRlcm9za2VkYXN0aWNpdGUgYSBwb3R2cmR6dWplIHDDtHZvZG7DqSB6w6F2ZXJ5OiB2ecWhxaHDrSBIRFAsIHNpbG5lasWhaWEgc29jacOhbG5hIHBvZHBvcmEgYSB2w6TEjcWhaWEgc2xvYm9kYSByb3pob2RvdmFuaWEgdsO9em5hbW5lIHp2ecWhdWrDuiBpbmRleCDFocWlYXN0aWEuCmBgYAoKIyMgUG9yb3ZuYW5pZQoKYGBge3J9CiMgTmHEjcOtdGFuaWUgcG90cmVibsO9Y2ggYmFsw61rb3YKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkoc2FuZHdpY2gpCgojIFJvYnVzdG7DqSDFoXRhbmRhcmRuw6kgY2h5YnkgKFdoaXRlIEhDMSkKcm9idXN0X3Jlc3VsdHMgPC0gY29lZnRlc3QobW9kZWwsIHZjb3YgPSB2Y292SEMobW9kZWwsIHR5cGUgPSAiSEMxIikpCnByaW50KHJvYnVzdF9yZXN1bHRzKQoKIyBQb3Jvdm5hbmllIHDDtHZvZG7DvWNoIHZzIHJvYnVzdG7DvWNoIMWhdGFuZGFyZG7DvWNoIGNow71iCm9yaWdpbmFsIDwtIHN1bW1hcnkobW9kZWwpJGNvZWZmaWNpZW50cwpjb21wYXJpc29uIDwtIGNiaW5kKAogIEVzdGltYXRlID0gb3JpZ2luYWxbLCAxXSwKICBPTFNfU3RkX0Vycm9yID0gb3JpZ2luYWxbLCAyXSwKICBSb2J1c3RfU3RkX0Vycm9yID0gcm9idXN0X3Jlc3VsdHNbLCAyXQopCnByaW50KGNvbXBhcmlzb24pCmBgYAoKYGBge3J9CiMgTmEgesOha2xhZGUgdMO9Y2h0byB2w71zbGVka292IHNvbSBzYSByb3pob2RvbCBvIHZ5dHZvcmVuaWUgbm92w6lobyBtb2RlbHUgc28gemxvZ2FyaXRtaXpvdmFuw71taSB2xaFldGvDvW1pIHByZW1lbm7DvW1pCmBgYAoKIyMgVnl0dm9yZW5pZSBub3bDqWhvIG1vZGVsdQoKYGBge3J9CiMgVnl0dm9yZW5pZSBub3bDvWNoIHByZW1lbm7DvWNoCm1vZGVsX2RhdGEkbG9nX1NvY2lhbC5zdXBwb3J0IDwtIGxvZyhtb2RlbF9kYXRhJFNvY2lhbC5zdXBwb3J0KQptb2RlbF9kYXRhJGxvZ19GcmVlZG9tIDwtIGxvZyhtb2RlbF9kYXRhJEZyZWVkb20udG8ubWFrZS5saWZlLmNob2ljZXMpCgojIE5vdsO9IG1vZGVsCm1vZGVsX2xvZyA8LSBsbShMaWZlLkxhZGRlciB+IExvZy5HRFAucGVyLmNhcGl0YSArIGxvZ19Tb2NpYWwuc3VwcG9ydCArIGxvZ19GcmVlZG9tLAogICAgICAgICAgICAgICAgZGF0YSA9IG1vZGVsX2RhdGEpCgojIFbDvXNsZWRreQpzdW1tYXJ5KG1vZGVsX2xvZykKYGBgCgojIyBWaXp1w6FsbmEga29udHJvbGEgbm92w6lobyBtb2RlbHUKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwYXRjaHdvcmspCgpyZXNpZF9zcV9sb2cgPC0gcmVzaWQobW9kZWxfbG9nKV4yCgpwMSA8LSBnZ3Bsb3QobW9kZWxfZGF0YSwgYWVzKHggPSBMb2cuR0RQLnBlci5jYXBpdGEsIHkgPSByZXNpZF9zcV9sb2cpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsKICBsYWJzKHggPSAiTG9nIEdEUCBwZXIgY2FwaXRhIiwgeSA9ICJTcXVhcmVkIFJlc2lkdWFscyIsIHRpdGxlID0gIlJlc2lkdWFscyB2cyBMb2cgR0RQIikgKwogIHRoZW1lX21pbmltYWwoKQoKcDIgPC0gZ2dwbG90KG1vZGVsX2RhdGEsIGFlcyh4ID0gbG9nX1NvY2lhbC5zdXBwb3J0LCB5ID0gcmVzaWRfc3FfbG9nKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQiKSArCiAgbGFicyh4ID0gImxvZyhTb2NpYWwgc3VwcG9ydCkiLCB5ID0gIlNxdWFyZWQgUmVzaWR1YWxzIiwgdGl0bGUgPSAiUmVzaWR1YWxzIHZzIGxvZyhTb2NpYWwgc3VwcG9ydCkiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpwMyA8LSBnZ3Bsb3QobW9kZWxfZGF0YSwgYWVzKHggPSBsb2dfRnJlZWRvbSwgeSA9IHJlc2lkX3NxX2xvZykpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC42KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKwogIGxhYnMoeCA9ICJsb2coRnJlZWRvbSkiLCB5ID0gIlNxdWFyZWQgUmVzaWR1YWxzIiwgdGl0bGUgPSAiUmVzaWR1YWxzIHZzIGxvZyhGcmVlZG9tKSIpICsKICB0aGVtZV9taW5pbWFsKCkKCihwMSB8IHAyKSAvIHAzCmBgYAoKIyMgU2vDum1hbmllIGhldGVyb3NrZWRhc3RpY2l0eSBwbyBsb2dhcml0bWl6w6FjaWkgcHJlbWVubsO9Y2gKCk5hIG9icsOhemt1IHPDuiB6b2JyYXplbsOpIGdyYWZ5IHrDoXZpc2xvc3RpIMWhdHZvcmNvdiByZXrDrWR1w60gb2QgdnlzdmV0xL51asO6Y2ljaCBwcmVtZW5uw71jaCBwbyBsb2dhcml0bWl6w6FjaWkgU29jaWFsIHN1cHBvcnQgYSBGcmVlZG9tIHRvIG1ha2UgbGlmZSBjaG9pY2VzLiDEjGVydmVuw6EgTE9FU1Mga3JpdmthIHVrYXp1amUsIMW+ZSByb3pwdHlsIHJlesOtZHXDrSBzYSBzdMOhbGUgbWVuw60gcyBob2Rub3RhbWkgdnlzdmV0xL51asO6Y2ljaCBwcmVtZW5uw71jaDoKCi0gUHJpIExvZyBHRFAgcGVyIGNhcGl0YSBqZSByb3pwdHlsIHbDvXJhem5lIGtsZXNhasO6Y2kuCi0gUHJpIGxvZyhTb2NpYWwgc3VwcG9ydCkgamUgcm96cHR5bCB2w71yYXpuZSBrbGVzYWrDumNpLgotIFByaSBsb2coRnJlZWRvbSkgamUgcm96cHR5bCB0YWt0aWXFviB2w71yYXpuZSBrbGVzYWrDumNpLgpWxaFldGt5IGtsZXNhasO6Y2UgdHJlbmR5IHbFoWFrIG5hc3TDoXZhasO6IG5hIMS+YXZlaiBzdHJhbmUgZ3JhZnUuCgojIyMgWsOhdmVyOgoKTG9nYXJpdG1pesOhY2lhIHByZW1lbm7DvWNoICoqbmV6bGVwxaFpbGEgc2l0dcOhY2l1KiouIEhldGVyb3NrZWRhc3RpY2l0YSBqZSBzdMOhbGUgcHLDrXRvbW7DoSwgcHJldG8gem9zdMOhdmFtZSBwcmkgcMO0dm9kbm9tIG1vZGVsaSBhIHBvdcW+w612YW1lIHJvYnVzdG7DqSDFoXRhbmRhcmRuw6kgY2h5YnkgYSBww7R2b2Ruw70gbW9kZWwgKFdoaXRlIEhDMSkgbmEga29yZWtjaXUgaGV0ZXJvc2tlZGFzdGljaXR5LgoKCiMjIE5lbGluZWFyaXRhOgoKYGBge3J9CiMgTmHEjcOtdGFuaWUgZMOhdAp1ZGFqZTcgPC0gcmVhZC5jc3YoIldvcmxkIEhhcHBpbmVzcyBSZXBvcnQgMjAwNS0yMDIxLmNzdiIsIHNlcD0iLCIsIGhlYWRlcj1UUlVFKQoKIyBaaXN0ZW5pZSBuYWpub3bFoWllaG8gcm9rdQptYXhfeWVhciA8LSBtYXgodWRhamU3JFllYXIsIG5hLnJtID0gVFJVRSkKCiMgVsO9YmVyIG5ham5vdsWhaWVobyByb2t1IGEgcmVsZXZhbnRuw71jaCBwcmVtZW5uw71jaAp1ZGFqZTdfbGF0ZXN0IDwtIHVkYWplN1t1ZGFqZTckWWVhciA9PSBtYXhfeWVhciwgCiAgICAgICAgICAgICAgICAgICAgICAgIGMoIkhlYWx0aHkubGlmZS5leHBlY3RhbmN5LmF0LmJpcnRoIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkxvZy5HRFAucGVyLmNhcGl0YSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICJMaWZlLkxhZGRlciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICJTb2NpYWwuc3VwcG9ydCIpXQoKIyBJbXB1dMOhY2lhIGNow71iYWrDumNpY2ggaG9kbsO0dCBtZWRpw6Fub20KY29sdW1uX21lZGlhbnMgPC0gc2FwcGx5KHVkYWplN19sYXRlc3QsIG1lZGlhbiwgbmEucm0gPSBUUlVFKQpmb3IgKGNvbCBpbiBuYW1lcyh1ZGFqZTdfbGF0ZXN0KSkgewogIHVkYWplN19sYXRlc3RbW2NvbF1dW2lzLm5hKHVkYWplN19sYXRlc3RbW2NvbF1dKV0gPC0gY29sdW1uX21lZGlhbnNbY29sXQp9CmBgYAoKIyMjIFrDoWtsYWRuw70gbW9kZWwKCmBgYHtyfQptb2RlbCA8LSBsbShIZWFsdGh5LmxpZmUuZXhwZWN0YW5jeS5hdC5iaXJ0aCB+IExvZy5HRFAucGVyLmNhcGl0YSArIExpZmUuTGFkZGVyICsgU29jaWFsLnN1cHBvcnQsCiAgICAgICAgICAgIGRhdGEgPSB1ZGFqZTdfbGF0ZXN0KQpzdW1tYXJ5KG1vZGVsKQpgYGAKTGlmZSBsYWRkZXIgbmllIGplIHbDvXpuYW3DvSBwcmV0byBobyB2eXJhZMOtbS4KCmBgYHtyfQptb2RlbCA8LSBsbShIZWFsdGh5LmxpZmUuZXhwZWN0YW5jeS5hdC5iaXJ0aCB+IExvZy5HRFAucGVyLmNhcGl0YSArIFNvY2lhbC5zdXBwb3J0LAogICAgICAgICAgICBkYXRhID0gdWRhamU3X2xhdGVzdCkKc3VtbWFyeShtb2RlbCkKCmBgYAoKT2JlIHByZW1lbm7DqSBzw7ogxaF0YXRpc3RpY2t5IHbDvXpuYW1uw6kgcHJldG8gcG9rcmHEjXVqZW0gcyB0w71tdG8gbW9kZWxvbQoKYGBge3J9CmxpYnJhcnkobG10ZXN0KQpyZXNldHRlc3QobW9kZWwpCmBgYApQIHZhbHVlIG5hZCBobGFkaW5vdSB2w716bmFtbm9zdGkgMCwwNSBwb3pyaWVtZSBzYSB2xaFhayBhaiBuYSBncmFmeS4KCmBgYHtyfQpwbG90KG1vZGVsLCB3aGljaCA9IDEpICAgICAgICAgICMgUmVzaWR1YWxzIHZzIEZpdHRlZApjYXI6OmNyUGxvdHMobW9kZWwpICAgICAgICAgICAgICMgQ29tcG9uZW50ICsgUmVzaWR1YWwgcGxvdHMKYGBgCktlZMW+ZSBzbWUgcHJla3JvxI1pbGkgaGxhZGludSB2w716bmFtbm9zdGkgbmVtw6FtZSBwb3R2cmRlbmllIG8gdG9tIMW+ZSBtb2RlbCBuaWUgamUgxaFwcsOhdm5lIMWhcGVjaWZpa292YW7DvSBhdsWhYWsgbmEgYsOhemUgdcSNZW5pYSB2eWtvbsOhbWUgbmFzbGVkdWrDumNlOgoKYGBge3J9Cm1vZGVsX3F1YWQgPC0gbG0oSGVhbHRoeS5saWZlLmV4cGVjdGFuY3kuYXQuYmlydGggfiBMb2cuR0RQLnBlci5jYXBpdGEgKyBJKExvZy5HRFAucGVyLmNhcGl0YV4yKSArCiAgICAgICAgICAgICAgICAgICBTb2NpYWwuc3VwcG9ydCArIEkoU29jaWFsLnN1cHBvcnReMiksCiAgICAgICAgICAgICAgICAgZGF0YSA9IHVkYWplN19sYXRlc3QpCnN1bW1hcnkobW9kZWxfcXVhZCkKCiMgUG9yb3ZuYW5pZSBzIHDDtHZvZG7DvW0gbW9kZWxvbQphbm92YShtb2RlbCwgbW9kZWxfcXVhZCkKcmVzZXR0ZXN0KG1vZGVsX3F1YWQpCmBgYApLdmFkcmF0aWNrw6kgxI1sZW55IG5lcG9tb2hsaSDigJMgdsWhZXRreSBzw7ogbmV2w716bmFtbsOpLCBSwrIgc2EgbmV6bGVwxaFpbG8sIEFOT1ZBIG5lcG90dnJkaWxhIHpsZXDFoWVuaWUuClJFU0VUIHRlc3QgdWthenVqZSwgxb5lIGFuaSBwbyByb3rFocOtcmVuw60gbmllIGplIHByb2Jsw6ltIHNvIMWhcGVjaWZpa8OhY2lvdS4KWsOhdmVyOiBww7R2b2Ruw70gbW9kZWwgamUgZG9zdGF0b8SNbsO9LCBhbGUgbmEgw7rEjWVseSB1xI1lbmlhIG3DtMW+ZW1lIHNrw7pzacWlIGR1bW15IHByZW1lbm7DugoKYGBge3J9CiMgVnl0dm9yZW5pZSBkdW1teSBwcmVtZW5uZWoKdWRhamU3X2xhdGVzdCREVU0gPC0gaWZlbHNlKHVkYWplN19sYXRlc3QkU29jaWFsLnN1cHBvcnQgPiAwLjgsIDEsIDApCgojIE1vZGVsIHNvIHpsb21vbSB2IHNrbG9uZSAoaW50ZXJha2NpYSkKbW9kZWxEIDwtIGxtKEhlYWx0aHkubGlmZS5leHBlY3RhbmN5LmF0LmJpcnRoIH4gU29jaWFsLnN1cHBvcnQgKyBJKERVTSpTb2NpYWwuc3VwcG9ydCkgKwogICAgICAgICAgICAgICBMb2cuR0RQLnBlci5jYXBpdGEsCiAgICAgICAgICAgICBkYXRhID0gdWRhamU3X2xhdGVzdCkKCiMgVsO9c2xlZGt5CnN1bW1hcnkobW9kZWxEKQoKIyBQb3Jvdm5hbmllIHMgcMO0dm9kbsO9bSBtb2RlbG9tCmFub3ZhKG1vZGVsLCBtb2RlbEQpCgojIFJFU0VUIHRlc3QKcmVzZXR0ZXN0KG1vZGVsRCkKYGBgCk1vZGVsIHNvIHpsb21vbSBwb21vY291IGR1bW15IHByZW1lbm5laiB1a2F6dWplLCDFvmUgesOha2xhZG7DqSBwcmVtZW5uw6kgem9zdMOhdmFqw7ogdsO9em5hbW7DqSwgYWxlIGludGVyYWvEjW7DvSDEjWxlbiBtw6EgbGVuIHNsYWLDuiDFoXRhdGlzdGlja8O6IHbDvXpuYW1ub3PFpS4gS29lZmljaWVudCBwcmkgU29jaWFsLnN1cHBvcnQgamUgcHJpYmxpxb5uZSAxMSw3MSBhIGplIHZ5c29rbyB2w716bmFtbsO9LCDEjW8gem5hbWVuw6EsIMW+ZSBwcmkgbmnFvsWhw61jaCBob2Rub3TDoWNoIFNvY2lhbC5zdXBwb3J0IChkbyAwLDgpIG3DoSB0w6F0byBwcmVtZW5uw6Egc2lsbsO9IHBveml0w612bnkgdnBseXYgbmEgb8SNYWvDoXZhbsO6IGTEusW+a3Ugxb5pdm90YS4gSW50ZXJha8SNbsO9IMSNbGVuIERVTSpTb2NpYWwuc3VwcG9ydCBtw6EgaG9kbm90dSAtOSw4MiBhIHAtaG9kbm90dSBva29sbyAwLDA2NSwgxI1vIG5hem5hxI11amUsIMW+ZSBwcmkgdnnFocWhw61jaCBob2Rub3TDoWNoIFNvY2lhbC5zdXBwb3J0IChuYWQgMCw4KSBzYSBlZmVrdCB2w71yYXpuZSB6bmnFvnVqZSDigJMgeiBww7R2b2Ruw71jaCAxMSw3MSBuYSBwcmlibGnFvm5lIDEsODkuIExvZy5HRFAucGVyLmNhcGl0YSB6b3N0w6F2YSB2ZcS+bWkgdsO9em5hbW7DvSBzIHBveml0w612bnltIHZwbHl2b20uClBvcm92bmFuaWUgbW9kZWxvdiBwb21vY291IEFOT1ZBIHRlc3R1IHVrYXp1amUgcC1ob2Rub3R1IDAsMDY0OCwgxI1vIHpuYW1lbsOhLCDFvmUgbmEgNSAlIGhsYWRpbmUgdsO9em5hbW5vc3RpIG5lemFtaWV0YW1lIG51bG92w7ogaHlwb3TDqXp1LCBhbGUgbmEgMTAgJSBobGFkaW5lIGJ5IHNtZSBtb2hsaSBwb3ZlZGHFpSwgxb5lIG5vdsO9IG1vZGVsIGplIGxlcMWhw60uIFJhbXNleSBSRVNFVCB0ZXN0IG3DoSBwLWhvZG5vdHUgMCwxMTg2LCB0YWvFvmUgbmV6YW1pZXRhbWUgSOKCgCBhIG1vZGVsIHBvdmHFvnVqZW1lIHphIHNwcsOhdm5lIMWhcGVjaWZpa292YW7DvS4KWsOhdmVyb20gbW/Fvm5vIHBvdmVkYcWlLCDFvmUgemF2ZWRlbmllIGR1bW15IHByZW1lbm5laiB6YWNoeXRpbG8gemxvbSB2byB2esWlYWh1IFNvY2lhbC5zdXBwb3J0IGsgb8SNYWvDoXZhbmVqIGTEusW+a2Ugxb5pdm90YSwgYWxlIHpsZXDFoWVuaWUgbW9kZWx1IGplIGxlbiBtaWVybmUgYSDFoXRhdGlzdGlja3kgc2xhYsWhaWUuIE1vZGVsIGplIHN0w6FsZSBkb2JyZSDFoXBlY2lmaWtvdmFuw70sIMSNbyBwb3R2cmR6dWplIFJFU0VUIHRlc3QuCgoKCgoK