Cel opracowania
Na moment pisania niniejszego opracowania od ponad szesciu miesiecy trwa epidemia koronawirusa. U jej początków, dzienna liczba zachorowań kształtowala się na poziomie ok 200-400 przypadków dziennie. W miarę zbliżania się do miesięcy jesiennych, liczba ta zaczęła rosnąć do ponad 3000 tysiecy przypadków dziennie. Większość państw, w tym Polska, podjęło szereg drastycznych środków, by ograniczyć rozmiary epidemii koronawirusa.
Jednak nawet oficjalne dane o zdrowiu publicznym, a także badania naukowe nad wirusami grypy skłaniają do zadania dwóch podstawowych pytań:
- czy zjawisko zachorowań na SARS-CoV-2 można w ogóle zaklasyfikowac jako epidemię?
- jesli nie, to czy obecne zachorowania nie są stałym zjawiskiem, nie diagnozowanym wcześniej.
Aby spróbować odpowiedzieć na te pytania (z pominięciem kwestii, jaka jest definicja epidemii wg WHO - i czy w ogóle istenieje takowa) warto:
- zbadać typową krzywą przebiegu zachorowań na grypę w ciągu roku,
- na tej podstawie zbudować model śródrocznych zachorowań na grypę oraz
- porównać dane o obecnych zachorowaniach na koronawirusa z danymi historycznymi i z modelem.
Dla zainteresowanych prześledzeniem poniższych rozważań, udostępniam kod w języku R służący do pobrania danych, ich przetworzenia i zaprezentowania.
Źródła danych
Badanie typowej krzywej przebiegu zachorowań na grypę w ciągu roku zostanie przeprowadzone na podstawie danych Państwowego Zakładu Higieny Narodowego Instytutu Zdrowia Publicznego. Dane te udostępnione są w formie dwutygodniowych raportów w formacie PDF na poprzedniej wersji strony tej instytucji. W 2020 roku NIZP rozpoczął udostępnianie danych poprzez serwisy EpiBaza i ProfiBaza (w trakcie rozwoju), lecz dane te są zagregowane i nie obejmują okresów śródrocznych. Stąd aby ustalić śródroczny przebieg zapadalności na wybrane choroby zakaźne w Polsce, trzeba sięgnąć do poprzedniej wersji strony. Dane do niniejszego opracowania zostały pobrane ze strony: http://wwwold.pzh.gov.pl/oldpage/epimeld/index_p.html
Zestaw danych zostanie przygotowany w dwóch krokach:
- dane zostaną pobrane w formie plików PDF
- z pobranych archiwów zostaną wyodrębnione dane dotyczące poszczególnych chorób.
# Wymagane biblioteki
library(rvest)
library(dplyr)
# Pobranie całego archiwum meldunków o zachorowaniach na choroby zakaźne, zakażeniach i zatruciach w Polsce (dwutygodniowe, kwartalne, półroczne, roczne)
url <- "http://wwwold.pzh.gov.pl/oldpage/epimeld/index_p.html"
pzholdwp <- read_html(url)
links <- pzholdwp %>% html_nodes("a") %>% html_attr("href")
links <- grep("index_mp.html$", links, value = TRUE)
links <- paste0("http://wwwold.pzh.gov.pl/oldpage/epimeld/",links)
yrs <- as.data.frame(stringr::str_extract(links, "\\d{4}"))
l2p <- data.frame()
for (i in 1:length(yrs[,1])){
url2 <- links[i]
pzhYR <- read_html(url2)
links2pdf <- pzhYR %>% html_nodes("a") %>% html_attr("href")
links2pdf <- grep("pdf$", links2pdf, value = TRUE)
links2pdf <- as.data.frame(paste0("http://wwwold.pzh.gov.pl/oldpage/epimeld/",yrs[i,],"/",links2pdf))
l2p <- rbind(l2p, links2pdf)
}
dir.create("pdf")
pth <- paste0(getwd(),"/pdf/")
for (i in 1:length(l2p[,1])){
fname <- stringr::str_sub(l2p[i,], -15, -1)
fname <- stringr::str_remove(fname, "[//]")
httr::GET(l2p[i,], httr::authenticate(":", ":", type="ntlm"),
httr::write_disk(paste0(pth,fname), overwrite = FALSE),
httr::progress()
)
}
Na moment sporządzania tego raportu, na stronach PZH znajduje się 637 meldunków o zachorowaniach na choroby zakaźne, zakażeniach i zatruciach w Polsce (dwutygodniowe, kwartalne, półroczne, roczne). Zestaw danych będzie oparty o raporty dwutygodniowe, by dokładniej zamodelować trend śródroczny.
# "Scrapping" plików pdf
library(pdftools)
library(stringr)
# library(lubridate)
library(plotly)
lista_plikow <- list.files(path = "pdf/")
grypa <- data.frame()
for (i in 1:length(lista_plikow)){
text_rep_temp <- pdf_text(pdf = paste0("pdf/",lista_plikow[i]))
text_rep_temp <- c(unlist(strsplit(text_rep_temp, "\r\n")))
# write(text_rep_temp, file = "test.txt")
wanted_lines <- c(grep("Grypa",text_rep_temp)[1],
grep("zgłoszonych w okresie od |o zgłoszonych zachorowaniach za okres od",text_rep_temp)[1]
)
wanted <- text_rep_temp[get("wanted_lines")]
data_raportu <- str_extract(wanted[2], "\\d{2}.\\d{2}.\\d{4}")
data_raportu <- lubridate::dmy(data_raportu)
wanted[1]
ilosc_przyp <- as.numeric(str_extract(wanted[1], "\\s\\d+"))
wiersz <- data.frame(data_raportu, ilosc_przyp)
grypa <- rbind(grypa, wiersz)
}
grypa <- grypa[complete.cases(grypa),]
#################################
# Dane po 2008 - zmiana formatu raportu (data jest we właściwościach pliku, dane o zachorowanian są prezentowane narastająco)
grypa08 <- data.frame()
for (i in 1:length(lista_plikow)){
text_rep_temp08 <- pdf_text(pdf = paste0("pdf/",lista_plikow[i]))
text_rep_temp08 <- c(unlist(strsplit(text_rep_temp08, "\r\n")))
wanted_lines08 <- c(grep("Grypa i podejrzenia",text_rep_temp08)[1]
)
wanted08_data_raportu <- pdf_info(pdf = paste0("pdf/",lista_plikow[i]))$keys$Title
wanted08 <- text_rep_temp08[get("wanted_lines08")]
data_raportu08 <- str_extract(wanted08_data_raportu, "\\d{2}.\\d{2}\\s\\d{4}|\\d{2}.\\d{2}.\\d{4}")
data_raportu08 <- lubridate::dmy(data_raportu08)
ilosc_przyp08 <- as.numeric(gsub("\\s","",(str_extract(wanted08[1], "(\\s\\d+){1,3}"))))
wiersz08 <- data.frame(data_raportu08, ilosc_przyp08)
grypa08 <- rbind(grypa08, wiersz08)
}
grypa08 <- grypa08[complete.cases(grypa08),]
# obliczenie ilości nowych przypadków (uwaga na dane z końca roku)
nowe_pryp_08 <- diff(grypa08$ilosc_przyp08)
nowe_pryp_08 <- c(grypa08[1,2],nowe_pryp_08)
grypa08 <- cbind(grypa08, nowe_pryp_08)
#poprawa danych z końca roku i pierwszego raportu z początku nowego roku
temp_ds <- subset(grypa08, nowe_pryp_08 <0)
temp_ds$nowe_pryp_08 <- temp_ds$ilosc_przyp08
grypa08a <- subset(grypa08, nowe_pryp_08 > 0)
grypa08a <- rbind(grypa08a, temp_ds)
grypa08a <- grypa08a[order(grypa08a$data_raportu08),]
grypa08a <- grypa08a[,c(1,3)]
# Połączenie danych do 2008 i po, w całość
cn <- colnames(grypa)
colnames(grypa08a) <- cn
grypa_calosc <- rbind(grypa, grypa08a)
grypa_calosc <- grypa_calosc[order(grypa_calosc$data_raportu),]
Po zebranu danych z plików pdf pobranych ze stron PZH, został utworzony zestaw danych zawierający ilość przypadków zachorowań na grypę w interwałach dwutygodniowych. Dane zawierają 580 obserwacji za okres od 1996-01-01 do 2020-09-30.
Analiza rozpoznawcza
Pierwsze spojrzenie na dane wyodrębnione z plików pdf:
Sezonowość dająca się zaobserwować jest oczywista. Niemniej odnośnie samego zestawu danych, trzeba zauważyć:
- dane ze stycznia 1996 roku zawierają najprawdopodoniej narastające dane z 1995 roku (wskazuje na to ilość zaraportowanych przypadków: 1 775 089),
- brak jest danych z pierwszej połowy 2009 roku,
- wzorzec raportowania danych w drugiej połowie lat 90tych XX w. i w pierwszych latach XXI w. wskazywał skokowy wzrost zachorowań w styczniu. Natomiast od roku 2010 widać, że ilość zaraportowanych przypadków rośnie stopniowo.
Z powyższego wynika, że do opracowania śródrocznego modelu zachorowań na grypę należy użyć danych po roku 2009, gdyż są one dokładniejsze.
Trendy długoterminowe prezentuje wykres rocznej ilości przypadków:
Wydaje się, że do dalszej analizy śródrocznego przebiegu zachorowań warto pobrać w pierwszym podejściu dane od roku 2013, w którym widać istotnie większą ilość (ok 3 mln) niż w latach poprzednich, kiedy roczna ilość przypadków kształtowała sie na pomiędzy 300 tys. a 1.5 mln.
Łącząc dwie powyższe obserwacje (dokładniejszy model raportowania po roku 2009 oraz większą liczbę rocznych zachorowań po roku 2013) dalsza analiza będzie oparta na danych z lat 2010-2019.
Śródroczny model zachorowań na grypę
Normalizacja danych do zakresu 0 - 1 będzie pierwszym krokiem budowy modelu. Normalizacja danych pozwoli przeanalizować przebieg zachorowań w ciągu roku z różnych lat, niezależnie od łącznej liczby przypadków. Dodatkową operacją na danych będzie przenumerowanie miesięcy w ten sposów, aby połączyć połówki lat w jeden sezon. Lipiec jest pierwszym miesiącem sezonu, czerwiec ostatnim. Normalizacja zostanie przeprowadzona na danych w obrębie jednego sezonu.
# Normalizacja danych
library(dplyr)
normalizacja <- function(x) {return ((x - min(x)) / (max(x) - min(x)))}
grypa_calosc_rrmm <- grypa_calosc %>% group_by(rok, msc) %>% summarise(suma_przypadkow = sum(ilosc_przyp))
grypa_calosc_rrmm$nr_miesiaca_sezon <- ifelse(grypa_calosc_rrmm$msc<=6, grypa_calosc_rrmm$msc+6, grypa_calosc_rrmm$msc-6)
grypa_calosc_rrmm <- grypa_calosc_rrmm %>% mutate(etykieta_sezonu =
ifelse(nr_miesiaca_sezon <= 6,
paste0(rok, "/",rok+1),
paste0(rok-1, "/",rok)
))
grypa_calosc_rrmm$msc_nazwa <- month(grypa_calosc_rrmm$msc, label = TRUE)
norm_data <- grypa_calosc_rrmm %>% group_by(etykieta_sezonu) %>% summarise(suma_przypadkow_norm = normalizacja(suma_przypadkow))
grypa_calosc_rrmm$sum_przy_norm <- norm_data$suma_przypadkow_norm
Wybrane dane z lat 2008-2019 pokazują następujący przebieg zachorowalności na grypę w ciągu roku:
Jak widać, śródroczny przebieg grypy w poszczególnych sezonach - jak wspomniano na wstępnie - przypomina prawoskośną krzywą dzwonowatą rozkładu normalnego. Jednak poszczególne lata dość znacząco się od siebie różniły - szczególnie w miesiącach wrzesień - grudzień:
| Miesiąc |
Współczynnik zmienności |
| wrz |
0.38 |
| paź |
0.29 |
| lis |
0.28 |
| gru |
0.27 |
Zaprezentowany współczynnik zmienności to stosunek odchylenia standardowego do średniej. Zachorowania we wrześniu w poszczególnch latach różniły się od swojej średniej 38%. Niemniej ogólny przebieg sezonu grypowego w tych latach wskazuje na występowanie wyraźnego wzorca.
Drugim krokiem będzie dobranie odpowiedniej funkcji i jej parametrów, która jest najlepiej dopasowana do znormalizowanych danych. Na zestawie danych określonym powyżej, został zastosowany algorym Quantile Random Forest (metoda numeryczna), dzięki której po normalizacji wyznaczono typowy przebieg sezonu grypowego. Ilustruje to poniższy wykres:
Z powyższego wykresu widać, że model dość dobrze odzwierciedla przebieg sezonu. W początkowej fazie wartości są niedoszacowane, jednak od miesiąca 6 do 10 znajdują się mniej więcej w środku obserwowanych wartości. Potwierdzają to także podstawowe parametry modelu (należy je czytać w kontekście przytoczonego powyżej współczynnika zmienności):
| mtry |
RMSE |
Rsquared |
MAE |
RMSESD |
RsquaredSD |
MAESD |
| 2 |
0.2598494 |
0.4511912 |
0.1803596 |
0.024928 |
0.0736318 |
0.0155539 |
Wartość Rsquared na poziomie 0.45 oznacza, że model wyjaśnia badane zjawisko w 45%. Wydawałoby się, że jest to słaby wynik. Jednak biorąc pod uwagę współczynnik zmienności kształtujący się pomiędzy 30% a 40% w poszczególnych miesiącach, wartość 45% dla modelu można uznać za satysfakcjonującą.
Prognoza QRF na sezon 2020 / 2021
Ponieważ cel niniejszego opracowania to budowa Śródrocznego modelu zachorowalności na grypę, nie zaś modelu wyjaśniającego czynniki decydujące o zachrowalności, prognoza na sezon 2020/2021 będzie wykonana uproszczonymi metodami. Wyjaśnienie przyczyn zjawiska zachorowalności to osobne zagadnienie. Prezentowane tutaj podejście jest podejściem czysto numerycznym, zatem dane zostaną potraktowane jako zwykłe szeregi czasowe.
Aby móc wykorzystać zbudowany model do prognozy zachrowań na grypę w sezonie 2020/2021 należy najpierw założyć, lub przewidzieć maksymalny poziom zachorowań w danym sezonie (najgorszy miesiąc w sezonie). Jest to potrzebne, by powrócić od danych znormalizowanych (z przedziału 0-1) do danych w skali pierwotnej (rzeczywistej). Dalej są zaprezentowane trzy scenariusze, by wyznaczyć maksymalny poziom zachorowań w sezonie. Podobnie jak w przypadku budowy śródrocznego modelu, prognoza będzie oparta na danych z lat 2010-2019. Do progozowania został użyty pakiet forecast a w jego ramach model ETS (Exponential smoothing state space model). Poniższa tabela prezentuje prognozę maksymalnej rocznej (sezonowej) ilości przypadków wraz z przedziałami ufności:
| |
Point Forecast |
Lo 80 |
Hi 80 |
| 11 |
847383 |
521187.5 |
1173578 |
Prognozowana ilość zachorowań w szczycie sezonu 2020/2021 to 847,3 tys. osób. Z prawdopodobieństwem 80% można oczekiwać, że liczba zachorowań w szczycie, będzie mieścić się w przedziale: 521,2 do 1 173,6 tys. osób. Posługując się tą prognozą oraz modelem wyznaczonym w poprzednim punkcie, mozna wyznaczyć prawdopodobny przebieg sezonu grypowego:
Zgodnie z numerycznym modelem QRF, sezon grypowy 2020/2021 będzie miał swój szczyt w lutym 2021. Łaczna ilość zachorowań według wariantu pośredniego wyniesie 3 588 814.
Szczegółową prognozę w miesiącach prezentuje poniższa tabela:
| Miesiąc |
Dzienne zachorowania, wariant minimalny |
Miesięcznie, wariant minimalny |
Dzienne zachorowania, wariant pośredni |
Miesięcznie, wariant pośredni |
Dzienne zachorowania, wariant maksymalny |
Miesięcznie, wariant maksymalny |
| lip |
1362 |
40854 |
1401 |
42043 |
1441 |
43233 |
| sie |
1303 |
39096 |
1303 |
39096 |
1303 |
39096 |
| wrz |
1726 |
51767 |
2011 |
60340 |
2297 |
68914 |
| paź |
4988 |
149640 |
7481 |
224437 |
9974 |
299235 |
| lis |
7026 |
210780 |
10898 |
326946 |
14770 |
443112 |
| gru |
7508 |
225228 |
11706 |
351170 |
15904 |
477112 |
| sty |
11733 |
352002 |
18791 |
563723 |
25848 |
775443 |
| lut |
17373 |
521187 |
28246 |
847383 |
39119 |
1173578 |
| mar |
14238 |
427146 |
22990 |
689712 |
31743 |
952276 |
| kwi |
6315 |
189457 |
9707 |
291196 |
13098 |
392934 |
| maj |
2104 |
63118 |
2646 |
79372 |
3188 |
95626 |
| cze |
1985 |
59554 |
2447 |
73396 |
2908 |
87238 |
Wnioski dotyczące SARS-CoV-2
Odnosząc powyższe rozważania odnośnie zachorowalności na grypę, na epidemię koronawirusa, należy przytoczyć najważniejsze badania w tym zakresie. Badania te pozwolą oszacować, jaka ilość zachorowań może w rzeczywistości dotyczyć koronawirusa. Warto poznać:
- “Virus–virus interactions impact the population dynamics of influenza and the common cold”, PNAS December 26, 2019 116 (52) 27142-27150; first published December 16, 2019, Sema Nickbakhsh, Colette Mair, Louise Matthews, Richard Reeve, Paul C. D. Johnson, Fiona Thorburn, Beatrix von Wissmann, Arlene Reynolds, James McMenamin, Rory N. Gunson, and Pablo R. Murcia PNAS
- “Epidemiology of Seasonal Coronaviruses: Establishing the Context for the Emergence of Coronavirus Disease 2019”, The Journal of Infectious Diseases, 01 Jun 2020, 222(1):17-25, EUROPE PMC
Najważniejszy wniosek płynący z tych badań to:
udział koronawirusów w corocznych zachorowaniach na grypę wynosi od 7 do 15 procent
Dzięki tym badaniom oraz zbudowanej prognozie, można w prosty sposób wyznaczyć prawodopodobną liczbę zachorowań na koronawirusa zarówno w latach ubiegłych, jak i w sezonie 2020/2021. Przy wszystkich zastrzeżeniach, że obecny szczep koronawirusa jest inny od poprzednich, należy zauważyć, że nawet “sezonowe” koronawirusy różnią się od siebie. Biorąc pod uwagę nowoczesną wiedzę molekularną o wirusach, można z dość dużą pewnością stwierdzić, że koronawirus z początków 2020 roku zdążył w ciągu kilku miesięcy zmutować i już różni się od początkowej swojej wersji.
| Sezon |
Suma zachorowań |
Zachorowania na koronawirusa (15%) |
Zachorowania na koronawirusa (7%) |
| 2010/2011 |
1055300 |
158295 |
738710 |
| 2011/2012 |
1040955 |
156143 |
728668 |
| 2012/2013 |
2959318 |
443898 |
2071523 |
| 2013/2014 |
2724400 |
408660 |
1907080 |
| 2014/2015 |
3786125 |
567919 |
2650288 |
| 2015/2016 |
4050970 |
607646 |
2835679 |
| 2016/2017 |
4803745 |
720562 |
3362622 |
| 2017/2018 |
5431585 |
814738 |
3802109 |
| 2018/2019 |
4635847 |
695377 |
3245093 |
| 2019/2020 |
4103763 |
615564 |
2872634 |
Jak wynika z tej prostej kalkulacji, w sezonie 2019/2020 liczba chorych na koronawirusa wynosła pomiędzy 287,2 tys. a 615,5 tys. co daje średnią dzienną zachorowalność w ciągu sezonu między ok 800 a 1670 przypadków dziennie.
Model zachrowalności na grypę użyty do prognozy ilości przypadków koronawirusa w sezonie 2020/2021 wskazuje na następujący teoretyczny przebieg zachorowań (wg 15% udziału w infekcjach):
Według modelu pośredniego, we wrześniu powinno być wykryte 51,8 tys. przypadków grypy. w tym 8,8 tys. przypadków koronawirusa. Jak wynika z danych PZH we wrześniu wykryto 217,6 tys. przypadków grypy, w tym 26,1 tys. przypadków koronawirusa:
### Budowa zestawu danych dla sezonu 2020/2021
grypa20 <- data.frame()
for (i in 1:length(lista_plikow)){
text_rep_temp20 <- pdf_text(pdf = paste0("pdf/",lista_plikow[i]))
text_rep_temp20 <- c(unlist(strsplit(text_rep_temp20, "\r\n")))
wanted_lines20 <- c(
grep("Zakażenia SARS-CoV-2",text_rep_temp20)[1]
)
wanted_lines20
wanted20_data_raportu <- pdf_info(pdf = paste0("pdf/",lista_plikow[i]))$keys$Title
wanted20 <- text_rep_temp20[get("wanted_lines20")]
data_raportu20 <- str_extract(wanted20_data_raportu, "\\d{2}.\\d{2}\\s\\d{4}|\\d{2}.\\d{2}.\\d{4}")
data_raportu20 <- lubridate::dmy(data_raportu20)
ilosc_przyp20 <- as.numeric(gsub("\\s","",(str_extract(wanted20[1], "(\\s\\d+){1,3}"))))
wiersz20 <- data.frame(data_raportu20, ilosc_przyp20)
grypa20 <- rbind(grypa20, wiersz20)
}
grypa20 <- grypa20[complete.cases(grypa20),]
# obliczenie ilości nowych przypadków (covida, dane od lipca)
nowe_pryp_20 <- diff(grypa20$ilosc_przyp20)
nowe_pryp_20 <- c(grypa20[1,2],nowe_pryp_20)
grypa20 <- cbind(grypa20, nowe_pryp_20)
grypa20 <- subset(grypa20, grypa20$data_raportu20 > "2020-06-30")
grypa20$msc <- month(grypa20$data_raportu20)
grypa20 <- grypa20 %>% group_by(msc) %>% summarise(suma_covid = sum(nowe_pryp_20))
gry2021 <- subset(grypa_calosc_rrmm, grypa_calosc_rrmm$etykieta_sezonu=="2020/2021"&grypa_calosc_rrmm$msc>6)
gry2021 <- gry2021[,c(1:6)]
gry2021 <- cbind(gry2021, grypa20$suma_covid)
gry2021$suma_przypadkow_z_cov <- gry2021$suma_przypadkow + gry2021$...7
| Miesiąc |
Suma przypadków |
Grypa: pozostałe szczepy |
Grypa: koronawirus |
| lip |
51331 |
39096 |
12235 |
| sie |
92087 |
70564 |
21523 |
| wrz |
217602 |
191476 |
26126 |
Udział koronawirusa w łącznej liczbie przypadków wynosi 12% i jest zgodny z obserwacjami i badaniami przytoczonymi powyżej: “Virus–virus interactions impact the population…” oraz “Epidemiology of Seasonal Coronaviruses: …”.
Rozwój zachorowań na grypę w sezonie 2020/2021 w porównaniu do modelu i ostatnich 5 lat wygląda na wykresie następująco:
Na powyższym wykresie wyraźnie widać dwie rzeczy:
- model teoretyczny zedycowanie niedoszacowuje rozwój zachorowań w początkowych miesiącach sezonu,
- sezon grypowy 2020/2021 jest zdecydowanie łagodniejszy niż sezony 2017/2018, 2018/2019, 2019/2020.
Na koniec niniejszego opracowania przytoczę jeszcze ostatni wykres, podobny jak poprzedni, tyle, że zawierający dane odnośnie zachorowań na grypę spowodowanych koronawirusem:
Dane historyczne odnośnie zachorowań są obliczone przy założeniu 15% udziału tego szczepu wirusa w ogólnych zachorowaniach. Sezon 2020/2021 jest nie tylko łagodniejszy (udział koronawirusa wynosi 12%) ale i ogólna liczba zachorowań jest znacząco mniejsza niż w latach ubiegłych.
LS0tDQp0aXRsZTogIsWacsOzZHJvY3pueSBtb2RlbCB6YXBhZGFsbm/Fm2NpIG5hIGdyeXDEmSINCmF1dGhvcjogIkJhcnRlayBCaWVsc2tpIg0KZGF0ZTogJzIwMjAtMTAtMDYnDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyMgQ2VsIG9wcmFjb3dhbmlhDQoNCk5hIG1vbWVudCBwaXNhbmlhIG5pbmllanN6ZWdvIG9wcmFjb3dhbmlhIG9kIHBvbmFkIHN6ZXNjaXUgbWllc2llY3kgdHJ3YSAgZXBpZGVtaWEga29yb25hd2lydXNhLiBVIGplaiBwb2N6xIV0a8OzdywgZHppZW5uYSBsaWN6YmEgemFjaG9yb3dhxYQga3N6dGHFgnRvd2FsYSBzacSZIG5hIHBvemlvbWllIG9rIDIwMC00MDAgcHJ6eXBhZGvDs3cgZHppZW5uaWUuIFcgbWlhcsSZIHpibGnFvGFuaWEgc2nEmSBkbyBtaWVzacSZY3kgamVzaWVubnljaCwgbGljemJhIHRhIHphY3rEmcWCYSByb3NuxIXEhyBkbyBwb25hZCAzMDAwIHR5c2llY3kgcHJ6eXBhZGvDs3cgZHppZW5uaWUuIFdpxJlrc3pvxZvEhyBwYcWEc3R3LCB3IHR5bSBQb2xza2EsIHBvZGrEmcWCbyBzemVyZWcgZHJhc3R5Y3pueWNoIMWbcm9ka8OzdywgYnkgb2dyYW5pY3p5xIcgcm96bWlhcnkgZXBpZGVtaWkga29yb25hd2lydXNhLg0KDQpKZWRuYWsgbmF3ZXQgb2ZpY2phbG5lIGRhbmUgbyB6ZHJvd2l1IHB1YmxpY3pueW0sIGEgdGFrxbxlIGJhZGFuaWEgbmF1a293ZSBuYWQgd2lydXNhbWkgZ3J5cHkgc2vFgmFuaWFqxIUgZG8gemFkYW5pYSBkd8OzY2ggcG9kc3Rhd293eWNoIHB5dGHFhDoNCg0KLSBjenkgemphd2lza28gemFjaG9yb3dhxYQgbmEgU0FSUy1Db1YtMiBtb8W8bmEgdyBvZ8OzbGUgemFrbGFzeWZpa293YWMgamFrbyBlcGlkZW1pxJk/DQotIGplc2xpIG5pZSwgdG8gY3p5IG9iZWNuZSB6YWNob3Jvd2FuaWEgbmllIHPEhSBzdGHFgnltIHpqYXdpc2tpZW0sIG5pZSBkaWFnbm96b3dhbnltIHdjemXFm25pZWouDQoNCkFieSBzcHLDs2Jvd2HEhyBvZHBvd2llZHppZcSHIG5hIHRlIHB5dGFuaWEgKHogcG9taW5pxJljaWVtIGt3ZXN0aWksIGpha2EgamVzdCBkZWZpbmljamEgZXBpZGVtaWkgd2cgV0hPIC0gaSBjenkgdyBvZ8OzbGUgaXN0ZW5pZWplIHRha293YSkgd2FydG86DQoNCi0gemJhZGHEhyB0eXBvd8SFIGtyenl3xIUgcHJ6ZWJpZWd1IHphY2hvcm93YcWEIG5hIGdyeXDEmSB3IGNpxIVndSByb2t1LCANCi0gbmEgdGVqIHBvZHN0YXdpZSB6YnVkb3dhxIcgbW9kZWwgxZtyw7Nkcm9jem55Y2ggemFjaG9yb3dhxYQgbmEgZ3J5cMSZIG9yYXogDQotIHBvcsOzd25hxIcgZGFuZSBvIG9iZWNueWNoIHphY2hvcm93YW5pYWNoIG5hIGtvcm9uYXdpcnVzYSB6IGRhbnltaSBoaXN0b3J5Y3pueW1pIGkgeiBtb2RlbGVtLg0KDQpEbGEgemFpbnRlcmVzb3dhbnljaCBwcnplxZtsZWR6ZW5pZW0gcG9uacW8c3p5Y2ggcm96d2HFvGHFhCwgdWRvc3TEmXBuaWFtIGtvZCB3IGrEmXp5a3UgUiBzxYJ1xbzEhWN5IGRvIHBvYnJhbmlhIGRhbnljaCwgaWNoIHByemV0d29yemVuaWEgaSB6YXByZXplbnRvd2FuaWEuDQoNCiMjIyDFuXLDs2TFgmEgZGFueWNoDQoNCkJhZGFuaWUgdHlwb3dlaiBrcnp5d2VqIHByemViaWVndSB6YWNob3Jvd2HFhCBuYSBncnlwxJkgdyBjacSFZ3Ugcm9rdSB6b3N0YW5pZSBwcnplcHJvd2Fkem9uZSBuYSBwb2RzdGF3aWUgZGFueWNoIFBhxYRzdHdvd2VnbyBaYWvFgmFkdSBIaWdpZW55IE5hcm9kb3dlZ28gSW5zdHl0dXR1IFpkcm93aWEgUHVibGljem5lZ28uIERhbmUgdGUgdWRvc3TEmXBuaW9uZSBzxIUgdyBmb3JtaWUgZHd1dHlnb2RuaW93eWNoIHJhcG9ydMOzdyB3IGZvcm1hY2llIFBERiBuYSBwb3ByemVkbmllaiB3ZXJzamkgc3Ryb255IHRlaiBpbnN0eXR1Y2ppLiBXIDIwMjAgcm9rdSBOSVpQIHJvenBvY3rEhcWCIHVkb3N0xJlwbmlhbmllIGRhbnljaCBwb3ByemV6IHNlcndpc3kgRXBpQmF6YSBpIFByb2ZpQmF6YSAodyB0cmFrY2llIHJvendvanUpLCBsZWN6IGRhbmUgdGUgc8SFIHphZ3JlZ293YW5lIGkgbmllIG9iZWptdWrEhSBva3Jlc8OzdyDFm3LDs2Ryb2N6bnljaC4gU3TEhWQgYWJ5IHVzdGFsacSHIMWbcsOzZHJvY3pueSBwcnplYmllZyB6YXBhZGFsbm/Fm2NpIG5hIHd5YnJhbmUgY2hvcm9ieSB6YWthxbpuZSB3IFBvbHNjZSwgdHJ6ZWJhIHNpxJlnbsSFxIcgZG8gcG9wcnplZG5pZWogd2Vyc2ppIHN0cm9ueS4gRGFuZSBkbyBuaW5pZWpzemVnbyBvcHJhY293YW5pYSB6b3N0YcWCeSBwb2JyYW5lIHplIHN0cm9ueToNCmh0dHA6Ly93d3dvbGQucHpoLmdvdi5wbC9vbGRwYWdlL2VwaW1lbGQvaW5kZXhfcC5odG1sDQoNClplc3RhdyBkYW55Y2ggem9zdGFuaWUgcHJ6eWdvdG93YW55IHcgZHfDs2NoIGtyb2thY2g6DQoNCmEuIGRhbmUgem9zdGFuxIUgcG9icmFuZSB3IGZvcm1pZSBwbGlrw7N3IFBERiANCmIuIHogcG9icmFueWNoIGFyY2hpd8OzdyB6b3N0YW7EhSB3eW9kcsSZYm5pb25lIGRhbmUgZG90eWN6xIVjZSBwb3N6Y3plZ8OzbG55Y2ggY2hvcsOzYi4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9VFJVRX0NCiMgV3ltYWdhbmUgYmlibGlvdGVraQ0KbGlicmFyeShydmVzdCkNCmxpYnJhcnkoZHBseXIpDQoNCiMgUG9icmFuaWUgY2HFgmVnbyBhcmNoaXd1bSBtZWxkdW5rw7N3IG8gemFjaG9yb3dhbmlhY2ggbmEgY2hvcm9ieSB6YWthxbpuZSwgemFrYcW8ZW5pYWNoIGkgemF0cnVjaWFjaCB3IFBvbHNjZSAoZHd1dHlnb2RuaW93ZSwga3dhcnRhbG5lLCBww7PFgnJvY3puZSwgcm9jem5lKQ0KdXJsIDwtICJodHRwOi8vd3d3b2xkLnB6aC5nb3YucGwvb2xkcGFnZS9lcGltZWxkL2luZGV4X3AuaHRtbCINCnB6aG9sZHdwIDwtIHJlYWRfaHRtbCh1cmwpDQpsaW5rcyA8LSBwemhvbGR3cCAlPiUgaHRtbF9ub2RlcygiYSIpICU+JSBodG1sX2F0dHIoImhyZWYiKQ0KbGlua3MgPC0gZ3JlcCgiaW5kZXhfbXAuaHRtbCQiLCBsaW5rcywgdmFsdWUgPSBUUlVFKQ0KbGlua3MgPC0gcGFzdGUwKCJodHRwOi8vd3d3b2xkLnB6aC5nb3YucGwvb2xkcGFnZS9lcGltZWxkLyIsbGlua3MpDQp5cnMgPC0gYXMuZGF0YS5mcmFtZShzdHJpbmdyOjpzdHJfZXh0cmFjdChsaW5rcywgIlxcZHs0fSIpKQ0KbDJwIDwtIGRhdGEuZnJhbWUoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKHlyc1ssMV0pKXsNCnVybDIgPC0gbGlua3NbaV0NCnB6aFlSIDwtIHJlYWRfaHRtbCh1cmwyKQ0KbGlua3MycGRmIDwtIHB6aFlSICU+JSBodG1sX25vZGVzKCJhIikgJT4lIGh0bWxfYXR0cigiaHJlZiIpDQpsaW5rczJwZGYgPC0gZ3JlcCgicGRmJCIsIGxpbmtzMnBkZiwgdmFsdWUgPSBUUlVFKQ0KbGlua3MycGRmIDwtIGFzLmRhdGEuZnJhbWUocGFzdGUwKCJodHRwOi8vd3d3b2xkLnB6aC5nb3YucGwvb2xkcGFnZS9lcGltZWxkLyIseXJzW2ksXSwiLyIsbGlua3MycGRmKSkNCmwycCA8LSByYmluZChsMnAsIGxpbmtzMnBkZikNCn0NCmRpci5jcmVhdGUoInBkZiIpDQpwdGggPC0gcGFzdGUwKGdldHdkKCksIi9wZGYvIikNCmZvciAoaSBpbiAxOmxlbmd0aChsMnBbLDFdKSl7DQpmbmFtZSA8LSBzdHJpbmdyOjpzdHJfc3ViKGwycFtpLF0sIC0xNSwgLTEpDQpmbmFtZSA8LSBzdHJpbmdyOjpzdHJfcmVtb3ZlKGZuYW1lLCAiWy8vXSIpDQpodHRyOjpHRVQobDJwW2ksXSwgaHR0cjo6YXV0aGVudGljYXRlKCI6IiwgIjoiLCB0eXBlPSJudGxtIiksDQogICAgICAgICAgaHR0cjo6d3JpdGVfZGlzayhwYXN0ZTAocHRoLGZuYW1lKSwgb3ZlcndyaXRlID0gRkFMU0UpLA0KICAgICAgICAgIGh0dHI6OnByb2dyZXNzKCkNCiAgICAgICAgICApDQp9DQpgYGANCk5hIG1vbWVudCBzcG9yesSFZHphbmlhIHRlZ28gcmFwb3J0dSwgbmEgc3Ryb25hY2ggUFpIIHpuYWpkdWplIHNpxJkgKio2MzcqKiBtZWxkdW5rw7N3IG8gemFjaG9yb3dhbmlhY2ggbmEgY2hvcm9ieSB6YWthxbpuZSwgemFrYcW8ZW5pYWNoIGkgemF0cnVjaWFjaCB3IFBvbHNjZSAoZHd1dHlnb2RuaW93ZSwga3dhcnRhbG5lLCBww7PFgnJvY3puZSwgcm9jem5lKS4gWmVzdGF3IGRhbnljaCBixJlkemllIG9wYXJ0eSBvIHJhcG9ydHkgZHd1dHlnb2RuaW93ZSwgYnkgZG9rxYJhZG5pZWogemFtb2RlbG93YcSHIHRyZW5kIMWbcsOzZHJvY3pueS4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9VFJVRX0NCiMgIlNjcmFwcGluZyIgcGxpa8OzdyBwZGYNCmxpYnJhcnkocGRmdG9vbHMpDQpsaWJyYXJ5KHN0cmluZ3IpDQojIGxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShwbG90bHkpDQoNCmxpc3RhX3BsaWtvdyA8LSBsaXN0LmZpbGVzKHBhdGggPSAicGRmLyIpDQpncnlwYSA8LSBkYXRhLmZyYW1lKCkNCg0KZm9yIChpIGluIDE6bGVuZ3RoKGxpc3RhX3BsaWtvdykpew0KdGV4dF9yZXBfdGVtcCA8LSBwZGZfdGV4dChwZGYgPSBwYXN0ZTAoInBkZi8iLGxpc3RhX3BsaWtvd1tpXSkpDQp0ZXh0X3JlcF90ZW1wIDwtIGModW5saXN0KHN0cnNwbGl0KHRleHRfcmVwX3RlbXAsICJcclxuIikpKQ0KIyB3cml0ZSh0ZXh0X3JlcF90ZW1wLCBmaWxlID0gInRlc3QudHh0IikNCndhbnRlZF9saW5lcyA8LSBjKGdyZXAoIkdyeXBhIix0ZXh0X3JlcF90ZW1wKVsxXSwNCiAgICAgICAgICAgICAgICAgIGdyZXAoInpnxYJvc3pvbnljaCB3IG9rcmVzaWUgb2QgfG8gemfFgm9zem9ueWNoIHphY2hvcm93YW5pYWNoIHphIG9rcmVzIG9kIix0ZXh0X3JlcF90ZW1wKVsxXQ0KICAgICAgICAgICAgICAgICAgKQ0Kd2FudGVkIDwtIHRleHRfcmVwX3RlbXBbZ2V0KCJ3YW50ZWRfbGluZXMiKV0NCmRhdGFfcmFwb3J0dSA8LSBzdHJfZXh0cmFjdCh3YW50ZWRbMl0sICJcXGR7Mn0uXFxkezJ9LlxcZHs0fSIpDQpkYXRhX3JhcG9ydHUgPC0gbHVicmlkYXRlOjpkbXkoZGF0YV9yYXBvcnR1KQ0Kd2FudGVkWzFdDQppbG9zY19wcnp5cCA8LSBhcy5udW1lcmljKHN0cl9leHRyYWN0KHdhbnRlZFsxXSwgIlxcc1xcZCsiKSkNCndpZXJzeiA8LSBkYXRhLmZyYW1lKGRhdGFfcmFwb3J0dSwgaWxvc2NfcHJ6eXApIA0KZ3J5cGEgPC0gcmJpbmQoZ3J5cGEsIHdpZXJzeikNCn0NCg0KZ3J5cGEgPC0gZ3J5cGFbY29tcGxldGUuY2FzZXMoZ3J5cGEpLF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgRGFuZSBwbyAyMDA4IC0gem1pYW5hIGZvcm1hdHUgcmFwb3J0dSAoZGF0YSBqZXN0IHdlIHfFgmHFm2Npd2/Fm2NpYWNoIHBsaWt1LCBkYW5lIG8gemFjaG9yb3dhbmlhbiBzxIUgcHJlemVudG93YW5lIG5hcmFzdGFqxIVjbykNCg0KZ3J5cGEwOCA8LSBkYXRhLmZyYW1lKCkNCmZvciAoaSBpbiAxOmxlbmd0aChsaXN0YV9wbGlrb3cpKXsNCnRleHRfcmVwX3RlbXAwOCA8LSBwZGZfdGV4dChwZGYgPSBwYXN0ZTAoInBkZi8iLGxpc3RhX3BsaWtvd1tpXSkpDQp0ZXh0X3JlcF90ZW1wMDggPC0gYyh1bmxpc3Qoc3Ryc3BsaXQodGV4dF9yZXBfdGVtcDA4LCAiXHJcbiIpKSkNCndhbnRlZF9saW5lczA4IDwtIGMoZ3JlcCgiR3J5cGEgaSBwb2RlanJ6ZW5pYSIsdGV4dF9yZXBfdGVtcDA4KVsxXQ0KICAgICAgICAgICAgICAgICAgKQ0Kd2FudGVkMDhfZGF0YV9yYXBvcnR1IDwtIHBkZl9pbmZvKHBkZiA9IHBhc3RlMCgicGRmLyIsbGlzdGFfcGxpa293W2ldKSkka2V5cyRUaXRsZQ0Kd2FudGVkMDggPC0gdGV4dF9yZXBfdGVtcDA4W2dldCgid2FudGVkX2xpbmVzMDgiKV0NCmRhdGFfcmFwb3J0dTA4IDwtIHN0cl9leHRyYWN0KHdhbnRlZDA4X2RhdGFfcmFwb3J0dSwgIlxcZHsyfS5cXGR7Mn1cXHNcXGR7NH18XFxkezJ9LlxcZHsyfS5cXGR7NH0iKQ0KZGF0YV9yYXBvcnR1MDggPC0gbHVicmlkYXRlOjpkbXkoZGF0YV9yYXBvcnR1MDgpDQppbG9zY19wcnp5cDA4IDwtIGFzLm51bWVyaWMoZ3N1YigiXFxzIiwiIiwoc3RyX2V4dHJhY3Qod2FudGVkMDhbMV0sICIoXFxzXFxkKyl7MSwzfSIpKSkpDQp3aWVyc3owOCA8LSBkYXRhLmZyYW1lKGRhdGFfcmFwb3J0dTA4LCBpbG9zY19wcnp5cDA4KSANCmdyeXBhMDggPC0gcmJpbmQoZ3J5cGEwOCwgd2llcnN6MDgpDQp9DQpncnlwYTA4IDwtIGdyeXBhMDhbY29tcGxldGUuY2FzZXMoZ3J5cGEwOCksXQ0KDQojIG9ibGljemVuaWUgaWxvxZtjaSBub3d5Y2ggcHJ6eXBhZGvDs3cgKHV3YWdhIG5hIGRhbmUgeiBrb8WEY2Egcm9rdSkNCm5vd2VfcHJ5cF8wOCA8LSBkaWZmKGdyeXBhMDgkaWxvc2NfcHJ6eXAwOCkgDQpub3dlX3ByeXBfMDggPC0gYyhncnlwYTA4WzEsMl0sbm93ZV9wcnlwXzA4KQ0KZ3J5cGEwOCA8LSBjYmluZChncnlwYTA4LCBub3dlX3ByeXBfMDgpDQoNCiNwb3ByYXdhIGRhbnljaCB6IGtvxYRjYSByb2t1IGkgcGllcndzemVnbyByYXBvcnR1IHogcG9jesSFdGt1IG5vd2VnbyByb2t1DQp0ZW1wX2RzIDwtIHN1YnNldChncnlwYTA4LCBub3dlX3ByeXBfMDggPDApDQp0ZW1wX2RzJG5vd2VfcHJ5cF8wOCA8LSB0ZW1wX2RzJGlsb3NjX3ByenlwMDgNCmdyeXBhMDhhIDwtIHN1YnNldChncnlwYTA4LCBub3dlX3ByeXBfMDggPiAwKQ0KZ3J5cGEwOGEgPC0gcmJpbmQoZ3J5cGEwOGEsIHRlbXBfZHMpDQpncnlwYTA4YSA8LSBncnlwYTA4YVtvcmRlcihncnlwYTA4YSRkYXRhX3JhcG9ydHUwOCksXQ0KZ3J5cGEwOGEgPC0gZ3J5cGEwOGFbLGMoMSwzKV0NCg0KDQojIFBvxYLEhWN6ZW5pZSBkYW55Y2ggZG8gMjAwOCBpIHBvLCB3IGNhxYJvxZvEhw0KY24gPC0gY29sbmFtZXMoZ3J5cGEpDQpjb2xuYW1lcyhncnlwYTA4YSkgPC0gY24NCmdyeXBhX2NhbG9zYyA8LSByYmluZChncnlwYSwgZ3J5cGEwOGEpDQpncnlwYV9jYWxvc2MgPC0gZ3J5cGFfY2Fsb3NjW29yZGVyKGdyeXBhX2NhbG9zYyRkYXRhX3JhcG9ydHUpLF0NCmBgYA0KDQpQbyB6ZWJyYW51IGRhbnljaCB6IHBsaWvDs3cgcGRmIHBvYnJhbnljaCB6ZSBzdHJvbiBQWkgsIHpvc3RhxYIgdXR3b3J6b255IHplc3RhdyBkYW55Y2ggemF3aWVyYWrEhWN5IGlsb8WbxIcgcHJ6eXBhZGvDs3cgemFjaG9yb3dhxYQgbmEgZ3J5cMSZIHcgaW50ZXJ3YcWCYWNoIGR3dXR5Z29kbmlvd3ljaC4gRGFuZSB6YXdpZXJhasSFIDU4MCBvYnNlcndhY2ppIHphIG9rcmVzIG9kIDE5OTYtMDEtMDEgZG8gMjAyMC0wOS0zMC4NCg0KIyMjIEFuYWxpemEgcm96cG96bmF3Y3phDQoNClBpZXJ3c3plIHNwb2pyemVuaWUgbmEgZGFuZSB3eW9kcsSZYm5pb25lIHogcGxpa8OzdyBwZGY6DQpgYGB7ciBaYWNoLTJ3ZWVrcywgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9RkFMU0V9DQpsaWJyYXJ5KHBsb3RseSkNCnd5ayA8LSBwbG90X2x5KGRhdGE9Z3J5cGFfY2Fsb3NjLCB4ID0gfmRhdGFfcmFwb3J0dSAsIHkgPSB+aWxvc2NfcHJ6eXAsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnKQ0Kd3lrIDwtIHd5ayAlPiUgbGF5b3V0KHRpdGxlID0gIlphY2hvcm93YW5pYSBuYSBncnlwxJkgdyBsYXRhY2ggMTk5Ni0yMDIwIChkYW5lIGR3dXR5Z29kbmlvd2UpIiwNCiAgICAgICAgICAgICAgICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiUm9rIiksIHlheGlzID0gbGlzdCh0aXRsZSA9ICJJbG/Fm8SHIHphY2hvcm93YcWEIikNCiAgICAgICAgICAgICAgICAgICAgICApDQp3eWsNCmBgYA0KDQpTZXpvbm93b8WbxIcgZGFqxIVjYSBzacSZIHphb2JzZXJ3b3dhxIcgamVzdCBvY3p5d2lzdGEuIE5pZW1uaWVqIG9kbm/Fm25pZSBzYW1lZ28gemVzdGF3dSBkYW55Y2gsIHRyemViYSB6YXV3YcW8ecSHOg0KDQphLiBkYW5lIHplIHN0eWN6bmlhIDE5OTYgcm9rdSB6YXdpZXJhasSFIG5hanByYXdkb3BvZG9uaWVqIG5hcmFzdGFqxIVjZSBkYW5lIHogMTk5NSByb2t1ICh3c2thenVqZSBuYSB0byBpbG/Fm8SHIHphcmFwb3J0b3dhbnljaCBwcnp5cGFka8OzdzogMSA3NzUgMDg5KSwNCmIuIGJyYWsgamVzdCBkYW55Y2ggeiBwaWVyd3N6ZWogcG/Fgm93eSAyMDA5IHJva3UsDQpjLiB3em9yemVjIHJhcG9ydG93YW5pYSBkYW55Y2ggdyBkcnVnaWVqIHBvxYJvd2llIGxhdCA5MHR5Y2ggWFggdy4gaSB3IHBpZXJ3c3p5Y2ggbGF0YWNoIFhYSSB3LiB3c2thenl3YcWCIHNrb2tvd3kgd3pyb3N0IHphY2hvcm93YcWEIHcgc3R5Y3puaXUuIE5hdG9taWFzdCBvZCByb2t1IDIwMTAgd2lkYcSHLCDFvGUgaWxvxZvEhyB6YXJhcG9ydG93YW55Y2ggcHJ6eXBhZGvDs3cgcm/Fm25pZSBzdG9wbmlvd28uDQoNClogcG93ecW8c3plZ28gd3luaWthLCDFvGUgZG8gb3ByYWNvd2FuaWEgxZtyw7Nkcm9jem5lZ28gbW9kZWx1IHphY2hvcm93YcWEIG5hIGdyeXDEmSBuYWxlxbx5IHXFvHnEhyBkYW55Y2ggcG8gcm9rdSAyMDA5LCBnZHnFvCBzxIUgb25lIGRva8WCYWRuaWVqc3plLg0KDQpUcmVuZHkgZMWCdWdvdGVybWlub3dlIHByZXplbnR1amUgd3lrcmVzIHJvY3puZWogaWxvxZtjaSBwcnp5cGFka8OzdzoNCmBgYHtyIFphY2gteWVhcmx5LCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZT1GQUxTRX0NCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShkcGx5cikNCmdyeXBhX2NhbG9zYyRyb2sgPC0geWVhcihncnlwYV9jYWxvc2MkZGF0YV9yYXBvcnR1KQ0KZ3J5cGFfY2Fsb3NjX3JvY3puaWUgPC0gZ3J5cGFfY2Fsb3NjICU+JSBncm91cF9ieShyb2spICU+JSBzdW1tYXJpc2Uoc3VtYV9wcnp5cGFka293ID0gc3VtKGlsb3NjX3ByenlwKSkNCmdyeXBhX2NhbG9zYyRtc2MgPC0gbW9udGgoZ3J5cGFfY2Fsb3NjJGRhdGFfcmFwb3J0dSkgDQp3eWsyIDwtIHBsb3RfbHkoZGF0YT1ncnlwYV9jYWxvc2Nfcm9jem5pZSwgeCA9IH5yb2sgLCB5ID0gfnN1bWFfcHJ6eXBhZGtvdywgdHlwZSA9ICdiYXInKQ0Kd3lrMiA8LSB3eWsyICU+JSBsYXlvdXQodGl0bGUgPSAiWmFjaG9yb3dhbmlhIG5hIGdyeXDEmSB3IGxhdGFjaCAxOTk2LTIwMjAgKHBvZHN1bW93YW5pZSByb2N6bmUpIiwNCiAgICAgICAgICAgICAgICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiUm9rIiksIHlheGlzID0gbGlzdCh0aXRsZSA9ICJJbG/Fm8SHIHphY2hvcm93YcWEIikNCiAgICAgICAgICAgICAgICAgICAgICApDQp3eWsyDQpgYGANCg0KV3lkYWplIHNpxJksIMW8ZSBkbyBkYWxzemVqIGFuYWxpenkgxZtyw7Nkcm9jem5lZ28gcHJ6ZWJpZWd1IHphY2hvcm93YcWEIHdhcnRvIHBvYnJhxIcgdyBwaWVyd3N6eW0gcG9kZWrFm2NpdSBkYW5lIG9kIHJva3UgMjAxMywgdyBrdMOzcnltIHdpZGHEhyBpc3RvdG5pZSB3acSZa3N6xIUgaWxvxZvEhyAob2sgMyBtbG4pIG5pxbwgdyBsYXRhY2ggcG9wcnplZG5pY2gsIGtpZWR5IHJvY3puYSBpbG/Fm8SHIHByenlwYWRrw7N3IGtzenRhxYJ0b3dhxYJhIHNpZSBuYSBwb21pxJlkenkgMzAwIHR5cy4gYSAxLjUgbWxuLiANCg0KxYHEhWN6xIVjIGR3aWUgcG93ecW8c3plIG9ic2Vyd2FjamUgKGRva8WCYWRuaWVqc3p5IG1vZGVsIHJhcG9ydG93YW5pYSBwbyByb2t1IDIwMDkgb3JheiB3acSZa3N6xIUgbGljemLEmSByb2N6bnljaCB6YWNob3Jvd2HFhCBwbyByb2t1IDIwMTMpIGRhbHN6YSBhbmFsaXphIGLEmWR6aWUgb3BhcnRhIG5hIGRhbnljaCB6IGxhdCAyMDEwLTIwMTkuDQoNCiMjIyDFmnLDs2Ryb2N6bnkgbW9kZWwgemFjaG9yb3dhxYQgbmEgZ3J5cMSZDQoNCk5vcm1hbGl6YWNqYSBkYW55Y2ggZG8gemFrcmVzdSAwIC0gMSBixJlkemllICoqcGllcndzenltKioga3Jva2llbSBidWRvd3kgbW9kZWx1LiBOb3JtYWxpemFjamEgZGFueWNoIHBvendvbGkgcHJ6ZWFuYWxpem93YcSHIHByemViaWVnIHphY2hvcm93YcWEIHcgY2nEhWd1IHJva3UgeiByw7PFvG55Y2ggbGF0LCBuaWV6YWxlxbxuaWUgb2QgxYLEhWN6bmVqICBsaWN6YnkgcHJ6eXBhZGvDs3cuIA0KRG9kYXRrb3fEhSBvcGVyYWNqxIUgbmEgZGFueWNoIGLEmWR6aWUgcHJ6ZW51bWVyb3dhbmllIG1pZXNpxJljeSB3IHRlbiBzcG9zw7N3LCBhYnkgcG/FgsSFY3p5xIcgcG/FgsOzd2tpIGxhdCB3IGplZGVuIHNlem9uLiBMaXBpZWMgamVzdCBwaWVyd3N6eW0gbWllc2nEhWNlbSBzZXpvbnUsIGN6ZXJ3aWVjIG9zdGF0bmltLiBOb3JtYWxpemFjamEgem9zdGFuaWUgcHJ6ZXByb3dhZHpvbmEgbmEgZGFueWNoIHcgb2JyxJliaWUgamVkbmVnbyBzZXpvbnUuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUV9DQojIE5vcm1hbGl6YWNqYSBkYW55Y2gNCg0KbGlicmFyeShkcGx5cikNCm5vcm1hbGl6YWNqYSA8LSBmdW5jdGlvbih4KSB7cmV0dXJuICgoeCAtIG1pbih4KSkgLyAobWF4KHgpIC0gbWluKHgpKSl9DQpncnlwYV9jYWxvc2NfcnJtbSA8LSBncnlwYV9jYWxvc2MgJT4lIGdyb3VwX2J5KHJvaywgbXNjKSAlPiUgc3VtbWFyaXNlKHN1bWFfcHJ6eXBhZGtvdyA9IHN1bShpbG9zY19wcnp5cCkpDQpncnlwYV9jYWxvc2NfcnJtbSRucl9taWVzaWFjYV9zZXpvbiA8LSBpZmVsc2UoZ3J5cGFfY2Fsb3NjX3JybW0kbXNjPD02LCBncnlwYV9jYWxvc2NfcnJtbSRtc2MrNiwgZ3J5cGFfY2Fsb3NjX3JybW0kbXNjLTYpDQpncnlwYV9jYWxvc2NfcnJtbSA8LSBncnlwYV9jYWxvc2NfcnJtbSAlPiUgbXV0YXRlKGV0eWtpZXRhX3Nlem9udSA9IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShucl9taWVzaWFjYV9zZXpvbiA8PSA2LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHJvaywgIi8iLHJvaysxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHJvay0xLCAiLyIscm9rKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKQ0KZ3J5cGFfY2Fsb3NjX3JybW0kbXNjX25hendhIDwtIG1vbnRoKGdyeXBhX2NhbG9zY19ycm1tJG1zYywgbGFiZWwgPSBUUlVFKQ0KDQpub3JtX2RhdGEgPC0gZ3J5cGFfY2Fsb3NjX3JybW0gJT4lIGdyb3VwX2J5KGV0eWtpZXRhX3Nlem9udSkgJT4lIHN1bW1hcmlzZShzdW1hX3ByenlwYWRrb3dfbm9ybSA9IG5vcm1hbGl6YWNqYShzdW1hX3ByenlwYWRrb3cpKQ0KDQpncnlwYV9jYWxvc2NfcnJtbSRzdW1fcHJ6eV9ub3JtIDwtIG5vcm1fZGF0YSRzdW1hX3ByenlwYWRrb3dfbm9ybQ0KDQpgYGANCg0KV3licmFuZSBkYW5lIHogbGF0IDIwMDgtMjAxOSBwb2thenVqxIUgbmFzdMSZcHVqxIVjeSBwcnplYmllZyB6YWNob3Jvd2Fsbm/Fm2NpIG5hIGdyeXDEmSB3IGNpxIVndSByb2t1Og0KYGBge3IgIHllYXJseV9ydW4sIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPUZBTFNFLCByZXN1bHRzID0gJ2hpZGUnfQ0Kd3lrMyA8LSBwbG90X2x5KGRhdGEgPSBzdWJzZXQoZ3J5cGFfY2Fsb3NjX3JybW0sZ3J5cGFfY2Fsb3NjX3JybW0kZXR5a2lldGFfc2V6b251ICVpbiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIjIwMTAvMjAxMSIsICIyMDExLzIwMTIiLCIyMDEyLzIwMTMiLCAiMjAxMy8yMDE0IiwgIjIwMTQvMjAxNSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTUvMjAxNiIsIjIwMTYvMjAxNyIsIjIwMTcvMjAxOCIsIjIwMTgvMjAxOSIsIjIwMTkvMjAyMCIpKVssYyg0OjcpXSwgDQogICAgICAgICAgICAgICAgeCA9IH5ucl9taWVzaWFjYV9zZXpvbiwNCiAgICAgICAgICAgICAgICB5ID0gfnN1bV9wcnp5X25vcm0sDQogICAgICAgICAgICAgICAgY29sb3IgPSB+ZXR5a2lldGFfc2V6b251LA0KICAgICAgICAgICAgICAgIHRleHQgPSB+bXNjX25hendhLCANCiAgICAgICAgICAgICAgICBob292ZXJpbmZvID0gJ3RleHQnDQogICAgICAgICAgICAgICAgKQ0Kd3lrMyA8LSB3eWszICU+JSAgYWRkX2xpbmVzKCkNCnd5azMgPC0gd3lrMyAlPiUgbGF5b3V0KHRpdGxlID0gIlphY2hvcm93YW5pYSBuYSBncnlwxJkgdyBsYXRhY2ggMjAxMC0yMDIwIChwb2RzdW1vd2FuaWUgc2V6b25vd2UpIiwNCiAgICAgICAgICAgICAgICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiTWllc2nEhWMgc2V6b251IGdyeXBvd2VnbyIpLCB5YXhpcyA9IGxpc3QodGl0bGUgPSAiSWxvxZvEhyB6YWNob3Jvd2HFhCAoem5vcm1hbGl6b3dhbmEpIikNCiAgICAgICAgICAgICAgICAgICAgICApDQp3eWszDQpgYGANCg0KSmFrIHdpZGHEhywgxZtyw7Nkcm9jem55IHByemViaWVnIGdyeXB5IHcgcG9zemN6ZWfDs2xueWNoIHNlem9uYWNoIC0gamFrIHdzcG9tbmlhbm8gbmEgd3N0xJlwbmllIC0gcHJ6eXBvbWluYSBwcmF3b3Nrb8WbbsSFIGtyenl3xIUgZHp3b25vd2F0xIUgcm96a8WCYWR1IG5vcm1hbG5lZ28uIEplZG5hayBwb3N6Y3plZ8OzbG5lIGxhdGEgZG/Fm8SHIHpuYWN6xIVjbyBzacSZIG9kIHNpZWJpZSByw7PFvG5pxYJ5IC0gc3pjemVnw7NsbmllIHcgbWllc2nEhWNhY2ggd3J6ZXNpZcWEIC0gZ3J1ZHppZcWEOiANCg0KYGBge3IgdmksIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHdhcm5pbmdzID0gRkFMU0UsIGNhY2hlPUZBTFNFLCByZXN1bHRzID0gJ2hpZGUnfQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KdmkgPC0gZGF0YS5mcmFtZSgpDQpmb3IgKGkgaW4gKDM6NikpIHsNCm1kcyA8LSBzdWJzZXQoZ3J5cGFfY2Fsb3NjX3JybW0sZ3J5cGFfY2Fsb3NjX3JybW0kZXR5a2lldGFfc2V6b251ICVpbiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIjIwMTAvMjAxMSIsICIyMDExLzIwMTIiLCIyMDEyLzIwMTMiLCAiMjAxMy8yMDE0IiwgIjIwMTQvMjAxNSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTUvMjAxNiIsIjIwMTYvMjAxNyIsIjIwMTcvMjAxOCIsIjIwMTgvMjAxOSIsIjIwMTkvMjAyMCIpICYgZ3J5cGFfY2Fsb3NjX3JybW0kbnJfbWllc2lhY2Ffc2V6b24gPT0gaQ0KICAgICAgICAgICAgICApWyxjKDQ6NyldDQptZHNfdmkgPC0gcm91bmQoc2QobWRzJHN1bV9wcnp5X25vcm0pIC8gbWVhbihtZHMkc3VtX3Byenlfbm9ybSksMikNCm0gPC0gdW5pcXVlKGdyeXBhX2NhbG9zY19ycm1tW2dyeXBhX2NhbG9zY19ycm1tJG5yX21pZXNpYWNhX3Nlem9uID09IGksIDZdKSAgIA0KcnIgPC0gZGF0YS5mcmFtZShtZHNfdmksIG0pDQp2aSA8LSByYmluZCh2aSwgcnIpDQp9DQp2aSA8LSB2aVssYygyLDEpXQ0KY29sbmFtZXModmkpIDwtIGMoIk1pZXNpxIVjIiwgIldzcMOzxYJjenlubmlrIHptaWVubm/Fm2NpIikNCnZpIDwtIHZpICU+JSAgIGtibCgpICU+JQ0KICBrYWJsZV9taW5pbWFsKCJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKQ0KdmkNCmBgYA0KWmFwcmV6ZW50b3dhbnkgd3Nww7PFgmN6eW5uaWsgem1pZW5ub8WbY2kgdG8gc3Rvc3VuZWsgb2RjaHlsZW5pYSBzdGFuZGFyZG93ZWdvIGRvIMWbcmVkbmllai4gWmFjaG9yb3dhbmlhIHdlIHdyemXFm25pdSB3IHBvc3pjemVnw7NsbmNoIGxhdGFjaCByw7PFvG5pxYJ5IHNpxJkgb2Qgc3dvamVqIMWbcmVkbmllaiAzOCUuIE5pZW1uaWVqIG9nw7NsbnkgcHJ6ZWJpZWcgc2V6b251IGdyeXBvd2VnbyB3IHR5Y2ggbGF0YWNoIHdza2F6dWplIG5hIHd5c3TEmXBvd2FuaWUgd3lyYcW6bmVnbyB3em9yY2EuDQoNCioqRHJ1Z2ltKioga3Jva2llbSBixJlkemllIGRvYnJhbmllIG9kcG93aWVkbmllaiBmdW5rY2ppIGkgamVqIHBhcmFtZXRyw7N3LCBrdMOzcmEgamVzdCBuYWpsZXBpZWogZG9wYXNvd2FuYSBkbyB6bm9ybWFsaXpvd2FueWNoIGRhbnljaC4gTmEgemVzdGF3aWUgZGFueWNoIG9rcmXFm2xvbnltIHBvd3nFvGVqLCB6b3N0YcWCIHphc3Rvc293YW55IGFsZ29yeW0gKipRdWFudGlsZSBSYW5kb20gRm9yZXN0KiogKG1ldG9kYSBudW1lcnljem5hKSwgZHppxJlraSBrdMOzcmVqIHBvIG5vcm1hbGl6YWNqaSB3eXpuYWN6b25vIHR5cG93eSBwcnplYmllZyBzZXpvbnUgZ3J5cG93ZWdvLiBbXjFdIElsdXN0cnVqZSB0byBwb25pxbxzenkgd3lrcmVzOg0KDQpgYGB7ciBtb2RlbCwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9RkFMU0UsIHJlc3VsdHMgPSAnaGlkZSd9DQpsaWJyYXJ5KGNhcmV0KQ0Kc2V0LnNlZWQoOTk5KQ0KbTEgPC0gYXMuZGF0YS5mcmFtZSh4ID0gc2VxKDE6MTIpKQ0KY29sbmFtZXMobTEpIDwtIGMoIm5yX21pZXNpYWNhX3Nlem9uIikNCm0xJGV0eWtpZXRhX3Nlem9udSA8LSAibW9kZWwiDQptb2RlbCA8LSB0cmFpbihzdW1fcHJ6eV9ub3Jtfm5yX21pZXNpYWNhX3Nlem9uLCBkYXRhID0gZ3J5cGFfY2Fsb3NjX3JybW0sIG1ldGhvZCA9ICJxcmYiKQ0KDQptMSRzdW1fcHJ6eV9ub3JtIDwtIHByZWRpY3QobW9kZWwsIG5ld2RhdGEgPSBtMSkNCm0xJHN1bV9wcnp5X25vcm0gPC0gbm9ybWFsaXphY2phKG0xJHN1bV9wcnp5X25vcm0pDQoNCnd5azQgPC0gcGxvdF9seShkYXRhID0gc3Vic2V0KGdyeXBhX2NhbG9zY19ycm1tLGdyeXBhX2NhbG9zY19ycm1tJGV0eWtpZXRhX3Nlem9udSAlaW4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCIyMDEwLzIwMTEiLCAiMjAxMS8yMDEyIiwiMjAxMi8yMDEzIiwgIjIwMTMvMjAxNCIsICIyMDE0LzIwMTUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDE1LzIwMTYiLCIyMDE2LzIwMTciLCIyMDE3LzIwMTgiLCIyMDE4LzIwMTkiLCIyMDE5LzIwMjAiKSlbLGMoNDo3KV0sIA0KICAgICAgICAgICAgICAgIHggPSB+bnJfbWllc2lhY2Ffc2V6b24sDQogICAgICAgICAgICAgICAgeSA9IH5zdW1fcHJ6eV9ub3JtLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gfmV0eWtpZXRhX3Nlem9udQ0KICAgICAgICAgICAgICAgICkNCnd5azQgPC0gd3lrNCAlPiUgIGFkZF9saW5lcygpDQp3eWs0IDwtIHd5azQgJT4lIGFkZF90cmFjZShkYXRhID0gbTEseSA9IH5tMSRzdW1fcHJ6eV9ub3JtICwgbmFtZSA9ICdNT0RFTCcsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAncmdiKDIyLCA5NiwgMTY3KScsIHdpZHRoID0gNiwgZGFzaCA9ICdkYXNoJykpDQoNCnd5azQgPC0gd3lrNCAlPiUgbGF5b3V0KHRpdGxlID0gIk1vZGVsIFFSRiB6YWNob3Jvd2HFhCBuYSBncnlwxJkiLA0KICAgICAgICAgICAgICAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJNaWVzacSFYyBzZXpvbnUgZ3J5cG93ZWdvIiksIHlheGlzID0gbGlzdCh0aXRsZSA9ICJJbG/Fm8SHIHphY2hvcm93YcWEICh6bm9ybWFsaXpvd2FuYSkiKQ0KICAgICAgICAgICAgICAgICAgICAgICkNCg0Kd3lrNA0KYGBgDQoNClogcG93ecW8c3plZ28gd3lrcmVzdSB3aWRhxIcsIMW8ZSBtb2RlbCBkb8WbxIcgZG9icnplIG9kendpZXJjaWVkbGEgcHJ6ZWJpZWcgc2V6b251LiBXIHBvY3rEhXRrb3dlaiBmYXppZSB3YXJ0b8WbY2kgc8SFIG5pZWRvc3phY293YW5lLCBqZWRuYWsgb2QgbWllc2nEhWNhIDYgZG8gMTAgem5hamR1asSFIHNpxJkgbW5pZWogd2nEmWNlaiB3IMWbcm9ka3Ugb2JzZXJ3b3dhbnljaCB3YXJ0b8WbY2kuIFBvdHdpZXJkemFqxIUgdG8gdGFrxbxlIHBvZHN0YXdvd2UgcGFyYW1ldHJ5IG1vZGVsdSAobmFsZcW8eSBqZSBjenl0YcSHIHcga29udGVrxZtjaWUgcHJ6eXRvY3pvbmVnbyBwb3d5xbxlaiB3c3DDs8WCY3p5bm5pa2Egem1pZW5ub8WbY2kpOg0KDQpgYGB7ciAgcXJmX21vZGVsLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCB3YXJuaW5ncyA9IEZBTFNFLCBjYWNoZT1GQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30NCmxpYnJhcnkoa2FibGVFeHRyYSkNCm1yIDwtIG1vZGVsJHJlc3VsdHMgJT4lICAga2JsKCkgJT4lDQogIGthYmxlX21pbmltYWwoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQptcg0KYGBgDQoNCldhcnRvxZvEhyBSc3F1YXJlZCBuYSBwb3ppb21pZSAwLjQ1IG96bmFjemEsIMW8ZSBtb2RlbCB3eWphxZtuaWEgYmFkYW5lIHpqYXdpc2tvIHcgNDUlLiBXeWRhd2HFgm9ieSBzacSZLCDFvGUgamVzdCB0byBzxYJhYnkgd3luaWsuIEplZG5hayBiaW9yxIVjIHBvZCB1d2FnxJkgd3Nww7PFgmN6eW5uaWsgem1pZW5ub8WbY2kga3N6dGHFgnR1asSFY3kgc2nEmSBwb21pxJlkenkgMzAlIGEgNDAlIHcgcG9zemN6ZWfDs2xueWNoIG1pZXNpxIVjYWNoLCB3YXJ0b8WbxIcgNDUlIGRsYSBtb2RlbHUgbW/FvG5hIHV6bmHEhyB6YSBzYXR5c2Zha2Nqb251asSFY8SFLg0KDQojIyMgUHJvZ25vemEgUVJGIG5hIHNlem9uIDIwMjAgLyAyMDIxDQoNClBvbmlld2HFvCBjZWwgbmluaWVqc3plZ28gb3ByYWNvd2FuaWEgdG8gYnVkb3dhICoqxZpyw7Nkcm9jem5lZ28gbW9kZWx1IHphY2hvcm93YWxub8WbY2kgbmEgZ3J5cMSZKiosIG5pZSB6YcWbIG1vZGVsdSB3eWphxZtuaWFqxIVjZWdvIGN6eW5uaWtpIGRlY3lkdWrEhWNlIG8gemFjaHJvd2Fsbm/Fm2NpLCBwcm9nbm96YSBuYSBzZXpvbiAyMDIwLzIwMjEgYsSZZHppZSB3eWtvbmFuYSB1cHJvc3pjem9ueW1pIG1ldG9kYW1pLiBXeWphxZtuaWVuaWUgcHJ6eWN6eW4gemphd2lza2EgemFjaG9yb3dhbG5vxZtjaSB0byBvc29ibmUgemFnYWRuaWVuaWUuIFByZXplbnRvd2FuZSB0dXRhaiBwb2RlasWbY2llIGplc3QgcG9kZWrFm2NpZW0gY3p5c3RvICoqbnVtZXJ5Y3pueW0qKiwgemF0ZW0gZGFuZSB6b3N0YW7EhSBwb3RyYWt0b3dhbmUgamFrbyB6d3lrxYJlIHN6ZXJlZ2kgY3phc293ZS4gDQoNCkFieSBtw7NjIHd5a29yenlzdGHEhyB6YnVkb3dhbnkgbW9kZWwgZG8gcHJvZ25venkgemFjaHJvd2HFhCBuYSBncnlwxJkgdyBzZXpvbmllIDIwMjAvMjAyMSBuYWxlxbx5IG5hanBpZXJ3IHphxYJvxbx5xIcsIGx1YiBwcnpld2lkemllxIcgbWFrc3ltYWxueSBwb3ppb20gemFjaG9yb3dhxYQgdyBkYW55bSBzZXpvbmllIChuYWpnb3JzenkgbWllc2nEhWMgdyBzZXpvbmllKS4gSmVzdCB0byBwb3RyemVibmUsIGJ5IHBvd3LDs2NpxIcgb2QgZGFueWNoIHpub3JtYWxpem93YW55Y2ggKHogcHJ6ZWR6aWHFgnUgMC0xKSBkbyBkYW55Y2ggdyBza2FsaSBwaWVyd290bmVqIChyemVjenl3aXN0ZWopLiBEYWxlaiBzxIUgemFwcmV6ZW50b3dhbmUgdHJ6eSBzY2VuYXJpdXN6ZSwgYnkgd3l6bmFjennEhyBtYWtzeW1hbG55IHBvemlvbSB6YWNob3Jvd2HFhCB3IHNlem9uaWUuIA0KUG9kb2JuaWUgamFrIHcgcHJ6eXBhZGt1IGJ1ZG93eSDFm3LDs2Ryb2N6bmVnbyBtb2RlbHUsIHByb2dub3phIGLEmWR6aWUgb3BhcnRhIG5hIGRhbnljaCB6IGxhdCAyMDEwLTIwMTkuIERvIHByb2dvem93YW5pYSB6b3N0YcWCIHXFvHl0eSBwYWtpZXQgYGZvcmVjYXN0YCBhIHcgamVnbyByYW1hY2ggbW9kZWwgRVRTIChFeHBvbmVudGlhbCBzbW9vdGhpbmcgc3RhdGUgc3BhY2UgbW9kZWwpW14yXS4gDQpQb25pxbxzemEgdGFiZWxhIHByZXplbnR1amUgcHJvZ25vesSZIG1ha3N5bWFsbmVqIHJvY3puZWogKHNlem9ub3dlaikgaWxvxZtjaSBwcnp5cGFka8OzdyB3cmF6IHogcHJ6ZWR6aWHFgmFtaSB1Zm5vxZtjaToNCg0KYGBge3IgcXJmX3Byb2duLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCB3YXJuaW5ncyA9IEZBTFNFLCBjYWNoZT1GQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30NCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0Kc2V0LnNlZWQoOTk5KQ0KZiA8LSBncnlwYV9jYWxvc2NfcnJtbSAlPiUgZ3JvdXBfYnkoZXR5a2lldGFfc2V6b251KSAlPiUgc3VtbWFyaXNlKG1heF9zZXpvbnUgPSBtYXgoc3VtYV9wcnp5cGFka293KSkNCmYgPC0gZltmJGV0eWtpZXRhX3Nlem9udSAlaW4lIGMoIjIwMTAvMjAxMSIsICIyMDExLzIwMTIiLCIyMDEyLzIwMTMiLCAiMjAxMy8yMDE0IiwgIjIwMTQvMjAxNSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTUvMjAxNiIsIjIwMTYvMjAxNyIsIjIwMTcvMjAxOCIsIjIwMTgvMjAxOSIsIjIwMTkvMjAyMCIpLF0NCiMgZiRldHlraWV0YV9zZXpvbnUgPC0gYXMuZmFjdG9yKGYkZXR5a2lldGFfc2V6b251KQ0KZnRzIDwtIGFzLnRzKGYkbWF4X3Nlem9udSkNCnByb2duX21heF9zZXpvbiA8LSBmb3JlY2FzdChmJG1heF9zZXpvbnUsIGg9MSwgbGV2ZWwgPSBjKDgwKSkNCnByb2duX21heF9zZXpvbiA8LSBhcy5kYXRhLmZyYW1lKHByb2duX21heF9zZXpvbikNCnQwIDwtIHByb2duX21heF9zZXpvbiAlPiUgICBrYmwoKSAlPiUNCiAga2FibGVfbWluaW1hbCgiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikNCnQwDQpgYGANCg0KUHJvZ25vem93YW5hIGlsb8WbxIcgemFjaG9yb3dhxYQgdyBzemN6eWNpZSBzZXpvbnUgMjAyMC8yMDIxIHRvICoqODQ3LDMqKiB0eXMuIG9zw7NiLiBaIHByYXdkb3BvZG9iaWXFhHN0d2VtIDgwJSBtb8W8bmEgb2N6ZWtpd2HEhywgxbxlIGxpY3piYSB6YWNob3Jvd2HFhCAqKncgc3pjenljaWUqKiwgYsSZZHppZSBtaWXFm2NpxIcgc2nEmSB3IHByemVkemlhbGU6ICoqNTIxLDIqKiBkbyAqKjEgMTczLDYqKiB0eXMuIG9zw7NiLiBQb3PFgnVndWrEhWMgc2nEmSB0xIUgcHJvZ25vesSFIG9yYXogbW9kZWxlbSB3eXpuYWN6b255bSB3IHBvcHJ6ZWRuaW0gcHVua2NpZSwgbW96bmEgd3l6bmFjennEhyBwcmF3ZG9wb2RvYm55IHByemViaWVnIHNlem9udSBncnlwb3dlZ286DQoNCg0KYGBge3IgcHJvZ25fd3lrLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZT1GQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30NCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpkZW5vcm1hbGl6YWNqYSA8LSBmdW5jdGlvbih4LCBteCwgbW4pIHtyZXR1cm4gKCh4KihteCAtIG1uKSkgKyBtbil9DQptbiA9IG1pbihncnlwYV9jYWxvc2NfcnJtbVtncnlwYV9jYWxvc2NfcnJtbSRldHlraWV0YV9zZXpvbnU9PSIyMDIwLzIwMjEiLF0kc3VtYV9wcnp5cGFka293KQ0KbXggPSByb3VuZChwcm9nbl9tYXhfc2V6b24kYFBvaW50IEZvcmVjYXN0YCwwKQ0KbXhsbyA9IHJvdW5kKHByb2duX21heF9zZXpvbiRgTG8gODBgLDApDQpteGhpID0gcm91bmQocHJvZ25fbWF4X3Nlem9uJGBIaSA4MGAsMCkNCg0KDQojIG5vcm1hbGl6YWNqYSA8LSBmdW5jdGlvbih4KSB7cmV0dXJuICgoeCAtIG1pbih4KSkgLyAobWF4KHgpIC0gbWluKHgpKSl9DQoNCm0xJHByb2dub3phX3NyIDwtIHJvdW5kKGRlbm9ybWFsaXphY2phKG0xJHN1bV9wcnp5X25vcm0sIG1uID0gbW4sIG14ID0gbXgpLDApDQptMSRwcm9nbm96YV9oaSA8LSByb3VuZChkZW5vcm1hbGl6YWNqYShtMSRzdW1fcHJ6eV9ub3JtLCBtbiA9IG1uLCBteCA9IG14aGkpLDApDQptMSRwcm9nbm96YV9sbyA8LSByb3VuZChkZW5vcm1hbGl6YWNqYShtMSRzdW1fcHJ6eV9ub3JtLCBtbiA9IG1uLCBteCA9IG14bG8pLDApDQptMSRwcm9nbm96YV9zcl9keiA8LSByb3VuZChkZW5vcm1hbGl6YWNqYShtMSRzdW1fcHJ6eV9ub3JtLCBtbiA9IG1uLCBteCA9IG14KS8zMCwwKQ0KbTEkcHJvZ25vemFfaGlfZHogPC0gcm91bmQoZGVub3JtYWxpemFjamEobTEkc3VtX3Byenlfbm9ybSwgbW4gPSBtbiwgbXggPSBteGhpKS8zMCwwKQ0KbTEkcHJvZ25vemFfbG9fZHogPC0gcm91bmQoZGVub3JtYWxpemFjamEobTEkc3VtX3Byenlfbm9ybSwgbW4gPSBtbiwgbXggPSBteGxvKS8zMCwwKQ0KDQoNCg0KDQptMSRucl9taWVzaWFjYSA8LSBpZmVsc2UobTEkbnJfbWllc2lhY2Ffc2V6b248PTYsIG0xJG5yX21pZXNpYWNhX3Nlem9uKzYsIG0xJG5yX21pZXNpYWNhX3Nlem9uLTYpDQptMSRtc2Nfa2FsZW5kIDwtIG1vbnRoKG0xJG5yX21pZXNpYWNhLCBsYWJlbCA9IFRSVUUpDQoNCnd5azYgPC0gcGxvdF9seShkYXRhID0gbTEsIHggPSB+bnJfbWllc2lhY2Ffc2V6b24sIHkgPSB+cHJvZ25vemFfc3IsIHRleHQgPSB+bXNjX2thbGVuZCwgaG9vdmVyaW5mbyA9ICd0ZXh0JywgbmFtZSA9ICd3YXJpYW50IHBvxZtyZWRuaScpDQp3eWs2IDwtIHd5azYgJT4lIGFkZF9saW5lcygpDQp3eWs2IDwtIHd5azYgJT4lIGFkZF90cmFjZSh5ID0gfnByb2dub3phX2xvLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywNCiAgICAgICAgICAgIGZpbGwgPSAndG9uZXh0eScsIGZpbGxjb2xvcj0ncmdiYSgwLDEwMCw4MCwwLjIpJywgbGluZSA9IGxpc3QoY29sb3IgPSAndHJhbnNwYXJlbnQnKSwNCiAgICAgICAgICAgIHNob3dsZWdlbmQgPSBUUlVFLCBuYW1lID0gJ3dhcmlhbnQgbWluaW1hbG55JykgDQp3eWs2IDwtIHd5azYgJT4lIGFkZF90cmFjZSh5ID0gfnByb2dub3phX2hpLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywNCiAgICAgICAgICAgIGZpbGwgPSAndG9uZXh0eScsIGZpbGxjb2xvcj0ncmdiYSgwLDEwMCw4MCwwLjIpJywgbGluZSA9IGxpc3QoY29sb3IgPSAndHJhbnNwYXJlbnQnKSwNCiAgICAgICAgICAgIHNob3dsZWdlbmQgPSBUUlVFLCBuYW1lID0gJ3dhcmlhbnQgbWFrc3ltYWxueScpIA0Kd3lrNiA8LSB3eWs2ICU+JSBsYXlvdXQodGl0bGUgPSAiUHJvZ25vemEgUVJGIHphY2hvcm93YcWEIG5hIGdyeXDEmSB3IHNlem9uaWUgMjAyMC8yMDIxIiwNCiAgICAgICAgICAgICAgICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiTWllc2nEhWMgc2V6b251IGdyeXBvd2VnbyIpLCB5YXhpcyA9IGxpc3QodGl0bGUgPSAiSWxvxZvEhyB6YWNob3Jvd2HFhCAoem5vcm1hbGl6b3dhbmEpIikNCiAgICAgICAgICAgICAgICAgICAgICApDQoNCnd5azYNCmBgYA0KDQpaZ29kbmllIHogbnVtZXJ5Y3pueW0gbW9kZWxlbSBRUkYsIHNlem9uIGdyeXBvd3kgMjAyMC8yMDIxIGLEmWR6aWUgbWlhxYIgc3fDs2ogc3pjenl0IHcgbHV0eW0gMjAyMS4gxYFhY3puYSBpbG/Fm8SHIHphY2hvcm93YcWEIHdlZMWCdWcgd2FyaWFudHUgcG/Fm3JlZG5pZWdvIHd5bmllc2llICoqMyA1ODggODE0KiouDQoNClN6Y3plZ8OzxYJvd8SFIHByb2dub3rEmSB3IG1pZXNpxIVjYWNoIHByZXplbnR1amUgcG9uacW8c3phIHRhYmVsYToNCmBgYHtyIHFyZl9wcm9nbl90YWJsZSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgd2FybmluZ3MgPSBGQUxTRSwgY2FjaGU9RkFMU0UsIHJlc3VsdHMgPSAnaGlkZSd9DQpsaWJyYXJ5KGthYmxlRXh0cmEpDQp0YWJlbGEyIDwtIG0xWyxjKDExLDksNiw3LDQsOCw1KV0NCmNuMyA8LSBjKCJNaWVzacSFYyIsICJEemllbm5lIHphY2hvcm93YW5pYSwgd2FyaWFudCBtaW5pbWFsbnkiLCAiTWllc2nEmWN6bmllLCB3YXJpYW50IG1pbmltYWxueSINCiAgICAgICAgICwgIkR6aWVubmUgemFjaG9yb3dhbmlhLCB3YXJpYW50IHBvxZtyZWRuaSIsICJNaWVzacSZY3puaWUsIHdhcmlhbnQgcG/Fm3JlZG5pIg0KICAgICAgICAgLCAiRHppZW5uZSB6YWNob3Jvd2FuaWEsIHdhcmlhbnQgbWFrc3ltYWxueSIsICJNaWVzacSZY3puaWUsIHdhcmlhbnQgbWFrc3ltYWxueSIpDQpjb2xuYW1lcyh0YWJlbGEyKSA8LSBjbjMNCnRhYmVsYTIgPC0gdGFiZWxhMiAlPiUga2JsKCkgJT4lIGthYmxlX21pbmltYWwoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQp0YWJlbGEyDQpgYGANCg0KDQoNCiMjIyBXbmlvc2tpIGRvdHljesSFY2UgU0FSUy1Db1YtMg0KDQpPZG5vc3rEhWMgcG93ecW8c3plIHJvendhxbxhbmlhIG9kbm/Fm25pZSB6YWNob3Jvd2Fsbm/Fm2NpIG5hIGdyeXDEmSwgbmEgZXBpZGVtacSZIGtvcm9uYXdpcnVzYSwgbmFsZcW8eSBwcnp5dG9jennEhyBuYWp3YcW8bmllanN6ZSBiYWRhbmlhIHcgdHltIHpha3Jlc2llLiBCYWRhbmlhIHRlIHBvendvbMSFIG9zemFjb3dhxIcsIGpha2EgaWxvxZvEhyB6YWNob3Jvd2HFhCBtb8W8ZSB3IHJ6ZWN6eXdpc3RvxZtjaSBkb3R5Y3p5xIcga29yb25hd2lydXNhLiBXYXJ0byBwb3puYcSHOg0KDQoxLiAiVmlydXPigJN2aXJ1cyBpbnRlcmFjdGlvbnMgaW1wYWN0IHRoZSBwb3B1bGF0aW9uIGR5bmFtaWNzIG9mIGluZmx1ZW56YSBhbmQgdGhlIGNvbW1vbiBjb2xkIiwgUE5BUyBEZWNlbWJlciAyNiwgMjAxOSAxMTYgKDUyKSAyNzE0Mi0yNzE1MDsgZmlyc3QgcHVibGlzaGVkIERlY2VtYmVyIDE2LCAyMDE5LCBTZW1hIE5pY2tiYWtoc2gsIENvbGV0dGUgTWFpciwgTG91aXNlIE1hdHRoZXdzLCBSaWNoYXJkIFJlZXZlLCBQYXVsIEMuIEQuIEpvaG5zb24sIEZpb25hIFRob3JidXJuLCBCZWF0cml4IHZvbiBXaXNzbWFubiwgQXJsZW5lIFJleW5vbGRzLCBKYW1lcyBNY01lbmFtaW4sIFJvcnkgTi4gR3Vuc29uLCBhbmQgUGFibG8gUi4gTXVyY2lhIFtQTkFTXShodHRwczovL3d3dy5wbmFzLm9yZy9jb250ZW50LzExNi81Mi8yNzE0MikNCjIuICJFcGlkZW1pb2xvZ3kgb2YgU2Vhc29uYWwgQ29yb25hdmlydXNlczogRXN0YWJsaXNoaW5nIHRoZSBDb250ZXh0IGZvciB0aGUgRW1lcmdlbmNlIG9mIENvcm9uYXZpcnVzIERpc2Vhc2UgMjAxOSIsIFRoZSBKb3VybmFsIG9mIEluZmVjdGlvdXMgRGlzZWFzZXMsIDAxIEp1biAyMDIwLCAyMjIoMSk6MTctMjUsIFtFVVJPUEUgUE1DXShodHRwczovL2V1cm9wZXBtYy5vcmcvYXJ0aWNsZS9QTUMvNzE4NDQwND90ZXN0aW5nKQ0KDQpOYWp3YcW8bmllanN6eSB3bmlvc2VrIHDFgnluxIVjeSB6IHR5Y2ggYmFkYcWEIHRvOg0KDQoNCjxjZW50ZXI+DQoqKnVkemlhxYIga29yb25hd2lydXPDs3cgdyBjb3JvY3pueWNoIHphY2hvcm93YW5pYWNoIG5hIGdyeXDEmSB3eW5vc2kgb2QgNyBkbyAxNSBwcm9jZW50KioNCjwvY2VudGVyPg0KDQpEemnEmWtpIHR5bSBiYWRhbmlvbSBvcmF6IHpidWRvd2FuZWogcHJvZ25vemllLCBtb8W8bmEgdyBwcm9zdHkgc3Bvc8OzYiB3eXpuYWN6ecSHIHByYXdvZG9wb2RvYm7EhSBsaWN6YsSZIHphY2hvcm93YcWEIG5hIGtvcm9uYXdpcnVzYSB6YXLDs3dubyB3IGxhdGFjaCB1YmllZ8WCeWNoLCBqYWsgaSB3IHNlem9uaWUgMjAyMC8yMDIxLiBQcnp5IHdzenlzdGtpY2ggemFzdHJ6ZcW8ZW5pYWNoLCDFvGUgb2JlY255IHN6Y3plcCBrb3JvbmF3aXJ1c2EgamVzdCBpbm55IG9kIHBvcHJ6ZWRuaWNoLCBuYWxlxbx5IHphdXdhxbx5xIcsIMW8ZSBuYXdldCAic2V6b25vd2UiIGtvcm9uYXdpcnVzeSByw7PFvG5pxIUgc2nEmSBvZCBzaWViaWUuIEJpb3LEhWMgcG9kIHV3YWfEmSBub3dvY3plc27EhSB3aWVkesSZIG1vbGVrdWxhcm7EhSBvIHdpcnVzYWNoLCBtb8W8bmEgeiBkb8WbxIcgZHXFvMSFIHBld25vxZtjacSFIHN0d2llcmR6acSHLCDFvGUga29yb25hd2lydXMgeiBwb2N6xIV0a8OzdyAyMDIwIHJva3UgemTEhcW8ecWCIHcgY2nEhWd1IGtpbGt1IG1pZXNpxJljeSB6bXV0b3dhxIcgaSBqdcW8IHLDs8W8bmkgc2nEmSBvZCBwb2N6xIV0a293ZWogc3dvamVqIHdlcnNqaS4NCg0KDQpgYGB7ciBxcmZfcHJvZ25fdGFibGUyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCB3YXJuaW5ncyA9IEZBTFNFLCBjYWNoZT1GQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30NCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoZHBseXIpDQprb3dfbGF0YV91YmllZ2xlIDwtIGdyeXBhX2NhbG9zY19ycm1tW2dyeXBhX2NhbG9zY19ycm1tJGV0eWtpZXRhX3Nlem9udSAlaW4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCIyMDEwLzIwMTEiLCAiMjAxMS8yMDEyIiwiMjAxMi8yMDEzIiwgIjIwMTMvMjAxNCIsICIyMDE0LzIwMTUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDE1LzIwMTYiLCIyMDE2LzIwMTciLCIyMDE3LzIwMTgiLCIyMDE4LzIwMTkiLCIyMDE5LzIwMjAiKSxdICU+JSBncm91cF9ieShldHlraWV0YV9zZXpvbnUpICU+JSBzdW1tYXJpc2Uoc3VtYV9wcnp5cGFka293ID0gc3VtKHN1bWFfcHJ6eXBhZGtvdykpIA0Ka293X2xhdGFfdWJpZWdsZSA8LSBrb3dfbGF0YV91YmllZ2xlICU+JSBtdXRhdGUoa293X21heCA9IHJvdW5kKHN1bWFfcHJ6eXBhZGtvdyouMTUsMCkpICU+JSBtdXRhdGUoa293X21pbiA9IHJvdW5kKHN1bWFfcHJ6eXBhZGtvdyouNywwKSkNCmNuNCA8LSBjKCJTZXpvbiIsICJTdW1hIHphY2hvcm93YcWEIiwgIlphY2hvcm93YW5pYSBuYSBrb3JvbmF3aXJ1c2EgKDE1JSkiLCAiWmFjaG9yb3dhbmlhIG5hIGtvcm9uYXdpcnVzYSAoNyUpIikNCmNvbG5hbWVzKGtvd19sYXRhX3ViaWVnbGUpIDwtIGNuNA0Ka293X2xhdGFfdWJpZWdsZTIgPC0ga293X2xhdGFfdWJpZWdsZSAlPiUga2JsKCkgJT4lIGthYmxlX21pbmltYWwoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQprb3dfbGF0YV91YmllZ2xlMg0KYGBgDQoNCkphayB3eW5pa2EgeiB0ZWogcHJvc3RlaiBrYWxrdWxhY2ppLCB3IHNlem9uaWUgMjAxOS8yMDIwIGxpY3piYSBjaG9yeWNoIG5hIGtvcm9uYXdpcnVzYSB3eW5vc8WCYSBwb21pxJlkenkgKioyODcsMiB0eXMuKiogYSAqKjYxNSw1IHR5cy4qKiBjbyBkYWplIMWbcmVkbmnEhSBkemllbm7EhSB6YWNob3Jvd2Fsbm/Fm8SHIHcgY2nEhWd1IHNlem9udSBtacSZZHp5IG9rICoqODAwKiogYSAqKjE2NzAqKiBwcnp5cGFka8OzdyBkemllbm5pZS4NCg0KTW9kZWwgemFjaHJvd2Fsbm/Fm2NpIG5hIGdyeXDEmSB1xbx5dHkgZG8gcHJvZ25venkgaWxvxZtjaSBwcnp5cGFka8OzdyBrb3JvbmF3aXJ1c2EgdyBzZXpvbmllIDIwMjAvMjAyMSB3c2thenVqZSBuYSBuYXN0xJlwdWrEhWN5IHRlb3JldHljem55IHByemViaWVnIHphY2hvcm93YcWEICh3ZyAxNSUgdWR6aWHFgnUgdyBpbmZla2NqYWNoKToNCg0KYGBge3IgcHJvZ25fd3lrMiwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9RkFMU0UsIHJlc3VsdHMgPSAnaGlkZSd9DQptMSRrb3dfbG8gPC0gcm91bmQobTEkcHJvZ25vemFfbG8qLjE1LDApDQptMSRrb3dfcG9zIDwtIHJvdW5kKG0xJHByb2dub3phX3NyKi4xNSwwKQ0KbTEka293X2hpIDwtIHJvdW5kKG0xJHByb2dub3phX2hpKi4xNSwwKQ0KDQp3eWs3IDwtIHd5azYgJT4lIGFkZF90cmFjZShkYXRhID0gbTEsIHkgPSB+a293X3BvcywgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycpDQoNCnd5azcgPC0gd3lrNyAlPiUgYWRkX3RyYWNlKGRhdGEgPSBtMSwgeSA9IH5rb3dfbG8sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLA0KICAgICAgICAgICAgZmlsbCA9ICd0b25leHR5JywgZmlsbGNvbG9yPSdyZ2JhKDIwMCwwLDAsMC4yKScsIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3RyYW5zcGFyZW50JyksDQogICAgICAgICAgICBzaG93bGVnZW5kID0gVFJVRSwgbmFtZSA9ICdLb3JvbmF3aXJ1czogd2FyaWFudCBtaW5pbWFsbnknKSANCg0Kd3lrNyA8LSB3eWs3ICU+JSBhZGRfdHJhY2UoZGF0YSA9IG0xLCB5ID0gfmtvd19oaSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsDQogICAgICAgICAgICBmaWxsID0gJ3RvbmV4dHknLCBmaWxsY29sb3I9J3JnYmEoMjUwLDAsMCwwLjIpJywgbGluZSA9IGxpc3QoY29sb3IgPSAndHJhbnNwYXJlbnQnKSwNCiAgICAgICAgICAgIHNob3dsZWdlbmQgPSBUUlVFLCBuYW1lID0gJ0tvcm9uYXdpcnVzOiB3YXJpYW50IG1ha3N5bWFsbnknKSANCnd5azcgPC0gd3lrNyAlPiUgbGF5b3V0KHRpdGxlID0gIlByb2dub3phIFFSRiB6YWNob3Jvd2HFhCBuYSBncnlwxJksIHcgdHltIGtvcm9uYXdpcnVzYSB3IHNlem9uaWUgMjAyMC8yMDIxIiwNCiAgICAgICAgICAgICAgICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiTWllc2nEhWMgc2V6b251IGdyeXBvd2VnbyIpLCB5YXhpcyA9IGxpc3QodGl0bGUgPSAiSWxvxZvEhyB6YWNob3Jvd2HFhCAoem5vcm1hbGl6b3dhbmEpIikNCiAgICAgICAgICAgICAgICAgICAgICApDQoNCnd5azcNCiAgDQpgYGANCg0KV2VkxYJ1ZyBtb2RlbHUgcG/Fm3JlZG5pZWdvLCB3ZSB3cnplxZtuaXUgcG93aW5ubyBiecSHIHd5a3J5dGUgNTEsOCB0eXMuIHByenlwYWRrw7N3IGdyeXB5LiB3IHR5bSA4LDggdHlzLiBwcnp5cGFka8OzdyBrb3JvbmF3aXJ1c2EuIEphayB3eW5pa2EgeiBkYW55Y2ggUFpIIHdlIHdyemXFm25pdSB3eWtyeXRvIDIxNyw2IHR5cy4gcHJ6eXBhZGvDs3cgZ3J5cHksIHcgdHltIDI2LDEgdHlzLiBwcnp5cGFka8OzdyBrb3JvbmF3aXJ1c2E6DQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUV9DQojIyMgQnVkb3dhIHplc3Rhd3UgZGFueWNoIGRsYSBzZXpvbnUgMjAyMC8yMDIxIA0KDQpncnlwYTIwIDwtIGRhdGEuZnJhbWUoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKGxpc3RhX3BsaWtvdykpew0KdGV4dF9yZXBfdGVtcDIwIDwtIHBkZl90ZXh0KHBkZiA9IHBhc3RlMCgicGRmLyIsbGlzdGFfcGxpa293W2ldKSkNCnRleHRfcmVwX3RlbXAyMCA8LSBjKHVubGlzdChzdHJzcGxpdCh0ZXh0X3JlcF90ZW1wMjAsICJcclxuIikpKQ0Kd2FudGVkX2xpbmVzMjAgPC0gYygNCiAgICAgICAgICAgICAgICAgIGdyZXAoIlpha2HFvGVuaWEgU0FSUy1Db1YtMiIsdGV4dF9yZXBfdGVtcDIwKVsxXQ0KICAgICAgICAgICAgICAgICAgKQ0Kd2FudGVkX2xpbmVzMjANCndhbnRlZDIwX2RhdGFfcmFwb3J0dSA8LSBwZGZfaW5mbyhwZGYgPSBwYXN0ZTAoInBkZi8iLGxpc3RhX3BsaWtvd1tpXSkpJGtleXMkVGl0bGUNCndhbnRlZDIwIDwtIHRleHRfcmVwX3RlbXAyMFtnZXQoIndhbnRlZF9saW5lczIwIildDQpkYXRhX3JhcG9ydHUyMCA8LSBzdHJfZXh0cmFjdCh3YW50ZWQyMF9kYXRhX3JhcG9ydHUsICJcXGR7Mn0uXFxkezJ9XFxzXFxkezR9fFxcZHsyfS5cXGR7Mn0uXFxkezR9IikNCmRhdGFfcmFwb3J0dTIwIDwtIGx1YnJpZGF0ZTo6ZG15KGRhdGFfcmFwb3J0dTIwKQ0KaWxvc2NfcHJ6eXAyMCA8LSBhcy5udW1lcmljKGdzdWIoIlxccyIsIiIsKHN0cl9leHRyYWN0KHdhbnRlZDIwWzFdLCAiKFxcc1xcZCspezEsM30iKSkpKQ0Kd2llcnN6MjAgPC0gZGF0YS5mcmFtZShkYXRhX3JhcG9ydHUyMCwgaWxvc2NfcHJ6eXAyMCkgDQpncnlwYTIwIDwtIHJiaW5kKGdyeXBhMjAsIHdpZXJzejIwKQ0KfQ0KZ3J5cGEyMCA8LSBncnlwYTIwW2NvbXBsZXRlLmNhc2VzKGdyeXBhMjApLF0NCg0KIyBvYmxpY3plbmllIGlsb8WbY2kgbm93eWNoIHByenlwYWRrw7N3IChjb3ZpZGEsIGRhbmUgb2QgbGlwY2EpDQpub3dlX3ByeXBfMjAgPC0gZGlmZihncnlwYTIwJGlsb3NjX3ByenlwMjApIA0Kbm93ZV9wcnlwXzIwIDwtIGMoZ3J5cGEyMFsxLDJdLG5vd2VfcHJ5cF8yMCkNCmdyeXBhMjAgPC0gY2JpbmQoZ3J5cGEyMCwgbm93ZV9wcnlwXzIwKQ0KZ3J5cGEyMCA8LSBzdWJzZXQoZ3J5cGEyMCwgZ3J5cGEyMCRkYXRhX3JhcG9ydHUyMCA+ICIyMDIwLTA2LTMwIikNCmdyeXBhMjAkbXNjIDwtIG1vbnRoKGdyeXBhMjAkZGF0YV9yYXBvcnR1MjApDQpncnlwYTIwIDwtIGdyeXBhMjAgJT4lIGdyb3VwX2J5KG1zYykgJT4lIHN1bW1hcmlzZShzdW1hX2NvdmlkID0gc3VtKG5vd2VfcHJ5cF8yMCkpDQpncnkyMDIxIDwtIHN1YnNldChncnlwYV9jYWxvc2NfcnJtbSwgZ3J5cGFfY2Fsb3NjX3JybW0kZXR5a2lldGFfc2V6b251PT0iMjAyMC8yMDIxIiZncnlwYV9jYWxvc2NfcnJtbSRtc2M+NikNCmdyeTIwMjEgPC0gZ3J5MjAyMVssYygxOjYpXQ0KZ3J5MjAyMSA8LSBjYmluZChncnkyMDIxLCBncnlwYTIwJHN1bWFfY292aWQpDQpncnkyMDIxJHN1bWFfcHJ6eXBhZGtvd196X2NvdiA8LSBncnkyMDIxJHN1bWFfcHJ6eXBhZGtvdyArIGdyeTIwMjEkLi4uNw0KDQpgYGANCg0KYGBge3IgcXJmX3Byb2duX3RhYmxlNCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgd2FybmluZ3MgPSBGQUxTRSwgY2FjaGU9RkFMU0UsIHJlc3VsdHMgPSAnaGlkZSd9DQojIyMgVGFiZWxhIHogZGFueW0gc2V6b251IDIwMjAvMjAyMQ0KDQp0YWIyMDIxIDwtIGdyeTIwMjFbLGMoNiw4LDMsNyldDQpjbjUgPC0gYygiTWllc2nEhWMiLCAiU3VtYSBwcnp5cGFka8OzdyIsICJHcnlwYTogcG96b3N0YcWCZSBzemN6ZXB5IiwgIkdyeXBhOiBrb3JvbmF3aXJ1cyIpDQpjb2xuYW1lcyh0YWIyMDIxKSA8LSBjbjUNCnRhYjIwMjEgPC0gdGFiMjAyMSAlPiUga2JsKCkgJT4lIGthYmxlX21pbmltYWwoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQp0YWIyMDIxDQoNCmBgYA0KDQoNClVkemlhxYIga29yb25hd2lydXNhIHcgxYLEhWN6bmVqIGxpY3piaWUgcHJ6eXBhZGvDs3cgd3lub3NpIDEyJSBpIGplc3QgemdvZG55IHogb2JzZXJ3YWNqYW1pIGkgYmFkYW5pYW1pIHByenl0b2N6b255bWkgcG93ecW8ZWo6ICJWaXJ1c+KAk3ZpcnVzIGludGVyYWN0aW9ucyBpbXBhY3QgdGhlIHBvcHVsYXRpb24uLi4iIG9yYXogIkVwaWRlbWlvbG9neSBvZiBTZWFzb25hbCBDb3JvbmF2aXJ1c2VzOiAuLi4iLg0KDQpSb3p3w7NqIHphY2hvcm93YcWEIG5hIGdyeXDEmSB3IHNlem9uaWUgMjAyMC8yMDIxIHcgcG9yw7N3bmFuaXUgZG8gbW9kZWx1IGkgb3N0YXRuaWNoIDUgbGF0IHd5Z2zEhWRhIG5hIHd5a3Jlc2llIG5hc3TEmXB1asSFY286DQpgYGB7ciAgcHJvZ25fd3lrNCwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9RkFMU0UsIHJlc3VsdHMgPSAnaGlkZSd9DQptY2UgPC0gYyg3LDgsOSkNCnNlem9ueV9hbmFsaXpvd2FuZSA8LSBjKCIyMDE0LzIwMTUiLCIyMDE1LzIwMTYiLCIyMDE3LzIwMTgiLCIyMDE4LzIwMTkiLCIyMDE5LzIwMjAiKQ0Ka3cxX3Nlem9udSA8LSBzdWJzZXQoZ3J5cGFfY2Fsb3NjX3JybW0sIChldHlraWV0YV9zZXpvbnUgJWluJSAgc2V6b255X2FuYWxpem93YW5lICYgbXNjICVpbiUgbWNlKSlbLGMoNSw2LDMpXQ0Ka3cxX3Nlem9udSA8LSBrdzFfc2V6b251ICU+JSBtdXRhdGUoImtvcm9uYXdpcnVzIiA9IHJvdW5kKHN1bWFfcHJ6eXBhZGtvdyouMTUsMCkpDQp0bXAgPC0gZ3J5MjAyMVssYyg1LDYsOCw3KV0NCmNuNiA8LSBjb2xuYW1lcyhrdzFfc2V6b251KQ0KY29sbmFtZXModG1wKSA8LSBjbjYNCiMga3cxX3Nlem9udSA8LSByYmluZChrdzFfc2V6b251LCB0bXApDQp0bXAyIDwtIG0xW20xJG5yX21pZXNpYWNhJWluJW1jZSxjKDIsMTEsNSwxNCldDQpjb2xuYW1lcyh0bXAyKSA8LSBjbjYNCiMgcm0odG1wKQ0Kd3lrOCA8LSBwbG90X2x5KGRhdGEgPSBrdzFfc2V6b251LCB4ID0gfm1zY19uYXp3YSwgeSA9IH5zdW1hX3ByenlwYWRrb3csIGNvbG9yID0gfmV0eWtpZXRhX3Nlem9udSkNCnd5azggPC0gd3lrOCAlPiUgYWRkX2xpbmVzKCkNCg0Kd3lrOCA8LSB3eWs4ICU+JSBhZGRfdHJhY2UoZGF0YSA9IHRtcCx5ID0gfnRtcCRzdW1hX3ByenlwYWRrb3cgLCBuYW1lID0gfmV0eWtpZXRhX3Nlem9udSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICdyZ2IoMjA1LCA5MiwgOTIpJywgd2lkdGggPSA2KSkNCnd5azggPC0gd3lrOCAlPiUgYWRkX3RyYWNlKGRhdGEgPSB0bXAyLHkgPSB+dG1wMiRzdW1hX3ByenlwYWRrb3cgLCBuYW1lID0gJ01PREVMJywgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICdyZ2IoMjIsIDk2LCAxNjcpJywgd2lkdGggPSA2LCBkYXNoID0gJ2Rhc2gnKSkNCnd5azggPC0gd3lrOCAlPiUgbGF5b3V0KHRpdGxlID0gIlphY2hvcm93YW5pYSBuYSBncnlwxJkgdyBzZXpvbmllIDIwMjAvMjAyMSB3IHN0b3N1bmt1IGRvIGxhdCB1YmllZ8WCeWNoIiwNCiAgICAgICAgICAgICAgICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiTWllc2nEhWMgc2V6b251IGdyeXBvd2VnbyIpLCB5YXhpcyA9IGxpc3QodGl0bGUgPSAiSWxvxZvEhyB6YWNob3Jvd2HFhCIpDQogICAgICAgICAgICAgICAgICAgICAgKQ0Kd3lrOA0KYGBgDQoNCk5hIHBvd3nFvHN6eW0gd3lrcmVzaWUgd3lyYcW6bmllIHdpZGHEhyBkd2llIHJ6ZWN6eToNCg0KMS4gbW9kZWwgdGVvcmV0eWN6bnkgemVkeWNvd2FuaWUgKipuaWVkb3N6YWNvd3VqZSoqIHJvenfDs2ogemFjaG9yb3dhxYQgdyBwb2N6xIV0a293eWNoIG1pZXNpxIVjYWNoIHNlem9udSwNCjIuIHNlem9uIGdyeXBvd3kgMjAyMC8yMDIxIGplc3QgKip6ZGVjeWRvd2FuaWUgxYJhZ29kbmllanN6eSoqIG5pxbwgc2V6b255IDIwMTcvMjAxOCwgMjAxOC8yMDE5LCAyMDE5LzIwMjAuDQoNCk5hIGtvbmllYyBuaW5pZWpzemVnbyBvcHJhY293YW5pYSBwcnp5dG9jesSZIGplc3pjemUgb3N0YXRuaSB3eWtyZXMsIHBvZG9ibnkgamFrIHBvcHJ6ZWRuaSwgdHlsZSwgxbxlIHphd2llcmFqxIVjeSBkYW5lIG9kbm/Fm25pZSB6YWNob3Jvd2HFhCBuYSBncnlwxJkgc3Bvd29kb3dhbnljaCBrb3JvbmF3aXJ1c2VtOg0KDQpgYGB7ciBwcm9nbl93eWs1LCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZT1GQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30NCnd5azkgPC0gcGxvdF9seShkYXRhID0ga3cxX3Nlem9udSwgeCA9IH5tc2NfbmF6d2EsIHkgPSB+a29yb25hd2lydXMsIGNvbG9yID0gfmV0eWtpZXRhX3Nlem9udSkNCnd5azkgPC0gd3lrOSAlPiUgYWRkX2xpbmVzKCkNCnd5azkgPC0gd3lrOSAlPiUgYWRkX3RyYWNlKGRhdGEgPSB0bXAseSA9IH50bXAka29yb25hd2lydXMgLCBuYW1lID0gfmV0eWtpZXRhX3Nlem9udSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICdyZ2IoMjU1LCAwLCAwKScsIHdpZHRoID0gNikpDQp3eWs5IDwtIHd5azkgJT4lIGxheW91dCh0aXRsZSA9ICJaYWNob3Jvd2FuaWEgbmEga29yb25hd2lydXNhIHcgMjAyMC8yMDIxIHcgc3Rvc3Vua3UgZG8gbGF0IHViaWVnxYJ5Y2giLA0KICAgICAgICAgICAgICAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJNaWVzacSFYyBzZXpvbnUgZ3J5cG93ZWdvIiksIHlheGlzID0gbGlzdCh0aXRsZSA9ICJJbG/Fm8SHIHphY2hvcm93YcWEIikNCiAgICAgICAgICAgICAgICAgICAgICApDQp3eWs5DQpgYGANCg0KRGFuZSBoaXN0b3J5Y3puZSBvZG5vxZtuaWUgemFjaG9yb3dhxYQgc8SFIG9ibGljem9uZSBwcnp5IHphxYJvxbxlbml1IDE1JSB1ZHppYcWCdSB0ZWdvIHN6Y3plcHUgd2lydXNhIHcgb2fDs2xueWNoIHphY2hvcm93YW5pYWNoLiBTZXpvbiAyMDIwLzIwMjEgamVzdCBuaWUgdHlsa28gxYJhZ29kbmllanN6eSAodWR6aWHFgiBrb3JvbmF3aXJ1c2Egd3lub3NpIDEyJSkgYWxlIGkgb2fDs2xuYSBsaWN6YmEgemFjaG9yb3dhxYQgamVzdCB6bmFjesSFY28gbW5pZWpzemEgbmnFvCB3IGxhdGFjaCB1YmllZ8WCeWNoLg0KDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KW14xXTogSm91cm5hbCBvZiBNYWNoaW5lIExlYXJuaW5nIFJlc2VhcmNoIDcgKDIwMDYpIDk4M+KAkzk5LCBOaWNvbGFpIE1laW5zaGF1c2VuICJRdWFudGlsZSBSZWdyZXNzaW9uIEZvcmVzdHMiLg0KW14yXTogSW50ZXJuYXRpb25hbCBKb3VybmFsIG9mIEZvcmVjYXN0aW5nLCBWb2x1bWUgMTgsIElzc3VlIDMsIEp1bHnigJNTZXB0ZW1iZXIgMjAwMiwgUGFnZXMgNDM5LTQ1NCwgUm9iIEogSHluZG1hbiwgQW5uZSBCIEtvZWhsZXIsIFJhbHBoIEQgU255ZGVyLCBTaW1vbmUgR3Jvc2VhDQo=