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

dwtest(model)

    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

bgtest(model, order = 1)

    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.

Koyckova transformácia

data_budapest <- data_budapest %>%
  mutate(BUDAPEST_temp_mean_lag1 = lag(BUDAPEST_temp_mean))

model_koyck <- lm(BUDAPEST_temp_mean ~ BASEL_temp_mean + BUDAPEST_humidity + BUDAPEST_pressure +
                    BUDAPEST_temp_mean_lag1,
                  data = data_budapest)

summary(model_koyck)

Call:
lm(formula = BUDAPEST_temp_mean ~ BASEL_temp_mean + BUDAPEST_humidity + 
    BUDAPEST_pressure + BUDAPEST_temp_mean_lag1, data = data_budapest)

Residuals:
   Min     1Q Median     3Q    Max 
-9.296 -1.096  0.148  1.218  7.268 

Coefficients:
                          Estimate Std. Error t value Pr(>|t|)    
(Intercept)              58.125838   4.366449   13.31   <2e-16 ***
BASEL_temp_mean           0.294767   0.008905   33.10   <2e-16 ***
BUDAPEST_humidity        -3.596009   0.241125  -14.91   <2e-16 ***
BUDAPEST_pressure       -54.489003   4.242025  -12.85   <2e-16 ***
BUDAPEST_temp_mean_lag1   0.704293   0.007964   88.43   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.855 on 3648 degrees of freedom
  (1 пропущенное наблюдение удалено)
Multiple R-squared:  0.955, Adjusted R-squared:  0.955 
F-statistic: 1.936e+04 on 4 and 3648 DF,  p-value: < 2.2e-16
dwtest(model_koyck)

    Durbin-Watson test

data:  model_koyck
DW = 1.5604, p-value < 2.2e-16
alternative hypothesis: true autocorrelation is greater than 0

Výrazné zlepšenie modelu:

  • \(R-squared = 0.955\) → model vysvetľuje \(95.5\)% variability teploty (v porovnaní s pôvodnými \(85.86\)%)

  • Reziduálna smerodajná odchýlka = \(1.855\)°C (výrazné zlepšenie z pôvodných \(3.29\)°C)

  • Rozsah rezíduí sa zmenšil z pôvodných \(±16\)°C na \(±9\)°C

Model je \(vysoko\) \(významný\) (\(p < 2.2e-16\)) so všetkými premennými štatisticky významnými.

Analýza koeficientov:

  • Oneskorená teplota (\(0.704\)) → silný pozitívny vplyv, teplota z predchádzajúceho dňa vysvetľuje veľkú časť variability

  • Teplota v Bazileji (\(0.295\)) → vplyv znížený ale stále vysoko \(významný\)

  • Vlhkosť (\(-3.596\)) → vplyv znížený ale stále \(významný\)

  • Tlak (\(-54.489\)) → vplyv znížený ale stále \(významný\)

Durbin-Watson test po transformácii:

  • \(DW = 1.5604\) → výrazné zlepšenie z pôvodných \(0.58232\)

Hodnota je bližšie k \(2\), čo indikuje slabšiu pozitívnu autokoreláciu.

  • \(p-value < 2.2e-16\) → autokorelácia nie je úplne eliminovaná, ale je výrazne redukovaná

Koyckova transformácia výrazne \(zlepšila\) model, ale úplne \(neodstránila\) \(problém\) autokorelácie.

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==