df <- read_rds(path = here::here("data_twitter", "data_processed", "covid_19.rds"))

Basic Data Information

total_tweets <- df %>%
  count()

n_users <- df %>%
  distinct(user_id) %>%
  count()

Below are the basic statistics (total number of tweets, number of unique users and date):

Number of total tweets: 677001. Number of diferent users: 110698.

Distribution of bots/no_bots/unknown:

df %>%
  distinct(user_id, .keep_all = T) %>%
  count(is_bot) %>%
  mutate(perct = n / sum(n)) %>%
  gt() %>%
  tab_options(
    heading.title.font.size = 13,
    column_labels.font.size = 11,
    table.font.size = 11
  ) %>%
  tab_header(
    title = "Distribution of bots/no_bots/unknown:"
  ) %>%
  fmt_number(
    columns = vars(n),
    decimals = 0
  ) %>%
  fmt_percent(
    columns = vars(perct),
    decimals = 2,
  )
Distribution of bots/no_bots/unknown:
is_bot n perct
Bot 601 0.54%
Bot_official 5 0.00%
No Bot 88,767 80.19%
Unknown 21,325 19.26%

Dates:

min(df$created_at)
## [1] "2020-03-16 00:51:30 UTC"
max(df$created_at)
## [1] "2020-03-23 18:45:30 UTC"

Accounts with the highest number of tweets:

df %>%
  mutate(user_id = as.character(user_id)) %>%
  count(user_name, user_id, sort = T) %>%
  slice(1:20) %>%
  gt() %>%
  tab_options(
    heading.title.font.size = 13,
    column_labels.font.size = 11,
    table.font.size = 11
  ) %>%
  tab_header(
    title = "# of different tweets by user"
  ) %>%
  fmt_number(
    columns = vars(n),
    decimals = 0
  )
# of different tweets by user
user_name user_id n
Coronavirus bot 1235367745539248128 2,477
covid19bot 1234752234124124160 2,040
Cyber Security Feed 1131854274223366144 940
🚨#CoronaCamps R THE PLAN🚨NOT A DRILL🌹#NotMeUs 1170258383506747392 645
COVID-19 Real Time Numbers 1237834300420173824 540
NaFe065 1226454737542930432 481
The Quint 2982269822 450
Hakkı Art. 3086632433 439
Sally Deal 817825066993860608 392
Shakthi Vadakkepat 18936284 374
NewsOnePlace.com 3534222021 370
A V 94979487 353
Hindusherni_ 🇮🇳 1236134854107860992 335
Security Testing 710123736175783936 317
Real Talk with JAM Podcast 1214084640916426752 305
Mark Dominic 856969871023890432 293
Hindustan Times 36327407 284
IMRAN KHAN® NIYAZI™ SELECTED© 788432343765626880 281
Tonya 287394890 276
and the livin's easy 132535895 269

Accounts with the highest number of users:

df %>%
  select(user_name, user_followers_count) %>%
  arrange(desc(user_followers_count)) %>%
  distinct(user_name, .keep_all = T) %>%
  slice(1:20) %>%
  gt() %>%
  tab_options(
    heading.title.font.size = 13,
    column_labels.font.size = 11,
    table.font.size = 11
  ) %>%
  tab_header(
    title = "Firts 20th users by # of followers"
  ) %>%
  fmt_number(
    columns = vars(user_followers_count),
    decimals = 0
  )
Firts 20th users by # of followers
user_name user_followers_count
CGTN 14,050,164
Rachel Maddow MSNBC 9,930,284
Hindustan Times 7,173,683
People's Daily, China 7,097,825
Lonely Planet 6,306,359
ESPNcricinfo 5,872,015
Department of State 5,690,004
UK Prime Minister 5,608,948
American Red Cross 5,320,293
Alfie Deyes 5,203,717
MTV NEWS 5,142,713
ABS-CBN News Channel 4,859,740
Filmfare 4,810,087
Dr. Mehmet Oz 4,082,376
The Indian Express 3,365,718
Nic Nemeth 2,842,804
Kal Naga - أبوالنجا 2,821,111
Bakhtawar B-Zardari 2,770,820
Sahara Reporters 2,697,417
Naveen Patnaik 2,647,178

Tweets per hour

library(scales)

df %>%
  select(created_at) %>%
  mutate(round_created_at_tweet = round_date(created_at, unit = "hour")) %>%
  count(round_created_at_tweet) %>%
  # filter(round_created_at_tweet > as.Date("2020-02-01")) %>% THIS HAS BEEN DONE PREVIOSLY
  ggplot(aes(x = round_created_at_tweet, y = n)) +
  geom_line() +
  labs(
    title = "",
    x = "Date",
    y = "# of tweets"
  ) +
  scale_x_datetime() +
  theme_light() +
  theme(legend.position = "bottom") +
  scale_color_brewer(palette = "Set1")

df %>%
  filter(is_bot != "Bot_official") %>%
  # select(is_bot, created_at) %>%
  mutate(round_created_at_tweet = round_date(created_at, unit = "hour")) %>%
  count(is_bot, round_created_at_tweet) %>%
  ggplot(aes(x = round_created_at_tweet, y = n, color = is_bot)) +
  geom_line() +
  labs(
    title = "",
    x = "Date",
    y = "# of tweets"
  ) +
  scale_x_datetime() +
  theme_light() +
  theme(legend.position = "bottom") +
  # facet_wrap(~ is_bot, scales = "free", ncol = 2) +
  scale_color_brewer(palette = "Set1")

BOTS

Distribution of prob_bot

Distribution of probability of being a bot:

df %>%
  select(prob_bot) %>%
  ggplot(aes(x = prob_bot)) +
  geom_histogram(bins = 10)

library(tidytext)

remove_reg <- "&amp;|&lt;|&gt;"
remove_urls <- "http"

