total_verse_clusts_by_col_by_year <- poems_to_cols %>% 
  inner_join(poem_verse_clusts) %>%
  inner_join(works_of_interest, join_by(year<=year)) %>%
  group_by(work, year=year.y,col_name,pl_name) %>%
  summarise(available_verse_clusts=n_distinct(clust_id),.groups="drop") %>%
  distinct(year,col_name,pl_name,available_verse_clusts) %>%
  compute_a()
d <- poems_to_cols %>% 
  inner_join(poem_verse_clusts) %>%
  inner_join(work_verse_clusts) %>%
  inner_join(works_of_interest, join_by(work, year<=year)) %>%
  group_by(col_name,pl_name, book, work, year=year.y) %>%
  summarise(shared_verse_clusts=n_distinct(clust_id),.groups="drop") %>%
  right_join(total_verse_clusts_by_col_by_year) %>%
  collect() %>%
  complete(nesting(year,work), fill=list(shared_verse_clusts=0)) %>%
  filter(!is.na(work)) %>%
  mutate(prop=shared_verse_clusts/available_verse_clusts) %>%
  arrange(year, work,col_name,pl_name)

d2 <- poems_to_cols %>% 
  inner_join(poem_verse_clusts) %>%
  inner_join(work_verse_clusts) %>%
  inner_join(works_of_interest, join_by(work, year<=year)) %>%
  group_by(col_name,pl_name, book, year=year.y) %>%
  summarise(shared_verse_clusts=n_distinct(clust_id),.groups="drop") %>%
  right_join(total_verse_clusts_by_col_by_year) %>%
  collect() %>%
  complete(nesting(year,book), fill=list(shared_verse_clusts=0)) %>%
  filter(!is.na(book)) %>%
  mutate(prop=shared_verse_clusts/available_verse_clusts) %>%
  arrange(year, book,col_name,pl_name) %>%
  rename(work=book)

Proportion of parts of the Kalevala for which we identify possible oral sources

d3 <- poems_to_cols %>% 
  inner_join(poem_verse_clusts) %>%
  inner_join(work_verse_clusts) %>%
  inner_join(works_of_interest, join_by(work, year<=year)) %>%
  group_by(book, work, year=year.y) %>%
  summarise(shared_verse_clusts=n_distinct(clust_id),.groups="drop") %>%
  right_join(work_verse_clusts %>% count(work,name="work_verse_clusts")) %>%
  collect() %>%
  complete(nesting(year,work), fill=list(shared_verse_clusts=0)) %>%
  filter(!is.na(work)) %>%
  mutate(prop=shared_verse_clusts/work_verse_clusts) %>%
  arrange(year, work)
d3 %>% 
  filter(book=="Kalevala (1849)") %>%
  ggplot(aes(x=work,y=prop)) +
  geom_col() +
  theme_hsci_discrete() +
  scale_y_continuous(labels=scales::percent) +
  coord_flip() +
  theme(legend.position="bottom") +
  guides(fill=guide_legend(ncol=1))

Composition of the Kalevala in terms of regions

As a whole

d4 <- poems_to_cols %>% 
  inner_join(poem_verse_clusts) %>%
  inner_join(work_verse_clusts) %>%
  inner_join(works_of_interest, join_by(work, year<=year)) %>%
  group_by(pl_name, book, year=year.y) %>%
  summarise(shared_verse_clusts=n_distinct(clust_id),.groups="drop") %>%
  right_join(work_verse_clusts %>% inner_join(works_of_interest) %>% group_by(book) %>% summarise(work_verse_clusts=n_distinct(clust_id))) %>%
  collect() %>%
  complete(nesting(year,book), fill=list(shared_verse_clusts=0)) %>%
  filter(!is.na(book)) %>%
  mutate(prop=shared_verse_clusts/work_verse_clusts) %>%
  arrange(year, book, pl_name)
d4 %>% 
  filter(book=="Kalevala (1849)") %>%
  ggplot(aes(x=pl_name,y=prop)) +
  geom_col(position='dodge') +
  theme_hsci_discrete() +
  scale_y_continuous(labels=scales::percent) +
  coord_flip() +
  theme(legend.position="bottom") +
  guides(fill=guide_legend(ncol=1))

By part

d5<- poems_to_cols %>% 
  inner_join(poem_verse_clusts) %>%
  inner_join(work_verse_clusts) %>%
  inner_join(works_of_interest, join_by(work, year<=year)) %>%
  group_by(pl_name, book, work, year=year.y) %>%
  summarise(shared_verse_clusts=n_distinct(clust_id),.groups="drop") %>%
  right_join(work_verse_clusts %>% count(work,name="work_verse_clusts")) %>%
  collect() %>%
  complete(nesting(year,work), fill=list(shared_verse_clusts=0)) %>%
  filter(!is.na(work)) %>%
  mutate(prop=shared_verse_clusts/work_verse_clusts) %>%
  arrange(year, work, pl_name)
