S využitím databázy Databaza.csv, ktorá obsahuje
počty obyvateľov slovenských obcí podľa okresu a mesiaca v roku
2024.
Pri ďalšej práci budeme používať knižnice
library(zoo)
library(tseries)
library(lmtest)
library(sandwich)
library(car)
library(dplyr)
library(tidyr)
rm(list = ls())
1. Úvod a údaje
Údaje o počte obyvateľov sú uložené v súbore
Databaza.csv.
Každý riadok predstavuje jednu obec, stĺpce:
Okres – názov okresu,
Obec – názov obce,
2024M01 … 2024M12 – počet obyvateľov v
danom mesiaci roku 2024.
Súbor predpokladáme uložený v podpriečinku
udaje v pracovnom priečinku (aby boli
údaje oddelené od zvyšku projektu).
1.1 Úvod do problému, stanovenie hypotéz
Rozhodli sme sa sledovať vývoj počtu obyvateľov v
čase vo vybranej obci.
Konkrétne budeme modelovať mesačný počet obyvateľov v
obci
„Bratislava - mestská časť Staré Mesto“ v závislosti od
času (index mesiaca).
Označme:
- \(Y_t\): počet obyvateľov v mesiaci
\(t\),
- \(t\): časový index (1 = január
2024, 2 = február 2024, …, 12 = december 2024).
Naša pracovná hypotéza:
- predpokladáme, že počet obyvateľov sa v priebehu roka mierne
mení (napr. vplyvom migrácie),
- očakávame hladký vývoj v čase, teda silnú
autokoreláciu, t. j. počet obyvateľov v mesiaci \(t\) je veľmi podobný počtu v mesiaci \(t-1\),
- očakávame kladný trendový koeficient (\(\beta_1 > 0\)), ak počet obyvateľov má
mierne rastúcu tendenciu.
1.2 Príprava databázy, úprava údajov
Databáza je v tzv. „wide“ tvare (mesiace v stĺpcoch). Pre časovú
analýzu jednej obce je výhodnejšie mať údaje v „long“ tvare: každý
riadok = jedna obec v jednom mesiaci.
Najskôr načítame údaje, potom vyberieme jednu obec a preklopíme
mesačné stĺpce do časového radu.
# načítanie databázy
udaje <- read.csv("Databaza.csv",
sep = ";",
dec = ",",
header = TRUE,
check.names = FALSE)
# vyberieme jednu konkrétnu obec (možeš zmeniť na inú)
udajeMesto <- udaje[udaje$Obec == "Bratislava - mestská časť Staré Mesto", ]
# preklopenie z wide na long (mesiace do riadkov)
udajeMesto_long <- udajeMesto %>%
pivot_longer(
cols = dplyr::starts_with("2024M"),
names_to = "RokMesiac",
values_to = "Pocet_obyvatelov"
) %>%
arrange(RokMesiac) %>%
mutate(
Rok = as.numeric(substr(RokMesiac, 1, 4)),
Mes = as.numeric(substr(RokMesiac, 6, 7)),
Time = dplyr::row_number() # 1 = január, 12 = december
)
udajeMesto_long
2. Lineárna regresia v základnom tvare
Ide o odhad rovnice
\[
\text{Pocet\_obyvatelov}_t = \beta_0 + \beta_1 \text{Time}_t + e_t,
\]
kde:
- \(\text{Pocet\_obyvatelov}_t\) –
počet obyvateľov vo vybranom mesiaci,
- \(\text{Time}_t\) – index mesiaca
(1–12),
- \(e_t\) – náhodná zložka
(rezíduum).
library(ggplot2)
# lineárny trendový model
model <- lm(Pocet_obyvatelov ~ Time, data = udajeMesto_long)
summary(model)
Call:
lm(formula = Pocet_obyvatelov ~ Time, data = udajeMesto_long)
Residuals:
Min 1Q Median 3Q Max
-26.232 -12.214 1.946 12.539 23.684
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 47339.47 10.96 4318.14 < 2e-16 ***
Time 24.44 1.49 16.41 1.47e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 17.81 on 10 degrees of freedom
Multiple R-squared: 0.9642, Adjusted R-squared: 0.9606
F-statistic: 269.2 on 1 and 10 DF, p-value: 1.472e-08
3. Autokorelácia rezíduí
V tejto časti sa pozrieme na ďalší dôležitý predpoklad klasického
lineárneho regresného modelu – nezávislosť rezíduí. V
časových radoch (ako je náš mesačný počet obyvateľov) sa často stáva, že
chyba v čase \(t\) je systematicky
spätá s chybou v čase \(t-1\), čo
nazývame autokoreláciou rezíduí.
3.1 Čo je autokorelácia rezíduí?
Autokorelácia rezíduí je situácia, keď platí:
\[
\operatorname{Corr}(e_t, e_{t-k}) \neq 0 \quad \text{pre niektoré } k
\neq 0.
\]
Najčastejšie sa skúma autokorelácia prvého rádu:
\[
e_t = \rho e_{t-1} + \nu_t,\quad |\rho| < 1.
\]
3.2 Dôsledky autokorelácie rezíduí
- odhady koeficientov \(\hat{\beta}\)
sú nestranné,
- ale neefektívne,
- štandardné chyby sú skreslené (často podhodnotené), teda p-hodnoty
sa javia menšie,
- t- a F-testy sú potom skreslené.
3.3 Detekcia autokorelácie
ACF graf (Autocorrelation Function)
Táto funkcia priraďuje odhad korelácie, ktorá je medzi jednotlivými
rezíduami v aktuálnom období a období posunutom (Lag) o \(k\) období späť.
acf(res, lag.max = 4, main = "Autokorelačná funkcia rezíduí")

