Intro

This R package implements an approach to estimating the causal effect of a designed intervention on a time series. For example, how many additional daily clicks were generated by an advertising campaign? Answering a question like this can be difficult when a randomized experiment is not available.

Given a response time series (e.g., clicks) and a set of control time series (e.g., clicks in non-affected markets or clicks on other sites), the package constructs a Bayesian structural time-series model. This model is then used to try and predict the counterfactual, i.e., how the response metric would have evolved after the intervention if the intervention had never occurred. For a quick overview, watch the tutorial video. For details, see: Brodersen et al., Annals of Applied Statistics (2015).

We will apply LIWC only in certain categories:

##  [1] "i"            "we"           "you"          "shehe"        "they"        
##  [6] "ipron"        "negate"       "compare"      "posemo"       "negemo"      
## [11] "anx"          "anger"        "sad"          "social"       "family"      
## [16] "friend"       "female"       "male"         "insight"      "cause"       
## [21] "discrep"      "tentat"       "certain"      "differ"       "see"         
## [26] "hear"         "feel"         "body"         "health"       "sexual"      
## [31] "ingest"       "affiliation"  "achiev"       "power"        "reward"      
## [36] "risk"         "focuspast"    "focuspresent" "focusfuture"  "relativ"     
## [41] "work"         "leisure"      "home"         "money"        "relig"       
## [46] "death"        "informal"     "swear"        "assent"       "nonflu"      
## [51] "filler"

LIWC

Data Example

Example: In our example data we consider two different days (-1,1), two different users (A, B). User A tweeted 3 times during day -1, and 2 times during day 1. A mentioned happy words 2 times in the first tweet and 1 time in the 3th tweet. During day 1 both users tweeted 2 times. A and B mentioned happyness 1 time. And A mentioned 1 time ipron.

days_tweet <- c(rep(-1, 4), rep(1,4))
id <- c(rep("A", 3), "B", rep("A",2), rep("B", 2))
id_tweet <- sample(30000:40000, 8, replace = F)
happy <- c(2, 0, 1, 0, 1, 0, 1, 0)
ipron <- c(0, 0, 0, 1, 1, 0, 0, 0)

d <- tibble(days_tweet, id, id_tweet, happy, ipron) 

d %>% 
  kable() %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE)
days_tweet id id_tweet happy ipron
-1 A 33451 2 0
-1 A 31439 0 0
-1 A 32404 1 0
-1 B 38084 0 1
1 A 36666 1 1
1 A 35090 0 0
1 B 34824 1 0
1 B 32405 0 0

First Approach

Steps:

  1. We compute the mean of word usage by day.
d %>% 
  group_by(days_tweet) %>% 
  summarise_at(vars(happy:ipron), mean) %>% 
  ungroup() %>% 
  kable() %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE)
days_tweet happy ipron
-1 0.75 0.25
1 0.50 0.25

Second Approach

Steps:

  1. We first computed the mean value per day and user.

  2. Then we computed the mean value per day.

d %>% 
  group_by(days_tweet, id) %>% 
  summarise_at(vars(happy:ipron), mean) %>% 
  ungroup() %>% 
  group_by(days_tweet) %>% 
  summarise_at(vars(happy:ipron), mean) %>% 
  ungroup() %>% 
  kable() %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE)
days_tweet happy ipron
-1 0.5 0.50
1 0.5 0.25

This is values in NEDA and baseline with the first approach:

baseline_liwc %>% 
  select(-text, -created_at, -id_tweet, -id) %>% 
  group_by(days_tweet) %>% 
  summarise_all(mean) %>% 
  ungroup() %>% 
  pivot_longer(cols = fun:filler, names_to = "categ", values_to = "values_baseline") -> ci_baseline

neda_liwc %>% 
  select(-id_tweet, -id) %>% 
  group_by(days_tweet) %>% 
  summarise_all(mean) %>% 
  ungroup() %>% 
  pivot_longer(-days_tweet, names_to = "categ", values_to = "values_neda") -> ci_neda_liwc 
  
pre_period <- c(1, 16)
post_period <- c(17, 31)

ci_baseline %>% 
  inner_join(ci_neda_liwc) -> d_first
d_first %>% 
  pivot_longer(cols = values_baseline:values_neda,
               names_to = "names", values_to = "values") %>% 
  mutate(names = case_when(names == "values_baseline" ~ "Baseline",
                           names == "values_neda" ~ "NEDA")) %>% 
  filter(categ %in% sel_cat[1:24]) %>% 
  ggplot(aes(x = days_tweet, y = values, color = names)) +
  geom_line() +
  facet_wrap(categ ~., scales = "free", ncol = 6) +
  labs(color = "", title = "First Approach") +
  theme(legend.position="top")

This is values in NEDA and baseline with the second approach:

Causal Impact Package

In the table bellow we compare result from computing Causal Impact Package using this two different approach. Only p_value < 0.05 are included. Columns contains information about:

  1. Word Category: Word category in LIWC.

  2. 1st App Relative Eff.: Cummulative relative effect in percentages with the first approach.

  3. 1st P Value: P Value first approach.

  4. 2nd App Relative Eff.: Cummulative relative effect in percentages with the second approach.

d_first %>% 
  select(categ, values_neda, values_baseline) %>% 
  nest(data = - categ) %>% 
  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(p < 0.05) %>% 
  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(desc(relative_effect)) %>% 
  select(categ, first_relative_effect = relative_effect, p_first = p) -> first_ap

d_second %>% 
  select(categ, values_neda, values_baseline) %>% 
  nest(data = - categ) %>% 
  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(p < 0.05) %>% 
  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(desc(relative_effect)) %>% 
  select(categ, second_relative_effect = relative_effect, p_second = p) -> second_ap

second_ap %>% 
  mutate(categ = str_to_title(categ)) %>% 
  mutate_at(vars(second_relative_effect), ~.*100) %>% 
  mutate_if(is.numeric, ~round(., digits = 3)) %>% 
  mutate_at(vars(second_relative_effect), function(x){
    cell_spec(x, "html", color = spec_color(x), bold = T)
  }) %>% 
  kable("html", escape = F,
        align = "lrr",
        col.names = c("Word Category", "Relative Eff.(%)",
                      "P Value")) %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE)
