Предмет исследования: распределение предлогов “про” и “о/об” в речи.
Материал исследования: примеры из Национального Корпуса Русского Языка.

Факторы, которые рассматриваются как возможно влияющие на выбор предлога (независимые переменнные):

*Жанр для письменных текстов в НКРЯ уже задан как дихотомия “художественных текстов” и “нехудожественных текстов”; в устном корпусе под “художественными” мы понимали жанры “театральная речь” и “речь кино”, под “нехудожественными” — жанры “устная публичная речь” и “устная непубличная речь”. Жанры “авторское чтение” и “художественное чтение” было решено не учитывать, так как тексты этих жанров — это фактически озвученная письменная, а не устная речь.

У каждой из первых четырех переменных два значения (уровня), и следовательно, при работе с каждым из рассмотренных корней было задано 16 комбинаций параметров поиска. Из выдачи были взяты все примеры, если их было 50 или меньше; если примеров в выдаче было больше 50, забирались первые 50 подходящих примеров.

Рассмотренные лексемы:

Нулевой гипотезой является предположение о том, что единственными факторами, влияющими на выбор предлога, являются регистр и жанр текста.

В результате получен 5151 пример. Для каждого примера указано, какой предлог был использован. Данные представлены в файле prepositions.csv и проиллюстрированы в графиках.

library(randomForest)
library(tidyverse)
library(caret)

data <- read.csv("prepositions.csv", head = TRUE, sep = ";", encoding = "UTF-8")
data <- data[, -c(7,8)]
data %>%
  ggplot(aes(register, fill = preposition)) +
  geom_bar(position = "dodge") +
  facet_wrap(~root) +
  labs(x = "Регистр", y = "Общее число примеров") +
  theme_bw() +
  guides(fill = guide_legend(title = "Предлог"))

# data %>%
#   ggplot(aes(genre, fill = preposition)) +
#   geom_bar(position = "dodge") +
#   facet_wrap(~root) +
#   labs(x = "Жанр текста", y = "Общее число примеров") +
#   theme_bw() +
#   guides(fill = guide_legend(title = "Предлог"))
# data %>%
#   ggplot(aes(date_of_creation, fill = preposition)) +
#   geom_bar(position = "dodge") +
#   facet_wrap(~root) +
#   labs(x = "Время создания текста", y = "Общее число примеров") +
#   theme_bw() +
#   guides(fill = guide_legend(title = "Предлог"))
# data %>%
#   ggplot(aes(head_pos, fill = preposition)) +
#   geom_bar(position = "dodge") +
#   facet_wrap(~root) +
#   labs(x = "Часть речи вершины", y = "Общее число примеров") +
#   theme_bw() +
#   guides(fill = guide_legend(title = "Предлог"))

Нагляднее представить изменение соотношения предлогов в зависимости от значений параметров можно по графикам, показывающим не абсолютное количество использованных “про” и “о/об”, а проценты от общего числа примеров:

data %>% 
  count(root, genre, head_pos, date_of_creation, register, preposition) %>% 
  spread(key = preposition, value = n) %>%
  mutate(sum = `о/об`+`про`,
        `о/об_%` = `о/об`/sum*100,
        `про_%` = `про`/sum*100) %>% 
  select(-c(`о/об`, `про`, sum)) %>% 
  gather(key = preposition, value = percent, `о/об_%`:`про_%`) %>% 
  na.omit() -> data_pct
data_pct %>% 
  filter(root == "говор") %>%  
  ggplot(aes(preposition, percent, fill = preposition)) +  
  geom_bar(stat = "identity") +
  facet_grid(genre + head_pos ~ date_of_creation + register) +
  labs(x = "Предлог", y = " ") +
  theme_bw() +
  guides(fill = FALSE)

# data_pct %>% 
#   filter(root == "знат") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)
# data_pct %>% 
#   filter(root == "прос") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)
# data_pct %>% 
#   filter(root == "помн") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)
# data_pct %>% 
#   filter(root == "шут") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)
# data_pct %>% 
#   filter(root == "сказ") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)
# data_pct %>% 
#   filter(root == "пис") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)
# data_pct %>% 
#   filter(root == "сужд") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)
# data_pct %>% 
#   filter(root == "слыш") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)
# data_pct %>% 
#   filter(root == "пе") %>% 
#   ggplot(aes(preposition, percent, fill = preposition)) +  
#   geom_bar(stat = "identity") +
#   facet_grid(genre + head_pos ~ date_of_creation + register) +
#   labs(x = "Предлог", y = " ") +
#   theme_bw() +
#   guides(fill = FALSE)

Препроцессинг данных

Данные были разделены на два сабсета - тренировочный (75%) и тестовый (25%) - с помощью метода стратифицированной выборки. Тестовый сабсет использовался при проверке обобщающей способности моделей.

#table(data$preposition)/sum(table(data$preposition)) #процентное соотношение предлогов 'о/об' и 'про'  
set.seed(123)
dataR <- data[order(runif(nrow(data))),]
data_split <- createDataPartition(y = dataR$preposition, p = 0.75, list = FALSE)
#head(data_split)
trainSet <- dataR[data_split, ]
testSet <- dataR[-data_split, ]
head(trainSet)

Логистическая регрессия

Мы обучили модель логистической регрессии с использованием всех возможных предикторов:

fit <- glm(preposition ~ ., data = trainSet, family = "binomial")
summary(fit)

Call:
glm(formula = preposition ~ ., family = "binomial", data = trainSet)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.7684  -0.5782  -0.3793  -0.1874   3.0390  

Coefficients:
                             Estimate Std. Error z value Pr(>|z|)    
(Intercept)                 -1.942501   0.178827 -10.862  < 2e-16 ***
genrenonfiction             -0.551943   0.098399  -5.609 2.03e-08 ***
registerwritten             -0.521263   0.108399  -4.809 1.52e-06 ***
date_of_creationbefore 1950 -0.891741   0.117472  -7.591 3.17e-14 ***
head_posV                    1.126598   0.108261  10.406  < 2e-16 ***
rootзнат                     0.227708   0.207427   1.098  0.27230    
rootпе                       2.144540   0.190094  11.281  < 2e-16 ***
rootпис                      0.002653   0.220135   0.012  0.99039    
rootпомн                    -0.402096   0.232081  -1.733  0.08317 .  
rootпрос                     0.759767   0.192715   3.942 8.07e-05 ***
rootсказ                     0.568335   0.193774   2.933  0.00336 ** 
rootслыш                    -0.175711   0.226043  -0.777  0.43696    
rootсужд                    -2.144164   0.475893  -4.506 6.62e-06 ***
rootшут                      2.158246   0.250032   8.632  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 3397.0  on 3863  degrees of freedom
Residual deviance: 2780.6  on 3850  degrees of freedom
AIC: 2808.6

Number of Fisher Scoring iterations: 7

Как видно, бОльшую часть признаков алгоритм считает значимыми для предсказания предлога. Проиллюстрируем его предсказательные возможности с помощью violin plots:

rd <- data.frame(p = predict(fit, newdata = testSet, type = "response"), prep = testSet$preposition, rt = testSet$root, hp = testSet$head_pos, gnr = testSet$genre, rgstr = testSet$register, dt = testSet$date_of_creation)
rd %>% 
  arrange(p) %>% 
  ggplot(aes(prep, p, fill = rt)) +
  geom_violin() +
  facet_wrap(~rt) +
  labs(x = "", y = "") +
  theme_bw() +
  guides(fill = FALSE)

rd %>% 
  arrange(p) %>% 
  ggplot(aes(prep, p, fill = hp)) +
  geom_violin() +
  facet_wrap(~hp) +
  labs(x = "", y = "") +
  theme_bw() +
  guides(fill = FALSE)

rd %>% 
  arrange(p) %>% 
  ggplot(aes(prep, p, fill = gnr)) +
  geom_violin() +
  facet_wrap(~gnr) +
  labs(x = "", y = "") +
  theme_bw() +
  guides(fill = FALSE)

rd %>% 
  arrange(p) %>% 
  ggplot(aes(prep, p, fill = rgstr)) +
  geom_violin() +
  facet_wrap(~rgstr) +
  labs(x = "", y = "") +
  theme_bw() +
  guides(fill = FALSE)

rd %>% 
  arrange(p) %>% 
  ggplot(aes(prep, p, fill = dt)) +
  geom_violin() +
  facet_wrap(~dt) +
  labs(x = "", y = "") +
  theme_bw() +
  guides(fill = FALSE)

Как можно видеть, все параметры, кроме корня вершины, не имеют значений, которые бы хорошо разделяли предлоги “о/об” и “про” - вероятность получить “о/об” выше во всех случаях. Три значения признака root (корень вершины) резко выделяются на общем фоне: вероятность увидеть предлог “про” еще более низка, чем обычно, если корень вершины - “сужд” (рассуждать/рассуждение), и неожиданно (принимая во внимание общие тенденции) высока, если корень вершины - “пе” (петь/песня) или “шут” (шутить/шутка).

Случайные леса (RandomForests)

Случайный лес - ансамбль решающих деревьев (строим много деревьев на случайных подвыборках и усредняем их результаты). Зд. алгоритм применяется для задач классификации (зависимая переменная - категориальная).

set.seed(123)
rf <- randomForest(preposition ~ ., data = trainSet, ntree = 1000, mtry = 3, importance = TRUE, do.trace = 500/10) #ntree - количество построенных деревьев, mtry - случайно выбираемые при каждом делении предикторы 
ntree      OOB      1      2
   50:  15.73%  3.45% 80.26%
  100:  15.53%  3.67% 77.83%
  150:  15.48%  3.51% 78.32%
  200:  15.37%  3.54% 77.51%
  250:  15.45%  3.57% 77.83%
  300:  15.30%  3.57% 76.86%
  350:  15.42%  3.57% 77.67%
  400:  15.45%  3.57% 77.83%
  450:  15.35%  3.57% 77.18%
  500:  15.35%  3.57% 77.18%
  550:  15.30%  3.57% 76.86%
  600:  15.11%  3.57% 75.73%
  650:  15.09%  3.57% 75.57%
  700:  15.11%  3.57% 75.73%
  750:  15.11%  3.57% 75.73%
  800:  15.17%  3.57% 76.05%
  850:  15.17%  3.57% 76.05%
  900:  15.14%  3.57% 75.89%
  950:  15.14%  3.57% 75.89%
 1000:  15.17%  3.57% 76.05%
