Error : Table 'vd17.vd17_normalized_years_c' doesn't exist [1146]
Joining, by = "record_number"Joining, by = "record_number"

Creating local tables of vd17 normalized years, genres, languages and id.

vd17_normalized_years_local <- vd17_normalized_years_a %>%
  collect()
vd17_genres_local <- vd17_genres_a %>%
  collect()
vd17_normalized_langs_local <- vd17_normalized_langs_a %>%
  collect()
vd17_id_local <- vd17_id_a %>%
  collect()

FBS publications by year for all members.

The below plot depicts the number of publications (plus cumulative distribution) by whole FBS members by year.

publications_fbs_all <- fbs_all_links_local %>%
  left_join(vd17_normalized_years_local, by = c("record_number")) %>%
  filter(normalized_year >= 1600, normalized_year <= 1700) %>%
  filter(nchar(normalized_year)==4)%>%
  select (record_number,normalized_year,vd17_id,title,Member_number_new,First_name_new,Last_name_new,Society_name,Estimated_admission_year,Estimated_DOD,GND,role2,field_code)

pub_fbs_all <-publications_fbs_all %>%
  group_by(normalized_year) %>%
  summarize(records = n_distinct(record_number), .groups = "drop") %>%
  mutate(phase = case_when(
    normalized_year < 1617 ~ "< 1617",
    normalized_year >= 1617 & normalized_year <= 1650 ~ "phase 1",
    normalized_year >= 1651 & normalized_year <= 1667 ~ "phase 2",
    normalized_year >= 1668 & normalized_year <= 1682 ~ "phase 3",
    normalized_year > 1682 ~ "> 1682"
  ))

  ggplot(pub_fbs_all,aes(x=normalized_year, y=records, color = phase)) + 
  geom_step()+
  xlab("Year") + ylab("FBS-Publications (all)")+
  scale_x_continuous(breaks = seq(1000, 2000, by = 5))+
  theme_hsci_discrete()+
  theme(axis.text.x=element_text(angle=90,hjust=1,vjust=0.5))

  
  
  cumulative_frequencies_pub_all <- pub_fbs_all %>% 
  arrange(normalized_year) %>% 
  mutate(cum_frequency=cumsum(records))%>%
  mutate(phase = case_when(
    normalized_year < 1617 ~ "< 1617",
    normalized_year >= 1617 & normalized_year <= 1650 ~ "phase 1",
    normalized_year >= 1651 & normalized_year <= 1667 ~ "phase 2",
    normalized_year >= 1668 & normalized_year <= 1682 ~ "phase 3",
    normalized_year > 1682 ~ "> 1682"
  ))


ggplot(cumulative_frequencies_pub_all, aes(x=normalized_year, y=cum_frequency)) +
  geom_step()+
  xlab("Year") + ylab("FBS-Publications-CD (all)")+
  scale_x_continuous(breaks = seq(1000, 2000, by = 5))+
  theme_hsci_discrete()+
  theme(axis.text.x=element_text(angle=90,hjust=1,vjust=0.5))

FBS genres by year (all).

The below plot depicts the top genre of whole FBS publications by year.

genres_fbs_all <- fbs_all_links_local %>%
  left_join(vd17_normalized_years_local, by = c("record_number")) %>%
  filter(normalized_year >= 1600, normalized_year <= 1700) %>%
  filter(nchar(normalized_year)==4)%>%
  left_join(vd17_genres_local, by = c("record_number"))%>%
  select (record_number,normalized_year,vd17_id,title,Member_number_new,First_name_new,Last_name_new,Society_name,Estimated_admission_year,Estimated_DOD,GND,role2,field_code,genre)

genre_fbs_all <- gs4_create(
  "sheets-genre_fbs_all",
  sheets = genres_fbs_all)
✔ Creating new Sheet: sheets-genre_fbs_all.
genre_fbs_all
Spreadsheet name: sheets-genre_fbs_all
              ID: 11W7X4MRfDIyAu2UPOFiHgK4xgr--8nUaQ4AL3Bm5TNI
          Locale: en_US
       Time zone: Etc/GMT
     # of sheets: 1

  (Sheet name): (Nominal extent in rows x columns)
genres_fbs_all: 23599 x 14
phase_genres_fbs_all <- genres_fbs_all%>%
  select(record_number,normalized_year,genre)%>%
  distinct(record_number,normalized_year,genre)%>%
  na.omit(genres_fbs_all)%>%
  group_by(normalized_year) %>%
  count(genre)%>%
  arrange(desc(n))%>%
  mutate(phase = case_when(
    normalized_year < 1617 ~ "< 1617",
    normalized_year >= 1617 & normalized_year <= 1650 ~ "phase 1",
    normalized_year >= 1651 & normalized_year <= 1667 ~ "phase 2",
    normalized_year >= 1668 & normalized_year <= 1682 ~ "phase 3",
    normalized_year > 1682 ~ "> 1682"
  ))

phase_genres_fbs_all%>%
  slice(1:1)%>%
  ggplot(aes(x=normalized_year,y=n,fill=genre))+
  geom_col()+
  xlab("Year") + ylab("FBS-Top Genre_all")+
  scale_x_continuous(breaks = seq(1000, 2000, by = 5))+
  theme_hsci_discrete()+
  theme(axis.text.x=element_text(angle=90,hjust=1,vjust=0.5))+
  theme(legend.position="right",
        legend.key.width=unit(0.15, "cm"))+
  geom_text(aes(label = n), color = "black", size = 1, position = position_stack(vjust = 0.9)) 

Translated vs Non-Translated member publications_fbs (all).

The below plot depicts the Translated vs Non-Translated member publications of FBS.

trans_vs_non_trans <- fbs_all_links_local %>%
  left_join(vd17_normalized_years_local, by = c("record_number")) %>%
  filter(normalized_year >= 1600, normalized_year <= 1700) %>%
  filter(nchar(normalized_year)==4)%>%
  left_join(vd17_normalized_langs_local, by = c("record_number"))%>%
  select (record_number,normalized_year,vd17_id,title,Member_number_new,First_name_new,Last_name_new,Society_name,Estimated_admission_year,Estimated_DOD,GND,role2,field_code,original_language,publication_language)


trans_vs_non_trans$type <- is.na(trans_vs_non_trans$original_language)

trans_vs_non_trans$type[trans_vs_non_trans$type == "FALSE"] <- "Translated"
trans_vs_non_trans$type[trans_vs_non_trans$type == "TRUE"] <- "Non-Translated"

translated_vs_non_translated <- gs4_create(
  "sheets-translated_vs_non_translated_fbs",
  sheets = trans_vs_non_trans)
✔ Creating new Sheet: sheets-translated_vs_non_translated_fbs.
translated_vs_non_translated
Spreadsheet name: sheets-translated_vs_non_translated_fbs
              ID: 1sFSYxEPi8p9szQo5QfLHOLtqqmFLeVoeKu5h1H7RwdM
          Locale: en_US
       Time zone: Etc/GMT
     # of sheets: 1

      (Sheet name): (Nominal extent in rows x columns)
trans_vs_non_trans: 14678 x 16
trans_vs_non_trans%>%
distinct(record_number,normalized_year,type)%>%
select(normalized_year,type)%>%
group_by(normalized_year)%>%
count(type)%>%
arrange(desc(n))%>%
ggplot(aes(x=normalized_year,y=n, fill=type)) + 
geom_col()+
labs(y = "Translated vs Non-Translated FBS", x= "Years")+
scale_x_continuous(breaks = seq(1000, 2000, by = 5))+
theme_hsci_discrete()+
theme(axis.text.x=element_text(angle=90,hjust=1,vjust=0.5))+
theme(legend.position="bottom",
        legend.key.width=unit(0.15, "cm"))+
geom_text(aes(label = n), color = "green", size = 1.8, position = position_stack(vjust = 0.9)) 

Translated vs Non-Translated member publications_fbs (all) (Percentage by year).