d3 %>% 
  filter(book=="Kalevala (1849)") %>%
  ggplot(aes(x=work,y=prop, fill=pl_name)) +
  geom_col(position='dodge') +
  theme_hsci_discrete() +
  scale_y_continuous(labels=scales::percent) +
  coord_flip() +
  theme(legend.position="bottom") +
  guides(fill=guide_legend(ncol=1))

Oral source as graph

Proportionally of the available material

d2 %>% 
  group_by(col_name,work) %>%
  filter(sum(available_verse_clusts)>=100) %>%
  ungroup() %>%
  arrange(col_name, pl_name) %>%
  mutate(col_name=fct_rev(fct_inorder(str_c(col_name,", ", pl_name)))) %>%
  arrange(year,work) %>%
  mutate(work=fct_inorder(work)) %>%
  complete(col_name,work,fill=list(prop=0)) %>%
  ggplot(aes(x=col_name,y=prop,fill=work)) +
  geom_col(position='dodge') +
  scale_y_continuous(labels=scales::percent) +
  coord_flip() +
  theme_hsci_discrete() +
  theme(legend.position="top")

In absolute numbers

d2 %>% 
  group_by(col_name,work) %>%
  filter(sum(available_verse_clusts)>=100) %>%
  ungroup() %>%
  arrange(col_name, pl_name) %>%
  mutate(col_name=fct_rev(fct_inorder(str_c(col_name,", ", pl_name)))) %>%
  arrange(year,work) %>%
  mutate(work=fct_inorder(work)) %>%
  complete(col_name,work,fill=list(prop=0,shared_verse_clusts=0)) %>%
  ggplot(aes(x=col_name,y=shared_verse_clusts,fill=work)) +
  geom_col(position='dodge') +
  coord_flip() +
  theme_hsci_discrete() +
  theme(legend.position="top")

Regional balance compared to a neutral baseline expectation

d6 <- poems_to_cols %>% 
  inner_join(poem_verse_clusts) %>%
  inner_join(work_verse_clusts) %>%
  inner_join(works_of_interest, join_by(work, year<=year)) %>%
  group_by(pl_name, book, year=year.y) %>%
  summarise(shared_verse_clusts=n_distinct(clust_id),.groups="drop") %>%
  right_join(total_verse_clusts_by_pl_by_year) %>%
  right_join(total_verse_clusts_by_year %>% rename(total_verse_clusts=available_verse_clusts)) %>%
  mutate(expected_prop=available_verse_clusts/total_verse_clusts) %>%
  collect() %>%
  complete(nesting(year,book), fill=list(shared_verse_clusts=0)) %>%
  filter(!is.na(book)) %>%
  mutate(prop=shared_verse_clusts/available_verse_clusts) %>%
  arrange(year, book,pl_name) %>%
  rename(work=book)
d6 %>% 
  filter(work=="Kalevala (1849)") %>%
  arrange(year, work) %>%
  mutate(work=fct_inorder(work)) %>%
  mutate(pl_name=fct_rev(fct_inorder(pl_name))) %>%
  complete(pl_name,work,fill=list(prop=0,expected_prop=0,shared_verse_clusts=0)) %>%
  mutate(ratio=prop/expected_prop) %>%
  ggplot(aes(x=pl_name,y=ratio)) +
  geom_point() +
#  scale_y_continuous(labels=function(x) { x %>% map_chr(function(lab) { if (lab < 0) { str_c(-1/lab,":1") } else {str_c("1:",lab)}})}) +
  coord_flip() +
  theme_hsci_discrete() +
  theme(legend.position="top")

Collector + Regional balance compared to a neutral baseline expectation

d2 %>% 
  group_by(col_name,work) %>%
  filter(sum(available_verse_clusts)>=100) %>%
  ungroup() %>%
  group_by(col_name,work) %>%
  filter(sum(shared_verse_clusts)>=20) %>%
  filter(n()>1) %>%
  ungroup() %>%
  arrange(col_name, pl_name) %>%
  group_by(col_name, pl_name) %>%
  mutate(expected_prop=available_verse_clusts/sum(available_verse_clusts)) %>%
  ungroup() %>%
  arrange(year, work) %>%
  mutate(work=fct_inorder(work)) %>%
  mutate(col_name=fct_rev(fct_inorder(str_c(work,", ", col_name)))) %>%
  complete(col_name,work,fill=list(prop=0,expected_prop=0,shared_verse_clusts=0)) %>%
  mutate(ratio=prop/expected_prop) %>%
  mutate(ratio=if_else(ratio>=1,ratio-1,-1/ratio+1)) %>%
  ggplot(aes(x=col_name,y=ratio,color=pl_name)) +
  geom_point() +
