Analýza meteorologických ukazovateľov

Úvod do problému a stanovenie hypotézy

Cieľom analýzy je modelovať strednú dennú teplotu v Bazileji (BASEL_temp_mean) na základe viacerých meteorologických premenných:

  • oblačnosť (BASEL_cloud_cover),

  • vlhkosť (BASEL_humidity),

  • tlak vzduchu (BASEL_pressure),

  • globálne žiarenie (BASEL_global_radiation),

  • zrážky (BASEL_precipitation),

  • slnečný svit (BASEL_sunshine) a minimálnu a maximálnu teplotu (BASEL_temp_min, BASEL_temp_max).

Pracovná hypotéza predpokladá, že tieto premenné významne ovplyvňujú strednú teplotu – napríklad vyššie globálne žiarenie alebo slnečný svit by mali viesť k vyšším teplotám, zatiaľ čo väčšia oblačnosť môže teplotu znižovať. Cieľom analýzy je overiť túto hypotézu pomocou lineárneho regresného modelu, posúdiť význam jednotlivých premenných a skontrolovať, či model spĺňa predpoklady lineárnej regresie, ako sú normalita rezíduí a konštantný rozptyl (homoskedasticita).

Na začiatku analýzy budeme najprv načítať potrebné knižnice, vyčistíme pracovné prostredie, načítame súbor weather_prediction_dataset.csv, vyberieme kľúčové stĺpce a doplníme chýbajúce hodnoty mediánom, aby boli údaje pripravené na ďalšie spracovanie.

Načítanie knižníc

library(zoo)
library(tseries)
library(lmtest)
library(sandwich)
library(car)
library(ggplot2)
library(cowplot)

Vyčistenie pracovného prostredia

rm(list=ls())

Načítanie údajov

udaje <- read.csv("weather_prediction_dataset.csv")

Výber potrebných stĺpcov

weather_data <- udaje[, c("BASEL_cloud_cover", "BASEL_humidity", "BASEL_pressure", 
                          "BASEL_global_radiation", "BASEL_precipitation", "BASEL_sunshine",
                          "BASEL_temp_mean", "BASEL_temp_min", "BASEL_temp_max")]

Imputácia chýbajúcich hodnôt mediánom

median_hodnoty <- sapply(weather_data, median, na.rm = TRUE)
weather_data_imputed <- weather_data
for (col in names(weather_data)) {
  weather_data_imputed[[col]][is.na(weather_data[[col]])] <- median_hodnoty[col]
}
weather_data <- weather_data_imputed

Boxploty pre vizuálnu kontrolu

Poskytnú nám rýchly prehľad o variabilite a rozsahu dát pred samotným modelovaním.

num_plots <- length(names(weather_data))
par(mfrow = c(3, 3))
par(mar = c(4, 4, 2, 1))
for (col in names(weather_data)) {
  boxplot(weather_data[[col]], main = col, xlab = "Hodnota", col = "lightblue")
}
par(mfrow = c(1, 1))

Lineárna regresia: závislá premenná BASEL_temp_mean

model <- lm(BASEL_temp_mean ~ BASEL_cloud_cover + BASEL_humidity + BASEL_pressure +
              BASEL_global_radiation + BASEL_precipitation + BASEL_sunshine +
              BASEL_temp_min + BASEL_temp_max, data = weather_data)
summary(model)

Call:
lm(formula = BASEL_temp_mean ~ BASEL_cloud_cover + BASEL_humidity + 
    BASEL_pressure + BASEL_global_radiation + BASEL_precipitation + 
    BASEL_sunshine + BASEL_temp_min + BASEL_temp_max, data = weather_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.6986 -0.3519  0.0137  0.3576  2.6206 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)            -1.490728   1.310306  -1.138 0.255323    
BASEL_cloud_cover       0.043206   0.007690   5.618 2.07e-08 ***
BASEL_humidity         -1.508743   0.127840 -11.802  < 2e-16 ***
BASEL_pressure          2.345408   1.279865   1.833 0.066952 .  
BASEL_global_radiation  0.090704   0.027478   3.301 0.000973 ***
BASEL_precipitation    -0.028120   0.019019  -1.479 0.139343    
BASEL_sunshine          0.007200   0.006625   1.087 0.277165    
BASEL_temp_min          0.498117   0.004798 103.822  < 2e-16 ***
BASEL_temp_max          0.475467   0.004462 106.549  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.5475 on 3645 degrees of freedom
Multiple R-squared:  0.9946,    Adjusted R-squared:  0.9945 
F-statistic: 8.329e+04 on 8 and 3645 DF,  p-value: < 2.2e-16

Pre lineárnu regresiu s BASEL_temp_mean ako závislou premennou model ukazuje veľmi dobrú zhody s dátami. Koeficienty naznačujú, že niektoré premenné majú silný vplyv na strednú teplotu.

Najdôležitejšie faktory sú:

  • Minimálna a maximálna teplota – hlavní prediktori s extrémne vysokými t-hodnotami a p-hodnotami < 2e-16.

  • Vlhkosť – výrazne znižuje strednú teplotu (-1,51, t = -11,8).

  • Oblačnosť a globálne žiarenie – mierny pozitívny efekt a štatisticky významné.

Premenné ako tlak, zrážky alebo slnečný svit sa v tomto modeli neprejavili ako významné.

Reziduá sú väčšinou malé (min = -2,6986, max = 2,6206, štandardná chyba = 0,5475), čo naznačuje dobrú presnosť predikcie.

Hodnota R-squared = 0,9946 ukazuje, že model vysvetľuje takmer všetku variabilitu strednej teploty, a vysoká F-statistika potvrdzuje celkovú štatistickú významnosť modelu.

Celkovo model veľmi dobre zachytáva vzťahy medzi meteorologickými premennými a strednou teplotou v Bazileji, pričom najdôležitejšie faktory sú jasne identifikovateľné a zodpovedajú očakávanému fyzikálnemu kontextu.

Diagnostické grafy

par(mfrow = c(2, 2))
plot(model)
par(mfrow = c(1, 1))

Residuals vs Fitted

  • Účel: Overiť, či má lineárny vzťah medzi premennými a či má reziduá konštantný rozptyl.

  • Na tomto grafe je červená čiara ideálne rovná a body sú náhodne rozmiestnené okolo nej. To znamená, že predpoklad linearity je splnený – medzi premennými existuje vhodný lineárny vzťah a model je dobre špecifikovaný.

Q-Q Residuals

  • Účel: Overiť, či sú reziduá normálne rozdelené.

  • Na tomto grafe body takmer dokonale sledujú diagonálnu čiaru. To znamená, že reziduá sú normálne rozdelené. Tento dôležitý predpoklad pre štatistické testovanie je splnený.

