Overview
Out of a total of 132,846 EEBO records, 60,227 (45.34%) are in EEBO-TCP (but 66 EEBO records have multiple TCP ids).
Out of the 132,846 EEBO records, 6,802 (5.12%) could not be matched to an ESTC record and will be left out of the analysis. On the other hand, 7,373 EEBO records (5.55%) were matched to more than one ESTC record, possibly causing bias.
Out of the 60,327 EEBO-TCP records, 1,143 (1.89%) could not be matched to an ESTC record and will be left out of the analysis. On the other hand, 3,269 EEBO-TCP records (5.42%) were matched to more than one ESTC record, possibly causing bias.
In the analysis, only ESTC records with publication years in the range [1474,1700] have been included. This results in the exclusion of 4,862 (4.17%) ESTC records that have representation in EEBO, possibly causing bias. 2,119 (3.41%) of the ESTC records with representation in EEBO-TCP are removed due to this filtering condition.
In the end, our working dataset consists of 132,412 ESTC records, of which 111,816 (84.45%) we estimate to have representation in EEBO, and 60,095 (45.38%) to have representation in EEBO-TCP.
Publication type analysis
library(ggbeeswarm)
bind_rows(
df %>% mutate(group = "Editions"),
df %>% group_by(work_id,type,first_publication_year,publication_year) %>%
summarize(in_eebo=any(in_eebo),in_eebo_tcp=any(in_eebo_tcp),.groups="drop") %>%
mutate(group = "Works",edition_type=if_else(publication_year==first_publication_year,"First year work","Later work"))
) %>%
mutate(edition_type=fct_relevel(edition_type,"Singular","First year work","Later work","First year edition","Later edition")) %>%
filter(type %in% c("Book","Pamphlet")) %>%
group_by(publication_year, edition_type, group, type, in_eebo) %>%
tally() %>%
mutate(prop = n / sum(n), tn = sum(n)) %>%
filter(in_eebo) %>%
ggplot(aes(x = type, y = prop, group = edition_type, color = edition_type)) +
geom_quasirandom(aes(size = tn), dodge = 1.0) +
stat_summary(aes(group = edition_type), position = position_dodge(width = 1.0), fun = median, fun.min = median, fun.max = median, geom = "crossbar", width = 0.5, color = "red") +
theme_hsci_discrete() +
xlab(NULL) +
ylab("EEBO coverage") +
scale_y_continuous(labels = scales::percent_format(accuracy = 1), breaks = seq(0, 1, by = 0.05)) +
scale_size(breaks = c(250, 500, 1500), range = c(0.1, 8.0)) +
theme(legend.justification = c(0, 0), legend.position = c(0.02, 0.02), legend.background = element_blank(), legend.box.just = "bottom", legend.key = element_blank(), legend.box = "horizontal") +
labs(color = "Representation type", size = "Count") +
guides(shape = "none")

library(ggbeeswarm)
bind_rows(
df %>% mutate(group = "Editions"),
df %>% group_by(work_id,type,first_publication_year,publication_year) %>%
summarize(in_eebo=any(in_eebo),in_eebo_tcp=any(in_eebo_tcp),.groups="drop") %>%
mutate(group = "Works",edition_type=if_else(publication_year==first_publication_year,"First year work","Later work"))
) %>%
mutate(edition_type=fct_relevel(edition_type,"Singular","First year work","Later work","First year edition","Later edition")) %>%
filter(type %in% c("Book","Pamphlet")) %>%
group_by(publication_year, edition_type, group, type, in_eebo_tcp) %>%
tally() %>%
mutate(prop = n / sum(n), tn = sum(n)) %>%
filter(in_eebo_tcp) %>%
ggplot(aes(x = type, y = prop, group = edition_type, color = edition_type)) +
geom_quasirandom(aes(size = tn), dodge = 1.0) +
stat_summary(aes(group = edition_type), position = position_dodge(width = 1.0), fun = median, fun.min = median, fun.max = median, geom = "crossbar", width = 0.5, color = "red") +
theme_hsci_discrete() +
xlab(NULL) +
ylab("EEBO-TCP coverage") +
scale_y_continuous(labels = scales::percent_format(accuracy = 1), breaks = seq(0, 1, by = 0.05)) +
scale_size(breaks = c(250, 500, 1500), range = c(0.1, 8.0)) +
theme(legend.justification = c(0, 0), legend.position = c(0.02, 0.02), legend.background = element_blank(), legend.box.just = "bottom", legend.key = element_blank(), legend.box = "horizontal") +
labs(color = "Representation type", size = "Count") +
guides(shape = "none")

Edition-level temporal overview
df %>% mutate(g = case_when(
!certain ~ "Uncertain dating",
in_eebo_tcp ~ "In EEBO-TCP",
in_eebo ~ "In EEBO",
T ~ "ESTC total",
)) %>%
ggplot(aes(x = publication_year, fill = fct_relevel(g, "Uncertain dating", "ESTC total", "In EEBO","In EEBO-TCP"))) +
geom_bar(width = 1) +
theme_hsci_discrete() +
scale_x_continuous(breaks = seq(1000, 2000, by = 20)) +
scale_y_continuous(breaks = seq(0, 10000, by = 1000)) +
xlab("Year") +
ylab("ESTC entries") +
theme(legend.justification = c(0, 1), legend.position = c(0.05, 0.95), legend.background = element_blank(), legend.key = element_blank()) +
labs(fill = NULL) +
guides(fill = guide_legend(reverse = TRUE))

df %>% filter(certain) %>% mutate(g = case_when(
in_eebo_tcp ~ "In EEBO-TCP",
in_eebo ~ "In EEBO",
T ~ "Not in EEBO",
)) %>%
ggplot(aes(x = publication_year, fill = fct_relevel(g, "Not in EEBO", "In EEBO","In EEBO-TCP"))) +
geom_bar(width = 1,position='fill') +
theme_hsci_discrete() +
scale_x_continuous(breaks = seq(1000, 2000, by = 20)) +
scale_y_continuous(breaks = seq(0, 1, by = 0.1),labels=scales::percent_format(accuracy=1)) +
xlab("Year") +
ylab("Proportion of ESTC entries") +
theme(legend.justification = c(1, 0), legend.position = c(0.94, 0.08), legend.key = element_blank()) +
labs(fill = NULL) +
guides(fill = guide_legend(reverse = TRUE))