print(rf)

Call:
 randomForest(formula = preposition ~ ., data = trainSet, ntree = 1000,      mtry = 3, importance = TRUE, do.trace = 500/10) 
               Type of random forest: classification
                     Number of trees: 1000
No. of variables tried at each split: 3

        OOB estimate of  error rate: 15.17%
Confusion matrix:
     о/об про class.error
о/об 3130 116  0.03573629
про   470 148  0.76051780

OOB (out-of-bag error rate) - оценка качества модели на неиспользуемой части выборки (out-of-bag samples).

plot(rf, main = "") #черная кривая на графике - out-of-bag ошибка

“Тонкая настройка”

Судя по выдаче функции и графику, при изменении количества деревьев в ансамбле out-of-bag ошибка меняется незначительно; при этом минимальное значение она принимает при ntree = 650. Скорректируем количество деревьев и определим оптимальное число выбираемых при каждом делении предикторов с помощью функции tuneRF():

tuneRF(trainSet[,-6], trainSet[,6], stepFactor = 0.5, plot = TRUE, ntreeTry = 650, trace = TRUE, improve = 0.05)
mtry = 2  OOB error = 15.73% 
Searching left ...
mtry = 4    OOB error = 14.91% 
0.05263158 0.05 
invalid mtry: reset to within valid range
mtry = 8    OOB error = 15.04% 
-0.008680556 0.05 
Searching right ...
mtry = 1    OOB error = 15.99% 
-0.07291667 0.05 
      mtry  OOBError
1.OOB    1 0.1599379
2.OOB    2 0.1573499
4.OOB    4 0.1490683
8.OOB    8 0.1503623

Наименьшую ошибку прогноза получаем при делении на основе четырех случайно выбранных переменных (mtry = 4).

set.seed(123)
tuned_rf <- randomForest(preposition ~ ., data = trainSet, ntree = 650, mtry = 4, importance = TRUE, do.trace = 650/10) #обучаем модель с новыми параметрами 
ntree      OOB      1      2
   65:  15.14%  3.45% 76.54%
  130:  15.14%  3.60% 75.73%
  195:  15.14%  3.67% 75.40%
  260:  15.14%  3.67% 75.40%
  325:  15.14%  3.67% 75.40%
  390:  15.19%  3.70% 75.57%
  455:  15.22%  3.70% 75.73%
  520:  15.19%  3.67% 75.73%
  585:  15.14%  3.67% 75.40%
  650:  14.96%  3.57% 74.76%
print(tuned_rf)

Call:
 randomForest(formula = preposition ~ ., data = trainSet, ntree = 650,      mtry = 4, importance = TRUE, do.trace = 650/10) 
               Type of random forest: classification
                     Number of trees: 650
No. of variables tried at each split: 4

        OOB estimate of  error rate: 14.96%
Confusion matrix:
     о/об про class.error
о/об 3130 116  0.03573629
про   462 156  0.74757282
plot(tuned_rf, main = "")

tree <- getTree(tuned_rf, 1, labelVar = TRUE) #достаем первое дерево
head(tree)
tail(tree)

split var - разделяющая переменная, split point - значение, с которым она сравнивается, status=1 - нетерминальный узел, left daughter, right daughter - следующие за ним левый и правый узлы, status=-1 - терминальный узел, prediction - прогноз для терминального узла.

hist(treesize(tuned_rf), main = "", xlab = "Размер дерева", ylab = "", col = "springgreen2") #график, показывающий количество узлов у построенных алгоритмом деревьев; больше всего деревьев (около 225) содержат от 90 до 95 узлов

Алгоритм позволяет добиться высокого качества классификации, но совершенно не объясняет, как устроены данные. Понять, что происходит “внутри”, достаточно сложно даже по одному дереву (а всего их несколько сотен). Для описания полученных результатов мы можем оценить, насколько важен тот или иной предиктор:

importance(tuned_rf, type = 1)
                 MeanDecreaseAccuracy
genre                         5.87068
register                     20.09619
date_of_creation             41.67389
head_pos                     18.71616
root                         95.58541

Самым значимым предиктором оказывается root, “полезность” всех остальных переменных для классификации данных гораздо ниже.

varImpPlot(tuned_rf, type = 1, main = "")

rfPredicted <- predict(tuned_rf, testSet)
confusionMatrix(rfPredicted, testSet$preposition) #строим матрицу ошибок на тестовых данных
Confusion Matrix and Statistics

          Reference
Prediction о/об  про
      о/об 1024  160
      про    58   45
                                         
               Accuracy : 0.8306         
                 95% CI : (0.809, 0.8507)
    No Information Rate : 0.8407         
    P-Value [Acc > NIR] : 0.848          
                                         
                  Kappa : 0.2078         
 Mcnemar's Test P-Value : 7.887e-12      
                                         
            Sensitivity : 0.9464         
            Specificity : 0.2195         
         Pos Pred Value : 0.8649         
         Neg Pred Value : 0.4369         
             Prevalence : 0.8407         
         Detection Rate : 0.7956         
   Detection Prevalence : 0.9200         
      Balanced Accuracy : 0.5830         
                                         
       'Positive' Class : о/об           
                                         
# metrics <- c(Accuracy = (1024 + 45)/nrow(testSet), Precision = 1024/(1024 + 160), Recall = 1024/(1024 + 58), Specificity = 45/(45 + 160))
# metrics

Модель склонна предсказывать предлог “о/об” в большинстве случаев - поэтому самой частотной ошибкой является предсказание “о/об” при истинном значении “про”. Это происходит потому, что случаев употребления предлога “о/об” в наших данных намного больше - 4328 наблюдений с “о/об” против 823 наблюдений с “про”. Метрики качества при этом оказываются неплохими, но причина этого - не удачный подбор признаков и успешное обучение алгоритма, а высокая частотность одного из классов, к которому модель в результате “склоняется”.

Вывод

Итак, построенные нами модели опровергают нашу нулевую гипотезу сразу по двум, причем противоречащим друг другу причинам. С одной стороны, модель логистической регрессии признает значимыми, помимо регистра и жанра текста, и другие параметры - и корень слова, и его часть речи, и дату возникновения текста. Деревья в случайном лесе также производят деления по всем этим параметрам, самым значимым при этом полагая корень вершины, а наименее значимым - жанр. С другой стороны, абсолютное преобладание предлога “о/об” над предлогом “про” в текстах приводит к тому, что ни один из выбранных нами признаков не может хорошо разделить случаи употребления “о/об” и “про” - в любых комбинациях “о/об” оказывается частотнее. Единственные значения параметров, при которых вероятность “про” действительно сильно повышается (что “ловится” обоими алгоритмами) - это корни “пе” (петь/песня) и “шут” (шутить/шутка). Поиск других признаков, которые бы хорошо разделили наши предлоги, остается задачей будущих исследований.

Appendix A

Trellis graphs (графики, визуализирующие определенный сабсет данных):

