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=