Work-level temporal overview
df %>%
filter(first_publication_year>1474) %>%
group_by(work_id,first_publication_year) %>%
summarize(in_eebo=any(in_eebo),in_eebo_tcp=any(in_eebo_tcp),certain=any(first_year_publication & certain),.groups="drop") %>%
mutate(g = case_when(
!certain ~ "Uncertain dating",
in_eebo_tcp ~ "In EEBO-TCP",
in_eebo ~ "In EEBO",
T ~ "ESTC total",
)) %>%
ggplot(aes(x = first_publication_year, fill = fct_relevel(g, "Uncertain dating", "ESTC total", "In EEBO","In EEBO-TCP"))) +
geom_bar(width = 1) +
theme_hsci_discrete() +
scale_x_continuous(breaks = seq(1000, 2000, by = 20)) +
scale_y_continuous(breaks = seq(0, 10000, by = 1000)) +
xlab("Year") +
ylab("ESTC entries") +
theme(legend.justification = c(0, 1), legend.position = c(0.05, 0.95), legend.background = element_blank(), legend.key = element_blank()) +
labs(fill = NULL) +
guides(fill = guide_legend(reverse = TRUE))

df %>%
filter(first_publication_year>1474) %>%
group_by(work_id,first_publication_year) %>%
summarize(in_eebo=any(in_eebo),in_eebo_tcp=any(in_eebo_tcp),.groups="drop") %>%
mutate(g = case_when(
in_eebo_tcp ~ "In EEBO-TCP",
in_eebo ~ "In EEBO",
T ~ "Not in EEBO",
)) %>%
ggplot(aes(x = first_publication_year, fill = fct_relevel(g, "Not in EEBO", "In EEBO","In EEBO-TCP"))) +
geom_bar(width = 1,position='fill') +
theme_hsci_discrete() +
scale_x_continuous(breaks = seq(1000, 2000, by = 20)) +
scale_y_continuous(breaks = seq(0, 1, by = 0.1),labels=scales::percent_format(accuracy=1)) +
xlab("Year of first publication") +
ylab("Proportion of ESTC works") +
theme(legend.justification = c(1, 0), legend.position = c(0.94, 0.08), legend.key = element_blank()) +
labs(fill = NULL) +
guides(fill = guide_legend(reverse = TRUE))

Document type coverage through time
bind_rows(
df %>% mutate(group = "Editions",type=recode(type,"Book"="Book (edition-level)","Pamphlet"="Pamphlet (edition-level)")),
df %>% group_by(work_id,type,first_publication_year,publication_year) %>%
summarize(in_eebo=any(in_eebo),in_eebo_tcp=any(in_eebo_tcp),certain=any(first_year_publication & certain),.groups="drop") %>%
mutate(group = "Works")
) %>%
mutate(type=fct_relevel(type,"Pamphlet (edition-level)","Book (edition-level)","Pamphlet","Book")) %>%
filter(certain) %>%
filter(!is.na(type),type!="In-between") %>%
group_by(publication_year, type, in_eebo) %>%
tally() %>%
mutate(prop = n / sum(n), tn = sum(n)) %>%
filter(in_eebo) %>%
ggplot(aes(x = publication_year, y = prop, color = type)) +
geom_smooth(aes(weight = n, fill = type), span = 0.3) +
geom_point(color = "gray", shape = 21, aes(size = tn)) +
geom_point(aes(size = n)) +
theme_hsci_discrete() +
scale_x_continuous(breaks = seq(1000, 2000, by = 20)) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1), breaks = seq(0, 1, by = 0.05)) +
xlab("Year") +
ylab("EEBO coverage") +
theme(legend.justification = c(0, 0), legend.box.just = "bottom", legend.position = c(0.05, 0.02), legend.background = element_blank(), legend.key = element_blank(), legend.box = "horizontal") +
labs(color = NULL, size = NULL, shape = NULL, fill = NULL) +
scale_size(breaks = c(500, 2000, 3500), range = c(0.1, 8.0))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'

bind_rows(
df %>% mutate(group = "Editions",type=recode(type,"Book"="Book (edition-level)","Pamphlet"="Pamphlet (edition-level)")),
df %>% group_by(work_id,type,first_publication_year,publication_year) %>%
summarize(in_eebo=any(in_eebo),in_eebo_tcp=any(in_eebo_tcp),certain=any(first_year_publication & certain),.groups="drop") %>%
mutate(group = "Works")
) %>%
mutate(type=fct_relevel(type,"Pamphlet (edition-level)","Book (edition-level)","Pamphlet","Book")) %>%
filter(certain) %>%
filter(!is.na(type),type!="In-between") %>%
group_by(publication_year, type, in_eebo_tcp) %>%
tally() %>%
mutate(prop = n / sum(n), tn = sum(n)) %>%
filter(in_eebo_tcp) %>%
ggplot(aes(x = publication_year, y = prop, color = type)) +
geom_smooth(aes(weight = n, fill = type), span = 0.3) +
geom_point(color = "gray", shape = 21, aes(size = tn)) +
geom_point(aes(size = n)) +
theme_hsci_discrete() +
scale_x_continuous(breaks = seq(1000, 2000, by = 20)) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1), breaks = seq(0, 1, by = 0.05)) +
xlab("Year") +
ylab("EEBO-TCP coverage") +
theme(legend.justification = c(0, 0), legend.box.just = "bottom", legend.position = c(0.05, 0.02), legend.background = element_blank(), legend.key = element_blank(), legend.box = "horizontal") +
labs(color = NULL, size = NULL, shape = NULL, fill = NULL) +
scale_size(breaks = c(500, 2000, 3500), range = c(0.1, 8.0))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'

Topical coverage EEBO-TCP vs EEBO
eebo_genres %>%
inner_join(eebo,by=c("eebo_id")) %>%
inner_join(estc_core,by=c("estc_id")) %>%
group_by(work_id,genre) %>%
summarize(in_eebo_tcp=any(!is.na(eebo_tcp_id)),.groups="drop") %>%
count(genre,in_eebo_tcp) %>%
group_by(genre) %>%
mutate(prop=n/sum(n)) %>%
ungroup() %>%
filter(in_eebo_tcp) %>%
mutate(genre=fct_reorder(genre,prop)) %>%
ggplot(aes(x=genre,y=prop)) +
geom_col() +
theme_hsci_discrete() +
scale_y_continuous(labels=scales::percent_format(accuracy=1)) +
xlab("Genre") +
ylab("Coverage in EEBO-TCP by work") +
coord_flip()

