Analiza opisowa
Jednym ze sposobów zrozumienia, jak działa rząd miasta, jest
spojrzenie na to, kogo zatrudnia i jak jego pracownicy są wynagradzani.
Dane te zawierają nazwiska, nazwę stanowiska i wynagrodzenie pracowników
miasta San Francisco w ujęciu rocznym od 2011 do 2014 roku.
Oto kilka pomysłów na eksplorację danych:
Jak zmieniały się wynagrodzenia w czasie między różnymi grupami
ludzi?
Jak płaca podstawowa, wynagrodzenie za nadgodziny i świadczenia
są rozdzielane pomiędzy różne grupy?
Czy w tym zestawie danych istnieją dowody na dyskryminację
płacową ze względu na płeć?
Jak przydzielany jest budżet w zależności od grupy i zakresu
obowiązków?
# wymiary ramki:
dim(salaries)
## [1] 148654 13
# nazwy kolumn:
names(salaries)
## [1] "Id" "EmployeeName" "JobTitle" "BasePay"
## [5] "OvertimePay" "OtherPay" "Benefits" "TotalPay"
## [9] "TotalPayBenefits" "Year" "Notes" "Agency"
## [13] "Status"
Histogramy
hist(salaries$TotalPay,main="Total Pay", xlab="Pay (in dollars)")
abline(v = mean(salaries$TotalPay),lty="dashed")
abline(v = median(salaries$TotalPay))
legend("topright", legend=c("Mediana","Średnia"),lty=c("solid","dashed"))

par(mfrow=c(2,2))
hist(salaries$TotalPay,main="Total Pay, default breaks", xlab="Pay (in dollars)")
hist(salaries$TotalPay,main="Total Pay, breaks=100", xlab="Pay (in dollars)", breaks=100)
hist(salaries$TotalPay,main="Total Pay, breaks=1000", xlab="Pay (in dollars)",breaks=1000)

hist(salaries$TotalPay,main="Total Pay, Zoomed-in", xlab="Pay (in dollars)", xlim=c(0,1e5), breaks=1000)

salaries2 <- subset(salaries, JobTitle=="Firefighter" & Status=="FT")
dim(salaries2)
## [1] 738 13
par(mfrow=c(2,2))
hist(salaries2$TotalPay,main="Firefighters, default breaks", xlab="Pay (in dollars)")
hist(salaries2$TotalPay,main="Firefighters, breaks=30", xlab="Pay (in dollars)", breaks=30)
hist(salaries2$TotalPay,main="Firefighters, breaks=100", xlab="Pay (in dollars)", breaks=100)
hist(salaries2$TotalPay,main="Firefighters, breaks=1000", xlab="Pay (in dollars)",breaks=1000)

Wykresy
pudełkowe
par(mfrow=c(1,1))
boxplot(salaries$TotalPay,main="Total Pay, breaks=1000", ylab="Pay (in dollars)")

Estymacja funkcji
gęstości
Pierwszy raport dotyczy nieparametrycznej estymacji gęstości.
Klasycznym nieparametrycznym estymatorem gęstości jest histogram, który
dostarcza nieciągłe i stałe oszacowania. W tym raporcie skupiono się na
niektórych alternatywach, które zapewniają ciągłe lub nawet gładkie
oszacowania zamiast.
Metody kernelowe stanowią ważną klasę gładkich estymatorów
gęstości i zaimplementowane są przez funkcję R density().
Estymatory te są w zasadzie tylko lokalnie ważonymi średnimi, a ich
obliczenie jest stosunkowo proste w teorii. W praktyce, różne wybory
sposobu implementacji obliczeń mogą jednak mieć duży wpływ na
rzeczywisty czas obliczeń, a implementację kernelowych estymatorów
gęstości zilustruje trzy punkty:
- jeśli to możliwe, wybierz wektoryzowane implementacje w R,
- jeśli niewielka strata w dokładności jest do zaakceptowania,
przybliżone rozwiązanie może być o rzędy wielkości szybsze niż
implementacja literalna,
- czas potrzebny do numerycznej oceny różnych funkcje
elementarne może bardzo zależeć od funkcji i sposobu implementacji
obliczeń.
Metody kernelowe opierają się na jednym lub więcej parametrach
regularności, które muszą być dobrane tak, aby osiągnąć właściwą
równowagę w dostosowaniu do danych bez zbytniego dostosowywania się do
losowej zmienności w danych.
Wybór odpowiedniej ilości regularności jest równie ważny jak wybór
metody do użycia w pierwszej kolejności. W rzeczywistości może być
ważniejszy. Tak naprawdę nie mamy kompletnej implementacji
nieparametrycznego estymatora dopóki nie zaimplementujemy
automatycznego, opartego na danych sposobu wyboru ilości regulacji.
Implementacja tylko obliczeń dla oceny estymatora jądra, powiedzmy, i
pozostawiając to całkowicie użytkownikowi wyboru szerokości pasma jest
pracą w połowie wykonaną. Metody i implementacje do wyboru szerokości
pasma są więc w tym raporcie omówione dość szczegółowo.
W ostatniej części przeprowadzona jest analiza prawdopodobieństwa.
Robi się to w celu dalszego wyjaśnienia, dlaczego potrzebne są
estymatory z regularyzacją w celu uniknięcia nadmiernego dopasowania do
danych, oraz dlaczego nie istnieje w ogóle nieparametryczny maksymalnego
prawdopodobieństwa estymatora gęstości. Regularyzację
prawdopodobieństwamożna osiągnąć poprzez ograniczenie szacunków gęstości
do rodziny coraz bardziej elastycznych gęstości parametrycznych, które
są dopasowane do danych. Jest to znane jako metoda sit. Inne
podejście opiera się na rozszerzeniach bazowych, ale w obu przypadkach
automatyczny wybór wielkości regularności jest tak samo ważny jak w
przypadku metod jądrowych.
Aby utworzyć wykres gęstości jądra, musisz oszacować gęstość jądra. W
tym celu można użyć funkcji density, a następnie przekazać obiekt
density do funkcji plot.
# dane
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data)
# Kernel density plot
plot(d, lwd = 2, main = "Default kernel density plot")

Argument jądra funkcji gęstości domyślnie używa jądra gaussowskiego
(kernel = “gaussian”), ale dostępnych jest więcej typów jądra, takich
jak “prostokątne”, “trójkątne”, “epanechnikov”, “biweight”, “cosine” i
“optcosine”. Wybór będzie zależał od twoich danych, ale w większości
scenariuszy wartość domyślna jest najbardziej zalecana.
# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
kernel = "rectangular")
# Kernel density plot
plot(d, lwd = 2, main = "Rectangular kernel")

# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
kernel = "triangular")
# Kernel density plot
plot(d, lwd = 2, main = "Triangular kernel")

# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
kernel = "epanechnikov")
# Kernel density plot
plot(d, lwd = 2, main = "Epanechnikov kernel")

# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
kernel = "biweight")
# Kernel density plot
plot(d, lwd = 2, main = "Biweight kernel")

# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
kernel = "cosine")
# Kernel density plot
plot(d, lwd = 2, main = "Cosine kernel")

Selekcja pasma
Argument bw funkcji gęstości pozwala na zmianę używanego pasma
wygładzania. Możesz przekazać wartość lub ciąg znaków podający regułę
wyboru lub funkcję. Domyślną wartością jest “nrd0” (lub bw.nrd0(.)),
która implementuje podejście oparte na zasadzie reguły kciuka :-) Inne
dostępne opcje to:
Reguła Scotta
(1992)
# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
bw = "nrd")
# Kernel density plot
plot(d, lwd = 2, main = "nrd bandwidth")

Nieobciążona
cross-walidacja
# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
bw = "ucv")
# Kernel density plot
plot(d, lwd = 2, main = "ucv bandwidth")

Obciążona
cross-walidacja
# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
bw = "bcv")
# Kernel density plot
plot(d, lwd = 2, main = "bcv bandwidth")

Metoda Sheather
& Jones (1991)
# Data
set.seed(14012021)
data <- rnorm(200, mean = 4)
# Kernel density estimation
d <- density(data,
bw = "SJ")
# Kernel density plot
plot(d, lwd = 2, main = "SJ bandwidth")

