Pokračujeme v predchádzajúcich úlohách, kde s pomocou regresnej
analýzy skúmame, ako demografické ukazovatele ovplyvňujú predpokladanú
veľkosť populácie krajín v roku 2025. V našom modeli sa zameriavame na
tri hlavné vysvetľujúce premenné:
Cieľom analýzy je zistiť, či a akým spôsobom tieto demografické
faktory prispievajú k očakávanému počtu obyvateľov v roku 2025.
Výsledok regresie je uvedený nižšie.
Testovať, či je model v správnej funkčnej forme (t. j. či je lineárna
špecifikácia vhodná, alebo či by ste mali transformovať premenné,
napríklad pomocou logaritmov alebo mocninami), možno vykonať viacerými
spôsobmi.
1. Test RESET (test chyby špecifikácie Ramseyho regresnej rovnice -
Ramsey Reset Test)
Ide o najštandardnejší formálny test nesprávnej špecifikácie funkčnej
formy ale dá sa použiť aj pre prípady, ak sme nešpecifikovali všetky
vysvetľujúce premenné.
Myšlienka: Nech pôvodný model má tvar \[y_t = \beta_0 + \beta_1 x_{t10} + \dots +\beta_k
x_{tk} + u_t\] Ak je váš model správne špecifikovaný, potom
pridaním mocnín vyrovnaných hodnôt (napr. \(\hat y_t^2\), \(\hat{y}_t^3\)) by sa pôvodný model nemal
podstatne zlepšiť, teda budeme testovať pôvodný model uvedený vyššie a
model
\[y_t = \beta_0 + \beta_1 x_{t10} + \dots
+\beta_k x_{tk} + \gamma_2\hat y_t^2 + \gamma_3\hat{y}_t^3 +
u_t\]
Budeme testovať hypotézu
\(H_0:\) model je správne
špecifikovaný (\(\gamma_2 = \gamma_3 =
0\))
oproti
\(H_1:\) model je nesprávne
špecifikovaný (\(\gamma_2 \ne 0 \quad
\text{alebo} \quad \gamma_3 \ne 0\))
library(lmtest)
# tvoj model:
model <- lm(Population.2025 ~ Fert..Rate + Median.Age + Migrants..net.,
data = data_selected)
# RESET test – test nesprávnej špecifikácie modelu
reset_results <- resettest(model, power = 2:3, type = "fitted")
reset_results
RESET test
data: model
RESET = 0.9428, df1 = 2, df2 = 227, p-value = 0.3911
Interpretácia: 🧪 RESET test – kontrola špecifikácie
modelu
Výsledok RESET testu:
- RESET = 0.9428
- p-value = 0.3911
Keďže p-value je vyššia ako 0.05, nezamietame
nulovú hypotézu, že model je správne špecifikovaný.
➡️ Model nepreukazuje chybnú funkčnú formu.
➡️ Nie je potrebné pridávať nelineárne členy ani ďalšie
premenné.
Model podľa RESET testu zodpovedá vhodnej
špecifikácii.
4. Porovnanie základného a modifikovaného modelu
Na základe grafov Component + Residual sme identifikovali, že
najväčší odklon od linearity vykazujú premenné Median.Age a
Migrants..net.. Tieto premenné nevytvárajú striktne lineárny vzťah so
závislou premennou Population.2025, čo naznačuje možnú potrebu doplnenia
kvadratických členov.
Preto predpokladáme, že pri nelineárnych úpravách pôvodného modelu
dôjde k zlepšeniu jeho špecifikácie práve po zavedení kvadrátov
premenných Median.Age² a Migrants..net.². Ich správanie v C+R grafoch
naznačovalo mierne zakrivenie, ktoré sa výraznejšie odchyľovalo od
priamky.
Ak má transformovaný model vyšší upravený koeficient determinácie
\(R^2_{adj}\), lepšiu štatistickú
významnosť a zároveň RESET test nepotvrdí nesprávnu špecifikáciu, môžeme
nový model považovať za vhodnejší. Odporúčame výsledky ďalej podporiť aj
porovnaním oboch modelov pomocou ANOVA testu, ktorý overí, či má
rozšírený model štatisticky významne lepšiu výkonnosť.
# Základný lineárny model
model <- lm(Population.2025 ~ 1 + Fert..Rate + Median.Age + Migrants..net.,
data = data_selected)
# Model s kvadratickými členmi na základe C+R grafov
model_kvadr <- lm(Population.2025 ~ 1 + Fert..Rate +
Median.Age + I(Median.Age^2) +
Migrants..net. + I(Migrants..net.^2),
data = data_selected)
# Výstupy modelu
summary(model_kvadr)
Call:
lm(formula = Population.2025 ~ 1 + Fert..Rate + Median.Age +
I(Median.Age^2) + Migrants..net. + I(Migrants..net.^2), data = data_selected)
Residuals:
Min 1Q Median 3Q Max
-93614219 -33867568 -24064751 -8026469 1418718877
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.873e+08 2.533e+08 0.739 0.461
Fert..Rate -2.194e+07 2.375e+07 -0.923 0.357
Median.Age -4.326e+06 1.151e+07 -0.376 0.707
I(Median.Age^2) 2.863e+04 1.502e+05 0.191 0.849
Migrants..net. 2.049e+02 1.952e+02 1.050 0.295
I(Migrants..net.^2) -8.655e-05 1.324e-04 -0.654 0.514
Residual standard error: 139500000 on 227 degrees of freedom
Multiple R-squared: 0.01705, Adjusted R-squared: -0.004599
F-statistic: 0.7876 on 5 and 227 DF, p-value: 0.5596
# Porovnanie základného a nelineárneho modelu
anova(model, model_kvadr)
Analysis of Variance Table
Model 1: Population.2025 ~ 1 + Fert..Rate + Median.Age + Migrants..net.
Model 2: Population.2025 ~ 1 + Fert..Rate + Median.Age + I(Median.Age^2) +
Migrants..net. + I(Migrants..net.^2)
Res.Df RSS Df Sum of Sq F Pr(>F)
1 229 4.4270e+18
2 227 4.4181e+18 2 8.9087e+15 0.2289 0.7956
# RESET test pre nelineárne rozšírený model
resettest(model_kvadr)
RESET test
data: model_kvadr
RESET = 0.74875, df1 = 2, df2 = 225, p-value = 0.4741
Takto modifikovaný model, v ktorom sme doplnili kvadrát premenných
Median.Age a Migrants..net., však neoznačuje žiadny z
kvadratických členov za štatisticky významný (p-hodnoty sú výrazne
väčšie ako 0,05). Zároveň nedochádza k zlepšeniu upraveného koeficientu
determinácie – naopak, jeho hodnota klesla na približne \(R^2_{\text{adj}} \approx -0{.}0046\).
Aj porovnanie modelov pomocou ANOVA (p-hodnota \(\approx 0{.}80\)) a RESET testu (p-hodnota
\(\approx 0{.}47\)) ukazuje, že
kvadratický model nie je lepší než pôvodný lineárny model. V ďalšej
analýze preto pracujeme s jednoduchším lineárnym modelom bez
kvadratických členov.
model_kvadr <- lm(Population.2025 ~ 1 + Fert..Rate + Median.Age + Migrants..net. +
I(Median.Age^2) + I(Migrants..net.^2),
data = data_selected)
summary(model_kvadr)
Call:
lm(formula = Population.2025 ~ 1 + Fert..Rate + Median.Age +
Migrants..net. + I(Median.Age^2) + I(Migrants..net.^2), data = data_selected)
Residuals:
Min 1Q Median 3Q Max
-93614219 -33867568 -24064751 -8026469 1418718877
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.873e+08 2.533e+08 0.739 0.461
Fert..Rate -2.194e+07 2.375e+07 -0.923 0.357
Median.Age -4.326e+06 1.151e+07 -0.376 0.707
Migrants..net. 2.049e+02 1.952e+02 1.050 0.295
I(Median.Age^2) 2.863e+04 1.502e+05 0.191 0.849
I(Migrants..net.^2) -8.655e-05 1.324e-04 -0.654 0.514
Residual standard error: 139500000 on 227 degrees of freedom
Multiple R-squared: 0.01705, Adjusted R-squared: -0.004599
F-statistic: 0.7876 on 5 and 227 DF, p-value: 0.5596
Porovnanie základného a kvadraticky modifikovaného modelu
Do modelu sme pridali kvadratické členy premenných
Median.Age a Migrants..net. s cieľom zachytiť
možné nelineárne vzťahy. Výsledky však ukazujú, že ani jeden z týchto
kvadratických členov nie je štatisticky významný (všetky p-hodnoty sú
výrazne väčšie ako 0.05).
Upravený koeficient determinácie zostal v podstate nezmenený a má
hodnotu
\(R^2_{adj} =
-0.0046\), čo naznačuje, že kvadraticky rozšírený model
nevysvetľuje variabilitu dát lepšie ako pôvodný model.
Zavedenie kvadratických členov preto neprinieslo
zlepšenie a v ďalšej analýze budeme pokračovať s pôvodným
lineárnym modelom.
5. Použitie rozšíreného RESET testu
model_rozsireny <- lm(
Population.2025 ~
Fert..Rate +
Median.Age +
Migrants..net. +
I(Median.Age^2) +
I(Migrants..net.^2),
data = data_selected
)
summary(model_rozsireny)
Call:
lm(formula = Population.2025 ~ Fert..Rate + Median.Age + Migrants..net. +
I(Median.Age^2) + I(Migrants..net.^2), data = data_selected)
Residuals:
Min 1Q Median 3Q Max
-93614219 -33867568 -24064751 -8026469 1418718877
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.873e+08 2.533e+08 0.739 0.461
Fert..Rate -2.194e+07 2.375e+07 -0.923 0.357
Median.Age -4.326e+06 1.151e+07 -0.376 0.707
Migrants..net. 2.049e+02 1.952e+02 1.050 0.295
I(Median.Age^2) 2.863e+04 1.502e+05 0.191 0.849
I(Migrants..net.^2) -8.655e-05 1.324e-04 -0.654 0.514
Residual standard error: 139500000 on 227 degrees of freedom
Multiple R-squared: 0.01705, Adjusted R-squared: -0.004599
F-statistic: 0.7876 on 5 and 227 DF, p-value: 0.5596
V tomto kroku testujeme, či kvadratické členy
Median.Age² a Migrants..net.²
prinášajú do modelu štatisticky významné informácie.
Ak by boli významné, mali by sme uvažovať nad kvadratickou
transformáciou týchto premenných.
Na základe výstupu summary(model_rozsireny) však vidíme,
že:
- koeficient pri
I(Median.Age^2) nie je
štatisticky významný (p = 0.849),
- koeficient pri
I(Migrants..net.^2) taktiež nie
je štatisticky významný (p = 0.514).
anova(model,model_rozsireny)
Analysis of Variance Table
Model 1: Population.2025 ~ 1 + Fert..Rate + Median.Age + Migrants..net.
Model 2: Population.2025 ~ Fert..Rate + Median.Age + Migrants..net. +
I(Median.Age^2) + I(Migrants..net.^2)
Res.Df RSS Df Sum of Sq F Pr(>F)
1 229 4.4270e+18
2 227 4.4181e+18 2 8.9087e+15 0.2289 0.7956
resettest(model_rozsireny)
RESET test
data: model_rozsireny
RESET = 0.74875, df1 = 2, df2 = 225, p-value = 0.4741
Pri RESET teste vidíme, že p-hodnota 0.4741 je
výrazne vyššia ako hladina významnosti 0.05.
To znamená, že nezamietame nulovú hypotézu správnej špecifikácie
modelu.
Zároveň však platí, že ani rozšírený model s kvadratickými členmi
nebol štatisticky významný
(ANOVA p = 0.7956), takže prípadný problém nesprávnej
špecifikácie modelu sa neodstránil,
ale zároveň nebol ani potvrdený. Zavedenie
kvadratických členov neprinieslo zlepšenie modelu.
6. Transformácia pomocou dummy premennej a lineárnej lomenej
funkcie
Predpokladajme, že máme dummy premennú \(D_t\), ktorá obsahuje len nuly a jedničky.
Takáto premenná sa dá využiť modelovanie zlomov, a to napr.
- zlom v autonómnom člene \(\beta_0\)
a to nasledovnou špecifikáciou \[y_t =
\beta_0 + \beta_D D+ \beta_1 x_{t1} + \dots +\beta_k x_{tk} +
u_t\] čo interpretujeme ako posun regresnej priamky (regresnej
nadroviny) o \(\beta_D\) jednotiek
pozdĺž zvislej osi a to len v pozorovaniach, ak je splnená podmienka
\(D_t = 1\)
- zlom v sklone regresnej priamky (nadroviny) a to len v
pozorovaniach, ak je splnená podmienka \(D_t =
1\), čo dosiahneme nasledovnou špecifikáciou \[y_t = \beta_0 + \beta_1 x_{t1} + \dots +
\beta_{i}x_{ti} + \beta_{Di}D_tx_{ti}+ \dots + \beta_k x_{tk} +
u_t\] kde teda sklon priamky pozdĺž premenne \(x_{ti}\) je \(\beta_i\) ale len v prípade \(D_t=0\), inak je ten sklon rovný \(\beta_i+\beta_{D_i}\).
Ak si pozrieme C+R grafy pre naše vysvetľujúce premenné, vidíme, že
najvýraznejšie odchýlky od linearity sa objavujú pri premenných
Migrants..net. a Median.Age. Vyrovnaná krivka pri
oboch premenných naznačuje mierne zakrivenie, najmä pri extrémnejších
hodnotách, čo môže signalizovať potrebu nelineárnej úpravy (t.j.
zavedenie kvadratického člena). Preto sme do modelu zaradili premenné
I(Median.Age²) a I(Migrants..net.²),
aby sme otestovali, či tieto nelineárne efekty dokážu zlepšiť
špecifikáciu modelu.
Kvantifikujme teraz model so zlomom v autonómnom členovi.
Keďže podľa C+R grafov zaznamenávame nelineárne správanie pri premenných
Migrants..net., zavedieme novú dummy premennú, ktorá rozdelí
krajiny podľa úrovne migrácie.
Nech
\(DUM_t = 0\) pre hodnoty
Migrants..net. nižšie ako medián
a
\(DUM_t = 1\) pre hodnoty
Migrants..net. vyššie alebo rovné mediánu.
Takto budeme môcť posúdiť, či sa intercept modelu výrazne mení pri
vyšších hodnotách migrácie.
# prah si môžeme určiť ako medián
threshold <- median(data_selected$Migrants..net., na.rm = TRUE)
# dummy premenná podľa prahu
data_selected$DUM <- ifelse(data_selected$Migrants..net. < threshold, 0, 1)
# model so zlomom v autonómnom členovi
model_auto <- lm(Population.2025 ~ 1 + DUM + Fert..Rate + Median.Age +
Migrants..net.,
data = data_selected)
summary(model_auto)
Call:
lm(formula = Population.2025 ~ 1 + DUM + Fert..Rate + Median.Age +
Migrants..net., data = data_selected)
Residuals:
Min 1Q Median 3Q Max
-128357100 -38514919 -22145390 1662071 1409733516
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.053e+08 9.279e+07 1.135 0.2577
DUM 3.905e+07 2.333e+07 1.674 0.0955 .
Fert..Rate -1.922e+07 1.547e+07 -1.243 0.2152
Median.Age -1.852e+06 1.787e+06 -1.036 0.3011
Migrants..net. 7.029e+01 6.337e+01 1.109 0.2686
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 138500000 on 228 degrees of freedom
Multiple R-squared: 0.02703, Adjusted R-squared: 0.009957
F-statistic: 1.583 on 4 and 228 DF, p-value: 0.1796
Zavedením zlomovej premennej DUM došlo k miernemu zlepšeniu modelu,
keďže koeficient pri DUM vyšiel na hladine významnosti 10 % štatisticky
významný (p ≈ 0.0955). To naznačuje, že pre krajiny nad zvolenou
hranicou fertility sa úroveň populácie systematicky líši (má iný
intercept). Ostatné premenné ostali nevýznamné a upravený R² zostal
veľmi nízky (≈ 0.00996). Celkový F-test naznačuje, že model ako celok
nie je významný (p ≈ 0.1796). Zavedenie zlomovej premennej preto
neprinieslo zásadné zlepšenie kvality modelu.
modelD_sklon <- lm(Population.2025 ~ 1 + Fert..Rate + I(DUM * Fert..Rate) +
Median.Age + Migrants..net.,
data = data_selected)
summary(modelD_sklon)
Call:
lm(formula = Population.2025 ~ 1 + Fert..Rate + I(DUM * Fert..Rate) +
Median.Age + Migrants..net., data = data_selected)
Residuals:
Min 1Q Median 3Q Max
-131583667 -36676438 -22886410 -753794 1411771077
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.444e+08 8.974e+07 1.610 0.1089
Fert..Rate -3.348e+07 1.850e+07 -1.810 0.0717 .
I(DUM * Fert..Rate) 1.549e+07 1.077e+07 1.439 0.1517
Median.Age -2.011e+06 1.783e+06 -1.128 0.2606
Migrants..net. 7.529e+01 6.323e+01 1.191 0.2350
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 138700000 on 228 degrees of freedom
Multiple R-squared: 0.02393, Adjusted R-squared: 0.006805
F-statistic: 1.397 on 4 and 228 DF, p-value: 0.2357
📌 Interpretácia výsledkov modelu so zlomom v sklone (interakcia
DUM * Fert..Rate)
V tomto kroku sme do modelu zaviedli zmenu sklonu pre
premennú Fert..Rate pomocou interakčného člena
I(DUM * Fert..Rate). Premenná DUM
rozdeľuje pozorovania na dve skupiny podľa vopred určenej hranice a
testujeme, či fertilita ovplyvňuje veľkosť populácie rozdielne v týchto
dvoch skupinách.
📊 Výsledky regresného modelu
- Fert..Rate
- odhad:
-3.348e+07
- p-hodnota:
0.0717
→ účinok je slabo významný (približne na 10 % hladine).
- Interakcia
DUM * Fert..Rate
- odhad:
1.549e+07
- p-hodnota:
0.1517
→ interakčný efekt nie je štatisticky významný, teda sklon
Fert..Rate sa po zmene DUM výrazne nemení.
- Median.Age
- p-hodnota:
0.2606
→ nevýznamný efekt.
- Migrants..net.
- p-hodnota:
0.2350
→ takisto nevýznamný efekt.
📈 Hodnotenie kvality modelu
Multiple R-squared: 0.02393
Adjusted R-squared: 0.006805
→ model vysvetľuje len približne 2,4 % variability v
údajoch.
F-test modelu: p-hodnota =
0.2357
→ model ako celok nie je štatisticky významný.
📝 Záver
- Interakčný člen
DUM * Fert..Rate
nezlepšil kvalitu modelu a nie je štatisticky
významný.
- Neexistuje dôkaz, že fertilita má odlišný vplyv na populáciu v roku
2025 medzi dvomi skupinami definovanými podľa premennej
DUM.
- Model má veľmi nízke hodnoty \(R^2\) aj \(R^2_{\text{adj}}\), čo znamená slabú
vysvetľovaciu schopnosť.
- Model so zlomom v sklone preto neodporúčame používať ako
finálny model.
anova(model, modelD_sklon)
Analysis of Variance Table
Model 1: Population.2025 ~ 1 + Fert..Rate + Median.Age + Migrants..net.
Model 2: Population.2025 ~ 1 + Fert..Rate + I(DUM * Fert..Rate) + Median.Age +
Migrants..net.
Res.Df RSS Df Sum of Sq F Pr(>F)
1 229 4.4270e+18
2 228 4.3872e+18 1 3.982e+16 2.0694 0.1517
resettest(modelD_sklon)
RESET test
data: modelD_sklon
RESET = 0.92117, df1 = 2, df2 = 226, p-value = 0.3995
📌 Porovnanie modelov pomocou ANOVA a RESET testu
Na overenie, či zavedenie interakčného člena
DUM * Fert..Rate viedlo k zlepšeniu špecifikácie modelu,
sme použili ANOVA test a následne aj RESET
test.
🔍 Výsledky ANOVA testu
ANOVA porovnáva:
- Model 1:
Population.2025 ~ 1 + Fert..Rate + Median.Age + Migrants..net.
- Model 2 (rozšírený):
Population.2025 ~ 1 + Fert..Rate + I(DUM * Fert..Rate) + Median.Age + Migrants..net.
Výsledok:
- F = 2.0694,
- p-hodnota = 0.1517
👉 Keďže p-hodnota je väčšia ako 0.05, rozšírený
model nevykazuje štatisticky významné zlepšenie oproti základnému
modelu.
Interakčný člen teda neprispel k lepšiemu vysvetleniu
variability v dátach.
🧪 RESET test pre model so zlomom v sklone
Výsledok RESET testu:
- RESET = 0.92117
- df1 = 2, df2 = 226
- p-hodnota = 0.3995
👉 Keďže p-hodnota je opäť oveľa vyššia ako 0.05,
nezamietame nulovú hypotézu správnej špecifikácie modelu.
RESET test teda neindicuje chybnú funkčnú formu, ale
zároveň ani nepotvrdzuje, že interakcia priniesla
zlepšenie.
📝 Záver
- Ani ANOVA, ani RESET test
nepreukázali, že by zavedenie interakčného člena
DUM * Fert..Rate prispelo k zlepšeniu modelu.
- Model so zlomom v sklone nie je štatisticky lepší
ako pôvodný model.
- Neexistuje dôkaz, že fertilita má odlišný vplyv na
populáciu v rôznych skupinách definovaných premennou DUM.
- Zostávame teda pri závere, že tento model nie je vhodný ako
finálny a nepodporuje hypotézu o zmene sklonu.
LS0tCnRpdGxlOiAiTmVsaW5lw6FybmUgxaFwZWNpZmlrw6FjaWUiCm91dHB1dDogaHRtbF9ub3RlYm9vawphdXRob3I6IFJhZG92YW4gU3RhbsSNw61rCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgpgYGB7cn0KbGlicmFyeSh6b28pCmxpYnJhcnkodHNlcmllcykKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkoc2FuZHdpY2gpCmxpYnJhcnkoY2FyKQpybShsaXN0PWxzKCkpCmBgYAoKUG9rcmHEjXVqZW1lIHYgcHJlZGNow6FkemFqw7pjaWNoIMO6bG9ow6FjaCwga2RlIHMgcG9tb2NvdSByZWdyZXNuZWogYW5hbMO9enkgc2vDum1hbWUsIApha28gZGVtb2dyYWZpY2vDqSB1a2F6b3ZhdGVsZSBvdnBseXbFiHVqw7ogcHJlZHBva2xhZGFuw7ogdmXEvmtvc8WlIHBvcHVsw6FjaWUga3JhasOtbiB2IHJva3UgMjAyNS4gClYgbmHFoW9tIG1vZGVsaSBzYSB6YW1lcmlhdmFtZSBuYSB0cmkgaGxhdm7DqSB2eXN2ZXTEvnVqw7pjZSBwcmVtZW5uw6k6CgotICoqbWllcmEgcGxvZG5vc3RpIChGZXJ0aWxpdHkgUmF0ZSwgcG91xb5pdMOhIHYgbG9nYXJpdG1vdmFuZWogZm9ybWUpLCoqCi0gKiptZWRpw6Fub3bDvSB2ZWsgb2J5dmF0ZcS+c3R2YSAoTWVkaWFuIEFnZSksKioKLSAqKsSNaXN0w6EgbWlncsOhY2lhIChNaWdyYW50cy5uZXQpLioqCgpDaWXEvm9tIGFuYWzDvXp5IGplIHppc3RpxaUsIMSNaSBhIGFrw71tIHNww7Rzb2JvbSB0aWV0byBkZW1vZ3JhZmlja8OpIGZha3RvcnkgCnByaXNwaWV2YWrDuiBrIG/EjWFrw6F2YW7DqW11IHBvxI10dSBvYnl2YXRlxL5vdiB2IHJva3UgMjAyNS4gIApWw71zbGVkb2sgcmVncmVzaWUgamUgdXZlZGVuw70gbmnFvsWhaWUuCgpgYGB7cn0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUFLDjVBSQVZBIMOaREFKT1YKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIG5hxI3DrXRhbmllIGTDoXQKw7pkYWplIDwtIHJlYWQuY3N2KCJwb3B1bGF0aW9uX2RhdGEuY3N2IiwKICAgICAgICAgICAgICAgICAgc2VwID0gIiwiLAogICAgICAgICAgICAgICAgICBkZWMgPSAiLiIsCiAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUpCgrDumRhamUkRmVydC4uUmF0ZSA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcijDumRhamUkRmVydC4uUmF0ZSkpCsO6ZGFqZSRNZWRpYW4uQWdlIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKMO6ZGFqZSRNZWRpYW4uQWdlKSkKw7pkYWplJE1pZ3JhbnRzLi5uZXQuIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKMO6ZGFqZSRNaWdyYW50cy4ubmV0LikpCsO6ZGFqZSRQb3B1bGF0aW9uLjIwMjUgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIow7pkYWplJFBvcHVsYXRpb24uMjAyNSkpCgpkYXRhX3NlbGVjdGVkIDwtIMO6ZGFqZVssIGMoIlBvcHVsYXRpb24uMjAyNSIsICJGZXJ0Li5SYXRlIiwgIk1lZGlhbi5BZ2UiLCAiTWlncmFudHMuLm5ldC4iKV0KCiMgdsO9YmVyIHByZW1lbm7DvWNoLCBzIGt0b3LDvW1pIHByYWN1amVtZQpkYXRhX3NlbGVjdGVkIDwtIMO6ZGFqZVssIGMoIlBvcHVsYXRpb24uMjAyNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJGZXJ0Li5SYXRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhbi5BZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiTWlncmFudHMuLm5ldC4iKV0KCiMgb2RzdHLDoW5lbmllIGNow71iYWrDumNpY2ggaG9kbsO0dCBpbXB1dMOhY2lvdSBtZWRpw6Fub20KY29sdW1uX21lZGlhbnMgPC0gc2FwcGx5KGRhdGFfc2VsZWN0ZWQsIG1lZGlhbiwgbmEucm0gPSBUUlVFKQoKZGF0YV9pbXB1dGVkIDwtIGRhdGFfc2VsZWN0ZWQKZm9yIChjb2wgaW4gbmFtZXMoZGF0YV9pbXB1dGVkKSkgewogIGRhdGFfaW1wdXRlZFtbY29sXV1baXMubmEoZGF0YV9pbXB1dGVkW1tjb2xdXSldIDwtIGNvbHVtbl9tZWRpYW5zW2NvbF0KfQoKIyBrb25lxI1uw70gZGF0YXNldApkYXRhX3NlbGVjdGVkIDwtIGRhdGFfaW1wdXRlZAoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgWkFLTEFETkEgUkVHUkVTSUEKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKYXR0YWNoKMO6ZGFqZSkKbW9kZWwgPC0gbG0oUG9wdWxhdGlvbi4yMDI1IH4gRmVydC4uUmF0ZSArIE1lZGlhbi5BZ2UgKyBNaWdyYW50cy4ubmV0LiwgCiAgICAgICAgICAgIGRhdGEgPSBkYXRhX3NlbGVjdGVkKQpzdW1tYXJ5KG1vZGVsKQpgYGAKClRlc3RvdmHFpSwgxI1pIGplIG1vZGVsIHYgc3Byw6F2bmVqIGZ1bmvEjW5laiBmb3JtZSAodC4gai4gxI1pIGplIGxpbmXDoXJuYSDFoXBlY2lmaWvDoWNpYSB2aG9kbsOhLCBhbGVibyDEjWkgYnkgc3RlIG1hbGkgdHJhbnNmb3Jtb3ZhxaUgcHJlbWVubsOpLCBuYXByw61rbGFkIHBvbW9jb3UgbG9nYXJpdG1vdiBhbGVibyBtb2NuaW5hbWkpLCBtb8W+bm8gdnlrb25hxaUgdmlhY2Vyw71taSBzcMO0c29ibWkuCgojIyMgMS4gVGVzdCBSRVNFVCAodGVzdCBjaHlieSDFoXBlY2lmaWvDoWNpZSBSYW1zZXlobyByZWdyZXNuZWogcm92bmljZSAtIFJhbXNleSBSZXNldCBUZXN0KQoKSWRlIG8gbmFqxaF0YW5kYXJkbmVqxaHDrSBmb3Jtw6FsbnkgdGVzdCBuZXNwcsOhdm5laiDFoXBlY2lmaWvDoWNpZSBmdW5rxI1uZWogZm9ybXkgYWxlIGTDoSBzYSBwb3XFvmnFpSBhaiBwcmUgcHLDrXBhZHksIGFrIHNtZSBuZcWhcGVjaWZpa292YWxpIHbFoWV0a3kgdnlzdmV0xL51asO6Y2UgcHJlbWVubsOpLgoKTXnFoWxpZW5rYTogTmVjaCBww7R2b2Ruw70gbW9kZWwgbcOhIHR2YXIKJCR5X3QgPSBcYmV0YV8wICsgXGJldGFfMSB4X3t0MTB9ICsgXGRvdHMgK1xiZXRhX2sgeF97dGt9ICsgdV90JCQKQWsgamUgdsOhxaEgbW9kZWwgc3Byw6F2bmUgxaFwZWNpZmlrb3ZhbsO9LCBwb3RvbSBwcmlkYW7DrW0gbW9jbsOtbiB2eXJvdm5hbsO9Y2ggaG9kbsO0dCAobmFwci4gJFxoYXQgeV90XjIkLCAkXGhhdHt5fV90XjMkKSBieSBzYSBww7R2b2Ruw70gbW9kZWwgbmVtYWwgcG9kc3RhdG5lIHpsZXDFoWnFpSwgdGVkYSBidWRlbWUgdGVzdG92YcWlIHDDtHZvZG7DvSBtb2RlbCB1dmVkZW7DvSB2ecWhxaFpZSBhIG1vZGVsCgokJHlfdCA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfe3QxMH0gKyBcZG90cyArXGJldGFfayB4X3t0a30gKyBcZ2FtbWFfMlxoYXQgeV90XjIgKyBcZ2FtbWFfM1xoYXR7eX1fdF4zICsgdV90JCQKCkJ1ZGVtZSB0ZXN0b3ZhxaUgaHlwb3TDqXp1IAoKJEhfMDokIG1vZGVsIGplIHNwcsOhdm5lIMWhcGVjaWZpa292YW7DvSAoJFxnYW1tYV8yID0gXGdhbW1hXzMgPSAwJCkKCm9wcm90aQoKJEhfMTokIG1vZGVsIGplIG5lc3Byw6F2bmUgxaFwZWNpZmlrb3ZhbsO9ICgkXGdhbW1hXzIgXG5lIDAgIFxxdWFkIFx0ZXh0e2FsZWJvfSAgXHF1YWQgXGdhbW1hXzMgXG5lIDAkKQoKYGBge3IgcmVzZXRfdGVzdCwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShsbXRlc3QpCgojIHR2b2ogbW9kZWw6Cm1vZGVsIDwtIGxtKFBvcHVsYXRpb24uMjAyNSB+IEZlcnQuLlJhdGUgKyBNZWRpYW4uQWdlICsgTWlncmFudHMuLm5ldC4sIAogICAgICAgICAgICBkYXRhID0gZGF0YV9zZWxlY3RlZCkKCiMgUkVTRVQgdGVzdCDigJMgdGVzdCBuZXNwcsOhdm5laiDFoXBlY2lmaWvDoWNpZSBtb2RlbHUKcmVzZXRfcmVzdWx0cyA8LSByZXNldHRlc3QobW9kZWwsIHBvd2VyID0gMjozLCB0eXBlID0gImZpdHRlZCIpCnJlc2V0X3Jlc3VsdHMKCmBgYAoKKipJbnRlcnByZXTDoWNpYToqKgrwn6eqIFJFU0VUIHRlc3Qg4oCTIGtvbnRyb2xhIMWhcGVjaWZpa8OhY2llIG1vZGVsdQoKVsO9c2xlZG9rIFJFU0VUIHRlc3R1OgoKLSAqKlJFU0VUID0gMC45NDI4KiogIAotICoqcC12YWx1ZSA9IDAuMzkxMSoqCgpLZcSPxb5lIHAtdmFsdWUgamUgKip2ecWhxaFpYSBha28gMC4wNSoqLCAqbmV6YW1pZXRhbWUgbnVsb3bDuiBoeXBvdMOpenUqLCDFvmUgbW9kZWwgamUgc3Byw6F2bmUgxaFwZWNpZmlrb3ZhbsO9LiAgCgrinqHvuI8gKipNb2RlbCBuZXByZXVrYXp1amUgY2h5Ym7DuiBmdW5rxI1uw7ogZm9ybXUuKiogIArinqHvuI8gKipOaWUgamUgcG90cmVibsOpIHByaWTDoXZhxaUgbmVsaW5lw6FybmUgxI1sZW55IGFuaSDEj2FsxaFpZSBwcmVtZW5uw6kuKioKCk1vZGVsIHBvZMS+YSBSRVNFVCB0ZXN0dSAqKnpvZHBvdmVkw6EgdmhvZG5laiDFoXBlY2lmaWvDoWNpaSoqLgoKCiMjIyAyLiBHcmFmaWNrw6EgYW5hbMO9emEKIyMjIyBHcmFmICpSZXNpZHVhbHMgdnMuIEZpdHRlZCoKCkdyYWZpY2vDoSBhbmFsw716YSB2esWlYWh1IG1lZHppIHZ5cm92bmFuw71taSBob2Rub3RhbWkgbsOhaG9kbmVqIHByZW1lbm5laiBhIHJlesOtZHVhbWk6CgpgYGB7cn0KcGxvdChtb2RlbCwgd2hpY2ggPSAxKQpgYGAKCiMjIyDwn5OKIEludGVycHJldMOhY2lhIGdyYWZ1ICpSZXNpZHVhbHMgdnMuIEZpdHRlZCoKCk5hIGdyYWZlICpSZXNpZHVhbHMgdnMuIEZpdHRlZCogc2kgdsWhw61tYW1lIHJvemxvxb5lbmllIHJlemlkdcOtIG9rb2xvIGhvcml6b250w6FsbmVqIMSNaWFyeS4gIApaIG7DocWhaG8gZ3JhZnUgbW/Fvm5vIHBvem9yb3ZhxaUgbmFzbGVkb3Zuw6k6CgotIFbDpMSNxaFpbmEgcmV6aWR1w60gc2EgbmFjaMOhZHphICoqYmzDrXprbyBudWxvdmVqIG9zaSoqLCDEjW8gbmF6bmHEjXVqZSwgxb5lIG1vZGVsIG5ldnlrYXp1amUgc3lzdGVtYXRpY2vDqSBjaHlieS4KLSBSZXppZHXDoSBuZXZ5dHbDoXJhasO6IMW+aWFkbnkgdsO9cmF6bsO9IHR2YXIgKG5hcHIuIHBhcmFib2xhIGFsZWJvIGxpZXZpayksIHRha8W+ZSAqKm5pZSBzw7ogdmlkaXRlxL5uw6kgem7DoW1reSBuZWxpbmVhcml0eSoqLgotIE5lb2JqYXZ1amUgc2EgYW5pIHR5cGlja8O9IOKAnnJvesWhaXJ1asO6Y2kgc2EgbGlldmlr4oCcLCDEjWnFvmUgKipoZXRlcm9za2VkYXN0aWNpdGEgbmllIGplIHZpenXDoWxuZSB6cmVqbcOhKiouCi0gViBncmFmZSBzYSB2eXNreXR1amUgbmlla2/EvmtvIG9kxL5haGzDvWNoIGJvZG92IChleHRyw6ltbmUgxaF0w6F0eSksIMSNbyBqZSBwcmkgZGVtb2dyYWZpY2vDvWNoIGTDoXRhY2ggYmXFvm7DqSBhIG5lb8SNYWvDoXZhIHNhLCDFvmUgYnkgem5laG9kbm90aWxpIGNlbMO9IG1vZGVsLgoKIyMjIOKchSBaw6F2ZXIKTmEgesOha2xhZGUgZ3JhZmlja2VqIGRpYWdub3N0aWt5IG1vxb5ubyBwb3ZlZGHFpSwgxb5lICoqbW9kZWwgbmV2eWthenVqZSB6w6F2YcW+bsOpIMWhdHJ1a3R1csOhbG5lIHByb2Jsw6lteSoqLiAgClNwcsOhdmFuaWUgcmV6aWR1w60gamUgcHJpbWVyYW5lIG7DoWhvZG7DqSwgxI1vIHBvZHBvcnVqZSB6w6F2ZXJ5IGFqIHogUkVTRVQgdGVzdHUuCgoKCiMjIyMgR3JhZnkgQytSICoqClTDoXRvIGFuYWzDvXphIG7DoW0gbcO0xb5lIHBvbcO0Y8WlIHByaSBoxL5hZGFuw60gb2Rwb3ZlZGUgbmEgb3TDoXprdSwga3RvcsO6IHByZW1lbm7DuiBieSBzbWUgbWFsaSB0cmFuc2ZvbW92YcWlIHBvbW9jb3UgbmVqYWtlaiB6bsOhbWVqIGZ1bmtjaWUuIFZ5Y2jDoWR6YWptZSB6IHDDtHZvZG5laiByb3ZuaWNlCgokJHlfdCA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfe3QxfSArIFxkb3RzICtcYmV0YV9rIHhfe3RrfSArIHVfdCQkClTDunRvIHJvdm5pY3UgbmFqcHJ2IG9kaGFkbmVtZSBhIHBvdG9tIHZ5a3Jlc8S+dWplbWUgZ3JhZnksIGtkZSB2w71yYXogY29tcG9uZW50K3Jlc2lkdWFsIChDK1IpIHBsb3QgdnlrcmVzxL51amUgbmEgenZpc2xlaiBvc2kgJFxoYXR7XGJldGF9X2l4X3t0aX0rZV90JCBhIG5hIHZvZG9yb3ZuZWogb3NpIHZ5a3Jlc8S+dWplIGhvZG5vdHkgJHhfe3RpfSQKClRpZXRvIGdyYWZ5IHBvbcOhaGFqw7ogaWRlbnRpZmlrb3ZhxaUgbmVsaW5lw6FybmUgdnrFpWFoeSBwcmUga2HFvmTDvSByZWdyZXNvcjoKCmBgYHtyfQpjYXI6OmNyUGxvdHMobW9kZWwpCgpgYGAKIyMjIPCfk4ogSW50ZXJwcmV0w6FjaWEgQ29tcG9uZW50ICsgUmVzaWR1YWwgKEMrUikgZ3JhZm92CgpDaWXEvm9tIEMrUiBncmFmb3YgamUgb3ZlcmnFpSwgxI1pIGplIHZ6xaVhaCBtZWR6aSBqZWRub3RsaXbDvW1pIHJlZ3Jlc29ybWkgYSB6w6F2aXNsb3UgcHJlbWVubm91IGxpbmXDoXJueSwgYWxlYm8gxI1pIGJ5IG1vaGxhIGJ5xaUgdmhvZG7DoSB0cmFuc2Zvcm3DoWNpYSAobG9nYXJpdG11cywgbW9jbmluYSBhIHBvZC4pLiAgCk5pxb7FoWllIHV2w6FkemFtIGludGVycHJldMOhY2l1IHByZSBrYcW+ZMO9IHJlZ3Jlc29yLgoKLS0tCgojIyMgKiox77iP4oOjIFByZW1lbm7DoSAqRmVydC4uUmF0ZSoqKgotIEtyaXZrYSBqZSB0YWttZXIgaG9yaXpvbnTDoWxuYSwgcyBtaW5pbcOhbG55bWkgb2RjaMO9bGthbWkuCi0gTmV2em5pa8OhIMW+aWFkbnkgdsO9cmF6bsO9IG5lbGluZcOhcm55IHZ6b3IuCgoqKuKeoe+4jyBMaW5lw6FybnkgdHZhciBqZSBwb3N0YcSNdWrDumNpLCB0cmFuc2Zvcm3DoWNpYSBuaWUgamUgcG90cmVibsOhLioqCgotLS0KCiMjIyAqKjLvuI/ig6MgUHJlbWVubsOhICpNZWRpYW4uQWdlKioqCi0gS3JpdmthIGplIHJvdm5ha28gdmXEvm1pIHBsb2Now6EgYSBiZXogbsOhem5ha3UgemFrcml2ZW5pYS4KLSBCb2RvdsOpIGhvZG5vdHkgc2Egcm96a2xhZGFqw7ogcm92bm9tZXJuZSBva29sbyDEjWlhcnkuCgoqKuKeoe+4jyBMaW5lw6FybmEgxaFwZWNpZmlrw6FjaWEgamUgdmhvZG7DoSwgdHJhbnNmb3Jtw6FjaWEgbmllIGplIHBvdHJlYm7DoS4qKgoKLS0tCgojIyMgKioz77iP4oOjIFByZW1lbm7DoSAqTWlncmFudHMuLm5ldC4qKioKLSBLcml2a2EgdWthenVqZSBqZW1uZSBzdMO6cGFqw7pjaSB0dmFyLCBuYWptw6QgcHJpIHZ5xaHFocOtY2ggaG9kbm90w6FjaCByZWdyZXNvcmEuCi0gVmlkaXRlxL5uw6EgamUgbWllcm5lIHbDpMSNxaFpYSB2YXJpYWJpbGl0YSBib2RvdiB2IHBvcm92bmFuw60gcyBvc3RhdG7DvW1pIHByZW1lbm7DvW1pLgotIElkZSB0YWsgbyBuYWp2w71yYXpuZWrFocOtIChob2NpIHN0w6FsZSBuaWUgdmXEvmvDvSkgb2RrbG9uIG9kIGxpbmVhcml0eS4KCioq4p6h77iPIE1vxb5uw6Ega2FuZGlkw6F0a2EgbmEgdHJhbnNmb3Jtw6FjaXUgKG5hcHIuIGxvZ2FyaXRtdXMpLCBhbGUgb2RrbG9uIG5pZSBqZSBkcmFtYXRpY2vDvSBhIG1vZGVsIGZ1bmd1amUgYWogYmV6IMO6cHJhdi4qKgoKLS0tCgojIyMg4pyFICoqWmhybnV0aWUqKgo+IEMrUiBncmFmeSBuYXpuYcSNdWrDuiwgxb5lIHJlZ3Jlc29yeSAqRmVydC4uUmF0ZSogYSAqTWVkaWFuLkFnZSogbWFqw7ogbGluZcOhcm55IHZ6xaVhaCBzbyB6w6F2aXNsb3UgcHJlbWVubm91LiBQcmVtZW5uw6EgKk1pZ3JhbnRzLi5uZXQuKiB1a2F6dWplIG1pZXJuZSBuZWxpbmXDoXJueSB0cmVuZCwgYWxlIG5pZSBuYXRvxL5rbyB2w71yYXpuw70sIGFieSBib2xvIG5ldnlobnV0bsOpIG1lbmnFpSDFoXBlY2lmaWvDoWNpdSBtb2RlbHUuIENlbGtvdm8gZ3JhZnkgbmVwb3VrYXp1asO6IG5hIHBvdHJlYnUgesOhc2FkbsO9Y2ggdHJhbnNmb3Jtw6FjacOtIHByZW1lbm7DvWNoLgoKCiMjIDMuIE5lbGluZcOhcm5hIMWhcGVjaWZpa8OhY2lhCsSMYXN0b2tyw6F0IG3DtMW+ZW1lIGFqIHpsb8W+aXRlasWhaWUgbmVsaW5lw6FybmUgdnrFpWFoeSBtb2RlbG92YcWlIHMgcG9tb2NvdSBpY2ggYXByb3hpbcOhY2llIHMgcG9seW7Ds21vbSwgdGVkYSB2IHByw61wYWRlIGt2YWRyYXRpY2vDvWNoIMSNbGVub3YKCiQkeV90ID0gXGJldGFfMCArIFxiZXRhXzEgeF97dDEwfSArIFxkb3RzICtcYmV0YV9rIHhfe3RrfSArIFxkb3RzICsgXGdhbW1hX2lcaGF0IHhfe2lrfV4yICsgXGRvdHMgKyBcZ2FtbWFfalxoYXQgeF97amt9XjIgKyBcZG90cyArIHVfdCQkClByw61rbGFkIG5hIHTDunRvIG1vZGlmaWvDoWNpdSB1dmlkw61tZSBuacW+xaFpZS4KCiMjIDQuIFBvcm92bmFuaWUgesOha2xhZG7DqWhvIGEgbW9kaWZpa292YW7DqWhvIG1vZGVsdQoKTmEgesOha2xhZGUgZ3JhZm92IENvbXBvbmVudCArIFJlc2lkdWFsIHNtZSBpZGVudGlmaWtvdmFsaSwgxb5lIG5hanbDpMSNxaHDrSBvZGtsb24gb2QgbGluZWFyaXR5IHZ5a2F6dWrDuiBwcmVtZW5uw6kgTWVkaWFuLkFnZSBhIE1pZ3JhbnRzLi5uZXQuLiBUaWV0byBwcmVtZW5uw6kgbmV2eXR2w6FyYWrDuiBzdHJpa3RuZSBsaW5lw6FybnkgdnrFpWFoIHNvIHrDoXZpc2xvdSBwcmVtZW5ub3UgUG9wdWxhdGlvbi4yMDI1LCDEjW8gbmF6bmHEjXVqZSBtb8W+bsO6IHBvdHJlYnUgZG9wbG5lbmlhIGt2YWRyYXRpY2vDvWNoIMSNbGVub3YuCgpQcmV0byBwcmVkcG9rbGFkw6FtZSwgxb5lIHByaSBuZWxpbmXDoXJueWNoIMO6cHJhdsOhY2ggcMO0dm9kbsOpaG8gbW9kZWx1IGTDtGpkZSBrIHpsZXDFoWVuaXUgamVobyDFoXBlY2lmaWvDoWNpZSBwcsOhdmUgcG8gemF2ZWRlbsOtIGt2YWRyw6F0b3YgcHJlbWVubsO9Y2ggTWVkaWFuLkFnZcKyIGEgTWlncmFudHMuLm5ldC7Csi4gSWNoIHNwcsOhdmFuaWUgdiBDK1IgZ3JhZm9jaCBuYXpuYcSNb3ZhbG8gbWllcm5lIHpha3JpdmVuaWUsIGt0b3LDqSBzYSB2w71yYXpuZWrFoWllIG9kY2h5xL5vdmFsbyBvZCBwcmlhbWt5LgoKQWsgbcOhIHRyYW5zZm9ybW92YW7DvSBtb2RlbCB2ecWhxaHDrSB1cHJhdmVuw70ga29lZmljaWVudCBkZXRlcm1pbsOhY2llICRSXjJfe2Fkan0kLCBsZXDFoWl1IMWhdGF0aXN0aWNrw7ogdsO9em5hbW5vc8WlIGEgesOhcm92ZcWIIFJFU0VUIHRlc3QgbmVwb3R2cmTDrSBuZXNwcsOhdm51IMWhcGVjaWZpa8OhY2l1LCBtw7TFvmVtZSBub3bDvSBtb2RlbCBwb3Zhxb5vdmHFpSB6YSB2aG9kbmVqxaHDrS4gT2Rwb3LDusSNYW1lIHbDvXNsZWRreSDEj2FsZWogcG9kcG9yacWlIGFqIHBvcm92bmFuw61tIG9ib2NoIG1vZGVsb3YgcG9tb2NvdSBBTk9WQSB0ZXN0dSwga3RvcsO9IG92ZXLDrSwgxI1pIG3DoSByb3rFocOtcmVuw70gbW9kZWwgxaF0YXRpc3RpY2t5IHbDvXpuYW1uZSBsZXDFoWl1IHbDvWtvbm5vc8WlLgoKYGBge3J9CiMgWsOha2xhZG7DvSBsaW5lw6FybnkgbW9kZWwKbW9kZWwgPC0gbG0oUG9wdWxhdGlvbi4yMDI1IH4gMSArIEZlcnQuLlJhdGUgKyBNZWRpYW4uQWdlICsgTWlncmFudHMuLm5ldC4sIAogICAgICAgICAgICBkYXRhID0gZGF0YV9zZWxlY3RlZCkKCiMgTW9kZWwgcyBrdmFkcmF0aWNrw71taSDEjWxlbm1pIG5hIHrDoWtsYWRlIEMrUiBncmFmb3YKbW9kZWxfa3ZhZHIgPC0gbG0oUG9wdWxhdGlvbi4yMDI1IH4gMSArIEZlcnQuLlJhdGUgKyAKICAgICAgICAgICAgICAgICAgICBNZWRpYW4uQWdlICsgSShNZWRpYW4uQWdlXjIpICsKICAgICAgICAgICAgICAgICAgICBNaWdyYW50cy4ubmV0LiArIEkoTWlncmFudHMuLm5ldC5eMiksCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX3NlbGVjdGVkKQoKIyBWw71zdHVweSBtb2RlbHUKc3VtbWFyeShtb2RlbF9rdmFkcikKCiMgUG9yb3ZuYW5pZSB6w6FrbGFkbsOpaG8gYSBuZWxpbmXDoXJuZWhvIG1vZGVsdQphbm92YShtb2RlbCwgbW9kZWxfa3ZhZHIpCgojIFJFU0VUIHRlc3QgcHJlIG5lbGluZcOhcm5lIHJvesWhw61yZW7DvSBtb2RlbApyZXNldHRlc3QobW9kZWxfa3ZhZHIpCgpgYGAKClRha3RvIG1vZGlmaWtvdmFuw70gbW9kZWwsIHYga3Rvcm9tIHNtZSBkb3BsbmlsaSBrdmFkcsOhdCBwcmVtZW5uw71jaCAqTWVkaWFuLkFnZSogYSAqTWlncmFudHMuLm5ldC4qLCB2xaFhayBuZW96bmHEjXVqZSDFvmlhZG55IHoga3ZhZHJhdGlja8O9Y2ggxI1sZW5vdiB6YSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSAocC1ob2Rub3R5IHPDuiB2w71yYXpuZSB2w6TEjcWhaWUgYWtvIDAsMDUpLiBaw6Fyb3ZlxYggbmVkb2Now6FkemEgayB6bGVwxaFlbml1IHVwcmF2ZW7DqWhvIGtvZWZpY2llbnR1IGRldGVybWluw6FjaWUg4oCTIG5hb3BhaywgamVobyBob2Rub3RhIGtsZXNsYSBuYSBwcmlibGnFvm5lICRSXjJfe1x0ZXh0e2Fkan19IFxhcHByb3ggLTB7Ln0wMDQ2JC4KCkFqIHBvcm92bmFuaWUgbW9kZWxvdiBwb21vY291IEFOT1ZBIChwLWhvZG5vdGEgJFxhcHByb3ggMHsufTgwJCkgYSBSRVNFVCB0ZXN0dSAocC1ob2Rub3RhICRcYXBwcm94IDB7Ln00NyQpIHVrYXp1amUsIMW+ZSBrdmFkcmF0aWNrw70gbW9kZWwgbmllIGplIGxlcMWhw60gbmXFviBww7R2b2Ruw70gbGluZcOhcm55IG1vZGVsLiBWIMSPYWzFoWVqIGFuYWzDvXplIHByZXRvIHByYWN1amVtZSBzIGplZG5vZHVjaMWhw61tIGxpbmXDoXJueW0gbW9kZWxvbSBiZXoga3ZhZHJhdGlja8O9Y2ggxI1sZW5vdi4KCmBgYHtyfQptb2RlbF9rdmFkciA8LSBsbShQb3B1bGF0aW9uLjIwMjUgfiAxICsgRmVydC4uUmF0ZSArIE1lZGlhbi5BZ2UgKyBNaWdyYW50cy4ubmV0LiArCiAgICAgICAgICAgICAgICAgICAgSShNZWRpYW4uQWdlXjIpICsgSShNaWdyYW50cy4ubmV0Ll4yKSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGFfc2VsZWN0ZWQpCgpzdW1tYXJ5KG1vZGVsX2t2YWRyKQoKYGBgCiMjIyBQb3Jvdm5hbmllIHrDoWtsYWRuw6lobyBhIGt2YWRyYXRpY2t5IG1vZGlmaWtvdmFuw6lobyBtb2RlbHUKCkRvIG1vZGVsdSBzbWUgcHJpZGFsaSBrdmFkcmF0aWNrw6kgxI1sZW55IHByZW1lbm7DvWNoIGBNZWRpYW4uQWdlYCBhIGBNaWdyYW50cy4ubmV0LmAgcyBjaWXEvm9tCnphY2h5dGnFpSBtb8W+bsOpIG5lbGluZcOhcm5lIHZ6xaVhaHkuIFbDvXNsZWRreSB2xaFhayB1a2F6dWrDuiwgxb5lIGFuaSBqZWRlbiB6IHTDvWNodG8Ka3ZhZHJhdGlja8O9Y2ggxI1sZW5vdiBuaWUgamUgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70gKHbFoWV0a3kgcC1ob2Rub3R5IHPDuiB2w71yYXpuZSB2w6TEjcWhaWUgYWtvIDAuMDUpLgoKVXByYXZlbsO9IGtvZWZpY2llbnQgZGV0ZXJtaW7DoWNpZSB6b3N0YWwgdiBwb2RzdGF0ZSBuZXptZW5lbsO9IGEgbcOhIGhvZG5vdHUgIAoqKiRSXjJfe2Fkan0gPSAtMC4wMDQ2JCoqLCDEjW8gbmF6bmHEjXVqZSwgxb5lIGt2YWRyYXRpY2t5IHJvesWhw61yZW7DvSBtb2RlbCBuZXZ5c3ZldMS+dWplCnZhcmlhYmlsaXR1IGTDoXQgbGVwxaFpZSBha28gcMO0dm9kbsO9IG1vZGVsLgoKWmF2ZWRlbmllIGt2YWRyYXRpY2vDvWNoIMSNbGVub3YgcHJldG8gKipuZXByaW5pZXNsbyB6bGVwxaFlbmllKiogYSB2IMSPYWzFoWVqIGFuYWzDvXplCmJ1ZGVtZSBwb2tyYcSNb3ZhxaUgcyBww7R2b2Ruw71tIGxpbmXDoXJueW0gbW9kZWxvbS4KCiMjIyA1LiBQb3XFvml0aWUgcm96xaHDrXJlbsOpaG8gUkVTRVQgdGVzdHUKYGBge3J9Cm1vZGVsX3JvenNpcmVueSA8LSBsbSgKICBQb3B1bGF0aW9uLjIwMjUgfiAKICAgIEZlcnQuLlJhdGUgKwogICAgTWVkaWFuLkFnZSArCiAgICBNaWdyYW50cy4ubmV0LiArCiAgICBJKE1lZGlhbi5BZ2VeMikgKwogICAgSShNaWdyYW50cy4ubmV0Ll4yKSwKICBkYXRhID0gZGF0YV9zZWxlY3RlZAopCgpzdW1tYXJ5KG1vZGVsX3JvenNpcmVueSkKCmBgYApWIHRvbXRvIGtyb2t1IHRlc3R1amVtZSwgxI1pIGt2YWRyYXRpY2vDqSDEjWxlbnkgKipNZWRpYW4uQWdlwrIqKiBhICoqTWlncmFudHMuLm5ldC7CsioqICAKcHJpbsOhxaFhasO6IGRvIG1vZGVsdSDFoXRhdGlzdGlja3kgdsO9em5hbW7DqSBpbmZvcm3DoWNpZS4gIApBayBieSBib2xpIHbDvXpuYW1uw6ksIG1hbGkgYnkgc21lIHV2YcW+b3ZhxaUgbmFkIGt2YWRyYXRpY2tvdSB0cmFuc2Zvcm3DoWNpb3UgdMO9Y2h0byBwcmVtZW5uw71jaC4KCk5hIHrDoWtsYWRlIHbDvXN0dXB1IGBzdW1tYXJ5KG1vZGVsX3JvenNpcmVueSlgIHbFoWFrIHZpZMOtbWUsIMW+ZToKCi0ga29lZmljaWVudCBwcmkgYEkoTWVkaWFuLkFnZV4yKWAgKipuaWUgamUgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70qKiAocCA9IDAuODQ5KSwKLSBrb2VmaWNpZW50IHByaSBgSShNaWdyYW50cy4ubmV0Ll4yKWAgKip0YWt0aWXFviBuaWUgamUgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70qKiAocCA9IDAuNTE0KS4KCmBgYHtyfQphbm92YShtb2RlbCxtb2RlbF9yb3pzaXJlbnkpCnJlc2V0dGVzdChtb2RlbF9yb3pzaXJlbnkpCmBgYApQcmkgUkVTRVQgdGVzdGUgdmlkw61tZSwgxb5lIHAtaG9kbm90YSAqKjAuNDc0MSoqIGplIHbDvXJhem5lIHZ5xaHFoWlhIGFrbyBobGFkaW5hIHbDvXpuYW1ub3N0aSAwLjA1LiAgClRvIHpuYW1lbsOhLCDFvmUgKipuZXphbWlldGFtZSBudWxvdsO6IGh5cG90w6l6dSBzcHLDoXZuZWogxaFwZWNpZmlrw6FjaWUgbW9kZWx1KiouCgpaw6Fyb3ZlxYggdsWhYWsgcGxhdMOtLCDFvmUgYW5pIHJvesWhw61yZW7DvSBtb2RlbCBzIGt2YWRyYXRpY2vDvW1pIMSNbGVubWkgbmVib2wgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70gIAooQU5PVkEgcCA9IDAuNzk1NiksIHRha8W+ZSAqKnByw61wYWRuw70gcHJvYmzDqW0gbmVzcHLDoXZuZWogxaFwZWNpZmlrw6FjaWUgbW9kZWx1IHNhIG5lb2RzdHLDoW5pbCoqLCAgCmFsZSB6w6Fyb3ZlxYggKipuZWJvbCBhbmkgcG90dnJkZW7DvSoqLiBaYXZlZGVuaWUga3ZhZHJhdGlja8O9Y2ggxI1sZW5vdiBuZXByaW5pZXNsbyB6bGVwxaFlbmllIG1vZGVsdS4KCgojIyMgNi4gVHJhbnNmb3Jtw6FjaWEgcG9tb2NvdSBkdW1teSBwcmVtZW5uZWogYSBsaW5lw6FybmVqIGxvbWVuZWogZnVua2NpZQoKUHJlZHBva2xhZGFqbWUsIMW+ZSBtw6FtZSBkdW1teSBwcmVtZW5uw7ogJERfdCQsIGt0b3LDoSBvYnNhaHVqZSBsZW4gbnVseSBhIGplZG5pxI1reS4gVGFrw6F0byBwcmVtZW5uw6Egc2EgZMOhIHZ5dcW+acWlIG1vZGVsb3ZhbmllIHpsb21vdiwgYSB0byBuYXByLgoKMS4gemxvbSB2IGF1dG9uw7Ntbm9tIMSNbGVuZSAkXGJldGFfMCQgYSB0byBuYXNsZWRvdm5vdSDFoXBlY2lmaWvDoWNpb3UKJCR5X3QgPSBcYmV0YV8wICsgXGJldGFfRCBEKyBcYmV0YV8xIHhfe3QxfSArIFxkb3RzICtcYmV0YV9rIHhfe3RrfSArIHVfdCQkCsSNbyBpbnRlcnByZXR1amVtZSBha28gcG9zdW4gcmVncmVzbmVqIHByaWFta3kgKHJlZ3Jlc25laiBuYWRyb3ZpbnkpIG8gJFxiZXRhX0QkIGplZG5vdGllayBwb3pkxLrFviB6dmlzbGVqIG9zaSBhIHRvIGxlbiB2IHBvem9yb3ZhbmlhY2gsIGFrIGplIHNwbG5lbsOhIHBvZG1pZW5rYSAkRF90ID0gMSQKMi4gemxvbSB2IHNrbG9uZSByZWdyZXNuZWogcHJpYW1reSAobmFkcm92aW55KSBhIHRvIGxlbiB2IHBvem9yb3ZhbmlhY2gsIGFrIGplIHNwbG5lbsOhIHBvZG1pZW5rYSAkRF90ID0gMSQsIMSNbyBkb3NpYWhuZW1lIG5hc2xlZG92bm91IMWhcGVjaWZpa8OhY2lvdQokJHlfdCA9IFxiZXRhXzAgKyAgXGJldGFfMSB4X3t0MX0gKyBcZG90cyArIFxiZXRhX3tpfXhfe3RpfSArIFxiZXRhX3tEaX1EX3R4X3t0aX0rIFxkb3RzICsgXGJldGFfayB4X3t0a30gKyB1X3QkJAprZGUgdGVkYSBza2xvbiBwcmlhbWt5IHBvemTEusW+IHByZW1lbm5lICR4X3t0aX0kIGplICRcYmV0YV9pJCBhbGUgbGVuIHYgcHLDrXBhZGUgJERfdD0wJCwgaW5hayBqZSB0ZW4gc2tsb24gcm92bsO9ICRcYmV0YV9pK1xiZXRhX3tEX2l9JC4KCkFrIHNpIHBvenJpZW1lIEMrUiBncmFmeSBwcmUgbmHFoWUgdnlzdmV0xL51asO6Y2UgcHJlbWVubsOpLCB2aWTDrW1lLCDFvmUKbmFqdsO9cmF6bmVqxaFpZSBvZGNow71sa3kgb2QgbGluZWFyaXR5IHNhIG9iamF2dWrDuiBwcmkgcHJlbWVubsO9Y2gKKk1pZ3JhbnRzLi5uZXQuKiBhICpNZWRpYW4uQWdlKi4gVnlyb3ZuYW7DoSBrcml2a2EgcHJpIG9ib2NoIHByZW1lbm7DvWNoIG5hem5hxI11amUgbWllcm5lIHpha3JpdmVuaWUsIG5ham3DpCBwcmkgZXh0csOpbW5lasWhw61jaCBob2Rub3TDoWNoLCDEjW8gbcO0xb5lIHNpZ25hbGl6b3ZhxaUgcG90cmVidSBuZWxpbmXDoXJuZWogw7pwcmF2eSAodC5qLiB6YXZlZGVuaWUga3ZhZHJhdGlja8OpaG8gxI1sZW5hKS4gUHJldG8gc21lIGRvIG1vZGVsdSB6YXJhZGlsaSBwcmVtZW5uw6kgKipJKE1lZGlhbi5BZ2XCsikqKiBhICoqSShNaWdyYW50cy4ubmV0LsKyKSoqLCBhYnkgc21lIG90ZXN0b3ZhbGksIMSNaSB0aWV0byBuZWxpbmXDoXJuZSBlZmVrdHkgZG9rw6HFvnUgemxlcMWhacWlIMWhcGVjaWZpa8OhY2l1IG1vZGVsdS4KIApLdmFudGlmaWt1am1lIHRlcmF6IG1vZGVsIHNvIHpsb21vbSB2IGF1dG9uw7Ntbm9tIMSNbGVub3ZpLiAgCktlxI/FvmUgcG9kxL5hIEMrUiBncmFmb3YgemF6bmFtZW7DoXZhbWUgbmVsaW5lw6FybmUgc3Byw6F2YW5pZSBwcmkgcHJlbWVubsO9Y2gKKk1pZ3JhbnRzLi5uZXQuKiwgemF2ZWRpZW1lIG5vdsO6IGR1bW15IHByZW1lbm7Duiwga3RvcsOhIHJvemRlbMOtIGtyYWppbnkgcG9kxL5hCsO6cm92bmUgbWlncsOhY2llLgoKTmVjaCAgCiREVU1fdCA9IDAkIHByZSBob2Rub3R5IE1pZ3JhbnRzLi5uZXQuIG5pxb7FoWllIGFrbyBtZWRpw6FuICAKYSAgCiREVU1fdCA9IDEkIHByZSBob2Rub3R5IE1pZ3JhbnRzLi5uZXQuIHZ5xaHFoWllIGFsZWJvIHJvdm7DqSBtZWRpw6FudS4KClRha3RvIGJ1ZGVtZSBtw7RjxaUgcG9zw7pkacWlLCDEjWkgc2EgaW50ZXJjZXB0IG1vZGVsdSB2w71yYXpuZSBtZW7DrSBwcmkgdnnFocWhw61jaApob2Rub3TDoWNoIG1pZ3LDoWNpZS4KCmBgYHtyfQojIHByYWggc2kgbcO0xb5lbWUgdXLEjWnFpSBha28gbWVkacOhbgp0aHJlc2hvbGQgPC0gbWVkaWFuKGRhdGFfc2VsZWN0ZWQkTWlncmFudHMuLm5ldC4sIG5hLnJtID0gVFJVRSkKCiMgZHVtbXkgcHJlbWVubsOhIHBvZMS+YSBwcmFodQpkYXRhX3NlbGVjdGVkJERVTSA8LSBpZmVsc2UoZGF0YV9zZWxlY3RlZCRNaWdyYW50cy4ubmV0LiA8IHRocmVzaG9sZCwgMCwgMSkKCiMgbW9kZWwgc28gemxvbW9tIHYgYXV0b27Ds21ub20gxI1sZW5vdmkKbW9kZWxfYXV0byA8LSBsbShQb3B1bGF0aW9uLjIwMjUgfiAxICsgRFVNICsgRmVydC4uUmF0ZSArIE1lZGlhbi5BZ2UgKwogICAgICAgICAgICAgICAgICAgTWlncmFudHMuLm5ldC4sIAogICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX3NlbGVjdGVkKQoKc3VtbWFyeShtb2RlbF9hdXRvKQoKYGBgClphdmVkZW7DrW0gemxvbW92ZWogcHJlbWVubmVqIERVTSBkb8WhbG8gayBtaWVybmVtdSB6bGVwxaFlbml1IG1vZGVsdSwga2XEj8W+ZSBrb2VmaWNpZW50IHByaSBEVU0gdnnFoWllbCBuYSBobGFkaW5lIHbDvXpuYW1ub3N0aSAxMCAlIMWhdGF0aXN0aWNreSB2w716bmFtbsO9IChwIOKJiCAwLjA5NTUpLiBUbyBuYXpuYcSNdWplLCDFvmUgcHJlIGtyYWppbnkgbmFkIHp2b2xlbm91IGhyYW5pY291IGZlcnRpbGl0eSBzYSDDunJvdmXFiCBwb3B1bMOhY2llIHN5c3RlbWF0aWNreSBsw63FoWkgKG3DoSBpbsO9IGludGVyY2VwdCkuIE9zdGF0bsOpIHByZW1lbm7DqSBvc3RhbGkgCm5ldsO9em5hbW7DqSBhIHVwcmF2ZW7DvSBSwrIgem9zdGFsIHZlxL5taSBuw616a3kgKOKJiCAwLjAwOTk2KS4gQ2Vsa292w70gRi10ZXN0IG5hem5hxI11amUsIMW+ZSBtb2RlbCBha28gY2Vsb2sgbmllIGplIHbDvXpuYW1uw70gKHAg4omIIDAuMTc5NikuIFphdmVkZW5pZSB6bG9tb3ZlaiBwcmVtZW5uZWogcHJldG8gbmVwcmluaWVzbG8gesOhc2FkbsOpIHpsZXDFoWVuaWUga3ZhbGl0eSBtb2RlbHUuCiAKYGBge3J9Cm1vZGVsRF9za2xvbiA8LSBsbShQb3B1bGF0aW9uLjIwMjUgfiAxICsgRmVydC4uUmF0ZSArIEkoRFVNICogRmVydC4uUmF0ZSkgKwogICAgICAgICAgICAgICAgICAgICBNZWRpYW4uQWdlICsgTWlncmFudHMuLm5ldC4sIAogICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGFfc2VsZWN0ZWQpCgpzdW1tYXJ5KG1vZGVsRF9za2xvbikKCmBgYAojIyMg8J+TjCBJbnRlcnByZXTDoWNpYSB2w71zbGVka292IG1vZGVsdSBzbyB6bG9tb20gdiBza2xvbmUgKGludGVyYWtjaWEgYERVTSAqIEZlcnQuLlJhdGVgKQoKViB0b210byBrcm9rdSBzbWUgZG8gbW9kZWx1IHphdmllZGxpICp6bWVudSBza2xvbnUqIHByZSBwcmVtZW5uw7ogKipGZXJ0Li5SYXRlKiogcG9tb2NvdSBpbnRlcmFrxI1uw6lobyDEjWxlbmEgYEkoRFVNICogRmVydC4uUmF0ZSlgLiBQcmVtZW5uw6EgKipEVU0qKiByb3pkZcS+dWplIHBvem9yb3ZhbmlhIG5hIGR2ZSBza3VwaW55IHBvZMS+YSB2b3ByZWQgdXLEjWVuZWogaHJhbmljZSBhIHRlc3R1amVtZSwgxI1pIGZlcnRpbGl0YSBvdnBseXbFiHVqZSB2ZcS+a29zxaUgcG9wdWzDoWNpZSByb3pkaWVsbmUgdiB0w71jaHRvIGR2b2NoIHNrdXBpbsOhY2guCgotLS0KCiMjIyAqKvCfk4ogVsO9c2xlZGt5IHJlZ3Jlc27DqWhvIG1vZGVsdSoqCgotICoqRmVydC4uUmF0ZSoqICAKICAtIG9kaGFkOiBgLTMuMzQ4ZSswN2AgIAogIC0gcC1ob2Rub3RhOiBgMC4wNzE3YCAgCiAg4oaSIMO6xI1pbm9rIGplICpzbGFibyB2w716bmFtbsO9KiAocHJpYmxpxb5uZSBuYSAxMCAlIGhsYWRpbmUpLgoKLSAqKkludGVyYWtjaWEgYERVTSAqIEZlcnQuLlJhdGVgKiogIAogIC0gb2RoYWQ6IGAxLjU0OWUrMDdgICAKICAtIHAtaG9kbm90YTogYDAuMTUxN2AgIAogIOKGkiBpbnRlcmFrxI1uw70gZWZla3QgKm5pZSBqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSosIHRlZGEgc2tsb24gRmVydC4uUmF0ZSBzYSBwbyB6bWVuZSBEVU0gdsO9cmF6bmUgbmVtZW7DrS4KCi0gKipNZWRpYW4uQWdlKiogIAogIC0gcC1ob2Rub3RhOiBgMC4yNjA2YCAgCiAg4oaSIG5ldsO9em5hbW7DvSBlZmVrdC4KCi0gKipNaWdyYW50cy4ubmV0LioqICAKICAtIHAtaG9kbm90YTogYDAuMjM1MGAgIAogIOKGkiB0YWtpc3RvIG5ldsO9em5hbW7DvSBlZmVrdC4KCi0tLQoKIyMjICoq8J+TiCBIb2Rub3RlbmllIGt2YWxpdHkgbW9kZWx1KioKCi0gKipNdWx0aXBsZSBSLXNxdWFyZWQ6KiogYDAuMDIzOTNgICAKLSAqKkFkanVzdGVkIFItc3F1YXJlZDoqKiBgMC4wMDY4MDVgICAKICDihpIgbW9kZWwgdnlzdmV0xL51amUgKipsZW4gcHJpYmxpxb5uZSAyLDQgJSB2YXJpYWJpbGl0eSoqIHYgw7pkYWpvY2guCgotICoqRi10ZXN0IG1vZGVsdToqKiBwLWhvZG5vdGEgPSBgMC4yMzU3YCAgCiAg4oaSIG1vZGVsIGFrbyBjZWxvayAqKm5pZSBqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSoqLgoKLS0tCgojIyMgKirwn5OdIFrDoXZlcioqCgotIEludGVyYWvEjW7DvSDEjWxlbiBgRFVNICogRmVydC4uUmF0ZWAgKipuZXpsZXDFoWlsKioga3ZhbGl0dSBtb2RlbHUgYSBuaWUgamUgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70uICAKLSBOZWV4aXN0dWplIGTDtGtheiwgxb5lIGZlcnRpbGl0YSBtw6Egb2RsacWhbsO9IHZwbHl2IG5hIHBvcHVsw6FjaXUgdiByb2t1IDIwMjUgbWVkemkgZHZvbWkgc2t1cGluYW1pIGRlZmlub3ZhbsO9bWkgcG9kxL5hIHByZW1lbm5laiAqKkRVTSoqLiAgCi0gTW9kZWwgbcOhIHZlxL5taSBuw616a2UgaG9kbm90eSBcKFJeMlwpIGFqIFwoUl4yX3tcdGV4dHthZGp9fVwpLCDEjW8gem5hbWVuw6Egc2xhYsO6IHZ5c3ZldMS+b3ZhY2l1IHNjaG9wbm9zxaUuICAKLSAqKk1vZGVsIHNvIHpsb21vbSB2IHNrbG9uZSBwcmV0byBuZW9kcG9yw7rEjWFtZSBwb3XFvsOtdmHFpSBha28gZmluw6FsbnkgbW9kZWwuKioKCi0tLQoKCmBgYHtyfQphbm92YShtb2RlbCwgbW9kZWxEX3NrbG9uKQpyZXNldHRlc3QobW9kZWxEX3NrbG9uKQpgYGAKIyMjIPCfk4wgUG9yb3ZuYW5pZSBtb2RlbG92IHBvbW9jb3UgQU5PVkEgYSBSRVNFVCB0ZXN0dQoKTmEgb3ZlcmVuaWUsIMSNaSB6YXZlZGVuaWUgaW50ZXJha8SNbsOpaG8gxI1sZW5hIGBEVU0gKiBGZXJ0Li5SYXRlYCB2aWVkbG8gayB6bGVwxaFlbml1IMWhcGVjaWZpa8OhY2llIG1vZGVsdSwgc21lIHBvdcW+aWxpICoqQU5PVkEgdGVzdCoqIGEgbsOhc2xlZG5lIGFqICoqUkVTRVQgdGVzdCoqLgoKLS0tCgojIyMg8J+UjSAqKlbDvXNsZWRreSBBTk9WQSB0ZXN0dSoqCgpBTk9WQSBwb3Jvdm7DoXZhOgoKLSAqKk1vZGVsIDE6KiogIAogIGBQb3B1bGF0aW9uLjIwMjUgfiAxICsgRmVydC4uUmF0ZSArIE1lZGlhbi5BZ2UgKyBNaWdyYW50cy4ubmV0LmAgIAotICoqTW9kZWwgMiAocm96xaHDrXJlbsO9KToqKiAgCiAgYFBvcHVsYXRpb24uMjAyNSB+IDEgKyBGZXJ0Li5SYXRlICsgSShEVU0gKiBGZXJ0Li5SYXRlKSArIE1lZGlhbi5BZ2UgKyBNaWdyYW50cy4ubmV0LmAKClbDvXNsZWRvazoKCi0gKipGID0gMi4wNjk0KiosICAKLSAqKnAtaG9kbm90YSA9IDAuMTUxNyoqCgrwn5GJIEtlxI/FvmUgcC1ob2Rub3RhIGplICoqdsOkxI3FoWlhIGFrbyAwLjA1KiosICpyb3rFocOtcmVuw70gbW9kZWwgbmV2eWthenVqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DqSB6bGVwxaFlbmllKiBvcHJvdGkgesOha2xhZG7DqW11IG1vZGVsdS4gIApJbnRlcmFrxI1uw70gxI1sZW4gdGVkYSAqKm5lcHJpc3BlbCBrIGxlcMWhaWVtdSB2eXN2ZXRsZW5pdSB2YXJpYWJpbGl0eSoqIHYgZMOhdGFjaC4KCi0tLQoKIyMjIPCfp6ogKipSRVNFVCB0ZXN0IHByZSBtb2RlbCBzbyB6bG9tb20gdiBza2xvbmUqKgoKVsO9c2xlZG9rIFJFU0VUIHRlc3R1OgoKLSAqKlJFU0VUID0gMC45MjExNyoqICAKLSAqKmRmMSA9IDIsIGRmMiA9IDIyNioqICAKLSAqKnAtaG9kbm90YSA9IDAuMzk5NSoqCgrwn5GJIEtlxI/FvmUgcC1ob2Rub3RhIGplIG9ww6TFpSAqKm92ZcS+YSB2ecWhxaFpYSBha28gMC4wNSoqLCAqbmV6YW1pZXRhbWUgbnVsb3bDuiBoeXBvdMOpenUgc3Byw6F2bmVqIMWhcGVjaWZpa8OhY2llIG1vZGVsdSouICAKUkVTRVQgdGVzdCB0ZWRhICoqbmVpbmRpY3VqZSBjaHlibsO6IGZ1bmvEjW7DuiBmb3JtdSoqLCBhbGUgesOhcm92ZcWIICoqYW5pIG5lcG90dnJkenVqZSoqLCDFvmUgaW50ZXJha2NpYSBwcmluaWVzbGEgemxlcMWhZW5pZS4KCi0tLQoKIyMjIPCfk50gKipaw6F2ZXIqKgoKLSBBbmkgKipBTk9WQSoqLCBhbmkgKipSRVNFVCB0ZXN0KiogbmVwcmV1a8OhemFsaSwgxb5lIGJ5IHphdmVkZW5pZSBpbnRlcmFrxI1uw6lobyDEjWxlbmEgYERVTSAqIEZlcnQuLlJhdGVgIHByaXNwZWxvIGsgemxlcMWhZW5pdSBtb2RlbHUuICAKLSBNb2RlbCBzbyB6bG9tb20gdiBza2xvbmUgKipuaWUgamUgxaF0YXRpc3RpY2t5IGxlcMWhw60qKiBha28gcMO0dm9kbsO9IG1vZGVsLiAgCi0gTmVleGlzdHVqZSBkw7RrYXosIMW+ZSBmZXJ0aWxpdGEgbcOhICpvZGxpxaFuw70gdnBseXYqIG5hIHBvcHVsw6FjaXUgdiByw7R6bnljaCBza3VwaW7DoWNoIGRlZmlub3ZhbsO9Y2ggcHJlbWVubm91IERVTS4gIAotIFpvc3TDoXZhbWUgdGVkYSBwcmkgesOhdmVyZSwgxb5lICoqdGVudG8gbW9kZWwgbmllIGplIHZob2Ruw70gYWtvIGZpbsOhbG55KiogYSBuZXBvZHBvcnVqZSBoeXBvdMOpenUgbyB6bWVuZSBza2xvbnUuCgotLS0K