Causal Impact

Number of total users:

neda_liwc %>% 
  select(id) %>% 
  distinct() %>% 
  nrow()
## [1] 431
Word Category Relative Eff.(%) P Value
Female 33.031 0.001
Risk 20.29 0.001
Relig 17.409 0.015
Anx 15.936 0.046
We 15.857 0.004
Money 10.6 0.002
Hear 9.708 0.002
Body 8.89 0.003
Nonflu 7.344 0.019
Power 6.675 0.001
Focusfuture 6.63 0.006
Relativ 6.452 0.001
Tentat 4.874 0.012
Focuspresent 4.403 0.001
Negemo 4.233 0.004
Work 3.925 0.022
Social 3.632 0.001
Informal 3.155 0.002
Focuspast 2.694 0.040
Posemo -2.59 0.007
Negate -3.469 0.048
See -15.408 0.001
Ingest -26.529 0.025
Friend -27.165 0.001
Filler -42.13 0.001

CAUSAL IMPACT BY GENDER

Number of users by gender (400~):

neda_liwc_gender %>% 
  select(id, gender) %>% 
  distinct() %>% 
  count(gender)
## # A tibble: 3 x 2
##   gender     n
##   <chr>  <int>
## 1 f        173
## 2 m         65
## 3 u        193

Number of users in the baseline ():

baseline_liwc_gender %>% 
  select(id, gender) %>% 
  distinct() %>% 
  count(gender)
## # A tibble: 3 x 2
##   gender     n
##   <chr>  <int>
## 1 f       1699
## 2 m       2066
## 3 u       2978
baseline_liwc_gender %>% 
  select(-text, -created_at_tweet, -id_tweet, -name) %>% 
  group_by(gender, id, days_tweet) %>% 
  summarise_all(mean) %>% 
  ungroup() %>% 
  select(-id) %>% 
  group_by(gender, days_tweet) %>% 
  summarise_all(mean) %>% 
  ungroup() %>% 
  pivot_longer(cols = fun:filler, names_to = "categ", values_to = "values_baseline") -> ci_baseline

neda_liwc_gender %>% 
  select(-id_tweet, -created_at_tweet) %>% 
  group_by(gender, id, days_tweet) %>% 
  summarise_all(mean) %>% 
  ungroup() %>% 
  select(-id) %>% 
  group_by(gender, days_tweet) %>% 
  summarise_all(mean) %>% 
  ungroup() %>% 
  pivot_longer(fun:filler, names_to = "categ", 
               values_to = "values_neda") -> ci_neda_liwc 

pre_period <- c(1, 16)
post_period <- c(17, 31)

ci_baseline %>% 
  full_join(ci_neda_liwc) -> d_second

d_second %>% 
  # count(gender, days_tweet) %>% 
  # view()
  # view()
  # select(categ, values_neda, values_baseline) %>% 
  # nest(data = - categ) %>% 
  select(gender, categ, values_neda, values_baseline) %>%
  # filter(gender == "m") %>% view()
  group_by(categ, gender) %>% 
  nest() %>% 
  ungroup() %>% 
  select(gender, categ, data) %>% 
  mutate(mod = map(data, ~CausalImpact::CausalImpact(., 
                                                     pre_period,
                                                     post_period))) -> ci
  
ci %>% 
  mutate(summary_mod = map(mod, "summary")) %>% 
  filter(!map_lgl(summary_mod, is.null)) -> ci_resul 

ci_resul %>% 
  mutate(p = map(summary_mod, "p")) %>% 
  mutate(p = map_dbl(p, 1)) %>% 
  filter(categ %in% categories_in_gender) %>% 
  mutate(relative_effect = map(summary_mod, "RelEffect")) %>% 
  mutate(relative_effect = map_dbl(relative_effect, 2))-> sig_cat

# sig_cat %>% 
#   filter(categ %in% sel_cat) -> sig_cat

sig_cat %>% 
  arrange(gender, desc(relative_effect)) %>% 
  select(gender, categ, 
         second_relative_effect = relative_effect, p_second = p) -> second_ap

second_ap %>% 
  pivot_wider(id_cols = categ, 
              values_from = c(second_relative_effect, p_second),
              names_from = gender) %>% 
  mutate(categ = str_to_title(categ)) %>% 
  mutate_at(vars(starts_with("second")), ~.*100) %>% 
  mutate_if(is.numeric, ~round(., digits = 3)) %>% 
  mutate_at(vars(starts_with("second")), function(x){
    cell_spec(x, "html", color = spec_color(x), bold = T)
  }) %>% 
  kable("html", escape = F,
        align = "lrr",
        col.names = c("Word Category", "FEMALE Relative Eff.(%)",
                      "MALE Relative Eff.(%)",
                      "UNKNOWN Relative Eff.(%)",
                      "FEMALE P Value",
                      "MALE P Value",
                      "UNKNOWN P Value")) %>%  
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE)
Word Category FEMALE Relative Eff.(%) MALE Relative Eff.(%) UNKNOWN Relative Eff.(%) FEMALE P Value MALE P Value UNKNOWN P Value
Risk 27.713 7.938 10.948 0.001 0.174 0.074
Female 26.164 22.59 34.262 0.001 0.005 0.001
Relig 25.409 -2.293 15.585 0.014 0.393 0.102
We 17.588 -0.364 18.167 0.028 0.471 0.002
Hear 10.457 -3.575 10.76 0.003 0.255 0.003
Power 9.825 0.762 5.091 0.001 0.417 0.012
Anx 8.477 6.309 29.838 0.174 0.270 0.031
Money 8.209 31.643 -0.583 0.029 0.001 0.464
Tentat 7.838 2.283 3.036 0.011 0.262 0.141
Relativ 7.719 1.424 2.714 0.001 0.256 0.070
Informal 6.653 4.143 0.35 0.001 0.001 0.391
Work 6.207 0.102 2.455 0.016 0.477 0.190
Focuspast 5.91 9.87 -4.13 0.010 0.007 0.024
Social 4.541 4.411 3.713 0.001 0.002 0.003
Focuspresent 3.932 10.171 3.492 0.007 0.001 0.001
Focusfuture 2.705 9.076 13.746 0.267 0.002 0.001
Nonflu 2.614 15.021 8.292 0.326 0.042 0.079
Negemo 1.98 13.916 2.728 0.253 0.001 0.156
Body -0.127 31.309 15.016 0.494 0.001 0.001
Negate -6.244 1.931 -0.057 0.080 0.346 0.483
Posemo -7.802 -0.554 -0.266 0.001 0.434 0.423
Ingest -17.991 -27.943 -12.164 0.188 0.012 0.207
See -20.432 1.343 -17.405 0.001 0.419 0.001
Friend -34.369 -16.925 -24.181 0.001 0.092 0.008
Filler -40.55 -34.464 -52.18 0.002 0.007 0.001

Words inside categ:

The tables below contain the changes for the 4 most changed words (positive and negative) within each of the categories. The first column is the specific word. Changes_total is the difference between the “before” and “after” frequency of all users. Changes_f same as Changes_total but for female users, Changes_m for male users and Changes_u for unknown users.

library(tidyverse)

read_delim(here::here("data", "liwc", "LIWC2015_English_Flat.dic"),
           delim = "\t", skip = 1, col_names = c("number", "name"), 
           n_max = 73) -> categories_name 

read_tsv(here::here("data", "liwc", "LIWC2015_English_Flat.dic"),
         skip = 75, col_names = paste0(c("x"), c("_"), 1:11),
         guess_max = 6000, col_types = "ccccccccccc") %>% 
  mutate(x_1 = str_remove(x_1, "\\*")) -> words_dic

categories_name %>% 
  filter(name %in% c("female", "family", "anx", "shehe", "affiliation", "friend")) %>% 
  pull(number) -> number_top_categ

words_dic %>% 
  filter_at(vars(-x_1), any_vars(. %in% number_top_categ)) %>%  
  pull(x_1) -> words_cat


# neda_timelapse ----------------------------------------------------------

library(lubridate)

# neda_hist <- read_rds(here::here("data", "NEDA_historical_twenty.rds")) %>% 
#   distinct() %>% 
#   filter(created_at_tweet >= ymd("2019-03-01")) %>% 
#   mutate(text = str_to_lower(text),
#          neda_related = str_detect(text, 
#                                    pattern = "#nedawareness|#comeasyouare|@nedastaff")) 