- Ostrzeżenie!
-
Szerokość pasma musi być bardzo starannie dobrana! Mała szerokość
pasma spowoduje powstanie nadmiernie dopasowanej krzywej, natomiast zbyt
duża szerokość pasma spowoduje powstanie krzywej nadmiernie
wygładzonej.
Ćwiczenie 1.
Uruchom demo estymatora funkcji gęstości kernel. Zmieniaj zarówno
dane wejściowe, jak i opcje estymatora - szerokość pasma oraz rodzaj
funkcji jądrowej. Czy widzisz istotne różnice w oszacowaniu?
#install.packages("remotes") #tylko raz! potem #
#install_github("hericks/KDE") #tylko raz! potem #
#install.packages("htmltools")
#remotes::install_github("hericks/KDE")
#install.packages("kde")
library(ggplot2)
library(KDE)
shiny_kde()
Shiny applications not supported in static R Markdown documents
Rzeczywiście można zauważyć wyraźne różnice. Zwiększenie wartości
odchylenia standardowego powoduje, że rozkład staje się bardziej płaski
i rozciągnięty, co oznacza większe rozproszenie danych wokół średniej. Z
kolei zmniejszenie odchylenia standardowego sprawia, że rozkład staje
się węższy i bardziej skupiony. Zmiana wartości średniej powoduje
przesunięcie środka rozkładu na osi poziomej (oś x). Innymi słowy, cały
rozkład przesuwa się w prawo lub w lewo w zależności od tego, czy
średnia została zwiększona, czy zmniejszona, ale sam kształt rozkładu
pozostaje taki sam. Natomiast modyfikacja szerokości pasma (bandwidth)
wpływa na stopień, w jakim krzywa dopasowuje się do danych. Im mniejsza
wartość pasma, tym bardziej krzywa staje się szczegółowa i lepiej
odwzorowuje lokalne zmiany w danych. Jednak większa szerokość pasma
powoduje wygładzenie krzywej, co prowadzi do bardziej ogólnego
dopasowania i pominięcia drobnych szczegółów.
Jeśli chodzi o różnice pomiędzy argumentami jądra funkcji gęstości,
to możemy zauwazyć, że rodzaj ‘rectangular’ jest najbardziej dopasowany
do danych, można by stwierdzić, że aż zbyt dobrze dopasowany, ponieważ
praktycznie wogóle nie wygładza rozkładu. Rodzaj ‘Logistic’, jest
najbardziej “spłaszczony” i wygładzony ze wszystkich rozkładów.
‘Triweight’,‘Triangular’,‘Tricube’, dobrze dopasowują się do danych, ale
niezbyt wygładzają rozkład. Posobnie ‘Epanechnikov’,‘Biweight’ i
‘Cosine’. ‘Silverman’ i ‘Sigmoid’ mają cechy zblizone do ‘Logistic’,
lecz są one mniej spłaszczone. Choć jeszcze mnie spłaszczony jest
klasyczny rozkład ‘Gaussian’.
Ćwiczenie 2.
Wykorzystując dowolną funkcję R do estymacji funkcji gęstości oszacuj
jej przebieg dla wynagrodzeń (zbiór danych salaries) strażaków w San
Francisco. Wykorzystaj metody graficzne dostępne w pakiecie ggplot2.
Mile widziane przekroje oraz odpowiedzi na pytania badawcze zadane na
wstępie.
salariesFFSanF <- subset(salaries, JobTitle=="Firefighter" & Agency=="San Francisco")
dim(salariesFFSanF)
## [1] 2359 13
Zaczniemy od pytań
badawczych.
Jak zmieniały się
wynagrodzenia w czasie między różnymi grupami ludzi?
Histogram wynagrodzeń
dla strażaków z San Francisco.
sr_mediana_linie <- data.frame(nazwa = c("Średnia",
"Mediana"),
wartość = c(mean(salariesFFSanF$TotalPay),
median(salariesFFSanF$TotalPay)))
ggplot(salariesFFSanF,aes(x = TotalPay)) +
geom_histogram(binwidth=10000, color="purple",fill="yellow") +
labs(x = "Pay (in dollars)", y = "Frequency", title = "Histogram wynagrodzeń strażaków w San Francisco") +
geom_vline(data=sr_mediana_linie,aes(xintercept = wartość,
linetype = nazwa,
col = nazwa),linewidth=1,color="blue")+
theme_minimal()
Możemy zauważyć, że badany rozkład wynagrodzeń jest prawoskośny i więcej
strażaków zarabia ponad średnie wynagrodzenie dla ich stanowiska. Mamy
również drugą, małą, lokalną modę w okolicach 0:50 000 USD, która zaniża
nam wartość mediany.
Poniżej histogram
zmian wynagrodzeń strażaków z SF na przestrzeni lat
sr_mediana_linie_2012 <- data.frame(nazwa = c("Średnia z 2012",
"Mediana z 2012"), wartość = c(mean(salariesFFSanF$TotalPay[salariesFFSanF$Year==2012]),
median(salariesFFSanF$TotalPay[salariesFFSanF$Year==2012])))
ggplot(salariesFFSanF,aes(x = TotalPay)) +
geom_histogram(binwidth=25000, color="purple",fill="yellow") +
labs(x = "Pay (in dollars)", y = "Frequency", title = "Histogram wynagrodzeń strażaków w San Francisco") +
geom_vline(data=sr_mediana_linie,aes(xintercept = wartość,
linetype = nazwa,
col = nazwa),linewidth=1,color="blue")+
theme_minimal()+
facet_grid(. ~ Year)
Możemy zauważyć, że w porównaniu do 2012 roku w 2013 roku liczba
strażaków, którzy zarabiali kwotę odpowiadającą średniej i medianie z
2012 roku, wzrosła. Jednak w 2014 roku wartości te powróciły do poziomów
zbliżonych do tych z 2012 roku. Świadczy o tym zmiana średniego
wynagrodzenia w analizowanych latach – po wzroście w 2013 roku osiągnęło
ono najwyższy poziom, by następnie w 2014 roku spaść poniżej wartości
odnotowanej w 2012 roku.
sr_mediany_lata <- data.frame(Rok = c(2012,2013,2014),
średnie = c(mean(salariesFFSanF$TotalPay[salariesFFSanF$Year==2012]),
mean(salariesFFSanF$TotalPay[salariesFFSanF$Year==2013]),
mean(salariesFFSanF$TotalPay[salariesFFSanF$Year==2014])),
mediany = c(median(salariesFFSanF$TotalPay[salariesFFSanF$Year==2012]),
median(salariesFFSanF$TotalPay[salariesFFSanF$Year==2013]),
median(salariesFFSanF$TotalPay[salariesFFSanF$Year==2014])))
Jak płaca podstawowa,
wynagrodzenie za nadgodziny i świadczenia są rozdzielane pomiędzy różne
grupy?
salariesFFSanF$Benefits<-as.numeric(salariesFFSanF$Benefits)
salariesFFSanF$OvertimePay<-as.numeric(salariesFFSanF$OvertimePay)
salariesFFSanF$BasePay<-as.numeric(salariesFFSanF$BasePay)
Płaca podstawowa
sr_mediana_linie_basepay <- data.frame(nazwa = c("Średnia dla FT",
"Mediana dla FT"),
wartość=c(mean(salariesFFSanF$BasePay[salariesFFSanF$Status=='FT']),
median(salariesFFSanF$BasePay[salariesFFSanF$Status=='FT'])))
ggplot(salariesFFSanF,aes(x = BasePay)) +
geom_histogram(binwidth=25000, color="green",fill="blue") +
labs(x = "Base Pay", y = "Frequency", title = "Histogram płacy podstawowej dla strażaków w San Francisco") +
geom_vline(data=sr_mediana_linie_basepay,aes(xintercept = wartość,
linetype = nazwa,
col = nazwa),linewidth=1,color="black")+
theme_minimal()+
facet_grid(. ~ Status)
## Warning: Removed 11 rows containing non-finite outside the scale range
## (`stat_bin()`).

Wynagrodzenie za
nadgodziny
sr_mediana_linie_overtime <- data.frame(nazwa = c("Średnia",
"Mediana"), wartość = c(mean(salariesFFSanF$OvertimePay),
median(salariesFFSanF$OvertimePay)))
ggplot(salariesFFSanF,aes(x = OvertimePay)) +
geom_histogram(binwidth=25000, color="green",fill="blue") +
labs(x = "Overtime Pay", y = "Frequency", title = "Histogram płacy za nadgodziny dla strażaków w San Francisco") +
geom_vline(data=sr_mediana_linie_overtime,aes(xintercept = wartość,
linetype = nazwa,
col = nazwa),linewidth=1,color="black")+
theme_minimal()+
facet_grid(. ~ Status)