Scale-Location

  • Účel: Tiež overuje predpoklad homoskedasticity (konštantný rozptyl reziduí). Je to podobné ako prvý graf, ale zobrazuje odmocninu štandardizovaných reziduí.

  • Na tomto grafe sú body veľmi rozťahané a odchádzajú od čiary, ktorá nie je dokonale rovná. To znamená, že dochádza k heteroskedasticite – rozptyl reziduí nie je konštantný. To je hlavný problém modelu, ktorý môže spôsobiť nespoľahlivosť štatistických testov.

Residuals vs Leverage

  • Účel: Identifikovať vplyvné body (outliery), ktoré môžu neúmerne ovplyvňovať výsledky regresie.

  • Na tomto grafe sú body sústredené v ľavej časti a červená čiara sa mierne vlní. To znamená, že väčšina pozorovaní má nízku vplyvnosť, čo je dobré, no niektoré body môžu mierne ovplyvňovať model. Nevidia sa však extrémne vplyvné odľahlé hodnoty.

Jarque Bera test na normalitu rezíduí

residuals <- residuals(model)
jb_test <- jarque.bera.test(residuals)
jb_test

    Jarque Bera Test

data:  residuals
X-squared = 113.49, df = 2, p-value < 2.2e-16

Test Jarque-Bera sme použili na overenie, či sú reziduá modelu normálne rozdelené. Tento test skúma rozdiel medzi tvarom rozdelenia reziduí a teoretickým normálnym rozdelením pomocou dvoch ukazovateľov – šikmosti (skewness) a špicatosti (kurtosis).

Výsledky:

  • X-squared = 113.49,

  • df = 2,

  • p-hodnota < 2.2e-16.

To znamená, že test zamieta nulovú hypotézu o normálnom rozdelení reziduí. Napriek tomu, že Q-Q graf vizuálne naznačoval takmer normálne rozdelenie, test ukazuje, že existujú drobné odchýlky — pravdepodobne spôsobené veľkým počtom pozorovaní, kde aj malé rozdiely vedú k štatistickej významnosti.

Reziduá nie sú úplne normálne rozdelené, hoci odchýlky nie sú výrazné a model zostáva spoľahlivý na predikčné účely.

Test na odľahlé hodnoty

outlier_test <- outlierTest(model)
outlier_test

Pri teste na odľahlé hodnoty (outliery) sme použili štandardizované reziduá (rstudent), aby sme identifikovali pozorovania s extrémnymi hodnotami, ktoré môžu ovplyvniť stabilitu modelu.

Najvýraznejšie odľahlé hodnoty:

  • pozorovanie 1815 (rstudent = -4.96, Bonferroni p = 0.0027),

  • pozorovanie 713 (rstudent = 4.81, Bonferroni p = 0.0056),

  • pozorovanie 1273 (rstudent = -4.38, Bonferroni p = 0.0454).

Tieto hodnoty prekračujú bežný limit ±3, čo znamená, že ide o potenciálne problematické pozorovania.

Záverom možno povedať, že niekoľko pozorovaní má vysoký vplyv a môžu mierne skresľovať odhady parametrov

Grafy pre kontrolu heteroskedasticity