# gender_output <- read_tsv(here::here("data", "gender_extractor", 
#                                      "neda_liwc_gender_output.tsv"),
#                           col_names = c("id", "name", "name_proc", "gender"))

gender_output <- read_rds(here::here("data", "neda_liwc_gender_twenty.rds")) %>% 
  select(gender, id_tweet, id)
# first_tweet <- neda_hist %>% 
#   select(created_at_tweet, text, id, id_tweet, neda_related) %>% 
#   filter(neda_related) %>% 
#   arrange(created_at_tweet) %>% 
#   group_by(id) %>% 
#   slice(1) %>% 
#   ungroup() %>% 
#   select(cero_date = created_at_tweet, id) %>% 
#   filter(cero_date >= ymd("2019-01-01"))
# 
# neda_change <- neda_hist %>% 
#   select(id_tweet, text, created_at_tweet, id) %>% 
#   inner_join(first_tweet) %>% 
#   mutate(days_tweet = interval(start = cero_date, end = created_at_tweet),
#          days_tweet = round(time_length(days_tweet, unit = "days"))) %>% 
#   select(-cero_date) %>% 
#   filter(days_tweet >= -15, days_tweet <= 15)
# 
# neda_timelapse <- neda_change %>%
#   count(id, before_after = sign(days_tweet), sort = T) %>% 
#   mutate(before_after = case_when(before_after == -1 ~ "before",
#                                   before_after == 1 ~ "after",
#                                   TRUE ~ "cero")) %>% 
#   pivot_wider(values_from = n, names_from = before_after) %>% 
#   filter(before >= 15 & after >= 15) %>% 
#   select(-cero) %>% 
#   semi_join(x = neda_change, y = .)



read_rds(here::here("data", "neda_timelapse_twenty.rds")) %>% 
  inner_join(gender_output) -> neda_timelapse

library(tidytext)

replace_reg1 <- "https://t.co/[A-Za-z]\\d]+|"
replace_reg2 <- "https://t.co/[A-Za-z]\\d]+|&amp;|&lt;|&gt;|RT|https"
replace_reg <- paste0(replace_reg1, replace_reg2)
unnest_reg <- "([^A-Za-z_\\d#@']|'(?![A-Za-z_\\d#@]))"

tidy_tweets <- neda_timelapse %>%
  mutate(text = str_to_lower(text)) %>% 
  mutate(text = str_replace_all(text, replace_reg, "")) %>% 
  unnest_tokens(word, text, token = "regex", pattern = unnest_reg)

tidy_tweets %>% 
  filter(word %in% words_cat) %>% 
  mutate(days_tweet = case_when(days_tweet < 0 ~ "before",
                                days_tweet > 0 ~ "after",
                                TRUE ~ "cero")) %>% 
  filter(days_tweet != "cero") -> tidy_words

neda_liwc <- read_rds(here::here("data", "neda_liwc_twenty.rds")) %>% 
  select(-created_at_tweet) %>% 
  filter(abs(days_tweet) <= 15)

FEMALE

# female ------------------------------------------------------------------
# female -> 43

words_dic %>% 
  filter_at(vars(-x_1), any_vars(. == 43)) %>% 
  pull(x_1) -> words_female

tidy_words %>% 
  filter(word %in% words_female) %>% 
  count(days_tweet, word) %>% 
  mutate(gender = "t") %>% 
  bind_rows(tidy_words %>% 
              filter(word %in% words_female) %>% 
              count(gender, days_tweet, word)) %>% 
  pivot_wider(names_from = c(days_tweet, gender), values_from = n) %>% 
  mutate_if(is.numeric, ~replace_na(., 0)) %>% 
  mutate(changes_total = after_t - before_t,
         changes_f = after_f - before_f,
         changes_m = after_m - before_m,
         changes_u = after_u - before_u) %>% 
  select(word, starts_with("changes")) %>% 
  arrange(desc(changes_total)) -> f 

f_top <- f %>% top_n(4, wt = changes_total)
f_bottom <- f %>% top_n(-4, wt = changes_total)

f_top %>% 
  bind_rows(f_bottom) %>% 
  gt::gt()
word changes_total changes_f changes_m changes_u
women 816 323 110 383
she 489 181 67 241
her 431 234 51 146
madam 233 39 2 192
girly -9 -4 -3 -2
witch -9 -10 -2 3
gal -10 -7 -2 -1
gals -14 -5 0 -9
lesbian -56 -24 -6 -26

RISK

# risk -> 85

words_dic %>% 
  filter_at(vars(-x_1), any_vars(. == 85)) %>% 
  pull(x_1) -> words_risk

tidy_words %>% 
  filter(word %in% words_risk) %>% 
  count(days_tweet, word) %>% 
  mutate(gender = "t") %>% 
  bind_rows(tidy_words %>% 
              filter(word %in% words_risk) %>% 
              count(gender, days_tweet, word)) %>% 
  pivot_wider(names_from = c(days_tweet, gender), values_from = n) %>% 
  mutate_if(is.numeric, ~replace_na(., 0)) %>% 
  mutate(changes_total = after_t - before_t,
         changes_f = after_f - before_f,
         changes_m = after_m - before_m,
         changes_u = after_u - before_u) %>% 
  select(word, starts_with("changes")) %>% 
  arrange(desc(changes_total)) -> f 

f_top <- f %>% top_n(4, wt = changes_total)
f_bottom <- f %>% top_n(-4, wt = changes_total)

f_top %>% 
  bind_rows(f_bottom) %>% 
  gt::gt()
word changes_total changes_f changes_m changes_u
avoid 92 39 19 34
risk 89 50 28 11
threat 51 32 7 12
alarm 11 4 2 5
dread 3 0 2 1
doubt 2 2 3 -3
inhibit 1 1 0 0
unsure -3 0 -2 -1

RELIGION

# relig -> 114

words_dic %>% 
  filter_at(vars(-x_1), any_vars(. == 114)) %>% 
  pull(x_1) -> words_relig

tidy_words %>% 
  filter(word %in% words_relig) %>% 
  count(days_tweet, word) %>% 
  mutate(gender = "t") %>% 
  bind_rows(tidy_words %>% 
              filter(word %in% words_relig) %>% 
              count(gender, days_tweet, word)) %>% 
  pivot_wider(names_from = c(days_tweet, gender), values_from = n) %>% 
  mutate_if(is.numeric, ~replace_na(., 0)) %>% 
  mutate(changes_total = after_t - before_t,
         changes_f = after_f - before_f,
         changes_m = after_m - before_m,
         changes_u = after_u - before_u) %>% 
  select(word, starts_with("changes")) %>% 
  arrange(desc(changes_total)) -> f 

f_top <- f %>% top_n(4, wt = changes_total)
f_bottom <- f %>% top_n(-4, wt = changes_total)

f_top %>% 
  bind_rows(f_bottom) %>% 
  gt::gt()
word changes_total changes_f changes_m changes_u
church 31 20 9 2
goddess 4 2 0 2
church 31 20 9 2
goddess 4 2 0 2

MONEY

# money -> 113

words_dic %>% 
  filter_at(vars(-x_1), any_vars(. == 113)) %>% 
  pull(x_1) -> words_money

tidy_words %>% 
  filter(word %in% words_money) %>% 
  count(days_tweet, word) %>% 
  mutate(gender = "t") %>% 
  bind_rows(tidy_words %>% 
              filter(word %in% words_money) %>% 
              count(gender, days_tweet, word)) %>% 
  pivot_wider(names_from = c(days_tweet, gender), values_from = n) %>% 
  mutate_if(is.numeric, ~replace_na(., 0)) %>% 
  mutate(changes_total = after_t - before_t,
         changes_f = after_f - before_f,
         changes_m = after_m - before_m,
         changes_u = after_u - before_u) %>% 
  select(word, starts_with("changes")) %>% 
  arrange(desc(changes_total)) -> f 

f_top <- f %>% top_n(4, wt = changes_total)
f_bottom <- f %>% top_n(-4, wt = changes_total)

f_top %>% 
  bind_rows(f_bottom) %>% 
  gt::gt()
word changes_total changes_f changes_m changes_u
donate 10 6 1 3
donation 10 0 6 4
donate 10 6 1 3
donation 10 0 6 4

BODY

# body -> 71

words_dic %>% 
  filter_at(vars(-x_1), any_vars(. == 114)) %>% 
  pull(x_1) -> words_body

