Setup

Analysis table creation (not run)

articles_opinionated_c <- articles_c %>% mutate(opinionated=case_when(
  media == "HS" ~ case_when(
    str_to_lower(section) == "pääkirjoitus" & str_detect(str_to_lower(story_logo),"ieras") ~ "external editorial",
    str_to_lower(section) == "pääkirjoitus" & is.na(story_logo) ~ "editorial",
    str_to_lower(section) == "pääkirjoitus" & str_to_lower(story_logo) == "pääkirjoitus" ~ "editorial",
    str_to_lower(section) == "mielipide" | str_to_lower(story_logo) == "mielipide" ~ "external opinion",
    str_detect(str_to_lower(title),"analyysi:") | str_detect(str_to_lower(story_logo),"analyysi")  ~ "analysis",
    str_detect(str_to_lower(title),"näkökulma:") | str_detect(str_to_lower(story_logo),"näkökulma") ~ "perspective",
    str_detect(str_to_lower(title),"kolumni:") | str_detect(str_to_lower(story_logo),"kolumni") ~ "column",
    str_detect(str_to_lower(title),"blogi:") | str_detect(str_to_lower(story_logo),"blog") ~ "blog"    
  ),
  media == "IL" ~ case_when(
    subsection == "paakirjoitus" ~ "editorial",
    str_detect(str_to_lower(title),"kommentti:") ~ "commentary",
    str_detect(str_to_lower(title),"analyysi:") ~ "analysis",
    str_detect(str_to_lower(title),"kolumni:") ~ "column",
    str_detect(str_to_lower(title),"näkökulma:") ~ "perspective"
  ),
  media == "YLE" ~ case_when(
    str_detect(str_to_lower(title),"kommentti:") ~ "commentary",
    str_detect(str_to_lower(title),"analyysi:") | str_detect(subject,"Analyysit \\(Yle Uutiset\\)") ~ "analysis",
    str_detect(str_to_lower(title),"kolumni:") | str_detect(str_to_lower(subject),"kolumn") ~ "column",
    str_detect(str_to_lower(title),"näkökulma:")  | str_detect(str_to_lower(subject),"näkökulm") ~ "perspective",
    str_detect(str_to_lower(title),"blogi:")  | str_detect(str_to_lower(subject),"blog") ~ "blog"
  )
)) %>%
  filter(!is.na(opinionated)) %>%
  distinct(a_id, opinionated) %>%
  compute_c(name="articles_opinionated_c")

article_types_c <- articles_c %>% 
  left_join(articles_opinionated_c) %>%
  mutate(type=case_when(
    media == "STT" & version != "Loppuversio" ~ "Other",
    !is.na(opinionated) & !str_detect(opinionated,"^external ") ~ "Journalistic opinion",
    !is.na(opinionated) ~ "External opinion",
    media == "HS" & section %in% c("Kotimaa", "Politiikka", "Talous") ~ "Domestic general/political/economic news",
  media == "IL" & subsection %in% c("kotimaa","politiikka","talous","uutiset") ~ "Domestic general/political/economic news",
  media == "STT" & section %in% c("Kotimaa","Politiikka","Talous") ~ "Domestic general/political/economic news",
  media == "YLE" & section == "Yle Uutiset" & str_detect(subject,"Kotimaan uutiset|politiikka|talous") & (!str_detect(subject,"Ulkomaat") | str_detect(subject,"Kotimaan uutiset")) ~ "Domestic general/political/economic news",
    media == "HS" & section == "Kulttuuri" ~ "Culture/entertainment",
    media == "IL" & section == "viihde" ~ "Culture/entertainment",
    media == "STT" & section == "Kulttuuri" ~ "Culture/entertainment",
    media == "YLE" & section == "Yle Uutiset" & str_detect(subject,"kulttuuri|musiikki|viihde") & !str_detect(subject, "Ulkomaat") ~ "Culture/entertainment",
    media == "HS" & section == "Kaupunki" ~ "Local news",
    media == "YLE" & section == "Yle Uutiset" & coverage=="local" ~ "Local news",
    media == "STT" & section == "Urheilu" ~ "Sports",
    media == "HS" & section == "Urheilu" ~ "Sports",
    media == "YLE" & section == "YLE Urheilu" ~ "Sports",
    media == "IL" & section == "urheilu" ~ "Sports",
    media == "STT" & section == "Ulkomaat" ~ "Foreign news",
    media == "HS" & section == "Ulkomaat" ~ "Foreign news",
    media == "YLE" & section == "Yle Uutiset" & str_detect(subject,"Ulkomaat") & !str_detect(subject,"Kotimaan uutiset") ~ "Foreign news",
    media == "IL" & subsection == "ulkomaat" ~ "Foreign news",
    T ~ "Other"
  )) %>%
  distinct(a_id,type) %>%
  compute_c(name="article_types")

article_quotes_stats_c <- corpus_c %>% 
  inner_join(quotes_c,sql_on="LHS.a_id=RHS.a_id AND (s_id > start_s_id OR (s_id=start_s_id AND pos >= start_pos)) AND (s_id < end_s_id OR (s_id=end_s_id AND pos <= end_pos))") %>%
  group_by(a_id=a_id.x, direct) %>%
  summarize(
    nr_quote_tokens=n_distinct(10000L*s_id+pos),
    nr_sentences_with_quotes=n_distinct(s_id),
    nr_paragraphs_with_quotes=n_distinct(par_id),
    nr_quotes=n_distinct(q_id),
    .groups="drop") %>%
  compute_c(name="article_quotes_stats_c")

article_stats_c <- 
  corpus_c %>%
  group_by(a_id) %>%
  summarize(
    nr_tokens=n(),
    nr_sentences=n_distinct(s_id),
    nr_paragraphs=n_distinct(par_id),
    .groups="drop") %>%
  compute_c() %>%
  left_join(
    article_quotes_stats_c %>%
      filter(direct==TRUE) %>%
      select(
        a_id,
        nr_direct_quote_tokens=nr_quote_tokens,
        nr_sentences_with_direct_quotes=nr_sentences_with_quotes,
        nr_paragraphs_with_direct_quotes=nr_paragraphs_with_quotes,
        nr_direct_quotes=nr_quotes)
  ) %>%
  left_join(
    article_quotes_stats_c %>%
      filter(direct==FALSE) %>%
      select(
        a_id,
        nr_indirect_quote_tokens=nr_quote_tokens,
        nr_sentences_with_indirect_quotes=nr_sentences_with_quotes,
        nr_paragraphs_with_indirect_quotes=nr_paragraphs_with_quotes,
        nr_indirect_quotes=nr_quotes)
  ) %>% 
  left_join(
    corpus_c %>% 
    inner_join(quotes_c,sql_on="LHS.a_id=RHS.a_id AND (s_id > start_s_id OR (s_id=start_s_id AND pos >= start_pos)) AND (s_id < end_s_id OR (s_id=end_s_id AND pos <= end_pos))") %>%
    group_by(a_id=a_id.x) %>%
    summarize(
      nr_quote_tokens=n_distinct(10000L*s_id+pos),
      nr_sentences_with_quotes=n_distinct(s_id),
      nr_paragraphs_with_quotes=n_distinct(par_id),
      nr_quotes=n_distinct(q_id),
      .groups="drop") %>%
    compute_c()
  ) %>%
  replace_na(list(
    nr_direct_quote_tokens=0L,nr_sentences_with_direct_quotes=0L,nr_paragraphs_with_direct_quotes=0L,nr_direct_quotes=0L,
    nr_indirect_quote_tokens=0L,nr_sentences_with_indirect_quotes=0L,nr_paragraphs_with_indirect_quotes=0L,nr_indirect_quotes=0L,
    nr_quote_tokens=0L,nr_sentences_with_quotes=0L,nr_paragraphs_with_quotes=0L,nr_quotes=0L
    )) %>%
  compute_c(name="article_stats_c")

adjective_counts_c <- words_c %>% 
  filter(upos=="ADJ") %>%
  inner_join(corpus_c) %>%
  left_join(quotes_c %>% mutate(article_part=if_else(direct,"direct quotation","indirect quotation")),sql_on="LHS.a_id=RHS.a_id AND (s_id > start_s_id OR (s_id=start_s_id AND pos >= start_pos)) AND (s_id < end_s_id OR (s_id=end_s_id AND pos <= end_pos))") %>%
  select(a_id=a_id.x,par_id,s_id,pos,article_part) %>%
  replace_na(list(article_part="journalistic text")) %>%
  group_by(a_id,article_part) %>%
  summarize(nr_adjectives=n_distinct(10000L*s_id+pos),nr_sentences_with_adjectives=n_distinct(s_id),nr_paragraphs_with_adjectives=n_distinct(par_id),.groups="drop") %>%
  compute_c(name="adjective_counts_c")

hedging_markers <- read_csv(here("data/input/hedging_markers.csv")) %>% 
  rename(type=...1,value=...2,class=...3)

hedging_counts_c <- words_c %>% 
  inner_join(hedging_markers %>% 
               filter(class %in% c("Adverbs","Adjective")) %>%
               select(lemma=value) %>% copy_to_c(con)) %>%
  inner_join(corpus_c) %>%
  left_join(quotes_c %>% mutate(article_part=if_else(direct,"direct quotation","indirect quotation")),sql_on="LHS.a_id=RHS.a_id AND (s_id > start_s_id OR (s_id=start_s_id AND pos >= start_pos)) AND (s_id < end_s_id OR (s_id=end_s_id AND pos <= end_pos))") %>%
  replace_na(list(article_part="journalistic text")) %>%
  select(a_id=a_id.x,par_id,s_id,pos, article_part) %>%
  group_by(a_id,article_part) %>%
  summarize(nr_hedgings=n_distinct(10000L*s_id+pos),nr_sentences_with_hedgings=n_distinct(s_id),nr_paragraphs_with_hedgings=n_distinct(par_id),.groups="drop") %>%
  compute_c(name="hedging_counts_c")

Analysis table loads

article_stats_c <- tbl(con,"article_stats_c")
article_quotes_stats_c <- tbl(con,"article_quotes_stats_c")
adjective_counts_c <- tbl(con,"adjective_counts_c")
hedging_counts_c <- tbl(con,"hedging_counts_c")

article_stats_long_c <-
  article_stats_c %>%
  mutate(nr_tokens=nr_tokens-nr_quote_tokens,nr_sentences=nr_sentences-nr_sentences_with_quotes,nr_paragraphs=nr_paragraphs-nr_paragraphs_with_quotes) %>%
  select(a_id,nr_tokens:nr_paragraphs) %>%
  mutate(article_part='journalistic text') %>%
  union_all(
    article_stats_c %>%
      filter(nr_direct_quote_tokens>0) %>%
      select(a_id,nr_tokens=nr_direct_quote_tokens,nr_sentences=nr_sentences_with_direct_quotes,nr_paragraphs=nr_paragraphs_with_direct_quotes) %>% 
      mutate(article_part='direct quotation')
  ) %>%
  union_all(
    article_stats_c %>%
      filter(nr_indirect_quote_tokens>0) %>%
      select(a_id,nr_tokens=nr_indirect_quote_tokens,nr_sentences=nr_sentences_with_indirect_quotes,nr_paragraphs=nr_paragraphs_with_indirect_quotes) %>% 
      mutate(article_part='indirect quotation')
  )  

Analysis

Opinionated genres

article_types_a %>%
  filter(type!="Other") %>%
  inner_join(articles_a %>% select(a_id,year_created,media)) %>%
  group_by(year_created,media) %>%
  summarize(n=sum(type=="Journalistic opinion")/n(),.groups="drop") %>%
  ungroup() %>%
  ggplot(aes(x=year_created,color=media,y=n)) +
  geom_step() +
  theme_hsci_discrete() +
  scale_y_continuous(breaks=seq(0,1,by=0.01),labels=scales::percent_format(accuracy=1)) +
  scale_x_continuous(breaks=seq(2000,2020,by=2)) +
  labs(x="Year",y="Percentage of articles being journalistic opinion")
Joining, by = "a_id"Warning: Missing values are always removed in SQL aggregation functions.
Use `na.rm = TRUE` to silence this warning

Interpretations:

  • The huge bump in opinionated articles for HS comes from a huge increase in columns. Will need to check whether we are picking up columns accurately before 2013. However, general trend towards having more opinionated texts is clear across the outlets.

Article length development

ld <- article_stats_c %>% 
  inner_join(articles_c %>% select(a_id,media,year_created)) %>%
  inner_join(article_types_c) %>%
  select(media,type,year_created,nr_tokens,nr_sentences,nr_paragraphs) %>% 
  collect()
Joining, by = "a_id"Joining, by = "a_id"
ld2 <- ld %>%
  group_by(year_created,media,type) %>% 
  summarize_all(list(q1=~quantile(.x,0.25)[[1]],q2=mean,q3=~quantile(.x,0.75)[[1]])) %>%
  ungroup() %>%
  pivot_longer(nr_tokens_q1:nr_paragraphs_q3) %>%
  separate(name,c(NA,"measure","quantile"),sep="_") %>%
  mutate(
    media=fct_relevel(media, "HS","STT"),
    linetype=if_else(quantile=="q2","mean","1st/3rd quartile"),
    linetype=fct_relevel(linetype,"mean"),
    type=fct_relevel(type,"External opinion", "Journalistic opinion", "Domestic general/political/economic news", "Local news", "Foreign news", "Culture/entertainment", "Sports"),
    measure=recode(measure,
      "tokens" = "Words",
      "sentences" = "Sentences",
      "paragraphs" = "Paragraphs",
    )
  )