p1 <- ggplot(weather_data, aes(x = BASEL_pressure, y = resid(model)^2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "darkred") +
  labs(x = "BASEL_pressure", y = "Štvorce rezíduí", title = "Rezíduá^2 vs Tlak") +
  theme_minimal()

p2 <- ggplot(weather_data, aes(x = BASEL_humidity, y = resid(model)^2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "darkred") +
  labs(x = "BASEL_humidity", y = "Štvorce rezíduí", title = "Rezíduá^2 vs Vlhkosť") +
  theme_minimal()

plot_grid(p1, p2)

Tieto grafy zobrazujú vzťah medzi štvorcami rezíduí a vybranými nezávislými premennými (tlakom a vlhkosťou). Ich cieľom je zistiť, či sa rozptyl rezíduí mení v závislosti od hodnôt týchto premenných – teda či sa v modeli prejavuje heteroskedasticita.

Rezíduá² vs Tlak

  • Väčšina bodov sa sústreďuje v spodnej časti grafu, prevažne medzi hodnotami 0 až 2 na osi Y.

  • Červená čiara je len mierne zvlnená – na niektorých miestach sa nepatrne dvíha a opäť klesá, no celkovo zostáva pomerne rovná.

  • Takýto priebeh naznačuje, že rozptyl rezíduí je relatívne stabilný a výrazná heteroskedasticita sa neprejavuje.

Rezíduá² vs Vlhkosť

  • Body sú rozložené pomerne rovnomerne, väčšina z nich sa nachádza v spodnej časti grafu.

  • Červená čiara je takmer rovná, bez výrazného zakrivenia, čo svedčí o konštantnom rozptyle rezíduí.

  • Niekoľko bodov sa síce odchyľuje smerom nahor, ale tieto odchýlky sú minimálne a nemajú zásadný vplyv na stabilitu rozptylu.

Na základe týchto grafov môžeme konštatovať, že model nevykazuje výrazné známky heteroskedasticity – rozptyl chýb je relatívne konštantný naprieč rôznymi hodnotami tlaku aj vlhkosti.

Breusch-Pagan test na heteroskedasticitu

Tento test sa používa na formálne overenie, či je rozptyl rezíduí konštantný (homoskedasticita), alebo sa mení v závislosti od hodnôt nezávislých premenných (heteroskedasticita).

bptest(model)

    studentized Breusch-Pagan test

data:  model
BP = 248.6, df = 8, p-value < 2.2e-16

Keďže p-hodnota je výrazne menšia ako 0.05, zamietame nulovú hypotézu o homoskedasticite. To znamená, že rozptyl rezíduí nie je konštantný a v modeli sa vyskytuje heteroskedasticita.

Aj napriek tomu, že vizuálna kontrola grafov neukázala výrazné porušenie predpokladov, štatistický test potvrdzuje, že variabilita rezíduí sa mení v závislosti od niektorých premenných.

Model nespĺňa predpoklad konštantného rozptylu chýb. Tento problém môžeme riešiť napríklad použitím robustných štandardných chýb, ktoré korigujú dôsledky heteroskedasticity bez nutnosti meniť samotný model.

library(lmtest)
library(sandwich)

Výpočet robustných štandardných chýb

robust_summary <- coeftest(model, vcov = vcovHC(model, type = "HC1"))
robust_summary

t test of coefficients:

                         Estimate Std. Error  t value  Pr(>|t|)    
(Intercept)            -1.4907281  1.3517456  -1.1028  0.270179    
BASEL_cloud_cover       0.0432057  0.0075177   5.7472 9.816e-09 ***
BASEL_humidity         -1.5087434  0.1343456 -11.2303 < 2.2e-16 ***
BASEL_pressure          2.3454082  1.3187298   1.7785  0.075399 .  
BASEL_global_radiation  0.0907036  0.0290459   3.1228  0.001806 ** 
BASEL_precipitation    -0.0281202  0.0231747  -1.2134  0.225057    
BASEL_sunshine          0.0072004  0.0065787   1.0945  0.273805    
BASEL_temp_min          0.4981170  0.0055186  90.2609 < 2.2e-16 ***
BASEL_temp_max          0.4754666  0.0051496  92.3314 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Z tabuľky výsledkov vyplýva:

  • Koeficienty odhadnuté pôvodným modelom sa nemenia, takže veľkosť a smer vplyvu jednotlivých premenných zostávajú rovnaké,

  • Štandardné chyby sa mierne upravili, čo ovplyvnilo hodnoty t a p-hodnoty.

Najsilnejšie a štatisticky významné premenné zostávajú:

  • Minimálna a maximálna teplota (p < 2.2e-16, extrémne vysoké t-hodnoty),

  • Vlhkosť (p < 2.2e-16, negatívny efekt),

  • Oblačnosť a globálne žiarenie (p < 0.01).

Premenné ako tlak, zrážky a slnečný svit sa stále neprejavili ako významné, hoci tlak je teraz mierne bližšie k hranici významnosti (p = 0.075).

Použitie robustných štandardných chýb zabezpečilo spoľahlivejšiu interpretáciu modelu aj napriek prítomnosti heteroskedasticity. Model naďalej vysvetľuje väčšinu variability strednej teploty a dôležité vzťahy medzi premennými sú jasne identifikovateľné.

Záver

Na základe vykonanej analýzy môžeme konštatovať, že model strednej teploty v Bazileji veľmi dobre vysvetľuje väčšinu variability dát. Robustné štandardné chyby zabezpečili spoľahlivejšiu inferenciu aj napriek prítomnosti heteroskedasticity. Kľúčové premenné, ako minimálna a maximálna teplota, vlhkosť, oblačnosť a globálne žiarenie, majú výrazný a štatisticky významný vplyv na strednú teplotu. Celkovo model poskytuje presný a interpretovateľný pohľad na vzťahy medzi meteorologickými faktormi a teplotou.

LS0tDQp0aXRsZTogIsOabG9oYV82Ig0KYXV0aG9yOiAiQmMuIEtyeXN0eW5hIFZhc3lseW5hIg0KZGF0ZTogIk5vdmVtYmVyIDIwMjUiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdGhlbWU6IHVuaXRlZA0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KZWRpdG9yX29wdGlvbnM6DQogIG1hcmtkb3duOg0KICAgIHdyYXA6IDcyDQotLS0NCg0KIyBBbmFsw716YSBtZXRlb3JvbG9naWNrw71jaCB1a2F6b3ZhdGXEvm92DQoNCiMjIMOadm9kIGRvIHByb2Jsw6ltdSBhIHN0YW5vdmVuaWUgaHlwb3TDqXp5DQoNCkNpZcS+b20gYW5hbMO9enkgamUgbW9kZWxvdmHFpSBzdHJlZG7DuiBkZW5uw7ogdGVwbG90dSB2IEJhemlsZWppIChCQVNFTF90ZW1wX21lYW4pIG5hIHrDoWtsYWRlIHZpYWNlcsO9Y2ggbWV0ZW9yb2xvZ2lja8O9Y2ggcHJlbWVubsO9Y2g6IA0KDQotIG9ibGHEjW5vc8WlIChCQVNFTF9jbG91ZF9jb3ZlciksIA0KDQotIHZsaGtvc8WlIChCQVNFTF9odW1pZGl0eSksIA0KDQotIHRsYWsgdnpkdWNodSAoQkFTRUxfcHJlc3N1cmUpLCANCg0KLSBnbG9iw6FsbmUgxb5pYXJlbmllIChCQVNFTF9nbG9iYWxfcmFkaWF0aW9uKSwgDQoNCi0genLDocW+a3kgKEJBU0VMX3ByZWNpcGl0YXRpb24pLCANCg0KLSBzbG5lxI1uw70gc3ZpdCAoQkFTRUxfc3Vuc2hpbmUpIGEgbWluaW3DoWxudSBhIG1heGltw6FsbnUgdGVwbG90dSAoQkFTRUxfdGVtcF9taW4sIEJBU0VMX3RlbXBfbWF4KS4NCg0KUHJhY292bsOhIGh5cG90w6l6YSBwcmVkcG9rbGFkw6EsIMW+ZSB0aWV0byBwcmVtZW5uw6kgdsO9em5hbW5lIG92cGx5dsWIdWrDuiBzdHJlZG7DuiB0ZXBsb3R1IOKAkyBuYXByw61rbGFkIHZ5xaHFoWllIGdsb2LDoWxuZSDFvmlhcmVuaWUgYWxlYm8gc2xuZcSNbsO9IHN2aXQgYnkgbWFsaSB2aWVzxaUgayB2ecWhxaHDrW0gdGVwbG90w6FtLCB6YXRpYcS+IMSNbyB2w6TEjcWhaWEgb2JsYcSNbm9zxaUgbcO0xb5lIHRlcGxvdHUgem5pxb5vdmHFpS4gQ2llxL5vbSBhbmFsw716eSBqZSBvdmVyacWlIHTDunRvIGh5cG90w6l6dSBwb21vY291IGxpbmXDoXJuZWhvIHJlZ3Jlc27DqWhvIG1vZGVsdSwgcG9zw7pkacWlIHbDvXpuYW0gamVkbm90bGl2w71jaCBwcmVtZW5uw71jaCBhIHNrb250cm9sb3ZhxaUsIMSNaSBtb2RlbCBzcMS6xYhhIHByZWRwb2tsYWR5IGxpbmXDoXJuZWogcmVncmVzaWUsIGFrbyBzw7ogbm9ybWFsaXRhIHJlesOtZHXDrSBhIGtvbsWhdGFudG7DvSByb3pwdHlsIChob21vc2tlZGFzdGljaXRhKS4NCg0KTmEgemHEjWlhdGt1IGFuYWzDvXp5IGJ1ZGVtZSBuYWpwcnYgbmHEjcOtdGHFpSBwb3RyZWJuw6kga25pxb5uaWNlLCB2ecSNaXN0w61tZSBwcmFjb3Zuw6kgcHJvc3RyZWRpZSwgbmHEjcOtdGFtZSBzw7pib3Igd2VhdGhlcl9wcmVkaWN0aW9uX2RhdGFzZXQuY3N2LCB2eWJlcmllbWUga8S+w7rEjW92w6kgc3TEunBjZSBhIGRvcGxuw61tZSBjaMO9YmFqw7pjZSBob2Rub3R5IG1lZGnDoW5vbSwgYWJ5IGJvbGkgw7pkYWplIHByaXByYXZlbsOpIG5hIMSPYWzFoWllIHNwcmFjb3ZhbmllLg0KDQojIyBOYcSNw610YW5pZSBrbmnFvm7DrWMNCg0KYGBge3J9DQpsaWJyYXJ5KHpvbykNCmxpYnJhcnkodHNlcmllcykNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShzYW5kd2ljaCkNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShjb3dwbG90KQ0KYGBgDQoNCiMjIFZ5xI1pc3RlbmllIHByYWNvdm7DqWhvIHByb3N0cmVkaWENCg0KYGBge3J9DQpybShsaXN0PWxzKCkpDQpgYGANCg0KIyMgTmHEjcOtdGFuaWUgw7pkYWpvdg0KDQpgYGB7cn0NCnVkYWplIDwtIHJlYWQuY3N2KCJ3ZWF0aGVyX3ByZWRpY3Rpb25fZGF0YXNldC5jc3YiKQ0KYGBgDQoNCiMjIFbDvWJlciBwb3RyZWJuw71jaCBzdMS6cGNvdg0KDQpgYGB7cn0NCndlYXRoZXJfZGF0YSA8LSB1ZGFqZVssIGMoIkJBU0VMX2Nsb3VkX2NvdmVyIiwgIkJBU0VMX2h1bWlkaXR5IiwgIkJBU0VMX3ByZXNzdXJlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICJCQVNFTF9nbG9iYWxfcmFkaWF0aW9uIiwgIkJBU0VMX3ByZWNpcGl0YXRpb24iLCAiQkFTRUxfc3Vuc2hpbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiQkFTRUxfdGVtcF9tZWFuIiwgIkJBU0VMX3RlbXBfbWluIiwgIkJBU0VMX3RlbXBfbWF4IildDQpgYGANCg0KIyMgSW1wdXTDoWNpYSBjaMO9YmFqw7pjaWNoIGhvZG7DtHQgbWVkacOhbm9tDQoNCmBgYHtyfQ0KbWVkaWFuX2hvZG5vdHkgPC0gc2FwcGx5KHdlYXRoZXJfZGF0YSwgbWVkaWFuLCBuYS5ybSA9IFRSVUUpDQp3ZWF0aGVyX2RhdGFfaW1wdXRlZCA8LSB3ZWF0aGVyX2RhdGENCmZvciAoY29sIGluIG5hbWVzKHdlYXRoZXJfZGF0YSkpIHsNCiAgd2VhdGhlcl9kYXRhX2ltcHV0ZWRbW2NvbF1dW2lzLm5hKHdlYXRoZXJfZGF0YVtbY29sXV0pXSA8LSBtZWRpYW5faG9kbm90eVtjb2xdDQp9DQp3ZWF0aGVyX2RhdGEgPC0gd2VhdGhlcl9kYXRhX2ltcHV0ZWQNCmBgYA0KDQojIyBCb3hwbG90eSBwcmUgdml6dcOhbG51IGtvbnRyb2x1DQoNClBvc2t5dG7DuiBuw6FtIHLDvWNobHkgcHJlaMS+YWQgbyB2YXJpYWJpbGl0ZSBhIHJvenNhaHUgZMOhdCBwcmVkIHNhbW90bsO9bSBtb2RlbG92YW7DrW0uDQoNCg0KYGBge3J9DQpudW1fcGxvdHMgPC0gbGVuZ3RoKG5hbWVzKHdlYXRoZXJfZGF0YSkpDQpwYXIobWZyb3cgPSBjKDMsIDMpKQ0KcGFyKG1hciA9IGMoNCwgNCwgMiwgMSkpDQpmb3IgKGNvbCBpbiBuYW1lcyh3ZWF0aGVyX2RhdGEpKSB7DQogIGJveHBsb3Qod2VhdGhlcl9kYXRhW1tjb2xdXSwgbWFpbiA9IGNvbCwgeGxhYiA9ICJIb2Rub3RhIiwgY29sID0gImxpZ2h0Ymx1ZSIpDQp9DQpwYXIobWZyb3cgPSBjKDEsIDEpKQ0KYGBgDQoNCiMjIExpbmXDoXJuYSByZWdyZXNpYTogesOhdmlzbMOhIHByZW1lbm7DoSBCQVNFTF90ZW1wX21lYW4NCg0KYGBge3J9DQptb2RlbCA8LSBsbShCQVNFTF90ZW1wX21lYW4gfiBCQVNFTF9jbG91ZF9jb3ZlciArIEJBU0VMX2h1bWlkaXR5ICsgQkFTRUxfcHJlc3N1cmUgKw0KICAgICAgICAgICAgICBCQVNFTF9nbG9iYWxfcmFkaWF0aW9uICsgQkFTRUxfcHJlY2lwaXRhdGlvbiArIEJBU0VMX3N1bnNoaW5lICsNCiAgICAgICAgICAgICAgQkFTRUxfdGVtcF9taW4gKyBCQVNFTF90ZW1wX21heCwgZGF0YSA9IHdlYXRoZXJfZGF0YSkNCnN1bW1hcnkobW9kZWwpDQpgYGANClByZSBsaW5lw6FybnUgcmVncmVzaXUgcyBCQVNFTF90ZW1wX21lYW4gYWtvIHrDoXZpc2xvdSBwcmVtZW5ub3UgbW9kZWwgdWthenVqZSB2ZcS+bWkgZG9icsO6IHpob2R5IHMgZMOhdGFtaS4gS29lZmljaWVudHkgbmF6bmHEjXVqw7osIMW+ZSBuaWVrdG9yw6kgcHJlbWVubsOpIG1hasO6IHNpbG7DvSB2cGx5diBuYSBzdHJlZG7DuiB0ZXBsb3R1Lg0KDQpOYWpkw7RsZcW+aXRlasWhaWUgZmFrdG9yeSBzw7o6DQoNCi0gTWluaW3DoWxuYSBhIG1heGltw6FsbmEgdGVwbG90YSDigJMgaGxhdm7DrSBwcmVkaWt0b3JpIHMgZXh0csOpbW5lIHZ5c29rw71taSB0LWhvZG5vdGFtaSBhIHAtaG9kbm90YW1pIDwgMmUtMTYuDQoNCi0gVmxoa29zxaUg4oCTIHbDvXJhem5lIHpuacW+dWplIHN0cmVkbsO6IHRlcGxvdHUgKC0xLDUxLCB0ID0gLTExLDgpLg0KDQotIE9ibGHEjW5vc8WlIGEgZ2xvYsOhbG5lIMW+aWFyZW5pZSDigJMgbWllcm55IHBveml0w612bnkgZWZla3QgYSDFoXRhdGlzdGlja3kgdsO9em5hbW7DqS4NCg0KUHJlbWVubsOpIGFrbyB0bGFrLCB6csOhxb5reSBhbGVibyBzbG5lxI1uw70gc3ZpdCBzYSB2IHRvbXRvIG1vZGVsaSBuZXByZWphdmlsaSBha28gdsO9em5hbW7DqS4gDQoNClJlemlkdcOhIHPDuiB2w6TEjcWhaW5vdSBtYWzDqSAobWluID0gLTIsNjk4NiwgbWF4ID0gMiw2MjA2LCDFoXRhbmRhcmRuw6EgY2h5YmEgPSAwLDU0NzUpLCDEjW8gbmF6bmHEjXVqZSBkb2Jyw7ogcHJlc25vc8WlIHByZWRpa2NpZS4gDQoNCkhvZG5vdGEgUi1zcXVhcmVkID0gMCw5OTQ2IHVrYXp1amUsIMW+ZSBtb2RlbCB2eXN2ZXTEvnVqZSB0YWttZXIgdsWhZXRrdSB2YXJpYWJpbGl0dSBzdHJlZG5laiB0ZXBsb3R5LCBhIHZ5c29rw6EgRi1zdGF0aXN0aWthIHBvdHZyZHp1amUgY2Vsa292w7ogxaF0YXRpc3RpY2vDuiB2w716bmFtbm9zxaUgbW9kZWx1Lg0KDQpDZWxrb3ZvIG1vZGVsIHZlxL5taSBkb2JyZSB6YWNoeXTDoXZhIHZ6xaVhaHkgbWVkemkgbWV0ZW9yb2xvZ2lja8O9bWkgcHJlbWVubsO9bWkgYSBzdHJlZG5vdSB0ZXBsb3RvdSB2IEJhemlsZWppLCBwcmnEjW9tIG5hamTDtGxlxb5pdGVqxaFpZSBmYWt0b3J5IHPDuiBqYXNuZSBpZGVudGlmaWtvdmF0ZcS+bsOpIGEgem9kcG92ZWRhasO6IG/EjWFrw6F2YW7DqW11IGZ5emlrw6FsbmVtdSBrb250ZXh0dS4NCg0KIyMgRGlhZ25vc3RpY2vDqSBncmFmeQ0KDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMoMiwgMikpDQpwbG90KG1vZGVsKQ0KcGFyKG1mcm93ID0gYygxLCAxKSkNCmBgYA0KIyMjIyBSZXNpZHVhbHMgdnMgRml0dGVkDQoNCi0gw5rEjWVsOiBPdmVyacWlLCDEjWkgbcOhIGxpbmXDoXJueSB2esWlYWggbWVkemkgcHJlbWVubsO9bWkgYSDEjWkgbcOhIHJlemlkdcOhIGtvbsWhdGFudG7DvSByb3pwdHlsLg0KDQotIE5hIHRvbXRvIGdyYWZlIGplIMSNZXJ2ZW7DoSDEjWlhcmEgaWRlw6FsbmUgcm92bsOhIGEgYm9keSBzw7ogbsOhaG9kbmUgcm96bWllc3RuZW7DqSBva29sbyBuZWouIFRvIHpuYW1lbsOhLCDFvmUgcHJlZHBva2xhZCBsaW5lYXJpdHkgamUgc3BsbmVuw70g4oCTIG1lZHppIHByZW1lbm7DvW1pIGV4aXN0dWplIHZob2Ruw70gbGluZcOhcm55IHZ6xaVhaCBhIG1vZGVsIGplIGRvYnJlIMWhcGVjaWZpa292YW7DvS4NCg0KIyMjIyBRLVEgUmVzaWR1YWxzDQoNCi0gw5rEjWVsOiBPdmVyacWlLCDEjWkgc8O6IHJlemlkdcOhIG5vcm3DoWxuZSByb3pkZWxlbsOpLg0KDQotIE5hIHRvbXRvIGdyYWZlIGJvZHkgdGFrbWVyIGRva29uYWxlIHNsZWR1asO6IGRpYWdvbsOhbG51IMSNaWFydS4gVG8gem5hbWVuw6EsIMW+ZSByZXppZHXDoSBzw7ogbm9ybcOhbG5lIHJvemRlbGVuw6kuIFRlbnRvIGTDtGxlxb5pdMO9IHByZWRwb2tsYWQgcHJlIMWhdGF0aXN0aWNrw6kgdGVzdG92YW5pZSBqZSBzcGxuZW7DvS4NCg0KIyMjIyBTY2FsZS1Mb2NhdGlvbg0KDQotIMOaxI1lbDogVGllxb4gb3ZlcnVqZSBwcmVkcG9rbGFkIGhvbW9za2VkYXN0aWNpdHkgKGtvbsWhdGFudG7DvSByb3pwdHlsIHJlemlkdcOtKS4gSmUgdG8gcG9kb2Juw6kgYWtvIHBydsO9IGdyYWYsIGFsZSB6b2JyYXp1amUgb2Rtb2NuaW51IMWhdGFuZGFyZGl6b3ZhbsO9Y2ggcmV6aWR1w60uDQoNCi0gTmEgdG9tdG8gZ3JhZmUgc8O6IGJvZHkgdmXEvm1pIHJvesWlYWhhbsOpIGEgb2RjaMOhZHphasO6IG9kIMSNaWFyeSwga3RvcsOhIG5pZSBqZSBkb2tvbmFsZSByb3Zuw6EuIFRvIHpuYW1lbsOhLCDFvmUgZG9jaMOhZHphIGsgaGV0ZXJvc2tlZGFzdGljaXRlIOKAkyByb3pwdHlsIHJlemlkdcOtIG5pZSBqZSBrb27FoXRhbnRuw70uIFRvIGplIGhsYXZuw70gcHJvYmzDqW0gbW9kZWx1LCBrdG9yw70gbcO0xb5lIHNww7Rzb2JpxaUgbmVzcG/EvmFobGl2b3PFpSDFoXRhdGlzdGlja8O9Y2ggdGVzdG92Lg0KDQojIyMjIFJlc2lkdWFscyB2cyBMZXZlcmFnZQ0KDQotIMOaxI1lbDogSWRlbnRpZmlrb3ZhxaUgdnBseXZuw6kgYm9keSAob3V0bGllcnkpLCBrdG9yw6kgbcO0xb51IG5lw7ptZXJuZSBvdnBseXbFiG92YcWlIHbDvXNsZWRreSByZWdyZXNpZS4NCg0KLSBOYSB0b210byBncmFmZSBzw7ogYm9keSBzw7pzdHJlZGVuw6kgdiDEvmF2ZWogxI1hc3RpIGEgxI1lcnZlbsOhIMSNaWFyYSBzYSBtaWVybmUgdmxuw60uIFRvIHpuYW1lbsOhLCDFvmUgdsOkxI3FoWluYSBwb3pvcm92YW7DrSBtw6EgbsOtemt1IHZwbHl2bm9zxaUsIMSNbyBqZSBkb2Jyw6ksIG5vIG5pZWt0b3LDqSBib2R5IG3DtMW+dSBtaWVybmUgb3ZwbHl2xYhvdmHFpSBtb2RlbC4gTmV2aWRpYSBzYSB2xaFhayBleHRyw6ltbmUgdnBseXZuw6kgb2TEvmFobMOpIGhvZG5vdHkuDQoNCiMjIEphcnF1ZSBCZXJhIHRlc3QgbmEgbm9ybWFsaXR1IHJlesOtZHXDrQ0KDQpgYGB7cn0NCnJlc2lkdWFscyA8LSByZXNpZHVhbHMobW9kZWwpDQpqYl90ZXN0IDwtIGphcnF1ZS5iZXJhLnRlc3QocmVzaWR1YWxzKQ0KamJfdGVzdA0KYGBgDQpUZXN0IEphcnF1ZS1CZXJhIHNtZSBwb3XFvmlsaSBuYSBvdmVyZW5pZSwgxI1pIHPDuiByZXppZHXDoSBtb2RlbHUgbm9ybcOhbG5lIHJvemRlbGVuw6kuIFRlbnRvIHRlc3Qgc2vDum1hIHJvemRpZWwgbWVkemkgdHZhcm9tIHJvemRlbGVuaWEgcmV6aWR1w60gYSB0ZW9yZXRpY2vDvW0gbm9ybcOhbG55bSByb3pkZWxlbsOtbSBwb21vY291IGR2b2NoIHVrYXpvdmF0ZcS+b3Yg4oCTIMWhaWttb3N0aSAoc2tld25lc3MpIGEgxaFwaWNhdG9zdGkgKGt1cnRvc2lzKS4NCg0KVsO9c2xlZGt5Og0KDQotIFgtc3F1YXJlZCA9IDExMy40OSwNCg0KLSBkZiA9IDIsDQoNCi0gcC1ob2Rub3RhIDwgMi4yZS0xNi4NCg0KVG8gem5hbWVuw6EsIMW+ZSB0ZXN0IHphbWlldGEgbnVsb3bDuiBoeXBvdMOpenUgbyBub3Jtw6Fsbm9tIHJvemRlbGVuw60gcmV6aWR1w60uIE5hcHJpZWsgdG9tdSwgxb5lIFEtUSBncmFmIHZpenXDoWxuZSBuYXpuYcSNb3ZhbCB0YWttZXIgbm9ybcOhbG5lIHJvemRlbGVuaWUsIHRlc3QgdWthenVqZSwgxb5lIGV4aXN0dWrDuiBkcm9ibsOpIG9kY2jDvWxreSDigJQgcHJhdmRlcG9kb2JuZSBzcMO0c29iZW7DqSB2ZcS+a8O9bSBwb8SNdG9tIHBvem9yb3ZhbsOtLCBrZGUgYWogbWFsw6kgcm96ZGllbHkgdmVkw7ogayDFoXRhdGlzdGlja2VqIHbDvXpuYW1ub3N0aS4NCg0KUmV6aWR1w6EgbmllIHPDuiDDunBsbmUgbm9ybcOhbG5lIHJvemRlbGVuw6ksIGhvY2kgb2RjaMO9bGt5IG5pZSBzw7ogdsO9cmF6bsOpIGEgbW9kZWwgem9zdMOhdmEgc3BvxL5haGxpdsO9IG5hIHByZWRpa8SNbsOpIMO6xI1lbHkuDQoNCiMjIFRlc3QgbmEgb2TEvmFobMOpIGhvZG5vdHkNCg0KYGBge3J9DQpvdXRsaWVyX3Rlc3QgPC0gb3V0bGllclRlc3QobW9kZWwpDQpvdXRsaWVyX3Rlc3QNCmBgYA0KUHJpIHRlc3RlIG5hIG9kxL5haGzDqSBob2Rub3R5IChvdXRsaWVyeSkgc21lIHBvdcW+aWxpIMWhdGFuZGFyZGl6b3ZhbsOpIHJlemlkdcOhIChyc3R1ZGVudCksIGFieSBzbWUgaWRlbnRpZmlrb3ZhbGkgcG96b3JvdmFuaWEgcyBleHRyw6ltbnltaSBob2Rub3RhbWksIGt0b3LDqSBtw7TFvnUgb3ZwbHl2bmnFpSBzdGFiaWxpdHUgbW9kZWx1Lg0KDQpOYWp2w71yYXpuZWrFoWllIG9kxL5haGzDqSBob2Rub3R5Og0KDQotIHBvem9yb3ZhbmllIDE4MTUgKHJzdHVkZW50ID0gLTQuOTYsIEJvbmZlcnJvbmkgcCA9IDAuMDAyNyksDQoNCi0gcG96b3JvdmFuaWUgNzEzIChyc3R1ZGVudCA9IDQuODEsIEJvbmZlcnJvbmkgcCA9IDAuMDA1NiksDQoNCi0gcG96b3JvdmFuaWUgMTI3MyAocnN0dWRlbnQgPSAtNC4zOCwgQm9uZmVycm9uaSBwID0gMC4wNDU0KS4NCg0KVGlldG8gaG9kbm90eSBwcmVrcmHEjXVqw7ogYmXFvm7DvSBsaW1pdCDCsTMsIMSNbyB6bmFtZW7DoSwgxb5lIGlkZSBvIHBvdGVuY2nDoWxuZSBwcm9ibGVtYXRpY2vDqSBwb3pvcm92YW5pYS4NCg0KWsOhdmVyb20gbW/Fvm5vIHBvdmVkYcWlLCDFvmUgbmlla2/EvmtvIHBvem9yb3ZhbsOtIG3DoSB2eXNva8O9IHZwbHl2IGEgbcO0xb51IG1pZXJuZSBza3Jlc8S+b3ZhxaUgb2RoYWR5IHBhcmFtZXRyb3YNCg0KIyMgR3JhZnkgcHJlIGtvbnRyb2x1IGhldGVyb3NrZWRhc3RpY2l0eQ0KDQpgYGB7cn0NCnAxIDwtIGdncGxvdCh3ZWF0aGVyX2RhdGEsIGFlcyh4ID0gQkFTRUxfcHJlc3N1cmUsIHkgPSByZXNpZChtb2RlbCleMikpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJkYXJrcmVkIikgKw0KICBsYWJzKHggPSAiQkFTRUxfcHJlc3N1cmUiLCB5ID0gIsWgdHZvcmNlIHJlesOtZHXDrSIsIHRpdGxlID0gIlJlesOtZHXDoV4yIHZzIFRsYWsiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpwMiA8LSBnZ3Bsb3Qod2VhdGhlcl9kYXRhLCBhZXMoeCA9IEJBU0VMX2h1bWlkaXR5LCB5ID0gcmVzaWQobW9kZWwpXjIpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAiZGFya3JlZCIpICsNCiAgbGFicyh4ID0gIkJBU0VMX2h1bWlkaXR5IiwgeSA9ICLFoHR2b3JjZSByZXrDrWR1w60iLCB0aXRsZSA9ICJSZXrDrWR1w6FeMiB2cyBWbGhrb3PFpSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCnBsb3RfZ3JpZChwMSwgcDIpDQpgYGANClRpZXRvIGdyYWZ5IHpvYnJhenVqw7ogdnrFpWFoIG1lZHppIMWhdHZvcmNhbWkgcmV6w61kdcOtIGEgdnlicmFuw71taSBuZXrDoXZpc2zDvW1pIHByZW1lbm7DvW1pICh0bGFrb20gYSB2bGhrb3PFpW91KS4gSWNoIGNpZcS+b20gamUgemlzdGnFpSwgxI1pIHNhIHJvenB0eWwgcmV6w61kdcOtIG1lbsOtIHYgesOhdmlzbG9zdGkgb2QgaG9kbsO0dCB0w71jaHRvIHByZW1lbm7DvWNoIOKAkyB0ZWRhIMSNaSBzYSB2IG1vZGVsaSBwcmVqYXZ1amUgaGV0ZXJvc2tlZGFzdGljaXRhLg0KDQojIyMjIFJlesOtZHXDocKyIHZzIFRsYWsNCg0KLSBWw6TEjcWhaW5hIGJvZG92IHNhIHPDunN0cmXEj3VqZSB2IHNwb2RuZWogxI1hc3RpIGdyYWZ1LCBwcmV2YcW+bmUgbWVkemkgaG9kbm90YW1pIDAgYcW+IDIgbmEgb3NpIFkuDQoNCi0gxIxlcnZlbsOhIMSNaWFyYSBqZSBsZW4gbWllcm5lIHp2bG5lbsOhIOKAkyBuYSBuaWVrdG9yw71jaCBtaWVzdGFjaCBzYSBuZXBhdHJuZSBkdsOtaGEgYSBvcMOkxaUga2xlc8OhLCBubyBjZWxrb3ZvIHpvc3TDoXZhIHBvbWVybmUgcm92bsOhLg0KDQotIFRha8O9dG8gcHJpZWJlaCBuYXpuYcSNdWplLCDFvmUgcm96cHR5bCByZXrDrWR1w60gamUgcmVsYXTDrXZuZSBzdGFiaWxuw70gYSB2w71yYXpuw6EgaGV0ZXJvc2tlZGFzdGljaXRhIHNhIG5lcHJlamF2dWplLg0KDQojIyMjIFJlesOtZHXDocKyIHZzIFZsaGtvc8WlDQoNCi0gQm9keSBzw7ogcm96bG/FvmVuw6kgcG9tZXJuZSByb3Zub21lcm5lLCB2w6TEjcWhaW5hIHogbmljaCBzYSBuYWNow6FkemEgdiBzcG9kbmVqIMSNYXN0aSBncmFmdS4NCg0KLSDEjGVydmVuw6EgxI1pYXJhIGplIHRha21lciByb3Zuw6EsIGJleiB2w71yYXpuw6lobyB6YWtyaXZlbmlhLCDEjW8gc3ZlZMSNw60gbyBrb27FoXRhbnRub20gcm96cHR5bGUgcmV6w61kdcOtLg0KDQotIE5pZWtvxL5rbyBib2RvdiBzYSBzw61jZSBvZGNoecS+dWplIHNtZXJvbSBuYWhvciwgYWxlIHRpZXRvIG9kY2jDvWxreSBzw7ogbWluaW3DoWxuZSBhIG5lbWFqw7ogesOhc2FkbsO9IHZwbHl2IG5hIHN0YWJpbGl0dSByb3pwdHlsdS4NCg0KTmEgesOha2xhZGUgdMO9Y2h0byBncmFmb3YgbcO0xb5lbWUga29uxaF0YXRvdmHFpSwgxb5lIG1vZGVsIG5ldnlrYXp1amUgdsO9cmF6bsOpIHpuw6Fta3kgaGV0ZXJvc2tlZGFzdGljaXR5IOKAkyByb3pwdHlsIGNow71iIGplIHJlbGF0w612bmUga29uxaF0YW50bsO9IG5hcHJpZcSNIHLDtHpueW1pIGhvZG5vdGFtaSB0bGFrdSBhaiB2bGhrb3N0aS4NCg0KIyMgQnJldXNjaC1QYWdhbiB0ZXN0IG5hIGhldGVyb3NrZWRhc3RpY2l0dQ0KDQpUZW50byB0ZXN0IHNhIHBvdcW+w612YSBuYSBmb3Jtw6FsbmUgb3ZlcmVuaWUsIMSNaSBqZSByb3pwdHlsIHJlesOtZHXDrSBrb27FoXRhbnRuw70gKGhvbW9za2VkYXN0aWNpdGEpLCBhbGVibyBzYSBtZW7DrSB2IHrDoXZpc2xvc3RpIG9kIGhvZG7DtHQgbmV6w6F2aXNsw71jaCBwcmVtZW5uw71jaCAoaGV0ZXJvc2tlZGFzdGljaXRhKS4NCg0KYGBge3J9DQpicHRlc3QobW9kZWwpDQpgYGANCktlxI/FvmUgcC1ob2Rub3RhIGplIHbDvXJhem5lIG1lbsWhaWEgYWtvIDAuMDUsIHphbWlldGFtZSBudWxvdsO6IGh5cG90w6l6dSBvIGhvbW9za2VkYXN0aWNpdGUuIFRvIHpuYW1lbsOhLCDFvmUgcm96cHR5bCByZXrDrWR1w60gbmllIGplIGtvbsWhdGFudG7DvSBhIHYgbW9kZWxpIHNhIHZ5c2t5dHVqZSBoZXRlcm9za2VkYXN0aWNpdGEuDQoNCkFqIG5hcHJpZWsgdG9tdSwgxb5lIHZpenXDoWxuYSBrb250cm9sYSBncmFmb3YgbmV1a8OhemFsYSB2w71yYXpuw6kgcG9ydcWhZW5pZSBwcmVkcG9rbGFkb3YsIMWhdGF0aXN0aWNrw70gdGVzdCBwb3R2cmR6dWplLCDFvmUgdmFyaWFiaWxpdGEgcmV6w61kdcOtIHNhIG1lbsOtIHYgesOhdmlzbG9zdGkgb2Qgbmlla3RvcsO9Y2ggcHJlbWVubsO9Y2guDQoNCk1vZGVsIG5lc3DEusWIYSBwcmVkcG9rbGFkIGtvbsWhdGFudG7DqWhvIHJvenB0eWx1IGNow71iLiBUZW50byBwcm9ibMOpbSBtw7TFvmVtZSByaWXFoWnFpSBuYXByw61rbGFkIHBvdcW+aXTDrW0gcm9idXN0bsO9Y2ggxaF0YW5kYXJkbsO9Y2ggY2jDvWIsIGt0b3LDqSBrb3JpZ3Vqw7ogZMO0c2xlZGt5IGhldGVyb3NrZWRhc3RpY2l0eSBiZXogbnV0bm9zdGkgbWVuacWlIHNhbW90bsO9IG1vZGVsLg0KDQpgYGB7cn0NCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShzYW5kd2ljaCkNCmBgYA0KDQojIyBWw71wb8SNZXQgcm9idXN0bsO9Y2ggxaF0YW5kYXJkbsO9Y2ggY2jDvWINCg0KYGBge3J9DQpyb2J1c3Rfc3VtbWFyeSA8LSBjb2VmdGVzdChtb2RlbCwgdmNvdiA9IHZjb3ZIQyhtb2RlbCwgdHlwZSA9ICJIQzEiKSkNCnJvYnVzdF9zdW1tYXJ5DQpgYGANClogdGFidcS+a3kgdsO9c2xlZGtvdiB2eXBsw712YToNCg0KLSBLb2VmaWNpZW50eSBvZGhhZG51dMOpIHDDtHZvZG7DvW0gbW9kZWxvbSBzYSBuZW1lbmlhLCB0YWvFvmUgdmXEvmtvc8WlIGEgc21lciB2cGx5dnUgamVkbm90bGl2w71jaCBwcmVtZW5uw71jaCB6b3N0w6F2YWrDuiByb3ZuYWvDqSwNCg0KLSDFoHRhbmRhcmRuw6kgY2h5Ynkgc2EgbWllcm5lIHVwcmF2aWxpLCDEjW8gb3ZwbHl2bmlsbyBob2Rub3R5IHQgYSBwLWhvZG5vdHkuDQoNCk5hanNpbG5lasWhaWUgYSDFoXRhdGlzdGlja3kgdsO9em5hbW7DqSBwcmVtZW5uw6kgem9zdMOhdmFqw7o6DQoNCi0gTWluaW3DoWxuYSBhIG1heGltw6FsbmEgdGVwbG90YSAocCA8IDIuMmUtMTYsIGV4dHLDqW1uZSB2eXNva8OpIHQtaG9kbm90eSksDQoNCi0gVmxoa29zxaUgKHAgPCAyLjJlLTE2LCBuZWdhdMOtdm55IGVmZWt0KSwNCg0KLSBPYmxhxI1ub3PFpSBhIGdsb2LDoWxuZSDFvmlhcmVuaWUgKHAgPCAwLjAxKS4NCg0KUHJlbWVubsOpIGFrbyB0bGFrLCB6csOhxb5reSBhIHNsbmXEjW7DvSBzdml0IHNhIHN0w6FsZSBuZXByZWphdmlsaSBha28gdsO9em5hbW7DqSwgaG9jaSB0bGFrIGplIHRlcmF6IG1pZXJuZSBibGnFvsWhaWUgayBocmFuaWNpIHbDvXpuYW1ub3N0aSAocCA9IDAuMDc1KS4NCg0KUG91xb5pdGllIHJvYnVzdG7DvWNoIMWhdGFuZGFyZG7DvWNoIGNow71iIHphYmV6cGXEjWlsbyBzcG/EvmFobGl2ZWrFoWl1IGludGVycHJldMOhY2l1IG1vZGVsdSBhaiBuYXByaWVrIHByw610b21ub3N0aSBoZXRlcm9za2VkYXN0aWNpdHkuIE1vZGVsIG5hxI9hbGVqIHZ5c3ZldMS+dWplIHbDpMSNxaFpbnUgdmFyaWFiaWxpdHkgc3RyZWRuZWogdGVwbG90eSBhIGTDtGxlxb5pdMOpIHZ6xaVhaHkgbWVkemkgcHJlbWVubsO9bWkgc8O6IGphc25lIGlkZW50aWZpa292YXRlxL5uw6kuDQoNCiMgWsOhdmVyDQoNCk5hIHrDoWtsYWRlIHZ5a29uYW5laiBhbmFsw716eSBtw7TFvmVtZSBrb27FoXRhdG92YcWlLCDFvmUgbW9kZWwgc3RyZWRuZWogdGVwbG90eSB2IEJhemlsZWppIHZlxL5taSBkb2JyZSB2eXN2ZXTEvnVqZSB2w6TEjcWhaW51IHZhcmlhYmlsaXR5IGTDoXQuIFJvYnVzdG7DqSDFoXRhbmRhcmRuw6kgY2h5YnkgemFiZXpwZcSNaWxpIHNwb8S+YWhsaXZlasWhaXUgaW5mZXJlbmNpdSBhaiBuYXByaWVrIHByw610b21ub3N0aSBoZXRlcm9za2VkYXN0aWNpdHkuIEvEvsO6xI1vdsOpIHByZW1lbm7DqSwgYWtvIG1pbmltw6FsbmEgYSBtYXhpbcOhbG5hIHRlcGxvdGEsIHZsaGtvc8WlLCBvYmxhxI1ub3PFpSBhIGdsb2LDoWxuZSDFvmlhcmVuaWUsIG1hasO6IHbDvXJhem7DvSBhIMWhdGF0aXN0aWNreSB2w716bmFtbsO9IHZwbHl2IG5hIHN0cmVkbsO6IHRlcGxvdHUuIENlbGtvdm8gbW9kZWwgcG9za3l0dWplIHByZXNuw70gYSBpbnRlcnByZXRvdmF0ZcS+bsO9IHBvaMS+YWQgbmEgdnrFpWFoeSBtZWR6aSBtZXRlb3JvbG9naWNrw71taSBmYWt0b3JtaSBhIHRlcGxvdG91Lg0K