0. Введение
Национальный корпус польского языка — вещь достаточно неудобная. Настройки в одном месте, выдача в другом, скачать можно только в html (хотя обещают, что можно и в Excel). Как было славно, если бы можно было сразу собирать в R выдачу и ее там анализировать?
1. API для польского корпуса
Для того, чтобы решить данную проблему я написал API (в этом мне немного помог Даня Алексеевский, спасибо!). Так что я написал на R достаточно неуклюжую, наверное, функцию pl.corpus
.
Чтобы не заставлять читателя разбираться в коде, поясню, что в результате в вашем окружении появляется функция pl.corpus
со следующими аргументами:
x
— запрос (обязательный аргумент);
tag
— логический вектор, отвечающий за то, нужны ли в выдачи морфологические теги или нет;
n.results
— переменная отвечающая за максимальное количество примеров в выдаче
corpus
— вектор, определяющий подкорпус, в котором следует искать (возможные значения: "nkjp300"
, "nkjp1800"
, "nkjp1M"
, "ipi250"
, "ipi030"
, "frequency-dictionary"
)
Приведу пример работы функции:
head(pl.corpus("witam"))
head(pl.corpus("An*a", tag = T))
head(pl.corpus("[base = 'witać']"))
Как видно из примеров, функция понимает самые разные запросы:
- простые
- регулярными выражениями
- Corpus Query Language CQL
2. Данные
Данные о польских городах я взял из Википедии. Были выбраны все города с населением больше 35500.
library(lingtypology)
miasta <- read.csv("https://goo.gl/1zZgOa")
map.feature(languages = "Polish",
popup = miasta$town.names,
latitude = miasta$lat,
longitude = miasta$long,
control = F)
Как видно из кода, для создания данной карты требуется написанный мной пакет lingtypology
. Данный пакет позволяет рисовать карты на основе названий языков, вставляет ссылки на данные языки в базе данных Glottolog.
Для дальнейшего исследования следует построить список запросов, которые бы можно было вставить в функцию pl.corpus
. Здесь таилось множество проблем, связанных с особенностью корпуса:
- в самом простом случае достаточно было лишь написать название города
- иногда приходилось менять большую букву на маленькую
- все города, содержащие дефис, следовало разделить на два отдельных слова
[base = 'Bielsko'] [base = 'Biała']
- некоторые города либо целиком, либо частично совпадали с какими-то польскими словами и так хранились в польском корпусе, в таком случае я требовал написания с большой буквы
[base = 'rudy' & orth = 'Rud.*'] [base = 'Śląsk']
- несколько городов пришлось выкинуть:
- из-за совпадений (Chrzanów, Jarosław)
- из-за ошибки в корпусе
Radomsko [radomsko:adv:pos]
, но Radomska [radomski:adj:sg:nom:f:pos]
(Knurów, Radomsko) В результате каждый запрос пришлось проверять, так что результат этой работы записан в базе:
head(miasta$query)
[1] [base = 'Będzin']
[2] [base = 'Bełchatów']
[3] [base = 'Biała'] [base = 'podlaski']
[4] [base = 'Białystok']
[5] [base = 'Bielsko'] [base = 'Biała']
[6] [base = 'Bolesławiec']
119 Levels: [base = 'Będzin'] ... [orth = 'Żar.*' & base = 'żar' & number=pl]
После обработки функцией pl.corpus
всех запросов получилась база данных, состоящая из 99129 примеров, полученных по шаблонному запросу:
head(pl.corpus(miasta$query[42], tag = T, n.results = 1000))
3. Обработка данных
Для обработки данных я написал две функции pl.base
и pl.case
.
pl.base <- function(x){
out <- c()
for(j in seq_along(x)) {
if(grepl("\\[.*:", x[j])){
out[j] <- unlist(strsplit(unlist(strsplit(x[j], "\\["))[2], "\\:"))[1]
} else {
warning(paste0('No tags were found in the query "', x, '"'))
}}
return(out)
}
pl.case <- function(x){
out <- c()
for(j in seq_along(x)) {
if(grepl("\\[.*:", x[j])){
out[j] <- unlist(strsplit(x[j], "\\:"))[4]
} else {
warning(paste0('No tags were found in the query "', x, '"'))
}}
return(out)
}
Функция pl.base
позволяет выделять основу:
pl.base("Wrocławia [Wrocław:subst:sg:gen:m3]")
[1] "Wrocław"
Функция pl.сase
позволяет выделять падеж:
pl.case("Wrocławia [Wrocław:subst:sg:gen:m3]")
[1] "gen"
Для дальнейшего анализа понадобиться пакет data.table
, который позволяет работать с бальшими файлами и пакет dtplyr
, который позволяет удобно обрабатывать данные. Необработанные данные, которые будут дальше анализироваться можно скачать здесь.
library(data.table); library(dtplyr)
df <- fread("moroz2016_polskie_miasta_row_data.csv", header = T)
Создадим новый датафрейм с основами и падежом:
library(tidyverse)
df %>%
mutate(base = pl.base(query)) %>%
mutate(case = pl.case(query)) %>%
select(base, case) %>%
group_by(base, case) %>%
summarise(number = n()) ->
base.case
head(base.case)
Source: local data table [6 x 3]
# tbl_dt [6 × 3]
base case number
<chr> <chr> <int>
1 Będzin acc 2
2 Będzin nom 312
3 Będzin gen 286
4 Będzin inst 9
5 Będzin loc 385
6 Będzin voc 1
Построим простой график:
base.case %>%
ggplot(aes(case, number))+
geom_bar(stat = "identity", position = "dodge", fill = "lightblue")+
theme_bw()
Для дальнейшей работы необходмо соединить изначальную базу (в переменной miasta
) и новые данные (в переменной base.case
).
base.case %>%
spread(case, number) ->
base.case
head(base.case)
Source: local data table [6 x 9]
# tbl_dt [6 × 9]
base acc dat gen inst loc nom
<chr> <int> <int> <int> <int> <int> <int>
1 Będzin 2 1 286 9 385 312
2 Bełchatów 3 NA 132 33 158 669
3 Biała 20 NA 357 NA 15 183
4 Białystok 3 NA 203 12 582 181
5 Bielsko NA NA 90 NA 169 160
6 Bolesławiec 1 4 254 21 284 433
# ... with 2 more variables: voc <int>, `<NA>` <int>
Теперь можно присоединить получившуюся таблицу к уже имеющейся, выкинув первый и последний столбец:
miasta <- cbind.data.frame(miasta[-52,], base.case[-73,])[,-c(6, 14)]
head(miasta)
Надо отметить, что не по всем запросам в корпусе нашлась 1000 примеров, так что абсолютные значения количества падежных форм для каждого города сравнивать между собой несколько бессмысленно. Поэтому заменим все пропущенные значения (NA
) на 0, посчитаем сумму абсолютных значений в каждой строчке, а потом переведем абсолютные значения количества падежей в доли.
miasta[is.na(miasta)] <- 0
for(i in 1:nrow(miasta)){
miasta %>%
select(6:12) %>%
slice(i) %>%
sum() ->
miasta$n[i]}
for(j in 1:nrow(miasta)){
miasta %>%
select(6:12) %>%
slice(j) %>%
prop.table() ->
miasta[j,6:12]}
head(miasta)
В результате данных операций возникли некоторые неправильные значения NaN
. Это связано с тем, что некоторые города в корпусе не распознаны должным образом и имеют один единственный тег ign
(Zawiercie, Chojnice). Избавимся от данных строчек:
miasta <- miasta[complete.cases(miasta),]
Теперь все данные (в итоге 116 городов) собраны воедино и можно приступать к анализу.
4. Анализ данных
Во-первых, конечно, хочется посмотреть, какие значения приимают получившиеся доли:
miasta %>%
gather(case, rate, acc:voc) ->
miasta.for.analysis
miasta.for.analysis_2 <- miasta.for.analysis[,-7]
miasta.for.analysis %>%
ggplot(aes(rate, fill = case))+
geom_histogram(data = miasta.for.analysis_2, fill = "lightgrey", bins = 17)+
geom_histogram(bins = 17)+
facet_wrap(~case)+
theme_bw()
Данный график трудно читать, так что я добавлю такое же, но с отлогарифмированными осями:
miasta.for.analysis %>%
filter(rate > 0) %>%
ggplot(aes(rate, fill = case))+
geom_histogram(data = miasta.for.analysis_2, fill = "lightgrey", bins = 17)+
geom_histogram(bins = 17)+
facet_wrap(~case)+
theme_bw() +
scale_y_log10()
Как следует читать данные графики? Серым цветом обозначена гистограмма всей выборки долей, без учета падежа. Цветом же показано, какой вклад вносит каждый падеж в создание общей гистограммы. Исследуя данный график можно сделать два наблюдения:
- во-первых, падежи делятся на те, которые чаще имеют маленькую долю (acc, dat, inst, voc), и на те, которые чаще имеют долю в промежутке между 0.2 и 0.6 (gen, nom, loc);
- во-вторых, некоторые города имеют в именительном падеже очень высокую долю близкую к единице (что в свою очередь означает, что они почти не выступают в других падежах).
Первый факт достаточно легко объяснить тем, что в польском латив и элатив маркируется предлогами do и z, управляющими родительным падежом, а эссив маркируется предлогом w, управляющий местным падежом. В целом есть множество разных значений, которые оказались вне данной сильно упрощенной схемы, однако в первом приближении такое объяснение принять можно.
Второй факт следует рассматреть отдельно. Вот список городов с высокой долей разных падежей:
- gen: Ostrów Wielkopolski, Siedlce
- nom: Ruda Śląska, Starogard Gdański, Zielona Góra, Kędzierzyn-Koźle, Tarnowskie Góry
Видимо, Siedlce, действительно представлены так в корпусе, а все остальные названия, видимо, неправильно обрабатывались морфологическим парсером. Избавляемся от них и строим графики заново:
miasta %>%
gather(case, rate, acc:voc) %>%
filter(rate < 1) ->
miasta.for.analysis
miasta.for.analysis_2 <- miasta.for.analysis[,-7]
miasta.for.analysis %>%
ggplot(aes(rate, fill = case))+
geom_histogram(data = miasta.for.analysis_2, fill = "lightgrey", bins = 17)+
geom_histogram(bins = 17)+
facet_wrap(~case)+
theme_bw()
И с отлогарифмированной осью:
miasta.for.analysis %>%
filter(rate > 0) %>%
ggplot(aes(rate, fill = case))+
geom_histogram(data = miasta.for.analysis_2, fill = "lightgrey", bins = 17)+
geom_histogram(bins = 17)+
facet_wrap(~case)+
theme_bw() +
scale_y_log10()
Может быть какой-то падеж коррелирует с количеством носителей? (Спасибо Ване Левину за этот вопрос).
library(PerformanceAnalytics)
miasta %>%
select(5:12) %>%
chart.Correlation(histogram = F, pch = ".")
Но все же в моих данных много размерностей, так что нужен способ их уменьшить. Так как данные числовые — PCA. Давайте посмотрим на биплот (более крупный вариант доступен здесь):
library(ggfortify)
miasta.for.pca <- miasta[,6:12]
row.names(miasta.for.pca) <- miasta$town.names
autoplot(prcomp(miasta.for.pca),
shape = F,
label = T,
label.size = 2,
loadings = T,
loadings.label = T)+
theme_bw()
В догонку к графику, обычно принято показывать, какой вклад вносят компоненты в объяснение изменчивости:
summary(prcomp(miasta.for.pca))
Importance of components:
PC1 PC2 PC3 PC4 PC5
Standard deviation 0.2278 0.2057 0.08500 0.01083 0.001372
Proportion of Variance 0.5111 0.4166 0.07116 0.00115 0.000020
Cumulative Proportion 0.5111 0.9277 0.99882 0.99998 0.999990
PC6 PC7
Standard deviation 0.0007626 3.908e-17
Proportion of Variance 0.0000100 0.000e+00
Cumulative Proportion 1.0000000 1.000e+00
Как видно из summary, уже первые две компоненты объясняют 92 процента всей изменчивости исходных данных.
Что нам говорит график биплот? Видимо, в наших данных нет четких кластеров, т. е. есть ядро и несколько переферий: с одной стороны видны Tarnowskie Góry и т. п., которые имеют максимальную долю в именительном падеже, с другой стороны Ostrów Wielkopolski, который имеет максимальную долю в родительном падеже, с третьей стороны Bydgoszcz, имеющий максимум в местном падеже. Переферия городов, имеющих много форм именительного и родительного падежа, но совсем мало местного падежа, кажется чуть больше.
Создадим переменную, отличающую города по степени переферичности.
miasta$core <- NA
miasta$core[-c(8, 42, 33, 94, 4, 13,22, 2, 46, 97, 31, 38, 39, 99, 77, 29, 56, 7, 73, 27, 64, 51, 63, 16, 20, 45, 112, 90, 3, 18, 114, 88, 72)] <- "core"
miasta$core[c(8, 42, 33, 94, 4, 13,22,2, 46, 97,31, 39, 38, 99, 77, 29, 56, 7, 73, 27, 64, 51, 63, 16, 20, 45, 112, 90, 3, 18, 114, 88, 72)] <- "periphery"
autoplot(prcomp(miasta.for.pca), data = miasta, colour = 'core', shape = FALSE, label.size = 3)+
theme_bw()
Видимо, выделенная черта, не связанна с географией.
set.seed(11)
map.feature(languages = "Polish",
features = miasta$core,
popup = miasta$town.names,
latitude = miasta$lat,
longitude = miasta$long)
Видимо, выделенная черта, не связанна с количеством населения.
miasta %>%
ggplot(aes(core, ludnosc_.31.12.2014., label = town.names))+
geom_violin(fill = "lightblue")+
geom_jitter(width = 0.3)+
theme_bw()+
ylab("количество человек (31.12.2014)")
LS0tCnRpdGxlOiAi0JvQuNC90LPQstC40YHRgtC40YfQtdGB0LrQuNC1INC/0LDQutC10YLRiyDQsiBSOiDQv9Cw0LTQtdC20L3Ri9C1INC/0YDQtdC00L/QvtGH0YLQtdC90LjRjyDQv9C+0LvRjNGB0LrQuNGFINCz0L7RgNC+0LTQvtCyIgphdXRob3I6ICLQky4g0JzQvtGA0L7QtywgMjEg0L7QutGC0Y/QsdGA0Y8gMjAxNiwgW2h0dHBzOi8vZ29vLmdsL1doMFdVcV0oaHR0cHM6Ly9nb28uZ2wvV2gwV1VxKSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBnaXRodWJfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgojIyMgMC4g0JLQstC10LTQtdC90LjQtQpb0J3QsNGG0LjQvtC90LDQu9GM0L3Ri9C5INC60L7RgNC/0YPRgSDQv9C+0LvRjNGB0LrQvtCz0L4g0Y/Qt9GL0LrQsF0oaHR0cDovL25ranAucGwvcG9saXFhcnAvKSAtLS0g0LLQtdGJ0Ywg0LTQvtGB0YLQsNGC0L7Rh9C90L4g0L3QtdGD0LTQvtCx0L3QsNGPLiDQndCw0YHRgtGA0L7QudC60Lgg0LIg0L7QtNC90L7QvCDQvNC10YHRgtC1LCDQstGL0LTQsNGH0LAg0LIg0LTRgNGD0LPQvtC8LCDRgdC60LDRh9Cw0YLRjCDQvNC+0LbQvdC+INGC0L7Qu9GM0LrQviDQsiBodG1sICjRhdC+0YLRjyDQvtCx0LXRidCw0Y7Rgiwg0YfRgtC+INC80L7QttC90L4g0Lgg0LIgRXhjZWwpLiDQmtCw0Log0LHRi9C70L4g0YHQu9Cw0LLQvdC+LCDQtdGB0LvQuCDQsdGLINC80L7QttC90L4g0LHRi9C70L4g0YHRgNCw0LfRgyDRgdC+0LHQuNGA0LDRgtGMINCyIFIg0LLRi9C00LDRh9GDINC4INC10LUg0YLQsNC8INCw0L3QsNC70LjQt9C40YDQvtCy0LDRgtGMPwoKIyMjIDEuIEFQSSDQtNC70Y8g0L/QvtC70YzRgdC60L7Qs9C+INC60L7RgNC/0YPRgdCwCtCU0LvRjyDRgtC+0LPQviwg0YfRgtC+0LHRiyDRgNC10YjQuNGC0Ywg0LTQsNC90L3Rg9GOINC/0YDQvtCx0LvQtdC80YMg0Y8g0L3QsNC/0LjRgdCw0LsgQVBJICjQsiDRjdGC0L7QvCDQvNC90LUg0L3QtdC80L3QvtCz0L4g0L/QvtC80L7QsyAqKtCU0LDQvdGPINCQ0LvQtdC60YHQtdC10LLRgdC60LjQuSoqLCDRgdC/0LDRgdC40LHQviEpLiDQotCw0Log0YfRgtC+INGPINC90LDQv9C40YHQsNC7INC90LAgUiDQtNC+0YHRgtCw0YLQvtGH0L3QviDQvdC10YPQutC70Y7QttGD0Y4sINC90LDQstC10YDQvdC+0LUsIFvRhNGD0L3QutGG0LjRjiBgcGwuY29ycHVzYF0oaHR0cHM6Ly9naXRodWIuY29tL2Fncmljb2xhbXovbGluZ2NvcnBvcmEvYmxvYi9tYXN0ZXIvcGwuY29ycHVzLlIpLgoKYGBge3IgcGwuY29ycHVzIC0tLSBBUEkg0LTQu9GPINC/0L7Qu9GM0YHQutC+0LPQviDQutC+0YDQv9GD0YHQsCwgZXZhbD1GQUxTRSwgY29sbGFwc2U9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBsLmNvcnB1cyA8LSBmdW5jdGlvbih4LCB0YWcgPSBGLCBuLnJlc3VsdHMgPSAxMDAsIGNvcnB1cyA9ICJua2pwMzAwIil7CiAgbGlicmFyeSh4bWwyKQogIGxpYnJhcnkocnZlc3QpCiAgbGlicmFyeShodHRyKQogIAogIGlmKGxlbmd0aCh4KSAhPSAxKXsKICAgIHdhcm5pbmcoJ3ggbXVzdCBiZSBvZiBsZW5ndGggMS4gSWYgeW91IHdhbnQgYSBkYXRhZnJhbWUgd2l0aCBkaWZmZXJlbnQgcXVlcmllcyB0cnkgXG4gZG8uY2FsbCgicmJpbmQuZGF0YS5mcmFtZSIsIHNhcHBseSh4LCBwbC5jb3JwdXMsIHNpbXBsaWZ5ID0gRikpJykKICB9CiAgIyBzaG93IHRhZ3M/CiAgaWYodGFnID09IFQpewogICAgdGFnLnZhcmlhYmxlIDwtICJzbHQiCiAgfSBlbHNlIHt0YWcudmFyaWFibGUgPC0gInMifQogIAogICMgc2V0IG5ranAucGwgc2V0dGluZ3MKICBzZXR0aW5ncyA8LSBodHRyOjpQT1NUKHVybCA9ICJodHRwOi8vbmtqcC5wbC9wb2xpcWFycC9zZXR0aW5ncy8iLAogICAgICAgICAgICAgICAgICAgICAgICAgYm9keSA9IGxpc3QoCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbV9zYW1wbGUgPSAiMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbV9zYW1wbGVfc2l6ZSA9ICI1MCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvcnRfY29sdW1uID0gInJtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc29ydF90eXBlID0gImFmcm9udGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzb3J0X2RpcmVjdGlvbiA9ICJhc2MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2luX21hdGNoID0gdGFnLnZhcmlhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2luX2NvbnRleHQgPSB0YWcudmFyaWFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnRfY29udGV4dF93aWR0aCA9ICIxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0X2NvbnRleHRfd2lkdGggPSAiMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICB3aWRlX2NvbnRleHRfd2lkdGggPSAiNTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzX3Blcl9wYWdlID0gYXMuY2hhcmFjdGVyKG4ucmVzdWx0cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGBuZXh0YCA9ICIvcG9saXFhcnAvIikpCiAgCiAgIyBnZXQgcmVxdWVzdCBkYXRhCiAgcmVxdWVzdCA8LSBodHRyOjpQT1NUKHVybCA9ICJodHRwOi8vbmtqcC5wbC9wb2xpcWFycC9xdWVyeS8iLAogICAgICAgICAgICAgICAgICAgICAgICBib2R5ID0gbGlzdChxdWVyeSA9IHgsIGNvcnB1cyA9IGNvcnB1cyksCiAgICAgICAgICAgICAgICAgICAgICAgIHNldF9jb29raWVzKGRvbWFpbiA9ICIjSHR0cE9ubHlfbmtqcC5wbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZsYWcgPSAiRkFMU0UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gIi8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWN1cmUgPSAiRkFMU0UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBpcmF0aW9uID0gIjxOQT4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gInNlc3Npb25pZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gYXMuY2hhcmFjdGVyKHNldHRpbmdzJGNvb2tpZXNbN10pKSkgIyBjb29raWVzIGZyb20gc2V0dGluZ3MKICAKICAjIGdldCBkYXRhCiAgbXkudXJsIDwtIGh0dHI6OkdFVCh1cmwgPSAiaHR0cDovL25ranAucGwvcG9saXFhcnAvbmtqcDMwMC9xdWVyeS8iLAogICAgICAgICAgICAgICAgICAgICAgc2V0X2Nvb2tpZXMoZG9tYWluID0gIiNIdHRwT25seV9ua2pwLnBsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZsYWcgPSAiRkFMU0UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9ICIvIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlY3VyZSA9ICJGQUxTRSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBpcmF0aW9uID0gIjxOQT4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJzZXNzaW9uaWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBhcy5jaGFyYWN0ZXIocmVxdWVzdCRjb29raWVzWzddKSkpICMgY29va2llcyBmcm9tIHJlcXVlc3QKICAKICAjIGNoZWNrIGZvciBlcnJvcnMKICB4bWwyOjpyZWFkX2h0bWwobXkudXJsKSAlPiUgCiAgICBodG1sX25vZGVzKCIuZXJyb3JsaXN0ID4gbGk6bnRoLWNoaWxkKDEpIikgJT4lCiAgICBodG1sX3RleHQoKSAtPiAKICAgIGVycm9ybGlzdAogIAogIGlmKGxlbmd0aChlcnJvcmxpc3QpID4gMCl7CiAgICB3YXJuaW5nKGVycm9ybGlzdCkKICB9CiAgCiAgIyBjaGVjayBmb3Igbm8gcmVzdWx0CiAgeG1sMjo6cmVhZF9odG1sKG15LnVybCkgJT4lIAogICAgaHRtbF9ub2RlcygiLnF1ZXJ5LXJlc3VsdHMgPiBwOm50aC1jaGlsZCgyKSIpICU+JQogICAgaHRtbF90ZXh0KCkgLT4gCiAgICBudW1iZXIucmVzdWx0cwogIGlmKGxlbmd0aChudW1iZXIucmVzdWx0cykgPiAxKXsKICAgIGlmKGdyZXBsKHBhdHRlcm4gPSAiRm91bmQgMCByZXN1bHRzIiwgbnVtYmVyLnJlc3VsdHMpKXsKICAgICAgd2FybmluZyhwYXN0ZSgnTm8gcmVzdWx0cyB3ZXJlIHJldHVybmVkIGJ5IHRoZSBxdWVyeSAiJywgeCwgJyInLCBzZXAgPSAiIikpCiAgICB9fQogIAogICMgZ2V0IGxlZnQgcGFydAogIHhtbDI6OnJlYWRfaHRtbChteS51cmwpICU+JSAKICAgIGh0bWxfbm9kZXMoInRkOm50aC1jaGlsZCgyKSIpICU+JQogICAgaHRtbF90ZXh0KCkgLT4gCiAgICBsZWZ0LnBhcnQKICBsZWZ0LnBhcnQgPC0gZ3N1YigiXFxzKyIsICIgIiwgbGVmdC5wYXJ0KSAjIGNsZWFuIGRhdGEKICAKICAjIGdldCBxdWVyeSB3b3JkCiAgeG1sMjo6cmVhZF9odG1sKG15LnVybCkgJT4lIAogICAgaHRtbF9ub2RlcygidGQ6bnRoLWNoaWxkKDMpIikgJT4lCiAgICBodG1sX3RleHQoKSAtPiAKICAgIGNlbnRlci5wYXJ0CiAgY2VudGVyLnBhcnQgPC0gZ3N1YigiXFxzKyIsICIgIiwgY2VudGVyLnBhcnQpICMgY2xlYW4gZGF0YQogIAogICMgZ2V0IHJpZ2h0IHBhcnQKICB4bWwyOjpyZWFkX2h0bWwobXkudXJsKSAlPiUgCiAgICBodG1sX25vZGVzKCJ0ZDpudGgtY2hpbGQoNCkiKSAlPiUKICAgIGh0bWxfdGV4dCgpIC0+IAogICAgcmlnaHQucGFydAogIHJpZ2h0LnBhcnQgPC0gZ3N1YigiXFxzKyIsICIgIiwgcmlnaHQucGFydCkgIyBjbGVhbiBkYXRhCiAgCiAgcmVzdWx0cyA8LSBkYXRhLmZyYW1lKGxlZnQucGFydCwgY2VudGVyLnBhcnQsIHJpZ2h0LnBhcnQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQogIHJldHVybihyZXN1bHRzKX0KYGBgCgrQp9GC0L7QsdGLINC90LUg0LfQsNGB0YLQsNCy0LvRj9GC0Ywg0YfQuNGC0LDRgtC10LvRjyDRgNCw0LfQsdC40YDQsNGC0YzRgdGPINCyINC60L7QtNC1LCDQv9C+0Y/RgdC90Y4sINGH0YLQviDQsiDRgNC10LfRg9C70YzRgtCw0YLQtSDQsiDQstCw0YjQtdC8INC+0LrRgNGD0LbQtdC90LjQuCDQv9C+0Y/QstC70Y/QtdGC0YHRjyDRhNGD0L3QutGG0LjRjyBgcGwuY29ycHVzYCDRgdC+INGB0LvQtdC00YPRjtGJ0LjQvNC4INCw0YDQs9GD0LzQtdC90YLQsNC80Lg6CgoqIGB4YCAtLS0g0LfQsNC/0YDQvtGBICjQvtCx0Y/Qt9Cw0YLQtdC70YzQvdGL0Lkg0LDRgNCz0YPQvNC10L3Rgik7CiogYHRhZ2AgLS0tINC70L7Qs9C40YfQtdGB0LrQuNC5INCy0LXQutGC0L7RgCwg0L7RgtCy0LXRh9Cw0Y7RidC40Lkg0LfQsCDRgtC+LCDQvdGD0LbQvdGLINC70Lgg0LIg0LLRi9C00LDRh9C4INC80L7RgNGE0L7Qu9C+0LPQuNGH0LXRgdC60LjQtSDRgtC10LPQuCDQuNC70Lgg0L3QtdGCOwoqIGBuLnJlc3VsdHNgIC0tLSDQv9C10YDQtdC80LXQvdC90LDRjyDQvtGC0LLQtdGH0LDRjtGJ0LDRjyDQt9CwINC80LDQutGB0LjQvNCw0LvRjNC90L7QtSDQutC+0LvQuNGH0LXRgdGC0LLQviDQv9GA0LjQvNC10YDQvtCyINCyINCy0YvQtNCw0YfQtQoqIGBjb3JwdXNgIC0tLSDQstC10LrRgtC+0YAsINC+0L/RgNC10LTQtdC70Y/RjtGJ0LjQuSDQv9C+0LTQutC+0YDQv9GD0YEsINCyINC60L7RgtC+0YDQvtC8INGB0LvQtdC00YPQtdGCINC40YHQutCw0YLRjCAo0LLQvtC30LzQvtC20L3Ri9C1INC30L3QsNGH0LXQvdC40Y86IGAibmtqcDMwMCJgLCBgIm5ranAxODAwImAsIGAibmtqcDFNImAsIGAiaXBpMjUwImAsIGAiaXBpMDMwImAsIGAiZnJlcXVlbmN5LWRpY3Rpb25hcnkiYCkKCtCf0YDQuNCy0LXQtNGDINC/0YDQuNC80LXRgCDRgNCw0LHQvtGC0Ysg0YTRg9C90LrRhtC40Lg6CmBgYHtyINC40YHQv9C+0LvRjNC30L7QstCw0L3QuNC1IHBsLmNvcnB1cyAxLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmhlYWQocGwuY29ycHVzKCJ3aXRhbSIpKQpgYGAKCmBgYHtyINC40YHQv9C+0LvRjNC30L7QstCw0L3QuNC1IHBsLmNvcnB1cyAyLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmhlYWQocGwuY29ycHVzKCJBbiphIiwgdGFnID0gVCkpCmBgYApgYGB7ciDQuNGB0L/QvtC70YzQt9C+0LLQsNC90LjQtSBwbC5jb3JwdXMgMywgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpoZWFkKHBsLmNvcnB1cygiW2Jhc2UgPSAnd2l0YcSHJ10iKSkKYGBgCtCa0LDQuiDQstC40LTQvdC+INC40Lcg0L/RgNC40LzQtdGA0L7Qsiwg0YTRg9C90LrRhtC40Y8g0L/QvtC90LjQvNCw0LXRgiDRgdCw0LzRi9C1INGA0LDQt9C90YvQtSDQt9Cw0L/RgNC+0YHRizoKCiog0L/RgNC+0YHRgtGL0LUKKiDRgNC10LPRg9C70Y/RgNC90YvQvNC4INCy0YvRgNCw0LbQtdC90LjRj9C80LgKKiBDb3JwdXMgUXVlcnkgTGFuZ3VhZ2UgQ1FMCgojIyMgMi4g0JTQsNC90L3Ri9C1CtCU0LDQvdC90YvQtSDQviDQv9C+0LvRjNGB0LrQuNGFINCz0L7RgNC+0LTQsNGFINGPINCy0LfRj9C7INC40LcgW9CS0LjQutC40L/QtdC00LjQuF0oaHR0cHM6Ly9wbC53aWtpcGVkaWEub3JnL3dpa2kvTWlhc3RhX3dfUG9sc2NlXyhzdGF0eXN0eWtpKSkuINCR0YvQu9C4INCy0YvQsdGA0LDQvdGLINCy0YHQtSDQs9C+0YDQvtC00LAg0YEg0L3QsNGB0LXQu9C10L3QuNC10Lwg0LHQvtC70YzRiNC1IDM1NTAwLgoKYGBge3IsIGVjaG89VFJVRX0KbGlicmFyeShsaW5ndHlwb2xvZ3kpCm1pYXN0YSA8LSByZWFkLmNzdigiaHR0cHM6Ly9nb28uZ2wvMXpaZ09hIikKbWFwLmZlYXR1cmUobGFuZ3VhZ2VzID0gIlBvbGlzaCIsCiAgICAgICAgICAgIHBvcHVwID0gbWlhc3RhJHRvd24ubmFtZXMsCiAgICAgICAgICAgIGxhdGl0dWRlID0gbWlhc3RhJGxhdCwKICAgICAgICAgICAgbG9uZ2l0dWRlID0gbWlhc3RhJGxvbmcsCiAgICAgICAgICAgIGNvbnRyb2wgPSBGKQpgYGAKCtCa0LDQuiDQstC40LTQvdC+INC40Lcg0LrQvtC00LAsINC00LvRjyDRgdC+0LfQtNCw0L3QuNGPINC00LDQvdC90L7QuSDQutCw0YDRgtGLINGC0YDQtdCx0YPQtdGC0YHRjyDQvdCw0L/QuNGB0LDQvdC90YvQuSDQvNC90L7QuSDQv9Cw0LrQtdGCIFtgbGluZ3R5cG9sb2d5YF0oaHR0cHM6Ly9naXRodWIuY29tL2Fncmljb2xhbXovbGluZ3R5cG9sb2d5L3dpa2kpLiDQlNCw0L3QvdGL0Lkg0L/QsNC60LXRgiDQv9C+0LfQstC+0LvRj9C10YIg0YDQuNGB0L7QstCw0YLRjCDQutCw0YDRgtGLINC90LAg0L7RgdC90L7QstC1INC90LDQt9Cy0LDQvdC40Lkg0Y/Qt9GL0LrQvtCyLCDQstGB0YLQsNCy0LvRj9C10YIg0YHRgdGL0LvQutC4INC90LAg0LTQsNC90L3Ri9C1INGP0LfRi9C60Lgg0LIg0LHQsNC30LUg0LTQsNC90L3Ri9GFIFtHbG90dG9sb2ddKGh0dHA6Ly9nbG90dG9sb2cub3JnLykuCgrQlNC70Y8g0LTQsNC70YzQvdC10LnRiNC10LPQviDQuNGB0YHQu9C10LTQvtCy0LDQvdC40Y8g0YHQu9C10LTRg9C10YIg0L/QvtGB0YLRgNC+0LjRgtGMINGB0L/QuNGB0L7QuiDQt9Cw0L/RgNC+0YHQvtCyLCDQutC+0YLQvtGA0YvQtSDQsdGLINC80L7QttC90L4g0LHRi9C70L4g0LLRgdGC0LDQstC40YLRjCDQsiDRhNGD0L3QutGG0LjRjiBgcGwuY29ycHVzYC4g0JfQtNC10YHRjCDRgtCw0LjQu9C+0YHRjCDQvNC90L7QttC10YHRgtCy0L4g0L/RgNC+0LHQu9C10LwsINGB0LLRj9C30LDQvdC90YvRhSDRgSDQvtGB0L7QsdC10L3QvdC+0YHRgtGM0Y4g0LrQvtGA0L/Rg9GB0LA6CgoqINCyINGB0LDQvNC+0Lwg0L/RgNC+0YHRgtC+0Lwg0YHQu9GD0YfQsNC1INC00L7RgdGC0LDRgtC+0YfQvdC+INCx0YvQu9C+INC70LjRiNGMINC90LDQv9C40YHQsNGC0Ywg0L3QsNC30LLQsNC90LjQtSDQs9C+0YDQvtC00LAKICAgICsgYFtiYXNlID0gJ0tyYWvDs3cnXWAKKiDQuNC90L7Qs9C00LAg0L/RgNC40YXQvtC00LjQu9C+0YHRjCDQvNC10L3Rj9GC0Ywg0LHQvtC70YzRiNGD0Y4g0LHRg9C60LLRgyDQvdCwINC80LDQu9C10L3RjNC60YPRjgogICAgKyBgW2Jhc2UgPSAnd2Fyc3phd2EnXWAKKiDQstGB0LUg0LPQvtGA0L7QtNCwLCDRgdC+0LTQtdGA0LbQsNGJ0LjQtSDQtNC10YTQuNGBLCDRgdC70LXQtNC+0LLQsNC70L4g0YDQsNC30LTQtdC70LjRgtGMINC90LAg0LTQstCwINC+0YLQtNC10LvRjNC90YvRhSDRgdC70L7QstCwCiAgICArIGBbYmFzZSA9ICdCaWVsc2tvJ10gW2Jhc2UgPSAnQmlhxYJhJ11gCiog0L3QtdC60L7RgtC+0YDRi9C1INCz0L7RgNC+0LTQsCDQu9C40LHQviDRhtC10LvQuNC60L7QvCwg0LvQuNCx0L4g0YfQsNGB0YLQuNGH0L3QviDRgdC+0LLQv9Cw0LTQsNC70Lgg0YEg0LrQsNC60LjQvNC4LdGC0L4g0L/QvtC70YzRgdC60LjQvNC4INGB0LvQvtCy0LDQvNC4INC4INGC0LDQuiDRhdGA0LDQvdC40LvQuNGB0Ywg0LIg0L/QvtC70YzRgdC60L7QvCDQutC+0YDQv9GD0YHQtSwg0LIg0YLQsNC60L7QvCDRgdC70YPRh9Cw0LUg0Y8g0YLRgNC10LHQvtCy0LDQuyDQvdCw0L/QuNGB0LDQvdC40Y8g0YEg0LHQvtC70YzRiNC+0Lkg0LHRg9C60LLRiwogICAgKyBgW2Jhc2UgPSAncnVkeScgJiBvcnRoID0gJ1J1ZC4qJ10gW2Jhc2UgPSAnxZpsxIVzayddYAoqINC90LXRgdC60L7Qu9GM0LrQviDQs9C+0YDQvtC00L7QsiDQv9GA0LjRiNC70L7RgdGMINCy0YvQutC40L3Rg9GC0Yw6CiAgICArINC40Lct0LfQsCDRgdC+0LLQv9Cw0LTQtdC90LjQuSAoQ2hyemFuw7N3LCBKYXJvc8WCYXcpCiAgICArINC40Lct0LfQsCDQvtGI0LjQsdC60Lgg0LIg0LrQvtGA0L/Rg9GB0LUgYFJhZG9tc2tvIFtyYWRvbXNrbzphZHY6cG9zXWAsINC90L4gYFJhZG9tc2thIFtyYWRvbXNraTphZGo6c2c6bm9tOmY6cG9zXWAgKEtudXLDs3csIFJhZG9tc2tvKQrQkiDRgNC10LfRg9C70YzRgtCw0YLQtSDQutCw0LbQtNGL0Lkg0LfQsNC/0YDQvtGBINC/0YDQuNGI0LvQvtGB0Ywg0L/RgNC+0LLQtdGA0Y/RgtGMLCDRgtCw0Log0YfRgtC+INGA0LXQt9GD0LvRjNGC0LDRgiDRjdGC0L7QuSDRgNCw0LHQvtGC0Ysg0LfQsNC/0LjRgdCw0L0g0LIg0LHQsNC30LU6CgpgYGB7ciwgZWNobz1UUlVFfQpoZWFkKG1pYXN0YSRxdWVyeSkKYGBgCgrQn9C+0YHQu9C1INC+0LHRgNCw0LHQvtGC0LrQuCDRhNGD0L3QutGG0LjQtdC5IGBwbC5jb3JwdXNgINCy0YHQtdGFINC30LDQv9GA0L7RgdC+0LIg0L/QvtC70YPRh9C40LvQsNGB0YwgW9Cx0LDQt9CwINC00LDQvdC90YvRhSwg0YHQvtGB0YLQvtGP0YnQsNGPINC40LcgOTkxMjkg0L/RgNC40LzQtdGA0L7Qsl0oaHR0cHM6Ly9nb28uZ2wvenUzYVRDKSwg0L/QvtC70YPRh9C10L3QvdGL0YUg0L/QviDRiNCw0LHQu9C+0L3QvdC+0LzRgyDQt9Cw0L/RgNC+0YHRgzoKYGBge3IsIGVjaG89VFJVRX0KaGVhZChwbC5jb3JwdXMobWlhc3RhJHF1ZXJ5WzQyXSwgdGFnID0gVCwgbi5yZXN1bHRzID0gMTAwMCkpCmBgYAoKIyMjIDMuINCe0LHRgNCw0LHQvtGC0LrQsCDQtNCw0L3QvdGL0YUK0JTQu9GPINC+0LHRgNCw0LHQvtGC0LrQuCDQtNCw0L3QvdGL0YUg0Y8g0L3QsNC/0LjRgdCw0Lsg0LTQstC1INGE0YPQvdC60YbQuNC4IGBwbC5iYXNlYCDQuCBgcGwuY2FzZWAuCmBgYHtyLCBlY2hvPVRSVUV9CnBsLmJhc2UgPC0gZnVuY3Rpb24oeCl7CiAgb3V0IDwtIGMoKQogIGZvcihqIGluIHNlcV9hbG9uZyh4KSkgewogICAgaWYoZ3JlcGwoIlxcWy4qOiIsIHhbal0pKXsKICAgICAgb3V0W2pdIDwtIHVubGlzdChzdHJzcGxpdCh1bmxpc3Qoc3Ryc3BsaXQoeFtqXSwgIlxcWyIpKVsyXSwgIlxcOiIpKVsxXQogICAgfSBlbHNlIHsKICAgICAgd2FybmluZyhwYXN0ZTAoJ05vIHRhZ3Mgd2VyZSBmb3VuZCBpbiB0aGUgcXVlcnkgIicsIHgsICciJykpCiAgICB9fQogIHJldHVybihvdXQpCn0KYGBgCgoKYGBge3IsIGVjaG89VFJVRX0KcGwuY2FzZSA8LSBmdW5jdGlvbih4KXsKICBvdXQgPC0gYygpCiAgZm9yKGogaW4gc2VxX2Fsb25nKHgpKSB7CiAgICBpZihncmVwbCgiXFxbLio6IiwgeFtqXSkpewogICAgICBvdXRbal0gPC0gdW5saXN0KHN0cnNwbGl0KHhbal0sICJcXDoiKSlbNF0KICAgIH0gZWxzZSB7CiAgICAgIHdhcm5pbmcocGFzdGUwKCdObyB0YWdzIHdlcmUgZm91bmQgaW4gdGhlIHF1ZXJ5ICInLCB4LCAnIicpKQogICAgfX0KICByZXR1cm4ob3V0KQp9CmBgYAoK0KTRg9C90LrRhtC40Y8gYHBsLmJhc2VgINC/0L7Qt9Cy0L7Qu9GP0LXRgiDQstGL0LTQtdC70Y/RgtGMINC+0YHQvdC+0LLRgzoKCmBgYHtyLCBlY2hvPVRSVUV9CnBsLmJhc2UoIldyb2PFgmF3aWEgW1dyb2PFgmF3OnN1YnN0OnNnOmdlbjptM10iKQpgYGAKCtCk0YPQvdC60YbQuNGPIGBwbC7RgWFzZWAg0L/QvtC30LLQvtC70Y/QtdGCINCy0YvQtNC10LvRj9GC0Ywg0L/QsNC00LXQtjoKCmBgYHtyLCBlY2hvPVRSVUV9CnBsLmNhc2UoIldyb2PFgmF3aWEgW1dyb2PFgmF3OnN1YnN0OnNnOmdlbjptM10iKQpgYGAKCtCU0LvRjyDQtNCw0LvRjNC90LXQudGI0LXQs9C+INCw0L3QsNC70LjQt9CwINC/0L7QvdCw0LTQvtCx0LjRgtGM0YHRjyDQv9Cw0LrQtdGCIGBkYXRhLnRhYmxlYCwg0LrQvtGC0L7RgNGL0Lkg0L/QvtC30LLQvtC70Y/QtdGCINGA0LDQsdC+0YLQsNGC0Ywg0YEg0LHQsNC70YzRiNC40LzQuCDRhNCw0LnQu9Cw0LzQuCDQuCDQv9Cw0LrQtdGCIGBkdHBseXJgLCDQutC+0YLQvtGA0YvQuSDQv9C+0LfQstC+0LvRj9C10YIg0YPQtNC+0LHQvdC+INC+0LHRgNCw0LHQsNGC0YvQstCw0YLRjCDQtNCw0L3QvdGL0LUuINCd0LXQvtCx0YDQsNCx0L7RgtCw0L3QvdGL0LUg0LTQsNC90L3Ri9C1LCDQutC+0YLQvtGA0YvQtSDQsdGD0LTRg9GCINC00LDQu9GM0YjQtSDQsNC90LDQu9C40LfQuNGA0L7QstCw0YLRjNGB0Y8g0LzQvtC20L3QviDRgdC60LDRh9Cw0YLRjCBb0LfQtNC10YHRjF0oaHR0cHM6Ly9nb28uZ2wvTTNCVDRsKS4KYGBge3IsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShkYXRhLnRhYmxlKTsgbGlicmFyeShkdHBseXIpCmRmIDwtIGZyZWFkKCJtb3JvejIwMTZfcG9sc2tpZV9taWFzdGFfcm93X2RhdGEuY3N2IiwgaGVhZGVyID0gVCkKYGBgCgrQodC+0LfQtNCw0LTQuNC8INC90L7QstGL0Lkg0LTQsNGC0LDRhNGA0LXQudC8INGBINC+0YHQvdC+0LLQsNC80Lgg0Lgg0L/QsNC00LXQttC+0Lw6CmBgYHtyLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpkZiAlPiUgCiAgbXV0YXRlKGJhc2UgPSBwbC5iYXNlKHF1ZXJ5KSkgJT4lIAogIG11dGF0ZShjYXNlID0gcGwuY2FzZShxdWVyeSkpICU+JSAKICBzZWxlY3QoYmFzZSwgY2FzZSkgJT4lIAogIGdyb3VwX2J5KGJhc2UsIGNhc2UpICU+JSAKICBzdW1tYXJpc2UobnVtYmVyID0gbigpKSAtPgogIGJhc2UuY2FzZQpoZWFkKGJhc2UuY2FzZSkKYGBgCgrQn9C+0YHRgtGA0L7QuNC8INC/0YDQvtGB0YLQvtC5INCz0YDQsNGE0LjQujoKYGBge3J9CmJhc2UuY2FzZSAlPiUgCiAgZ2dwbG90KGFlcyhjYXNlLCBudW1iZXIpKSsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCBmaWxsID0gImxpZ2h0Ymx1ZSIpKwogIHRoZW1lX2J3KCkKYGBgCgrQlNC70Y8g0LTQsNC70YzQvdC10LnRiNC10Lkg0YDQsNCx0L7RgtGLINC90LXQvtCx0YXQvtC00LzQviDRgdC+0LXQtNC40L3QuNGC0Ywg0LjQt9C90LDRh9Cw0LvRjNC90YPRjiDQsdCw0LfRgyAo0LIg0L/QtdGA0LXQvNC10L3QvdC+0LkgYG1pYXN0YWApINC4INC90L7QstGL0LUg0LTQsNC90L3Ri9C1ICjQsiDQv9C10YDQtdC80LXQvdC90L7QuSBgYmFzZS5jYXNlYCkuCgpgYGB7cn0KYmFzZS5jYXNlICU+JSAKICBzcHJlYWQoY2FzZSwgbnVtYmVyKSAtPgogIGJhc2UuY2FzZQpoZWFkKGJhc2UuY2FzZSkKYGBgCgrQotC10L/QtdGA0Ywg0LzQvtC20L3QviDQv9GA0LjRgdC+0LXQtNC40L3QuNGC0Ywg0L/QvtC70YPRh9C40LLRiNGD0Y7RgdGPINGC0LDQsdC70LjRhtGDINC6INGD0LbQtSDQuNC80LXRjtGJ0LXQudGB0Y8sINCy0YvQutC40L3Rg9CyINC/0LXRgNCy0YvQuSDQuCDQv9C+0YHQu9C10LTQvdC40Lkg0YHRgtC+0LvQsdC10YY6CmBgYHtyfQptaWFzdGEgPC0gY2JpbmQuZGF0YS5mcmFtZShtaWFzdGFbLTUyLF0sIGJhc2UuY2FzZVstNzMsXSlbLC1jKDYsIDE0KV0KaGVhZChtaWFzdGEpCmBgYAoK0J3QsNC00L4g0L7RgtC80LXRgtC40YLRjCwg0YfRgtC+INC90LUg0L/QviDQstGB0LXQvCDQt9Cw0L/RgNC+0YHQsNC8INCyINC60L7RgNC/0YPRgdC1INC90LDRiNC70LDRgdGMIDEwMDAg0L/RgNC40LzQtdGA0L7Qsiwg0YLQsNC6INGH0YLQviDQsNCx0YHQvtC70Y7RgtC90YvQtSDQt9C90LDRh9C10L3QuNGPINC60L7Qu9C40YfQtdGB0YLQstCwINC/0LDQtNC10LbQvdGL0YUg0YTQvtGA0Lwg0LTQu9GPINC60LDQttC00L7Qs9C+INCz0L7RgNC+0LTQsCDRgdGA0LDQstC90LjQstCw0YLRjCDQvNC10LbQtNGDINGB0L7QsdC+0Lkg0L3QtdGB0LrQvtC70YzQutC+INCx0LXRgdGB0LzRi9GB0LvQtdC90L3Qvi4g0J/QvtGN0YLQvtC80YMg0LfQsNC80LXQvdC40Lwg0LLRgdC1INC/0YDQvtC/0YPRidC10L3QvdGL0LUg0LfQvdCw0YfQtdC90LjRjyAoYE5BYCkg0L3QsCAwLCDQv9C+0YHRh9C40YLQsNC10Lwg0YHRg9C80LzRgyDQsNCx0YHQvtC70Y7RgtC90YvRhSDQt9C90LDRh9C10L3QuNC5INCyINC60LDQttC00L7QuSDRgdGC0YDQvtGH0LrQtSwg0LAg0L/QvtGC0L7QvCDQv9C10YDQtdCy0LXQtNC10Lwg0LDQsdGB0L7Qu9GO0YLQvdGL0LUg0LfQvdCw0YfQtdC90LjRjyDQutC+0LvQuNGH0LXRgdGC0LLQsCDQv9Cw0LTQtdC20LXQuSDQsiDQtNC+0LvQuC4KCmBgYHtyfQptaWFzdGFbaXMubmEobWlhc3RhKV0gPC0gMAoKZm9yKGkgaW4gMTpucm93KG1pYXN0YSkpewptaWFzdGEgJT4lCiAgICBzZWxlY3QoNjoxMikgJT4lCiAgICBzbGljZShpKSAlPiUgCiAgICBzdW0oKSAtPgogIG1pYXN0YSRuW2ldfQoKZm9yKGogaW4gMTpucm93KG1pYXN0YSkpewogIG1pYXN0YSAlPiUKICAgIHNlbGVjdCg2OjEyKSAlPiUKICAgIHNsaWNlKGopICU+JSAKICAgIHByb3AudGFibGUoKSAtPgogICAgbWlhc3RhW2osNjoxMl19CmhlYWQobWlhc3RhKQpgYGAKYGBge3IsIGluY2x1ZGU9RkFMU0V9CnJtKGkpOyBybShqKQpgYGAKCtCSINGA0LXQt9GD0LvRjNGC0LDRgtC1INC00LDQvdC90YvRhSDQvtC/0LXRgNCw0YbQuNC5INCy0L7Qt9C90LjQutC70Lgg0L3QtdC60L7RgtC+0YDRi9C1INC90LXQv9GA0LDQstC40LvRjNC90YvQtSDQt9C90LDRh9C10L3QuNGPIGBOYU5gLiDQrdGC0L4g0YHQstGP0LfQsNC90L4g0YEg0YLQtdC8LCDRh9GC0L4g0L3QtdC60L7RgtC+0YDRi9C1INCz0L7RgNC+0LTQsCDQsiDQutC+0YDQv9GD0YHQtSDQvdC1INGA0LDRgdC/0L7Qt9C90LDQvdGLINC00L7Qu9C20L3Ri9C8INC+0LHRgNCw0LfQvtC8INC4INC40LzQtdGO0YIg0L7QtNC40L0g0LXQtNC40L3RgdGC0LLQtdC90L3Ri9C5INGC0LXQsyBgaWduYCAoWmF3aWVyY2llLCBDaG9qbmljZSkuINCY0LfQsdCw0LLQuNC80YHRjyDQvtGCINC00LDQvdC90YvRhSDRgdGC0YDQvtGH0LXQujoKCmBgYHtyfQptaWFzdGEgPC0gbWlhc3RhW2NvbXBsZXRlLmNhc2VzKG1pYXN0YSksXQpgYGAKCtCi0LXQv9C10YDRjCDQstGB0LUg0LTQsNC90L3Ri9C1ICjQsiDQuNGC0L7Qs9C1IDExNiDQs9C+0YDQvtC00L7Qsikg0YHQvtCx0YDQsNC90Ysg0LLQvtC10LTQuNC90L4g0Lgg0LzQvtC20L3QviDQv9GA0LjRgdGC0YPQv9Cw0YLRjCDQuiDQsNC90LDQu9C40LfRgy4KCiMjIyA0LiDQkNC90LDQu9C40Lcg0LTQsNC90L3Ri9GFCtCS0L4t0L/QtdGA0LLRi9GFLCDQutC+0L3QtdGH0L3Qviwg0YXQvtGH0LXRgtGB0Y8g0L/QvtGB0LzQvtGC0YDQtdGC0YwsINC60LDQutC40LUg0LfQvdCw0YfQtdC90LjRjyDQv9GA0LjQuNC80LDRjtGCINC/0L7Qu9GD0YfQuNCy0YjQuNC10YHRjyDQtNC+0LvQuDoKYGBge3J9Cm1pYXN0YSAlPiUKICBnYXRoZXIoY2FzZSwgcmF0ZSwgYWNjOnZvYykgLT4KbWlhc3RhLmZvci5hbmFseXNpcwptaWFzdGEuZm9yLmFuYWx5c2lzXzIgPC0gbWlhc3RhLmZvci5hbmFseXNpc1ssLTddCgptaWFzdGEuZm9yLmFuYWx5c2lzICU+JSAKICBnZ3Bsb3QoYWVzKHJhdGUsIGZpbGwgPSBjYXNlKSkrCiAgZ2VvbV9oaXN0b2dyYW0oZGF0YSA9IG1pYXN0YS5mb3IuYW5hbHlzaXNfMiwgZmlsbCA9ICJsaWdodGdyZXkiLCBiaW5zID0gMTcpKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAxNykrCiAgZmFjZXRfd3JhcCh+Y2FzZSkrCiAgdGhlbWVfYncoKQpgYGAK0JTQsNC90L3Ri9C5INCz0YDQsNGE0LjQuiDRgtGA0YPQtNC90L4g0YfQuNGC0LDRgtGMLCDRgtCw0Log0YfRgtC+INGPINC00L7QsdCw0LLQu9GOINGC0LDQutC+0LUg0LbQtSwg0L3QviDRgSDQvtGC0LvQvtCz0LDRgNC40YTQvNC40YDQvtCy0LDQvdC90YvQvNC4INC+0YHRj9C80Lg6CgpgYGB7cn0KbWlhc3RhLmZvci5hbmFseXNpcyAlPiUgCiAgZmlsdGVyKHJhdGUgPiAwKSAlPiUgCiAgZ2dwbG90KGFlcyhyYXRlLCBmaWxsID0gY2FzZSkpKwogIGdlb21faGlzdG9ncmFtKGRhdGEgPSBtaWFzdGEuZm9yLmFuYWx5c2lzXzIsIGZpbGwgPSAibGlnaHRncmV5IiwgYmlucyA9IDE3KSsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTcpKwogIGZhY2V0X3dyYXAofmNhc2UpKwogIHRoZW1lX2J3KCkgKwogIHNjYWxlX3lfbG9nMTAoKQpgYGAKCtCa0LDQuiDRgdC70LXQtNGD0LXRgiDRh9C40YLQsNGC0Ywg0LTQsNC90L3Ri9C1INCz0YDQsNGE0LjQutC4PyDQodC10YDRi9C8INGG0LLQtdGC0L7QvCDQvtCx0L7Qt9C90LDRh9C10L3QsCDQs9C40YHRgtC+0LPRgNCw0LzQvNCwXlvQodGD0YnQtdGB0YLQstGD0LXRgiDRgdGC0LDQvdC00LDRgNGC0L3QsNGPINC/0YDQvtCx0LvQtdC80LzQsCDRgSDQs9C40YHRgtC+0LPRgNCw0LzQvNC+0LksINGB0LLRj9C30LDQvdC90LDRjyDRgSDRgtGA0YPQtNC90L7RgdGC0YzRjiDRhNC+0YDQvNCw0LvQuNC30L7QstCw0YLRjCDQstGL0LHQvtGAINC60L7Qu9C40YfQtdGB0YLQstCwINGP0YfQtdC10Log0LPQuNGB0YLQvtCz0YDQsNC80LzRiy4g0KHRg9GJ0LXRgdGC0LLRg9C10YIg0L3QtdGB0LrQvtC70YzQutC+INC/0L7QtNGF0L7QtNC+0LIsINC30LTQtdGB0Ywg0Y8g0LLRi9Cx0YDQsNC7INCw0LvQs9C+0YDQuNGC0Lwg0LjQtyDRgNCw0LHQvtGC0YsgKEZyZWVkbWFuLCBEaWFjb25pcyAxOTgxKSwg0YHQvtCz0LvQsNGB0L3QviDQutC+0YLQvtGA0L7QvNGDINC00LvRjyDQuNGB0YHQu9C10LTRg9C10LzRi9GFINC00LDQvdC90YvRhSDRgdC70LXQtNGD0LXRgiDQuNGB0L/QvtC70YzQt9C+0LLQsNGC0YwgMTcg0Y/Rh9C10LXQui5dINCy0YHQtdC5INCy0YvQsdC+0YDQutC4INC00L7Qu9C10LksINCx0LXQtyDRg9GH0LXRgtCwINC/0LDQtNC10LbQsC4g0KbQstC10YLQvtC8INC20LUg0L/QvtC60LDQt9Cw0L3Qviwg0LrQsNC60L7QuSDQstC60LvQsNC0INCy0L3QvtGB0LjRgiDQutCw0LbQtNGL0Lkg0L/QsNC00LXQtiDQsiDRgdC+0LfQtNCw0L3QuNC1INC+0LHRidC10Lkg0LPQuNGB0YLQvtCz0YDQsNC80LzRiy4g0JjRgdGB0LvQtdC00YPRjyDQtNCw0L3QvdGL0Lkg0LPRgNCw0YTQuNC6INC80L7QttC90L4g0YHQtNC10LvQsNGC0Ywg0LTQstCwINC90LDQsdC70Y7QtNC10L3QuNGPOgoKKiDQstC+LdC/0LXRgNCy0YvRhSwg0L/QsNC00LXQttC4INC00LXQu9GP0YLRgdGPINC90LAg0YLQtSwg0LrQvtGC0L7RgNGL0LUg0YfQsNGJ0LUg0LjQvNC10Y7RgiDQvNCw0LvQtdC90YzQutGD0Y4g0LTQvtC70Y4gKGFjYywgZGF0LCBpbnN0LCB2b2MpLCDQuCDQvdCwINGC0LUsINC60L7RgtC+0YDRi9C1INGH0LDRidC1INC40LzQtdGO0YIg0LTQvtC70Y4g0LIg0L/RgNC+0LzQtdC20YPRgtC60LUg0LzQtdC20LTRgyAwLjIg0LggMC42IChnZW4sIG5vbSwgbG9jKTsKKiDQstC+LdCy0YLQvtGA0YvRhSwg0L3QtdC60L7RgtC+0YDRi9C1INCz0L7RgNC+0LTQsCDQuNC80LXRjtGCINCyINC40LzQtdC90LjRgtC10LvRjNC90L7QvCDQv9Cw0LTQtdC20LUg0L7Rh9C10L3RjCDQstGL0YHQvtC60YPRjiDQtNC+0LvRjiDQsdC70LjQt9C60YPRjiDQuiDQtdC00LjQvdC40YbQtSAo0YfRgtC+INCyINGB0LLQvtGOINC+0YfQtdGA0LXQtNGMINC+0LfQvdCw0YfQsNC10YIsINGH0YLQviDQvtC90Lgg0L/QvtGH0YLQuCDQvdC1INCy0YvRgdGC0YPQv9Cw0Y7RgiDQsiDQtNGA0YPQs9C40YUg0L/QsNC00LXQttCw0YUpLgoK0J/QtdGA0LLRi9C5INGE0LDQutGCINC00L7RgdGC0LDRgtC+0YfQvdC+INC70LXQs9C60L4g0L7QsdGK0Y/RgdC90LjRgtGMINGC0LXQvCwg0YfRgtC+INCyINC/0L7Qu9GM0YHQutC+0Lwg0LvQsNGC0LjQsiDQuCDRjdC70LDRgtC40LIg0LzQsNGA0LrQuNGA0YPQtdGC0YHRjyDQv9GA0LXQtNC70L7Qs9Cw0LzQuCBfZG9fINC4IF96Xywg0YPQv9GA0LDQstC70Y/RjtGJ0LjQvNC4INGA0L7QtNC40YLQtdC70YzQvdGL0Lwg0L/QsNC00LXQttC+0LwsINCwINGN0YHRgdC40LIg0LzQsNGA0LrQuNGA0YPQtdGC0YHRjyDQv9GA0LXQtNC70L7Qs9C+0LwgX3dfLCDRg9C/0YDQsNCy0LvRj9GO0YnQuNC5INC80LXRgdGC0L3Ri9C8INC/0LDQtNC10LbQvtC8LiDQkiDRhtC10LvQvtC8INC10YHRgtGMINC80L3QvtC20LXRgdGC0LLQviDRgNCw0LfQvdGL0YUg0LfQvdCw0YfQtdC90LjQuSwg0LrQvtGC0L7RgNGL0LUg0L7QutCw0LfQsNC70LjRgdGMINCy0L3QtSDQtNCw0L3QvdC+0Lkg0YHQuNC70YzQvdC+INGD0L/RgNC+0YnQtdC90L3QvtC5INGB0YXQtdC80YssINC+0LTQvdCw0LrQviDQsiDQv9C10YDQstC+0Lwg0L/RgNC40LHQu9C40LbQtdC90LjQuCDRgtCw0LrQvtC1INC+0LHRitGP0YHQvdC10L3QuNC1INC/0YDQuNC90Y/RgtGMINC80L7QttC90L4uCgrQktGC0L7RgNC+0Lkg0YTQsNC60YIg0YHQu9C10LTRg9C10YIg0YDQsNGB0YHQvNCw0YLRgNC10YLRjCDQvtGC0LTQtdC70YzQvdC+LiDQktC+0YIg0YHQv9C40YHQvtC6INCz0L7RgNC+0LTQvtCyINGBINCy0YvRgdC+0LrQvtC5INC00L7Qu9C10Lkg0YDQsNC30L3Ri9GFINC/0LDQtNC10LbQtdC5OgoKKiAqKmdlbjoqKiBPc3Ryw7N3IFdpZWxrb3BvbHNraSwgU2llZGxjZQoqICoqbm9tOioqIFJ1ZGEgxZpsxIVza2EsIFN0YXJvZ2FyZCBHZGHFhHNraSwgWmllbG9uYSBHw7NyYSwgS8SZZHppZXJ6eW4tS2/FumxlLCBUYXJub3dza2llIEfDs3J5CgrQktC40LTQuNC80L4sIFNpZWRsY2UsINC00LXQudGB0YLQstC40YLQtdC70YzQvdC+INC/0YDQtdC00YHRgtCw0LLQu9C10L3RiyDRgtCw0Log0LIg0LrQvtGA0L/Rg9GB0LUsINCwINCy0YHQtSDQvtGB0YLQsNC70YzQvdGL0LUg0L3QsNC30LLQsNC90LjRjywg0LLQuNC00LjQvNC+LCDQvdC10L/RgNCw0LLQuNC70YzQvdC+INC+0LHRgNCw0LHQsNGC0YvQstCw0LvQuNGB0Ywg0LzQvtGA0YTQvtC70L7Qs9C40YfQtdGB0LrQuNC8INC/0LDRgNGB0LXRgNC+0LwuINCY0LfQsdCw0LLQu9GP0LXQvNGB0Y8g0L7RgiDQvdC40YUg0Lgg0YHRgtGA0L7QuNC8INCz0YDQsNGE0LjQutC4INC30LDQvdC+0LLQvjoKCmBgYHtyfQptaWFzdGEgJT4lIAogIGdhdGhlcihjYXNlLCByYXRlLCBhY2M6dm9jKSAlPiUgCiAgZmlsdGVyKHJhdGUgPCAxKSAtPgogIG1pYXN0YS5mb3IuYW5hbHlzaXMKbWlhc3RhLmZvci5hbmFseXNpc18yIDwtIG1pYXN0YS5mb3IuYW5hbHlzaXNbLC03XQoKbWlhc3RhLmZvci5hbmFseXNpcyAlPiUgCiAgZ2dwbG90KGFlcyhyYXRlLCBmaWxsID0gY2FzZSkpKwogIGdlb21faGlzdG9ncmFtKGRhdGEgPSBtaWFzdGEuZm9yLmFuYWx5c2lzXzIsIGZpbGwgPSAibGlnaHRncmV5IiwgYmlucyA9IDE3KSsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTcpKwogIGZhY2V0X3dyYXAofmNhc2UpKwogIHRoZW1lX2J3KCkKYGBgCgrQmCDRgSDQvtGC0LvQvtCz0LDRgNC40YTQvNC40YDQvtCy0LDQvdC90L7QuSDQvtGB0YzRjjoKYGBge3J9Cm1pYXN0YS5mb3IuYW5hbHlzaXMgJT4lIAogIGZpbHRlcihyYXRlID4gMCkgJT4lIAogIGdncGxvdChhZXMocmF0ZSwgZmlsbCA9IGNhc2UpKSsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gbWlhc3RhLmZvci5hbmFseXNpc18yLCBmaWxsID0gImxpZ2h0Z3JleSIsIGJpbnMgPSAxNykrCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDE3KSsKICBmYWNldF93cmFwKH5jYXNlKSsKICB0aGVtZV9idygpICsKICBzY2FsZV95X2xvZzEwKCkKYGBgCgrQnNC+0LbQtdGCINCx0YvRgtGMINC60LDQutC+0Lkt0YLQviDQv9Cw0LTQtdC2INC60L7RgNGA0LXQu9C40YDRg9C10YIg0YEg0LrQvtC70LjRh9C10YHRgtCy0L7QvCDQvdC+0YHQuNGC0LXQu9C10Lk/ICjQodC/0LDRgdC40LHQviDQktCw0L3QtSDQm9C10LLQuNC90YMg0LfQsCDRjdGC0L7RgiDQstC+0L/RgNC+0YEpLgpgYGB7cn0KbGlicmFyeShQZXJmb3JtYW5jZUFuYWx5dGljcykKbWlhc3RhICU+JSAKICBzZWxlY3QoNToxMikgJT4lCiAgY2hhcnQuQ29ycmVsYXRpb24oaGlzdG9ncmFtID0gRiwgcGNoID0gIi4iKQpgYGAKCtCd0L4g0LLRgdC1INC20LUg0LIg0LzQvtC40YUg0LTQsNC90L3Ri9GFINC80L3QvtCz0L4g0YDQsNC30LzQtdGA0L3QvtGB0YLQtdC5LCDRgtCw0Log0YfRgtC+INC90YPQttC10L0g0YHQv9C+0YHQvtCxINC40YUg0YPQvNC10L3RjNGI0LjRgtGMLiDQotCw0Log0LrQsNC6INC00LDQvdC90YvQtSDRh9C40YHQu9C+0LLRi9C1IC0tLSBQQ0EuINCU0LDQstCw0LnRgtC1INC/0L7RgdC80L7RgtGA0LjQvCDQvdCwINCx0LjQv9C70L7RgiAo0LHQvtC70LXQtSDQutGA0YPQv9C90YvQuSDQstCw0YDQuNCw0L3RgiDQtNC+0YHRgtGD0L/QtdC9IFvQt9C00LXRgdGMXShodHRwczovL2dvby5nbC9CWkN4OFIpKToKCmBgYHtyfQpsaWJyYXJ5KGdnZm9ydGlmeSkKbWlhc3RhLmZvci5wY2EgPC0gbWlhc3RhWyw2OjEyXQpyb3cubmFtZXMobWlhc3RhLmZvci5wY2EpIDwtIG1pYXN0YSR0b3duLm5hbWVzCmF1dG9wbG90KHByY29tcChtaWFzdGEuZm9yLnBjYSksCiAgICAgICAgIHNoYXBlID0gRiwKICAgICAgICAgbGFiZWwgPSBULAogICAgICAgICBsYWJlbC5zaXplID0gMiwKICAgICAgICAgbG9hZGluZ3MgPSBULAogICAgICAgICBsb2FkaW5ncy5sYWJlbCA9IFQpKwogIHRoZW1lX2J3KCkKYGBgCgrQkiDQtNC+0LPQvtC90LrRgyDQuiDQs9GA0LDRhNC40LrRgywg0L7QsdGL0YfQvdC+INC/0YDQuNC90Y/RgtC+INC/0L7QutCw0LfRi9Cy0LDRgtGMLCDQutCw0LrQvtC5INCy0LrQu9Cw0LQg0LLQvdC+0YHRj9GCINC60L7QvNC/0L7QvdC10L3RgtGLINCyINC+0LHRitGP0YHQvdC10L3QuNC1INC40LfQvNC10L3Rh9C40LLQvtGB0YLQuDoKCmBgYHtyfQpzdW1tYXJ5KHByY29tcChtaWFzdGEuZm9yLnBjYSkpCmBgYArQmtCw0Log0LLQuNC00L3QviDQuNC3IHN1bW1hcnksINGD0LbQtSDQv9C10YDQstGL0LUg0LTQstC1INC60L7QvNC/0L7QvdC10L3RgtGLINC+0LHRitGP0YHQvdGP0Y7RgiA5MiDQv9GA0L7RhtC10L3RgtCwINCy0YHQtdC5INC40LfQvNC10L3Rh9C40LLQvtGB0YLQuCDQuNGB0YXQvtC00L3Ri9GFINC00LDQvdC90YvRhS4KCtCn0YLQviDQvdCw0Lwg0LPQvtCy0L7RgNC40YIg0LPRgNCw0YTQuNC6INCx0LjQv9C70L7Rgj8g0JLQuNC00LjQvNC+LCDQsiDQvdCw0YjQuNGFINC00LDQvdC90YvRhSDQvdC10YIg0YfQtdGC0LrQuNGFINC60LvQsNGB0YLQtdGA0L7Qsiwg0YIuINC1LiDQtdGB0YLRjCDRj9C00YDQviDQuCDQvdC10YHQutC+0LvRjNC60L4g0L/QtdGA0LXRhNC10YDQuNC5OiDRgSDQvtC00L3QvtC5INGB0YLQvtGA0L7QvdGLINCy0LjQtNC90YsgVGFybm93c2tpZSBHw7NyeSDQuCDRgi4g0L8uLCDQutC+0YLQvtGA0YvQtSDQuNC80LXRjtGCINC80LDQutGB0LjQvNCw0LvRjNC90YPRjiDQtNC+0LvRjiDQsiDQuNC80LXQvdC40YLQtdC70YzQvdC+0Lwg0L/QsNC00LXQttC1LCDRgSDQtNGA0YPQs9C+0Lkg0YHRgtC+0YDQvtC90YsgT3N0csOzdyBXaWVsa29wb2xza2ksINC60L7RgtC+0YDRi9C5INC40LzQtdC10YIg0LzQsNC60YHQuNC80LDQu9GM0L3Rg9GOINC00L7Qu9GOINCyINGA0L7QtNC40YLQtdC70YzQvdC+0Lwg0L/QsNC00LXQttC1LCDRgSDRgtGA0LXRgtGM0LXQuSDRgdGC0L7RgNC+0L3RiyBCeWRnb3N6Y3osINC40LzQtdGO0YnQuNC5INC80LDQutGB0LjQvNGD0Lwg0LIg0LzQtdGB0YLQvdC+0Lwg0L/QsNC00LXQttC1LiDQn9C10YDQtdGE0LXRgNC40Y8g0LPQvtGA0L7QtNC+0LIsINC40LzQtdGO0YnQuNGFINC80L3QvtCz0L4g0YTQvtGA0Lwg0LjQvNC10L3QuNGC0LXQu9GM0L3QvtCz0L4g0Lgg0YDQvtC00LjRgtC10LvRjNC90L7Qs9C+INC/0LDQtNC10LbQsCwg0L3QviDRgdC+0LLRgdC10Lwg0LzQsNC70L4g0LzQtdGB0YLQvdC+0LPQviDQv9Cw0LTQtdC20LAsINC60LDQttC10YLRgdGPINGH0YPRgtGMINCx0L7Qu9GM0YjQtS4KCtCh0L7Qt9C00LDQtNC40Lwg0L/QtdGA0LXQvNC10L3QvdGD0Y4sINC+0YLQu9C40YfQsNGO0YnRg9GOINCz0L7RgNC+0LTQsCDQv9C+INGB0YLQtdC/0LXQvdC4INC/0LXRgNC10YTQtdGA0LjRh9C90L7RgdGC0LguCmBgYHtyfQptaWFzdGEkY29yZSA8LSBOQQptaWFzdGEkY29yZVstYyg4LCA0MiwgMzMsIDk0LCA0LCAxMywyMiwgMiwgNDYsIDk3LCAzMSwgMzgsIDM5LCA5OSwgNzcsIDI5LCA1NiwgNywgNzMsIDI3LCA2NCwgNTEsIDYzLCAxNiwgMjAsIDQ1LCAxMTIsIDkwLCAzLCAxOCwgMTE0LCA4OCwgNzIpXSA8LSAiY29yZSIKbWlhc3RhJGNvcmVbYyg4LCA0MiwgMzMsIDk0LCA0LCAxMywyMiwyLCA0NiwgOTcsMzEsIDM5LCAzOCwgOTksIDc3LCAyOSwgNTYsIDcsIDczLCAyNywgNjQsIDUxLCA2MywgMTYsIDIwLCA0NSwgMTEyLCA5MCwgMywgMTgsIDExNCwgODgsIDcyKV0gPC0gInBlcmlwaGVyeSIKYXV0b3Bsb3QocHJjb21wKG1pYXN0YS5mb3IucGNhKSwgZGF0YSA9IG1pYXN0YSwgY29sb3VyID0gJ2NvcmUnLCAgc2hhcGUgPSBGQUxTRSwgbGFiZWwuc2l6ZSA9IDMpKwogIHRoZW1lX2J3KCkKYGBgCgrQktC40LTQuNC80L4sINCy0YvQtNC10LvQtdC90L3QsNGPINGH0LXRgNGC0LAsINC90LUg0YHQstGP0LfQsNC90L3QsCDRgSDQs9C10L7Qs9GA0LDRhNC40LXQuS4KYGBge3J9CnNldC5zZWVkKDExKQptYXAuZmVhdHVyZShsYW5ndWFnZXMgPSAiUG9saXNoIiwKICAgICAgICAgICAgZmVhdHVyZXMgPSBtaWFzdGEkY29yZSwKICAgICAgICAgICAgcG9wdXAgPSBtaWFzdGEkdG93bi5uYW1lcywKICAgICAgICAgICAgbGF0aXR1ZGUgPSBtaWFzdGEkbGF0LAogICAgICAgICAgICBsb25naXR1ZGUgPSBtaWFzdGEkbG9uZykKYGBgCgrQktC40LTQuNC80L4sINCy0YvQtNC10LvQtdC90L3QsNGPINGH0LXRgNGC0LAsINC90LUg0YHQstGP0LfQsNC90L3QsCDRgSDQutC+0LvQuNGH0LXRgdGC0LLQvtC8INC90LDRgdC10LvQtdC90LjRjy4KCmBgYHtyfQptaWFzdGEgJT4lCiAgZ2dwbG90KGFlcyhjb3JlLCBsdWRub3NjXy4zMS4xMi4yMDE0LiwgbGFiZWwgPSB0b3duLm5hbWVzKSkrCiAgZ2VvbV92aW9saW4oZmlsbCA9ICJsaWdodGJsdWUiKSsKICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMykrCiAgdGhlbWVfYncoKSsKICB5bGFiKCLQutC+0LvQuNGH0LXRgdGC0LLQviDRh9C10LvQvtCy0LXQuiAoMzEuMTIuMjAxNCkiKQpgYGAKCg==