Word Category Relative Eff.(%) P Value
Female 17.418 0.001
Anx 7.566 0.004
Family 6.452 0.004
Money 5.991 0.001
Relig 5.209 0.042
Achiev 3.813 0.006
They 3.397 0.034
Negate 2.889 0.004
Health 2.526 0.005
Power 2.458 0.017
Negemo 2.066 0.041
Informal 1.116 0.036
Ipron -1.476 0.011
Discrep -1.977 0.037
See -2.036 0.027
You -2.238 0.029
Differ -2.694 0.012
Posemo -3.277 0.001
Tentat -3.347 0.002
Shehe -7.042 0.030
Affiliation -7.167 0.002

Female

d_second %>% 
  select(categ, values_neda, values_baseline) %>% 
  filter(categ == "female") %>% 
  select(-categ) -> d

CausalImpact::CausalImpact(data = d, pre_period, post_period) -> ci

plot(ci) +
  theme_light()

summary(ci, "report")
## Analysis report {CausalImpact}
## 
## 
## During the post-intervention period, the response variable had an average value of approx. 0.12. By contrast, in the absence of an intervention, we would have expected an average response of 0.10. The 95% interval of this counterfactual prediction is [0.096, 0.11]. Subtracting this prediction from the observed response yields an estimate of the causal effect the intervention had on the response variable. This effect is 0.018 with a 95% interval of [0.012, 0.024]. For a discussion of the significance of this effect, see below.
## 
## Summing up the individual data points during the post-intervention period (which can only sometimes be meaningfully interpreted), the response variable had an overall value of 1.80. By contrast, had the intervention not taken place, we would have expected a sum of 1.54. The 95% interval of this prediction is [1.45, 1.63].
## 
## The above results are given in terms of absolute numbers. In relative terms, the response variable showed an increase of +17%. The 95% interval of this percentage is [+11%, +23%].
## 
## This means that the positive effect observed during the intervention period is statistically significant and unlikely to be due to random fluctuations. It should be noted, however, that the question of whether this increase also bears substantive significance can only be answered by comparing the absolute effect (0.018) to the original goal of the underlying intervention.
## 
## The probability of obtaining this effect by chance is very small (Bayesian one-sided tail-area probability p = 0.001). This means the causal effect can be considered statistically significant.

Family

d_second %>% 
  select(categ, values_neda, values_baseline) %>% 
  filter(categ == "family") %>% 
  select(-categ) -> d

CausalImpact::CausalImpact(data = d, pre_period, post_period) -> ci

plot(ci)

summary(ci, "report")
## Analysis report {CausalImpact}
## 
## 
## During the post-intervention period, the response variable had an average value of approx. 0.061. By contrast, in the absence of an intervention, we would have expected an average response of 0.057. The 95% interval of this counterfactual prediction is [0.054, 0.060]. Subtracting this prediction from the observed response yields an estimate of the causal effect the intervention had on the response variable. This effect is 0.0037 with a 95% interval of [0.00091, 0.0062]. For a discussion of the significance of this effect, see below.
## 
## Summing up the individual data points during the post-intervention period (which can only sometimes be meaningfully interpreted), the response variable had an overall value of 0.91. By contrast, had the intervention not taken place, we would have expected a sum of 0.85. The 95% interval of this prediction is [0.81, 0.89].
## 
## The above results are given in terms of absolute numbers. In relative terms, the response variable showed an increase of +6%. The 95% interval of this percentage is [+2%, +11%].
## 
## This means that the positive effect observed during the intervention period is statistically significant and unlikely to be due to random fluctuations. It should be noted, however, that the question of whether this increase also bears substantive significance can only be answered by comparing the absolute effect (0.0037) to the original goal of the underlying intervention.
## 
## The probability of obtaining this effect by chance is very small (Bayesian one-sided tail-area probability p = 0.004). This means the causal effect can be considered statistically significant.

Anxiety

d_second %>% 
  select(categ, values_neda, values_baseline) %>% 
  filter(categ == "anx") %>% 
  select(-categ) -> d

CausalImpact::CausalImpact(data = d, pre_period, post_period) -> ci

plot(ci) +
  theme_light()

summary(ci, "report")
## Analysis report {CausalImpact}
## 
## 
## During the post-intervention period, the response variable had an average value of approx. 0.049. By contrast, in the absence of an intervention, we would have expected an average response of 0.046. The 95% interval of this counterfactual prediction is [0.044, 0.048]. Subtracting this prediction from the observed response yields an estimate of the causal effect the intervention had on the response variable. This effect is 0.0034 with a 95% interval of [0.0015, 0.0055]. For a discussion of the significance of this effect, see below.
## 
## Summing up the individual data points during the post-intervention period (which can only sometimes be meaningfully interpreted), the response variable had an overall value of 0.74. By contrast, had the intervention not taken place, we would have expected a sum of 0.68. The 95% interval of this prediction is [0.65, 0.71].
## 
## The above results are given in terms of absolute numbers. In relative terms, the response variable showed an increase of +8%. The 95% interval of this percentage is [+3%, +12%].
## 
## This means that the positive effect observed during the intervention period is statistically significant and unlikely to be due to random fluctuations. It should be noted, however, that the question of whether this increase also bears substantive significance can only be answered by comparing the absolute effect (0.0034) to the original goal of the underlying intervention.
## 
## The probability of obtaining this effect by chance is very small (Bayesian one-sided tail-area probability p = 0.001). This means the causal effect can be considered statistically significant.

She/He

d_second %>% 
  select(categ, values_neda, values_baseline) %>% 
  filter(categ == "shehe") %>% 
  select(-categ) -> d

CausalImpact::CausalImpact(data = d, pre_period, post_period) -> ci

plot(ci)

