Causal Impact

Number of total users:

neda_liwc %>% 
  select(id) %>% 
  distinct() %>% 
  nrow()
## [1] 1746
Word Category Relative Eff.(%) P Value
Female 17.418 0.001
Anx 7.566 0.002
Family 6.452 0.005
Money 5.991 0.002
Relig 5.209 0.045
Achiev 3.813 0.011
They 3.397 0.034
Negate 2.889 0.003
Health 2.526 0.004
Power 2.458 0.010
Negemo 2.066 0.037
Informal 1.116 0.038
Ipron -1.476 0.015
See -2.036 0.025
You -2.238 0.034
Differ -2.694 0.006
Posemo -3.277 0.001
Tentat -3.347 0.001
Shehe -7.042 0.020
Affiliation -7.167 0.003
Friend -16.459 0.041

CAUSAL IMPACT BY GENDER

Number of users by gender (1746 total):

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

Number of users in the baseline (2991 total):

baseline_liwc_gender %>% 
  select(id, gender) %>% 
  distinct() %>% 
  count(gender)
## # A tibble: 3 x 2
##   gender     n
##   <chr>  <int>
## 1 f        855
## 2 m        748
## 3 u       1388
baseline_liwc_gender %>% 
  select(-text, -created_at, -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, -name, -name_proc) %>% 
  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
Female 13.112 24.294 23.987 0.001 0.001 0.001
Anx 13.005 -2.704 10.903 0.001 0.283 0.001
Family 6.994 4.204 15.167 0.003 0.092 0.001
They 5.827 1.555 0.672 0.010 0.330 0.415
Achiev 5.153 -2.931 4.033 0.018 0.078 0.030
Money 4.866 14.027 4.088 0.002 0.002 0.104
Negate 4.449 -6.645 6.511 0.001 0.025 0.008
Health 4.246 9.044 -2.452 0.010 0.001 0.132
Negemo 3.94 -3.356 0.572 0.001 0.055 0.388
See 2.013 0.151 -7.928 0.146 0.485 0.001
Power 1.014 1.295 4.504 0.253 0.213 0.001
Relig 0.745 8.26 12.547 0.426 0.079 0.012
Informal -0.048 3.212 0.702 0.473 0.006 0.192
Ipron -0.233 -3.002 -1.231 0.401 0.026 0.111
Differ -0.539 -5.58 -0.83 0.340 0.006 0.224
Tentat -0.93 -3.098 -5.979 0.233 0.050 0.001
You -3.067 1.011 -2.898 0.014 0.249 0.046
Posemo -3.119 -7.538 -1.434 0.001 0.001 0.099
Affiliation -5.861 -8.878 -6.936 0.003 0.001 0.011
Shehe -7.875 -1.764 -4.549 0.038 0.384 0.096
Friend -11.06 -19.113 -19.873 0.135 0.002 0.054

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.rds")) %>% 
  distinct() %>% 
  filter(created_at_tweet >= ymd("2018-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"))

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

neda_timelapse %>% 
  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.rds")) %>% 
  select(-created_at_tweet) %>% 
  filter(abs(days_tweet) <= 15)

FEMALE CATEGORY

# 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 2117 903 403 811
her 320 251 -18 87
she 228 296 -30 -38
woman 207 90 37 80
gf -30 -20 -8 -2
wife -78 -37 -43 2
queen -96 1 -32 -65
lady -158 -115 -22 -21

FAMILY

words_dic %>% 
  filter_at(vars(-x_1), any_vars(. == 41)) %>% 
  pull(x_1) -> words_family

