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:

Publication type analysis

Coverage of different publication types in EEBO

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")

In terms of coverage of ESTC’s pre-18th-century material, EEBO is quite good, with a median coverage of about 95% of books both at the edition as well as the work-level, with only a slight drop in coverage for later year editions (meaning that even for later editions, EEBO often contains at least one edition from each year, but may not contain all distinct printings from that year).

For pamphlets, coverage is about 85% across the board, with an interesting increase for later year editions (this may be caused either by reprinted pamphlets having been though of as important to capture, or due to e.g. temporal artifacts, even though it does not appear that overall coverage improves with time, as seen later).

Coverage of different publication types in EEBO-TCP

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")

For coverage in EEBO-TCP, a clear pattern emerges where coverage of singular and first editions is much better than coverage of later editions. This has an important bearing for all following analyses, which in the case of EEBO-TCP, should mostly evaluate coverage on this work-level. As a separate observation, interestingly, coverage of books and pamphlets also seems quite even even.

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))

In terms of a temporal overview, it is important to note how here in an absolute graph, the amount of entries grows significantly overall through time, as well as has large variations and spikes multiple times between 1640 and 1700 (with the larger bump between 1640 and 1660 most likely consisting mainly of the Thomason Tracts).

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))

In terms of edition-level proportional coverage, EEBO coverage is quite balanced throughout the period, with just a slight drop at the end of the 17th century. For EEBO-TCP, edition-level coverage is much more varied, but as noted, it actually does not make that much sense to look at edition-level coverage with respect to it.

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))  

In terms of work-level coverage, also EEBO-TCP appears quite nicely balanced temporally, apart from dips between 1500 and 1530. However, it must be noted how the total amount of content is also very low for those early years, so larger variation can also be expected.

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, method='loess',formula=y~x) +
  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))

Drilling in and separating books and pamphlets from each other, we can see that EEBO coverage of both is very good, apart from a noticeable drop in pamphlet coverage in the late 17th century.

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, method='loess',formula=y~x) +
  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))

For EEBO-TCP, on the work level, the same drop in coverage for pamphlets at the end of the 17th century can be seen, but otherwise coverage is relatively stable through time for both books as well as pamphlets, except for a marked uptick between 1640 and 1660 (caused most likely by more judicious inclusion of the Thomason Tracts). On the work level, pamphlets are just slightly better covered than books, but on the on the edition level, coverage of books is much lower. This can be seen as only the natural consequence of EEBO-TCP favouring including only first editions. Books typically have more editions than pamphlets, so excluding later editions affects edition-level coverage for books much more than it does for pamphlets.

Topical coverage EEBO-TCP vs EEBO

EEBO work-level genre use frequencies

(subset that is in ESTC to get the work information)

eebo_ustc_genres %>% 
  inner_join(eebo_core,by=c("eebo_id")) %>%
  inner_join(estc_core,by=c("estc_id")) %>% 
  group_by(ustc_genre,in_eebo_tcp) %>%
  summarize(n=n_distinct(work_id),.groups="drop") %>%
  group_by(ustc_genre) %>%
  mutate(tn=sum(n)) %>%
  ungroup() %>%
  mutate(ustc_genre=fct_reorder(ustc_genre,tn)) %>%
  ggplot(aes(x=ustc_genre,y=n,fill=in_eebo_tcp)) + 
  geom_col(show.legend=F) + 
  xlab("USTC genre") +
  ylab("Number of works") +
  scale_y_continuous(labels=scales::number) +
  theme_hsci_discrete() +
  coord_flip()

Open question: are the USTC categories usable? Is this a believable genre distribution? If it is, the below graphs show interesting difference and temporal shifts in the coverage of the various categories, the interpretation of which I leave up to you.

EEBO-TCP work-level genre coverage

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

Genre coverage through time

eebo_core %>% 
  inner_join(df,by=c("estc_id")) %>%
  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") %>%
  filter(certain) %>% 
  left_join(eebo_ustc_genres %>% 
              inner_join(eebo_core,by=c("eebo_id")) %>%
              inner_join(estc_core,by=c("estc_id")) %>%
              distinct(work_id,ustc_genre) %>%
              mutate(ustc_genre=fct_lump_n(ustc_genre,10)),
            by=c("work_id")
            ) %>%
  mutate(ustc_genre=fct_explicit_na(ustc_genre,"Unknown")) %>%
  group_by(first_publication_year, ustc_genre, in_eebo_tcp) %>% 
  tally() %>% 
  mutate(prop = n / sum(n), tn = sum(n)) %>% 
  filter(in_eebo_tcp) %>%
  ggplot(aes(x = first_publication_year, y = prop, color = ustc_genre)) +
  geom_point(color = "gray", shape = 21, aes(size = tn)) +
  geom_point(aes(size = n)) +
  geom_smooth(aes(weight = n, fill = ustc_genre), span = 0.3, method='loess',formula=y~x) +
  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) +
  coord_cartesian(ylim=c(0,1)) +
  scale_size(breaks = c(100, 500, 1000), range = c(0.1, 8.0)) +
  guides(color="none",fill="none") +
  facet_wrap(~ustc_genre)

Topical coverage of EEBO vs ESTC through time

Here, we are projecting subject category information from EEBO/ECCO throughout the whole of the ESTC in order to compare their coverage. For the 18th century and ECCO, this seemed to work relatively well for all the 8 categories. For USTC/EEBO, I was comfortable including only the religious/history and chronicles and economics -categories.

Using projected ECCO modules

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") %>%
  filter(certain) %>% 
  left_join(combined_projected_ecco_modules,by=c("work_id")) %>%
  replace_na(list(projected_ecco_module="Other/Unknown")) %>%
  mutate(projected_ecco_module=fct_relevel(projected_ecco_module,"Other/Unknown")) %>%
  group_by(first_publication_year, projected_ecco_module, in_eebo) %>% 
  tally() %>% 
  mutate(prop = n / sum(n), tn = sum(n)) %>% 
  filter(in_eebo) %>%
  ggplot(aes(x = first_publication_year, y = prop, color = projected_ecco_module)) +
  geom_point(color = "gray", shape = 21, aes(size = tn)) +
  geom_point(aes(size = n)) +
  geom_smooth(aes(weight = n, fill = projected_ecco_module), span = 0.3, method='loess',formula=y~x) +
  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) +
  coord_cartesian(ylim=c(0.5,1)) +  
  scale_size(breaks = c(100, 500, 1000), range = c(0.1, 8.0)) + 
  guides(color="none",fill="none") +
  facet_wrap(~projected_ecco_module)

Using projected USTC Religious/History and chronicles/Economics

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") %>%
  filter(certain) %>% 
  left_join(estc_projected_ustc_genres %>% 
  filter(max_prop>=0.7,projected_ustc_genre %in% c("Religious","History and chronicles","Economics")),by=c("work_id")) %>%
  replace_na(list(projected_ustc_genre="Other/Unknown")) %>%
  mutate(projected_ustc_genre=fct_relevel(projected_ustc_genre,"Other/Unknown")) %>%
  group_by(first_publication_year, projected_ustc_genre, in_eebo) %>% 
  tally() %>% 
  mutate(prop = n / sum(n), tn = sum(n)) %>% 
  filter(in_eebo) %>%
  ggplot(aes(x = first_publication_year, y = prop, color = projected_ustc_genre)) +
  geom_point(color = "gray", shape = 21, aes(size = tn)) +
  geom_point(aes(size = n)) +
  geom_smooth(aes(weight = n, fill = projected_ustc_genre), span = 0.3, method='loess',formula=y~x) +
  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) +
  coord_cartesian(ylim=c(0,1)) +
  scale_size(breaks = c(100, 500, 1000), range = c(0.1, 8.0))

Topical coverage of EEBO-TCP vs ESTC through time

Using projected ECCO modules

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") %>%
  filter(certain) %>% 
  left_join(combined_projected_ecco_modules,by=c("work_id")) %>%
  replace_na(list(projected_ecco_module="Other/Unknown")) %>%
  mutate(projected_ecco_module=fct_relevel(projected_ecco_module,"Other/Unknown")) %>%
  group_by(first_publication_year, projected_ecco_module, in_eebo_tcp) %>% 
  tally() %>% 
  mutate(prop = n / sum(n), tn = sum(n)) %>% 
  filter(in_eebo_tcp) %>%
  ggplot(aes(x = first_publication_year, y = prop, color = projected_ecco_module)) +
  geom_point(color = "gray", shape = 21, aes(size = tn)) +
  geom_point(aes(size = n)) +
  geom_smooth(aes(weight = n, fill = projected_ecco_module), span = 0.3, method='loess',formula=y~x) +
  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) +
  coord_cartesian(ylim=c(0,1)) +
  scale_size(breaks = c(100, 500, 1000), range = c(0.1, 8.0)) +
  guides(color="none",fill="none") +
  facet_wrap(~projected_ecco_module)

Using projected USTC Religious/History and chronicles/Economics

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") %>%
  filter(certain) %>% 
  left_join(combined_projected_ustc_genres %>% 
  filter(projected_ustc_genre %in% c("Religious","History and chronicles","Economics")),by=c("work_id")) %>%
  replace_na(list(projected_ustc_genre="Other/Unknown")) %>%
  mutate(projected_ustc_genre=fct_relevel(projected_ustc_genre,"Other/Unknown")) %>%
  group_by(first_publication_year, projected_ustc_genre, in_eebo_tcp) %>% 
  tally() %>% 
  mutate(prop = n / sum(n), tn = sum(n)) %>% 
  filter(in_eebo_tcp) %>%
  ggplot(aes(x = first_publication_year, y = prop, color = projected_ustc_genre)) +
  geom_point(color = "gray", shape = 21, aes(size = tn)) +
  geom_point(aes(size = n)) +
  geom_smooth(aes(weight = n, fill = projected_ustc_genre), span = 0.3, method='loess',formula=y~x) +
  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) +
  coord_cartesian(ylim=c(0,1)) +
  scale_size(breaks = c(100, 500, 1000), range = c(0.1, 8.0))

(compare this with the raw EEBO-TCP vs EEBO coverage as well as the ECCO module coverage graphs)

