works_of_interest_l <- tribble(
  ~book, ~work, ~pattern, ~year, ~n_verses_prev, ~publication_order,
  "Väitöskirjan aineksia (1827)", "Väitöskirjan aineksia (1827)", "^kr00031", 1827, 95, 1,
  "Kantele I (1829)", "Kantele I (1829)", "^kr00038", 1829, NA, 2,
  "Kantele II (1829)", "Kantele II (1829)", "^kr00039", 1829, NA, 3,
  "Kantele III (1830)", "Kantele III (1830)", "^kr00040", 1830, NA, 4,
  "Kantele IV (1831)", "Kantele IV (1831)", "^kr00041", 1831, NA, 5,
  "Sikermä-Kalevala (1833)", "Sikermä-Kalevala (1833) - Lemminkäinen", "^kr00032", 1833, 825, 6,
  "Sikermä-Kalevala (1833)", "Sikermä-Kalevala (1833) - Väinämöinen", "^kr00033", 1833, 1867, 6,
  "Sikermä-Kalevala (1833)", "Sikermä-Kalevala (1833) - Naimakansan virsiä Vuokkiniemeltä", "^kr00034", 1833, 499, 6,
  "Runokokous Väinämöisestä (1833)","Runokokous Väinämöisestä (1833)", "^kr00035", 1833, 5052, 7,
  "Lisiä runokokoukseen Väinämöisestä (1834)", "Lisiä runokokoukseen Väinämöisestä (1834)", "^kr00036", 1834, NA, 8,
  "Vanha Kalevala (1835)", "Vanha Kalevala (1835)", "^vkalevala", 1835, 12078, 9,
  "Lisiä Vanhaan Kalevalaan (1836-1837)", "Lisiä Vanhaan Kalevalaan (1836-1837)", "^kr00037", 1836, NA, 10,
  "Kanteletar (1840)", "Kanteletar (1840)", "^kt", 1840, NA, 11,
  "Kalevala (1849)", "Kalevala (1849) - Luominen ja Väinämöisen syntymä", "^kalevala0[1-2]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Aino-runo", "^kalevala0[3-5]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Väinämöisen ja Ilmarisen matkat Pohjolaan", "^kalevala(0[6-9]|10)", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Lemminkäinen I", "^kalevala1[1-5]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Väinämöisen veneenveisto ja Pohjolasta kosinta I", "^kalevala1[6-9]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Häärunot", "^kalevala2[0-5]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Lemminkäinen II", "^kalevala(2[6-9]|30)", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Kullervo", "^kalevala3[1-6]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Kultaneito ja Pohjolasta kosinta II", "^kalevala3[7-8]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Matkalla sammon ryöstöön", "^kalevala(39|4[0-1])", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Taistelu sammosta", "^kalevala4[2-3]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Kanteleen soitto", "^kalevala44", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Kalevalan ja Pohjolan välinen taistelu", "^kalevala4[5-9]", 1849, 22795, 12,
  "Kalevala (1849)", "Kalevala (1849) - Väinämöisen lähtö", "^kalevala50", 1849, 22795, 12,
) %>% mutate(display_order=row_number())

works_of_interest <- works_of_interest_l %>%
  copy_to_a(con, temporary=FALSE, overwrite=TRUE, name="works_of_interest", unique_indexes=list(c("work")))

work_parts_of_interest <- works_of_interest_l %>% 
  mutate(p_id=map(pattern,~poems %>% 
                    filter(str_detect(nro,.x)) %>% 
                    pull(p_id))) %>% 
  unnest(p_id) %>% 
  select(-pattern) %>%
  copy_to_a(con, temporary=FALSE, overwrite=TRUE, name="work_parts_of_interest", indexes=list(c("work")), unique_indexes=list(c("p_id")))

work_verses <- work_parts_of_interest %>% 
  select(work,p_id) %>%
  inner_join(verse_poem %>% 
               select(p_id, pos, v_id)) %>% 
  inner_join(verses %>% 
               filter(type=="V") %>% 
               select(v_id)) %>%
  compute_a(temporary=FALSE, overwrite=TRUE, name="work_verses", indexes=list(c("v_id"),c("work")), unique_indexes=list(c("p_id","pos","v_id")))

poems_of_interest <- poems %>% 
  filter(collection %in% c("skvr","jr")) %>%
  inner_join(p_year %>% filter(year>=1700,year<1849)) %>%
  compute_a(temporary=FALSE, overwrite=TRUE, name="poems_of_interest", unique_indexes=list(c("p_id")))

poem_verses <- poems_of_interest %>%
  select(p_id) %>%
  inner_join(verse_poem %>% 
               select(p_id, pos, v_id)) %>% 
  inner_join(verses %>% 
               filter(type=="V") %>% 
               select(v_id)) %>%
  compute_a(temporary=FALSE, overwrite=TRUE, name="poems_verses", indexes=list(c("v_id")), unique_indexes=list(c("p_id","pos","v_id")))

poem_verse_clusts <- poem_verses %>% 
  inner_join(v_clust %>% inner_join(v_clusterings %>% filter(name=="loose"))) %>% 
  distinct(p_id,clust_id) %>%
  compute_a(temporary=FALSE, overwrite=TRUE, name="poem_verse_clusts", indexes=list(c("clust_id")), unique_indexes=list(c("p_id","clust_id")))

work_poem_sims <- work_verses %>% 
  rename(v1_id=v_id, p1_id=p_id, pos1=pos) %>%
  inner_join(v_sim) %>%
  inner_join(poem_verses %>% 
               rename(v2_id=v_id, p2_id=p_id, pos2=pos)) %>% 
  compute_a(temporary=FALSE,overwrite=TRUE, name="work_poem_sims", indexes=list(c("work"),c("p1_id","pos1"),c("p2_id","pos2")))

work_work_sims <- work_verses %>% 
  rename(v1_id=v_id, p1_id=p_id, pos1=pos, work1=work) %>%
  inner_join(v_sim) %>% 
  inner_join(work_verses %>% rename(v2_id=v_id, p2_id=p_id, pos2=pos, work2=work)) %>% 
  filter(work1!=work2) %>%
  compute_a(temporary=FALSE,overwrite=TRUE, name="work_work_sims", indexes=list(c("sim_cos"),c("work1"),c("work2"),c("p1_id","pos1"),c("p2_id","pos2")))

work_verse_clusts <- work_verses %>% 
  inner_join(v_clust %>% inner_join(v_clusterings %>% filter(name=="loose"))) %>% 
  distinct(work,clust_id) %>%
  compute_a(temporary=FALSE, overwrite=TRUE, name="work_verse_clusts", indexes=list(c("clust_id")), unique_indexes=list(c("work","clust_id")))

work_verse_clust_origins <- work_verse_clusts %>%
  inner_join(works_of_interest) %>%
  group_by(clust_id) %>%
  filter(publication_order==min(publication_order)) %>%
  ungroup() %>%
  select(origin_work=work, clust_id) %>%
  compute_a(temporary=FALSE, overwrite=TRUE, name="work_verse_clust_origins", indexes=list(c("origin_work"), c("clust_id")))

poems_to_cols <- poems_of_interest %>%
  inner_join(p_col) %>%
  inner_join(collectors %>% rename(col_name=name)) %>%
  inner_join(p_pl) %>%
  inner_join(places %>% select(pl_id, par_id)) %>%
  inner_join(places %>% filter(type=="county") %>% rename(pl_name=name), join_by(par_id==pl_id)) %>%
  mutate(pl_name=case_match(pl_name,
                            c("Uusimaa","Varsinais-Suomi","Etelä-Pohjanmaa") ~ "Uusimaa/Varsinais-Suomi/Etelä-Pohjanmaa",
                            c("Keski-Suomi","Pohjois-Savo","Etelä-Savo") ~ "Keski-Suomi/Savo",
                            c("Satakunta","Häme") ~ "Satakunta/Häme",
                            c("Peräpohjola","Pohjois-Pohjanmaa","Kainuu") ~ "Peräpohjola/Pohjois-Pohjanmaa/Kainuu",
                            c("Etelä-Karjala") ~ "Etelä-Karjala",
                            c("Aunus") ~ "Aunus",
                            c("Länsi-Inkeri","Keski-Inkeri","Itä- ja Pohjois-Inkeri") ~ "Inkeri",
                            c("Laatokan Karjala (Raja-Karjala)") ~ "Laatokan Karjala",
                            c("Viena") ~ "Viena",
                            c("Pohjois-Karjala") ~ "Pohjois-Karjala")) %>%
  distinct(p_id, year, col_name, pl_name) %>%
  compute_a(temporary=FALSE, overwrite=TRUE, name="poems_to_cols",indexes=list(c("p_id"), c("year")))