tidy_words %>% 
  filter(word %in% words_body) %>% 
  count(days_tweet, word) %>% 
  mutate(gender = "t") %>% 
  bind_rows(tidy_words %>% 
              filter(word %in% words_body) %>% 
              count(gender, days_tweet, word)) %>% 
  pivot_wider(names_from = c(days_tweet, gender), values_from = n) %>% 
  mutate_if(is.numeric, ~replace_na(., 0)) %>% 
  mutate(changes_total = after_t - before_t,
         changes_f = after_f - before_f,
         changes_m = after_m - before_m,
         changes_u = after_u - before_u) %>% 
  select(word, starts_with("changes")) %>% 
  arrange(desc(changes_total)) -> f 

f_top <- f %>% top_n(4, wt = changes_total)
f_bottom <- f %>% top_n(-4, wt = changes_total)

f_top %>% 
  bind_rows(f_bottom) %>% 
  gt::gt()
word changes_total changes_f changes_m changes_u
church 31 20 9 2
goddess 4 2 0 2
church 31 20 9 2
goddess 4 2 0 2

COMMON WORDS IN TWEETS BY WORDS CATEGORY:

neda_liwc_gender %>% 
  filter(days_tweet >= 0) %>% 
  select(id_tweet, id, gender, female, risk, relig, body, money) %>% 
  pivot_longer(cols = female:money) %>% 
  filter(value > 0) %>% 
  left_join(neda_liwc %>% 
              select(id, id_tweet, text)) %>%  
  rename("category" = name) %>% 
  mutate(text = str_remove_all(text, pattern = "[:graph:]+(…)")) %>% 
  unnest_tokens(word, text, token = "tweets") %>%  
  filter(!word %in% stop_words$word,
         !word %in% c("de", 4, "da", "la", "en", "le", "los", 3),
         word != "rt",
         !word %in% str_remove_all(stop_words$word, "'")) %>% 
  # mutate(word = case_when(category == "female" & word %in% c(words_female,
  #                                                            "womens") ~ NA_character_,
  #                         category == "family" & word %in% c(words_family,
  #                                                            "parents",
  #                                                            "brothers")~ NA_character_,
  #                         category == "anx" & word %in% words_anxiety ~ NA_character_,
  #                         TRUE ~ word)) %>% 
  filter(!is.na(word),
         word != "amp") %>% 
  count(category, gender, word, sort = T) %>%
  group_by(gender, category) %>% 
  top_n(10, wt = n) %>% 
  ungroup() %>% 
  pivot_wider(id_cols = c(category, word), names_from = gender, values_from = n) %>% 
  mutate(category = str_to_title(category)) %>% 
  gt::gt(groupname_col = "category",
         rowname_col = "word")   