summary(ci)
## Posterior inference {CausalImpact}
## 
##                          Average             Cumulative       
## Actual                   0.077               1.160            
## Prediction (s.d.)        0.083 (0.003)       1.248 (0.045)    
## 95% CI                   [0.077, 0.089]      [1.158, 1.331]   
##                                                               
## Absolute effect (s.d.)   -0.0059 (0.003)     -0.0879 (0.045)  
## 95% CI                   [-0.011, 0.00014]   [-0.170, 0.00216]
##                                                               
## Relative effect (s.d.)   -7% (3.6%)          -7% (3.6%)       
## 95% CI                   [-14%, 0.17%]       [-14%, 0.17%]    
## 
## Posterior tail-area probability p:   0.02926
## Posterior prob. of a causal effect:  97.074%
## 
## For more details, type: summary(impact, "report")
summary(ci, "report")
## Analysis report {CausalImpact}
## 
## 
## During the post-intervention period, the response variable had an average value of approx. 0.077. In the absence of an intervention, we would have expected an average response of 0.083. The 95% interval of this counterfactual prediction is [0.077, 0.089]. Subtracting this prediction from the observed response yields an estimate of the causal effect the intervention had on the response variable. This effect is -0.0059 with a 95% interval of [-0.011, 0.00014]. For a discussion of the significance of this effect, see below.
## 
## Summing up the individual data points during the post-intervention period (which can only sometimes be meaningfully interpreted), the response variable had an overall value of 1.16. Had the intervention not taken place, we would have expected a sum of 1.25. The 95% interval of this prediction is [1.16, 1.33].
## 
## The above results are given in terms of absolute numbers. In relative terms, the response variable showed a decrease of -7%. The 95% interval of this percentage is [-14%, +0%].
## 
## This means that, although it may look as though the intervention has exerted a negative effect on the response variable when considering the intervention period as a whole, this effect is not statistically significant, and so cannot be meaningfully interpreted. The apparent effect could be the result of random fluctuations that are unrelated to the intervention. This is often the case when the intervention period is very long and includes much of the time when the effect has already worn off. It can also be the case when the intervention period is too short to distinguish the signal from the noise. Finally, failing to find a significant effect can happen when there are not enough control variables or when these variables do not correlate well with the response variable during the learning period.
## 
## The probability of obtaining this effect by chance is very small (Bayesian one-sided tail-area probability p = 0.029). This means the causal effect can be considered statistically significant.

Affiliation

d_second %>% 
  select(categ, values_neda, values_baseline) %>% 
  filter(categ == "affiliation") %>% 
  select(-categ) -> d

CausalImpact::CausalImpact(data = d, pre_period, post_period) -> ci

plot(ci)

summary(ci, "report")
## Analysis report {CausalImpact}
## 
## 
## During the post-intervention period, the response variable had an average value of approx. 0.43. By contrast, in the absence of an intervention, we would have expected an average response of 0.46. The 95% interval of this counterfactual prediction is [0.44, 0.48]. Subtracting this prediction from the observed response yields an estimate of the causal effect the intervention had on the response variable. This effect is -0.033 with a 95% interval of [-0.054, -0.011]. For a discussion of the significance of this effect, see below.
## 
## Summing up the individual data points during the post-intervention period (which can only sometimes be meaningfully interpreted), the response variable had an overall value of 6.41. By contrast, had the intervention not taken place, we would have expected a sum of 6.91. The 95% interval of this prediction is [6.57, 7.22].
## 
## The above results are given in terms of absolute numbers. In relative terms, the response variable showed a decrease of -7%. The 95% interval of this percentage is [-12%, -2%].
## 
## This means that the negative effect observed during the intervention period is statistically significant. If the experimenter had expected a positive effect, it is recommended to double-check whether anomalies in the control variables may have caused an overly optimistic expectation of what should have happened in the response variable in the absence of the intervention.
## 
## The probability of obtaining this effect by chance is very small (Bayesian one-sided tail-area probability p = 0.004). This means the causal effect can be considered statistically significant.

Friend

d_second %>% 
  select(categ, values_neda, values_baseline) %>% 
  filter(categ == "friend") %>% 
  select(-categ) -> d

CausalImpact::CausalImpact(data = d, pre_period, post_period, alpha = .05) -> ci

plot(ci)

summary(ci, "report")
## Analysis report {CausalImpact}
## 
## 
## During the post-intervention period, the response variable had an average value of approx. 0.048. In the absence of an intervention, we would have expected an average response of 0.058. The 95% interval of this counterfactual prediction is [0.047, 0.070]. Subtracting this prediction from the observed response yields an estimate of the causal effect the intervention had on the response variable. This effect is -0.0095 with a 95% interval of [-0.022, 0.0016]. For a discussion of the significance of this effect, see below.
## 
## Summing up the individual data points during the post-intervention period (which can only sometimes be meaningfully interpreted), the response variable had an overall value of 0.72. Had the intervention not taken place, we would have expected a sum of 0.87. The 95% interval of this prediction is [0.70, 1.05].
## 
## The above results are given in terms of absolute numbers. In relative terms, the response variable showed a decrease of -16%. The 95% interval of this percentage is [-37%, +3%].
## 
## This means that, although it may look as though the intervention has exerted a negative effect on the response variable when considering the intervention period as a whole, this effect is not statistically significant, and so cannot be meaningfully interpreted. The apparent effect could be the result of random fluctuations that are unrelated to the intervention. This is often the case when the intervention period is very long and includes much of the time when the effect has already worn off. It can also be the case when the intervention period is too short to distinguish the signal from the noise. Finally, failing to find a significant effect can happen when there are not enough control variables or when these variables do not correlate well with the response variable during the learning period.
## 
## The probability of obtaining this effect by chance is very small (Bayesian one-sided tail-area probability p = 0.045). This means the causal effect can be considered statistically significant.

Relig

d_second %>% 
  select(categ, values_neda, values_baseline) %>% 
  filter(categ == "relig") %>% 
  select(-categ) -> d

CausalImpact::CausalImpact(data = d, pre_period, post_period, alpha = .05) -> ci

plot(ci)