df %>%
  mutate(
    text = str_remove_all(text, remove_reg),
    text = str_replace_all(text, "(?<=\\S)#", " #")
  ) %>%
  unnest_tokens(word, text, token = "tweets") %>%
  filter(
    !word %in% stop_words$word,
    !word %in% str_detect(word, remove_urls),
    !word %in% str_remove_all(stop_words$word, "'"),
    !word %in% c(
      "rt", "#covid_19", "#covid19", "#covid", "#covid19esp",
      "#coronavirus", "#coronavirusesp"
    ),
    !word %in% c("coronavirus", "covid", "covid-19", "covid19"),
    str_detect(word, "[a-z]")
  ) -> tidy_df

tidy_df %>%
  group_by(is_bot) %>%
  count(word, sort = T) %>%
  ungroup() %>%
  left_join(tidy_df %>%
    group_by(is_bot) %>%
    summarise(total = n())) %>%
  mutate(freq = n / total) -> tidy_freq
df %>%
  filter(!str_detect(text, "^RT")) %>%
  mutate(
    text = str_remove_all(text, remove_reg),
    text = str_remove_all(text, "#"),
    text = str_remove_all(text, "countryregion"),
    text = str_remove_all(text, "ocoronavirus")
  ) %>%
  unnest_tokens(word, text, token = "tweets", strip_url = TRUE) %>%
  filter(
    !word %in% stop_words$word,
    !word %in% str_remove_all(stop_words$word, "'"),
    !word %in% c("rt", "covid_19", "covid19", "covid", "covid19esp", "coronavirus", "coronavirusesp", "countryregion", "ocoronavirus", "gcoronavirus"),
    str_detect(word, "[a-z]")
  ) %>%
  count(is_bot, word, sort = T) %>%
  group_by(is_bot) %>%
  # summarise(n = n()) %>%
  slice_max(n, n = 10) %>%
  # arrange(n) %>%
  ungroup() %>%
  # mutate(word = fct_infreq(word, ordered = T)) %>%
  ggplot(aes(reorder_within(word, n, is_bot), n, fill = is_bot)) +
  geom_col(show.legend = F) +
  scale_x_reordered() +
  facet_wrap(~is_bot, scales = "free", ncol = 2) +
  coord_flip()

Topic Modeling

Latent Dirichlet allocation (LDA) is a particularly popular method for fitting a topic model. It treats each document as a mixture of topics, and each topic as a mixture of words. This allows documents to “overlap” each other in terms of content, rather than being separated into discrete groups, in a way that mirrors typical use of natural language:

Word-topic probabilities

Bot

lda_tweets <- read_rds(here::here(
  "data_twitter",
  "data_processed", "lda_bot.rds"
))

topic_tweets <- tidy(lda_tweets, matrix = "gamma")

topic_tweets %>%
  distinct(document) %>%
  nrow() -> n_total

topic_tweets %>%
  rename("id" = "document") %>%
  arrange(id) %>%
  group_by(id) %>%
  top_n(1, wt = gamma) %>%
  ungroup() %>%
  count(topic) %>%
  mutate(
    n_total = n_total,
    percentage = n / n_total
  ) %>%
  arrange(desc(percentage)) %>%
  filter(percentage > .05) %>%
  mutate(
    curly_name = paste0(
      "Topic ",
      topic, " (",
      round(percentage * 100, 2), "%)"
    ),
    curly_name = as_factor(curly_name)
  ) -> cmn_topics

topic_tweets <- tidy(lda_tweets)

tw_top_terms <- topic_tweets %>%
  inner_join(cmn_topics %>% select(topic, curly_name)) %>%
  group_by(topic) %>%
  top_n(20, beta) %>%
  ungroup() %>%
  arrange(topic, -beta)

tw_top_terms %>%
  mutate(
    term = reorder_within(term, beta, topic)
  ) %>%
  ggplot(aes(term, beta, fill = factor(topic))) +
  geom_col(show.legend = F) +
  facet_wrap(~curly_name, scales = "free", ncol = 3) +
  coord_flip() +
  scale_x_reordered()

No Bot

lda_tweets <- read_rds(here::here(
  "data_twitter",
  "data_processed", "lda_no_bot.rds"
))

topic_tweets <- tidy(lda_tweets, matrix = "gamma")

topic_tweets %>%
  distinct(document) %>%
  nrow() -> n_total

topic_tweets %>%
  rename("id" = "document") %>%
  arrange(id) %>%
  group_by(id) %>%
  top_n(1, wt = gamma) %>%
  ungroup() %>%
  count(topic) %>%
  mutate(
    n_total = n_total,
    percentage = n / n_total
  ) %>%
  arrange(desc(percentage)) %>%
  filter(percentage > .05) %>%
  mutate(
    curly_name = paste0(
      "Topic ",
      topic, " (",
      round(percentage * 100, 2), "%)"
    ),
    curly_name = as_factor(curly_name)
  ) -> cmn_topics

topic_tweets <- tidy(lda_tweets)

tw_top_terms <- topic_tweets %>%
  inner_join(cmn_topics %>% select(topic, curly_name)) %>%
  group_by(topic) %>%
  top_n(20, beta) %>%
  ungroup() %>%
  arrange(topic, -beta)

tw_top_terms %>%
  mutate(
    term = reorder_within(term, beta, topic)
  ) %>%
  ggplot(aes(term, beta, fill = factor(topic))) +
  geom_col(show.legend = F) +
  facet_wrap(~curly_name, scales = "free", ncol = 3) +
  coord_flip() +
  scale_x_reordered()

Unknown

lda_tweets <- read_rds(here::here(
  "data_twitter",
  "data_processed", "lda_unknown.rds"
))

topic_tweets <- tidy(lda_tweets, matrix = "gamma")

topic_tweets %>%
  distinct(document) %>%
  nrow() -> n_total

topic_tweets %>%
  rename("id" = "document") %>%
  arrange(id) %>%
  group_by(id) %>%
  top_n(1, wt = gamma) %>%
  ungroup() %>%
  count(topic) %>%
  mutate(
    n_total = n_total,
    percentage = n / n_total
  ) %>%
  arrange(desc(percentage)) %>%
  filter(percentage > .05) %>%
  mutate(
    curly_name = paste0(
      "Topic ",
      topic, " (",
      round(percentage * 100, 2), "%)"
    ),
    curly_name = as_factor(curly_name)
  ) -> cmn_topics

