Weather Prediction Analysis
Úvod a údaje
Rozhodla som sa modelovať \(teplotu\) \(v\) \(Budapešti\) ako funkciu troch
vysvetľujúcich premenných:
- BASEL_temp_mean — \(teplota\) \(v\) \(Bazileji\) (referenčné mesto)
- BUDAPEST_humidity — \(vlhkosť\)
\(v\) \(Budapešti\)
- BUDAPEST_pressure — \(atmosférický\) \(tlak\) \(v\) \(Budapešti\)
Hypotézy:
- \(H1\): Vyššia teplota v Bazileji
vedie k vyššej teplote v Budapešti
- \(H2\): Vyššia vlhkosť v Budapešti
vedie k nižšej teplote
- \(H3\): Vyšší atmosférický tlak v
Budapešti vedie k vyššej teplote
Príprava databázy
# Načítanie knižníc
library(zoo)
library(tseries)
library(lmtest)
library(sandwich)
library(car)
library(dplyr)
library(ggplot2)
rm(list = ls())
# Načítanie údajov
data <- read.csv("weather_prediction_dataset.csv",
dec = ".", sep = ",", header = TRUE)
# Konverzia DATE na správny formát dátumu
data$DATE <- as.Date(as.character(data$DATE), format = "%Y%m%d")
# Výber relevantných premenných
data_budapest <- data %>%
select(DATE,
BUDAPEST_temp_mean,
BASEL_temp_mean,
BUDAPEST_humidity,
BUDAPEST_pressure) %>%
arrange(DATE)
# Kontrola chýbajúcich hodnôt
sum(is.na(data_budapest))
Lineárna regresia
model <- lm(BUDAPEST_temp_mean ~ BASEL_temp_mean + BUDAPEST_humidity + BUDAPEST_pressure,
data = data_budapest)
summary(model)
Call:
lm(formula = BUDAPEST_temp_mean ~ BASEL_temp_mean + BUDAPEST_humidity +
BUDAPEST_pressure, data = data_budapest)
Residuals:
Min 1Q Median 3Q Max
-16.3082 -1.8862 0.1244 2.0250 12.6856
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.787e+02 7.355e+00 24.30 <2e-16 ***
BASEL_temp_mean 9.590e-01 8.484e-03 113.03 <2e-16 ***
BUDAPEST_humidity -8.762e+00 4.148e-01 -21.12 <2e-16 ***
BUDAPEST_pressure -1.685e+02 7.166e+00 -23.52 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 3.29 on 3650 degrees of freedom
Multiple R-squared: 0.8586, Adjusted R-squared: 0.8585
F-statistic: 7387 on 3 and 3650 DF, p-value: < 2.2e-16
Odhadnutý lineárny regresný model vykazuje vysoko vysokú celkovú
vysvetľujúcu silu, o čom svedčí koeficient determinácie (Multiple
R-squared) \(0.8586\), čo znamená, že
premenné spolu vysvetľujú \(85.86\)%
variability teploty v Budapešti.
Rezíduá:
Rozsah od \(-16.31\)°C do \(12.69\)°C
Medián rezíduí je blízko nule - \(0.1244\), čo naznačuje dobrú centrálnu
tendenciu
Kvartily sú relatívne symetrické okolo nuly
Celkový model je štatisticky \(vysoko\) \(významný\).
Posúdenie hypotéz:
- \(H1\): Teplota v Bazileji →
Koeficient \(0.959\) je kladný a vysoko
významný (\(p < 2e-16\)).
\(Hypotéza\) \(sa\) \(potvrdzuje\) - vyššia teplota v Bazileji
skutočne vedie k vyššej teplote v Budapešti.
- \(H2\): Vlhkosť v Budapešti →
Koeficient \(-8.762\) je záporný a
vysoko významný (\(p <
2e-16\)).
\(Hypotéza\) \(sa\) \(potvrdzuje\) - vyššia vlhkosť vedie k
nižšej teplote.
- \(H3\): Atmosférický tlak →
Koeficient \(-168.5\) je záporný
(oproti očakávanému kladnému) ale vysoko významný (\(p < 2e-16\)).
\(Hypotéza\) \(sa\) \(nepotvrdzuje\) - vyšší tlak vedie k nižšej
teplote, čo je opačný efekt ako sme predpokladali.
Porovnanie empirických a fitovaných hodnôt
data_budapest$fitted <- fitted(model)
ggplot(data_budapest, aes(x = DATE, y = BUDAPEST_temp_mean)) +
geom_point(color = "blue", size = 2) +
geom_line(aes(y = fitted), color = "red", size = 1) +
labs(title = "Teplota v Budapešti: Empirické vs Fitované hodnoty",
x = "Dátum", y = "Teplota (°C)") +
theme_minimal()

