Загрузка библиотек

library(tidyverse)
library(xml2)
library(igraph)
library(ggraph)

Постановка задачи

В этой работе строится граф персонажей романа «Война и мир». Связь между двумя персонажами определяется по факту прямой речи: персонажи считаются связанными, если они вступают в диалог.

Вес ребра показывает, сколько раз один персонаж обращается к другому (реплика диалога). Граф строится по всем томам, представленным в XML-файле.

Дополнительно вводится фильтрация: в анализ включаются только персонажи, у которых не меньше заданного числа реплик (конкретно в примере 10).

Импорт и парсинг XML

filename <- "War_and_Peace.xml"

doc <- read_xml(filename)
ns <- xml_ns_rename(xml_ns(doc), d1 = "tei")
rootnode <- xml_root(doc)

Извлечение всех глав из всех томов

chapters <- xml_find_all(
  rootnode,
  "//tei:text//tei:div[@type='chapter']",
  ns
)

length(chapters)
[1] 358

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

Сбор данных о речевых актах

dialogues <- tibble(
  volume = character(),
  chapter = character(),
  speech_id = character(),
  speaker = character(),
  addressee = character()
)

for (i in seq_along(chapters)) {
  chapter_node <- chapters[[i]]

  volume_node <- xml_find_first(
    chapter_node,
    "./ancestor::tei:div[@type='volume'][1]",
    ns
  )

  volume_id <- xml_attr(volume_node, "n")
  chapter_id <- paste0("chapter_", i)

  said_nodes <- xml_find_all(
    chapter_node,
    ".//tei:said[@who and @corresp]",
    ns
  )

  speech_id <- xml_attr(said_nodes, "speech_id")
  speaker <- xml_attr(said_nodes, "who")
  addressee <- xml_attr(said_nodes, "corresp")

  chapter_tbl <- tibble(
    volume = volume_id,
    chapter = chapter_id,
    speech_id = speech_id,
    speaker = speaker,
    addressee = addressee
  ) |>
    filter(!is.na(speaker)) |>
    filter(!is.na(addressee)) |>
    filter(speaker != "") |>
    filter(addressee != "") |>
    filter(speaker != addressee)

  dialogues <- bind_rows(dialogues, chapter_tbl)
}

dialogues |>
  head(10)

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

Подсчёт числа реплик на персонажа

char_counts <- dialogues |>
  pivot_longer(
    cols = c(speaker, addressee),
    values_to = "character"
  ) |>
  count(character, name = "n_replicas", sort = TRUE)

char_counts |>
  head(15)

Считается речевая активность персонажей. Персонаж учитывается и как говорящий, и как адресат, потому что обе роли важны для участия в коммуникационной сети.

Фильтрация персонажей по числу реплик

threshold <- 10

valid_chars <- char_counts |>
  filter(n_replicas >= threshold)

valid_chars |>
  head(15)

Порог фильтрации можно менять. Например, можно сравнить графы при threshold <- 5, 10 или 20.

Фильтрация исходных речевых актов

dialogues_filtered <- dialogues |>
  filter(speaker %in% valid_chars$character) |>
  filter(addressee %in% valid_chars$character)

dialogues_filtered |>
  head(10)

Здесь остаются только те речевые акты, в которых оба участника проходят порог по числу реплик.

Важно: в этой версии решения дубликаты не удаляются. Каждая реплика учитывается как отдельное наблюдение.

Формирование рёбер графа

edges <- dialogues_filtered |>
  mutate(
    from = if_else(speaker < addressee, speaker, addressee),
    to = if_else(speaker < addressee, addressee, speaker)
  ) |>
  count(from, to, name = "weight", sort = TRUE)

edges |>
  head(15)

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

Вес ребра weight показывает, сколько раз данная пара персонажей вступала в прямое речевое взаимодействие.

Формирование вершин графа

vertices <- tibble(
  name = sort(unique(c(edges$from, edges$to)))
)

vertices |>
  head(15)

Здесь перечисляются все персонажи, которые вошли в граф после фильтрации.

Создание объекта графа

g <- graph_from_data_frame(
  edges,
  directed = FALSE,
  vertices = vertices
)

g
IGRAPH 8b71d78 UNW- 100 325 -- 
+ attr: name (v/c), weight (e/n)
+ edges from 8b71d78 (vertex names):
 [1] NatashaRostova          --Nikolai_Rostov             
 [2] AndreyBolkonsky         --Pierre_Bezukhov            
 [3] NatashaRostova          --Sonya_Rostova              
 [4] Countess_Natalya_Rostova--NatashaRostova             
 [5] NatashaRostova          --Pierre_Bezukhov            
 [6] Boris_Drubetskoy        --Nikolai_Rostov             
 [7] Nikolai_Rostov          --Telyanin                   
 [8] Nikolai_Rostov          --Vasily__Vasska__Denisov    
+ ... omitted several edges

Получен объект igraph. Граф является неориентированным и взвешенным: вершины соответствуют персонажам, а ребра отражают речевые взаимодействия между ними. Вес ребра показывает, сколько раз один персонаж обращался к другому. Для графа были рассчитаны базовые характеристики: число вершин, число ребер, число компонент связности и плотность. Эти параметры позволяют описать общую структуру сети до более детального анализа.

Краткое описание графа

vcount(g)
[1] 100
ecount(g)
[1] 325
components(g)
$membership
                               Anatole_Kuragin                                AndreyBolkonsky 
                                             1                                              1 
                         Anna_Pavlovna_Scherer                                      Arakcheev 
                                             1                                              1 
                                      Balashev                                        Bilibin 
                                             1                                              1 
                                  Bolhovitinov                               Boris_Drubetskoy 
                                             1                                              1 
                              Captain_Ramballe                       Catiche(eldest princess) 
                                             1                                              1 
                             Count_Ilya_Rostov                               Count_Rostopchin 
                                             1                                              1 
                      Countess_Natalya_Rostova                                         Danila 
                                             1                                              1 
                                Dron_Zakharych                                       Dunyasha 
                                             1                                              1 
                     Dunyasha (Bolkonsky maid)                   Emperor_Francis_I_of_Austria 
                                             1                                              1 
                                esaul Lovaysky                       Fedor_Ivanovich_Dolokhov 
                                             1                                              1 
                                    Ferapontov                                General_Davoust 
                                             1                                              1 
                                  General_Mack                                governor's wife 
                                             1                                              1 
                                 HeleneKuragin                              Hippolyte_Kuragin 
                                             1                                              1 
                                        Ilagin                                          Ilyin 
                                             1                                              1 
                     Joseph_Alexeevich_Bazdeev                                 Julie_Karagina 
                                             1                                              1 
                                      Kirsten                                       Lavrushka 
                                             1                                              1 
            Lieutenant_Alphonse_Karlovich_Berg                         mademoiselle_Bourienne 
                                             1                                              1 
                 Marya_Dmitriyevna_Akhrosimova                          Marya_Lvovna_Karagina 
                                             1                                              1 
                             Mavra_Kuzminishna                                        Michaud 
                                             1                                              1 
                  Mikhail_Ilarionovich_Kutuzov                             Napoleon_Bonaparte 
                                             1                                              1 
                                NatashaRostova                                 Nikolai_Rostov 
                                             1                                              1 
                                  Petya_Rostov                                Pierre_Bezukhov 
                                             1                                              1 
                               Platon_Karataev                               Prince_Bagration 
                                             1                                              1 
                             Prince_Dolgorukov                               Prince_Kozlovsky 
                                             1                                              1 
                              Prince_Nesvitsky                       Prince_Nikolay_Bolkonsky 
                                             1                                              1 
         Princess_Anna_Mikhaylovna_Drubetskaya Princess_Elisabeta__Lisa__Karlovna_Bolkonskaya 
                                             1                                              1 
                   Princess_Mariya_Bolkonskaya                      Pyotr_Nikolaitch_Shinshin 
                                             1                                              1 
                          regimental commander                                          Rugai 
                                             1                                              1 
                                   Shcherbinin                                  Sonya_Rostova 
                                             1                                              1 
                          Staff_Captain_Tushin                                       Telyanin 
                                             1                                              1 
                              Tikhon (servant)                            Tikhon_Shtcherbatov 
                                             1                                              1 
                                       Timohin                     Tsar_Alexander_I_of_Russia 
                                             1                                              1 
                              Tushin's gunner                                           Uncle 
                                             1                                              1 
                                Vasili_Kuragin                        Vasily__Vasska__Denisov 
                                             1                                              1 
                                  Vera_Rostova                                      Villarsky 
                                             1                                              1 
                                      viscount                                 Yakov_Alpatych 
                                             1                                              1 
                                      Yermolov                      young Nikolenka Bolkonsky 
                                             1                                              1 
                                       Zherkov                                       адъютант 
                                             1                                              1 
                                        Балага                                       берейтор 
                                             1                                              2 
                                      Богданыч                                        генерал 
                                             1                                              1 
                                         гусар                                         денщик 
                                             1                                              1 
                                        Десаль                                         доктор 
                                             1                                              1 
                                       лекарша                                        Лихачев 
                                             1                                              1 
                                     ополченец                                         офицер 
                                             1                                              1 
                                    Пелагеюшка                                пехотный офицер 
                                             1                                              1 
                                        плясун                            Смольянинов (ритор) 
                                             1                                              1 
                                        солдат                                        солдаты 
                                             1                                              1 
                                    Сперанский                                            Тит 
                                             1                                              2 
                                   фельдфебель                                       фельдшер 
                                             1                                              1 
                                       француз                                    штаб-офицер 
                                             1                                              1 