LS0tCnRpdGxlOiAiRUVCTy9FU1RDIGFuYWx5c2lzIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0b2M6IHllcwotLS0KCmBgYHtyIHNldHVwLGVjaG89Rn0Ka25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSBoZXJlOjpoZXJlKCkpCmBgYAoKYGBge3IsaW5jbHVkZT1GfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShoZXJlKQpwYWs6OnBrZ19pbnN0YWxsKCJoc2NpLXIvZ2doc2NpIikKbGlicmFyeShnZ2hzY2kpCmBgYAoKYGBge3IsaW5jbHVkZT1GfQpwIDwtIGZ1bmN0aW9uKG51bWJlcikgewogIHJldHVybihmb3JtYXQobnVtYmVyLCBzY2llbnRpZmljID0gRkFMU0UsIGJpZy5tYXJrID0gIiwiKSkKfQpwcCA8LSBmdW5jdGlvbihwZXJjZW50YWdlLGFjY3VyYWN5PTAuMDEpIHsKICByZXR1cm4oc2NhbGVzOjpwZXJjZW50KHBlcmNlbnRhZ2UsIGFjY3VyYWN5ID0gYWNjdXJhY3kpKQp9CmBgYAoKYGBge3IsaW5jbHVkZT1GfQpzb3VyY2UoaGVyZSgiY29kZS9sb2FkX2FuZF9wcmVwYXJlX2RhdGEuUiIpLCBsb2NhbCA9IGtuaXRyOjprbml0X2dsb2JhbCgpKQpgYGAKCgpgYGB7cixpbmNsdWRlPUZ9CmxpYnJhcnkoYXNzZXJ0dGhhdCkKCm5fZWVib19pZHMgPC0gZWVib19jb3JlICU+JQogIGRpc3RpbmN0KGVlYm9faWQpICU+JQogIG5yb3coKQpuX2VlYm9fdGNwX2lkcyA8LSBlZWJvX3RjcF9jb3JlICU+JQogIGRpc3RpbmN0KGVlYm9fdGNwX2lkKSAlPiUKICBucm93KCkKbl9lZWJvX2lkc19pbl9lZWJvX3RjcCA8LSBlZWJvX2NvcmUgJT4lCiAgZmlsdGVyKCFpcy5uYShlZWJvX3RjcF9pZCkpICU+JQogIGRpc3RpbmN0KGVlYm9faWQpICU+JQogIG5yb3coKQoKYXNzZXJ0X3RoYXQoZWVib19jb3JlICU+JSBmaWx0ZXIoIWlzLm5hKGVlYm9fdGNwX2lkKSkgJT4lIGRpc3RpbmN0KGVlYm9faWQsIGVlYm9fdGNwX2lkKSAlPiUgY291bnQoZWVib190Y3BfaWQpICU+JSBmaWx0ZXIobiA+IDEpICU+JSBucm93KCkgPT0gMCkKCm5fZWVib19pZHNfbXVsdGltYXBwZWRfdG9fZWVib190Y3AgPC0gZWVib19jb3JlICU+JQogIGZpbHRlcighaXMubmEoZWVib190Y3BfaWQpKSAlPiUKICBkaXN0aW5jdChlZWJvX2lkLCBlZWJvX3RjcF9pZCkgJT4lCiAgY291bnQoZWVib19pZCkgJT4lCiAgZmlsdGVyKG4gPiAxKSAlPiUKICBucm93KCkKCm5fZWVib19pZHNfbm90X2luX2VzdGMgPC0gZWVib19jb3JlICU+JQogIGZpbHRlcihpcy5uYShlc3RjX2lkKSkgJT4lCiAgZGlzdGluY3QoZWVib19pZCkgJT4lCiAgbnJvdygpCm5fZWVib190Y3BfaWRzX25vdF9pbl9lc3RjIDwtIGVlYm9fdGNwX2NvcmUgJT4lCiAgZmlsdGVyKGlzLm5hKGVzdGNfaWQpKSAlPiUKICBkaXN0aW5jdChlZWJvX3RjcF9pZCkgJT4lCiAgbnJvdygpCgpuX2VlYm9faWRzX211bHRpbWFwcGVkX3RvX2VzdGMgPC0gZWVib19jb3JlICU+JQogIGZpbHRlcighaXMubmEoZXN0Y19pZCkpICU+JQogIGRpc3RpbmN0KGVlYm9faWQsIGVzdGNfaWQpICU+JQogIGNvdW50KGVlYm9faWQpICU+JQogIGZpbHRlcihuID4gMSkgJT4lCiAgbnJvdygpCm5fZWVib190Y3BfaWRzX211bHRpbWFwcGVkX3RvX2VzdGMgPC0gZWVib190Y3BfY29yZSAlPiUKICBmaWx0ZXIoIWlzLm5hKGVzdGNfaWQpKSAlPiUKICBkaXN0aW5jdChlZWJvX3RjcF9pZCwgZXN0Y19pZCkgJT4lCiAgY291bnQoZWVib190Y3BfaWQpICU+JQogIGZpbHRlcihuID4gMSkgJT4lCiAgbnJvdygpCgpuX2VzdGNfaWRzX3dpdGhfZWVib19pZHMgPC0gZXN0Y19jb3JlICU+JQogIGZpbHRlcihpbl9lZWJvKSAlPiUKICBucm93KCkKbl9lc3RjX2lkc19pbl9kZl93aXRoX2VlYm9faWRzIDwtIGRmICU+JQogIGZpbHRlcihpbl9lZWJvKSAlPiUKICBucm93KCkKbl9lc3RjX2lkc193aXRoX2VlYm9fdGNwX2lkcyA8LSBlc3RjX2NvcmUgJT4lCiAgZmlsdGVyKGluX2VlYm9fdGNwKSAlPiUKICBucm93KCkKbl9lc3RjX2lkc19pbl9kZl93aXRoX2VlYm9fdGNwX2lkcyA8LSBkZiAlPiUKICBmaWx0ZXIoaW5fZWVib190Y3ApICU+JQogIG5yb3coKQoKbl9lc3RjX2lkc19pbl9kZiA8LSBkZiAlPiUgbnJvdygpCm5fZWVib19pZHNfaW5fZGYgPC0gZGYgJT4lCiAgaW5uZXJfam9pbihlZWJvX2NvcmUsIGJ5ID0gYygiZXN0Y19pZCIpKSAlPiUKICBkaXN0aW5jdChlZWJvX2lkKSAlPiUKICBucm93KCkKbl9lZWJvX3RjcF9pZHNfaW5fZGYgPC0gZGYgJT4lCiAgaW5uZXJfam9pbihlZWJvX3RjcF9jb3JlLCBieSA9IGMoImVzdGNfaWQiKSkgJT4lCiAgZGlzdGluY3QoZWVib190Y3BfaWQpICU+JQogIG5yb3coKQpgYGAKCiMgT3ZlcnZpZXcKCk91dCBvZiBhIHRvdGFsIG9mIGByIHAobl9lZWJvX2lkcylgIEVFQk8gcmVjb3JkcywgYHIgcChuX2VlYm9faWRzX2luX2VlYm9fdGNwKWAgKGByIHBwKG5fZWVib19pZHNfaW5fZWVib190Y3Avbl9lZWJvX2lkcylgKSBhcmUgaW4gRUVCTy1UQ1AgKGJ1dCBgciBwKG5fZWVib19pZHNfbXVsdGltYXBwZWRfdG9fZWVib190Y3ApYCBFRUJPIHJlY29yZHMgaGF2ZSBtdWx0aXBsZSBUQ1AgaWRzKS4KCk91dCBvZiB0aGUgYHIgcChuX2VlYm9faWRzKWAgRUVCTyByZWNvcmRzLCBgciBwKG5fZWVib19pZHNfbm90X2luX2VzdGMpYCAgKGByIHBwKG5fZWVib19pZHNfbm90X2luX2VzdGMvbl9lZWJvX2lkcylgKSBjb3VsZCBub3QgYmUgbWF0Y2hlZCB0byBhbiBFU1RDIHJlY29yZCBhbmQgd2lsbCBiZSBsZWZ0IG91dCBvZiB0aGUgYW5hbHlzaXMuIE9uIHRoZSBvdGhlciBoYW5kLCBgciBwKG5fZWVib19pZHNfbXVsdGltYXBwZWRfdG9fZXN0YylgIEVFQk8gcmVjb3JkcyAoYHIgcHAobl9lZWJvX2lkc19tdWx0aW1hcHBlZF90b19lc3RjL25fZWVib19pZHMpYCkgd2VyZSBtYXRjaGVkIHRvIG1vcmUgdGhhbiBvbmUgRVNUQyByZWNvcmQsIHBvc3NpYmx5IGNhdXNpbmcgYmlhcy4KCk91dCBvZiB0aGUgYHIgcChuX2VlYm9fdGNwX2lkcylgIEVFQk8tVENQIHJlY29yZHMsIGByIHAobl9lZWJvX3RjcF9pZHNfbm90X2luX2VzdGMpYCAoYHIgcHAobl9lZWJvX3RjcF9pZHNfbm90X2luX2VzdGMvbl9lZWJvX3RjcF9pZHMpYCkgY291bGQgbm90IGJlIG1hdGNoZWQgdG8gYW4gRVNUQyByZWNvcmQgYW5kIHdpbGwgYmUgbGVmdCBvdXQgb2YgdGhlIGFuYWx5c2lzLiBPbiB0aGUgb3RoZXIgaGFuZCwgYHIgcChuX2VlYm9fdGNwX2lkc19tdWx0aW1hcHBlZF90b19lc3RjKWAgRUVCTy1UQ1AgcmVjb3JkcyAoYHIgcHAobl9lZWJvX3RjcF9pZHNfbXVsdGltYXBwZWRfdG9fZXN0Yy9uX2VlYm9fdGNwX2lkcylgKSB3ZXJlIG1hdGNoZWQgdG8gbW9yZSB0aGFuIG9uZSBFU1RDIHJlY29yZCwgcG9zc2libHkgY2F1c2luZyBiaWFzLgoKSW4gdGhlIGFuYWx5c2lzLCBvbmx5IEVTVEMgcmVjb3JkcyB3aXRoIHB1YmxpY2F0aW9uIHllYXJzIGluIHRoZSByYW5nZSBbMTQ3NCwxNzAwKSBoYXZlIGJlZW4gaW5jbHVkZWQuIFRoaXMgcmVzdWx0cyBpbiB0aGUgZXhjbHVzaW9uIG9mIGByIHAobl9lc3RjX2lkc193aXRoX2VlYm9faWRzLW5fZXN0Y19pZHNfaW5fZGZfd2l0aF9lZWJvX2lkcylgIChgciBwcCgobl9lc3RjX2lkc193aXRoX2VlYm9faWRzLW5fZXN0Y19pZHNfaW5fZGZfd2l0aF9lZWJvX2lkcykvbl9lc3RjX2lkc193aXRoX2VlYm9faWRzKWApIEVTVEMgcmVjb3JkcyB0aGF0IGhhdmUgcmVwcmVzZW50YXRpb24gaW4gRUVCTywgcG9zc2libHkgY2F1c2luZyBiaWFzLiBgciBwKG5fZXN0Y19pZHNfd2l0aF9lZWJvX3RjcF9pZHMtbl9lc3RjX2lkc19pbl9kZl93aXRoX2VlYm9fdGNwX2lkcylgIChgciBwcCgobl9lc3RjX2lkc193aXRoX2VlYm9fdGNwX2lkcy1uX2VzdGNfaWRzX2luX2RmX3dpdGhfZWVib190Y3BfaWRzKS9uX2VzdGNfaWRzX3dpdGhfZWVib190Y3BfaWRzKWApIG9mIHRoZSBFU1RDIHJlY29yZHMgd2l0aCByZXByZXNlbnRhdGlvbiBpbiBFRUJPLVRDUCBhcmUgcmVtb3ZlZCBkdWUgdG8gdGhpcyBmaWx0ZXJpbmcgY29uZGl0aW9uLgoKSW4gdGhlIGVuZCwgb3VyIHdvcmtpbmcgZGF0YXNldDoKCiogRnJvbSB0aGUgdmlld3BvaW50IG9mIEVFQk8sIGNvbnRhaW5zIGByIHAobl9lZWJvX2lkc19pbl9kZilgIChgciBwcChuX2VlYm9faWRzX2luX2RmL25fZWVib19pZHMpYCkgb3V0IG9mIHRoZSBvcmlnaW5hbCBgciBwKG5fZWVib19pZHMpYCBFRUJPIGlkcy4gCiogRnJvbSB0aGUgdmlld3BvaW50IG9mIEVFQk8tVENQLCBjb250YWlucyBgciBwKG5fZWVib190Y3BfaWRzX2luX2RmKWAgKGByIHBwKG5fZWVib190Y3BfaWRzX2luX2RmL25fZWVib190Y3BfaWRzKWApIG91dCBvZiB0aGUgb3JpZ2luYWwgYHIgcChuX2VlYm9fdGNwX2lkcylgIEVFQk8gaWRzLiAKKiBDb25zaXN0cyBvZiBgciBwKG5fZXN0Y19pZHNfaW5fZGYpYCBFU1RDIHJlY29yZHMsIG9mIHdoaWNoIGByIHAobl9lc3RjX2lkc19pbl9kZl93aXRoX2VlYm9faWRzKWAgKGByIHBwKG5fZXN0Y19pZHNfaW5fZGZfd2l0aF9lZWJvX2lkcy9uX2VzdGNfaWRzX2luX2RmKWApIHdlIGVzdGltYXRlIHRvIGhhdmUgcmVwcmVzZW50YXRpb24gaW4gRUVCTywgYW5kIGByIHAobl9lc3RjX2lkc19pbl9kZl93aXRoX2VlYm9fdGNwX2lkcylgIChgciBwcChuX2VzdGNfaWRzX2luX2RmX3dpdGhfZWVib190Y3BfaWRzL25fZXN0Y19pZHNfaW5fZGYpYCkgdG8gaGF2ZSByZXByZXNlbnRhdGlvbiBpbiBFRUJPLVRDUC4KCiMgUHVibGljYXRpb24gdHlwZSBhbmFseXNpcwoKIyMgQ292ZXJhZ2Ugb2YgZGlmZmVyZW50IHB1YmxpY2F0aW9uIHR5cGVzIGluIEVFQk8KCmBgYHtyfQpsaWJyYXJ5KGdnYmVlc3dhcm0pCmJpbmRfcm93cygKICBkZiAlPiUgbXV0YXRlKGdyb3VwID0gIkVkaXRpb25zIiksCiAgZGYgJT4lIGdyb3VwX2J5KHdvcmtfaWQsdHlwZSxmaXJzdF9wdWJsaWNhdGlvbl95ZWFyLHB1YmxpY2F0aW9uX3llYXIpICU+JQogICAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksLmdyb3Vwcz0iZHJvcCIpICU+JQogICAgbXV0YXRlKGdyb3VwID0gIldvcmtzIixlZGl0aW9uX3R5cGU9aWZfZWxzZShwdWJsaWNhdGlvbl95ZWFyPT1maXJzdF9wdWJsaWNhdGlvbl95ZWFyLCJGaXJzdCB5ZWFyIHdvcmsiLCJMYXRlciB3b3JrIikpCikgJT4lCiAgbXV0YXRlKGVkaXRpb25fdHlwZT1mY3RfcmVsZXZlbChlZGl0aW9uX3R5cGUsIlNpbmd1bGFyIiwiRmlyc3QgeWVhciB3b3JrIiwiTGF0ZXIgd29yayIsIkZpcnN0IHllYXIgZWRpdGlvbiIsIkxhdGVyIGVkaXRpb24iKSkgJT4lCiAgZmlsdGVyKHR5cGUgJWluJSBjKCJCb29rIiwiUGFtcGhsZXQiKSkgJT4lCiAgZ3JvdXBfYnkocHVibGljYXRpb25feWVhciwgZWRpdGlvbl90eXBlLCBncm91cCwgdHlwZSwgaW5fZWVibykgJT4lIAogIHRhbGx5KCkgJT4lIAogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSwgdG4gPSBzdW0obikpICU+JSAKICBmaWx0ZXIoaW5fZWVibykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdHlwZSwgeSA9IHByb3AsIGdyb3VwID0gZWRpdGlvbl90eXBlLCBjb2xvciA9IGVkaXRpb25fdHlwZSkpICsKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyhzaXplID0gdG4pLCBkb2RnZSA9IDEuMCkgKwogIHN0YXRfc3VtbWFyeShhZXMoZ3JvdXAgPSBlZGl0aW9uX3R5cGUpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMS4wKSwgZnVuID0gbWVkaWFuLCBmdW4ubWluID0gbWVkaWFuLCBmdW4ubWF4ID0gbWVkaWFuLCBnZW9tID0gImNyb3NzYmFyIiwgd2lkdGggPSAwLjUsIGNvbG9yID0gInJlZCIpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHhsYWIoTlVMTCkgKwogIHlsYWIoIkVFQk8gY292ZXJhZ2UiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4wNSkpICsKICBzY2FsZV9zaXplKGJyZWFrcyA9IGMoMjUwLCA1MDAsIDE1MDApLCByYW5nZSA9IGMoMC4xLCA4LjApKSArCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDApLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDIsIDAuMDIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmJveC5qdXN0ID0gImJvdHRvbSIsIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICsKICBsYWJzKGNvbG9yID0gIlJlcHJlc2VudGF0aW9uIHR5cGUiLCBzaXplID0gIkNvdW50IikgKwogIGd1aWRlcyhzaGFwZSA9ICJub25lIikKYGBgCgpJbiB0ZXJtcyBvZiBjb3ZlcmFnZSBvZiBFU1RDJ3MgcHJlLTE4dGgtY2VudHVyeSBtYXRlcmlhbCwgRUVCTyBpcyBxdWl0ZSBnb29kLCB3aXRoIGEgbWVkaWFuIGNvdmVyYWdlIG9mIGFib3V0IDk1JSBvZiBib29rcyBib3RoIGF0IHRoZSBlZGl0aW9uIGFzIHdlbGwgYXMgdGhlIHdvcmstbGV2ZWwsIHdpdGggb25seSBhIHNsaWdodCBkcm9wIGluIGNvdmVyYWdlIGZvciBsYXRlciB5ZWFyIGVkaXRpb25zIChtZWFuaW5nIHRoYXQgZXZlbiBmb3IgbGF0ZXIgZWRpdGlvbnMsIEVFQk8gb2Z0ZW4gY29udGFpbnMgYXQgbGVhc3Qgb25lIGVkaXRpb24gZnJvbSBlYWNoIHllYXIsIGJ1dCBtYXkgbm90IGNvbnRhaW4gYWxsIGRpc3RpbmN0IHByaW50aW5ncyBmcm9tIHRoYXQgeWVhcikuCgpGb3IgcGFtcGhsZXRzLCBjb3ZlcmFnZSBpcyBhYm91dCA4NSUgYWNyb3NzIHRoZSBib2FyZCwgd2l0aCBhbiBpbnRlcmVzdGluZyBpbmNyZWFzZSBmb3IgbGF0ZXIgeWVhciBlZGl0aW9ucyAodGhpcyBtYXkgYmUgY2F1c2VkIGVpdGhlciBieSByZXByaW50ZWQgcGFtcGhsZXRzIGhhdmluZyBiZWVuIHRob3VnaCBvZiBhcyBpbXBvcnRhbnQgdG8gY2FwdHVyZSwgb3IgZHVlIHRvIGUuZy4gdGVtcG9yYWwgYXJ0aWZhY3RzLCBldmVuIHRob3VnaCBpdCBkb2VzIG5vdCBhcHBlYXIgdGhhdCBvdmVyYWxsIGNvdmVyYWdlIGltcHJvdmVzIHdpdGggdGltZSwgYXMgc2VlbiBsYXRlcikuCgojIyBDb3ZlcmFnZSBvZiBkaWZmZXJlbnQgcHVibGljYXRpb24gdHlwZXMgaW4gRUVCTy1UQ1AKCmBgYHtyfQpsaWJyYXJ5KGdnYmVlc3dhcm0pCmJpbmRfcm93cygKICBkZiAlPiUgbXV0YXRlKGdyb3VwID0gIkVkaXRpb25zIiksCiAgZGYgJT4lIGdyb3VwX2J5KHdvcmtfaWQsdHlwZSxmaXJzdF9wdWJsaWNhdGlvbl95ZWFyLHB1YmxpY2F0aW9uX3llYXIpICU+JQogICAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksLmdyb3Vwcz0iZHJvcCIpICU+JQogICAgbXV0YXRlKGdyb3VwID0gIldvcmtzIixlZGl0aW9uX3R5cGU9aWZfZWxzZShwdWJsaWNhdGlvbl95ZWFyPT1maXJzdF9wdWJsaWNhdGlvbl95ZWFyLCJGaXJzdCB5ZWFyIHdvcmsiLCJMYXRlciB3b3JrIikpCikgJT4lCiAgbXV0YXRlKGVkaXRpb25fdHlwZT1mY3RfcmVsZXZlbChlZGl0aW9uX3R5cGUsIlNpbmd1bGFyIiwiRmlyc3QgeWVhciB3b3JrIiwiTGF0ZXIgd29yayIsIkZpcnN0IHllYXIgZWRpdGlvbiIsIkxhdGVyIGVkaXRpb24iKSkgJT4lCiAgZmlsdGVyKHR5cGUgJWluJSBjKCJCb29rIiwiUGFtcGhsZXQiKSkgJT4lCiAgZ3JvdXBfYnkocHVibGljYXRpb25feWVhciwgZWRpdGlvbl90eXBlLCBncm91cCwgdHlwZSwgaW5fZWVib190Y3ApICU+JSAKICB0YWxseSgpICU+JSAKICBtdXRhdGUocHJvcCA9IG4gLyBzdW0obiksIHRuID0gc3VtKG4pKSAlPiUgCiAgZmlsdGVyKGluX2VlYm9fdGNwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB0eXBlLCB5ID0gcHJvcCwgZ3JvdXAgPSBlZGl0aW9uX3R5cGUsIGNvbG9yID0gZWRpdGlvbl90eXBlKSkgKwogIGdlb21fcXVhc2lyYW5kb20oYWVzKHNpemUgPSB0biksIGRvZGdlID0gMS4wKSArCiAgc3RhdF9zdW1tYXJ5KGFlcyhncm91cCA9IGVkaXRpb25fdHlwZSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxLjApLCBmdW4gPSBtZWRpYW4sIGZ1bi5taW4gPSBtZWRpYW4sIGZ1bi5tYXggPSBtZWRpYW4sIGdlb20gPSAiY3Jvc3NiYXIiLCB3aWR0aCA9IDAuNSwgY29sb3IgPSAicmVkIikgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgeGxhYihOVUxMKSArCiAgeWxhYigiRUVCTy1UQ1AgY292ZXJhZ2UiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4wNSkpICsKICBzY2FsZV9zaXplKGJyZWFrcyA9IGMoMjUwLCA1MDAsIDE1MDApLCByYW5nZSA9IGMoMC4xLCA4LjApKSArCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDApLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDIsIDAuMDIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmJveC5qdXN0ID0gImJvdHRvbSIsIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICsKICBsYWJzKGNvbG9yID0gIlJlcHJlc2VudGF0aW9uIHR5cGUiLCBzaXplID0gIkNvdW50IikgKwogIGd1aWRlcyhzaGFwZSA9ICJub25lIikKYGBgCgpGb3IgY292ZXJhZ2UgaW4gRUVCTy1UQ1AsIGEgY2xlYXIgcGF0dGVybiBlbWVyZ2VzIHdoZXJlIGNvdmVyYWdlIG9mIHNpbmd1bGFyIGFuZCBmaXJzdCBlZGl0aW9ucyBpcyBtdWNoIGJldHRlciB0aGFuIGNvdmVyYWdlIG9mIGxhdGVyIGVkaXRpb25zLiBUaGlzIGhhcyBhbiBpbXBvcnRhbnQgYmVhcmluZyBmb3IgYWxsIGZvbGxvd2luZyBhbmFseXNlcywgd2hpY2ggaW4gdGhlIGNhc2Ugb2YgRUVCTy1UQ1AsIHNob3VsZCBtb3N0bHkgZXZhbHVhdGUgY292ZXJhZ2Ugb24gdGhpcyB3b3JrLWxldmVsLiBBcyBhIHNlcGFyYXRlIG9ic2VydmF0aW9uLCBpbnRlcmVzdGluZ2x5LCBjb3ZlcmFnZSBvZiBib29rcyBhbmQgcGFtcGhsZXRzIGFsc28gc2VlbXMgcXVpdGUgZXZlbiBldmVuLgoKIyBFZGl0aW9uLWxldmVsIHRlbXBvcmFsIG92ZXJ2aWV3CgpgYGB7cixmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gM30KZGYgJT4lICBtdXRhdGUoZyA9IGNhc2Vfd2hlbigKICAhY2VydGFpbiB+ICJVbmNlcnRhaW4gZGF0aW5nIiwKICBpbl9lZWJvX3RjcCAgfiAiSW4gRUVCTy1UQ1AiLAogIGluX2VlYm8gfiAiSW4gRUVCTyIsCiAgVCB+ICJFU1RDIHRvdGFsIiwKKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcHVibGljYXRpb25feWVhciwgZmlsbCA9IGZjdF9yZWxldmVsKGcsICJVbmNlcnRhaW4gZGF0aW5nIiwgIkVTVEMgdG90YWwiLCAiSW4gRUVCTyIsIkluIEVFQk8tVENQIikpKSArCiAgZ2VvbV9iYXIod2lkdGggPSAxKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwMDAsIDIwMDAsIGJ5ID0gMjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMDAwMCwgYnkgPSAxMDAwKSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRVNUQyBlbnRyaWVzIikgKwogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjA1LCAwLjk1KSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKGZpbGwgPSBOVUxMKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKQpgYGAKSW4gdGVybXMgb2YgYSB0ZW1wb3JhbCBvdmVydmlldywgaXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgaG93IGhlcmUgaW4gYW4gYWJzb2x1dGUgZ3JhcGgsIHRoZSBhbW91bnQgb2YgZW50cmllcyBncm93cyBzaWduaWZpY2FudGx5IG92ZXJhbGwgdGhyb3VnaCB0aW1lLCBhcyB3ZWxsIGFzIGhhcyBsYXJnZSB2YXJpYXRpb25zIGFuZCBzcGlrZXMgbXVsdGlwbGUgdGltZXMgYmV0d2VlbiAxNjQwIGFuZCAxNzAwICh3aXRoIHRoZSBsYXJnZXIgYnVtcCBiZXR3ZWVuIDE2NDAgYW5kIDE2NjAgbW9zdCBsaWtlbHkgY29uc2lzdGluZyBtYWlubHkgb2YgdGhlIFRob21hc29uIFRyYWN0cykuCgpgYGB7cixmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gM30KZGYgJT4lIGZpbHRlcihjZXJ0YWluKSAlPiUgbXV0YXRlKGcgPSBjYXNlX3doZW4oCiAgaW5fZWVib190Y3AgIH4gIkluIEVFQk8tVENQIiwKICBpbl9lZWJvIH4gIkluIEVFQk8iLAogIFQgfiAiTm90IGluIEVFQk8iLAopKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBwdWJsaWNhdGlvbl95ZWFyLCBmaWxsID0gZmN0X3JlbGV2ZWwoZywgIk5vdCBpbiBFRUJPIiwgIkluIEVFQk8iLCJJbiBFRUJPLVRDUCIpKSkgKwogIGdlb21fYmFyKHdpZHRoID0gMSxwb3NpdGlvbj0nZmlsbCcpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4xKSxsYWJlbHM9c2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeT0xKSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiUHJvcG9ydGlvbiBvZiBFU1RDIGVudHJpZXMiKSArCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDApLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuOTQsIDAuMDgpLCBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpKSArCiAgbGFicyhmaWxsID0gTlVMTCkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFKSkKYGBgCkluIHRlcm1zIG9mIGVkaXRpb24tbGV2ZWwgcHJvcG9ydGlvbmFsIGNvdmVyYWdlLCBFRUJPIGNvdmVyYWdlIGlzIHF1aXRlIGJhbGFuY2VkIHRocm91Z2hvdXQgdGhlIHBlcmlvZCwgd2l0aCBqdXN0IGEgc2xpZ2h0IGRyb3AgYXQgdGhlIGVuZCBvZiB0aGUgMTd0aCBjZW50dXJ5LiBGb3IgRUVCTy1UQ1AsIGVkaXRpb24tbGV2ZWwgY292ZXJhZ2UgaXMgbXVjaCBtb3JlIHZhcmllZCwgYnV0IGFzIG5vdGVkLCBpdCBhY3R1YWxseSBkb2VzIG5vdCBtYWtlIHRoYXQgbXVjaCBzZW5zZSB0byBsb29rIGF0IGVkaXRpb24tbGV2ZWwgY292ZXJhZ2Ugd2l0aCByZXNwZWN0IHRvIGl0LgoKIyBXb3JrLWxldmVsIHRlbXBvcmFsIG92ZXJ2aWV3CgpgYGB7cn0KZGYgJT4lIAogIGZpbHRlcihmaXJzdF9wdWJsaWNhdGlvbl95ZWFyPjE0NzQpICU+JQogIGdyb3VwX2J5KHdvcmtfaWQsZmlyc3RfcHVibGljYXRpb25feWVhcikgJT4lCiAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksY2VydGFpbj1hbnkoZmlyc3RfeWVhcl9wdWJsaWNhdGlvbiAmIGNlcnRhaW4pLC5ncm91cHM9ImRyb3AiKSAlPiUgCiAgbXV0YXRlKGcgPSBjYXNlX3doZW4oCiAgICAhY2VydGFpbiB+ICJVbmNlcnRhaW4gZGF0aW5nIiwKICAgIGluX2VlYm9fdGNwICB+ICJJbiBFRUJPLVRDUCIsCiAgICBpbl9lZWJvIH4gIkluIEVFQk8iLAogICAgVCB+ICJFU1RDIHRvdGFsIiwKICApKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZmlyc3RfcHVibGljYXRpb25feWVhciwgZmlsbCA9IGZjdF9yZWxldmVsKGcsICJVbmNlcnRhaW4gZGF0aW5nIiwgIkVTVEMgdG90YWwiLCAiSW4gRUVCTyIsIkluIEVFQk8tVENQIikpKSArCiAgZ2VvbV9iYXIod2lkdGggPSAxKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwMDAsIDIwMDAsIGJ5ID0gMjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMDAwMCwgYnkgPSAxMDAwKSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRVNUQyBlbnRyaWVzIikgKwogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjA1LCAwLjk1KSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKGZpbGwgPSBOVUxMKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKQpgYGAKCgpgYGB7cn0KZGYgJT4lIAogIGZpbHRlcihmaXJzdF9wdWJsaWNhdGlvbl95ZWFyPjE0NzQpICU+JQogIGdyb3VwX2J5KHdvcmtfaWQsZmlyc3RfcHVibGljYXRpb25feWVhcikgJT4lCiAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksLmdyb3Vwcz0iZHJvcCIpICU+JQogIG11dGF0ZShnID0gY2FzZV93aGVuKAogIGluX2VlYm9fdGNwICB+ICJJbiBFRUJPLVRDUCIsCiAgaW5fZWVibyB+ICJJbiBFRUJPIiwKICBUIH4gIk5vdCBpbiBFRUJPIiwKKSkgJT4lICAKZ2dwbG90KGFlcyh4ID0gZmlyc3RfcHVibGljYXRpb25feWVhciwgZmlsbCA9IGZjdF9yZWxldmVsKGcsICJOb3QgaW4gRUVCTyIsICJJbiBFRUJPIiwiSW4gRUVCTy1UQ1AiKSkpICsKICBnZW9tX2Jhcih3aWR0aCA9IDEscG9zaXRpb249J2ZpbGwnKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwMDAsIDIwMDAsIGJ5ID0gMjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxLCBieSA9IDAuMSksbGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3k9MSkpICsKICB4bGFiKCJZZWFyIG9mIGZpcnN0IHB1YmxpY2F0aW9uIikgKwogIHlsYWIoIlByb3BvcnRpb24gb2YgRVNUQyB3b3JrcyIpICsKICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMCksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45NCwgMC4wOCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKGZpbGwgPSBOVUxMKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKSAgCmBgYApJbiB0ZXJtcyBvZiB3b3JrLWxldmVsIGNvdmVyYWdlLCBhbHNvIEVFQk8tVENQIGFwcGVhcnMgcXVpdGUgbmljZWx5IGJhbGFuY2VkIHRlbXBvcmFsbHksIGFwYXJ0IGZyb20gZGlwcyBiZXR3ZWVuIDE1MDAgYW5kIDE1MzAuIEhvd2V2ZXIsIGl0IG11c3QgYmUgbm90ZWQgaG93IHRoZSB0b3RhbCBhbW91bnQgb2YgY29udGVudCBpcyBhbHNvIHZlcnkgbG93IGZvciB0aG9zZSBlYXJseSB5ZWFycywgc28gbGFyZ2VyIHZhcmlhdGlvbiBjYW4gYWxzbyBiZSBleHBlY3RlZC4KCiMgRG9jdW1lbnQgdHlwZSBjb3ZlcmFnZSB0aHJvdWdoIHRpbWUKCmBgYHtyfQpiaW5kX3Jvd3MoCiAgZGYgJT4lIG11dGF0ZShncm91cCA9ICJFZGl0aW9ucyIsdHlwZT1yZWNvZGUodHlwZSwiQm9vayI9IkJvb2sgKGVkaXRpb24tbGV2ZWwpIiwiUGFtcGhsZXQiPSJQYW1waGxldCAoZWRpdGlvbi1sZXZlbCkiKSksCiAgZGYgJT4lIGdyb3VwX2J5KHdvcmtfaWQsdHlwZSxmaXJzdF9wdWJsaWNhdGlvbl95ZWFyLHB1YmxpY2F0aW9uX3llYXIpICU+JQogICAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksY2VydGFpbj1hbnkoZmlyc3RfeWVhcl9wdWJsaWNhdGlvbiAmIGNlcnRhaW4pLC5ncm91cHM9ImRyb3AiKSAlPiUKICAgIG11dGF0ZShncm91cCA9ICJXb3JrcyIpCikgJT4lCiAgbXV0YXRlKHR5cGU9ZmN0X3JlbGV2ZWwodHlwZSwiUGFtcGhsZXQgKGVkaXRpb24tbGV2ZWwpIiwiQm9vayAoZWRpdGlvbi1sZXZlbCkiLCJQYW1waGxldCIsIkJvb2siKSkgJT4lCiAgZmlsdGVyKGNlcnRhaW4pICU+JSAKICBmaWx0ZXIoIWlzLm5hKHR5cGUpLHR5cGUhPSJJbi1iZXR3ZWVuIikgJT4lIAogIGdyb3VwX2J5KHB1YmxpY2F0aW9uX3llYXIsIHR5cGUsIGluX2VlYm8pICU+JSAKICB0YWxseSgpICU+JSAKICBtdXRhdGUocHJvcCA9IG4gLyBzdW0obiksIHRuID0gc3VtKG4pKSAlPiUgCiAgZmlsdGVyKGluX2VlYm8pICU+JQogIGdncGxvdChhZXMoeCA9IHB1YmxpY2F0aW9uX3llYXIsIHkgPSBwcm9wLCBjb2xvciA9IHR5cGUpKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHdlaWdodCA9IG4sIGZpbGwgPSB0eXBlKSwgc3BhbiA9IDAuMywgbWV0aG9kPSdsb2VzcycsZm9ybXVsYT15fngpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImdyYXkiLCBzaGFwZSA9IDIxLCBhZXMoc2l6ZSA9IHRuKSkgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBuKSkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMDAwLCAyMDAwLCBieSA9IDIwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksIGJyZWFrcyA9IHNlcSgwLCAxLCBieSA9IDAuMDUpKSArCiAgeGxhYigiWWVhciIpICsKICB5bGFiKCJFRUJPIGNvdmVyYWdlIikgKwogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAwKSwgbGVnZW5kLmJveC5qdXN0ID0gImJvdHRvbSIsIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4wNSwgMC4wMiksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQuYm94ID0gImhvcml6b250YWwiKSArCiAgbGFicyhjb2xvciA9IE5VTEwsIHNpemUgPSBOVUxMLCBzaGFwZSA9IE5VTEwsIGZpbGwgPSBOVUxMKSArCiAgc2NhbGVfc2l6ZShicmVha3MgPSBjKDUwMCwgMjAwMCwgMzUwMCksIHJhbmdlID0gYygwLjEsIDguMCkpCmBgYApEcmlsbGluZyBpbiBhbmQgc2VwYXJhdGluZyBib29rcyBhbmQgcGFtcGhsZXRzIGZyb20gZWFjaCBvdGhlciwgd2UgY2FuIHNlZSB0aGF0IEVFQk8gY292ZXJhZ2Ugb2YgYm90aCBpcyB2ZXJ5IGdvb2QsIGFwYXJ0IGZyb20gYSBub3RpY2VhYmxlIGRyb3AgaW4gcGFtcGhsZXQgY292ZXJhZ2UgaW4gdGhlIGxhdGUgMTd0aCBjZW50dXJ5LgoKYGBge3J9CmJpbmRfcm93cygKICBkZiAlPiUgbXV0YXRlKGdyb3VwID0gIkVkaXRpb25zIix0eXBlPXJlY29kZSh0eXBlLCJCb29rIj0iQm9vayAoZWRpdGlvbi1sZXZlbCkiLCJQYW1waGxldCI9IlBhbXBobGV0IChlZGl0aW9uLWxldmVsKSIpKSwKICBkZiAlPiUgZ3JvdXBfYnkod29ya19pZCx0eXBlLGZpcnN0X3B1YmxpY2F0aW9uX3llYXIscHVibGljYXRpb25feWVhcikgJT4lCiAgICBzdW1tYXJpemUoaW5fZWVibz1hbnkoaW5fZWVibyksaW5fZWVib190Y3A9YW55KGluX2VlYm9fdGNwKSxjZXJ0YWluPWFueShmaXJzdF95ZWFyX3B1YmxpY2F0aW9uICYgY2VydGFpbiksLmdyb3Vwcz0iZHJvcCIpICU+JQogICAgbXV0YXRlKGdyb3VwID0gIldvcmtzIikKKSAlPiUKICBtdXRhdGUodHlwZT1mY3RfcmVsZXZlbCh0eXBlLCJQYW1waGxldCAoZWRpdGlvbi1sZXZlbCkiLCJCb29rIChlZGl0aW9uLWxldmVsKSIsIlBhbXBobGV0IiwiQm9vayIpKSAlPiUKICBmaWx0ZXIoY2VydGFpbikgJT4lIAogIGZpbHRlcighaXMubmEodHlwZSksdHlwZSE9IkluLWJldHdlZW4iKSAlPiUgCiAgZ3JvdXBfYnkocHVibGljYXRpb25feWVhciwgdHlwZSwgaW5fZWVib190Y3ApICU+JSAKICB0YWxseSgpICU+JSAKICBtdXRhdGUocHJvcCA9IG4gLyBzdW0obiksIHRuID0gc3VtKG4pKSAlPiUgCiAgZmlsdGVyKGluX2VlYm9fdGNwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBwdWJsaWNhdGlvbl95ZWFyLCB5ID0gcHJvcCwgY29sb3IgPSB0eXBlKSkgKwogIGdlb21fc21vb3RoKGFlcyh3ZWlnaHQgPSBuLCBmaWxsID0gdHlwZSksIHNwYW4gPSAwLjMsIG1ldGhvZD0nbG9lc3MnLGZvcm11bGE9eX54KSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJncmF5Iiwgc2hhcGUgPSAyMSwgYWVzKHNpemUgPSB0bikpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gbikpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLCBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjA1KSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRUVCTy1UQ1AgY292ZXJhZ2UiKSArCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDApLCBsZWdlbmQuYm94Lmp1c3QgPSAiYm90dG9tIiwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjA1LCAwLjAyKSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICsKICBsYWJzKGNvbG9yID0gTlVMTCwgc2l6ZSA9IE5VTEwsIHNoYXBlID0gTlVMTCwgZmlsbCA9IE5VTEwpICsKICBzY2FsZV9zaXplKGJyZWFrcyA9IGMoNTAwLCAyMDAwLCAzNTAwKSwgcmFuZ2UgPSBjKDAuMSwgOC4wKSkKYGBgCkZvciBFRUJPLVRDUCwgb24gdGhlIHdvcmsgbGV2ZWwsIHRoZSBzYW1lIGRyb3AgaW4gY292ZXJhZ2UgZm9yIHBhbXBobGV0cyBhdCB0aGUgZW5kIG9mIHRoZSAxN3RoIGNlbnR1cnkgY2FuIGJlIHNlZW4sIGJ1dCBvdGhlcndpc2UgY292ZXJhZ2UgaXMgcmVsYXRpdmVseSBzdGFibGUgdGhyb3VnaCB0aW1lIGZvciBib3RoIGJvb2tzIGFzIHdlbGwgYXMgcGFtcGhsZXRzLCBleGNlcHQgZm9yIGEgbWFya2VkIHVwdGljayBiZXR3ZWVuIDE2NDAgYW5kIDE2NjAgKGNhdXNlZCBtb3N0IGxpa2VseSBieSBtb3JlIGp1ZGljaW91cyBpbmNsdXNpb24gb2YgdGhlIFRob21hc29uIFRyYWN0cykuIE9uIHRoZSB3b3JrIGxldmVsLCBwYW1waGxldHMgYXJlIGp1c3Qgc2xpZ2h0bHkgYmV0dGVyIGNvdmVyZWQgdGhhbiBib29rcywgYnV0IG9uIHRoZSBvbiB0aGUgZWRpdGlvbiBsZXZlbCwgY292ZXJhZ2Ugb2YgYm9va3MgaXMgbXVjaCBsb3dlci4gVGhpcyBjYW4gYmUgc2VlbiBhcyBvbmx5IHRoZSBuYXR1cmFsIGNvbnNlcXVlbmNlIG9mIEVFQk8tVENQIGZhdm91cmluZyBpbmNsdWRpbmcgb25seSBmaXJzdCBlZGl0aW9ucy4gQm9va3MgdHlwaWNhbGx5IGhhdmUgbW9yZSBlZGl0aW9ucyB0aGFuIHBhbXBobGV0cywgc28gZXhjbHVkaW5nIGxhdGVyIGVkaXRpb25zIGFmZmVjdHMgZWRpdGlvbi1sZXZlbCBjb3ZlcmFnZSBmb3IgYm9va3MgbXVjaCBtb3JlIHRoYW4gaXQgZG9lcyBmb3IgcGFtcGhsZXRzLgoKIyBUb3BpY2FsIGNvdmVyYWdlIEVFQk8tVENQIHZzIEVFQk8KCiMjIEVFQk8gd29yay1sZXZlbCBnZW5yZSB1c2UgZnJlcXVlbmNpZXMKCihzdWJzZXQgdGhhdCBpcyBpbiBFU1RDIHRvIGdldCB0aGUgd29yayBpbmZvcm1hdGlvbikKCmBgYHtyfQplZWJvX3VzdGNfZ2VucmVzICU+JSAKICBpbm5lcl9qb2luKGVlYm9fY29yZSxieT1jKCJlZWJvX2lkIikpICU+JQogIGlubmVyX2pvaW4oZXN0Y19jb3JlLGJ5PWMoImVzdGNfaWQiKSkgJT4lIAogIGdyb3VwX2J5KHVzdGNfZ2VucmUsaW5fZWVib190Y3ApICU+JQogIHN1bW1hcml6ZShuPW5fZGlzdGluY3Qod29ya19pZCksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGdyb3VwX2J5KHVzdGNfZ2VucmUpICU+JQogIG11dGF0ZSh0bj1zdW0obikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUodXN0Y19nZW5yZT1mY3RfcmVvcmRlcih1c3RjX2dlbnJlLHRuKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXVzdGNfZ2VucmUseT1uLGZpbGw9aW5fZWVib190Y3ApKSArIAogIGdlb21fY29sKHNob3cubGVnZW5kPUYpICsgCiAgeGxhYigiVVNUQyBnZW5yZSIpICsKICB5bGFiKCJOdW1iZXIgb2Ygd29ya3MiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6Om51bWJlcikgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKT3BlbiBxdWVzdGlvbjogYXJlIHRoZSBVU1RDIGNhdGVnb3JpZXMgdXNhYmxlPyBJcyB0aGlzIGEgYmVsaWV2YWJsZSBnZW5yZSBkaXN0cmlidXRpb24/IElmIGl0IGlzLCB0aGUgYmVsb3cgZ3JhcGhzIHNob3cgaW50ZXJlc3RpbmcgZGlmZmVyZW5jZSBhbmQgdGVtcG9yYWwgc2hpZnRzIGluIHRoZSBjb3ZlcmFnZSBvZiB0aGUgdmFyaW91cyBjYXRlZ29yaWVzLCB0aGUgaW50ZXJwcmV0YXRpb24gb2Ygd2hpY2ggSSBsZWF2ZSB1cCB0byB5b3UuIAoKIyMgRUVCTy1UQ1Agd29yay1sZXZlbCBnZW5yZSBjb3ZlcmFnZQoKYGBge3J9CmVlYm9fdXN0Y19nZW5yZXMgJT4lIAogICAgaW5uZXJfam9pbihlZWJvX2NvcmUsYnk9YygiZWVib19pZCIpKSAlPiUKICAgIGlubmVyX2pvaW4oZXN0Y19jb3JlLGJ5PWMoImVzdGNfaWQiKSkgJT4lCiAgZ3JvdXBfYnkod29ya19pZCx1c3RjX2dlbnJlKSAlPiUKICBzdW1tYXJpemUoaW5fZWVib190Y3A9YW55KCFpcy5uYShlZWJvX3RjcF9pZCkpLC5ncm91cHM9ImRyb3AiKSAlPiUKICBjb3VudCh1c3RjX2dlbnJlLGluX2VlYm9fdGNwKSAlPiUgCiAgZ3JvdXBfYnkodXN0Y19nZW5yZSkgJT4lCiAgbXV0YXRlKHByb3A9bi9zdW0obikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIoaW5fZWVib190Y3ApICU+JQogIG11dGF0ZSh1c3RjX2dlbnJlPWZjdF9yZW9yZGVyKHVzdGNfZ2VucmUscHJvcCkpICU+JQogIGdncGxvdChhZXMoeD11c3RjX2dlbnJlLHk9cHJvcCkpICsgCiAgZ2VvbV9jb2woKSArIAogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5PTEpKSArCiAgeGxhYigiVVNUQyBnZW5yZSIpICsKICB5bGFiKCJDb3ZlcmFnZSBpbiBFRUJPLVRDUCBieSB3b3JrIikgKwogIGNvb3JkX2ZsaXAoKSAKYGBgCgojIyBHZW5yZSBjb3ZlcmFnZSB0aHJvdWdoIHRpbWUKCmBgYHtyLGZpZy53aWR0aD0xMn0KZWVib19jb3JlICU+JSAKICBpbm5lcl9qb2luKGRmLGJ5PWMoImVzdGNfaWQiKSkgJT4lCiAgZmlsdGVyKGZpcnN0X3B1YmxpY2F0aW9uX3llYXI+MTQ3NCkgJT4lCiAgZ3JvdXBfYnkod29ya19pZCxmaXJzdF9wdWJsaWNhdGlvbl95ZWFyKSAlPiUKICBzdW1tYXJpemUoaW5fZWVibz1hbnkoaW5fZWVibyksaW5fZWVib190Y3A9YW55KGluX2VlYm9fdGNwKSxjZXJ0YWluPWFueShmaXJzdF95ZWFyX3B1YmxpY2F0aW9uICYgY2VydGFpbiksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGZpbHRlcihjZXJ0YWluKSAlPiUgCiAgbGVmdF9qb2luKGVlYm9fdXN0Y19nZW5yZXMgJT4lIAogICAgICAgICAgICAgIGlubmVyX2pvaW4oZWVib19jb3JlLGJ5PWMoImVlYm9faWQiKSkgJT4lCiAgICAgICAgICAgICAgaW5uZXJfam9pbihlc3RjX2NvcmUsYnk9YygiZXN0Y19pZCIpKSAlPiUKICAgICAgICAgICAgICBkaXN0aW5jdCh3b3JrX2lkLHVzdGNfZ2VucmUpICU+JQogICAgICAgICAgICAgIG11dGF0ZSh1c3RjX2dlbnJlPWZjdF9sdW1wX24odXN0Y19nZW5yZSwxMCkpLAogICAgICAgICAgICBieT1jKCJ3b3JrX2lkIikKICAgICAgICAgICAgKSAlPiUKICBtdXRhdGUodXN0Y19nZW5yZT1mY3RfZXhwbGljaXRfbmEodXN0Y19nZW5yZSwiVW5rbm93biIpKSAlPiUKICBncm91cF9ieShmaXJzdF9wdWJsaWNhdGlvbl95ZWFyLCB1c3RjX2dlbnJlLCBpbl9lZWJvX3RjcCkgJT4lIAogIHRhbGx5KCkgJT4lIAogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSwgdG4gPSBzdW0obikpICU+JSAKICBmaWx0ZXIoaW5fZWVib190Y3ApICU+JQogIGdncGxvdChhZXMoeCA9IGZpcnN0X3B1YmxpY2F0aW9uX3llYXIsIHkgPSBwcm9wLCBjb2xvciA9IHVzdGNfZ2VucmUpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJncmF5Iiwgc2hhcGUgPSAyMSwgYWVzKHNpemUgPSB0bikpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gbikpICsKICBnZW9tX3Ntb290aChhZXMod2VpZ2h0ID0gbiwgZmlsbCA9IHVzdGNfZ2VucmUpLCBzcGFuID0gMC4zLCBtZXRob2Q9J2xvZXNzJyxmb3JtdWxhPXl+eCkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMDAwLCAyMDAwLCBieSA9IDIwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksIGJyZWFrcyA9IHNlcSgwLCAxLCBieSA9IDAuMDUpKSArCiAgeGxhYigiWWVhciIpICsKICB5bGFiKCJFRUJPLVRDUCBjb3ZlcmFnZSIpICsKICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMCksIGxlZ2VuZC5ib3guanVzdCA9ICJib3R0b20iLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDUsIDAuMDIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIikgKwogIGxhYnMoY29sb3IgPSBOVUxMLCBzaXplID0gTlVMTCwgc2hhcGUgPSBOVUxMLCBmaWxsID0gTlVMTCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCwxKSkgKwogIHNjYWxlX3NpemUoYnJlYWtzID0gYygxMDAsIDUwMCwgMTAwMCksIHJhbmdlID0gYygwLjEsIDguMCkpICsKICBndWlkZXMoY29sb3I9Im5vbmUiLGZpbGw9Im5vbmUiKSArCiAgZmFjZXRfd3JhcCh+dXN0Y19nZW5yZSkKYGBgCgojIFRvcGljYWwgY292ZXJhZ2Ugb2YgRUVCTyB2cyBFU1RDIHRocm91Z2ggdGltZQoKSGVyZSwgd2UgYXJlIHByb2plY3Rpbmcgc3ViamVjdCBjYXRlZ29yeSBpbmZvcm1hdGlvbiBmcm9tIEVFQk8vRUNDTyB0aHJvdWdob3V0IHRoZSB3aG9sZSBvZiB0aGUgRVNUQyBpbiBvcmRlciB0byBjb21wYXJlIHRoZWlyIGNvdmVyYWdlLiBGb3IgdGhlIDE4dGggY2VudHVyeSBhbmQgRUNDTywgdGhpcyBzZWVtZWQgdG8gd29yayByZWxhdGl2ZWx5IHdlbGwgZm9yIGFsbCB0aGUgOCBjYXRlZ29yaWVzLiBGb3IgVVNUQy9FRUJPLCBJIHdhcyBjb21mb3J0YWJsZSBpbmNsdWRpbmcgb25seSB0aGUgcmVsaWdpb3VzL2hpc3RvcnkgYW5kIGNocm9uaWNsZXMgYW5kIGVjb25vbWljcyAtY2F0ZWdvcmllcy4KCiMjIFVzaW5nIHByb2plY3RlZCBFQ0NPIG1vZHVsZXMKCmBgYHtyLGluY2x1ZGU9Rn0KcGFrOjpwa2dfaW5zdGFsbCgiQ09NSElTL2VjY29yIikKbGlicmFyeShlY2NvcikKZWNjb19jb3JlIDwtIGxvYWRfZWNjb19jb3JlKCkKY29tYmluZWRfcHJvamVjdGVkX2VjY29fbW9kdWxlcyA8LSBlY2NvX2NvcmUgJT4lIAogIGlubmVyX2pvaW4oZXN0Y19jb3JlLGJ5PWMoImVzdGNfaWQiKSkgJT4lCiAgZGlzdGluY3Qod29ya19pZCxwcm9qZWN0ZWRfZWNjb19tb2R1bGU9ZWNjb19tb2R1bGUpCgpjb21iaW5lZF9wcm9qZWN0ZWRfZWNjb19tb2R1bGVzIDwtIGNvbWJpbmVkX3Byb2plY3RlZF9lY2NvX21vZHVsZXMgJT4lCiAgYmluZF9yb3dzKGVzdGNfcHJvamVjdGVkX2VjY29fbW9kdWxlcyAlPiUgCiAgICBmaWx0ZXIobWF4X3Byb3A+PTAuNykgJT4lCiAgICAgIHNlbGVjdCgtbWF4X3Byb3ApICU+JQogICAgICBhbnRpX2pvaW4oY29tYmluZWRfcHJvamVjdGVkX2VjY29fbW9kdWxlcyxieT1jKCJ3b3JrX2lkIikpKQpgYGAKCmBgYHtyLGZpZy53aWR0aD0xMn0KZGYgJT4lIAogIGZpbHRlcihmaXJzdF9wdWJsaWNhdGlvbl95ZWFyPjE0NzQpICU+JQogIGdyb3VwX2J5KHdvcmtfaWQsZmlyc3RfcHVibGljYXRpb25feWVhcikgJT4lCiAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksY2VydGFpbj1hbnkoZmlyc3RfeWVhcl9wdWJsaWNhdGlvbiAmIGNlcnRhaW4pLC5ncm91cHM9ImRyb3AiKSAlPiUKICBmaWx0ZXIoY2VydGFpbikgJT4lIAogIGxlZnRfam9pbihjb21iaW5lZF9wcm9qZWN0ZWRfZWNjb19tb2R1bGVzLGJ5PWMoIndvcmtfaWQiKSkgJT4lCiAgcmVwbGFjZV9uYShsaXN0KHByb2plY3RlZF9lY2NvX21vZHVsZT0iT3RoZXIvVW5rbm93biIpKSAlPiUKICBtdXRhdGUocHJvamVjdGVkX2VjY29fbW9kdWxlPWZjdF9yZWxldmVsKHByb2plY3RlZF9lY2NvX21vZHVsZSwiT3RoZXIvVW5rbm93biIpKSAlPiUKICBncm91cF9ieShmaXJzdF9wdWJsaWNhdGlvbl95ZWFyLCBwcm9qZWN0ZWRfZWNjb19tb2R1bGUsIGluX2VlYm8pICU+JSAKICB0YWxseSgpICU+JSAKICBtdXRhdGUocHJvcCA9IG4gLyBzdW0obiksIHRuID0gc3VtKG4pKSAlPiUgCiAgZmlsdGVyKGluX2VlYm8pICU+JQogIGdncGxvdChhZXMoeCA9IGZpcnN0X3B1YmxpY2F0aW9uX3llYXIsIHkgPSBwcm9wLCBjb2xvciA9IHByb2plY3RlZF9lY2NvX21vZHVsZSkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImdyYXkiLCBzaGFwZSA9IDIxLCBhZXMoc2l6ZSA9IHRuKSkgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBuKSkgKwogIGdlb21fc21vb3RoKGFlcyh3ZWlnaHQgPSBuLCBmaWxsID0gcHJvamVjdGVkX2VjY29fbW9kdWxlKSwgc3BhbiA9IDAuMywgbWV0aG9kPSdsb2VzcycsZm9ybXVsYT15fngpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLCBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjA1KSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRUVCTyBjb3ZlcmFnZSIpICsKICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMCksIGxlZ2VuZC5ib3guanVzdCA9ICJib3R0b20iLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDUsIDAuMDIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIikgKwogIGxhYnMoY29sb3IgPSBOVUxMLCBzaXplID0gTlVMTCwgc2hhcGUgPSBOVUxMLCBmaWxsID0gTlVMTCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMC41LDEpKSArICAKICBzY2FsZV9zaXplKGJyZWFrcyA9IGMoMTAwLCA1MDAsIDEwMDApLCByYW5nZSA9IGMoMC4xLCA4LjApKSArIAogIGd1aWRlcyhjb2xvcj0ibm9uZSIsZmlsbD0ibm9uZSIpICsKICBmYWNldF93cmFwKH5wcm9qZWN0ZWRfZWNjb19tb2R1bGUpCmBgYAoKIyMgVXNpbmcgcHJvamVjdGVkIFVTVEMgUmVsaWdpb3VzL0hpc3RvcnkgYW5kIGNocm9uaWNsZXMvRWNvbm9taWNzCgpgYGB7cixpbmNsdWRlPUZ9CnBhazo6cGtnX2luc3RhbGwoIkNPTUhJUy9lZWJvciIpCmxpYnJhcnkoZWVib3IpCmVlYm9fY29yZSA8LSBsb2FkX2VlYm9fY29yZSgpCmVlYm9fdXN0Y19nZW5yZXMgPC0gbG9hZF9lZWJvX3VzdGNfZ2VucmVzKCkKY29tYmluZWRfcHJvamVjdGVkX3VzdGNfZ2VucmVzIDwtIGVlYm9fdXN0Y19nZW5yZXMgJT4lCiAgaW5uZXJfam9pbihlZWJvX2NvcmUsYnk9YygiZWVib19pZCIpKSAlPiUKICBpbm5lcl9qb2luKGVzdGNfY29yZSxieT1jKCJlc3RjX2lkIikpICU+JQogIGRpc3RpbmN0KHdvcmtfaWQscHJvamVjdGVkX3VzdGNfZ2VucmU9dXN0Y19nZW5yZSkKCmNvbWJpbmVkX3Byb2plY3RlZF91c3RjX2dlbnJlcyA8LSBjb21iaW5lZF9wcm9qZWN0ZWRfdXN0Y19nZW5yZXMgJT4lCiAgYmluZF9yb3dzKGVzdGNfcHJvamVjdGVkX3VzdGNfZ2VucmVzICU+JSAKICAgIGZpbHRlcihtYXhfcHJvcD49MC43KSAlPiUKICAgICAgc2VsZWN0KC1tYXhfcHJvcCkgJT4lCiAgICAgIGFudGlfam9pbihjb21iaW5lZF9wcm9qZWN0ZWRfdXN0Y19nZW5yZXMsYnk9Yygid29ya19pZCIpKSkKYGBgCgpgYGB7cn0KZGYgJT4lIAogIGZpbHRlcihmaXJzdF9wdWJsaWNhdGlvbl95ZWFyPjE0NzQpICU+JQogIGdyb3VwX2J5KHdvcmtfaWQsZmlyc3RfcHVibGljYXRpb25feWVhcikgJT4lCiAgc3VtbWFyaXplKGluX2VlYm89YW55KGluX2VlYm8pLGluX2VlYm9fdGNwPWFueShpbl9lZWJvX3RjcCksY2VydGFpbj1hbnkoZmlyc3RfeWVhcl9wdWJsaWNhdGlvbiAmIGNlcnRhaW4pLC5ncm91cHM9ImRyb3AiKSAlPiUKICBmaWx0ZXIoY2VydGFpbikgJT4lIAogIGxlZnRfam9pbihlc3RjX3Byb2plY3RlZF91c3RjX2dlbnJlcyAlPiUgCiAgZmlsdGVyKG1heF9wcm9wPj0wLjcscHJvamVjdGVkX3VzdGNfZ2VucmUgJWluJSBjKCJSZWxpZ2lvdXMiLCJIaXN0b3J5IGFuZCBjaHJvbmljbGVzIiwiRWNvbm9taWNzIikpLGJ5PWMoIndvcmtfaWQiKSkgJT4lCiAgcmVwbGFjZV9uYShsaXN0KHByb2plY3RlZF91c3RjX2dlbnJlPSJPdGhlci9Vbmtub3duIikpICU+JQogIG11dGF0ZShwcm9qZWN0ZWRfdXN0Y19nZW5yZT1mY3RfcmVsZXZlbChwcm9qZWN0ZWRfdXN0Y19nZW5yZSwiT3RoZXIvVW5rbm93biIpKSAlPiUKICBncm91cF9ieShmaXJzdF9wdWJsaWNhdGlvbl95ZWFyLCBwcm9qZWN0ZWRfdXN0Y19nZW5yZSwgaW5fZWVibykgJT4lIAogIHRhbGx5KCkgJT4lIAogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSwgdG4gPSBzdW0obikpICU+JSAKICBmaWx0ZXIoaW5fZWVibykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmlyc3RfcHVibGljYXRpb25feWVhciwgeSA9IHByb3AsIGNvbG9yID0gcHJvamVjdGVkX3VzdGNfZ2VucmUpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJncmF5Iiwgc2hhcGUgPSAyMSwgYWVzKHNpemUgPSB0bikpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gbikpICsKICBnZW9tX3Ntb290aChhZXMod2VpZ2h0ID0gbiwgZmlsbCA9IHByb2plY3RlZF91c3RjX2dlbnJlKSwgc3BhbiA9IDAuMywgbWV0aG9kPSdsb2VzcycsZm9ybXVsYT15fngpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLCBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjA1KSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRUVCTyBjb3ZlcmFnZSIpICsKICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMCksIGxlZ2VuZC5ib3guanVzdCA9ICJib3R0b20iLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDUsIDAuMDIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIikgKwogIGxhYnMoY29sb3IgPSBOVUxMLCBzaXplID0gTlVMTCwgc2hhcGUgPSBOVUxMLCBmaWxsID0gTlVMTCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCwxKSkgKwogIHNjYWxlX3NpemUoYnJlYWtzID0gYygxMDAsIDUwMCwgMTAwMCksIHJhbmdlID0gYygwLjEsIDguMCkpCmBgYAoKIyBUb3BpY2FsIGNvdmVyYWdlIG9mIEVFQk8tVENQIHZzIEVTVEMgdGhyb3VnaCB0aW1lCgojIyBVc2luZyBwcm9qZWN0ZWQgRUNDTyBtb2R1bGVzCgpgYGB7cixmaWcud2lkdGg9MTJ9CmRmICU+JSAKICBmaWx0ZXIoZmlyc3RfcHVibGljYXRpb25feWVhcj4xNDc0KSAlPiUKICBncm91cF9ieSh3b3JrX2lkLGZpcnN0X3B1YmxpY2F0aW9uX3llYXIpICU+JQogIHN1bW1hcml6ZShpbl9lZWJvPWFueShpbl9lZWJvKSxpbl9lZWJvX3RjcD1hbnkoaW5fZWVib190Y3ApLGNlcnRhaW49YW55KGZpcnN0X3llYXJfcHVibGljYXRpb24gJiBjZXJ0YWluKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgZmlsdGVyKGNlcnRhaW4pICU+JSAKICBsZWZ0X2pvaW4oY29tYmluZWRfcHJvamVjdGVkX2VjY29fbW9kdWxlcyxieT1jKCJ3b3JrX2lkIikpICU+JQogIHJlcGxhY2VfbmEobGlzdChwcm9qZWN0ZWRfZWNjb19tb2R1bGU9Ik90aGVyL1Vua25vd24iKSkgJT4lCiAgbXV0YXRlKHByb2plY3RlZF9lY2NvX21vZHVsZT1mY3RfcmVsZXZlbChwcm9qZWN0ZWRfZWNjb19tb2R1bGUsIk90aGVyL1Vua25vd24iKSkgJT4lCiAgZ3JvdXBfYnkoZmlyc3RfcHVibGljYXRpb25feWVhciwgcHJvamVjdGVkX2VjY29fbW9kdWxlLCBpbl9lZWJvX3RjcCkgJT4lIAogIHRhbGx5KCkgJT4lIAogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSwgdG4gPSBzdW0obikpICU+JSAKICBmaWx0ZXIoaW5fZWVib190Y3ApICU+JQogIGdncGxvdChhZXMoeCA9IGZpcnN0X3B1YmxpY2F0aW9uX3llYXIsIHkgPSBwcm9wLCBjb2xvciA9IHByb2plY3RlZF9lY2NvX21vZHVsZSkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImdyYXkiLCBzaGFwZSA9IDIxLCBhZXMoc2l6ZSA9IHRuKSkgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBuKSkgKwogIGdlb21fc21vb3RoKGFlcyh3ZWlnaHQgPSBuLCBmaWxsID0gcHJvamVjdGVkX2VjY29fbW9kdWxlKSwgc3BhbiA9IDAuMywgbWV0aG9kPSdsb2VzcycsZm9ybXVsYT15fngpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLCBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjA1KSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRUVCTy1UQ1AgY292ZXJhZ2UiKSArCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDApLCBsZWdlbmQuYm94Lmp1c3QgPSAiYm90dG9tIiwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjA1LCAwLjAyKSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICsKICBsYWJzKGNvbG9yID0gTlVMTCwgc2l6ZSA9IE5VTEwsIHNoYXBlID0gTlVMTCwgZmlsbCA9IE5VTEwpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsMSkpICsKICBzY2FsZV9zaXplKGJyZWFrcyA9IGMoMTAwLCA1MDAsIDEwMDApLCByYW5nZSA9IGMoMC4xLCA4LjApKSArCiAgZ3VpZGVzKGNvbG9yPSJub25lIixmaWxsPSJub25lIikgKwogIGZhY2V0X3dyYXAofnByb2plY3RlZF9lY2NvX21vZHVsZSkKYGBgCgojIyBVc2luZyBwcm9qZWN0ZWQgVVNUQyBSZWxpZ2lvdXMvSGlzdG9yeSBhbmQgY2hyb25pY2xlcy9FY29ub21pY3MKCmBgYHtyfQpkZiAlPiUgCiAgZmlsdGVyKGZpcnN0X3B1YmxpY2F0aW9uX3llYXI+MTQ3NCkgJT4lCiAgZ3JvdXBfYnkod29ya19pZCxmaXJzdF9wdWJsaWNhdGlvbl95ZWFyKSAlPiUKICBzdW1tYXJpemUoaW5fZWVibz1hbnkoaW5fZWVibyksaW5fZWVib190Y3A9YW55KGluX2VlYm9fdGNwKSxjZXJ0YWluPWFueShmaXJzdF95ZWFyX3B1YmxpY2F0aW9uICYgY2VydGFpbiksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGZpbHRlcihjZXJ0YWluKSAlPiUgCiAgbGVmdF9qb2luKGNvbWJpbmVkX3Byb2plY3RlZF91c3RjX2dlbnJlcyAlPiUgCiAgZmlsdGVyKHByb2plY3RlZF91c3RjX2dlbnJlICVpbiUgYygiUmVsaWdpb3VzIiwiSGlzdG9yeSBhbmQgY2hyb25pY2xlcyIsIkVjb25vbWljcyIpKSxieT1jKCJ3b3JrX2lkIikpICU+JQogIHJlcGxhY2VfbmEobGlzdChwcm9qZWN0ZWRfdXN0Y19nZW5yZT0iT3RoZXIvVW5rbm93biIpKSAlPiUKICBtdXRhdGUocHJvamVjdGVkX3VzdGNfZ2VucmU9ZmN0X3JlbGV2ZWwocHJvamVjdGVkX3VzdGNfZ2VucmUsIk90aGVyL1Vua25vd24iKSkgJT4lCiAgZ3JvdXBfYnkoZmlyc3RfcHVibGljYXRpb25feWVhciwgcHJvamVjdGVkX3VzdGNfZ2VucmUsIGluX2VlYm9fdGNwKSAlPiUgCiAgdGFsbHkoKSAlPiUgCiAgbXV0YXRlKHByb3AgPSBuIC8gc3VtKG4pLCB0biA9IHN1bShuKSkgJT4lIAogIGZpbHRlcihpbl9lZWJvX3RjcCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmlyc3RfcHVibGljYXRpb25feWVhciwgeSA9IHByb3AsIGNvbG9yID0gcHJvamVjdGVkX3VzdGNfZ2VucmUpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJncmF5Iiwgc2hhcGUgPSAyMSwgYWVzKHNpemUgPSB0bikpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gbikpICsKICBnZW9tX3Ntb290aChhZXMod2VpZ2h0ID0gbiwgZmlsbCA9IHByb2plY3RlZF91c3RjX2dlbnJlKSwgc3BhbiA9IDAuMywgbWV0aG9kPSdsb2VzcycsZm9ybXVsYT15fngpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLCBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjA1KSkgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiRUVCTy1UQ1AgY292ZXJhZ2UiKSArCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDApLCBsZWdlbmQuYm94Lmp1c3QgPSAiYm90dG9tIiwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjA1LCAwLjAyKSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICsKICBsYWJzKGNvbG9yID0gTlVMTCwgc2l6ZSA9IE5VTEwsIHNoYXBlID0gTlVMTCwgZmlsbCA9IE5VTEwpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsMSkpICsKICBzY2FsZV9zaXplKGJyZWFrcyA9IGMoMTAwLCA1MDAsIDEwMDApLCByYW5nZSA9IGMoMC4xLCA4LjApKQpgYGAKKGNvbXBhcmUgdGhpcyB3aXRoIHRoZSByYXcgRUVCTy1UQ1AgdnMgRUVCTyBjb3ZlcmFnZSBhcyB3ZWxsIGFzIHRoZSBFQ0NPIG1vZHVsZSBjb3ZlcmFnZSBncmFwaHMp