#  scale_y_continuous(labels=function(x) { x %>% map_chr(function(lab) { if (lab < 0) { str_c(-1/lab,":1") } else {str_c("1:",lab)}})}) +
  coord_flip() +
  theme_hsci_discrete() +
  theme(legend.position="top")

Oral sources as table

d2 %>% 
  group_by(col_name,work) %>%
  filter(sum(available_verse_clusts)>=100) %>%
  ungroup() %>%
  mutate(col_name=fct_rev(fct_inorder(str_c(col_name,", ", pl_name)))) %>%
  select(-year,-pl_name) %>%
  gt(groupname_col="work",rowname_col="col_name") %>%
  fmt_integer(shared_verse_clusts) %>%
  fmt_percent(prop) %>%
  cols_label(
    shared_verse_clusts="Shared verse clusters",
    available_verse_clusts="Available verse clusters",
    prop="Proportion of available verse clusters used"
  )
  
  
LS0tCnRpdGxlOiAiT3JhbCBTb3VyY2VzIG9mIHRoZSBLYWxldmFsYSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRvYzogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2U9RkFMU0UsZHBpPTMwMCxmaWcucmV0aW5hPTIsZmlnLndpZHRoPTgpCnNvdXJjZShoZXJlOjpoZXJlKCJzcmMvY29tbW9uX2Jhc2lzLlIiKSkKdG1hcF9tb2RlKCJwbG90IikKc2F2ZV9wbG90cyA8LSBmdW5jdGlvbihkaXIsYmFzZW5hbWUscGxvdCx3aWR0aD02LGhlaWdodD01LHVuaXRzPSJpbiIsZHBpPTMwMCkgewogIGdnc2F2ZShnbHVlKCJ7ZGlyfS97YmFzZW5hbWV9LnBuZyIpLHBsb3Qsd2lkdGg9d2lkdGgsaGVpZ2h0PWhlaWdodCxkcGk9ZHBpLCB1bml0cz11bml0cykKICBnZ3NhdmUoZ2x1ZSgie2Rpcn0ve2Jhc2VuYW1lfS5zdmciKSxwbG90LHdpZHRoPXdpZHRoLGhlaWdodD1oZWlnaHQsZHBpPWRwaSwgdW5pdHM9dW5pdHMpCiAgZ2dzYXZlKGdsdWUoIntkaXJ9L3tiYXNlbmFtZX0ucGRmIikscGxvdCx3aWR0aD13aWR0aCxoZWlnaHQ9aGVpZ2h0LGRwaT1kcGksIHVuaXRzPXVuaXRzLCBkZXZpY2UgPSBjYWlyb19wZGYpCiAga25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoZ2x1ZSgie2Rpcn0ve2Jhc2VuYW1lfS5zdmciKSwgZHBpPWRwaSkKfQpgYGAKCmBgYHtyfQp0b3RhbF92ZXJzZV9jbHVzdHNfYnlfY29sX2J5X3llYXIgPC0gcG9lbXNfdG9fY29scyAlPiUgCiAgaW5uZXJfam9pbihwb2VtX3ZlcnNlX2NsdXN0cykgJT4lCiAgaW5uZXJfam9pbih3b3Jrc19vZl9pbnRlcmVzdCwgam9pbl9ieSh5ZWFyPD15ZWFyKSkgJT4lCiAgZ3JvdXBfYnkod29yaywgeWVhcj15ZWFyLnksY29sX25hbWUscGxfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGF2YWlsYWJsZV92ZXJzZV9jbHVzdHM9bl9kaXN0aW5jdChjbHVzdF9pZCksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGRpc3RpbmN0KHllYXIsY29sX25hbWUscGxfbmFtZSxhdmFpbGFibGVfdmVyc2VfY2x1c3RzKSAlPiUKICBjb21wdXRlX2EoKQoKdG90YWxfdmVyc2VfY2x1c3RzX2J5X3BsX2J5X3llYXIgPC0gcG9lbXNfdG9fY29scyAlPiUgCiAgaW5uZXJfam9pbihwb2VtX3ZlcnNlX2NsdXN0cykgJT4lCiAgaW5uZXJfam9pbih3b3Jrc19vZl9pbnRlcmVzdCwgam9pbl9ieSh5ZWFyPD15ZWFyKSkgJT4lCiAgZ3JvdXBfYnkod29yaywgeWVhcj15ZWFyLnkscGxfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGF2YWlsYWJsZV92ZXJzZV9jbHVzdHM9bl9kaXN0aW5jdChjbHVzdF9pZCksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGRpc3RpbmN0KHllYXIscGxfbmFtZSxhdmFpbGFibGVfdmVyc2VfY2x1c3RzKSAlPiUKICBjb21wdXRlX2EoKQoKdG90YWxfdmVyc2VfY2x1c3RzX2J5X3llYXIgPC0gcG9lbXNfdG9fY29scyAlPiUgCiAgaW5uZXJfam9pbihwb2VtX3ZlcnNlX2NsdXN0cykgJT4lCiAgaW5uZXJfam9pbih3b3Jrc19vZl9pbnRlcmVzdCwgam9pbl9ieSh5ZWFyPD15ZWFyKSkgJT4lCiAgZ3JvdXBfYnkod29yaywgeWVhcj15ZWFyLnkpICU+JQogIHN1bW1hcmlzZShhdmFpbGFibGVfdmVyc2VfY2x1c3RzPW5fZGlzdGluY3QoY2x1c3RfaWQpLC5ncm91cHM9ImRyb3AiKSAlPiUKICBkaXN0aW5jdCh5ZWFyLGF2YWlsYWJsZV92ZXJzZV9jbHVzdHMpICU+JQogIGNvbXB1dGVfYSgpCmBgYAoKCmBgYHtyfQpkIDwtIHBvZW1zX3RvX2NvbHMgJT4lIAogIGlubmVyX2pvaW4ocG9lbV92ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya192ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QsIGpvaW5fYnkod29yaywgeWVhcjw9eWVhcikpICU+JQogIGdyb3VwX2J5KGNvbF9uYW1lLHBsX25hbWUsIGJvb2ssIHdvcmssIHllYXI9eWVhci55KSAlPiUKICBzdW1tYXJpc2Uoc2hhcmVkX3ZlcnNlX2NsdXN0cz1uX2Rpc3RpbmN0KGNsdXN0X2lkKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgcmlnaHRfam9pbih0b3RhbF92ZXJzZV9jbHVzdHNfYnlfY29sX2J5X3llYXIpICU+JQogIGNvbGxlY3QoKSAlPiUKICBjb21wbGV0ZShuZXN0aW5nKHllYXIsd29yayksIGZpbGw9bGlzdChzaGFyZWRfdmVyc2VfY2x1c3RzPTApKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHdvcmspKSAlPiUKICBtdXRhdGUocHJvcD1zaGFyZWRfdmVyc2VfY2x1c3RzL2F2YWlsYWJsZV92ZXJzZV9jbHVzdHMpICU+JQogIGFycmFuZ2UoeWVhciwgd29yayxjb2xfbmFtZSxwbF9uYW1lKQoKZDIgPC0gcG9lbXNfdG9fY29scyAlPiUgCiAgaW5uZXJfam9pbihwb2VtX3ZlcnNlX2NsdXN0cykgJT4lCiAgaW5uZXJfam9pbih3b3JrX3ZlcnNlX2NsdXN0cykgJT4lCiAgaW5uZXJfam9pbih3b3Jrc19vZl9pbnRlcmVzdCwgam9pbl9ieSh3b3JrLCB5ZWFyPD15ZWFyKSkgJT4lCiAgZ3JvdXBfYnkoY29sX25hbWUscGxfbmFtZSwgYm9vaywgeWVhcj15ZWFyLnkpICU+JQogIHN1bW1hcmlzZShzaGFyZWRfdmVyc2VfY2x1c3RzPW5fZGlzdGluY3QoY2x1c3RfaWQpLC5ncm91cHM9ImRyb3AiKSAlPiUKICByaWdodF9qb2luKHRvdGFsX3ZlcnNlX2NsdXN0c19ieV9jb2xfYnlfeWVhcikgJT4lCiAgY29sbGVjdCgpICU+JQogIGNvbXBsZXRlKG5lc3RpbmcoeWVhcixib29rKSwgZmlsbD1saXN0KHNoYXJlZF92ZXJzZV9jbHVzdHM9MCkpICU+JQogIGZpbHRlcighaXMubmEoYm9vaykpICU+JQogIG11dGF0ZShwcm9wPXNoYXJlZF92ZXJzZV9jbHVzdHMvYXZhaWxhYmxlX3ZlcnNlX2NsdXN0cykgJT4lCiAgYXJyYW5nZSh5ZWFyLCBib29rLGNvbF9uYW1lLHBsX25hbWUpICU+JQogIHJlbmFtZSh3b3JrPWJvb2spCmBgYAoKIyMgUHJvcG9ydGlvbiBvZiBwYXJ0cyBvZiB0aGUgS2FsZXZhbGEgZm9yIHdoaWNoIHdlIGlkZW50aWZ5IHBvc3NpYmxlIG9yYWwgc291cmNlcwoKYGBge3J9CmQzIDwtIHBvZW1zX3RvX2NvbHMgJT4lIAogIGlubmVyX2pvaW4ocG9lbV92ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya192ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QsIGpvaW5fYnkod29yaywgeWVhcjw9eWVhcikpICU+JQogIGdyb3VwX2J5KGJvb2ssIHdvcmssIHllYXI9eWVhci55KSAlPiUKICBzdW1tYXJpc2Uoc2hhcmVkX3ZlcnNlX2NsdXN0cz1uX2Rpc3RpbmN0KGNsdXN0X2lkKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgcmlnaHRfam9pbih3b3JrX3ZlcnNlX2NsdXN0cyAlPiUgY291bnQod29yayxuYW1lPSJ3b3JrX3ZlcnNlX2NsdXN0cyIpKSAlPiUKICBjb2xsZWN0KCkgJT4lCiAgY29tcGxldGUobmVzdGluZyh5ZWFyLHdvcmspLCBmaWxsPWxpc3Qoc2hhcmVkX3ZlcnNlX2NsdXN0cz0wKSkgJT4lCiAgZmlsdGVyKCFpcy5uYSh3b3JrKSkgJT4lCiAgbXV0YXRlKHByb3A9c2hhcmVkX3ZlcnNlX2NsdXN0cy93b3JrX3ZlcnNlX2NsdXN0cykgJT4lCiAgYXJyYW5nZSh5ZWFyLCB3b3JrKQpgYGAKCmBgYHtyLGZpZy5oZWlnaHQ9MTAsZmlnLndpZHRoPTh9CmQzICU+JSAKICBmaWx0ZXIoYm9vaz09IkthbGV2YWxhICgxODQ5KSIpICU+JQogIGdncGxvdChhZXMoeD13b3JrLHk9cHJvcCkpICsKICBnZW9tX2NvbCgpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQobmNvbD0xKSkKYGBgCiMjIENvbXBvc2l0aW9uIG9mIHRoZSBLYWxldmFsYSBpbiB0ZXJtcyBvZiByZWdpb25zCgojIyMgQXMgYSB3aG9sZQoKYGBge3J9CmQ0IDwtIHBvZW1zX3RvX2NvbHMgJT4lIAogIGlubmVyX2pvaW4ocG9lbV92ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya192ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QsIGpvaW5fYnkod29yaywgeWVhcjw9eWVhcikpICU+JQogIGdyb3VwX2J5KHBsX25hbWUsIGJvb2ssIHllYXI9eWVhci55KSAlPiUKICBzdW1tYXJpc2Uoc2hhcmVkX3ZlcnNlX2NsdXN0cz1uX2Rpc3RpbmN0KGNsdXN0X2lkKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgcmlnaHRfam9pbih3b3JrX3ZlcnNlX2NsdXN0cyAlPiUgaW5uZXJfam9pbih3b3Jrc19vZl9pbnRlcmVzdCkgJT4lIGdyb3VwX2J5KGJvb2spICU+JSBzdW1tYXJpc2Uod29ya192ZXJzZV9jbHVzdHM9bl9kaXN0aW5jdChjbHVzdF9pZCkpKSAlPiUKICBjb2xsZWN0KCkgJT4lCiAgY29tcGxldGUobmVzdGluZyh5ZWFyLGJvb2spLCBmaWxsPWxpc3Qoc2hhcmVkX3ZlcnNlX2NsdXN0cz0wKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShib29rKSkgJT4lCiAgbXV0YXRlKHByb3A9c2hhcmVkX3ZlcnNlX2NsdXN0cy93b3JrX3ZlcnNlX2NsdXN0cykgJT4lCiAgYXJyYW5nZSh5ZWFyLCBib29rLCBwbF9uYW1lKQpgYGAKCmBgYHtyLGZpZy5oZWlnaHQ9MTAsZmlnLndpZHRoPTh9CmQ0ICU+JSAKICBmaWx0ZXIoYm9vaz09IkthbGV2YWxhICgxODQ5KSIpICU+JQogIGdncGxvdChhZXMoeD1wbF9uYW1lLHk9cHJvcCkpICsKICBnZW9tX2NvbChwb3NpdGlvbj0nZG9kZ2UnKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKG5jb2w9MSkpCmBgYAoKIyMjIEJ5IHBhcnQKCmBgYHtyfQpkNTwtIHBvZW1zX3RvX2NvbHMgJT4lIAogIGlubmVyX2pvaW4ocG9lbV92ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya192ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QsIGpvaW5fYnkod29yaywgeWVhcjw9eWVhcikpICU+JQogIGdyb3VwX2J5KHBsX25hbWUsIGJvb2ssIHdvcmssIHllYXI9eWVhci55KSAlPiUKICBzdW1tYXJpc2Uoc2hhcmVkX3ZlcnNlX2NsdXN0cz1uX2Rpc3RpbmN0KGNsdXN0X2lkKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgcmlnaHRfam9pbih3b3JrX3ZlcnNlX2NsdXN0cyAlPiUgY291bnQod29yayxuYW1lPSJ3b3JrX3ZlcnNlX2NsdXN0cyIpKSAlPiUKICBjb2xsZWN0KCkgJT4lCiAgY29tcGxldGUobmVzdGluZyh5ZWFyLHdvcmspLCBmaWxsPWxpc3Qoc2hhcmVkX3ZlcnNlX2NsdXN0cz0wKSkgJT4lCiAgZmlsdGVyKCFpcy5uYSh3b3JrKSkgJT4lCiAgbXV0YXRlKHByb3A9c2hhcmVkX3ZlcnNlX2NsdXN0cy93b3JrX3ZlcnNlX2NsdXN0cykgJT4lCiAgYXJyYW5nZSh5ZWFyLCB3b3JrLCBwbF9uYW1lKQpgYGAKCmBgYHtyLGZpZy5oZWlnaHQ9MTAsZmlnLndpZHRoPTh9CmQ1ICU+JSAKICBmaWx0ZXIoYm9vaz09IkthbGV2YWxhICgxODQ5KSIpICU+JQogIGdncGxvdChhZXMoeD13b3JrLHk9cHJvcCwgZmlsbD1wbF9uYW1lKSkgKwogIGdlb21fY29sKHBvc2l0aW9uPSdkb2RnZScpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQobmNvbD0xKSkKYGBgCgojIyBPcmFsIHNvdXJjZSBhcyBncmFwaAoKIyMjIFByb3BvcnRpb25hbGx5IG9mIHRoZSBhdmFpbGFibGUgbWF0ZXJpYWwKCmBgYHtyLGZpZy5oZWlnaHQ9MTAwLHdpZHRoPTEwfQpkMiAlPiUgCiAgZ3JvdXBfYnkoY29sX25hbWUsd29yaykgJT4lCiAgZmlsdGVyKHN1bShhdmFpbGFibGVfdmVyc2VfY2x1c3RzKT49MTAwKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZShjb2xfbmFtZSwgcGxfbmFtZSkgJT4lCiAgbXV0YXRlKGNvbF9uYW1lPWZjdF9yZXYoZmN0X2lub3JkZXIoc3RyX2MoY29sX25hbWUsIiwgIiwgcGxfbmFtZSkpKSkgJT4lCiAgYXJyYW5nZSh5ZWFyLHdvcmspICU+JQogIG11dGF0ZSh3b3JrPWZjdF9pbm9yZGVyKHdvcmspKSAlPiUKICBjb21wbGV0ZShjb2xfbmFtZSx3b3JrLGZpbGw9bGlzdChwcm9wPTApKSAlPiUKICBnZ3Bsb3QoYWVzKHg9Y29sX25hbWUseT1wcm9wLGZpbGw9d29yaykpICsKICBnZW9tX2NvbChwb3NpdGlvbj0nZG9kZ2UnKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBjb29yZF9mbGlwKCkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKQpgYGAKCiMjIyBJbiBhYnNvbHV0ZSBudW1iZXJzCgpgYGB7cixmaWcuaGVpZ2h0PTEwMCx3aWR0aD0xMH0KZDIgJT4lIAogIGdyb3VwX2J5KGNvbF9uYW1lLHdvcmspICU+JQogIGZpbHRlcihzdW0oYXZhaWxhYmxlX3ZlcnNlX2NsdXN0cyk+PTEwMCkgJT4lCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2UoY29sX25hbWUsIHBsX25hbWUpICU+JQogIG11dGF0ZShjb2xfbmFtZT1mY3RfcmV2KGZjdF9pbm9yZGVyKHN0cl9jKGNvbF9uYW1lLCIsICIsIHBsX25hbWUpKSkpICU+JQogIGFycmFuZ2UoeWVhcix3b3JrKSAlPiUKICBtdXRhdGUod29yaz1mY3RfaW5vcmRlcih3b3JrKSkgJT4lCiAgY29tcGxldGUoY29sX25hbWUsd29yayxmaWxsPWxpc3QocHJvcD0wLHNoYXJlZF92ZXJzZV9jbHVzdHM9MCkpICU+JQogIGdncGxvdChhZXMoeD1jb2xfbmFtZSx5PXNoYXJlZF92ZXJzZV9jbHVzdHMsZmlsbD13b3JrKSkgKwogIGdlb21fY29sKHBvc2l0aW9uPSdkb2RnZScpICsKICBjb29yZF9mbGlwKCkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKQpgYGAKCiMjIyBSZWdpb25hbCBiYWxhbmNlIGNvbXBhcmVkIHRvIGEgbmV1dHJhbCBiYXNlbGluZSBleHBlY3RhdGlvbgoKYGBge3J9CmQ2IDwtIHBvZW1zX3RvX2NvbHMgJT4lIAogIGlubmVyX2pvaW4ocG9lbV92ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya192ZXJzZV9jbHVzdHMpICU+JQogIGlubmVyX2pvaW4od29ya3Nfb2ZfaW50ZXJlc3QsIGpvaW5fYnkod29yaywgeWVhcjw9eWVhcikpICU+JQogIGdyb3VwX2J5KHBsX25hbWUsIGJvb2ssIHllYXI9eWVhci55KSAlPiUKICBzdW1tYXJpc2Uoc2hhcmVkX3ZlcnNlX2NsdXN0cz1uX2Rpc3RpbmN0KGNsdXN0X2lkKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgcmlnaHRfam9pbih0b3RhbF92ZXJzZV9jbHVzdHNfYnlfcGxfYnlfeWVhcikgJT4lCiAgcmlnaHRfam9pbih0b3RhbF92ZXJzZV9jbHVzdHNfYnlfeWVhciAlPiUgcmVuYW1lKHRvdGFsX3ZlcnNlX2NsdXN0cz1hdmFpbGFibGVfdmVyc2VfY2x1c3RzKSkgJT4lCiAgbXV0YXRlKGV4cGVjdGVkX3Byb3A9YXZhaWxhYmxlX3ZlcnNlX2NsdXN0cy90b3RhbF92ZXJzZV9jbHVzdHMpICU+JQogIGNvbGxlY3QoKSAlPiUKICBjb21wbGV0ZShuZXN0aW5nKHllYXIsYm9vayksIGZpbGw9bGlzdChzaGFyZWRfdmVyc2VfY2x1c3RzPTApKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGJvb2spKSAlPiUKICBtdXRhdGUocHJvcD1zaGFyZWRfdmVyc2VfY2x1c3RzL2F2YWlsYWJsZV92ZXJzZV9jbHVzdHMpICU+JQogIGFycmFuZ2UoeWVhciwgYm9vayxwbF9uYW1lKSAlPiUKICByZW5hbWUod29yaz1ib29rKQpgYGAKCgpgYGB7cn0KZDYgJT4lIAogIGZpbHRlcih3b3JrPT0iS2FsZXZhbGEgKDE4NDkpIikgJT4lCiAgYXJyYW5nZSh5ZWFyLCB3b3JrKSAlPiUKICBtdXRhdGUod29yaz1mY3RfaW5vcmRlcih3b3JrKSkgJT4lCiAgbXV0YXRlKHBsX25hbWU9ZmN0X3JldihmY3RfaW5vcmRlcihwbF9uYW1lKSkpICU+JQogIGNvbXBsZXRlKHBsX25hbWUsd29yayxmaWxsPWxpc3QocHJvcD0wLGV4cGVjdGVkX3Byb3A9MCxzaGFyZWRfdmVyc2VfY2x1c3RzPTApKSAlPiUKICBtdXRhdGUocmF0aW89cHJvcC9leHBlY3RlZF9wcm9wKSAlPiUKICBnZ3Bsb3QoYWVzKHg9cGxfbmFtZSx5PXJhdGlvKSkgKwogIGdlb21fcG9pbnQoKSArCiMgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9ZnVuY3Rpb24oeCkgeyB4ICU+JSBtYXBfY2hyKGZ1bmN0aW9uKGxhYikgeyBpZiAobGFiIDwgMCkgeyBzdHJfYygtMS9sYWIsIjoxIikgfSBlbHNlIHtzdHJfYygiMToiLGxhYil9fSl9KSArCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikKYGBgCgoKIyMjIENvbGxlY3RvciArIFJlZ2lvbmFsIGJhbGFuY2UgY29tcGFyZWQgdG8gYSBuZXV0cmFsIGJhc2VsaW5lIGV4cGVjdGF0aW9uCgpgYGB7cixmaWcuaGVpZ2h0PTEwMCx3aWR0aD0xMH0KZDIgJT4lIAogIGdyb3VwX2J5KGNvbF9uYW1lLHdvcmspICU+JQogIGZpbHRlcihzdW0oYXZhaWxhYmxlX3ZlcnNlX2NsdXN0cyk+PTEwMCkgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KGNvbF9uYW1lLHdvcmspICU+JQogIGZpbHRlcihzdW0oc2hhcmVkX3ZlcnNlX2NsdXN0cyk+PTIwKSAlPiUKICBmaWx0ZXIobigpPjEpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKGNvbF9uYW1lLCBwbF9uYW1lKSAlPiUKICBncm91cF9ieShjb2xfbmFtZSwgcGxfbmFtZSkgJT4lCiAgbXV0YXRlKGV4cGVjdGVkX3Byb3A9YXZhaWxhYmxlX3ZlcnNlX2NsdXN0cy9zdW0oYXZhaWxhYmxlX3ZlcnNlX2NsdXN0cykpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKHllYXIsIHdvcmspICU+JQogIG11dGF0ZSh3b3JrPWZjdF9pbm9yZGVyKHdvcmspKSAlPiUKICBtdXRhdGUoY29sX25hbWU9ZmN0X3JldihmY3RfaW5vcmRlcihzdHJfYyh3b3JrLCIsICIsIGNvbF9uYW1lKSkpKSAlPiUKICBjb21wbGV0ZShjb2xfbmFtZSx3b3JrLGZpbGw9bGlzdChwcm9wPTAsZXhwZWN0ZWRfcHJvcD0wLHNoYXJlZF92ZXJzZV9jbHVzdHM9MCkpICU+JQogIG11dGF0ZShyYXRpbz1wcm9wL2V4cGVjdGVkX3Byb3ApICU+JQogIG11dGF0ZShyYXRpbz1pZl9lbHNlKHJhdGlvPj0xLHJhdGlvLTEsLTEvcmF0aW8rMSkpICU+JQogIGdncGxvdChhZXMoeD1jb2xfbmFtZSx5PXJhdGlvLGNvbG9yPXBsX25hbWUpKSArCiAgZ2VvbV9wb2ludCgpICsKIyAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1mdW5jdGlvbih4KSB7IHggJT4lIG1hcF9jaHIoZnVuY3Rpb24obGFiKSB7IGlmIChsYWIgPCAwKSB7IHN0cl9jKC0xL2xhYiwiOjEiKSB9IGVsc2Uge3N0cl9jKCIxOiIsbGFiKX19KX0pICsKICBjb29yZF9mbGlwKCkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKQpgYGAKCiMjIE9yYWwgc291cmNlcyBhcyB0YWJsZQoKYGBge3J9CmQyICU+JSAKICBncm91cF9ieShjb2xfbmFtZSx3b3JrKSAlPiUKICBmaWx0ZXIoc3VtKGF2YWlsYWJsZV92ZXJzZV9jbHVzdHMpPj0xMDApICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoY29sX25hbWU9ZmN0X3JldihmY3RfaW5vcmRlcihzdHJfYyhjb2xfbmFtZSwiLCAiLCBwbF9uYW1lKSkpKSAlPiUKICBzZWxlY3QoLXllYXIsLXBsX25hbWUpICU+JQogIGd0KGdyb3VwbmFtZV9jb2w9IndvcmsiLHJvd25hbWVfY29sPSJjb2xfbmFtZSIpICU+JQogIGZtdF9pbnRlZ2VyKHNoYXJlZF92ZXJzZV9jbHVzdHMpICU+JQogIGZtdF9wZXJjZW50KHByb3ApICU+JQogIGNvbHNfbGFiZWwoCiAgICBzaGFyZWRfdmVyc2VfY2x1c3RzPSJTaGFyZWQgdmVyc2UgY2x1c3RlcnMiLAogICAgYXZhaWxhYmxlX3ZlcnNlX2NsdXN0cz0iQXZhaWxhYmxlIHZlcnNlIGNsdXN0ZXJzIiwKICAgIHByb3A9IlByb3BvcnRpb24gb2YgYXZhaWxhYmxlIHZlcnNlIGNsdXN0ZXJzIHVzZWQiCiAgKQogIAogIApgYGAK