Benefity
sr_mediana_linie_benefits <- data.frame(nazwa = c("Średnia",
"Mediana"), wartość = c(mean(salariesFFSanF$Benefits),
median(salariesFFSanF$Benefits)))
ggplot(salariesFFSanF,aes(x = Benefits)) +
geom_histogram(binwidth=10000, color="red",fill="blue") +
labs(x = "Benefits", y = "Frequency", title = "Histogram świadczeń/Benefitów dla strażaków w San Francisco") +
geom_vline(data=sr_mediana_linie_benefits,aes(xintercept = wartość,
linetype = nazwa,
col = nazwa),linewidth=1,color="black")+
theme_minimal()+
facet_grid(. ~ Status)
Możemy zauważyć, że budżet przeznaczony na wynagrodzenie podstawowe,
płatności za nadgodziny oraz świadczenia różni się w zależności od tego,
czy strażacy są zatrudnieni w pełnym wymiarze godzin (FT), czy na pół
etatu (ST). Zgodnie z przewidywaniami, wszystkie te wydatki są niższe w
przypadku strażaków pracujących w niepełnym wymiarze godzin.
Czy w tym zestawie
danych istnieją dowody na dyskryminację płacową ze względu na płeć?
Nie jesteśmy w stanie obliczyć tego dla tego zbioru danych, ponieważ
nie mamy w nim zmiennej dotyczącej płci.
Oszacowanie gęstości
rozkładu wynagrodzeń strażaków w San Francisco:
# Kernel density estimation
d <- density(salariesFFSanF$TotalPay,
kernel = "gaussian",
bw = 10000)
# Kernel density plot
plot(d, lwd = 2, main = "Gaussian kernel")
Dzięki zwiększeniu szerokości pasma do 10000,udało się wygładzić
rozkład, który ułatwia nam wyciągnięcie wniosków. Mamy tutaj przykład
rozkładu bimodalnego, który pomaga zrozumieć wcześniej zauważone
zjawisko, że mediana przewyższa średnią. Wynika to z obecności znacznej
grupy strażaków (stanowiącej drugie lokalne maksimum), którzy zarabiają
niewielkie kwoty w przedziale <0; 50 000 USD>. Ich zarobki
znacząco obniżają średnią płac, ale ich liczba nie jest na tyle duża,
aby w istotny sposób wpłynąć na obniżenie mediany.
LS0tDQp0aXRsZTogIktlcm5lbCINCmF1dGhvcjogIkFsZWtzYW5kcmEgQnVrb3dza2EiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdGhlbWU6IGNlcnVsZWFuDQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIGZvbnRzaXplOiA4cHQNCiAgICB0b2M6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBmYWxzZQ0KZWRpdG9yX29wdGlvbnM6IA0KICBtYXJrZG93bjogDQogICAgd3JhcDogNzINCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCm9wdGlvbnMoc2NpcGVuPTk5OSwgZGlnaXRzPTMpDQpzYWxhcmllcyA8LSByZWFkLmNzdigiaHR0cHM6Ly9naXRodWIuY29tL2tmbGlzaWtvd3NraS9kcy9yYXcvbWFzdGVyL1NhbGFyaWVzLmNzdiIpDQpgYGANCg0KIyBBbmFsaXphIG9waXNvd2ENCg0KSmVkbnltIHplIHNwb3NvYsOzdyB6cm96dW1pZW5pYSwgamFrIGR6aWHFgmEgcnrEhWQgbWlhc3RhLCBqZXN0IHNwb2pyemVuaWUgbmEgdG8sIGtvZ28gemF0cnVkbmlhIGkgamFrIGplZ28gcHJhY293bmljeSBzxIUgd3luYWdyYWR6YW5pLiBEYW5lIHRlIHphd2llcmFqxIUgbmF6d2lza2EsIG5henfEmSBzdGFub3dpc2thIGkgd3luYWdyb2R6ZW5pZSBwcmFjb3duaWvDs3cgbWlhc3RhIFNhbiBGcmFuY2lzY28gdyB1asSZY2l1IHJvY3pueW0gb2QgMjAxMSBkbyAyMDE0IHJva3UuDQoNCk90byBraWxrYSBwb215c8WCw7N3IG5hIGVrc3Bsb3JhY2rEmSBkYW55Y2g6DQoNCi0gSmFrIHptaWVuaWHFgnkgc2nEmSB3eW5hZ3JvZHplbmlhIHcgY3phc2llIG1pxJlkenkgcsOzxbxueW1pIGdydXBhbWkgbHVkemk/DQoNCi0gSmFrIHDFgmFjYSBwb2RzdGF3b3dhLCB3eW5hZ3JvZHplbmllIHphIG5hZGdvZHppbnkgaSDFm3dpYWRjemVuaWEgc8SFIHJvemR6aWVsYW5lIHBvbWnEmWR6eSByw7PFvG5lIGdydXB5Pw0KDQotIEN6eSB3IHR5bSB6ZXN0YXdpZSBkYW55Y2ggaXN0bmllasSFIGRvd29keSBuYSBkeXNrcnltaW5hY2rEmSBwxYJhY293xIUgemUgd3pnbMSZZHUgbmEgcMWCZcSHPw0KDQotIEphayBwcnp5ZHppZWxhbnkgamVzdCBidWTFvGV0IHcgemFsZcW8bm/Fm2NpIG9kIGdydXB5IGkgemFrcmVzdSBvYm93acSFemvDs3c/DQoNCmBgYHtyIH0NCiMgd3ltaWFyeSByYW1raToNCmRpbShzYWxhcmllcykNCiMgbmF6d3kga29sdW1uOg0KbmFtZXMoc2FsYXJpZXMpDQpgYGANCg0KIyMgSGlzdG9ncmFteQ0KDQpgYGB7ciB9DQpoaXN0KHNhbGFyaWVzJFRvdGFsUGF5LG1haW49IlRvdGFsIFBheSIsIHhsYWI9IlBheSAoaW4gZG9sbGFycykiKQ0KYWJsaW5lKHYgPSBtZWFuKHNhbGFyaWVzJFRvdGFsUGF5KSxsdHk9ImRhc2hlZCIpDQphYmxpbmUodiA9IG1lZGlhbihzYWxhcmllcyRUb3RhbFBheSkpDQpsZWdlbmQoInRvcHJpZ2h0IiwgbGVnZW5kPWMoIk1lZGlhbmEiLCLFmnJlZG5pYSIpLGx0eT1jKCJzb2xpZCIsImRhc2hlZCIpKQ0KYGBgDQoNCmBgYHtyIH0NCnBhcihtZnJvdz1jKDIsMikpDQpoaXN0KHNhbGFyaWVzJFRvdGFsUGF5LG1haW49IlRvdGFsIFBheSwgZGVmYXVsdCBicmVha3MiLCB4bGFiPSJQYXkgKGluIGRvbGxhcnMpIikNCmhpc3Qoc2FsYXJpZXMkVG90YWxQYXksbWFpbj0iVG90YWwgUGF5LCBicmVha3M9MTAwIiwgeGxhYj0iUGF5IChpbiBkb2xsYXJzKSIsIGJyZWFrcz0xMDApDQpoaXN0KHNhbGFyaWVzJFRvdGFsUGF5LG1haW49IlRvdGFsIFBheSwgYnJlYWtzPTEwMDAiLCB4bGFiPSJQYXkgKGluIGRvbGxhcnMpIixicmVha3M9MTAwMCkNCmBgYA0KDQpgYGB7ciB9DQpoaXN0KHNhbGFyaWVzJFRvdGFsUGF5LG1haW49IlRvdGFsIFBheSwgWm9vbWVkLWluIiwgeGxhYj0iUGF5IChpbiBkb2xsYXJzKSIsIHhsaW09YygwLDFlNSksIGJyZWFrcz0xMDAwKQ0KYGBgDQoNCmBgYHtyIH0NCnNhbGFyaWVzMiA8LSBzdWJzZXQoc2FsYXJpZXMsIEpvYlRpdGxlPT0iRmlyZWZpZ2h0ZXIiICYgU3RhdHVzPT0iRlQiKQ0KZGltKHNhbGFyaWVzMikNCmBgYA0KDQpgYGB7ciB9DQpwYXIobWZyb3c9YygyLDIpKQ0KaGlzdChzYWxhcmllczIkVG90YWxQYXksbWFpbj0iRmlyZWZpZ2h0ZXJzLCBkZWZhdWx0IGJyZWFrcyIsIHhsYWI9IlBheSAoaW4gZG9sbGFycykiKQ0KaGlzdChzYWxhcmllczIkVG90YWxQYXksbWFpbj0iRmlyZWZpZ2h0ZXJzLCBicmVha3M9MzAiLCB4bGFiPSJQYXkgKGluIGRvbGxhcnMpIiwgYnJlYWtzPTMwKQ0KaGlzdChzYWxhcmllczIkVG90YWxQYXksbWFpbj0iRmlyZWZpZ2h0ZXJzLCBicmVha3M9MTAwIiwgeGxhYj0iUGF5IChpbiBkb2xsYXJzKSIsIGJyZWFrcz0xMDApDQpoaXN0KHNhbGFyaWVzMiRUb3RhbFBheSxtYWluPSJGaXJlZmlnaHRlcnMsIGJyZWFrcz0xMDAwIiwgeGxhYj0iUGF5IChpbiBkb2xsYXJzKSIsYnJlYWtzPTEwMDApDQpgYGANCg0KIyMgV3lrcmVzeSBwdWRlxYJrb3dlDQoNCmBgYHtyIH0NCnBhcihtZnJvdz1jKDEsMSkpDQpib3hwbG90KHNhbGFyaWVzJFRvdGFsUGF5LG1haW49IlRvdGFsIFBheSwgYnJlYWtzPTEwMDAiLCB5bGFiPSJQYXkgKGluIGRvbGxhcnMpIikNCmBgYA0KDQojIEVzdHltYWNqYSBmdW5rY2ppIGfEmXN0b8WbY2kNCg0KUGllcndzenkgcmFwb3J0IGRvdHljenkgbmllcGFyYW1ldHJ5Y3puZWogZXN0eW1hY2ppIGfEmXN0b8WbY2kuIEtsYXN5Y3pueW0gbmllcGFyYW1ldHJ5Y3pueW0gZXN0eW1hdG9yZW0gZ8SZc3RvxZtjaSBqZXN0IGhpc3RvZ3JhbSwga3TDs3J5IGRvc3RhcmN6YSBuaWVjacSFZ8WCZSBpIHN0YcWCZSBvc3phY293YW5pYS4gVyB0eW0gcmFwb3JjaWUgc2t1cGlvbm8gc2nEmSBuYSBuaWVrdMOzcnljaA0KYWx0ZXJuYXR5d2FjaCwga3TDs3JlIHphcGV3bmlhasSFIGNpxIVnxYJlIGx1YiBuYXdldCBnxYJhZGtpZSBvc3phY293YW5pYSB6YW1pYXN0Lg0KDQoqTWV0b2R5IGtlcm5lbG93ZSogc3Rhbm93acSFIHdhxbxuxIUga2xhc8SZIGfFgmFka2ljaCBlc3R5bWF0b3LDs3cgZ8SZc3RvxZtjaSBpIHphaW1wbGVtZW50b3dhbmUgc8SFIHByemV6IGZ1bmtjasSZIFIgYGRlbnNpdHkoKWAuIEVzdHltYXRvcnkgdGUgc8SFIHcgemFzYWR6aWUgdHlsa28gbG9rYWxuaWUgd2HFvG9ueW1pIMWbcmVkbmltaSwgYSBpY2ggb2JsaWN6ZW5pZSBqZXN0IHN0b3N1bmtvd28gcHJvc3RlIHcgdGVvcmlpLiBXIHByYWt0eWNlLCByw7PFvG5lIHd5Ym9yeSBzcG9zb2J1IGltcGxlbWVudGFjamkgb2JsaWN6ZcWEIG1vZ8SFIGplZG5hayBtaWXEhyBkdcW8eSB3cMWCeXcgbmEgcnplY3p5d2lzdHkgY3phcw0Kb2JsaWN6ZcWELCBhIGltcGxlbWVudGFjasSZIGtlcm5lbG93eWNoIGVzdHltYXRvcsOzdyBnxJlzdG/Fm2NpIHppbHVzdHJ1amUgdHJ6eSBwdW5rdHk6DQoNCi0gICBqZcWbbGkgdG8gbW/FvGxpd2UsIHd5Ymllcnogd2VrdG9yeXpvd2FuZSBpbXBsZW1lbnRhY2plIHcgUiwNCi0gICBqZcWbbGkgbmlld2llbGthIHN0cmF0YSB3IGRva8WCYWRub8WbY2kgamVzdCBkbyB6YWFrY2VwdG93YW5pYSwgcHJ6eWJsacW8b25lIHJvendpxIV6YW5pZSBtb8W8ZSBiecSHIG8gcnrEmWR5IHdpZWxrb8WbY2kgc3p5YnN6ZSBuacW8IGltcGxlbWVudGFjamEgbGl0ZXJhbG5hLA0KLSAgIGN6YXMgcG90cnplYm55IGRvIG51bWVyeWN6bmVqIG9jZW55IHLDs8W8bnljaCBbZnVua2NqZSBlbGVtZW50YXJuZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRWxlbWVudGFyeV9mdW5jdGlvbikgbW/FvGUgYmFyZHpvIHphbGXFvGXEhyBvZCBmdW5rY2ppIGkgc3Bvc29idSBpbXBsZW1lbnRhY2ppIG9ibGljemXFhC4NCg0KTWV0b2R5IGtlcm5lbG93ZSBvcGllcmFqxIUgc2nEmSBuYSBqZWRueW0gbHViIHdpxJljZWogKnBhcmFtZXRyYWNoIHJlZ3VsYXJub8WbY2kqLCBrdMOzcmUgbXVzesSFIGJ5xIcgZG9icmFuZSB0YWssIGFieSBvc2nEhWduxIXEhyB3xYJhxZtjaXfEhSByw7N3bm93YWfEmSB3IGRvc3Rvc293YW5pdSBkbyBkYW55Y2ggYmV6IHpieXRuaWVnbyBkb3N0b3Nvd3l3YW5pYSBzacSZIGRvIGxvc293ZWogem1pZW5ub8WbY2kgdyBkYW55Y2guDQoNCld5YsOzciBvZHBvd2llZG5pZWogaWxvxZtjaSByZWd1bGFybm/Fm2NpIGplc3QgcsOzd25pZSB3YcW8bnkgamFrIHd5YsOzciBtZXRvZHkgZG8gdcW8eWNpYSB3IHBpZXJ3c3plaiBrb2xlam5vxZtjaS4gVyAgcnplY3p5d2lzdG/Fm2NpIG1vxbxlIGJ5xIcgd2HFvG5pZWpzenkuIFRhayBuYXByYXdkxJkgbmllIG1hbXkga29tcGxldG5laiBpbXBsZW1lbnRhY2ppIG5pZXBhcmFtZXRyeWN6bmVnbyBlc3R5bWF0b3JhIGRvcMOza2kgbmllIHphaW1wbGVtZW50dWplbXkgYXV0b21hdHljem5lZ28sIG9wYXJ0ZWdvIG5hIGRhbnljaCBzcG9zb2J1IHd5Ym9ydSBpbG/Fm2NpIHJlZ3VsYWNqaS4NCg0KSW1wbGVtZW50YWNqYSB0eWxrbyBvYmxpY3plxYQgZGxhIG9jZW55IGVzdHltYXRvcmEgasSFZHJhLCBwb3dpZWR6bXksIGkgcG96b3N0YXdpYWrEhWMgdG8gY2HFgmtvd2ljaWUgdcW8eXRrb3duaWtvd2kgd3lib3J1IHN6ZXJva2/Fm2NpIHBhc21hIGplc3QgcHJhY8SFIHcgcG/Fgm93aWUgd3lrb25hbsSFLiBNZXRvZHkgaSBpbXBsZW1lbnRhY2plIGRvIHd5Ym9ydSBzemVyb2tvxZtjaSBwYXNtYSBzxIUgd2nEmWMgdyB0eW0gcmFwb3JjaWUgb23Ds3dpb25lIGRvxZvEhyBzemN6ZWfDs8WCb3dvLg0KDQpXIG9zdGF0bmllaiBjesSZxZtjaSBwcnplcHJvd2Fkem9uYSBqZXN0IGFuYWxpemEgcHJhd2RvcG9kb2JpZcWEc3R3YS4gUm9iaSBzacSZIHRvIHcgY2VsdSBkYWxzemVnbyB3eWphxZtuaWVuaWEsIGRsYWN6ZWdvIHBvdHJ6ZWJuZSBzxIUgZXN0eW1hdG9yeSB6IHJlZ3VsYXJ5emFjasSFIHcgY2VsdSB1bmlrbmnEmWNpYSBuYWRtaWVybmVnbyBkb3Bhc293YW5pYSBkbyBkYW55Y2gsIG9yYXogZGxhY3plZ28gbmllIGlzdG5pZWplIHcgb2fDs2xlIG5pZXBhcmFtZXRyeWN6bnkgbWFrc3ltYWxuZWdvIHByYXdkb3BvZG9iaWXFhHN0d2EgZXN0eW1hdG9yYSBnxJlzdG/Fm2NpLiBSZWd1bGFyeXphY2rEmSBwcmF3ZG9wb2RvYmllxYRzdHdhbW/FvG5hIG9zacSFZ27EhcSHIHBvcHJ6ZXogb2dyYW5pY3plbmllIHN6YWN1bmvDs3cgZ8SZc3RvxZtjaSBkbyByb2R6aW55IGNvcmF6IGJhcmR6aWVqIGVsYXN0eWN6bnljaCBnxJlzdG/Fm2NpIHBhcmFtZXRyeWN6bnljaCwga3TDs3JlIHPEhSBkb3Bhc293YW5lIGRvIGRhbnljaC4gSmVzdCB0byB6bmFuZSBqYWtvICptZXRvZGEgc2l0Ki4gSW5uZSBwb2RlasWbY2llIG9waWVyYSBzacSZIG5hIHJvenN6ZXJ6ZW5pYWNoIGJhem93eWNoLCBhbGUgdyBvYnUgcHJ6eXBhZGthY2ggYXV0b21hdHljem55IHd5YsOzciB3aWVsa2/Fm2NpIHJlZ3VsYXJub8WbY2kgamVzdCB0YWsgc2FtbyB3YcW8bnkgamFrIHcgcHJ6eXBhZGt1IG1ldG9kIGrEhWRyb3d5Y2guDQoNCkFieSB1dHdvcnp5xIcgd3lrcmVzIGfEmXN0b8WbY2kgasSFZHJhLCBtdXNpc3ogb3N6YWNvd2HEhyBnxJlzdG/Fm8SHIGrEhWRyYS4gVyB0eW0gY2VsdSBtb8W8bmEgdcW8ecSHIGZ1bmtjamkgZGVuc2l0eSwgYSBuYXN0xJlwbmllIHByemVrYXphxIcgb2JpZWt0IGRlbnNpdHkgZG8gZnVua2NqaSBwbG90Lg0KDQpgYGB7cn0NCiMgZGFuZQ0Kc2V0LnNlZWQoMTQwMTIwMjEpDQpkYXRhIDwtIHJub3JtKDIwMCwgbWVhbiA9IDQpDQoNCiMgS2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbg0KZCA8LSBkZW5zaXR5KGRhdGEpDQoNCiMgS2VybmVsIGRlbnNpdHkgcGxvdA0KcGxvdChkLCBsd2QgPSAyLCBtYWluID0gIkRlZmF1bHQga2VybmVsIGRlbnNpdHkgcGxvdCIpDQoNCmBgYA0KDQpBcmd1bWVudCBqxIVkcmEgZnVua2NqaSBnxJlzdG/Fm2NpIGRvbXnFm2xuaWUgdcW8eXdhIGrEhWRyYSBnYXVzc293c2tpZWdvIChrZXJuZWwgPSAiZ2F1c3NpYW4iKSwgYWxlIGRvc3TEmXBueWNoIGplc3Qgd2nEmWNlaiB0eXDDs3cgasSFZHJhLCB0YWtpY2ggamFrICJwcm9zdG9rxIV0bmUiLCAidHLDs2prxIV0bmUiLCAiZXBhbmVjaG5pa292IiwgImJpd2VpZ2h0IiwgImNvc2luZSIgaSAib3B0Y29zaW5lIi4gV3liw7NyIGLEmWR6aWUgemFsZcW8YcWCIG9kIHR3b2ljaCBkYW55Y2gsIGFsZSB3IHdpxJlrc3pvxZtjaSBzY2VuYXJpdXN6eSB3YXJ0b8WbxIcgZG9tecWbbG5hIGplc3QgbmFqYmFyZHppZWogemFsZWNhbmEuDQoNCmBgYHtyfQ0KIyBEYXRhDQpzZXQuc2VlZCgxNDAxMjAyMSkNCmRhdGEgPC0gcm5vcm0oMjAwLCBtZWFuID0gNCkNCg0KIyBLZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uDQpkIDwtIGRlbnNpdHkoZGF0YSwNCiAgICAgICAgICAgICBrZXJuZWwgPSAicmVjdGFuZ3VsYXIiKQ0KDQojIEtlcm5lbCBkZW5zaXR5IHBsb3QNCnBsb3QoZCwgbHdkID0gMiwgbWFpbiA9ICJSZWN0YW5ndWxhciBrZXJuZWwiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBEYXRhDQpzZXQuc2VlZCgxNDAxMjAyMSkNCmRhdGEgPC0gcm5vcm0oMjAwLCBtZWFuID0gNCkNCg0KIyBLZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uDQpkIDwtIGRlbnNpdHkoZGF0YSwNCiAgICAgICAgICAgICBrZXJuZWwgPSAidHJpYW5ndWxhciIpDQoNCiMgS2VybmVsIGRlbnNpdHkgcGxvdA0KcGxvdChkLCBsd2QgPSAyLCBtYWluID0gIlRyaWFuZ3VsYXIga2VybmVsIikNCmBgYA0KDQpgYGB7cn0NCiMgRGF0YQ0Kc2V0LnNlZWQoMTQwMTIwMjEpDQpkYXRhIDwtIHJub3JtKDIwMCwgbWVhbiA9IDQpDQoNCiMgS2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbg0KZCA8LSBkZW5zaXR5KGRhdGEsDQogICAgICAgICAgICAga2VybmVsID0gImVwYW5lY2huaWtvdiIpDQoNCiMgS2VybmVsIGRlbnNpdHkgcGxvdA0KcGxvdChkLCBsd2QgPSAyLCBtYWluID0gIkVwYW5lY2huaWtvdiBrZXJuZWwiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBEYXRhDQpzZXQuc2VlZCgxNDAxMjAyMSkNCmRhdGEgPC0gcm5vcm0oMjAwLCBtZWFuID0gNCkNCg0KIyBLZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uDQpkIDwtIGRlbnNpdHkoZGF0YSwNCiAgICAgICAgICAgICBrZXJuZWwgPSAiYml3ZWlnaHQiKQ0KDQojIEtlcm5lbCBkZW5zaXR5IHBsb3QNCnBsb3QoZCwgbHdkID0gMiwgbWFpbiA9ICJCaXdlaWdodCBrZXJuZWwiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBEYXRhDQpzZXQuc2VlZCgxNDAxMjAyMSkNCmRhdGEgPC0gcm5vcm0oMjAwLCBtZWFuID0gNCkNCg0KIyBLZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uDQpkIDwtIGRlbnNpdHkoZGF0YSwNCiAgICAgICAgICAgICBrZXJuZWwgPSAiY29zaW5lIikNCg0KIyBLZXJuZWwgZGVuc2l0eSBwbG90DQpwbG90KGQsIGx3ZCA9IDIsIG1haW4gPSAiQ29zaW5lIGtlcm5lbCIpDQpgYGANCg0KIyMgU2VsZWtjamEgcGFzbWENCg0KQXJndW1lbnQgYncgZnVua2NqaSBnxJlzdG/Fm2NpIHBvendhbGEgbmEgem1pYW7EmSB1xbx5d2FuZWdvIHBhc21hIHd5Z8WCYWR6YW5pYS4gTW/FvGVzeiBwcnpla2F6YcSHIHdhcnRvxZvEhyBsdWIgY2nEhWcgem5ha8OzdyBwb2RhasSFY3kgcmVndcWCxJkgd3lib3J1IGx1YiBmdW5rY2rEmS4gRG9tecWbbG7EhSB3YXJ0b8WbY2nEhSBqZXN0ICJucmQwIiAobHViIGJ3Lm5yZDAoLikpLCBrdMOzcmEgaW1wbGVtZW50dWplIHBvZGVqxZtjaWUgb3BhcnRlIG5hIHphc2FkemllIHJlZ3XFgnkga2NpdWthIDotKSBJbm5lIGRvc3TEmXBuZSBvcGNqZSB0bzoNCg0KIyMjIFJlZ3XFgmEgU2NvdHRhICgxOTkyKQ0KDQpgYGB7cn0NCiMgRGF0YQ0Kc2V0LnNlZWQoMTQwMTIwMjEpDQpkYXRhIDwtIHJub3JtKDIwMCwgbWVhbiA9IDQpDQoNCiMgS2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbg0KZCA8LSBkZW5zaXR5KGRhdGEsDQogICAgICAgICAgICAgYncgPSAibnJkIikNCg0KIyBLZXJuZWwgZGVuc2l0eSBwbG90DQpwbG90KGQsIGx3ZCA9IDIsIG1haW4gPSAibnJkIGJhbmR3aWR0aCIpDQpgYGANCg0KIyMjIE5pZW9iY2nEhcW8b25hIGNyb3NzLXdhbGlkYWNqYQ0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBEYXRhDQpzZXQuc2VlZCgxNDAxMjAyMSkNCmRhdGEgPC0gcm5vcm0oMjAwLCBtZWFuID0gNCkNCg0KIyBLZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uDQpkIDwtIGRlbnNpdHkoZGF0YSwNCiAgICAgICAgICAgICBidyA9ICJ1Y3YiKQ0KDQojIEtlcm5lbCBkZW5zaXR5IHBsb3QNCnBsb3QoZCwgbHdkID0gMiwgbWFpbiA9ICJ1Y3YgYmFuZHdpZHRoIikNCmBgYA0KDQojIyMgT2JjacSFxbxvbmEgY3Jvc3Mtd2FsaWRhY2phDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIERhdGENCnNldC5zZWVkKDE0MDEyMDIxKQ0KZGF0YSA8LSBybm9ybSgyMDAsIG1lYW4gPSA0KQ0KDQojIEtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24NCmQgPC0gZGVuc2l0eShkYXRhLA0KICAgICAgICAgICAgIGJ3ID0gImJjdiIpDQoNCiMgS2VybmVsIGRlbnNpdHkgcGxvdA0KcGxvdChkLCBsd2QgPSAyLCBtYWluID0gImJjdiBiYW5kd2lkdGgiKSANCg0KYGBgDQoNCiMjIyBNZXRvZGEgU2hlYXRoZXIgJiBKb25lcyAoMTk5MSkNCg0KYGBge3J9DQojIERhdGENCnNldC5zZWVkKDE0MDEyMDIxKQ0KZGF0YSA8LSBybm9ybSgyMDAsIG1lYW4gPSA0KQ0KDQojIEtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24NCmQgPC0gZGVuc2l0eShkYXRhLA0KICAgICAgICAgICAgIGJ3ID0gIlNKIikNCg0KIyBLZXJuZWwgZGVuc2l0eSBwbG90DQpwbG90KGQsIGx3ZCA9IDIsIG1haW4gPSAiU0ogYmFuZHdpZHRoIikNCmBgYA0KDQpPc3RyemXFvGVuaWUhDQoNCjogICBTemVyb2tvxZvEhyBwYXNtYSBtdXNpIGJ5xIcgYmFyZHpvIHN0YXJhbm5pZSBkb2JyYW5hISBNYcWCYSBzemVyb2tvxZvEhyBwYXNtYSBzcG93b2R1amUgcG93c3RhbmllIG5hZG1pZXJuaWUgZG9wYXNvd2FuZWoga3J6eXdlaiwgbmF0b21pYXN0IHpieXQgZHXFvGEgc3plcm9rb8WbxIcgcGFzbWEgc3Bvd29kdWplIHBvd3N0YW5pZSBrcnp5d2VqIG5hZG1pZXJuaWUgd3lnxYJhZHpvbmVqLg0KDQojIMSGd2ljemVuaWUgMS4NCg0KVXJ1Y2hvbSBkZW1vIGVzdHltYXRvcmEgZnVua2NqaSBnxJlzdG/Fm2NpIGtlcm5lbC4gWm1pZW5pYWogemFyw7N3bm8gZGFuZSB3ZWrFm2Npb3dlLCBqYWsgaSBvcGNqZSBlc3R5bWF0b3JhIC0gc3plcm9rb8WbxIcgcGFzbWEgb3JheiByb2R6YWogZnVua2NqaSBqxIVkcm93ZWouIEN6eSB3aWR6aXN6IGlzdG90bmUgcsOzxbxuaWNlIHcgb3N6YWNvd2FuaXU/DQoNCg0KDQpgYGB7ciBjd2ljemVuaWUxfQ0KI2luc3RhbGwucGFja2FnZXMoInJlbW90ZXMiKSAjdHlsa28gcmF6ISBwb3RlbSAjDQojaW5zdGFsbF9naXRodWIoImhlcmlja3MvS0RFIikgI3R5bGtvIHJheiEgcG90ZW0gIw0KI2luc3RhbGwucGFja2FnZXMoImh0bWx0b29scyIpDQojcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoImhlcmlja3MvS0RFIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJrZGUiKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShLREUpDQpzaGlueV9rZGUoKQ0KYGBgDQpSemVjenl3acWbY2llIG1vxbxuYSB6YXV3YcW8ecSHIHd5cmHFum5lIHLDs8W8bmljZS4gWndpxJlrc3plbmllIHdhcnRvxZtjaSBvZGNoeWxlbmlhIHN0YW5kYXJkb3dlZ28gcG93b2R1amUsIMW8ZSByb3prxYJhZCBzdGFqZSBzacSZIGJhcmR6aWVqIHDFgmFza2kgaSByb3pjacSFZ25pxJl0eSwgY28gb3puYWN6YSB3acSZa3N6ZSByb3pwcm9zemVuaWUgZGFueWNoIHdva8OzxYIgxZtyZWRuaWVqLiBaIGtvbGVpIHptbmllanN6ZW5pZSBvZGNoeWxlbmlhIHN0YW5kYXJkb3dlZ28gc3ByYXdpYSwgxbxlIHJvemvFgmFkIHN0YWplIHNpxJkgd8SZxbxzenkgaSBiYXJkemllaiBza3VwaW9ueS4NClptaWFuYSB3YXJ0b8WbY2kgxZtyZWRuaWVqIHBvd29kdWplIHByemVzdW5pxJljaWUgxZtyb2RrYSByb3prxYJhZHUgbmEgb3NpIHBvemlvbWVqIChvxZsgeCkuIElubnltaSBzxYJvd3ksIGNhxYJ5IHJvemvFgmFkIHByemVzdXdhIHNpxJkgdyBwcmF3byBsdWIgdyBsZXdvIHcgemFsZcW8bm/Fm2NpIG9kIHRlZ28sIGN6eSDFm3JlZG5pYSB6b3N0YcWCYSB6d2nEmWtzem9uYSwgY3p5IHptbmllanN6b25hLCBhbGUgc2FtIGtzenRhxYJ0IHJvemvFgmFkdSBwb3pvc3RhamUgdGFraSBzYW0uDQpOYXRvbWlhc3QgbW9keWZpa2FjamEgc3plcm9rb8WbY2kgcGFzbWEgKGJhbmR3aWR0aCkgd3DFgnl3YSBuYSBzdG9waWXFhCwgdyBqYWtpbSBrcnp5d2EgZG9wYXNvd3VqZSBzacSZIGRvIGRhbnljaC4gSW0gbW5pZWpzemEgd2FydG/Fm8SHIHBhc21hLCB0eW0gYmFyZHppZWoga3J6eXdhIHN0YWplIHNpxJkgc3pjemVnw7PFgm93YSBpIGxlcGllaiBvZHd6b3Jvd3VqZSBsb2thbG5lIHptaWFueSB3IGRhbnljaC4gSmVkbmFrIHdpxJlrc3phIHN6ZXJva2/Fm8SHIHBhc21hIHBvd29kdWplIHd5Z8WCYWR6ZW5pZSBrcnp5d2VqLCBjbyBwcm93YWR6aSBkbyBiYXJkemllaiBvZ8OzbG5lZ28gZG9wYXNvd2FuaWEgaSBwb21pbmnEmWNpYSBkcm9ibnljaCBzemN6ZWfDs8WCw7N3Lg0KDQpKZcWbbGkgY2hvZHppIG8gcsOzxbxuaWNlIHBvbWnEmWR6eSBhcmd1bWVudGFtaSBqxIVkcmEgZnVua2NqaSBnxJlzdG/Fm2NpLCB0byBtb8W8ZW15IHphdXdhennEhywgxbxlIHJvZHphaiAncmVjdGFuZ3VsYXInIGplc3QgbmFqYmFyZHppZWogZG9wYXNvd2FueSBkbyBkYW55Y2gsIG1vxbxuYSBieSBzdHdpZXJkemnEhywgxbxlIGHFvCB6Ynl0IGRvYnJ6ZSBkb3Bhc293YW55LCBwb25pZXdhxbwgcHJha3R5Y3puaWUgd29nw7NsZSBuaWUgd3lnxYJhZHphIHJvemvFgmFkdS4gUm9kemFqICdMb2dpc3RpYycsIGplc3QgbmFqYmFyZHppZWogInNwxYJhc3pjem9ueSIgaSB3eWfFgmFkem9ueSB6ZSB3c3p5c3RraWNoIHJvemvFgmFkw7N3LiAnVHJpd2VpZ2h0JywnVHJpYW5ndWxhcicsJ1RyaWN1YmUnLCBkb2JyemUgZG9wYXNvd3VqxIUgc2nEmSBkbyBkYW55Y2gsIGFsZSBuaWV6Ynl0IHd5Z8WCYWR6YWrEhSByb3prxYJhZC4gUG9zb2JuaWUgJ0VwYW5lY2huaWtvdicsJ0Jpd2VpZ2h0JyBpICdDb3NpbmUnLiAnU2lsdmVybWFuJyBpICdTaWdtb2lkJyBtYWrEhSBjZWNoeSB6Ymxpem9uZSBkbyAnTG9naXN0aWMnLCBsZWN6IHPEhSBvbmUgbW5pZWogc3DFgmFzemN6b25lLiBDaG/EhyBqZXN6Y3plIG1uaWUgc3DFgmFzemN6b255IGplc3Qga2xhc3ljem55IHJvemvFgmFkICdHYXVzc2lhbicuDQoNCiMgxIZ3aWN6ZW5pZSAyLg0KDQpXeWtvcnp5c3R1asSFYyBkb3dvbG7EhSBmdW5rY2rEmSBSIGRvIGVzdHltYWNqaSBmdW5rY2ppIGfEmXN0b8WbY2kgb3N6YWN1aiBqZWogcHJ6ZWJpZWcgZGxhIHd5bmFncm9kemXFhCAoemJpw7NyIGRhbnljaCBzYWxhcmllcykgc3RyYcW8YWvDs3cgdyBTYW4gRnJhbmNpc2NvLiBXeWtvcnp5c3RhaiBtZXRvZHkgZ3JhZmljem5lIGRvc3TEmXBuZSB3IHBha2llY2llIGdncGxvdDIuIE1pbGUgd2lkemlhbmUgcHJ6ZWtyb2plIG9yYXogb2Rwb3dpZWR6aSBuYSBweXRhbmlhIGJhZGF3Y3plIHphZGFuZSBuYSB3c3TEmXBpZS4NCg0KDQpgYGB7ciB9DQpzYWxhcmllc0ZGU2FuRiA8LSBzdWJzZXQoc2FsYXJpZXMsIEpvYlRpdGxlPT0iRmlyZWZpZ2h0ZXIiICYgQWdlbmN5PT0iU2FuIEZyYW5jaXNjbyIpDQpkaW0oc2FsYXJpZXNGRlNhbkYpDQpgYGANCiMjIFphY3puaWVteSBvZCBweXRhxYQgYmFkYXdjenljaC4NCiMjIEphayB6bWllbmlhxYJ5IHNpxJkgd3luYWdyb2R6ZW5pYSB3IGN6YXNpZSBtacSZZHp5IHLDs8W8bnltaSBncnVwYW1pIGx1ZHppPw0KDQojIyBIaXN0b2dyYW0gd3luYWdyb2R6ZcWEIGRsYSBzdHJhxbxha8OzdyB6IFNhbiBGcmFuY2lzY28uDQoNCmBgYHtyfQ0Kc3JfbWVkaWFuYV9saW5pZSA8LSBkYXRhLmZyYW1lKG5hendhID0gYygixZpyZWRuaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZWRpYW5hIiksDQogICAgICAgICAgICAgICAgICAgICAgIHdhcnRvxZvEhyAgICAgPSBjKG1lYW4oc2FsYXJpZXNGRlNhbkYkVG90YWxQYXkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihzYWxhcmllc0ZGU2FuRiRUb3RhbFBheSkpKQ0KDQpnZ3Bsb3Qoc2FsYXJpZXNGRlNhbkYsYWVzKHggPSBUb3RhbFBheSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MTAwMDAsIGNvbG9yPSJwdXJwbGUiLGZpbGw9InllbGxvdyIpICsNCiAgbGFicyh4ID0gIlBheSAoaW4gZG9sbGFycykiLCB5ID0gIkZyZXF1ZW5jeSIsIHRpdGxlID0gIkhpc3RvZ3JhbSB3eW5hZ3JvZHplxYQgc3RyYcW8YWvDs3cgdyBTYW4gRnJhbmNpc2NvIikgKw0KICBnZW9tX3ZsaW5lKGRhdGE9c3JfbWVkaWFuYV9saW5pZSxhZXMoeGludGVyY2VwdCA9IHdhcnRvxZvEhywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9IG5hendhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IG5hendhKSxsaW5ld2lkdGg9MSxjb2xvcj0iYmx1ZSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCiAgDQpgYGANCk1vxbxlbXkgemF1d2HFvHnEhywgxbxlIGJhZGFueSByb3prxYJhZCB3eW5hZ3JvZHplxYQgamVzdCBwcmF3b3Nrb8WbbnkgaSB3acSZY2VqIHN0cmHFvGFrw7N3IHphcmFiaWEgcG9uYWQgxZtyZWRuaWUgd3luYWdyb2R6ZW5pZSBkbGEgaWNoIHN0YW5vd2lza2EuIE1hbXkgcsOzd25pZcW8IGRydWfEhSwgbWHFgsSFLCBsb2thbG7EhSBtb2TEmSB3IG9rb2xpY2FjaCAwOjUwIDAwMCBVU0QsIGt0w7NyYSB6YW5pxbxhIG5hbSB3YXJ0b8WbxIcgbWVkaWFueS4NCg0KIyMgUG9uacW8ZWogaGlzdG9ncmFtICB6bWlhbiB3eW5hZ3JvZHplxYQgc3RyYcW8YWvDs3cgeiBTRiBuYSBwcnplc3RyemVuaSBsYXQNCg0KYGBge3J9DQpzcl9tZWRpYW5hX2xpbmllXzIwMTIgPC0gZGF0YS5mcmFtZShuYXp3YSA9IGMoIsWacmVkbmlhIHogMjAxMiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhbmEgeiAyMDEyIiksIHdhcnRvxZvEhyA9IGMobWVhbihzYWxhcmllc0ZGU2FuRiRUb3RhbFBheVtzYWxhcmllc0ZGU2FuRiRZZWFyPT0yMDEyXSksDQogbWVkaWFuKHNhbGFyaWVzRkZTYW5GJFRvdGFsUGF5W3NhbGFyaWVzRkZTYW5GJFllYXI9PTIwMTJdKSkpDQoNCmdncGxvdChzYWxhcmllc0ZGU2FuRixhZXMoeCA9IFRvdGFsUGF5KSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0yNTAwMCwgY29sb3I9InB1cnBsZSIsZmlsbD0ieWVsbG93IikgKw0KICBsYWJzKHggPSAiUGF5IChpbiBkb2xsYXJzKSIsIHkgPSAiRnJlcXVlbmN5IiwgdGl0bGUgPSAiSGlzdG9ncmFtIHd5bmFncm9kemXFhCBzdHJhxbxha8OzdyB3IFNhbiBGcmFuY2lzY28iKSArDQogIGdlb21fdmxpbmUoZGF0YT1zcl9tZWRpYW5hX2xpbmllLGFlcyh4aW50ZXJjZXB0ID0gd2FydG/Fm8SHLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gbmF6d2EsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sID0gbmF6d2EpLGxpbmV3aWR0aD0xLGNvbG9yPSJibHVlIikrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgZmFjZXRfZ3JpZCguIH4gWWVhcikNCg0KYGBgDQpNb8W8ZW15IHphdXdhxbx5xIcsIMW8ZSB3IHBvcsOzd25hbml1IGRvIDIwMTIgcm9rdSB3IDIwMTMgcm9rdSBsaWN6YmEgc3RyYcW8YWvDs3csIGt0w7NyenkgemFyYWJpYWxpIGt3b3TEmSBvZHBvd2lhZGFqxIVjxIUgxZtyZWRuaWVqIGkgbWVkaWFuaWUgeiAyMDEyIHJva3UsIHd6cm9zxYJhLiBKZWRuYWsgdyAyMDE0IHJva3Ugd2FydG/Fm2NpIHRlIHBvd3LDs2NpxYJ5IGRvIHBvemlvbcOzdyB6YmxpxbxvbnljaCBkbyB0eWNoIHogMjAxMiByb2t1LiDFmndpYWRjenkgbyB0eW0gem1pYW5hIMWbcmVkbmllZ28gd3luYWdyb2R6ZW5pYSB3IGFuYWxpem93YW55Y2ggbGF0YWNoIOKAkyBwbyB3enJvxZtjaWUgdyAyMDEzIHJva3Ugb3NpxIVnbsSZxYJvIG9ubyBuYWp3ecW8c3p5IHBvemlvbSwgYnkgbmFzdMSZcG5pZSB3IDIwMTQgcm9rdSBzcGHFm8SHIHBvbmnFvGVqIHdhcnRvxZtjaSBvZG5vdG93YW5laiB3IDIwMTIgcm9rdS4gDQoNCmBgYHtyfQ0KDQpzcl9tZWRpYW55X2xhdGEgPC0gZGF0YS5mcmFtZShSb2sgPSBjKDIwMTIsMjAxMywyMDE0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDFm3JlZG5pZSA9IGMobWVhbihzYWxhcmllc0ZGU2FuRiRUb3RhbFBheVtzYWxhcmllc0ZGU2FuRiRZZWFyPT0yMDEyXSksDQptZWFuKHNhbGFyaWVzRkZTYW5GJFRvdGFsUGF5W3NhbGFyaWVzRkZTYW5GJFllYXI9PTIwMTNdKSwNCm1lYW4oc2FsYXJpZXNGRlNhbkYkVG90YWxQYXlbc2FsYXJpZXNGRlNhbkYkWWVhcj09MjAxNF0pKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbnkgPSBjKG1lZGlhbihzYWxhcmllc0ZGU2FuRiRUb3RhbFBheVtzYWxhcmllc0ZGU2FuRiRZZWFyPT0yMDEyXSksDQptZWRpYW4oc2FsYXJpZXNGRlNhbkYkVG90YWxQYXlbc2FsYXJpZXNGRlNhbkYkWWVhcj09MjAxM10pLA0KbWVkaWFuKHNhbGFyaWVzRkZTYW5GJFRvdGFsUGF5W3NhbGFyaWVzRkZTYW5GJFllYXI9PTIwMTRdKSkpDQpgYGANCg0KIyMgV3lrcmVzIHBva2F6dWrEhWN5IHptaWFueSDFm3JlZG5pZWogaSBtZWRpYW55IHDFgmFjIGRsYSBzdHJhxbxha8OzdyB3IFNhbiBGcmFuY2lzY28gdyBsYXRhY2ggMjAxMi0yMDE0DQoNCmBgYHtyfQ0KZ2dwbG90KHNyX21lZGlhbnlfbGF0YSwgYWVzKFJvaywgxZtyZWRuaWUpKSArIA0KICAgIGdlb21fcmliYm9uKGFlcyh5bWluID0gxZtyZWRuaWUsIHltYXggPSBtZWRpYW55KSxmaWxsID0gInB1cnBsZSIpKw0KICBnZW9tX2xpbmUoYWVzKHg9Um9rLHk9bWVkaWFueSxjb2xvcj0iTWVkaWFueSIpLGx3ZD0xKSsNCiAgZ2VvbV9saW5lKGFlcyh4PVJvayx5PcWbcmVkbmllLGNvbG9yPSLFmnJlZG5pZSIpLGx3ZD0xKSsNCiAgbGFicyh4ID0gIlllYXIiLCB5ID0gIlRvdGFsIFBheSAoaW4gRG9sbGFycykiLCB0aXRsZSA9ICJabWlhbnkgcsOzxbxuaWN5IG1pxJlkenkgxZtyZWRuacSFIGkgbWVkaWFuxIUgbmEgcHJ6ZXN0cnplbmkgdHJ6ZWNoIGxhdCB3xZtyw7NkIHN0cmHFvGFrw7N3IFNhbiBGcmFuY2lzY28iKSsNCiAgIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCk1vxbxlbXkgemFvYnNlcndvd2HEhyB6bWlhbnkgdyDFm3JlZG5pZWogaSBtZWRpYW5pZSB3eW5hZ3JvZHplxYQgc3RyYcW8YWvDs3cgdyBhbmFsaXpvd2FueWNoIGxhdGFjaCwgamFrIHdzcG9tbmlhbm8gd2N6ZcWbbmllai4gQ28gd2nEmWNlaiwgcsOzxbxuaWNhIG1pxJlkenkgbWVkaWFuxIUgYSDFm3JlZG5pxIUgc3RhamUgc2nEmSBjb3JheiBiYXJkemllaiB3aWRvY3puYSwgcHJ6eSBjenltIMWbcmVkbmlhIHd5cGFkYSBuYSBuacW8c3p5bSBwb3ppb21pZSB3IHN0b3N1bmt1IGRvIG1lZGlhbnkuIFRvIHdza2F6dWplLCDFvGUgd2nEmWtzem/Fm8SHIHN0cmHFvGFrw7N3IG90cnp5bXVqZSB3eW5hZ3JvZHplbmllIHd5xbxzemUgbmnFvCBwcnplY2nEmXRuYSBwxYJhY2EgdyB0ZWogZ3J1cGllIHphd29kb3dlai4NCg0KIyMgSmFrIHDFgmFjYSBwb2RzdGF3b3dhLCB3eW5hZ3JvZHplbmllIHphIG5hZGdvZHppbnkgaSDFm3dpYWRjemVuaWEgc8SFIHJvemR6aWVsYW5lIHBvbWnEmWR6eSByw7PFvG5lIGdydXB5Pw0KYGBge3J9DQpzYWxhcmllc0ZGU2FuRiRCZW5lZml0czwtYXMubnVtZXJpYyhzYWxhcmllc0ZGU2FuRiRCZW5lZml0cykNCnNhbGFyaWVzRkZTYW5GJE92ZXJ0aW1lUGF5PC1hcy5udW1lcmljKHNhbGFyaWVzRkZTYW5GJE92ZXJ0aW1lUGF5KQ0Kc2FsYXJpZXNGRlNhbkYkQmFzZVBheTwtYXMubnVtZXJpYyhzYWxhcmllc0ZGU2FuRiRCYXNlUGF5KQ0KYGBgDQoNCg0KIyMgUMWCYWNhIHBvZHN0YXdvd2ENCg0KYGBge3J9DQpzcl9tZWRpYW5hX2xpbmllX2Jhc2VwYXkgPC0gZGF0YS5mcmFtZShuYXp3YSA9IGMoIsWacmVkbmlhIGRsYSBGVCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhbmEgZGxhIEZUIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcnRvxZvEhz1jKG1lYW4oc2FsYXJpZXNGRlNhbkYkQmFzZVBheVtzYWxhcmllc0ZGU2FuRiRTdGF0dXM9PSdGVCddKSwNCiBtZWRpYW4oc2FsYXJpZXNGRlNhbkYkQmFzZVBheVtzYWxhcmllc0ZGU2FuRiRTdGF0dXM9PSdGVCddKSkpDQoNCmdncGxvdChzYWxhcmllc0ZGU2FuRixhZXMoeCA9IEJhc2VQYXkpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTI1MDAwLCBjb2xvcj0iZ3JlZW4iLGZpbGw9ImJsdWUiKSArDQogIGxhYnMoeCA9ICJCYXNlIFBheSIsIHkgPSAiRnJlcXVlbmN5IiwgdGl0bGUgPSAiSGlzdG9ncmFtIHDFgmFjeSBwb2RzdGF3b3dlaiBkbGEgc3RyYcW8YWvDs3cgdyBTYW4gRnJhbmNpc2NvIikgKw0KICBnZW9tX3ZsaW5lKGRhdGE9c3JfbWVkaWFuYV9saW5pZV9iYXNlcGF5LGFlcyh4aW50ZXJjZXB0ID0gd2FydG/Fm8SHLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gbmF6d2EsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sID0gbmF6d2EpLGxpbmV3aWR0aD0xLGNvbG9yPSJibGFjayIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIGZhY2V0X2dyaWQoLiB+IFN0YXR1cykNCg0KYGBgDQoNCiMjIFd5bmFncm9kemVuaWUgemEgbmFkZ29kemlueQ0KYGBge3J9DQpzcl9tZWRpYW5hX2xpbmllX292ZXJ0aW1lIDwtIGRhdGEuZnJhbWUobmF6d2EgPSBjKCLFmnJlZG5pYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhbmEiKSwgd2FydG/Fm8SHID0gYyhtZWFuKHNhbGFyaWVzRkZTYW5GJE92ZXJ0aW1lUGF5KSwNCiBtZWRpYW4oc2FsYXJpZXNGRlNhbkYkT3ZlcnRpbWVQYXkpKSkNCg0KZ2dwbG90KHNhbGFyaWVzRkZTYW5GLGFlcyh4ID0gT3ZlcnRpbWVQYXkpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTI1MDAwLCBjb2xvcj0iZ3JlZW4iLGZpbGw9ImJsdWUiKSArDQogIGxhYnMoeCA9ICJPdmVydGltZSBQYXkiLCB5ID0gIkZyZXF1ZW5jeSIsIHRpdGxlID0gIkhpc3RvZ3JhbSBwxYJhY3kgemEgbmFkZ29kemlueSBkbGEgc3RyYcW8YWvDs3cgdyBTYW4gRnJhbmNpc2NvIikgKw0KICBnZW9tX3ZsaW5lKGRhdGE9c3JfbWVkaWFuYV9saW5pZV9vdmVydGltZSxhZXMoeGludGVyY2VwdCA9IHdhcnRvxZvEhywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9IG5hendhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IG5hendhKSxsaW5ld2lkdGg9MSxjb2xvcj0iYmxhY2siKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICBmYWNldF9ncmlkKC4gfiBTdGF0dXMpDQoNCmBgYA0KDQojIyBCZW5lZml0eQ0KYGBge3J9DQpzcl9tZWRpYW5hX2xpbmllX2JlbmVmaXRzIDwtIGRhdGEuZnJhbWUobmF6d2EgPSBjKCLFmnJlZG5pYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhbmEiKSwgd2FydG/Fm8SHID0gYyhtZWFuKHNhbGFyaWVzRkZTYW5GJEJlbmVmaXRzKSwNCiBtZWRpYW4oc2FsYXJpZXNGRlNhbkYkQmVuZWZpdHMpKSkNCg0KZ2dwbG90KHNhbGFyaWVzRkZTYW5GLGFlcyh4ID0gQmVuZWZpdHMpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTEwMDAwLCBjb2xvcj0icmVkIixmaWxsPSJibHVlIikgKw0KICBsYWJzKHggPSAiQmVuZWZpdHMiLCB5ID0gIkZyZXF1ZW5jeSIsIHRpdGxlID0gIkhpc3RvZ3JhbSDFm3dpYWRjemXFhC9CZW5lZml0w7N3IGRsYSBzdHJhxbxha8OzdyB3IFNhbiBGcmFuY2lzY28iKSArDQogIGdlb21fdmxpbmUoZGF0YT1zcl9tZWRpYW5hX2xpbmllX2JlbmVmaXRzLGFlcyh4aW50ZXJjZXB0ID0gd2FydG/Fm8SHLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gbmF6d2EsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sID0gbmF6d2EpLGxpbmV3aWR0aD0xLGNvbG9yPSJibGFjayIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIGZhY2V0X2dyaWQoLiB+IFN0YXR1cykNCg0KYGBgDQpNb8W8ZW15IHphdXdhxbx5xIcsIMW8ZSBidWTFvGV0IHByemV6bmFjem9ueSBuYSB3eW5hZ3JvZHplbmllIHBvZHN0YXdvd2UsIHDFgmF0bm/Fm2NpIHphIG5hZGdvZHppbnkgb3JheiDFm3dpYWRjemVuaWEgcsOzxbxuaSBzacSZIHcgemFsZcW8bm/Fm2NpIG9kIHRlZ28sIGN6eSBzdHJhxbxhY3kgc8SFIHphdHJ1ZG5pZW5pIHcgcGXFgm55bSB3eW1pYXJ6ZSBnb2R6aW4gKEZUKSwgY3p5IG5hIHDDs8WCIGV0YXR1IChTVCkuIFpnb2RuaWUgeiBwcnpld2lkeXdhbmlhbWksIHdzenlzdGtpZSB0ZSB3eWRhdGtpIHPEhSBuacW8c3plIHcgcHJ6eXBhZGt1IHN0cmHFvGFrw7N3IHByYWN1asSFY3ljaCB3IG5pZXBlxYJueW0gd3ltaWFyemUgZ29kemluLg0KDQojIyBDenkgdyB0eW0gemVzdGF3aWUgZGFueWNoIGlzdG5pZWrEhSBkb3dvZHkgbmEgZHlza3J5bWluYWNqxJkgcMWCYWNvd8SFIHplIHd6Z2zEmWR1IG5hIHDFgmXEhz8gDQoNCk5pZSBqZXN0ZcWbbXkgdyBzdGFuaWUgb2JsaWN6ecSHIHRlZ28gZGxhIHRlZ28gemJpb3J1IGRhbnljaCwgcG9uaWV3YcW8IG5pZSBtYW15IHcgbmltIHptaWVubmVqIGRvdHljesSFY2VqIHDFgmNpLg0KDQoNCiMjIE9zemFjb3dhbmllIGfEmXN0b8WbY2kgcm96a8WCYWR1IHd5bmFncm9kemXFhCBzdHJhxbxha8OzdyB3IFNhbiBGcmFuY2lzY286DQpgYGB7cn0NCiMgS2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbg0KZCA8LSBkZW5zaXR5KHNhbGFyaWVzRkZTYW5GJFRvdGFsUGF5LA0KICAgICAgICAgICAgIGtlcm5lbCA9ICJnYXVzc2lhbiIsDQogICAgICAgICAgICAgYncgPSAxMDAwMCkNCiMgS2VybmVsIGRlbnNpdHkgcGxvdA0KcGxvdChkLCBsd2QgPSAyLCBtYWluID0gIkdhdXNzaWFuIGtlcm5lbCIpDQpgYGANCkR6acSZa2kgendpxJlrc3plbml1IHN6ZXJva2/Fm2NpIHBhc21hIGRvIDEwMDAwLHVkYcWCbyBzacSZIHd5Z8WCYWR6acSHIHJvemvFgmFkLCBrdMOzcnkgdcWCYXR3aWEgbmFtIHd5Y2nEhWduacSZY2llIHduaW9za8Ozdy4gTWFteSB0dXRhaiBwcnp5a8WCYWQgcm96a8WCYWR1IGJpbW9kYWxuZWdvLCBrdMOzcnkgcG9tYWdhIHpyb3p1bWllxIcgd2N6ZcWbbmllaiB6YXV3YcW8b25lIHpqYXdpc2tvLCDFvGUgbWVkaWFuYSBwcnpld3nFvHN6YSDFm3JlZG5pxIUuIFd5bmlrYSB0byB6IG9iZWNub8WbY2kgem5hY3puZWogZ3J1cHkgc3RyYcW8YWvDs3cgKHN0YW5vd2nEhWNlaiBkcnVnaWUgbG9rYWxuZSBtYWtzaW11bSksIGt0w7NyenkgemFyYWJpYWrEhSBuaWV3aWVsa2llIGt3b3R5IHcgcHJ6ZWR6aWFsZSA8MDsgNTAgMDAwIFVTRD4uIEljaCB6YXJvYmtpIHpuYWN6xIVjbyBvYm5pxbxhasSFIMWbcmVkbmnEhSBwxYJhYywgYWxlIGljaCBsaWN6YmEgbmllIGplc3QgbmEgdHlsZSBkdcW8YSwgYWJ5IHcgaXN0b3RueSBzcG9zw7NiIHdwxYJ5bsSFxIcgbmEgb2JuacW8ZW5pZSBtZWRpYW55Lg0KDQo=