$csize
[1] 98  2

$no
[1] 2
edge_density(g)
[1] 0.06565657

Здесь выводятся базовые характеристики графа: число вершин, число рёбер, число компонент связности и плотность.

Атрибуты узлов: показатели важности

V(g)$degree <- degree(g)
V(g)$weighted_degree <- strength(g)
V(g)$closeness <- closeness(g)
V(g)$betweenness <- betweenness(g)
V(g)$eigenvector <- eigen_centrality(g)$vector

Здесь каждому узлу добавляются основные показатели важности.

Топ персонажей по взвешенной степени

top_nodes <- tibble(
  name = V(g)$name,
  degree = V(g)$degree,
  weighted_degree = V(g)$weighted_degree,
  closeness = V(g)$closeness,
  betweenness = V(g)$betweenness,
  eigenvector = V(g)$eigenvector
) |>
  arrange(-weighted_degree)

top_nodes |>
  head(15)

Эта таблица показывает наиболее активных персонажей в коммуникационной сети.

Топ рёбер по весу

top_edges <- edges |>
  arrange(-weight)

top_edges |>
  head(15)

Здесь видно, какие пары персонажей чаще всего разговаривают друг с другом.

Подграф: k-core

В качестве подграфа выбран k-core, так как этот метод выделяет плотное структурное ядро сети, а не просто удаляет слабосвязанные вершины. Порог core >= 3 позволяет убрать периферийных персонажей и сохранить центральную часть коммуникационной структуры, которая остается достаточно большой для анализа.

V(g)$core <- coreness(g)

table(V(g)$core)

 1  2  3  4  5  6 
18 19 14 11  3 35 
g_core <- induced_subgraph(g, vids = V(g)[core >= 3])

g_core
IGRAPH 8b8baf3 UNW- 63 271 -- 
+ attr: name (v/c), degree (v/n), weighted_degree (v/n), closeness (v/n), betweenness
| (v/n), eigenvector (v/n), core (v/n), weight (e/n)
+ edges from 8b8baf3 (vertex names):
 [1] NatashaRostova          --Nikolai_Rostov             
 [2] AndreyBolkonsky         --Pierre_Bezukhov            
 [3] NatashaRostova          --Sonya_Rostova              
 [4] Countess_Natalya_Rostova--NatashaRostova             
 [5] NatashaRostova          --Pierre_Bezukhov            
 [6] Boris_Drubetskoy        --Nikolai_Rostov             
 [7] Nikolai_Rostov          --Vasily__Vasska__Denisov    
+ ... omitted several edges
vcount(g_core)
[1] 63
ecount(g_core)
[1] 271

Здесь создаётся подграф с условием core >= 3. Если нужно, это значение можно изменить.

Анализ сообществ

cw <- cluster_walktrap(g, steps = 45)

membership(cw) |>
  head()
      Anatole_Kuragin       AndreyBolkonsky Anna_Pavlovna_Scherer             Arakcheev 
                    4                     5                     1                     5 
             Balashev               Bilibin 
                   10                     5 
modularity(cw)
[1] 0.2568506

Для анализа сообществ был использован алгоритм Walktrap. Он позволяет выделить группы персонажей, внутри которых связи плотнее, чем между группами. Значение модулярности показывает, насколько отчетливо сеть делится на такие сообщества: в данном случае модульная структура выражена, но группы не являются полностью изолированными, что хорошо соответствует устройству большого романа с пересекающимися сюжетными линиями.

V(g)$community <- membership(cw)

Точки сочленения

articulation_points(g)
+ 10/100 vertices, named, from 8b71d78:
 [1] Yakov_Alpatych               Uncle                        Petya_Rostov                
 [4] Tsar_Alexander_I_of_Russia   Julie_Karagina               Pierre_Bezukhov             
 [7] Nikolai_Rostov               Mikhail_Ilarionovich_Kutuzov Prince_Nikolay_Bolkonsky    
[10] AndreyBolkonsky             

Точки сочленения — это узлы, удаление которых увеличивает число компонент связности.

Клики

largest_cliques(g)
[[1]]
+ 7/100 vertices, named, from 8b71d78:
[1] AndreyBolkonsky             Pierre_Bezukhov             Nikolai_Rostov             
[4] Countess_Natalya_Rostova    NatashaRostova              Sonya_Rostova              
[7] Princess_Mariya_Bolkonskaya

Клики — это полностью связные подмножества узлов.

Среди точек сочленения закономерно выделяются Pierre_Bezukhov, Nikolai_Rostov и AndreyBolkonsky, что подтверждает их роль посредников между разными частями сети. Такие узлы особенно важны для связности графа: их удаление сильнее всего меняет структуру сети. Клики, найденные в графе, показывают наиболее плотные группы персонажей, где каждый участник связан с каждым.

Визуализация полного графа

set.seed(42)

ggraph(g, layout = "stress") +
  geom_edge_link(aes(alpha = weight), width = 0.5, show.legend = FALSE) +
  geom_node_point(
    aes(size = weighted_degree, color = as.factor(community)),
    show.legend = TRUE
  ) +
  geom_node_text(
    aes(
      filter = weighted_degree > mean(weighted_degree),
      label = name
    ),
    repel = TRUE,
    size = 3,
    show.legend = FALSE
  ) +
  theme_void()

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

Визуализация подграфа k-core

set.seed(42)

ggraph(g_core, layout = "stress") +
  geom_edge_link(aes(alpha = weight), width = 0.6, show.legend = FALSE) +
  geom_node_point(
    aes(size = weighted_degree, color = as.factor(core)),
    show.legend = TRUE
  ) +
  geom_node_text(
    aes(label = name),
    repel = TRUE,
    size = 3,
    show.legend = FALSE
  ) +
  theme_void()

Подграф показывает наиболее плотное ядро сети персонажей.

Дендрограмма сообществ

par(mar = rep(0, 4))
plot(cw, g,
     vertex.label.cex = 0.5,   # размер текста
     vertex.label.color = "black",
     vertex.size = 3)          # размер точек (чтобы не мешали)

Вывод

В работе был построен граф персонажей романа «Война и мир» на основе XML-разметки. Данные извлекались из тегов , где фиксируется, кто говорит и кому, поэтому связь между персонажами определяется через прямую речь. Вес ребра показывает число таких обращений. При сборе данных использовались циклы, фильтрация и агрегирование, что делает процедуру воспроизводимой.

Полученный граф является неориентированным и взвешенным. После фильтрации по числу реплик он включает около 100 вершин и более 300 ребер, при этом почти все персонажи входят в одну большую компоненту. Это соответствует структуре романа Толстого как единого повествовательного мира с множеством пересекающихся линий. Наиболее центральные позиции занимают Пьер Безухов, Наташа Ростова, Николай Ростов и Андрей Болконский. Это ожидаемо с литературной точки зрения: именно эти персонажи находятся в центре основных сюжетных линий и активно взаимодействуют с разными группами героев. Например, Пьер соединяет светское общество, военную линию и философские эпизоды, а Наташа связана как с семьей Ростовых, так и с линией Болконских.

В качестве подграфа был выбран метод k-core, позволяющий выделить плотное ядро сети. Подграф с core ≥ 3 включает большинство ключевых персонажей и отражает центральный круг общения, в который входят Ростовы, Болконские и их ближайшее окружение. Визуализация показывает, что именно эти группы формируют ядро романа, тогда как второстепенные персонажи образуют периферию.

Анализ сообществ с помощью алгоритма Walktrap выявил несколько групп, которые можно интерпретировать как сюжетные и социальные кластеры: семейный круг Ростовых, круг Болконских, а также персонажи, связанные с военной и придворной линиями. Значение модулярности около 0.35 показывает, что эти группы различимы, но не изолированы, что хорошо соответствует композиции романа, где линии постоянно пересекаются.

Дополнительно были найдены точки сочленения и клики. Среди точек сочленения оказываются Пьер Безухов, Николай Ростов и Андрей Болконский — они играют роль посредников между различными частями сети. Крупнейшая клика объединяет персонажей из центральных семейных линий (Ростовы и Болконские), что отражает их тесную взаимосвязь в тексте. В целом полученный граф хорошо воспроизводит литературную структуру романа: он показывает плотное ядро ключевых героев и более разреженную периферию второстепенных персонажей.