work_parts_of_interest %>% 
  inner_join(poem_stats) %>% 
  group_by(publication_order,work, n_verses_prev) %>% 
  summarise(poems=n(), verses=sum(nverses), all_lines=sum(n_all_lines)) %>% 
  arrange(publication_order,work) %>%
  relocate(n_verses_prev, .before=verses)

Works under analysis

work_parts_of_interest %>% 
  inner_join(poem_stats) %>% 
  group_by(book) %>% 
  summarise(poems=n(), verses=sum(nverses), all_lines=sum(n_all_lines),.groups="drop") %>% 
  inner_join(work_verse_clusts %>% inner_join(works_of_interest) %>% count(book, name="verse_types")) %>%
  left_join(works_of_interest %>% group_by(book) %>% summarise(display_order=min(display_order))) %>%
  arrange(display_order) %>%
  select(book,poems,verses,verse_types) %>%
  gt(rowname_col = "book") %>%
  fmt_integer(c(poems, verses, verse_types), sep_mark = " ") %>%
  cols_label(verses="Verses",poems="Poems",verse_types="Verse types")
Poems Verses Verse types
Väitöskirjan aineksia (1827) 1 98 80
Kantele I (1829) 25 1 490 1 207
Kantele II (1829) 54 1 814 1 499
Kantele III (1830) 16 1 493 1 223
Kantele IV (1831) 27 1 609 1 384
Sikermä-Kalevala (1833) 7 4 754 3 113
Runokokous Väinämöisestä (1833) 17 8 006 4 681
Lisiä runokokoukseen Väinämöisestä (1834) 1 4 040 2 700
Vanha Kalevala (1835) 64 15 249 8 121
Lisiä Vanhaan Kalevalaan (1836-1837) 34 21 399 12 319
Kanteletar (1840) 676 23 133 14 071
Kalevala (1849) 50 22 796 16 788

Work development

work_nodes_l <- works_of_interest_l %>% 
  mutate(id=row_number() - 1)

work_verse_network_l <- work_verse_clusts %>% 
  inner_join(works_of_interest %>% select(work, publication_order)) %>%
  right_join(work_verse_clusts %>% 
    inner_join(works_of_interest %>% select(work, publication_order)), join_by(clust_id, publication_order < publication_order)) %>%
  mutate(work.x=coalesce(work.x,work.y), publication_order.x=coalesce(publication_order.x,publication_order.y)) %>%
  group_by(clust_id, work.y) %>%
  filter(publication_order.x==max(publication_order.x)) %>%
  ungroup() %>%
  inner_join(work_verse_clust_origins) %>%
  count(origin_work, work.x,work.y) %>%
  collect() %>%
  inner_join(work_nodes_l %>% select(work.x=work,id.x=id)) %>%
  inner_join(work_nodes_l %>% select(work.y=work,id.y=id)) %>% 
  mutate(id.x=if_else(id.y==id.x,14+id.x,id.x))

work_nodes_l <- work_nodes_l %>%
  union_all(work_nodes_l %>% mutate(id=id+14))
library(networkD3)
sankeyNetwork(Nodes=work_nodes_l,Links=work_verse_network_l, NodeID='work', Source='id.x', Target='id.y',Value='n', fontSize = 12, width=2048, height=2048, nodeWidth = 30, LinkGroup = 'origin_work', units="verses", colourScale=JS("d3.scaleOrdinal(d3.schemeCategory20c);"))
work_nodes_l <- works_of_interest_l %>% 
  mutate(id=row_number() - 1)

n_works <- work_nodes_l %>% count() %>% pull()

work_verse_network_l <- work_verse_clusts %>% 
  inner_join(works_of_interest %>% select(work, publication_order)) %>%
  right_join(work_verse_clusts %>% 
    inner_join(works_of_interest %>% select(work, publication_order)), join_by(clust_id, publication_order < publication_order)) %>%
  mutate(work.x=coalesce(work.x,work.y), publication_order.x=coalesce(publication_order.x,publication_order.y)) %>%
  group_by(clust_id, work.y) %>%
  filter(publication_order.x==max(publication_order.x)) %>%
  ungroup() %>%
  inner_join(work_verse_clust_origins) %>%
  count(work.x,work.y) %>%
  collect() %>%
  inner_join(work_nodes_l %>% select(work.x=work,id.x=id)) %>%
  inner_join(work_nodes_l %>% select(work.y=work,id.y=id)) %>% 
  mutate(id.x=if_else(id.y==id.x,n_works+id.x,id.x))
Joining with `by = join_by(work)`Joining with `by = join_by(work)`Joining with `by = join_by(clust_id)`Joining with `by = join_by(work.x)`Joining with `by = join_by(work.y)`
work_nodes_l <- work_nodes_l %>%
  union_all(work_nodes_l %>% mutate(id=id+n_works))
library(networkD3)
sankeyNetwork(Nodes=work_nodes_l,Links=work_verse_network_l, NodeID='work', Source='id.x', Target='id.y',Value='n', fontSize = 12, width=2048, height=2048, nodeWidth = 30, LinkGroup = 'work.x', units="verses", colourScale=JS("d3.scaleOrdinal(d3.schemeCategory20c);"))
Links is a tbl_df. Converting to a plain data frame.
Nodes is a tbl_df. Converting to a plain data frame.
work_nodes_l <- works_of_interest_l %>% 
  mutate(id=row_number() - 1)
Error: object 'works_of_interest_l' not found
library(networkD3)
sankeyNetwork(Nodes=work_nodes_l,Links=work_verse_network_l, NodeID='work', Source='id.x', Target='id.y',Value='n', fontSize = 12, width=2048, height=2048, nodeWidth = 30, LinkGroup = 'work.x', units="verses", colourScale=JS("d3.scaleOrdinal(d3.schemeCategory20c);"))
work_verse_clusts %>% 
  inner_join(work_verse_clust_origins) %>%
  inner_join(works_of_interest %>% select(origin_work=work,publication_order)) %>%
  inner_join(works_of_interest %>% select(work,publication_order), join_by(work)) %>%
  filter(publication_order.x<publication_order.y | work == origin_work) %>%
  count(origin_work, work, publication_order.x, publication_order.y) %>%
  group_by(work) %>%
  mutate(prop=n/sum(n)) %>%
  ungroup() %>%
  collect() %>%
  mutate(origin_work=fct_reorder(origin_work, publication_order.x),work=fct_reorder(work, publication_order.y)) %>%
  ggplot(aes(x=origin_work,y=work,fill=prop)) +
  geom_tile() +
  theme_hsci_continuous() +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
Joining with `by = join_by(clust_id)`Joining with `by = join_by(origin_work)`

Origins of verse types in parts of the Kalevala in terms of earlier works

work_verse_clusts %>% 
  inner_join(work_verse_clust_origins) %>%
  inner_join(works_of_interest %>% select(origin_work=work,publication_order)) %>%
  inner_join(works_of_interest %>% select(work,publication_order), join_by(work)) %>%
  filter(publication_order.x<publication_order.y | work == origin_work) %>%
  count(origin_work, work, publication_order.x, publication_order.y) %>%
  group_by(work) %>%
  mutate(prop=n/sum(n)) %>%
  ungroup() %>%
  filter(publication_order.y==12,origin_work!=work) %>%
  collect() %>%
  inner_join(works_of_interest_l %>% mutate(order=row_number()) %>% select(work,order)) %>%
  mutate(origin_work=fct_reorder(origin_work, publication_order.x),work=fct_reorder(work, order,.desc=TRUE)) %>%
  ggplot(aes(x=work,y=prop,fill=origin_work)) +
  geom_col() +
  scale_y_continuous(labels=scales::percent) +
  coord_flip() +
  theme_hsci_discrete() +
  labs(fill="") +
  theme(legend.position="bottom") +
  guides(fill=guide_legend(ncol=1))