u f m
Female
women 569 448 194
girl 491 251 84
sharlene 483 187 NA
love 274 183 60
na 265 NA NA
woman 229 247 104
day 229 192 51
madam 229 NA NA
girls 211 174 61
happy 197 149 NA
mom NA 155 NA
womens NA 142 52
people NA NA 72
trans NA NA 68
time NA NA 50
Risk
stop 514 349 205
bad 403 260 167
people 247 185 128
safe 237 127 59
coronavirus 121 192 58
wrong 174 86 71
crisis NA 148 98
health NA 138 59
protect 127 87 NA
lose 122 NA NA
stay 119 NA NA
trump NA 109 NA
worst 105 NA NA
time NA NA 61
security NA NA 58
Body
shit 444 207 132
heart 302 158 94
hands 249 259 96
body 239 151 64
people 218 141 91
sleep 210 NA NA
ass 186 124 53
hand 163 147 72
love 158 NA NA
wash NA 145 52
time 144 NA NA
head NA 108 63
coronavirus NA 88 NA
eyes NA NA 52
Relig
god 334 270 369
lord NA 37 131
@youversion NA NA 130
jesus NA 36 102
holy 100 55 NA
love 94 66 72
life NA NA 79
angel 75 29 NA
soul 74 51 NA
bless 70 29 NA
people 62 50 42
shit 60 38 NA
sin 59 39 52
day 55 NA NA
@neilvermillion NA NA 48
@janayellis NA NA 43
minister NA 29 NA
Money
free 203 221 87
people 181 193 96
money 166 135 85
coronavirus 99 146 57
account 135 NA 46
pay 91 130 NA
worth 123 92 NA
time 117 122 57
sharlene 100 NA NA
paid NA 96 NA
buy 87 93 50
bill NA 91 NA
marketing NA NA 87
sales NA NA 70
business NA NA 46
LS0tCnRpdGxlOiAiQ2F1c2FsIEltcGFjdCIgCmNsZWFuOiB0cnVlCm91dHB1dDoKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogZmFsc2UKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkKCnhmdW46OnBrZ19hdHRhY2goInRpZHl2ZXJzZSIsICJsdWJyaWRhdGUiLCAia2FibGVFeHRyYSIpCgp0aGVtZV9zZXQodGhlbWVfbGluZWRyYXcoKSkKYGBgCgojIyBDYXVzYWwgSW1wYWN0IAoKYGBge3IgZWNobz1GQUxTRX0KYmFzZWxpbmVfbGl3YyA8LSByZWFkX3JkcyhoZXJlOjpoZXJlKCJkYXRhIiwgImJhc2VsaW5lX2xpd2NfdHdlbnR5LnJkcyIpKQoKbmVkYV9saXdjIDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGEiLCAibmVkYV9saXdjX3R3ZW50eS5yZHMiKSkgJT4lIAogIHNlbGVjdCgtdGV4dCwgLWNyZWF0ZWRfYXRfdHdlZXQpICU+JSAKICBmaWx0ZXIoYWJzKGRheXNfdHdlZXQpIDw9IDE1KQoKc2VsX2NhdCA8LSBjKAogICJpIiwid2UiLCJ5b3UiLCJzaGVoZSIsInRoZXkiLCJpcHJvbiIsIm5lZ2F0ZSIsImNvbXBhcmUiLCJwb3NlbW8iLCJuZWdlbW8iLCJhbngiLCJhbmdlciIsInNhZCIsInNvY2lhbCIsImZhbWlseSIsImZyaWVuZCIsImZlbWFsZSIsIm1hbGUiLCJpbnNpZ2h0IiwiY2F1c2UiLCJkaXNjcmVwIiwidGVudGF0IiwiY2VydGFpbiIsImRpZmZlciIsInNlZSIsImhlYXIiLCJmZWVsIiwiYm9keSIsImhlYWx0aCIsInNleHVhbCIsImluZ2VzdCIsImFmZmlsaWF0aW9uIiwiYWNoaWV2IiwicG93ZXIiLCJyZXdhcmQiLCJyaXNrIiwiZm9jdXNwYXN0IiwiZm9jdXNwcmVzZW50IiwiZm9jdXNmdXR1cmUiLCJyZWxhdGl2Iiwid29yayIsImxlaXN1cmUiLCJob21lIiwibW9uZXkiLCJyZWxpZyIsImRlYXRoIiwiaW5mb3JtYWwiLCJzd2VhciIsImFzc2VudCIsIm5vbmZsdSIsImZpbGxlciIKKQpgYGAKCk51bWJlciBvZiB0b3RhbCB1c2VyczoKYGBge3J9Cm5lZGFfbGl3YyAlPiUgCiAgc2VsZWN0KGlkKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgbnJvdygpCmBgYAoKYGBge3IgZWNobz1GQUxTRX0KYmFzZWxpbmVfbGl3YyAlPiUgCiAgc2VsZWN0KC10ZXh0LCAtY3JlYXRlZF9hdF90d2VldCwgLWlkX3R3ZWV0KSAlPiUgCiAgZ3JvdXBfYnkoZGF5c190d2VldCwgaWQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdCgtaWQpICU+JSAKICBncm91cF9ieShkYXlzX3R3ZWV0KSAlPiUgCiAgc3VtbWFyaXNlX2FsbChtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGZ1bjpmaWxsZXIsIG5hbWVzX3RvID0gImNhdGVnIiwgdmFsdWVzX3RvID0gInZhbHVlc19iYXNlbGluZSIpIC0+IGNpX2Jhc2VsaW5lCgpuZWRhX2xpd2MgJT4lIAogIHNlbGVjdCgtaWRfdHdlZXQpICU+JSAKICBncm91cF9ieShkYXlzX3R3ZWV0LCBpZCkgJT4lIAogIHN1bW1hcmlzZV9hbGwobWVhbikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KC1pZCkgJT4lIAogIGdyb3VwX2J5KGRheXNfdHdlZXQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHBpdm90X2xvbmdlcigtZGF5c190d2VldCwgbmFtZXNfdG8gPSAiY2F0ZWciLCB2YWx1ZXNfdG8gPSAidmFsdWVzX25lZGEiKSAtPiBjaV9uZWRhX2xpd2MgCiAgCnByZV9wZXJpb2QgPC0gYygxLCAxNikKcG9zdF9wZXJpb2QgPC0gYygxNywgMzEpCgpjaV9iYXNlbGluZSAlPiUgCiAgaW5uZXJfam9pbihjaV9uZWRhX2xpd2MpIC0+IGRfc2Vjb25kCgpkX3NlY29uZCAlPiUgCiAgc2VsZWN0KGNhdGVnLCB2YWx1ZXNfbmVkYSwgdmFsdWVzX2Jhc2VsaW5lKSAlPiUgCiAgbmVzdChkYXRhID0gLSBjYXRlZykgJT4lIAogIG11dGF0ZShtb2QgPSBtYXAoZGF0YSwgfkNhdXNhbEltcGFjdDo6Q2F1c2FsSW1wYWN0KC4sIHByZV9wZXJpb2QsIHBvc3RfcGVyaW9kKSkpIC0+IGNpCiAgCmNpICU+JSAKICBtdXRhdGUoc3VtbWFyeV9tb2QgPSBtYXAobW9kLCAic3VtbWFyeSIpKSAlPiUgCiAgZmlsdGVyKCFtYXBfbGdsKHN1bW1hcnlfbW9kLCBpcy5udWxsKSkgLT4gY2lfcmVzdWwgCgpjaV9yZXN1bCAlPiUgCiAgbXV0YXRlKHAgPSBtYXAoc3VtbWFyeV9tb2QsICJwIikpICU+JSAKICBtdXRhdGUocCA9IG1hcF9kYmwocCwgMSkpICU+JSAKICBmaWx0ZXIocCA8IDAuMDUpICU+JSAKICBtdXRhdGUocmVsYXRpdmVfZWZmZWN0ID0gbWFwKHN1bW1hcnlfbW9kLCAiUmVsRWZmZWN0IikpICU+JSAKICBtdXRhdGUocmVsYXRpdmVfZWZmZWN0ID0gbWFwX2RibChyZWxhdGl2ZV9lZmZlY3QsIDIpKS0+IHNpZ19jYXQKCnNpZ19jYXQgJT4lIAogIGZpbHRlcihjYXRlZyAlaW4lIHNlbF9jYXQpIC0+IHNpZ19jYXQKCmNhdGVnb3JpZXNfaW5fZ2VuZGVyIDwtIHNpZ19jYXQgJT4lIHB1bGwoY2F0ZWcpCgpzaWdfY2F0ICU+JSAKICBhcnJhbmdlKGRlc2MocmVsYXRpdmVfZWZmZWN0KSkgJT4lIAogIHNlbGVjdChjYXRlZywgc2Vjb25kX3JlbGF0aXZlX2VmZmVjdCA9IHJlbGF0aXZlX2VmZmVjdCwgcF9zZWNvbmQgPSBwKSAtPiBzZWNvbmRfYXAKCnNlY29uZF9hcCAlPiUgCiAgbXV0YXRlKGNhdGVnID0gc3RyX3RvX3RpdGxlKGNhdGVnKSkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKHNlY29uZF9yZWxhdGl2ZV9lZmZlY3QpLCB+LioxMDApICU+JSAKICBtdXRhdGVfaWYoaXMubnVtZXJpYywgfnJvdW5kKC4sIGRpZ2l0cyA9IDMpKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoc2Vjb25kX3JlbGF0aXZlX2VmZmVjdCksIGZ1bmN0aW9uKHgpewogICAgY2VsbF9zcGVjKHgsICJodG1sIiwgY29sb3IgPSBzcGVjX2NvbG9yKHgpLCBib2xkID0gVCkKICB9KSAlPiUgCiAga2FibGUoImh0bWwiLCBlc2NhcGUgPSBGLAogICAgICAgIGFsaWduID0gImxyciIsCiAgICAgICAgY29sLm5hbWVzID0gYygiV29yZCBDYXRlZ29yeSIsICJSZWxhdGl2ZSBFZmYuKCUpIiwKICAgICAgICAgICAgICAgICAgICAgICJQIFZhbHVlIikpICU+JSAKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkKYGBgCgojIyBDQVVTQUwgSU1QQUNUIEJZIEdFTkRFUgoKYGBge3IgZWNobz1GQUxTRX0KYmFzZWxpbmVfbGl3Y19nZW5kZXIgPC0gcmVhZF9yZHMoaGVyZTo6aGVyZSgiZGF0YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJhc2VsaW5lX2xpd2NfZ2VuZGVyX3R3ZW50eS5yZHMiKSkKCm5lZGFfbGl3Y19nZW5kZXIgPC0gcmVhZF9yZHMoaGVyZTo6aGVyZSgiZGF0YSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5lZGFfbGl3Y19nZW5kZXJfdHdlbnR5LnJkcyIpKSAlPiUgCiAgIyBzZWxlY3QoLXRleHQsIC1jcmVhdGVkX2F0X3R3ZWV0KSAlPiUgCiAgZmlsdGVyKGFicyhkYXlzX3R3ZWV0KSA8PSAxNSkKCnNlbF9jYXQgPC0gYygKICAiaSIsIndlIiwieW91Iiwic2hlaGUiLCJ0aGV5IiwiaXByb24iLCJuZWdhdGUiLCJjb21wYXJlIiwicG9zZW1vIiwibmVnZW1vIiwiYW54IiwiYW5nZXIiLCJzYWQiLCJzb2NpYWwiLCJmYW1pbHkiLCJmcmllbmQiLCJmZW1hbGUiLCJtYWxlIiwiaW5zaWdodCIsImNhdXNlIiwiZGlzY3JlcCIsInRlbnRhdCIsImNlcnRhaW4iLCJkaWZmZXIiLCJzZWUiLCJoZWFyIiwiZmVlbCIsImJvZHkiLCJoZWFsdGgiLCJzZXh1YWwiLCJpbmdlc3QiLCJhZmZpbGlhdGlvbiIsImFjaGlldiIsInBvd2VyIiwicmV3YXJkIiwicmlzayIsImZvY3VzcGFzdCIsImZvY3VzcHJlc2VudCIsImZvY3VzZnV0dXJlIiwicmVsYXRpdiIsIndvcmsiLCJsZWlzdXJlIiwiaG9tZSIsIm1vbmV5IiwicmVsaWciLCJkZWF0aCIsImluZm9ybWFsIiwic3dlYXIiLCJhc3NlbnQiLCJub25mbHUiLCJmaWxsZXIiCikKYGBgCgpOdW1iZXIgb2YgdXNlcnMgYnkgZ2VuZGVyICg0MDB+KToKYGBge3J9Cm5lZGFfbGl3Y19nZW5kZXIgJT4lIAogIHNlbGVjdChpZCwgZ2VuZGVyKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgY291bnQoZ2VuZGVyKQpgYGAKCk51bWJlciBvZiB1c2VycyBpbiB0aGUgYmFzZWxpbmUgKCk6CmBgYHtyfQpiYXNlbGluZV9saXdjX2dlbmRlciAlPiUgCiAgc2VsZWN0KGlkLCBnZW5kZXIpICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBjb3VudChnZW5kZXIpCmBgYAoKYGBge3IgfQpiYXNlbGluZV9saXdjX2dlbmRlciAlPiUgCiAgc2VsZWN0KC10ZXh0LCAtY3JlYXRlZF9hdF90d2VldCwgLWlkX3R3ZWV0LCAtbmFtZSkgJT4lIAogIGdyb3VwX2J5KGdlbmRlciwgaWQsIGRheXNfdHdlZXQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdCgtaWQpICU+JSAKICBncm91cF9ieShnZW5kZXIsIGRheXNfdHdlZXQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gZnVuOmZpbGxlciwgbmFtZXNfdG8gPSAiY2F0ZWciLCB2YWx1ZXNfdG8gPSAidmFsdWVzX2Jhc2VsaW5lIikgLT4gY2lfYmFzZWxpbmUKCm5lZGFfbGl3Y19nZW5kZXIgJT4lIAogIHNlbGVjdCgtaWRfdHdlZXQsIC1jcmVhdGVkX2F0X3R3ZWV0KSAlPiUgCiAgZ3JvdXBfYnkoZ2VuZGVyLCBpZCwgZGF5c190d2VldCkgJT4lIAogIHN1bW1hcmlzZV9hbGwobWVhbikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KC1pZCkgJT4lIAogIGdyb3VwX2J5KGdlbmRlciwgZGF5c190d2VldCkgJT4lIAogIHN1bW1hcmlzZV9hbGwobWVhbikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGZ1bjpmaWxsZXIsIG5hbWVzX3RvID0gImNhdGVnIiwgCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZXNfbmVkYSIpIC0+IGNpX25lZGFfbGl3YyAKCnByZV9wZXJpb2QgPC0gYygxLCAxNikKcG9zdF9wZXJpb2QgPC0gYygxNywgMzEpCgpjaV9iYXNlbGluZSAlPiUgCiAgZnVsbF9qb2luKGNpX25lZGFfbGl3YykgLT4gZF9zZWNvbmQKCmRfc2Vjb25kICU+JSAKICAjIGNvdW50KGdlbmRlciwgZGF5c190d2VldCkgJT4lIAogICMgdmlldygpCiAgIyB2aWV3KCkKICAjIHNlbGVjdChjYXRlZywgdmFsdWVzX25lZGEsIHZhbHVlc19iYXNlbGluZSkgJT4lIAogICMgbmVzdChkYXRhID0gLSBjYXRlZykgJT4lIAogIHNlbGVjdChnZW5kZXIsIGNhdGVnLCB2YWx1ZXNfbmVkYSwgdmFsdWVzX2Jhc2VsaW5lKSAlPiUKICAjIGZpbHRlcihnZW5kZXIgPT0gIm0iKSAlPiUgdmlldygpCiAgZ3JvdXBfYnkoY2F0ZWcsIGdlbmRlcikgJT4lIAogIG5lc3QoKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3QoZ2VuZGVyLCBjYXRlZywgZGF0YSkgJT4lIAogIG11dGF0ZShtb2QgPSBtYXAoZGF0YSwgfkNhdXNhbEltcGFjdDo6Q2F1c2FsSW1wYWN0KC4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZV9wZXJpb2QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zdF9wZXJpb2QpKSkgLT4gY2kKICAKY2kgJT4lIAogIG11dGF0ZShzdW1tYXJ5X21vZCA9IG1hcChtb2QsICJzdW1tYXJ5IikpICU+JSAKICBmaWx0ZXIoIW1hcF9sZ2woc3VtbWFyeV9tb2QsIGlzLm51bGwpKSAtPiBjaV9yZXN1bCAKCmNpX3Jlc3VsICU+JSAKICBtdXRhdGUocCA9IG1hcChzdW1tYXJ5X21vZCwgInAiKSkgJT4lIAogIG11dGF0ZShwID0gbWFwX2RibChwLCAxKSkgJT4lIAogIGZpbHRlcihjYXRlZyAlaW4lIGNhdGVnb3JpZXNfaW5fZ2VuZGVyKSAlPiUgCiAgbXV0YXRlKHJlbGF0aXZlX2VmZmVjdCA9IG1hcChzdW1tYXJ5X21vZCwgIlJlbEVmZmVjdCIpKSAlPiUgCiAgbXV0YXRlKHJlbGF0aXZlX2VmZmVjdCA9IG1hcF9kYmwocmVsYXRpdmVfZWZmZWN0LCAyKSktPiBzaWdfY2F0CgojIHNpZ19jYXQgJT4lIAojICAgZmlsdGVyKGNhdGVnICVpbiUgc2VsX2NhdCkgLT4gc2lnX2NhdAoKc2lnX2NhdCAlPiUgCiAgYXJyYW5nZShnZW5kZXIsIGRlc2MocmVsYXRpdmVfZWZmZWN0KSkgJT4lIAogIHNlbGVjdChnZW5kZXIsIGNhdGVnLCAKICAgICAgICAgc2Vjb25kX3JlbGF0aXZlX2VmZmVjdCA9IHJlbGF0aXZlX2VmZmVjdCwgcF9zZWNvbmQgPSBwKSAtPiBzZWNvbmRfYXAKCnNlY29uZF9hcCAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGNhdGVnLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGMoc2Vjb25kX3JlbGF0aXZlX2VmZmVjdCwgcF9zZWNvbmQpLAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBnZW5kZXIpICU+JSAKICBtdXRhdGUoY2F0ZWcgPSBzdHJfdG9fdGl0bGUoY2F0ZWcpKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoInNlY29uZCIpKSwgfi4qMTAwKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIH5yb3VuZCguLCBkaWdpdHMgPSAzKSkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJzZWNvbmQiKSksIGZ1bmN0aW9uKHgpewogICAgY2VsbF9zcGVjKHgsICJodG1sIiwgY29sb3IgPSBzcGVjX2NvbG9yKHgpLCBib2xkID0gVCkKICB9KSAlPiUgCiAga2FibGUoImh0bWwiLCBlc2NhcGUgPSBGLAogICAgICAgIGFsaWduID0gImxyciIsCiAgICAgICAgY29sLm5hbWVzID0gYygiV29yZCBDYXRlZ29yeSIsICJGRU1BTEUgUmVsYXRpdmUgRWZmLiglKSIsCiAgICAgICAgICAgICAgICAgICAgICAiTUFMRSBSZWxhdGl2ZSBFZmYuKCUpIiwKICAgICAgICAgICAgICAgICAgICAgICJVTktOT1dOIFJlbGF0aXZlIEVmZi4oJSkiLAogICAgICAgICAgICAgICAgICAgICAgIkZFTUFMRSBQIFZhbHVlIiwKICAgICAgICAgICAgICAgICAgICAgICJNQUxFIFAgVmFsdWUiLAogICAgICAgICAgICAgICAgICAgICAgIlVOS05PV04gUCBWYWx1ZSIpKSAlPiUgIAogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLAogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFKQpgYGAKCiMjIFdvcmRzIGluc2lkZSBjYXRlZzoKClRoZSB0YWJsZXMgYmVsb3cgY29udGFpbiB0aGUgY2hhbmdlcyBmb3IgdGhlIDQgbW9zdCBjaGFuZ2VkIHdvcmRzIChwb3NpdGl2ZSBhbmQgbmVnYXRpdmUpIHdpdGhpbiBlYWNoIG9mIHRoZSBjYXRlZ29yaWVzLiBUaGUgZmlyc3QgY29sdW1uIGlzIHRoZSBzcGVjaWZpYyB3b3JkLiBDaGFuZ2VzX3RvdGFsIGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlICJiZWZvcmUiIGFuZCAiYWZ0ZXIiIGZyZXF1ZW5jeSBvZiBhbGwgdXNlcnMuIENoYW5nZXNfZiBzYW1lIGFzIENoYW5nZXNfdG90YWwgYnV0IGZvciBmZW1hbGUgdXNlcnMsIENoYW5nZXNfbSBmb3IgbWFsZSB1c2VycyBhbmQgQ2hhbmdlc191IGZvciB1bmtub3duIHVzZXJzLgoKYGBge3IgfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKCnJlYWRfZGVsaW0oaGVyZTo6aGVyZSgiZGF0YSIsICJsaXdjIiwgIkxJV0MyMDE1X0VuZ2xpc2hfRmxhdC5kaWMiKSwKICAgICAgICAgICBkZWxpbSA9ICJcdCIsIHNraXAgPSAxLCBjb2xfbmFtZXMgPSBjKCJudW1iZXIiLCAibmFtZSIpLCAKICAgICAgICAgICBuX21heCA9IDczKSAtPiBjYXRlZ29yaWVzX25hbWUgCgpyZWFkX3RzdihoZXJlOjpoZXJlKCJkYXRhIiwgImxpd2MiLCAiTElXQzIwMTVfRW5nbGlzaF9GbGF0LmRpYyIpLAogICAgICAgICBza2lwID0gNzUsIGNvbF9uYW1lcyA9IHBhc3RlMChjKCJ4IiksIGMoIl8iKSwgMToxMSksCiAgICAgICAgIGd1ZXNzX21heCA9IDYwMDAsIGNvbF90eXBlcyA9ICJjY2NjY2NjY2NjYyIpICU+JSAKICBtdXRhdGUoeF8xID0gc3RyX3JlbW92ZSh4XzEsICJcXCoiKSkgLT4gd29yZHNfZGljCgpjYXRlZ29yaWVzX25hbWUgJT4lIAogIGZpbHRlcihuYW1lICVpbiUgYygiZmVtYWxlIiwgImZhbWlseSIsICJhbngiLCAic2hlaGUiLCAiYWZmaWxpYXRpb24iLCAiZnJpZW5kIikpICU+JSAKICBwdWxsKG51bWJlcikgLT4gbnVtYmVyX3RvcF9jYXRlZwoKd29yZHNfZGljICU+JSAKICBmaWx0ZXJfYXQodmFycygteF8xKSwgYW55X3ZhcnMoLiAlaW4lIG51bWJlcl90b3BfY2F0ZWcpKSAlPiUgIAogIHB1bGwoeF8xKSAtPiB3b3Jkc19jYXQKCgojIG5lZGFfdGltZWxhcHNlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmxpYnJhcnkobHVicmlkYXRlKQoKIyBuZWRhX2hpc3QgPC0gcmVhZF9yZHMoaGVyZTo6aGVyZSgiZGF0YSIsICJORURBX2hpc3RvcmljYWxfdHdlbnR5LnJkcyIpKSAlPiUgCiMgICBkaXN0aW5jdCgpICU+JSAKIyAgIGZpbHRlcihjcmVhdGVkX2F0X3R3ZWV0ID49IHltZCgiMjAxOS0wMy0wMSIpKSAlPiUgCiMgICBtdXRhdGUodGV4dCA9IHN0cl90b19sb3dlcih0ZXh0KSwKIyAgICAgICAgICBuZWRhX3JlbGF0ZWQgPSBzdHJfZGV0ZWN0KHRleHQsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIjbmVkYXdhcmVuZXNzfCNjb21lYXN5b3VhcmV8QG5lZGFzdGFmZiIpKSAKCiMgZ2VuZGVyX291dHB1dCA8LSByZWFkX3RzdihoZXJlOjpoZXJlKCJkYXRhIiwgImdlbmRlcl9leHRyYWN0b3IiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5lZGFfbGl3Y19nZW5kZXJfb3V0cHV0LnRzdiIpLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sX25hbWVzID0gYygiaWQiLCAibmFtZSIsICJuYW1lX3Byb2MiLCAiZ2VuZGVyIikpCgpnZW5kZXJfb3V0cHV0IDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGEiLCAibmVkYV9saXdjX2dlbmRlcl90d2VudHkucmRzIikpICU+JSAKICBzZWxlY3QoZ2VuZGVyLCBpZF90d2VldCwgaWQpCiMgZmlyc3RfdHdlZXQgPC0gbmVkYV9oaXN0ICU+JSAKIyAgIHNlbGVjdChjcmVhdGVkX2F0X3R3ZWV0LCB0ZXh0LCBpZCwgaWRfdHdlZXQsIG5lZGFfcmVsYXRlZCkgJT4lIAojICAgZmlsdGVyKG5lZGFfcmVsYXRlZCkgJT4lIAojICAgYXJyYW5nZShjcmVhdGVkX2F0X3R3ZWV0KSAlPiUgCiMgICBncm91cF9ieShpZCkgJT4lIAojICAgc2xpY2UoMSkgJT4lIAojICAgdW5ncm91cCgpICU+JSAKIyAgIHNlbGVjdChjZXJvX2RhdGUgPSBjcmVhdGVkX2F0X3R3ZWV0LCBpZCkgJT4lIAojICAgZmlsdGVyKGNlcm9fZGF0ZSA+PSB5bWQoIjIwMTktMDEtMDEiKSkKIyAKIyBuZWRhX2NoYW5nZSA8LSBuZWRhX2hpc3QgJT4lIAojICAgc2VsZWN0KGlkX3R3ZWV0LCB0ZXh0LCBjcmVhdGVkX2F0X3R3ZWV0LCBpZCkgJT4lIAojICAgaW5uZXJfam9pbihmaXJzdF90d2VldCkgJT4lIAojICAgbXV0YXRlKGRheXNfdHdlZXQgPSBpbnRlcnZhbChzdGFydCA9IGNlcm9fZGF0ZSwgZW5kID0gY3JlYXRlZF9hdF90d2VldCksCiMgICAgICAgICAgZGF5c190d2VldCA9IHJvdW5kKHRpbWVfbGVuZ3RoKGRheXNfdHdlZXQsIHVuaXQgPSAiZGF5cyIpKSkgJT4lIAojICAgc2VsZWN0KC1jZXJvX2RhdGUpICU+JSAKIyAgIGZpbHRlcihkYXlzX3R3ZWV0ID49IC0xNSwgZGF5c190d2VldCA8PSAxNSkKIyAKIyBuZWRhX3RpbWVsYXBzZSA8LSBuZWRhX2NoYW5nZSAlPiUKIyAgIGNvdW50KGlkLCBiZWZvcmVfYWZ0ZXIgPSBzaWduKGRheXNfdHdlZXQpLCBzb3J0ID0gVCkgJT4lIAojICAgbXV0YXRlKGJlZm9yZV9hZnRlciA9IGNhc2Vfd2hlbihiZWZvcmVfYWZ0ZXIgPT0gLTEgfiAiYmVmb3JlIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVmb3JlX2FmdGVyID09IDEgfiAiYWZ0ZXIiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gImNlcm8iKSkgJT4lIAojICAgcGl2b3Rfd2lkZXIodmFsdWVzX2Zyb20gPSBuLCBuYW1lc19mcm9tID0gYmVmb3JlX2FmdGVyKSAlPiUgCiMgICBmaWx0ZXIoYmVmb3JlID49IDE1ICYgYWZ0ZXIgPj0gMTUpICU+JSAKIyAgIHNlbGVjdCgtY2VybykgJT4lIAojICAgc2VtaV9qb2luKHggPSBuZWRhX2NoYW5nZSwgeSA9IC4pCgoKCnJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGEiLCAibmVkYV90aW1lbGFwc2VfdHdlbnR5LnJkcyIpKSAlPiUgCiAgaW5uZXJfam9pbihnZW5kZXJfb3V0cHV0KSAtPiBuZWRhX3RpbWVsYXBzZQoKbGlicmFyeSh0aWR5dGV4dCkKCnJlcGxhY2VfcmVnMSA8LSAiaHR0cHM6Ly90LmNvL1tBLVphLXpdXFxkXSt8IgpyZXBsYWNlX3JlZzIgPC0gImh0dHBzOi8vdC5jby9bQS1aYS16XVxcZF0rfCZhbXA7fCZsdDt8Jmd0O3xSVHxodHRwcyIKcmVwbGFjZV9yZWcgPC0gcGFzdGUwKHJlcGxhY2VfcmVnMSwgcmVwbGFjZV9yZWcyKQp1bm5lc3RfcmVnIDwtICIoW15BLVphLXpfXFxkI0AnXXwnKD8hW0EtWmEtel9cXGQjQF0pKSIKCnRpZHlfdHdlZXRzIDwtIG5lZGFfdGltZWxhcHNlICU+JQogIG11dGF0ZSh0ZXh0ID0gc3RyX3RvX2xvd2VyKHRleHQpKSAlPiUgCiAgbXV0YXRlKHRleHQgPSBzdHJfcmVwbGFjZV9hbGwodGV4dCwgcmVwbGFjZV9yZWcsICIiKSkgJT4lIAogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCwgdG9rZW4gPSAicmVnZXgiLCBwYXR0ZXJuID0gdW5uZXN0X3JlZykKCnRpZHlfdHdlZXRzICU+JSAKICBmaWx0ZXIod29yZCAlaW4lIHdvcmRzX2NhdCkgJT4lIAogIG11dGF0ZShkYXlzX3R3ZWV0ID0gY2FzZV93aGVuKGRheXNfdHdlZXQgPCAwIH4gImJlZm9yZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF5c190d2VldCA+IDAgfiAiYWZ0ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiY2VybyIpKSAlPiUgCiAgZmlsdGVyKGRheXNfdHdlZXQgIT0gImNlcm8iKSAtPiB0aWR5X3dvcmRzCgpuZWRhX2xpd2MgPC0gcmVhZF9yZHMoaGVyZTo6aGVyZSgiZGF0YSIsICJuZWRhX2xpd2NfdHdlbnR5LnJkcyIpKSAlPiUgCiAgc2VsZWN0KC1jcmVhdGVkX2F0X3R3ZWV0KSAlPiUgCiAgZmlsdGVyKGFicyhkYXlzX3R3ZWV0KSA8PSAxNSkKCmBgYAoKIyMjIEZFTUFMRSAKCmBgYHtyIH0KIyBmZW1hbGUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgZmVtYWxlIC0+IDQzCgp3b3Jkc19kaWMgJT4lIAogIGZpbHRlcl9hdCh2YXJzKC14XzEpLCBhbnlfdmFycyguID09IDQzKSkgJT4lIAogIHB1bGwoeF8xKSAtPiB3b3Jkc19mZW1hbGUKCnRpZHlfd29yZHMgJT4lIAogIGZpbHRlcih3b3JkICVpbiUgd29yZHNfZmVtYWxlKSAlPiUgCiAgY291bnQoZGF5c190d2VldCwgd29yZCkgJT4lIAogIG11dGF0ZShnZW5kZXIgPSAidCIpICU+JSAKICBiaW5kX3Jvd3ModGlkeV93b3JkcyAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKHdvcmQgJWluJSB3b3Jkc19mZW1hbGUpICU+JSAKICAgICAgICAgICAgICBjb3VudChnZW5kZXIsIGRheXNfdHdlZXQsIHdvcmQpKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGMoZGF5c190d2VldCwgZ2VuZGVyKSwgdmFsdWVzX2Zyb20gPSBuKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIH5yZXBsYWNlX25hKC4sIDApKSAlPiUgCiAgbXV0YXRlKGNoYW5nZXNfdG90YWwgPSBhZnRlcl90IC0gYmVmb3JlX3QsCiAgICAgICAgIGNoYW5nZXNfZiA9IGFmdGVyX2YgLSBiZWZvcmVfZiwKICAgICAgICAgY2hhbmdlc19tID0gYWZ0ZXJfbSAtIGJlZm9yZV9tLAogICAgICAgICBjaGFuZ2VzX3UgPSBhZnRlcl91IC0gYmVmb3JlX3UpICU+JSAKICBzZWxlY3Qod29yZCwgc3RhcnRzX3dpdGgoImNoYW5nZXMiKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhjaGFuZ2VzX3RvdGFsKSkgLT4gZiAKCmZfdG9wIDwtIGYgJT4lIHRvcF9uKDQsIHd0ID0gY2hhbmdlc190b3RhbCkKZl9ib3R0b20gPC0gZiAlPiUgdG9wX24oLTQsIHd0ID0gY2hhbmdlc190b3RhbCkKCmZfdG9wICU+JSAKICBiaW5kX3Jvd3MoZl9ib3R0b20pICU+JSAKICBndDo6Z3QoKQpgYGAKCiMjIyBSSVNLCgpgYGB7cn0KIyByaXNrIC0+IDg1Cgp3b3Jkc19kaWMgJT4lIAogIGZpbHRlcl9hdCh2YXJzKC14XzEpLCBhbnlfdmFycyguID09IDg1KSkgJT4lIAogIHB1bGwoeF8xKSAtPiB3b3Jkc19yaXNrCgp0aWR5X3dvcmRzICU+JSAKICBmaWx0ZXIod29yZCAlaW4lIHdvcmRzX3Jpc2spICU+JSAKICBjb3VudChkYXlzX3R3ZWV0LCB3b3JkKSAlPiUgCiAgbXV0YXRlKGdlbmRlciA9ICJ0IikgJT4lIAogIGJpbmRfcm93cyh0aWR5X3dvcmRzICU+JSAKICAgICAgICAgICAgICBmaWx0ZXIod29yZCAlaW4lIHdvcmRzX3Jpc2spICU+JSAKICAgICAgICAgICAgICBjb3VudChnZW5kZXIsIGRheXNfdHdlZXQsIHdvcmQpKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGMoZGF5c190d2VldCwgZ2VuZGVyKSwgdmFsdWVzX2Zyb20gPSBuKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIH5yZXBsYWNlX25hKC4sIDApKSAlPiUgCiAgbXV0YXRlKGNoYW5nZXNfdG90YWwgPSBhZnRlcl90IC0gYmVmb3JlX3QsCiAgICAgICAgIGNoYW5nZXNfZiA9IGFmdGVyX2YgLSBiZWZvcmVfZiwKICAgICAgICAgY2hhbmdlc19tID0gYWZ0ZXJfbSAtIGJlZm9yZV9tLAogICAgICAgICBjaGFuZ2VzX3UgPSBhZnRlcl91IC0gYmVmb3JlX3UpICU+JSAKICBzZWxlY3Qod29yZCwgc3RhcnRzX3dpdGgoImNoYW5nZXMiKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhjaGFuZ2VzX3RvdGFsKSkgLT4gZiAKCmZfdG9wIDwtIGYgJT4lIHRvcF9uKDQsIHd0ID0gY2hhbmdlc190b3RhbCkKZl9ib3R0b20gPC0gZiAlPiUgdG9wX24oLTQsIHd0ID0gY2hhbmdlc190b3RhbCkKCmZfdG9wICU+JSAKICBiaW5kX3Jvd3MoZl9ib3R0b20pICU+JSAKICBndDo6Z3QoKQpgYGAKCiMjIyBSRUxJR0lPTgpgYGB7cn0KIyByZWxpZyAtPiAxMTQKCndvcmRzX2RpYyAlPiUgCiAgZmlsdGVyX2F0KHZhcnMoLXhfMSksIGFueV92YXJzKC4gPT0gMTE0KSkgJT4lIAogIHB1bGwoeF8xKSAtPiB3b3Jkc19yZWxpZwoKdGlkeV93b3JkcyAlPiUgCiAgZmlsdGVyKHdvcmQgJWluJSB3b3Jkc19yZWxpZykgJT4lIAogIGNvdW50KGRheXNfdHdlZXQsIHdvcmQpICU+JSAKICBtdXRhdGUoZ2VuZGVyID0gInQiKSAlPiUgCiAgYmluZF9yb3dzKHRpZHlfd29yZHMgJT4lIAogICAgICAgICAgICAgIGZpbHRlcih3b3JkICVpbiUgd29yZHNfcmVsaWcpICU+JSAKICAgICAgICAgICAgICBjb3VudChnZW5kZXIsIGRheXNfdHdlZXQsIHdvcmQpKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGMoZGF5c190d2VldCwgZ2VuZGVyKSwgdmFsdWVzX2Zyb20gPSBuKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIH5yZXBsYWNlX25hKC4sIDApKSAlPiUgCiAgbXV0YXRlKGNoYW5nZXNfdG90YWwgPSBhZnRlcl90IC0gYmVmb3JlX3QsCiAgICAgICAgIGNoYW5nZXNfZiA9IGFmdGVyX2YgLSBiZWZvcmVfZiwKICAgICAgICAgY2hhbmdlc19tID0gYWZ0ZXJfbSAtIGJlZm9yZV9tLAogICAgICAgICBjaGFuZ2VzX3UgPSBhZnRlcl91IC0gYmVmb3JlX3UpICU+JSAKICBzZWxlY3Qod29yZCwgc3RhcnRzX3dpdGgoImNoYW5nZXMiKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhjaGFuZ2VzX3RvdGFsKSkgLT4gZiAKCmZfdG9wIDwtIGYgJT4lIHRvcF9uKDQsIHd0ID0gY2hhbmdlc190b3RhbCkKZl9ib3R0b20gPC0gZiAlPiUgdG9wX24oLTQsIHd0ID0gY2hhbmdlc190b3RhbCkKCmZfdG9wICU+JSAKICBiaW5kX3Jvd3MoZl9ib3R0b20pICU+JSAKICBndDo6Z3QoKQoKYGBgCgojIyBNT05FWQoKYGBge3J9CiMgbW9uZXkgLT4gMTEzCgp3b3Jkc19kaWMgJT4lIAogIGZpbHRlcl9hdCh2YXJzKC14XzEpLCBhbnlfdmFycyguID09IDExMykpICU+JSAKICBwdWxsKHhfMSkgLT4gd29yZHNfbW9uZXkKCnRpZHlfd29yZHMgJT4lIAogIGZpbHRlcih3b3JkICVpbiUgd29yZHNfbW9uZXkpICU+JSAKICBjb3VudChkYXlzX3R3ZWV0LCB3b3JkKSAlPiUgCiAgbXV0YXRlKGdlbmRlciA9ICJ0IikgJT4lIAogIGJpbmRfcm93cyh0aWR5X3dvcmRzICU+JSAKICAgICAgICAgICAgICBmaWx0ZXIod29yZCAlaW4lIHdvcmRzX21vbmV5KSAlPiUgCiAgICAgICAgICAgICAgY291bnQoZ2VuZGVyLCBkYXlzX3R3ZWV0LCB3b3JkKSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjKGRheXNfdHdlZXQsIGdlbmRlciksIHZhbHVlc19mcm9tID0gbikgJT4lIAogIG11dGF0ZV9pZihpcy5udW1lcmljLCB+cmVwbGFjZV9uYSguLCAwKSkgJT4lIAogIG11dGF0ZShjaGFuZ2VzX3RvdGFsID0gYWZ0ZXJfdCAtIGJlZm9yZV90LAogICAgICAgICBjaGFuZ2VzX2YgPSBhZnRlcl9mIC0gYmVmb3JlX2YsCiAgICAgICAgIGNoYW5nZXNfbSA9IGFmdGVyX20gLSBiZWZvcmVfbSwKICAgICAgICAgY2hhbmdlc191ID0gYWZ0ZXJfdSAtIGJlZm9yZV91KSAlPiUgCiAgc2VsZWN0KHdvcmQsIHN0YXJ0c193aXRoKCJjaGFuZ2VzIikpICU+JSAKICBhcnJhbmdlKGRlc2MoY2hhbmdlc190b3RhbCkpIC0+IGYgCgpmX3RvcCA8LSBmICU+JSB0b3Bfbig0LCB3dCA9IGNoYW5nZXNfdG90YWwpCmZfYm90dG9tIDwtIGYgJT4lIHRvcF9uKC00LCB3dCA9IGNoYW5nZXNfdG90YWwpCgpmX3RvcCAlPiUgCiAgYmluZF9yb3dzKGZfYm90dG9tKSAlPiUgCiAgZ3Q6Omd0KCkKCmBgYAoKIyMgQk9EWQpgYGB7cn0KIyBib2R5IC0+IDcxCgp3b3Jkc19kaWMgJT4lIAogIGZpbHRlcl9hdCh2YXJzKC14XzEpLCBhbnlfdmFycyguID09IDExNCkpICU+JSAKICBwdWxsKHhfMSkgLT4gd29yZHNfYm9keQoKdGlkeV93b3JkcyAlPiUgCiAgZmlsdGVyKHdvcmQgJWluJSB3b3Jkc19ib2R5KSAlPiUgCiAgY291bnQoZGF5c190d2VldCwgd29yZCkgJT4lIAogIG11dGF0ZShnZW5kZXIgPSAidCIpICU+JSAKICBiaW5kX3Jvd3ModGlkeV93b3JkcyAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKHdvcmQgJWluJSB3b3Jkc19ib2R5KSAlPiUgCiAgICAgICAgICAgICAgY291bnQoZ2VuZGVyLCBkYXlzX3R3ZWV0LCB3b3JkKSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjKGRheXNfdHdlZXQsIGdlbmRlciksIHZhbHVlc19mcm9tID0gbikgJT4lIAogIG11dGF0ZV9pZihpcy5udW1lcmljLCB+cmVwbGFjZV9uYSguLCAwKSkgJT4lIAogIG11dGF0ZShjaGFuZ2VzX3RvdGFsID0gYWZ0ZXJfdCAtIGJlZm9yZV90LAogICAgICAgICBjaGFuZ2VzX2YgPSBhZnRlcl9mIC0gYmVmb3JlX2YsCiAgICAgICAgIGNoYW5nZXNfbSA9IGFmdGVyX20gLSBiZWZvcmVfbSwKICAgICAgICAgY2hhbmdlc191ID0gYWZ0ZXJfdSAtIGJlZm9yZV91KSAlPiUgCiAgc2VsZWN0KHdvcmQsIHN0YXJ0c193aXRoKCJjaGFuZ2VzIikpICU+JSAKICBhcnJhbmdlKGRlc2MoY2hhbmdlc190b3RhbCkpIC0+IGYgCgpmX3RvcCA8LSBmICU+JSB0b3Bfbig0LCB3dCA9IGNoYW5nZXNfdG90YWwpCmZfYm90dG9tIDwtIGYgJT4lIHRvcF9uKC00LCB3dCA9IGNoYW5nZXNfdG90YWwpCgpmX3RvcCAlPiUgCiAgYmluZF9yb3dzKGZfYm90dG9tKSAlPiUgCiAgZ3Q6Omd0KCkKCmBgYAoKCiMjIENPTU1PTiBXT1JEUyBJTiBUV0VFVFMgQlkgV09SRFMgQ0FURUdPUlk6CgpgYGB7ciB9Cm5lZGFfbGl3Y19nZW5kZXIgJT4lIAogIGZpbHRlcihkYXlzX3R3ZWV0ID49IDApICU+JSAKICBzZWxlY3QoaWRfdHdlZXQsIGlkLCBnZW5kZXIsIGZlbWFsZSwgcmlzaywgcmVsaWcsIGJvZHksIG1vbmV5KSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBmZW1hbGU6bW9uZXkpICU+JSAKICBmaWx0ZXIodmFsdWUgPiAwKSAlPiUgCiAgbGVmdF9qb2luKG5lZGFfbGl3YyAlPiUgCiAgICAgICAgICAgICAgc2VsZWN0KGlkLCBpZF90d2VldCwgdGV4dCkpICU+JSAgCiAgcmVuYW1lKCJjYXRlZ29yeSIgPSBuYW1lKSAlPiUgCiAgbXV0YXRlKHRleHQgPSBzdHJfcmVtb3ZlX2FsbCh0ZXh0LCBwYXR0ZXJuID0gIls6Z3JhcGg6XSso4oCmKSIpKSAlPiUgCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0LCB0b2tlbiA9ICJ0d2VldHMiKSAlPiUgIAogIGZpbHRlcighd29yZCAlaW4lIHN0b3Bfd29yZHMkd29yZCwKICAgICAgICAgIXdvcmQgJWluJSBjKCJkZSIsIDQsICJkYSIsICJsYSIsICJlbiIsICJsZSIsICJsb3MiLCAzKSwKICAgICAgICAgd29yZCAhPSAicnQiLAogICAgICAgICAhd29yZCAlaW4lIHN0cl9yZW1vdmVfYWxsKHN0b3Bfd29yZHMkd29yZCwgIiciKSkgJT4lIAogICMgbXV0YXRlKHdvcmQgPSBjYXNlX3doZW4oY2F0ZWdvcnkgPT0gImZlbWFsZSIgJiB3b3JkICVpbiUgYyh3b3Jkc19mZW1hbGUsCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3b21lbnMiKSB+IE5BX2NoYXJhY3Rlcl8sCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICBjYXRlZ29yeSA9PSAiZmFtaWx5IiAmIHdvcmQgJWluJSBjKHdvcmRzX2ZhbWlseSwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBhcmVudHMiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYnJvdGhlcnMiKX4gTkFfY2hhcmFjdGVyXywKICAjICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5ID09ICJhbngiICYgd29yZCAlaW4lIHdvcmRzX2FueGlldHkgfiBOQV9jaGFyYWN0ZXJfLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IHdvcmQpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYSh3b3JkKSwKICAgICAgICAgd29yZCAhPSAiYW1wIikgJT4lIAogIGNvdW50KGNhdGVnb3J5LCBnZW5kZXIsIHdvcmQsIHNvcnQgPSBUKSAlPiUKICBncm91cF9ieShnZW5kZXIsIGNhdGVnb3J5KSAlPiUgCiAgdG9wX24oMTAsIHd0ID0gbikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoY2F0ZWdvcnksIHdvcmQpLCBuYW1lc19mcm9tID0gZ2VuZGVyLCB2YWx1ZXNfZnJvbSA9IG4pICU+JSAKICBtdXRhdGUoY2F0ZWdvcnkgPSBzdHJfdG9fdGl0bGUoY2F0ZWdvcnkpKSAlPiUgCiAgZ3Q6Omd0KGdyb3VwbmFtZV9jb2wgPSAiY2F0ZWdvcnkiLAogICAgICAgICByb3duYW1lX2NvbCA9ICJ3b3JkIikgICAKICAKYGBgCgo=