Dominantným prvkom je výrazná ročná sezónnosť s periodickými minimami
v zime (cca \(-10\)°C) a maximami v
lete (až do cca \(35\)°C).
Fitovaný model úspešne zachytáva hlavný ročný cyklus a dlhodobý
stacionárny trend dátového radu.
Avšak, empirické hodnoty vykazujú značnú vysokofrekvenčnú variabilitu
a extrémy, ktoré model často podhodnocuje, čo implikuje signifikantné
reziduálne chyby v aproximácii krátkodobých výkyvov.
ACF graf rezíduí
res <- residuals(model)
acf(res, lag.max = 12, main = "ACF rezíduí")

Graf autokorelačnej funkcie rezíduí demonštruje \(silnú\) a \(štatisticky\) \(významnú\) pozitívnu sériovú koreláciu pri
nízkych časových posunoch.
Prekročenie intervalov spoľahlivosti potvrdzuje, že \(rezíduá\) \(nie\) \(sú\) \(biely\) \(šum\). To indikuje nedostatočnú
špecifikáciu modelu, keďže v rezíduách zostáva nezachytená časovo
závislá (autokorelačná) štruktúra dát.
Durbin–Watson test
Durbin-Watson test
data: model
DW = 0.58232, p-value < 2.2e-16
alternative hypothesis: true autocorrelation is greater than 0
\(DW štatistika = 0.58232\) -
táto hodnota je výrazne nižšia ako \(2\), čo jasne indikuje prítomnosť silnej
pozitívnej autokorelácie v rezíduách modelu.
\(p-hodnota < 2.2e-16\) -
táto extrémne nízka hodnota je výrazne nižšia ako štandardná hladina
významnosti \(α = 0.05\), čo nám
umožňuje zamietnuť nulovú hypotézu o absencii autokorelácie.
Breusch–Godfrey test
Breusch-Godfrey test for serial correlation of order up to 1
data: model
LM test = 1852.7, df = 1, p-value < 2.2e-16
\(LM test = 1852.7\) - táto
extrémne vysoká hodnota testovacej štatistiky jasne potvrdzuje
prítomnosť výraznej sériovej korelácie v modeli.
\(p-hodnota < 2.2e-16\) -
táto extrémne nízka hodnota je výrazne nižšia ako akákoľvek štandardná
hladina významnosti (\(α = 0.05, 0.01,
0.001\)).
Môžeme rozhodne \(zamietnuť\) \(nulovú\) \(hypotézu\) o absencii sériovej korelácie.
Existuje štatisticky \(vysoko\) \(významná\) autokorelácia prvého rádu v
rezíduách modelu.
Newey–West robustné štandardné chyby
coeftest(model, vcov = NeweyWest(model))
t test of coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 178.726529 15.407961 11.600 < 2.2e-16 ***
BASEL_temp_mean 0.958971 0.016079 59.641 < 2.2e-16 ***
BUDAPEST_humidity -8.761963 0.811397 -10.799 < 2.2e-16 ***
BUDAPEST_pressure -168.516112 14.959908 -11.264 < 2.2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Štandardné chyby sa všetky zvýšili po aplikácii robustnej
korekcie:
Intercept: z \(7.355\) na \(15.408\) (\(2.1×\) vyššia)
BASEL_temp_mean: z \(0.00848\)
na \(0.01608\) (\(1.9×\) vyššia)
BUDAPEST_humidity: z \(0.4148\)
na \(0.8114\) (\(2.0×\) vyššia)
BUDAPEST_pressure: z \(7.166\)
na \(14.960\) (\(2.1×\) vyššia)
Napriek zvýšeniu štandardných chýb, všetky premenné ostávajú vysoko
štatisticky \(významné\).
Záver
Analýza potvrdila, že pôvodný model teploty v Budapešti bol
štatisticky vysoko významný s vynikajúcou vysvetľujúcou silou (\(R² = 85.86\)%), avšak trpel závažným
problémom silnej pozitívnej autokorelácie rezíduí (\(DW = 0.58\), BG test \(p < 2.2e-16\)).
Hypotézy \(H1\) a \(H2\) \(sa\) plne \(potvrdili\) - teplota v Bazileji a vlhkosť
v Budapešti sú štatisticky \(vysoko\)
\(významné\) determinanty teploty s
očakávaným smerom vplyvu. Hypotéza \(H3\) \(sa\) \(nepotvrdila\), pretože atmosférický tlak
mal opačný smer vplyvu ako sa predpokladalo, no bol tiež štatisticky
\(vysoko\) \(významný\).
Aplikácia Koyckovej transformácie výrazne zlepšila model - zvýšila
vysvetľujúcu silu na \(95.5\)% a
redukovala autokoreláciu (\(DW =
1.56\)), čím demonštrovala dôležitosť zahrnutia časového rozmeru
do modelu. Napriek tomu, autokorelácia nebola úplne eliminovaná.
Robustná Newey-West korekcia potvrdila spoľahlivosť odhadov - všetky
premenné ostali \(vysoko\) \(významné\) aj po konzervatívnej korekcii
štandardných chýb, čo svedčí o robustnosti identifikovaných vzťahov.
Model je vhodný pre predikciu teploty, no pre presnejšie odhady by
bolo vhodné uvažovať pokročilejšie časovo radové modely, ktoré by lepšie
zachytili sezónnu dynamiku a úplne eliminovali problém
autokorelácie.
LS0tDQp0aXRsZTogIsOabG9oYV85Ig0KYXV0aG9yOiAiQmMuIEtyeXN0eW5hIFZhc3lseW5hIg0KZGF0ZTogIk5vdmVtYmVyIDIwMjUiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdGhlbWU6IHVuaXRlZA0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KZWRpdG9yX29wdGlvbnM6DQogIG1hcmtkb3duOg0KICAgIHdyYXA6IDcyDQotLS0NCg0KIyBXZWF0aGVyIFByZWRpY3Rpb24gQW5hbHlzaXMNCg0KIyMgw5p2b2QgYSDDumRhamUNCg0KUm96aG9kbGEgc29tIHNhIG1vZGVsb3ZhxaUgJHRlcGxvdHUkICR2JCAkQnVkYXBlxaF0aSQgYWtvIGZ1bmtjaXUgdHJvY2ggdnlzdmV0xL51asO6Y2ljaCBwcmVtZW5uw71jaDoNCg0KLSBCQVNFTF90ZW1wX21lYW4g4oCUICR0ZXBsb3RhJCAkdiQgJEJhemlsZWppJCAocmVmZXJlbsSNbsOpIG1lc3RvKQ0KLSBCVURBUEVTVF9odW1pZGl0eSDigJQgJHZsaGtvc8WlJCAkdiQgJEJ1ZGFwZcWhdGkkDQotIEJVREFQRVNUX3ByZXNzdXJlIOKAlCAkYXRtb3Nmw6lyaWNrw70kICR0bGFrJCAkdiQgJEJ1ZGFwZcWhdGkkDQoNCkh5cG90w6l6eToNCg0KLSAkSDEkOiBWecWhxaFpYSB0ZXBsb3RhIHYgQmF6aWxlamkgdmVkaWUgayB2ecWhxaFlaiB0ZXBsb3RlIHYgQnVkYXBlxaF0aQ0KLSAkSDIkOiBWecWhxaFpYSB2bGhrb3PFpSB2IEJ1ZGFwZcWhdGkgdmVkaWUgayBuacW+xaFlaiB0ZXBsb3RlDQotICRIMyQ6IFZ5xaHFocOtIGF0bW9zZsOpcmlja8O9IHRsYWsgdiBCdWRhcGXFoXRpIHZlZGllIGsgdnnFocWhZWogdGVwbG90ZQ0KDQojIyMgUHLDrXByYXZhIGRhdGFiw6F6eQ0KDQpgYGB7cn0NCiMgTmHEjcOtdGFuaWUga25pxb5uw61jDQpsaWJyYXJ5KHpvbykNCmxpYnJhcnkodHNlcmllcykNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShzYW5kd2ljaCkNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCnJtKGxpc3QgPSBscygpKQ0KDQojIE5hxI3DrXRhbmllIMO6ZGFqb3YNCmRhdGEgPC0gcmVhZC5jc3YoIndlYXRoZXJfcHJlZGljdGlvbl9kYXRhc2V0LmNzdiIsDQogICAgICAgICAgICAgICAgIGRlYyA9ICIuIiwgc2VwID0gIiwiLCBoZWFkZXIgPSBUUlVFKQ0KDQojIEtvbnZlcnppYSBEQVRFIG5hIHNwcsOhdm55IGZvcm3DoXQgZMOhdHVtdQ0KZGF0YSREQVRFIDwtIGFzLkRhdGUoYXMuY2hhcmFjdGVyKGRhdGEkREFURSksIGZvcm1hdCA9ICIlWSVtJWQiKQ0KDQojIFbDvWJlciByZWxldmFudG7DvWNoIHByZW1lbm7DvWNoDQpkYXRhX2J1ZGFwZXN0IDwtIGRhdGEgJT4lDQogIHNlbGVjdChEQVRFLCANCiAgICAgICAgIEJVREFQRVNUX3RlbXBfbWVhbiwNCiAgICAgICAgIEJBU0VMX3RlbXBfbWVhbiwNCiAgICAgICAgIEJVREFQRVNUX2h1bWlkaXR5LA0KICAgICAgICAgQlVEQVBFU1RfcHJlc3N1cmUpICU+JQ0KICBhcnJhbmdlKERBVEUpDQoNCiMgS29udHJvbGEgY2jDvWJhasO6Y2ljaCBob2Ruw7R0DQpzdW0oaXMubmEoZGF0YV9idWRhcGVzdCkpDQpgYGANCg0KIyMgTGluZcOhcm5hIHJlZ3Jlc2lhDQoNCmBgYHtyfQ0KbW9kZWwgPC0gbG0oQlVEQVBFU1RfdGVtcF9tZWFuIH4gQkFTRUxfdGVtcF9tZWFuICsgQlVEQVBFU1RfaHVtaWRpdHkgKyBCVURBUEVTVF9wcmVzc3VyZSwNCiAgICAgICAgICAgIGRhdGEgPSBkYXRhX2J1ZGFwZXN0KQ0KDQpzdW1tYXJ5KG1vZGVsKQ0KYGBgDQpPZGhhZG51dMO9IGxpbmXDoXJueSByZWdyZXNuw70gbW9kZWwgdnlrYXp1amUgdnlzb2tvIHZ5c29rw7ogY2Vsa292w7ogdnlzdmV0xL51asO6Y3Ugc2lsdSwgbyDEjW9tIHN2ZWTEjcOtIGtvZWZpY2llbnQgZGV0ZXJtaW7DoWNpZSAoTXVsdGlwbGUgUi1zcXVhcmVkKSAkMC44NTg2JCwgxI1vIHpuYW1lbsOhLCDFvmUgcHJlbWVubsOpIHNwb2x1IHZ5c3ZldMS+dWrDuiAkODUuODYkJSB2YXJpYWJpbGl0eSB0ZXBsb3R5IHYgQnVkYXBlxaF0aS4NCg0KUmV6w61kdcOhOg0KDQotIFJvenNhaCBvZCAkLTE2LjMxJMKwQyBkbyAkMTIuNjkkwrBDDQoNCi0gTWVkacOhbiByZXrDrWR1w60gamUgYmzDrXprbyBudWxlIC0gJDAuMTI0NCQsIMSNbyBuYXpuYcSNdWplIGRvYnLDuiBjZW50csOhbG51IHRlbmRlbmNpdQ0KDQotIEt2YXJ0aWx5IHPDuiByZWxhdMOtdm5lIHN5bWV0cmlja8OpIG9rb2xvIG51bHkNCg0KQ2Vsa292w70gbW9kZWwgamUgxaF0YXRpc3RpY2t5ICR2eXNva28kICR2w716bmFtbsO9JC4NCg0KUG9zw7pkZW5pZSBoeXBvdMOpejoNCg0KLSAkSDEkOiBUZXBsb3RhIHYgQmF6aWxlamkg4oaSIEtvZWZpY2llbnQgJDAuOTU5JCBqZSBrbGFkbsO9IGEgdnlzb2tvIHbDvXpuYW1uw70gKCRwIDwgMmUtMTYkKS4gDQoNCiRIeXBvdMOpemEkICRzYSQgJHBvdHZyZHp1amUkIC0gdnnFocWhaWEgdGVwbG90YSB2IEJhemlsZWppIHNrdXRvxI1uZSB2ZWRpZSBrIHZ5xaHFoWVqIHRlcGxvdGUgdiBCdWRhcGXFoXRpLg0KDQotICRIMiQ6IFZsaGtvc8WlIHYgQnVkYXBlxaF0aSDihpIgS29lZmljaWVudCAkLTguNzYyJCBqZSB6w6Fwb3Juw70gYSB2eXNva28gdsO9em5hbW7DvSAoJHAgPCAyZS0xNiQpLiANCg0KJEh5cG90w6l6YSQgJHNhJCAkcG90dnJkenVqZSQgLSB2ecWhxaFpYSB2bGhrb3PFpSB2ZWRpZSBrIG5pxb7FoWVqIHRlcGxvdGUuDQoNCi0gJEgzJDogQXRtb3Nmw6lyaWNrw70gdGxhayDihpIgS29lZmljaWVudCAkLTE2OC41JCBqZSB6w6Fwb3Juw70gKG9wcm90aSBvxI1ha8OhdmFuw6ltdSBrbGFkbsOpbXUpIGFsZSB2eXNva28gdsO9em5hbW7DvSAoJHAgPCAyZS0xNiQpLiANCg0KJEh5cG90w6l6YSQgJHNhJCAkbmVwb3R2cmR6dWplJCAtIHZ5xaHFocOtIHRsYWsgdmVkaWUgayBuacW+xaFlaiB0ZXBsb3RlLCDEjW8gamUgb3BhxI1uw70gZWZla3QgYWtvIHNtZSBwcmVkcG9rbGFkYWxpLg0KDQojIyBQb3Jvdm5hbmllIGVtcGlyaWNrw71jaCBhIGZpdG92YW7DvWNoIGhvZG7DtHQNCg0KYGBge3J9DQpkYXRhX2J1ZGFwZXN0JGZpdHRlZCA8LSBmaXR0ZWQobW9kZWwpDQoNCmdncGxvdChkYXRhX2J1ZGFwZXN0LCBhZXMoeCA9IERBVEUsIHkgPSBCVURBUEVTVF90ZW1wX21lYW4pKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAyKSArDQogIGdlb21fbGluZShhZXMoeSA9IGZpdHRlZCksIGNvbG9yID0gInJlZCIsIHNpemUgPSAxKSArDQogIGxhYnModGl0bGUgPSAiVGVwbG90YSB2IEJ1ZGFwZcWhdGk6IEVtcGlyaWNrw6kgdnMgRml0b3ZhbsOpIGhvZG5vdHkiLA0KICAgICAgIHggPSAiRMOhdHVtIiwgeSA9ICJUZXBsb3RhICjCsEMpIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KRG9taW5hbnRuw71tIHBydmtvbSBqZSB2w71yYXpuw6Egcm/EjW7DoSBzZXrDs25ub3PFpSBzIHBlcmlvZGlja8O9bWkgbWluaW1hbWkgdiB6aW1lIChjY2EgJC0xMCTCsEMpIGEgbWF4aW1hbWkgdiBsZXRlIChhxb4gZG8gY2NhICQzNSTCsEMpLiANCg0KRml0b3ZhbsO9IG1vZGVsIMO6c3BlxaFuZSB6YWNoeXTDoXZhIGhsYXZuw70gcm/EjW7DvSBjeWtsdXMgYSBkbGhvZG9iw70gc3RhY2lvbsOhcm55IHRyZW5kIGTDoXRvdsOpaG8gcmFkdS4gDQoNCkF2xaFhaywgZW1waXJpY2vDqSBob2Rub3R5IHZ5a2F6dWrDuiB6bmHEjW7DuiB2eXNva29mcmVrdmVuxI1uw7ogdmFyaWFiaWxpdHUgYSBleHRyw6lteSwga3RvcsOpIG1vZGVsIMSNYXN0byBwb2Rob2Rub2N1amUsIMSNbyBpbXBsaWt1amUgc2lnbmlmaWthbnRuw6kgcmV6aWR1w6FsbmUgY2h5YnkgdiBhcHJveGltw6FjaWkga3LDoXRrb2RvYsO9Y2ggdsO9a3l2b3YuDQoNCg0KIyMgQUNGIGdyYWYgcmV6w61kdcOtDQoNCmBgYHtyfQ0KcmVzIDwtIHJlc2lkdWFscyhtb2RlbCkNCg0KYWNmKHJlcywgbGFnLm1heCA9IDEyLCBtYWluID0gIkFDRiByZXrDrWR1w60iKQ0KYGBgDQpHcmFmIGF1dG9rb3JlbGHEjW5laiBmdW5rY2llIHJlesOtZHXDrSBkZW1vbsWhdHJ1amUgJHNpbG7DuiQgYSAkxaF0YXRpc3RpY2t5JCAkdsO9em5hbW7DuiQgcG96aXTDrXZudSBzw6lyaW92w7oga29yZWzDoWNpdSBwcmkgbsOtemt5Y2ggxI1hc292w71jaCBwb3N1bm9jaC4NCg0KUHJla3JvxI1lbmllIGludGVydmFsb3Ygc3BvxL5haGxpdm9zdGkgcG90dnJkenVqZSwgxb5lICRyZXrDrWR1w6EkICRuaWUkICRzw7okICRiaWVseSQgJMWhdW0kLiBUbyBpbmRpa3VqZSBuZWRvc3RhdG/EjW7DuiDFoXBlY2lmaWvDoWNpdSBtb2RlbHUsIGtlxI/FvmUgdiByZXrDrWR1w6FjaCB6b3N0w6F2YSBuZXphY2h5dGVuw6EgxI1hc292byB6w6F2aXNsw6EgKGF1dG9rb3JlbGHEjW7DoSkgxaF0cnVrdMO6cmEgZMOhdC4NCg0KIyMgRHVyYmlu4oCTV2F0c29uIHRlc3QNCg0KYGBge3J9DQpkd3Rlc3QobW9kZWwpDQpgYGANCi0gJERXIMWhdGF0aXN0aWthID0gMC41ODIzMiQgLSB0w6F0byBob2Rub3RhIGplIHbDvXJhem5lIG5pxb7FoWlhIGFrbyAkMiQsIMSNbyBqYXNuZSBpbmRpa3VqZSBwcsOtdG9tbm9zxaUgc2lsbmVqIHBveml0w612bmVqIGF1dG9rb3JlbMOhY2llIHYgcmV6w61kdcOhY2ggbW9kZWx1Lg0KDQotICRwLWhvZG5vdGEgPCAyLjJlLTE2JCAtIHTDoXRvIGV4dHLDqW1uZSBuw616a2EgaG9kbm90YSBqZSB2w71yYXpuZSBuacW+xaFpYSBha28gxaF0YW5kYXJkbsOhIGhsYWRpbmEgdsO9em5hbW5vc3RpICTOsSA9IDAuMDUkLCDEjW8gbsOhbSB1bW/FvsWIdWplIHphbWlldG51xaUgbnVsb3bDuiBoeXBvdMOpenUgbyBhYnNlbmNpaSBhdXRva29yZWzDoWNpZS4NCg0KIyMgQnJldXNjaOKAk0dvZGZyZXkgdGVzdA0KDQpgYGB7cn0NCmJndGVzdChtb2RlbCwgb3JkZXIgPSAxKQ0KYGBgDQotICRMTSB0ZXN0ID0gMTg1Mi43JCAtIHTDoXRvIGV4dHLDqW1uZSB2eXNva8OhIGhvZG5vdGEgdGVzdG92YWNlaiDFoXRhdGlzdGlreSBqYXNuZSBwb3R2cmR6dWplIHByw610b21ub3PFpSB2w71yYXpuZWogc8OpcmlvdmVqIGtvcmVsw6FjaWUgdiBtb2RlbGkuDQoNCi0gJHAtaG9kbm90YSA8IDIuMmUtMTYkIC0gdMOhdG8gZXh0csOpbW5lIG7DrXprYSBob2Rub3RhIGplIHbDvXJhem5lIG5pxb7FoWlhIGFrbyBha8Oha2/EvnZlayDFoXRhbmRhcmRuw6EgaGxhZGluYSB2w716bmFtbm9zdGkgKCTOsSA9IDAuMDUsIDAuMDEsIDAuMDAxJCkuDQoNCk3DtMW+ZW1lIHJvemhvZG5lICR6YW1pZXRudcWlJCAkbnVsb3bDuiQgJGh5cG90w6l6dSQgbyBhYnNlbmNpaSBzw6lyaW92ZWoga29yZWzDoWNpZS4gRXhpc3R1amUgxaF0YXRpc3RpY2t5ICR2eXNva28kICR2w716bmFtbsOhJCBhdXRva29yZWzDoWNpYSBwcnbDqWhvIHLDoWR1IHYgcmV6w61kdcOhY2ggbW9kZWx1Lg0KDQojIyBLb3lja292YSB0cmFuc2Zvcm3DoWNpYQ0KDQpgYGB7cn0NCmRhdGFfYnVkYXBlc3QgPC0gZGF0YV9idWRhcGVzdCAlPiUNCiAgbXV0YXRlKEJVREFQRVNUX3RlbXBfbWVhbl9sYWcxID0gbGFnKEJVREFQRVNUX3RlbXBfbWVhbikpDQoNCm1vZGVsX2tveWNrIDwtIGxtKEJVREFQRVNUX3RlbXBfbWVhbiB+IEJBU0VMX3RlbXBfbWVhbiArIEJVREFQRVNUX2h1bWlkaXR5ICsgQlVEQVBFU1RfcHJlc3N1cmUgKw0KICAgICAgICAgICAgICAgICAgICBCVURBUEVTVF90ZW1wX21lYW5fbGFnMSwNCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX2J1ZGFwZXN0KQ0KDQpzdW1tYXJ5KG1vZGVsX2tveWNrKQ0KDQpkd3Rlc3QobW9kZWxfa295Y2spDQpgYGANClbDvXJhem7DqSB6bGVwxaFlbmllIG1vZGVsdToNCg0KLSAkUi1zcXVhcmVkID0gMC45NTUkIOKGkiBtb2RlbCB2eXN2ZXTEvnVqZSAkOTUuNSQlIHZhcmlhYmlsaXR5IHRlcGxvdHkgKHYgcG9yb3ZuYW7DrSBzIHDDtHZvZG7DvW1pICQ4NS44NiQlKQ0KDQotIFJlemlkdcOhbG5hIHNtZXJvZGFqbsOhIG9kY2jDvWxrYSA9ICQxLjg1NSTCsEMgKHbDvXJhem7DqSB6bGVwxaFlbmllIHogcMO0dm9kbsO9Y2ggJDMuMjkkwrBDKQ0KDQotIFJvenNhaCByZXrDrWR1w60gc2Egem1lbsWhaWwgeiBww7R2b2Ruw71jaCAkwrExNiTCsEMgbmEgJMKxOSTCsEMNCg0KTW9kZWwgamUgJHZ5c29rbyQgJHbDvXpuYW1uw70kICgkcCA8IDIuMmUtMTYkKSBzbyB2xaFldGvDvW1pIHByZW1lbm7DvW1pIMWhdGF0aXN0aWNreSB2w716bmFtbsO9bWkuDQoNCkFuYWzDvXphIGtvZWZpY2llbnRvdjoNCg0KLSBPbmVza29yZW7DoSB0ZXBsb3RhICgkMC43MDQkKSDihpIgc2lsbsO9IHBveml0w612bnkgdnBseXYsIHRlcGxvdGEgeiBwcmVkY2jDoWR6YWrDumNlaG8gZMWIYSB2eXN2ZXTEvnVqZSB2ZcS+a8O6IMSNYXPFpSB2YXJpYWJpbGl0eQ0KDQotIFRlcGxvdGEgdiBCYXppbGVqaSAoJDAuMjk1JCkg4oaSIHZwbHl2IHpuw63FvmVuw70gYWxlIHN0w6FsZSB2eXNva28gJHbDvXpuYW1uw70kDQoNCi0gVmxoa29zxaUgKCQtMy41OTYkKSDihpIgdnBseXYgem7DrcW+ZW7DvSBhbGUgc3TDoWxlICR2w716bmFtbsO9JA0KDQotIFRsYWsgKCQtNTQuNDg5JCkg4oaSIHZwbHl2IHpuw63FvmVuw70gYWxlIHN0w6FsZSAkdsO9em5hbW7DvSQNCg0KRHVyYmluLVdhdHNvbiB0ZXN0IHBvIHRyYW5zZm9ybcOhY2lpOg0KDQotICREVyA9IDEuNTYwNCQg4oaSIHbDvXJhem7DqSB6bGVwxaFlbmllIHogcMO0dm9kbsO9Y2ggJDAuNTgyMzIkDQoNCkhvZG5vdGEgamUgYmxpxb7FoWllIGsgJDIkLCDEjW8gaW5kaWt1amUgc2xhYsWhaXUgcG96aXTDrXZudSBhdXRva29yZWzDoWNpdS4NCg0KLSAkcC12YWx1ZSA8IDIuMmUtMTYkIOKGkiBhdXRva29yZWzDoWNpYSBuaWUgamUgw7pwbG5lIGVsaW1pbm92YW7DoSwgYWxlIGplIHbDvXJhem5lIHJlZHVrb3ZhbsOhDQoNCktveWNrb3ZhIHRyYW5zZm9ybcOhY2lhIHbDvXJhem5lICR6bGVwxaFpbGEkIG1vZGVsLCBhbGUgw7pwbG5lICRuZW9kc3Ryw6FuaWxhJCAkcHJvYmzDqW0kIGF1dG9rb3JlbMOhY2llLg0KDQojIyBOZXdleeKAk1dlc3Qgcm9idXN0bsOpIMWhdGFuZGFyZG7DqSBjaHlieQ0KDQpgYGB7cn0NCmNvZWZ0ZXN0KG1vZGVsLCB2Y292ID0gTmV3ZXlXZXN0KG1vZGVsKSkNCmBgYA0KxaB0YW5kYXJkbsOpIGNoeWJ5IHNhIHbFoWV0a3kgenbDvcWhaWxpIHBvIGFwbGlrw6FjaWkgcm9idXN0bmVqIGtvcmVrY2llOg0KDQotIEludGVyY2VwdDogeiAkNy4zNTUkIG5hICQxNS40MDgkICgkMi4xw5ckIHZ5xaHFoWlhKQ0KDQotIEJBU0VMX3RlbXBfbWVhbjogeiAkMC4wMDg0OCQgbmEgJDAuMDE2MDgkICgkMS45w5ckIHZ5xaHFoWlhKQ0KDQotIEJVREFQRVNUX2h1bWlkaXR5OiB6ICQwLjQxNDgkIG5hICQwLjgxMTQkICgkMi4ww5ckIHZ5xaHFoWlhKQ0KDQotIEJVREFQRVNUX3ByZXNzdXJlOiB6ICQ3LjE2NiQgbmEgJDE0Ljk2MCQgKCQyLjHDlyQgdnnFocWhaWEpDQoNCk5hcHJpZWsgenbDvcWhZW5pdSDFoXRhbmRhcmRuw71jaCBjaMO9YiwgdsWhZXRreSBwcmVtZW5uw6kgb3N0w6F2YWrDuiB2eXNva28gxaF0YXRpc3RpY2t5ICR2w716bmFtbsOpJC4NCg0KIyMgWsOhdmVyDQoNCkFuYWzDvXphIHBvdHZyZGlsYSwgxb5lIHDDtHZvZG7DvSBtb2RlbCB0ZXBsb3R5IHYgQnVkYXBlxaF0aSBib2wgxaF0YXRpc3RpY2t5IHZ5c29rbyB2w716bmFtbsO9IHMgdnluaWthasO6Y291IHZ5c3ZldMS+dWrDumNvdSBzaWxvdSAoJFLCsiA9IDg1Ljg2JCUpLCBhdsWhYWsgdHJwZWwgesOhdmHFvm7DvW0gcHJvYmzDqW1vbSBzaWxuZWogcG96aXTDrXZuZWogYXV0b2tvcmVsw6FjaWUgcmV6w61kdcOtICgkRFcgPSAwLjU4JCwgQkcgdGVzdCAkcCA8IDIuMmUtMTYkKS4gDQoNCkh5cG90w6l6eSAkSDEkIGEgJEgyJCAkc2EkIHBsbmUgJHBvdHZyZGlsaSQgLSB0ZXBsb3RhIHYgQmF6aWxlamkgYSB2bGhrb3PFpSB2IEJ1ZGFwZcWhdGkgc8O6IMWhdGF0aXN0aWNreSAkdnlzb2tvJCAkdsO9em5hbW7DqSQgZGV0ZXJtaW5hbnR5IHRlcGxvdHkgcyBvxI1ha8OhdmFuw71tIHNtZXJvbSB2cGx5dnUuIEh5cG90w6l6YSAkSDMkICRzYSQgJG5lcG90dnJkaWxhJCwgcHJldG/FvmUgYXRtb3Nmw6lyaWNrw70gdGxhayBtYWwgb3BhxI1uw70gc21lciB2cGx5dnUgYWtvIHNhIHByZWRwb2tsYWRhbG8sIG5vIGJvbCB0aWXFviDFoXRhdGlzdGlja3kgJHZ5c29rbyQgJHbDvXpuYW1uw70kLg0KDQpBcGxpa8OhY2lhIEtveWNrb3ZlaiB0cmFuc2Zvcm3DoWNpZSB2w71yYXpuZSB6bGVwxaFpbGEgbW9kZWwgLSB6dsO9xaFpbGEgdnlzdmV0xL51asO6Y3Ugc2lsdSBuYSAkOTUuNSQlIGEgcmVkdWtvdmFsYSBhdXRva29yZWzDoWNpdSAoJERXID0gMS41NiQpLCDEjcOtbSBkZW1vbsWhdHJvdmFsYSBkw7RsZcW+aXRvc8WlIHphaHJudXRpYSDEjWFzb3bDqWhvIHJvem1lcnUgZG8gbW9kZWx1LiBOYXByaWVrIHRvbXUsIGF1dG9rb3JlbMOhY2lhIG5lYm9sYSDDunBsbmUgZWxpbWlub3ZhbsOhLg0KDQpSb2J1c3Ruw6EgTmV3ZXktV2VzdCBrb3Jla2NpYSBwb3R2cmRpbGEgc3BvxL5haGxpdm9zxaUgb2RoYWRvdiAtIHbFoWV0a3kgcHJlbWVubsOpIG9zdGFsaSAkdnlzb2tvJCAkdsO9em5hbW7DqSQgYWogcG8ga29uemVydmF0w612bmVqIGtvcmVrY2lpIMWhdGFuZGFyZG7DvWNoIGNow71iLCDEjW8gc3ZlZMSNw60gbyByb2J1c3Rub3N0aSBpZGVudGlmaWtvdmFuw71jaCB2esWlYWhvdi4NCg0KTW9kZWwgamUgdmhvZG7DvSBwcmUgcHJlZGlrY2l1IHRlcGxvdHksIG5vIHByZSBwcmVzbmVqxaFpZSBvZGhhZHkgYnkgYm9sbyB2aG9kbsOpIHV2YcW+b3ZhxaUgcG9rcm/EjWlsZWrFoWllIMSNYXNvdm8gcmFkb3bDqSBtb2RlbHksIGt0b3LDqSBieSBsZXDFoWllIHphY2h5dGlsaSBzZXrDs25udSBkeW5hbWlrdSBhIMO6cGxuZSBlbGltaW5vdmFsaSBwcm9ibMOpbSBhdXRva29yZWzDoWNpZS4NCg==