eebo_genres %>%
left_join(eebo %>%
filter(!is.na(eebo_tcp_id)) %>%
distinct(eebo_id) %>%
mutate(in_eebo_tcp=T),by=c("eebo_id")) %>%
count(genre,in_eebo_tcp) %>%
group_by(genre) %>%
mutate(prop=n/sum(n)) %>%
ungroup() %>%
filter(in_eebo_tcp) %>%
mutate(genre=fct_reorder(genre,prop)) %>%
ggplot(aes(x=genre,y=prop)) +
geom_col() +
theme_hsci_discrete() +
scale_y_continuous(labels=scales::percent_format(accuracy=1)) +
xlab("Genre") +
ylab("Coverage in EEBO-TCP by edition") +
coord_flip()

LS0tCnRpdGxlOiAiRUVCTy9FU1RDIGFuYWx5c2lzIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0b2M6IHllcwotLS0KCmBgYHtyIHNldHVwLGVjaG89Rn0Ka25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSBoZXJlOjpoZXJlKCkpCmBgYAoKCmBgYHtyLGluY2x1ZGU9Rn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoaGVyZSkKcGFrOjpwa2dfaW5zdGFsbCgiaHNjaS1yL2dnaHNjaSIpCmxpYnJhcnkoZ2doc2NpKQpgYGAKCmBgYHtyLGluY2x1ZGU9Rn0KcCA8LSBmdW5jdGlvbihudW1iZXIpIHsKICByZXR1cm4oZm9ybWF0KG51bWJlciwgc2NpZW50aWZpYyA9IEZBTFNFLCBiaWcubWFyayA9ICIsIikpCn0KcHAgPC0gZnVuY3Rpb24ocGVyY2VudGFnZSxhY2N1cmFjeT0wLjAxKSB7CiAgcmV0dXJuKHNjYWxlczo6cGVyY2VudChwZXJjZW50YWdlLCBhY2N1cmFjeSA9IGFjY3VyYWN5KSkKfQpgYGAKCmBgYHtyLGluY2x1ZGU9Rn0KcGFrOjpwa2dfaW5zdGFsbCgiQ09NSElTL2VzdGNyIikKbGlicmFyeShlc3RjcikKbG9hZF9lc3RjKCkKcm0oZXN0Y19lY2NvX2VlYm9fbGlua3MpCmBgYAoKYGBge3IsaW5jbHVkZT1GfQplZWJvIDwtIHJlYWRfdHN2KGhlcmUoImRhdGEvaW5wdXQvZWViby9lZWJvLnRzdiIpLGNvbF90eXBlcz1jb2xzKGVlYm9faWQ9J2MnKSkKZWVib19rZXltYXBwZWQgPC0gcmVhZF90c3YoaGVyZSgiZGF0YS9pbnB1dC9lZWJvL2VlYm8ta2V5bWFwcGVkLnRzdiIpLGNvbF90eXBlcz1jb2xzKGVlYm9faWQ9J2MnKSkKZWVibyA8LSBlZWJvICU+JSAKICBhbnRpX2pvaW4oZWVib19rZXltYXBwZWQsYnk9YygiZWVib19pZCIsImVlYm9fdGNwX2lkIikpICU+JSAKICBiaW5kX3Jvd3MoZWVib19rZXltYXBwZWQpCnJtKGVlYm9fa2V5bWFwcGVkKQplZWJvX3RjcCA8LSBlZWJvICU+JSBmaWx0ZXIoIWlzLm5hKGVlYm9fdGNwX2lkKSkKZXN0Y19jb3JlIDwtIGVzdGNfY29yZSAlPiUgbXV0YXRlKGluX2VlYm89ZXN0Y19pZCAlaW4lIGVlYm8kZXN0Y19pZCxpbl9lZWJvX3RjcD1lc3RjX2lkICVpbiUgZWVib190Y3AkZXN0Y19pZCkKZWVib19nZW5yZXMgPC0gcmVhZF90c3YoaGVyZSgiZGF0YS9pbnB1dC9lZWJvL2VlYm8tZ2VucmVzLnRzdiIpKQpgYGAKCmBgYHtyLGluY2x1ZGU9Rn0KZXN0Y19jb3JlIDwtIGVzdGNfY29yZSAlPiUKICBncm91cF9ieSh3b3JrX2lkKSAlPiUKICBtdXRhdGUoZmlyc3RfcHVibGljYXRpb25feWVhciA9IG1pbihwdWJsaWNhdGlvbl95ZWFyKSwgZWRpdGlvbnM9bigpKSAlPiUKICBtdXRhdGUoZmlyc3RfeWVhcl9wdWJsaWNhdGlvbiA9IGZpcnN0X3B1YmxpY2F0aW9uX3llYXIgPT0gcHVibGljYXRpb25feWVhcikgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShlZGl0aW9uX3R5cGU9aWZfZWxzZShlZGl0aW9ucz09MSwiU2luZ3VsYXIiLGlmX2Vsc2UoZmlyc3RfeWVhcl9wdWJsaWNhdGlvbiwiRmlyc3QgeWVhciBlZGl0aW9uIiwiTGF0ZXIgZWRpdGlvbiIpKSkgJT4lCiAgbXV0YXRlKAogICAgY2VydGFpbiA9ICF1bmNlcnRhaW4gJiAhY2lyY2EgJiAhcmFuZ2UsCiAgICB0eXBlID0gY2FzZV93aGVuKAogICAgICBwYWdlY291bnQgPD0gMzIgfiAiUGFtcGhsZXQiLAogICAgICBwYWdlY291bnQgPiAzMiAmIHBhZ2Vjb3VudCA8IDEyOCB+ICJJbi1iZXR3ZWVuIiwKICAgICAgcGFnZWNvdW50ID49IDEyOCB+ICJCb29rIgogICAgKQogICkKCmRmIDwtIGVzdGNfY29yZSAlPiUgCiAgZmlsdGVyKHB1YmxpY2F0aW9uX3llYXIgPj0gMTQ3NCwgcHVibGljYXRpb25feWVhciA8IDE3MDApCiAgCmBgYAoKCmBgYHtyLGluY2x1ZGU9Rn0KbGlicmFyeShhc3NlcnR0aGF0KQpuX2VlYm9faWRzIDwtIGVlYm8gJT4lIGRpc3RpbmN0KGVlYm9faWQpICU+JSBucm93KCkKbl9lZWJvX3RjcF9pZHMgPC0gZWVib190Y3AgJT4lIGRpc3RpbmN0KGVlYm9fdGNwX2lkKSAlPiUgbnJvdygpCm5fZWVib19pZHNfaW5fZWVib190Y3AgPC0gZWVibyAlPiUgZmlsdGVyKCFpcy5uYShlZWJvX3RjcF9pZCkpICU+JSBkaXN0aW5jdChlZWJvX2lkKSAlPiUgbnJvdygpCmFzc2VydF90aGF0KGVlYm8gJT4lIGZpbHRlcighaXMubmEoZWVib190Y3BfaWQpKSAlPiUgZGlzdGluY3QoZWVib19pZCxlZWJvX3RjcF9pZCkgJT4lIGNvdW50KGVlYm9fdGNwX2lkKSAlPiUgZmlsdGVyKG4+MSkgJT4lIG5yb3coKT09MCkKbl9lZWJvX2lkc19tdWx0aW1hcHBlZF90b19lZWJvX3RjcCA8LSBlZWJvICU+JSBmaWx0ZXIoIWlzLm5hKGVlYm9fdGNwX2lkKSkgJT4lIGRpc3RpbmN0KGVlYm9faWQsZWVib190Y3BfaWQpICU+JSBjb3VudChlZWJvX2lkKSAlPiUgZmlsdGVyKG4+MSkgJT4lIG5yb3coKQoKbl9lZWJvX2lkc19ub3RfaW5fZXN0YyA8LSBlZWJvICU+JSBmaWx0ZXIoaXMubmEoZXN0Y19pZCkpICU+JSBkaXN0aW5jdChlZWJvX2lkKSAlPiUgbnJvdygpCm5fZWVib190Y3BfaWRzX25vdF9pbl9lc3RjIDwtIGVlYm9fdGNwICU+JSBmaWx0ZXIoaXMubmEoZXN0Y19pZCkpICU+JSBkaXN0aW5jdChlZWJvX3RjcF9pZCkgJT4lIG5yb3coKQoKbl9lZWJvX2lkc19tdWx0aW1hcHBlZF90b19lc3RjIDwtIGVlYm8gJT4lIGZpbHRlcighaXMubmEoZXN0Y19pZCkpICU+JSBkaXN0aW5jdChlZWJvX2lkLGVzdGNfaWQpICU+JSBjb3VudChlZWJvX2lkKSAlPiUgZmlsdGVyKG4+MSkgJT4lIG5yb3coKQpuX2VlYm9fdGNwX2lkc19tdWx0aW1hcHBlZF90b19lc3RjIDwtIGVlYm9fdGNwJT4lIGZpbHRlcighaXMubmEoZXN0Y19pZCkpICU+JSBkaXN0aW5jdChlZWJvX3RjcF9pZCxlc3RjX2lkKSAlPiUgY291bnQoZWVib190Y3BfaWQpICU+JSBmaWx0ZXIobj4xKSAlPiUgbnJvdygpCgpuX2VzdGNfaWRzX3dpdGhfZWVib19pZHMgPC0gZXN0Y19jb3JlICU+JSBmaWx0ZXIoaW5fZWVibykgJT4lIG5yb3coKQpuX2VzdGNfaWRzX2luX2RmX3dpdGhfZWVib19pZHMgPC0gZGYgJT4lIGZpbHRlcihpbl9lZWJvKSAlPiUgbnJvdygpCm5fZXN0Y19pZHNfd2l0aF9lZWJvX3RjcF9pZHMgPC0gZXN0Y19jb3JlICU+JSBmaWx0ZXIoaW5fZWVib190Y3ApICU+JSBucm93KCkKbl9lc3RjX2lkc19pbl9kZl93aXRoX2VlYm9fdGNwX2lkcyA8LSBkZiAlPiUgZmlsdGVyKGluX2VlYm9fdGNwKSAlPiUgbnJvdygpCgpuX2VzdGNfaWRzX2luX2RmIDwtIGRmICU+JSBucm93KCkKYGBgCgojIE92ZXJ2aWV3CgpPdXQgb2YgYSB0b3RhbCBvZiBgciBwKG5fZWVib19pZHMpYCBFRUJPIHJlY29yZHMsIGByIHAobl9lZWJvX2lkc19pbl9lZWJvX3RjcClgIChgciBwcChuX2VlYm9faWRzX2luX2VlYm9fdGNwL25fZWVib19pZHMpYCkgYXJlIGluIEVFQk8tVENQIChidXQgYHIgcChuX2VlYm9faWRzX211bHRpbWFwcGVkX3RvX2VlYm9fdGNwKWAgRUVCTyByZWNvcmRzIGhhdmUgbXVsdGlwbGUgVENQIGlkcykuCgpPdXQgb2YgdGhlIGByIHAobl9lZWJvX2lkcylgIEVFQk8gcmVjb3JkcywgYHIgcChuX2VlYm9faWRzX25vdF9pbl9lc3RjKWAgIChgciBwcChuX2VlYm9faWRzX25vdF9pbl9lc3RjL25fZWVib19pZHMpYCkgY291bGQgbm90IGJlIG1hdGNoZWQgdG8gYW4gRVNUQyByZWNvcmQgYW5kIHdpbGwgYmUgbGVmdCBvdXQgb2YgdGhlIGFuYWx5c2lzLiBPbiB0aGUgb3RoZXIgaGFuZCwgYHIgcChuX2VlYm9faWRzX211bHRpbWFwcGVkX3RvX2VzdGMpYCBFRUJPIHJlY29yZHMgKGByIHBwKG5fZWVib19pZHNfbXVsdGltYXBwZWRfdG9fZXN0Yy9uX2VlYm9faWRzKWApIHdlcmUgbWF0Y2hlZCB0byBtb3JlIHRoYW4gb25lIEVTVEMgcmVjb3JkLCBwb3NzaWJseSBjYXVzaW5nIGJpYXMuCgpPdXQgb2YgdGhlIGByIHAobl9lZWJvX3RjcF9pZHMpYCBFRUJPLVRDUCByZWNvcmRzLCBgciBwKG5fZWVib190Y3BfaWRzX25vdF9pbl9lc3RjKWAgKGByIHBwKG5fZWVib190Y3BfaWRzX25vdF9pbl9lc3RjL25fZWVib190Y3BfaWRzKWApIGNvdWxkIG5vdCBiZSBtYXRjaGVkIHRvIGFuIEVTVEMgcmVjb3JkIGFuZCB3aWxsIGJlIGxlZnQgb3V0IG9mIHRoZSBhbmFseXNpcy4gT24gdGhlIG90aGVyIGhhbmQsIGByIHAobl9lZWJvX3RjcF9pZHNfbXVsdGltYXBwZWRfdG9fZXN0YylgIEVFQk8tVENQIHJlY29yZHMgKGByIHBwKG5fZWVib190Y3BfaWRzX211bHRpbWFwcGVkX3RvX2VzdGMvbl9lZWJvX3RjcF9pZHMpYCkgd2VyZSBtYXRjaGVkIHRvIG1vcmUgdGhhbiBvbmUgRVNUQyByZWNvcmQsIHBvc3NpYmx5IGNhdXNpbmcgYmlhcy4KCkluIHRoZSBhbmFseXNpcywgb25seSBFU1RDIHJlY29yZHMgd2l0aCBwdWJsaWNhdGlvbiB5ZWFycyBpbiB0aGUgcmFuZ2UgWzE0NzQsMTcwMF0gaGF2ZSBiZWVuIGluY2x1ZGVkLiBUaGlzIHJlc3VsdHMgaW4gdGhlIGV4Y2x1c2lvbiBvZiBgciBwKG5fZXN0Y19pZHNfd2l0aF9lZWJvX2lkcy1uX2VzdGNfaWRzX2luX2RmX3dpdGhfZWVib19pZHMpYCAoYHIgcHAoKG5fZXN0Y19pZHNfd2l0aF9lZWJvX2lkcy1uX2VzdGNfaWRzX2luX2RmX3dpdGhfZWVib19pZHMpL25fZXN0Y19pZHNfd2l0aF9lZWJvX2lkcylgKSBFU1RDIHJlY29yZHMgdGhhdCBoYXZlIHJlcHJlc2VudGF0aW9uIGluIEVFQk8sIHBvc3NpYmx5IGNhdXNpbmcgYmlhcy4gYHIgcChuX2VzdGNfaWRzX3dpdGhfZWVib190Y3BfaWRzLW5fZXN0Y19pZHNfaW5fZGZfd2l0aF9lZWJvX3RjcF9pZHMpYCAoYHIgcHAoKG5fZXN0Y19pZHNfd2l0aF9lZWJvX3RjcF9pZHMtbl9lc3RjX2lkc19pbl9kZl93aXRoX2VlYm9fdGNwX2lkcykvbl9lc3RjX2lkc193aXRoX2VlYm9fdGNwX2lkcylgKSBvZiB0aGUgRVNUQyByZWNvcmRzIHdpdGggcmVwcmVzZW50YXRpb24gaW4gRUVCTy1UQ1AgYXJlIHJlbW92ZWQgZHVlIHRvIHRoaXMgZmlsdGVyaW5nIGNvbmRpdGlvbi4KCkluIHRoZSBlbmQsIG91ciB3b3JraW5nIGRhdGFzZXQgY29uc2lzdHMgb2YgYHIgcChuX2VzdGNfaWRzX2luX2RmKWAgRVNUQyByZWNvcmRzLCBvZiB3aGljaCBgciBwKG5fZXN0Y19pZHNfaW5fZGZfd2l0aF9lZWJvX2lkcylgIChgciBwcChuX2VzdGNfaWRzX2luX2RmX3dpdGhfZWVib19pZHMvbl9lc3RjX2lkc19pbl9kZilgKSB3ZSBlc3RpbWF0ZSB0byBoYXZlIHJlcHJlc2VudGF0aW9uIGluIEVFQk8sIGFuZCBgciBwKG5fZXN0Y19pZHNfaW5fZGZfd2l0aF9lZWJvX3RjcF9pZHMpYCAoYHIgcHAobl9lc3RjX2lkc19pbl9kZl93aXRoX2VlYm9fdGNwX2lkcy9uX2VzdGNfaWRzX2luX2RmKWApIHRvIGhhdmUgcmVwcmVzZW50YXRpb24gaW4gRUVCTy1UQ1AuCgojIFB1YmxpY2F0aW9uIHR5cGUgYW5hbHlzaXMKCmBgYHtyfQpsaWJyYXJ5KGdnYmVlc3dhcm0pCmJpbmRfcm93cygKICBkZiAlPiUgbXV0YXRlKGdyb3VwID0gIkVkaXRpb25zIiksCiAgZGYgJT4lIGdyb3VwX2J5KHdvcmtfaWQsdHlwZSxmaXJzdF9wdWJsaWNhdGlvbl95ZWFyLHB1YmxpY2F0aW9uX3llYXIpICU+JQogICAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksLmdyb3Vwcz0iZHJvcCIpICU+JQogICAgbXV0YXRlKGdyb3VwID0gIldvcmtzIixlZGl0aW9uX3R5cGU9aWZfZWxzZShwdWJsaWNhdGlvbl95ZWFyPT1maXJzdF9wdWJsaWNhdGlvbl95ZWFyLCJGaXJzdCB5ZWFyIHdvcmsiLCJMYXRlciB3b3JrIikpCikgJT4lCiAgbXV0YXRlKGVkaXRpb25fdHlwZT1mY3RfcmVsZXZlbChlZGl0aW9uX3R5cGUsIlNpbmd1bGFyIiwiRmlyc3QgeWVhciB3b3JrIiwiTGF0ZXIgd29yayIsIkZpcnN0IHllYXIgZWRpdGlvbiIsIkxhdGVyIGVkaXRpb24iKSkgJT4lCiAgZmlsdGVyKHR5cGUgJWluJSBjKCJCb29rIiwiUGFtcGhsZXQiKSkgJT4lCiAgZ3JvdXBfYnkocHVibGljYXRpb25feWVhciwgZWRpdGlvbl90eXBlLCBncm91cCwgdHlwZSwgaW5fZWVibykgJT4lIAogIHRhbGx5KCkgJT4lIAogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSwgdG4gPSBzdW0obikpICU+JSAKICBmaWx0ZXIoaW5fZWVibykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdHlwZSwgeSA9IHByb3AsIGdyb3VwID0gZWRpdGlvbl90eXBlLCBjb2xvciA9IGVkaXRpb25fdHlwZSkpICsKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyhzaXplID0gdG4pLCBkb2RnZSA9IDEuMCkgKwogIHN0YXRfc3VtbWFyeShhZXMoZ3JvdXAgPSBlZGl0aW9uX3R5cGUpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMS4wKSwgZnVuID0gbWVkaWFuLCBmdW4ubWluID0gbWVkaWFuLCBmdW4ubWF4ID0gbWVkaWFuLCBnZW9tID0gImNyb3NzYmFyIiwgd2lkdGggPSAwLjUsIGNvbG9yID0gInJlZCIpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHhsYWIoTlVMTCkgKwogIHlsYWIoIkVFQk8gY292ZXJhZ2UiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4wNSkpICsKICBzY2FsZV9zaXplKGJyZWFrcyA9IGMoMjUwLCA1MDAsIDE1MDApLCByYW5nZSA9IGMoMC4xLCA4LjApKSArCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDApLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDIsIDAuMDIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmJveC5qdXN0ID0gImJvdHRvbSIsIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICsKICBsYWJzKGNvbG9yID0gIlJlcHJlc2VudGF0aW9uIHR5cGUiLCBzaXplID0gIkNvdW50IikgKwogIGd1aWRlcyhzaGFwZSA9ICJub25lIikKYGBgCgpgYGB7cn0KbGlicmFyeShnZ2JlZXN3YXJtKQpiaW5kX3Jvd3MoCiAgZGYgJT4lIG11dGF0ZShncm91cCA9ICJFZGl0aW9ucyIpLAogIGRmICU+JSBncm91cF9ieSh3b3JrX2lkLHR5cGUsZmlyc3RfcHVibGljYXRpb25feWVhcixwdWJsaWNhdGlvbl95ZWFyKSAlPiUKICAgIHN1bW1hcml6ZShpbl9lZWJvPWFueShpbl9lZWJvKSxpbl9lZWJvX3RjcD1hbnkoaW5fZWVib190Y3ApLC5ncm91cHM9ImRyb3AiKSAlPiUKICAgIG11dGF0ZShncm91cCA9ICJXb3JrcyIsZWRpdGlvbl90eXBlPWlmX2Vsc2UocHVibGljYXRpb25feWVhcj09Zmlyc3RfcHVibGljYXRpb25feWVhciwiRmlyc3QgeWVhciB3b3JrIiwiTGF0ZXIgd29yayIpKQopICU+JQogIG11dGF0ZShlZGl0aW9uX3R5cGU9ZmN0X3JlbGV2ZWwoZWRpdGlvbl90eXBlLCJTaW5ndWxhciIsIkZpcnN0IHllYXIgd29yayIsIkxhdGVyIHdvcmsiLCJGaXJzdCB5ZWFyIGVkaXRpb24iLCJMYXRlciBlZGl0aW9uIikpICU+JQogIGZpbHRlcih0eXBlICVpbiUgYygiQm9vayIsIlBhbXBobGV0IikpICU+JQogIGdyb3VwX2J5KHB1YmxpY2F0aW9uX3llYXIsIGVkaXRpb25fdHlwZSwgZ3JvdXAsIHR5cGUsIGluX2VlYm9fdGNwKSAlPiUgCiAgdGFsbHkoKSAlPiUgCiAgbXV0YXRlKHByb3AgPSBuIC8gc3VtKG4pLCB0biA9IHN1bShuKSkgJT4lIAogIGZpbHRlcihpbl9lZWJvX3RjcCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdHlwZSwgeSA9IHByb3AsIGdyb3VwID0gZWRpdGlvbl90eXBlLCBjb2xvciA9IGVkaXRpb25fdHlwZSkpICsKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyhzaXplID0gdG4pLCBkb2RnZSA9IDEuMCkgKwogIHN0YXRfc3VtbWFyeShhZXMoZ3JvdXAgPSBlZGl0aW9uX3R5cGUpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMS4wKSwgZnVuID0gbWVkaWFuLCBmdW4ubWluID0gbWVkaWFuLCBmdW4ubWF4ID0gbWVkaWFuLCBnZW9tID0gImNyb3NzYmFyIiwgd2lkdGggPSAwLjUsIGNvbG9yID0gInJlZCIpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHhsYWIoTlVMTCkgKwogIHlsYWIoIkVFQk8tVENQIGNvdmVyYWdlIikgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksIGJyZWFrcyA9IHNlcSgwLCAxLCBieSA9IDAuMDUpKSArCiAgc2NhbGVfc2l6ZShicmVha3MgPSBjKDI1MCwgNTAwLCAxNTAwKSwgcmFuZ2UgPSBjKDAuMSwgOC4wKSkgKwogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAwKSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjAyLCAwLjAyKSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5ib3guanVzdCA9ICJib3R0b20iLCBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQuYm94ID0gImhvcml6b250YWwiKSArCiAgbGFicyhjb2xvciA9ICJSZXByZXNlbnRhdGlvbiB0eXBlIiwgc2l6ZSA9ICJDb3VudCIpICsKICBndWlkZXMoc2hhcGUgPSAibm9uZSIpCmBgYAoKIyBFZGl0aW9uLWxldmVsIHRlbXBvcmFsIG92ZXJ2aWV3CgpgYGB7cixmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gM30KZGYgJT4lICBtdXRhdGUoZyA9IGNhc2Vfd2hlbigKICAhY2VydGFpbiB+ICJVbmNlcnRhaW4gZGF0aW5nIiwKICBpbl9lZWJvX3RjcCAgfiAiSW4gRUVCTy1UQ1AiLAogIGluX2VlYm8gfiAiSW4gRUVCTyIsCiAgVCB+ICJFU1RDIHRvdGFsIiwKKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcHVibGljYXRpb25feWVhciwgZmlsbCA9IGZjdF9yZWxldmVsKGcsICJVbmNlcnRhaW4gZGF0aW5nIiwgIkVTVEMgdG90YWwiLCAiSW4gRUVCTyIsIkluIEVFQk8tVENQIikpKSArCiAgZ2VvbV9iYXIod2lkdGggPSAxKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwMDAsIDIwMDAsIGJ5ID0gMjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMDAwMCwgYnkgPSAxMDAwKSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRVNUQyBlbnRyaWVzIikgKwogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjA1LCAwLjk1KSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKGZpbGwgPSBOVUxMKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKQpgYGAKCmBgYHtyLGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSAzfQpkZiAlPiUgZmlsdGVyKGNlcnRhaW4pICU+JSBtdXRhdGUoZyA9IGNhc2Vfd2hlbigKICBpbl9lZWJvX3RjcCAgfiAiSW4gRUVCTy1UQ1AiLAogIGluX2VlYm8gfiAiSW4gRUVCTyIsCiAgVCB+ICJOb3QgaW4gRUVCTyIsCikpICU+JQogIGdncGxvdChhZXMoeCA9IHB1YmxpY2F0aW9uX3llYXIsIGZpbGwgPSBmY3RfcmVsZXZlbChnLCAiTm90IGluIEVFQk8iLCAiSW4gRUVCTyIsIkluIEVFQk8tVENQIikpKSArCiAgZ2VvbV9iYXIod2lkdGggPSAxLHBvc2l0aW9uPSdmaWxsJykgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMDAwLCAyMDAwLCBieSA9IDIwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjEpLGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5PTEpKSArCiAgeGxhYigiWWVhciIpICsKICB5bGFiKCJQcm9wb3J0aW9uIG9mIEVTVEMgZW50cmllcyIpICsKICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMCksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45NCwgMC4wOCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKGZpbGwgPSBOVUxMKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKQpgYGAKIyBXb3JrLWxldmVsIHRlbXBvcmFsIG92ZXJ2aWV3CgpgYGB7cn0KZGYgJT4lIAogIGZpbHRlcihmaXJzdF9wdWJsaWNhdGlvbl95ZWFyPjE0NzQpICU+JQogIGdyb3VwX2J5KHdvcmtfaWQsZmlyc3RfcHVibGljYXRpb25feWVhcikgJT4lCiAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksY2VydGFpbj1hbnkoZmlyc3RfeWVhcl9wdWJsaWNhdGlvbiAmIGNlcnRhaW4pLC5ncm91cHM9ImRyb3AiKSAlPiUgCiAgbXV0YXRlKGcgPSBjYXNlX3doZW4oCiAgICAhY2VydGFpbiB+ICJVbmNlcnRhaW4gZGF0aW5nIiwKICAgIGluX2VlYm9fdGNwICB+ICJJbiBFRUJPLVRDUCIsCiAgICBpbl9lZWJvIH4gIkluIEVFQk8iLAogICAgVCB+ICJFU1RDIHRvdGFsIiwKICApKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZmlyc3RfcHVibGljYXRpb25feWVhciwgZmlsbCA9IGZjdF9yZWxldmVsKGcsICJVbmNlcnRhaW4gZGF0aW5nIiwgIkVTVEMgdG90YWwiLCAiSW4gRUVCTyIsIkluIEVFQk8tVENQIikpKSArCiAgZ2VvbV9iYXIod2lkdGggPSAxKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwMDAsIDIwMDAsIGJ5ID0gMjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMDAwMCwgYnkgPSAxMDAwKSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRVNUQyBlbnRyaWVzIikgKwogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjA1LCAwLjk1KSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKGZpbGwgPSBOVUxMKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKQpgYGAKCgpgYGB7cn0KZGYgJT4lIAogIGZpbHRlcihmaXJzdF9wdWJsaWNhdGlvbl95ZWFyPjE0NzQpICU+JQogIGdyb3VwX2J5KHdvcmtfaWQsZmlyc3RfcHVibGljYXRpb25feWVhcikgJT4lCiAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksLmdyb3Vwcz0iZHJvcCIpICU+JQogIG11dGF0ZShnID0gY2FzZV93aGVuKAogIGluX2VlYm9fdGNwICB+ICJJbiBFRUJPLVRDUCIsCiAgaW5fZWVibyB+ICJJbiBFRUJPIiwKICBUIH4gIk5vdCBpbiBFRUJPIiwKKSkgJT4lICAKZ2dwbG90KGFlcyh4ID0gZmlyc3RfcHVibGljYXRpb25feWVhciwgZmlsbCA9IGZjdF9yZWxldmVsKGcsICJOb3QgaW4gRUVCTyIsICJJbiBFRUJPIiwiSW4gRUVCTy1UQ1AiKSkpICsKICBnZW9tX2Jhcih3aWR0aCA9IDEscG9zaXRpb249J2ZpbGwnKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwMDAsIDIwMDAsIGJ5ID0gMjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxLCBieSA9IDAuMSksbGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3k9MSkpICsKICB4bGFiKCJZZWFyIG9mIGZpcnN0IHB1YmxpY2F0aW9uIikgKwogIHlsYWIoIlByb3BvcnRpb24gb2YgRVNUQyB3b3JrcyIpICsKICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMCksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45NCwgMC4wOCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKGZpbGwgPSBOVUxMKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKSAgCmBgYAoKIyBEb2N1bWVudCB0eXBlIGNvdmVyYWdlIHRocm91Z2ggdGltZQoKYGBge3J9CmJpbmRfcm93cygKICBkZiAlPiUgbXV0YXRlKGdyb3VwID0gIkVkaXRpb25zIix0eXBlPXJlY29kZSh0eXBlLCJCb29rIj0iQm9vayAoZWRpdGlvbi1sZXZlbCkiLCJQYW1waGxldCI9IlBhbXBobGV0IChlZGl0aW9uLWxldmVsKSIpKSwKICBkZiAlPiUgZ3JvdXBfYnkod29ya19pZCx0eXBlLGZpcnN0X3B1YmxpY2F0aW9uX3llYXIscHVibGljYXRpb25feWVhcikgJT4lCiAgICBzdW1tYXJpemUoaW5fZWVibz1hbnkoaW5fZWVibyksaW5fZWVib190Y3A9YW55KGluX2VlYm9fdGNwKSxjZXJ0YWluPWFueShmaXJzdF95ZWFyX3B1YmxpY2F0aW9uICYgY2VydGFpbiksLmdyb3Vwcz0iZHJvcCIpICU+JQogICAgbXV0YXRlKGdyb3VwID0gIldvcmtzIikKKSAlPiUKICBtdXRhdGUodHlwZT1mY3RfcmVsZXZlbCh0eXBlLCJQYW1waGxldCAoZWRpdGlvbi1sZXZlbCkiLCJCb29rIChlZGl0aW9uLWxldmVsKSIsIlBhbXBobGV0IiwiQm9vayIpKSAlPiUKICBmaWx0ZXIoY2VydGFpbikgJT4lIAogIGZpbHRlcighaXMubmEodHlwZSksdHlwZSE9IkluLWJldHdlZW4iKSAlPiUgCiAgZ3JvdXBfYnkocHVibGljYXRpb25feWVhciwgdHlwZSwgaW5fZWVibykgJT4lIAogIHRhbGx5KCkgJT4lIAogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSwgdG4gPSBzdW0obikpICU+JSAKICBmaWx0ZXIoaW5fZWVibykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcHVibGljYXRpb25feWVhciwgeSA9IHByb3AsIGNvbG9yID0gdHlwZSkpICsKICBnZW9tX3Ntb290aChhZXMod2VpZ2h0ID0gbiwgZmlsbCA9IHR5cGUpLCBzcGFuID0gMC4zKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJncmF5Iiwgc2hhcGUgPSAyMSwgYWVzKHNpemUgPSB0bikpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gbikpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLCBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjA1KSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRUVCTyBjb3ZlcmFnZSIpICsKICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMCksIGxlZ2VuZC5ib3guanVzdCA9ICJib3R0b20iLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDUsIDAuMDIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIikgKwogIGxhYnMoY29sb3IgPSBOVUxMLCBzaXplID0gTlVMTCwgc2hhcGUgPSBOVUxMLCBmaWxsID0gTlVMTCkgKwogIHNjYWxlX3NpemUoYnJlYWtzID0gYyg1MDAsIDIwMDAsIDM1MDApLCByYW5nZSA9IGMoMC4xLCA4LjApKQpgYGAKCgpgYGB7cn0KYmluZF9yb3dzKAogIGRmICU+JSBtdXRhdGUoZ3JvdXAgPSAiRWRpdGlvbnMiLHR5cGU9cmVjb2RlKHR5cGUsIkJvb2siPSJCb29rIChlZGl0aW9uLWxldmVsKSIsIlBhbXBobGV0Ij0iUGFtcGhsZXQgKGVkaXRpb24tbGV2ZWwpIikpLAogIGRmICU+JSBncm91cF9ieSh3b3JrX2lkLHR5cGUsZmlyc3RfcHVibGljYXRpb25feWVhcixwdWJsaWNhdGlvbl95ZWFyKSAlPiUKICAgIHN1bW1hcml6ZShpbl9lZWJvPWFueShpbl9lZWJvKSxpbl9lZWJvX3RjcD1hbnkoaW5fZWVib190Y3ApLGNlcnRhaW49YW55KGZpcnN0X3llYXJfcHVibGljYXRpb24gJiBjZXJ0YWluKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgICBtdXRhdGUoZ3JvdXAgPSAiV29ya3MiKQopICU+JQogIG11dGF0ZSh0eXBlPWZjdF9yZWxldmVsKHR5cGUsIlBhbXBobGV0IChlZGl0aW9uLWxldmVsKSIsIkJvb2sgKGVkaXRpb24tbGV2ZWwpIiwiUGFtcGhsZXQiLCJCb29rIikpICU+JQogIGZpbHRlcihjZXJ0YWluKSAlPiUgCiAgZmlsdGVyKCFpcy5uYSh0eXBlKSx0eXBlIT0iSW4tYmV0d2VlbiIpICU+JSAKICBncm91cF9ieShwdWJsaWNhdGlvbl95ZWFyLCB0eXBlLCBpbl9lZWJvX3RjcCkgJT4lIAogIHRhbGx5KCkgJT4lIAogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSwgdG4gPSBzdW0obikpICU+JSAKICBmaWx0ZXIoaW5fZWVib190Y3ApICU+JQogIGdncGxvdChhZXMoeCA9IHB1YmxpY2F0aW9uX3llYXIsIHkgPSBwcm9wLCBjb2xvciA9IHR5cGUpKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHdlaWdodCA9IG4sIGZpbGwgPSB0eXBlKSwgc3BhbiA9IDAuMykgKwogIGdlb21fcG9pbnQoY29sb3IgPSAiZ3JheSIsIHNoYXBlID0gMjEsIGFlcyhzaXplID0gdG4pKSArCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IG4pKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwMDAsIDIwMDAsIGJ5ID0gMjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4wNSkpICsKICB4bGFiKCJZZWFyIikgKwogIHlsYWIoIkVFQk8tVENQIGNvdmVyYWdlIikgKwogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAwKSwgbGVnZW5kLmJveC5qdXN0ID0gImJvdHRvbSIsIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4wNSwgMC4wMiksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQuYm94ID0gImhvcml6b250YWwiKSArCiAgbGFicyhjb2xvciA9IE5VTEwsIHNpemUgPSBOVUxMLCBzaGFwZSA9IE5VTEwsIGZpbGwgPSBOVUxMKSArCiAgc2NhbGVfc2l6ZShicmVha3MgPSBjKDUwMCwgMjAwMCwgMzUwMCksIHJhbmdlID0gYygwLjEsIDguMCkpCmBgYAoKIyBUb3BpY2FsIGNvdmVyYWdlIEVFQk8tVENQIHZzIEVFQk8KCmBgYHtyfQplZWJvX2dlbnJlcyAlPiUgCiAgICBpbm5lcl9qb2luKGVlYm8sYnk9YygiZWVib19pZCIpKSAlPiUKICAgIGlubmVyX2pvaW4oZXN0Y19jb3JlLGJ5PWMoImVzdGNfaWQiKSkgJT4lCiAgZ3JvdXBfYnkod29ya19pZCxnZW5yZSkgJT4lCiAgc3VtbWFyaXplKGluX2VlYm9fdGNwPWFueSghaXMubmEoZWVib190Y3BfaWQpKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgY291bnQoZ2VucmUsaW5fZWVib190Y3ApICU+JSAKICBncm91cF9ieShnZW5yZSkgJT4lCiAgbXV0YXRlKHByb3A9bi9zdW0obikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIoaW5fZWVib190Y3ApICU+JQogIG11dGF0ZShnZW5yZT1mY3RfcmVvcmRlcihnZW5yZSxwcm9wKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWdlbnJlLHk9cHJvcCkpICsgCiAgZ2VvbV9jb2woKSArIAogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5PTEpKSArCiAgeGxhYigiR2VucmUiKSArCiAgeWxhYigiQ292ZXJhZ2UgaW4gRUVCTy1UQ1AgYnkgd29yayIpICsKICBjb29yZF9mbGlwKCkgCmBgYAoKYGBge3J9CmVlYm9fZ2VucmVzICU+JSAKICBsZWZ0X2pvaW4oZWVibyAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKCFpcy5uYShlZWJvX3RjcF9pZCkpICU+JQogICAgICAgICAgICAgIGRpc3RpbmN0KGVlYm9faWQpICU+JSAKICAgICAgICAgICAgICBtdXRhdGUoaW5fZWVib190Y3A9VCksYnk9YygiZWVib19pZCIpKSAlPiUKICBjb3VudChnZW5yZSxpbl9lZWJvX3RjcCkgJT4lIAogIGdyb3VwX2J5KGdlbnJlKSAlPiUKICBtdXRhdGUocHJvcD1uL3N1bShuKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGZpbHRlcihpbl9lZWJvX3RjcCkgJT4lCiAgbXV0YXRlKGdlbnJlPWZjdF9yZW9yZGVyKGdlbnJlLHByb3ApKSAlPiUKICBnZ3Bsb3QoYWVzKHg9Z2VucmUseT1wcm9wKSkgKyAKICBnZW9tX2NvbCgpICsgCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3k9MSkpICsKICB4bGFiKCJHZW5yZSIpICsKICB5bGFiKCJDb3ZlcmFnZSBpbiBFRUJPLVRDUCBieSBlZGl0aW9uIikgKwogIGNvb3JkX2ZsaXAoKSAKYGBgCgo=