# data %>%
#   count(root, genre, head_pos, date_of_creation, register, preposition) %>%
#   spread(key = preposition, value = n) -> data_summed
# barchart(`о/об`+`про` ~ genre | register + root + head_pos + date_of_creation, data_summed, layout = c(5, 2), auto.key = TRUE, xlab = "Жанр текста", ylab = "Число примеров")
# barchart(`о/об`+`про` ~ head_pos | register + genre + root + date_of_creation, data_summed, layout = c(5, 2), auto.key = TRUE, xlab = "Часть речи вершины", ylab = "Число примеров")
# barchart(`о/об`+`про` ~ register | root + genre + head_pos + date_of_creation, data_summed, layout = c(5, 1), aspect = 1.5, auto.key = TRUE, xlab = "Регистр речи", ylab = "Число примеров")
# barchart(`о/об`+`про` ~ root | register + genre + head_pos + date_of_creation, data_summed, layout = c(1, 2), auto.key = TRUE, xlab = "Корень", ylab = "Число примеров")
# barchart(`о/об`+`про` ~ date_of_creation | register + root + head_pos + genre, data_summed, layout = c(4, 2), auto.key = TRUE, xlab = "Дата создания текста", ylab = "Число примеров")
LS0tCnRpdGxlOiAnUiBwcm9qZWN0OiBQcmVwb3NpdGlvbnMnCmF1dGhvcjogItCh0L7QvdGPINCd0LjQutC40YTQvtGA0L7QstCwLCDQr9C90LAg0JrRg9GA0LzQsNGH0LXQstCwIgpkYXRlOiAiMTkvMDYvMjAxNyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQrQn9GA0LXQtNC80LXRgiDQuNGB0YHQu9C10LTQvtCy0LDQvdC40Y86INGA0LDRgdC/0YDQtdC00LXQu9C10L3QuNC1INC/0YDQtdC00LvQvtCz0L7QsiDigJzQv9GA0L7igJ0g0Lgg4oCc0L4v0L7QseKAnSDQsiDRgNC10YfQuC4gIArQnNCw0YLQtdGA0LjQsNC7INC40YHRgdC70LXQtNC+0LLQsNC90LjRjzog0L/RgNC40LzQtdGA0Ysg0LjQtyDQndCw0YbQuNC+0L3QsNC70YzQvdC+0LPQviDQmtC+0YDQv9GD0YHQsCDQoNGD0YHRgdC60L7Qs9C+INCv0LfRi9C60LAuCgrQpNCw0LrRgtC+0YDRiywg0LrQvtGC0L7RgNGL0LUg0YDQsNGB0YHQvNCw0YLRgNC40LLQsNGO0YLRgdGPINC60LDQuiDQstC+0LfQvNC+0LbQvdC+INCy0LvQuNGP0Y7RidC40LUg0L3QsCDQstGL0LHQvtGAINC/0YDQtdC00LvQvtCz0LAgKNC90LXQt9Cw0LLQuNGB0LjQvNGL0LUg0L/QtdGA0LXQvNC10L3QvdC90YvQtSk6CgotINGA0LXQs9C40YHRgtGAINGA0LXRh9C4ICjQv9C40YHRjNC80LXQvdC90YvQuSwg0YPRgdGC0L3Ri9C5KTsgICAKLSDQttCw0L3RgCDRgtC10LrRgdGC0LAgKNGF0YPQtNC+0LbQtdGB0YLQstC10L3QvdGL0LksINC90LXRhdGD0LTQvtC20LXRgdGC0LLQtdC90L3Ri9C5KSo7ICAgCi0g0YfQsNGB0YLRjCDRgNC10YfQuCDRgdC70L7QstCwLCDQvtGCINC60L7RgtC+0YDQvtCz0L4g0LfQsNCy0LjRgdC40YIg0L/RgNC10LTQu9C+0LMgKNCz0LvQsNCz0L7Quywg0YHRg9GJ0LXRgdGC0LLQuNGC0LXQu9GM0L3QvtC1KTsgICAKLSDQstGA0LXQvNGPINGB0L7Qt9C00LDQvdC40Y8g0YLQtdC60YHRgtCwICjQtNC+IDE5NTAg0LPQvtC00LAsINC/0L7RgdC70LUgMTk1MCDQs9C+0LTQsCk7ICAKLSDRgtC40L8g0LrQvtGA0L3Rjy4KCirQltCw0L3RgCDQtNC70Y8g0L/QuNGB0YzQvNC10L3QvdGL0YUg0YLQtdC60YHRgtC+0LIg0LIg0J3QmtCg0K8g0YPQttC1INC30LDQtNCw0L0g0LrQsNC6INC00LjRhdC+0YLQvtC80LjRjyAi0YXRg9C00L7QttC10YHRgtCy0LXQvdC90YvRhSDRgtC10LrRgdGC0L7QsiIg0LggItC90LXRhdGD0LTQvtC20LXRgdGC0LLQtdC90L3Ri9GFINGC0LXQutGB0YLQvtCyIjsg0LIg0YPRgdGC0L3QvtC8INC60L7RgNC/0YPRgdC1INC/0L7QtCAi0YXRg9C00L7QttC10YHRgtCy0LXQvdC90YvQvNC4IiDQvNGLINC/0L7QvdC40LzQsNC70Lgg0LbQsNC90YDRiyAi0YLQtdCw0YLRgNCw0LvRjNC90LDRjyDRgNC10YfRjCIg0LggItGA0LXRh9GMINC60LjQvdC+Iiwg0L/QvtC0ICLQvdC10YXRg9C00L7QttC10YHRgtCy0LXQvdC90YvQvNC4IiDigJQg0LbQsNC90YDRiyAi0YPRgdGC0L3QsNGPINC/0YPQsdC70LjRh9C90LDRjyDRgNC10YfRjCIg0LggItGD0YHRgtC90LDRjyDQvdC10L/Rg9Cx0LvQuNGH0L3QsNGPINGA0LXRh9GMIi4g0JbQsNC90YDRiyAi0LDQstGC0L7RgNGB0LrQvtC1INGH0YLQtdC90LjQtSIg0LggItGF0YPQtNC+0LbQtdGB0YLQstC10L3QvdC+0LUg0YfRgtC10L3QuNC1IiDQsdGL0LvQviDRgNC10YjQtdC90L4g0L3QtSDRg9GH0LjRgtGL0LLQsNGC0YwsINGC0LDQuiDQutCw0Log0YLQtdC60YHRgtGLINGN0YLQuNGFINC20LDQvdGA0L7QsiDigJQg0Y3RgtC+INGE0LDQutGC0LjRh9C10YHQutC4INC+0LfQstGD0YfQtdC90L3QsNGPINC/0LjRgdGM0LzQtdC90L3QsNGPLCDQsCDQvdC1INGD0YHRgtC90LDRjyDRgNC10YfRjC4KCtCjINC60LDQttC00L7QuSDQuNC3INC/0LXRgNCy0YvRhSDRh9C10YLRi9GA0LXRhSDQv9C10YDQtdC80LXQvdC90YvRhSDQtNCy0LAg0LfQvdCw0YfQtdC90LjRjyAo0YPRgNC+0LLQvdGPKSwg0Lgg0YHQu9C10LTQvtCy0LDRgtC10LvRjNC90L4sINC/0YDQuCDRgNCw0LHQvtGC0LUg0YEg0LrQsNC20LTRi9C8INC40Lcg0YDQsNGB0YHQvNC+0YLRgNC10L3QvdGL0YUg0LrQvtGA0L3QtdC5INCx0YvQu9C+INC30LDQtNCw0L3QviAxNiDQutC+0LzQsdC40L3QsNGG0LjQuSDQv9Cw0YDQsNC80LXRgtGA0L7QsiDQv9C+0LjRgdC60LAuINCY0Lcg0LLRi9C00LDRh9C4INCx0YvQu9C4INCy0LfRj9GC0Ysg0LLRgdC1INC/0YDQuNC80LXRgNGLLCDQtdGB0LvQuCDQuNGFINCx0YvQu9C+IDUwINC40LvQuCDQvNC10L3RjNGI0LU7INC10YHQu9C4INC/0YDQuNC80LXRgNC+0LIg0LIg0LLRi9C00LDRh9C1INCx0YvQu9C+INCx0L7Qu9GM0YjQtSA1MCwg0LfQsNCx0LjRgNCw0LvQuNGB0Ywg0L/QtdGA0LLRi9C1IDUwINC/0L7QtNGF0L7QtNGP0YnQuNGFINC/0YDQuNC80LXRgNC+0LIuIAoK0KDQsNGB0YHQvNC+0YLRgNC10L3QvdGL0LUg0LvQtdC60YHQtdC80Ys6CgotINGA0LDQt9Cz0L7QstCw0YDQuNCy0LDRgtGMICjQs9C+0LLQvtGA0LjRgtGMLCDQv9C+0LPQvtCy0L7RgNC40YLRjCkgLyDRgNCw0LfQs9C+0LLQvtGAICAKLSDQt9C90LDRgtGMICjRg9C30L3QsNGC0YwpIC8g0LfQvdCw0L3QuNC1ICAKLSDRgdC/0YDQsNGI0LjQstCw0YLRjCAo0YHQv9GA0L7RgdC40YLRjCkgLyDQstC+0L/RgNC+0YEgKNCyINC30L3QsNGH0LXQvdC40LggcXVlc3Rpb24sINC90LUgaXNzdWUpLiAgCi0g0L/QvtC80L3QuNGC0YwgKNCy0YHQv9C+0LzQvdC40YLRjCwg0LLRgdC/0L7QvNC40L3QsNGC0YwpIC8g0LLQvtGB0L/QvtC80LjQvdCw0L3QuNC1ICjQv9Cw0LzRj9GC0YwpICAKLSDRiNGD0YLQuNGC0YwgKNC/0L7RiNGD0YLQuNGC0YwpIC8g0YjRg9GC0LrQsCAgCi0g0YDQsNGB0YHQutCw0LfRi9Cy0LDRgtGMICjRgNCw0YHRgdC60LDQt9Cw0YLRjCkgLyDRgNCw0YHRgdC60LDQtyAgCi0g0L/QuNGB0LDRgtGMICjQvdCw0L/QuNGB0LDRgtGMKSAvINC/0LjRgdGM0LzQviAgCi0g0YDQsNGB0YHRg9C20LTQsNGC0YwgLyDRgNCw0YHRgdGD0LbQtNC10L3QuNC1ICAKLSDRgdC70YvRiNCw0YLRjCAo0YPRgdC70YvRiNCw0YLRjCkgLyDRgdC70YPRhSAgCi0g0L/QtdGC0YwgKNGB0L/QtdGC0YwpIC8g0L/QtdGB0L3RjwoK0J3Rg9C70LXQstC+0Lkg0LPQuNC/0L7RgtC10LfQvtC5INGP0LLQu9GP0LXRgtGB0Y8g0L/RgNC10LTQv9C+0LvQvtC20LXQvdC40LUg0L4g0YLQvtC8LCDRh9GC0L4g0LXQtNC40L3RgdGC0LLQtdC90L3Ri9C80Lgg0YTQsNC60YLQvtGA0LDQvNC4LCDQstC70LjRj9GO0YnQuNC80Lgg0L3QsCDQstGL0LHQvtGAINC/0YDQtdC00LvQvtCz0LAsINGP0LLQu9GP0Y7RgtGB0Y8g0YDQtdCz0LjRgdGC0YAg0Lgg0LbQsNC90YAg0YLQtdC60YHRgtCwLgoK0JIg0YDQtdC30YPQu9GM0YLQsNGC0LUg0L/QvtC70YPRh9C10L0gNTE1MSDQv9GA0LjQvNC10YAuINCU0LvRjyDQutCw0LbQtNC+0LPQviDQv9GA0LjQvNC10YDQsCDRg9C60LDQt9Cw0L3Qviwg0LrQsNC60L7QuSDQv9GA0LXQtNC70L7QsyDQsdGL0Lsg0LjRgdC/0L7Qu9GM0LfQvtCy0LDQvS4g0JTQsNC90L3Ri9C1INC/0YDQtdC00YHRgtCw0LLQu9C10L3RiyDQsiDRhNCw0LnQu9C1IHByZXBvc2l0aW9ucy5jc3Yg0Lgg0L/RgNC+0LjQu9C70Y7RgdGC0YDQuNGA0L7QstCw0L3RiyDQsiDQs9GA0LDRhNC40LrQsNGFLgoKYGBge3J9CmxpYnJhcnkocmFuZG9tRm9yZXN0KQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShjYXJldCkKCmRhdGEgPC0gcmVhZC5jc3YoInByZXBvc2l0aW9ucy5jc3YiLCBoZWFkID0gVFJVRSwgc2VwID0gIjsiLCBlbmNvZGluZyA9ICJVVEYtOCIpCmRhdGEgPC0gZGF0YVssIC1jKDcsOCldCmBgYAoKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyhyZWdpc3RlciwgZmlsbCA9IHByZXBvc2l0aW9uKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKwogIGZhY2V0X3dyYXAofnJvb3QpICsKICBsYWJzKHggPSAi0KDQtdCz0LjRgdGC0YAiLCB5ID0gItCe0LHRidC10LUg0YfQuNGB0LvQviDQv9GA0LjQvNC10YDQvtCyIikgKwogIHRoZW1lX2J3KCkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gItCf0YDQtdC00LvQvtCzIikpCmBgYAoKYGBge3J9CiMgZGF0YSAlPiUKIyAgIGdncGxvdChhZXMoZ2VucmUsIGZpbGwgPSBwcmVwb3NpdGlvbikpICsKIyAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKwojICAgZmFjZXRfd3JhcCh+cm9vdCkgKwojICAgbGFicyh4ID0gItCW0LDQvdGAINGC0LXQutGB0YLQsCIsIHkgPSAi0J7QsdGJ0LXQtSDRh9C40YHQu9C+INC/0YDQuNC80LXRgNC+0LIiKSArCiMgICB0aGVtZV9idygpICsKIyAgIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gItCf0YDQtdC00LvQvtCzIikpCmBgYAoKYGBge3J9CiMgZGF0YSAlPiUKIyAgIGdncGxvdChhZXMoZGF0ZV9vZl9jcmVhdGlvbiwgZmlsbCA9IHByZXBvc2l0aW9uKSkgKwojICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiKSArCiMgICBmYWNldF93cmFwKH5yb290KSArCiMgICBsYWJzKHggPSAi0JLRgNC10LzRjyDRgdC+0LfQtNCw0L3QuNGPINGC0LXQutGB0YLQsCIsIHkgPSAi0J7QsdGJ0LXQtSDRh9C40YHQu9C+INC/0YDQuNC80LXRgNC+0LIiKSArCiMgICB0aGVtZV9idygpICsKIyAgIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gItCf0YDQtdC00LvQvtCzIikpCmBgYAoKYGBge3J9CiMgZGF0YSAlPiUKIyAgIGdncGxvdChhZXMoaGVhZF9wb3MsIGZpbGwgPSBwcmVwb3NpdGlvbikpICsKIyAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKwojICAgZmFjZXRfd3JhcCh+cm9vdCkgKwojICAgbGFicyh4ID0gItCn0LDRgdGC0Ywg0YDQtdGH0Lgg0LLQtdGA0YjQuNC90YsiLCB5ID0gItCe0LHRidC10LUg0YfQuNGB0LvQviDQv9GA0LjQvNC10YDQvtCyIikgKwojICAgdGhlbWVfYncoKSArCiMgICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICLQn9GA0LXQtNC70L7QsyIpKQpgYGAKCtCd0LDQs9C70Y/QtNC90LXQtSDQv9GA0LXQtNGB0YLQsNCy0LjRgtGMINC40LfQvNC10L3QtdC90LjQtSDRgdC+0L7RgtC90L7RiNC10L3QuNGPINC/0YDQtdC00LvQvtCz0L7QsiDQsiDQt9Cw0LLQuNGB0LjQvNC+0YHRgtC4INC+0YIg0LfQvdCw0YfQtdC90LjQuSDQv9Cw0YDQsNC80LXRgtGA0L7QsiDQvNC+0LbQvdC+INC/0L4g0LPRgNCw0YTQuNC60LDQvCwg0L/QvtC60LDQt9GL0LLQsNGO0YnQuNC8INC90LUg0LDQsdGB0L7Qu9GO0YLQvdC+0LUg0LrQvtC70LjRh9C10YHRgtCy0L4g0LjRgdC/0L7Qu9GM0LfQvtCy0LDQvdC90YvRhSDigJzQv9GA0L7igJ0g0Lgg4oCc0L4v0L7QseKAnSwg0LAg0L/RgNC+0YbQtdC90YLRiyDQvtGCINC+0LHRidC10LPQviDRh9C40YHQu9CwINC/0YDQuNC80LXRgNC+0LI6CgpgYGB7cn0KZGF0YSAlPiUgCiAgY291bnQocm9vdCwgZ2VucmUsIGhlYWRfcG9zLCBkYXRlX29mX2NyZWF0aW9uLCByZWdpc3RlciwgcHJlcG9zaXRpb24pICU+JSAKICBzcHJlYWQoa2V5ID0gcHJlcG9zaXRpb24sIHZhbHVlID0gbikgJT4lCiAgbXV0YXRlKHN1bSA9IGDQvi/QvtCxYCtg0L/RgNC+YCwKICAgICAgICBg0L4v0L7QsV8lYCA9IGDQvi/QvtCxYC9zdW0qMTAwLAogICAgICAgIGDQv9GA0L5fJWAgPSBg0L/RgNC+YC9zdW0qMTAwKSAlPiUgCiAgc2VsZWN0KC1jKGDQvi/QvtCxYCwgYNC/0YDQvmAsIHN1bSkpICU+JSAKICBnYXRoZXIoa2V5ID0gcHJlcG9zaXRpb24sIHZhbHVlID0gcGVyY2VudCwgYNC+L9C+0LFfJWA6YNC/0YDQvl8lYCkgJT4lIAogIG5hLm9taXQoKSAtPiBkYXRhX3BjdApgYGAKCmBgYHtyfQpkYXRhX3BjdCAlPiUgCiAgZmlsdGVyKHJvb3QgPT0gItCz0L7QstC+0YAiKSAlPiUgIAogIGdncGxvdChhZXMocHJlcG9zaXRpb24sIHBlcmNlbnQsIGZpbGwgPSBwcmVwb3NpdGlvbikpICsgIAogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZmFjZXRfZ3JpZChnZW5yZSArIGhlYWRfcG9zIH4gZGF0ZV9vZl9jcmVhdGlvbiArIHJlZ2lzdGVyKSArCiAgbGFicyh4ID0gItCf0YDQtdC00LvQvtCzIiwgeSA9ICIgIikgKwogIHRoZW1lX2J3KCkgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UpCmBgYAoKYGBge3J9CiMgZGF0YV9wY3QgJT4lIAojICAgZmlsdGVyKHJvb3QgPT0gItC30L3QsNGCIikgJT4lIAojICAgZ2dwbG90KGFlcyhwcmVwb3NpdGlvbiwgcGVyY2VudCwgZmlsbCA9IHByZXBvc2l0aW9uKSkgKyAgCiMgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwojICAgZmFjZXRfZ3JpZChnZW5yZSArIGhlYWRfcG9zIH4gZGF0ZV9vZl9jcmVhdGlvbiArIHJlZ2lzdGVyKSArCiMgICBsYWJzKHggPSAi0J/RgNC10LTQu9C+0LMiLCB5ID0gIiAiKSArCiMgICB0aGVtZV9idygpICsKIyAgIGd1aWRlcyhmaWxsID0gRkFMU0UpCmBgYAoKYGBge3J9CiMgZGF0YV9wY3QgJT4lIAojICAgZmlsdGVyKHJvb3QgPT0gItC/0YDQvtGBIikgJT4lIAojICAgZ2dwbG90KGFlcyhwcmVwb3NpdGlvbiwgcGVyY2VudCwgZmlsbCA9IHByZXBvc2l0aW9uKSkgKyAgCiMgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwojICAgZmFjZXRfZ3JpZChnZW5yZSArIGhlYWRfcG9zIH4gZGF0ZV9vZl9jcmVhdGlvbiArIHJlZ2lzdGVyKSArCiMgICBsYWJzKHggPSAi0J/RgNC10LTQu9C+0LMiLCB5ID0gIiAiKSArCiMgICB0aGVtZV9idygpICsKIyAgIGd1aWRlcyhmaWxsID0gRkFMU0UpCmBgYAoKYGBge3J9CiMgZGF0YV9wY3QgJT4lIAojICAgZmlsdGVyKHJvb3QgPT0gItC/0L7QvNC9IikgJT4lIAojICAgZ2dwbG90KGFlcyhwcmVwb3NpdGlvbiwgcGVyY2VudCwgZmlsbCA9IHByZXBvc2l0aW9uKSkgKyAgCiMgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwojICAgZmFjZXRfZ3JpZChnZW5yZSArIGhlYWRfcG9zIH4gZGF0ZV9vZl9jcmVhdGlvbiArIHJlZ2lzdGVyKSArCiMgICBsYWJzKHggPSAi0J/RgNC10LTQu9C+0LMiLCB5ID0gIiAiKSArCiMgICB0aGVtZV9idygpICsKIyAgIGd1aWRlcyhmaWxsID0gRkFMU0UpCmBgYAoKYGBge3J9CiMgZGF0YV9wY3QgJT4lIAojICAgZmlsdGVyKHJvb3QgPT0gItGI0YPRgiIpICU+JSAKIyAgIGdncGxvdChhZXMocHJlcG9zaXRpb24sIHBlcmNlbnQsIGZpbGwgPSBwcmVwb3NpdGlvbikpICsgIAojICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKIyAgIGZhY2V0X2dyaWQoZ2VucmUgKyBoZWFkX3BvcyB+IGRhdGVfb2ZfY3JlYXRpb24gKyByZWdpc3RlcikgKwojICAgbGFicyh4ID0gItCf0YDQtdC00LvQvtCzIiwgeSA9ICIgIikgKwojICAgdGhlbWVfYncoKSArCiMgICBndWlkZXMoZmlsbCA9IEZBTFNFKQpgYGAKCmBgYHtyfQojIGRhdGFfcGN0ICU+JSAKIyAgIGZpbHRlcihyb290ID09ICLRgdC60LDQtyIpICU+JSAKIyAgIGdncGxvdChhZXMocHJlcG9zaXRpb24sIHBlcmNlbnQsIGZpbGwgPSBwcmVwb3NpdGlvbikpICsgIAojICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKIyAgIGZhY2V0X2dyaWQoZ2VucmUgKyBoZWFkX3BvcyB+IGRhdGVfb2ZfY3JlYXRpb24gKyByZWdpc3RlcikgKwojICAgbGFicyh4ID0gItCf0YDQtdC00LvQvtCzIiwgeSA9ICIgIikgKwojICAgdGhlbWVfYncoKSArCiMgICBndWlkZXMoZmlsbCA9IEZBTFNFKQpgYGAKCmBgYHtyfQojIGRhdGFfcGN0ICU+JSAKIyAgIGZpbHRlcihyb290ID09ICLQv9C40YEiKSAlPiUgCiMgICBnZ3Bsb3QoYWVzKHByZXBvc2l0aW9uLCBwZXJjZW50LCBmaWxsID0gcHJlcG9zaXRpb24pKSArICAKIyAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiMgICBmYWNldF9ncmlkKGdlbnJlICsgaGVhZF9wb3MgfiBkYXRlX29mX2NyZWF0aW9uICsgcmVnaXN0ZXIpICsKIyAgIGxhYnMoeCA9ICLQn9GA0LXQtNC70L7QsyIsIHkgPSAiICIpICsKIyAgIHRoZW1lX2J3KCkgKwojICAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkKYGBgCgpgYGB7cn0KIyBkYXRhX3BjdCAlPiUgCiMgICBmaWx0ZXIocm9vdCA9PSAi0YHRg9C20LQiKSAlPiUgCiMgICBnZ3Bsb3QoYWVzKHByZXBvc2l0aW9uLCBwZXJjZW50LCBmaWxsID0gcHJlcG9zaXRpb24pKSArICAKIyAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiMgICBmYWNldF9ncmlkKGdlbnJlICsgaGVhZF9wb3MgfiBkYXRlX29mX2NyZWF0aW9uICsgcmVnaXN0ZXIpICsKIyAgIGxhYnMoeCA9ICLQn9GA0LXQtNC70L7QsyIsIHkgPSAiICIpICsKIyAgIHRoZW1lX2J3KCkgKwojICAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkKYGBgCgpgYGB7cn0KIyBkYXRhX3BjdCAlPiUgCiMgICBmaWx0ZXIocm9vdCA9PSAi0YHQu9GL0YgiKSAlPiUgCiMgICBnZ3Bsb3QoYWVzKHByZXBvc2l0aW9uLCBwZXJjZW50LCBmaWxsID0gcHJlcG9zaXRpb24pKSArICAKIyAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiMgICBmYWNldF9ncmlkKGdlbnJlICsgaGVhZF9wb3MgfiBkYXRlX29mX2NyZWF0aW9uICsgcmVnaXN0ZXIpICsKIyAgIGxhYnMoeCA9ICLQn9GA0LXQtNC70L7QsyIsIHkgPSAiICIpICsKIyAgIHRoZW1lX2J3KCkgKwojICAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkKYGBgCgpgYGB7cn0KIyBkYXRhX3BjdCAlPiUgCiMgICBmaWx0ZXIocm9vdCA9PSAi0L/QtSIpICU+JSAKIyAgIGdncGxvdChhZXMocHJlcG9zaXRpb24sIHBlcmNlbnQsIGZpbGwgPSBwcmVwb3NpdGlvbikpICsgIAojICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKIyAgIGZhY2V0X2dyaWQoZ2VucmUgKyBoZWFkX3BvcyB+IGRhdGVfb2ZfY3JlYXRpb24gKyByZWdpc3RlcikgKwojICAgbGFicyh4ID0gItCf0YDQtdC00LvQvtCzIiwgeSA9ICIgIikgKwojICAgdGhlbWVfYncoKSArCiMgICBndWlkZXMoZmlsbCA9IEZBTFNFKQpgYGAKCiMjI9Cf0YDQtdC/0YDQvtGG0LXRgdGB0LjQvdCzINC00LDQvdC90YvRhQoK0JTQsNC90L3Ri9C1INCx0YvQu9C4INGA0LDQt9C00LXQu9C10L3RiyDQvdCwINC00LLQsCDRgdCw0LHRgdC10YLQsCAtINGC0YDQtdC90LjRgNC+0LLQvtGH0L3Ri9C5ICg3NSUpINC4INGC0LXRgdGC0L7QstGL0LkgKDI1JSkgLSDRgSDQv9C+0LzQvtGJ0YzRjiDQvNC10YLQvtC00LAg0YHRgtGA0LDRgtC40YTQuNGG0LjRgNC+0LLQsNC90L3QvtC5INCy0YvQsdC+0YDQutC4LiDQotC10YHRgtC+0LLRi9C5INGB0LDQsdGB0LXRgiDQuNGB0L/QvtC70YzQt9C+0LLQsNC70YHRjyDQv9GA0Lgg0L/RgNC+0LLQtdGA0LrQtSDQvtCx0L7QsdGJ0LDRjtGJ0LXQuSDRgdC/0L7RgdC+0LHQvdC+0YHRgtC4INC80L7QtNC10LvQtdC5LgoKYGBge3J9CiN0YWJsZShkYXRhJHByZXBvc2l0aW9uKS9zdW0odGFibGUoZGF0YSRwcmVwb3NpdGlvbikpICPQv9GA0L7RhtC10L3RgtC90L7QtSDRgdC+0L7RgtC90L7RiNC10L3QuNC1INC/0YDQtdC00LvQvtCz0L7QsiAn0L4v0L7QsScg0LggJ9C/0YDQvicgIAoKc2V0LnNlZWQoMTIzKQpkYXRhUiA8LSBkYXRhW29yZGVyKHJ1bmlmKG5yb3coZGF0YSkpKSxdCmRhdGFfc3BsaXQgPC0gY3JlYXRlRGF0YVBhcnRpdGlvbih5ID0gZGF0YVIkcHJlcG9zaXRpb24sIHAgPSAwLjc1LCBsaXN0ID0gRkFMU0UpCiNoZWFkKGRhdGFfc3BsaXQpCgp0cmFpblNldCA8LSBkYXRhUltkYXRhX3NwbGl0LCBdCnRlc3RTZXQgPC0gZGF0YVJbLWRhdGFfc3BsaXQsIF0KCmhlYWQodHJhaW5TZXQpCmBgYAoKIyMj0JvQvtCz0LjRgdGC0LjRh9C10YHQutCw0Y8g0YDQtdCz0YDQtdGB0YHQuNGPCgrQnNGLINC+0LHRg9GH0LjQu9C4INC80L7QtNC10LvRjCDQu9C+0LPQuNGB0YLQuNGH0LXRgdC60L7QuSDRgNC10LPRgNC10YHRgdC40Lgg0YEg0LjRgdC/0L7Qu9GM0LfQvtCy0LDQvdC40LXQvCDQstGB0LXRhSDQstC+0LfQvNC+0LbQvdGL0YUg0L/RgNC10LTQuNC60YLQvtGA0L7QsjoKCmBgYHtyfQpmaXQgPC0gZ2xtKHByZXBvc2l0aW9uIH4gLiwgZGF0YSA9IHRyYWluU2V0LCBmYW1pbHkgPSAiYmlub21pYWwiKQpzdW1tYXJ5KGZpdCkKYGBgCtCa0LDQuiDQstC40LTQvdC+LCDQsdCe0LvRjNGI0YPRjiDRh9Cw0YHRgtGMINC/0YDQuNC30L3QsNC60L7QsiDQsNC70LPQvtGA0LjRgtC8INGB0YfQuNGC0LDQtdGCINC30L3QsNGH0LjQvNGL0LzQuCDQtNC70Y8g0L/RgNC10LTRgdC60LDQt9Cw0L3QuNGPINC/0YDQtdC00LvQvtCz0LAuINCf0YDQvtC40LvQu9GO0YHRgtGA0LjRgNGD0LXQvCDQtdCz0L4g0L/RgNC10LTRgdC60LDQt9Cw0YLQtdC70YzQvdGL0LUg0LLQvtC30LzQvtC20L3QvtGB0YLQuCDRgSDQv9C+0LzQvtGJ0YzRjiB2aW9saW4gcGxvdHM6CgpgYGB7cn0KcmQgPC0gZGF0YS5mcmFtZShwID0gcHJlZGljdChmaXQsIG5ld2RhdGEgPSB0ZXN0U2V0LCB0eXBlID0gInJlc3BvbnNlIiksIHByZXAgPSB0ZXN0U2V0JHByZXBvc2l0aW9uLCBydCA9IHRlc3RTZXQkcm9vdCwgaHAgPSB0ZXN0U2V0JGhlYWRfcG9zLCBnbnIgPSB0ZXN0U2V0JGdlbnJlLCByZ3N0ciA9IHRlc3RTZXQkcmVnaXN0ZXIsIGR0ID0gdGVzdFNldCRkYXRlX29mX2NyZWF0aW9uKQpgYGAKCmBgYHtyfQpyZCAlPiUgCiAgYXJyYW5nZShwKSAlPiUgCiAgZ2dwbG90KGFlcyhwcmVwLCBwLCBmaWxsID0gcnQpKSArCiAgZ2VvbV92aW9saW4oKSArCiAgZmFjZXRfd3JhcCh+cnQpICsKICBsYWJzKHggPSAiIiwgeSA9ICIiKSArCiAgdGhlbWVfYncoKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkKYGBgCgpgYGB7cn0KcmQgJT4lIAogIGFycmFuZ2UocCkgJT4lIAogIGdncGxvdChhZXMocHJlcCwgcCwgZmlsbCA9IGhwKSkgKwogIGdlb21fdmlvbGluKCkgKwogIGZhY2V0X3dyYXAofmhwKSArCiAgbGFicyh4ID0gIiIsIHkgPSAiIikgKwogIHRoZW1lX2J3KCkgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UpCmBgYAoKYGBge3J9CnJkICU+JSAKICBhcnJhbmdlKHApICU+JSAKICBnZ3Bsb3QoYWVzKHByZXAsIHAsIGZpbGwgPSBnbnIpKSArCiAgZ2VvbV92aW9saW4oKSArCiAgZmFjZXRfd3JhcCh+Z25yKSArCiAgbGFicyh4ID0gIiIsIHkgPSAiIikgKwogIHRoZW1lX2J3KCkgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UpCmBgYAoKYGBge3J9CnJkICU+JSAKICBhcnJhbmdlKHApICU+JSAKICBnZ3Bsb3QoYWVzKHByZXAsIHAsIGZpbGwgPSByZ3N0cikpICsKICBnZW9tX3Zpb2xpbigpICsKICBmYWNldF93cmFwKH5yZ3N0cikgKwogIGxhYnMoeCA9ICIiLCB5ID0gIiIpICsKICB0aGVtZV9idygpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFKQpgYGAKCmBgYHtyfQpyZCAlPiUgCiAgYXJyYW5nZShwKSAlPiUgCiAgZ2dwbG90KGFlcyhwcmVwLCBwLCBmaWxsID0gZHQpKSArCiAgZ2VvbV92aW9saW4oKSArCiAgZmFjZXRfd3JhcCh+ZHQpICsKICBsYWJzKHggPSAiIiwgeSA9ICIiKSArCiAgdGhlbWVfYncoKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkKYGBgCgrQmtCw0Log0LzQvtC20L3QviDQstC40LTQtdGC0YwsINCy0YHQtSDQv9Cw0YDQsNC80LXRgtGA0YssINC60YDQvtC80LUg0LrQvtGA0L3RjyDQstC10YDRiNC40L3Riywg0L3QtSDQuNC80LXRjtGCINC30L3QsNGH0LXQvdC40LksINC60L7RgtC+0YDRi9C1INCx0Ysg0YXQvtGA0L7RiNC+INGA0LDQt9C00LXQu9GP0LvQuCDQv9GA0LXQtNC70L7Qs9C4ICLQvi/QvtCxIiDQuCAi0L/RgNC+IiAtINCy0LXRgNC+0Y/RgtC90L7RgdGC0Ywg0L/QvtC70YPRh9C40YLRjCAi0L4v0L7QsSIg0LLRi9GI0LUg0LLQviDQstGB0LXRhSDRgdC70YPRh9Cw0Y/RhS4K0KLRgNC4INC30L3QsNGH0LXQvdC40Y8g0L/RgNC40LfQvdCw0LrQsCByb290ICjQutC+0YDQtdC90Ywg0LLQtdGA0YjQuNC90YspINGA0LXQt9C60L4g0LLRi9C00LXQu9GP0Y7RgtGB0Y8g0L3QsCDQvtCx0YnQtdC8INGE0L7QvdC1OiDQstC10YDQvtGP0YLQvdC+0YHRgtGMINGD0LLQuNC00LXRgtGMINC/0YDQtdC00LvQvtCzICLQv9GA0L4iINC10YnQtSDQsdC+0LvQtdC1INC90LjQt9C60LAsINGH0LXQvCDQvtCx0YvRh9C90L4sINC10YHQu9C4INC60L7RgNC10L3RjCDQstC10YDRiNC40L3RiyAtICLRgdGD0LbQtCIgKNGA0LDRgdGB0YPQttC00LDRgtGML9GA0LDRgdGB0YPQttC00LXQvdC40LUpLCDQuCDQvdC10L7QttC40LTQsNC90L3QviAo0L/RgNC40L3QuNC80LDRjyDQstC+INCy0L3QuNC80LDQvdC40LUg0L7QsdGJ0LjQtSDRgtC10L3QtNC10L3RhtC40LgpINCy0YvRgdC+0LrQsCwg0LXRgdC70Lgg0LrQvtGA0LXQvdGMINCy0LXRgNGI0LjQvdGLIC0gItC/0LUiICjQv9C10YLRjC/Qv9C10YHQvdGPKSDQuNC70LggItGI0YPRgiIgKNGI0YPRgtC40YLRjC/RiNGD0YLQutCwKS4KCiMjI9Ch0LvRg9GH0LDQudC90YvQtSDQu9C10YHQsCAoUmFuZG9tRm9yZXN0cykKCtCh0LvRg9GH0LDQudC90YvQuSDQu9C10YEgLSDQsNC90YHQsNC80LHQu9GMINGA0LXRiNCw0Y7RidC40YUg0LTQtdGA0LXQstGM0LXQsiAo0YHRgtGA0L7QuNC8INC80L3QvtCz0L4g0LTQtdGA0LXQstGM0LXQsiDQvdCwINGB0LvRg9GH0LDQudC90YvRhSDQv9C+0LTQstGL0LHQvtGA0LrQsNGFINC4INGD0YHRgNC10LTQvdGP0LXQvCDQuNGFINGA0LXQt9GD0LvRjNGC0LDRgtGLKS4g0JfQtC4g0LDQu9Cz0L7RgNC40YLQvCDQv9GA0LjQvNC10L3Rj9C10YLRgdGPINC00LvRjyDQt9Cw0LTQsNGHINC60LvQsNGB0YHQuNGE0LjQutCw0YbQuNC4ICjQt9Cw0LLQuNGB0LjQvNCw0Y8g0L/QtdGA0LXQvNC10L3QvdCw0Y8gLSDQutCw0YLQtdCz0L7RgNC40LDQu9GM0L3QsNGPKS4gIAoKYGBge3J9CnNldC5zZWVkKDEyMykKcmYgPC0gcmFuZG9tRm9yZXN0KHByZXBvc2l0aW9uIH4gLiwgZGF0YSA9IHRyYWluU2V0LCBudHJlZSA9IDEwMDAsIG10cnkgPSAzLCBpbXBvcnRhbmNlID0gVFJVRSwgZG8udHJhY2UgPSA1MDAvMTApICNudHJlZSAtINC60L7Qu9C40YfQtdGB0YLQstC+INC/0L7RgdGC0YDQvtC10L3QvdGL0YUg0LTQtdGA0LXQstGM0LXQsiwgbXRyeSAtINGB0LvRg9GH0LDQudC90L4g0LLRi9Cx0LjRgNCw0LXQvNGL0LUg0L/RgNC4INC60LDQttC00L7QvCDQtNC10LvQtdC90LjQuCDQv9GA0LXQtNC40LrRgtC+0YDRiyAKcHJpbnQocmYpCmBgYAoKT09CIChvdXQtb2YtYmFnIGVycm9yIHJhdGUpIC0g0L7RhtC10L3QutCwINC60LDRh9C10YHRgtCy0LAg0LzQvtC00LXQu9C4INC90LAg0L3QtdC40YHQv9C+0LvRjNC30YPQtdC80L7QuSDRh9Cw0YHRgtC4INCy0YvQsdC+0YDQutC4IChvdXQtb2YtYmFnIHNhbXBsZXMpLgoKYGBge3J9CnBsb3QocmYsIG1haW4gPSAiIikgI9GH0LXRgNC90LDRjyDQutGA0LjQstCw0Y8g0L3QsCDQs9GA0LDRhNC40LrQtSAtIG91dC1vZi1iYWcg0L7RiNC40LHQutCwCmBgYAoKIyMjIyLQotC+0L3QutCw0Y8g0L3QsNGB0YLRgNC+0LnQutCwIgoK0KHRg9C00Y8g0L/QviDQstGL0LTQsNGH0LUg0YTRg9C90LrRhtC40Lgg0Lgg0LPRgNCw0YTQuNC60YMsINC/0YDQuCDQuNC30LzQtdC90LXQvdC40Lgg0LrQvtC70LjRh9C10YHRgtCy0LAg0LTQtdGA0LXQstGM0LXQsiDQsiDQsNC90YHQsNC80LHQu9C1IG91dC1vZi1iYWcg0L7RiNC40LHQutCwINC80LXQvdGP0LXRgtGB0Y8g0L3QtdC30L3QsNGH0LjRgtC10LvRjNC90L47INC/0YDQuCDRjdGC0L7QvCDQvNC40L3QuNC80LDQu9GM0L3QvtC1INC30L3QsNGH0LXQvdC40LUg0L7QvdCwINC/0YDQuNC90LjQvNCw0LXRgiDQv9GA0LggbnRyZWUgPSA2NTAuINCh0LrQvtGA0YDQtdC60YLQuNGA0YPQtdC8INC60L7Qu9C40YfQtdGB0YLQstC+INC00LXRgNC10LLRjNC10LIg0Lgg0L7Qv9GA0LXQtNC10LvQuNC8INC+0L/RgtC40LzQsNC70YzQvdC+0LUg0YfQuNGB0LvQviDQstGL0LHQuNGA0LDQtdC80YvRhSDQv9GA0Lgg0LrQsNC20LTQvtC8INC00LXQu9C10L3QuNC4INC/0YDQtdC00LjQutGC0L7RgNC+0LIg0YEg0L/QvtC80L7RidGM0Y4g0YTRg9C90LrRhtC40LggdHVuZVJGKCk6CgpgYGB7cn0KdHVuZVJGKHRyYWluU2V0WywtNl0sIHRyYWluU2V0Wyw2XSwgc3RlcEZhY3RvciA9IDAuNSwgcGxvdCA9IFRSVUUsIG50cmVlVHJ5ID0gNjUwLCB0cmFjZSA9IFRSVUUsIGltcHJvdmUgPSAwLjA1KQpgYGAKCtCd0LDQuNC80LXQvdGM0YjRg9GOINC+0YjQuNCx0LrRgyDQv9GA0L7Qs9C90L7Qt9CwINC/0L7Qu9GD0YfQsNC10Lwg0L/RgNC4INC00LXQu9C10L3QuNC4INC90LAg0L7RgdC90L7QstC1INGH0LXRgtGL0YDQtdGFINGB0LvRg9GH0LDQudC90L4g0LLRi9Cx0YDQsNC90L3Ri9GFINC/0LXRgNC10LzQtdC90L3Ri9GFIChtdHJ5ID0gNCkuCgpgYGB7cn0Kc2V0LnNlZWQoMTIzKQp0dW5lZF9yZiA8LSByYW5kb21Gb3Jlc3QocHJlcG9zaXRpb24gfiAuLCBkYXRhID0gdHJhaW5TZXQsIG50cmVlID0gNjUwLCBtdHJ5ID0gNCwgaW1wb3J0YW5jZSA9IFRSVUUsIGRvLnRyYWNlID0gNjUwLzEwKSAj0L7QsdGD0YfQsNC10Lwg0LzQvtC00LXQu9GMINGBINC90L7QstGL0LzQuCDQv9Cw0YDQsNC80LXRgtGA0LDQvNC4IApwcmludCh0dW5lZF9yZikKYGBgCgpgYGB7cn0KcGxvdCh0dW5lZF9yZiwgbWFpbiA9ICIiKQpgYGAKCmBgYHtyfQp0cmVlIDwtIGdldFRyZWUodHVuZWRfcmYsIDEsIGxhYmVsVmFyID0gVFJVRSkgI9C00L7RgdGC0LDQtdC8INC/0LXRgNCy0L7QtSDQtNC10YDQtdCy0L4KaGVhZCh0cmVlKQp0YWlsKHRyZWUpCmBgYAoKc3BsaXQgdmFyIC0g0YDQsNC30LTQtdC70Y/RjtGJ0LDRjyDQv9C10YDQtdC80LXQvdC90LDRjywgc3BsaXQgcG9pbnQgLSDQt9C90LDRh9C10L3QuNC1LCDRgSDQutC+0YLQvtGA0YvQvCDQvtC90LAg0YHRgNCw0LLQvdC40LLQsNC10YLRgdGPLCBzdGF0dXM9MSAtINC90LXRgtC10YDQvNC40L3QsNC70YzQvdGL0Lkg0YPQt9C10LssIGxlZnQgZGF1Z2h0ZXIsIHJpZ2h0IGRhdWdodGVyIC0g0YHQu9C10LTRg9GO0YnQuNC1INC30LAg0L3QuNC8INC70LXQstGL0Lkg0Lgg0L/RgNCw0LLRi9C5INGD0LfQu9GLLCBzdGF0dXM9LTEgLSDRgtC10YDQvNC40L3QsNC70YzQvdGL0Lkg0YPQt9C10LssIHByZWRpY3Rpb24gLSDQv9GA0L7Qs9C90L7QtyDQtNC70Y8g0YLQtdGA0LzQuNC90LDQu9GM0L3QvtCz0L4g0YPQt9C70LAuCgpgYGB7cn0KaGlzdCh0cmVlc2l6ZSh0dW5lZF9yZiksIG1haW4gPSAiIiwgeGxhYiA9ICLQoNCw0LfQvNC10YAg0LTQtdGA0LXQstCwIiwgeWxhYiA9ICIiLCBjb2wgPSAic3ByaW5nZ3JlZW4yIikgI9Cz0YDQsNGE0LjQuiwg0L/QvtC60LDQt9GL0LLQsNGO0YnQuNC5INC60L7Qu9C40YfQtdGB0YLQstC+INGD0LfQu9C+0LIg0YMg0L/QvtGB0YLRgNC+0LXQvdC90YvRhSDQsNC70LPQvtGA0LjRgtC80L7QvCDQtNC10YDQtdCy0YzQtdCyOyDQsdC+0LvRjNGI0LUg0LLRgdC10LPQviDQtNC10YDQtdCy0YzQtdCyICjQvtC60L7Qu9C+IDIyNSkg0YHQvtC00LXRgNC20LDRgiDQvtGCIDkwINC00L4gOTUg0YPQt9C70L7QsgpgYGAKCtCQ0LvQs9C+0YDQuNGC0Lwg0L/QvtC30LLQvtC70Y/QtdGCINC00L7QsdC40YLRjNGB0Y8g0LLRi9GB0L7QutC+0LPQviDQutCw0YfQtdGB0YLQstCwINC60LvQsNGB0YHQuNGE0LjQutCw0YbQuNC4LCDQvdC+INGB0L7QstC10YDRiNC10L3QvdC+INC90LUg0L7QsdGK0Y/RgdC90Y/QtdGCLCDQutCw0Log0YPRgdGC0YDQvtC10L3RiyDQtNCw0L3QvdGL0LUuINCf0L7QvdGP0YLRjCwg0YfRgtC+INC/0YDQvtC40YHRhdC+0LTQuNGCICLQstC90YPRgtGA0LgiLCDQtNC+0YHRgtCw0YLQvtGH0L3QviDRgdC70L7QttC90L4g0LTQsNC20LUg0L/QviDQvtC00L3QvtC80YMg0LTQtdGA0LXQstGDICjQsCDQstGB0LXQs9C+INC40YUg0L3QtdGB0LrQvtC70YzQutC+INGB0L7RgtC10L0pLiDQlNC70Y8g0L7Qv9C40YHQsNC90LjRjyDQv9C+0LvRg9GH0LXQvdC90YvRhSDRgNC10LfRg9C70YzRgtCw0YLQvtCyINC80Ysg0LzQvtC20LXQvCDQvtGG0LXQvdC40YLRjCwg0L3QsNGB0LrQvtC70YzQutC+INCy0LDQttC10L0g0YLQvtGCINC40LvQuCDQuNC90L7QuSDQv9GA0LXQtNC40LrRgtC+0YA6IAoKYGBge3J9CmltcG9ydGFuY2UodHVuZWRfcmYsIHR5cGUgPSAxKQpgYGAKCtCh0LDQvNGL0Lwg0LfQvdCw0YfQuNC80YvQvCDQv9GA0LXQtNC40LrRgtC+0YDQvtC8INC+0LrQsNC30YvQstCw0LXRgtGB0Y8gcm9vdCwgItC/0L7Qu9C10LfQvdC+0YHRgtGMIiDQstGB0LXRhSDQvtGB0YLQsNC70YzQvdGL0YUg0L/QtdGA0LXQvNC10L3QvdGL0YUg0LTQu9GPINC60LvQsNGB0YHQuNGE0LjQutCw0YbQuNC4INC00LDQvdC90YvRhSDQs9C+0YDQsNC30LTQviDQvdC40LbQtS4gIAoKYGBge3J9CnZhckltcFBsb3QodHVuZWRfcmYsIHR5cGUgPSAxLCBtYWluID0gIiIpCmBgYAoKYGBge3J9CnJmUHJlZGljdGVkIDwtIHByZWRpY3QodHVuZWRfcmYsIHRlc3RTZXQpCmNvbmZ1c2lvbk1hdHJpeChyZlByZWRpY3RlZCwgdGVzdFNldCRwcmVwb3NpdGlvbikgI9GB0YLRgNC+0LjQvCDQvNCw0YLRgNC40YbRgyDQvtGI0LjQsdC+0Log0L3QsCDRgtC10YHRgtC+0LLRi9GFINC00LDQvdC90YvRhQpgYGAKCmBgYHtyfQojIG1ldHJpY3MgPC0gYyhBY2N1cmFjeSA9ICgxMDI0ICsgNDUpL25yb3codGVzdFNldCksIFByZWNpc2lvbiA9IDEwMjQvKDEwMjQgKyAxNjApLCBSZWNhbGwgPSAxMDI0LygxMDI0ICsgNTgpLCBTcGVjaWZpY2l0eSA9IDQ1Lyg0NSArIDE2MCkpCiMgbWV0cmljcwpgYGAKCtCc0L7QtNC10LvRjCDRgdC60LvQvtC90L3QsCDQv9GA0LXQtNGB0LrQsNC30YvQstCw0YLRjCDQv9GA0LXQtNC70L7QsyDigJzQvi/QvtCx4oCdINCyINCx0L7Qu9GM0YjQuNC90YHRgtCy0LUg0YHQu9GD0YfQsNC10LIgLSDQv9C+0Y3RgtC+0LzRgyDRgdCw0LzQvtC5INGH0LDRgdGC0L7RgtC90L7QuSDQvtGI0LjQsdC60L7QuSDRj9Cy0LvRj9C10YLRgdGPINC/0YDQtdC00YHQutCw0LfQsNC90LjQtSDigJzQvi/QvtCx4oCdINC/0YDQuCDQuNGB0YLQuNC90L3QvtC8INC30L3QsNGH0LXQvdC40Lgg4oCc0L/RgNC+4oCdLiDQrdGC0L4g0L/RgNC+0LjRgdGF0L7QtNC40YIg0L/QvtGC0L7QvNGDLCDRh9GC0L4g0YHQu9GD0YfQsNC10LIg0YPQv9C+0YLRgNC10LHQu9C10L3QuNGPINC/0YDQtdC00LvQvtCz0LAg4oCc0L4v0L7QseKAnSDQsiDQvdCw0YjQuNGFINC00LDQvdC90YvRhSDQvdCw0LzQvdC+0LPQviDQsdC+0LvRjNGI0LUgLSA0MzI4INC90LDQsdC70Y7QtNC10L3QuNC5INGBIOKAnNC+L9C+0LHigJ0g0L/RgNC+0YLQuNCyIDgyMyDQvdCw0LHQu9GO0LTQtdC90LjQuSDRgSDigJzQv9GA0L7igJ0uINCc0LXRgtGA0LjQutC4INC60LDRh9C10YHRgtCy0LAg0L/RgNC4INGN0YLQvtC8INC+0LrQsNC30YvQstCw0Y7RgtGB0Y8g0L3QtdC/0LvQvtGF0LjQvNC4LCDQvdC+INC/0YDQuNGH0LjQvdCwINGN0YLQvtCz0L4gLSDQvdC1INGD0LTQsNGH0L3Ri9C5INC/0L7QtNCx0L7RgCDQv9GA0LjQt9C90LDQutC+0LIg0Lgg0YPRgdC/0LXRiNC90L7QtSDQvtCx0YPRh9C10L3QuNC1INCw0LvQs9C+0YDQuNGC0LzQsCwg0LAg0LLRi9GB0L7QutCw0Y8g0YfQsNGB0YLQvtGC0L3QvtGB0YLRjCDQvtC00L3QvtCz0L4g0LjQtyDQutC70LDRgdGB0L7Qsiwg0Log0LrQvtGC0L7RgNC+0LzRgyDQvNC+0LTQtdC70Ywg0LIg0YDQtdC30YPQu9GM0YLQsNGC0LUgItGB0LrQu9C+0L3Rj9C10YLRgdGPIi4KCiMj0JLRi9Cy0L7QtAoK0JjRgtCw0LosINC/0L7RgdGC0YDQvtC10L3QvdGL0LUg0L3QsNC80Lgg0LzQvtC00LXQu9C4INC+0L/RgNC+0LLQtdGA0LPQsNGO0YIg0L3QsNGI0YMg0L3Rg9C70LXQstGD0Y4g0LPQuNC/0L7RgtC10LfRgyDRgdGA0LDQt9GDINC/0L4g0LTQstGD0LwsINC/0YDQuNGH0LXQvCDQv9GA0L7RgtC40LLQvtGA0LXRh9Cw0YnQuNC8INC00YDRg9CzINC00YDRg9Cz0YMg0L/RgNC40YfQuNC90LDQvC4gCtChINC+0LTQvdC+0Lkg0YHRgtC+0YDQvtC90YssINC80L7QtNC10LvRjCDQu9C+0LPQuNGB0YLQuNGH0LXRgdC60L7QuSDRgNC10LPRgNC10YHRgdC40Lgg0L/RgNC40LfQvdCw0LXRgiDQt9C90LDRh9C40LzRi9C80LgsINC/0L7QvNC40LzQviDRgNC10LPQuNGB0YLRgNCwINC4INC20LDQvdGA0LAg0YLQtdC60YHRgtCwLCDQuCDQtNGA0YPQs9C40LUg0L/QsNGA0LDQvNC10YLRgNGLIC0g0Lgg0LrQvtGA0LXQvdGMINGB0LvQvtCy0LAsINC4INC10LPQviDRh9Cw0YHRgtGMINGA0LXRh9C4LCDQuCDQtNCw0YLRgyDQstC+0LfQvdC40LrQvdC+0LLQtdC90LjRjyDRgtC10LrRgdGC0LAuINCU0LXRgNC10LLRjNGPINCyINGB0LvRg9GH0LDQudC90L7QvCDQu9C10YHQtSDRgtCw0LrQttC1INC/0YDQvtC40LfQstC+0LTRj9GCINC00LXQu9C10L3QuNGPINC/0L4g0LLRgdC10Lwg0Y3RgtC40Lwg0L/QsNGA0LDQvNC10YLRgNCw0LwsINGB0LDQvNGL0Lwg0LfQvdCw0YfQuNC80YvQvCDQv9GA0Lgg0Y3RgtC+0Lwg0L/QvtC70LDQs9Cw0Y8g0LrQvtGA0LXQvdGMINCy0LXRgNGI0LjQvdGLLCDQsCDQvdCw0LjQvNC10L3QtdC1INC30L3QsNGH0LjQvNGL0LwgLSDQttCw0L3RgC4K0KEg0LTRgNGD0LPQvtC5INGB0YLQvtGA0L7QvdGLLCDQsNCx0YHQvtC70Y7RgtC90L7QtSDQv9GA0LXQvtCx0LvQsNC00LDQvdC40LUg0L/RgNC10LTQu9C+0LPQsCAi0L4v0L7QsSIg0L3QsNC0INC/0YDQtdC00LvQvtCz0L7QvCAi0L/RgNC+IiDQsiDRgtC10LrRgdGC0LDRhSDQv9GA0LjQstC+0LTQuNGCINC6INGC0L7QvNGDLCDRh9GC0L4g0L3QuCDQvtC00LjQvSDQuNC3INCy0YvQsdGA0LDQvdC90YvRhSDQvdCw0LzQuCDQv9GA0LjQt9C90LDQutC+0LIg0L3QtSDQvNC+0LbQtdGCINGF0L7RgNC+0YjQviDRgNCw0LfQtNC10LvQuNGC0Ywg0YHQu9GD0YfQsNC4INGD0L/QvtGC0YDQtdCx0LvQtdC90LjRjyAi0L4v0L7QsSIg0LggItC/0YDQviIgLSDQsiDQu9GO0LHRi9GFINC60L7QvNCx0LjQvdCw0YbQuNGP0YUgItC+L9C+0LEiINC+0LrQsNC30YvQstCw0LXRgtGB0Y8g0YfQsNGB0YLQvtGC0L3QtdC1LiAK0JXQtNC40L3RgdGC0LLQtdC90L3Ri9C1INC30L3QsNGH0LXQvdC40Y8g0L/QsNGA0LDQvNC10YLRgNC+0LIsINC/0YDQuCDQutC+0YLQvtGA0YvRhSDQstC10YDQvtGP0YLQvdC+0YHRgtGMICLQv9GA0L4iINC00LXQudGB0YLQstC40YLQtdC70YzQvdC+INGB0LjQu9GM0L3QviDQv9C+0LLRi9GI0LDQtdGC0YHRjyAo0YfRgtC+ICLQu9C+0LLQuNGC0YHRjyIg0L7QsdC+0LjQvNC4INCw0LvQs9C+0YDQuNGC0LzQsNC80LgpIC0g0Y3RgtC+INC60L7RgNC90LggItC/0LUiICjQv9C10YLRjC/Qv9C10YHQvdGPKSDQuCAi0YjRg9GCIiAo0YjRg9GC0LjRgtGML9GI0YPRgtC60LApLgrQn9C+0LjRgdC6INC00YDRg9Cz0LjRhSDQv9GA0LjQt9C90LDQutC+0LIsINC60L7RgtC+0YDRi9C1INCx0Ysg0YXQvtGA0L7RiNC+INGA0LDQt9C00LXQu9C40LvQuCDQvdCw0YjQuCDQv9GA0LXQtNC70L7Qs9C4LCDQvtGB0YLQsNC10YLRgdGPINC30LDQtNCw0YfQtdC5INCx0YPQtNGD0YnQuNGFINC40YHRgdC70LXQtNC+0LLQsNC90LjQuS4KCiMjI0FwcGVuZGl4IEEKClRyZWxsaXMgZ3JhcGhzICjQs9GA0LDRhNC40LrQuCwg0LLQuNC30YPQsNC70LjQt9C40YDRg9GO0YnQuNC1INC+0L/RgNC10LTQtdC70LXQvdC90YvQuSDRgdCw0LHRgdC10YIg0LTQsNC90L3Ri9GFKToKCmBgYHtyfQojIGRhdGEgJT4lCiMgICBjb3VudChyb290LCBnZW5yZSwgaGVhZF9wb3MsIGRhdGVfb2ZfY3JlYXRpb24sIHJlZ2lzdGVyLCBwcmVwb3NpdGlvbikgJT4lCiMgICBzcHJlYWQoa2V5ID0gcHJlcG9zaXRpb24sIHZhbHVlID0gbikgLT4gZGF0YV9zdW1tZWQKYGBgCgpgYGB7cn0KIyBiYXJjaGFydChg0L4v0L7QsWArYNC/0YDQvmAgfiBnZW5yZSB8IHJlZ2lzdGVyICsgcm9vdCArIGhlYWRfcG9zICsgZGF0ZV9vZl9jcmVhdGlvbiwgZGF0YV9zdW1tZWQsIGxheW91dCA9IGMoNSwgMiksIGF1dG8ua2V5ID0gVFJVRSwgeGxhYiA9ICLQltCw0L3RgCDRgtC10LrRgdGC0LAiLCB5bGFiID0gItCn0LjRgdC70L4g0L/RgNC40LzQtdGA0L7QsiIpCmBgYAoKYGBge3J9CiMgYmFyY2hhcnQoYNC+L9C+0LFgK2DQv9GA0L5gIH4gaGVhZF9wb3MgfCByZWdpc3RlciArIGdlbnJlICsgcm9vdCArIGRhdGVfb2ZfY3JlYXRpb24sIGRhdGFfc3VtbWVkLCBsYXlvdXQgPSBjKDUsIDIpLCBhdXRvLmtleSA9IFRSVUUsIHhsYWIgPSAi0KfQsNGB0YLRjCDRgNC10YfQuCDQstC10YDRiNC40L3RiyIsIHlsYWIgPSAi0KfQuNGB0LvQviDQv9GA0LjQvNC10YDQvtCyIikKYGBgCgpgYGB7cn0KIyBiYXJjaGFydChg0L4v0L7QsWArYNC/0YDQvmAgfiByZWdpc3RlciB8IHJvb3QgKyBnZW5yZSArIGhlYWRfcG9zICsgZGF0ZV9vZl9jcmVhdGlvbiwgZGF0YV9zdW1tZWQsIGxheW91dCA9IGMoNSwgMSksIGFzcGVjdCA9IDEuNSwgYXV0by5rZXkgPSBUUlVFLCB4bGFiID0gItCg0LXQs9C40YHRgtGAINGA0LXRh9C4IiwgeWxhYiA9ICLQp9C40YHQu9C+INC/0YDQuNC80LXRgNC+0LIiKQpgYGAKCmBgYHtyfQojIGJhcmNoYXJ0KGDQvi/QvtCxYCtg0L/RgNC+YCB+IHJvb3QgfCByZWdpc3RlciArIGdlbnJlICsgaGVhZF9wb3MgKyBkYXRlX29mX2NyZWF0aW9uLCBkYXRhX3N1bW1lZCwgbGF5b3V0ID0gYygxLCAyKSwgYXV0by5rZXkgPSBUUlVFLCB4bGFiID0gItCa0L7RgNC10L3RjCIsIHlsYWIgPSAi0KfQuNGB0LvQviDQv9GA0LjQvNC10YDQvtCyIikKYGBgCgpgYGB7cn0KIyBiYXJjaGFydChg0L4v0L7QsWArYNC/0YDQvmAgfiBkYXRlX29mX2NyZWF0aW9uIHwgcmVnaXN0ZXIgKyByb290ICsgaGVhZF9wb3MgKyBnZW5yZSwgZGF0YV9zdW1tZWQsIGxheW91dCA9IGMoNCwgMiksIGF1dG8ua2V5ID0gVFJVRSwgeGxhYiA9ICLQlNCw0YLQsCDRgdC+0LfQtNCw0L3QuNGPINGC0LXQutGB0YLQsCIsIHlsYWIgPSAi0KfQuNGB0LvQviDQv9GA0LjQvNC10YDQvtCyIikKYGBgCg==