topic_tweets <- tidy(lda_tweets)

tw_top_terms <- topic_tweets %>%
  inner_join(cmn_topics %>% select(topic, curly_name)) %>%
  group_by(topic) %>%
  top_n(20, beta) %>%
  ungroup() %>%
  arrange(topic, -beta)

tw_top_terms %>%
  mutate(
    term = reorder_within(term, beta, topic)
  ) %>%
  ggplot(aes(term, beta, fill = factor(topic))) +
  geom_col(show.legend = F) +
  facet_wrap(~curly_name, scales = "free", ncol = 3) +
  coord_flip() +
  scale_x_reordered()

Bot official

lda_tweets <- read_rds(here::here(
  "data_twitter",
  "data_processed", "lda_botofficial.rds"
))

topic_tweets <- tidy(lda_tweets, matrix = "gamma")

topic_tweets %>%
  distinct(document) %>%
  nrow() -> n_total

topic_tweets %>%
  rename("id" = "document") %>%
  arrange(id) %>%
  group_by(id) %>%
  top_n(1, wt = gamma) %>%
  ungroup() %>%
  count(topic) %>%
  mutate(
    n_total = n_total,
    percentage = n / n_total
  ) %>%
  arrange(desc(percentage)) %>%
  filter(percentage > .05) %>%
  mutate(
    curly_name = paste0(
      "Topic ",
      topic, " (",
      round(percentage * 100, 2), "%)"
    ),
    curly_name = as_factor(curly_name)
  ) -> cmn_topics

topic_tweets <- tidy(lda_tweets)

tw_top_terms <- topic_tweets %>%
  inner_join(cmn_topics %>% select(topic, curly_name)) %>%
  group_by(topic) %>%
  top_n(20, beta) %>%
  ungroup() %>%
  arrange(topic, -beta)

tw_top_terms %>%
  mutate(
    term = reorder_within(term, beta, topic)
  ) %>%
  ggplot(aes(term, beta, fill = factor(topic))) +
  geom_col(show.legend = F) +
  facet_wrap(~curly_name, scales = "free", ncol = 3) +
  coord_flip() +
  scale_x_reordered()

Sentiment Analysis

library(tidytext)
library(tidyverse)

remove_reg <- "&amp;|&lt;|&gt;"
remove_urls <- "http"

df %>%
  filter(is_bot != "Bot_official") %>%
  mutate(
    text = str_remove_all(text, remove_reg),
    text = str_replace_all(text, "(?<=\\S)#", " #")
  ) %>%
  unnest_tokens(word, text, token = "tweets") %>%
  filter(
    !word %in% stop_words$word,
    !word %in% str_detect(word, remove_urls),
    !word %in% str_remove_all(stop_words$word, "'"),
    !word %in% c("rt", "#covid_19", "#covid19", "#covid", "#covid19esp", "#coronavirus", "#coronavirusesp"),
    str_detect(word, "[a-z]")
  ) -> tidy_df

tidy_df %>%
  select(is_bot, id, word, created_at) %>%
  mutate(id = as.character(id)) %>%
  inner_join(get_sentiments("afinn")) %>%
  mutate(round_created_at_tweet = lubridate::round_date(created_at, unit = "day")) %>%
  group_by(id) %>%
  mutate(sentiment = mean(value)) %>%
  ungroup() %>%
  group_by(is_bot, round_created_at_tweet) %>%
  mutate(sentiment_per_day = mean(sentiment)) -> foo

library(scales)

foo %>%
  ggplot(aes(x = round_created_at_tweet, y = sentiment_per_day, colour = is_bot)) +
  geom_line() +
  scale_x_datetime() +
  theme_light() +
  theme(legend.position = "bottom") +
  scale_color_brewer(palette = "Set1")