Na tomto grafe je modrou prerušovanou čiarou vyjadrený aj 95 %
interval spoľahlivosti pre hodnotu autokorelačného koeficientu s
príslušným posunom. Ak sa niektorý stĺpec nachádza mimo tohto pásma,
naznačuje to štatisticky významnú autokoreláciu pri
danom posune.
Durbin–Watsonov test
Durbin–Watsonov koeficient (DW) je vypočítaný z rezíduí podľa
vzorca
\[
DW = \frac{\sum_{t=2}^{n} (e_t - e_{t-1})^{2}}{\sum_{t=1}^{n} e_t^{2}}
\]
kde \(n\) je počet pozorovaní. Medzi
koeficientom autokorelácie dvoch susedných rezíduí a DW platí približný
vzťah
\[
\hat{\rho} \approx 1 - \frac{DW}{2}.
\]
Hodnoty:
- blízke nule → silná pozitívna
autokorelácia,
- blízke 4 → silná negatívna
autokorelácia,
- okolo 2 → žiadny výrazný problém s
autokoreláciou.
V praxi sa často používa intuitívne pravidlo: ak sa DW nachádza v
intervale približne 1,8 až 2,2, problém autokorelácie
väčšinou nepovažujeme za vážny.
library(lmtest)
dwtest(model)
Durbin-Watson test
data: model
DW = 2.4468, p-value = 0.6766
alternative hypothesis: true autocorrelation is greater than 0
DW test má isté obmedzenia – regresory nesmú byť časovo posunuté a
nesmú obsahovať oneskorené pozorovania vysvetľovanej veličiny ako
regresory. Tieto obmedzenia neplatia pre Breusch–Godfreyov test.
Breusch–Godfreyov test (BG test)
Čo test testuje
BG test je formálnym testom autokorelácie (sériovej
korelácie) rezíduí:
\[
u_t = \rho_1 u_{t-1} + \rho_2 u_{t-2} + \cdots + \rho_p u_{t-p} +
\varepsilon_t.
\]
Testuje, či sú rezíduá korelované v čase až do rádu \(p\), čo je typické pre časové rady.
Na rozdiel od DW testu:
- testuje autokoreláciu s vyšším posunom (lag 1, 2,
3, …),
- funguje aj pri modeloch s oneskorenou vysvetľovanou
premennou ako regresorom,
- pracuje s nekonštantnými regresormi (trend, dummy premenné
atď.).
Hypotézy
Pre test autokorelácie až do rádu \(p\):
Ako funguje BG test
- Odhadneme pôvodnú regresiu (u nás trendový model) a získame rezíduá
\(e_t\).
- Spustíme pomocnú regresiu: \[
e_t
= \alpha_0 + \alpha_1 x_{1t} + \cdots + \alpha_k x_{kt}
+ \rho_1 e_{t-1} + \cdots + \rho_p e_{t-p} + v_t,
\] kde \(x_{jt}\) sú pôvodné
regresory.
- Z tejto regresie vypočítame: \[
\text{BG} = (n - p) R^2_{\text{aux}}
\]
- Pod \(H_0\) platí približne: \[
\text{BG} \sim \chi^2_p.
\]
Interpretácia
- Veľká hodnota testovej štatistiky BG (malá
p-hodnota) → zamietame \(H_0\)
→ autokorelácia prítomná.
- Malá hodnota BG (veľká p-hodnota) → nezamietneme
\(H_0\) → nie je dôkaz
autokorelácie.
Praktický výpočet v R
Breusch-Godfrey test for serial correlation of order up to 1
data: model
LM test = 0.70926, df = 1, p-value = 0.3997
V našich údajoch (mesačný počet obyvateľov vo vybranej obci v roku
2024) sa ukáže, či BG test potvrdí alebo vyvráti prítomnosť
autokorelácie prvého rádu. Aj keď pri krátkom časovom rade (len 12
mesiacov) nebýva test príliš silný, pre demonštračné
účely použijeme aj postup odstránenia dôsledkov autokorelácie
pomocou dynamizácie modelu.
Ako riešiť autokoreláciu
Odstraňovanie problému autokorelácie rezíduí
Odhad Koyckovho modelu v R
Najjednoduchšia implementácia pre naše údaje:
udajeMesto_long <- udajeMesto_long %>%
arrange(Time) %>%
mutate(
Pocet_obyvatelov_lag1 = dplyr::lag(Pocet_obyvatelov)
)
model_koyck <- lm(Pocet_obyvatelov ~ Time + Pocet_obyvatelov_lag1,
data = udajeMesto_long)
summary(model_koyck)
Call:
lm(formula = Pocet_obyvatelov ~ Time + Pocet_obyvatelov_lag1,
data = udajeMesto_long)
Residuals:
Min 1Q Median 3Q Max
-24.591 -16.219 2.003 13.554 23.918
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 58792.7569 15755.3637 3.732 0.00577 **
Time 30.9479 8.3103 3.724 0.00584 **
Pocet_obyvatelov_lag1 -0.2422 0.3330 -0.727 0.48779
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 18.75 on 8 degrees of freedom
(1 observation deleted due to missingness)
Multiple R-squared: 0.9609, Adjusted R-squared: 0.9512
F-statistic: 98.4 on 2 and 8 DF, p-value: 2.329e-06
Durbin-Watson test
data: model_koyck
DW = 2.2885, p-value = 0.5587
alternative hypothesis: true autocorrelation is greater than 0
V dynamizovanom modeli vystupuje aj oneskorená hodnota vysvetľovanej
premennej (Pocet_obyvatelov_lag1). Ak je jej koeficient
kladný a menší ako 1, interpretujeme to tak, že
časť úrovne z minulého mesiaca sa prenáša do aktuálneho
mesiaca (zotrvačnosť). Pri hodnotení kvality modelu je vhodné
porovnať napríklad Adjusted R-squared pôvodného a
dynamického modelu, prípadne znova overiť autokoreláciu rezíduí (DW, BG
test).
Newey–West robustné štandardné chyby
Ešte jednou možnosťou, ako reagovať na prítomnosť autokorelácie (a
heteroskedasticity), je použiť robustné štandardné
chyby podľa Newey–Westa. Tie nemenia samotné odhady
koeficientov, ale korigujú odhady smerodajných odchýlok.
library(sandwich)
library(lmtest)
coeftest(model, vcov = NeweyWest(model))
t test of coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.7339e+04 6.5101e+00 7271.681 < 2.2e-16 ***
Time 2.4441e+01 7.7275e-01 31.628 2.347e-11 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
4. Záver
Na jednoduchom príklade mesačného počtu obyvateľov vo vybranej
slovenskej obci v roku 2024 sme ukázali:
- ako odhadnúť trendový model v čase,
- ako graficky a štatisticky testovať autokoreláciu
rezíduí (ACF, Durbin–Watson, BG test),
- ako možno model dynamizovať pomocou
Koyckovej rovnice,
- a ako využiť Newey–Westove robustné štandardné
chyby.
Autokorelácia rezíduí a z nej vyplývajúca potreba dynamizácie modelov
má v ekonometrii veľký význam. Tu sme uviedli len základné prístupy – k
zložitejším patrí napríklad Almonov model distribuovaného oneskorenia,
metóda Cochran–Orcutt alebo všeobecnejšie ARIMA modely,
ktoré sa používajú pri dlhších časových radoch.
LS0tCnRpdGxlOiAiRWNvbm9tZXRyaWNzIGluIFIgLSBjdmnEjWVuaWUgOSIKYXV0aG9yOiAiRmlsaXAgSnVya8OhxI1layAoemEgcG9tb2NpIENoYXRHUFQpIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdGhlbWU6IHVuaXRlZAogICAgaGlnaGxpZ2h0OiB0YW5nbwplZGl0b3Jfb3B0aW9uczogCiAgbWFya2Rvd246IAogICAgd3JhcDogNzIKLS0tCgpTIHZ5dcW+aXTDrW0gZGF0YWLDoXp5ICoqRGF0YWJhemEuY3N2KiosIGt0b3LDoSBvYnNhaHVqZSAqKnBvxI10eSBvYnl2YXRlxL5vdiBzbG92ZW5za8O9Y2ggb2Jjw60gcG9kxL5hIG9rcmVzdSBhIG1lc2lhY2EgdiByb2t1IDIwMjQqKi4KClByaSDEj2FsxaFlaiBwcsOhY2kgYnVkZW1lIHBvdcW+w612YcWlIGtuacW+bmljZQoKYGBge3J9CmxpYnJhcnkoem9vKQpsaWJyYXJ5KHRzZXJpZXMpCmxpYnJhcnkobG10ZXN0KQpsaWJyYXJ5KHNhbmR3aWNoKQpsaWJyYXJ5KGNhcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKcm0obGlzdCA9IGxzKCkpCmBgYAoKLS0tCgojIyAxLiDDmnZvZCBhIMO6ZGFqZQoKw5pkYWplIG8gcG/EjXRlIG9ieXZhdGXEvm92IHPDuiB1bG/FvmVuw6kgdiBzw7pib3JlIGBEYXRhYmF6YS5jc3ZgLiAgCkthxb5kw70gcmlhZG9rIHByZWRzdGF2dWplIGplZG51ICoqb2JlYyoqLCBzdMS6cGNlOgoKLSBgT2tyZXNgIOKAkyBuw6F6b3Ygb2tyZXN1LAotIGBPYmVjYCDigJMgbsOhem92IG9iY2UsCi0gYDIwMjRNMDFgIOKApiBgMjAyNE0xMmAg4oCTIHBvxI1ldCBvYnl2YXRlxL5vdiB2IGRhbm9tIG1lc2lhY2kgcm9rdSAyMDI0LgoKU8O6Ym9yIHByZWRwb2tsYWTDoW1lIHVsb8W+ZW7DvSB2IHBvZHByaWXEjWlua3UgKipgdWRhamVgKiogdiBwcmFjb3Zub20gcHJpZcSNaW5rdSAoYWJ5IGJvbGkgw7pkYWplIG9kZGVsZW7DqSBvZCB6dnnFoWt1IHByb2pla3R1KS4KCiMjIyAxLjEgw5p2b2QgZG8gcHJvYmzDqW11LCBzdGFub3ZlbmllIGh5cG90w6l6CgpSb3pob2RsaSBzbWUgc2Egc2xlZG92YcWlICoqdsO9dm9qIHBvxI10dSBvYnl2YXRlxL5vdiB2IMSNYXNlKiogdm8gdnlicmFuZWogb2JjaS4gIApLb25rcsOpdG5lIGJ1ZGVtZSBtb2RlbG92YcWlICoqbWVzYcSNbsO9IHBvxI1ldCBvYnl2YXRlxL5vdioqIHYgb2JjaSAgCioq4oCeQnJhdGlzbGF2YSAtIG1lc3Rza8OhIMSNYXPFpSBTdGFyw6kgTWVzdG/igJwqKiB2IHrDoXZpc2xvc3RpIG9kIMSNYXN1IChpbmRleCBtZXNpYWNhKS4KCk96bmHEjW1lOgoKLSBcKFlfdFwpOiBwb8SNZXQgb2J5dmF0ZcS+b3YgdiBtZXNpYWNpIFwodFwpLAotIFwodFwpOiDEjWFzb3bDvSBpbmRleCAoMSA9IGphbnXDoXIgMjAyNCwgMiA9IGZlYnJ1w6FyIDIwMjQsIOKApiwgMTIgPSBkZWNlbWJlciAyMDI0KS4KCk5hxaFhIHByYWNvdm7DoSBoeXBvdMOpemE6CgotIHByZWRwb2tsYWTDoW1lLCDFvmUgKipwb8SNZXQgb2J5dmF0ZcS+b3Ygc2EgdiBwcmllYmVodSByb2thIG1pZXJuZSBtZW7DrSoqIChuYXByLiB2cGx5dm9tIG1pZ3LDoWNpZSksCi0gb8SNYWvDoXZhbWUgKipobGFka8O9IHbDvXZvaiB2IMSNYXNlKiosIHRlZGEgc2lsbsO6ICoqYXV0b2tvcmVsw6FjaXUqKiwgdC4gai4gcG/EjWV0IG9ieXZhdGXEvm92IHYgbWVzaWFjaSBcKHRcKSBqZSB2ZcS+bWkgcG9kb2Juw70gcG/EjXR1IHYgbWVzaWFjaSBcKHQtMVwpLAotIG/EjWFrw6F2YW1lICoqa2xhZG7DvSB0cmVuZG92w70ga29lZmljaWVudCoqIChcKFxiZXRhXzEgPiAwXCkpLCBhayBwb8SNZXQgb2J5dmF0ZcS+b3YgbcOhIG1pZXJuZSByYXN0w7pjdSB0ZW5kZW5jaXUuCgojIyMgMS4yIFByw61wcmF2YSBkYXRhYsOhenksIMO6cHJhdmEgw7pkYWpvdgoKRGF0YWLDoXphIGplIHYgdHp2LiDigJ53aWRl4oCcIHR2YXJlIChtZXNpYWNlIHYgc3TEunBjb2NoKS4gUHJlIMSNYXNvdsO6IGFuYWzDvXp1IGplZG5laiBvYmNlIGplIHbDvWhvZG5lasWhaWUgbWHFpSDDumRhamUgdiDigJ5sb25n4oCcIHR2YXJlOiBrYcW+ZMO9IHJpYWRvayA9IGplZG5hIG9iZWMgdiBqZWRub20gbWVzaWFjaS4KCk5hanNrw7RyIG5hxI3DrXRhbWUgw7pkYWplLCBwb3RvbSB2eWJlcmllbWUgamVkbnUgb2JlYyBhIHByZWtsb3DDrW1lIG1lc2HEjW7DqSBzdMS6cGNlIGRvIMSNYXNvdsOpaG8gcmFkdS4KCmBgYHtyfQojIG5hxI3DrXRhbmllIGRhdGFiw6F6eQp1ZGFqZSA8LSByZWFkLmNzdigiRGF0YWJhemEuY3N2IiwKICAgICAgICAgICAgICAgICAgc2VwID0gIjsiLAogICAgICAgICAgICAgICAgICBkZWMgPSAiLCIsCiAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRkFMU0UpCgojIHZ5YmVyaWVtZSBqZWRudSBrb25rcsOpdG51IG9iZWMgKG1vxb5lxaEgem1lbmnFpSBuYSBpbsO6KQp1ZGFqZU1lc3RvIDwtIHVkYWplW3VkYWplJE9iZWMgPT0gIkJyYXRpc2xhdmEgLSBtZXN0c2vDoSDEjWFzxaUgU3RhcsOpIE1lc3RvIiwgXQoKIyBwcmVrbG9wZW5pZSB6IHdpZGUgbmEgbG9uZyAobWVzaWFjZSBkbyByaWFka292KQp1ZGFqZU1lc3RvX2xvbmcgPC0gdWRhamVNZXN0byAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gZHBseXI6OnN0YXJ0c193aXRoKCIyMDI0TSIpLAogICAgbmFtZXNfdG8gPSAiUm9rTWVzaWFjIiwKICAgIHZhbHVlc190byA9ICJQb2NldF9vYnl2YXRlbG92IgogICkgJT4lCiAgYXJyYW5nZShSb2tNZXNpYWMpICU+JSAKICBtdXRhdGUoCiAgICBSb2sgPSBhcy5udW1lcmljKHN1YnN0cihSb2tNZXNpYWMsIDEsIDQpKSwKICAgIE1lcyA9IGFzLm51bWVyaWMoc3Vic3RyKFJva01lc2lhYywgNiwgNykpLAogICAgVGltZSA9IGRwbHlyOjpyb3dfbnVtYmVyKCkgICMgMSA9IGphbnXDoXIsIDEyID0gZGVjZW1iZXIKICApCgp1ZGFqZU1lc3RvX2xvbmcKYGBgCgotLS0KCiMjIDIuIExpbmXDoXJuYSByZWdyZXNpYSB2IHrDoWtsYWRub20gdHZhcmUKCklkZSBvIG9kaGFkIHJvdm5pY2UKClxbClx0ZXh0e1BvY2V0XF9vYnl2YXRlbG92fV90ID0gXGJldGFfMCArIFxiZXRhXzEgXHRleHR7VGltZX1fdCArIGVfdCwKXF0KCmtkZToKCi0gXChcdGV4dHtQb2NldFxfb2J5dmF0ZWxvdn1fdFwpIOKAkyBwb8SNZXQgb2J5dmF0ZcS+b3Ygdm8gdnlicmFub20gbWVzaWFjaSwKLSBcKFx0ZXh0e1RpbWV9X3RcKSDigJMgaW5kZXggbWVzaWFjYSAoMeKAkzEyKSwKLSBcKGVfdFwpIOKAkyBuw6Fob2Ruw6Egemxvxb5rYSAocmV6w61kdXVtKS4KCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIGxpbmXDoXJueSB0cmVuZG92w70gbW9kZWwKbW9kZWwgPC0gbG0oUG9jZXRfb2J5dmF0ZWxvdiB+IFRpbWUsIGRhdGEgPSB1ZGFqZU1lc3RvX2xvbmcpCnN1bW1hcnkobW9kZWwpCmBgYAoKLS0tCgojIyAzLiBBdXRva29yZWzDoWNpYSByZXrDrWR1w60KClYgdGVqdG8gxI1hc3RpIHNhIHBvenJpZW1lIG5hIMSPYWzFocOtIGTDtGxlxb5pdMO9IHByZWRwb2tsYWQga2xhc2lja8OpaG8gbGluZcOhcm5laG8KcmVncmVzbsOpaG8gbW9kZWx1IOKAkyAqKm5lesOhdmlzbG9zxaUgcmV6w61kdcOtKiouIFYgxI1hc292w71jaCByYWRvY2ggKGFrbyBqZSBuw6HFoSBtZXNhxI1uw70KcG/EjWV0IG9ieXZhdGXEvm92KSBzYSDEjWFzdG8gc3TDoXZhLCDFvmUgY2h5YmEgdiDEjWFzZSBcKHRcKSBqZSBzeXN0ZW1hdGlja3kgc3DDpHTDoQpzIGNoeWJvdSB2IMSNYXNlIFwodC0xXCksIMSNbyBuYXrDvXZhbWUgKiphdXRva29yZWzDoWNpb3UgcmV6w61kdcOtKiouCgojIyMgMy4xIMSMbyBqZSBhdXRva29yZWzDoWNpYSByZXrDrWR1w60/CgpBdXRva29yZWzDoWNpYSByZXrDrWR1w60gamUgc2l0dcOhY2lhLCBrZcSPIHBsYXTDrToKClxbClxvcGVyYXRvcm5hbWV7Q29ycn0oZV90LCBlX3t0LWt9KSBcbmVxIDAgXHF1YWQgXHRleHR7cHJlIG5pZWt0b3LDqSB9IGsgXG5lcSAwLgpcXQoKTmFqxI1hc3RlasWhaWUgc2Egc2vDum1hIGF1dG9rb3JlbMOhY2lhIHBydsOpaG8gcsOhZHU6CgpcWwplX3QgPSBccmhvIGVfe3QtMX0gKyBcbnVfdCxccXVhZCB8XHJob3wgPCAxLgpcXQoKIyMjIDMuMiBEw7RzbGVka3kgYXV0b2tvcmVsw6FjaWUgcmV6w61kdcOtCgotIG9kaGFkeSBrb2VmaWNpZW50b3YgXChcaGF0e1xiZXRhfVwpIHPDuiBuZXN0cmFubsOpLAotIGFsZSBuZWVmZWt0w612bmUsCi0gxaF0YW5kYXJkbsOpIGNoeWJ5IHPDuiBza3Jlc2xlbsOpICjEjWFzdG8gcG9kaG9kbm90ZW7DqSksIHRlZGEgcC1ob2Rub3R5IHNhIGphdmlhIG1lbsWhaWUsCi0gdC0gYSBGLXRlc3R5IHPDuiBwb3RvbSBza3Jlc2xlbsOpLgoKLS0tCgojIyMgMy4zIERldGVrY2lhIGF1dG9rb3JlbMOhY2llIAoKIyMjIyBHcmFmaWNrw6EgaW5mb3Jtw6FjaWEKCmBgYHtyfQojIHByaWTDoW1lIGRvIGTDoXQgZml0dGVkIHZhbHVlcyB6IG1vZGVsdQp1ZGFqZU1lc3RvX2xvbmckZml0dGVkIDwtIGZpdHRlZChtb2RlbCkKCiMgc2NhdHRlcnBsb3QgKyB2eXJvdm5hbsOhIHRyZW5kb3bDoSDEjWlhcmEKZ2dwbG90KHVkYWplTWVzdG9fbG9uZywgYWVzKHggPSBUaW1lLCB5ID0gUG9jZXRfb2J5dmF0ZWxvdikpICsKICBnZW9tX3BvaW50KGNvbG9yID0gInN0ZWVsYmx1ZSIsIHNpemUgPSAyKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gZml0dGVkKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUG/EjWV0IG9ieXZhdGXEvm92OiBlbXBpcmlja8OpIMO6ZGFqZSAobW9kcsOhKSB2cy4gb2RoYWRudXTDvSB0cmVuZCAoxI1lcnZlbsOhKSIsCiAgICB4ID0gIk1lc2lhYyAoMjAyNCkiLAogICAgeSA9ICJQb8SNZXQgb2J5dmF0ZcS+b3YiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKQW5hbMO9em91IG9icsOhemthIHZpZMOtbWUsIMW+ZSAqKm1lc2HEjW7DqSBob2Rub3R5IHBvxI10dSBvYnl2YXRlxL5vdiBuYSBzZWJhIHBseW51bG8gbmFkdsOkenVqw7oqKiDigJMgdiBzdXNlZG7DvWNoIG1lc2lhY29jaCBzw7ogc2kgdmXEvm1pIHBvZG9ibsOpLiBBayBieSBzbWUgc2kgem9icmF6aWxpIHJlesOtZHXDoSAocm96ZGllbCBtZWR6aSBlbXBpcmlja8O9bWkgYSB2eXJvdm5hbsO9bWkgaG9kbm90YW1pKSwgamUgcHJpcm9kemVuw6kgb8SNYWvDoXZhxaUsIMW+ZSBwb8SNYXMgbmlla2/EvmvDvWNoIHBvIHNlYmUgaWTDumNpY2ggbWVzaWFjb3YgYnVkw7ogbWHFpSBwb2RvYm7DqSB6bmFtaWVua28uIFRvIGplIHR5cGlja8O9IHZpenXDoWxueSBzaWduw6FsIG1vxb5uZWogYXV0b2tvcmVsw6FjaWUuCgpgYGB7cn0KIyB1bG/FvsOtbWUgc2kgcmV6aWR1w6EgeiBww7R2b2Ruw6lobyBtb2RlbHUKcmVzIDwtIHJlc2lkdWFscyhtb2RlbCkKYGBgCgotLS0KCiMjIyMgQUNGIGdyYWYgKEF1dG9jb3JyZWxhdGlvbiBGdW5jdGlvbikKClTDoXRvIGZ1bmtjaWEgcHJpcmHEj3VqZSBvZGhhZCBrb3JlbMOhY2llLCBrdG9yw6EgamUgbWVkemkgamVkbm90bGl2w71taSByZXrDrWR1YW1pCnYgYWt0dcOhbG5vbSBvYmRvYsOtIGEgb2Jkb2LDrSBwb3N1bnV0b20gKExhZykgbyBcKGtcKSBvYmRvYsOtIHNww6TFpS4KCmBgYHtyfQphY2YocmVzLCBsYWcubWF4ID0gNCwgbWFpbiA9ICJBdXRva29yZWxhxI1uw6EgZnVua2NpYSByZXrDrWR1w60iKQpgYGAKCk5hIHRvbXRvIGdyYWZlIGplIG1vZHJvdSBwcmVydcWhb3Zhbm91IMSNaWFyb3UgdnlqYWRyZW7DvSBhaiA5NSAlIGludGVydmFsCnNwb8S+YWhsaXZvc3RpIHByZSBob2Rub3R1IGF1dG9rb3JlbGHEjW7DqWhvIGtvZWZpY2llbnR1IHMgcHLDrXNsdcWhbsO9bSBwb3N1bm9tLgpBayBzYSBuaWVrdG9yw70gc3TEunBlYyBuYWNow6FkemEgbWltbyB0b2h0byBww6FzbWEsIG5hem5hxI11amUgdG8gKirFoXRhdGlzdGlja3kKdsO9em5hbW7DuiBhdXRva29yZWzDoWNpdSoqIHByaSBkYW5vbSBwb3N1bmUuCgotLS0KCiMjIyMgRHVyYmlu4oCTV2F0c29ub3YgdGVzdAoKRHVyYmlu4oCTV2F0c29ub3Yga29lZmljaWVudCAoRFcpIGplIHZ5cG/EjcOtdGFuw70geiByZXrDrWR1w60gcG9kxL5hIHZ6b3JjYQoKXFsKRFcgPSBcZnJhY3tcc3VtX3t0PTJ9XntufSAoZV90IC0gZV97dC0xfSleezJ9fXtcc3VtX3t0PTF9XntufSBlX3ReezJ9fQpcXQoKa2RlIFwoblwpIGplIHBvxI1ldCBwb3pvcm92YW7DrS4gTWVkemkga29lZmljaWVudG9tIGF1dG9rb3JlbMOhY2llIGR2b2NoIHN1c2VkbsO9Y2ggcmV6w61kdcOtIGEgRFcgcGxhdMOtIHByaWJsacW+bsO9IHZ6xaVhaAoKXFsKXGhhdHtccmhvfSBcYXBwcm94IDEgLSBcZnJhY3tEV317Mn0uClxdCgpIb2Rub3R5OgoKLSAqKmJsw616a2UgbnVsZSoqIOKGkiBzaWxuw6EgKipwb3ppdMOtdm5hIGF1dG9rb3JlbMOhY2lhKiosCi0gKipibMOtemtlIDQqKiDihpIgc2lsbsOhICoqbmVnYXTDrXZuYSBhdXRva29yZWzDoWNpYSoqLAotICoqb2tvbG8gMioqIOKGkiDFvmlhZG55IHbDvXJhem7DvSBwcm9ibMOpbSBzIGF1dG9rb3JlbMOhY2lvdS4KClYgcHJheGkgc2EgxI1hc3RvIHBvdcW+w612YSBpbnR1aXTDrXZuZSBwcmF2aWRsbzogYWsgc2EgRFcgbmFjaMOhZHphIHYgaW50ZXJ2YWxlCnByaWJsacW+bmUgKioxLDggYcW+IDIsMioqLCBwcm9ibMOpbSBhdXRva29yZWzDoWNpZSB2w6TEjcWhaW5vdSBuZXBvdmHFvnVqZW1lIHphIHbDocW+bnkuCgpgYGB7cn0KbGlicmFyeShsbXRlc3QpCmR3dGVzdChtb2RlbCkKYGBgCgpEVyB0ZXN0IG3DoSBpc3TDqSBvYm1lZHplbmlhIOKAkyByZWdyZXNvcnkgbmVzbcO6IGJ5xaUgxI1hc292byBwb3N1bnV0w6kgYSBuZXNtw7oKb2JzYWhvdmHFpSBvbmVza29yZW7DqSBwb3pvcm92YW5pYSB2eXN2ZXTEvm92YW5laiB2ZWxpxI1pbnkgYWtvIHJlZ3Jlc29yeS4KVGlldG8gb2JtZWR6ZW5pYSBuZXBsYXRpYSBwcmUgQnJldXNjaOKAk0dvZGZyZXlvdiB0ZXN0LgoKLS0tCgojIyMjIEJyZXVzY2jigJNHb2RmcmV5b3YgdGVzdCAoQkcgdGVzdCkKCiMjIyMjIMSMbyB0ZXN0IHRlc3R1amUKCkJHIHRlc3QgamUgZm9ybcOhbG55bSB0ZXN0b20gKiphdXRva29yZWzDoWNpZSAoc8OpcmlvdmVqIGtvcmVsw6FjaWUpKiogcmV6w61kdcOtOgoKXFsKdV90ID0gXHJob18xIHVfe3QtMX0gKyBccmhvXzIgdV97dC0yfSArIFxjZG90cyArIFxyaG9fcCB1X3t0LXB9ICsgXHZhcmVwc2lsb25fdC4KXF0KClRlc3R1amUsIMSNaSBzw7ogcmV6w61kdcOhIGtvcmVsb3ZhbsOpIHYgxI1hc2UgYcW+IGRvIHLDoWR1IFwocFwpLCDEjW8gamUgdHlwaWNrw6kgcHJlIMSNYXNvdsOpIHJhZHkuCgpOYSByb3pkaWVsIG9kIERXIHRlc3R1OgoKLSB0ZXN0dWplICoqYXV0b2tvcmVsw6FjaXUgcyB2ecWhxaHDrW0gcG9zdW5vbSoqIChsYWcgMSwgMiwgMywg4oCmKSwKLSBmdW5ndWplIGFqIHByaSBtb2RlbG9jaCBzICoqb25lc2tvcmVub3UgdnlzdmV0xL5vdmFub3UgcHJlbWVubm91KiogYWtvIHJlZ3Jlc29yb20sCi0gcHJhY3VqZSBzIG5la29uxaF0YW50bsO9bWkgcmVncmVzb3JtaSAodHJlbmQsIGR1bW15IHByZW1lbm7DqSBhdMSPLikuCgotLS0KCiMjIyMjIEh5cG90w6l6eQoKUHJlIHRlc3QgYXV0b2tvcmVsw6FjaWUgYcW+IGRvIHLDoWR1IFwocFwpOgoKLSAqKk51bG92w6EgaHlwb3TDqXphIFwoSF8wXCkqKjogxb5pYWRuYSBzw6lyaW92w6Ega29yZWzDoWNpYSAgCiAgXFsKICBccmhvXzEgPSBccmhvXzIgPSBcY2RvdHMgPSBccmhvX3AgPSAwCiAgXF0KCi0gKipBbHRlcm5hdMOtdm5hIGh5cG90w6l6YSBcKEhfMVwpKio6IHPDqXJpYSBqZSBhdXRva29yZWxvdmFuw6EgIAogIEFzcG/FiCBqZWRuYSB6IFwoXHJob19qXCkgamUgb2RsacWhbsOhIG9kIG51bHkuCgotLS0KCiMjIyMjIEFrbyBmdW5ndWplIEJHIHRlc3QKCjEuIE9kaGFkbmVtZSBww7R2b2Ruw7ogcmVncmVzaXUgKHUgbsOhcyB0cmVuZG92w70gbW9kZWwpIGEgesOtc2thbWUgcmV6w61kdcOhIFwoZV90XCkuCjIuIFNwdXN0w61tZSBwb21vY27DuiByZWdyZXNpdToKICAgXFsKICAgZV90CiAgID0gXGFscGhhXzAgKyBcYWxwaGFfMSB4X3sxdH0gKyBcY2RvdHMgKyBcYWxwaGFfayB4X3trdH0KICAgKyBccmhvXzEgZV97dC0xfSArIFxjZG90cyArIFxyaG9fcCBlX3t0LXB9ICsgdl90LAogICBcXQogICBrZGUgXCh4X3tqdH1cKSBzw7ogcMO0dm9kbsOpIHJlZ3Jlc29yeS4KMy4gWiB0ZWp0byByZWdyZXNpZSB2eXBvxI3DrXRhbWU6CiAgIFxbCiAgIFx0ZXh0e0JHfSA9IChuIC0gcCkgUl4yX3tcdGV4dHthdXh9fQogICBcXQo0LiBQb2QgXChIXzBcKSBwbGF0w60gcHJpYmxpxb5uZToKICAgXFsKICAgXHRleHR7Qkd9IFxzaW0gXGNoaV4yX3AuCiAgIFxdCgotLS0KCiMjIyMjIEludGVycHJldMOhY2lhCgotICoqVmXEvmvDoSBob2Rub3RhIHRlc3RvdmVqIMWhdGF0aXN0aWt5IEJHIChtYWzDoSBwLWhvZG5vdGEpKiog4oaSIHphbWlldGFtZSBcKEhfMFwpIOKGkiAqKmF1dG9rb3JlbMOhY2lhIHByw610b21uw6EqKi4KLSAqKk1hbMOhIGhvZG5vdGEgQkcgKHZlxL5rw6EgcC1ob2Rub3RhKSoqIOKGkiBuZXphbWlldG5lbWUgXChIXzBcKSDihpIgKipuaWUgamUgZMO0a2F6IGF1dG9rb3JlbMOhY2llKiouCgotLS0KCiMjIyMjICBQcmFrdGlja8O9IHbDvXBvxI1ldCB2IFIKCmBgYHtyfQpiZ3Rlc3QobW9kZWwsIG9yZGVyID0gMSkKYGBgCgpWIG5hxaFpY2ggw7pkYWpvY2ggKG1lc2HEjW7DvSBwb8SNZXQgb2J5dmF0ZcS+b3Ygdm8gdnlicmFuZWogb2JjaSB2IHJva3UgMjAyNCkKc2EgdWvDocW+ZSwgxI1pIEJHIHRlc3QgcG90dnJkw60gYWxlYm8gdnl2csOhdGkgcHLDrXRvbW5vc8WlIGF1dG9rb3JlbMOhY2llIHBydsOpaG8KcsOhZHUuIEFqIGtlxI8gcHJpIGtyw6F0a29tIMSNYXNvdm9tIHJhZGUgKGxlbiAxMiBtZXNpYWNvdikgbmViw712YSB0ZXN0IHByw61sacWhCnNpbG7DvSwgcHJlICoqZGVtb27FoXRyYcSNbsOpIMO6xI1lbHkqKiBwb3XFvmlqZW1lIGFqIHBvc3R1cCBvZHN0csOhbmVuaWEKZMO0c2xlZGtvdiBhdXRva29yZWzDoWNpZSBwb21vY291IGR5bmFtaXrDoWNpZSBtb2RlbHUuCgotLS0KCiMjIEFrbyByaWXFoWnFpSBhdXRva29yZWzDoWNpdQoKIyMjIEtveWNrb3ZhIHRyYW5zZm9ybcOhY2lhIGEgS295Y2tvdmEgcm92bmljYQoKViBwcmVkY2jDoWR6YWrDumNlaiDEjWFzdGkgc21lIHNhIHZlbm92YWxpIGF1dG9rb3JlbMOhY2lpIHJlesOtZHXDrS4gVGVyYXoKcm96xaHDrXJpbWUgbW9kZWwgbyBkeW5hbWlja8O6IMWhdHJ1a3TDunJ1IHphbG/FvmVuw7ogbmEgdHp2LiAqKmdlb21ldHJpY2t5CmtsZXNhasO6Y29tIHJvemxvxb5lbsOtIG9uZXNrb3JlbsO9Y2ggZWZla3RvdioqLiBUYWvDvXRvIG1vZGVsIHNhIG5hesO9dmEKKipLb3lja292IG1vZGVsKiogYSBqZWhvIMO6c3RyZWRuw71tIHBydmtvbSBqZSAqKktveWNrb3ZhIHRyYW5zZm9ybcOhY2lhKiouCgotLS0KCiMjIyMjIFbDvWNob2Rpc2tvdsO9IG1vZGVsIHMgZGlzdHJpYnVvdmFuw71tIG9uZXNrb3JlbsOtbQoKVXZhxb51am1lIG1vZGVsOgoKXFsKeV90ID0gXGFscGhhICsgXGJldGFfMCB4X3QgKyBcYmV0YV8xIHhfe3QtMX0gKyBcYmV0YV8yIHhfe3QtMn0gKyBcY2RvdHMgKyB1X3QuClxdCgotLS0KCiMjIyMjICBLb3lja292YSDFoXRydWt0w7pyYSBrb2VmaWNpZW50b3YKCktveWNrIG5hdnJob2wsIMW+ZSBvbmVza29yZW7DqSBlZmVrdHkgbWFqw7ogKipnZW9tZXRyaWNreSBrbGVzYWrDumN1IHBvZG9idSoqOgoKXFsKXGJldGFfayA9IFxsYW1iZGFeayBcYmV0YV8wLCBccXF1YWQgMCA8IFxsYW1iZGEgPCAxLgpcXQoKVMO9bSBzYSBkaXN0cmlidcSNbsOpIG9uZXNrb3JlbmllIHpqZWRub2R1xaHDrSB0YWssIMW+ZSBuYW1pZXN0byBuZWtvbmXEjW7DqWhvCnBvxI10dSBwYXJhbWV0cm92IG9kaGFkdWplbWUgbGVuOgoKLSBcKFxiZXRhXzBcKSDigJMgb2thbcW+aXTDvSBlZmVrdCwKLSBcKFxsYW1iZGFcKSDigJMgcsO9Y2hsb3PFpSB0bG1lbmlhIGVmZWt0b3Ygb25lc2tvcmVuaWEuCgotLS0KCiMjIyMjIEtveWNrb3ZhIHRyYW5zZm9ybcOhY2lhCgpQw7R2b2Ruw70gbW9kZWw6CgpcWwp5X3QgPSBcYWxwaGEgKyBcYmV0YV8wIHhfdCArIFxsYW1iZGEgXGJldGFfMCB4X3t0LTF9CiAgICAgICsgXGxhbWJkYV4yIFxiZXRhXzAgeF97dC0yfSArIFxjZG90cyArIHVfdC4KXF0KClZ5bsOhc29iw61tZSBtb2RlbCBrb27FoXRhbnRvdSBcKFxsYW1iZGFcKSBhIHBvc3VuaWVtZSDEjWFzb3bDvSBpbmRleCBvIDEgZG96YWR1OgoKXFsKXGxhbWJkYSB5X3t0LTF9ID0gXGxhbWJkYVxhbHBoYSArIFxiZXRhXzAgeF97dC0xfQogICAgICArIFxsYW1iZGEgXGJldGFfMCB4X3t0LTJ9ICsgXGNkb3RzICsgXGxhbWJkYSB1X3t0LTF9LgpcXQoKT2TEjcOtdGFuw61tIG9ib2NoIHbDvXJhem92IGRvc3RhbmVtZToKClxbCnlfdCAtIFxsYW1iZGEgeV97dC0xfQo9IFxhbHBoYSgxLVxsYW1iZGEpICsgXGJldGFfMCAoeF90IC0gXGxhbWJkYSB4X3t0LTF9KQogICsgKHVfdCAtIFxsYW1iZGEgdV97dC0xfSkuClxdCgpUbyBqZSAqKktveWNrb3ZhIHRyYW5zZm9ybcOhY2lhKiouCgotLS0KCiMjIyMjIEtveWNrb3ZhIHJvdm5pY2EgKGF1dG9yZWdyZXPDrXZueSBtb2RlbCkKClBvIGFsZ2VicmFpY2tlaiDDunByYXZlOgoKXFsKeV90ID0gXGFscGhhKDEtXGxhbWJkYSkgKyBcYmV0YV8wIHhfdCArIFxsYW1iZGEgeV97dC0xfSArIHZfdCwKXF0KCmtkZToKClxbCnZfdCA9IHVfdCAtIFxsYW1iZGEgdV97dC0xfS4KXF0KClRvdG8gamUgKipLb3lja292YSByb3ZuaWNhKiog4oCTIGR5bmFtaWNrw70gYXV0b3JlZ3Jlc8Otdm55IG1vZGVsIHNvCnrDoXZpc2xvc8Wlb3UgbmEgbWludWxvc3RpLgoKViBuYcWhb20ga29udGV4dGU6CgotIFwoeV90XCkgPSBwb8SNZXQgb2J5dmF0ZcS+b3YgdiBtZXNpYWNpIFwodFwpLAotIFwoeF90XCkg4oCTIG5hcHLDrWtsYWQgxI1hc292w70gdHJlbmQgKFRpbWUpLAotIFwoeV97dC0xfVwpIOKAkyBwb8SNZXQgb2J5dmF0ZcS+b3YgdiBwcmVkY2jDoWR6YWrDumNvbSBtZXNpYWNpLgoKLS0tCgojIyMgT2RzdHJhxYhvdmFuaWUgcHJvYmzDqW11IGF1dG9rb3JlbMOhY2llIHJlesOtZHXDrQoKIyMjIyBPZGhhZCBLb3lja292aG8gbW9kZWx1IHYgUgoKTmFqamVkbm9kdWNoxaFpYSBpbXBsZW1lbnTDoWNpYSBwcmUgbmHFoWUgw7pkYWplOgoKYGBge3J9CnVkYWplTWVzdG9fbG9uZyA8LSB1ZGFqZU1lc3RvX2xvbmcgJT4lCiAgYXJyYW5nZShUaW1lKSAlPiUKICBtdXRhdGUoCiAgICBQb2NldF9vYnl2YXRlbG92X2xhZzEgPSBkcGx5cjo6bGFnKFBvY2V0X29ieXZhdGVsb3YpCiAgKQoKbW9kZWxfa295Y2sgPC0gbG0oUG9jZXRfb2J5dmF0ZWxvdiB+IFRpbWUgKyBQb2NldF9vYnl2YXRlbG92X2xhZzEsIAogICAgICAgICAgICAgICAgICBkYXRhID0gdWRhamVNZXN0b19sb25nKQoKc3VtbWFyeShtb2RlbF9rb3ljaykKYGBgCgpgYGB7cn0KZHd0ZXN0KG1vZGVsX2tveWNrKQpgYGAKClYgZHluYW1pem92YW5vbSBtb2RlbGkgdnlzdHVwdWplIGFqIG9uZXNrb3JlbsOhIGhvZG5vdGEgdnlzdmV0xL5vdmFuZWogcHJlbWVubmVqCihgUG9jZXRfb2J5dmF0ZWxvdl9sYWcxYCkuIEFrIGplIGplaiBrb2VmaWNpZW50ICoqa2xhZG7DvSBhIG1lbsWhw60gYWtvIDEqKiwgaW50ZXJwcmV0dWplbWUgdG8gdGFrLCDFvmUgKirEjWFzxaUgw7pyb3ZuZSB6IG1pbnVsw6lobyBtZXNpYWNhIHNhIHByZW7DocWhYSBkbyBha3R1w6FsbmVobyBtZXNpYWNhKiogKHpvdHJ2YcSNbm9zxaUpLiBQcmkgaG9kbm90ZW7DrSBrdmFsaXR5IG1vZGVsdSBqZSB2aG9kbsOpIHBvcm92bmHFpSBuYXByw61rbGFkICoqQWRqdXN0ZWQgUi1zcXVhcmVkKiogcMO0dm9kbsOpaG8gYSBkeW5hbWlja8OpaG8gbW9kZWx1LCBwcsOtcGFkbmUgem5vdmEgb3ZlcmnFpSBhdXRva29yZWzDoWNpdSByZXrDrWR1w60gKERXLCBCRyB0ZXN0KS4KCi0tLQoKIyMjIyBOZXdleeKAk1dlc3Qgcm9idXN0bsOpIMWhdGFuZGFyZG7DqSBjaHlieQoKRcWhdGUgamVkbm91IG1vxb5ub3PFpW91LCBha28gcmVhZ292YcWlIG5hIHByw610b21ub3PFpSBhdXRva29yZWzDoWNpZSAoYSBoZXRlcm9za2VkYXN0aWNpdHkpLApqZSBwb3XFvmnFpSAqKnJvYnVzdG7DqSDFoXRhbmRhcmRuw6kgY2h5YnkqKiBwb2TEvmEgTmV3ZXnigJNXZXN0YS4gVGllIG5lbWVuaWEgc2Ftb3Ruw6kKb2RoYWR5IGtvZWZpY2llbnRvdiwgYWxlIGtvcmlndWrDuiBvZGhhZHkgc21lcm9kYWpuw71jaCBvZGNow71sb2suCgpgYGB7cn0KbGlicmFyeShzYW5kd2ljaCkKbGlicmFyeShsbXRlc3QpCgpjb2VmdGVzdChtb2RlbCwgdmNvdiA9IE5ld2V5V2VzdChtb2RlbCkpCmBgYAoKLS0tCgojIyA0LiBaw6F2ZXIKCk5hIGplZG5vZHVjaG9tIHByw61rbGFkZSBtZXNhxI1uw6lobyBwb8SNdHUgb2J5dmF0ZcS+b3Ygdm8gdnlicmFuZWogc2xvdmVuc2tlaiBvYmNpCnYgcm9rdSAyMDI0IHNtZSB1a8OhemFsaToKCi0gYWtvIG9kaGFkbsO6xaUgKip0cmVuZG92w70gbW9kZWwqKiB2IMSNYXNlLAotIGFrbyBncmFmaWNreSBhIMWhdGF0aXN0aWNreSB0ZXN0b3ZhxaUgKiphdXRva29yZWzDoWNpdSByZXrDrWR1w60qKiAoQUNGLCBEdXJiaW7igJNXYXRzb24sIEJHIHRlc3QpLAotIGFrbyBtb8W+bm8gbW9kZWwgKipkeW5hbWl6b3ZhxaUqKiBwb21vY291ICoqS295Y2tvdmVqIHJvdm5pY2UqKiwKLSBhIGFrbyB2eXXFvmnFpSAqKk5ld2V54oCTV2VzdG92ZSByb2J1c3Ruw6kgxaF0YW5kYXJkbsOpIGNoeWJ5KiouCgpBdXRva29yZWzDoWNpYSByZXrDrWR1w60gYSB6IG5laiB2eXBsw712YWrDumNhIHBvdHJlYmEgZHluYW1pesOhY2llIG1vZGVsb3YgbcOhCnYgZWtvbm9tZXRyaWkgdmXEvmvDvSB2w716bmFtLiBUdSBzbWUgdXZpZWRsaSBsZW4gesOha2xhZG7DqSBwcsOtc3R1cHkg4oCTIGsgemxvxb5pdGVqxaHDrW0KcGF0csOtIG5hcHLDrWtsYWQgQWxtb25vdiBtb2RlbCBkaXN0cmlidW92YW7DqWhvIG9uZXNrb3JlbmlhLCBtZXTDs2RhIENvY2hyYW7igJNPcmN1dHQKYWxlYm8gdsWhZW9iZWNuZWrFoWllICoqQVJJTUEgbW9kZWx5KiosIGt0b3LDqSBzYSBwb3XFvsOtdmFqw7ogcHJpIGRsaMWhw61jaCDEjWFzb3bDvWNoIHJhZG9jaC4K