summary(ci, "report")
## Analysis report {CausalImpact}
## 
## 
## During the post-intervention period, the response variable had an average value of approx. 0.046. In the absence of an intervention, we would have expected an average response of 0.044. The 95% interval of this counterfactual prediction is [0.041, 0.046]. Subtracting this prediction from the observed response yields an estimate of the causal effect the intervention had on the response variable. This effect is 0.0023 with a 95% interval of [-0.00012, 0.0048]. For a discussion of the significance of this effect, see below.
## 
## Summing up the individual data points during the post-intervention period (which can only sometimes be meaningfully interpreted), the response variable had an overall value of 0.69. Had the intervention not taken place, we would have expected a sum of 0.66. The 95% interval of this prediction is [0.62, 0.69].
## 
## The above results are given in terms of absolute numbers. In relative terms, the response variable showed an increase of +5%. The 95% interval of this percentage is [-0%, +11%].
## 
## This means that, although the intervention appears to have caused a positive effect, this effect is not statistically significant when considering the entire post-intervention period as a whole. Individual days or shorter stretches within the intervention period may of course still have had a significant effect, as indicated whenever the lower limit of the impact time series (lower plot) was above zero. The apparent effect could be the result of random fluctuations that are unrelated to the intervention. This is often the case when the intervention period is very long and includes much of the time when the effect has already worn off. It can also be the case when the intervention period is too short to distinguish the signal from the noise. Finally, failing to find a significant effect can happen when there are not enough control variables or when these variables do not correlate well with the response variable during the learning period.
## 
## The probability of obtaining this effect by chance is very small (Bayesian one-sided tail-area probability p = 0.034). This means the causal effect can be considered statistically significant.
LS0tCnRpdGxlOiAiQ2F1c2FsIEltcGFjdCIgCmNsZWFuOiB0cnVlCm91dHB1dDoKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogZmFsc2UKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkKCnhmdW46OnBrZ19hdHRhY2goInRpZHl2ZXJzZSIsICJsdWJyaWRhdGUiLCAia2FibGVFeHRyYSIpCgp0aGVtZV9zZXQodGhlbWVfbGluZWRyYXcoKSkKYGBgCgojIyBJbnRybwoKVGhpcyBSIHBhY2thZ2UgaW1wbGVtZW50cyBhbiBhcHByb2FjaCB0byBlc3RpbWF0aW5nIHRoZSBjYXVzYWwgZWZmZWN0IG9mIGEgZGVzaWduZWQgaW50ZXJ2ZW50aW9uIG9uIGEgdGltZSBzZXJpZXMuIEZvciBleGFtcGxlLCBob3cgbWFueSBhZGRpdGlvbmFsIGRhaWx5IGNsaWNrcyB3ZXJlIGdlbmVyYXRlZCBieSBhbiBhZHZlcnRpc2luZyBjYW1wYWlnbj8gQW5zd2VyaW5nIGEgcXVlc3Rpb24gbGlrZSB0aGlzIGNhbiBiZSBkaWZmaWN1bHQgd2hlbiBhIHJhbmRvbWl6ZWQgZXhwZXJpbWVudCBpcyBub3QgYXZhaWxhYmxlLgoKR2l2ZW4gYSByZXNwb25zZSB0aW1lIHNlcmllcyAoZS5nLiwgY2xpY2tzKSBhbmQgYSBzZXQgb2YgY29udHJvbCB0aW1lIHNlcmllcyAoZS5nLiwgY2xpY2tzIGluIG5vbi1hZmZlY3RlZCBtYXJrZXRzIG9yIGNsaWNrcyBvbiBvdGhlciBzaXRlcyksIHRoZSBwYWNrYWdlIGNvbnN0cnVjdHMgYSBCYXllc2lhbiBzdHJ1Y3R1cmFsIHRpbWUtc2VyaWVzIG1vZGVsLiBUaGlzIG1vZGVsIGlzIHRoZW4gdXNlZCB0byB0cnkgYW5kIHByZWRpY3QgdGhlIGNvdW50ZXJmYWN0dWFsLCBpLmUuLCBob3cgdGhlIHJlc3BvbnNlIG1ldHJpYyB3b3VsZCBoYXZlIGV2b2x2ZWQgYWZ0ZXIgdGhlIGludGVydmVudGlvbiBpZiB0aGUgaW50ZXJ2ZW50aW9uIGhhZCBuZXZlciBvY2N1cnJlZC4gRm9yIGEgcXVpY2sgb3ZlcnZpZXcsIHdhdGNoIHRoZSB0dXRvcmlhbCB2aWRlby4gRm9yIGRldGFpbHMsIHNlZTogQnJvZGVyc2VuIGV0IGFsLiwgQW5uYWxzIG9mIEFwcGxpZWQgU3RhdGlzdGljcyAoMjAxNSkuCgpXZSB3aWxsIGFwcGx5IExJV0Mgb25seSBpbiBjZXJ0YWluIGNhdGVnb3JpZXM6CgpgYGB7ciBlY2hvPUZBTFNFfQpiYXNlbGluZV9saXdjIDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGEiLCAiYmFzZWxpbmVfbGl3Yy5yZHMiKSkKbmVkYV9saXdjIDwtIHJlYWRfcmRzKGhlcmU6OmhlcmUoImRhdGEiLCAibmVkYV9saXdjLnJkcyIpKSAlPiUgCiAgc2VsZWN0KC10ZXh0LCAtY3JlYXRlZF9hdF90d2VldCkgJT4lIAogIGZpbHRlcihhYnMoZGF5c190d2VldCkgPD0gMTUpCgpzZWxfY2F0IDwtIGMoCiAgImkiLCJ3ZSIsInlvdSIsInNoZWhlIiwidGhleSIsImlwcm9uIiwibmVnYXRlIiwiY29tcGFyZSIsInBvc2VtbyIsIm5lZ2VtbyIsImFueCIsImFuZ2VyIiwic2FkIiwic29jaWFsIiwiZmFtaWx5IiwiZnJpZW5kIiwiZmVtYWxlIiwibWFsZSIsImluc2lnaHQiLCJjYXVzZSIsImRpc2NyZXAiLCJ0ZW50YXQiLCJjZXJ0YWluIiwiZGlmZmVyIiwic2VlIiwiaGVhciIsImZlZWwiLCJib2R5IiwiaGVhbHRoIiwic2V4dWFsIiwiaW5nZXN0IiwiYWZmaWxpYXRpb24iLCJhY2hpZXYiLCJwb3dlciIsInJld2FyZCIsInJpc2siLCJmb2N1c3Bhc3QiLCJmb2N1c3ByZXNlbnQiLCJmb2N1c2Z1dHVyZSIsInJlbGF0aXYiLCJ3b3JrIiwibGVpc3VyZSIsImhvbWUiLCJtb25leSIsInJlbGlnIiwiZGVhdGgiLCJpbmZvcm1hbCIsInN3ZWFyIiwiYXNzZW50Iiwibm9uZmx1IiwiZmlsbGVyIgopCgpzZWxfY2F0CmBgYAoKIyMgTElXQwoKIyMjIERhdGEgRXhhbXBsZQoKRXhhbXBsZTogSW4gb3VyIGV4YW1wbGUgZGF0YSB3ZSBjb25zaWRlciB0d28gZGlmZmVyZW50IGRheXMgKC0xLDEpLCB0d28gZGlmZmVyZW50IHVzZXJzIChBLCBCKS4gVXNlciBgQWAgdHdlZXRlZCBgMyB0aW1lc2AgZHVyaW5nIGRheSBgLTFgLCBhbmQgYDIgdGltZXNgIGR1cmluZyBkYXkgYDFgLiBgQWAgbWVudGlvbmVkIGhhcHB5IHdvcmRzIDIgdGltZXMgaW4gdGhlIGZpcnN0IHR3ZWV0IGFuZCAxIHRpbWUgaW4gdGhlIDN0aCB0d2VldC4gRHVyaW5nIGRheSBgMWAgYm90aCB1c2VycyB0d2VldGVkIGAyYCB0aW1lcy4gQSBhbmQgQiBtZW50aW9uZWQgaGFwcHluZXNzIGAxYCB0aW1lLiBBbmQgQSBtZW50aW9uZWQgYDFgIHRpbWUgYGlwcm9uYC4gICAgCgpgYGB7cn0KZGF5c190d2VldCA8LSBjKHJlcCgtMSwgNCksIHJlcCgxLDQpKQppZCA8LSBjKHJlcCgiQSIsIDMpLCAiQiIsIHJlcCgiQSIsMiksIHJlcCgiQiIsIDIpKQppZF90d2VldCA8LSBzYW1wbGUoMzAwMDA6NDAwMDAsIDgsIHJlcGxhY2UgPSBGKQpoYXBweSA8LSBjKDIsIDAsIDEsIDAsIDEsIDAsIDEsIDApCmlwcm9uIDwtIGMoMCwgMCwgMCwgMSwgMSwgMCwgMCwgMCkKCmQgPC0gdGliYmxlKGRheXNfdHdlZXQsIGlkLCBpZF90d2VldCwgaGFwcHksIGlwcm9uKSAKCmQgJT4lIAogIGthYmxlKCkgJT4lIAogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLAogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFKQpgYGAKCiMjIyMgRmlyc3QgQXBwcm9hY2gKClN0ZXBzOgoKMS4gV2UgY29tcHV0ZSB0aGUgbWVhbiBvZiB3b3JkIHVzYWdlIGJ5IGRheS4KCmBgYHtyfQpkICU+JSAKICBncm91cF9ieShkYXlzX3R3ZWV0KSAlPiUgCiAgc3VtbWFyaXNlX2F0KHZhcnMoaGFwcHk6aXByb24pLCBtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBrYWJsZSgpICU+JSAKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkKYGBgCgojIyMjIFNlY29uZCBBcHByb2FjaAoKU3RlcHM6CgoxLiBXZSBmaXJzdCBjb21wdXRlZCB0aGUgbWVhbiB2YWx1ZSBwZXIgZGF5IGFuZCB1c2VyLgoKMS4gVGhlbiB3ZSBjb21wdXRlZCB0aGUgbWVhbiB2YWx1ZSBwZXIgZGF5LgoKYGBge3J9CmQgJT4lIAogIGdyb3VwX2J5KGRheXNfdHdlZXQsIGlkKSAlPiUgCiAgc3VtbWFyaXNlX2F0KHZhcnMoaGFwcHk6aXByb24pLCBtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShkYXlzX3R3ZWV0KSAlPiUgCiAgc3VtbWFyaXNlX2F0KHZhcnMoaGFwcHk6aXByb24pLCBtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBrYWJsZSgpICU+JSAKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkKYGBgCgpUaGlzIGlzIHZhbHVlcyBpbiBORURBIGFuZCBiYXNlbGluZSB3aXRoIHRoZSBfX2ZpcnN0IGFwcHJvYWNoX186CmBgYHtyIH0KYmFzZWxpbmVfbGl3YyAlPiUgCiAgc2VsZWN0KC10ZXh0LCAtY3JlYXRlZF9hdCwgLWlkX3R3ZWV0LCAtaWQpICU+JSAKICBncm91cF9ieShkYXlzX3R3ZWV0KSAlPiUgCiAgc3VtbWFyaXNlX2FsbChtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGZ1bjpmaWxsZXIsIG5hbWVzX3RvID0gImNhdGVnIiwgdmFsdWVzX3RvID0gInZhbHVlc19iYXNlbGluZSIpIC0+IGNpX2Jhc2VsaW5lCgpuZWRhX2xpd2MgJT4lIAogIHNlbGVjdCgtaWRfdHdlZXQsIC1pZCkgJT4lIAogIGdyb3VwX2J5KGRheXNfdHdlZXQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHBpdm90X2xvbmdlcigtZGF5c190d2VldCwgbmFtZXNfdG8gPSAiY2F0ZWciLCB2YWx1ZXNfdG8gPSAidmFsdWVzX25lZGEiKSAtPiBjaV9uZWRhX2xpd2MgCiAgCnByZV9wZXJpb2QgPC0gYygxLCAxNikKcG9zdF9wZXJpb2QgPC0gYygxNywgMzEpCgpjaV9iYXNlbGluZSAlPiUgCiAgaW5uZXJfam9pbihjaV9uZWRhX2xpd2MpIC0+IGRfZmlyc3QKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PSAxMH0KZF9maXJzdCAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSB2YWx1ZXNfYmFzZWxpbmU6dmFsdWVzX25lZGEsCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIm5hbWVzIiwgdmFsdWVzX3RvID0gInZhbHVlcyIpICU+JSAKICBtdXRhdGUobmFtZXMgPSBjYXNlX3doZW4obmFtZXMgPT0gInZhbHVlc19iYXNlbGluZSIgfiAiQmFzZWxpbmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lcyA9PSAidmFsdWVzX25lZGEiIH4gIk5FREEiKSkgJT4lIAogIGZpbHRlcihjYXRlZyAlaW4lIHNlbF9jYXRbMToyNF0pICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3R3ZWV0LCB5ID0gdmFsdWVzLCBjb2xvciA9IG5hbWVzKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKGNhdGVnIH4uLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSA2KSArCiAgbGFicyhjb2xvciA9ICIiLCB0aXRsZSA9ICJGaXJzdCBBcHByb2FjaCIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIpCmBgYAoKVGhpcyBpcyB2YWx1ZXMgaW4gTkVEQSBhbmQgYmFzZWxpbmUgd2l0aCB0aGUgX19zZWNvbmQgYXBwcm9hY2hfXzoKYGBge3IgZWNobz1GQUxTRX0KYmFzZWxpbmVfbGl3YyAlPiUgCiAgc2VsZWN0KC10ZXh0LCAtY3JlYXRlZF9hdCwgLWlkX3R3ZWV0KSAlPiUgCiAgZ3JvdXBfYnkoZGF5c190d2VldCwgaWQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdCgtaWQpICU+JSAKICBncm91cF9ieShkYXlzX3R3ZWV0KSAlPiUgCiAgc3VtbWFyaXNlX2FsbChtZWFuKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGZ1bjpmaWxsZXIsIG5hbWVzX3RvID0gImNhdGVnIiwgdmFsdWVzX3RvID0gInZhbHVlc19iYXNlbGluZSIpIC0+IGNpX2Jhc2VsaW5lCgpuZWRhX2xpd2MgJT4lIAogIHNlbGVjdCgtaWRfdHdlZXQpICU+JSAKICBncm91cF9ieShkYXlzX3R3ZWV0LCBpZCkgJT4lIAogIHN1bW1hcmlzZV9hbGwobWVhbikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KC1pZCkgJT4lIAogIGdyb3VwX2J5KGRheXNfdHdlZXQpICU+JSAKICBzdW1tYXJpc2VfYWxsKG1lYW4pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHBpdm90X2xvbmdlcigtZGF5c190d2VldCwgbmFtZXNfdG8gPSAiY2F0ZWciLCB2YWx1ZXNfdG8gPSAidmFsdWVzX25lZGEiKSAtPiBjaV9uZWRhX2xpd2MgCiAgCnByZV9wZXJpb2QgPC0gYygxLCAxNikKcG9zdF9wZXJpb2QgPC0gYygxNywgMzEpCgpjaV9iYXNlbGluZSAlPiUgCiAgaW5uZXJfam9pbihjaV9uZWRhX2xpd2MpIC0+IGRfc2Vjb25kCmBgYAoKYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0xMH0KZF9zZWNvbmQgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gdmFsdWVzX2Jhc2VsaW5lOnZhbHVlc19uZWRhLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJuYW1lcyIsIHZhbHVlc190byA9ICJ2YWx1ZXMiKSAlPiUgCiAgbXV0YXRlKG5hbWVzID0gY2FzZV93aGVuKG5hbWVzID09ICJ2YWx1ZXNfYmFzZWxpbmUiIH4gIkJhc2VsaW5lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXMgPT0gInZhbHVlc19uZWRhIiB+ICJORURBIikpICU+JSAKICBmaWx0ZXIoY2F0ZWcgJWluJSBzZWxfY2F0WzE6MjRdKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF5c190d2VldCwgeSA9IHZhbHVlcywgY29sb3IgPSBuYW1lcykpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcChjYXRlZyB+Liwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gNikgKwogIGxhYnMoY29sb3IgPSAiIiwgdGl0bGUgPSAiU2Vjb25kIEFwcHJvYWNoIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikKYGBgCgojIyBDYXVzYWwgSW1wYWN0IFBhY2thZ2UKSW4gdGhlIHRhYmxlIGJlbGxvdyB3ZSBjb21wYXJlIHJlc3VsdCBmcm9tIGNvbXB1dGluZyBDYXVzYWwgSW1wYWN0IFBhY2thZ2UgdXNpbmcgdGhpcyB0d28gZGlmZmVyZW50IGFwcHJvYWNoLiBPbmx5IHBfdmFsdWUgPCAwLjA1IGFyZSBpbmNsdWRlZC4gQ29sdW1ucyBjb250YWlucyBpbmZvcm1hdGlvbiBhYm91dDoKCjEuIF9fV29yZCBDYXRlZ29yeV9fOiBXb3JkIGNhdGVnb3J5IGluIExJV0MuCgoxLiBfXzFzdCBBcHAgUmVsYXRpdmUgRWZmLl9fOiBDdW1tdWxhdGl2ZSByZWxhdGl2ZSBlZmZlY3QgaW4gcGVyY2VudGFnZXMgd2l0aCB0aGUgZmlyc3QgYXBwcm9hY2guCgoxLiBfXzFzdCBQIFZhbHVlX186IFAgVmFsdWUgZmlyc3QgYXBwcm9hY2guCgoxLiBfXzJuZCBBcHAgUmVsYXRpdmUgRWZmLl9fOiBDdW1tdWxhdGl2ZSByZWxhdGl2ZSBlZmZlY3QgaW4gcGVyY2VudGFnZXMgd2l0aCB0aGUgc2Vjb25kIGFwcHJvYWNoLgoKYGBge3IgfQpkX2ZpcnN0ICU+JSAKICBzZWxlY3QoY2F0ZWcsIHZhbHVlc19uZWRhLCB2YWx1ZXNfYmFzZWxpbmUpICU+JSAKICBuZXN0KGRhdGEgPSAtIGNhdGVnKSAlPiUgCiAgbXV0YXRlKG1vZCA9IG1hcChkYXRhLCB+Q2F1c2FsSW1wYWN0OjpDYXVzYWxJbXBhY3QoLiwgcHJlX3BlcmlvZCwgcG9zdF9wZXJpb2QpKSkgLT4gY2kKICAKY2kgJT4lIAogIG11dGF0ZShzdW1tYXJ5X21vZCA9IG1hcChtb2QsICJzdW1tYXJ5IikpICU+JSAKICBmaWx0ZXIoIW1hcF9sZ2woc3VtbWFyeV9tb2QsIGlzLm51bGwpKSAtPiBjaV9yZXN1bCAKCmNpX3Jlc3VsICU+JSAKICBtdXRhdGUocCA9IG1hcChzdW1tYXJ5X21vZCwgInAiKSkgJT4lIAogIG11dGF0ZShwID0gbWFwX2RibChwLCAxKSkgJT4lIAogIGZpbHRlcihwIDwgMC4wNSkgJT4lIAogIG11dGF0ZShyZWxhdGl2ZV9lZmZlY3QgPSBtYXAoc3VtbWFyeV9tb2QsICJSZWxFZmZlY3QiKSkgJT4lIAogIG11dGF0ZShyZWxhdGl2ZV9lZmZlY3QgPSBtYXBfZGJsKHJlbGF0aXZlX2VmZmVjdCwgMikpLT4gc2lnX2NhdAoKc2lnX2NhdCAlPiUgCiAgZmlsdGVyKGNhdGVnICVpbiUgc2VsX2NhdCkgLT4gc2lnX2NhdAoKc2lnX2NhdCAlPiUgCiAgYXJyYW5nZShkZXNjKHJlbGF0aXZlX2VmZmVjdCkpICU+JSAKICBzZWxlY3QoY2F0ZWcsIGZpcnN0X3JlbGF0aXZlX2VmZmVjdCA9IHJlbGF0aXZlX2VmZmVjdCwgcF9maXJzdCA9IHApIC0+IGZpcnN0X2FwCgpkX3NlY29uZCAlPiUgCiAgc2VsZWN0KGNhdGVnLCB2YWx1ZXNfbmVkYSwgdmFsdWVzX2Jhc2VsaW5lKSAlPiUgCiAgbmVzdChkYXRhID0gLSBjYXRlZykgJT4lIAogIG11dGF0ZShtb2QgPSBtYXAoZGF0YSwgfkNhdXNhbEltcGFjdDo6Q2F1c2FsSW1wYWN0KC4sIHByZV9wZXJpb2QsIHBvc3RfcGVyaW9kKSkpIC0+IGNpCiAgCmNpICU+JSAKICBtdXRhdGUoc3VtbWFyeV9tb2QgPSBtYXAobW9kLCAic3VtbWFyeSIpKSAlPiUgCiAgZmlsdGVyKCFtYXBfbGdsKHN1bW1hcnlfbW9kLCBpcy5udWxsKSkgLT4gY2lfcmVzdWwgCgpjaV9yZXN1bCAlPiUgCiAgbXV0YXRlKHAgPSBtYXAoc3VtbWFyeV9tb2QsICJwIikpICU+JSAKICBtdXRhdGUocCA9IG1hcF9kYmwocCwgMSkpICU+JSAKICBmaWx0ZXIocCA8IDAuMDUpICU+JSAKICBtdXRhdGUocmVsYXRpdmVfZWZmZWN0ID0gbWFwKHN1bW1hcnlfbW9kLCAiUmVsRWZmZWN0IikpICU+JSAKICBtdXRhdGUocmVsYXRpdmVfZWZmZWN0ID0gbWFwX2RibChyZWxhdGl2ZV9lZmZlY3QsIDIpKS0+IHNpZ19jYXQKCnNpZ19jYXQgJT4lIAogIGZpbHRlcihjYXRlZyAlaW4lIHNlbF9jYXQpIC0+IHNpZ19jYXQKCnNpZ19jYXQgJT4lIAogIGFycmFuZ2UoZGVzYyhyZWxhdGl2ZV9lZmZlY3QpKSAlPiUgCiAgc2VsZWN0KGNhdGVnLCBzZWNvbmRfcmVsYXRpdmVfZWZmZWN0ID0gcmVsYXRpdmVfZWZmZWN0LCBwX3NlY29uZCA9IHApIC0+IHNlY29uZF9hcAoKc2Vjb25kX2FwICU+JSAKICBtdXRhdGUoY2F0ZWcgPSBzdHJfdG9fdGl0bGUoY2F0ZWcpKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoc2Vjb25kX3JlbGF0aXZlX2VmZmVjdCksIH4uKjEwMCkgJT4lIAogIG11dGF0ZV9pZihpcy5udW1lcmljLCB+cm91bmQoLiwgZGlnaXRzID0gMykpICU+JSAKICBtdXRhdGVfYXQodmFycyhzZWNvbmRfcmVsYXRpdmVfZWZmZWN0KSwgZnVuY3Rpb24oeCl7CiAgICBjZWxsX3NwZWMoeCwgImh0bWwiLCBjb2xvciA9IHNwZWNfY29sb3IoeCksIGJvbGQgPSBUKQogIH0pICU+JSAKICBrYWJsZSgiaHRtbCIsIGVzY2FwZSA9IEYsCiAgICAgICAgYWxpZ24gPSAibHJyIiwKICAgICAgICBjb2wubmFtZXMgPSBjKCJXb3JkIENhdGVnb3J5IiwgIlJlbGF0aXZlIEVmZi4oJSkiLAogICAgICAgICAgICAgICAgICAgICAgIlAgVmFsdWUiKSkgJT4lIAogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLAogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFKQpgYGAKCiMgRmVtYWxlIAoKYGBge3J9CmRfc2Vjb25kICU+JSAKICBzZWxlY3QoY2F0ZWcsIHZhbHVlc19uZWRhLCB2YWx1ZXNfYmFzZWxpbmUpICU+JSAKICBmaWx0ZXIoY2F0ZWcgPT0gImZlbWFsZSIpICU+JSAKICBzZWxlY3QoLWNhdGVnKSAtPiBkCgpDYXVzYWxJbXBhY3Q6OkNhdXNhbEltcGFjdChkYXRhID0gZCwgcHJlX3BlcmlvZCwgcG9zdF9wZXJpb2QpIC0+IGNpCgpwbG90KGNpKSArCiAgdGhlbWVfbGlnaHQoKQoKc3VtbWFyeShjaSwgInJlcG9ydCIpCmBgYAoKIyBGYW1pbHkKCmBgYHtyfQpkX3NlY29uZCAlPiUgCiAgc2VsZWN0KGNhdGVnLCB2YWx1ZXNfbmVkYSwgdmFsdWVzX2Jhc2VsaW5lKSAlPiUgCiAgZmlsdGVyKGNhdGVnID09ICJmYW1pbHkiKSAlPiUgCiAgc2VsZWN0KC1jYXRlZykgLT4gZAoKQ2F1c2FsSW1wYWN0OjpDYXVzYWxJbXBhY3QoZGF0YSA9IGQsIHByZV9wZXJpb2QsIHBvc3RfcGVyaW9kKSAtPiBjaQoKcGxvdChjaSkKCnN1bW1hcnkoY2ksICJyZXBvcnQiKQpgYGAKCiMgQW54aWV0eQoKYGBge3J9CmRfc2Vjb25kICU+JSAKICBzZWxlY3QoY2F0ZWcsIHZhbHVlc19uZWRhLCB2YWx1ZXNfYmFzZWxpbmUpICU+JSAKICBmaWx0ZXIoY2F0ZWcgPT0gImFueCIpICU+JSAKICBzZWxlY3QoLWNhdGVnKSAtPiBkCgpDYXVzYWxJbXBhY3Q6OkNhdXNhbEltcGFjdChkYXRhID0gZCwgcHJlX3BlcmlvZCwgcG9zdF9wZXJpb2QpIC0+IGNpCgpwbG90KGNpKSArCiAgdGhlbWVfbGlnaHQoKQoKc3VtbWFyeShjaSwgInJlcG9ydCIpCmBgYAoKIyBTaGUvSGUKCmBgYHtyfQpkX3NlY29uZCAlPiUgCiAgc2VsZWN0KGNhdGVnLCB2YWx1ZXNfbmVkYSwgdmFsdWVzX2Jhc2VsaW5lKSAlPiUgCiAgZmlsdGVyKGNhdGVnID09ICJzaGVoZSIpICU+JSAKICBzZWxlY3QoLWNhdGVnKSAtPiBkCgpDYXVzYWxJbXBhY3Q6OkNhdXNhbEltcGFjdChkYXRhID0gZCwgcHJlX3BlcmlvZCwgcG9zdF9wZXJpb2QpIC0+IGNpCgpwbG90KGNpKQoKc3VtbWFyeShjaSkKc3VtbWFyeShjaSwgInJlcG9ydCIpCmBgYAoKIyBBZmZpbGlhdGlvbgoKYGBge3J9CmRfc2Vjb25kICU+JSAKICBzZWxlY3QoY2F0ZWcsIHZhbHVlc19uZWRhLCB2YWx1ZXNfYmFzZWxpbmUpICU+JSAKICBmaWx0ZXIoY2F0ZWcgPT0gImFmZmlsaWF0aW9uIikgJT4lIAogIHNlbGVjdCgtY2F0ZWcpIC0+IGQKCkNhdXNhbEltcGFjdDo6Q2F1c2FsSW1wYWN0KGRhdGEgPSBkLCBwcmVfcGVyaW9kLCBwb3N0X3BlcmlvZCkgLT4gY2kKCnBsb3QoY2kpCgpzdW1tYXJ5KGNpLCAicmVwb3J0IikKYGBgCgojIEZyaWVuZAoKYGBge3J9CmRfc2Vjb25kICU+JSAKICBzZWxlY3QoY2F0ZWcsIHZhbHVlc19uZWRhLCB2YWx1ZXNfYmFzZWxpbmUpICU+JSAKICBmaWx0ZXIoY2F0ZWcgPT0gImZyaWVuZCIpICU+JSAKICBzZWxlY3QoLWNhdGVnKSAtPiBkCgpDYXVzYWxJbXBhY3Q6OkNhdXNhbEltcGFjdChkYXRhID0gZCwgcHJlX3BlcmlvZCwgcG9zdF9wZXJpb2QsIGFscGhhID0gLjA1KSAtPiBjaQoKcGxvdChjaSkKCnN1bW1hcnkoY2ksICJyZXBvcnQiKQpgYGAKCiMgUmVsaWcKCmBgYHtyfQpkX3NlY29uZCAlPiUgCiAgc2VsZWN0KGNhdGVnLCB2YWx1ZXNfbmVkYSwgdmFsdWVzX2Jhc2VsaW5lKSAlPiUgCiAgZmlsdGVyKGNhdGVnID09ICJyZWxpZyIpICU+JSAKICBzZWxlY3QoLWNhdGVnKSAtPiBkCgpDYXVzYWxJbXBhY3Q6OkNhdXNhbEltcGFjdChkYXRhID0gZCwgcHJlX3BlcmlvZCwgcG9zdF9wZXJpb2QsIGFscGhhID0gLjA1KSAtPiBjaQoKcGxvdChjaSkKCnN1bW1hcnkoY2ksICJyZXBvcnQiKQpgYGAKCgo=