LS0tDQp0aXRsZTogItCk0LjQvdCw0LvRjNC90YvQuSDQv9GA0L7QtdC60YIgMjog0YHQtdGC0Ywg0L/QtdGA0YHQvtC90LDQttC10Lkg0LIg0YDQvtC80LDQvdC1IMKr0JLQvtC50L3QsCDQuCDQvNC40YDCuyINCmF1dGhvcjogItCU0LzQuNGC0YDQuNC5INCf0YDQvtC90LjQvSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjINCX0LDQs9GA0YPQt9C60LAg0LHQuNCx0LvQuNC+0YLQtdC6DQoNCmBgYHtyIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoeG1sMikNCmxpYnJhcnkoaWdyYXBoKQ0KbGlicmFyeShnZ3JhcGgpDQpgYGANCg0KIyMg0J/QvtGB0YLQsNC90L7QstC60LAg0LfQsNC00LDRh9C4DQoNCtCSINGN0YLQvtC5INGA0LDQsdC+0YLQtSDRgdGC0YDQvtC40YLRgdGPINCz0YDQsNGEINC/0LXRgNGB0L7QvdCw0LbQtdC5INGA0L7QvNCw0L3QsCDCq9CS0L7QudC90LAg0Lgg0LzQuNGAwrsuDQrQodCy0Y/Qt9GMINC80LXQttC00YMg0LTQstGD0LzRjyDQv9C10YDRgdC+0L3QsNC20LDQvNC4INC+0L/RgNC10LTQtdC70Y/QtdGC0YHRjyDQv9C+INGE0LDQutGC0YMg0L/RgNGP0LzQvtC5INGA0LXRh9C4Og0K0L/QtdGA0YHQvtC90LDQttC4INGB0YfQuNGC0LDRjtGC0YHRjyDRgdCy0Y/Qt9Cw0L3QvdGL0LzQuCwg0LXRgdC70Lgg0L7QvdC4INCy0YHRgtGD0L/QsNGO0YIg0LIg0LTQuNCw0LvQvtCzLg0KDQrQktC10YEg0YDQtdCx0YDQsCDQv9C+0LrQsNC30YvQstCw0LXRgiwg0YHQutC+0LvRjNC60L4g0YDQsNC3INC+0LTQuNC9INC/0LXRgNGB0L7QvdCw0LYg0L7QsdGA0LDRidCw0LXRgtGB0Y8g0Log0LTRgNGD0LPQvtC80YMgKNGA0LXQv9C70LjQutCwINC00LjQsNC70L7Qs9CwKS4NCtCT0YDQsNGEINGB0YLRgNC+0LjRgtGB0Y8g0L/QviDQstGB0LXQvCDRgtC+0LzQsNC8LCDQv9GA0LXQtNGB0YLQsNCy0LvQtdC90L3Ri9C8INCyIFhNTC3RhNCw0LnQu9C1Lg0KDQrQlNC+0L/QvtC70L3QuNGC0LXQu9GM0L3QviDQstCy0L7QtNC40YLRgdGPINGE0LjQu9GM0YLRgNCw0YbQuNGPOg0K0LIg0LDQvdCw0LvQuNC3INCy0LrQu9GO0YfQsNGO0YLRgdGPINGC0L7Qu9GM0LrQviDQv9C10YDRgdC+0L3QsNC20LgsINGDINC60L7RgtC+0YDRi9GFINC90LUg0LzQtdC90YzRiNC1INC30LDQtNCw0L3QvdC+0LPQviDRh9C40YHQu9CwINGA0LXQv9C70LjQuiAo0LrQvtC90LrRgNC10YLQvdC+INCyINC/0YDQuNC80LXRgNC1IDEwKS4NCg0KIyMg0JjQvNC/0L7RgNGCINC4INC/0LDRgNGB0LjQvdCzIFhNTA0KDQpgYGB7cn0NCmZpbGVuYW1lIDwtICJXYXJfYW5kX1BlYWNlLnhtbCINCg0KZG9jIDwtIHJlYWRfeG1sKGZpbGVuYW1lKQ0KbnMgPC0geG1sX25zX3JlbmFtZSh4bWxfbnMoZG9jKSwgZDEgPSAidGVpIikNCnJvb3Rub2RlIDwtIHhtbF9yb290KGRvYykNCmBgYA0KDQojIyDQmNC30LLQu9C10YfQtdC90LjQtSDQstGB0LXRhSDQs9C70LDQsiDQuNC3INCy0YHQtdGFINGC0L7QvNC+0LINCg0KYGBge3J9DQpjaGFwdGVycyA8LSB4bWxfZmluZF9hbGwoDQogIHJvb3Rub2RlLA0KICAiLy90ZWk6dGV4dC8vdGVpOmRpdltAdHlwZT0nY2hhcHRlciddIiwNCiAgbnMNCikNCg0KbGVuZ3RoKGNoYXB0ZXJzKQ0KYGBgDQoNCtCX0LTQtdGB0Ywg0LLRi9Cx0LjRgNCw0Y7RgtGB0Y8g0LLRgdC1INCz0LvQsNCy0Ysg0LHQtdC3INC+0LPRgNCw0L3QuNGH0LXQvdC40Y8g0L/QviDQutC+0L3QutGA0LXRgtC90L7QvNGDINGC0L7QvNGDLg0K0K3RgtC+INC30L3QsNGH0LjRgiwg0YfRgtC+INC00LDQu9C10LUg0LIg0LDQvdCw0LvQuNC3INC/0L7Qv9Cw0LTQsNGO0YIg0LLRgdC1INGC0L7QvNCwLCDQutC+0YLQvtGA0YvQtSDQtdGB0YLRjCDQsiDRhNCw0LnQu9C1Lg0KDQojIyDQodCx0L7RgCDQtNCw0L3QvdGL0YUg0L4g0YDQtdGH0LXQstGL0YUg0LDQutGC0LDRhQ0KDQpgYGB7cn0NCmRpYWxvZ3VlcyA8LSB0aWJibGUoDQogIHZvbHVtZSA9IGNoYXJhY3RlcigpLA0KICBjaGFwdGVyID0gY2hhcmFjdGVyKCksDQogIHNwZWVjaF9pZCA9IGNoYXJhY3RlcigpLA0KICBzcGVha2VyID0gY2hhcmFjdGVyKCksDQogIGFkZHJlc3NlZSA9IGNoYXJhY3RlcigpDQopDQoNCmZvciAoaSBpbiBzZXFfYWxvbmcoY2hhcHRlcnMpKSB7DQogIGNoYXB0ZXJfbm9kZSA8LSBjaGFwdGVyc1tbaV1dDQoNCiAgdm9sdW1lX25vZGUgPC0geG1sX2ZpbmRfZmlyc3QoDQogICAgY2hhcHRlcl9ub2RlLA0KICAgICIuL2FuY2VzdG9yOjp0ZWk6ZGl2W0B0eXBlPSd2b2x1bWUnXVsxXSIsDQogICAgbnMNCiAgKQ0KDQogIHZvbHVtZV9pZCA8LSB4bWxfYXR0cih2b2x1bWVfbm9kZSwgIm4iKQ0KICBjaGFwdGVyX2lkIDwtIHBhc3RlMCgiY2hhcHRlcl8iLCBpKQ0KDQogIHNhaWRfbm9kZXMgPC0geG1sX2ZpbmRfYWxsKA0KICAgIGNoYXB0ZXJfbm9kZSwNCiAgICAiLi8vdGVpOnNhaWRbQHdobyBhbmQgQGNvcnJlc3BdIiwNCiAgICBucw0KICApDQoNCiAgc3BlZWNoX2lkIDwtIHhtbF9hdHRyKHNhaWRfbm9kZXMsICJzcGVlY2hfaWQiKQ0KICBzcGVha2VyIDwtIHhtbF9hdHRyKHNhaWRfbm9kZXMsICJ3aG8iKQ0KICBhZGRyZXNzZWUgPC0geG1sX2F0dHIoc2FpZF9ub2RlcywgImNvcnJlc3AiKQ0KDQogIGNoYXB0ZXJfdGJsIDwtIHRpYmJsZSgNCiAgICB2b2x1bWUgPSB2b2x1bWVfaWQsDQogICAgY2hhcHRlciA9IGNoYXB0ZXJfaWQsDQogICAgc3BlZWNoX2lkID0gc3BlZWNoX2lkLA0KICAgIHNwZWFrZXIgPSBzcGVha2VyLA0KICAgIGFkZHJlc3NlZSA9IGFkZHJlc3NlZQ0KICApIHw+DQogICAgZmlsdGVyKCFpcy5uYShzcGVha2VyKSkgfD4NCiAgICBmaWx0ZXIoIWlzLm5hKGFkZHJlc3NlZSkpIHw+DQogICAgZmlsdGVyKHNwZWFrZXIgIT0gIiIpIHw+DQogICAgZmlsdGVyKGFkZHJlc3NlZSAhPSAiIikgfD4NCiAgICBmaWx0ZXIoc3BlYWtlciAhPSBhZGRyZXNzZWUpDQoNCiAgZGlhbG9ndWVzIDwtIGJpbmRfcm93cyhkaWFsb2d1ZXMsIGNoYXB0ZXJfdGJsKQ0KfQ0KDQpkaWFsb2d1ZXMgfD4NCiAgaGVhZCgxMCkNCmBgYA0KDQrQndCwINGN0YLQvtC8INGN0YLQsNC/0LUg0YHQvtCx0LjRgNCw0Y7RgtGB0Y8g0LLRgdC1INGA0LXRh9C10LLRi9C1INCw0LrRgtGLINC/0L4g0LLRgdC10Lwg0LPQu9Cw0LLQsNC8Lg0K0JrQsNC20LTQsNGPINGB0YLRgNC+0LrQsCDRgtCw0LHQu9C40YbRiyDRgdC+0L7RgtCy0LXRgtGB0YLQstGD0LXRgiDRgdC70YPRh9Cw0Y4sINC60L7Qs9C00LAg0L7QtNC40L0g0L/QtdGA0YHQvtC90LDQtiDQvtCx0YDQsNGJ0LDQtdGC0YHRjyDQuiDQtNGA0YPQs9C+0LzRgy4NCg0KIyMg0J/QvtC00YHRh9GR0YIg0YfQuNGB0LvQsCDRgNC10L/Qu9C40Log0L3QsCDQv9C10YDRgdC+0L3QsNC20LANCg0KYGBge3J9DQpjaGFyX2NvdW50cyA8LSBkaWFsb2d1ZXMgfD4NCiAgcGl2b3RfbG9uZ2VyKA0KICAgIGNvbHMgPSBjKHNwZWFrZXIsIGFkZHJlc3NlZSksDQogICAgdmFsdWVzX3RvID0gImNoYXJhY3RlciINCiAgKSB8Pg0KICBjb3VudChjaGFyYWN0ZXIsIG5hbWUgPSAibl9yZXBsaWNhcyIsIHNvcnQgPSBUUlVFKQ0KDQpjaGFyX2NvdW50cyB8Pg0KICBoZWFkKDE1KQ0KYGBgDQoNCtCh0YfQuNGC0LDQtdGC0YHRjyDRgNC10YfQtdCy0LDRjyDQsNC60YLQuNCy0L3QvtGB0YLRjCDQv9C10YDRgdC+0L3QsNC20LXQuS4NCtCf0LXRgNGB0L7QvdCw0LYg0YPRh9C40YLRi9Cy0LDQtdGC0YHRjyDQuCDQutCw0Log0LPQvtCy0L7RgNGP0YnQuNC5LCDQuCDQutCw0Log0LDQtNGA0LXRgdCw0YIsDQrQv9C+0YLQvtC80YMg0YfRgtC+INC+0LHQtSDRgNC+0LvQuCDQstCw0LbQvdGLINC00LvRjyDRg9GH0LDRgdGC0LjRjyDQsiDQutC+0LzQvNGD0L3QuNC60LDRhtC40L7QvdC90L7QuSDRgdC10YLQuC4NCg0KIyMg0KTQuNC70YzRgtGA0LDRhtC40Y8g0L/QtdGA0YHQvtC90LDQttC10Lkg0L/QviDRh9C40YHQu9GDINGA0LXQv9C70LjQug0KDQpgYGB7cn0NCnRocmVzaG9sZCA8LSAxMA0KDQp2YWxpZF9jaGFycyA8LSBjaGFyX2NvdW50cyB8Pg0KICBmaWx0ZXIobl9yZXBsaWNhcyA+PSB0aHJlc2hvbGQpDQoNCnZhbGlkX2NoYXJzIHw+DQogIGhlYWQoMTUpDQpgYGANCg0K0J/QvtGA0L7QsyDRhNC40LvRjNGC0YDQsNGG0LjQuCDQvNC+0LbQvdC+INC80LXQvdGP0YLRjC4NCtCd0LDQv9GA0LjQvNC10YAsINC80L7QttC90L4g0YHRgNCw0LLQvdC40YLRjCDQs9GA0LDRhNGLINC/0YDQuCBgdGhyZXNob2xkIDwtIDVgLCBgMTBgINC40LvQuCBgMjBgLg0KDQojIyDQpNC40LvRjNGC0YDQsNGG0LjRjyDQuNGB0YXQvtC00L3Ri9GFINGA0LXRh9C10LLRi9GFINCw0LrRgtC+0LINCg0KYGBge3J9DQpkaWFsb2d1ZXNfZmlsdGVyZWQgPC0gZGlhbG9ndWVzIHw+DQogIGZpbHRlcihzcGVha2VyICVpbiUgdmFsaWRfY2hhcnMkY2hhcmFjdGVyKSB8Pg0KICBmaWx0ZXIoYWRkcmVzc2VlICVpbiUgdmFsaWRfY2hhcnMkY2hhcmFjdGVyKQ0KDQpkaWFsb2d1ZXNfZmlsdGVyZWQgfD4NCiAgaGVhZCgxMCkNCmBgYA0KDQrQl9C00LXRgdGMINC+0YHRgtCw0Y7RgtGB0Y8g0YLQvtC70YzQutC+INGC0LUg0YDQtdGH0LXQstGL0LUg0LDQutGC0YssDQrQsiDQutC+0YLQvtGA0YvRhSDQvtCx0LAg0YPRh9Cw0YHRgtC90LjQutCwINC/0YDQvtGF0L7QtNGP0YIg0L/QvtGA0L7QsyDQv9C+INGH0LjRgdC70YMg0YDQtdC/0LvQuNC6Lg0KDQrQktCw0LbQvdC+OiDQsiDRjdGC0L7QuSDQstC10YDRgdC40Lgg0YDQtdGI0LXQvdC40Y8g0LTRg9Cx0LvQuNC60LDRgtGLINC90LUg0YPQtNCw0LvRj9GO0YLRgdGPLg0K0JrQsNC20LTQsNGPINGA0LXQv9C70LjQutCwINGD0YfQuNGC0YvQstCw0LXRgtGB0Y8g0LrQsNC6INC+0YLQtNC10LvRjNC90L7QtSDQvdCw0LHQu9GO0LTQtdC90LjQtS4NCg0KIyMg0KTQvtGA0LzQuNGA0L7QstCw0L3QuNC1INGA0ZHQsdC10YAg0LPRgNCw0YTQsA0KDQpgYGB7cn0NCmVkZ2VzIDwtIGRpYWxvZ3Vlc19maWx0ZXJlZCB8Pg0KICBtdXRhdGUoDQogICAgZnJvbSA9IGlmX2Vsc2Uoc3BlYWtlciA8IGFkZHJlc3NlZSwgc3BlYWtlciwgYWRkcmVzc2VlKSwNCiAgICB0byA9IGlmX2Vsc2Uoc3BlYWtlciA8IGFkZHJlc3NlZSwgYWRkcmVzc2VlLCBzcGVha2VyKQ0KICApIHw+DQogIGNvdW50KGZyb20sIHRvLCBuYW1lID0gIndlaWdodCIsIHNvcnQgPSBUUlVFKQ0KDQplZGdlcyB8Pg0KICBoZWFkKDE1KQ0KYGBgDQoNCtCd0LAg0Y3RgtC+0Lwg0YjQsNCz0LUg0YHQvtC30LTQsNGO0YLRgdGPINGA0ZHQsdGA0LAg0LPRgNCw0YTQsC4NCtCT0YDQsNGEINGB0YLRgNC+0LjRgtGB0Y8g0LrQsNC6INC90LXQvtGA0LjQtdC90YLQuNGA0L7QstCw0L3QvdGL0Lk6DQrQtdGB0LvQuCDQv9C10YDRgdC+0L3QsNC20Lgg0LPQvtCy0L7RgNGP0YIg0LTRgNGD0LMg0YEg0LTRgNGD0LPQvtC8INCyINC+0LHQtSDRgdGC0L7RgNC+0L3RiywNCtGN0YLQviDRgdGH0LjRgtCw0LXRgtGB0Y8g0L7QtNC90L7QuSDRgdCy0Y/Qt9GM0Y4g0LzQtdC20LTRgyDQvdC40LzQuC4NCg0K0JLQtdGBINGA0LXQsdGA0LAgYHdlaWdodGAg0L/QvtC60LDQt9GL0LLQsNC10YIsDQrRgdC60L7Qu9GM0LrQviDRgNCw0Lcg0LTQsNC90L3QsNGPINC/0LDRgNCwINC/0LXRgNGB0L7QvdCw0LbQtdC5INCy0YHRgtGD0L/QsNC70LAg0LIg0L/RgNGP0LzQvtC1INGA0LXRh9C10LLQvtC1INCy0LfQsNC40LzQvtC00LXQudGB0YLQstC40LUuDQoNCiMjINCk0L7RgNC80LjRgNC+0LLQsNC90LjQtSDQstC10YDRiNC40L0g0LPRgNCw0YTQsA0KDQpgYGB7cn0NCnZlcnRpY2VzIDwtIHRpYmJsZSgNCiAgbmFtZSA9IHNvcnQodW5pcXVlKGMoZWRnZXMkZnJvbSwgZWRnZXMkdG8pKSkNCikNCg0KdmVydGljZXMgfD4NCiAgaGVhZCgxNSkNCmBgYA0KDQrQl9C00LXRgdGMINC/0LXRgNC10YfQuNGB0LvRj9GO0YLRgdGPINCy0YHQtSDQv9C10YDRgdC+0L3QsNC20LgsDQrQutC+0YLQvtGA0YvQtSDQstC+0YjQu9C4INCyINCz0YDQsNGEINC/0L7RgdC70LUg0YTQuNC70YzRgtGA0LDRhtC40LguDQoNCiMjINCh0L7Qt9C00LDQvdC40LUg0L7QsdGK0LXQutGC0LAg0LPRgNCw0YTQsA0KDQpgYGB7cn0NCmcgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKA0KICBlZGdlcywNCiAgZGlyZWN0ZWQgPSBGQUxTRSwNCiAgdmVydGljZXMgPSB2ZXJ0aWNlcw0KKQ0KDQpnDQpgYGANCg0K0J/QvtC70YPRh9C10L0g0L7QsdGK0LXQutGCIGBpZ3JhcGhgLg0K0JPRgNCw0YQg0Y/QstC70Y/QtdGC0YHRjyDQvdC10L7RgNC40LXQvdGC0LjRgNC+0LLQsNC90L3Ri9C8INC4INCy0LfQstC10YjQtdC90L3Ri9C8OiDQstC10YDRiNC40L3RiyDRgdC+0L7RgtCy0LXRgtGB0YLQstGD0Y7RgiDQv9C10YDRgdC+0L3QsNC20LDQvCwg0LAg0YDQtdCx0YDQsCDQvtGC0YDQsNC20LDRjtGCINGA0LXRh9C10LLRi9C1INCy0LfQsNC40LzQvtC00LXQudGB0YLQstC40Y8g0LzQtdC20LTRgyDQvdC40LzQuC4g0JLQtdGBINGA0LXQsdGA0LAg0L/QvtC60LDQt9GL0LLQsNC10YIsINGB0LrQvtC70YzQutC+INGA0LDQtyDQvtC00LjQvSDQv9C10YDRgdC+0L3QsNC2INC+0LHRgNCw0YnQsNC70YHRjyDQuiDQtNGA0YPQs9C+0LzRgy4g0JTQu9GPINCz0YDQsNGE0LAg0LHRi9C70Lgg0YDQsNGB0YHRh9C40YLQsNC90Ysg0LHQsNC30L7QstGL0LUg0YXQsNGA0LDQutGC0LXRgNC40YHRgtC40LrQuDog0YfQuNGB0LvQviDQstC10YDRiNC40L0sINGH0LjRgdC70L4g0YDQtdCx0LXRgCwg0YfQuNGB0LvQviDQutC+0LzQv9C+0L3QtdC90YIg0YHQstGP0LfQvdC+0YHRgtC4INC4INC/0LvQvtGC0L3QvtGB0YLRjC4g0K3RgtC4INC/0LDRgNCw0LzQtdGC0YDRiyDQv9C+0LfQstC+0LvRj9GO0YIg0L7Qv9C40YHQsNGC0Ywg0L7QsdGJ0YPRjiDRgdGC0YDRg9C60YLRg9GA0YMg0YHQtdGC0Lgg0LTQviDQsdC+0LvQtdC1INC00LXRgtCw0LvRjNC90L7Qs9C+INCw0L3QsNC70LjQt9CwLg0KDQojIyDQmtGA0LDRgtC60L7QtSDQvtC/0LjRgdCw0L3QuNC1INCz0YDQsNGE0LANCg0KYGBge3J9DQp2Y291bnQoZykNCmVjb3VudChnKQ0KY29tcG9uZW50cyhnKQ0KZWRnZV9kZW5zaXR5KGcpDQpgYGANCg0K0JfQtNC10YHRjCDQstGL0LLQvtC00Y/RgtGB0Y8g0LHQsNC30L7QstGL0LUg0YXQsNGA0LDQutGC0LXRgNC40YHRgtC40LrQuCDQs9GA0LDRhNCwOg0K0YfQuNGB0LvQviDQstC10YDRiNC40L0sINGH0LjRgdC70L4g0YDRkdCx0LXRgCwg0YfQuNGB0LvQviDQutC+0LzQv9C+0L3QtdC90YIg0YHQstGP0LfQvdC+0YHRgtC4INC4INC/0LvQvtGC0L3QvtGB0YLRjC4NCg0KIyMg0JDRgtGA0LjQsdGD0YLRiyDRg9C30LvQvtCyOiDQv9C+0LrQsNC30LDRgtC10LvQuCDQstCw0LbQvdC+0YHRgtC4DQoNCmBgYHtyfQ0KVihnKSRkZWdyZWUgPC0gZGVncmVlKGcpDQpWKGcpJHdlaWdodGVkX2RlZ3JlZSA8LSBzdHJlbmd0aChnKQ0KVihnKSRjbG9zZW5lc3MgPC0gY2xvc2VuZXNzKGcpDQpWKGcpJGJldHdlZW5uZXNzIDwtIGJldHdlZW5uZXNzKGcpDQpWKGcpJGVpZ2VudmVjdG9yIDwtIGVpZ2VuX2NlbnRyYWxpdHkoZykkdmVjdG9yDQpgYGANCg0K0JfQtNC10YHRjCDQutCw0LbQtNC+0LzRgyDRg9C30LvRgyDQtNC+0LHQsNCy0LvRj9GO0YLRgdGPINC+0YHQvdC+0LLQvdGL0LUg0L/QvtC60LDQt9Cw0YLQtdC70Lgg0LLQsNC20L3QvtGB0YLQuC4NCg0KIyMg0KLQvtC/INC/0LXRgNGB0L7QvdCw0LbQtdC5INC/0L4g0LLQt9Cy0LXRiNC10L3QvdC+0Lkg0YHRgtC10L/QtdC90LgNCg0KYGBge3J9DQp0b3Bfbm9kZXMgPC0gdGliYmxlKA0KICBuYW1lID0gVihnKSRuYW1lLA0KICBkZWdyZWUgPSBWKGcpJGRlZ3JlZSwNCiAgd2VpZ2h0ZWRfZGVncmVlID0gVihnKSR3ZWlnaHRlZF9kZWdyZWUsDQogIGNsb3NlbmVzcyA9IFYoZykkY2xvc2VuZXNzLA0KICBiZXR3ZWVubmVzcyA9IFYoZykkYmV0d2Vlbm5lc3MsDQogIGVpZ2VudmVjdG9yID0gVihnKSRlaWdlbnZlY3Rvcg0KKSB8Pg0KICBhcnJhbmdlKC13ZWlnaHRlZF9kZWdyZWUpDQoNCnRvcF9ub2RlcyB8Pg0KICBoZWFkKDE1KQ0KYGBgDQoNCtCt0YLQsCDRgtCw0LHQu9C40YbQsCDQv9C+0LrQsNC30YvQstCw0LXRgiDQvdCw0LjQsdC+0LvQtdC1INCw0LrRgtC40LLQvdGL0YUg0L/QtdGA0YHQvtC90LDQttC10LkNCtCyINC60L7QvNC80YPQvdC40LrQsNGG0LjQvtC90L3QvtC5INGB0LXRgtC4Lg0KDQojIyDQotC+0L8g0YDRkdCx0LXRgCDQv9C+INCy0LXRgdGDDQoNCmBgYHtyfQ0KdG9wX2VkZ2VzIDwtIGVkZ2VzIHw+DQogIGFycmFuZ2UoLXdlaWdodCkNCg0KdG9wX2VkZ2VzIHw+DQogIGhlYWQoMTUpDQpgYGANCg0K0JfQtNC10YHRjCDQstC40LTQvdC+LCDQutCw0LrQuNC1INC/0LDRgNGLINC/0LXRgNGB0L7QvdCw0LbQtdC5DQrRh9Cw0YnQtSDQstGB0LXQs9C+INGA0LDQt9Cz0L7QstCw0YDQuNCy0LDRjtGCINC00YDRg9CzINGBINC00YDRg9Cz0L7QvC4NCg0KIyMg0J/QvtC00LPRgNCw0YQ6IGstY29yZQ0KDQrQkiDQutCw0YfQtdGB0YLQstC1INC/0L7QtNCz0YDQsNGE0LAg0LLRi9Cx0YDQsNC9IGstY29yZSwg0YLQsNC6INC60LDQuiDRjdGC0L7RgiDQvNC10YLQvtC0INCy0YvQtNC10LvRj9C10YIg0L/Qu9C+0YLQvdC+0LUg0YHRgtGA0YPQutGC0YPRgNC90L7QtSDRj9C00YDQviDRgdC10YLQuCwg0LAg0L3QtSDQv9GA0L7RgdGC0L4g0YPQtNCw0LvRj9C10YIg0YHQu9Cw0LHQvtGB0LLRj9C30LDQvdC90YvQtSDQstC10YDRiNC40L3Riy4g0J/QvtGA0L7QsyBjb3JlID49IDMg0L/QvtC30LLQvtC70Y/QtdGCINGD0LHRgNCw0YLRjCDQv9C10YDQuNGE0LXRgNC40LnQvdGL0YUg0L/QtdGA0YHQvtC90LDQttC10Lkg0Lgg0YHQvtGF0YDQsNC90LjRgtGMINGG0LXQvdGC0YDQsNC70YzQvdGD0Y4g0YfQsNGB0YLRjCDQutC+0LzQvNGD0L3QuNC60LDRhtC40L7QvdC90L7QuSDRgdGC0YDRg9C60YLRg9GA0YssINC60L7RgtC+0YDQsNGPINC+0YHRgtCw0LXRgtGB0Y8g0LTQvtGB0YLQsNGC0L7Rh9C90L4g0LHQvtC70YzRiNC+0Lkg0LTQu9GPINCw0L3QsNC70LjQt9CwLg0KDQpgYGB7cn0NClYoZykkY29yZSA8LSBjb3JlbmVzcyhnKQ0KDQp0YWJsZShWKGcpJGNvcmUpDQpgYGANCg0KYGBge3J9DQpnX2NvcmUgPC0gaW5kdWNlZF9zdWJncmFwaChnLCB2aWRzID0gVihnKVtjb3JlID49IDNdKQ0KDQpnX2NvcmUNCnZjb3VudChnX2NvcmUpDQplY291bnQoZ19jb3JlKQ0KYGBgDQoNCtCX0LTQtdGB0Ywg0YHQvtC30LTQsNGR0YLRgdGPINC/0L7QtNCz0YDQsNGEINGBINGD0YHQu9C+0LLQuNC10LwgYGNvcmUgPj0gM2AuDQrQldGB0LvQuCDQvdGD0LbQvdC+LCDRjdGC0L4g0LfQvdCw0YfQtdC90LjQtSDQvNC+0LbQvdC+INC40LfQvNC10L3QuNGC0YwuDQoNCiMjINCQ0L3QsNC70LjQtyDRgdC+0L7QsdGJ0LXRgdGC0LINCg0KYGBge3J9DQpjdyA8LSBjbHVzdGVyX3dhbGt0cmFwKGcsIHN0ZXBzID0gNDUpDQoNCm1lbWJlcnNoaXAoY3cpIHw+DQogIGhlYWQoKQ0KDQptb2R1bGFyaXR5KGN3KQ0KYGBgDQoNCtCU0LvRjyDQsNC90LDQu9C40LfQsCDRgdC+0L7QsdGJ0LXRgdGC0LIg0LHRi9C7INC40YHQv9C+0LvRjNC30L7QstCw0L0g0LDQu9Cz0L7RgNC40YLQvCBXYWxrdHJhcC4g0J7QvSDQv9C+0LfQstC+0LvRj9C10YIg0LLRi9C00LXQu9C40YLRjCDQs9GA0YPQv9C/0Ysg0L/QtdGA0YHQvtC90LDQttC10LksINCy0L3Rg9GC0YDQuCDQutC+0YLQvtGA0YvRhSDRgdCy0Y/Qt9C4INC/0LvQvtGC0L3QtdC1LCDRh9C10Lwg0LzQtdC20LTRgyDQs9GA0YPQv9C/0LDQvNC4LiDQl9C90LDRh9C10L3QuNC1INC80L7QtNGD0LvRj9GA0L3QvtGB0YLQuCDQv9C+0LrQsNC30YvQstCw0LXRgiwg0L3QsNGB0LrQvtC70YzQutC+INC+0YLRh9C10YLQu9C40LLQviDRgdC10YLRjCDQtNC10LvQuNGC0YHRjyDQvdCwINGC0LDQutC40LUg0YHQvtC+0LHRidC10YHRgtCy0LA6INCyINC00LDQvdC90L7QvCDRgdC70YPRh9Cw0LUg0LzQvtC00YPQu9GM0L3QsNGPINGB0YLRgNGD0LrRgtGD0YDQsCDQstGL0YDQsNC20LXQvdCwLCDQvdC+INCz0YDRg9C/0L/RiyDQvdC1INGP0LLQu9GP0Y7RgtGB0Y8g0L/QvtC70L3QvtGB0YLRjNGOINC40LfQvtC70LjRgNC+0LLQsNC90L3Ri9C80LgsINGH0YLQviDRhdC+0YDQvtGI0L4g0YHQvtC+0YLQstC10YLRgdGC0LLRg9C10YIg0YPRgdGC0YDQvtC50YHRgtCy0YMg0LHQvtC70YzRiNC+0LPQviDRgNC+0LzQsNC90LAg0YEg0L/QtdGA0LXRgdC10LrQsNGO0YnQuNC80LjRgdGPINGB0Y7QttC10YLQvdGL0LzQuCDQu9C40L3QuNGP0LzQuC4NCg0KYGBge3J9DQpWKGcpJGNvbW11bml0eSA8LSBtZW1iZXJzaGlwKGN3KQ0KYGBgDQoNCiMjINCi0L7Rh9C60Lgg0YHQvtGH0LvQtdC90LXQvdC40Y8NCg0KYGBge3J9DQphcnRpY3VsYXRpb25fcG9pbnRzKGcpDQpgYGANCg0K0KLQvtGH0LrQuCDRgdC+0YfQu9C10L3QtdC90LjRjyDigJQg0Y3RgtC+INGD0LfQu9GLLA0K0YPQtNCw0LvQtdC90LjQtSDQutC+0YLQvtGA0YvRhSDRg9Cy0LXQu9C40YfQuNCy0LDQtdGCINGH0LjRgdC70L4g0LrQvtC80L/QvtC90LXQvdGCINGB0LLRj9C30L3QvtGB0YLQuC4NCg0KIyMg0JrQu9C40LrQuA0KDQpgYGB7cn0NCmxhcmdlc3RfY2xpcXVlcyhnKQ0KYGBgDQoNCtCa0LvQuNC60Lgg4oCUINGN0YLQviDQv9C+0LvQvdC+0YHRgtGM0Y4g0YHQstGP0LfQvdGL0LUg0L/QvtC00LzQvdC+0LbQtdGB0YLQstCwINGD0LfQu9C+0LIuDQoNCtCh0YDQtdC00Lgg0YLQvtGH0LXQuiDRgdC+0YfQu9C10L3QtdC90LjRjyDQt9Cw0LrQvtC90L7QvNC10YDQvdC+INCy0YvQtNC10LvRj9GO0YLRgdGPIFBpZXJyZV9CZXp1a2hvdiwgTmlrb2xhaV9Sb3N0b3Yg0LggQW5kcmV5Qm9sa29uc2t5LCDRh9GC0L4g0L/QvtC00YLQstC10YDQttC00LDQtdGCINC40YUg0YDQvtC70Ywg0L/QvtGB0YDQtdC00L3QuNC60L7QsiDQvNC10LbQtNGDINGA0LDQt9C90YvQvNC4INGH0LDRgdGC0Y/QvNC4INGB0LXRgtC4LiDQotCw0LrQuNC1INGD0LfQu9GLINC+0YHQvtCx0LXQvdC90L4g0LLQsNC20L3RiyDQtNC70Y8g0YHQstGP0LfQvdC+0YHRgtC4INCz0YDQsNGE0LA6INC40YUg0YPQtNCw0LvQtdC90LjQtSDRgdC40LvRjNC90LXQtSDQstGB0LXQs9C+INC80LXQvdGP0LXRgiDRgdGC0YDRg9C60YLRg9GA0YMg0YHQtdGC0LguINCa0LvQuNC60LgsINC90LDQudC00LXQvdC90YvQtSDQsiDQs9GA0LDRhNC1LCDQv9C+0LrQsNC30YvQstCw0Y7RgiDQvdCw0LjQsdC+0LvQtdC1INC/0LvQvtGC0L3Ri9C1INCz0YDRg9C/0L/RiyDQv9C10YDRgdC+0L3QsNC20LXQuSwg0LPQtNC1INC60LDQttC00YvQuSDRg9GH0LDRgdGC0L3QuNC6INGB0LLRj9C30LDQvSDRgSDQutCw0LbQtNGL0LwuDQoNCiMjINCS0LjQt9GD0LDQu9C40LfQsNGG0LjRjyDQv9C+0LvQvdC+0LPQviDQs9GA0LDRhNCwDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoNDIpDQoNCmdncmFwaChnLCBsYXlvdXQgPSAic3RyZXNzIikgKw0KICBnZW9tX2VkZ2VfbGluayhhZXMoYWxwaGEgPSB3ZWlnaHQpLCB3aWR0aCA9IDAuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBnZW9tX25vZGVfcG9pbnQoDQogICAgYWVzKHNpemUgPSB3ZWlnaHRlZF9kZWdyZWUsIGNvbG9yID0gYXMuZmFjdG9yKGNvbW11bml0eSkpLA0KICAgIHNob3cubGVnZW5kID0gVFJVRQ0KICApICsNCiAgZ2VvbV9ub2RlX3RleHQoDQogICAgYWVzKA0KICAgICAgZmlsdGVyID0gd2VpZ2h0ZWRfZGVncmVlID4gbWVhbih3ZWlnaHRlZF9kZWdyZWUpLA0KICAgICAgbGFiZWwgPSBuYW1lDQogICAgKSwNCiAgICByZXBlbCA9IFRSVUUsDQogICAgc2l6ZSA9IDMsDQogICAgc2hvdy5sZWdlbmQgPSBGQUxTRQ0KICApICsNCiAgdGhlbWVfdm9pZCgpDQpgYGANCg0K0JLQuNC30YPQsNC70LjQt9Cw0YbQuNGPINC/0L7Qu9C90L7Qs9C+INCz0YDQsNGE0LAg0L/QvtC30LLQvtC70Y/QtdGCINC+0LTQvdC+0LLRgNC10LzQtdC90L3QviDQstC40LTQtdGC0Ywg0YbQtdC90YLRgNCw0LvRjNC90YvRhSDQv9C10YDRgdC+0L3QsNC20LXQuSwg0YHQuNC70YMg0YHQstGP0LfQtdC5INC4INGB0L7QvtCx0YnQtdGB0YLQstCwLiDQoNCw0LfQvNC10YAg0YPQt9C70LAg0L7RgtGA0LDQttCw0LXRgiDQstC30LLQtdGI0LXQvdC90YPRjiDRgdGC0LXQv9C10L3RjCwg0YbQstC10YIg0L/QvtC60LDQt9GL0LLQsNC10YIg0L/RgNC40L3QsNC00LvQtdC20L3QvtGB0YLRjCDQuiDRgdC+0L7QsdGJ0LXRgdGC0LLRgywg0LAg0L/RgNC+0LfRgNCw0YfQvdC+0YHRgtGMINGA0LXQsdGA0LAg0LfQsNCy0LjRgdC40YIg0L7RgiDQstC10YHQsCDRgdCy0Y/Qt9C4Lg0KDQojIyDQktC40LfRg9Cw0LvQuNC30LDRhtC40Y8g0L/QvtC00LPRgNCw0YTQsCBrLWNvcmUNCg0KYGBge3J9DQpzZXQuc2VlZCg0MikNCg0KZ2dyYXBoKGdfY29yZSwgbGF5b3V0ID0gInN0cmVzcyIpICsNCiAgZ2VvbV9lZGdlX2xpbmsoYWVzKGFscGhhID0gd2VpZ2h0KSwgd2lkdGggPSAwLjYsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZ2VvbV9ub2RlX3BvaW50KA0KICAgIGFlcyhzaXplID0gd2VpZ2h0ZWRfZGVncmVlLCBjb2xvciA9IGFzLmZhY3Rvcihjb3JlKSksDQogICAgc2hvdy5sZWdlbmQgPSBUUlVFDQogICkgKw0KICBnZW9tX25vZGVfdGV4dCgNCiAgICBhZXMobGFiZWwgPSBuYW1lKSwNCiAgICByZXBlbCA9IFRSVUUsDQogICAgc2l6ZSA9IDMsDQogICAgc2hvdy5sZWdlbmQgPSBGQUxTRQ0KICApICsNCiAgdGhlbWVfdm9pZCgpDQpgYGANCg0K0J/QvtC00LPRgNCw0YQg0L/QvtC60LDQt9GL0LLQsNC10YIg0L3QsNC40LHQvtC70LXQtSDQv9C70L7RgtC90L7QtSDRj9C00YDQviDRgdC10YLQuCDQv9C10YDRgdC+0L3QsNC20LXQuS4NCg0KIyMg0JTQtdC90LTRgNC+0LPRgNCw0LzQvNCwINGB0L7QvtCx0YnQtdGB0YLQsg0KDQpgYGB7cn0NCnBhcihtYXIgPSByZXAoMCwgNCkpDQpwbG90KGN3LCBnLA0KICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC41LCAgICMg0YDQsNC30LzQtdGAINGC0LXQutGB0YLQsA0KICAgICB2ZXJ0ZXgubGFiZWwuY29sb3IgPSAiYmxhY2siLA0KICAgICB2ZXJ0ZXguc2l6ZSA9IDMpICAgICAgICAgICMg0YDQsNC30LzQtdGAINGC0L7Rh9C10LogKNGH0YLQvtCx0Ysg0L3QtSDQvNC10YjQsNC70LgpDQpgYGANCg0KIyMg0JLRi9Cy0L7QtA0KDQrQkiDRgNCw0LHQvtGC0LUg0LHRi9C7INC/0L7RgdGC0YDQvtC10L0g0LPRgNCw0YQg0L/QtdGA0YHQvtC90LDQttC10Lkg0YDQvtC80LDQvdCwIMKr0JLQvtC50L3QsCDQuCDQvNC40YDCuyDQvdCwINC+0YHQvdC+0LLQtSBYTUwt0YDQsNC30LzQtdGC0LrQuC4g0JTQsNC90L3Ri9C1INC40LfQstC70LXQutCw0LvQuNGB0Ywg0LjQtyDRgtC10LPQvtCyIDxzYWlkPiwg0LPQtNC1INGE0LjQutGB0LjRgNGD0LXRgtGB0Y8sINC60YLQviDQs9C+0LLQvtGA0LjRgiDQuCDQutC+0LzRgywg0L/QvtGN0YLQvtC80YMg0YHQstGP0LfRjCDQvNC10LbQtNGDINC/0LXRgNGB0L7QvdCw0LbQsNC80Lgg0L7Qv9GA0LXQtNC10LvRj9C10YLRgdGPINGH0LXRgNC10Lcg0L/RgNGP0LzRg9GOINGA0LXRh9GMLiDQktC10YEg0YDQtdCx0YDQsCDQv9C+0LrQsNC30YvQstCw0LXRgiDRh9C40YHQu9C+INGC0LDQutC40YUg0L7QsdGA0LDRidC10L3QuNC5LiDQn9GA0Lgg0YHQsdC+0YDQtSDQtNCw0L3QvdGL0YUg0LjRgdC/0L7Qu9GM0LfQvtCy0LDQu9C40YHRjCDRhtC40LrQu9GLLCDRhNC40LvRjNGC0YDQsNGG0LjRjyDQuCDQsNCz0YDQtdCz0LjRgNC+0LLQsNC90LjQtSwg0YfRgtC+INC00LXQu9Cw0LXRgiDQv9GA0L7RhtC10LTRg9GA0YMg0LLQvtGB0L/RgNC+0LjQt9Cy0L7QtNC40LzQvtC5Lg0KDQrQn9C+0LvRg9GH0LXQvdC90YvQuSDQs9GA0LDRhCDRj9Cy0LvRj9C10YLRgdGPINC90LXQvtGA0LjQtdC90YLQuNGA0L7QstCw0L3QvdGL0Lwg0Lgg0LLQt9Cy0LXRiNC10L3QvdGL0LwuINCf0L7RgdC70LUg0YTQuNC70YzRgtGA0LDRhtC40Lgg0L/QviDRh9C40YHQu9GDINGA0LXQv9C70LjQuiDQvtC9INCy0LrQu9GO0YfQsNC10YIg0L7QutC+0LvQviAxMDAg0LLQtdGA0YjQuNC9INC4INCx0L7Qu9C10LUgMzAwINGA0LXQsdC10YAsINC/0YDQuCDRjdGC0L7QvCDQv9C+0YfRgtC4INCy0YHQtSDQv9C10YDRgdC+0L3QsNC20Lgg0LLRhdC+0LTRj9GCINCyINC+0LTQvdGDINCx0L7Qu9GM0YjRg9GOINC60L7QvNC/0L7QvdC10L3RgtGDLiDQrdGC0L4g0YHQvtC+0YLQstC10YLRgdGC0LLRg9C10YIg0YHRgtGA0YPQutGC0YPRgNC1INGA0L7QvNCw0L3QsCDQotC+0LvRgdGC0L7Qs9C+INC60LDQuiDQtdC00LjQvdC+0LPQviDQv9C+0LLQtdGB0YLQstC+0LLQsNGC0LXQu9GM0L3QvtCz0L4g0LzQuNGA0LAg0YEg0LzQvdC+0LbQtdGB0YLQstC+0Lwg0L/QtdGA0LXRgdC10LrQsNGO0YnQuNGF0YHRjyDQu9C40L3QuNC5LiDQndCw0LjQsdC+0LvQtdC1INGG0LXQvdGC0YDQsNC70YzQvdGL0LUg0L/QvtC30LjRhtC40Lgg0LfQsNC90LjQvNCw0Y7RgiDQn9GM0LXRgCDQkdC10LfRg9GF0L7Qsiwg0J3QsNGC0LDRiNCwINCg0L7RgdGC0L7QstCwLCDQndC40LrQvtC70LDQuSDQoNC+0YHRgtC+0LIg0Lgg0JDQvdC00YDQtdC5INCR0L7Qu9C60L7QvdGB0LrQuNC5LiDQrdGC0L4g0L7QttC40LTQsNC10LzQviDRgSDQu9C40YLQtdGA0LDRgtGD0YDQvdC+0Lkg0YLQvtGH0LrQuCDQt9GA0LXQvdC40Y86INC40LzQtdC90L3QviDRjdGC0Lgg0L/QtdGA0YHQvtC90LDQttC4INC90LDRhdC+0LTRj9GC0YHRjyDQsiDRhtC10L3RgtGA0LUg0L7RgdC90L7QstC90YvRhSDRgdGO0LbQtdGC0L3Ri9GFINC70LjQvdC40Lkg0Lgg0LDQutGC0LjQstC90L4g0LLQt9Cw0LjQvNC+0LTQtdC50YHRgtCy0YPRjtGCINGBINGA0LDQt9C90YvQvNC4INCz0YDRg9C/0L/QsNC80Lgg0LPQtdGA0L7QtdCyLiDQndCw0L/RgNC40LzQtdGALCDQn9GM0LXRgCDRgdC+0LXQtNC40L3Rj9C10YIg0YHQstC10YLRgdC60L7QtSDQvtCx0YnQtdGB0YLQstC+LCDQstC+0LXQvdC90YPRjiDQu9C40L3QuNGOINC4INGE0LjQu9C+0YHQvtGE0YHQutC40LUg0Y3Qv9C40LfQvtC00YssINCwINCd0LDRgtCw0YjQsCDRgdCy0Y/Qt9Cw0L3QsCDQutCw0Log0YEg0YHQtdC80YzQtdC5INCg0L7RgdGC0L7QstGL0YUsINGC0LDQuiDQuCDRgSDQu9C40L3QuNC10Lkg0JHQvtC70LrQvtC90YHQutC40YUuDQoNCtCSINC60LDRh9C10YHRgtCy0LUg0L/QvtC00LPRgNCw0YTQsCDQsdGL0Lsg0LLRi9Cx0YDQsNC9INC80LXRgtC+0LQgay1jb3JlLCDQv9C+0LfQstC+0LvRj9GO0YnQuNC5INCy0YvQtNC10LvQuNGC0Ywg0L/Qu9C+0YLQvdC+0LUg0Y/QtNGA0L4g0YHQtdGC0LguINCf0L7QtNCz0YDQsNGEINGBIGNvcmUg4omlIDMg0LLQutC70Y7Rh9Cw0LXRgiDQsdC+0LvRjNGI0LjQvdGB0YLQstC+INC60LvRjtGH0LXQstGL0YUg0L/QtdGA0YHQvtC90LDQttC10Lkg0Lgg0L7RgtGA0LDQttCw0LXRgiDRhtC10L3RgtGA0LDQu9GM0L3Ri9C5INC60YDRg9CzINC+0LHRidC10L3QuNGPLCDQsiDQutC+0YLQvtGA0YvQuSDQstGF0L7QtNGP0YIg0KDQvtGB0YLQvtCy0YssINCR0L7Qu9C60L7QvdGB0LrQuNC1INC4INC40YUg0LHQu9C40LbQsNC50YjQtdC1INC+0LrRgNGD0LbQtdC90LjQtS4g0JLQuNC30YPQsNC70LjQt9Cw0YbQuNGPINC/0L7QutCw0LfRi9Cy0LDQtdGCLCDRh9GC0L4g0LjQvNC10L3QvdC+INGN0YLQuCDQs9GA0YPQv9C/0Ysg0YTQvtGA0LzQuNGA0YPRjtGCINGP0LTRgNC+INGA0L7QvNCw0L3QsCwg0YLQvtCz0LTQsCDQutCw0Log0LLRgtC+0YDQvtGB0YLQtdC/0LXQvdC90YvQtSDQv9C10YDRgdC+0L3QsNC20Lgg0L7QsdGA0LDQt9GD0Y7RgiDQv9C10YDQuNGE0LXRgNC40Y4uDQoNCtCQ0L3QsNC70LjQtyDRgdC+0L7QsdGJ0LXRgdGC0LIg0YEg0L/QvtC80L7RidGM0Y4g0LDQu9Cz0L7RgNC40YLQvNCwIFdhbGt0cmFwINCy0YvRj9Cy0LjQuyDQvdC10YHQutC+0LvRjNC60L4g0LPRgNGD0L/Qvywg0LrQvtGC0L7RgNGL0LUg0LzQvtC20L3QviDQuNC90YLQtdGA0L/RgNC10YLQuNGA0L7QstCw0YLRjCDQutCw0Log0YHRjtC20LXRgtC90YvQtSDQuCDRgdC+0YbQuNCw0LvRjNC90YvQtSDQutC70LDRgdGC0LXRgNGLOiDRgdC10LzQtdC50L3Ri9C5INC60YDRg9CzINCg0L7RgdGC0L7QstGL0YUsINC60YDRg9CzINCR0L7Qu9C60L7QvdGB0LrQuNGFLCDQsCDRgtCw0LrQttC1INC/0LXRgNGB0L7QvdCw0LbQuCwg0YHQstGP0LfQsNC90L3Ri9C1INGBINCy0L7QtdC90L3QvtC5INC4INC/0YDQuNC00LLQvtGA0L3QvtC5INC70LjQvdC40Y/QvNC4LiDQl9C90LDRh9C10L3QuNC1INC80L7QtNGD0LvRj9GA0L3QvtGB0YLQuCDQvtC60L7Qu9C+IDAuMzUg0L/QvtC60LDQt9GL0LLQsNC10YIsINGH0YLQviDRjdGC0Lgg0LPRgNGD0L/Qv9GLINGA0LDQt9C70LjRh9C40LzRiywg0L3QviDQvdC1INC40LfQvtC70LjRgNC+0LLQsNC90YssINGH0YLQviDRhdC+0YDQvtGI0L4g0YHQvtC+0YLQstC10YLRgdGC0LLRg9C10YIg0LrQvtC80L/QvtC30LjRhtC40Lgg0YDQvtC80LDQvdCwLCDQs9C00LUg0LvQuNC90LjQuCDQv9C+0YHRgtC+0Y/QvdC90L4g0L/QtdGA0LXRgdC10LrQsNGO0YLRgdGPLg0KDQrQlNC+0L/QvtC70L3QuNGC0LXQu9GM0L3QviDQsdGL0LvQuCDQvdCw0LnQtNC10L3RiyDRgtC+0YfQutC4INGB0L7Rh9C70LXQvdC10L3QuNGPINC4INC60LvQuNC60LguINCh0YDQtdC00Lgg0YLQvtGH0LXQuiDRgdC+0YfQu9C10L3QtdC90LjRjyDQvtC60LDQt9GL0LLQsNGO0YLRgdGPINCf0YzQtdGAINCR0LXQt9GD0YXQvtCyLCDQndC40LrQvtC70LDQuSDQoNC+0YHRgtC+0LIg0Lgg0JDQvdC00YDQtdC5INCR0L7Qu9C60L7QvdGB0LrQuNC5IOKAlCDQvtC90Lgg0LjQs9GA0LDRjtGCINGA0L7Qu9GMINC/0L7RgdGA0LXQtNC90LjQutC+0LIg0LzQtdC20LTRgyDRgNCw0LfQu9C40YfQvdGL0LzQuCDRh9Cw0YHRgtGP0LzQuCDRgdC10YLQuC4g0JrRgNGD0L/QvdC10LnRiNCw0Y8g0LrQu9C40LrQsCDQvtCx0YrQtdC00LjQvdGP0LXRgiDQv9C10YDRgdC+0L3QsNC20LXQuSDQuNC3INGG0LXQvdGC0YDQsNC70YzQvdGL0YUg0YHQtdC80LXQudC90YvRhSDQu9C40L3QuNC5ICjQoNC+0YHRgtC+0LLRiyDQuCDQkdC+0LvQutC+0L3RgdC60LjQtSksINGH0YLQviDQvtGC0YDQsNC20LDQtdGCINC40YUg0YLQtdGB0L3Rg9GOINCy0LfQsNC40LzQvtGB0LLRj9C30Ywg0LIg0YLQtdC60YHRgtC1LiDQkiDRhtC10LvQvtC8INC/0L7Qu9GD0YfQtdC90L3Ri9C5INCz0YDQsNGEINGF0L7RgNC+0YjQviDQstC+0YHQv9GA0L7QuNC30LLQvtC00LjRgiDQu9C40YLQtdGA0LDRgtGD0YDQvdGD0Y4g0YHRgtGA0YPQutGC0YPRgNGDINGA0L7QvNCw0L3QsDog0L7QvSDQv9C+0LrQsNC30YvQstCw0LXRgiDQv9C70L7RgtC90L7QtSDRj9C00YDQviDQutC70Y7Rh9C10LLRi9GFINCz0LXRgNC+0LXQsiDQuCDQsdC+0LvQtdC1INGA0LDQt9GA0LXQttC10L3QvdGD0Y4g0L/QtdGA0LjRhNC10YDQuNGOINCy0YLQvtGA0L7RgdGC0LXQv9C10L3QvdGL0YUg0L/QtdGA0YHQvtC90LDQttC10LkuDQo=