0. Введение

Национальный корпус польского языка — вещь достаточно неудобная. Настройки в одном месте, выдача в другом, скачать можно только в html (хотя обещают, что можно и в Excel). Как было славно, если бы можно было сразу собирать в R выдачу и ее там анализировать?

1. API для польского корпуса

Для того, чтобы решить данную проблему я написал API (в этом мне немного помог Даня Алексеевский, спасибо!). Так что я написал на R достаточно неуклюжую, наверное, функцию pl.corpus.

Чтобы не заставлять читателя разбираться в коде, поясню, что в результате в вашем окружении появляется функция pl.corpus со следующими аргументами:

Приведу пример работы функции:

head(pl.corpus("witam"))
head(pl.corpus("An*a", tag = T))
head(pl.corpus("[base = 'witać']"))

Как видно из примеров, функция понимает самые разные запросы:

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. Здесь таилось множество проблем, связанных с особенностью корпуса:

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()

Как следует читать данные графики? Серым цветом обозначена гистограмма1 всей выборки долей, без учета падежа. Цветом же показано, какой вклад вносит каждый падеж в создание общей гистограммы. Исследуя данный график можно сделать два наблюдения:

Первый факт достаточно легко объяснить тем, что в польском латив и элатив маркируется предлогами do и z, управляющими родительным падежом, а эссив маркируется предлогом w, управляющий местным падежом. В целом есть множество разных значений, которые оказались вне данной сильно упрощенной схемы, однако в первом приближении такое объяснение принять можно.

Второй факт следует рассматреть отдельно. Вот список городов с высокой долей разных падежей:

Видимо, 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)")


  1. Существует стандартная проблемма с гистограммой, связанная с трудностью формализовать выбор количества ячеек гистограммы. Существует несколько подходов, здесь я выбрал алгоритм из работы (Freedman, Diaconis 1981), согласно которому для исследуемых данных следует использовать 17 ячеек.

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==