tidy_words %>% 
  filter(word %in% words_family) %>% 
  count(days_tweet, word) %>% 
  mutate(gender = "t") %>% 
  bind_rows(tidy_words %>% 
              filter(word %in% words_family) %>% 
              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
ma 132 52 49 31
family 122 97 11 14
daughter 115 36 26 53
families 88 47 21 20
mama -19 -24 -2 7
pa -19 -10 7 -16
daddy -23 -10 -6 -7
bro -63 7 30 -100
wife -78 -37 -43 2

ANXIETY

# anxiety -----------------------------------------------------------------
# anxiety -> 33

words_dic %>% 
  filter_at(vars(-x_1), any_vars(. == 33)) %>% 
  pull(x_1) -> words_anxiety

tidy_words %>% 
  filter(word %in% words_anxiety) %>% 
  count(days_tweet, word) %>% 
  mutate(gender = "t") %>% 
  bind_rows(tidy_words %>% 
              filter(word %in% words_anxiety) %>% 
              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
risk 190 16 117 57
stress 78 40 12 26
upset 73 32 13 28
worried 70 33 14 23
confuse -10 -6 1 -5
horrible -11 -5 3 -9
doubt -21 -11 -1 -9
scared -31 16 -13 -34

COMMON WORDS IN TWEETS BY WORDS CATEGORY:

neda_liwc_gender %>% 
  filter(days_tweet >= 0) %>% 
  select(id_tweet, id, gender, family, female, anx) %>% 
  pivot_longer(cols = family:anx) %>% 
  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")   
f u m
Female
day 521 453 232
love 410 276 135
happy 333 340 145
time 311 219 123
international 281 245 130
people 271 210 91
black 239 202 99
notre NA 227 NA
life 194 146 97
white 184 NA NA
#internationalwomensday 165 180 NA
amazing NA NA 107
world NA NA 105
Anx
love 138 362 152
people 351 287 105
struggling 243 218 NA
feel 168 124 NA
time 159 NA NA
struggle 158 NA NA
@swampmusicinfo NA 157 70
mental 152 123 NA
@laurarjacobs NA 148 NA
laura NA 145 65
jacobs NA 135 NA
life 124 NA NA
depression 121 NA NA
eating 119 NA NA
ft NA 117 NA
sixty NA NA 92
$safe NA NA 90
cse NA NA 90
solutions NA NA 90
news NA NA 86
@financialbuzz NA NA 84
Family
love 258 160 78
day 219 148 90
people 203 167 54
kids 202 153 NA
time 197 126 74
apologize NA 170 NA
ur NA 170 NA
children 157 159 NA
friends 142 NA 63
women 136 NA NA
child 128 NA NA
follow NA 126 NA
pregnant 123 NA NA
half NA 120 NA
life NA 120 86
fathersrightshq NA NA 52
happy NA NA 49
married NA NA 45
school NA NA 45
LS0tCnRpdGxlOiAiQ2F1c2FsIEltcGFjdCIgCmNsZWFuOiB0cnVlCm91dHB1dDoKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogZmFsc2UKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkKCnhmdW46OnBrZ19hdHRhY2goInRpZHl2ZXJzZSIsICJsdWJyaWRhdGUiLCAia2FibGVFeHRyYSIpCgp0aGVtZV9zZXQodGhlbWVfbGluZWRyYXcoKSkKYGBgCgojIyBDYXVzYWwgSW1wYWN0IAoKYGBge3IgZWNobz1GQUxTRX0KYmFzZWxpbmVfbGl3YyA8LSByZWFkX3JkcyhoZXJlOjpoZXJlKCJkYXRhIiwgImJhc2VsaW5lX2xpd2MucmRzIikpCgpuZWRhX2xpd2MgPC0gcmVhZF9yZHMoaGVyZTo6aGVyZSgiZGF0YSIsICJuZWRhX2xpd2MucmRzIikpICU+JSAKICBzZWxlY3QoLXRleHQsIC1jcmVhdGVkX2F0X3R3ZWV0KSAlPiUgCiAgZmlsdGVyKGFicyhkYXlzX3R3ZWV0KSA8PSAxNSkKICAKCnNlbF9jYXQgPC0gYygKICAiaSIsIndlIiwieW91Iiwic2hlaGUiLCJ0aGV5IiwiaXByb24iLCJuZWdhdGUiLCJjb21wYXJlIiwicG9zZW1vIiwibmVnZW1vIiwiYW54IiwiYW5nZXIiLCJzYWQiLCJzb2NpYWwiLCJmYW1pbHkiLCJmcmllbmQiLCJmZW1hbGUiLCJtYWxlIiwiaW5zaWdodCIsImNhdXNlIiwiZGlzY3JlcCIsInRlbnRhdCIsImNlcnRhaW4iLCJkaWZmZXIiLCJzZWUiLCJoZWFyIiwiZmVlbCIsImJvZHkiLCJoZWFsdGgiLCJzZXh1YWwiLCJpbmdlc3QiLCJhZmZpbGlhdGlvbiIsImFjaGlldiIsInBvd2VyIiwicmV3YXJkIiwicmlzayIsImZvY3VzcGFzdCIsImZvY3VzcHJlc2VudCIsImZvY3VzZnV0dXJlIiwicmVsYXRpdiIsIndvcmsiLCJsZWlzdXJlIiwiaG9tZSIsIm1vbmV5IiwicmVsaWciLCJkZWF0aCIsImluZm9ybWFsIiwic3dlYXIiLCJhc3NlbnQiLCJub25mbHUiLCJmaWxsZXIiCikKYGBgCgpOdW1iZXIgb2YgdG90YWwgdXNlcnM6CmBgYHtyfQpuZWRhX2xpd2MgJT4lIAogIHNlbGVjdChpZCkgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIG5yb3coKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CmJhc2VsaW5lX2xpd2MgJT4lIAogIHNlbGVjdCgtdGV4dCwgLWNyZWF0ZWRfYXQsIC1pZF90d2VldCkgJT4lIAogIGdyb3VwX2J5KGRheXNfdHdlZXQsIGlkKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3QoLWlkKSAlPiUgCiAgZ3JvdXBfYnkoZGF5c190d2VldCkgJT4lIAogIHN1bW1hcmlzZV9hbGwobWVhbikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBmdW46ZmlsbGVyLCBuYW1lc190byA9ICJjYXRlZyIsIHZhbHVlc190byA9ICJ2YWx1ZXNfYmFzZWxpbmUiKSAtPiBjaV9iYXNlbGluZQoKbmVkYV9saXdjICU+JSAKICBzZWxlY3QoLWlkX3R3ZWV0KSAlPiUgCiAgZ3JvdXBfYnkoZGF5c190d2VldCwgaWQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdCgtaWQpICU+JSAKICBncm91cF9ieShkYXlzX3R3ZWV0KSAlPiUgCiAgc3VtbWFyaXNlX2FsbChtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBwaXZvdF9sb25nZXIoLWRheXNfdHdlZXQsIG5hbWVzX3RvID0gImNhdGVnIiwgdmFsdWVzX3RvID0gInZhbHVlc19uZWRhIikgLT4gY2lfbmVkYV9saXdjIAogIApwcmVfcGVyaW9kIDwtIGMoMSwgMTYpCnBvc3RfcGVyaW9kIDwtIGMoMTcsIDMxKQoKY2lfYmFzZWxpbmUgJT4lIAogIGlubmVyX2pvaW4oY2lfbmVkYV9saXdjKSAtPiBkX3NlY29uZAoKZF9zZWNvbmQgJT4lIAogIHNlbGVjdChjYXRlZywgdmFsdWVzX25lZGEsIHZhbHVlc19iYXNlbGluZSkgJT4lIAogIG5lc3QoZGF0YSA9IC0gY2F0ZWcpICU+JSAKICBtdXRhdGUobW9kID0gbWFwKGRhdGEsIH5DYXVzYWxJbXBhY3Q6OkNhdXNhbEltcGFjdCguLCBwcmVfcGVyaW9kLCBwb3N0X3BlcmlvZCkpKSAtPiBjaQogIApjaSAlPiUgCiAgbXV0YXRlKHN1bW1hcnlfbW9kID0gbWFwKG1vZCwgInN1bW1hcnkiKSkgJT4lIAogIGZpbHRlcighbWFwX2xnbChzdW1tYXJ5X21vZCwgaXMubnVsbCkpIC0+IGNpX3Jlc3VsIAoKY2lfcmVzdWwgJT4lIAogIG11dGF0ZShwID0gbWFwKHN1bW1hcnlfbW9kLCAicCIpKSAlPiUgCiAgbXV0YXRlKHAgPSBtYXBfZGJsKHAsIDEpKSAlPiUgCiAgZmlsdGVyKHAgPCAwLjA1KSAlPiUgCiAgbXV0YXRlKHJlbGF0aXZlX2VmZmVjdCA9IG1hcChzdW1tYXJ5X21vZCwgIlJlbEVmZmVjdCIpKSAlPiUgCiAgbXV0YXRlKHJlbGF0aXZlX2VmZmVjdCA9IG1hcF9kYmwocmVsYXRpdmVfZWZmZWN0LCAyKSktPiBzaWdfY2F0CgpzaWdfY2F0ICU+JSAKICBmaWx0ZXIoY2F0ZWcgJWluJSBzZWxfY2F0KSAtPiBzaWdfY2F0CgpjYXRlZ29yaWVzX2luX2dlbmRlciA8LSBzaWdfY2F0ICU+JSBwdWxsKGNhdGVnKQoKc2lnX2NhdCAlPiUgCiAgYXJyYW5nZShkZXNjKHJlbGF0aXZlX2VmZmVjdCkpICU+JSAKICBzZWxlY3QoY2F0ZWcsIHNlY29uZF9yZWxhdGl2ZV9lZmZlY3QgPSByZWxhdGl2ZV9lZmZlY3QsIHBfc2Vjb25kID0gcCkgLT4gc2Vjb25kX2FwCgpzZWNvbmRfYXAgJT4lIAogIG11dGF0ZShjYXRlZyA9IHN0cl90b190aXRsZShjYXRlZykpICU+JSAKICBtdXRhdGVfYXQodmFycyhzZWNvbmRfcmVsYXRpdmVfZWZmZWN0KSwgfi4qMTAwKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIH5yb3VuZCguLCBkaWdpdHMgPSAzKSkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKHNlY29uZF9yZWxhdGl2ZV9lZmZlY3QpLCBmdW5jdGlvbih4KXsKICAgIGNlbGxfc3BlYyh4LCAiaHRtbCIsIGNvbG9yID0gc3BlY19jb2xvcih4KSwgYm9sZCA9IFQpCiAgfSkgJT4lIAogIGthYmxlKCJodG1sIiwgZXNjYXBlID0gRiwKICAgICAgICBhbGlnbiA9ICJscnIiLAogICAgICAgIGNvbC5uYW1lcyA9IGMoIldvcmQgQ2F0ZWdvcnkiLCAiUmVsYXRpdmUgRWZmLiglKSIsCiAgICAgICAgICAgICAgICAgICAgICAiUCBWYWx1ZSIpKSAlPiUgCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRkFMU0UpCmBgYAoKIyMgQ0FVU0FMIElNUEFDVCBCWSBHRU5ERVIKCmBgYHtyIGVjaG89RkFMU0V9CmJhc2VsaW5lX2xpd2NfZ2VuZGVyIDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJiYXNlbGluZV9saXdjX2dlbmRlci5yZHMiKSkKCm5lZGFfbGl3Y19nZW5kZXIgPC0gcmVhZF9yZHMoaGVyZTo6aGVyZSgiZGF0YSIsICJuZWRhX2xpd2NfZ2VuZGVyLnJkcyIpKSAlPiUgCiAgIyBzZWxlY3QoLXRleHQsIC1jcmVhdGVkX2F0X3R3ZWV0KSAlPiUgCiAgZmlsdGVyKGFicyhkYXlzX3R3ZWV0KSA8PSAxNSkKCnNlbF9jYXQgPC0gYygKICAiaSIsIndlIiwieW91Iiwic2hlaGUiLCJ0aGV5IiwiaXByb24iLCJuZWdhdGUiLCJjb21wYXJlIiwicG9zZW1vIiwibmVnZW1vIiwiYW54IiwiYW5nZXIiLCJzYWQiLCJzb2NpYWwiLCJmYW1pbHkiLCJmcmllbmQiLCJmZW1hbGUiLCJtYWxlIiwiaW5zaWdodCIsImNhdXNlIiwiZGlzY3JlcCIsInRlbnRhdCIsImNlcnRhaW4iLCJkaWZmZXIiLCJzZWUiLCJoZWFyIiwiZmVlbCIsImJvZHkiLCJoZWFsdGgiLCJzZXh1YWwiLCJpbmdlc3QiLCJhZmZpbGlhdGlvbiIsImFjaGlldiIsInBvd2VyIiwicmV3YXJkIiwicmlzayIsImZvY3VzcGFzdCIsImZvY3VzcHJlc2VudCIsImZvY3VzZnV0dXJlIiwicmVsYXRpdiIsIndvcmsiLCJsZWlzdXJlIiwiaG9tZSIsIm1vbmV5IiwicmVsaWciLCJkZWF0aCIsImluZm9ybWFsIiwic3dlYXIiLCJhc3NlbnQiLCJub25mbHUiLCJmaWxsZXIiCikKYGBgCgpOdW1iZXIgb2YgdXNlcnMgYnkgZ2VuZGVyICgxNzQ2IHRvdGFsKToKYGBge3J9Cm5lZGFfbGl3Y19nZW5kZXIgJT4lIAogIHNlbGVjdChpZCwgZ2VuZGVyKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgY291bnQoZ2VuZGVyKQpgYGAKCk51bWJlciBvZiB1c2VycyBpbiB0aGUgYmFzZWxpbmUgKDI5OTEgdG90YWwpOgpgYGB7cn0KYmFzZWxpbmVfbGl3Y19nZW5kZXIgJT4lIAogIHNlbGVjdChpZCwgZ2VuZGVyKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgY291bnQoZ2VuZGVyKQpgYGAKCmBgYHtyIH0KYmFzZWxpbmVfbGl3Y19nZW5kZXIgJT4lIAogIHNlbGVjdCgtdGV4dCwgLWNyZWF0ZWRfYXQsIC1pZF90d2VldCwgLW5hbWUpICU+JSAKICBncm91cF9ieShnZW5kZXIsIGlkLCBkYXlzX3R3ZWV0KSAlPiUgCiAgc3VtbWFyaXNlX2FsbChtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3QoLWlkKSAlPiUgCiAgZ3JvdXBfYnkoZ2VuZGVyLCBkYXlzX3R3ZWV0KSAlPiUgCiAgc3VtbWFyaXNlX2FsbChtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGZ1bjpmaWxsZXIsIG5hbWVzX3RvID0gImNhdGVnIiwgdmFsdWVzX3RvID0gInZhbHVlc19iYXNlbGluZSIpIC0+IGNpX2Jhc2VsaW5lCgpuZWRhX2xpd2NfZ2VuZGVyICU+JSAKICBzZWxlY3QoLWlkX3R3ZWV0LCAtbmFtZSwgLW5hbWVfcHJvYykgJT4lIAogIGdyb3VwX2J5KGdlbmRlciwgaWQsIGRheXNfdHdlZXQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdCgtaWQpICU+JSAKICBncm91cF9ieShnZW5kZXIsIGRheXNfdHdlZXQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHBpdm90X2xvbmdlcihmdW46ZmlsbGVyLCBuYW1lc190byA9ICJjYXRlZyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidmFsdWVzX25lZGEiKSAtPiBjaV9uZWRhX2xpd2MgCgpwcmVfcGVyaW9kIDwtIGMoMSwgMTYpCnBvc3RfcGVyaW9kIDwtIGMoMTcsIDMxKQoKY2lfYmFzZWxpbmUgJT4lIAogIGZ1bGxfam9pbihjaV9uZWRhX2xpd2MpIC0+IGRfc2Vjb25kCgpkX3NlY29uZCAlPiUgCiAgIyBjb3VudChnZW5kZXIsIGRheXNfdHdlZXQpICU+JSAKICAjIHZpZXcoKQogICMgdmlldygpCiAgIyBzZWxlY3QoY2F0ZWcsIHZhbHVlc19uZWRhLCB2YWx1ZXNfYmFzZWxpbmUpICU+JSAKICAjIG5lc3QoZGF0YSA9IC0gY2F0ZWcpICU+JSAKICBzZWxlY3QoZ2VuZGVyLCBjYXRlZywgdmFsdWVzX25lZGEsIHZhbHVlc19iYXNlbGluZSkgJT4lCiAgIyBmaWx0ZXIoZ2VuZGVyID09ICJtIikgJT4lIHZpZXcoKQogIGdyb3VwX2J5KGNhdGVnLCBnZW5kZXIpICU+JSAKICBuZXN0KCkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KGdlbmRlciwgY2F0ZWcsIGRhdGEpICU+JSAKICBtdXRhdGUobW9kID0gbWFwKGRhdGEsIH5DYXVzYWxJbXBhY3Q6OkNhdXNhbEltcGFjdCguLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVfcGVyaW9kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc3RfcGVyaW9kKSkpIC0+IGNpCiAgCmNpICU+JSAKICBtdXRhdGUoc3VtbWFyeV9tb2QgPSBtYXAobW9kLCAic3VtbWFyeSIpKSAlPiUgCiAgZmlsdGVyKCFtYXBfbGdsKHN1bW1hcnlfbW9kLCBpcy5udWxsKSkgLT4gY2lfcmVzdWwgCgpjaV9yZXN1bCAlPiUgCiAgbXV0YXRlKHAgPSBtYXAoc3VtbWFyeV9tb2QsICJwIikpICU+JSAKICBtdXRhdGUocCA9IG1hcF9kYmwocCwgMSkpICU+JSAKICBmaWx0ZXIoY2F0ZWcgJWluJSBjYXRlZ29yaWVzX2luX2dlbmRlcikgJT4lIAogIG11dGF0ZShyZWxhdGl2ZV9lZmZlY3QgPSBtYXAoc3VtbWFyeV9tb2QsICJSZWxFZmZlY3QiKSkgJT4lIAogIG11dGF0ZShyZWxhdGl2ZV9lZmZlY3QgPSBtYXBfZGJsKHJlbGF0aXZlX2VmZmVjdCwgMikpLT4gc2lnX2NhdAoKIyBzaWdfY2F0ICU+JSAKIyAgIGZpbHRlcihjYXRlZyAlaW4lIHNlbF9jYXQpIC0+IHNpZ19jYXQKCnNpZ19jYXQgJT4lIAogIGFycmFuZ2UoZ2VuZGVyLCBkZXNjKHJlbGF0aXZlX2VmZmVjdCkpICU+JSAKICBzZWxlY3QoZ2VuZGVyLCBjYXRlZywgCiAgICAgICAgIHNlY29uZF9yZWxhdGl2ZV9lZmZlY3QgPSByZWxhdGl2ZV9lZmZlY3QsIHBfc2Vjb25kID0gcCkgLT4gc2Vjb25kX2FwCgpzZWNvbmRfYXAgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjYXRlZywgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBjKHNlY29uZF9yZWxhdGl2ZV9lZmZlY3QsIHBfc2Vjb25kKSwKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gZ2VuZGVyKSAlPiUgCiAgbXV0YXRlKGNhdGVnID0gc3RyX3RvX3RpdGxlKGNhdGVnKSkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJzZWNvbmQiKSksIH4uKjEwMCkgJT4lIAogIG11dGF0ZV9pZihpcy5udW1lcmljLCB+cm91bmQoLiwgZGlnaXRzID0gMykpICU+JSAKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgic2Vjb25kIikpLCBmdW5jdGlvbih4KXsKICAgIGNlbGxfc3BlYyh4LCAiaHRtbCIsIGNvbG9yID0gc3BlY19jb2xvcih4KSwgYm9sZCA9IFQpCiAgfSkgJT4lIAogIGthYmxlKCJodG1sIiwgZXNjYXBlID0gRiwKICAgICAgICBhbGlnbiA9ICJscnIiLAogICAgICAgIGNvbC5uYW1lcyA9IGMoIldvcmQgQ2F0ZWdvcnkiLCAiRkVNQUxFIFJlbGF0aXZlIEVmZi4oJSkiLAogICAgICAgICAgICAgICAgICAgICAgIk1BTEUgUmVsYXRpdmUgRWZmLiglKSIsCiAgICAgICAgICAgICAgICAgICAgICAiVU5LTk9XTiBSZWxhdGl2ZSBFZmYuKCUpIiwKICAgICAgICAgICAgICAgICAgICAgICJGRU1BTEUgUCBWYWx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAiTUFMRSBQIFZhbHVlIiwKICAgICAgICAgICAgICAgICAgICAgICJVTktOT1dOIFAgVmFsdWUiKSkgJT4lICAKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkKYGBgCgojIyBXb3JkcyBpbnNpZGUgY2F0ZWc6CgpUaGUgdGFibGVzIGJlbG93IGNvbnRhaW4gdGhlIGNoYW5nZXMgZm9yIHRoZSA0IG1vc3QgY2hhbmdlZCB3b3JkcyAocG9zaXRpdmUgYW5kIG5lZ2F0aXZlKSB3aXRoaW4gZWFjaCBvZiB0aGUgY2F0ZWdvcmllcy4gVGhlIGZpcnN0IGNvbHVtbiBpcyB0aGUgc3BlY2lmaWMgd29yZC4gQ2hhbmdlc190b3RhbCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSAiYmVmb3JlIiBhbmQgImFmdGVyIiBmcmVxdWVuY3kgb2YgYWxsIHVzZXJzLiBDaGFuZ2VzX2Ygc2FtZSBhcyBDaGFuZ2VzX3RvdGFsIGJ1dCBmb3IgZmVtYWxlIHVzZXJzLCBDaGFuZ2VzX20gZm9yIG1hbGUgdXNlcnMgYW5kIENoYW5nZXNfdSBmb3IgdW5rbm93biB1c2Vycy4KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKCnJlYWRfZGVsaW0oaGVyZTo6aGVyZSgiZGF0YSIsICJsaXdjIiwgIkxJV0MyMDE1X0VuZ2xpc2hfRmxhdC5kaWMiKSwKICAgICAgICAgICBkZWxpbSA9ICJcdCIsIHNraXAgPSAxLCBjb2xfbmFtZXMgPSBjKCJudW1iZXIiLCAibmFtZSIpLCAKICAgICAgICAgICBuX21heCA9IDczKSAtPiBjYXRlZ29yaWVzX25hbWUgCgpyZWFkX3RzdihoZXJlOjpoZXJlKCJkYXRhIiwgImxpd2MiLCAiTElXQzIwMTVfRW5nbGlzaF9GbGF0LmRpYyIpLAogICAgICAgICBza2lwID0gNzUsIGNvbF9uYW1lcyA9IHBhc3RlMChjKCJ4IiksIGMoIl8iKSwgMToxMSksCiAgICAgICAgIGd1ZXNzX21heCA9IDYwMDAsIGNvbF90eXBlcyA9ICJjY2NjY2NjY2NjYyIpICU+JSAKICBtdXRhdGUoeF8xID0gc3RyX3JlbW92ZSh4XzEsICJcXCoiKSkgLT4gd29yZHNfZGljCgpjYXRlZ29yaWVzX25hbWUgJT4lIAogIGZpbHRlcihuYW1lICVpbiUgYygiZmVtYWxlIiwgImZhbWlseSIsICJhbngiLCAic2hlaGUiLCAiYWZmaWxpYXRpb24iLCAiZnJpZW5kIikpICU+JSAKICBwdWxsKG51bWJlcikgLT4gbnVtYmVyX3RvcF9jYXRlZwoKd29yZHNfZGljICU+JSAKICBmaWx0ZXJfYXQodmFycygteF8xKSwgYW55X3ZhcnMoLiAlaW4lIG51bWJlcl90b3BfY2F0ZWcpKSAlPiUgIAogIHB1bGwoeF8xKSAtPiB3b3Jkc19jYXQKCgojIG5lZGFfdGltZWxhcHNlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmxpYnJhcnkobHVicmlkYXRlKQoKbmVkYV9oaXN0IDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGEiLCAiTkVEQV9oaXN0b3JpY2FsLnJkcyIpKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgZmlsdGVyKGNyZWF0ZWRfYXRfdHdlZXQgPj0geW1kKCIyMDE4LTAzLTAxIikpICU+JSAKICBtdXRhdGUodGV4dCA9IHN0cl90b19sb3dlcih0ZXh0KSwKICAgICAgICAgbmVkYV9yZWxhdGVkID0gc3RyX2RldGVjdCh0ZXh0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIiNuZWRhd2FyZW5lc3N8I2NvbWVhc3lvdWFyZXxAbmVkYXN0YWZmIikpIAoKZ2VuZGVyX291dHB1dCA8LSByZWFkX3RzdihoZXJlOjpoZXJlKCJkYXRhIiwgImdlbmRlcl9leHRyYWN0b3IiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuZWRhX2xpd2NfZ2VuZGVyX291dHB1dC50c3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjKCJpZCIsICJuYW1lIiwgIm5hbWVfcHJvYyIsICJnZW5kZXIiKSkKCmZpcnN0X3R3ZWV0IDwtIG5lZGFfaGlzdCAlPiUgCiAgc2VsZWN0KGNyZWF0ZWRfYXRfdHdlZXQsIHRleHQsIGlkLCBpZF90d2VldCwgbmVkYV9yZWxhdGVkKSAlPiUgCiAgZmlsdGVyKG5lZGFfcmVsYXRlZCkgJT4lIAogIGFycmFuZ2UoY3JlYXRlZF9hdF90d2VldCkgJT4lIAogIGdyb3VwX2J5KGlkKSAlPiUgCiAgc2xpY2UoMSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KGNlcm9fZGF0ZSA9IGNyZWF0ZWRfYXRfdHdlZXQsIGlkKSAlPiUgCiAgZmlsdGVyKGNlcm9fZGF0ZSA+PSB5bWQoIjIwMTktMDEtMDEiKSkKCm5lZGFfY2hhbmdlIDwtIG5lZGFfaGlzdCAlPiUgCiAgc2VsZWN0KGlkX3R3ZWV0LCB0ZXh0LCBjcmVhdGVkX2F0X3R3ZWV0LCBpZCkgJT4lIAogIGlubmVyX2pvaW4oZmlyc3RfdHdlZXQpICU+JSAKICBtdXRhdGUoZGF5c190d2VldCA9IGludGVydmFsKHN0YXJ0ID0gY2Vyb19kYXRlLCBlbmQgPSBjcmVhdGVkX2F0X3R3ZWV0KSwKICAgICAgICAgZGF5c190d2VldCA9IHJvdW5kKHRpbWVfbGVuZ3RoKGRheXNfdHdlZXQsIHVuaXQgPSAiZGF5cyIpKSkgJT4lIAogIHNlbGVjdCgtY2Vyb19kYXRlKSAlPiUgCiAgZmlsdGVyKGRheXNfdHdlZXQgPj0gLTE1LCBkYXlzX3R3ZWV0IDw9IDE1KQoKbmVkYV90aW1lbGFwc2UgPC0gbmVkYV9jaGFuZ2UgJT4lCiAgY291bnQoaWQsIGJlZm9yZV9hZnRlciA9IHNpZ24oZGF5c190d2VldCksIHNvcnQgPSBUKSAlPiUgCiAgbXV0YXRlKGJlZm9yZV9hZnRlciA9IGNhc2Vfd2hlbihiZWZvcmVfYWZ0ZXIgPT0gLTEgfiAiYmVmb3JlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlZm9yZV9hZnRlciA9PSAxIH4gImFmdGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiY2VybyIpKSAlPiUgCiAgcGl2b3Rfd2lkZXIodmFsdWVzX2Zyb20gPSBuLCBuYW1lc19mcm9tID0gYmVmb3JlX2FmdGVyKSAlPiUgCiAgZmlsdGVyKGJlZm9yZSA+PSAxNSAmIGFmdGVyID49IDE1KSAlPiUgCiAgc2VsZWN0KC1jZXJvKSAlPiUgCiAgc2VtaV9qb2luKHggPSBuZWRhX2NoYW5nZSwgeSA9IC4pCgpuZWRhX3RpbWVsYXBzZSAlPiUgCiAgaW5uZXJfam9pbihnZW5kZXJfb3V0cHV0KSAtPiBuZWRhX3RpbWVsYXBzZQoKbGlicmFyeSh0aWR5dGV4dCkKCnJlcGxhY2VfcmVnMSA8LSAiaHR0cHM6Ly90LmNvL1tBLVphLXpdXFxkXSt8IgpyZXBsYWNlX3JlZzIgPC0gImh0dHBzOi8vdC5jby9bQS1aYS16XVxcZF0rfCZhbXA7fCZsdDt8Jmd0O3xSVHxodHRwcyIKcmVwbGFjZV9yZWcgPC0gcGFzdGUwKHJlcGxhY2VfcmVnMSwgcmVwbGFjZV9yZWcyKQp1bm5lc3RfcmVnIDwtICIoW15BLVphLXpfXFxkI0AnXXwnKD8hW0EtWmEtel9cXGQjQF0pKSIKCnRpZHlfdHdlZXRzIDwtIG5lZGFfdGltZWxhcHNlICU+JQogIG11dGF0ZSh0ZXh0ID0gc3RyX3RvX2xvd2VyKHRleHQpKSAlPiUgCiAgbXV0YXRlKHRleHQgPSBzdHJfcmVwbGFjZV9hbGwodGV4dCwgcmVwbGFjZV9yZWcsICIiKSkgJT4lIAogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCwgdG9rZW4gPSAicmVnZXgiLCBwYXR0ZXJuID0gdW5uZXN0X3JlZykKCnRpZHlfdHdlZXRzICU+JSAKICBmaWx0ZXIod29yZCAlaW4lIHdvcmRzX2NhdCkgJT4lIAogIG11dGF0ZShkYXlzX3R3ZWV0ID0gY2FzZV93aGVuKGRheXNfdHdlZXQgPCAwIH4gImJlZm9yZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF5c190d2VldCA+IDAgfiAiYWZ0ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiY2VybyIpKSAlPiUgCiAgZmlsdGVyKGRheXNfdHdlZXQgIT0gImNlcm8iKSAtPiB0aWR5X3dvcmRzCgpuZWRhX2xpd2MgPC0gcmVhZF9yZHMoaGVyZTo6aGVyZSgiZGF0YSIsICJuZWRhX2xpd2MucmRzIikpICU+JSAKICBzZWxlY3QoLWNyZWF0ZWRfYXRfdHdlZXQpICU+JSAKICBmaWx0ZXIoYWJzKGRheXNfdHdlZXQpIDw9IDE1KQoKYGBgCgojIyMgRkVNQUxFIENBVEVHT1JZCgpgYGB7cn0KIyBmZW1hbGUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgZmVtYWxlIC0+IDQzCgp3b3Jkc19kaWMgJT4lIAogIGZpbHRlcl9hdCh2YXJzKC14XzEpLCBhbnlfdmFycyguID09IDQzKSkgJT4lIAogIHB1bGwoeF8xKSAtPiB3b3Jkc19mZW1hbGUKCnRpZHlfd29yZHMgJT4lIAogIGZpbHRlcih3b3JkICVpbiUgd29yZHNfZmVtYWxlKSAlPiUgCiAgY291bnQoZGF5c190d2VldCwgd29yZCkgJT4lIAogIG11dGF0ZShnZW5kZXIgPSAidCIpICU+JSAKICBiaW5kX3Jvd3ModGlkeV93b3JkcyAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKHdvcmQgJWluJSB3b3Jkc19mZW1hbGUpICU+JSAKICAgICAgICAgICAgICBjb3VudChnZW5kZXIsIGRheXNfdHdlZXQsIHdvcmQpKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGMoZGF5c190d2VldCwgZ2VuZGVyKSwgdmFsdWVzX2Zyb20gPSBuKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIH5yZXBsYWNlX25hKC4sIDApKSAlPiUgCiAgbXV0YXRlKGNoYW5nZXNfdG90YWwgPSBhZnRlcl90IC0gYmVmb3JlX3QsCiAgICAgICAgIGNoYW5nZXNfZiA9IGFmdGVyX2YgLSBiZWZvcmVfZiwKICAgICAgICAgY2hhbmdlc19tID0gYWZ0ZXJfbSAtIGJlZm9yZV9tLAogICAgICAgICBjaGFuZ2VzX3UgPSBhZnRlcl91IC0gYmVmb3JlX3UpICU+JSAKICBzZWxlY3Qod29yZCwgc3RhcnRzX3dpdGgoImNoYW5nZXMiKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhjaGFuZ2VzX3RvdGFsKSkgLT4gZiAKCmZfdG9wIDwtIGYgJT4lIHRvcF9uKDQsIHd0ID0gY2hhbmdlc190b3RhbCkKZl9ib3R0b20gPC0gZiAlPiUgdG9wX24oLTQsIHd0ID0gY2hhbmdlc190b3RhbCkKCmZfdG9wICU+JSAKICBiaW5kX3Jvd3MoZl9ib3R0b20pICU+JSAKICBndDo6Z3QoKQpgYGAKCiMjIyBGQU1JTFkKCmBgYHtyfQp3b3Jkc19kaWMgJT4lIAogIGZpbHRlcl9hdCh2YXJzKC14XzEpLCBhbnlfdmFycyguID09IDQxKSkgJT4lIAogIHB1bGwoeF8xKSAtPiB3b3Jkc19mYW1pbHkKCnRpZHlfd29yZHMgJT4lIAogIGZpbHRlcih3b3JkICVpbiUgd29yZHNfZmFtaWx5KSAlPiUgCiAgY291bnQoZGF5c190d2VldCwgd29yZCkgJT4lIAogIG11dGF0ZShnZW5kZXIgPSAidCIpICU+JSAKICBiaW5kX3Jvd3ModGlkeV93b3JkcyAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKHdvcmQgJWluJSB3b3Jkc19mYW1pbHkpICU+JSAKICAgICAgICAgICAgICBjb3VudChnZW5kZXIsIGRheXNfdHdlZXQsIHdvcmQpKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGMoZGF5c190d2VldCwgZ2VuZGVyKSwgdmFsdWVzX2Zyb20gPSBuKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIH5yZXBsYWNlX25hKC4sIDApKSAlPiUgCiAgbXV0YXRlKGNoYW5nZXNfdG90YWwgPSBhZnRlcl90IC0gYmVmb3JlX3QsCiAgICAgICAgIGNoYW5nZXNfZiA9IGFmdGVyX2YgLSBiZWZvcmVfZiwKICAgICAgICAgY2hhbmdlc19tID0gYWZ0ZXJfbSAtIGJlZm9yZV9tLAogICAgICAgICBjaGFuZ2VzX3UgPSBhZnRlcl91IC0gYmVmb3JlX3UpICU+JSAKICBzZWxlY3Qod29yZCwgc3RhcnRzX3dpdGgoImNoYW5nZXMiKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhjaGFuZ2VzX3RvdGFsKSkgIC0+IGYgCgpmX3RvcCA8LSBmICU+JSB0b3Bfbig0LCB3dCA9IGNoYW5nZXNfdG90YWwpCmZfYm90dG9tIDwtIGYgJT4lIHRvcF9uKC00LCB3dCA9IGNoYW5nZXNfdG90YWwpCgpmX3RvcCAlPiUgCiAgYmluZF9yb3dzKGZfYm90dG9tKSAlPiUgCiAgZ3Q6Omd0KCkKYGBgCgojIyMgQU5YSUVUWQoKYGBge3J9CiMgYW54aWV0eSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIGFueGlldHkgLT4gMzMKCndvcmRzX2RpYyAlPiUgCiAgZmlsdGVyX2F0KHZhcnMoLXhfMSksIGFueV92YXJzKC4gPT0gMzMpKSAlPiUgCiAgcHVsbCh4XzEpIC0+IHdvcmRzX2FueGlldHkKCnRpZHlfd29yZHMgJT4lIAogIGZpbHRlcih3b3JkICVpbiUgd29yZHNfYW54aWV0eSkgJT4lIAogIGNvdW50KGRheXNfdHdlZXQsIHdvcmQpICU+JSAKICBtdXRhdGUoZ2VuZGVyID0gInQiKSAlPiUgCiAgYmluZF9yb3dzKHRpZHlfd29yZHMgJT4lIAogICAgICAgICAgICAgIGZpbHRlcih3b3JkICVpbiUgd29yZHNfYW54aWV0eSkgJT4lIAogICAgICAgICAgICAgIGNvdW50KGdlbmRlciwgZGF5c190d2VldCwgd29yZCkpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gYyhkYXlzX3R3ZWV0LCBnZW5kZXIpLCB2YWx1ZXNfZnJvbSA9IG4pICU+JSAKICBtdXRhdGVfaWYoaXMubnVtZXJpYywgfnJlcGxhY2VfbmEoLiwgMCkpICU+JSAKICBtdXRhdGUoY2hhbmdlc190b3RhbCA9IGFmdGVyX3QgLSBiZWZvcmVfdCwKICAgICAgICAgY2hhbmdlc19mID0gYWZ0ZXJfZiAtIGJlZm9yZV9mLAogICAgICAgICBjaGFuZ2VzX20gPSBhZnRlcl9tIC0gYmVmb3JlX20sCiAgICAgICAgIGNoYW5nZXNfdSA9IGFmdGVyX3UgLSBiZWZvcmVfdSkgJT4lIAogIHNlbGVjdCh3b3JkLCBzdGFydHNfd2l0aCgiY2hhbmdlcyIpKSAlPiUgCiAgYXJyYW5nZShkZXNjKGNoYW5nZXNfdG90YWwpKSAgLT4gZiAKCmZfdG9wIDwtIGYgJT4lIHRvcF9uKDQsIHd0ID0gY2hhbmdlc190b3RhbCkKZl9ib3R0b20gPC0gZiAlPiUgdG9wX24oLTQsIHd0ID0gY2hhbmdlc190b3RhbCkKCmZfdG9wICU+JSAKICBiaW5kX3Jvd3MoZl9ib3R0b20pICU+JSAKICBndDo6Z3QoKQpgYGAKCiMjIENPTU1PTiBXT1JEUyBJTiBUV0VFVFMgQlkgV09SRFMgQ0FURUdPUlk6CgpgYGB7cn0KbmVkYV9saXdjX2dlbmRlciAlPiUgCiAgZmlsdGVyKGRheXNfdHdlZXQgPj0gMCkgJT4lIAogIHNlbGVjdChpZF90d2VldCwgaWQsIGdlbmRlciwgZmFtaWx5LCBmZW1hbGUsIGFueCkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gZmFtaWx5OmFueCkgJT4lIAogIGZpbHRlcih2YWx1ZSA+IDApICU+JSAKICBsZWZ0X2pvaW4obmVkYV9saXdjICU+JSAKICAgICAgICAgICAgICBzZWxlY3QoaWQsIGlkX3R3ZWV0LCB0ZXh0KSkgJT4lICAKICByZW5hbWUoImNhdGVnb3J5IiA9IG5hbWUpICU+JSAKICBtdXRhdGUodGV4dCA9IHN0cl9yZW1vdmVfYWxsKHRleHQsIHBhdHRlcm4gPSAiWzpncmFwaDpdKyjigKYpIikpICU+JSAKICB1bm5lc3RfdG9rZW5zKHdvcmQsIHRleHQsIHRva2VuID0gInR3ZWV0cyIpICU+JSAgCiAgZmlsdGVyKCF3b3JkICVpbiUgc3RvcF93b3JkcyR3b3JkLAogICAgICAgICAhd29yZCAlaW4lIGMoImRlIiwgNCwgImRhIiwgImxhIiwgImVuIiwgImxlIiwgImxvcyIsIDMpLAogICAgICAgICB3b3JkICE9ICJydCIsCiAgICAgICAgICF3b3JkICVpbiUgc3RyX3JlbW92ZV9hbGwoc3RvcF93b3JkcyR3b3JkLCAiJyIpKSAlPiUgCiAgbXV0YXRlKHdvcmQgPSBjYXNlX3doZW4oY2F0ZWdvcnkgPT0gImZlbWFsZSIgJiB3b3JkICVpbiUgYyh3b3Jkc19mZW1hbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid29tZW5zIikgfiBOQV9jaGFyYWN0ZXJfLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5ID09ICJmYW1pbHkiICYgd29yZCAlaW4lIGMod29yZHNfZmFtaWx5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBhcmVudHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJyb3RoZXJzIil+IE5BX2NoYXJhY3Rlcl8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcnkgPT0gImFueCIgJiB3b3JkICVpbiUgd29yZHNfYW54aWV0eSB+IE5BX2NoYXJhY3Rlcl8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IHdvcmQpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYSh3b3JkKSwKICAgICAgICAgd29yZCAhPSAiYW1wIikgJT4lIAogIGNvdW50KGNhdGVnb3J5LCBnZW5kZXIsIHdvcmQsIHNvcnQgPSBUKSAlPiUKICBncm91cF9ieShnZW5kZXIsIGNhdGVnb3J5KSAlPiUgCiAgdG9wX24oMTAsIHd0ID0gbikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoY2F0ZWdvcnksIHdvcmQpLCBuYW1lc19mcm9tID0gZ2VuZGVyLCB2YWx1ZXNfZnJvbSA9IG4pICU+JSAKICBtdXRhdGUoY2F0ZWdvcnkgPSBzdHJfdG9fdGl0bGUoY2F0ZWdvcnkpKSAlPiUgCiAgZ3Q6Omd0KGdyb3VwbmFtZV9jb2wgPSAiY2F0ZWdvcnkiLAogICAgICAgICByb3duYW1lX2NvbCA9ICJ3b3JkIikgICAKICAKYGBgCgo=