ld2 %>% 
  group_by(measure) %>%
  group_map(~.x %>%
    filter(!str_detect(type,"Other")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap(~type,scales="free") +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
#    scale_y_continuous(breaks=seq(0,1,by=0.02), labels=scales::percent_format(accuract=1)) +
    labs(x="Year",y=.y)
  )
[[1]]

[[2]]

[[3]]

ld3 <- ld %>%
  group_by(year_created,media,type) %>%
  summarize_all(sum) %>%
  ungroup() %>%
  mutate(
    type=fct_relevel(type,"External opinion", "Journalistic opinion", "Domestic general/political/economic news", "Local news", "Foreign news", "Culture/entertainment", "Sports")
  )
ld3 %>%
    filter(!str_detect(type,"Other")) %>%
    ggplot(aes(x=year_created,y=nr_sentences/nr_paragraphs,color=media)) +
    geom_step() +
    facet_wrap(~type,scales="free") +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
    #scale_y_continuous(breaks=seq(0,1,by=0.02), labels=scales::percent_format(accuracy=1)) +
    labs(x="Year",y="Sentences/paragraph")
ld3 %>%
    filter(!str_detect(type,"Other")) %>%
    ggplot(aes(x=year_created,y=nr_tokens/nr_sentences,color=media)) +
    geom_step() +
    facet_wrap(~type,scales="free") +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
    #scale_y_continuous(breaks=seq(0,1,by=0.02), labels=scales::percent_format(accuracy=1)) +
    labs(x="Year",y="Words/sentence")

Interpretations:

  • After 2012, stories get longer across the board, both in number of sentences/paragraphs as well as words per sentence
  • Before 2012 there has been a modest drive toward shorter articles. The cause of this is unclear. However, this needs to be kept in mind when interpreting the following main analyses, which often also show diminishing signals before 2012

Proportion of articles being quotations

qd <- article_stats_c %>% 
  mutate(quote_proportion=nr_quote_tokens/nr_tokens) %>%
  inner_join(articles_c %>% select(a_id,media,year_created)) %>%
  inner_join(article_types_c) %>%
  select(media,type,year_created,quote_proportion) %>% 
  collect()
Joining, by = "a_id"Joining, by = "a_id"
qd2 <- qd %>%
  group_by(year_created,media,type) %>% 
  summarize_all(list(q1=~quantile(.x,0.25)[[1]],q2=mean,q3=~quantile(.x,0.75)[[1]])) %>%
  ungroup() %>%
  pivot_longer(q1:q3) %>%
  mutate(
    media=fct_relevel(media, "HS","STT"),
    linetype=if_else(name=="q2","mean","1st/3rd quartile"),
    linetype=fct_relevel(linetype,"mean"),
    type=fct_relevel(type,"External opinion", "Journalistic opinion", "Domestic general/political/economic news", "Local news", "Foreign news", "Culture/entertainment", "Sports")        
    )

qd3 <- article_stats_c %>% 
  select(a_id,nr_tokens) %>%
  inner_join(article_quotes_stats_c) %>%
  mutate(quote_proportion=nr_quote_tokens/nr_tokens) %>%
  inner_join(articles_c %>% select(a_id,media,year_created)) %>%
  inner_join(article_types_c) %>%
  select(media,direct,type,year_created,quote_proportion) %>% 
  collect()
Joining, by = "a_id"Joining, by = "a_id"Joining, by = "a_id"
qd4 <- qd3 %>%
  group_by(direct,year_created,media,type) %>% 
  summarize_all(list(q1=~quantile(.x,0.25)[[1]],q2=mean,q3=~quantile(.x,0.75)[[1]])) %>%
  ungroup() %>%
  pivot_longer(q1:q3) %>%
  mutate(
    media=fct_relevel(media, "HS","STT"),
    linetype=if_else(name=="q2","mean","1st/3rd quartile"),
    linetype=fct_relevel(linetype,"mean"),
    type=fct_relevel(type,"External opinion", "Journalistic opinion", "Domestic general/political/economic news", "Local news", "Foreign news", "Culture/entertainment", "Sports")        
    )

qd5 <- qd3 %>%
  count(direct,year_created,media,type) %>%
  group_by(year_created,media,type) %>%
  mutate(p=n/sum(n))

Overall

qd2 %>% 
  filter(type!="Other") %>%
  ggplot(aes(x=year_created,y=value,color=media,group=interaction(name,media),linetype=linetype)) +
  geom_step() +
  facet_wrap(~type) +
  theme_hsci_discrete(base_family="Arial") +
  theme(legend.position="bottom") +
  scale_x_continuous(breaks=seq(2000,2020,by=4)) +
  scale_y_continuous(breaks=seq(0,1,by=0.1),labels=scales::percent_format(accuracy=1)) +
  labs(x="Year",y="Proportion of quotes in articles")

Proportion of quotes that are direct

qd5 %>%
  filter(direct==1) %>%
  ggplot(aes(x=year_created,y=p,color=media)) +
  geom_step() +
  facet_wrap(~type) +
  theme_hsci_discrete(base_family="Arial") +
  theme(legend.position="bottom") +
  scale_x_continuous(breaks=seq(2000,2020,by=4)) +
  scale_y_continuous(breaks=seq(0,1,by=0.1),labels=scales::percent_format(accuracy=1)) +
  labs(x="Year",y="Proportion of quotes that are direct")

Interpretations:

  • Usage of quotation constructs is increasing
  • Particularly direct quotes are used more

Adjective proportions

d <- article_stats_long_c %>% 
  left_join(adjective_counts_c) %>%
  replace_na(list(nr_adjectives=0,nr_sentences_with_adjectives=0,nr_paragraphs_with_adjectives=0)) %>%
  inner_join(article_types_c) %>%
  mutate(type2=str_c(article_part," in ",type)) %>%
  union_all(
    article_stats_long_c %>% 
    left_join(adjective_counts_c) %>%
    replace_na(list(nr_adjectives=0,nr_sentences_with_adjectives=0,nr_paragraphs_with_adjectives=0)) %>%
    inner_join(article_types_c %>% rename(type2=type))
  ) %>%
  group_by(a_id,type2) %>%
  summarize(nr_tokens=sum(nr_tokens),nr_adjectives=sum(nr_adjectives),nr_sentences=sum(nr_sentences),nr_paragraphs=sum(nr_paragraphs),nr_sentences_with_adjectives=sum(nr_sentences_with_adjectives),nr_paragraphs_with_adjectives=sum(nr_paragraphs_with_adjectives),.groups="drop") %>%
  inner_join(articles_c %>% select(a_id,media,year_created)) %>%
  mutate(
    apw=nr_adjectives/nr_tokens,
    aps=nr_adjectives/nr_sentences,
    app=nr_adjectives/nr_paragraphs,
    apa=nr_adjectives,
    asps=nr_sentences_with_adjectives/nr_sentences,
    aspp=nr_sentences_with_adjectives/nr_paragraphs,
    aspa=nr_sentences_with_adjectives,
    appp=nr_paragraphs_with_adjectives/nr_paragraphs,
    appa=nr_paragraphs_with_adjectives,
    aapa=if_else(nr_adjectives>0,1,0)
  ) %>%
  select(year_created,media,type2,apw:aapa) %>%
  collect()
Joining, by = c("a_id", "article_part")Joining, by = "a_id"Joining, by = c("a_id", "article_part")Joining, by = "a_id"Joining, by = "a_id"Warning in for (Cl in classes) if (is(object, Cl)) return(object) :
  call dbDisconnect() when finished working with a connection
d2 <- d %>%
  replace_na(list(apw=0,aps=0,app=0,apa=0,asps=0,aspp=0,aspa=0,appp=0,appa=0,aapa=0)) %>%
  group_by(year_created,media,type2) %>% 
  summarize_at(vars(apw:aapa),list(q1=~quantile(.x,0.25)[[1]],q2=mean,q3=~quantile(.x,0.75)[[1]])) %>%
  ungroup() %>%
  pivot_longer(apw_q1:aapa_q3) %>%
  separate(name,c("measure","quantile"),sep="_") %>%
  mutate(
    media=fct_relevel(media, "HS","STT"),
    measure=recode(measure,
      "apw" = "Adjectives/words",
      "aps" = "Adjectives/sentences",
      "app" = "Adjectives/paragrahs",
      "apa" = "Adjectives/articles",
      "asps" = "Sentences containing adjectives/sentences",
      "aspp" = "Sentences containing adjectives/paragrahs",
      "aspa" = "Sentences containing adjectives/articles",
      "appp" = "Paragraphs containing adjectives/paragrahs",
      "appa" = "Paragraphs containing adjectives/articles",
      "aapa" = "Articles containing adjectives/articles"
    ),
    linetype=if_else(quantile=="q2","mean","1/3 quartile"),
    linetype=fct_relevel(linetype,"mean"),
    type2=fct_relevel(type2,"Domestic general/political/economic news", "journalistic text in Domestic general/political/economic news", "indirect quotation in Domestic general/political/economic news", "direct quotation in Domestic general/political/economic news", "Local news", "journalistic text in Local news", "indirect quotation in Local news", "direct quotation in Local news", "Foreign news", "journalistic text in Foreign news", "indirect quotation in Foreign news", "direct quotation in Foreign news", "Culture/entertainment", "journalistic text in Culture/entertainment", "indirect quotation in Culture/entertainment", "direct quotation in Culture/entertainment", "Sports", "journalistic text in Sports", "indirect quotation in Sports", "direct quotation in Sports","External opinion", "Journalistic opinion")
    )
d2 %>% 
  filter(str_detect(type2,"Other")) %>%
  ggplot(aes(x=year_created,y=value,color=media,group=interaction(measure,quantile,media),linetype=linetype)) +
  geom_step() +
  facet_wrap(measure~type2,scales="free") +
  theme_hsci_discrete(base_family="Arial") +
  theme(legend.position="bottom")
d2 %>% 
  group_by(measure) %>%
  group_map(~.x %>%
    filter(!str_detect(type2,"Other")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap(~type2,scales="free") +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
#    scale_y_continuous(breaks=seq(0,1,by=0.02), labels=scales::percent_format(accuract=1)) +
    labs(x="Year",y="Number of adjectives") +
    ggtitle(.y)
  )

Due to the lengthening of article texts causing complexities for analyses, all the following adjective proportions were calculated and evaluated:

  • Adjectives/words
  • Adjectives/sentences
  • Adjectives/paragrahs
  • Adjectives/articles
  • Sentences containing adjectives/sentences
  • Sentences containing adjectives/paragrahs
  • Sentences containing adjectives/articles
  • Paragraphs containing adjectives/paragrahs
  • Paragraphs containing adjectives/articles
  • Articles containing adjectives/articles

Out of these, “Adjectives/words” and “Adjectives/sentences” were retained for final analysis:

Adjectives/words

1:2 %>% map(~
  d2 %>% 
    filter(measure=="Adjectives/words") %>%
    filter(!str_detect(type2,"Other"),!str_detect(type2,"in Journalistic opinion"),!str_detect(type2,"in External opinion")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap_paginate(~type2,ncol=4,nrow=3,page=.x) +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
    labs(x="Year",y="Adjectives/words")
  )
[[1]]

[[2]]

Adjectives/sentences

1:2 %>% map(~
  d2 %>% 
    filter(measure=="Adjectives/sentences") %>%
    filter(!str_detect(type2,"Other"),!str_detect(type2,"in Journalistic opinion"),!str_detect(type2,"in External opinion")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap_paginate(~type2,ncol=4,nrow=3,page=.x) +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
    labs(x="Year",y="Adjectives/sentences")
)
[[1]]

[[2]]

Interpretations:

  • In general, adjective use seems to decline. In quotes, this happens throughout.
  • However, in the case of journalistic writing, there are the following intriguing aberrations from this:
    • adjective use increases significantly after 2010 in HS & IL sports journalistic writing
    • adjective use increases after 2010 in the journalistic portion of domestic general/political/economic news texts in all outlets
    • adjective use increases in HS local reporting (Helsinki), but not in YLE regional reporting
  • Altogether, these increases in journalistic writing lead to similar increases in the articles overall.

Hedging proportions

hd <- article_stats_long_c %>% 
  inner_join(article_types_c) %>%
  mutate(type2=str_c(article_part," in ",type)) %>%
  union_all(
    article_stats_long_c %>% 
    inner_join(article_types_c %>% rename(type2=type))
  ) %>%
  left_join(hedging_counts_c) %>%
  replace_na(list(nr_hedgings=0,nr_sentences_with_hedgings=0,nr_paragraphs_with_hedgings=0)) %>%
  group_by(a_id,type2) %>%
  summarize(nr_tokens=sum(nr_tokens),nr_hedgings=sum(nr_hedgings),nr_sentences=sum(nr_sentences),nr_paragraphs=sum(nr_paragraphs),nr_sentences_with_hedgings=sum(nr_sentences_with_hedgings),nr_paragraphs_with_hedgings=sum(nr_paragraphs_with_hedgings),.groups="drop") %>%
  inner_join(articles_c %>% select(a_id,media,year_created)) %>%
  mutate(
    hpw=nr_hedgings/nr_tokens,
    hps=nr_hedgings/nr_sentences,
    hpp=nr_hedgings/nr_paragraphs,
    hpa=nr_hedgings,
    hsps=nr_sentences_with_hedgings/nr_sentences,
    hspp=nr_sentences_with_hedgings/nr_paragraphs,
    hspa=nr_sentences_with_hedgings,
    hppp=nr_paragraphs_with_hedgings/nr_paragraphs,
    hppa=nr_paragraphs_with_hedgings,
    hapa=if_else(nr_hedgings>0,1,0)
  ) %>%
  select(year_created,media,type2,hpw:hapa) %>%
  collect()
Joining, by = "a_id"Joining, by = "a_id"Joining, by = c("a_id", "article_part")Joining, by = "a_id"
hd2 <- hd %>%
  replace_na(list(hpw=0,hps=0,hpp=0,hpa=0,hsps=0,hspp=0,hspa=0,hppp=0,hppa=0,hapa=0)) %>%
  group_by(year_created,media,type2) %>% 
  summarize_at(vars(hpw:hapa),list(q1=~quantile(.x,0.1)[[1]],q2=mean,q3=~quantile(.x,0.9)[[1]])) %>%
  ungroup() %>%
  pivot_longer(hpw_q1:hapa_q3) %>%
  separate(name,c("measure","quantile"),sep="_") %>%
  mutate(
    media=fct_relevel(media, "HS","STT"),
    measure=recode(measure,
      "hpw" = "Hedgings/words",
      "hps" = "Hedgings/sentences",
      "hpp" = "Hedgings/paragrahs",
      "hpa" = "Hedgings/articles",
      "hsps" = "Sentences containing hedgings/sentences",
      "hspp" = "Sentences containing hedgings/paragrahs",
      "hspa" = "Sentences containing hedgings/articles",
      "hppp" = "Paragraphs containing hedgings/paragrahs",
      "hppa" = "Paragraphs containing hedgings/articles",
      "hapa" = "Articles containing hedgings/articles"
    ),
    linetype=if_else(quantile=="q2","mean","1st/9th centile"),
    linetype=fct_relevel(linetype,"mean"),
    type2=fct_relevel(type2,"journalistic text in Domestic general/political/economic news", "indirect quotation in Domestic general/political/economic news", "direct quotation in Domestic general/political/economic news", "journalistic text in Local news", "indirect quotation in Local news", "direct quotation in Local news", "journalistic text in Foreign news", "indirect quotation in Foreign news", "direct quotation in Foreign news", "journalistic text in Culture/entertainment", "indirect quotation in Culture/entertainment", "direct quotation in Culture/entertainment", "journalistic text in Sports", "indirect quotation in Sports", "direct quotation in Sports","External opinion", "Journalistic opinion")
    )
hd2 %>% 
  filter(str_detect(type2,"Other")) %>%
  ggplot(aes(x=year_created,y=value,color=media,group=interaction(measure,quantile,media),linetype=linetype)) +
  geom_step() +
  facet_wrap(measure~type2,scales="free") +
  theme_hsci_discrete(base_family="Arial") +
  theme(legend.position="bottom")
hd2 %>% 
  group_by(measure) %>%
  group_map(~.x %>%
    filter(!str_detect(type2,"Other")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap(~type2,scales="free") +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
#    scale_y_continuous(breaks=seq(0,1,by=0.02), labels=scales::percent_format(accuract=1)) +
    labs(x="Year",y="Number of hedgings") +
    ggtitle(.y)
  )

Due to the lengthening of article texts causing complexities for analyses, all the following hedging proportions were calculated and evaluated:

  • Hedgings/words
  • Hedgings/sentences
  • Hedgings/paragrahs
  • Hedgings/articles
  • Sentences containing hedgings/sentences
  • Sentences containing hedgings/paragrahs
  • Sentences containing hedgings/articles
  • Paragraphs containing hedgings/paragrahs
  • Paragraphs containing hedgings/articles
  • Articles containing hedgings/articles

Out of these, “hedgings/words” and “hedgings/sentences” were retained for final analysis:

Hedgings/words

1:2 %>% map(~
  hd2 %>% 
    filter(measure=="Hedgings/words") %>%
    filter(!str_detect(type2,"Other"),!str_detect(type2,"in Journalistic opinion"),!str_detect(type2,"in External opinion")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap_paginate(~type2,ncol=4,nrow=3,page=.x) +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
    labs(x="Year",y="Hedgings/words")
)
[[1]]

[[2]]

Hedgings/sentences

1:2 %>% map(~
  hd2 %>% 
    filter(measure=="Hedgings/sentences") %>%
    filter(!str_detect(type2,"Other"),!str_detect(type2,"in Journalistic opinion"),!str_detect(type2,"in External opinion")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap_paginate(~type2,ncol=4,nrow=3,page=.x) +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
    labs(x="Year",y="Hedgings/sentences")
)
[[1]]

[[2]]

Interpretations:

  • Again, one can see an increase in the use of hedgings in journalistic text of domestic general/political/economic news, HS local news (Kaupunki) as well as this time in foreign news. Further, the increase in the use of direct quotes further adds hedging to the articles as a whole.

Usage of selected conjunctions

The following conjunctions were tracked:

  • subordinate conjunctions jotta, koska, kun, jos, vaikka, kunnes, mikäli
  • sillä, mutta
conjunction_counts_c <- words_c %>%
  filter(lemma %in% c("jotta","koska","kun","jos","vaikka","kunnes","mikäli","sillä","mutta")) %>%
  inner_join(corpus_c) %>%
  left_join(quotes_c %>% mutate(article_part=if_else(direct,"direct quotation","indirect quotation")),sql_on="LHS.a_id=RHS.a_id AND (s_id > start_s_id OR (s_id=start_s_id AND pos >= start_pos)) AND (s_id < end_s_id OR (s_id=end_s_id AND pos <= end_pos))") %>%
  replace_na(list(article_part="journalistic text")) %>%
  select(a_id=a_id.x,par_id,s_id,pos, article_part) %>%
  group_by(a_id,article_part) %>%
  summarize(nr_conjunctions=n_distinct(10000L*s_id+pos),nr_sentences_with_conjunctions=n_distinct(s_id),nr_paragraphs_with_conjunctions=n_distinct(par_id),.groups="drop") %>%
  compute_c(name="conjunction_counts_c")
conjunction_counts_c <- tbl(con,"conjunction_counts_c")
cd <- article_stats_long_c %>% 
  inner_join(article_types_c) %>%
  mutate(type2=str_c(article_part," in ",type)) %>%
  union_all(
    article_stats_long_c %>% 
    inner_join(article_types_c %>% rename(type2=type))
  ) %>%
  left_join(hedging_counts_c) %>%
  left_join(conjunction_counts_c) %>%
  replace_na(list(nr_conjunctions=0,nr_sentences_with_conjunctions=0,nr_paragraphs_with_conjunctions=0)) %>%
  group_by(a_id,type2) %>%
  summarize(nr_tokens=sum(nr_tokens),nr_conjunctions=sum(nr_conjunctions),nr_sentences=sum(nr_sentences),nr_paragraphs=sum(nr_paragraphs),nr_sentences_with_conjunctions=sum(nr_sentences_with_conjunctions),nr_paragraphs_with_conjunctions=sum(nr_paragraphs_with_conjunctions),.groups="drop") %>%
  inner_join(articles_c %>% select(a_id,media,year_created)) %>%
  mutate(
    cpw=nr_conjunctions/nr_tokens,
    cps=nr_conjunctions/nr_sentences,
    cpp=nr_conjunctions/nr_paragraphs,
    cpa=nr_conjunctions,
    csps=nr_sentences_with_conjunctions/nr_sentences,
    cspp=nr_sentences_with_conjunctions/nr_paragraphs,
    cspa=nr_sentences_with_conjunctions,
    cppp=nr_paragraphs_with_conjunctions/nr_paragraphs,
    cppa=nr_paragraphs_with_conjunctions,
    capa=if_else(nr_conjunctions>0,1,0)
  ) %>%
  select(year_created,media,type2,cpw:capa) %>%
  collect()

cd2 <- cd %>%
  replace_na(list(cpw=0,cps=0,cpp=0,cpa=0,csps=0,cspp=0,cspa=0,cppp=0,cppa=0,capa=0)) %>%
  group_by(year_created,media,type2) %>% 
  summarize_at(vars(cpw:capa),list(q1=~quantile(.x,0.25)[[1]],q2=mean,q3=~quantile(.x,0.75)[[1]])) %>%
  ungroup() %>%
  pivot_longer(cpw_q1:capa_q3) %>%
  separate(name,c("measure","quantile"),sep="_") %>%
  mutate(
    media=fct_relevel(media, "HS","STT"),
    measure=recode(measure,
      "cpw" = "Conjunctions/words",
      "cps" = "Conjunctions/sentences",
      "cpp" = "Conjunctions/paragrahs",
      "cpa" = "Conjunctions/articles",
      "csps" = "Sentences containing conjunctions/sentences",
      "cspp" = "Sentences containing conjunctions/paragrahs",
      "cspa" = "Sentences containing conjunctions/articles",
      "cppp" = "Paragraphs containing conjunctions/paragrahs",
      "cppa" = "Paragraphs containing conjunctions/articles",
      "capa" = "Articles containing conjunctions/articles"
    ),
    linetype=if_else(quantile=="q2","mean","1st/3rd quartile"),
    linetype=fct_relevel(linetype,"mean"),
    type2=fct_relevel(type2,"Domestic general/political/economic news", "journalistic text in Domestic general/political/economic news", "indirect quotation in Domestic general/political/economic news", "direct quotation in Domestic general/political/economic news", "Local news", "journalistic text in Local news", "indirect quotation in Local news", "direct quotation in Local news", "Foreign news", "journalistic text in Foreign news", "indirect quotation in Foreign news", "direct quotation in Foreign news", "Culture/entertainment", "journalistic text in Culture/entertainment", "indirect quotation in Culture/entertainment", "direct quotation in Culture/entertainment", "Sports", "journalistic text in Sports", "indirect quotation in Sports", "direct quotation in Sports","External opinion", "Journalistic opinion")
    )
cd2 %>% 
  filter(str_detect(type2,"Other")) %>%
  ggplot(aes(x=year_created,y=value,color=media,group=interaction(measure,quantile,media),linetype=linetype)) +
  geom_step() +
  facet_wrap(measure~type2,scales="free") +
  theme_hsci_discrete(base_family="Arial") +
  theme(legend.position="bottom")
cd2 %>% 
  group_by(measure) %>%
  group_map(~.x %>%
    filter(!str_detect(type2,"Other")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap(~type2,scales="free") +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
    labs(x="Year",y="Number of conjunctions") +
    ggtitle(.y)
  )

Due to the lengthening of article texts causing complexities for analyses, all the following conjunction proportions were calculated and evaluated:

  • Conjunctions/words
  • Conjunctions/sentences
  • Conjunctions/paragrahs
  • Conjunctions/articles
  • Sentences containing conjunctions/sentences
  • Sentences containing conjunctions/paragrahs
  • Sentences containing conjunctions/articles
  • Paragraphs containing conjunctions/paragrahs
  • Paragraphs containing conjunctions/articles
  • Articles containing conjunctions/articles

Out of these, “Sentences containing conjunctions/sentences” was retained for final analysis:

Sentences containing conjunctions/sentences

1:2 %>% map(~
  cd2 %>% 
    filter(measure=="Sentences containing conjunctions/sentences") %>%
    filter(!str_detect(type2,"Other"),!str_detect(type2,"in Journalistic opinion"),!str_detect(type2,"in External opinion")) %>%
    ggplot(aes(x=year_created,y=value,color=media,group=interaction(quantile,media),linetype=linetype)) +
    geom_step() +
    facet_wrap_paginate(~type2,ncol=4,nrow=3,page=.x) +
    theme_hsci_discrete(base_family="Arial") +
    theme(legend.position="bottom") +
    scale_x_continuous(breaks=seq(2000,2020,by=4)) +
    labs(x="Year",y="Sentences containing conjunctions/sentences")
)
[[1]]

[[2]]

Interpretations:

  • There is an increase in sentence constructions with conjunctions denoting interpretive subclauses in particularly domestic news reporting and HS Kaupunki. The overall increase comes mostly from journalistic text and not from an increase in quotes.
LS0tCnRpdGxlOiAiRGV2ZWxvcG1lbnQgb2YgaW50ZXJwcmV0YXRpdmVuZXNzIGluIGpvdXJuYWxpc20iCmF1dGhvcjogIkVldHUgTcOka2Vsw6QiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0b2M6IHllcwotLS0KCiMgU2V0dXAKCmBgYHtyIHNldHVwLGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gaGVyZTo6aGVyZSgpKQoKbGlicmFyeShoZXJlKQpzb3VyY2UoaGVyZSgiY29kZS9jb21tb25fYmFzaXMuUiIpLCBsb2NhbCA9IGtuaXRyOjprbml0X2dsb2JhbCgpKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGhtcykKbGlicmFyeShnZ2JlZXN3YXJtKQpsaWJyYXJ5KGdnaHNjaSkKbGlicmFyeShnZ2ZvcmNlKQpsaWJyYXJ5KGd0KQoKcCA8LSBmdW5jdGlvbihudW1iZXIpIHsKICByZXR1cm4oZm9ybWF0KG51bWJlciwgc2NpZW50aWZpYyA9IEZBTFNFLCBiaWcubWFyayA9ICIsIikpCn0KcHAgPC0gZnVuY3Rpb24ocGVyY2VudGFnZSxhY2N1cmFjeT0wLjAxKSB7CiAgcmV0dXJuKHNjYWxlczo6cGVyY2VudChwZXJjZW50YWdlLCBhY2N1cmFjeSA9IGFjY3VyYWN5KSkKfQoKYGBgCgojIyBBbmFseXNpcyB0YWJsZSBjcmVhdGlvbiAobm90IHJ1bikKCmBgYHtyLGV2YWw9RkFMU0V9CmFydGljbGVzX29waW5pb25hdGVkX2MgPC0gYXJ0aWNsZXNfYyAlPiUgbXV0YXRlKG9waW5pb25hdGVkPWNhc2Vfd2hlbigKICBtZWRpYSA9PSAiSFMiIH4gY2FzZV93aGVuKAogICAgc3RyX3RvX2xvd2VyKHNlY3Rpb24pID09ICJww6TDpGtpcmpvaXR1cyIgJiBzdHJfZGV0ZWN0KHN0cl90b19sb3dlcihzdG9yeV9sb2dvKSwiaWVyYXMiKSB+ICJleHRlcm5hbCBlZGl0b3JpYWwiLAogICAgc3RyX3RvX2xvd2VyKHNlY3Rpb24pID09ICJww6TDpGtpcmpvaXR1cyIgJiBpcy5uYShzdG9yeV9sb2dvKSB+ICJlZGl0b3JpYWwiLAogICAgc3RyX3RvX2xvd2VyKHNlY3Rpb24pID09ICJww6TDpGtpcmpvaXR1cyIgJiBzdHJfdG9fbG93ZXIoc3RvcnlfbG9nbykgPT0gInDDpMOka2lyam9pdHVzIiB+ICJlZGl0b3JpYWwiLAogICAgc3RyX3RvX2xvd2VyKHNlY3Rpb24pID09ICJtaWVsaXBpZGUiIHwgc3RyX3RvX2xvd2VyKHN0b3J5X2xvZ28pID09ICJtaWVsaXBpZGUiIH4gImV4dGVybmFsIG9waW5pb24iLAogICAgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIodGl0bGUpLCJhbmFseXlzaToiKSB8IHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHN0b3J5X2xvZ28pLCJhbmFseXlzaSIpICB+ICJhbmFseXNpcyIsCiAgICBzdHJfZGV0ZWN0KHN0cl90b19sb3dlcih0aXRsZSksIm7DpGvDtmt1bG1hOiIpIHwgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIoc3RvcnlfbG9nbyksIm7DpGvDtmt1bG1hIikgfiAicGVyc3BlY3RpdmUiLAogICAgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIodGl0bGUpLCJrb2x1bW5pOiIpIHwgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIoc3RvcnlfbG9nbyksImtvbHVtbmkiKSB+ICJjb2x1bW4iLAogICAgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIodGl0bGUpLCJibG9naToiKSB8IHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHN0b3J5X2xvZ28pLCJibG9nIikgfiAiYmxvZyIgICAgCiAgKSwKICBtZWRpYSA9PSAiSUwiIH4gY2FzZV93aGVuKAogICAgc3Vic2VjdGlvbiA9PSAicGFha2lyam9pdHVzIiB+ICJlZGl0b3JpYWwiLAogICAgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIodGl0bGUpLCJrb21tZW50dGk6IikgfiAiY29tbWVudGFyeSIsCiAgICBzdHJfZGV0ZWN0KHN0cl90b19sb3dlcih0aXRsZSksImFuYWx5eXNpOiIpIH4gImFuYWx5c2lzIiwKICAgIHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHRpdGxlKSwia29sdW1uaToiKSB+ICJjb2x1bW4iLAogICAgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIodGl0bGUpLCJuw6Rrw7ZrdWxtYToiKSB+ICJwZXJzcGVjdGl2ZSIKICApLAogIG1lZGlhID09ICJZTEUiIH4gY2FzZV93aGVuKAogICAgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIodGl0bGUpLCJrb21tZW50dGk6IikgfiAiY29tbWVudGFyeSIsCiAgICBzdHJfZGV0ZWN0KHN0cl90b19sb3dlcih0aXRsZSksImFuYWx5eXNpOiIpIHwgc3RyX2RldGVjdChzdWJqZWN0LCJBbmFseXlzaXQgXFwoWWxlIFV1dGlzZXRcXCkiKSB+ICJhbmFseXNpcyIsCiAgICBzdHJfZGV0ZWN0KHN0cl90b19sb3dlcih0aXRsZSksImtvbHVtbmk6IikgfCBzdHJfZGV0ZWN0KHN0cl90b19sb3dlcihzdWJqZWN0KSwia29sdW1uIikgfiAiY29sdW1uIiwKICAgIHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHRpdGxlKSwibsOka8O2a3VsbWE6IikgIHwgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIoc3ViamVjdCksIm7DpGvDtmt1bG0iKSB+ICJwZXJzcGVjdGl2ZSIsCiAgICBzdHJfZGV0ZWN0KHN0cl90b19sb3dlcih0aXRsZSksImJsb2dpOiIpICB8IHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHN1YmplY3QpLCJibG9nIikgfiAiYmxvZyIKICApCikpICU+JQogIGZpbHRlcighaXMubmEob3BpbmlvbmF0ZWQpKSAlPiUKICBkaXN0aW5jdChhX2lkLCBvcGluaW9uYXRlZCkgJT4lCiAgY29tcHV0ZV9jKG5hbWU9ImFydGljbGVzX29waW5pb25hdGVkX2MiKQoKYXJ0aWNsZV90eXBlc19jIDwtIGFydGljbGVzX2MgJT4lIAogIGxlZnRfam9pbihhcnRpY2xlc19vcGluaW9uYXRlZF9jKSAlPiUKICBtdXRhdGUodHlwZT1jYXNlX3doZW4oCiAgICBtZWRpYSA9PSAiU1RUIiAmIHZlcnNpb24gIT0gIkxvcHB1dmVyc2lvIiB+ICJPdGhlciIsCiAgICAhaXMubmEob3BpbmlvbmF0ZWQpICYgIXN0cl9kZXRlY3Qob3BpbmlvbmF0ZWQsIl5leHRlcm5hbCAiKSB+ICJKb3VybmFsaXN0aWMgb3BpbmlvbiIsCiAgICAhaXMubmEob3BpbmlvbmF0ZWQpIH4gIkV4dGVybmFsIG9waW5pb24iLAogICAgbWVkaWEgPT0gIkhTIiAmIHNlY3Rpb24gJWluJSBjKCJLb3RpbWFhIiwgIlBvbGl0aWlra2EiLCAiVGFsb3VzIikgfiAiRG9tZXN0aWMgZ2VuZXJhbC9wb2xpdGljYWwvZWNvbm9taWMgbmV3cyIsCiAgbWVkaWEgPT0gIklMIiAmIHN1YnNlY3Rpb24gJWluJSBjKCJrb3RpbWFhIiwicG9saXRpaWtrYSIsInRhbG91cyIsInV1dGlzZXQiKSB+ICJEb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzIiwKICBtZWRpYSA9PSAiU1RUIiAmIHNlY3Rpb24gJWluJSBjKCJLb3RpbWFhIiwiUG9saXRpaWtrYSIsIlRhbG91cyIpIH4gIkRvbWVzdGljIGdlbmVyYWwvcG9saXRpY2FsL2Vjb25vbWljIG5ld3MiLAogIG1lZGlhID09ICJZTEUiICYgc2VjdGlvbiA9PSAiWWxlIFV1dGlzZXQiICYgc3RyX2RldGVjdChzdWJqZWN0LCJLb3RpbWFhbiB1dXRpc2V0fHBvbGl0aWlra2F8dGFsb3VzIikgJiAoIXN0cl9kZXRlY3Qoc3ViamVjdCwiVWxrb21hYXQiKSB8IHN0cl9kZXRlY3Qoc3ViamVjdCwiS290aW1hYW4gdXV0aXNldCIpKSB+ICJEb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzIiwKICAgIG1lZGlhID09ICJIUyIgJiBzZWN0aW9uID09ICJLdWx0dHV1cmkiIH4gIkN1bHR1cmUvZW50ZXJ0YWlubWVudCIsCiAgICBtZWRpYSA9PSAiSUwiICYgc2VjdGlvbiA9PSAidmlpaGRlIiB+ICJDdWx0dXJlL2VudGVydGFpbm1lbnQiLAogICAgbWVkaWEgPT0gIlNUVCIgJiBzZWN0aW9uID09ICJLdWx0dHV1cmkiIH4gIkN1bHR1cmUvZW50ZXJ0YWlubWVudCIsCiAgICBtZWRpYSA9PSAiWUxFIiAmIHNlY3Rpb24gPT0gIllsZSBVdXRpc2V0IiAmIHN0cl9kZXRlY3Qoc3ViamVjdCwia3VsdHR1dXJpfG11c2lpa2tpfHZpaWhkZSIpICYgIXN0cl9kZXRlY3Qoc3ViamVjdCwgIlVsa29tYWF0IikgfiAiQ3VsdHVyZS9lbnRlcnRhaW5tZW50IiwKICAgIG1lZGlhID09ICJIUyIgJiBzZWN0aW9uID09ICJLYXVwdW5raSIgfiAiTG9jYWwgbmV3cyIsCiAgICBtZWRpYSA9PSAiWUxFIiAmIHNlY3Rpb24gPT0gIllsZSBVdXRpc2V0IiAmIGNvdmVyYWdlPT0ibG9jYWwiIH4gIkxvY2FsIG5ld3MiLAogICAgbWVkaWEgPT0gIlNUVCIgJiBzZWN0aW9uID09ICJVcmhlaWx1IiB+ICJTcG9ydHMiLAogICAgbWVkaWEgPT0gIkhTIiAmIHNlY3Rpb24gPT0gIlVyaGVpbHUiIH4gIlNwb3J0cyIsCiAgICBtZWRpYSA9PSAiWUxFIiAmIHNlY3Rpb24gPT0gIllMRSBVcmhlaWx1IiB+ICJTcG9ydHMiLAogICAgbWVkaWEgPT0gIklMIiAmIHNlY3Rpb24gPT0gInVyaGVpbHUiIH4gIlNwb3J0cyIsCiAgICBtZWRpYSA9PSAiU1RUIiAmIHNlY3Rpb24gPT0gIlVsa29tYWF0IiB+ICJGb3JlaWduIG5ld3MiLAogICAgbWVkaWEgPT0gIkhTIiAmIHNlY3Rpb24gPT0gIlVsa29tYWF0IiB+ICJGb3JlaWduIG5ld3MiLAogICAgbWVkaWEgPT0gIllMRSIgJiBzZWN0aW9uID09ICJZbGUgVXV0aXNldCIgJiBzdHJfZGV0ZWN0KHN1YmplY3QsIlVsa29tYWF0IikgJiAhc3RyX2RldGVjdChzdWJqZWN0LCJLb3RpbWFhbiB1dXRpc2V0IikgfiAiRm9yZWlnbiBuZXdzIiwKICAgIG1lZGlhID09ICJJTCIgJiBzdWJzZWN0aW9uID09ICJ1bGtvbWFhdCIgfiAiRm9yZWlnbiBuZXdzIiwKICAgIFQgfiAiT3RoZXIiCiAgKSkgJT4lCiAgZGlzdGluY3QoYV9pZCx0eXBlKSAlPiUKICBjb21wdXRlX2MobmFtZT0iYXJ0aWNsZV90eXBlcyIpCgphcnRpY2xlX3F1b3Rlc19zdGF0c19jIDwtIGNvcnB1c19jICU+JSAKICBpbm5lcl9qb2luKHF1b3Rlc19jLHNxbF9vbj0iTEhTLmFfaWQ9UkhTLmFfaWQgQU5EIChzX2lkID4gc3RhcnRfc19pZCBPUiAoc19pZD1zdGFydF9zX2lkIEFORCBwb3MgPj0gc3RhcnRfcG9zKSkgQU5EIChzX2lkIDwgZW5kX3NfaWQgT1IgKHNfaWQ9ZW5kX3NfaWQgQU5EIHBvcyA8PSBlbmRfcG9zKSkiKSAlPiUKICBncm91cF9ieShhX2lkPWFfaWQueCwgZGlyZWN0KSAlPiUKICBzdW1tYXJpemUoCiAgICBucl9xdW90ZV90b2tlbnM9bl9kaXN0aW5jdCgxMDAwMEwqc19pZCtwb3MpLAogICAgbnJfc2VudGVuY2VzX3dpdGhfcXVvdGVzPW5fZGlzdGluY3Qoc19pZCksCiAgICBucl9wYXJhZ3JhcGhzX3dpdGhfcXVvdGVzPW5fZGlzdGluY3QocGFyX2lkKSwKICAgIG5yX3F1b3Rlcz1uX2Rpc3RpbmN0KHFfaWQpLAogICAgLmdyb3Vwcz0iZHJvcCIpICU+JQogIGNvbXB1dGVfYyhuYW1lPSJhcnRpY2xlX3F1b3Rlc19zdGF0c19jIikKCmFydGljbGVfc3RhdHNfYyA8LSAKICBjb3JwdXNfYyAlPiUKICBncm91cF9ieShhX2lkKSAlPiUKICBzdW1tYXJpemUoCiAgICBucl90b2tlbnM9bigpLAogICAgbnJfc2VudGVuY2VzPW5fZGlzdGluY3Qoc19pZCksCiAgICBucl9wYXJhZ3JhcGhzPW5fZGlzdGluY3QocGFyX2lkKSwKICAgIC5ncm91cHM9ImRyb3AiKSAlPiUKICBjb21wdXRlX2MoKSAlPiUKICBsZWZ0X2pvaW4oCiAgICBhcnRpY2xlX3F1b3Rlc19zdGF0c19jICU+JQogICAgICBmaWx0ZXIoZGlyZWN0PT1UUlVFKSAlPiUKICAgICAgc2VsZWN0KAogICAgICAgIGFfaWQsCiAgICAgICAgbnJfZGlyZWN0X3F1b3RlX3Rva2Vucz1ucl9xdW90ZV90b2tlbnMsCiAgICAgICAgbnJfc2VudGVuY2VzX3dpdGhfZGlyZWN0X3F1b3Rlcz1ucl9zZW50ZW5jZXNfd2l0aF9xdW90ZXMsCiAgICAgICAgbnJfcGFyYWdyYXBoc193aXRoX2RpcmVjdF9xdW90ZXM9bnJfcGFyYWdyYXBoc193aXRoX3F1b3RlcywKICAgICAgICBucl9kaXJlY3RfcXVvdGVzPW5yX3F1b3RlcykKICApICU+JQogIGxlZnRfam9pbigKICAgIGFydGljbGVfcXVvdGVzX3N0YXRzX2MgJT4lCiAgICAgIGZpbHRlcihkaXJlY3Q9PUZBTFNFKSAlPiUKICAgICAgc2VsZWN0KAogICAgICAgIGFfaWQsCiAgICAgICAgbnJfaW5kaXJlY3RfcXVvdGVfdG9rZW5zPW5yX3F1b3RlX3Rva2VucywKICAgICAgICBucl9zZW50ZW5jZXNfd2l0aF9pbmRpcmVjdF9xdW90ZXM9bnJfc2VudGVuY2VzX3dpdGhfcXVvdGVzLAogICAgICAgIG5yX3BhcmFncmFwaHNfd2l0aF9pbmRpcmVjdF9xdW90ZXM9bnJfcGFyYWdyYXBoc193aXRoX3F1b3RlcywKICAgICAgICBucl9pbmRpcmVjdF9xdW90ZXM9bnJfcXVvdGVzKQogICkgJT4lIAogIGxlZnRfam9pbigKICAgIGNvcnB1c19jICU+JSAKICAgIGlubmVyX2pvaW4ocXVvdGVzX2Msc3FsX29uPSJMSFMuYV9pZD1SSFMuYV9pZCBBTkQgKHNfaWQgPiBzdGFydF9zX2lkIE9SIChzX2lkPXN0YXJ0X3NfaWQgQU5EIHBvcyA+PSBzdGFydF9wb3MpKSBBTkQgKHNfaWQgPCBlbmRfc19pZCBPUiAoc19pZD1lbmRfc19pZCBBTkQgcG9zIDw9IGVuZF9wb3MpKSIpICU+JQogICAgZ3JvdXBfYnkoYV9pZD1hX2lkLngpICU+JQogICAgc3VtbWFyaXplKAogICAgICBucl9xdW90ZV90b2tlbnM9bl9kaXN0aW5jdCgxMDAwMEwqc19pZCtwb3MpLAogICAgICBucl9zZW50ZW5jZXNfd2l0aF9xdW90ZXM9bl9kaXN0aW5jdChzX2lkKSwKICAgICAgbnJfcGFyYWdyYXBoc193aXRoX3F1b3Rlcz1uX2Rpc3RpbmN0KHBhcl9pZCksCiAgICAgIG5yX3F1b3Rlcz1uX2Rpc3RpbmN0KHFfaWQpLAogICAgICAuZ3JvdXBzPSJkcm9wIikgJT4lCiAgICBjb21wdXRlX2MoKQogICkgJT4lCiAgcmVwbGFjZV9uYShsaXN0KAogICAgbnJfZGlyZWN0X3F1b3RlX3Rva2Vucz0wTCxucl9zZW50ZW5jZXNfd2l0aF9kaXJlY3RfcXVvdGVzPTBMLG5yX3BhcmFncmFwaHNfd2l0aF9kaXJlY3RfcXVvdGVzPTBMLG5yX2RpcmVjdF9xdW90ZXM9MEwsCiAgICBucl9pbmRpcmVjdF9xdW90ZV90b2tlbnM9MEwsbnJfc2VudGVuY2VzX3dpdGhfaW5kaXJlY3RfcXVvdGVzPTBMLG5yX3BhcmFncmFwaHNfd2l0aF9pbmRpcmVjdF9xdW90ZXM9MEwsbnJfaW5kaXJlY3RfcXVvdGVzPTBMLAogICAgbnJfcXVvdGVfdG9rZW5zPTBMLG5yX3NlbnRlbmNlc193aXRoX3F1b3Rlcz0wTCxucl9wYXJhZ3JhcGhzX3dpdGhfcXVvdGVzPTBMLG5yX3F1b3Rlcz0wTAogICAgKSkgJT4lCiAgY29tcHV0ZV9jKG5hbWU9ImFydGljbGVfc3RhdHNfYyIpCgphZGplY3RpdmVfY291bnRzX2MgPC0gd29yZHNfYyAlPiUgCiAgZmlsdGVyKHVwb3M9PSJBREoiKSAlPiUKICBpbm5lcl9qb2luKGNvcnB1c19jKSAlPiUKICBsZWZ0X2pvaW4ocXVvdGVzX2MgJT4lIG11dGF0ZShhcnRpY2xlX3BhcnQ9aWZfZWxzZShkaXJlY3QsImRpcmVjdCBxdW90YXRpb24iLCJpbmRpcmVjdCBxdW90YXRpb24iKSksc3FsX29uPSJMSFMuYV9pZD1SSFMuYV9pZCBBTkQgKHNfaWQgPiBzdGFydF9zX2lkIE9SIChzX2lkPXN0YXJ0X3NfaWQgQU5EIHBvcyA+PSBzdGFydF9wb3MpKSBBTkQgKHNfaWQgPCBlbmRfc19pZCBPUiAoc19pZD1lbmRfc19pZCBBTkQgcG9zIDw9IGVuZF9wb3MpKSIpICU+JQogIHNlbGVjdChhX2lkPWFfaWQueCxwYXJfaWQsc19pZCxwb3MsYXJ0aWNsZV9wYXJ0KSAlPiUKICByZXBsYWNlX25hKGxpc3QoYXJ0aWNsZV9wYXJ0PSJqb3VybmFsaXN0aWMgdGV4dCIpKSAlPiUKICBncm91cF9ieShhX2lkLGFydGljbGVfcGFydCkgJT4lCiAgc3VtbWFyaXplKG5yX2FkamVjdGl2ZXM9bl9kaXN0aW5jdCgxMDAwMEwqc19pZCtwb3MpLG5yX3NlbnRlbmNlc193aXRoX2FkamVjdGl2ZXM9bl9kaXN0aW5jdChzX2lkKSxucl9wYXJhZ3JhcGhzX3dpdGhfYWRqZWN0aXZlcz1uX2Rpc3RpbmN0KHBhcl9pZCksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGNvbXB1dGVfYyhuYW1lPSJhZGplY3RpdmVfY291bnRzX2MiKQoKaGVkZ2luZ19tYXJrZXJzIDwtIHJlYWRfY3N2KGhlcmUoImRhdGEvaW5wdXQvaGVkZ2luZ19tYXJrZXJzLmNzdiIpKSAlPiUgCiAgcmVuYW1lKHR5cGU9Li4uMSx2YWx1ZT0uLi4yLGNsYXNzPS4uLjMpCgpoZWRnaW5nX2NvdW50c19jIDwtIHdvcmRzX2MgJT4lIAogIGlubmVyX2pvaW4oaGVkZ2luZ19tYXJrZXJzICU+JSAKICAgICAgICAgICAgICAgZmlsdGVyKGNsYXNzICVpbiUgYygiQWR2ZXJicyIsIkFkamVjdGl2ZSIpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KGxlbW1hPXZhbHVlKSAlPiUgY29weV90b19jKGNvbikpICU+JQogIGlubmVyX2pvaW4oY29ycHVzX2MpICU+JQogIGxlZnRfam9pbihxdW90ZXNfYyAlPiUgbXV0YXRlKGFydGljbGVfcGFydD1pZl9lbHNlKGRpcmVjdCwiZGlyZWN0IHF1b3RhdGlvbiIsImluZGlyZWN0IHF1b3RhdGlvbiIpKSxzcWxfb249IkxIUy5hX2lkPVJIUy5hX2lkIEFORCAoc19pZCA+IHN0YXJ0X3NfaWQgT1IgKHNfaWQ9c3RhcnRfc19pZCBBTkQgcG9zID49IHN0YXJ0X3BvcykpIEFORCAoc19pZCA8IGVuZF9zX2lkIE9SIChzX2lkPWVuZF9zX2lkIEFORCBwb3MgPD0gZW5kX3BvcykpIikgJT4lCiAgcmVwbGFjZV9uYShsaXN0KGFydGljbGVfcGFydD0iam91cm5hbGlzdGljIHRleHQiKSkgJT4lCiAgc2VsZWN0KGFfaWQ9YV9pZC54LHBhcl9pZCxzX2lkLHBvcywgYXJ0aWNsZV9wYXJ0KSAlPiUKICBncm91cF9ieShhX2lkLGFydGljbGVfcGFydCkgJT4lCiAgc3VtbWFyaXplKG5yX2hlZGdpbmdzPW5fZGlzdGluY3QoMTAwMDBMKnNfaWQrcG9zKSxucl9zZW50ZW5jZXNfd2l0aF9oZWRnaW5ncz1uX2Rpc3RpbmN0KHNfaWQpLG5yX3BhcmFncmFwaHNfd2l0aF9oZWRnaW5ncz1uX2Rpc3RpbmN0KHBhcl9pZCksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGNvbXB1dGVfYyhuYW1lPSJoZWRnaW5nX2NvdW50c19jIikKYGBgCgojIyBBbmFseXNpcyB0YWJsZSBsb2FkcwoKYGBge3J9CmFydGljbGVfc3RhdHNfYyA8LSB0YmwoY29uLCJhcnRpY2xlX3N0YXRzX2MiKQphcnRpY2xlX3F1b3Rlc19zdGF0c19jIDwtIHRibChjb24sImFydGljbGVfcXVvdGVzX3N0YXRzX2MiKQphZGplY3RpdmVfY291bnRzX2MgPC0gdGJsKGNvbiwiYWRqZWN0aXZlX2NvdW50c19jIikKaGVkZ2luZ19jb3VudHNfYyA8LSB0YmwoY29uLCJoZWRnaW5nX2NvdW50c19jIikKCmFydGljbGVfc3RhdHNfbG9uZ19jIDwtCiAgYXJ0aWNsZV9zdGF0c19jICU+JQogIG11dGF0ZShucl90b2tlbnM9bnJfdG9rZW5zLW5yX3F1b3RlX3Rva2Vucyxucl9zZW50ZW5jZXM9bnJfc2VudGVuY2VzLW5yX3NlbnRlbmNlc193aXRoX3F1b3Rlcyxucl9wYXJhZ3JhcGhzPW5yX3BhcmFncmFwaHMtbnJfcGFyYWdyYXBoc193aXRoX3F1b3RlcykgJT4lCiAgc2VsZWN0KGFfaWQsbnJfdG9rZW5zOm5yX3BhcmFncmFwaHMpICU+JQogIG11dGF0ZShhcnRpY2xlX3BhcnQ9J2pvdXJuYWxpc3RpYyB0ZXh0JykgJT4lCiAgdW5pb25fYWxsKAogICAgYXJ0aWNsZV9zdGF0c19jICU+JQogICAgICBmaWx0ZXIobnJfZGlyZWN0X3F1b3RlX3Rva2Vucz4wKSAlPiUKICAgICAgc2VsZWN0KGFfaWQsbnJfdG9rZW5zPW5yX2RpcmVjdF9xdW90ZV90b2tlbnMsbnJfc2VudGVuY2VzPW5yX3NlbnRlbmNlc193aXRoX2RpcmVjdF9xdW90ZXMsbnJfcGFyYWdyYXBocz1ucl9wYXJhZ3JhcGhzX3dpdGhfZGlyZWN0X3F1b3RlcykgJT4lIAogICAgICBtdXRhdGUoYXJ0aWNsZV9wYXJ0PSdkaXJlY3QgcXVvdGF0aW9uJykKICApICU+JQogIHVuaW9uX2FsbCgKICAgIGFydGljbGVfc3RhdHNfYyAlPiUKICAgICAgZmlsdGVyKG5yX2luZGlyZWN0X3F1b3RlX3Rva2Vucz4wKSAlPiUKICAgICAgc2VsZWN0KGFfaWQsbnJfdG9rZW5zPW5yX2luZGlyZWN0X3F1b3RlX3Rva2Vucyxucl9zZW50ZW5jZXM9bnJfc2VudGVuY2VzX3dpdGhfaW5kaXJlY3RfcXVvdGVzLG5yX3BhcmFncmFwaHM9bnJfcGFyYWdyYXBoc193aXRoX2luZGlyZWN0X3F1b3RlcykgJT4lIAogICAgICBtdXRhdGUoYXJ0aWNsZV9wYXJ0PSdpbmRpcmVjdCBxdW90YXRpb24nKQogICkgIApgYGAKCgojIEFuYWx5c2lzCgojIyBPcGluaW9uYXRlZCBnZW5yZXMKCmBgYHtyfQphcnRpY2xlX3R5cGVzX2EgJT4lCiAgZmlsdGVyKHR5cGUhPSJPdGhlciIpICU+JQogIGlubmVyX2pvaW4oYXJ0aWNsZXNfYSAlPiUgc2VsZWN0KGFfaWQseWVhcl9jcmVhdGVkLG1lZGlhKSkgJT4lCiAgZ3JvdXBfYnkoeWVhcl9jcmVhdGVkLG1lZGlhKSAlPiUKICBzdW1tYXJpemUobj1zdW0odHlwZT09IkpvdXJuYWxpc3RpYyBvcGluaW9uIikvbigpLC5ncm91cHM9ImRyb3AiKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXJfY3JlYXRlZCxjb2xvcj1tZWRpYSx5PW4pKSArCiAgZ2VvbV9zdGVwKCkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwxLGJ5PTAuMDEpLGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5PTEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMjAwMCwyMDIwLGJ5PTIpKSArCiAgbGFicyh4PSJZZWFyIix5PSJQZXJjZW50YWdlIG9mIGFydGljbGVzIGJlaW5nIGpvdXJuYWxpc3RpYyBvcGluaW9uIikKYGBgCgpJbnRlcnByZXRhdGlvbnM6CgogLSBUaGUgaHVnZSBidW1wIGluIG9waW5pb25hdGVkIGFydGljbGVzIGZvciBIUyBjb21lcyBmcm9tIGEgaHVnZSBpbmNyZWFzZSBpbiBjb2x1bW5zLiBXaWxsIG5lZWQgdG8gY2hlY2sgd2hldGhlciB3ZSBhcmUgcGlja2luZyB1cCBjb2x1bW5zIGFjY3VyYXRlbHkgYmVmb3JlIDIwMTMuIEhvd2V2ZXIsIGdlbmVyYWwgdHJlbmQgdG93YXJkcyBoYXZpbmcgbW9yZSBvcGluaW9uYXRlZCB0ZXh0cyBpcyBjbGVhciBhY3Jvc3MgdGhlIG91dGxldHMuCgojIyBBcnRpY2xlIGxlbmd0aCBkZXZlbG9wbWVudAoKYGBge3J9CmxkIDwtIGFydGljbGVfc3RhdHNfYyAlPiUgCiAgaW5uZXJfam9pbihhcnRpY2xlc19jICU+JSBzZWxlY3QoYV9pZCxtZWRpYSx5ZWFyX2NyZWF0ZWQpKSAlPiUKICBpbm5lcl9qb2luKGFydGljbGVfdHlwZXNfYykgJT4lCiAgc2VsZWN0KG1lZGlhLHR5cGUseWVhcl9jcmVhdGVkLG5yX3Rva2Vucyxucl9zZW50ZW5jZXMsbnJfcGFyYWdyYXBocykgJT4lIAogIGNvbGxlY3QoKQoKbGQyIDwtIGxkICU+JQogIGdyb3VwX2J5KHllYXJfY3JlYXRlZCxtZWRpYSx0eXBlKSAlPiUgCiAgc3VtbWFyaXplX2FsbChsaXN0KHExPX5xdWFudGlsZSgueCwwLjI1KVtbMV1dLHEyPW1lYW4scTM9fnF1YW50aWxlKC54LDAuNzUpW1sxXV0pKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKG5yX3Rva2Vuc19xMTpucl9wYXJhZ3JhcGhzX3EzKSAlPiUKICBzZXBhcmF0ZShuYW1lLGMoTkEsIm1lYXN1cmUiLCJxdWFudGlsZSIpLHNlcD0iXyIpICU+JQogIG11dGF0ZSgKICAgIG1lZGlhPWZjdF9yZWxldmVsKG1lZGlhLCAiSFMiLCJTVFQiKSwKICAgIGxpbmV0eXBlPWlmX2Vsc2UocXVhbnRpbGU9PSJxMiIsIm1lYW4iLCIxc3QvM3JkIHF1YXJ0aWxlIiksCiAgICBsaW5ldHlwZT1mY3RfcmVsZXZlbChsaW5ldHlwZSwibWVhbiIpLAogICAgdHlwZT1mY3RfcmVsZXZlbCh0eXBlLCJFeHRlcm5hbCBvcGluaW9uIiwgIkpvdXJuYWxpc3RpYyBvcGluaW9uIiwgIkRvbWVzdGljIGdlbmVyYWwvcG9saXRpY2FsL2Vjb25vbWljIG5ld3MiLCAiTG9jYWwgbmV3cyIsICJGb3JlaWduIG5ld3MiLCAiQ3VsdHVyZS9lbnRlcnRhaW5tZW50IiwgIlNwb3J0cyIpLAogICAgbWVhc3VyZT1yZWNvZGUobWVhc3VyZSwKICAgICAgInRva2VucyIgPSAiV29yZHMiLAogICAgICAic2VudGVuY2VzIiA9ICJTZW50ZW5jZXMiLAogICAgICAicGFyYWdyYXBocyIgPSAiUGFyYWdyYXBocyIsCiAgICApCiAgKQoKYGBgCgpgYGB7cixmaWcud2lkdGg9OH0KbGQyICU+JSAKICBncm91cF9ieShtZWFzdXJlKSAlPiUKICBncm91cF9tYXAofi54ICU+JQogICAgZmlsdGVyKCFzdHJfZGV0ZWN0KHR5cGUsIk90aGVyIikpICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXJfY3JlYXRlZCx5PXZhbHVlLGNvbG9yPW1lZGlhLGdyb3VwPWludGVyYWN0aW9uKHF1YW50aWxlLG1lZGlhKSxsaW5ldHlwZT1saW5ldHlwZSkpICsKICAgIGdlb21fc3RlcCgpICsKICAgIGZhY2V0X3dyYXAofnR5cGUsc2NhbGVzPSJmcmVlIikgKwogICAgdGhlbWVfaHNjaV9kaXNjcmV0ZShiYXNlX2ZhbWlseT0iQXJpYWwiKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDIwMDAsMjAyMCxieT00KSkgKwojICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3M9c2VxKDAsMSxieT0wLjAyKSwgbGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3Q9MSkpICsKICAgIGxhYnMoeD0iWWVhciIseT0ueSkKICApCmBgYAoKCmBgYHtyfQpsZDMgPC0gbGQgJT4lCiAgZ3JvdXBfYnkoeWVhcl9jcmVhdGVkLG1lZGlhLHR5cGUpICU+JQogIHN1bW1hcml6ZV9hbGwoc3VtKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKAogICAgdHlwZT1mY3RfcmVsZXZlbCh0eXBlLCJFeHRlcm5hbCBvcGluaW9uIiwgIkpvdXJuYWxpc3RpYyBvcGluaW9uIiwgIkRvbWVzdGljIGdlbmVyYWwvcG9saXRpY2FsL2Vjb25vbWljIG5ld3MiLCAiTG9jYWwgbmV3cyIsICJGb3JlaWduIG5ld3MiLCAiQ3VsdHVyZS9lbnRlcnRhaW5tZW50IiwgIlNwb3J0cyIpCiAgKQpgYGAKCgpgYGB7cixldmFsPUZBTFNFfQpsZDMgJT4lCiAgICBmaWx0ZXIoIXN0cl9kZXRlY3QodHlwZSwiT3RoZXIiKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcl9jcmVhdGVkLHk9bnJfc2VudGVuY2VzL25yX3BhcmFncmFwaHMsY29sb3I9bWVkaWEpKSArCiAgICBnZW9tX3N0ZXAoKSArCiAgICBmYWNldF93cmFwKH50eXBlLHNjYWxlcz0iZnJlZSIpICsKICAgIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgyMDAwLDIwMjAsYnk9NCkpICsKICAgICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEsYnk9MC4wMiksIGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5PTEpKSArCiAgICBsYWJzKHg9IlllYXIiLHk9IlNlbnRlbmNlcy9wYXJhZ3JhcGgiKQpgYGAKCgpgYGB7cixmaWcud2lkdGg9OH0KbGQzICU+JQogICAgZmlsdGVyKCFzdHJfZGV0ZWN0KHR5cGUsIk90aGVyIikpICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXJfY3JlYXRlZCx5PW5yX3Rva2Vucy9ucl9zZW50ZW5jZXMsY29sb3I9bWVkaWEpKSArCiAgICBnZW9tX3N0ZXAoKSArCiAgICBmYWNldF93cmFwKH50eXBlLHNjYWxlcz0iZnJlZSIpICsKICAgIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgyMDAwLDIwMjAsYnk9NCkpICsKICAgICNzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEsYnk9MC4wMiksIGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5PTEpKSArCiAgICBsYWJzKHg9IlllYXIiLHk9IldvcmRzL3NlbnRlbmNlIikKYGBgCgpJbnRlcnByZXRhdGlvbnM6CgogLSBBZnRlciAyMDEyLCBzdG9yaWVzIGdldCBsb25nZXIgYWNyb3NzIHRoZSBib2FyZCwgYm90aCBpbiBudW1iZXIgb2Ygc2VudGVuY2VzL3BhcmFncmFwaHMgYXMgd2VsbCBhcyB3b3JkcyBwZXIgc2VudGVuY2UKIC0gQmVmb3JlIDIwMTIgdGhlcmUgaGFzIGJlZW4gYSBtb2Rlc3QgZHJpdmUgdG93YXJkIHNob3J0ZXIgYXJ0aWNsZXMuIFRoZSBjYXVzZSBvZiB0aGlzIGlzIHVuY2xlYXIuIEhvd2V2ZXIsIHRoaXMgbmVlZHMgdG8gYmUga2VwdCBpbiBtaW5kIHdoZW4gaW50ZXJwcmV0aW5nIHRoZSBmb2xsb3dpbmcgbWFpbiBhbmFseXNlcywgd2hpY2ggb2Z0ZW4gYWxzbyBzaG93IGRpbWluaXNoaW5nIHNpZ25hbHMgYmVmb3JlIDIwMTIKCiMjIFByb3BvcnRpb24gb2YgYXJ0aWNsZXMgYmVpbmcgcXVvdGF0aW9ucwogCmBgYHtyfQpxZCA8LSBhcnRpY2xlX3N0YXRzX2MgJT4lIAogIG11dGF0ZShxdW90ZV9wcm9wb3J0aW9uPW5yX3F1b3RlX3Rva2Vucy9ucl90b2tlbnMpICU+JQogIGlubmVyX2pvaW4oYXJ0aWNsZXNfYyAlPiUgc2VsZWN0KGFfaWQsbWVkaWEseWVhcl9jcmVhdGVkKSkgJT4lCiAgaW5uZXJfam9pbihhcnRpY2xlX3R5cGVzX2MpICU+JQogIHNlbGVjdChtZWRpYSx0eXBlLHllYXJfY3JlYXRlZCxxdW90ZV9wcm9wb3J0aW9uKSAlPiUgCiAgY29sbGVjdCgpCgpxZDIgPC0gcWQgJT4lCiAgZ3JvdXBfYnkoeWVhcl9jcmVhdGVkLG1lZGlhLHR5cGUpICU+JSAKICBzdW1tYXJpemVfYWxsKGxpc3QocTE9fnF1YW50aWxlKC54LDAuMjUpW1sxXV0scTI9bWVhbixxMz1+cXVhbnRpbGUoLngsMC43NSlbWzFdXSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBwaXZvdF9sb25nZXIocTE6cTMpICU+JQogIG11dGF0ZSgKICAgIG1lZGlhPWZjdF9yZWxldmVsKG1lZGlhLCAiSFMiLCJTVFQiKSwKICAgIGxpbmV0eXBlPWlmX2Vsc2UobmFtZT09InEyIiwibWVhbiIsIjFzdC8zcmQgcXVhcnRpbGUiKSwKICAgIGxpbmV0eXBlPWZjdF9yZWxldmVsKGxpbmV0eXBlLCJtZWFuIiksCiAgICB0eXBlPWZjdF9yZWxldmVsKHR5cGUsIkV4dGVybmFsIG9waW5pb24iLCAiSm91cm5hbGlzdGljIG9waW5pb24iLCAiRG9tZXN0aWMgZ2VuZXJhbC9wb2xpdGljYWwvZWNvbm9taWMgbmV3cyIsICJMb2NhbCBuZXdzIiwgIkZvcmVpZ24gbmV3cyIsICJDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiU3BvcnRzIikgICAgICAgIAogICAgKQoKcWQzIDwtIGFydGljbGVfc3RhdHNfYyAlPiUgCiAgc2VsZWN0KGFfaWQsbnJfdG9rZW5zKSAlPiUKICBpbm5lcl9qb2luKGFydGljbGVfcXVvdGVzX3N0YXRzX2MpICU+JQogIG11dGF0ZShxdW90ZV9wcm9wb3J0aW9uPW5yX3F1b3RlX3Rva2Vucy9ucl90b2tlbnMpICU+JQogIGlubmVyX2pvaW4oYXJ0aWNsZXNfYyAlPiUgc2VsZWN0KGFfaWQsbWVkaWEseWVhcl9jcmVhdGVkKSkgJT4lCiAgaW5uZXJfam9pbihhcnRpY2xlX3R5cGVzX2MpICU+JQogIHNlbGVjdChtZWRpYSxkaXJlY3QsdHlwZSx5ZWFyX2NyZWF0ZWQscXVvdGVfcHJvcG9ydGlvbikgJT4lIAogIGNvbGxlY3QoKQoKcWQ0IDwtIHFkMyAlPiUKICBncm91cF9ieShkaXJlY3QseWVhcl9jcmVhdGVkLG1lZGlhLHR5cGUpICU+JSAKICBzdW1tYXJpemVfYWxsKGxpc3QocTE9fnF1YW50aWxlKC54LDAuMjUpW1sxXV0scTI9bWVhbixxMz1+cXVhbnRpbGUoLngsMC43NSlbWzFdXSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBwaXZvdF9sb25nZXIocTE6cTMpICU+JQogIG11dGF0ZSgKICAgIG1lZGlhPWZjdF9yZWxldmVsKG1lZGlhLCAiSFMiLCJTVFQiKSwKICAgIGxpbmV0eXBlPWlmX2Vsc2UobmFtZT09InEyIiwibWVhbiIsIjFzdC8zcmQgcXVhcnRpbGUiKSwKICAgIGxpbmV0eXBlPWZjdF9yZWxldmVsKGxpbmV0eXBlLCJtZWFuIiksCiAgICB0eXBlPWZjdF9yZWxldmVsKHR5cGUsIkV4dGVybmFsIG9waW5pb24iLCAiSm91cm5hbGlzdGljIG9waW5pb24iLCAiRG9tZXN0aWMgZ2VuZXJhbC9wb2xpdGljYWwvZWNvbm9taWMgbmV3cyIsICJMb2NhbCBuZXdzIiwgIkZvcmVpZ24gbmV3cyIsICJDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiU3BvcnRzIikgICAgICAgIAogICAgKQoKcWQ1IDwtIHFkMyAlPiUKICBjb3VudChkaXJlY3QseWVhcl9jcmVhdGVkLG1lZGlhLHR5cGUpICU+JQogIGdyb3VwX2J5KHllYXJfY3JlYXRlZCxtZWRpYSx0eXBlKSAlPiUKICBtdXRhdGUocD1uL3N1bShuKSkKYGBgCiAKIyMjIE92ZXJhbGwKCmBgYHtyLGZpZy53aWR0aD04fQpxZDIgJT4lIAogIGZpbHRlcih0eXBlIT0iT3RoZXIiKSAlPiUKICBnZ3Bsb3QoYWVzKHg9eWVhcl9jcmVhdGVkLHk9dmFsdWUsY29sb3I9bWVkaWEsZ3JvdXA9aW50ZXJhY3Rpb24obmFtZSxtZWRpYSksbGluZXR5cGU9bGluZXR5cGUpKSArCiAgZ2VvbV9zdGVwKCkgKwogIGZhY2V0X3dyYXAofnR5cGUpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgyMDAwLDIwMjAsYnk9NCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEsYnk9MC4xKSxsYWJlbHM9c2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeT0xKSkgKwogIGxhYnMoeD0iWWVhciIseT0iUHJvcG9ydGlvbiBvZiBxdW90ZXMgaW4gYXJ0aWNsZXMiKQpgYGAKCiMjIyBQcm9wb3J0aW9uIG9mIHF1b3RlcyB0aGF0IGFyZSBkaXJlY3QKCmBgYHtyLGZpZy53aWR0aD04fQpxZDUgJT4lCiAgZmlsdGVyKGRpcmVjdD09MSkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXJfY3JlYXRlZCx5PXAsY29sb3I9bWVkaWEpKSArCiAgZ2VvbV9zdGVwKCkgKwogIGZhY2V0X3dyYXAofnR5cGUpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgyMDAwLDIwMjAsYnk9NCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEsYnk9MC4xKSxsYWJlbHM9c2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeT0xKSkgKwogIGxhYnMoeD0iWWVhciIseT0iUHJvcG9ydGlvbiBvZiBxdW90ZXMgdGhhdCBhcmUgZGlyZWN0IikKYGBgCgogSW50ZXJwcmV0YXRpb25zOgogCiAgLSBVc2FnZSBvZiBxdW90YXRpb24gY29uc3RydWN0cyBpcyBpbmNyZWFzaW5nCiAgLSBQYXJ0aWN1bGFybHkgZGlyZWN0IHF1b3RlcyBhcmUgdXNlZCBtb3JlCiAgCiMjIEFkamVjdGl2ZSBwcm9wb3J0aW9ucwoKYGBge3J9CmQgPC0gYXJ0aWNsZV9zdGF0c19sb25nX2MgJT4lIAogIGxlZnRfam9pbihhZGplY3RpdmVfY291bnRzX2MpICU+JQogIHJlcGxhY2VfbmEobGlzdChucl9hZGplY3RpdmVzPTAsbnJfc2VudGVuY2VzX3dpdGhfYWRqZWN0aXZlcz0wLG5yX3BhcmFncmFwaHNfd2l0aF9hZGplY3RpdmVzPTApKSAlPiUKICBpbm5lcl9qb2luKGFydGljbGVfdHlwZXNfYykgJT4lCiAgbXV0YXRlKHR5cGUyPXN0cl9jKGFydGljbGVfcGFydCwiIGluICIsdHlwZSkpICU+JQogIHVuaW9uX2FsbCgKICAgIGFydGljbGVfc3RhdHNfbG9uZ19jICU+JSAKICAgIGxlZnRfam9pbihhZGplY3RpdmVfY291bnRzX2MpICU+JQogICAgcmVwbGFjZV9uYShsaXN0KG5yX2FkamVjdGl2ZXM9MCxucl9zZW50ZW5jZXNfd2l0aF9hZGplY3RpdmVzPTAsbnJfcGFyYWdyYXBoc193aXRoX2FkamVjdGl2ZXM9MCkpICU+JQogICAgaW5uZXJfam9pbihhcnRpY2xlX3R5cGVzX2MgJT4lIHJlbmFtZSh0eXBlMj10eXBlKSkKICApICU+JQogIGdyb3VwX2J5KGFfaWQsdHlwZTIpICU+JQogIHN1bW1hcml6ZShucl90b2tlbnM9c3VtKG5yX3Rva2VucyksbnJfYWRqZWN0aXZlcz1zdW0obnJfYWRqZWN0aXZlcyksbnJfc2VudGVuY2VzPXN1bShucl9zZW50ZW5jZXMpLG5yX3BhcmFncmFwaHM9c3VtKG5yX3BhcmFncmFwaHMpLG5yX3NlbnRlbmNlc193aXRoX2FkamVjdGl2ZXM9c3VtKG5yX3NlbnRlbmNlc193aXRoX2FkamVjdGl2ZXMpLG5yX3BhcmFncmFwaHNfd2l0aF9hZGplY3RpdmVzPXN1bShucl9wYXJhZ3JhcGhzX3dpdGhfYWRqZWN0aXZlcyksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGlubmVyX2pvaW4oYXJ0aWNsZXNfYyAlPiUgc2VsZWN0KGFfaWQsbWVkaWEseWVhcl9jcmVhdGVkKSkgJT4lCiAgbXV0YXRlKAogICAgYXB3PW5yX2FkamVjdGl2ZXMvbnJfdG9rZW5zLAogICAgYXBzPW5yX2FkamVjdGl2ZXMvbnJfc2VudGVuY2VzLAogICAgYXBwPW5yX2FkamVjdGl2ZXMvbnJfcGFyYWdyYXBocywKICAgIGFwYT1ucl9hZGplY3RpdmVzLAogICAgYXNwcz1ucl9zZW50ZW5jZXNfd2l0aF9hZGplY3RpdmVzL25yX3NlbnRlbmNlcywKICAgIGFzcHA9bnJfc2VudGVuY2VzX3dpdGhfYWRqZWN0aXZlcy9ucl9wYXJhZ3JhcGhzLAogICAgYXNwYT1ucl9zZW50ZW5jZXNfd2l0aF9hZGplY3RpdmVzLAogICAgYXBwcD1ucl9wYXJhZ3JhcGhzX3dpdGhfYWRqZWN0aXZlcy9ucl9wYXJhZ3JhcGhzLAogICAgYXBwYT1ucl9wYXJhZ3JhcGhzX3dpdGhfYWRqZWN0aXZlcywKICAgIGFhcGE9aWZfZWxzZShucl9hZGplY3RpdmVzPjAsMSwwKQogICkgJT4lCiAgc2VsZWN0KHllYXJfY3JlYXRlZCxtZWRpYSx0eXBlMixhcHc6YWFwYSkgJT4lCiAgY29sbGVjdCgpCgpkMiA8LSBkICU+JQogIHJlcGxhY2VfbmEobGlzdChhcHc9MCxhcHM9MCxhcHA9MCxhcGE9MCxhc3BzPTAsYXNwcD0wLGFzcGE9MCxhcHBwPTAsYXBwYT0wLGFhcGE9MCkpICU+JQogIGdyb3VwX2J5KHllYXJfY3JlYXRlZCxtZWRpYSx0eXBlMikgJT4lIAogIHN1bW1hcml6ZV9hdCh2YXJzKGFwdzphYXBhKSxsaXN0KHExPX5xdWFudGlsZSgueCwwLjI1KVtbMV1dLHEyPW1lYW4scTM9fnF1YW50aWxlKC54LDAuNzUpW1sxXV0pKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKGFwd19xMTphYXBhX3EzKSAlPiUKICBzZXBhcmF0ZShuYW1lLGMoIm1lYXN1cmUiLCJxdWFudGlsZSIpLHNlcD0iXyIpICU+JQogIG11dGF0ZSgKICAgIG1lZGlhPWZjdF9yZWxldmVsKG1lZGlhLCAiSFMiLCJTVFQiKSwKICAgIG1lYXN1cmU9cmVjb2RlKG1lYXN1cmUsCiAgICAgICJhcHciID0gIkFkamVjdGl2ZXMvd29yZHMiLAogICAgICAiYXBzIiA9ICJBZGplY3RpdmVzL3NlbnRlbmNlcyIsCiAgICAgICJhcHAiID0gIkFkamVjdGl2ZXMvcGFyYWdyYWhzIiwKICAgICAgImFwYSIgPSAiQWRqZWN0aXZlcy9hcnRpY2xlcyIsCiAgICAgICJhc3BzIiA9ICJTZW50ZW5jZXMgY29udGFpbmluZyBhZGplY3RpdmVzL3NlbnRlbmNlcyIsCiAgICAgICJhc3BwIiA9ICJTZW50ZW5jZXMgY29udGFpbmluZyBhZGplY3RpdmVzL3BhcmFncmFocyIsCiAgICAgICJhc3BhIiA9ICJTZW50ZW5jZXMgY29udGFpbmluZyBhZGplY3RpdmVzL2FydGljbGVzIiwKICAgICAgImFwcHAiID0gIlBhcmFncmFwaHMgY29udGFpbmluZyBhZGplY3RpdmVzL3BhcmFncmFocyIsCiAgICAgICJhcHBhIiA9ICJQYXJhZ3JhcGhzIGNvbnRhaW5pbmcgYWRqZWN0aXZlcy9hcnRpY2xlcyIsCiAgICAgICJhYXBhIiA9ICJBcnRpY2xlcyBjb250YWluaW5nIGFkamVjdGl2ZXMvYXJ0aWNsZXMiCiAgICApLAogICAgbGluZXR5cGU9aWZfZWxzZShxdWFudGlsZT09InEyIiwibWVhbiIsIjEvMyBxdWFydGlsZSIpLAogICAgbGluZXR5cGU9ZmN0X3JlbGV2ZWwobGluZXR5cGUsIm1lYW4iKSwKICAgIHR5cGUyPWZjdF9yZWxldmVsKHR5cGUyLCJEb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzIiwgImpvdXJuYWxpc3RpYyB0ZXh0IGluIERvbWVzdGljIGdlbmVyYWwvcG9saXRpY2FsL2Vjb25vbWljIG5ld3MiLCAiaW5kaXJlY3QgcXVvdGF0aW9uIGluIERvbWVzdGljIGdlbmVyYWwvcG9saXRpY2FsL2Vjb25vbWljIG5ld3MiLCAiZGlyZWN0IHF1b3RhdGlvbiBpbiBEb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzIiwgIkxvY2FsIG5ld3MiLCAiam91cm5hbGlzdGljIHRleHQgaW4gTG9jYWwgbmV3cyIsICJpbmRpcmVjdCBxdW90YXRpb24gaW4gTG9jYWwgbmV3cyIsICJkaXJlY3QgcXVvdGF0aW9uIGluIExvY2FsIG5ld3MiLCAiRm9yZWlnbiBuZXdzIiwgImpvdXJuYWxpc3RpYyB0ZXh0IGluIEZvcmVpZ24gbmV3cyIsICJpbmRpcmVjdCBxdW90YXRpb24gaW4gRm9yZWlnbiBuZXdzIiwgImRpcmVjdCBxdW90YXRpb24gaW4gRm9yZWlnbiBuZXdzIiwgIkN1bHR1cmUvZW50ZXJ0YWlubWVudCIsICJqb3VybmFsaXN0aWMgdGV4dCBpbiBDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiaW5kaXJlY3QgcXVvdGF0aW9uIGluIEN1bHR1cmUvZW50ZXJ0YWlubWVudCIsICJkaXJlY3QgcXVvdGF0aW9uIGluIEN1bHR1cmUvZW50ZXJ0YWlubWVudCIsICJTcG9ydHMiLCAiam91cm5hbGlzdGljIHRleHQgaW4gU3BvcnRzIiwgImluZGlyZWN0IHF1b3RhdGlvbiBpbiBTcG9ydHMiLCAiZGlyZWN0IHF1b3RhdGlvbiBpbiBTcG9ydHMiLCJFeHRlcm5hbCBvcGluaW9uIiwgIkpvdXJuYWxpc3RpYyBvcGluaW9uIikKICAgICkKYGBgCgpgYGB7cixldmFsPUZBTFNFfQpkMiAlPiUgCiAgZmlsdGVyKHN0cl9kZXRlY3QodHlwZTIsIk90aGVyIikpICU+JQogIGdncGxvdChhZXMoeD15ZWFyX2NyZWF0ZWQseT12YWx1ZSxjb2xvcj1tZWRpYSxncm91cD1pbnRlcmFjdGlvbihtZWFzdXJlLHF1YW50aWxlLG1lZGlhKSxsaW5ldHlwZT1saW5ldHlwZSkpICsKICBnZW9tX3N0ZXAoKSArCiAgZmFjZXRfd3JhcChtZWFzdXJlfnR5cGUyLHNjYWxlcz0iZnJlZSIpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpCmBgYAoKYGBge3IsZmlnLndpZHRoPTgsZmlnLmhlaWdodD0xMSxldmFsPUZBTFNFfQpkMiAlPiUgCiAgZ3JvdXBfYnkobWVhc3VyZSkgJT4lCiAgZ3JvdXBfbWFwKH4ueCAlPiUKICAgIGZpbHRlcighc3RyX2RldGVjdCh0eXBlMiwiT3RoZXIiKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcl9jcmVhdGVkLHk9dmFsdWUsY29sb3I9bWVkaWEsZ3JvdXA9aW50ZXJhY3Rpb24ocXVhbnRpbGUsbWVkaWEpLGxpbmV0eXBlPWxpbmV0eXBlKSkgKwogICAgZ2VvbV9zdGVwKCkgKwogICAgZmFjZXRfd3JhcCh+dHlwZTIsc2NhbGVzPSJmcmVlIikgKwogICAgdGhlbWVfaHNjaV9kaXNjcmV0ZShiYXNlX2ZhbWlseT0iQXJpYWwiKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDIwMDAsMjAyMCxieT00KSkgKwojICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3M9c2VxKDAsMSxieT0wLjAyKSwgbGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3Q9MSkpICsKICAgIGxhYnMoeD0iWWVhciIseT0iTnVtYmVyIG9mIGFkamVjdGl2ZXMiKSArCiAgICBnZ3RpdGxlKC55KQogICkKYGBgCkR1ZSB0byB0aGUgbGVuZ3RoZW5pbmcgb2YgYXJ0aWNsZSB0ZXh0cyBjYXVzaW5nIGNvbXBsZXhpdGllcyBmb3IgYW5hbHlzZXMsIGFsbCB0aGUgZm9sbG93aW5nIGFkamVjdGl2ZSBwcm9wb3J0aW9ucyB3ZXJlIGNhbGN1bGF0ZWQgYW5kIGV2YWx1YXRlZDoKIAogLSBBZGplY3RpdmVzL3dvcmRzCiAtIEFkamVjdGl2ZXMvc2VudGVuY2VzCiAtIEFkamVjdGl2ZXMvcGFyYWdyYWhzCiAtIEFkamVjdGl2ZXMvYXJ0aWNsZXMKIC0gU2VudGVuY2VzIGNvbnRhaW5pbmcgYWRqZWN0aXZlcy9zZW50ZW5jZXMKIC0gU2VudGVuY2VzIGNvbnRhaW5pbmcgYWRqZWN0aXZlcy9wYXJhZ3JhaHMKIC0gU2VudGVuY2VzIGNvbnRhaW5pbmcgYWRqZWN0aXZlcy9hcnRpY2xlcwogLSBQYXJhZ3JhcGhzIGNvbnRhaW5pbmcgYWRqZWN0aXZlcy9wYXJhZ3JhaHMKIC0gUGFyYWdyYXBocyBjb250YWluaW5nIGFkamVjdGl2ZXMvYXJ0aWNsZXMKIC0gQXJ0aWNsZXMgY29udGFpbmluZyBhZGplY3RpdmVzL2FydGljbGVzCiAKT3V0IG9mIHRoZXNlLCAiQWRqZWN0aXZlcy93b3JkcyIgYW5kICJBZGplY3RpdmVzL3NlbnRlbmNlcyIgd2VyZSByZXRhaW5lZCBmb3IgZmluYWwgYW5hbHlzaXM6CgojIyMgQWRqZWN0aXZlcy93b3JkcwpgYGB7cixmaWcud2lkdGg9OCxmaWcuaGVpZ2h0PTExfQoxOjIgJT4lIG1hcCh+CiAgZDIgJT4lIAogICAgZmlsdGVyKG1lYXN1cmU9PSJBZGplY3RpdmVzL3dvcmRzIikgJT4lCiAgICBmaWx0ZXIoIXN0cl9kZXRlY3QodHlwZTIsIk90aGVyIiksIXN0cl9kZXRlY3QodHlwZTIsImluIEpvdXJuYWxpc3RpYyBvcGluaW9uIiksIXN0cl9kZXRlY3QodHlwZTIsImluIEV4dGVybmFsIG9waW5pb24iKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcl9jcmVhdGVkLHk9dmFsdWUsY29sb3I9bWVkaWEsZ3JvdXA9aW50ZXJhY3Rpb24ocXVhbnRpbGUsbWVkaWEpLGxpbmV0eXBlPWxpbmV0eXBlKSkgKwogICAgZ2VvbV9zdGVwKCkgKwogICAgZmFjZXRfd3JhcF9wYWdpbmF0ZSh+dHlwZTIsbmNvbD00LG5yb3c9MyxwYWdlPS54KSArCiAgICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMjAwMCwyMDIwLGJ5PTQpKSArCiAgICBsYWJzKHg9IlllYXIiLHk9IkFkamVjdGl2ZXMvd29yZHMiKQogICkKYGBgCgojIyMgQWRqZWN0aXZlcy9zZW50ZW5jZXMKYGBge3IsZmlnLndpZHRoPTgsZmlnLmhlaWdodD0xMX0KMToyICU+JSBtYXAofgogIGQyICU+JSAKICAgIGZpbHRlcihtZWFzdXJlPT0iQWRqZWN0aXZlcy9zZW50ZW5jZXMiKSAlPiUKICAgIGZpbHRlcighc3RyX2RldGVjdCh0eXBlMiwiT3RoZXIiKSwhc3RyX2RldGVjdCh0eXBlMiwiaW4gSm91cm5hbGlzdGljIG9waW5pb24iKSwhc3RyX2RldGVjdCh0eXBlMiwiaW4gRXh0ZXJuYWwgb3BpbmlvbiIpKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyX2NyZWF0ZWQseT12YWx1ZSxjb2xvcj1tZWRpYSxncm91cD1pbnRlcmFjdGlvbihxdWFudGlsZSxtZWRpYSksbGluZXR5cGU9bGluZXR5cGUpKSArCiAgICBnZW9tX3N0ZXAoKSArCiAgICBmYWNldF93cmFwX3BhZ2luYXRlKH50eXBlMixuY29sPTQsbnJvdz0zLHBhZ2U9LngpICsKICAgIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgyMDAwLDIwMjAsYnk9NCkpICsKICAgIGxhYnMoeD0iWWVhciIseT0iQWRqZWN0aXZlcy9zZW50ZW5jZXMiKQopCmBgYAoKSW50ZXJwcmV0YXRpb25zOgoKIC0gSW4gZ2VuZXJhbCwgYWRqZWN0aXZlIHVzZSBzZWVtcyB0byBkZWNsaW5lLiBJbiBxdW90ZXMsIHRoaXMgaGFwcGVucyB0aHJvdWdob3V0LgogLSBIb3dldmVyLCBpbiB0aGUgY2FzZSBvZiBqb3VybmFsaXN0aWMgd3JpdGluZywgdGhlcmUgYXJlIHRoZSBmb2xsb3dpbmcgaW50cmlndWluZyBhYmVycmF0aW9ucyBmcm9tIHRoaXM6CiAgIC0gYWRqZWN0aXZlIHVzZSBpbmNyZWFzZXMgc2lnbmlmaWNhbnRseSBhZnRlciAyMDEwIGluIEhTICYgSUwgc3BvcnRzIGpvdXJuYWxpc3RpYyB3cml0aW5nCiAgIC0gYWRqZWN0aXZlIHVzZSBpbmNyZWFzZXMgYWZ0ZXIgMjAxMCBpbiB0aGUgam91cm5hbGlzdGljIHBvcnRpb24gb2YgZG9tZXN0aWMgZ2VuZXJhbC9wb2xpdGljYWwvZWNvbm9taWMgbmV3cyB0ZXh0cyBpbiBhbGwgb3V0bGV0cwogICAtIGFkamVjdGl2ZSB1c2UgaW5jcmVhc2VzIGluIEhTIGxvY2FsIHJlcG9ydGluZyAoSGVsc2lua2kpLCBidXQgbm90IGluIFlMRSByZWdpb25hbCByZXBvcnRpbmcKIC0gQWx0b2dldGhlciwgdGhlc2UgaW5jcmVhc2VzIGluIGpvdXJuYWxpc3RpYyB3cml0aW5nIGxlYWQgdG8gc2ltaWxhciBpbmNyZWFzZXMgaW4gdGhlIGFydGljbGVzIG92ZXJhbGwuCiAgIAojIyBIZWRnaW5nIHByb3BvcnRpb25zCgpgYGB7cn0KaGQgPC0gYXJ0aWNsZV9zdGF0c19sb25nX2MgJT4lIAogIGlubmVyX2pvaW4oYXJ0aWNsZV90eXBlc19jKSAlPiUKICBtdXRhdGUodHlwZTI9c3RyX2MoYXJ0aWNsZV9wYXJ0LCIgaW4gIix0eXBlKSkgJT4lCiAgdW5pb25fYWxsKAogICAgYXJ0aWNsZV9zdGF0c19sb25nX2MgJT4lIAogICAgaW5uZXJfam9pbihhcnRpY2xlX3R5cGVzX2MgJT4lIHJlbmFtZSh0eXBlMj10eXBlKSkKICApICU+JQogIGxlZnRfam9pbihoZWRnaW5nX2NvdW50c19jKSAlPiUKICByZXBsYWNlX25hKGxpc3QobnJfaGVkZ2luZ3M9MCxucl9zZW50ZW5jZXNfd2l0aF9oZWRnaW5ncz0wLG5yX3BhcmFncmFwaHNfd2l0aF9oZWRnaW5ncz0wKSkgJT4lCiAgZ3JvdXBfYnkoYV9pZCx0eXBlMikgJT4lCiAgc3VtbWFyaXplKG5yX3Rva2Vucz1zdW0obnJfdG9rZW5zKSxucl9oZWRnaW5ncz1zdW0obnJfaGVkZ2luZ3MpLG5yX3NlbnRlbmNlcz1zdW0obnJfc2VudGVuY2VzKSxucl9wYXJhZ3JhcGhzPXN1bShucl9wYXJhZ3JhcGhzKSxucl9zZW50ZW5jZXNfd2l0aF9oZWRnaW5ncz1zdW0obnJfc2VudGVuY2VzX3dpdGhfaGVkZ2luZ3MpLG5yX3BhcmFncmFwaHNfd2l0aF9oZWRnaW5ncz1zdW0obnJfcGFyYWdyYXBoc193aXRoX2hlZGdpbmdzKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgaW5uZXJfam9pbihhcnRpY2xlc19jICU+JSBzZWxlY3QoYV9pZCxtZWRpYSx5ZWFyX2NyZWF0ZWQpKSAlPiUKICBtdXRhdGUoCiAgICBocHc9bnJfaGVkZ2luZ3MvbnJfdG9rZW5zLAogICAgaHBzPW5yX2hlZGdpbmdzL25yX3NlbnRlbmNlcywKICAgIGhwcD1ucl9oZWRnaW5ncy9ucl9wYXJhZ3JhcGhzLAogICAgaHBhPW5yX2hlZGdpbmdzLAogICAgaHNwcz1ucl9zZW50ZW5jZXNfd2l0aF9oZWRnaW5ncy9ucl9zZW50ZW5jZXMsCiAgICBoc3BwPW5yX3NlbnRlbmNlc193aXRoX2hlZGdpbmdzL25yX3BhcmFncmFwaHMsCiAgICBoc3BhPW5yX3NlbnRlbmNlc193aXRoX2hlZGdpbmdzLAogICAgaHBwcD1ucl9wYXJhZ3JhcGhzX3dpdGhfaGVkZ2luZ3MvbnJfcGFyYWdyYXBocywKICAgIGhwcGE9bnJfcGFyYWdyYXBoc193aXRoX2hlZGdpbmdzLAogICAgaGFwYT1pZl9lbHNlKG5yX2hlZGdpbmdzPjAsMSwwKQogICkgJT4lCiAgc2VsZWN0KHllYXJfY3JlYXRlZCxtZWRpYSx0eXBlMixocHc6aGFwYSkgJT4lCiAgY29sbGVjdCgpCgpoZDIgPC0gaGQgJT4lCiAgcmVwbGFjZV9uYShsaXN0KGhwdz0wLGhwcz0wLGhwcD0wLGhwYT0wLGhzcHM9MCxoc3BwPTAsaHNwYT0wLGhwcHA9MCxocHBhPTAsaGFwYT0wKSkgJT4lCiAgZ3JvdXBfYnkoeWVhcl9jcmVhdGVkLG1lZGlhLHR5cGUyKSAlPiUgCiAgc3VtbWFyaXplX2F0KHZhcnMoaHB3OmhhcGEpLGxpc3QocTE9fnF1YW50aWxlKC54LDAuMSlbWzFdXSxxMj1tZWFuLHEzPX5xdWFudGlsZSgueCwwLjkpW1sxXV0pKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKGhwd19xMTpoYXBhX3EzKSAlPiUKICBzZXBhcmF0ZShuYW1lLGMoIm1lYXN1cmUiLCJxdWFudGlsZSIpLHNlcD0iXyIpICU+JQogIG11dGF0ZSgKICAgIG1lZGlhPWZjdF9yZWxldmVsKG1lZGlhLCAiSFMiLCJTVFQiKSwKICAgIG1lYXN1cmU9cmVjb2RlKG1lYXN1cmUsCiAgICAgICJocHciID0gIkhlZGdpbmdzL3dvcmRzIiwKICAgICAgImhwcyIgPSAiSGVkZ2luZ3Mvc2VudGVuY2VzIiwKICAgICAgImhwcCIgPSAiSGVkZ2luZ3MvcGFyYWdyYWhzIiwKICAgICAgImhwYSIgPSAiSGVkZ2luZ3MvYXJ0aWNsZXMiLAogICAgICAiaHNwcyIgPSAiU2VudGVuY2VzIGNvbnRhaW5pbmcgaGVkZ2luZ3Mvc2VudGVuY2VzIiwKICAgICAgImhzcHAiID0gIlNlbnRlbmNlcyBjb250YWluaW5nIGhlZGdpbmdzL3BhcmFncmFocyIsCiAgICAgICJoc3BhIiA9ICJTZW50ZW5jZXMgY29udGFpbmluZyBoZWRnaW5ncy9hcnRpY2xlcyIsCiAgICAgICJocHBwIiA9ICJQYXJhZ3JhcGhzIGNvbnRhaW5pbmcgaGVkZ2luZ3MvcGFyYWdyYWhzIiwKICAgICAgImhwcGEiID0gIlBhcmFncmFwaHMgY29udGFpbmluZyBoZWRnaW5ncy9hcnRpY2xlcyIsCiAgICAgICJoYXBhIiA9ICJBcnRpY2xlcyBjb250YWluaW5nIGhlZGdpbmdzL2FydGljbGVzIgogICAgKSwKICAgIGxpbmV0eXBlPWlmX2Vsc2UocXVhbnRpbGU9PSJxMiIsIm1lYW4iLCIxc3QvOXRoIGNlbnRpbGUiKSwKICAgIGxpbmV0eXBlPWZjdF9yZWxldmVsKGxpbmV0eXBlLCJtZWFuIiksCiAgICB0eXBlMj1mY3RfcmVsZXZlbCh0eXBlMiwiRG9tZXN0aWMgZ2VuZXJhbC9wb2xpdGljYWwvZWNvbm9taWMgbmV3cyIsICJqb3VybmFsaXN0aWMgdGV4dCBpbiBEb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzIiwgImluZGlyZWN0IHF1b3RhdGlvbiBpbiBEb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzIiwgImRpcmVjdCBxdW90YXRpb24gaW4gRG9tZXN0aWMgZ2VuZXJhbC9wb2xpdGljYWwvZWNvbm9taWMgbmV3cyIsICJMb2NhbCBuZXdzIiwgImpvdXJuYWxpc3RpYyB0ZXh0IGluIExvY2FsIG5ld3MiLCAiaW5kaXJlY3QgcXVvdGF0aW9uIGluIExvY2FsIG5ld3MiLCAiZGlyZWN0IHF1b3RhdGlvbiBpbiBMb2NhbCBuZXdzIiwgIkZvcmVpZ24gbmV3cyIsICJqb3VybmFsaXN0aWMgdGV4dCBpbiBGb3JlaWduIG5ld3MiLCAiaW5kaXJlY3QgcXVvdGF0aW9uIGluIEZvcmVpZ24gbmV3cyIsICJkaXJlY3QgcXVvdGF0aW9uIGluIEZvcmVpZ24gbmV3cyIsICJDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiam91cm5hbGlzdGljIHRleHQgaW4gQ3VsdHVyZS9lbnRlcnRhaW5tZW50IiwgImluZGlyZWN0IHF1b3RhdGlvbiBpbiBDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiZGlyZWN0IHF1b3RhdGlvbiBpbiBDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiU3BvcnRzIiwgImpvdXJuYWxpc3RpYyB0ZXh0IGluIFNwb3J0cyIsICJpbmRpcmVjdCBxdW90YXRpb24gaW4gU3BvcnRzIiwgImRpcmVjdCBxdW90YXRpb24gaW4gU3BvcnRzIiwiRXh0ZXJuYWwgb3BpbmlvbiIsICJKb3VybmFsaXN0aWMgb3BpbmlvbiIpCiAgICApCmBgYAoKYGBge3IsZXZhbD1GQUxTRX0KaGQyICU+JSAKICBmaWx0ZXIoc3RyX2RldGVjdCh0eXBlMiwiT3RoZXIiKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXJfY3JlYXRlZCx5PXZhbHVlLGNvbG9yPW1lZGlhLGdyb3VwPWludGVyYWN0aW9uKG1lYXN1cmUscXVhbnRpbGUsbWVkaWEpLGxpbmV0eXBlPWxpbmV0eXBlKSkgKwogIGdlb21fc3RlcCgpICsKICBmYWNldF93cmFwKG1lYXN1cmV+dHlwZTIsc2NhbGVzPSJmcmVlIikgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikKYGBgCgpgYGB7cixmaWcud2lkdGg9OCxmaWcuaGVpZ2h0PTExLGV2YWw9RkFMU0V9CmhkMiAlPiUgCiAgZ3JvdXBfYnkobWVhc3VyZSkgJT4lCiAgZ3JvdXBfbWFwKH4ueCAlPiUKICAgIGZpbHRlcighc3RyX2RldGVjdCh0eXBlMiwiT3RoZXIiKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcl9jcmVhdGVkLHk9dmFsdWUsY29sb3I9bWVkaWEsZ3JvdXA9aW50ZXJhY3Rpb24ocXVhbnRpbGUsbWVkaWEpLGxpbmV0eXBlPWxpbmV0eXBlKSkgKwogICAgZ2VvbV9zdGVwKCkgKwogICAgZmFjZXRfd3JhcCh+dHlwZTIsc2NhbGVzPSJmcmVlIikgKwogICAgdGhlbWVfaHNjaV9kaXNjcmV0ZShiYXNlX2ZhbWlseT0iQXJpYWwiKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDIwMDAsMjAyMCxieT00KSkgKwojICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3M9c2VxKDAsMSxieT0wLjAyKSwgbGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3Q9MSkpICsKICAgIGxhYnMoeD0iWWVhciIseT0iTnVtYmVyIG9mIGhlZGdpbmdzIikgKwogICAgZ2d0aXRsZSgueSkKICApCmBgYApEdWUgdG8gdGhlIGxlbmd0aGVuaW5nIG9mIGFydGljbGUgdGV4dHMgY2F1c2luZyBjb21wbGV4aXRpZXMgZm9yIGFuYWx5c2VzLCBhbGwgdGhlIGZvbGxvd2luZyBoZWRnaW5nIHByb3BvcnRpb25zIHdlcmUgY2FsY3VsYXRlZCBhbmQgZXZhbHVhdGVkOgogCiAtIEhlZGdpbmdzL3dvcmRzCiAtIEhlZGdpbmdzL3NlbnRlbmNlcwogLSBIZWRnaW5ncy9wYXJhZ3JhaHMKIC0gSGVkZ2luZ3MvYXJ0aWNsZXMKIC0gU2VudGVuY2VzIGNvbnRhaW5pbmcgaGVkZ2luZ3Mvc2VudGVuY2VzCiAtIFNlbnRlbmNlcyBjb250YWluaW5nIGhlZGdpbmdzL3BhcmFncmFocwogLSBTZW50ZW5jZXMgY29udGFpbmluZyBoZWRnaW5ncy9hcnRpY2xlcwogLSBQYXJhZ3JhcGhzIGNvbnRhaW5pbmcgaGVkZ2luZ3MvcGFyYWdyYWhzCiAtIFBhcmFncmFwaHMgY29udGFpbmluZyBoZWRnaW5ncy9hcnRpY2xlcwogLSBBcnRpY2xlcyBjb250YWluaW5nIGhlZGdpbmdzL2FydGljbGVzCiAKT3V0IG9mIHRoZXNlLCAiaGVkZ2luZ3Mvd29yZHMiIGFuZCAiaGVkZ2luZ3Mvc2VudGVuY2VzIiB3ZXJlIHJldGFpbmVkIGZvciBmaW5hbCBhbmFseXNpczoKCiMjIyBIZWRnaW5ncy93b3JkcwpgYGB7cixmaWcud2lkdGg9OCxmaWcuaGVpZ2h0PTExfQoxOjIgJT4lIG1hcCh+CiAgaGQyICU+JSAKICAgIGZpbHRlcihtZWFzdXJlPT0iSGVkZ2luZ3Mvd29yZHMiKSAlPiUKICAgIGZpbHRlcighc3RyX2RldGVjdCh0eXBlMiwiT3RoZXIiKSwhc3RyX2RldGVjdCh0eXBlMiwiaW4gSm91cm5hbGlzdGljIG9waW5pb24iKSwhc3RyX2RldGVjdCh0eXBlMiwiaW4gRXh0ZXJuYWwgb3BpbmlvbiIpKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyX2NyZWF0ZWQseT12YWx1ZSxjb2xvcj1tZWRpYSxncm91cD1pbnRlcmFjdGlvbihxdWFudGlsZSxtZWRpYSksbGluZXR5cGU9bGluZXR5cGUpKSArCiAgICBnZW9tX3N0ZXAoKSArCiAgICBmYWNldF93cmFwX3BhZ2luYXRlKH50eXBlMixuY29sPTQsbnJvdz0zLHBhZ2U9LngpICsKICAgIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgyMDAwLDIwMjAsYnk9NCkpICsKICAgIGxhYnMoeD0iWWVhciIseT0iSGVkZ2luZ3Mvd29yZHMiKQopCmBgYAoKIyMjIEhlZGdpbmdzL3NlbnRlbmNlcwpgYGB7cixmaWcud2lkdGg9OCxmaWcuaGVpZ2h0PTExfQoxOjIgJT4lIG1hcCh+CiAgaGQyICU+JSAKICAgIGZpbHRlcihtZWFzdXJlPT0iSGVkZ2luZ3Mvc2VudGVuY2VzIikgJT4lCiAgICBmaWx0ZXIoIXN0cl9kZXRlY3QodHlwZTIsIk90aGVyIiksIXN0cl9kZXRlY3QodHlwZTIsImluIEpvdXJuYWxpc3RpYyBvcGluaW9uIiksIXN0cl9kZXRlY3QodHlwZTIsImluIEV4dGVybmFsIG9waW5pb24iKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcl9jcmVhdGVkLHk9dmFsdWUsY29sb3I9bWVkaWEsZ3JvdXA9aW50ZXJhY3Rpb24ocXVhbnRpbGUsbWVkaWEpLGxpbmV0eXBlPWxpbmV0eXBlKSkgKwogICAgZ2VvbV9zdGVwKCkgKwogICAgZmFjZXRfd3JhcF9wYWdpbmF0ZSh+dHlwZTIsbmNvbD00LG5yb3c9MyxwYWdlPS54KSArCiAgICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMjAwMCwyMDIwLGJ5PTQpKSArCiAgICBsYWJzKHg9IlllYXIiLHk9IkhlZGdpbmdzL3NlbnRlbmNlcyIpCikKYGBgCgpJbnRlcnByZXRhdGlvbnM6CgogLSBBZ2Fpbiwgb25lIGNhbiBzZWUgYW4gaW5jcmVhc2UgaW4gdGhlIHVzZSBvZiBoZWRnaW5ncyBpbiBqb3VybmFsaXN0aWMgdGV4dCBvZiBkb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzLCBIUyBsb2NhbCBuZXdzIChLYXVwdW5raSkgYXMgd2VsbCBhcyB0aGlzIHRpbWUgaW4gZm9yZWlnbiBuZXdzLiBGdXJ0aGVyLCB0aGUgaW5jcmVhc2UgaW4gdGhlIHVzZSBvZiBkaXJlY3QgcXVvdGVzIGZ1cnRoZXIgYWRkcyBoZWRnaW5nIHRvIHRoZSBhcnRpY2xlcyBhcyBhIHdob2xlLgogCiMjIFVzYWdlIG9mIHNlbGVjdGVkIGNvbmp1bmN0aW9ucyAKClRoZSBmb2xsb3dpbmcgY29uanVuY3Rpb25zIHdlcmUgdHJhY2tlZDoKCiAtIHN1Ym9yZGluYXRlIGNvbmp1bmN0aW9ucyBqb3R0YSwga29za2EsIGt1biwgam9zLCB2YWlra2EsIGt1bm5lcywgbWlrw6RsaQogLSBzaWxsw6QsIG11dHRhCgpgYGB7cixldmFsPUZBTFNFfQpjb25qdW5jdGlvbl9jb3VudHNfYyA8LSB3b3Jkc19jICU+JQogIGZpbHRlcihsZW1tYSAlaW4lIGMoImpvdHRhIiwia29za2EiLCJrdW4iLCJqb3MiLCJ2YWlra2EiLCJrdW5uZXMiLCJtaWvDpGxpIiwic2lsbMOkIiwibXV0dGEiKSkgJT4lCiAgaW5uZXJfam9pbihjb3JwdXNfYykgJT4lCiAgbGVmdF9qb2luKHF1b3Rlc19jICU+JSBtdXRhdGUoYXJ0aWNsZV9wYXJ0PWlmX2Vsc2UoZGlyZWN0LCJkaXJlY3QgcXVvdGF0aW9uIiwiaW5kaXJlY3QgcXVvdGF0aW9uIikpLHNxbF9vbj0iTEhTLmFfaWQ9UkhTLmFfaWQgQU5EIChzX2lkID4gc3RhcnRfc19pZCBPUiAoc19pZD1zdGFydF9zX2lkIEFORCBwb3MgPj0gc3RhcnRfcG9zKSkgQU5EIChzX2lkIDwgZW5kX3NfaWQgT1IgKHNfaWQ9ZW5kX3NfaWQgQU5EIHBvcyA8PSBlbmRfcG9zKSkiKSAlPiUKICByZXBsYWNlX25hKGxpc3QoYXJ0aWNsZV9wYXJ0PSJqb3VybmFsaXN0aWMgdGV4dCIpKSAlPiUKICBzZWxlY3QoYV9pZD1hX2lkLngscGFyX2lkLHNfaWQscG9zLCBhcnRpY2xlX3BhcnQpICU+JQogIGdyb3VwX2J5KGFfaWQsYXJ0aWNsZV9wYXJ0KSAlPiUKICBzdW1tYXJpemUobnJfY29uanVuY3Rpb25zPW5fZGlzdGluY3QoMTAwMDBMKnNfaWQrcG9zKSxucl9zZW50ZW5jZXNfd2l0aF9jb25qdW5jdGlvbnM9bl9kaXN0aW5jdChzX2lkKSxucl9wYXJhZ3JhcGhzX3dpdGhfY29uanVuY3Rpb25zPW5fZGlzdGluY3QocGFyX2lkKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgY29tcHV0ZV9jKG5hbWU9ImNvbmp1bmN0aW9uX2NvdW50c19jIikKYGBgCgpgYGB7cn0KY29uanVuY3Rpb25fY291bnRzX2MgPC0gdGJsKGNvbiwiY29uanVuY3Rpb25fY291bnRzX2MiKQpgYGAKCmBgYHtyfQpjZCA8LSBhcnRpY2xlX3N0YXRzX2xvbmdfYyAlPiUgCiAgaW5uZXJfam9pbihhcnRpY2xlX3R5cGVzX2MpICU+JQogIG11dGF0ZSh0eXBlMj1zdHJfYyhhcnRpY2xlX3BhcnQsIiBpbiAiLHR5cGUpKSAlPiUKICB1bmlvbl9hbGwoCiAgICBhcnRpY2xlX3N0YXRzX2xvbmdfYyAlPiUgCiAgICBpbm5lcl9qb2luKGFydGljbGVfdHlwZXNfYyAlPiUgcmVuYW1lKHR5cGUyPXR5cGUpKQogICkgJT4lCiAgbGVmdF9qb2luKGhlZGdpbmdfY291bnRzX2MpICU+JQogIGxlZnRfam9pbihjb25qdW5jdGlvbl9jb3VudHNfYykgJT4lCiAgcmVwbGFjZV9uYShsaXN0KG5yX2Nvbmp1bmN0aW9ucz0wLG5yX3NlbnRlbmNlc193aXRoX2Nvbmp1bmN0aW9ucz0wLG5yX3BhcmFncmFwaHNfd2l0aF9jb25qdW5jdGlvbnM9MCkpICU+JQogIGdyb3VwX2J5KGFfaWQsdHlwZTIpICU+JQogIHN1bW1hcml6ZShucl90b2tlbnM9c3VtKG5yX3Rva2VucyksbnJfY29uanVuY3Rpb25zPXN1bShucl9jb25qdW5jdGlvbnMpLG5yX3NlbnRlbmNlcz1zdW0obnJfc2VudGVuY2VzKSxucl9wYXJhZ3JhcGhzPXN1bShucl9wYXJhZ3JhcGhzKSxucl9zZW50ZW5jZXNfd2l0aF9jb25qdW5jdGlvbnM9c3VtKG5yX3NlbnRlbmNlc193aXRoX2Nvbmp1bmN0aW9ucyksbnJfcGFyYWdyYXBoc193aXRoX2Nvbmp1bmN0aW9ucz1zdW0obnJfcGFyYWdyYXBoc193aXRoX2Nvbmp1bmN0aW9ucyksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGlubmVyX2pvaW4oYXJ0aWNsZXNfYyAlPiUgc2VsZWN0KGFfaWQsbWVkaWEseWVhcl9jcmVhdGVkKSkgJT4lCiAgbXV0YXRlKAogICAgY3B3PW5yX2Nvbmp1bmN0aW9ucy9ucl90b2tlbnMsCiAgICBjcHM9bnJfY29uanVuY3Rpb25zL25yX3NlbnRlbmNlcywKICAgIGNwcD1ucl9jb25qdW5jdGlvbnMvbnJfcGFyYWdyYXBocywKICAgIGNwYT1ucl9jb25qdW5jdGlvbnMsCiAgICBjc3BzPW5yX3NlbnRlbmNlc193aXRoX2Nvbmp1bmN0aW9ucy9ucl9zZW50ZW5jZXMsCiAgICBjc3BwPW5yX3NlbnRlbmNlc193aXRoX2Nvbmp1bmN0aW9ucy9ucl9wYXJhZ3JhcGhzLAogICAgY3NwYT1ucl9zZW50ZW5jZXNfd2l0aF9jb25qdW5jdGlvbnMsCiAgICBjcHBwPW5yX3BhcmFncmFwaHNfd2l0aF9jb25qdW5jdGlvbnMvbnJfcGFyYWdyYXBocywKICAgIGNwcGE9bnJfcGFyYWdyYXBoc193aXRoX2Nvbmp1bmN0aW9ucywKICAgIGNhcGE9aWZfZWxzZShucl9jb25qdW5jdGlvbnM+MCwxLDApCiAgKSAlPiUKICBzZWxlY3QoeWVhcl9jcmVhdGVkLG1lZGlhLHR5cGUyLGNwdzpjYXBhKSAlPiUKICBjb2xsZWN0KCkKCmNkMiA8LSBjZCAlPiUKICByZXBsYWNlX25hKGxpc3QoY3B3PTAsY3BzPTAsY3BwPTAsY3BhPTAsY3Nwcz0wLGNzcHA9MCxjc3BhPTAsY3BwcD0wLGNwcGE9MCxjYXBhPTApKSAlPiUKICBncm91cF9ieSh5ZWFyX2NyZWF0ZWQsbWVkaWEsdHlwZTIpICU+JSAKICBzdW1tYXJpemVfYXQodmFycyhjcHc6Y2FwYSksbGlzdChxMT1+cXVhbnRpbGUoLngsMC4yNSlbWzFdXSxxMj1tZWFuLHEzPX5xdWFudGlsZSgueCwwLjc1KVtbMV1dKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIHBpdm90X2xvbmdlcihjcHdfcTE6Y2FwYV9xMykgJT4lCiAgc2VwYXJhdGUobmFtZSxjKCJtZWFzdXJlIiwicXVhbnRpbGUiKSxzZXA9Il8iKSAlPiUKICBtdXRhdGUoCiAgICBtZWRpYT1mY3RfcmVsZXZlbChtZWRpYSwgIkhTIiwiU1RUIiksCiAgICBtZWFzdXJlPXJlY29kZShtZWFzdXJlLAogICAgICAiY3B3IiA9ICJDb25qdW5jdGlvbnMvd29yZHMiLAogICAgICAiY3BzIiA9ICJDb25qdW5jdGlvbnMvc2VudGVuY2VzIiwKICAgICAgImNwcCIgPSAiQ29uanVuY3Rpb25zL3BhcmFncmFocyIsCiAgICAgICJjcGEiID0gIkNvbmp1bmN0aW9ucy9hcnRpY2xlcyIsCiAgICAgICJjc3BzIiA9ICJTZW50ZW5jZXMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvc2VudGVuY2VzIiwKICAgICAgImNzcHAiID0gIlNlbnRlbmNlcyBjb250YWluaW5nIGNvbmp1bmN0aW9ucy9wYXJhZ3JhaHMiLAogICAgICAiY3NwYSIgPSAiU2VudGVuY2VzIGNvbnRhaW5pbmcgY29uanVuY3Rpb25zL2FydGljbGVzIiwKICAgICAgImNwcHAiID0gIlBhcmFncmFwaHMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvcGFyYWdyYWhzIiwKICAgICAgImNwcGEiID0gIlBhcmFncmFwaHMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvYXJ0aWNsZXMiLAogICAgICAiY2FwYSIgPSAiQXJ0aWNsZXMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvYXJ0aWNsZXMiCiAgICApLAogICAgbGluZXR5cGU9aWZfZWxzZShxdWFudGlsZT09InEyIiwibWVhbiIsIjFzdC8zcmQgcXVhcnRpbGUiKSwKICAgIGxpbmV0eXBlPWZjdF9yZWxldmVsKGxpbmV0eXBlLCJtZWFuIiksCiAgICB0eXBlMj1mY3RfcmVsZXZlbCh0eXBlMiwiRG9tZXN0aWMgZ2VuZXJhbC9wb2xpdGljYWwvZWNvbm9taWMgbmV3cyIsICJqb3VybmFsaXN0aWMgdGV4dCBpbiBEb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzIiwgImluZGlyZWN0IHF1b3RhdGlvbiBpbiBEb21lc3RpYyBnZW5lcmFsL3BvbGl0aWNhbC9lY29ub21pYyBuZXdzIiwgImRpcmVjdCBxdW90YXRpb24gaW4gRG9tZXN0aWMgZ2VuZXJhbC9wb2xpdGljYWwvZWNvbm9taWMgbmV3cyIsICJMb2NhbCBuZXdzIiwgImpvdXJuYWxpc3RpYyB0ZXh0IGluIExvY2FsIG5ld3MiLCAiaW5kaXJlY3QgcXVvdGF0aW9uIGluIExvY2FsIG5ld3MiLCAiZGlyZWN0IHF1b3RhdGlvbiBpbiBMb2NhbCBuZXdzIiwgIkZvcmVpZ24gbmV3cyIsICJqb3VybmFsaXN0aWMgdGV4dCBpbiBGb3JlaWduIG5ld3MiLCAiaW5kaXJlY3QgcXVvdGF0aW9uIGluIEZvcmVpZ24gbmV3cyIsICJkaXJlY3QgcXVvdGF0aW9uIGluIEZvcmVpZ24gbmV3cyIsICJDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiam91cm5hbGlzdGljIHRleHQgaW4gQ3VsdHVyZS9lbnRlcnRhaW5tZW50IiwgImluZGlyZWN0IHF1b3RhdGlvbiBpbiBDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiZGlyZWN0IHF1b3RhdGlvbiBpbiBDdWx0dXJlL2VudGVydGFpbm1lbnQiLCAiU3BvcnRzIiwgImpvdXJuYWxpc3RpYyB0ZXh0IGluIFNwb3J0cyIsICJpbmRpcmVjdCBxdW90YXRpb24gaW4gU3BvcnRzIiwgImRpcmVjdCBxdW90YXRpb24gaW4gU3BvcnRzIiwiRXh0ZXJuYWwgb3BpbmlvbiIsICJKb3VybmFsaXN0aWMgb3BpbmlvbiIpCiAgICApCmBgYAoKYGBge3IsZXZhbD1GQUxTRX0KY2QyICU+JSAKICBmaWx0ZXIoc3RyX2RldGVjdCh0eXBlMiwiT3RoZXIiKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXJfY3JlYXRlZCx5PXZhbHVlLGNvbG9yPW1lZGlhLGdyb3VwPWludGVyYWN0aW9uKG1lYXN1cmUscXVhbnRpbGUsbWVkaWEpLGxpbmV0eXBlPWxpbmV0eXBlKSkgKwogIGdlb21fc3RlcCgpICsKICBmYWNldF93cmFwKG1lYXN1cmV+dHlwZTIsc2NhbGVzPSJmcmVlIikgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikKYGBgCgpgYGB7cixmaWcud2lkdGg9OCxmaWcuaGVpZ2h0PTExLGV2YWw9RkFMU0V9CmNkMiAlPiUgCiAgZ3JvdXBfYnkobWVhc3VyZSkgJT4lCiAgZ3JvdXBfbWFwKH4ueCAlPiUKICAgIGZpbHRlcighc3RyX2RldGVjdCh0eXBlMiwiT3RoZXIiKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcl9jcmVhdGVkLHk9dmFsdWUsY29sb3I9bWVkaWEsZ3JvdXA9aW50ZXJhY3Rpb24ocXVhbnRpbGUsbWVkaWEpLGxpbmV0eXBlPWxpbmV0eXBlKSkgKwogICAgZ2VvbV9zdGVwKCkgKwogICAgZmFjZXRfd3JhcCh+dHlwZTIsc2NhbGVzPSJmcmVlIikgKwogICAgdGhlbWVfaHNjaV9kaXNjcmV0ZShiYXNlX2ZhbWlseT0iQXJpYWwiKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDIwMDAsMjAyMCxieT00KSkgKwogICAgbGFicyh4PSJZZWFyIix5PSJOdW1iZXIgb2YgY29uanVuY3Rpb25zIikgKwogICAgZ2d0aXRsZSgueSkKICApCmBgYApEdWUgdG8gdGhlIGxlbmd0aGVuaW5nIG9mIGFydGljbGUgdGV4dHMgY2F1c2luZyBjb21wbGV4aXRpZXMgZm9yIGFuYWx5c2VzLCBhbGwgdGhlIGZvbGxvd2luZyBjb25qdW5jdGlvbiBwcm9wb3J0aW9ucyB3ZXJlIGNhbGN1bGF0ZWQgYW5kIGV2YWx1YXRlZDoKIAogLSBDb25qdW5jdGlvbnMvd29yZHMKIC0gQ29uanVuY3Rpb25zL3NlbnRlbmNlcwogLSBDb25qdW5jdGlvbnMvcGFyYWdyYWhzCiAtIENvbmp1bmN0aW9ucy9hcnRpY2xlcwogLSBTZW50ZW5jZXMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvc2VudGVuY2VzCiAtIFNlbnRlbmNlcyBjb250YWluaW5nIGNvbmp1bmN0aW9ucy9wYXJhZ3JhaHMKIC0gU2VudGVuY2VzIGNvbnRhaW5pbmcgY29uanVuY3Rpb25zL2FydGljbGVzCiAtIFBhcmFncmFwaHMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvcGFyYWdyYWhzCiAtIFBhcmFncmFwaHMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvYXJ0aWNsZXMKIC0gQXJ0aWNsZXMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvYXJ0aWNsZXMKIApPdXQgb2YgdGhlc2UsICJTZW50ZW5jZXMgY29udGFpbmluZyBjb25qdW5jdGlvbnMvc2VudGVuY2VzIiB3YXMgcmV0YWluZWQgZm9yIGZpbmFsIGFuYWx5c2lzOgoKIyMjIFNlbnRlbmNlcyBjb250YWluaW5nIGNvbmp1bmN0aW9ucy9zZW50ZW5jZXMKYGBge3IsZmlnLndpZHRoPTgsZmlnLmhlaWdodD0xMX0KMToyICU+JSBtYXAofgogIGNkMiAlPiUgCiAgICBmaWx0ZXIobWVhc3VyZT09IlNlbnRlbmNlcyBjb250YWluaW5nIGNvbmp1bmN0aW9ucy9zZW50ZW5jZXMiKSAlPiUKICAgIGZpbHRlcighc3RyX2RldGVjdCh0eXBlMiwiT3RoZXIiKSwhc3RyX2RldGVjdCh0eXBlMiwiaW4gSm91cm5hbGlzdGljIG9waW5pb24iKSwhc3RyX2RldGVjdCh0eXBlMiwiaW4gRXh0ZXJuYWwgb3BpbmlvbiIpKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyX2NyZWF0ZWQseT12YWx1ZSxjb2xvcj1tZWRpYSxncm91cD1pbnRlcmFjdGlvbihxdWFudGlsZSxtZWRpYSksbGluZXR5cGU9bGluZXR5cGUpKSArCiAgICBnZW9tX3N0ZXAoKSArCiAgICBmYWNldF93cmFwX3BhZ2luYXRlKH50eXBlMixuY29sPTQsbnJvdz0zLHBhZ2U9LngpICsKICAgIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgyMDAwLDIwMjAsYnk9NCkpICsKICAgIGxhYnMoeD0iWWVhciIseT0iU2VudGVuY2VzIGNvbnRhaW5pbmcgY29uanVuY3Rpb25zL3NlbnRlbmNlcyIpCikKYGBgCgpJbnRlcnByZXRhdGlvbnM6CgogLSBUaGVyZSBpcyBhbiBpbmNyZWFzZSBpbiBzZW50ZW5jZSBjb25zdHJ1Y3Rpb25zIHdpdGggY29uanVuY3Rpb25zIGRlbm90aW5nIGludGVycHJldGl2ZSBzdWJjbGF1c2VzIGluIHBhcnRpY3VsYXJseSBkb21lc3RpYyBuZXdzIHJlcG9ydGluZyBhbmQgSFMgS2F1cHVua2kuIFRoZSBvdmVyYWxsIGluY3JlYXNlIGNvbWVzIG1vc3RseSBmcm9tIGpvdXJuYWxpc3RpYyB0ZXh0IGFuZCBub3QgZnJvbSBhbiBpbmNyZWFzZSBpbiBxdW90ZXMu