Joining with `by = join_by(clust_id)`Joining with `by = join_by(origin_work)`Joining with `by = join_by(work)`

work_verse_clusts %>% 
  inner_join(works_of_interest %>% select(work,publication_order)) %>%
  inner_join(work_verse_clusts %>% 
    inner_join(works_of_interest %>% filter(publication_order==12) %>% select(work,publication_order)), join_by(clust_id, publication_order<publication_order)
  ) %>%
  count(work.x,work.y) %>%
  inner_join(work_verse_clusts %>% count(work.x=work, name="on")) %>%
  mutate(prop=n/on) %>%
  ggplot(aes(x=work.y,y=prop,fill=work.x)) +
  geom_col(position='dodge') +
  scale_y_continuous(labels=scales::percent) +
  coord_flip() +
  theme_hsci_discrete() +
  labs(fill="") +
  theme(legend.position="bottom") +
  guides(fill=guide_legend(ncol=1))

work_verse_clusts %>% 
  inner_join(works_of_interest %>% select(work,book,publication_order)) %>%
  inner_join(work_verse_clusts %>% 
    inner_join(works_of_interest %>% filter(publication_order==12)) %>% select(clust_id,work,book,publication_order), join_by(clust_id, publication_order<publication_order)
  ) %>%
  group_by(work.x,book.y) %>%
  summarise(n=n_distinct(clust_id),.groups="drop") %>%
  inner_join(work_verse_clusts %>% count(work.x=work, name="on")) %>%
  mutate(prop=n/on) %>%
  ggplot(aes(x=work.x,y=prop)) +
  geom_col(position='dodge') +
  scale_y_continuous(labels=scales::percent) +
  coord_flip() +
  theme_hsci_discrete() +
  labs(fill="") +
  theme(legend.position="bottom") +
  guides(fill=guide_legend(ncol=1))

