Úvod
Klastrová (zhluková) analýza patrí medzi najpoužívanejšie metódy
exploratívnej štatistiky. V praxi sa využíva všade tam, kde je potrebné
rozdeliť pozorovania do homogénnych celkov - napríklad pri segmentácii
zákazníkov v marketingu, identifikácii podobných krajín v
makroekonomických ukazovateľoch, hodnotenízdravotných rizík,
klasifikácii biologických vzoriek či v geoinformatike pri zoskupovaní
priestorových sobjektov. Jej výhodou je, že pracuje s viacerými
premennými naraz a dokáže odhaliť vzory, ktoré by pri samotnom hodnotení
jednotlivých ukazovateľov zostali skryté. Správne zvolená metrika
vzdialenosti a metóda zhlukovania umožňujú odhaliť skryté vzťahy v
dátach, čím poskytujú cenný podklad pre rozhodovanie v rôznych
oblastiach aplikovaného výskumu.
Predstavím zhlukovú analýzu pri analýze krajín sveta z hľadiska
demografických ukazovateľov, ako sú predpokladaná populácia v roku 2025,
miera plodnosti, medián veku a čistá migrácia. Cieľom je identifikovať
skupiny krajín, ktoré majú podobné demografické profily a môžu byť preto
analyzované spoločne. Takto vytvorené zhluky poskytujú prehľad o
krajinách s podobným populačným vývojom či dynamikou rastu populácie.
Pri analýze využívame najnovšie dostupné údaje z databázy, s ktorou sme
pracovali aj v predchádzajúcich častiach.
library(knitr)
library(kableExtra)
# Načítanie dát
udaje <- read.csv("population_data.csv", stringsAsFactors = FALSE)
# 10 európskych krajín, s ktorými chcem pracovať
krajiny10 <- c("Germany",
"United Kingdom",
"France",
"Italy",
"Spain",
"Ukraine",
"Poland",
"Romania",
"Netherlands",
"Belgium")
# Výber len týchto krajín a požadovaných premenných
udaje10 <- subset(
udaje,
Country..or.dependency. %in% krajiny10,
select = c(
Country..or.dependency.,
Population.2025,
Fert..Rate,
Median.Age,
Migrants..net.
)
)
# Pre pomenovanie stĺpcov v tabuľke
colnames(udaje10) <- c(
"Krajina",
"Populácia 2025",
"Miera plodnosti",
"Medián veku",
"Čistá migrácia"
)
Table 1.
udaje10
Hierarchická zhluková analýza pracuje s mierami vzdialenosti medzi
pozorovaniami. Aby boli tieto vzdialenosti porovnateľné, je potrebné,
aby všetky premenné boli definované na rovnakejškále. Používame pritom
tzv. z-škálovanie, pričom transformované \(z\) hodnoty (skóre) vypočítame
nasledovne
\[z = \frac{x-\mu}{\sigma}\]
kde \(\mu\) je stredná hodnota a
\(\sigma\) je štandardná odchýlka
pozorovaní \(x\). Predpokladáme pritom,
že súbor údajov už neobsahuje NA hodnoty, ktoré boli ošetrené v
predchádzajúcich krokoch.
Touto operáciou získame škálované pozorovania, pričom ich rozloženie
je znázornené nasledovne:
# 1) Načítanie dát -------------------------------------------------------
udaje <- read.csv("population_data.csv",
sep = ",",
header = TRUE,
stringsAsFactors = FALSE)
# 2) Vyberieme 10 európskych krajín, s ktorými chceme pracovať ----------
krajiny10 <- c("Germany",
"United Kingdom",
"France",
"Italy",
"Spain",
"Ukraine",
"Poland",
"Romania",
"Netherlands",
"Belgium")
# filter na týchto 10 krajín
udaje10 <- subset(udaje, Country..or.dependency. %in% krajiny10)
# pre istotu zoradíme riadky v rovnakom poradí ako vo vektore krajiny10
udaje10 <- udaje10[match(krajiny10, udaje10$Country..or.dependency.), ]
# 3) Pripravíme dátový rámec len s číselnými premennými -----------------
# (populácia 2025, miera plodnosti, medián veku, čistá migrácia)
udaje_complete <- udaje10[, c("Population.2025",
"Fert..Rate",
"Median.Age",
"Migrants..net.")]
# istota: pretypujeme stĺpce na numeric (keby ich R načítal ako text)
udaje_complete[] <- lapply(udaje_complete, function(x) as.numeric(x))
# pomenujeme riadky podľa krajín
rownames(udaje_complete) <- udaje10$Country..or..dependency.
# 4) Škálovanie premenných (z-skóre) ------------------------------------
udaje_scaled <- scale(udaje_complete)
# Výstupy do tabuľky (najprv pôvodné dáta, potom škálované)
udaje_complete # neškálované hodnoty
udaje_scaled # z-skóre
Population.2025 Fert..Rate Median.Age Migrants..net.
[1,] 1.5833411 0.31344708 0.89440379 NA
[2,] 0.9895915 0.68771224 -1.29101724 0.05585233
[3,] 0.8710141 1.15554370 -0.40066052 -0.43681319
[4,] 0.5642185 -0.85613157 1.98711431 -0.46372711
[5,] 0.1040462 -0.76256528 1.05628683 -0.42872861
[6,] -0.2601892 -1.83857763 -0.60301432 2.22437606
[7,] -0.2945077 -0.38830011 -0.31971900 NA
[8,] -1.0807476 1.48302572 -0.03642368 NA
[9,] -1.1037160 0.21988079 -0.72442660 -0.41542614
[10,] -1.3730509 -0.01403494 -0.56254356 -0.53553334
attr(,"scaled:center")
Population.2025 Fert..Rate Median.Age Migrants..net.
45344878.700 1.393 43.290 356107.714
attr(,"scaled:scale")
Population.2025 Fert..Rate Median.Age Migrants..net.
2.446106e+07 2.137522e-01 2.470920e+00 6.052260e+05
Obr. 1.
num_vars <- as.data.frame(udaje_scaled)
num_plots <- ncol(num_vars)
par(mfrow = c(ceiling(sqrt(num_plots)), ceiling(num_plots / ceiling(sqrt(num_plots)))))
par(mar = c(4, 4, 2, 1))
for (col in names(num_vars)) {
boxplot(num_vars[[col]],
main = col,
col = "lightblue",
horizontal = TRUE)
}
mtext("Boxploty numerických premenných (vybraných 10 krajín)", outer = TRUE, cex = 1.3, font = 2)

Tentokrát odľahlé hodnoty nevylúčime, nakoľko definujú konkrétnu
krajinu.
Pri zhlukovej analýze je dôležitá korelačná matica premenných. Vysoká
korelácia zvýhodňuje pri zhlukovej analýze korelované premenné. Preto
pri korelácii nad 0,8 alebo 0.9 vylúčime jednu z korelovaných
premenných. V Tab. 2. sa však takáto vysoká korelácia
nenachádza, preto sa nemusíme ďalej s problémom zaoberať. > V
prípade, ak máme väčší počet významne korelovaných premenných, sa
odporúča i transformácia pomocou Analýzy hlavných komponentov (Principal
Component Analysis) Pri zhlukovej analýze je dôležitá korelačná matica
premenných. Vysoká korelácia medzi premennými môže spôsobovať, že
niektoré z nich budú mať pri tvorbe zhlukov neprimerane veľký vplyv.
Preto sa pri koreláciách vyšších ako 0.8 – 0.9 často odporúča vylúčiť
jednu z dvojice silne korelovaných premenných. V našom prípade (pozri
Tab. 2) však žiadna z korelácií nedosahuje hodnotu,
ktorá by bola problematická:
najvyššia korelácia je medzi premennými Fert..Rate a Migrants..net.
na úrovni –0.64, ostatné korelácie sa pohybujú len v intervale približne
–0.30 až 0.32, premenné teda nie sú výrazne multikolineárne. To znamená,
že sa nemusíme zaoberať odstraňovaním premenných ani uvažovať o ďalšej
transformácii z dôvodu vysokej korelácie. V prípade, že by sme mali
väčší počet veľmi korelovaných ukazovateľov, bolo by vhodné zvážiť
transformáciu pomocou Analýzy hlavných komponentov (Principal Component
Analysis). V našom prípade to však nie je potrebné.
Tab. 2
cor_mat <- cor(udaje_scaled, use="pairwise.complete.obs")
cor_mat <- round(cor_mat,2)
print(cor_mat)
Population.2025 Fert..Rate Median.Age Migrants..net.
Population.2025 1.00 0.04 0.32 0.00
Fert..Rate 0.04 1.00 -0.28 -0.64
Median.Age 0.32 -0.28 1.00 -0.29
Migrants..net. 0.00 -0.64 -0.29 1.00
Každej krajine zodpovedá jeden riadok pozorovaní. Vzdialenosť medzi
krajinami \(i\) a \(j\) je:
\[
d^{ij} = \sqrt{\sum_k (x^i_k - x^j_k)^2}
\] kde \(x^i_k\) je \(k\)ta premenná vstupujúca do výpočtu
(Population.2025, Fert..Rate, Median.Age a Migrants..net.) krajiny \(i\). Tento typ vzdialenosti nazývame aj
Euklidovská vzdialenosť. Vzdialenosti medzi jednotlivými krajinami sa
súhrnne vyjadrujú aj v matici vzdialenosti, čo v našom prípade je
uvedené v Tab.3.. Na základe výsledkov z Tab.
3 môžeme uviesť nasledovné:
Najväčšia vzdialenosť (t. j. najmenšia podobnosť) bola zistená medzi
Ukrajinou a Nemeckom (3.70), ako aj medzi Ukrajinou a Francúzskom
(3.62). Tieto krajiny sa výrazne líšia najmä v migračnej bilancii,
vekovej štruktúre aj plodnosti. Silné rozdiely pozorujeme aj medzi
Rumunskom a Dánskom (3.19) a Rumunskom a Holandskom (3.36), čo môže
súvisieť s vyššou plodnosťou a odlišnou migračnou dynamikou Rumunska.
Najmenšiu vzdialenosť, teda najväčšiu podobnosť, nachádzame medzi:
Holandskom a Belgickom (0.41), Francúzskom a Belgickom (1.13), Nemeckom
a Veľkou Britániou (2.65) Tieto krajiny vykazujú podobné hodnoty medianu
veku a relatívne vyrovnanú migračnú bilanciu. Stredná úroveň podobnosti
je napríklad medzi Poľskom a Španielskom (1.71) alebo Francúzskom a
Španielskom (2.94). Celkovo teda vidíme, že európske krajiny vytvárajú
podľa svojich ukazovateľov prirodzené skupiny – napr.
Belgicko–Holandsko, Nemecko–UK, zatiaľ čo krajiny ako Ukrajina či
Rumunsko sa od väčšiny ostatných výraznejšie odlišujú.
Tab. 3
## ============================
## 3) Distance matrix
## ============================
# Pomenovanie riadkov podľa 10 zvolených krajín
rownames(udaje_scaled) <- c("Germany",
"United Kingdom",
"France",
"Italy",
"Spain",
"Ukraine",
"Poland",
"Romania",
"Netherlands",
"Belgium")
# Výpočet euklidovskej vzdialenosti a zaokrúhlenie na 2 desatinné miesta
dist_mat <- round(dist(udaje_scaled, method = "euclidean"), 2)
dist_mat
Germany United Kingdom France Italy Spain Ukraine Poland
United Kingdom 2.65
France 1.96 1.13
Italy 2.19 3.69 3.14
Spain 2.12 2.94 2.53 1.04
Ukraine 3.70 3.62 4.17 3.95 3.33
Poland 2.71 2.24 2.24 2.89 1.71 1.71
Romania 3.53 2.94 2.32 4.05 3.19 4.00 2.37
Netherlands 3.62 2.27 2.21 3.36 2.37 3.45 1.26
Belgium 3.82 2.64 2.54 3.31 2.32 3.49 1.35
Romania Netherlands
United Kingdom
France
Italy
Spain
Ukraine
Poland
Romania
Netherlands 1.66
Belgium 1.86 0.41
Princíp hierarchického zhlukovania (Wardova metóda)
Zhlukovanie v prípade Wardovej metódy prebieha zdola smerom nahor,
t.j. začíname s jednočlennými klastrami, ktoré postupne zlučujeme. Táto
metóda patrí teda medzi aglomeratívne hierarchické metódy. Minimalizuje
nárast vnútornej variability pri spojení dvoch klastrov, pričom využíva
nasledovné výpočty:
Wardová metóda minimalizuje sumu štvorcov chýb (Error sum of Squares
- ESS)
\[ESS(C) = \sum_{i \in C} \lVert x_i -
\bar{x}_C \rVert^2\] kde \(C\)
je zvažovaný klaster (zhluk). V každom kroku zlučovania dvoch klasterov,
Wardova metóda hľadá minimálny prírastok sumy štvorcov chýb (\(\Delta ESS\)), pričom
\[\Delta ESS = ESS(A \cup B) - ESS(A) -
ESS(B)\] Dvojica zhlukov, ktoré tejto podmienke o minimalizácii
vyhovuje, je následne zlúčená a prechádza sa k ďalšiemu kkroku. To
spravidla vedie k vytváraniu homogénnych zhlukov, pričom nedochádza k
odtrhávaniu odľahlých hodnôt tak, ako pri iných zhlukovacích
metódach.
Obr. 2. Hierarchické zhlukovanie - dendogram.
Červená čiara určuje rez definujúci tri klastre.
## ============================
## 4) Hierarchical klastering
## ============================
hc <- hclust(dist_mat, method = "ward.D2")
plot(hc, labels = rownames(udaje_scaled),
main = "Hierarchical klastering of countries (Ward.D2)",
xlab = "", sub = "")
k <- 3
h_cut <- hc$height[length(hc$height) - (k - 1)]
abline(h = h_cut, col = "red", lwd = 2, lty = 2)