trans_non_trans_percentage <- trans_vs_non_trans%>%
  distinct(record_number,normalized_year,type)%>%
  select(normalized_year,type)%>%
  mutate(type = factor(type)) %>%
  count(normalized_year, type, .drop = FALSE, name = 'Percentage') %>%
  group_by(normalized_year) %>%
  mutate(Percentage = round(Percentage/sum(Percentage) * 100),2)

translated_non_translated_percentage <- gs4_create(
  "sheets-translated_non_translated_percentage_fbs",
  sheets = trans_non_trans_percentage)
✔ Creating new Sheet: sheets-translated_non_translated_percentage_fbs.
translated_non_translated_percentage
Spreadsheet name: sheets-translated_non_translated_percentage_fbs
              ID: 1lngxNQmTxVjsKYyXtPeHlfhY4T_FVFlVcQeTUffBSUo
          Locale: en_US
       Time zone: Etc/GMT
     # of sheets: 1

              (Sheet name): (Nominal extent in rows x columns)
trans_non_trans_percentage: 201 x 4

Translated vs Non-Translated member publications_fbs (all) (Percentage by whole).

print(c("Translated",round(sum(trans_vs_non_trans$type=="Translated")/length(trans_vs_non_trans$type)*100,2)))
[1] "Translated" "2.95"      
print(c("Non-Translated",round(sum(trans_vs_non_trans$type=="Non-Translated")/length(trans_vs_non_trans$type)*100,2)))
[1] "Non-Translated" "97.05"         
LS0tCnRpdGxlOiAiRkJTIGFuYWx5c2lzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKLS0tCgpgYGB7ciBzZXR1cCxlY2hvPUZ9CmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gaGVyZTo6aGVyZSgpKQpsaWJyYXJ5KGhlcmUpCnNvdXJjZShoZXJlKCJjb2RlL2NvbW1vbl9iYXNpcy5SIiksIGxvY2FsID0ga25pdHI6OmtuaXRfZ2xvYmFsKCkpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdnaHNjaSkKbGlicmFyeShndCkKcCA8LSBmdW5jdGlvbihudW1iZXIpIHsKICByZXR1cm4oZm9ybWF0KG51bWJlciwgc2NpZW50aWZpYyA9IEZBTFNFLCBiaWcubWFyayA9ICIsIikpCn0KcHAgPC0gZnVuY3Rpb24ocGVyY2VudGFnZSwgYWNjdXJhY3kgPSAwLjAxKSB7CiAgcmV0dXJuKHNjYWxlczo6cGVyY2VudChwZXJjZW50YWdlLCBhY2N1cmFjeSA9IGFjY3VyYWN5KSkKfQpgYGAKCiMgSm9pbmluZyB2ZDE3X2lkIGFuZCB2ZDE3X3RpdGxlcyB0YWJsZXMgd2l0aCBmYnNfbGlua3Nfb2ZfaW50ZXJlc3QgCmBgYHtyfQpmYnNfbGlua3Nfb2ZfaW50ZXJlc3RfbG9jYWwgPC0gZmJzX2xpbmtzX29mX2ludGVyZXN0X2EgJT4lCiAgaW5uZXJfam9pbihmYnNfbWV0YWRhdGFfYSAlPiUgc2VsZWN0KEdORCxNZW1iZXJfbnVtYmVyX25ldyxGaXJzdF9uYW1lX25ldyxMYXN0X25hbWVfbmV3LFNvY2lldHlfbmFtZSxFc3RpbWF0ZWRfYWRtaXNzaW9uX3llYXIsRXN0aW1hdGVkX0RPRCkgJT4lIG11dGF0ZShHTkQgPSBzdHJfYygiZ25kLyIsIEdORCkpKSAlPiUKICBpbm5lcl9qb2luKHZkMTdfaWRfYSkgJT4lCiAgaW5uZXJfam9pbih2ZDE3X3RpdGxlc19hICU+JSBzZWxlY3QocmVjb3JkX251bWJlcix0aXRsZSkpICU+JQogIGNvbGxlY3QoKSAlPiUKICBzZWxlY3Qod2hlcmUofiFhbGwoaXMubmEoLngpKSkpCgpmYnNfbGlua3Nfb2ZfaW50ZXJlc3RfbG9jYWwgPC0gc2VsZWN0IChmYnNfbGlua3Nfb2ZfaW50ZXJlc3RfbG9jYWwsIGMoJ3JlY29yZF9udW1iZXInLCd2ZDE3X2lkJywndGl0bGUnLCdNZW1iZXJfbnVtYmVyX25ldycsJ0ZpcnN0X25hbWVfbmV3JywgJ0xhc3RfbmFtZV9uZXcnLCdTb2NpZXR5X25hbWUnLCdHTkQnLCdFc3RpbWF0ZWRfYWRtaXNzaW9uX3llYXInLCdFc3RpbWF0ZWRfRE9EJywncm9sZTInLCdmaWVsZF9jb2RlJykpCmBgYAojIEpvaW5pbmcgdmQxN19pZCBhbmQgdmQxN190aXRsZXMgdGFibGVzIHdpdGggd2hvbGUgRkJTIChub3QgbGlua3Nfb2ZfaW50ZXJlc3QpCmBgYHtyfQpmYnNfYWxsX2xpbmtzX2xvY2FsIDwtIGZic19saW5rc19hICU+JQogIGlubmVyX2pvaW4oZmJzX21ldGFkYXRhX2EgJT4lIHNlbGVjdChHTkQsTWVtYmVyX251bWJlcl9uZXcsRmlyc3RfbmFtZV9uZXcsTGFzdF9uYW1lX25ldyxTb2NpZXR5X25hbWUsRXN0aW1hdGVkX2FkbWlzc2lvbl95ZWFyLEVzdGltYXRlZF9ET0QpICU+JSBtdXRhdGUoR05EID0gc3RyX2MoImduZC8iLCBHTkQpKSkgJT4lCiAgaW5uZXJfam9pbih2ZDE3X2lkX2EpICU+JQogIGlubmVyX2pvaW4odmQxN190aXRsZXNfYSAlPiUgc2VsZWN0KHJlY29yZF9udW1iZXIsdGl0bGUpKSAlPiUKICBjb2xsZWN0KCkgJT4lCiAgc2VsZWN0KHdoZXJlKH4hYWxsKGlzLm5hKC54KSkpKQoKZmJzX2FsbF9saW5rc19sb2NhbCA8LSBzZWxlY3QgKGZic19hbGxfbGlua3NfbG9jYWwsIGMoJ3JlY29yZF9udW1iZXInLCd2ZDE3X2lkJywndGl0bGUnLCdNZW1iZXJfbnVtYmVyX25ldycsJ0ZpcnN0X25hbWVfbmV3JywgJ0xhc3RfbmFtZV9uZXcnLCdTb2NpZXR5X25hbWUnLCdHTkQnLCdFc3RpbWF0ZWRfYWRtaXNzaW9uX3llYXInLCdFc3RpbWF0ZWRfRE9EJywncm9sZTInLCdmaWVsZF9jb2RlJykpCmBgYAojIENyZWF0aW5nIGxvY2FsIHRhYmxlcyBvZiB2ZDE3IG5vcm1hbGl6ZWQgeWVhcnMsIGdlbnJlcywgbGFuZ3VhZ2VzIGFuZCBpZC4KYGBge3J9CnZkMTdfbm9ybWFsaXplZF95ZWFyc19sb2NhbCA8LSB2ZDE3X25vcm1hbGl6ZWRfeWVhcnNfYSAlPiUKICBjb2xsZWN0KCkKdmQxN19nZW5yZXNfbG9jYWwgPC0gdmQxN19nZW5yZXNfYSAlPiUKICBjb2xsZWN0KCkKdmQxN19ub3JtYWxpemVkX2xhbmdzX2xvY2FsIDwtIHZkMTdfbm9ybWFsaXplZF9sYW5nc19hICU+JQogIGNvbGxlY3QoKQp2ZDE3X2lkX2xvY2FsIDwtIHZkMTdfaWRfYSAlPiUKICBjb2xsZWN0KCkKYGBgCgojIEZCUyBwdWJsaWNhdGlvbnMgYnkgeWVhciBmb3IgbWVtYmVycyAobGlua3Mgb2YgaW50ZXJlc3QpLgojIFRoZSBiZWxvdyBwbG90IGRlcGljdHMgdGhlIG51bWJlciBvZiBwdWJsaWNhdGlvbnMgKHBsdXMgY3VtdWxhdGl2ZSBkaXN0cmlidXRpb24pIGJ5IEZCUyBtZW1iZXJzIGJ5IHllYXIgZm9yIGxpbmtzIG9mIGludGVyZXN0LiAKYGBge3J9CnB1YmxpY2F0aW9uc19mYnMgPC0gZmJzX2xpbmtzX29mX2ludGVyZXN0X2xvY2FsICU+JQogIGxlZnRfam9pbih2ZDE3X25vcm1hbGl6ZWRfeWVhcnNfbG9jYWwsIGJ5ID0gYygicmVjb3JkX251bWJlciIpKSAlPiUKICBmaWx0ZXIobm9ybWFsaXplZF95ZWFyID49IDE2MDAsIG5vcm1hbGl6ZWRfeWVhciA8PSAxNzAwKSAlPiUKICBmaWx0ZXIobmNoYXIobm9ybWFsaXplZF95ZWFyKT09NCklPiUKICBzZWxlY3QgKHJlY29yZF9udW1iZXIsbm9ybWFsaXplZF95ZWFyLHZkMTdfaWQsdGl0bGUsTWVtYmVyX251bWJlcl9uZXcsRmlyc3RfbmFtZV9uZXcsTGFzdF9uYW1lX25ldyxTb2NpZXR5X25hbWUsRXN0aW1hdGVkX2FkbWlzc2lvbl95ZWFyLEVzdGltYXRlZF9ET0QsR05ELHJvbGUyLGZpZWxkX2NvZGUpCgpwdWJfZmJzIDwtcHVibGljYXRpb25zX2ZicyAlPiUKICBncm91cF9ieShub3JtYWxpemVkX3llYXIpICU+JQogIHN1bW1hcml6ZShyZWNvcmRzID0gbl9kaXN0aW5jdChyZWNvcmRfbnVtYmVyKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgbXV0YXRlKHBoYXNlID0gY2FzZV93aGVuKAogICAgbm9ybWFsaXplZF95ZWFyIDwgMTYxNyB+ICI8IDE2MTciLAogICAgbm9ybWFsaXplZF95ZWFyID49IDE2MTcgJiBub3JtYWxpemVkX3llYXIgPD0gMTY1MCB+ICJwaGFzZSAxIiwKICAgIG5vcm1hbGl6ZWRfeWVhciA+PSAxNjUxICYgbm9ybWFsaXplZF95ZWFyIDw9IDE2NjcgfiAicGhhc2UgMiIsCiAgICBub3JtYWxpemVkX3llYXIgPj0gMTY2OCAmIG5vcm1hbGl6ZWRfeWVhciA8PSAxNjgyIH4gInBoYXNlIDMiLAogICAgbm9ybWFsaXplZF95ZWFyID4gMTY4MiB+ICI+IDE2ODIiCiAgKSkKCiAgZ2dwbG90KHB1Yl9mYnMsYWVzKHg9bm9ybWFsaXplZF95ZWFyLCB5PXJlY29yZHMsIGNvbG9yID0gcGhhc2UpKSArIAogIGdlb21fc3RlcCgpKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIkZCUy1QdWJsaWNhdGlvbnMobGlua3Mgb2YgaW50ZXJlc3QpIikrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMDAwLCAyMDAwLCBieSA9IDUpKSsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkrCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEsdmp1c3Q9MC41KSkKICAKICBjdW11bGF0aXZlX2ZyZXF1ZW5jaWVzX3B1YiA8LSBwdWJfZmJzICU+JSAKICBhcnJhbmdlKG5vcm1hbGl6ZWRfeWVhcikgJT4lIAogIG11dGF0ZShjdW1fZnJlcXVlbmN5PWN1bXN1bShyZWNvcmRzKSklPiUKICBtdXRhdGUocGhhc2UgPSBjYXNlX3doZW4oCiAgICBub3JtYWxpemVkX3llYXIgPCAxNjE3IH4gIjwgMTYxNyIsCiAgICBub3JtYWxpemVkX3llYXIgPj0gMTYxNyAmIG5vcm1hbGl6ZWRfeWVhciA8PSAxNjUwIH4gInBoYXNlIDEiLAogICAgbm9ybWFsaXplZF95ZWFyID49IDE2NTEgJiBub3JtYWxpemVkX3llYXIgPD0gMTY2NyB+ICJwaGFzZSAyIiwKICAgIG5vcm1hbGl6ZWRfeWVhciA+PSAxNjY4ICYgbm9ybWFsaXplZF95ZWFyIDw9IDE2ODIgfiAicGhhc2UgMyIsCiAgICBub3JtYWxpemVkX3llYXIgPiAxNjgyIH4gIj4gMTY4MiIKICApKQoKCmdncGxvdChjdW11bGF0aXZlX2ZyZXF1ZW5jaWVzX3B1YiwgYWVzKHg9bm9ybWFsaXplZF95ZWFyLCB5PWN1bV9mcmVxdWVuY3kpKSArCiAgZ2VvbV9zdGVwKCkrCiAgeGxhYigiWWVhciIpICsgeWxhYigiRkJTLVB1YmxpY2F0aW9ucy1DRCAobGlua3Mgb2YgaW50ZXJlc3QpIikrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMDAwLCAyMDAwLCBieSA9IDUpKSsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkrCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEsdmp1c3Q9MC41KSkKYGBgCiMgRkJTIHB1YmxpY2F0aW9ucyBieSB5ZWFyIGZvciBhbGwgbWVtYmVycy4gCiMgVGhlIGJlbG93IHBsb3QgZGVwaWN0cyB0aGUgbnVtYmVyIG9mIHB1YmxpY2F0aW9ucyAocGx1cyBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbikgYnkgd2hvbGUgRkJTIG1lbWJlcnMgYnkgeWVhci4gCmBgYHtyfQpwdWJsaWNhdGlvbnNfZmJzX2FsbCA8LSBmYnNfYWxsX2xpbmtzX2xvY2FsICU+JQogIGxlZnRfam9pbih2ZDE3X25vcm1hbGl6ZWRfeWVhcnNfbG9jYWwsIGJ5ID0gYygicmVjb3JkX251bWJlciIpKSAlPiUKICBmaWx0ZXIobm9ybWFsaXplZF95ZWFyID49IDE2MDAsIG5vcm1hbGl6ZWRfeWVhciA8PSAxNzAwKSAlPiUKICBmaWx0ZXIobmNoYXIobm9ybWFsaXplZF95ZWFyKT09NCklPiUKICBzZWxlY3QgKHJlY29yZF9udW1iZXIsbm9ybWFsaXplZF95ZWFyLHZkMTdfaWQsdGl0bGUsTWVtYmVyX251bWJlcl9uZXcsRmlyc3RfbmFtZV9uZXcsTGFzdF9uYW1lX25ldyxTb2NpZXR5X25hbWUsRXN0aW1hdGVkX2FkbWlzc2lvbl95ZWFyLEVzdGltYXRlZF9ET0QsR05ELHJvbGUyLGZpZWxkX2NvZGUpCgpwdWJfZmJzX2FsbCA8LXB1YmxpY2F0aW9uc19mYnNfYWxsICU+JQogIGdyb3VwX2J5KG5vcm1hbGl6ZWRfeWVhcikgJT4lCiAgc3VtbWFyaXplKHJlY29yZHMgPSBuX2Rpc3RpbmN0KHJlY29yZF9udW1iZXIpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUKICBtdXRhdGUocGhhc2UgPSBjYXNlX3doZW4oCiAgICBub3JtYWxpemVkX3llYXIgPCAxNjE3IH4gIjwgMTYxNyIsCiAgICBub3JtYWxpemVkX3llYXIgPj0gMTYxNyAmIG5vcm1hbGl6ZWRfeWVhciA8PSAxNjUwIH4gInBoYXNlIDEiLAogICAgbm9ybWFsaXplZF95ZWFyID49IDE2NTEgJiBub3JtYWxpemVkX3llYXIgPD0gMTY2NyB+ICJwaGFzZSAyIiwKICAgIG5vcm1hbGl6ZWRfeWVhciA+PSAxNjY4ICYgbm9ybWFsaXplZF95ZWFyIDw9IDE2ODIgfiAicGhhc2UgMyIsCiAgICBub3JtYWxpemVkX3llYXIgPiAxNjgyIH4gIj4gMTY4MiIKICApKQoKICBnZ3Bsb3QocHViX2Zic19hbGwsYWVzKHg9bm9ybWFsaXplZF95ZWFyLCB5PXJlY29yZHMsIGNvbG9yID0gcGhhc2UpKSArIAogIGdlb21fc3RlcCgpKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIkZCUy1QdWJsaWNhdGlvbnMgKGFsbCkiKSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwMDAsIDIwMDAsIGJ5ID0gNSkpKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTAsaGp1c3Q9MSx2anVzdD0wLjUpKQogIAogIAogIGN1bXVsYXRpdmVfZnJlcXVlbmNpZXNfcHViX2FsbCA8LSBwdWJfZmJzX2FsbCAlPiUgCiAgYXJyYW5nZShub3JtYWxpemVkX3llYXIpICU+JSAKICBtdXRhdGUoY3VtX2ZyZXF1ZW5jeT1jdW1zdW0ocmVjb3JkcykpJT4lCiAgbXV0YXRlKHBoYXNlID0gY2FzZV93aGVuKAogICAgbm9ybWFsaXplZF95ZWFyIDwgMTYxNyB+ICI8IDE2MTciLAogICAgbm9ybWFsaXplZF95ZWFyID49IDE2MTcgJiBub3JtYWxpemVkX3llYXIgPD0gMTY1MCB+ICJwaGFzZSAxIiwKICAgIG5vcm1hbGl6ZWRfeWVhciA+PSAxNjUxICYgbm9ybWFsaXplZF95ZWFyIDw9IDE2NjcgfiAicGhhc2UgMiIsCiAgICBub3JtYWxpemVkX3llYXIgPj0gMTY2OCAmIG5vcm1hbGl6ZWRfeWVhciA8PSAxNjgyIH4gInBoYXNlIDMiLAogICAgbm9ybWFsaXplZF95ZWFyID4gMTY4MiB+ICI+IDE2ODIiCiAgKSkKCgpnZ3Bsb3QoY3VtdWxhdGl2ZV9mcmVxdWVuY2llc19wdWJfYWxsLCBhZXMoeD1ub3JtYWxpemVkX3llYXIsIHk9Y3VtX2ZyZXF1ZW5jeSkpICsKICBnZW9tX3N0ZXAoKSsKICB4bGFiKCJZZWFyIikgKyB5bGFiKCJGQlMtUHVibGljYXRpb25zLUNEIChhbGwpIikrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMDAwLCAyMDAwLCBieSA9IDUpKSsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkrCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEsdmp1c3Q9MC41KSkKYGBgCiMgRkJTIGdlbnJlcyBieSB5ZWFyIChsaW5rcyBvZiBpbnRlcmVzdCkuCiMgVGhlIGJlbG93IHBsb3QgZGVwaWN0cyB0aGUgdG9wIGdlbnJlIG9mIEZCUyBwdWJsaWNhdGlvbnMgYnkgeWVhciBmb3IgbGlua3Mgb2YgaW50ZXJlc3QuCmBgYHtyfQpnZW5yZXNfZmJzIDwtIGZic19saW5rc19vZl9pbnRlcmVzdF9sb2NhbCAlPiUKICBsZWZ0X2pvaW4odmQxN19ub3JtYWxpemVkX3llYXJzX2xvY2FsLCBieSA9IGMoInJlY29yZF9udW1iZXIiKSkgJT4lCiAgZmlsdGVyKG5vcm1hbGl6ZWRfeWVhciA+PSAxNjAwLCBub3JtYWxpemVkX3llYXIgPD0gMTcwMCkgJT4lCiAgZmlsdGVyKG5jaGFyKG5vcm1hbGl6ZWRfeWVhcik9PTQpJT4lCiAgbGVmdF9qb2luKHZkMTdfZ2VucmVzX2xvY2FsLCBieSA9IGMoInJlY29yZF9udW1iZXIiKSklPiUKICBzZWxlY3QgKHJlY29yZF9udW1iZXIsbm9ybWFsaXplZF95ZWFyLHZkMTdfaWQsdGl0bGUsTWVtYmVyX251bWJlcl9uZXcsRmlyc3RfbmFtZV9uZXcsTGFzdF9uYW1lX25ldyxTb2NpZXR5X25hbWUsRXN0aW1hdGVkX2FkbWlzc2lvbl95ZWFyLEVzdGltYXRlZF9ET0QsR05ELHJvbGUyLGZpZWxkX2NvZGUsZ2VucmUpCgpnZW5yZV9mYnNfbGlua3Nfb2ZfaW50ZXJlc3QgPC0gZ3M0X2NyZWF0ZSgKICAic2hlZXRzLWdlbnJlX2Zic19saW5rc19vZl9pbnRlcmVzdCIsCiAgc2hlZXRzID0gZ2VucmVzX2ZicykKCmdlbnJlX2Zic19saW5rc19vZl9pbnRlcmVzdAoKcGhhc2VfZ2VucmVzX2ZicyA8LSBnZW5yZXNfZmJzJT4lCiAgc2VsZWN0KHJlY29yZF9udW1iZXIsbm9ybWFsaXplZF95ZWFyLGdlbnJlKSU+JQogIGRpc3RpbmN0KHJlY29yZF9udW1iZXIsbm9ybWFsaXplZF95ZWFyLGdlbnJlKSU+JQogIG5hLm9taXQoZ2VucmVzX2ZicyklPiUKICBncm91cF9ieShub3JtYWxpemVkX3llYXIpICU+JQogIGNvdW50KGdlbnJlKSU+JQogIGFycmFuZ2UoZGVzYyhuKSklPiUKICBtdXRhdGUocGhhc2UgPSBjYXNlX3doZW4oCiAgICBub3JtYWxpemVkX3llYXIgPCAxNjE3IH4gIjwgMTYxNyIsCiAgICBub3JtYWxpemVkX3llYXIgPj0gMTYxNyAmIG5vcm1hbGl6ZWRfeWVhciA8PSAxNjUwIH4gInBoYXNlIDEiLAogICAgbm9ybWFsaXplZF95ZWFyID49IDE2NTEgJiBub3JtYWxpemVkX3llYXIgPD0gMTY2NyB+ICJwaGFzZSAyIiwKICAgIG5vcm1hbGl6ZWRfeWVhciA+PSAxNjY4ICYgbm9ybWFsaXplZF95ZWFyIDw9IDE2ODIgfiAicGhhc2UgMyIsCiAgICBub3JtYWxpemVkX3llYXIgPiAxNjgyIH4gIj4gMTY4MiIKICApKQoKCnBoYXNlX2dlbnJlc19mYnMlPiUKICBzbGljZSgxOjEpJT4lCiAgZ2dwbG90KGFlcyh4PW5vcm1hbGl6ZWRfeWVhcix5PW4sZmlsbD1nZW5yZSkpKwogIGdlb21fY29sKCkrCiAgeGxhYigiWWVhciIpICsgeWxhYigiRkJTLVRvcCBHZW5yZV9saW5rc19vZl9pbnRlcmVzdCIpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSA1KSkrCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCxoanVzdD0xLHZqdXN0PTAuNSkpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiLAogICAgICAgIGxlZ2VuZC5rZXkud2lkdGg9dW5pdCgwLjE1LCAiY20iKSkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC45KSkgCmBgYAoKIyBGQlMgZ2VucmVzIGJ5IHllYXIgKGFsbCkuCiMgVGhlIGJlbG93IHBsb3QgZGVwaWN0cyB0aGUgdG9wIGdlbnJlIG9mIHdob2xlIEZCUyBwdWJsaWNhdGlvbnMgYnkgeWVhci4KYGBge3J9CmdlbnJlc19mYnNfYWxsIDwtIGZic19hbGxfbGlua3NfbG9jYWwgJT4lCiAgbGVmdF9qb2luKHZkMTdfbm9ybWFsaXplZF95ZWFyc19sb2NhbCwgYnkgPSBjKCJyZWNvcmRfbnVtYmVyIikpICU+JQogIGZpbHRlcihub3JtYWxpemVkX3llYXIgPj0gMTYwMCwgbm9ybWFsaXplZF95ZWFyIDw9IDE3MDApICU+JQogIGZpbHRlcihuY2hhcihub3JtYWxpemVkX3llYXIpPT00KSU+JQogIGxlZnRfam9pbih2ZDE3X2dlbnJlc19sb2NhbCwgYnkgPSBjKCJyZWNvcmRfbnVtYmVyIikpJT4lCiAgc2VsZWN0IChyZWNvcmRfbnVtYmVyLG5vcm1hbGl6ZWRfeWVhcix2ZDE3X2lkLHRpdGxlLE1lbWJlcl9udW1iZXJfbmV3LEZpcnN0X25hbWVfbmV3LExhc3RfbmFtZV9uZXcsU29jaWV0eV9uYW1lLEVzdGltYXRlZF9hZG1pc3Npb25feWVhcixFc3RpbWF0ZWRfRE9ELEdORCxyb2xlMixmaWVsZF9jb2RlLGdlbnJlKQoKZ2VucmVfZmJzX2FsbCA8LSBnczRfY3JlYXRlKAogICJzaGVldHMtZ2VucmVfZmJzX2FsbCIsCiAgc2hlZXRzID0gZ2VucmVzX2Zic19hbGwpCgpnZW5yZV9mYnNfYWxsCgpwaGFzZV9nZW5yZXNfZmJzX2FsbCA8LSBnZW5yZXNfZmJzX2FsbCU+JQogIHNlbGVjdChyZWNvcmRfbnVtYmVyLG5vcm1hbGl6ZWRfeWVhcixnZW5yZSklPiUKICBkaXN0aW5jdChyZWNvcmRfbnVtYmVyLG5vcm1hbGl6ZWRfeWVhcixnZW5yZSklPiUKICBuYS5vbWl0KGdlbnJlc19mYnNfYWxsKSU+JQogIGdyb3VwX2J5KG5vcm1hbGl6ZWRfeWVhcikgJT4lCiAgY291bnQoZ2VucmUpJT4lCiAgYXJyYW5nZShkZXNjKG4pKSU+JQogIG11dGF0ZShwaGFzZSA9IGNhc2Vfd2hlbigKICAgIG5vcm1hbGl6ZWRfeWVhciA8IDE2MTcgfiAiPCAxNjE3IiwKICAgIG5vcm1hbGl6ZWRfeWVhciA+PSAxNjE3ICYgbm9ybWFsaXplZF95ZWFyIDw9IDE2NTAgfiAicGhhc2UgMSIsCiAgICBub3JtYWxpemVkX3llYXIgPj0gMTY1MSAmIG5vcm1hbGl6ZWRfeWVhciA8PSAxNjY3IH4gInBoYXNlIDIiLAogICAgbm9ybWFsaXplZF95ZWFyID49IDE2NjggJiBub3JtYWxpemVkX3llYXIgPD0gMTY4MiB+ICJwaGFzZSAzIiwKICAgIG5vcm1hbGl6ZWRfeWVhciA+IDE2ODIgfiAiPiAxNjgyIgogICkpCgpwaGFzZV9nZW5yZXNfZmJzX2FsbCU+JQogIHNsaWNlKDE6MSklPiUKICBnZ3Bsb3QoYWVzKHg9bm9ybWFsaXplZF95ZWFyLHk9bixmaWxsPWdlbnJlKSkrCiAgZ2VvbV9jb2woKSsKICB4bGFiKCJZZWFyIikgKyB5bGFiKCJGQlMtVG9wIEdlbnJlX2FsbCIpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSA1KSkrCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCxoanVzdD0xLHZqdXN0PTAuNSkpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiLAogICAgICAgIGxlZ2VuZC5rZXkud2lkdGg9dW5pdCgwLjE1LCAiY20iKSkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC45KSkgCmBgYAojIFRoZSBiZWxvdyBjb2RlLCBzaG93cyB0aGUga2V5d29yZHMgcmVsYXRlZCB0byB0cmFuc2xhdGlvbnMgYXZhaWxhYmxlIGluIG5vdGVzLCB0aXRsZXMgYW5kIHN1YnRpdGxlcyBvZiBwdWJsaWNhdGlvbnMgKGluIGEgY2FzZSB0aGF0IHRoZWlyIG9yaWdpbmFsIGxhbmd1YWdlIGlzIE5BKQoKYGBge3J9Cmxpc3QxIDwtIGMoIsOcYmVydHJhZyIsIsOcYmVyc2V0eiIsIkdldGV1dHNjaCIsIkdlZG9sbWV0c2NoIiwiRG9sbWV0c2NoIiwiVmVyZGXDvHRzY2giLCJWZXJkZXV0c2NoIiwiVmVydGV1dHNjaCIsIsOcYmVyZ2VzZXR6IiwiVmVyc2V0enQiLCJHZWdlbsO8YmVyc2V0eiIsIlViZXJnZXNhdHoiLCJVYmVyYnJhY2h0Iiwiw5xiZXJicmFjaHQiLCJUZXV0c2NoIiwiRGV1dHNjaCIsIkdlYnJhY2h0Iiwiw7xiZXJ0cmFnIiwiw7xiZXJzZXR6IiwiZ2V0ZXV0c2NoIiwiZ2Vkb2xtZXRzY2giLCJkb2xtZXRzY2giLCJ2ZXJkZcO8dHNjaCIsInZlcmRldXRzY2giLCJ2ZXJ0ZXV0c2NoIiwiw7xiZXJnZXNldHoiLCJ2ZXJzZXR6dCIsImdlZ2Vuw7xiZXJzZXR6IiwidWJlcmdlc2F0eiIsInViZXJicmFjaHQiLCLDvGJlcmJyYWNodCIsInRldXRzY2giLCJkZXV0c2NoIiwiZ2VicmFjaHQiKQpsaXN0MiA8LSBjKCLDnGJlcnMiLCLDvGJlcnMiKQoKdmQxN19hX3RyYW5zbGF0aW9uc19saW5rMSA8LSB2ZDE3X2EgJT4lIAogIG11dGF0ZSh2YWx1ZSA9IHN0cl9yZXBsYWNlX2FsbCh2YWx1ZSwgc3FsKCJDSFIoMCkiKSwgIl8iKSkgJT4lCiAgY29sbGVjdCgpJT4lCiAgZmlsdGVyKGZpZWxkX2NvZGUgJWluJSBjKCIwMjFBIiwiMDIxRyIsIjAyMU0iLCIwMjFOIiksZ3JlcGwocGFzdGUobGlzdDEsIGNvbGxhcHNlPSJ8IiksIHZhbHVlKSklPiUKICBtdXRhdGUodHJhbnNsYXRpb25zX3ZhbHVlMT12YWx1ZSklPiUKICBzZWxlY3QocmVjb3JkX251bWJlcix0cmFuc2xhdGlvbnNfdmFsdWUxKSU+JQogIGRpc3RpbmN0KCkKCnZkMTdfYV90cmFuc2xhdGlvbnNfbGluazIgPC0gdmQxN19hICU+JSAKICBtdXRhdGUodmFsdWUgPSBzdHJfcmVwbGFjZV9hbGwodmFsdWUsIHNxbCgiQ0hSKDApIiksICJfIikpICU+JQogIGNvbGxlY3QoKSU+JQogIGZpbHRlcihmaWVsZF9jb2RlICVpbiUgYygiMDM3QSIsIjA0NkwiKSxncmVwbChwYXN0ZShsaXN0MiwgY29sbGFwc2U9InwiKSwgdmFsdWUpKSU+JQogIG11dGF0ZSh0cmFuc2xhdGlvbnNfdmFsdWUyPXZhbHVlKSU+JQogIHNlbGVjdChyZWNvcmRfbnVtYmVyLHRyYW5zbGF0aW9uc192YWx1ZTIpJT4lCiAgZGlzdGluY3QoKQoKdmQxN19hX3RyYW5zbGF0aW9uc19saW5rIDwtIG1lcmdlKHZkMTdfYV90cmFuc2xhdGlvbnNfbGluazEsIHZkMTdfYV90cmFuc2xhdGlvbnNfbGluazIsYnk9YygicmVjb3JkX251bWJlciIpLGFsbD1UUlVFKQp2ZDE3X2FfdHJhbnNsYXRpb25zX2xpbmsgPC0gdmQxN19hX3RyYW5zbGF0aW9uc19saW5rICU+JQogIGRpc3RpbmN0KCkKCnZkMTdfaWRfdHJhbnNsYXRpb25zX2xpbmsgPC0gdmQxN19hX3RyYW5zbGF0aW9uc19saW5rICU+JQogIGlubmVyX2pvaW4odmQxN19pZF9sb2NhbCxieT1jKCJyZWNvcmRfbnVtYmVyIikpCgp2ZDE3X3NwZWNpZmljX2xpbmtfdHJhbnNsYXRpb25zIDwtIGdzNF9jcmVhdGUoCiAgInNoZWV0cy12ZDE3X3NwZWNpZmljX2xpbmtfdHJhbnNsYXRpb25zX2ZicyIsCiAgc2hlZXRzID0gdmQxN19pZF90cmFuc2xhdGlvbnNfbGluaykKdmQxN19zcGVjaWZpY19saW5rX3RyYW5zbGF0aW9ucwpgYGAKYGBge3J9CnZkMTdfaWRfdHJhbnNsYXRpb25zX2xpbmtfMiA9IHN1YnNldCh2ZDE3X2lkX3RyYW5zbGF0aW9uc19saW5rLCBzZWxlY3QgPSAtYyh0cmFuc2xhdGlvbnNfdmFsdWUxLHRyYW5zbGF0aW9uc192YWx1ZTIsdmQxN19pZCkpCmBgYAoKYGBge3J9CiMgRkJTIHRyYW5zbGF0aW9ucyAobGlua3Mgb2YgaW50ZXJlc3QpIChJdCBpbmNsdWRlcyBhbGwgdHJhbnNsYXRpb25zIG5vdCBvbmx5IEdlcm1hbiBvbmUgd2hpY2ggdGhlaXIgb3JpZ2luYWwgbGFuZ3VhZ2UgaXMgbm90IE5BKS4KCmZic190cmFuc2xhdGlvbiA8LSBmYnNfbGlua3Nfb2ZfaW50ZXJlc3RfbG9jYWwgJT4lCiAgbGVmdF9qb2luKHZkMTdfbm9ybWFsaXplZF95ZWFyc19sb2NhbCwgYnkgPSBjKCJyZWNvcmRfbnVtYmVyIikpICU+JQogIGZpbHRlcihub3JtYWxpemVkX3llYXIgPj0gMTYwMCwgbm9ybWFsaXplZF95ZWFyIDw9IDE3MDApICU+JQogIGZpbHRlcihuY2hhcihub3JtYWxpemVkX3llYXIpPT00KSU+JQogIGxlZnRfam9pbih2ZDE3X25vcm1hbGl6ZWRfbGFuZ3NfbG9jYWwsIGJ5ID0gYygicmVjb3JkX251bWJlciIpKSU+JQogIGZpbHRlcighaXMubmEob3JpZ2luYWxfbGFuZ3VhZ2UpKSU+JQogIGxlZnRfam9pbih2ZDE3X2dlbnJlc19sb2NhbCwgYnkgPSBjKCJyZWNvcmRfbnVtYmVyIikpJT4lCiAgc2VsZWN0IChyZWNvcmRfbnVtYmVyLG5vcm1hbGl6ZWRfeWVhcix2ZDE3X2lkLHRpdGxlLE1lbWJlcl9udW1iZXJfbmV3LEZpcnN0X25hbWVfbmV3LExhc3RfbmFtZV9uZXcsU29jaWV0eV9uYW1lLEVzdGltYXRlZF9hZG1pc3Npb25feWVhcixFc3RpbWF0ZWRfRE9ELEdORCxyb2xlMixmaWVsZF9jb2RlLG9yaWdpbmFsX2xhbmd1YWdlLGludGVybWVkaWFyeV9sYW5ndWFnZSxwdWJsaWNhdGlvbl9sYW5ndWFnZSxnZW5yZSklPiUKICBkaXN0aW5jdCgpCgojIEpvaW5pbmcgdGhlIHZkMTcgdHJhbnNsYXRpb25zICh3aGljaCBleHRyYWN0ZWQgYnkgdGhlIGtleXdvcmRzIGluIHRoZWlyIG5vdGVzLCB0aXRsZXMsIHN1YnRpdGxlcykgd2l0aCBmYnMgcHVibGljYXRpb25zLCB0byBleHRyYWN0IG1vcmUgdHJhbnNsYXRpb25zIChpbiBhIGNhc2UgdGhhdCB0aGVpciBvcmlnaW5hbCBsYW5ndWFnZSBpcyBOQSkuCnNwZWNpZmllZF90cmFuc2xhdGlvbl9mYnMgPC0gZmJzX2xpbmtzX29mX2ludGVyZXN0X2xvY2FsICU+JQogIGlubmVyX2pvaW4odmQxN19pZF90cmFuc2xhdGlvbnNfbGlua18yLCBieSA9IGMoInJlY29yZF9udW1iZXIiKSklPiUKICBsZWZ0X2pvaW4odmQxN19ub3JtYWxpemVkX3llYXJzX2xvY2FsLCBieSA9IGMoInJlY29yZF9udW1iZXIiKSkgJT4lCiAgZmlsdGVyKG5vcm1hbGl6ZWRfeWVhciA+PSAxNjAwLCBub3JtYWxpemVkX3llYXIgPD0gMTcwMCkgJT4lCiAgZmlsdGVyKG5jaGFyKG5vcm1hbGl6ZWRfeWVhcik9PTQpJT4lCiAgbGVmdF9qb2luKHZkMTdfbm9ybWFsaXplZF9sYW5nc19sb2NhbCwgYnkgPSBjKCJyZWNvcmRfbnVtYmVyIikpJT4lCiAgbGVmdF9qb2luKHZkMTdfZ2VucmVzX2xvY2FsLCBieSA9IGMoInJlY29yZF9udW1iZXIiKSklPiUKICBzZWxlY3QgKHJlY29yZF9udW1iZXIsbm9ybWFsaXplZF95ZWFyLHZkMTdfaWQsdGl0bGUsTWVtYmVyX251bWJlcl9uZXcsRmlyc3RfbmFtZV9uZXcsTGFzdF9uYW1lX25ldyxTb2NpZXR5X25hbWUsRXN0aW1hdGVkX2FkbWlzc2lvbl95ZWFyLEVzdGltYXRlZF9ET0QsR05ELHJvbGUyLGZpZWxkX2NvZGUsb3JpZ2luYWxfbGFuZ3VhZ2UsaW50ZXJtZWRpYXJ5X2xhbmd1YWdlLHB1YmxpY2F0aW9uX2xhbmd1YWdlLGdlbnJlKSU+JQogIGRpc3RpbmN0KCkKCiMgRmluZGluZyB0aGUgcmVjb3JkcyBvZiBvZiB0cmFuc2xhdGlvbnMgd2l0aCBrZXl3b3Jkcywgd2hpY2ggYXJlIG5vdCBhdmFpbGFibGUgaW4gRkJTIHRyYW5zbGF0aW9ucyAoYnkgb3JpZ2luYWwgbGFuZ3VhZ2UpLgpuZWVkZWRfdHJhbnNsYXRpb25fZmJzIDwtIHNwZWNpZmllZF90cmFuc2xhdGlvbl9mYnNbIXNwZWNpZmllZF90cmFuc2xhdGlvbl9mYnMkcmVjb3JkX251bWJlciAlaW4lIGZic190cmFuc2xhdGlvbiRyZWNvcmRfbnVtYmVyLCAsIGRyb3AgPSBGQUxTRV0KCgpuZWVkZWRfdHJhbnNsYXRpb25zX29mX2ZicyA8LSBnczRfY3JlYXRlKAogICJzaGVldHMtdHJhbnNsYXRpb25zX29mX2ZicyIsCiAgc2hlZXRzID0gbmVlZGVkX3RyYW5zbGF0aW9uX2ZicykKbmVlZGVkX3RyYW5zbGF0aW9uc19vZl9mYnMKYGBgCgojIEdlbnJlIG9mIEZCUyAobGlua3Mgb2YgaW50ZXJlc3QpIChmb3IgR2VybWFuIHRyYW5zbGF0aW9ucykuCiMgVGhlIGJlbG93IHdvcmRjbG91ZCBkZXBpY3RzIHRoZSBmcmVxdWVuY3kgb2YgZ2VucmVzIG9mIEZCUyB0cmFuc2xhdGlvbnMgZm9yIGxpbmtzIG9mIGludGVyZXN0LgpgYGB7cn0KbGlicmFyeSh3b3JkY2xvdWQpCmdlbnJlX3RyYW5zbGF0aW9uX2ZicyA8LSBmYnNfdHJhbnNsYXRpb24lPiUKICBmaWx0ZXIocHVibGljYXRpb25fbGFuZ3VhZ2U9PSJnZXIiKSU+JQogIHNlbGVjdChyZWNvcmRfbnVtYmVyLG5vcm1hbGl6ZWRfeWVhcixnZW5yZSklPiUKICBkaXN0aW5jdChyZWNvcmRfbnVtYmVyLG5vcm1hbGl6ZWRfeWVhcixnZW5yZSklPiUKICBuYS5vbWl0KHRyYW5zbGF0aW9uX2ZicyklPiUKICBncm91cF9ieShnZW5yZSkgJT4lCiAgY291bnQoZ2VucmUpJT4lCiAgYXJyYW5nZShkZXNjKG4pKQoKd29yZGNsb3VkKHdvcmRzID0gZ2VucmVfdHJhbnNsYXRpb25fZmJzJGdlbnJlLCBmcmVxID0gZ2VucmVfdHJhbnNsYXRpb25fZmJzJG4sIG1pbi5mcmVxID0gMSwKICAgICAgICAgIGNvbG9ycyA9IGJyZXdlci5wYWwoMjAsIlBhaXJlZCIpLCByYW5kb20ub3JkZXI9RkFMU0UsIHNjYWxlID0gYygxLCAwLjQpKQpgYGAKCiMgT3JpZ2luYWwgbGFuZ3VhZ2Ugb2YgRkJTIHRyYW5zbGF0aW9ucyAobGlua3Mgb2YgaW50ZXJlc3QpKEl0IGluY2x1ZGVzIGFsbCB0cmFuc2xhdGlvbnMgbm90IG9ubHkgR2VybWFuIG9uZSkuIAojIFRoZSBiZWxvdyB3b3JkY2xvdWQgZGVwaWN0cyB0aGUgZnJlcXVlbmN5IG9mIG9yaWdpbmFsX2xhbmd1YWdlIG9mIEZCUyB0cmFuc2xhdGlvbnMgZm9yIGxpbmtzIG9mIGludGVyZXN0LgpgYGB7cn0Kb19sYW5ndWFnZV90cmFuc2xhdGlvbl9mYnMgPC0gZmJzX3RyYW5zbGF0aW9uJT4lCiAgc2VsZWN0KHJlY29yZF9udW1iZXIsbm9ybWFsaXplZF95ZWFyLG9yaWdpbmFsX2xhbmd1YWdlKSU+JQogIGRpc3RpbmN0KHJlY29yZF9udW1iZXIsbm9ybWFsaXplZF95ZWFyLG9yaWdpbmFsX2xhbmd1YWdlKSU+JQogIG5hLm9taXQoZ2VyX3RyYW5zbGF0aW9uX2Zic19hbGwpJT4lCiAgZ3JvdXBfYnkob3JpZ2luYWxfbGFuZ3VhZ2UpICU+JQogIGNvdW50KG9yaWdpbmFsX2xhbmd1YWdlKSU+JQogIGFycmFuZ2UoZGVzYyhuKSkKCndvcmRjbG91ZCh3b3JkcyA9IG9fbGFuZ3VhZ2VfdHJhbnNsYXRpb25fZmJzJG9yaWdpbmFsX2xhbmd1YWdlLCBmcmVxID0gb19sYW5ndWFnZV90cmFuc2xhdGlvbl9mYnMkbiwgbWluLmZyZXEgPSAxLAogICAgICAgICAgY29sb3JzID0gYnJld2VyLnBhbCgyMCwiUGFpcmVkIiksIHJhbmRvbS5vcmRlcj1GQUxTRSwgc2NhbGUgPSBjKDEsIDAuNCkpCmBgYAojIFByaW1hcnkgYXV0aG9ycyBhbmQgVHJhbnNsYXRvcnMgb2YgRkJTIHRyYW5zbGF0aW9ucyAobGlua3Mgb2YgaW50ZXJlc3QpKEl0IGluY2x1ZGVzIGFsbCB0cmFuc2xhdGlvbnMgbm90IG9ubHkgR2VybWFuIG9uZSkuCmBgYHtyfQpwcmltYXJ5X2F1dGhvcnNfbGlua3Nfb2ZfaW50ZXJlc3RzIDwtIGZic190cmFuc2xhdGlvbiU+JSAKICBmaWx0ZXIoZmllbGRfY29kZT09IjAyOEEiKQoKcHJpbWFyeV9hdXRob3JzIDwtIGdzNF9jcmVhdGUoCiAgInNoZWV0cy1wcmltYXJ5X2F1dGhvcnNfdHJhbnNsYXRpb25zX2Zic19saW5rc19vZl9pbnRlcmVzdCIsCiAgc2hlZXRzID0gcHJpbWFyeV9hdXRob3JzX2xpbmtzX29mX2ludGVyZXN0cykKcHJpbWFyeV9hdXRob3JzCiAgICAKdHJhbnNsYXRvcnNfdHJhbnNsYXRpb25fbGlua3Nfb2ZfaW50ZXJlc3QgPC0gZmJzX3RyYW5zbGF0aW9uICU+JSAKICBmaWx0ZXIoZmllbGRfY29kZT09IjAyOEMiLChncmVwbChwYXN0ZShjKCLDnGJlcnMiKSwgY29sbGFwc2U9InwiKSwgcm9sZTIpfHJvbGUyICVpbiUoTkEpKSkgIAoKdHJhbnNsYXRvcnNfdHJhbnNsYXRpb24gPC0gZ3M0X2NyZWF0ZSgKICAic2hlZXRzLXRyYW5zbGF0b3JfdHJhbnNsYXRpb25zX2ZicyIsCiAgc2hlZXRzID0gdHJhbnNsYXRvcnNfdHJhbnNsYXRpb25fbGlua3Nfb2ZfaW50ZXJlc3QpCnRyYW5zbGF0b3JzX3RyYW5zbGF0aW9uCmBgYAoKIyBUcmFuc2xhdGVkIHZzIE5vbi1UcmFuc2xhdGVkIG1lbWJlciBwdWJsaWNhdGlvbnNfZmJzIChhbGwpLgojIFRoZSBiZWxvdyBwbG90IGRlcGljdHMgdGhlIFRyYW5zbGF0ZWQgdnMgTm9uLVRyYW5zbGF0ZWQgbWVtYmVyIHB1YmxpY2F0aW9ucyBvZiBGQlMuCmBgYHtyfQp0cmFuc192c19ub25fdHJhbnMgPC0gZmJzX2FsbF9saW5rc19sb2NhbCAlPiUKICBsZWZ0X2pvaW4odmQxN19ub3JtYWxpemVkX3llYXJzX2xvY2FsLCBieSA9IGMoInJlY29yZF9udW1iZXIiKSkgJT4lCiAgZmlsdGVyKG5vcm1hbGl6ZWRfeWVhciA+PSAxNjAwLCBub3JtYWxpemVkX3llYXIgPD0gMTcwMCkgJT4lCiAgZmlsdGVyKG5jaGFyKG5vcm1hbGl6ZWRfeWVhcik9PTQpJT4lCiAgbGVmdF9qb2luKHZkMTdfbm9ybWFsaXplZF9sYW5nc19sb2NhbCwgYnkgPSBjKCJyZWNvcmRfbnVtYmVyIikpJT4lCiAgc2VsZWN0IChyZWNvcmRfbnVtYmVyLG5vcm1hbGl6ZWRfeWVhcix2ZDE3X2lkLHRpdGxlLE1lbWJlcl9udW1iZXJfbmV3LEZpcnN0X25hbWVfbmV3LExhc3RfbmFtZV9uZXcsU29jaWV0eV9uYW1lLEVzdGltYXRlZF9hZG1pc3Npb25feWVhcixFc3RpbWF0ZWRfRE9ELEdORCxyb2xlMixmaWVsZF9jb2RlLG9yaWdpbmFsX2xhbmd1YWdlLHB1YmxpY2F0aW9uX2xhbmd1YWdlKQoKCnRyYW5zX3ZzX25vbl90cmFucyR0eXBlIDwtIGlzLm5hKHRyYW5zX3ZzX25vbl90cmFucyRvcmlnaW5hbF9sYW5ndWFnZSkKCnRyYW5zX3ZzX25vbl90cmFucyR0eXBlW3RyYW5zX3ZzX25vbl90cmFucyR0eXBlID09ICJGQUxTRSJdIDwtICJUcmFuc2xhdGVkIgp0cmFuc192c19ub25fdHJhbnMkdHlwZVt0cmFuc192c19ub25fdHJhbnMkdHlwZSA9PSAiVFJVRSJdIDwtICJOb24tVHJhbnNsYXRlZCIKCnRyYW5zbGF0ZWRfdnNfbm9uX3RyYW5zbGF0ZWQgPC0gZ3M0X2NyZWF0ZSgKICAic2hlZXRzLXRyYW5zbGF0ZWRfdnNfbm9uX3RyYW5zbGF0ZWRfZmJzIiwKICBzaGVldHMgPSB0cmFuc192c19ub25fdHJhbnMpCnRyYW5zbGF0ZWRfdnNfbm9uX3RyYW5zbGF0ZWQKCnRyYW5zX3ZzX25vbl90cmFucyU+JQpkaXN0aW5jdChyZWNvcmRfbnVtYmVyLG5vcm1hbGl6ZWRfeWVhcix0eXBlKSU+JQpzZWxlY3Qobm9ybWFsaXplZF95ZWFyLHR5cGUpJT4lCmdyb3VwX2J5KG5vcm1hbGl6ZWRfeWVhciklPiUKY291bnQodHlwZSklPiUKYXJyYW5nZShkZXNjKG4pKSU+JQpnZ3Bsb3QoYWVzKHg9bm9ybWFsaXplZF95ZWFyLHk9biwgZmlsbD10eXBlKSkgKyAKZ2VvbV9jb2woKSsKbGFicyh5ID0gIlRyYW5zbGF0ZWQgdnMgTm9uLVRyYW5zbGF0ZWQgRkJTIiwgeD0gIlllYXJzIikrCnNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTAwMCwgMjAwMCwgYnkgPSA1KSkrCnRoZW1lX2hzY2lfZGlzY3JldGUoKSsKdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwLGhqdXN0PTEsdmp1c3Q9MC41KSkrCnRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIiwKICAgICAgICBsZWdlbmQua2V5LndpZHRoPXVuaXQoMC4xNSwgImNtIikpKwpnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksIGNvbG9yID0gImdyZWVuIiwgc2l6ZSA9IDEuOCwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuOSkpIApgYGAKIyBUcmFuc2xhdGVkIHZzIE5vbi1UcmFuc2xhdGVkIG1lbWJlciBwdWJsaWNhdGlvbnNfZmJzIChhbGwpIChQZXJjZW50YWdlIGJ5IHllYXIpLgpgYGB7cn0KdHJhbnNfbm9uX3RyYW5zX3BlcmNlbnRhZ2UgPC0gdHJhbnNfdnNfbm9uX3RyYW5zJT4lCiAgZGlzdGluY3QocmVjb3JkX251bWJlcixub3JtYWxpemVkX3llYXIsdHlwZSklPiUKICBzZWxlY3Qobm9ybWFsaXplZF95ZWFyLHR5cGUpJT4lCiAgbXV0YXRlKHR5cGUgPSBmYWN0b3IodHlwZSkpICU+JQogIGNvdW50KG5vcm1hbGl6ZWRfeWVhciwgdHlwZSwgLmRyb3AgPSBGQUxTRSwgbmFtZSA9ICdQZXJjZW50YWdlJykgJT4lCiAgZ3JvdXBfYnkobm9ybWFsaXplZF95ZWFyKSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IHJvdW5kKFBlcmNlbnRhZ2Uvc3VtKFBlcmNlbnRhZ2UpICogMTAwKSwyKQoKdHJhbnNsYXRlZF9ub25fdHJhbnNsYXRlZF9wZXJjZW50YWdlIDwtIGdzNF9jcmVhdGUoCiAgInNoZWV0cy10cmFuc2xhdGVkX25vbl90cmFuc2xhdGVkX3BlcmNlbnRhZ2VfZmJzIiwKICBzaGVldHMgPSB0cmFuc19ub25fdHJhbnNfcGVyY2VudGFnZSkKdHJhbnNsYXRlZF9ub25fdHJhbnNsYXRlZF9wZXJjZW50YWdlCmBgYAoKIyBUcmFuc2xhdGVkIHZzIE5vbi1UcmFuc2xhdGVkIG1lbWJlciBwdWJsaWNhdGlvbnNfZmJzIChhbGwpIChQZXJjZW50YWdlIGJ5IHdob2xlKS4KYGBge3J9CnByaW50KGMoIlRyYW5zbGF0ZWQiLHJvdW5kKHN1bSh0cmFuc192c19ub25fdHJhbnMkdHlwZT09IlRyYW5zbGF0ZWQiKS9sZW5ndGgodHJhbnNfdnNfbm9uX3RyYW5zJHR5cGUpKjEwMCwyKSkpCnByaW50KGMoIk5vbi1UcmFuc2xhdGVkIixyb3VuZChzdW0odHJhbnNfdnNfbm9uX3RyYW5zJHR5cGU9PSJOb24tVHJhbnNsYXRlZCIpL2xlbmd0aCh0cmFuc192c19ub25fdHJhbnMkdHlwZSkqMTAwLDIpKSkKYGBg