LS0tCnRpdGxlOiAiU291cmNlcyBvZiB0aGUgS2FsZXZhbGEiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRvYzogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlPUZBTFNFLGRwaT0zMDAsZmlnLnJldGluYT0yLGZpZy53aWR0aD04KQpzb3VyY2UoaGVyZTo6aGVyZSgic3JjL2NvbW1vbl9iYXNpcy5SIikpCnRtYXBfbW9kZSgicGxvdCIpCnNhdmVfcGxvdHMgPC0gZnVuY3Rpb24oZGlyLGJhc2VuYW1lLHBsb3Qsd2lkdGg9NixoZWlnaHQ9NSx1bml0cz0iaW4iLGRwaT0zMDApIHsKICBnZ3NhdmUoZ2x1ZSgie2Rpcn0ve2Jhc2VuYW1lfS5wbmciKSxwbG90LHdpZHRoPXdpZHRoLGhlaWdodD1oZWlnaHQsZHBpPWRwaSwgdW5pdHM9dW5pdHMpCiAgZ2dzYXZlKGdsdWUoIntkaXJ9L3tiYXNlbmFtZX0uc3ZnIikscGxvdCx3aWR0aD13aWR0aCxoZWlnaHQ9aGVpZ2h0LGRwaT1kcGksIHVuaXRzPXVuaXRzKQogIGdnc2F2ZShnbHVlKCJ7ZGlyfS97YmFzZW5hbWV9LnBkZiIpLHBsb3Qsd2lkdGg9d2lkdGgsaGVpZ2h0PWhlaWdodCxkcGk9ZHBpLCB1bml0cz11bml0cywgZGV2aWNlID0gY2Fpcm9fcGRmKQogIGtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGdsdWUoIntkaXJ9L3tiYXNlbmFtZX0uc3ZnIiksIGRwaT1kcGkpCn0KYGBgCgoKYGBge3IgbG9hZF9kYXRhLCBldmFsPUZBTFNFfQp3b3Jrc19vZl9pbnRlcmVzdF9sIDwtIHRyaWJibGUoCiAgfmJvb2ssIH53b3JrLCB+cGF0dGVybiwgfnllYXIsIH5uX3ZlcnNlc19wcmV2LCB+cHVibGljYXRpb25fb3JkZXIsCiAgIlbDpGl0w7Zza2lyamFuIGFpbmVrc2lhICgxODI3KSIsICJWw6RpdMO2c2tpcmphbiBhaW5la3NpYSAoMTgyNykiLCAiXmtyMDAwMzEiLCAxODI3LCA5NSwgMSwKICAiS2FudGVsZSBJICgxODI5KSIsICJLYW50ZWxlIEkgKDE4MjkpIiwgIl5rcjAwMDM4IiwgMTgyOSwgTkEsIDIsCiAgIkthbnRlbGUgSUkgKDE4MjkpIiwgIkthbnRlbGUgSUkgKDE4MjkpIiwgIl5rcjAwMDM5IiwgMTgyOSwgTkEsIDMsCiAgIkthbnRlbGUgSUlJICgxODMwKSIsICJLYW50ZWxlIElJSSAoMTgzMCkiLCAiXmtyMDAwNDAiLCAxODMwLCBOQSwgNCwKICAiS2FudGVsZSBJViAoMTgzMSkiLCAiS2FudGVsZSBJViAoMTgzMSkiLCAiXmtyMDAwNDEiLCAxODMxLCBOQSwgNSwKICAiU2lrZXJtw6QtS2FsZXZhbGEgKDE4MzMpIiwgIlNpa2VybcOkLUthbGV2YWxhICgxODMzKSAtIExlbW1pbmvDpGluZW4iLCAiXmtyMDAwMzIiLCAxODMzLCA4MjUsIDYsCiAgIlNpa2VybcOkLUthbGV2YWxhICgxODMzKSIsICJTaWtlcm3DpC1LYWxldmFsYSAoMTgzMykgLSBWw6RpbsOkbcO2aW5lbiIsICJea3IwMDAzMyIsIDE4MzMsIDE4NjcsIDYsCiAgIlNpa2VybcOkLUthbGV2YWxhICgxODMzKSIsICJTaWtlcm3DpC1LYWxldmFsYSAoMTgzMykgLSBOYWltYWthbnNhbiB2aXJzacOkIFZ1b2traW5pZW1lbHTDpCIsICJea3IwMDAzNCIsIDE4MzMsIDQ5OSwgNiwKICAiUnVub2tva291cyBWw6RpbsOkbcO2aXNlc3TDpCAoMTgzMykiLCJSdW5va29rb3VzIFbDpGluw6Rtw7Zpc2VzdMOkICgxODMzKSIsICJea3IwMDAzNSIsIDE4MzMsIDUwNTIsIDcsCiAgIkxpc2nDpCBydW5va29rb3Vrc2VlbiBWw6RpbsOkbcO2aXNlc3TDpCAoMTgzNCkiLCAiTGlzacOkIHJ1bm9rb2tvdWtzZWVuIFbDpGluw6Rtw7Zpc2VzdMOkICgxODM0KSIsICJea3IwMDAzNiIsIDE4MzQsIE5BLCA4LAogICJWYW5oYSBLYWxldmFsYSAoMTgzNSkiLCAiVmFuaGEgS2FsZXZhbGEgKDE4MzUpIiwgIl52a2FsZXZhbGEiLCAxODM1LCAxMjA3OCwgOSwKICAiTGlzacOkIFZhbmhhYW4gS2FsZXZhbGFhbiAoMTgzNi0xODM3KSIsICJMaXNpw6QgVmFuaGFhbiBLYWxldmFsYWFuICgxODM2LTE4MzcpIiwgIl5rcjAwMDM3IiwgMTgzNiwgTkEsIDEwLAogICJLYW50ZWxldGFyICgxODQwKSIsICJLYW50ZWxldGFyICgxODQwKSIsICJea3QiLCAxODQwLCBOQSwgMTEsCiAgIkthbGV2YWxhICgxODQ5KSIsICJLYWxldmFsYSAoMTg0OSkgLSBMdW9taW5lbiBqYSBWw6RpbsOkbcO2aXNlbiBzeW50eW3DpCIsICJea2FsZXZhbGEwWzEtMl0iLCAxODQ5LCAyMjc5NSwgMTIsCiAgIkthbGV2YWxhICgxODQ5KSIsICJLYWxldmFsYSAoMTg0OSkgLSBBaW5vLXJ1bm8iLCAiXmthbGV2YWxhMFszLTVdIiwgMTg0OSwgMjI3OTUsIDEyLAogICJLYWxldmFsYSAoMTg0OSkiLCAiS2FsZXZhbGEgKDE4NDkpIC0gVsOkaW7DpG3DtmlzZW4gamEgSWxtYXJpc2VuIG1hdGthdCBQb2hqb2xhYW4iLCAiXmthbGV2YWxhKDBbNi05XXwxMCkiLCAxODQ5LCAyMjc5NSwgMTIsCiAgIkthbGV2YWxhICgxODQ5KSIsICJLYWxldmFsYSAoMTg0OSkgLSBMZW1taW5rw6RpbmVuIEkiLCAiXmthbGV2YWxhMVsxLTVdIiwgMTg0OSwgMjI3OTUsIDEyLAogICJLYWxldmFsYSAoMTg0OSkiLCAiS2FsZXZhbGEgKDE4NDkpIC0gVsOkaW7DpG3DtmlzZW4gdmVuZWVudmVpc3RvIGphIFBvaGpvbGFzdGEga29zaW50YSBJIiwgIl5rYWxldmFsYTFbNi05XSIsIDE4NDksIDIyNzk1LCAxMiwKICAiS2FsZXZhbGEgKDE4NDkpIiwgIkthbGV2YWxhICgxODQ5KSAtIEjDpMOkcnVub3QiLCAiXmthbGV2YWxhMlswLTVdIiwgMTg0OSwgMjI3OTUsIDEyLAogICJLYWxldmFsYSAoMTg0OSkiLCAiS2FsZXZhbGEgKDE4NDkpIC0gTGVtbWlua8OkaW5lbiBJSSIsICJea2FsZXZhbGEoMls2LTldfDMwKSIsIDE4NDksIDIyNzk1LCAxMiwKICAiS2FsZXZhbGEgKDE4NDkpIiwgIkthbGV2YWxhICgxODQ5KSAtIEt1bGxlcnZvIiwgIl5rYWxldmFsYTNbMS02XSIsIDE4NDksIDIyNzk1LCAxMiwKICAiS2FsZXZhbGEgKDE4NDkpIiwgIkthbGV2YWxhICgxODQ5KSAtIEt1bHRhbmVpdG8gamEgUG9oam9sYXN0YSBrb3NpbnRhIElJIiwgIl5rYWxldmFsYTNbNy04XSIsIDE4NDksIDIyNzk1LCAxMiwKICAiS2FsZXZhbGEgKDE4NDkpIiwgIkthbGV2YWxhICgxODQ5KSAtIE1hdGthbGxhIHNhbW1vbiByecO2c3TDtsO2biIsICJea2FsZXZhbGEoMzl8NFswLTFdKSIsIDE4NDksIDIyNzk1LCAxMiwKICAiS2FsZXZhbGEgKDE4NDkpIiwgIkthbGV2YWxhICgxODQ5KSAtIFRhaXN0ZWx1IHNhbW1vc3RhIiwgIl5rYWxldmFsYTRbMi0zXSIsIDE4NDksIDIyNzk1LCAxMiwKICAiS2FsZXZhbGEgKDE4NDkpIiwgIkthbGV2YWxhICgxODQ5KSAtIEthbnRlbGVlbiBzb2l0dG8iLCAiXmthbGV2YWxhNDQiLCAxODQ5LCAyMjc5NSwgMTIsCiAgIkthbGV2YWxhICgxODQ5KSIsICJLYWxldmFsYSAoMTg0OSkgLSBLYWxldmFsYW4gamEgUG9oam9sYW4gdsOkbGluZW4gdGFpc3RlbHUiLCAiXmthbGV2YWxhNFs1LTldIiwgMTg0OSwgMjI3OTUsIDEyLAogICJLYWxldmFsYSAoMTg0OSkiLCAiS2FsZXZhbGEgKDE4NDkpIC0gVsOkaW7DpG3DtmlzZW4gbMOkaHTDtiIsICJea2FsZXZhbGE1MCIsIDE4NDksIDIyNzk1LCAxMiwKKSAlPiUgbXV0YXRlKGRpc3BsYXlfb3JkZXI9cm93X251bWJlcigpKQoKd29ya3Nfb2ZfaW50ZXJlc3QgPC0gd29ya3Nfb2ZfaW50ZXJlc3RfbCAlPiUKICBjb3B5X3RvX2EoY29uLCB0ZW1wb3Jhcnk9RkFMU0UsIG92ZXJ3cml0ZT1UUlVFLCBuYW1lPSJ3b3Jrc19vZl9pbnRlcmVzdCIsIHVuaXF1ZV9pbmRleGVzPWxpc3QoYygid29yayIpKSkKCndvcmtfcGFydHNfb2ZfaW50ZXJlc3QgPC0gd29ya3Nfb2ZfaW50ZXJlc3RfbCAlPiUgCiAgbXV0YXRlKHBfaWQ9bWFwKHBhdHRlcm4sfnBvZW1zICU+JSAKICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoc3RyX2RldGVjdChucm8sLngpKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgcHVsbChwX2lkKSkpICU+JSAKICB1bm5lc3QocF9pZCkgJT4lIAogIHNlbGVjdCgtcGF0dGVybikgJT4lCiAgY29weV90b19hKGNvbiwgdGVtcG9yYXJ5PUZBTFNFLCBvdmVyd3JpdGU9VFJVRSwgbmFtZT0id29ya19wYXJ0c19vZl9pbnRlcmVzdCIsIGluZGV4ZXM9bGlzdChjKCJ3b3JrIikpLCB1bmlxdWVfaW5kZXhlcz1saXN0KGMoInBfaWQiKSkpCgp3b3JrX3ZlcnNlcyA8LSB3b3JrX3BhcnRzX29mX2ludGVyZXN0ICU+JSAKICBzZWxlY3Qod29yayxwX2lkKSAlPiUKICBpbm5lcl9qb2luKHZlcnNlX3BvZW0gJT4lIAogICAgICAgICAgICAgICBzZWxlY3QocF9pZCwgcG9zLCB2X2lkKSkgJT4lIAogIGlubmVyX2pvaW4odmVyc2VzICU+JSAKICAgICAgICAgICAgICAgZmlsdGVyKHR5cGU9PSJWIikgJT4lIAogICAgICAgICAgICAgICBzZWxlY3Qodl9pZCkpICU+JQogIGNvbXB1dGVfYSh0ZW1wb3Jhcnk9RkFMU0UsIG92ZXJ3cml0ZT1UUlVFLCBuYW1lPSJ3b3JrX3ZlcnNlcyIsIGluZGV4ZXM9bGlzdChjKCJ2X2lkIiksYygid29yayIpKSwgdW5pcXVlX2luZGV4ZXM9bGlzdChjKCJwX2lkIiwicG9zIiwidl9pZCIpKSkKCnBvZW1zX29mX2ludGVyZXN0IDwtIHBvZW1zICU+JSAKICBmaWx0ZXIoY29sbGVjdGlvbiAlaW4lIGMoInNrdnIiLCJqciIpKSAlPiUKICBpbm5lcl9qb2luKHBfeWVhciAlPiUgZmlsdGVyKHllYXI+PTE3MDAseWVhcjwxODQ5KSkgJT4lCiAgY29tcHV0ZV9hKHRlbXBvcmFyeT1GQUxTRSwgb3ZlcndyaXRlPVRSVUUsIG5hbWU9InBvZW1zX29mX2ludGVyZXN0IiwgdW5pcXVlX2luZGV4ZXM9bGlzdChjKCJwX2lkIikpKQoKcG9lbV92ZXJzZXMgPC0gcG9lbXNfb2ZfaW50ZXJlc3QgJT4lCiAgc2VsZWN0KHBfaWQpICU+JQogIGlubmVyX2pvaW4odmVyc2VfcG9lbSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChwX2lkLCBwb3MsIHZfaWQpKSAlPiUgCiAgaW5uZXJfam9pbih2ZXJzZXMgJT4lIAogICAgICAgICAgICAgICBmaWx0ZXIodHlwZT09IlYiKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdCh2X2lkKSkgJT4lCiAgY29tcHV0ZV9hKHRlbXBvcmFyeT1GQUxTRSwgb3ZlcndyaXRlPVRSVUUsIG5hbWU9InBvZW1zX3ZlcnNlcyIsIGluZGV4ZXM9bGlzdChjKCJ2X2lkIikpLCB1bmlxdWVfaW5kZXhlcz1saXN0KGMoInBfaWQiLCJwb3MiLCJ2X2lkIikpKQoKcG9lbV92ZXJzZV9jbHVzdHMgPC0gcG9lbV92ZXJzZXMgJT4lIAogIGlubmVyX2pvaW4odl9jbHVzdCAlPiUgaW5uZXJfam9pbih2X2NsdXN0ZXJpbmdzICU+JSBmaWx0ZXIobmFtZT09Imxvb3NlIikpKSAlPiUgCiAgZGlzdGluY3QocF9pZCxjbHVzdF9pZCkgJT4lCiAgY29tcHV0ZV9hKHRlbXBvcmFyeT1GQUxTRSwgb3ZlcndyaXRlPVRSVUUsIG5hbWU9InBvZW1fdmVyc2VfY2x1c3RzIiwgaW5kZXhlcz1saXN0KGMoImNsdXN0X2lkIikpLCB1bmlxdWVfaW5kZXhlcz1saXN0KGMoInBfaWQiLCJjbHVzdF9pZCIpKSkKCndvcmtfcG9lbV9zaW1zIDwtIHdvcmtfdmVyc2VzICU+JSAKICByZW5hbWUodjFfaWQ9dl9pZCwgcDFfaWQ9cF9pZCwgcG9zMT1wb3MpICU+JQogIGlubmVyX2pvaW4odl9zaW0pICU+JQogIGlubmVyX2pvaW4ocG9lbV92ZXJzZXMgJT4lIAogICAgICAgICAgICAgICByZW5hbWUodjJfaWQ9dl9pZCwgcDJfaWQ9cF9pZCwgcG9zMj1wb3MpKSAlPiUgCiAgY29tcHV0ZV9hKHRlbXBvcmFyeT1GQUxTRSxvdmVyd3JpdGU9VFJVRSwgbmFtZT0id29ya19wb2VtX3NpbXMiLCBpbmRleGVzPWxpc3QoYygid29yayIpLGMoInAxX2lkIiwicG9zMSIpLGMoInAyX2lkIiwicG9zMiIpKSkKCndvcmtfd29ya19zaW1zIDwtIHdvcmtfdmVyc2VzICU+JSAKICByZW5hbWUodjFfaWQ9dl9pZCwgcDFfaWQ9cF9pZCwgcG9zMT1wb3MsIHdvcmsxPXdvcmspICU+JQogIGlubmVyX2pvaW4odl9zaW0pICU+JSAKICBpbm5lcl9qb2luKHdvcmtfdmVyc2VzICU+JSByZW5hbWUodjJfaWQ9dl9pZCwgcDJfaWQ9cF9pZCwgcG9zMj1wb3MsIHdvcmsyPXdvcmspKSAlPiUgCiAgZmlsdGVyKHdvcmsxIT13b3JrMikgJT4lCiAgY29tcHV0ZV9hKHRlbXBvcmFyeT1GQUxTRSxvdmVyd3JpdGU9VFJVRSwgbmFtZT0id29ya193b3JrX3NpbXMiLCBpbmRleGVzPWxpc3QoYygic2ltX2NvcyIpLGMoIndvcmsxIiksYygid29yazIiKSxjKCJwMV9pZCIsInBvczEiKSxjKCJwMl9pZCIsInBvczIiKSkpCgp3b3JrX3ZlcnNlX2NsdXN0cyA8LSB3b3JrX3ZlcnNlcyAlPiUgCiAgaW5uZXJfam9pbih2X2NsdXN0ICU+JSBpbm5lcl9qb2luKHZfY2x1c3RlcmluZ3MgJT4lIGZpbHRlcihuYW1lPT0ibG9vc2UiKSkpICU+JSAKICBkaXN0aW5jdCh3b3JrLGNsdXN0X2lkKSAlPiUKICBjb21wdXRlX2EodGVtcG9yYXJ5PUZBTFNFLCBvdmVyd3JpdGU9VFJVRSwgbmFtZT0id29ya192ZXJzZV9jbHVzdHMiLCBpbmRleGVzPWxpc3QoYygiY2x1c3RfaWQiKSksIHVuaXF1ZV9pbmRleGVzPWxpc3QoYygid29yayIsImNsdXN0X2lkIikpKQoKd29ya192ZXJzZV9jbHVzdF9vcmlnaW5zIDwtIHdvcmtfdmVyc2VfY2x1c3RzICU+JQogIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QpICU+JQogIGdyb3VwX2J5KGNsdXN0X2lkKSAlPiUKICBmaWx0ZXIocHVibGljYXRpb25fb3JkZXI9PW1pbihwdWJsaWNhdGlvbl9vcmRlcikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBzZWxlY3Qob3JpZ2luX3dvcms9d29yaywgY2x1c3RfaWQpICU+JQogIGNvbXB1dGVfYSh0ZW1wb3Jhcnk9RkFMU0UsIG92ZXJ3cml0ZT1UUlVFLCBuYW1lPSJ3b3JrX3ZlcnNlX2NsdXN0X29yaWdpbnMiLCBpbmRleGVzPWxpc3QoYygib3JpZ2luX3dvcmsiKSwgYygiY2x1c3RfaWQiKSkpCgpwb2Vtc190b19jb2xzIDwtIHBvZW1zX29mX2ludGVyZXN0ICU+JQogIGlubmVyX2pvaW4ocF9jb2wpICU+JQogIGlubmVyX2pvaW4oY29sbGVjdG9ycyAlPiUgcmVuYW1lKGNvbF9uYW1lPW5hbWUpKSAlPiUKICBpbm5lcl9qb2luKHBfcGwpICU+JQogIGlubmVyX2pvaW4ocGxhY2VzICU+JSBzZWxlY3QocGxfaWQsIHBhcl9pZCkpICU+JQogIGlubmVyX2pvaW4ocGxhY2VzICU+JSBmaWx0ZXIodHlwZT09ImNvdW50eSIpICU+JSByZW5hbWUocGxfbmFtZT1uYW1lKSwgam9pbl9ieShwYXJfaWQ9PXBsX2lkKSkgJT4lCiAgbXV0YXRlKHBsX25hbWU9Y2FzZV9tYXRjaChwbF9uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiVXVzaW1hYSIsIlZhcnNpbmFpcy1TdW9taSIsIkV0ZWzDpC1Qb2hqYW5tYWEiKSB+ICJVdXNpbWFhL1ZhcnNpbmFpcy1TdW9taS9FdGVsw6QtUG9oamFubWFhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIktlc2tpLVN1b21pIiwiUG9oam9pcy1TYXZvIiwiRXRlbMOkLVNhdm8iKSB+ICJLZXNraS1TdW9taS9TYXZvIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIlNhdGFrdW50YSIsIkjDpG1lIikgfiAiU2F0YWt1bnRhL0jDpG1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIlBlcsOkcG9oam9sYSIsIlBvaGpvaXMtUG9oamFubWFhIiwiS2FpbnV1IikgfiAiUGVyw6Rwb2hqb2xhL1BvaGpvaXMtUG9oamFubWFhL0thaW51dSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJFdGVsw6QtS2FyamFsYSIpIH4gIkV0ZWzDpC1LYXJqYWxhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIkF1bnVzIikgfiAiQXVudXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiTMOkbnNpLUlua2VyaSIsIktlc2tpLUlua2VyaSIsIkl0w6QtIGphIFBvaGpvaXMtSW5rZXJpIikgfiAiSW5rZXJpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIkxhYXRva2FuIEthcmphbGEgKFJhamEtS2FyamFsYSkiKSB+ICJMYWF0b2thbiBLYXJqYWxhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIlZpZW5hIikgfiAiVmllbmEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiUG9oam9pcy1LYXJqYWxhIikgfiAiUG9oam9pcy1LYXJqYWxhIikpICU+JQogIGRpc3RpbmN0KHBfaWQsIHllYXIsIGNvbF9uYW1lLCBwbF9uYW1lKSAlPiUKICBjb21wdXRlX2EodGVtcG9yYXJ5PUZBTFNFLCBvdmVyd3JpdGU9VFJVRSwgbmFtZT0icG9lbXNfdG9fY29scyIsaW5kZXhlcz1saXN0KGMoInBfaWQiKSwgYygieWVhciIpKSkKYGBgCgpgYGB7cn0Kd29ya19wYXJ0c19vZl9pbnRlcmVzdCAlPiUgCiAgaW5uZXJfam9pbihwb2VtX3N0YXRzKSAlPiUgCiAgZ3JvdXBfYnkocHVibGljYXRpb25fb3JkZXIsd29yaywgbl92ZXJzZXNfcHJldikgJT4lIAogIHN1bW1hcmlzZShwb2Vtcz1uKCksIHZlcnNlcz1zdW0obnZlcnNlcyksIGFsbF9saW5lcz1zdW0obl9hbGxfbGluZXMpKSAlPiUgCiAgYXJyYW5nZShwdWJsaWNhdGlvbl9vcmRlcix3b3JrKSAlPiUKICByZWxvY2F0ZShuX3ZlcnNlc19wcmV2LCAuYmVmb3JlPXZlcnNlcykKYGBgCgojIFdvcmtzIHVuZGVyIGFuYWx5c2lzCgpgYGB7cn0Kd29ya19wYXJ0c19vZl9pbnRlcmVzdCAlPiUgCiAgaW5uZXJfam9pbihwb2VtX3N0YXRzKSAlPiUgCiAgZ3JvdXBfYnkoYm9vaykgJT4lIAogIHN1bW1hcmlzZShwb2Vtcz1uKCksIHZlcnNlcz1zdW0obnZlcnNlcyksIGFsbF9saW5lcz1zdW0obl9hbGxfbGluZXMpLC5ncm91cHM9ImRyb3AiKSAlPiUgCiAgaW5uZXJfam9pbih3b3JrX3ZlcnNlX2NsdXN0cyAlPiUgaW5uZXJfam9pbih3b3Jrc19vZl9pbnRlcmVzdCkgJT4lIGNvdW50KGJvb2ssIG5hbWU9InZlcnNlX3R5cGVzIikpICU+JQogIGxlZnRfam9pbih3b3Jrc19vZl9pbnRlcmVzdCAlPiUgZ3JvdXBfYnkoYm9vaykgJT4lIHN1bW1hcmlzZShkaXNwbGF5X29yZGVyPW1pbihkaXNwbGF5X29yZGVyKSkpICU+JQogIGFycmFuZ2UoZGlzcGxheV9vcmRlcikgJT4lCiAgc2VsZWN0KGJvb2sscG9lbXMsdmVyc2VzLHZlcnNlX3R5cGVzKSAlPiUKICBndChyb3duYW1lX2NvbCA9ICJib29rIikgJT4lCiAgZm10X2ludGVnZXIoYyhwb2VtcywgdmVyc2VzLCB2ZXJzZV90eXBlcyksIHNlcF9tYXJrID0gIiAiKSAlPiUKICBjb2xzX2xhYmVsKHZlcnNlcz0iVmVyc2VzIixwb2Vtcz0iUG9lbXMiLHZlcnNlX3R5cGVzPSJWZXJzZSB0eXBlcyIpCmBgYAoKCiMgV29yayBkZXZlbG9wbWVudAoKYGBge3J9Cndvcmtfbm9kZXNfbCA8LSB3b3Jrc19vZl9pbnRlcmVzdF9sICU+JSAKICBtdXRhdGUoaWQ9cm93X251bWJlcigpIC0gMSkKCm5fd29ya3MgPC0gd29ya19ub2Rlc19sICU+JSBjb3VudCgpICU+JSBwdWxsKCkKCndvcmtfdmVyc2VfbmV0d29ya19sIDwtIHdvcmtfdmVyc2VfY2x1c3RzICU+JSAKICBpbm5lcl9qb2luKHdvcmtzX29mX2ludGVyZXN0ICU+JSBzZWxlY3Qod29yaywgcHVibGljYXRpb25fb3JkZXIpKSAlPiUKICByaWdodF9qb2luKHdvcmtfdmVyc2VfY2x1c3RzICU+JSAKICAgIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QgJT4lIHNlbGVjdCh3b3JrLCBwdWJsaWNhdGlvbl9vcmRlcikpLCBqb2luX2J5KGNsdXN0X2lkLCBwdWJsaWNhdGlvbl9vcmRlciA8IHB1YmxpY2F0aW9uX29yZGVyKSkgJT4lCiAgbXV0YXRlKHdvcmsueD1jb2FsZXNjZSh3b3JrLngsd29yay55KSwgcHVibGljYXRpb25fb3JkZXIueD1jb2FsZXNjZShwdWJsaWNhdGlvbl9vcmRlci54LHB1YmxpY2F0aW9uX29yZGVyLnkpKSAlPiUKICBncm91cF9ieShjbHVzdF9pZCwgd29yay55KSAlPiUKICBmaWx0ZXIocHVibGljYXRpb25fb3JkZXIueD09bWF4KHB1YmxpY2F0aW9uX29yZGVyLngpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgaW5uZXJfam9pbih3b3JrX3ZlcnNlX2NsdXN0X29yaWdpbnMpICU+JQogIGNvdW50KG9yaWdpbl93b3JrLCB3b3JrLngsd29yay55KSAlPiUKICBjb2xsZWN0KCkgJT4lCiAgaW5uZXJfam9pbih3b3JrX25vZGVzX2wgJT4lIHNlbGVjdCh3b3JrLng9d29yayxpZC54PWlkKSkgJT4lCiAgaW5uZXJfam9pbih3b3JrX25vZGVzX2wgJT4lIHNlbGVjdCh3b3JrLnk9d29yayxpZC55PWlkKSkgJT4lIAogIG11dGF0ZShpZC54PWlmX2Vsc2UoaWQueT09aWQueCxuX3dvcmtzK2lkLngsaWQueCkpCgp3b3JrX25vZGVzX2wgPC0gd29ya19ub2Rlc19sICU+JQogIHVuaW9uX2FsbCh3b3JrX25vZGVzX2wgJT4lIG11dGF0ZShpZD1pZCtuX3dvcmtzKSkKYGBgCgpgYGB7cn0KbGlicmFyeShuZXR3b3JrRDMpCnNhbmtleU5ldHdvcmsoTm9kZXM9d29ya19ub2Rlc19sLExpbmtzPXdvcmtfdmVyc2VfbmV0d29ya19sLCBOb2RlSUQ9J3dvcmsnLCBTb3VyY2U9J2lkLngnLCBUYXJnZXQ9J2lkLnknLFZhbHVlPSduJywgZm9udFNpemUgPSAxMiwgd2lkdGg9MjA0OCwgaGVpZ2h0PTIwNDgsIG5vZGVXaWR0aCA9IDMwLCBMaW5rR3JvdXAgPSAnb3JpZ2luX3dvcmsnLCB1bml0cz0idmVyc2VzIiwgY29sb3VyU2NhbGU9SlMoImQzLnNjYWxlT3JkaW5hbChkMy5zY2hlbWVDYXRlZ29yeTIwYyk7IikpCmBgYAoKYGBge3J9Cndvcmtfbm9kZXNfbCA8LSB3b3Jrc19vZl9pbnRlcmVzdF9sICU+JSAKICBtdXRhdGUoaWQ9cm93X251bWJlcigpIC0gMSkKCm5fd29ya3MgPC0gd29ya19ub2Rlc19sICU+JSBjb3VudCgpICU+JSBwdWxsKCkKCndvcmtfdmVyc2VfbmV0d29ya19sIDwtIHdvcmtfdmVyc2VfY2x1c3RzICU+JSAKICBpbm5lcl9qb2luKHdvcmtzX29mX2ludGVyZXN0ICU+JSBzZWxlY3Qod29yaywgcHVibGljYXRpb25fb3JkZXIpKSAlPiUKICByaWdodF9qb2luKHdvcmtfdmVyc2VfY2x1c3RzICU+JSAKICAgIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QgJT4lIHNlbGVjdCh3b3JrLCBwdWJsaWNhdGlvbl9vcmRlcikpLCBqb2luX2J5KGNsdXN0X2lkLCBwdWJsaWNhdGlvbl9vcmRlciA8IHB1YmxpY2F0aW9uX29yZGVyKSkgJT4lCiAgbXV0YXRlKHdvcmsueD1jb2FsZXNjZSh3b3JrLngsd29yay55KSwgcHVibGljYXRpb25fb3JkZXIueD1jb2FsZXNjZShwdWJsaWNhdGlvbl9vcmRlci54LHB1YmxpY2F0aW9uX29yZGVyLnkpKSAlPiUKICBncm91cF9ieShjbHVzdF9pZCwgd29yay55KSAlPiUKICBmaWx0ZXIocHVibGljYXRpb25fb3JkZXIueD09bWF4KHB1YmxpY2F0aW9uX29yZGVyLngpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgaW5uZXJfam9pbih3b3JrX3ZlcnNlX2NsdXN0X29yaWdpbnMpICU+JQogIGNvdW50KHdvcmsueCx3b3JrLnkpICU+JQogIGNvbGxlY3QoKSAlPiUKICBpbm5lcl9qb2luKHdvcmtfbm9kZXNfbCAlPiUgc2VsZWN0KHdvcmsueD13b3JrLGlkLng9aWQpKSAlPiUKICBpbm5lcl9qb2luKHdvcmtfbm9kZXNfbCAlPiUgc2VsZWN0KHdvcmsueT13b3JrLGlkLnk9aWQpKSAlPiUgCiAgbXV0YXRlKGlkLng9aWZfZWxzZShpZC55PT1pZC54LG5fd29ya3MraWQueCxpZC54KSkKCndvcmtfbm9kZXNfbCA8LSB3b3JrX25vZGVzX2wgJT4lCiAgdW5pb25fYWxsKHdvcmtfbm9kZXNfbCAlPiUgbXV0YXRlKGlkPWlkK25fd29ya3MpKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KG5ldHdvcmtEMykKc2Fua2V5TmV0d29yayhOb2Rlcz13b3JrX25vZGVzX2wsTGlua3M9d29ya192ZXJzZV9uZXR3b3JrX2wsIE5vZGVJRD0nd29yaycsIFNvdXJjZT0naWQueCcsIFRhcmdldD0naWQueScsVmFsdWU9J24nLCBmb250U2l6ZSA9IDEyLCB3aWR0aD0yMDQ4LCBoZWlnaHQ9MjA0OCwgbm9kZVdpZHRoID0gMzAsIExpbmtHcm91cCA9ICd3b3JrLngnLCB1bml0cz0idmVyc2VzIiwgY29sb3VyU2NhbGU9SlMoImQzLnNjYWxlT3JkaW5hbChkMy5zY2hlbWVDYXRlZ29yeTIwYyk7IikpCmBgYAoKYGBge3J9Cndvcmtfbm9kZXNfbCA8LSB3b3Jrc19vZl9pbnRlcmVzdF9sICU+JSAKICBtdXRhdGUoaWQ9cm93X251bWJlcigpIC0gMSkKCm5fd29ya3MgPC0gd29ya19ub2Rlc19sICU+JSBjb3VudCgpICU+JSBwdWxsKCkKCndvcmtfdmVyc2VfbmV0d29ya19sIDwtIHdvcmtfdmVyc2VfY2x1c3RzICU+JSAKICBpbm5lcl9qb2luKHdvcmtzX29mX2ludGVyZXN0ICU+JSBzZWxlY3Qod29yaywgcHVibGljYXRpb25fb3JkZXIpKSAlPiUKICByaWdodF9qb2luKHdvcmtfdmVyc2VfY2x1c3RzICU+JSAKICAgIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QgJT4lIHNlbGVjdCh3b3JrLCBwdWJsaWNhdGlvbl9vcmRlcikpLCBqb2luX2J5KGNsdXN0X2lkLCBwdWJsaWNhdGlvbl9vcmRlciA8IHB1YmxpY2F0aW9uX29yZGVyKSkgJT4lCiAgbXV0YXRlKHdvcmsueD1jb2FsZXNjZSh3b3JrLngsd29yay55KSwgcHVibGljYXRpb25fb3JkZXIueD1jb2FsZXNjZShwdWJsaWNhdGlvbl9vcmRlci54LHB1YmxpY2F0aW9uX29yZGVyLnkpKSAlPiUKICBncm91cF9ieShjbHVzdF9pZCwgd29yay55KSAlPiUKICBmaWx0ZXIocHVibGljYXRpb25fb3JkZXIueD09bWF4KHB1YmxpY2F0aW9uX29yZGVyLngpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgaW5uZXJfam9pbih3b3JrX3ZlcnNlX2NsdXN0X29yaWdpbnMpICU+JQogIGNvdW50KHdvcmsueCx3b3JrLnkpICU+JQogIGNvbGxlY3QoKSAlPiUKICBpbm5lcl9qb2luKHdvcmtfbm9kZXNfbCAlPiUgc2VsZWN0KHdvcmsueD13b3JrLGlkLng9aWQpKSAlPiUKICBpbm5lcl9qb2luKHdvcmtfbm9kZXNfbCAlPiUgc2VsZWN0KHdvcmsueT13b3JrLGlkLnk9aWQpKSAlPiUgCiAgZmlsdGVyKGlkLnkhPWlkLngpCmBgYAoKYGBge3J9CmxpYnJhcnkobmV0d29ya0QzKQpzYW5rZXlOZXR3b3JrKE5vZGVzPXdvcmtfbm9kZXNfbCxMaW5rcz13b3JrX3ZlcnNlX25ldHdvcmtfbCwgTm9kZUlEPSd3b3JrJywgU291cmNlPSdpZC54JywgVGFyZ2V0PSdpZC55JyxWYWx1ZT0nbicsIGZvbnRTaXplID0gMTIsIHdpZHRoPTIwNDgsIGhlaWdodD0yMDQ4LCBub2RlV2lkdGggPSAzMCwgTGlua0dyb3VwID0gJ3dvcmsueCcsIHVuaXRzPSJ2ZXJzZXMiLCBjb2xvdXJTY2FsZT1KUygiZDMuc2NhbGVPcmRpbmFsKGQzLnNjaGVtZUNhdGVnb3J5MjBjKTsiKSkKYGBgCgpgYGB7cixmaWcud2lkdGg9OSxmaWcuaGVpZ2h0PTEwfQp3b3JrX3ZlcnNlX2NsdXN0cyAlPiUgCiAgaW5uZXJfam9pbih3b3JrX3ZlcnNlX2NsdXN0X29yaWdpbnMpICU+JQogIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QgJT4lIHNlbGVjdChvcmlnaW5fd29yaz13b3JrLHB1YmxpY2F0aW9uX29yZGVyKSkgJT4lCiAgaW5uZXJfam9pbih3b3Jrc19vZl9pbnRlcmVzdCAlPiUgc2VsZWN0KHdvcmsscHVibGljYXRpb25fb3JkZXIpLCBqb2luX2J5KHdvcmspKSAlPiUKICBmaWx0ZXIocHVibGljYXRpb25fb3JkZXIueDxwdWJsaWNhdGlvbl9vcmRlci55IHwgd29yayA9PSBvcmlnaW5fd29yaykgJT4lCiAgY291bnQob3JpZ2luX3dvcmssIHdvcmssIHB1YmxpY2F0aW9uX29yZGVyLngsIHB1YmxpY2F0aW9uX29yZGVyLnkpICU+JQogIGdyb3VwX2J5KHdvcmspICU+JQogIG11dGF0ZShwcm9wPW4vc3VtKG4pKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgY29sbGVjdCgpICU+JQogIG11dGF0ZShvcmlnaW5fd29yaz1mY3RfcmVvcmRlcihvcmlnaW5fd29yaywgcHVibGljYXRpb25fb3JkZXIueCksd29yaz1mY3RfcmVvcmRlcih3b3JrLCBwdWJsaWNhdGlvbl9vcmRlci55KSkgJT4lCiAgZ2dwbG90KGFlcyh4PW9yaWdpbl93b3JrLHk9d29yayxmaWxsPXByb3ApKSArCiAgZ2VvbV90aWxlKCkgKwogIHRoZW1lX2hzY2lfY29udGludW91cygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCgpgYGAKCiMjIE9yaWdpbnMgb2YgdmVyc2UgdHlwZXMgaW4gcGFydHMgb2YgdGhlIEthbGV2YWxhIGluIHRlcm1zIG9mIGVhcmxpZXIgd29ya3MKCmBgYHtyLGZpZy53aWR0aD04LGZpZy5oZWlnaHQ9MTB9CndvcmtfdmVyc2VfY2x1c3RzICU+JSAKICBpbm5lcl9qb2luKHdvcmtfdmVyc2VfY2x1c3Rfb3JpZ2lucykgJT4lCiAgaW5uZXJfam9pbih3b3Jrc19vZl9pbnRlcmVzdCAlPiUgc2VsZWN0KG9yaWdpbl93b3JrPXdvcmsscHVibGljYXRpb25fb3JkZXIpKSAlPiUKICBpbm5lcl9qb2luKHdvcmtzX29mX2ludGVyZXN0ICU+JSBzZWxlY3Qod29yayxwdWJsaWNhdGlvbl9vcmRlciksIGpvaW5fYnkod29yaykpICU+JQogIGZpbHRlcihwdWJsaWNhdGlvbl9vcmRlci54PHB1YmxpY2F0aW9uX29yZGVyLnkgfCB3b3JrID09IG9yaWdpbl93b3JrKSAlPiUKICBjb3VudChvcmlnaW5fd29yaywgd29yaywgcHVibGljYXRpb25fb3JkZXIueCwgcHVibGljYXRpb25fb3JkZXIueSkgJT4lCiAgZ3JvdXBfYnkod29yaykgJT4lCiAgbXV0YXRlKHByb3A9bi9zdW0obikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIocHVibGljYXRpb25fb3JkZXIueT09MTIsb3JpZ2luX3dvcmshPXdvcmspICU+JQogIGNvbGxlY3QoKSAlPiUKICBpbm5lcl9qb2luKHdvcmtzX29mX2ludGVyZXN0X2wgJT4lIG11dGF0ZShvcmRlcj1yb3dfbnVtYmVyKCkpICU+JSBzZWxlY3Qod29yayxvcmRlcikpICU+JQogIG11dGF0ZShvcmlnaW5fd29yaz1mY3RfcmVvcmRlcihvcmlnaW5fd29yaywgcHVibGljYXRpb25fb3JkZXIueCksd29yaz1mY3RfcmVvcmRlcih3b3JrLCBvcmRlciwuZGVzYz1UUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXdvcmsseT1wcm9wLGZpbGw9b3JpZ2luX3dvcmspKSArCiAgZ2VvbV9jb2woKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBjb29yZF9mbGlwKCkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgbGFicyhmaWxsPSIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKG5jb2w9MSkpCmBgYAoKYGBge3IsZmlnLndpZHRoPTgsZmlnLmhlaWdodD0xMH0Kd29ya192ZXJzZV9jbHVzdHMgJT4lIAogIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QgJT4lIHNlbGVjdCh3b3JrLHB1YmxpY2F0aW9uX29yZGVyKSkgJT4lCiAgaW5uZXJfam9pbih3b3JrX3ZlcnNlX2NsdXN0cyAlPiUgCiAgICBpbm5lcl9qb2luKHdvcmtzX29mX2ludGVyZXN0ICU+JSBmaWx0ZXIocHVibGljYXRpb25fb3JkZXI9PTEyKSAlPiUgc2VsZWN0KHdvcmsscHVibGljYXRpb25fb3JkZXIpKSwgam9pbl9ieShjbHVzdF9pZCwgcHVibGljYXRpb25fb3JkZXI8cHVibGljYXRpb25fb3JkZXIpCiAgKSAlPiUKICBjb3VudCh3b3JrLngsd29yay55KSAlPiUKICBpbm5lcl9qb2luKHdvcmtfdmVyc2VfY2x1c3RzICU+JSBjb3VudCh3b3JrLng9d29yaywgbmFtZT0ib24iKSkgJT4lCiAgbXV0YXRlKHByb3A9bi9vbikgJT4lCiAgZ2dwbG90KGFlcyh4PXdvcmsueSx5PXByb3AsZmlsbD13b3JrLngpKSArCiAgZ2VvbV9jb2wocG9zaXRpb249J2RvZGdlJykgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIGxhYnMoZmlsbD0iIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKwogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZChuY29sPTEpKQpgYGAKCmBgYHtyLGZpZy53aWR0aD04LGZpZy5oZWlnaHQ9MTB9CndvcmtfdmVyc2VfY2x1c3RzICU+JSAKICBpbm5lcl9qb2luKHdvcmtzX29mX2ludGVyZXN0ICU+JSBzZWxlY3Qod29yayxib29rLHB1YmxpY2F0aW9uX29yZGVyKSkgJT4lCiAgaW5uZXJfam9pbih3b3JrX3ZlcnNlX2NsdXN0cyAlPiUgCiAgICBpbm5lcl9qb2luKHdvcmtzX29mX2ludGVyZXN0ICU+JSBmaWx0ZXIocHVibGljYXRpb25fb3JkZXI9PTEyKSkgJT4lIHNlbGVjdChjbHVzdF9pZCx3b3JrLGJvb2sscHVibGljYXRpb25fb3JkZXIpLCBqb2luX2J5KGNsdXN0X2lkLCBwdWJsaWNhdGlvbl9vcmRlcjxwdWJsaWNhdGlvbl9vcmRlcikKICApICU+JQogIGdyb3VwX2J5KHdvcmsueCxib29rLnkpICU+JQogIHN1bW1hcmlzZShuPW5fZGlzdGluY3QoY2x1c3RfaWQpLC5ncm91cHM9ImRyb3AiKSAlPiUKICBpbm5lcl9qb2luKHdvcmtfdmVyc2VfY2x1c3RzICU+JSBjb3VudCh3b3JrLng9d29yaywgbmFtZT0ib24iKSkgJT4lCiAgbXV0YXRlKHByb3A9bi9vbikgJT4lCiAgZ2dwbG90KGFlcyh4PXdvcmsueCx5PXByb3ApKSArCiAgZ2VvbV9jb2wocG9zaXRpb249J2RvZGdlJykgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIGxhYnMoZmlsbD0iIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKwogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZChuY29sPTEpKQpgYGA=