klaster_membership <- cutree(hc, k = k)
udaje_klasters <- data.frame(
Country = rownames(udaje_complete),
udaje_complete,
klaster = factor(klaster_membership)
)
Tab.4. Príslušnosť krajín do klastrov.
## Tab. 4 – Príslušnosť krajín do klastrov
# Vytvoríme dátový rámec s krajinami a ich klastrom
data_prac <- data.frame(
Country = rownames(udaje_scaled),
klaster = udaje_klasters
)
# Zobrazíme výslednú tabuľku
data_prac
NA
# Výsledná tabuľka krajín a ich klastrov
data_prac <- data.frame(
Country = udaje_klasters$Country,
Klastor = udaje_klasters$klaster
)
data_prac
NA
Na základe hierarchickej zhlukovej analýzy (Wardova metóda) sme
analyzovali podobnosť desiatich európskych krajín podľa vybraných
ukazovateľov (Population 2025, Fertility Rate, Median Age, Net
Migration). Výsledkom procesu bolo rozdelenie krajín do troch klastrov,
pričom krajiny v rámci jedného klastru majú podobnejšie demografické
ukazovatele ako krajiny v iných klastroch.
Z tabuľky vidíme nasledovné zaradenie:
Klastre typu 1: tvorí ho Nemecko, Taliansko a Španielsko. Tieto
krajiny majú podobnú populačnú veľkosť a spoločné demografické črty,
napríklad nízku mieru plodnosti a vyšší mediánový vek, čo sú typické
znaky západoeurópskych krajín s dlhodobým starnutím populácie.
Klastre typu 2: sem spadajú Spojené kráľovstvo, Francúzsko, Poľsko,
Holandsko, Belgicko a Ukrajina. Ide o najrozmanitejší klaster, ktorý
zahŕňa veľké aj stredne veľké krajiny s mierne vyššou plodnosťou,
odlišným migračným profilom a rôznorodým vekovým zložením populácie.
Klastre typu 3: predstavuje ho len Rumunsko. Zaradenie Rumunska do
samostatného klastru naznačuje, že sa jeho demografické charakteristiky
významne odlišujú od ostatných analyzovaných krajín — napríklad nižšou
populačnou veľkosťou, špecifickou migráciou či výraznejšími rozdielmi v
plodnosti alebo vekovej štruktúre.
Celkovo môžeme konštatovať, že klastrová analýza odhalila prirodzené
skupiny krajín so spoločnými demografickými znakmi. Najviac homogénny je
klaster č. 1, zatiaľ čo klaster č. 2 zahŕňa krajiny s väčšou vnútornou
variabilitou. Samostatné postavenie Rumunska v klasteri č. 3 poukazuje
na jeho výraznú odlišnosť od ostatných európskych krajín v sledovaných
premenných.
Deskriptívne štatistiky výsledkov
Pri analýze rozkladu variancie sledujeme, aká časť variability
jednotlivých premenných je vysvetlená samotným klastrovým riešením.
Kľúčovým ukazovateľom je stĺpec Prop_Between, ktorý udáva podiel
variability vysvetlenej rozdielmi medzi klastrami (BSS / TSS). Čím je
táto hodnota vyššia, tým lepšie klastrovanie zachytáva rozdiely medzi
krajinami podľa danej premennej.
Z Tab. 5. vyplýva nasledovné:
Population.2025 – Prop_Between ≈ 0.268 Podiel variability vysvetlenej
klastrami je približne 27 %, čo znamená, že populácia iba mierne
prispieva k odlišovaniu klastrov. Krajiny sa teda z hľadiska veľkosti
populácie v roku 2025 neodlišujú natoľko, aby tvorili jasne oddelené
skupiny.
Fert..Rate – Prop_Between ≈ 0.621 Miera plodnosti vysvetľuje až 62 %
variability medzi klastrami, čo je pomerne vysoká hodnota. To znamená,
že fertilita je významným faktorom, podľa ktorého sa krajiny skutočne
odlišujú. Klastry teda zachytávajú rozdiely v demografickej dynamike
veľmi dobre.
Median.Age – Prop_Between ≈ 0.821 Až 82 % variability v mediánovom
veku je vysvetlených klastrami. Ide o najvyššiu hodnotu zo všetkých
sledovaných premenných. Znamená to, že mediánový vek populácie je
dominantným ukazovateľom, ktorý najlepšie odlišuje vytvorené skupiny
krajín. Krajiny sa teda výrazne líšia v tom, či majú mladšiu alebo
staršiu populáciu.
Migrants..net – nebolo možné vyhodnotiť (NA) Pre túto premennú nebol
výpočet možný, pravdepodobne kvôli chýbajúcim hodnotám (NA). Preto
nevystupuje v rozklade variancie ani v posudzovaní vhodnosti
klastrovania.
Tab. 5. Vysvetlenie vnútroklastrovej variability z
hľadiska jednotlivých premenných
## ============================
## 5) Variability measures
## ============================
ssq <- function(x, m) sum((x - m)^2)
var_names <- colnames(udaje_scaled)
TSS <- sapply(var_names, function(v) ssq(udaje_scaled[, v], mean(udaje_scaled[, v])))
WSS <- sapply(var_names, function(v) {
x <- udaje_scaled[, v]
tapply(x, klaster_membership, function(z) ssq(z, mean(z))) |> sum()
})
BSS <- TSS - WSS
ss_table <- data.frame(
Variable = var_names,
TSS = TSS,
WSS = WSS,
BSS = BSS,
Prop_Between = BSS / TSS
)
ss_table
# Pridáme ku datasetu priradené klastry
udaje10 <- data.frame(
Country = udaje10$Country..or.dependency.,
Population.2025 = udaje10$Population.2025,
Fert..Rate = udaje10$Fert..Rate,
Median.Age = udaje10$Median.Age,
Migrants..net. = udaje10$Migrants..net.,
klaster = udaje_klasters$klaster
)
# Zobrazenie výsledného datasetu
udaje10
NA
Tab. 6. Centroidy - priemerné hodnoty sledovaných
premenných
library(dplyr)
descriptives <- udaje10 %>%
group_by(klaster) %>%
summarise(
across(
.cols = where(is.numeric),
.fns = list(
mean = ~mean(.x, na.rm = TRUE)
),
.names = "{.col}_{.fn}"
)
)
descriptives
NA
Na záver sme porovnali priemerné charakteristiky troch klastrov
vybraných európskych krajín.
Klaster 1 (Nemecko, Taliansko, Španielsko) má
najväčšiu priemernú populáciu – približne 63,7
milióna obyvateľov, strednú mieru plodnosti
okolo 1,30 dieťaťa na ženu a zároveň najvyšší
mediánový vek (≈ 46,5 roka). Tento klaster
teda reprezentuje veľké a demograficky „starnúce“ krajiny so skôr
nižšou, ale nie úplne kriticky nízkou plodnosťou.
Klaster 2 (Spojené kráľovstvo, Francúzsko, Poľsko,
Rumunsko, Holandsko, Belgicko) má nižšiu priemernú
populáciu – asi 37,2 milióna obyvateľov, no
zároveň najvyššiu priemernú mieru plodnosti (≈
1,51) a mladšiu vekovú štruktúru s mediánovým
vekom približne 41,9 roka. Tento klaster združuje
stredne veľké krajiny, kde je plodnosť relatívne najvyššia a populácia
je v priemere mladšia než v klustri 1.
Klaster 3 je tvorený jedinou krajinou –
Ukrajinou. Jej priemerná (a zároveň skutočná) populácia
je približne 38,98 milióna obyvateľov, pričom má
najnižšiu mieru plodnosti (≈ 1,00) a
mediánový vek okolo 41,8 roka. Tento klaster
predstavuje krajinu s veľmi nízkou plodnosťou, pri vekovej štruktúre
podobnej klastru 2.
Z porovnania klastrov vidno, že najvyšší priemerný počet obyvateľov
sa spája so staršou populáciou (klaster 1), zatiaľ čo najvyššia plodnosť
sa vyskytuje v krajinách so skôr mladšou populáciou (klaster 2).
Ukrajina tvorí samostatný klaster kvôli kombinácii priemernej veľkosti
populácie a extrémne nízkej miery plodnosti.
Záver
Predložená analýza sa zameriava na demografické charakteristiky
vybraných európskych krajín na základe ich predpokladanej populácie v
roku 2025, miery plodnosti a mediánu veku obyvateľstva. Na základe
týchto premenných boli krajiny rozdelené do troch klastrov, pričom
jednotlivé klastry odrážajú spoločné demografické črty týchto
štátov.
Výsledné klastry predstavujú tri odlišné skupiny krajín. Prvý klaster
tvoria štáty s najvyššou predpokladanou populáciou a zároveň vyšším
mediánovým vekom obyvateľstva, čo naznačuje starnúcu populáciu veľkých
krajín. Druhý klaster združuje krajiny s relatívne vyššou mierou
plodnosti a strednými hodnotami populácie, čo poukazuje na dynamickejší
populačný vývoj. Tretí klaster obsahuje krajiny s najnižšou mierou
plodnosti a zároveň strednou až nižšou veľkosťou populácie.
Takáto klasifikácia umožňuje pochopiť vzťahy medzi demografickými
ukazovateľmi a poukazuje na podobnosti v populačnom vývoji naprieč
Európou. Analýza môže slúžiť ako podklad pre tvorbu populačných či
sociálnych politík, prípadne pre ďalšie porovnávacie štúdie medzi
európskymi krajinami.
LS0tCnRpdGxlOiAiWmhsdWtvdsOhIGFuYWzDvXphIChrbGFzdGVyIEFuYWx5c2lzKSIKYXV0aG9yOiAiUmFkb3ZhbiBTdGFuxI3DrWsiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCi0tLS0tLS0tLQoKYGBge3Igc2V0dXAxLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyAgICA9IFRSVUUsICAgIyBkbyBub3Qgc2hvdyBjb2RlCiAgbWVzc2FnZSA9IFRSVUUsICAgIyBzdXBwcmVzcyBwYWNrYWdlL3N5c3RlbSBtZXNzYWdlcwogIHdhcm5pbmcgPSBGQUxTRSwgICAjIHN1cHByZXNzIHdhcm5pbmdzCiAgZXJyb3IgICA9IEZBTFNFICAgICMgc3VwcHJlc3MgZXJyb3Igb3V0cHV0CikKYGBgCgojIyDDmnZvZAoKS2xhc3Ryb3bDoSAoemhsdWtvdsOhKSBhbmFsw716YSBwYXRyw60gbWVkemkgbmFqcG91xb7DrXZhbmVqxaFpZSBtZXTDs2R5IGV4cGxvcmF0w612bmVqIMWhdGF0aXN0aWt5LiBWIHByYXhpIHNhIHZ5dcW+w612YSB2xaFhZGUgdGFtLCBrZGUgamUgcG90cmVibsOpIHJvemRlbGnFpSBwb3pvcm92YW5pYSBkbyBob21vZ8Opbm55Y2ggY2Vsa292IC0gbmFwcsOta2xhZCBwcmkgc2VnbWVudMOhY2lpIHrDoWthem7DrWtvdiB2IG1hcmtldGluZ3UsIGlkZW50aWZpa8OhY2lpIHBvZG9ibsO9Y2gga3JhasOtbiB2IG1ha3JvZWtvbm9taWNrw71jaCB1a2F6b3ZhdGXEvm9jaCwgaG9kbm90ZW7DrXpkcmF2b3Ruw71jaCByaXrDrWssIGtsYXNpZmlrw6FjaWkgYmlvbG9naWNrw71jaCB2em9yaWVrIMSNaSB2IGdlb2luZm9ybWF0aWtlIHByaSB6b3NrdXBvdmFuw60gcHJpZXN0b3JvdsO9Y2ggc29iamVrdG92LiBKZWogdsO9aG9kb3UgamUsIMW+ZSBwcmFjdWplIHMgdmlhY2Vyw71taSBwcmVtZW5uw71taSBuYXJheiBhIGRva8Ohxb5lIG9kaGFsacWlIHZ6b3J5LCBrdG9yw6kgYnkgcHJpIHNhbW90bm9tIGhvZG5vdGVuw60gamVkbm90bGl2w71jaCB1a2F6b3ZhdGXEvm92IHpvc3RhbGkgc2tyeXTDqS4gU3Byw6F2bmUgenZvbGVuw6EgbWV0cmlrYSB2emRpYWxlbm9zdGkgYSBtZXTDs2RhIHpobHVrb3ZhbmlhIHVtb8W+xYh1asO6IG9kaGFsacWlIHNrcnl0w6kgdnrFpWFoeSB2IGTDoXRhY2gsIMSNw61tIHBvc2t5dHVqw7ogY2VubsO9IHBvZGtsYWQgcHJlIHJvemhvZG92YW5pZSB2IHLDtHpueWNoIG9ibGFzdGlhY2ggYXBsaWtvdmFuw6lobyB2w71za3VtdS4KClByZWRzdGF2w61tIHpobHVrb3bDuiBhbmFsw716dSBwcmkgYW5hbMO9emUga3JhasOtbiBzdmV0YSB6IGjEvmFkaXNrYSBkZW1vZ3JhZmlja8O9Y2ggdWthem92YXRlxL5vdiwgYWtvIHPDuiBwcmVkcG9rbGFkYW7DoSBwb3B1bMOhY2lhIHYgcm9rdSAyMDI1LCBtaWVyYSBwbG9kbm9zdGksIG1lZGnDoW4gdmVrdSBhIMSNaXN0w6EgbWlncsOhY2lhLiBDaWXEvm9tIGplIGlkZW50aWZpa292YcWlIHNrdXBpbnkga3JhasOtbiwga3RvcsOpIG1hasO6IHBvZG9ibsOpIGRlbW9ncmFmaWNrw6kgcHJvZmlseSBhIG3DtMW+dSBiecWlIHByZXRvIGFuYWx5em92YW7DqSBzcG9sb8SNbmUuIFRha3RvIHZ5dHZvcmVuw6kgemhsdWt5IHBvc2t5dHVqw7ogcHJlaMS+YWQgbyBrcmFqaW7DoWNoIHMgcG9kb2Juw71tIHBvcHVsYcSNbsO9bSB2w712b2pvbSDEjWkgZHluYW1pa291IHJhc3R1IHBvcHVsw6FjaWUuIFByaSBhbmFsw716ZSB2eXXFvsOtdmFtZSBuYWpub3bFoWllIGRvc3R1cG7DqSDDumRhamUgeiBkYXRhYsOhenksIHMga3Rvcm91IHNtZSBwcmFjb3ZhbGkgYWogdiBwcmVkY2jDoWR6YWrDumNpY2ggxI1hc3RpYWNoLgoKYGBge3Igc2V0dXAyLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmBgYAoKYGBge3IgdGFibGUxLCBtZXNzYWdlPUZBTFNFfQojIE5hxI3DrXRhbmllIGTDoXQKdWRhamUgPC0gcmVhZC5jc3YoInBvcHVsYXRpb25fZGF0YS5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIDEwIGV1csOzcHNreWNoIGtyYWrDrW4sIHMga3RvcsO9bWkgY2hjZW0gcHJhY292YcWlCmtyYWppbnkxMCA8LSBjKCJHZXJtYW55IiwKICAgICAgICAgICAgICAgIlVuaXRlZCBLaW5nZG9tIiwKICAgICAgICAgICAgICAgIkZyYW5jZSIsCiAgICAgICAgICAgICAgICJJdGFseSIsCiAgICAgICAgICAgICAgICJTcGFpbiIsCiAgICAgICAgICAgICAgICJVa3JhaW5lIiwKICAgICAgICAgICAgICAgIlBvbGFuZCIsCiAgICAgICAgICAgICAgICJSb21hbmlhIiwKICAgICAgICAgICAgICAgIk5ldGhlcmxhbmRzIiwKICAgICAgICAgICAgICAgIkJlbGdpdW0iKQoKIyBWw71iZXIgbGVuIHTDvWNodG8ga3JhasOtbiBhIHBvxb5hZG92YW7DvWNoIHByZW1lbm7DvWNoCnVkYWplMTAgPC0gc3Vic2V0KAogIHVkYWplLAogIENvdW50cnkuLm9yLmRlcGVuZGVuY3kuICVpbiUga3JhamlueTEwLAogIHNlbGVjdCA9IGMoCiAgICBDb3VudHJ5Li5vci5kZXBlbmRlbmN5LiwKICAgIFBvcHVsYXRpb24uMjAyNSwKICAgIEZlcnQuLlJhdGUsCiAgICBNZWRpYW4uQWdlLAogICAgTWlncmFudHMuLm5ldC4KICApCikKCiMgUHJlIHBvbWVub3ZhbmllIHN0xLpwY292IHYgdGFidcS+a2UKY29sbmFtZXModWRhamUxMCkgPC0gYygKICAiS3JhamluYSIsCiAgIlBvcHVsw6FjaWEgMjAyNSIsCiAgIk1pZXJhIHBsb2Rub3N0aSIsCiAgIk1lZGnDoW4gdmVrdSIsCiAgIsSMaXN0w6EgbWlncsOhY2lhIgopCgpgYGAKCioqVGFibGUgMS4qKgpgYGB7cn0KdWRhamUxMApgYGAKCkhpZXJhcmNoaWNrw6EgemhsdWtvdsOhIGFuYWzDvXphIHByYWN1amUgcyBtaWVyYW1pIHZ6ZGlhbGVub3N0aSBtZWR6aSBwb3pvcm92YW5pYW1pLiBBYnkgYm9saSB0aWV0byB2emRpYWxlbm9zdGkgcG9yb3ZuYXRlxL5uw6ksIGplIHBvdHJlYm7DqSwgYWJ5IHbFoWV0a3kgcHJlbWVubsOpIGJvbGkgZGVmaW5vdmFuw6kgbmEgcm92bmFrZWrFoWvDoWxlLiBQb3XFvsOtdmFtZSBwcml0b20gdHp2LiB6LcWha8OhbG92YW5pZSwgcHJpxI1vbSB0cmFuc2Zvcm1vdmFuw6kgJHokIGhvZG5vdHkgKHNrw7NyZSkgdnlwb8SNw610YW1lIG5hc2xlZG92bmUKCiQkeiA9IFxmcmFje3gtXG11fXtcc2lnbWF9JCQKCmtkZSAkXG11JCBqZSBzdHJlZG7DoSBob2Rub3RhIGEgJFxzaWdtYSQgamUgxaF0YW5kYXJkbsOhIG9kY2jDvWxrYSBwb3pvcm92YW7DrSAkeCQuIFByZWRwb2tsYWTDoW1lIHByaXRvbSwgxb5lIHPDumJvciDDumRham92IHXFviBuZW9ic2FodWplIE5BIGhvZG5vdHksIGt0b3LDqSBib2xpIG/FoWV0cmVuw6kgdiBwcmVkY2jDoWR6YWrDumNpY2gga3Jva29jaC4KClRvdXRvIG9wZXLDoWNpb3UgesOtc2thbWUgxaFrw6Fsb3ZhbsOpIHBvem9yb3ZhbmlhLCBwcmnEjW9tIGljaCByb3psb8W+ZW5pZSBqZSB6bsOhem9ybmVuw6kgbmFzbGVkb3ZuZToKCmBgYHtyfQojIDEpIE5hxI3DrXRhbmllIGTDoXQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp1ZGFqZSA8LSByZWFkLmNzdigicG9wdWxhdGlvbl9kYXRhLmNzdiIsCiAgICAgICAgICAgICAgICAgIHNlcCA9ICIsIiwKICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyAyKSBWeWJlcmllbWUgMTAgZXVyw7Nwc2t5Y2gga3JhasOtbiwgcyBrdG9yw71taSBjaGNlbWUgcHJhY292YcWlIC0tLS0tLS0tLS0Ka3JhamlueTEwIDwtIGMoIkdlcm1hbnkiLAogICAgICAgICAgICAgICAiVW5pdGVkIEtpbmdkb20iLAogICAgICAgICAgICAgICAiRnJhbmNlIiwKICAgICAgICAgICAgICAgIkl0YWx5IiwKICAgICAgICAgICAgICAgIlNwYWluIiwKICAgICAgICAgICAgICAgIlVrcmFpbmUiLAogICAgICAgICAgICAgICAiUG9sYW5kIiwKICAgICAgICAgICAgICAgIlJvbWFuaWEiLAogICAgICAgICAgICAgICAiTmV0aGVybGFuZHMiLAogICAgICAgICAgICAgICAiQmVsZ2l1bSIpCgojIGZpbHRlciBuYSB0w71jaHRvIDEwIGtyYWrDrW4KdWRhamUxMCA8LSBzdWJzZXQodWRhamUsIENvdW50cnkuLm9yLmRlcGVuZGVuY3kuICVpbiUga3JhamlueTEwKQoKIyBwcmUgaXN0b3R1IHpvcmFkw61tZSByaWFka3kgdiByb3ZuYWtvbSBwb3JhZMOtIGFrbyB2byB2ZWt0b3JlIGtyYWppbnkxMAp1ZGFqZTEwIDwtIHVkYWplMTBbbWF0Y2goa3JhamlueTEwLCB1ZGFqZTEwJENvdW50cnkuLm9yLmRlcGVuZGVuY3kuKSwgXQoKIyAzKSBQcmlwcmF2w61tZSBkw6F0b3bDvSByw6FtZWMgbGVuIHMgxI3DrXNlbG7DvW1pIHByZW1lbm7DvW1pIC0tLS0tLS0tLS0tLS0tLS0tCiMgICAgKHBvcHVsw6FjaWEgMjAyNSwgbWllcmEgcGxvZG5vc3RpLCBtZWRpw6FuIHZla3UsIMSNaXN0w6EgbWlncsOhY2lhKQp1ZGFqZV9jb21wbGV0ZSA8LSB1ZGFqZTEwWywgYygiUG9wdWxhdGlvbi4yMDI1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZlcnQuLlJhdGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWVkaWFuLkFnZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNaWdyYW50cy4ubmV0LiIpXQoKIyBpc3RvdGE6IHByZXR5cHVqZW1lIHN0xLpwY2UgbmEgbnVtZXJpYyAoa2VieSBpY2ggUiBuYcSNw610YWwgYWtvIHRleHQpCnVkYWplX2NvbXBsZXRlW10gPC0gbGFwcGx5KHVkYWplX2NvbXBsZXRlLCBmdW5jdGlvbih4KSBhcy5udW1lcmljKHgpKQoKIyBwb21lbnVqZW1lIHJpYWRreSBwb2TEvmEga3JhasOtbgpyb3duYW1lcyh1ZGFqZV9jb21wbGV0ZSkgPC0gdWRhamUxMCRDb3VudHJ5Li5vci4uZGVwZW5kZW5jeS4KCiMgNCkgxaBrw6Fsb3ZhbmllIHByZW1lbm7DvWNoICh6LXNrw7NyZSkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnVkYWplX3NjYWxlZCA8LSBzY2FsZSh1ZGFqZV9jb21wbGV0ZSkKCiMgVsO9c3R1cHkgZG8gdGFidcS+a3kgKG5hanBydiBww7R2b2Ruw6kgZMOhdGEsIHBvdG9tIMWha8OhbG92YW7DqSkKdWRhamVfY29tcGxldGUgICAgICAjIG5lxaFrw6Fsb3ZhbsOpIGhvZG5vdHkKdWRhamVfc2NhbGVkICAgICAgICAjIHotc2vDs3JlCgpgYGAKCgoqKk9ici4gMS4qKgpgYGB7ciBib3hwbG90cywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLnNob3c9J2hvbGQnfQpudW1fdmFycyA8LSBhcy5kYXRhLmZyYW1lKHVkYWplX3NjYWxlZCkKbnVtX3Bsb3RzIDwtIG5jb2wobnVtX3ZhcnMpCgpwYXIobWZyb3cgPSBjKGNlaWxpbmcoc3FydChudW1fcGxvdHMpKSwgY2VpbGluZyhudW1fcGxvdHMgLyBjZWlsaW5nKHNxcnQobnVtX3Bsb3RzKSkpKSkKcGFyKG1hciA9IGMoNCwgNCwgMiwgMSkpCgpmb3IgKGNvbCBpbiBuYW1lcyhudW1fdmFycykpIHsKICBib3hwbG90KG51bV92YXJzW1tjb2xdXSwKICAgICAgICAgIG1haW4gPSBjb2wsCiAgICAgICAgICBjb2wgPSAibGlnaHRibHVlIiwKICAgICAgICAgIGhvcml6b250YWwgPSBUUlVFKQp9CgptdGV4dCgiQm94cGxvdHkgbnVtZXJpY2vDvWNoIHByZW1lbm7DvWNoICh2eWJyYW7DvWNoIDEwIGtyYWrDrW4pIiwgb3V0ZXIgPSBUUlVFLCBjZXggPSAxLjMsIGZvbnQgPSAyKQpgYGAKCgpUZW50b2tyw6F0IG9kxL5haGzDqSBob2Rub3R5IG5ldnlsw7rEjWltZSwgbmFrb8S+a28gZGVmaW51asO6IGtvbmtyw6l0bnUga3JhamludS4gCgoKClByaSB6aGx1a292ZWogYW5hbMO9emUgamUgZMO0bGXFvml0w6Ega29yZWxhxI1uw6EgbWF0aWNhIHByZW1lbm7DvWNoLiBWeXNva8OhIGtvcmVsw6FjaWEgenbDvWhvZMWIdWplIHByaSB6aGx1a292ZWogYW5hbMO9emUga29yZWxvdmFuw6kgcHJlbWVubsOpLiBQcmV0byBwcmkga29yZWzDoWNpaSBuYWQgMCw4IGFsZWJvIDAuOSB2eWzDusSNaW1lIGplZG51IHoga29yZWxvdmFuw71jaCBwcmVtZW5uw71jaC4gViAqKlRhYi4gMi4qKiBzYSB2xaFhayB0YWvDoXRvIHZ5c29rw6Ega29yZWzDoWNpYSBuZW5hY2jDoWR6YSwgcHJldG8gc2EgbmVtdXPDrW1lIMSPYWxlaiBzIHByb2Jsw6ltb20gemFvYmVyYcWlLiAKPiBWIHByw61wYWRlLCBhayBtw6FtZSB2w6TEjcWhw60gcG/EjWV0IHbDvXpuYW1uZSBrb3JlbG92YW7DvWNoIHByZW1lbm7DvWNoLCBzYSBvZHBvcsO6xI1hIGkgdHJhbnNmb3Jtw6FjaWEgcG9tb2NvdSBBbmFsw716eSBobGF2bsO9Y2gga29tcG9uZW50b3YgKFByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMpIApQcmkgemhsdWtvdmVqIGFuYWzDvXplIGplIGTDtGxlxb5pdMOhIGtvcmVsYcSNbsOhIG1hdGljYSBwcmVtZW5uw71jaC4gVnlzb2vDoSBrb3JlbMOhY2lhIG1lZHppIHByZW1lbm7DvW1pIG3DtMW+ZSBzcMO0c29ib3ZhxaUsIMW+ZSBuaWVrdG9yw6kgeiBuaWNoIGJ1ZMO6IG1hxaUgcHJpIHR2b3JiZSB6aGx1a292IG5lcHJpbWVyYW5lIHZlxL5rw70gdnBseXYuIFByZXRvIHNhIHByaSBrb3JlbMOhY2nDoWNoIHZ5xaHFocOtY2ggYWtvIDAuOCDigJMgMC45IMSNYXN0byBvZHBvcsO6xI1hIHZ5bMO6xI1pxaUgamVkbnUgeiBkdm9qaWNlIHNpbG5lIGtvcmVsb3ZhbsO9Y2ggcHJlbWVubsO9Y2guIFYgbmHFoW9tIHByw61wYWRlIChwb3pyaSAqKlRhYi4gMioqKSB2xaFhayDFvmlhZG5hIHoga29yZWzDoWNpw60gbmVkb3NhaHVqZSBob2Rub3R1LCBrdG9yw6EgYnkgYm9sYSBwcm9ibGVtYXRpY2vDoToKCm5hanZ5xaHFoWlhIGtvcmVsw6FjaWEgamUgbWVkemkgcHJlbWVubsO9bWkgRmVydC4uUmF0ZSBhIE1pZ3JhbnRzLi5uZXQuIG5hIMO6cm92bmkg4oCTMC42NCwgb3N0YXRuw6kga29yZWzDoWNpZSBzYSBwb2h5YnVqw7ogbGVuIHYgaW50ZXJ2YWxlIHByaWJsacW+bmUg4oCTMC4zMCBhxb4gMC4zMiwgcHJlbWVubsOpIHRlZGEgbmllIHPDuiB2w71yYXpuZSBtdWx0aWtvbGluZcOhcm5lLiBUbyB6bmFtZW7DoSwgxb5lIHNhIG5lbXVzw61tZSB6YW9iZXJhxaUgb2RzdHJhxYhvdmFuw61tIHByZW1lbm7DvWNoIGFuaSB1dmHFvm92YcWlIG8gxI9hbMWhZWogdHJhbnNmb3Jtw6FjaWkgeiBkw7R2b2R1IHZ5c29rZWoga29yZWzDoWNpZS4gViBwcsOtcGFkZSwgxb5lIGJ5IHNtZSBtYWxpIHbDpMSNxaHDrSBwb8SNZXQgdmXEvm1pIGtvcmVsb3ZhbsO9Y2ggdWthem92YXRlxL5vdiwgYm9sbyBieSB2aG9kbsOpIHp2w6HFvmnFpSB0cmFuc2Zvcm3DoWNpdSBwb21vY291IEFuYWzDvXp5IGhsYXZuw71jaCBrb21wb25lbnRvdiAoUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcykuIFYgbmHFoW9tIHByw61wYWRlIHRvIHbFoWFrIG5pZSBqZSBwb3RyZWJuw6kuCgoKKipUYWIuIDIqKgpgYGB7cn0KY29yX21hdCA8LSBjb3IodWRhamVfc2NhbGVkLCB1c2U9InBhaXJ3aXNlLmNvbXBsZXRlLm9icyIpCmNvcl9tYXQgPC0gcm91bmQoY29yX21hdCwyKQpwcmludChjb3JfbWF0KQpgYGAKS2HFvmRlaiBrcmFqaW5lIHpvZHBvdmVkw6EgamVkZW4gcmlhZG9rIHBvem9yb3ZhbsOtLiBWemRpYWxlbm9zxaUgbWVkemkga3JhamluYW1pICRpJCBhICRqJCBqZToKCiQkCmRee2lqfSA9IFxzcXJ0e1xzdW1fayAoeF5pX2sgLSB4XmpfayleMn0KJCQKa2RlICR4XmlfayQgamUgJGskdGEgcHJlbWVubsOhIHZzdHVwdWrDumNhIGRvIHbDvXBvxI10dSAoUG9wdWxhdGlvbi4yMDI1LCBGZXJ0Li5SYXRlLCBNZWRpYW4uQWdlIGEgTWlncmFudHMuLm5ldC4pIGtyYWppbnkgJGkkLiAgVGVudG8gdHlwIHZ6ZGlhbGVub3N0aSBuYXrDvXZhbWUgYWogRXVrbGlkb3Zza8OhIHZ6ZGlhbGVub3PFpS4gVnpkaWFsZW5vc3RpIG1lZHppIGplZG5vdGxpdsO9bWkga3JhamluYW1pIHNhIHPDumhybm5lIHZ5amFkcnVqw7ogYWogdiBtYXRpY2kgdnpkaWFsZW5vc3RpLCDEjW8gdiBuYcWhb20gcHLDrXBhZGUgamUgdXZlZGVuw6kgdiAqKlRhYi4zLioqLiBOYSB6w6FrbGFkZSB2w71zbGVka292IHogKipUYWIuIDMqKiBtw7TFvmVtZSB1dmllc8WlIG5hc2xlZG92bsOpOgoKTmFqdsOkxI3FoWlhIHZ6ZGlhbGVub3PFpSAodC4gai4gbmFqbWVuxaFpYSBwb2RvYm5vc8WlKSBib2xhIHppc3RlbsOhIG1lZHppIFVrcmFqaW5vdSBhIE5lbWVja29tICgzLjcwKSwgYWtvIGFqIG1lZHppIFVrcmFqaW5vdSBhIEZyYW5jw7p6c2tvbSAoMy42MikuIFRpZXRvIGtyYWppbnkgc2EgdsO9cmF6bmUgbMOtxaFpYSBuYWptw6QgdiBtaWdyYcSNbmVqIGJpbGFuY2lpLCB2ZWtvdmVqIMWhdHJ1a3TDunJlIGFqIHBsb2Rub3N0aS4gU2lsbsOpIHJvemRpZWx5IHBvem9ydWplbWUgYWogbWVkemkgUnVtdW5za29tIGEgRMOhbnNrb20gKDMuMTkpIGEgUnVtdW5za29tIGEgSG9sYW5kc2tvbSAoMy4zNiksIMSNbyBtw7TFvmUgc8O6dmlzaWXFpSBzIHZ5xaHFoW91IHBsb2Rub3PFpW91IGEgb2RsacWhbm91IG1pZ3JhxI1ub3UgZHluYW1pa291IFJ1bXVuc2thLiBOYWptZW7FoWl1IHZ6ZGlhbGVub3PFpSwgdGVkYSBuYWp2w6TEjcWhaXUgcG9kb2Jub3PFpSwgbmFjaMOhZHphbWUgbWVkemk6CkhvbGFuZHNrb20gYSBCZWxnaWNrb20gKDAuNDEpLCBGcmFuY8O6enNrb20gYSBCZWxnaWNrb20gKDEuMTMpLCBOZW1lY2tvbSBhIFZlxL5rb3UgQnJpdMOhbmlvdSAoMi42NSkKVGlldG8ga3JhamlueSB2eWthenVqw7ogcG9kb2Juw6kgaG9kbm90eSBtZWRpYW51IHZla3UgYSByZWxhdMOtdm5lIHZ5cm92bmFuw7ogbWlncmHEjW7DuiBiaWxhbmNpdS4KU3RyZWRuw6Egw7pyb3ZlxYggcG9kb2Jub3N0aSBqZSBuYXByw61rbGFkIG1lZHppIFBvxL5za29tIGEgxaBwYW5pZWxza29tICgxLjcxKSBhbGVibyBGcmFuY8O6enNrb20gYSDFoHBhbmllbHNrb20gKDIuOTQpLgpDZWxrb3ZvIHRlZGEgdmlkw61tZSwgxb5lIGV1csOzcHNrZSBrcmFqaW55IHZ5dHbDoXJhasO6IHBvZMS+YSBzdm9qaWNoIHVrYXpvdmF0ZcS+b3YgcHJpcm9kemVuw6kgc2t1cGlueSDigJMgbmFwci4gQmVsZ2lja2/igJNIb2xhbmRza28sIE5lbWVja2/igJNVSywgemF0aWHEviDEjW8ga3JhamlueSBha28gVWtyYWppbmEgxI1pIFJ1bXVuc2tvIHNhIG9kIHbDpMSNxaFpbnkgb3N0YXRuw71jaCB2w71yYXpuZWrFoWllIG9kbGnFoXVqw7ouCgoqKlRhYi4gMyoqCmBgYHtyfQojIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMjIDMpIERpc3RhbmNlIG1hdHJpeAojIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojIFBvbWVub3ZhbmllIHJpYWRrb3YgcG9kxL5hIDEwIHp2b2xlbsO9Y2gga3JhasOtbgpyb3duYW1lcyh1ZGFqZV9zY2FsZWQpIDwtIGMoIkdlcm1hbnkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuaXRlZCBLaW5nZG9tIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGcmFuY2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkl0YWx5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTcGFpbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVWtyYWluZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUG9sYW5kIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSb21hbmlhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZXRoZXJsYW5kcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmVsZ2l1bSIpCgojIFbDvXBvxI1ldCBldWtsaWRvdnNrZWogdnpkaWFsZW5vc3RpIGEgemFva3LDumhsZW5pZSBuYSAyIGRlc2F0aW5uw6kgbWllc3RhCmRpc3RfbWF0IDwtIHJvdW5kKGRpc3QodWRhamVfc2NhbGVkLCBtZXRob2QgPSAiZXVjbGlkZWFuIiksIDIpCgpkaXN0X21hdAoKYGBgCgoKIyMgUHJpbmPDrXAgaGllcmFyY2hpY2vDqWhvIHpobHVrb3ZhbmlhIChXYXJkb3ZhIG1ldMOzZGEpCgpaaGx1a292YW5pZSB2IHByw61wYWRlIFdhcmRvdmVqIG1ldMOzZHkgcHJlYmllaGEgemRvbGEgc21lcm9tIG5haG9yLCB0LmouIHphxI3DrW5hbWUgcyBqZWRub8SNbGVubsO9bWkga2xhc3RyYW1pLCBrdG9yw6kgcG9zdHVwbmUgemx1xI11amVtZS4gVMOhdG8gbWV0w7NkYSBwYXRyw60gdGVkYSBtZWR6aSBhZ2xvbWVyYXTDrXZuZSBoaWVyYXJjaGlja8OpIG1ldMOzZHkuIE1pbmltYWxpenVqZSBuw6FyYXN0IHZuw7p0b3JuZWogdmFyaWFiaWxpdHkgcHJpIHNwb2plbsOtIGR2b2NoIGtsYXN0cm92LCBwcmnEjW9tIHZ5dcW+w612YSBuYXNsZWRvdm7DqSB2w71wb8SNdHk6CgpXYXJkb3bDoSBtZXTDs2RhIG1pbmltYWxpenVqZSBzdW11IMWhdHZvcmNvdiBjaMO9YiAoRXJyb3Igc3VtIG9mIFNxdWFyZXMgLSBFU1MpCgokJEVTUyhDKSA9IFxzdW1fe2kgXGluIEN9IFxsVmVydCB4X2kgLSBcYmFye3h9X0MgXHJWZXJ0XjIkJAprZGUgJEMkIGplIHp2YcW+b3ZhbsO9IGtsYXN0ZXIgKHpobHVrKS4gViBrYcW+ZG9tIGtyb2t1IHpsdcSNb3ZhbmlhIGR2b2NoIGtsYXN0ZXJvdiwgV2FyZG92YSBtZXTDs2RhIGjEvmFkw6EgbWluaW3DoWxueSBwcsOtcmFzdG9rIHN1bXkgxaF0dm9yY292IGNow71iICgkXERlbHRhIEVTUyQpLCBwcmnEjW9tCgokJFxEZWx0YSBFU1MgPSBFU1MoQSBcY3VwIEIpIC0gRVNTKEEpIC0gRVNTKEIpJCQKRHZvamljYSB6aGx1a292LCBrdG9yw6kgdGVqdG8gcG9kbWllbmtlIG8gbWluaW1hbGl6w6FjaWkgdnlob3Z1amUsIGplIG7DoXNsZWRuZSB6bMO6xI1lbsOhIGEgcHJlY2jDoWR6YSBzYSBrIMSPYWzFoWllbXUga2tyb2t1LiBUbyBzcHJhdmlkbGEgdmVkaWUgayB2eXR2w6FyYW5pdSBob21vZ8Opbm55Y2ggemhsdWtvdiwgcHJpxI1vbSBuZWRvY2jDoWR6YSBrIG9kdHJow6F2YW5pdSBvZMS+YWhsw71jaCBob2Ruw7R0IHRhaywgYWtvIHByaSBpbsO9Y2ggemhsdWtvdmFjw61jaCBtZXTDs2RhY2guCgoKKipPYnIuIDIuKiogSGllcmFyY2hpY2vDqSB6aGx1a292YW5pZSAtIGRlbmRvZ3JhbS4gxIxlcnZlbsOhIMSNaWFyYSB1csSNdWplIHJleiBkZWZpbnVqw7pjaSB0cmkga2xhc3RyZS4KYGBge3J9CiMjID09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyMgNCkgSGllcmFyY2hpY2FsIGtsYXN0ZXJpbmcKIyMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKaGMgPC0gaGNsdXN0KGRpc3RfbWF0LCBtZXRob2QgPSAid2FyZC5EMiIpCgpwbG90KGhjLCBsYWJlbHMgPSByb3duYW1lcyh1ZGFqZV9zY2FsZWQpLAogICAgIG1haW4gPSAiSGllcmFyY2hpY2FsIGtsYXN0ZXJpbmcgb2YgY291bnRyaWVzIChXYXJkLkQyKSIsCiAgICAgeGxhYiA9ICIiLCBzdWIgPSAiIikKCmsgPC0gMwpoX2N1dCA8LSBoYyRoZWlnaHRbbGVuZ3RoKGhjJGhlaWdodCkgLSAoayAtIDEpXQphYmxpbmUoaCA9IGhfY3V0LCBjb2wgPSAicmVkIiwgbHdkID0gMiwgbHR5ID0gMikKCmtsYXN0ZXJfbWVtYmVyc2hpcCA8LSBjdXRyZWUoaGMsIGsgPSBrKQoKdWRhamVfa2xhc3RlcnMgPC0gZGF0YS5mcmFtZSgKICBDb3VudHJ5ID0gcm93bmFtZXModWRhamVfY29tcGxldGUpLAogIHVkYWplX2NvbXBsZXRlLAogIGtsYXN0ZXIgPSBmYWN0b3Ioa2xhc3Rlcl9tZW1iZXJzaGlwKQopCmBgYAoKKipUYWIuNC4qKiAgUHLDrXNsdcWhbm9zxaUga3JhasOtbiBkbyBrbGFzdHJvdi4KYGBge3J9CiMjIFRhYi4gNCDigJMgUHLDrXNsdcWhbm9zxaUga3JhasOtbiBkbyBrbGFzdHJvdgoKIyBWeXR2b3LDrW1lIGTDoXRvdsO9IHLDoW1lYyBzIGtyYWppbmFtaSBhIGljaCBrbGFzdHJvbQpkYXRhX3ByYWMgPC0gZGF0YS5mcmFtZSgKICBDb3VudHJ5ID0gcm93bmFtZXModWRhamVfc2NhbGVkKSwKICBrbGFzdGVyID0gdWRhamVfa2xhc3RlcnMKKQoKIyBab2JyYXrDrW1lIHbDvXNsZWRuw7ogdGFidcS+a3UKZGF0YV9wcmFjCgpgYGAKCmBgYHtyfQojIFbDvXNsZWRuw6EgdGFidcS+a2Ega3JhasOtbiBhIGljaCBrbGFzdHJvdgpkYXRhX3ByYWMgPC0gZGF0YS5mcmFtZSgKICBDb3VudHJ5ID0gdWRhamVfa2xhc3RlcnMkQ291bnRyeSwKICBLbGFzdG9yID0gdWRhamVfa2xhc3RlcnMka2xhc3RlcgopCgpkYXRhX3ByYWMKCmBgYApOYSB6w6FrbGFkZSBoaWVyYXJjaGlja2VqIHpobHVrb3ZlaiBhbmFsw716eSAoV2FyZG92YSBtZXTDs2RhKSBzbWUgYW5hbHl6b3ZhbGkgcG9kb2Jub3PFpSBkZXNpYXRpY2ggZXVyw7Nwc2t5Y2gga3JhasOtbiBwb2TEvmEgdnlicmFuw71jaCB1a2F6b3ZhdGXEvm92IChQb3B1bGF0aW9uIDIwMjUsIEZlcnRpbGl0eSBSYXRlLCBNZWRpYW4gQWdlLCBOZXQgTWlncmF0aW9uKS4gVsO9c2xlZGtvbSBwcm9jZXN1IGJvbG8gcm96ZGVsZW5pZSBrcmFqw61uIGRvIHRyb2NoIGtsYXN0cm92LCBwcmnEjW9tIGtyYWppbnkgdiByw6FtY2kgamVkbsOpaG8ga2xhc3RydSBtYWrDuiBwb2RvYm5lasWhaWUgZGVtb2dyYWZpY2vDqSB1a2F6b3ZhdGVsZSBha28ga3JhamlueSB2IGluw71jaCBrbGFzdHJvY2guCgpaIHRhYnXEvmt5IHZpZMOtbWUgbmFzbGVkb3Zuw6kgemFyYWRlbmllOgoKS2xhc3RyZSB0eXB1IDE6IHR2b3LDrSBobyBOZW1lY2tvLCBUYWxpYW5za28gYSDFoHBhbmllbHNrby4gVGlldG8ga3JhamlueSBtYWrDuiBwb2RvYm7DuiBwb3B1bGHEjW7DuiB2ZcS+a29zxaUgYSBzcG9sb8SNbsOpIGRlbW9ncmFmaWNrw6kgxI1ydHksIG5hcHLDrWtsYWQgbsOtemt1IG1pZXJ1IHBsb2Rub3N0aSBhIHZ5xaHFocOtIG1lZGnDoW5vdsO9IHZlaywgxI1vIHPDuiB0eXBpY2vDqSB6bmFreSB6w6FwYWRvZXVyw7Nwc2t5Y2gga3JhasOtbiBzIGRsaG9kb2LDvW0gc3Rhcm51dMOtbSBwb3B1bMOhY2llLgoKS2xhc3RyZSB0eXB1IDI6IHNlbSBzcGFkYWrDuiBTcG9qZW7DqSBrcsOhxL5vdnN0dm8sIEZyYW5jw7p6c2tvLCBQb8S+c2tvLCBIb2xhbmRza28sIEJlbGdpY2tvIGEgVWtyYWppbmEuIElkZSBvIG5hanJvem1hbml0ZWrFocOtIGtsYXN0ZXIsIGt0b3LDvSB6YWjFlcWIYSB2ZcS+a8OpIGFqIHN0cmVkbmUgdmXEvmvDqSBrcmFqaW55IHMgbWllcm5lIHZ5xaHFoW91IHBsb2Rub3PFpW91LCBvZGxpxaFuw71tIG1pZ3JhxI1uw71tIHByb2ZpbG9tIGEgcsO0em5vcm9kw71tIHZla292w71tIHpsb8W+ZW7DrW0gcG9wdWzDoWNpZS4KCktsYXN0cmUgdHlwdSAzOiBwcmVkc3RhdnVqZSBobyBsZW4gUnVtdW5za28uIFphcmFkZW5pZSBSdW11bnNrYSBkbyBzYW1vc3RhdG7DqWhvIGtsYXN0cnUgbmF6bmHEjXVqZSwgxb5lIHNhIGplaG8gZGVtb2dyYWZpY2vDqSBjaGFyYWt0ZXJpc3Rpa3kgdsO9em5hbW5lIG9kbGnFoXVqw7ogb2Qgb3N0YXRuw71jaCBhbmFseXpvdmFuw71jaCBrcmFqw61uIOKAlCBuYXByw61rbGFkIG5pxb7FoW91IHBvcHVsYcSNbm91IHZlxL5rb3PFpW91LCDFoXBlY2lmaWNrb3UgbWlncsOhY2lvdSDEjWkgdsO9cmF6bmVqxaHDrW1pIHJvemRpZWxtaSB2IHBsb2Rub3N0aSBhbGVibyB2ZWtvdmVqIMWhdHJ1a3TDunJlLgoKQ2Vsa292byBtw7TFvmVtZSBrb27FoXRhdG92YcWlLCDFvmUga2xhc3Ryb3bDoSBhbmFsw716YSBvZGhhbGlsYSBwcmlyb2R6ZW7DqSBza3VwaW55IGtyYWrDrW4gc28gc3BvbG/EjW7DvW1pIGRlbW9ncmFmaWNrw71taSB6bmFrbWkuIE5hanZpYWMgaG9tb2fDqW5ueSBqZSBrbGFzdGVyIMSNLiAxLCB6YXRpYcS+IMSNbyBrbGFzdGVyIMSNLiAyIHphaMWVxYhhIGtyYWppbnkgcyB2w6TEjcWhb3Ugdm7DunRvcm5vdSB2YXJpYWJpbGl0b3UuIFNhbW9zdGF0bsOpIHBvc3RhdmVuaWUgUnVtdW5za2EgdiBrbGFzdGVyaSDEjS4gMyBwb3VrYXp1amUgbmEgamVobyB2w71yYXpuw7ogb2RsacWhbm9zxaUgb2Qgb3N0YXRuw71jaCBldXLDs3Bza3ljaCBrcmFqw61uIHYgc2xlZG92YW7DvWNoIHByZW1lbm7DvWNoLgoKIyMgRGVza3JpcHTDrXZuZSDFoXRhdGlzdGlreSB2w71zbGVka292CgpQcmkgYW5hbMO9emUgcm96a2xhZHUgdmFyaWFuY2llIHNsZWR1amVtZSwgYWvDoSDEjWFzxaUgdmFyaWFiaWxpdHkgamVkbm90bGl2w71jaCBwcmVtZW5uw71jaCBqZSB2eXN2ZXRsZW7DoSBzYW1vdG7DvW0ga2xhc3Ryb3bDvW0gcmllxaFlbsOtbS4gS8S+w7rEjW92w71tIHVrYXpvdmF0ZcS+b20gamUgc3TEunBlYyBQcm9wX0JldHdlZW4sIGt0b3LDvSB1ZMOhdmEgcG9kaWVsIHZhcmlhYmlsaXR5IHZ5c3ZldGxlbmVqIHJvemRpZWxtaSBtZWR6aSBrbGFzdHJhbWkgKEJTUyAvIFRTUykuIMSMw61tIGplIHTDoXRvIGhvZG5vdGEgdnnFocWhaWEsIHTDvW0gbGVwxaFpZSBrbGFzdHJvdmFuaWUgemFjaHl0w6F2YSByb3pkaWVseSBtZWR6aSBrcmFqaW5hbWkgcG9kxL5hIGRhbmVqIHByZW1lbm5lai4KClogKipUYWIuIDUuKiogdnlwbMO9dmEgbmFzbGVkb3Zuw6k6CgpQb3B1bGF0aW9uLjIwMjUg4oCTIFByb3BfQmV0d2VlbiDiiYggMC4yNjgKUG9kaWVsIHZhcmlhYmlsaXR5IHZ5c3ZldGxlbmVqIGtsYXN0cmFtaSBqZSBwcmlibGnFvm5lIDI3ICUsIMSNbyB6bmFtZW7DoSwgxb5lIHBvcHVsw6FjaWEgaWJhIG1pZXJuZSBwcmlzcGlldmEgayBvZGxpxaFvdmFuaXUga2xhc3Ryb3YuIEtyYWppbnkgc2EgdGVkYSB6IGjEvmFkaXNrYSB2ZcS+a29zdGkgcG9wdWzDoWNpZSB2IHJva3UgMjAyNSBuZW9kbGnFoXVqw7ogbmF0b8S+a28sIGFieSB0dm9yaWxpIGphc25lIG9kZGVsZW7DqSBza3VwaW55LgoKRmVydC4uUmF0ZSDigJMgUHJvcF9CZXR3ZWVuIOKJiCAwLjYyMQpNaWVyYSBwbG9kbm9zdGkgdnlzdmV0xL51amUgYcW+IDYyICUgdmFyaWFiaWxpdHkgbWVkemkga2xhc3RyYW1pLCDEjW8gamUgcG9tZXJuZSB2eXNva8OhIGhvZG5vdGEuIFRvIHpuYW1lbsOhLCDFvmUgZmVydGlsaXRhIGplIHbDvXpuYW1uw71tIGZha3Rvcm9tLCBwb2TEvmEga3RvcsOpaG8gc2Ega3JhamlueSBza3V0b8SNbmUgb2RsacWhdWrDui4gS2xhc3RyeSB0ZWRhIHphY2h5dMOhdmFqw7ogcm96ZGllbHkgdiBkZW1vZ3JhZmlja2VqIGR5bmFtaWtlIHZlxL5taSBkb2JyZS4KCk1lZGlhbi5BZ2Ug4oCTIFByb3BfQmV0d2VlbiDiiYggMC44MjEKQcW+IDgyICUgdmFyaWFiaWxpdHkgdiBtZWRpw6Fub3ZvbSB2ZWt1IGplIHZ5c3ZldGxlbsO9Y2gga2xhc3RyYW1pLiBJZGUgbyBuYWp2ecWhxaFpdSBob2Rub3R1IHpvIHbFoWV0a8O9Y2ggc2xlZG92YW7DvWNoIHByZW1lbm7DvWNoLiBabmFtZW7DoSB0bywgxb5lIG1lZGnDoW5vdsO9IHZlayBwb3B1bMOhY2llIGplIGRvbWluYW50bsO9bSB1a2F6b3ZhdGXEvm9tLCBrdG9yw70gbmFqbGVwxaFpZSBvZGxpxaF1amUgdnl0dm9yZW7DqSBza3VwaW55IGtyYWrDrW4uIEtyYWppbnkgc2EgdGVkYSB2w71yYXpuZSBsw63FoWlhIHYgdG9tLCDEjWkgbWFqw7ogbWxhZMWhaXUgYWxlYm8gc3RhcsWhaXUgcG9wdWzDoWNpdS4KCk1pZ3JhbnRzLi5uZXQg4oCTIG5lYm9sbyBtb8W+bsOpIHZ5aG9kbm90acWlIChOQSkKUHJlIHTDunRvIHByZW1lbm7DuiBuZWJvbCB2w71wb8SNZXQgbW/Fvm7DvSwgcHJhdmRlcG9kb2JuZSBrdsO0bGkgY2jDvWJhasO6Y2ltIGhvZG5vdMOhbSAoTkEpLiBQcmV0byBuZXZ5c3R1cHVqZSB2IHJvemtsYWRlIHZhcmlhbmNpZSBhbmkgdiBwb3N1ZHpvdmFuw60gdmhvZG5vc3RpIGtsYXN0cm92YW5pYS4KCgoqKlRhYi4gNS4qKiBWeXN2ZXRsZW5pZSB2bsO6dHJva2xhc3Ryb3ZlaiB2YXJpYWJpbGl0eSB6IGjEvmFkaXNrYSBqZWRub3RsaXbDvWNoIHByZW1lbm7DvWNoCgpgYGB7cn0KIyMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIyA1KSBWYXJpYWJpbGl0eSBtZWFzdXJlcwojIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09Cgpzc3EgPC0gZnVuY3Rpb24oeCwgbSkgc3VtKCh4IC0gbSleMikKCnZhcl9uYW1lcyA8LSBjb2xuYW1lcyh1ZGFqZV9zY2FsZWQpCgpUU1MgPC0gc2FwcGx5KHZhcl9uYW1lcywgZnVuY3Rpb24odikgc3NxKHVkYWplX3NjYWxlZFssIHZdLCBtZWFuKHVkYWplX3NjYWxlZFssIHZdKSkpCgpXU1MgPC0gc2FwcGx5KHZhcl9uYW1lcywgZnVuY3Rpb24odikgewogIHggPC0gdWRhamVfc2NhbGVkWywgdl0KICB0YXBwbHkoeCwga2xhc3Rlcl9tZW1iZXJzaGlwLCBmdW5jdGlvbih6KSBzc3EoeiwgbWVhbih6KSkpIHw+IHN1bSgpCn0pCgpCU1MgPC0gVFNTIC0gV1NTCgpzc190YWJsZSA8LSBkYXRhLmZyYW1lKAogIFZhcmlhYmxlID0gdmFyX25hbWVzLAogIFRTUyA9IFRTUywKICBXU1MgPSBXU1MsCiAgQlNTID0gQlNTLAogIFByb3BfQmV0d2VlbiA9IEJTUyAvIFRTUwopCgpzc190YWJsZQpgYGAKCmBgYHtyfQojIFByaWTDoW1lIGt1IGRhdGFzZXR1IHByaXJhZGVuw6kga2xhc3RyeQp1ZGFqZTEwIDwtIGRhdGEuZnJhbWUoCiAgQ291bnRyeSAgICAgICAgICA9IHVkYWplMTAkQ291bnRyeS4ub3IuZGVwZW5kZW5jeS4sCiAgUG9wdWxhdGlvbi4yMDI1ICA9IHVkYWplMTAkUG9wdWxhdGlvbi4yMDI1LAogIEZlcnQuLlJhdGUgICAgICAgPSB1ZGFqZTEwJEZlcnQuLlJhdGUsCiAgTWVkaWFuLkFnZSAgICAgICA9IHVkYWplMTAkTWVkaWFuLkFnZSwKICBNaWdyYW50cy4ubmV0LiAgID0gdWRhamUxMCRNaWdyYW50cy4ubmV0LiwKICBrbGFzdGVyICAgICAgICAgID0gdWRhamVfa2xhc3RlcnMka2xhc3RlcgopCgojIFpvYnJhemVuaWUgdsO9c2xlZG7DqWhvIGRhdGFzZXR1CnVkYWplMTAKCmBgYAoKKipUYWIuIDYuKiogQ2VudHJvaWR5IC0gcHJpZW1lcm7DqSBob2Rub3R5IHNsZWRvdmFuw71jaCBwcmVtZW5uw71jaApgYGB7cn0KbGlicmFyeShkcGx5cikKCmRlc2NyaXB0aXZlcyA8LSB1ZGFqZTEwICU+JQogIGdyb3VwX2J5KGtsYXN0ZXIpICU+JQogIHN1bW1hcmlzZSgKICAgIGFjcm9zcygKICAgICAgLmNvbHMgPSB3aGVyZShpcy5udW1lcmljKSwKICAgICAgLmZucyA9IGxpc3QoCiAgICAgICAgbWVhbiA9IH5tZWFuKC54LCBuYS5ybSA9IFRSVUUpCiAgICAgICksCiAgICAgIC5uYW1lcyA9ICJ7LmNvbH1fey5mbn0iCiAgICApCiAgKQpkZXNjcmlwdGl2ZXMKCmBgYAoKTmEgesOhdmVyIHNtZSBwb3Jvdm5hbGkgcHJpZW1lcm7DqSBjaGFyYWt0ZXJpc3Rpa3kgdHJvY2gga2xhc3Ryb3YgdnlicmFuw71jaCBldXLDs3Bza3ljaCBrcmFqw61uLiAgCgoqKktsYXN0ZXIgMSoqIChOZW1lY2tvLCBUYWxpYW5za28sIMWgcGFuaWVsc2tvKSBtw6EgKipuYWp2w6TEjcWhaXUgcHJpZW1lcm7DuiBwb3B1bMOhY2l1Kiog4oCTIHByaWJsacW+bmUgKio2Myw3IG1pbGnDs25hIG9ieXZhdGXEvm92KiosICoqc3RyZWRuw7ogbWllcnUgcGxvZG5vc3RpKiogb2tvbG8gKioxLDMwIGRpZcWlYcWlYSBuYSDFvmVudSoqIGEgesOhcm92ZcWIICoqbmFqdnnFocWhw60gbWVkacOhbm92w70gdmVrKiogKCoq4omIIDQ2LDUgcm9rYSoqKS4gVGVudG8ga2xhc3RlciB0ZWRhIHJlcHJlemVudHVqZSB2ZcS+a8OpIGEgZGVtb2dyYWZpY2t5IOKAnnN0YXJuw7pjZeKAnCBrcmFqaW55IHNvIHNrw7RyIG5pxb7FoW91LCBhbGUgbmllIMO6cGxuZSBrcml0aWNreSBuw616a291IHBsb2Rub3PFpW91LiAgCgoqKktsYXN0ZXIgMioqIChTcG9qZW7DqSBrcsOhxL5vdnN0dm8sIEZyYW5jw7p6c2tvLCBQb8S+c2tvLCBSdW11bnNrbywgSG9sYW5kc2tvLCBCZWxnaWNrbykgbcOhICoqbmnFvsWhaXUgcHJpZW1lcm7DuiBwb3B1bMOhY2l1Kiog4oCTIGFzaSAqKjM3LDIgbWlsacOzbmEgb2J5dmF0ZcS+b3YqKiwgbm8gesOhcm92ZcWIICoqbmFqdnnFocWhaXUgcHJpZW1lcm7DuiBtaWVydSBwbG9kbm9zdGkqKiAoKiriiYggMSw1MSoqKSBhICoqbWxhZMWhaXUgdmVrb3bDuiDFoXRydWt0w7pydSoqIHMgbWVkacOhbm92w71tIHZla29tIHByaWJsacW+bmUgKio0MSw5IHJva2EqKi4gVGVudG8ga2xhc3RlciB6ZHJ1xb51amUgc3RyZWRuZSB2ZcS+a8OpIGtyYWppbnksIGtkZSBqZSBwbG9kbm9zxaUgcmVsYXTDrXZuZSBuYWp2ecWhxaFpYSBhIHBvcHVsw6FjaWEgamUgdiBwcmllbWVyZSBtbGFkxaFpYSBuZcW+IHYga2x1c3RyaSAxLiAgCgoqKktsYXN0ZXIgMyoqIGplIHR2b3JlbsO9IGplZGlub3Uga3Jhamlub3Ug4oCTICoqVWtyYWppbm91KiouIEplaiBwcmllbWVybsOhIChhIHrDoXJvdmXFiCBza3V0b8SNbsOhKSBwb3B1bMOhY2lhIGplIHByaWJsacW+bmUgKiozOCw5OCBtaWxpw7NuYSBvYnl2YXRlxL5vdioqLCBwcmnEjW9tIG3DoSAqKm5ham5pxb7FoWl1IG1pZXJ1IHBsb2Rub3N0aSoqICgqKuKJiCAxLDAwKiopIGEgbWVkacOhbm92w70gdmVrIG9rb2xvICoqNDEsOCByb2thKiouIFRlbnRvIGtsYXN0ZXIgcHJlZHN0YXZ1amUga3JhamludSBzIHZlxL5taSBuw616a291IHBsb2Rub3PFpW91LCBwcmkgdmVrb3ZlaiDFoXRydWt0w7pyZSBwb2RvYm5laiBrbGFzdHJ1IDIuICAKClogcG9yb3ZuYW5pYSBrbGFzdHJvdiB2aWRubywgxb5lIG5hanZ5xaHFocOtIHByaWVtZXJuw70gcG/EjWV0IG9ieXZhdGXEvm92IHNhIHNww6FqYSBzbyBzdGFyxaFvdSBwb3B1bMOhY2lvdSAoa2xhc3RlciAxKSwgemF0aWHEviDEjW8gbmFqdnnFocWhaWEgcGxvZG5vc8WlIHNhIHZ5c2t5dHVqZSB2IGtyYWppbsOhY2ggc28gc2vDtHIgbWxhZMWhb3UgcG9wdWzDoWNpb3UgKGtsYXN0ZXIgMikuIFVrcmFqaW5hIHR2b3LDrSBzYW1vc3RhdG7DvSBrbGFzdGVyIGt2w7RsaSBrb21iaW7DoWNpaSBwcmllbWVybmVqIHZlxL5rb3N0aSBwb3B1bMOhY2llIGEgZXh0csOpbW5lIG7DrXprZWogbWllcnkgcGxvZG5vc3RpLgogCgojIyBaw6F2ZXIKUHJlZGxvxb5lbsOhIGFuYWzDvXphIHNhIHphbWVyaWF2YSBuYSBkZW1vZ3JhZmlja8OpIGNoYXJha3RlcmlzdGlreSB2eWJyYW7DvWNoIGV1csOzcHNreWNoIGtyYWrDrW4gbmEgesOha2xhZGUgaWNoIHByZWRwb2tsYWRhbmVqIHBvcHVsw6FjaWUgdiByb2t1IDIwMjUsIG1pZXJ5IHBsb2Rub3N0aSBhIG1lZGnDoW51IHZla3Ugb2J5dmF0ZcS+c3R2YS4gTmEgesOha2xhZGUgdMO9Y2h0byBwcmVtZW5uw71jaCBib2xpIGtyYWppbnkgcm96ZGVsZW7DqSBkbyB0cm9jaCBrbGFzdHJvdiwgcHJpxI1vbSBqZWRub3RsaXbDqSBrbGFzdHJ5IG9kcsOhxb5hasO6IHNwb2xvxI1uw6kgZGVtb2dyYWZpY2vDqSDEjXJ0eSB0w71jaHRvIMWhdMOhdG92LgoKVsO9c2xlZG7DqSBrbGFzdHJ5IHByZWRzdGF2dWrDuiB0cmkgb2RsacWhbsOpIHNrdXBpbnkga3JhasOtbi4gUHJ2w70ga2xhc3RlciB0dm9yaWEgxaF0w6F0eSBzIG5hanZ5xaHFoW91IHByZWRwb2tsYWRhbm91IHBvcHVsw6FjaW91IGEgesOhcm92ZcWIIHZ5xaHFocOtbSBtZWRpw6Fub3bDvW0gdmVrb20gb2J5dmF0ZcS+c3R2YSwgxI1vIG5hem5hxI11amUgc3Rhcm7DumN1IHBvcHVsw6FjaXUgdmXEvmvDvWNoIGtyYWrDrW4uIERydWjDvSBrbGFzdGVyIHpkcnXFvnVqZSBrcmFqaW55IHMgcmVsYXTDrXZuZSB2ecWhxaFvdSBtaWVyb3UgcGxvZG5vc3RpIGEgc3RyZWRuw71taSBob2Rub3RhbWkgcG9wdWzDoWNpZSwgxI1vIHBvdWthenVqZSBuYSBkeW5hbWlja2VqxaHDrSBwb3B1bGHEjW7DvSB2w712b2ouIFRyZXTDrSBrbGFzdGVyIG9ic2FodWplIGtyYWppbnkgcyBuYWpuacW+xaFvdSBtaWVyb3UgcGxvZG5vc3RpIGEgesOhcm92ZcWIIHN0cmVkbm91IGHFviBuacW+xaFvdSB2ZcS+a29zxaVvdSBwb3B1bMOhY2llLgoKVGFrw6F0byBrbGFzaWZpa8OhY2lhIHVtb8W+xYh1amUgcG9jaG9wacWlIHZ6xaVhaHkgbWVkemkgZGVtb2dyYWZpY2vDvW1pIHVrYXpvdmF0ZcS+bWkgYSBwb3VrYXp1amUgbmEgcG9kb2Jub3N0aSB2IHBvcHVsYcSNbm9tIHbDvXZvamkgbmFwcmllxI0gRXVyw7Nwb3UuIEFuYWzDvXphIG3DtMW+ZSBzbMO6xb5pxaUgYWtvIHBvZGtsYWQgcHJlIHR2b3JidSBwb3B1bGHEjW7DvWNoIMSNaSBzb2Npw6FsbnljaCBwb2xpdMOtaywgcHLDrXBhZG5lIHByZSDEj2FsxaFpZSBwb3Jvdm7DoXZhY2llIMWhdMO6ZGllIG1lZHppIGV1csOzcHNreW1pIGtyYWppbmFtaS4=