LS0tCnRpdGxlOiBEZXNjcmlwdGl2ZSBhbmFseXNpcyAKY2xlYW46IHRydWUKb3V0cHV0OgogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiBmYWxzZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgY2FjaGUgPSBGQUxTRSwKICBjYWNoZS5sYXp5ID0gRkFMU0UsCgllY2hvID0gVFJVRSwKCW1lc3NhZ2UgPSBGQUxTRSwKCXdhcm5pbmcgPSBGQUxTRSwKCXRpZHkgPSAic3R5bGVyIgopCnhmdW46OnBrZ19hdHRhY2goInRpZHl2ZXJzZSIsICJndCIsICJsdWJyaWRhdGUiKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfbGluZWRyYXcoYmFzZV9zaXplID0gOCkpCmBgYAoKYGBge3J9CmRmIDwtIHJlYWRfcmRzKHBhdGggPSBoZXJlOjpoZXJlKCJkYXRhX3R3aXR0ZXIiLCAiZGF0YV9wcm9jZXNzZWQiLCAiY292aWRfMTkucmRzIikpCgpgYGAKCiMjIEJhc2ljIERhdGEgSW5mb3JtYXRpb24KCmBgYHtyfQp0b3RhbF90d2VldHMgPC0gZGYgJT4lCiAgY291bnQoKQoKbl91c2VycyA8LSBkZiAlPiUgCiAgZGlzdGluY3QodXNlcl9pZCkgJT4lIAogIGNvdW50KCkKYGBgCgpCZWxvdyBhcmUgdGhlIGJhc2ljIHN0YXRpc3RpY3MgKHRvdGFsIG51bWJlciBvZiB0d2VldHMsIG51bWJlciBvZiB1bmlxdWUgdXNlcnMgYW5kIGRhdGUpOgoKTnVtYmVyIG9mIHRvdGFsIHR3ZWV0czogYHIgdG90YWxfdHdlZXRzYC4KTnVtYmVyIG9mIGRpZmVyZW50IHVzZXJzOiBgciBuX3VzZXJzYC4KCkRpc3RyaWJ1dGlvbiBvZiBib3RzL25vX2JvdHMvdW5rbm93bjoKCmBgYHtyfQpkZiAlPiUgCiAgZGlzdGluY3QodXNlcl9pZCwgLmtlZXBfYWxsID0gVCkgJT4lIAogIGNvdW50KGlzX2JvdCkgJT4lIAogIG11dGF0ZShwZXJjdCA9IG4vc3VtKG4pKSAlPiUgIAogIGd0KCkgJT4lIAogICAgdGFiX29wdGlvbnMoCiAgICBoZWFkaW5nLnRpdGxlLmZvbnQuc2l6ZSA9IDEzLAogICAgY29sdW1uX2xhYmVscy5mb250LnNpemUgPSAxMSwKICAgIHRhYmxlLmZvbnQuc2l6ZSA9IDExCiAgKSAlPiUKICAgIHRhYl9oZWFkZXIoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgYm90cy9ub19ib3RzL3Vua25vd246IgogICkgJT4lIAogIGZtdF9udW1iZXIoCiAgICBjb2x1bW5zID0gdmFycyhuKSwKICAgIGRlY2ltYWxzID0gMAogICkgJT4lIAogIGZtdF9wZXJjZW50KAogICAgY29sdW1ucyA9IHZhcnMocGVyY3QpLAogICAgZGVjaW1hbHMgPSAyLAogICkKYGBgCgpEYXRlczoKYGBge3J9Cm1pbihkZiRjcmVhdGVkX2F0KQptYXgoZGYkY3JlYXRlZF9hdCkgIApgYGAKCgojIyMgQWNjb3VudHMgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2YgdHdlZXRzOgoKYGBge3J9CmRmICU+JSAKICBtdXRhdGUodXNlcl9pZCAgPSBhcy5jaGFyYWN0ZXIodXNlcl9pZCkpICU+JSAKICBjb3VudCh1c2VyX25hbWUsIHVzZXJfaWQsIHNvcnQgPSBUKSAlPiUKICBzbGljZSgxOjIwKSAlPiUgCiAgZ3QoKSAlPiUgCiAgICB0YWJfb3B0aW9ucygKICAgIGhlYWRpbmcudGl0bGUuZm9udC5zaXplID0gMTMsCiAgICBjb2x1bW5fbGFiZWxzLmZvbnQuc2l6ZSA9IDExLAogICAgdGFibGUuZm9udC5zaXplID0gMTEKICApICU+JQogICAgdGFiX2hlYWRlcigKICAgIHRpdGxlID0gIiMgb2YgZGlmZmVyZW50IHR3ZWV0cyBieSB1c2VyIgogICkgJT4lIAogIGZtdF9udW1iZXIoCiAgICBjb2x1bW5zID0gdmFycyhuKSwKICAgIGRlY2ltYWxzID0gMAogICkKYGBgCgojIyMgQWNjb3VudHMgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2YgdXNlcnM6CmBgYHtyfQpkZiAlPiUgCiAgc2VsZWN0KHVzZXJfbmFtZSwgdXNlcl9mb2xsb3dlcnNfY291bnQpICU+JSAKICBhcnJhbmdlKGRlc2ModXNlcl9mb2xsb3dlcnNfY291bnQpKSAlPiUgCiAgZGlzdGluY3QodXNlcl9uYW1lLCAua2VlcF9hbGwgPSBUKSAlPiUgCiAgc2xpY2UoMToyMCkgJT4lIAogIGd0KCkgJT4lIAogICAgdGFiX29wdGlvbnMoCiAgICBoZWFkaW5nLnRpdGxlLmZvbnQuc2l6ZSA9IDEzLAogICAgY29sdW1uX2xhYmVscy5mb250LnNpemUgPSAxMSwKICAgIHRhYmxlLmZvbnQuc2l6ZSA9IDExCiAgKSAlPiUKICB0YWJfaGVhZGVyKAogICAgdGl0bGUgPSAiRmlydHMgMjB0aCB1c2VycyBieSAjIG9mIGZvbGxvd2VycyIKICApICU+JSAKICBmbXRfbnVtYmVyKAogICAgY29sdW1ucyA9IHZhcnModXNlcl9mb2xsb3dlcnNfY291bnQpLAogICAgZGVjaW1hbHMgPSAwCiAgKQogIApgYGAKCiMjIyBUd2VldHMgcGVyIGhvdXIKCmBgYHtyfQpsaWJyYXJ5KHNjYWxlcykKCmRmICU+JSAKICBzZWxlY3QoY3JlYXRlZF9hdCkgJT4lCiAgbXV0YXRlKHJvdW5kX2NyZWF0ZWRfYXRfdHdlZXQgPSByb3VuZF9kYXRlKGNyZWF0ZWRfYXQsIHVuaXQgPSAiaG91ciIpKSAlPiUKICBjb3VudChyb3VuZF9jcmVhdGVkX2F0X3R3ZWV0KSAlPiUKICAjIGZpbHRlcihyb3VuZF9jcmVhdGVkX2F0X3R3ZWV0ID4gYXMuRGF0ZSgiMjAyMC0wMi0wMSIpKSAlPiUgVEhJUyBIQVMgQkVFTiBET05FIFBSRVZJT1NMWQogIGdncGxvdChhZXMoeCA9IHJvdW5kX2NyZWF0ZWRfYXRfdHdlZXQsIHkgPSBuKSkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIiIsIAogICAgICAgeCA9ICJEYXRlIiwKICAgICAgIHkgPSAiIyBvZiB0d2VldHMiKSArCiAgc2NhbGVfeF9kYXRldGltZSgpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKQpgYGAKCmBgYHtyfQpkZiAlPiUgCiAgZmlsdGVyKGlzX2JvdCAhPSAiQm90X29mZmljaWFsIikgJT4lIAogICMgc2VsZWN0KGlzX2JvdCwgY3JlYXRlZF9hdCkgJT4lCiAgbXV0YXRlKHJvdW5kX2NyZWF0ZWRfYXRfdHdlZXQgPSByb3VuZF9kYXRlKGNyZWF0ZWRfYXQsIHVuaXQgPSAiaG91ciIpKSAlPiUKICBjb3VudChpc19ib3QsIHJvdW5kX2NyZWF0ZWRfYXRfdHdlZXQpICU+JQogIGdncGxvdChhZXMoeCA9IHJvdW5kX2NyZWF0ZWRfYXRfdHdlZXQsIHkgPSBuLCBjb2xvciA9IGlzX2JvdCkpICsKICBnZW9tX2xpbmUoKSArCiAgICBsYWJzKHRpdGxlID0gIiIsIAogICAgICAgeCA9ICJEYXRlIiwKICAgICAgIHkgPSAiIyBvZiB0d2VldHMiKSArCiAgc2NhbGVfeF9kYXRldGltZSgpICsKICB0aGVtZV9saWdodCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogICMgZmFjZXRfd3JhcCh+IGlzX2JvdCwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKQpgYGAKCgojIyBCT1RTCgojIyMgRGlzdHJpYnV0aW9uIG9mIHByb2JfYm90CkRpc3RyaWJ1dGlvbiBvZiBwcm9iYWJpbGl0eSBvZiBiZWluZyBhIGJvdDoKCmBgYHtyfQpkZiAlPiUgCiAgc2VsZWN0KHByb2JfYm90KSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcHJvYl9ib3QpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDEwKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHRpZHl0ZXh0KQoKcmVtb3ZlX3JlZyA8LSAiJmFtcDt8Jmx0O3wmZ3Q7IgpyZW1vdmVfdXJscyA8LSAiaHR0cCIKCmRmICU+JSAKICBtdXRhdGUodGV4dCA9IHN0cl9yZW1vdmVfYWxsKHRleHQsIHJlbW92ZV9yZWcpLAogICAgICAgICB0ZXh0ID0gc3RyX3JlcGxhY2VfYWxsKHRleHQsICIoPzw9XFxTKSMiLCAiICMiKSkgJT4lCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0LCB0b2tlbiA9ICJ0d2VldHMiKSAlPiUKICBmaWx0ZXIoIXdvcmQgJWluJSBzdG9wX3dvcmRzJHdvcmQsCiAgICAgICAgICF3b3JkICVpbiUgc3RyX2RldGVjdCh3b3JkLCByZW1vdmVfdXJscyksCiAgICAgICAgICF3b3JkICVpbiUgc3RyX3JlbW92ZV9hbGwoc3RvcF93b3JkcyR3b3JkLCAiJyIpLAogICAgICAgICAhd29yZCAlaW4lIGMoInJ0IiwgIiNjb3ZpZF8xOSIsICIjY292aWQxOSIsICIjY292aWQiLCAiI2NvdmlkMTllc3AiLCAKICAgICAgICAgICAgICAgICAgICAgICIjY29yb25hdmlydXMiLCAiI2Nvcm9uYXZpcnVzZXNwIiksCiAgICAgICAgICF3b3JkICVpbiUgYygiY29yb25hdmlydXMiLCAiY292aWQiLCAiY292aWQtMTkiLCAiY292aWQxOSIpLAogICAgICAgICBzdHJfZGV0ZWN0KHdvcmQsICJbYS16XSIpKSAtPiB0aWR5X2RmCgp0aWR5X2RmICU+JSAKICBncm91cF9ieShpc19ib3QpICU+JSAKICBjb3VudCh3b3JkLCBzb3J0ID0gVCkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgbGVmdF9qb2luKHRpZHlfZGYgJT4lIAogICAgICAgICAgICAgIGdyb3VwX2J5KGlzX2JvdCkgJT4lIAogICAgICAgICAgICAgIHN1bW1hcmlzZSh0b3RhbCA9IG4oKSkpICU+JQogIG11dGF0ZShmcmVxID0gbi90b3RhbCkgLT4gdGlkeV9mcmVxCmBgYAoKYGBge3J9CmRmICU+JSAKICBmaWx0ZXIoIXN0cl9kZXRlY3QodGV4dCwgIl5SVCIpKSAlPiUgCiAgbXV0YXRlKHRleHQgPSBzdHJfcmVtb3ZlX2FsbCh0ZXh0LCByZW1vdmVfcmVnKSwKICAgICAgICAgdGV4dCA9IHN0cl9yZW1vdmVfYWxsKHRleHQsICIjIiksCiAgICAgICAgIHRleHQgPSBzdHJfcmVtb3ZlX2FsbCh0ZXh0LCAiY291bnRyeXJlZ2lvbiIpLAogICAgICAgICB0ZXh0ID0gc3RyX3JlbW92ZV9hbGwodGV4dCwgIm9jb3JvbmF2aXJ1cyIpKSAlPiUKICB1bm5lc3RfdG9rZW5zKHdvcmQsIHRleHQsIHRva2VuID0gInR3ZWV0cyIsIHN0cmlwX3VybCA9IFRSVUUpICU+JSAKICBmaWx0ZXIoIXdvcmQgJWluJSBzdG9wX3dvcmRzJHdvcmQsCiAgICAgICAgICF3b3JkICVpbiUgc3RyX3JlbW92ZV9hbGwoc3RvcF93b3JkcyR3b3JkLCAiJyIpLAogICAgICAgICAhd29yZCAlaW4lIGMoInJ0IiwgImNvdmlkXzE5IiwgImNvdmlkMTkiLCAiY292aWQiLCAiY292aWQxOWVzcCIsICJjb3JvbmF2aXJ1cyIsICJjb3JvbmF2aXJ1c2VzcCIsICJjb3VudHJ5cmVnaW9uIiwgIm9jb3JvbmF2aXJ1cyIsICJnY29yb25hdmlydXMiKSwKICAgICAgICAgc3RyX2RldGVjdCh3b3JkLCAiW2Etel0iKSkgJT4lCiAgY291bnQoaXNfYm90LCB3b3JkLCBzb3J0ID0gVCkgJT4lIAogIGdyb3VwX2J5KGlzX2JvdCkgJT4lIAogICMgc3VtbWFyaXNlKG4gPSBuKCkpICU+JSAKICBzbGljZV9tYXgobiwgbiA9IDEwKSAlPiUKICAjIGFycmFuZ2UobikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgIyBtdXRhdGUod29yZCA9IGZjdF9pbmZyZXEod29yZCwgb3JkZXJlZCA9IFQpKSAlPiUgCiAgZ2dwbG90KGFlcyhyZW9yZGVyX3dpdGhpbih3b3JkLG4sIGlzX2JvdCksIG4sIGZpbGwgPSBpc19ib3QpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGKSArCiAgc2NhbGVfeF9yZW9yZGVyZWQoKSArCiAgZmFjZXRfd3JhcCh+IGlzX2JvdCwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMikgKwogIGNvb3JkX2ZsaXAoKQpgYGAKCiMjIFRvcGljIE1vZGVsaW5nCgpMYXRlbnQgRGlyaWNobGV0IGFsbG9jYXRpb24gKExEQSkgaXMgYSBwYXJ0aWN1bGFybHkgcG9wdWxhciBtZXRob2QgZm9yIGZpdHRpbmcgYSB0b3BpYyBtb2RlbC4gSXQgdHJlYXRzIGVhY2ggZG9jdW1lbnQgYXMgYSBtaXh0dXJlIG9mIHRvcGljcywgYW5kIGVhY2ggdG9waWMgYXMgYSBtaXh0dXJlIG9mIHdvcmRzLiBUaGlzIGFsbG93cyBkb2N1bWVudHMgdG8g4oCcb3ZlcmxhcOKAnSBlYWNoIG90aGVyIGluIHRlcm1zIG9mIGNvbnRlbnQsIHJhdGhlciB0aGFuIGJlaW5nIHNlcGFyYXRlZCBpbnRvIGRpc2NyZXRlIGdyb3VwcywgaW4gYSB3YXkgdGhhdCBtaXJyb3JzIHR5cGljYWwgdXNlIG9mIG5hdHVyYWwgbGFuZ3VhZ2U6CgojIyMgV29yZC10b3BpYyBwcm9iYWJpbGl0aWVzCgojIyMjIEJvdCAKCmBgYHtyIG91dC53aWR0aCA9ICIxMDAlIiwgZmlnLmhlaWdodD0gMTB9CgpsZGFfdHdlZXRzIDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGFfdHdpdHRlciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF0YV9wcm9jZXNzZWQiLCAibGRhX2JvdC5yZHMiKSkKCnRvcGljX3R3ZWV0cyA8LSB0aWR5KGxkYV90d2VldHMsIG1hdHJpeCA9ICJnYW1tYSIpCgp0b3BpY190d2VldHMgJT4lIAogIGRpc3RpbmN0KGRvY3VtZW50KSAlPiUgCiAgbnJvdygpIC0+IG5fdG90YWwKCnRvcGljX3R3ZWV0cyAlPiUgCiAgcmVuYW1lKCJpZCIgPSAiZG9jdW1lbnQiKSAlPiUgCiAgYXJyYW5nZShpZCkgJT4lIAogIGdyb3VwX2J5KGlkKSAlPiUgCiAgdG9wX24oMSwgd3QgPSBnYW1tYSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgY291bnQodG9waWMpICU+JSAKICBtdXRhdGUobl90b3RhbCA9IG5fdG90YWwsCiAgICAgICAgIHBlcmNlbnRhZ2UgPSBuL25fdG90YWwpICU+JSAKICBhcnJhbmdlKGRlc2MocGVyY2VudGFnZSkpICU+JSAKICBmaWx0ZXIocGVyY2VudGFnZSA+IC4wNSkgJT4lIAogIG11dGF0ZShjdXJseV9uYW1lID0gcGFzdGUwKCJUb3BpYyAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BpYywgIiAoIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQocGVyY2VudGFnZSAqIDEwMCwgMiksICIlKSIpLAogICAgICAgICBjdXJseV9uYW1lID0gYXNfZmFjdG9yKGN1cmx5X25hbWUpKSAtPiBjbW5fdG9waWNzCiAgCnRvcGljX3R3ZWV0cyA8LSB0aWR5KGxkYV90d2VldHMpCgp0d190b3BfdGVybXMgPC0gdG9waWNfdHdlZXRzICU+JQogIGlubmVyX2pvaW4oY21uX3RvcGljcyAlPiUgc2VsZWN0KHRvcGljLCBjdXJseV9uYW1lKSkgJT4lIAogIGdyb3VwX2J5KHRvcGljKSAlPiUKICB0b3BfbigyMCwgYmV0YSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2UodG9waWMsIC1iZXRhKQoKdHdfdG9wX3Rlcm1zICU+JQogIG11dGF0ZSgKICAgIHRlcm0gPSByZW9yZGVyX3dpdGhpbih0ZXJtLCBiZXRhLCB0b3BpYykKICApICU+JQogIGdncGxvdChhZXModGVybSwgYmV0YSwgZmlsbCA9IGZhY3Rvcih0b3BpYykpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGKSArCiAgZmFjZXRfd3JhcCh+Y3VybHlfbmFtZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMykgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeF9yZW9yZGVyZWQoKQpgYGAKCiMjIyMgTm8gQm90CmBgYHtyIG91dC53aWR0aCA9ICIxMDAlIiwgZmlnLmhlaWdodD0gMTV9CgpsZGFfdHdlZXRzIDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGFfdHdpdHRlciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF0YV9wcm9jZXNzZWQiLCAibGRhX25vX2JvdC5yZHMiKSkKCnRvcGljX3R3ZWV0cyA8LSB0aWR5KGxkYV90d2VldHMsIG1hdHJpeCA9ICJnYW1tYSIpCgp0b3BpY190d2VldHMgJT4lIAogIGRpc3RpbmN0KGRvY3VtZW50KSAlPiUgCiAgbnJvdygpIC0+IG5fdG90YWwKCnRvcGljX3R3ZWV0cyAlPiUgCiAgcmVuYW1lKCJpZCIgPSAiZG9jdW1lbnQiKSAlPiUgCiAgYXJyYW5nZShpZCkgJT4lIAogIGdyb3VwX2J5KGlkKSAlPiUgCiAgdG9wX24oMSwgd3QgPSBnYW1tYSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgY291bnQodG9waWMpICU+JSAKICBtdXRhdGUobl90b3RhbCA9IG5fdG90YWwsCiAgICAgICAgIHBlcmNlbnRhZ2UgPSBuL25fdG90YWwpICU+JSAKICBhcnJhbmdlKGRlc2MocGVyY2VudGFnZSkpICU+JSAKICBmaWx0ZXIocGVyY2VudGFnZSA+IC4wNSkgJT4lIAogIG11dGF0ZShjdXJseV9uYW1lID0gcGFzdGUwKCJUb3BpYyAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BpYywgIiAoIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQocGVyY2VudGFnZSAqIDEwMCwgMiksICIlKSIpLAogICAgICAgICBjdXJseV9uYW1lID0gYXNfZmFjdG9yKGN1cmx5X25hbWUpKSAtPiBjbW5fdG9waWNzCiAgCnRvcGljX3R3ZWV0cyA8LSB0aWR5KGxkYV90d2VldHMpCgp0d190b3BfdGVybXMgPC0gdG9waWNfdHdlZXRzICU+JQogIGlubmVyX2pvaW4oY21uX3RvcGljcyAlPiUgc2VsZWN0KHRvcGljLCBjdXJseV9uYW1lKSkgJT4lIAogIGdyb3VwX2J5KHRvcGljKSAlPiUKICB0b3BfbigyMCwgYmV0YSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2UodG9waWMsIC1iZXRhKQoKdHdfdG9wX3Rlcm1zICU+JQogIG11dGF0ZSgKICAgIHRlcm0gPSByZW9yZGVyX3dpdGhpbih0ZXJtLCBiZXRhLCB0b3BpYykKICApICU+JQogIGdncGxvdChhZXModGVybSwgYmV0YSwgZmlsbCA9IGZhY3Rvcih0b3BpYykpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGKSArCiAgZmFjZXRfd3JhcCh+Y3VybHlfbmFtZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMykgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeF9yZW9yZGVyZWQoKQpgYGAKCiMjIyMgVW5rbm93bgpgYGB7ciBvdXQud2lkdGggPSAiMTAwJSIsIGZpZy5oZWlnaHQ9IDE1fQoKbGRhX3R3ZWV0cyA8LSByZWFkX3JkcyhoZXJlOjpoZXJlKCJkYXRhX3R3aXR0ZXIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImRhdGFfcHJvY2Vzc2VkIiwgImxkYV91bmtub3duLnJkcyIpKQoKdG9waWNfdHdlZXRzIDwtIHRpZHkobGRhX3R3ZWV0cywgbWF0cml4ID0gImdhbW1hIikKCnRvcGljX3R3ZWV0cyAlPiUgCiAgZGlzdGluY3QoZG9jdW1lbnQpICU+JSAKICBucm93KCkgLT4gbl90b3RhbAoKdG9waWNfdHdlZXRzICU+JSAKICByZW5hbWUoImlkIiA9ICJkb2N1bWVudCIpICU+JSAKICBhcnJhbmdlKGlkKSAlPiUgCiAgZ3JvdXBfYnkoaWQpICU+JSAKICB0b3BfbigxLCB3dCA9IGdhbW1hKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBjb3VudCh0b3BpYykgJT4lIAogIG11dGF0ZShuX3RvdGFsID0gbl90b3RhbCwKICAgICAgICAgcGVyY2VudGFnZSA9IG4vbl90b3RhbCkgJT4lIAogIGFycmFuZ2UoZGVzYyhwZXJjZW50YWdlKSkgJT4lIAogIGZpbHRlcihwZXJjZW50YWdlID4gLjA1KSAlPiUgCiAgbXV0YXRlKGN1cmx5X25hbWUgPSBwYXN0ZTAoIlRvcGljICIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvcGljLCAiICgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3VuZChwZXJjZW50YWdlICogMTAwLCAyKSwgIiUpIiksCiAgICAgICAgIGN1cmx5X25hbWUgPSBhc19mYWN0b3IoY3VybHlfbmFtZSkpIC0+IGNtbl90b3BpY3MKICAKdG9waWNfdHdlZXRzIDwtIHRpZHkobGRhX3R3ZWV0cykKCnR3X3RvcF90ZXJtcyA8LSB0b3BpY190d2VldHMgJT4lCiAgaW5uZXJfam9pbihjbW5fdG9waWNzICU+JSBzZWxlY3QodG9waWMsIGN1cmx5X25hbWUpKSAlPiUgCiAgZ3JvdXBfYnkodG9waWMpICU+JQogIHRvcF9uKDIwLCBiZXRhKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZSh0b3BpYywgLWJldGEpCgp0d190b3BfdGVybXMgJT4lCiAgbXV0YXRlKAogICAgdGVybSA9IHJlb3JkZXJfd2l0aGluKHRlcm0sIGJldGEsIHRvcGljKQogICkgJT4lCiAgZ2dwbG90KGFlcyh0ZXJtLCBiZXRhLCBmaWxsID0gZmFjdG9yKHRvcGljKSkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEYpICsKICBmYWNldF93cmFwKH5jdXJseV9uYW1lLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAzKSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV94X3Jlb3JkZXJlZCgpCmBgYAoKIyMjIyBCb3Qgb2ZmaWNpYWwgCmBgYHtyIG91dC53aWR0aCA9ICIxMDAlIiwgZmlnLmhlaWdodD0gMTV9CgpsZGFfdHdlZXRzIDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGFfdHdpdHRlciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF0YV9wcm9jZXNzZWQiLCAibGRhX2JvdG9mZmljaWFsLnJkcyIpKQoKdG9waWNfdHdlZXRzIDwtIHRpZHkobGRhX3R3ZWV0cywgbWF0cml4ID0gImdhbW1hIikKCnRvcGljX3R3ZWV0cyAlPiUgCiAgZGlzdGluY3QoZG9jdW1lbnQpICU+JSAKICBucm93KCkgLT4gbl90b3RhbAoKdG9waWNfdHdlZXRzICU+JSAKICByZW5hbWUoImlkIiA9ICJkb2N1bWVudCIpICU+JSAKICBhcnJhbmdlKGlkKSAlPiUgCiAgZ3JvdXBfYnkoaWQpICU+JSAKICB0b3BfbigxLCB3dCA9IGdhbW1hKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBjb3VudCh0b3BpYykgJT4lIAogIG11dGF0ZShuX3RvdGFsID0gbl90b3RhbCwKICAgICAgICAgcGVyY2VudGFnZSA9IG4vbl90b3RhbCkgJT4lIAogIGFycmFuZ2UoZGVzYyhwZXJjZW50YWdlKSkgJT4lIAogIGZpbHRlcihwZXJjZW50YWdlID4gLjA1KSAlPiUgCiAgbXV0YXRlKGN1cmx5X25hbWUgPSBwYXN0ZTAoIlRvcGljICIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvcGljLCAiICgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3VuZChwZXJjZW50YWdlICogMTAwLCAyKSwgIiUpIiksCiAgICAgICAgIGN1cmx5X25hbWUgPSBhc19mYWN0b3IoY3VybHlfbmFtZSkpIC0+IGNtbl90b3BpY3MKICAKdG9waWNfdHdlZXRzIDwtIHRpZHkobGRhX3R3ZWV0cykKCnR3X3RvcF90ZXJtcyA8LSB0b3BpY190d2VldHMgJT4lCiAgaW5uZXJfam9pbihjbW5fdG9waWNzICU+JSBzZWxlY3QodG9waWMsIGN1cmx5X25hbWUpKSAlPiUgCiAgZ3JvdXBfYnkodG9waWMpICU+JQogIHRvcF9uKDIwLCBiZXRhKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZSh0b3BpYywgLWJldGEpCgp0d190b3BfdGVybXMgJT4lCiAgbXV0YXRlKAogICAgdGVybSA9IHJlb3JkZXJfd2l0aGluKHRlcm0sIGJldGEsIHRvcGljKQogICkgJT4lCiAgZ2dwbG90KGFlcyh0ZXJtLCBiZXRhLCBmaWxsID0gZmFjdG9yKHRvcGljKSkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEYpICsKICBmYWNldF93cmFwKH5jdXJseV9uYW1lLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAzKSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV94X3Jlb3JkZXJlZCgpCmBgYAoKIyMgU2VudGltZW50IEFuYWx5c2lzCgpgYGB7ciB9CmxpYnJhcnkodGlkeXRleHQpCmxpYnJhcnkodGlkeXZlcnNlKQoKcmVtb3ZlX3JlZyA8LSAiJmFtcDt8Jmx0O3wmZ3Q7IgpyZW1vdmVfdXJscyA8LSAiaHR0cCIKCmRmICU+JQogIGZpbHRlcihpc19ib3QgIT0gIkJvdF9vZmZpY2lhbCIpICU+JSAKICBtdXRhdGUodGV4dCA9IHN0cl9yZW1vdmVfYWxsKHRleHQsIHJlbW92ZV9yZWcpLAogICAgICAgICB0ZXh0ID0gc3RyX3JlcGxhY2VfYWxsKHRleHQsICIoPzw9XFxTKSMiLCAiICMiKSkgJT4lCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0LCB0b2tlbiA9ICJ0d2VldHMiKSAlPiUKICBmaWx0ZXIoIXdvcmQgJWluJSBzdG9wX3dvcmRzJHdvcmQsCiAgICAgICAgICF3b3JkICVpbiUgc3RyX2RldGVjdCh3b3JkLCByZW1vdmVfdXJscyksCiAgICAgICAgICF3b3JkICVpbiUgc3RyX3JlbW92ZV9hbGwoc3RvcF93b3JkcyR3b3JkLCAiJyIpLAogICAgICAgICAhd29yZCAlaW4lIGMoInJ0IiwgIiNjb3ZpZF8xOSIsICIjY292aWQxOSIsICIjY292aWQiLCAiI2NvdmlkMTllc3AiLCAiI2Nvcm9uYXZpcnVzIiwgIiNjb3JvbmF2aXJ1c2VzcCIpLAogICAgICAgICBzdHJfZGV0ZWN0KHdvcmQsICJbYS16XSIpKSAtPiB0aWR5X2RmCgp0aWR5X2RmICU+JQogIHNlbGVjdChpc19ib3QsIGlkLCB3b3JkLCBjcmVhdGVkX2F0KSAlPiUKICBtdXRhdGUoaWQgPSBhcy5jaGFyYWN0ZXIoaWQpKSAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJhZmlubiIpKSAlPiUKICBtdXRhdGUocm91bmRfY3JlYXRlZF9hdF90d2VldCA9IGx1YnJpZGF0ZTo6cm91bmRfZGF0ZShjcmVhdGVkX2F0LCB1bml0ID0gImRheSIpKSAlPiUKICBncm91cF9ieShpZCkgJT4lCiAgbXV0YXRlKHNlbnRpbWVudCA9IG1lYW4odmFsdWUpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkoaXNfYm90LCByb3VuZF9jcmVhdGVkX2F0X3R3ZWV0KSAlPiUKICBtdXRhdGUoc2VudGltZW50X3Blcl9kYXkgPSBtZWFuKHNlbnRpbWVudCkpIC0+IGZvbwoKbGlicmFyeShzY2FsZXMpCgpmb28gJT4lCiAgZ2dwbG90KGFlcyh4ID0gcm91bmRfY3JlYXRlZF9hdF90d2VldCwgeSA9IHNlbnRpbWVudF9wZXJfZGF5LCBjb2xvdXIgPSBpc19ib3QpKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX3hfZGF0ZXRpbWUoKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikKYGBgCgo=