library(tidyverse)
library(crackdownsphilanthropy)
library(rstan)
library(tidybayes)
library(broom)
library(ggstance)
library(ggdag)
library(ggraph)
library(patchwork)
library(pander)
library(scales)
library(janitor)
library(here)

source(here("analysis", "options.R"))

# Load data
results <- readRDS(here("data", "derived_data", "results_clean.rds"))
# qwraps2::lazyload_cache_dir("02_analysis_cache/html")

Causal pathway

Our theory and hypotheses are laid out in the causal pathway below. Our outcomes (Y: % likely to donate and amount donated) “listen to” or respond to C (crackdown), which is our main treatment or exposure. Funding (F) and issue (I) serve as heuristics for donation and influence a government’s decision to crack down on NGOs, hence the dual arrows to C and Y.

theory_dag <- dagify(Y ~ I + C + F,
                     C ~ I + F,
                     outcome = "Y",
                     exposure = "C",
                     labels = c("Y" = "Outcome (Likelihood of donation & amount donated)", 
                                "C" = "Anti-NGO legal crackdown", 
                                "I" = "NGO issue area", 
                                "F" = "NGO funding source")) %>% 
  tidy_dagitty(layout = "sugiyama")

plot_dag <- ggplot(theory_dag, aes(x = x, y = y, xend = xend, yend = yend)) +
  geom_dag_point(size = 6) +
  geom_dag_edges(start_cap = circle(4, "mm"),
                 end_cap = circle(4, "mm")) +
  geom_dag_text(size = pts(6), family = "Roboto Condensed", fontface = "bold") +
  geom_dag_label_repel(aes(label = label), size = pts(6), box.padding = 0.1, 
                       direction = "x", seed = 12345,
                       family = "Roboto Condensed", fontface = "plain") +
  labs(x = NULL) +
  theme_ngos() +
  theme(panel.grid = element_blank(),
        axis.title = element_blank(),
        axis.text = element_blank())

plot_dag %T>% 
  print() %T>%
  ggsave(., filename = here("analysis", "output", "figures", "causal-path.pdf"),
         width = 4.75, height = 2, units = "in", device = cairo_pdf) %>% 
  ggsave(., filename = here("analysis", "output", "figures", "causal-path.png"),
         width = 4.75, height = 2, units = "in", type = "cairo", dpi = 300)

Overview of data

Balance of experimental conditions

results %>% count(crackdown, issue, funding) %>% 
  rename(Crackdown = crackdown, Issue = issue, Funding = funding) %>% 
  janitor::adorn_totals(., where = "row") %T>% 
  pandoc.table() %>% 
  pandoc.table.return(caption = "Balance of experimental conditions {#tbl:experimental-conditions}") %>% 
  cat(file = here("analysis", "output", "tables", "tbl-experimental-conditions.md"))
Crackdown Issue Funding n
No crackdown Human rights Government 68
No crackdown Human rights Private 64
No crackdown Humanitarian assistance Government 68
No crackdown Humanitarian assistance Private 65
Crackdown Human rights Government 65
Crackdown Human rights Private 65
Crackdown Humanitarian assistance Government 68
Crackdown Humanitarian assistance Private 68
Total - - 531

Descriptive statistics table

vars_to_summarize <- tribble(
  ~variable_name, ~clean_name,
  "donate_likely", "Likelihood of donation",
  "donate_likely_bin", "Likelihood of donation (binary)",
  "amount_donate", "Amount hypothetically donated ($)",
  "gender", "Gender",
  "age", "Age",
  "income", "Income",
  "education", "Education",
  "religiosity", "Frequency of attending religious services",
  "ideology", "Political views",
  "political_knowledge", "Frequency of following public affairs",
  "give_charity", "Frequency of charitable donations",
  "volunteer", "Volunteered in past 12 months",
  "favor_humanitarian", "Prior favorability towards humanitarian NGOs",
  "favor_humanitarian_bin", "Prior favorability towards humanitarian NGOs (binary)",
  "favor_human_rights", "Prior favorability towards human rights NGOs",
  "favor_human_rights_bin", "Prior favorability towards human rights NGOs (binary)",
  "favor_development", "Prior favorability towards development NGOs",
  "favor_development_bin", "Prior favorability towards development NGOs (binary)",
  "check2", "Attention check 2"
)

results_summary_stats <- results %>% 
  select(one_of(vars_to_summarize$variable_name)) %>% 
  summarise_all(~list(.)) %>% 
  pivot_longer(everything(), names_to = "variable_name", values_to = "value") %>% 
  mutate(N = value %>% map_int(~ length(na.omit(.))),
         summary = map2(.x = value, .y = variable_name, ~ md_summary_row(.x, .y))) %>% 
  left_join(vars_to_summarize, by = "variable_name") %>% 
  mutate(variable_name = factor(variable_name, 
                                levels = vars_to_summarize$variable_name, 
                                ordered = TRUE)) %>% 
  arrange(variable_name) %>% 
  select(-value, -variable_name) %>% 
  unnest(summary) %>% 
  select(Variable = clean_name, N, ` ` = spark, Details = summary)

results_summary_stats %>% 
  select(-N) %>% 
  pandoc.table.return(caption = "Descriptive statistics {#tbl:descriptive-stats}",
                      split.cell = 80, split.table = Inf) %T>% 
  cat(file = here("analysis", "output", "tables", "tbl-descriptive-stats.md")) %>%
  cat()
Descriptive statistics {#tbl:descriptive-stats}
Variable Details
Likelihood of donation Extremely unlikely (46; 8.66%) | Somewhat unlikely (110; 20.72%) | Neither likely nor unlikely (138; 25.99%) | Somewhat likely (192; 36.16%) | Extremely likely (45; 8.47%)
Likelihood of donation (binary) Not likely (294; 55%) | Likely (237; 45%)
Amount hypothetically donated ($) Median: 10 | Mean: 22.4 | Std. Dev.: 25.67
Gender Female (291; 54.80%) | Male (237; 44.63%) | Other (1; 0.19%) | Prefer not to say (2; 0.38%)
Age Under 18 (1; 0.19%) | 18 – 24 (43; 8.10%) | 25 – 34 (207; 38.98%) | 35 – 44 (129; 24.29%) | 45 – 54 (90; 16.95%) | 55 – 64 (44; 8.29%) | 65 – 74 (16; 3.01%) | 75 – 84 (1; 0.19%)
Income Less than $10,000 (32; 6.03%) | $10,000 – $19,999 (43; 8.10%) | $20,000 – $29,999 (50; 9.42%) | $30,000 – $39,999 (78; 14.69%) | $40,000 – $49,999 (58; 10.92%) | $50,000 – $59,999 (55; 10.36%) | $60,000 – $69,999 (43; 8.10%) | $70,000 – $79,999 (38; 7.16%) | $80,000 – $89,999 (25; 4.71%) | $90,000 – $99,999 (30; 5.65%) | $100,000 – $149,999 (45; 8.47%) | More than $150,000 (21; 3.95%) | Prefer not to say (13; 2.45%)
Education Less than high school (2; 0.38%) | High school graduate (47; 8.85%) | Some college (128; 24.11%) | 2 year degree (68; 12.81%) | 4 year degree (212; 39.92%) | Graduate or professional degree (66; 12.43%) | Doctorate (8; 1.51%)
Frequency of attending religious services More than once a week (19; 3.58%) | Once a week (74; 13.94%) | Once or twice a month (50; 9.42%) | A few times a year (71; 13.37%) | Seldom (98; 18.46%) | Never (215; 40.49%) | Don’t know (4; 0.75%)
Political views Strong liberal (76; 14.31%) | Liberal (150; 28.25%) | Independent, leaning liberal (82; 15.44%) | Independent (80; 15.07%) | Independent, leaning conservative (60; 11.30%) | Conservative (61; 11.49%) | Very conservative (22; 4.14%)
Frequency of following public affairs Most of the time (217; 40.87%) | Some of the time (213; 40.11%) | Only now and then (84; 15.82%) | Hardly at all (17; 3.20%)
Frequency of charitable donations Once a week (37; 6.97%) | Once a month (105; 19.77%) | Once every three months (105; 19.77%) | Once every six months (102; 19.21%) | Once a year (89; 16.76%) | Once every few years (56; 10.55%) | Never (37; 6.97%)
Volunteered in past 12 months No (288; 54.2%) | Yes (243; 45.8%)
Prior favorability towards humanitarian NGOs Very unfavorable (2; 0.38%) | Unfavorable (6; 1.13%) | Neutral (39; 7.34%) | Favorable (235; 44.26%) | Very favorable (249; 46.89%)
Prior favorability towards humanitarian NGOs (binary) Not favorable (47; 9%) | Favorable (484; 91%)
Prior favorability towards human rights NGOs Very unfavorable (5; 0.94%) | Unfavorable (12; 2.26%) | Neutral (61; 11.49%) | Favorable (226; 42.56%) | Very favorable (227; 42.75%)
Prior favorability towards human rights NGOs (binary) Not favorable (78; 15%) | Favorable (453; 85%)
Prior favorability towards development NGOs Very unfavorable (5; 0.94%) | Unfavorable (8; 1.51%) | Neutral (45; 8.47%) | Favorable (235; 44.26%) | Very favorable (238; 44.82%)
Prior favorability towards development NGOs (binary) Not favorable (58; 11%) | Favorable (473; 89%)
Attention check 2 Correct (531; 100%)

Average likelihood and amount donated across conditions

conditions_summary <- bind_rows(group_by(results, crackdown, issue, funding) %>% nest(),
                                group_by(results, crackdown, issue) %>% nest(),
                                group_by(results, crackdown) %>% nest(),
                                results %>% nest(data = everything())) %>% 
  arrange(crackdown, issue, funding) %>% 
  mutate(summary = data %>%
           map(~ summarize(., pct_likely = table(donate_likely_bin)[["Likely"]] /
                             length(donate_likely_bin),
                           mean_donation = mean(amount_donate, na.rm = TRUE),
                           sd_donation = sd(amount_donate, na.rm = TRUE),
                           N = nrow(.)))) %>% 
  unnest(summary) %>% select(-data) %>% ungroup()

conditions_summary_clean <- conditions_summary %>% 
  mutate(funding = ifelse(is.na(funding) & !is.na(issue) , "*Total*", as.character(funding)),
         issue = ifelse(is.na(issue) & !is.na(crackdown), "*Total*", as.character(issue)),
         crackdown = ifelse(is.na(crackdown), "*Total*", as.character(crackdown))) %>% 
  group_by(crackdown) %>% 
  mutate(issue = replace(issue, duplicated(issue), NA)) %>% 
  ungroup() %>% 
  mutate(crackdown = replace(crackdown, duplicated(crackdown), NA)) %>% 
  mutate(pct_likely = percent(pct_likely)) %>% 
  rename(`Crackdown condition` = crackdown, `Issue condition` = issue,
         `Funding condition` = funding, `% likely to donate` = pct_likely,
         `Amount donated (mean)` = mean_donation, `Amount donated (sd)` = sd_donation)

conditions_summary_clean %T>% 
  pandoc.table() %>% 
  pandoc.table.return(caption = "Average likelihood and amount donated across experimental conditions {#tbl:avg-results}") %>% 
  cat(file = here("analysis", "output", "tables", "tbl-avg-results.md"))
Crackdown condition Issue condition Funding condition % likely to donate Amount donated (mean) Amount donated (sd) N
No crackdown Human rights Government 47.06% 22.4 24.8 68
Private 39.06% 19.3 22.4 64
Total 43.18% 20.9 23.6 132
Humanitarian assistance Government 44.12% 17.9 21.4 68
Private 40.00% 21.9 26.9 65
Total 42.11% 19.9 24.2 133
Total 42.64% 20.4 23.9 265
Crackdown Human rights Government 29.23% 19.4 25.8 65
Private 58.46% 28 26.4 65
Total 43.85% 23.7 26.3 130
Humanitarian assistance Government 51.47% 30.4 32.7 68
Private 47.06% 19.8 21.5 68
Total 49.26% 25.1 28.1 136
Total 46.62% 24.4 27.2 266
Total 44.63% 22.4 25.7 531


Visualize important variables

Likelihood of donation

donate_summary <- results %>% 
  count(donate_likely) %>% 
  mutate(perc = n / sum(n)) %>% 
  mutate(highlight = ifelse(donate_likely %in% c("Extremely likely", "Somewhat likely"), TRUE, FALSE))

plot_donate_summary <- ggplot(donate_summary, aes(x = n, y = donate_likely, 
                                                  fill = highlight)) +
  geom_barh(stat = "identity") +
  scale_x_continuous(sec.axis = sec_axis(~ . / sum(donate_summary$n),
                                         labels = percent_format(accuracy = 1))) +
  scale_fill_manual(values = ngo_cols("green", "blue", name = FALSE), guide = FALSE) +
  labs(x = NULL, y = NULL) +
  theme_ngos() +
  theme(panel.grid.major.y = element_blank())

plot_donate_summary %T>% 
  print() %T>%
  ggsave(., filename = here("analysis", "output", "figures", "donate_summary.pdf"),
         width = 9, height = 4, units = "in", device = cairo_pdf) %>% 
  ggsave(., filename = here("analysis", "output", "figures", "donate_summary.png"),
         width = 9, height = 4, units = "in", type = "cairo", dpi = 300)

Amount donated

plot_amount_summary <- ggplot(results, aes(x = amount_donate)) +
  geom_histogram(bins = 20, fill = ngo_cols("blue")) +
  scale_x_continuous(labels = dollar) +
  labs(x = NULL, y = NULL) +
  theme_ngos() +
  theme(panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank())

plot_amount_summary %T>% 
  print() %T>%
  ggsave(., filename = here("analysis", "output", "figures", "amount_summary.pdf"),
         width = 9, height = 2.75, units = "in", device = cairo_pdf) %>% 
  ggsave(., filename = here("analysis", "output", "figures", "amount_summary.png"),
         width = 9, height = 2.75, units = "in", type = "cairo", dpi = 300)


all_models <- tribble(
  ~title, ~df,
  "Crackdown", results,
  # Ha, cheat here by renaming the issue and funding columns to crackdown. 
  # All other tests are based on the crackdown column except these two, so
  # rather than build all sorts of convoluted arguments and functions, we just
  # rename these as issue and funding
  "Issue", mutate(results, crackdown = issue),
  "Funding", mutate(results, crackdown = funding),
  # Create all the nested conditions
  "Human rights | Crackdown", filter(results, issue == "Human rights"),
  "Humanitarian assistance | Crackdown", filter(results, issue != "Human rights"),
  "Government | Crackdown", filter(results, funding == "Government"),
  "Private | Crackdown", filter(results, funding == "Private"),
  "Human rights | Government | Crackdown", filter(results, issue == "Human rights", funding == "Government"),
  "Human rights | Private | Crackdown", filter(results, issue == "Human rights", funding == "Private"),
  "Humanitarian assistance | Government | Crackdown", filter(results, issue != "Human rights", funding == "Government"),
  "Humanitarian assistance | Private | Crackdown", filter(results, issue != "Human rights", funding == "Private")
) 

Treatment effects: Likelihood of donation

This time around, we’re not using interactionful regression models to calculate all these differences in groups. Instead we use real live Stan code to estimate the differences in group means and proportions!

Priors and models

We estimate the proportion of people responding that they’d be likely to donate to the organization with a binomial distribution, with a prior \(\theta\) distribution of \(\text{Beta}(5, 5)\). We build the following model in Stan:

\[ \begin{aligned} n_{\text{group 1, group 2}} &\sim \text{Binomial}(n_{\text{total in group}}, \theta_{\text{group}}) &\text{[likelihood]}\\ \text{Difference} &= n_{\text{group 2}} - n_{\text{group 1}} &\text{[difference in proportions]} \\ n &: \text{Number likely to donate} \\ \\ \theta_{\text{group 1, group 2}} &\sim \text{Beta}(5, 5) &\text{[prior prob. of being likely to donate]} \end{aligned} \]

likely_theta <- ggplot(data = tibble(x = c(0, 1)), aes(x = x)) +
  geom_area(stat = "function", fun = dbeta, args = list(shape1 = 5, shape2 = 5), 
            fill = "grey80", color = "black") +
  labs(x = expression(Probability ~ of ~ being ~ likely ~ to ~ donate ~ (theta)), y = "Density") +
  annotate(geom = "label", x = 0.5, y = 1, label = "Beta(5, 5)", size = pts(9)) +
  theme_ngos(base_size = 9, density = TRUE)
likely_theta

likely_theta %T>% 
  ggsave(., filename = here("analysis", "output", "figures", "prior-likely.pdf"),
         width = 2.75, height = 1.5, units = "in", device = cairo_pdf) %>%
  ggsave(., filename = here("analysis", "output", "figures", "prior-likely.png"),
         width = 2.75, height = 1.5, units = "in", type = "cairo", dpi = 300)

Differences

# This takes forever because of MCMC sampling, so this chunk is cached

# Sample from the compiled model
all_models_likely_run <- all_models %>% 
  # Simplify data for sending to Stan
  mutate(stan_data_counts = df %>% map(~ {
    df_counts <- .x %>% 
      count(crackdown, donate_likely_bin) %>% 
      group_by(crackdown) %>% 
      mutate(total = sum(n)) %>% 
      filter(donate_likely_bin == "Likely")
    
    return(list(
      n_total_1 = df_counts$total[1],
      n_total_2 = df_counts$total[2],
      n_likely_1 = df_counts$n[1],
      n_likely_2 = df_counts$n[2]
    ))
  })) %>% 
  # Run the actual model on the simplified data
  mutate(model = stan_data_counts %>% map(~ {
    donate_likely(n_total_1 = .x$n_total_1, n_total_2 = .x$n_total_2,
                  n_likely_1 = .x$n_likely_1, n_likely_2 = .x$n_likely_2,
                  control = list(max_treedepth = 15),
                  chains = CHAINS, iter = ITER, warmup = WARMUP, seed = BAYES_SEED)
  })) 

# Extract stuff
all_models_likely <- all_models_likely_run %>%
  # Extract posterior chains
  mutate(posterior_chains_long = map(model, ~ {
      .x %>% gather_draws(theta_1, theta_2, theta_diff, pct_change)
  })) %>% 
  mutate(posterior_chains_wide = map(model, ~ {
      .x %>% spread_draws(theta_1, theta_2, theta_diff, pct_change)
  })) %>% 
  # Get HDI medians in tidy form
  mutate(tidy = posterior_chains_long %>% map(~ {
    .x %>% median_hdci() %>% to_broom_names()
  }))
tidied_diffs_likely <- all_models_likely %>% 
  unnest(posterior_chains_long) %>% 
  filter(.variable == "theta_diff") %>% 
  mutate(category = case_when(
    str_count(title, "\\|") == 0 ~ "Level 1",
    str_count(title, "\\|") == 1 ~ "Level 2",
    str_count(title, "\\|") == 2 ~ "Level 3"
  )) %>% 
  mutate(title = str_remove(title, " \\| Crackdown"))

level1_likely <- tidied_diffs_likely %>% 
  filter(category == "Level 1") %>%
  mutate(title = recode(title, 
                        Crackdown = "Crackdown −\nNo crackdown",
                        Issue = "Humanitarian\nassistance −\nHuman rights",
                        Funding = "Private −\nGovernment\nfunding")) %>% 
  mutate(title = fct_inorder(title))

plot_diff_likely_a <- ggplot(level1_likely, aes(x = .value, y = fct_rev(title), fill = title)) +
  stat_halfeye(.width = c(0.8, 0.95)) +
  geom_vline(xintercept = 0) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  scale_fill_manual(values = ngo_cols(c("blue", "red", "orange"), name = FALSE), guide = FALSE) +
  labs(x = "Difference in donation likelihood", y = NULL, tag = "A") +
  theme_ngos(base_size = 8) +
  theme(panel.grid.major.y = element_blank())

level2_likely <- tidied_diffs_likely %>% 
  filter(category == "Level 2") %>%
  mutate(condition = case_when(
    title %in% c("Human rights", "Humanitarian assistance") ~ "Issue",
    title %in% c("Government", "Private") ~ "Funding"
  )) %>% 
  mutate(facet_title = case_when(
    title %in% c("Human rights", "Humanitarian assistance") ~ paste(title, "issues"),
    title %in% c("Government", "Private") ~ paste(title, "funding")
  )) %>% 
  mutate(title = case_when(
    title %in% c("Humanitarian assistance", "Private") ~ "",
    TRUE ~ "Crackdown −\nNo crackdown")
  )

plot_diff_likely_b <- ggplot(filter(level2_likely, condition == "Issue"), 
                             aes(x = .value, y = fct_rev(title))) +
  stat_halfeye(.width = c(0.8, 0.95), fill = ngo_cols("red", name = FALSE)) +
  geom_vline(xintercept = 0) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  labs(x = NULL, y = NULL, tag = "B") +
  facet_wrap(~ facet_title, scales = "free_y") +
  theme_ngos(base_size = 8) +
  theme(panel.grid.major.y = element_blank())

plot_diff_likely_c <- ggplot(filter(level2_likely, condition == "Funding"), 
                             aes(x = .value, y = fct_rev(title))) +
  stat_halfeye(.width = c(0.8, 0.95), fill = ngo_cols("orange", name = FALSE)) +
  geom_vline(xintercept = 0) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  labs(x = "Difference in donation likelihood", y = NULL, tag = "C") +
  facet_wrap(~ facet_title, scales = "free_y") +
  theme_ngos(base_size = 8) +
  theme(panel.grid.major.y = element_blank())

level3_likely <- tidied_diffs_likely %>% 
  filter(category == "Level 3") %>%
  separate(title, c("issue", "funding"), sep = " \\| ") %>%
  mutate(issue = paste(issue, "issues"),
         funding = paste(funding, "funding")) %>% 
  mutate(facet_title = paste0(issue, "\n", funding)) %>% 
  mutate(title = case_when(
    funding == "Private funding" ~ "",
    TRUE ~ "Crackdown −\nNo crackdown")
  )

plot_diff_likely_d <- ggplot(level3_likely, aes(x = .value, y = fct_rev(title))) +
  stat_halfeye(.width = c(0.8, 0.95), fill = ngo_cols("green", name = FALSE)) +
  geom_vline(xintercept = 0) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  labs(x = "Difference in donation likelihood", y = NULL, tag = "D",
       caption = "Point shows posterior median; thick black lines show 80% credible interval;\nthin black lines show 95% credible interval") +
  facet_wrap(~ facet_title, scales = "free_y") +
  theme_ngos(base_size = 8) +
  theme(panel.grid.major.y = element_blank())

plot_diffs_likely_all <- plot_diff_likely_a / 
  (plot_diff_likely_b / plot_diff_likely_c) / 
  plot_diff_likely_d

plot_diffs_likely_all

plot_diffs_likely_all %T>% 
  ggsave(., filename = here("analysis", "output", "figures", "likely-diffs.pdf"),
         width = 4.75, height = 5.5, units = "in", device = cairo_pdf) %>%
  ggsave(., filename = here("analysis", "output", "figures", "likely-diffs.png"),
         width = 4.75, height = 5.5, units = "in", type = "cairo", dpi = 300)
tbl_likely_tidy <- all_models_likely %>% 
  unnest(tidy) %>% 
  filter(term %in% c("theta_1", "theta_2", "theta_diff", "pct_change")) %>% 
  select(title, term, estimate) %>% 
  pivot_wider(names_from = term, values_from = estimate) %>%
  mutate(category = case_when(
    str_count(title, "\\|") == 0 ~ "Level 1",
    str_count(title, "\\|") == 1 ~ "Level 2",
    str_count(title, "\\|") == 2 ~ "Level 3"
  )) 

tbl_likely_probs <- all_models_likely %>% 
  unnest(posterior_chains_long) %>% 
  filter(.variable == "theta_diff") %>% 
  group_by(title) %>% 
  summarize(p.greater0 = mean(.value > 0),
            p.less0 = mean(.value < 0),
            p.diff.not0 = ifelse(median(.value) > 0, p.greater0, p.less0)) %>% 
  ungroup()

# Save combined table for later use in manuscript
tbl_likely_tidy %>% 
  left_join(tbl_likely_probs, by = "title") %>% 
  saveRDS(here("data", "derived_data", "results_models_likely.rds"))
  
tbl_likely_1 <- tbl_likely_tidy %>% 
  left_join(tbl_likely_probs, by = "title") %>% 
  filter(category == "Level 1") %>%
  mutate(title = recode(title, 
                        Crackdown = "Crackdown − No crackdown",
                        Issue = "*Humanitarian assistance − Human rights*",
                        Funding = "*Private − Government funding*")) %>% 
  mutate_at(vars(theta_1, theta_2, theta_diff, pct_change), 
            list(~percent_format(accuracy = 0.1)(.))) %>% 
  mutate(p.diff.not0 = as.character(round(p.diff.not0, 2))) %>%
  select(Frame = title, `% likely~Treatment~` = theta_2, `% likely~Control~` = theta_1,
         `$\\Delta$` = theta_diff, `$\\%\\Delta$` = pct_change, 
         `$p(\\Delta \\neq 0)$` = p.diff.not0)
tbl_likely_2 <- tbl_likely_tidy %>% 
  left_join(tbl_likely_probs, by = "title") %>% 
  filter(category == "Level 2") %>%
  mutate(title_clean = str_remove(title, " \\| Crackdown")) %>% 
  mutate(title_clean = case_when(
    title_clean %in% c("Human rights", "Humanitarian assistance") ~ paste(title_clean, "issues"),
    title_clean %in% c("Government", "Private") ~ paste(title_clean, "funding")
  )) %>% 
  mutate(title_clean = factor(title_clean, 
                              levels = c("Human rights issues", 
                                         "Humanitarian assistance issues", 
                                         "Government funding", "Private funding"))) %>% 
  arrange(title_clean) %>% 
  mutate_at(vars(theta_1, theta_2, theta_diff, pct_change), 
            list(~percent_format(accuracy = 0.1)(.))) %>% 
  mutate(p.diff.not0 = as.character(round(p.diff.not0, 2))) %>% 
  mutate(title_clean = as.character(title_clean)) %>% 
  select(`H~2a~ and H~3a~` = title_clean, 
         `% likely~Crackdown~` = theta_2, `% likely~No\\ crackdown~` = theta_1,
         `$\\Delta$` = theta_diff, `$\\%\\Delta$` = pct_change, 
         `$p(\\Delta \\neq 0)$` = p.diff.not0)
tbl_likely_3 <- tbl_likely_tidy %>% 
  left_join(tbl_likely_probs, by = "title") %>% 
  filter(category == "Level 3") %>%
  mutate(title_clean = str_remove(title, " \\| Crackdown")) %>% 
  separate(title_clean, c("Issue", "Funding"), sep = " \\| ") %>% 
  mutate(Issue = factor(Issue, levels = c("Human rights", "Humanitarian assistance")),
         Funding = factor(Funding, levels = c("Government", "Private"))) %>% 
  arrange(Issue, Funding) %>% 
  mutate_at(vars(theta_1, theta_2, theta_diff, pct_change), 
            list(~percent_format(accuracy = 0.1)(.))) %>% 
  mutate(p.diff.not0 = as.character(round(p.diff.not0, 2))) %>%
  mutate(Frame = paste0(Issue, " issues, ", Funding, " funding")) %>% 
  select(`H~2a~ and H~3a~ (nested)` = Frame,
         `% likely~Crackdown~` = theta_2, `% likely~No\\ crackdown~` = theta_1,
         `$\\Delta$` = theta_diff, `$\\%\\Delta$` = pct_change, 
         `$p(\\Delta \\neq 0)$` = p.diff.not0)
tbl_likely_2_header <- enframe(colnames(tbl_likely_2)) %>% 
  mutate(value = (value)) %>% 
  pivot_wider(names_from = name, values_from = value) %>% 
  set_names(colnames(tbl_likely_1))

tbl_likely_3_header <- enframe(colnames(tbl_likely_3)) %>% 
  mutate(value = (value)) %>% 
  pivot_wider(names_from = name, values_from = value) %>% 
  set_names(colnames(tbl_likely_1))

bind_rows(tbl_likely_1, 
          tbl_likely_2_header, 
          set_names(tbl_likely_2, colnames(tbl_likely_1)),
          tbl_likely_3_header,
          set_names(tbl_likely_3, colnames(tbl_likely_1))) %>% 
  rename(`H~1a~` = Frame) %>% 
  pandoc.table.return(caption = 'Likelihood of donation and differences in proportions in "crackdown" (treatment) and "no crackdown" (control) conditions; values represent posterior medians {#tbl:likely-diffs}',
                      justify = "lccccc") %T>%
  cat() %>%
  cat(file = here("analysis", "output", "tables", "tbl-likely-diffs.md"))
Likelihood of donation and differences in proportions in “crackdown” (treatment) and “no crackdown” (control) conditions; values represent posterior medians {#tbl:likely-diffs}
H1a % likelyTreatment % likelyControl \(\Delta\) \(\%\Delta\) \(p(\Delta \neq 0)\)
Crackdown − No crackdown 46.7% 42.9% 3.8% 8.9% 0.82
Humanitarian assistance − Human rights 45.9% 43.7% 2.3% 5.4% 0.7
Private − Government funding 46.3% 43.4% 2.9% 6.8% 0.75
H2a and H3a % likelyCrackdown % likelyNo crackdown \(\Delta\) \(\%\Delta\) \(p(\Delta \neq 0)\)
Human rights issues 44.3% 43.6% 0.6% 1.5% 0.54
Humanitarian assistance issues 49.4% 42.5% 6.8% 15.9% 0.88
Government funding 41.3% 45.8% -4.6% -10.0% 0.78
Private funding 52.4% 40.3% 12.1% 30.2% 0.98
H2a and H3a (nested) % likelyCrackdown % likelyNo crackdown \(\Delta\) \(\%\Delta\) \(p(\Delta \neq 0)\)
Human rights issues, Government funding 32.0% 47.4% -15.4% -32.5% 0.97
Human rights issues, Private funding 57.4% 40.4% 16.9% 41.5% 0.98
Humanitarian assistance issues, Government funding 51.4% 44.7% 6.8% 15.2% 0.8
Humanitarian assistance issues, Private funding 47.5% 41.2% 6.1% 14.8% 0.78


Treatment effects: Amount donated

Priors and models

Following John Kruschke’s “Bayesian Estimation Supersedes the t-test (BEST)” procedure, we estimate means for each group with a t-distribution. We use the following priors for the distribution parameters:

\[ \begin{aligned} x_{\text{group 1, group 2}} &\sim \text{Student } t(\nu, \mu, \sigma) &\text{[likelihood]}\\ \text{Difference} &= x_{\text{group 2}} - x_{\text{group 1}} &\text{[difference in means]} \\ x &: \text{Mean amount donated} \\ \\ \nu &\sim \text{Exponential}(1 / 29) &\text{[prior normality]} \\ \mu_{\text{group 1, group 2}} &\sim \mathcal{N}(\bar{x}_{\text{group 1, group 2}}, 10) &\text{[prior donation mean per group]}\\ \sigma_{\text{group 1, group 2}} &\sim \text{Cauchy}(0, 1)&\text{[prior donation sd per group]} \end{aligned} \]

amount_nu <- ggplot(data = tibble(x = c(0, 200)), aes(x = x)) +
  geom_area(stat = "function", fun = dexp, args = list(rate = 1/29), 
            fill = "grey80", color = "black") +
  labs(x = expression(Normality ~ parameter ~ (nu)), y = "Density") +
  annotate(geom = "label", x = 100, y = 0.009, 
           label = "Exponential(1/29)", size = pts(9)) +
  theme_ngos(base_size = 9, density = TRUE)

amount_mu <- ggplot(data = tibble(x = c(0, 100)), aes(x = x)) +
  geom_area(stat = "function", fun = dnorm, args = list(mean = 50, sd = 10),
            fill = "grey80", color = "black") +
  scale_x_continuous(breaks = c(seq(0, 100, 25)),
                     labels = c("−$50", "−$25", "Group average", "+$25", "+$50")) +
  annotate(geom = "label", x = 50, y = 0.01, label = "N(bar(x), 10)", 
           parse = TRUE, size = pts(9)) +
  labs(x = expression(Average ~ donated ~ (mu)), y = NULL) +
  theme_ngos(base_size = 9, density = TRUE)

amount_sigma <- ggplot(data = tibble(x = c(0, 10)), aes(x = x)) +
  geom_area(stat = "function", fun = dcauchy, args = list(location = 0, scale = 1),
            fill = "grey80", color = "black") +
  scale_x_continuous(labels = dollar) +
  annotate(geom = "label", x = 5, y = 0.08, label = "Cauchy(0, 1)", size = pts(9)) +
  labs(x = expression(SD ~ donated ~ (sigma)), y = NULL) +
  theme_ngos(base_size = 9, density = TRUE)

amount_priors <- amount_nu + amount_mu + amount_sigma
amount_priors

amount_priors %T>% 
  ggsave(., filename = here("analysis", "output", "figures", "prior-amount.pdf"),
         width = 8, height = 1.5, units = "in", device = cairo_pdf) %>%
  ggsave(., filename = here("analysis", "output", "figures", "prior-amount.png"),
         width = 8, height = 1.5, units = "in", type = "cairo", dpi = 300)

Differences

# Sample from the compiled model
all_models_amount_run <- all_models %>% 
  # Simplify data for sending to Stan
  mutate(stan_data = df %>% map(~ {
    select(.x, amount = amount_donate, group = crackdown)
  })) %>% 
  # Run the actual model on the simplified data
  mutate(model = stan_data %>% map(~ {
    amount_donated_best(df = .x, chains = CHAINS, iter = ITER, 
                        warmup = WARMUP, seed = BAYES_SEED)
  })) 

# Extract stuff
all_models_amount <- all_models_amount_run %>% 
  # Extract posterior chains
  mutate(posterior_chains_long = map2(model, stan_data, ~ {
    .x %>% 
      recover_types(.y) %>% 
      gather_draws(mu[group], sigma[group], mu_diff, pct_change, cohen_d, cles, nu, log10nu)
  })) %>% 
  mutate(posterior_chains_wide = map2(model, stan_data, ~ {
    .x %>% 
      recover_types(.y) %>% 
      spread_draws(mu[group], sigma[group], mu_diff, pct_change, cohen_d, cles, nu, log10nu)
  })) %>% 
  # Get HDI medians in tidy form
  mutate(tidy = posterior_chains_long %>% map(~ {
    .x %>% median_hdci() %>% to_broom_names()
  }))
all_models_amount <- all_models_amount %>% 
  # The `group` and `tidy` columns in each of these nested models contain
  # ordered factors, but we can't combine them with unnest() directly because
  # they have different levels (crackdown, issue, and funding), so we need to
  # make them unordered factors before unnesting
  mutate(posterior_chains_long = map(
    posterior_chains_long, ~mutate(., group = factor(group, ordered = FALSE)))
  ) %>% 
  mutate(tidy = map(
    tidy, ~mutate(., group = factor(group, ordered = FALSE)))
  )

tidied_diffs_amount <- all_models_amount %>% 
  unnest(posterior_chains_long) %>% 
  filter(.variable == "mu_diff") %>% 
  mutate(category = case_when(
    str_count(title, "\\|") == 0 ~ "Level 1",
    str_count(title, "\\|") == 1 ~ "Level 2",
    str_count(title, "\\|") == 2 ~ "Level 3"
  )) %>% 
  mutate(title = str_remove(title, " \\| Crackdown"))

level1_amount <- tidied_diffs_amount %>% 
  filter(category == "Level 1") %>%
  mutate(title = recode(title, 
                        Crackdown = "Crackdown −\nNo crackdown",
                        Issue = "Humanitarian\nassistance −\nHuman rights",
                        Funding = "Private −\nGovernment\nfunding")) %>% 
  mutate(title = fct_inorder(title))

plot_diff_amount_a <- ggplot(level1_amount, aes(x = .value, y = fct_rev(title), fill = title)) +
  geom_vline(xintercept = 0) +
  stat_halfeye(.width = c(0.8, 0.95)) +
  scale_x_continuous(labels = dollar) +
  scale_fill_manual(values = ngo_cols(c("blue", "red", "orange"), name = FALSE), guide = FALSE) +
  labs(x = "Difference in amount donated", y = NULL, tag = "A") +
  theme_ngos(base_size = 8) +
  theme(panel.grid.major.y = element_blank())

level2_amount <- tidied_diffs_amount %>% 
  filter(category == "Level 2") %>%
  mutate(condition = case_when(
    title %in% c("Human rights", "Humanitarian assistance") ~ "Issue",
    title %in% c("Government", "Private") ~ "Funding"
  )) %>% 
  mutate(facet_title = case_when(
    title %in% c("Human rights", "Humanitarian assistance") ~ paste(title, "issues"),
    title %in% c("Government", "Private") ~ paste(title, "funding")
  )) %>% 
  mutate(title = case_when(
    title %in% c("Humanitarian assistance", "Private") ~ "",
    TRUE ~ "Crackdown −\nNo crackdown")
  )

plot_diff_amount_b <- ggplot(filter(level2_amount, condition == "Issue"), 
                             aes(x = .value, y = fct_rev(title))) +
  stat_halfeye(.width = c(0.8, 0.95), fill = ngo_cols("red", name = FALSE)) +
  geom_vline(xintercept = 0) +
  scale_x_continuous(labels = dollar) +
  labs(x = NULL, y = NULL, tag = "B") +
  facet_wrap(~ facet_title, scales = "free_y") +
  theme_ngos(base_size = 8) +
  theme(panel.grid.major.y = element_blank())

plot_diff_amount_c <- ggplot(filter(level2_amount, condition == "Funding"), 
                             aes(x = .value, y = fct_rev(title))) +
  stat_halfeye(.width = c(0.8, 0.95), fill = ngo_cols("orange", name = FALSE)) +
  geom_vline(xintercept = 0) +
  scale_x_continuous(labels = dollar) +
  labs(x = "Difference in amount donated", y = NULL, tag = "C") +
  facet_wrap(~ facet_title, scales = "free_y") +
  theme_ngos(base_size = 8) +
  theme(panel.grid.major.y = element_blank())

level3_amount <- tidied_diffs_amount %>% 
  filter(category == "Level 3") %>%
  separate(title, c("issue", "funding"), sep = " \\| ") %>%
  mutate(issue = paste(issue, "issues"),
         funding = paste(funding, "funding")) %>% 
  mutate(facet_title = paste0(issue, "\n", funding)) %>% 
  mutate(title = case_when(
    funding == "Private funding" ~ "",
    TRUE ~ "Crackdown −\nNo crackdown")
  )

plot_diff_amount_d <- ggplot(level3_amount, aes(x = .value, y = fct_rev(title))) +
  stat_halfeye(.width = c(0.8, 0.95), fill = ngo_cols("green", name = FALSE)) +
  geom_vline(xintercept = 0) +
  scale_x_continuous(labels = dollar) +
  labs(x = "Difference in amount donated", y = NULL, tag = "D",
       caption = "Point shows posterior median; thick black lines show 80% credible interval;\nthin black lines show 95% credible interval") +
  facet_wrap(~ facet_title, scales = "free_y") +
  theme_ngos(base_size = 8) +
  theme(panel.grid.major.y = element_blank())

plot_diffs_amounts_all <- plot_diff_amount_a / 
  (plot_diff_amount_b / plot_diff_amount_c) / 
  plot_diff_amount_d

plot_diffs_amounts_all

plot_diffs_amounts_all %T>% 
  ggsave(., filename = here("analysis", "output", "figures", "amount-diffs.pdf"),
         width = 4.75, height = 5.5, units = "in", device = cairo_pdf) %>%
  ggsave(., filename = here("analysis", "output", "figures", "amount-diffs.png"),
         width = 4.75, height = 5.5, units = "in", type = "cairo", dpi = 300)
tbl_amounts_tidy <- all_models_amount %>% 
  unnest(tidy) %>% 
  filter(term %in% c("mu", "mu_diff", "pct_change")) %>% 
  group_by(title) %>% 
  mutate(group_id = 1:n()) %>% 
  mutate(term = case_when(
    term == "mu" ~ paste0(term, "_", group_id),
    TRUE ~ term
  )) %>% 
  select(title, term, estimate) %>% 
  pivot_wider(names_from = term, values_from = estimate) %>% 
  mutate(category = case_when(
    str_count(title, "\\|") == 0 ~ "Level 1",
    str_count(title, "\\|") == 1 ~ "Level 2",
    str_count(title, "\\|") == 2 ~ "Level 3"
  )) %>% 
  ungroup()

tbl_amounts_probs <- all_models_amount %>% 
  unnest(posterior_chains_long) %>% 
  filter(.variable == "mu_diff") %>% 
  group_by(title) %>% 
  summarize(p.greater0 = mean(.value > 0),
            p.less0 = mean(.value < 0),
            p.diff.not0 = ifelse(median(.value) > 0, p.greater0, p.less0)) %>% 
  ungroup()

# Save combined table for later use in manuscript
tbl_amounts_tidy %>% 
  left_join(tbl_amounts_probs, by = "title") %>% 
  saveRDS(here("data", "derived_data", "results_models_amount.rds"))

tbl_amount_1 <- tbl_amounts_tidy %>% 
  left_join(tbl_amounts_probs, by = "title") %>% 
  filter(category == "Level 1") %>%
  mutate(title = recode(title, 
                        Crackdown = "Crackdown − No crackdown",
                        Issue = "*Humanitarian assistance − Human rights*",
                        Funding = "*Private − Government funding*")) %>% 
  mutate_at(vars(mu_1, mu_2, mu_diff, p.diff.not0), list(~as.character(round(., 2)))) %>% 
  mutate(pct_change = percent_format(accuracy = 0.1)(pct_change)) %>%
  select(`Frame` = title, `Amount~Treatment~` = mu_2, `Amount~Control~` = mu_1,
         `$\\Delta$` = mu_diff, `$\\%\\Delta$` = pct_change, 
         `$p(\\Delta \\neq 0)$` = p.diff.not0)
tbl_amount_2 <- tbl_amounts_tidy %>% 
  left_join(tbl_amounts_probs, by = "title") %>% 
  filter(category == "Level 2") %>%
  mutate(title_clean = str_remove(title, " \\| Crackdown")) %>% 
  mutate(title_clean = case_when(
    title_clean %in% c("Human rights", "Humanitarian assistance") ~ paste(title_clean, "issues"),
    title_clean %in% c("Government", "Private") ~ paste(title_clean, "funding")
  )) %>% 
  mutate(title_clean = factor(title_clean, 
                              levels = c("Human rights issues", 
                                         "Humanitarian assistance issues", 
                                         "Government funding", "Private funding"))) %>% 
  arrange(title_clean) %>% 
  mutate_at(vars(mu_1, mu_2, mu_diff, p.diff.not0), list(~as.character(round(., 2)))) %>% 
  mutate(pct_change = percent_format(accuracy = 0.1)(pct_change)) %>%
  mutate(title_clean = as.character(title_clean)) %>% 
  select(`H~2b~ and H~3b~` = title_clean, `Amount~Crackdown~` = mu_2, `Amount~No\\ crackdown~` = mu_1,
         `$\\Delta$` = mu_diff, `$\\%\\Delta$` = pct_change, 
         `$p(\\Delta \\neq 0)$` = p.diff.not0)
tbl_amount_3 <- tbl_amounts_tidy %>% 
  left_join(tbl_amounts_probs, by = "title") %>% 
  filter(category == "Level 3") %>%
  mutate(title_clean = str_remove(title, " \\| Crackdown")) %>% 
  separate(title_clean, c("Issue", "Funding"), sep = " \\| ") %>% 
  mutate(Issue = factor(Issue, levels = c("Human rights", "Humanitarian assistance")),
         Funding = factor(Funding, levels = c("Government", "Private"))) %>% 
  arrange(Issue, Funding) %>% 
  mutate(Frame = paste0(Issue, " issues, ", Funding, " funding")) %>% 
  mutate_at(vars(mu_1, mu_2, mu_diff, p.diff.not0), list(~as.character(round(., 2)))) %>% 
  mutate(pct_change = percent_format(accuracy = 0.1)(pct_change)) %>%
  select(`H~2b~ and H~3b~ (nested)` = Frame,
         `Amount~Crackdown~` = mu_2, `Amount~No\\ crackdown~` = mu_1,
         `$\\Delta$` = mu_diff, `$\\%\\Delta$` = pct_change, 
         `$p(\\Delta \\neq 0)$` = p.diff.not0)
tbl_amount_2_header <- enframe(colnames(tbl_amount_2)) %>% 
  mutate(value = (value)) %>% 
  pivot_wider(names_from = name, values_from = value) %>% 
  set_names(colnames(tbl_amount_1))

tbl_amount_3_header <- enframe(colnames(tbl_amount_3)) %>% 
  mutate(value = (value)) %>% 
  pivot_wider(names_from = name, values_from = value) %>% 
  set_names(colnames(tbl_amount_1))

bind_rows(tbl_amount_1, 
          tbl_amount_2_header, 
          set_names(tbl_amount_2, colnames(tbl_amount_1)),
          tbl_amount_3_header,
          set_names(tbl_amount_3, colnames(tbl_amount_1))) %>% 
  rename(`H~1b~` = Frame) %>% 
  pandoc.table.return(caption = 'Mean values and differences in means for amount donated in "crackdown" (treatment) and "no crackdown" (control) conditions; values represent posterior medians {#tbl:amount-diffs}',
                      justify = "lccccc") %T>%
  cat() %>%
  cat(file = here("analysis", "output", "tables", "tbl-amount-diffs.md"))
Mean values and differences in means for amount donated in “crackdown” (treatment) and “no crackdown” (control) conditions; values represent posterior medians {#tbl:amount-diffs}
H1b AmountTreatment AmountControl \(\Delta\) \(\%\Delta\) \(p(\Delta \neq 0)\)
Crackdown − No crackdown 16.35 12.96 3.39 26.3% 0.97
Humanitarian assistance − Human rights 14.01 14.84 -0.78 -5.3% 0.66
Private − Government funding 15.11 13.65 1.44 10.6% 0.78
H2b and H3b AmountCrackdown AmountNo crackdown \(\Delta\) \(\%\Delta\) \(p(\Delta \neq 0)\)
Human rights issues 17.43 14.94 2.49 16.8% 0.83
Humanitarian assistance issues 16.01 11.74 4.27 36.5% 0.96
Government funding 13.87 12.26 1.64 13.5% 0.74
Private funding 18.97 14.33 4.55 31.6% 0.96
H2b and H3b (nested) AmountCrackdown AmountNo crackdown \(\Delta\) \(\%\Delta\) \(p(\Delta \neq 0)\)
Human rights issues, Government funding 10.55 15.04 -4.49 -29.9% 0.9
Human rights issues, Private funding 23.71 14.5 9.09 62.7% 0.99
Humanitarian assistance issues, Government funding 21.42 11.97 9.18 76.4% 0.99
Humanitarian assistance issues, Private funding 15.73 15.79 -0.03 -0.2% 0.5

Effect size

# Effect size
# (μ₁ - μ₂) / sqrt( (σ₁² + σ₂²) / 2)
tidied_eff_size_amount <- all_models_amount %>% 
  unnest(posterior_chains_long) %>% 
  filter(.variable == "cohen_d") %>% 
  mutate(category = case_when(
    str_count(title, "\\|") == 0 ~ "Level 1",
    str_count(title, "\\|") == 1 ~ "Level 2",
    str_count(title, "\\|") == 2 ~ "Level 3"
  )) %>% 
  mutate(title = str_remove(title, " \\| Crackdown")) %>% 
  mutate(title = fct_inorder(title))

effect_sizes <- tribble(
  ~size, ~x_end,
  "Small", 0.2,
  "Medium", 0.5,
  "Large", 0.8
) %>% 
  mutate(x_start = -x_end)

ggplot(tidied_eff_size_amount, aes(x = .value, y = fct_rev(title))) +
  stat_halfeye(.width = c(0.8, 0.95)) +
  geom_vline(xintercept = 0, size = 1) +
  geom_vline(xintercept = c(0.2, -0.2), linetype = "dotted", size = 0.5) +
  geom_vline(xintercept = c(0.5, -0.5), linetype = "dotted", size = 0.5) +
  geom_vline(xintercept = c(0.5, -0.5), linetype = "dotted", size = 0.5) +
  coord_cartesian(xlim = c(-1, 1)) +
  labs(x = "Cohen's d (effect size)", y = NULL) +
  theme_ngos()


Original computing environment

writeLines(readLines(file.path(Sys.getenv("HOME"), ".R/Makevars")))
## # http://dirk.eddelbuettel.com/blog/2017/11/27/#011_faster_package_installation_one
## VER=
## CCACHE=ccache
## CC=$(CCACHE) gcc$(VER)
## CXX=$(CCACHE) g++$(VER)
## CXX11=$(CCACHE) g++$(VER)
## CXX14=$(CCACHE) g++$(VER)
## FC=$(CCACHE) gfortran$(VER)
## F77=$(CCACHE) gfortran$(VER)
## 
## CXX14FLAGS=-O3 -march=native -mtune=native -fPIC
devtools::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value                       
##  version  R version 4.0.2 (2020-06-22)
##  os       macOS Catalina 10.15.6      
##  system   x86_64, darwin17.0          
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  ctype    en_US.UTF-8                 
##  tz       America/New_York            
##  date     2020-10-01                  
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package                * version  date       lib source        
##  arrayhelpers             1.1-0    2020-02-04 [1] CRAN (R 4.0.0)
##  assertthat               0.2.1    2019-03-21 [1] CRAN (R 4.0.0)
##  backports                1.1.9    2020-08-24 [1] CRAN (R 4.0.2)
##  base64enc                0.1-3    2015-07-28 [1] CRAN (R 4.0.0)
##  blob                     1.2.1    2020-01-20 [1] CRAN (R 4.0.0)
##  boot                     1.3-25   2020-04-26 [1] CRAN (R 4.0.2)
##  broom                  * 0.7.0    2020-07-09 [1] CRAN (R 4.0.2)
##  callr                    3.4.3    2020-03-28 [1] CRAN (R 4.0.0)
##  cellranger               1.1.0    2016-07-27 [1] CRAN (R 4.0.0)
##  cli                      2.0.2    2020-02-28 [1] CRAN (R 4.0.0)
##  coda                     0.19-3   2019-07-05 [1] CRAN (R 4.0.0)
##  codetools                0.2-16   2018-12-24 [1] CRAN (R 4.0.2)
##  colorspace               1.4-1    2019-03-18 [1] CRAN (R 4.0.0)
##  crackdownsphilanthropy * 0.9      2020-10-01 [1] local         
##  crayon                   1.3.4    2017-09-16 [1] CRAN (R 4.0.0)
##  curl                     4.3      2019-12-02 [1] CRAN (R 4.0.0)
##  dagitty                  0.3-0    2020-07-21 [1] CRAN (R 4.0.2)
##  DBI                      1.1.0    2019-12-15 [1] CRAN (R 4.0.0)
##  dbplyr                   1.4.4    2020-05-27 [1] CRAN (R 4.0.2)
##  desc                     1.2.0    2018-05-01 [1] CRAN (R 4.0.0)
##  devtools                 2.3.1    2020-07-21 [1] CRAN (R 4.0.2)
##  digest                   0.6.25   2020-02-23 [1] CRAN (R 4.0.0)
##  distributional           0.2.0    2020-08-03 [1] CRAN (R 4.0.2)
##  dplyr                  * 1.0.2    2020-08-18 [1] CRAN (R 4.0.2)
##  ellipsis                 0.3.1    2020-05-15 [1] CRAN (R 4.0.0)
##  evaluate                 0.14     2019-05-28 [1] CRAN (R 4.0.0)
##  fansi                    0.4.1    2020-01-08 [1] CRAN (R 4.0.0)
##  farver                   2.0.3    2020-01-16 [1] CRAN (R 4.0.0)
##  forcats                * 0.5.0    2020-03-01 [1] CRAN (R 4.0.0)
##  fs                       1.5.0    2020-07-31 [1] CRAN (R 4.0.2)
##  generics                 0.0.2    2018-11-29 [1] CRAN (R 4.0.0)
##  ggdag                  * 0.2.2    2020-02-13 [1] CRAN (R 4.0.0)
##  ggdist                   2.2.0    2020-07-12 [1] CRAN (R 4.0.2)
##  ggforce                  0.3.2    2020-06-23 [1] CRAN (R 4.0.2)
##  ggplot2                * 3.3.2    2020-06-19 [1] CRAN (R 4.0.2)
##  ggraph                 * 2.0.3    2020-05-20 [1] CRAN (R 4.0.2)
##  ggrepel                  0.8.2    2020-03-08 [1] CRAN (R 4.0.0)
##  ggstance               * 0.3.4    2020-04-02 [1] CRAN (R 4.0.0)
##  glue                     1.4.2    2020-08-27 [1] CRAN (R 4.0.2)
##  graphlayouts             0.7.0    2020-04-25 [1] CRAN (R 4.0.0)
##  gridExtra                2.3      2017-09-09 [1] CRAN (R 4.0.0)
##  gtable                   0.3.0    2019-03-25 [1] CRAN (R 4.0.0)
##  haven                    2.3.1    2020-06-01 [1] CRAN (R 4.0.2)
##  here                   * 0.1      2017-05-28 [1] CRAN (R 4.0.0)
##  hms                      0.5.3    2020-01-08 [1] CRAN (R 4.0.0)
##  htmltools                0.5.0    2020-06-16 [1] CRAN (R 4.0.0)
##  httr                     1.4.2    2020-07-20 [1] CRAN (R 4.0.2)
##  igraph                   1.2.5    2020-03-19 [1] CRAN (R 4.0.0)
##  inline                   0.3.15   2018-05-18 [1] CRAN (R 4.0.0)
##  janitor                * 2.0.1    2020-04-12 [1] CRAN (R 4.0.0)
##  jsonlite                 1.7.0    2020-06-25 [1] CRAN (R 4.0.2)
##  knitr                    1.29     2020-06-23 [1] CRAN (R 4.0.2)
##  labeling                 0.3      2014-08-23 [1] CRAN (R 4.0.0)
##  lattice                  0.20-41  2020-04-02 [1] CRAN (R 4.0.2)
##  lifecycle                0.2.0    2020-03-06 [1] CRAN (R 4.0.0)
##  loo                      2.3.1    2020-07-14 [1] CRAN (R 4.0.2)
##  lubridate                1.7.9    2020-06-08 [1] CRAN (R 4.0.2)
##  magrittr                 1.5      2014-11-22 [1] CRAN (R 4.0.0)
##  MASS                     7.3-52   2020-08-18 [1] CRAN (R 4.0.2)
##  matrixStats              0.56.0   2020-03-13 [1] CRAN (R 4.0.0)
##  memoise                  1.1.0    2017-04-21 [1] CRAN (R 4.0.0)
##  modelr                   0.1.8    2020-05-19 [1] CRAN (R 4.0.2)
##  munsell                  0.5.0    2018-06-12 [1] CRAN (R 4.0.0)
##  pander                 * 0.6.3    2018-11-06 [1] CRAN (R 4.0.0)
##  patchwork              * 1.0.1    2020-06-22 [1] CRAN (R 4.0.2)
##  pillar                   1.4.6    2020-07-10 [1] CRAN (R 4.0.2)
##  pkgbuild                 1.1.0    2020-07-13 [1] CRAN (R 4.0.2)
##  pkgconfig                2.0.3    2019-09-22 [1] CRAN (R 4.0.0)
##  pkgload                  1.1.0    2020-05-29 [1] CRAN (R 4.0.2)
##  plyr                     1.8.6    2020-03-03 [1] CRAN (R 4.0.0)
##  polyclip                 1.10-0   2019-03-14 [1] CRAN (R 4.0.0)
##  prettyunits              1.1.1    2020-01-24 [1] CRAN (R 4.0.0)
##  processx                 3.4.3    2020-07-05 [1] CRAN (R 4.0.0)
##  ps                       1.3.4    2020-08-11 [1] CRAN (R 4.0.2)
##  purrr                  * 0.3.4    2020-04-17 [1] CRAN (R 4.0.0)
##  R6                       2.4.1    2019-11-12 [1] CRAN (R 4.0.0)
##  Rcpp                     1.0.5    2020-07-06 [1] CRAN (R 4.0.2)
##  RcppParallel             5.0.2    2020-06-24 [1] CRAN (R 4.0.2)
##  readr                  * 1.3.1    2018-12-21 [1] CRAN (R 4.0.0)
##  readxl                   1.3.1    2019-03-13 [1] CRAN (R 4.0.0)
##  remotes                  2.2.0    2020-07-21 [1] CRAN (R 4.0.2)
##  reprex                   0.3.0    2019-05-16 [1] CRAN (R 4.0.0)
##  rlang                    0.4.7    2020-07-09 [1] CRAN (R 4.0.2)
##  rmarkdown                2.3      2020-06-18 [1] CRAN (R 4.0.2)
##  rprojroot                1.3-2    2018-01-03 [1] CRAN (R 4.0.0)
##  rstan                  * 2.21.2   2020-07-27 [1] CRAN (R 4.0.2)
##  rstudioapi               0.11     2020-02-07 [1] CRAN (R 4.0.0)
##  rvest                    0.3.6    2020-07-25 [1] CRAN (R 4.0.2)
##  scales                 * 1.1.1    2020-05-11 [1] CRAN (R 4.0.0)
##  sessioninfo              1.1.1    2018-11-05 [1] CRAN (R 4.0.0)
##  snakecase                0.11.0   2019-05-25 [1] CRAN (R 4.0.0)
##  StanHeaders            * 2.21.0-6 2020-08-16 [1] CRAN (R 4.0.2)
##  stringi                  1.4.6    2020-02-17 [1] CRAN (R 4.0.0)
##  stringr                * 1.4.0    2019-02-10 [1] CRAN (R 4.0.0)
##  svUnit                   1.0.3    2020-04-20 [1] CRAN (R 4.0.0)
##  testthat                 2.3.2    2020-03-02 [1] CRAN (R 4.0.0)
##  tibble                 * 3.0.3    2020-07-10 [1] CRAN (R 4.0.2)
##  tidybayes              * 2.1.1    2020-06-19 [1] CRAN (R 4.0.2)
##  tidygraph                1.2.0    2020-05-12 [1] CRAN (R 4.0.0)
##  tidyr                  * 1.1.2    2020-08-27 [1] CRAN (R 4.0.2)
##  tidyselect               1.1.0    2020-05-11 [1] CRAN (R 4.0.0)
##  tidyverse              * 1.3.0    2019-11-21 [1] CRAN (R 4.0.0)
##  tweenr                   1.0.1    2018-12-14 [1] CRAN (R 4.0.0)
##  usethis                  1.6.1    2020-04-29 [1] CRAN (R 4.0.0)
##  V8                       3.2.0    2020-06-19 [1] CRAN (R 4.0.2)
##  vctrs                    0.3.4    2020-08-29 [1] CRAN (R 4.0.2)
##  viridis                  0.5.1    2018-03-29 [1] CRAN (R 4.0.0)
##  viridisLite              0.3.0    2018-02-01 [1] CRAN (R 4.0.0)
##  withr                    2.2.0    2020-04-20 [1] CRAN (R 4.0.0)
##  xfun                     0.16     2020-07-24 [1] CRAN (R 4.0.2)
##  xml2                     1.3.2    2020-04-23 [1] CRAN (R 4.0.0)
##  yaml                     2.2.1    2020-02-01 [1] CRAN (R 4.0.0)
## 
## [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library
LS0tCnRpdGxlOiAiUmVzdWx0cyIKYXV0aG9yOiAiQW5kcmV3IEhlaXNzIGFuZCBTdXBhcm5hIENoYXVkaHJ5IgpkYXRlOiAiTGFzdCBydW46IGByIGZvcm1hdChTeXMudGltZSgpLCAnJUYnKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgcGFuZG9jX2FyZ3M6CiAgICAgIC0gIi0tZGVmYXVsdC1pbWFnZS1leHRlbnNpb249cG5nIgplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5yZXRpbmEgPSAzLCBmaWcuYWxpZ24gPSAiY2VudGVyIikKYGBgCgpgYGB7ciBsb2FkLWxpYnJhcmllcy1kYXRhLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShjcmFja2Rvd25zcGhpbGFudGhyb3B5KQpsaWJyYXJ5KHJzdGFuKQpsaWJyYXJ5KHRpZHliYXllcykKbGlicmFyeShicm9vbSkKbGlicmFyeShnZ3N0YW5jZSkKbGlicmFyeShnZ2RhZykKbGlicmFyeShnZ3JhcGgpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHBhbmRlcikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoamFuaXRvcikKbGlicmFyeShoZXJlKQoKc291cmNlKGhlcmUoImFuYWx5c2lzIiwgIm9wdGlvbnMuUiIpKQoKIyBMb2FkIGRhdGEKcmVzdWx0cyA8LSByZWFkUkRTKGhlcmUoImRhdGEiLCAiZGVyaXZlZF9kYXRhIiwgInJlc3VsdHNfY2xlYW4ucmRzIikpCiMgcXdyYXBzMjo6bGF6eWxvYWRfY2FjaGVfZGlyKCIwMl9hbmFseXNpc19jYWNoZS9odG1sIikKYGBgCgoKIyBDYXVzYWwgcGF0aHdheQoKT3VyIHRoZW9yeSBhbmQgaHlwb3RoZXNlcyBhcmUgbGFpZCBvdXQgaW4gdGhlIGNhdXNhbCBwYXRod2F5IGJlbG93LiBPdXIgb3V0Y29tZXMgKFk6ICUgbGlrZWx5IHRvIGRvbmF0ZSBhbmQgYW1vdW50IGRvbmF0ZWQpICJsaXN0ZW4gdG8iIG9yIHJlc3BvbmQgdG8gQyAoY3JhY2tkb3duKSwgd2hpY2ggaXMgb3VyIG1haW4gdHJlYXRtZW50IG9yIGV4cG9zdXJlLiBGdW5kaW5nIChGKSBhbmQgaXNzdWUgKEkpIHNlcnZlIGFzIGhldXJpc3RpY3MgZm9yIGRvbmF0aW9uIGFuZCBpbmZsdWVuY2UgYSBnb3Zlcm5tZW50J3MgZGVjaXNpb24gdG8gY3JhY2sgZG93biBvbiBOR09zLCBoZW5jZSB0aGUgZHVhbCBhcnJvd3MgdG8gQyBhbmQgWS4gCgpgYGB7ciBjYXVzYWwtZGFnLCBmaWcud2lkdGg9NC43NSwgZmlnLmhlaWdodD0yLCBvdXQud2lkdGg9IjcwJSJ9CnRoZW9yeV9kYWcgPC0gZGFnaWZ5KFkgfiBJICsgQyArIEYsCiAgICAgICAgICAgICAgICAgICAgIEMgfiBJICsgRiwKICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZSA9ICJZIiwKICAgICAgICAgICAgICAgICAgICAgZXhwb3N1cmUgPSAiQyIsCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlkiID0gIk91dGNvbWUgKExpa2VsaWhvb2Qgb2YgZG9uYXRpb24gJiBhbW91bnQgZG9uYXRlZCkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQyIgPSAiQW50aS1OR08gbGVnYWwgY3JhY2tkb3duIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkkiID0gIk5HTyBpc3N1ZSBhcmVhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkYiID0gIk5HTyBmdW5kaW5nIHNvdXJjZSIpKSAlPiUgCiAgdGlkeV9kYWdpdHR5KGxheW91dCA9ICJzdWdpeWFtYSIpCgpwbG90X2RhZyA8LSBnZ3Bsb3QodGhlb3J5X2RhZywgYWVzKHggPSB4LCB5ID0geSwgeGVuZCA9IHhlbmQsIHllbmQgPSB5ZW5kKSkgKwogIGdlb21fZGFnX3BvaW50KHNpemUgPSA2KSArCiAgZ2VvbV9kYWdfZWRnZXMoc3RhcnRfY2FwID0gY2lyY2xlKDQsICJtbSIpLAogICAgICAgICAgICAgICAgIGVuZF9jYXAgPSBjaXJjbGUoNCwgIm1tIikpICsKICBnZW9tX2RhZ190ZXh0KHNpemUgPSBwdHMoNiksIGZhbWlseSA9ICJSb2JvdG8gQ29uZGVuc2VkIiwgZm9udGZhY2UgPSAiYm9sZCIpICsKICBnZW9tX2RhZ19sYWJlbF9yZXBlbChhZXMobGFiZWwgPSBsYWJlbCksIHNpemUgPSBwdHMoNiksIGJveC5wYWRkaW5nID0gMC4xLCAKICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAieCIsIHNlZWQgPSAxMjM0NSwKICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSAiUm9ib3RvIENvbmRlbnNlZCIsIGZvbnRmYWNlID0gInBsYWluIikgKwogIGxhYnMoeCA9IE5VTEwpICsKICB0aGVtZV9uZ29zKCkgKwogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpCgpwbG90X2RhZyAlVD4lIAogIHByaW50KCkgJVQ+JQogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoImFuYWx5c2lzIiwgIm91dHB1dCIsICJmaWd1cmVzIiwgImNhdXNhbC1wYXRoLnBkZiIpLAogICAgICAgICB3aWR0aCA9IDQuNzUsIGhlaWdodCA9IDIsIHVuaXRzID0gImluIiwgZGV2aWNlID0gY2Fpcm9fcGRmKSAlPiUgCiAgZ2dzYXZlKC4sIGZpbGVuYW1lID0gaGVyZSgiYW5hbHlzaXMiLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAiY2F1c2FsLXBhdGgucG5nIiksCiAgICAgICAgIHdpZHRoID0gNC43NSwgaGVpZ2h0ID0gMiwgdW5pdHMgPSAiaW4iLCB0eXBlID0gImNhaXJvIiwgZHBpID0gMzAwKQpgYGAKCgojIE92ZXJ2aWV3IG9mIGRhdGEKCiMjIEJhbGFuY2Ugb2YgZXhwZXJpbWVudGFsIGNvbmRpdGlvbnMKCmBgYHtyIGNoZWNrLWNvbmRpdGlvbnMsIHJlc3VsdHM9ImFzaXMifQpyZXN1bHRzICU+JSBjb3VudChjcmFja2Rvd24sIGlzc3VlLCBmdW5kaW5nKSAlPiUgCiAgcmVuYW1lKENyYWNrZG93biA9IGNyYWNrZG93biwgSXNzdWUgPSBpc3N1ZSwgRnVuZGluZyA9IGZ1bmRpbmcpICU+JSAKICBqYW5pdG9yOjphZG9ybl90b3RhbHMoLiwgd2hlcmUgPSAicm93IikgJVQ+JSAKICBwYW5kb2MudGFibGUoKSAlPiUgCiAgcGFuZG9jLnRhYmxlLnJldHVybihjYXB0aW9uID0gIkJhbGFuY2Ugb2YgZXhwZXJpbWVudGFsIGNvbmRpdGlvbnMgeyN0Ymw6ZXhwZXJpbWVudGFsLWNvbmRpdGlvbnN9IikgJT4lIAogIGNhdChmaWxlID0gaGVyZSgiYW5hbHlzaXMiLCAib3V0cHV0IiwgInRhYmxlcyIsICJ0YmwtZXhwZXJpbWVudGFsLWNvbmRpdGlvbnMubWQiKSkKYGBgCgojIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIHRhYmxlCgpgYGB7ciB0YmwtZGVzY3JpcHRpdmUtc3RhdGlzdGljcywgcmVzdWx0cz0iYXNpcyJ9CnZhcnNfdG9fc3VtbWFyaXplIDwtIHRyaWJibGUoCiAgfnZhcmlhYmxlX25hbWUsIH5jbGVhbl9uYW1lLAogICJkb25hdGVfbGlrZWx5IiwgIkxpa2VsaWhvb2Qgb2YgZG9uYXRpb24iLAogICJkb25hdGVfbGlrZWx5X2JpbiIsICJMaWtlbGlob29kIG9mIGRvbmF0aW9uIChiaW5hcnkpIiwKICAiYW1vdW50X2RvbmF0ZSIsICJBbW91bnQgaHlwb3RoZXRpY2FsbHkgZG9uYXRlZCAoJCkiLAogICJnZW5kZXIiLCAiR2VuZGVyIiwKICAiYWdlIiwgIkFnZSIsCiAgImluY29tZSIsICJJbmNvbWUiLAogICJlZHVjYXRpb24iLCAiRWR1Y2F0aW9uIiwKICAicmVsaWdpb3NpdHkiLCAiRnJlcXVlbmN5IG9mIGF0dGVuZGluZyByZWxpZ2lvdXMgc2VydmljZXMiLAogICJpZGVvbG9neSIsICJQb2xpdGljYWwgdmlld3MiLAogICJwb2xpdGljYWxfa25vd2xlZGdlIiwgIkZyZXF1ZW5jeSBvZiBmb2xsb3dpbmcgcHVibGljIGFmZmFpcnMiLAogICJnaXZlX2NoYXJpdHkiLCAiRnJlcXVlbmN5IG9mIGNoYXJpdGFibGUgZG9uYXRpb25zIiwKICAidm9sdW50ZWVyIiwgIlZvbHVudGVlcmVkIGluIHBhc3QgMTIgbW9udGhzIiwKICAiZmF2b3JfaHVtYW5pdGFyaWFuIiwgIlByaW9yIGZhdm9yYWJpbGl0eSB0b3dhcmRzIGh1bWFuaXRhcmlhbiBOR09zIiwKICAiZmF2b3JfaHVtYW5pdGFyaWFuX2JpbiIsICJQcmlvciBmYXZvcmFiaWxpdHkgdG93YXJkcyBodW1hbml0YXJpYW4gTkdPcyAoYmluYXJ5KSIsCiAgImZhdm9yX2h1bWFuX3JpZ2h0cyIsICJQcmlvciBmYXZvcmFiaWxpdHkgdG93YXJkcyBodW1hbiByaWdodHMgTkdPcyIsCiAgImZhdm9yX2h1bWFuX3JpZ2h0c19iaW4iLCAiUHJpb3IgZmF2b3JhYmlsaXR5IHRvd2FyZHMgaHVtYW4gcmlnaHRzIE5HT3MgKGJpbmFyeSkiLAogICJmYXZvcl9kZXZlbG9wbWVudCIsICJQcmlvciBmYXZvcmFiaWxpdHkgdG93YXJkcyBkZXZlbG9wbWVudCBOR09zIiwKICAiZmF2b3JfZGV2ZWxvcG1lbnRfYmluIiwgIlByaW9yIGZhdm9yYWJpbGl0eSB0b3dhcmRzIGRldmVsb3BtZW50IE5HT3MgKGJpbmFyeSkiLAogICJjaGVjazIiLCAiQXR0ZW50aW9uIGNoZWNrIDIiCikKCnJlc3VsdHNfc3VtbWFyeV9zdGF0cyA8LSByZXN1bHRzICU+JSAKICBzZWxlY3Qob25lX29mKHZhcnNfdG9fc3VtbWFyaXplJHZhcmlhYmxlX25hbWUpKSAlPiUgCiAgc3VtbWFyaXNlX2FsbCh+bGlzdCguKSkgJT4lIAogIHBpdm90X2xvbmdlcihldmVyeXRoaW5nKCksIG5hbWVzX3RvID0gInZhcmlhYmxlX25hbWUiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUgCiAgbXV0YXRlKE4gPSB2YWx1ZSAlPiUgbWFwX2ludCh+IGxlbmd0aChuYS5vbWl0KC4pKSksCiAgICAgICAgIHN1bW1hcnkgPSBtYXAyKC54ID0gdmFsdWUsIC55ID0gdmFyaWFibGVfbmFtZSwgfiBtZF9zdW1tYXJ5X3JvdygueCwgLnkpKSkgJT4lIAogIGxlZnRfam9pbih2YXJzX3RvX3N1bW1hcml6ZSwgYnkgPSAidmFyaWFibGVfbmFtZSIpICU+JSAKICBtdXRhdGUodmFyaWFibGVfbmFtZSA9IGZhY3Rvcih2YXJpYWJsZV9uYW1lLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB2YXJzX3RvX3N1bW1hcml6ZSR2YXJpYWJsZV9uYW1lLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpICU+JSAKICBhcnJhbmdlKHZhcmlhYmxlX25hbWUpICU+JSAKICBzZWxlY3QoLXZhbHVlLCAtdmFyaWFibGVfbmFtZSkgJT4lIAogIHVubmVzdChzdW1tYXJ5KSAlPiUgCiAgc2VsZWN0KFZhcmlhYmxlID0gY2xlYW5fbmFtZSwgTiwgYCBgID0gc3BhcmssIERldGFpbHMgPSBzdW1tYXJ5KQoKcmVzdWx0c19zdW1tYXJ5X3N0YXRzICU+JSAKICBzZWxlY3QoLU4pICU+JSAKICBwYW5kb2MudGFibGUucmV0dXJuKGNhcHRpb24gPSAiRGVzY3JpcHRpdmUgc3RhdGlzdGljcyB7I3RibDpkZXNjcmlwdGl2ZS1zdGF0c30iLAogICAgICAgICAgICAgICAgICAgICAgc3BsaXQuY2VsbCA9IDgwLCBzcGxpdC50YWJsZSA9IEluZikgJVQ+JSAKICBjYXQoZmlsZSA9IGhlcmUoImFuYWx5c2lzIiwgIm91dHB1dCIsICJ0YWJsZXMiLCAidGJsLWRlc2NyaXB0aXZlLXN0YXRzLm1kIikpICU+JQogIGNhdCgpCmBgYAoKIyMgQXZlcmFnZSBsaWtlbGlob29kIGFuZCBhbW91bnQgZG9uYXRlZCBhY3Jvc3MgY29uZGl0aW9ucwoKYGBge3IgdGJsLXJlc3VsdHMtY29uZGl0aW9ucywgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0iYXNpcyJ9CmNvbmRpdGlvbnNfc3VtbWFyeSA8LSBiaW5kX3Jvd3MoZ3JvdXBfYnkocmVzdWx0cywgY3JhY2tkb3duLCBpc3N1ZSwgZnVuZGluZykgJT4lIG5lc3QoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShyZXN1bHRzLCBjcmFja2Rvd24sIGlzc3VlKSAlPiUgbmVzdCgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KHJlc3VsdHMsIGNyYWNrZG93bikgJT4lIG5lc3QoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzICU+JSBuZXN0KGRhdGEgPSBldmVyeXRoaW5nKCkpKSAlPiUgCiAgYXJyYW5nZShjcmFja2Rvd24sIGlzc3VlLCBmdW5kaW5nKSAlPiUgCiAgbXV0YXRlKHN1bW1hcnkgPSBkYXRhICU+JQogICAgICAgICAgIG1hcCh+IHN1bW1hcml6ZSguLCBwY3RfbGlrZWx5ID0gdGFibGUoZG9uYXRlX2xpa2VseV9iaW4pW1siTGlrZWx5Il1dIC8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgoZG9uYXRlX2xpa2VseV9iaW4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuX2RvbmF0aW9uID0gbWVhbihhbW91bnRfZG9uYXRlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzZF9kb25hdGlvbiA9IHNkKGFtb3VudF9kb25hdGUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIE4gPSBucm93KC4pKSkpICU+JSAKICB1bm5lc3Qoc3VtbWFyeSkgJT4lIHNlbGVjdCgtZGF0YSkgJT4lIHVuZ3JvdXAoKQoKY29uZGl0aW9uc19zdW1tYXJ5X2NsZWFuIDwtIGNvbmRpdGlvbnNfc3VtbWFyeSAlPiUgCiAgbXV0YXRlKGZ1bmRpbmcgPSBpZmVsc2UoaXMubmEoZnVuZGluZykgJiAhaXMubmEoaXNzdWUpICwgIipUb3RhbCoiLCBhcy5jaGFyYWN0ZXIoZnVuZGluZykpLAogICAgICAgICBpc3N1ZSA9IGlmZWxzZShpcy5uYShpc3N1ZSkgJiAhaXMubmEoY3JhY2tkb3duKSwgIipUb3RhbCoiLCBhcy5jaGFyYWN0ZXIoaXNzdWUpKSwKICAgICAgICAgY3JhY2tkb3duID0gaWZlbHNlKGlzLm5hKGNyYWNrZG93biksICIqVG90YWwqIiwgYXMuY2hhcmFjdGVyKGNyYWNrZG93bikpKSAlPiUgCiAgZ3JvdXBfYnkoY3JhY2tkb3duKSAlPiUgCiAgbXV0YXRlKGlzc3VlID0gcmVwbGFjZShpc3N1ZSwgZHVwbGljYXRlZChpc3N1ZSksIE5BKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgbXV0YXRlKGNyYWNrZG93biA9IHJlcGxhY2UoY3JhY2tkb3duLCBkdXBsaWNhdGVkKGNyYWNrZG93biksIE5BKSkgJT4lIAogIG11dGF0ZShwY3RfbGlrZWx5ID0gcGVyY2VudChwY3RfbGlrZWx5KSkgJT4lIAogIHJlbmFtZShgQ3JhY2tkb3duIGNvbmRpdGlvbmAgPSBjcmFja2Rvd24sIGBJc3N1ZSBjb25kaXRpb25gID0gaXNzdWUsCiAgICAgICAgIGBGdW5kaW5nIGNvbmRpdGlvbmAgPSBmdW5kaW5nLCBgJSBsaWtlbHkgdG8gZG9uYXRlYCA9IHBjdF9saWtlbHksCiAgICAgICAgIGBBbW91bnQgZG9uYXRlZCAobWVhbilgID0gbWVhbl9kb25hdGlvbiwgYEFtb3VudCBkb25hdGVkIChzZClgID0gc2RfZG9uYXRpb24pCgpjb25kaXRpb25zX3N1bW1hcnlfY2xlYW4gJVQ+JSAKICBwYW5kb2MudGFibGUoKSAlPiUgCiAgcGFuZG9jLnRhYmxlLnJldHVybihjYXB0aW9uID0gIkF2ZXJhZ2UgbGlrZWxpaG9vZCBhbmQgYW1vdW50IGRvbmF0ZWQgYWNyb3NzIGV4cGVyaW1lbnRhbCBjb25kaXRpb25zIHsjdGJsOmF2Zy1yZXN1bHRzfSIpICU+JSAKICBjYXQoZmlsZSA9IGhlcmUoImFuYWx5c2lzIiwgIm91dHB1dCIsICJ0YWJsZXMiLCAidGJsLWF2Zy1yZXN1bHRzLm1kIikpCmBgYAoKXAoKIyBWaXN1YWxpemUgaW1wb3J0YW50IHZhcmlhYmxlcwoKIyMgTGlrZWxpaG9vZCBvZiBkb25hdGlvbgoKYGBge3IgZmlnLWxpa2VsaWhvb2QtYmFycywgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NCwgb3V0LndpZHRoPSI4MCUifQpkb25hdGVfc3VtbWFyeSA8LSByZXN1bHRzICU+JSAKICBjb3VudChkb25hdGVfbGlrZWx5KSAlPiUgCiAgbXV0YXRlKHBlcmMgPSBuIC8gc3VtKG4pKSAlPiUgCiAgbXV0YXRlKGhpZ2hsaWdodCA9IGlmZWxzZShkb25hdGVfbGlrZWx5ICVpbiUgYygiRXh0cmVtZWx5IGxpa2VseSIsICJTb21ld2hhdCBsaWtlbHkiKSwgVFJVRSwgRkFMU0UpKQoKcGxvdF9kb25hdGVfc3VtbWFyeSA8LSBnZ3Bsb3QoZG9uYXRlX3N1bW1hcnksIGFlcyh4ID0gbiwgeSA9IGRvbmF0ZV9saWtlbHksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBoaWdobGlnaHQpKSArCiAgZ2VvbV9iYXJoKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXMofiAuIC8gc3VtKGRvbmF0ZV9zdW1tYXJ5JG4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbmdvX2NvbHMoImdyZWVuIiwgImJsdWUiLCBuYW1lID0gRkFMU0UpLCBndWlkZSA9IEZBTFNFKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwpICsKICB0aGVtZV9uZ29zKCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKCnBsb3RfZG9uYXRlX3N1bW1hcnkgJVQ+JSAKICBwcmludCgpICVUPiUKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJhbmFseXNpcyIsICJvdXRwdXQiLCAiZmlndXJlcyIsICJkb25hdGVfc3VtbWFyeS5wZGYiKSwKICAgICAgICAgd2lkdGggPSA5LCBoZWlnaHQgPSA0LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lIAogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoImFuYWx5c2lzIiwgIm91dHB1dCIsICJmaWd1cmVzIiwgImRvbmF0ZV9zdW1tYXJ5LnBuZyIpLAogICAgICAgICB3aWR0aCA9IDksIGhlaWdodCA9IDQsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgojIyBBbW91bnQgZG9uYXRlZAoKYGBge3IgZmlnLWFtb3VudC1iYXJzLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD0yLjc1LCBvdXQud2lkdGg9IjgwJSJ9CnBsb3RfYW1vdW50X3N1bW1hcnkgPC0gZ2dwbG90KHJlc3VsdHMsIGFlcyh4ID0gYW1vdW50X2RvbmF0ZSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMjAsIGZpbGwgPSBuZ29fY29scygiYmx1ZSIpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IGRvbGxhcikgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMKSArCiAgdGhlbWVfbmdvcygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpKQoKcGxvdF9hbW91bnRfc3VtbWFyeSAlVD4lIAogIHByaW50KCkgJVQ+JQogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoImFuYWx5c2lzIiwgIm91dHB1dCIsICJmaWd1cmVzIiwgImFtb3VudF9zdW1tYXJ5LnBkZiIpLAogICAgICAgICB3aWR0aCA9IDksIGhlaWdodCA9IDIuNzUsIHVuaXRzID0gImluIiwgZGV2aWNlID0gY2Fpcm9fcGRmKSAlPiUgCiAgZ2dzYXZlKC4sIGZpbGVuYW1lID0gaGVyZSgiYW5hbHlzaXMiLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAiYW1vdW50X3N1bW1hcnkucG5nIiksCiAgICAgICAgIHdpZHRoID0gOSwgaGVpZ2h0ID0gMi43NSwgdW5pdHMgPSAiaW4iLCB0eXBlID0gImNhaXJvIiwgZHBpID0gMzAwKQpgYGAKClwKCmBgYHtyIGFsbC1kYXRhc2V0cy1uZXN0ZWR9CmFsbF9tb2RlbHMgPC0gdHJpYmJsZSgKICB+dGl0bGUsIH5kZiwKICAiQ3JhY2tkb3duIiwgcmVzdWx0cywKICAjIEhhLCBjaGVhdCBoZXJlIGJ5IHJlbmFtaW5nIHRoZSBpc3N1ZSBhbmQgZnVuZGluZyBjb2x1bW5zIHRvIGNyYWNrZG93bi4gCiAgIyBBbGwgb3RoZXIgdGVzdHMgYXJlIGJhc2VkIG9uIHRoZSBjcmFja2Rvd24gY29sdW1uIGV4Y2VwdCB0aGVzZSB0d28sIHNvCiAgIyByYXRoZXIgdGhhbiBidWlsZCBhbGwgc29ydHMgb2YgY29udm9sdXRlZCBhcmd1bWVudHMgYW5kIGZ1bmN0aW9ucywgd2UganVzdAogICMgcmVuYW1lIHRoZXNlIGFzIGlzc3VlIGFuZCBmdW5kaW5nCiAgIklzc3VlIiwgbXV0YXRlKHJlc3VsdHMsIGNyYWNrZG93biA9IGlzc3VlKSwKICAiRnVuZGluZyIsIG11dGF0ZShyZXN1bHRzLCBjcmFja2Rvd24gPSBmdW5kaW5nKSwKICAjIENyZWF0ZSBhbGwgdGhlIG5lc3RlZCBjb25kaXRpb25zCiAgIkh1bWFuIHJpZ2h0cyB8IENyYWNrZG93biIsIGZpbHRlcihyZXN1bHRzLCBpc3N1ZSA9PSAiSHVtYW4gcmlnaHRzIiksCiAgIkh1bWFuaXRhcmlhbiBhc3Npc3RhbmNlIHwgQ3JhY2tkb3duIiwgZmlsdGVyKHJlc3VsdHMsIGlzc3VlICE9ICJIdW1hbiByaWdodHMiKSwKICAiR292ZXJubWVudCB8IENyYWNrZG93biIsIGZpbHRlcihyZXN1bHRzLCBmdW5kaW5nID09ICJHb3Zlcm5tZW50IiksCiAgIlByaXZhdGUgfCBDcmFja2Rvd24iLCBmaWx0ZXIocmVzdWx0cywgZnVuZGluZyA9PSAiUHJpdmF0ZSIpLAogICJIdW1hbiByaWdodHMgfCBHb3Zlcm5tZW50IHwgQ3JhY2tkb3duIiwgZmlsdGVyKHJlc3VsdHMsIGlzc3VlID09ICJIdW1hbiByaWdodHMiLCBmdW5kaW5nID09ICJHb3Zlcm5tZW50IiksCiAgIkh1bWFuIHJpZ2h0cyB8IFByaXZhdGUgfCBDcmFja2Rvd24iLCBmaWx0ZXIocmVzdWx0cywgaXNzdWUgPT0gIkh1bWFuIHJpZ2h0cyIsIGZ1bmRpbmcgPT0gIlByaXZhdGUiKSwKICAiSHVtYW5pdGFyaWFuIGFzc2lzdGFuY2UgfCBHb3Zlcm5tZW50IHwgQ3JhY2tkb3duIiwgZmlsdGVyKHJlc3VsdHMsIGlzc3VlICE9ICJIdW1hbiByaWdodHMiLCBmdW5kaW5nID09ICJHb3Zlcm5tZW50IiksCiAgIkh1bWFuaXRhcmlhbiBhc3Npc3RhbmNlIHwgUHJpdmF0ZSB8IENyYWNrZG93biIsIGZpbHRlcihyZXN1bHRzLCBpc3N1ZSAhPSAiSHVtYW4gcmlnaHRzIiwgZnVuZGluZyA9PSAiUHJpdmF0ZSIpCikgCmBgYAoKIyBUcmVhdG1lbnQgZWZmZWN0czogTGlrZWxpaG9vZCBvZiBkb25hdGlvbgoKVGhpcyB0aW1lIGFyb3VuZCwgd2UncmUgbm90IHVzaW5nIGludGVyYWN0aW9uZnVsIHJlZ3Jlc3Npb24gbW9kZWxzIHRvIGNhbGN1bGF0ZSBhbGwgdGhlc2UgZGlmZmVyZW5jZXMgaW4gZ3JvdXBzLiBJbnN0ZWFkIHdlIHVzZSByZWFsIGxpdmUgU3RhbiBjb2RlIHRvIGVzdGltYXRlIHRoZSBkaWZmZXJlbmNlcyBpbiBncm91cCBtZWFucyBhbmQgcHJvcG9ydGlvbnMhIAoKIyMgUHJpb3JzIGFuZCBtb2RlbHMKCldlIGVzdGltYXRlIHRoZSBwcm9wb3J0aW9uIG9mIHBlb3BsZSByZXNwb25kaW5nIHRoYXQgdGhleSdkIGJlIGxpa2VseSB0byBkb25hdGUgdG8gdGhlIG9yZ2FuaXphdGlvbiB3aXRoIGEgYmlub21pYWwgZGlzdHJpYnV0aW9uLCB3aXRoIGEgcHJpb3IgJFx0aGV0YSQgZGlzdHJpYnV0aW9uIG9mICRcdGV4dHtCZXRhfSg1LCA1KSQuIFdlIGJ1aWxkIHRoZSBmb2xsb3dpbmcgbW9kZWwgaW4gU3RhbjoKCiQkClxiZWdpbnthbGlnbmVkfQpuX3tcdGV4dHtncm91cCAxLCBncm91cCAyfX0gJlxzaW0gXHRleHR7Qmlub21pYWx9KG5fe1x0ZXh0e3RvdGFsIGluIGdyb3VwfX0sIFx0aGV0YV97XHRleHR7Z3JvdXB9fSkgJlx0ZXh0e1tsaWtlbGlob29kXX1cXApcdGV4dHtEaWZmZXJlbmNlfSAmPSBuX3tcdGV4dHtncm91cCAyfX0gLSBuX3tcdGV4dHtncm91cCAxfX0gJlx0ZXh0e1tkaWZmZXJlbmNlIGluIHByb3BvcnRpb25zXX0gXFwKbiAmOiBcdGV4dHtOdW1iZXIgbGlrZWx5IHRvIGRvbmF0ZX0gXFwKXFwKXHRoZXRhX3tcdGV4dHtncm91cCAxLCBncm91cCAyfX0gJlxzaW0gXHRleHR7QmV0YX0oNSwgNSkgJlx0ZXh0e1twcmlvciBwcm9iLiBvZiBiZWluZyBsaWtlbHkgdG8gZG9uYXRlXX0KXGVuZHthbGlnbmVkfQokJAoKYGBge3IgcHJpb3JzLWxpa2VseSwgZmlnLndpZHRoPTIuNzUsIGZpZy5oZWlnaHQ9MS41LCBvdXQud2lkdGg9IjUwJSJ9Cmxpa2VseV90aGV0YSA8LSBnZ3Bsb3QoZGF0YSA9IHRpYmJsZSh4ID0gYygwLCAxKSksIGFlcyh4ID0geCkpICsKICBnZW9tX2FyZWEoc3RhdCA9ICJmdW5jdGlvbiIsIGZ1biA9IGRiZXRhLCBhcmdzID0gbGlzdChzaGFwZTEgPSA1LCBzaGFwZTIgPSA1KSwgCiAgICAgICAgICAgIGZpbGwgPSAiZ3JleTgwIiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh4ID0gZXhwcmVzc2lvbihQcm9iYWJpbGl0eSB+IG9mIH4gYmVpbmcgfiBsaWtlbHkgfiB0byB+IGRvbmF0ZSB+ICh0aGV0YSkpLCB5ID0gIkRlbnNpdHkiKSArCiAgYW5ub3RhdGUoZ2VvbSA9ICJsYWJlbCIsIHggPSAwLjUsIHkgPSAxLCBsYWJlbCA9ICJCZXRhKDUsIDUpIiwgc2l6ZSA9IHB0cyg5KSkgKwogIHRoZW1lX25nb3MoYmFzZV9zaXplID0gOSwgZGVuc2l0eSA9IFRSVUUpCmxpa2VseV90aGV0YQoKbGlrZWx5X3RoZXRhICVUPiUgCiAgZ2dzYXZlKC4sIGZpbGVuYW1lID0gaGVyZSgiYW5hbHlzaXMiLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAicHJpb3ItbGlrZWx5LnBkZiIpLAogICAgICAgICB3aWR0aCA9IDIuNzUsIGhlaWdodCA9IDEuNSwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSBjYWlyb19wZGYpICU+JQogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoImFuYWx5c2lzIiwgIm91dHB1dCIsICJmaWd1cmVzIiwgInByaW9yLWxpa2VseS5wbmciKSwKICAgICAgICAgd2lkdGggPSAyLjc1LCBoZWlnaHQgPSAxLjUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgojIyBEaWZmZXJlbmNlcwoKYGBge3IgcnVuLWxpa2VseS1tb2RlbHMsIHJlc3VsdHM9ImhpZGUiLCBjYWNoZT1UUlVFfQojIFRoaXMgdGFrZXMgZm9yZXZlciBiZWNhdXNlIG9mIE1DTUMgc2FtcGxpbmcsIHNvIHRoaXMgY2h1bmsgaXMgY2FjaGVkCgojIFNhbXBsZSBmcm9tIHRoZSBjb21waWxlZCBtb2RlbAphbGxfbW9kZWxzX2xpa2VseV9ydW4gPC0gYWxsX21vZGVscyAlPiUgCiAgIyBTaW1wbGlmeSBkYXRhIGZvciBzZW5kaW5nIHRvIFN0YW4KICBtdXRhdGUoc3Rhbl9kYXRhX2NvdW50cyA9IGRmICU+JSBtYXAofiB7CiAgICBkZl9jb3VudHMgPC0gLnggJT4lIAogICAgICBjb3VudChjcmFja2Rvd24sIGRvbmF0ZV9saWtlbHlfYmluKSAlPiUgCiAgICAgIGdyb3VwX2J5KGNyYWNrZG93bikgJT4lIAogICAgICBtdXRhdGUodG90YWwgPSBzdW0obikpICU+JSAKICAgICAgZmlsdGVyKGRvbmF0ZV9saWtlbHlfYmluID09ICJMaWtlbHkiKQogICAgCiAgICByZXR1cm4obGlzdCgKICAgICAgbl90b3RhbF8xID0gZGZfY291bnRzJHRvdGFsWzFdLAogICAgICBuX3RvdGFsXzIgPSBkZl9jb3VudHMkdG90YWxbMl0sCiAgICAgIG5fbGlrZWx5XzEgPSBkZl9jb3VudHMkblsxXSwKICAgICAgbl9saWtlbHlfMiA9IGRmX2NvdW50cyRuWzJdCiAgICApKQogIH0pKSAlPiUgCiAgIyBSdW4gdGhlIGFjdHVhbCBtb2RlbCBvbiB0aGUgc2ltcGxpZmllZCBkYXRhCiAgbXV0YXRlKG1vZGVsID0gc3Rhbl9kYXRhX2NvdW50cyAlPiUgbWFwKH4gewogICAgZG9uYXRlX2xpa2VseShuX3RvdGFsXzEgPSAueCRuX3RvdGFsXzEsIG5fdG90YWxfMiA9IC54JG5fdG90YWxfMiwKICAgICAgICAgICAgICAgICAgbl9saWtlbHlfMSA9IC54JG5fbGlrZWx5XzEsIG5fbGlrZWx5XzIgPSAueCRuX2xpa2VseV8yLAogICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChtYXhfdHJlZWRlcHRoID0gMTUpLAogICAgICAgICAgICAgICAgICBjaGFpbnMgPSBDSEFJTlMsIGl0ZXIgPSBJVEVSLCB3YXJtdXAgPSBXQVJNVVAsIHNlZWQgPSBCQVlFU19TRUVEKQogIH0pKSAKCiMgRXh0cmFjdCBzdHVmZgphbGxfbW9kZWxzX2xpa2VseSA8LSBhbGxfbW9kZWxzX2xpa2VseV9ydW4gJT4lCiAgIyBFeHRyYWN0IHBvc3RlcmlvciBjaGFpbnMKICBtdXRhdGUocG9zdGVyaW9yX2NoYWluc19sb25nID0gbWFwKG1vZGVsLCB+IHsKICAgICAgLnggJT4lIGdhdGhlcl9kcmF3cyh0aGV0YV8xLCB0aGV0YV8yLCB0aGV0YV9kaWZmLCBwY3RfY2hhbmdlKQogIH0pKSAlPiUgCiAgbXV0YXRlKHBvc3Rlcmlvcl9jaGFpbnNfd2lkZSA9IG1hcChtb2RlbCwgfiB7CiAgICAgIC54ICU+JSBzcHJlYWRfZHJhd3ModGhldGFfMSwgdGhldGFfMiwgdGhldGFfZGlmZiwgcGN0X2NoYW5nZSkKICB9KSkgJT4lIAogICMgR2V0IEhESSBtZWRpYW5zIGluIHRpZHkgZm9ybQogIG11dGF0ZSh0aWR5ID0gcG9zdGVyaW9yX2NoYWluc19sb25nICU+JSBtYXAofiB7CiAgICAueCAlPiUgbWVkaWFuX2hkY2koKSAlPiUgdG9fYnJvb21fbmFtZXMoKQogIH0pKQpgYGAKCmBgYHtyIHBsb3QtbGlrZWx5LWRpZmZzLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9NC43NSwgZmlnLmhlaWdodD01LjUsIG91dC53aWR0aD0iOTAlIn0KdGlkaWVkX2RpZmZzX2xpa2VseSA8LSBhbGxfbW9kZWxzX2xpa2VseSAlPiUgCiAgdW5uZXN0KHBvc3Rlcmlvcl9jaGFpbnNfbG9uZykgJT4lIAogIGZpbHRlcigudmFyaWFibGUgPT0gInRoZXRhX2RpZmYiKSAlPiUgCiAgbXV0YXRlKGNhdGVnb3J5ID0gY2FzZV93aGVuKAogICAgc3RyX2NvdW50KHRpdGxlLCAiXFx8IikgPT0gMCB+ICJMZXZlbCAxIiwKICAgIHN0cl9jb3VudCh0aXRsZSwgIlxcfCIpID09IDEgfiAiTGV2ZWwgMiIsCiAgICBzdHJfY291bnQodGl0bGUsICJcXHwiKSA9PSAyIH4gIkxldmVsIDMiCiAgKSkgJT4lIAogIG11dGF0ZSh0aXRsZSA9IHN0cl9yZW1vdmUodGl0bGUsICIgXFx8IENyYWNrZG93biIpKQoKbGV2ZWwxX2xpa2VseSA8LSB0aWRpZWRfZGlmZnNfbGlrZWx5ICU+JSAKICBmaWx0ZXIoY2F0ZWdvcnkgPT0gIkxldmVsIDEiKSAlPiUKICBtdXRhdGUodGl0bGUgPSByZWNvZGUodGl0bGUsIAogICAgICAgICAgICAgICAgICAgICAgICBDcmFja2Rvd24gPSAiQ3JhY2tkb3duIOKIklxuTm8gY3JhY2tkb3duIiwKICAgICAgICAgICAgICAgICAgICAgICAgSXNzdWUgPSAiSHVtYW5pdGFyaWFuXG5hc3Npc3RhbmNlIOKIklxuSHVtYW4gcmlnaHRzIiwKICAgICAgICAgICAgICAgICAgICAgICAgRnVuZGluZyA9ICJQcml2YXRlIOKIklxuR292ZXJubWVudFxuZnVuZGluZyIpKSAlPiUgCiAgbXV0YXRlKHRpdGxlID0gZmN0X2lub3JkZXIodGl0bGUpKQoKcGxvdF9kaWZmX2xpa2VseV9hIDwtIGdncGxvdChsZXZlbDFfbGlrZWx5LCBhZXMoeCA9IC52YWx1ZSwgeSA9IGZjdF9yZXYodGl0bGUpLCBmaWxsID0gdGl0bGUpKSArCiAgc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC44LCAwLjk1KSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG5nb19jb2xzKGMoImJsdWUiLCAicmVkIiwgIm9yYW5nZSIpLCBuYW1lID0gRkFMU0UpLCBndWlkZSA9IEZBTFNFKSArCiAgbGFicyh4ID0gIkRpZmZlcmVuY2UgaW4gZG9uYXRpb24gbGlrZWxpaG9vZCIsIHkgPSBOVUxMLCB0YWcgPSAiQSIpICsKICB0aGVtZV9uZ29zKGJhc2Vfc2l6ZSA9IDgpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpsZXZlbDJfbGlrZWx5IDwtIHRpZGllZF9kaWZmc19saWtlbHkgJT4lIAogIGZpbHRlcihjYXRlZ29yeSA9PSAiTGV2ZWwgMiIpICU+JQogIG11dGF0ZShjb25kaXRpb24gPSBjYXNlX3doZW4oCiAgICB0aXRsZSAlaW4lIGMoIkh1bWFuIHJpZ2h0cyIsICJIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSIpIH4gIklzc3VlIiwKICAgIHRpdGxlICVpbiUgYygiR292ZXJubWVudCIsICJQcml2YXRlIikgfiAiRnVuZGluZyIKICApKSAlPiUgCiAgbXV0YXRlKGZhY2V0X3RpdGxlID0gY2FzZV93aGVuKAogICAgdGl0bGUgJWluJSBjKCJIdW1hbiByaWdodHMiLCAiSHVtYW5pdGFyaWFuIGFzc2lzdGFuY2UiKSB+IHBhc3RlKHRpdGxlLCAiaXNzdWVzIiksCiAgICB0aXRsZSAlaW4lIGMoIkdvdmVybm1lbnQiLCAiUHJpdmF0ZSIpIH4gcGFzdGUodGl0bGUsICJmdW5kaW5nIikKICApKSAlPiUgCiAgbXV0YXRlKHRpdGxlID0gY2FzZV93aGVuKAogICAgdGl0bGUgJWluJSBjKCJIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSIsICJQcml2YXRlIikgfiAiIiwKICAgIFRSVUUgfiAiQ3JhY2tkb3duIOKIklxuTm8gY3JhY2tkb3duIikKICApCgpwbG90X2RpZmZfbGlrZWx5X2IgPC0gZ2dwbG90KGZpbHRlcihsZXZlbDJfbGlrZWx5LCBjb25kaXRpb24gPT0gIklzc3VlIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gLnZhbHVlLCB5ID0gZmN0X3Jldih0aXRsZSkpKSArCiAgc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC44LCAwLjk1KSwgZmlsbCA9IG5nb19jb2xzKCJyZWQiLCBuYW1lID0gRkFMU0UpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIHRhZyA9ICJCIikgKwogIGZhY2V0X3dyYXAofiBmYWNldF90aXRsZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICB0aGVtZV9uZ29zKGJhc2Vfc2l6ZSA9IDgpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpwbG90X2RpZmZfbGlrZWx5X2MgPC0gZ2dwbG90KGZpbHRlcihsZXZlbDJfbGlrZWx5LCBjb25kaXRpb24gPT0gIkZ1bmRpbmciKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSAudmFsdWUsIHkgPSBmY3RfcmV2KHRpdGxlKSkpICsKICBzdGF0X2hhbGZleWUoLndpZHRoID0gYygwLjgsIDAuOTUpLCBmaWxsID0gbmdvX2NvbHMoIm9yYW5nZSIsIG5hbWUgPSBGQUxTRSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKHggPSAiRGlmZmVyZW5jZSBpbiBkb25hdGlvbiBsaWtlbGlob29kIiwgeSA9IE5VTEwsIHRhZyA9ICJDIikgKwogIGZhY2V0X3dyYXAofiBmYWNldF90aXRsZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICB0aGVtZV9uZ29zKGJhc2Vfc2l6ZSA9IDgpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpsZXZlbDNfbGlrZWx5IDwtIHRpZGllZF9kaWZmc19saWtlbHkgJT4lIAogIGZpbHRlcihjYXRlZ29yeSA9PSAiTGV2ZWwgMyIpICU+JQogIHNlcGFyYXRlKHRpdGxlLCBjKCJpc3N1ZSIsICJmdW5kaW5nIiksIHNlcCA9ICIgXFx8ICIpICU+JQogIG11dGF0ZShpc3N1ZSA9IHBhc3RlKGlzc3VlLCAiaXNzdWVzIiksCiAgICAgICAgIGZ1bmRpbmcgPSBwYXN0ZShmdW5kaW5nLCAiZnVuZGluZyIpKSAlPiUgCiAgbXV0YXRlKGZhY2V0X3RpdGxlID0gcGFzdGUwKGlzc3VlLCAiXG4iLCBmdW5kaW5nKSkgJT4lIAogIG11dGF0ZSh0aXRsZSA9IGNhc2Vfd2hlbigKICAgIGZ1bmRpbmcgPT0gIlByaXZhdGUgZnVuZGluZyIgfiAiIiwKICAgIFRSVUUgfiAiQ3JhY2tkb3duIOKIklxuTm8gY3JhY2tkb3duIikKICApCgpwbG90X2RpZmZfbGlrZWx5X2QgPC0gZ2dwbG90KGxldmVsM19saWtlbHksIGFlcyh4ID0gLnZhbHVlLCB5ID0gZmN0X3Jldih0aXRsZSkpKSArCiAgc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC44LCAwLjk1KSwgZmlsbCA9IG5nb19jb2xzKCJncmVlbiIsIG5hbWUgPSBGQUxTRSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKHggPSAiRGlmZmVyZW5jZSBpbiBkb25hdGlvbiBsaWtlbGlob29kIiwgeSA9IE5VTEwsIHRhZyA9ICJEIiwKICAgICAgIGNhcHRpb24gPSAiUG9pbnQgc2hvd3MgcG9zdGVyaW9yIG1lZGlhbjsgdGhpY2sgYmxhY2sgbGluZXMgc2hvdyA4MCUgY3JlZGlibGUgaW50ZXJ2YWw7XG50aGluIGJsYWNrIGxpbmVzIHNob3cgOTUlIGNyZWRpYmxlIGludGVydmFsIikgKwogIGZhY2V0X3dyYXAofiBmYWNldF90aXRsZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICB0aGVtZV9uZ29zKGJhc2Vfc2l6ZSA9IDgpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpwbG90X2RpZmZzX2xpa2VseV9hbGwgPC0gcGxvdF9kaWZmX2xpa2VseV9hIC8gCiAgKHBsb3RfZGlmZl9saWtlbHlfYiAvIHBsb3RfZGlmZl9saWtlbHlfYykgLyAKICBwbG90X2RpZmZfbGlrZWx5X2QKCnBsb3RfZGlmZnNfbGlrZWx5X2FsbAoKcGxvdF9kaWZmc19saWtlbHlfYWxsICVUPiUgCiAgZ2dzYXZlKC4sIGZpbGVuYW1lID0gaGVyZSgiYW5hbHlzaXMiLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAibGlrZWx5LWRpZmZzLnBkZiIpLAogICAgICAgICB3aWR0aCA9IDQuNzUsIGhlaWdodCA9IDUuNSwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSBjYWlyb19wZGYpICU+JQogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoImFuYWx5c2lzIiwgIm91dHB1dCIsICJmaWd1cmVzIiwgImxpa2VseS1kaWZmcy5wbmciKSwKICAgICAgICAgd2lkdGggPSA0Ljc1LCBoZWlnaHQgPSA1LjUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgpgYGB7ciB0YmwtbGlrZWx5LWRpZmZzLWxldmVsMSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KdGJsX2xpa2VseV90aWR5IDwtIGFsbF9tb2RlbHNfbGlrZWx5ICU+JSAKICB1bm5lc3QodGlkeSkgJT4lIAogIGZpbHRlcih0ZXJtICVpbiUgYygidGhldGFfMSIsICJ0aGV0YV8yIiwgInRoZXRhX2RpZmYiLCAicGN0X2NoYW5nZSIpKSAlPiUgCiAgc2VsZWN0KHRpdGxlLCB0ZXJtLCBlc3RpbWF0ZSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSB0ZXJtLCB2YWx1ZXNfZnJvbSA9IGVzdGltYXRlKSAlPiUKICBtdXRhdGUoY2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICBzdHJfY291bnQodGl0bGUsICJcXHwiKSA9PSAwIH4gIkxldmVsIDEiLAogICAgc3RyX2NvdW50KHRpdGxlLCAiXFx8IikgPT0gMSB+ICJMZXZlbCAyIiwKICAgIHN0cl9jb3VudCh0aXRsZSwgIlxcfCIpID09IDIgfiAiTGV2ZWwgMyIKICApKSAKCnRibF9saWtlbHlfcHJvYnMgPC0gYWxsX21vZGVsc19saWtlbHkgJT4lIAogIHVubmVzdChwb3N0ZXJpb3JfY2hhaW5zX2xvbmcpICU+JSAKICBmaWx0ZXIoLnZhcmlhYmxlID09ICJ0aGV0YV9kaWZmIikgJT4lIAogIGdyb3VwX2J5KHRpdGxlKSAlPiUgCiAgc3VtbWFyaXplKHAuZ3JlYXRlcjAgPSBtZWFuKC52YWx1ZSA+IDApLAogICAgICAgICAgICBwLmxlc3MwID0gbWVhbigudmFsdWUgPCAwKSwKICAgICAgICAgICAgcC5kaWZmLm5vdDAgPSBpZmVsc2UobWVkaWFuKC52YWx1ZSkgPiAwLCBwLmdyZWF0ZXIwLCBwLmxlc3MwKSkgJT4lIAogIHVuZ3JvdXAoKQoKIyBTYXZlIGNvbWJpbmVkIHRhYmxlIGZvciBsYXRlciB1c2UgaW4gbWFudXNjcmlwdAp0YmxfbGlrZWx5X3RpZHkgJT4lIAogIGxlZnRfam9pbih0YmxfbGlrZWx5X3Byb2JzLCBieSA9ICJ0aXRsZSIpICU+JSAKICBzYXZlUkRTKGhlcmUoImRhdGEiLCAiZGVyaXZlZF9kYXRhIiwgInJlc3VsdHNfbW9kZWxzX2xpa2VseS5yZHMiKSkKICAKdGJsX2xpa2VseV8xIDwtIHRibF9saWtlbHlfdGlkeSAlPiUgCiAgbGVmdF9qb2luKHRibF9saWtlbHlfcHJvYnMsIGJ5ID0gInRpdGxlIikgJT4lIAogIGZpbHRlcihjYXRlZ29yeSA9PSAiTGV2ZWwgMSIpICU+JQogIG11dGF0ZSh0aXRsZSA9IHJlY29kZSh0aXRsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgIENyYWNrZG93biA9ICJDcmFja2Rvd24g4oiSIE5vIGNyYWNrZG93biIsCiAgICAgICAgICAgICAgICAgICAgICAgIElzc3VlID0gIipIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSDiiJIgSHVtYW4gcmlnaHRzKiIsCiAgICAgICAgICAgICAgICAgICAgICAgIEZ1bmRpbmcgPSAiKlByaXZhdGUg4oiSIEdvdmVybm1lbnQgZnVuZGluZyoiKSkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKHRoZXRhXzEsIHRoZXRhXzIsIHRoZXRhX2RpZmYsIHBjdF9jaGFuZ2UpLCAKICAgICAgICAgICAgbGlzdCh+cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKC4pKSkgJT4lIAogIG11dGF0ZShwLmRpZmYubm90MCA9IGFzLmNoYXJhY3Rlcihyb3VuZChwLmRpZmYubm90MCwgMikpKSAlPiUKICBzZWxlY3QoRnJhbWUgPSB0aXRsZSwgYCUgbGlrZWx5flRyZWF0bWVudH5gID0gdGhldGFfMiwgYCUgbGlrZWx5fkNvbnRyb2x+YCA9IHRoZXRhXzEsCiAgICAgICAgIGAkXFxEZWx0YSRgID0gdGhldGFfZGlmZiwgYCRcXCVcXERlbHRhJGAgPSBwY3RfY2hhbmdlLCAKICAgICAgICAgYCRwKFxcRGVsdGEgXFxuZXEgMCkkYCA9IHAuZGlmZi5ub3QwKQpgYGAKCmBgYHtyIHRibC1saWtlbHktZGlmZnMtbGV2ZWwyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0YmxfbGlrZWx5XzIgPC0gdGJsX2xpa2VseV90aWR5ICU+JSAKICBsZWZ0X2pvaW4odGJsX2xpa2VseV9wcm9icywgYnkgPSAidGl0bGUiKSAlPiUgCiAgZmlsdGVyKGNhdGVnb3J5ID09ICJMZXZlbCAyIikgJT4lCiAgbXV0YXRlKHRpdGxlX2NsZWFuID0gc3RyX3JlbW92ZSh0aXRsZSwgIiBcXHwgQ3JhY2tkb3duIikpICU+JSAKICBtdXRhdGUodGl0bGVfY2xlYW4gPSBjYXNlX3doZW4oCiAgICB0aXRsZV9jbGVhbiAlaW4lIGMoIkh1bWFuIHJpZ2h0cyIsICJIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSIpIH4gcGFzdGUodGl0bGVfY2xlYW4sICJpc3N1ZXMiKSwKICAgIHRpdGxlX2NsZWFuICVpbiUgYygiR292ZXJubWVudCIsICJQcml2YXRlIikgfiBwYXN0ZSh0aXRsZV9jbGVhbiwgImZ1bmRpbmciKQogICkpICU+JSAKICBtdXRhdGUodGl0bGVfY2xlYW4gPSBmYWN0b3IodGl0bGVfY2xlYW4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJIdW1hbiByaWdodHMgaXNzdWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkh1bWFuaXRhcmlhbiBhc3Npc3RhbmNlIGlzc3VlcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHb3Zlcm5tZW50IGZ1bmRpbmciLCAiUHJpdmF0ZSBmdW5kaW5nIikpKSAlPiUgCiAgYXJyYW5nZSh0aXRsZV9jbGVhbikgJT4lIAogIG11dGF0ZV9hdCh2YXJzKHRoZXRhXzEsIHRoZXRhXzIsIHRoZXRhX2RpZmYsIHBjdF9jaGFuZ2UpLCAKICAgICAgICAgICAgbGlzdCh+cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKC4pKSkgJT4lIAogIG11dGF0ZShwLmRpZmYubm90MCA9IGFzLmNoYXJhY3Rlcihyb3VuZChwLmRpZmYubm90MCwgMikpKSAlPiUgCiAgbXV0YXRlKHRpdGxlX2NsZWFuID0gYXMuY2hhcmFjdGVyKHRpdGxlX2NsZWFuKSkgJT4lIAogIHNlbGVjdChgSH4yYX4gYW5kIEh+M2F+YCA9IHRpdGxlX2NsZWFuLCAKICAgICAgICAgYCUgbGlrZWx5fkNyYWNrZG93bn5gID0gdGhldGFfMiwgYCUgbGlrZWx5fk5vXFwgY3JhY2tkb3dufmAgPSB0aGV0YV8xLAogICAgICAgICBgJFxcRGVsdGEkYCA9IHRoZXRhX2RpZmYsIGAkXFwlXFxEZWx0YSRgID0gcGN0X2NoYW5nZSwgCiAgICAgICAgIGAkcChcXERlbHRhIFxcbmVxIDApJGAgPSBwLmRpZmYubm90MCkKYGBgCgpgYGB7ciB0YmwtbGlrZWx5LWRpZmZzLWxldmVsMywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KdGJsX2xpa2VseV8zIDwtIHRibF9saWtlbHlfdGlkeSAlPiUgCiAgbGVmdF9qb2luKHRibF9saWtlbHlfcHJvYnMsIGJ5ID0gInRpdGxlIikgJT4lIAogIGZpbHRlcihjYXRlZ29yeSA9PSAiTGV2ZWwgMyIpICU+JQogIG11dGF0ZSh0aXRsZV9jbGVhbiA9IHN0cl9yZW1vdmUodGl0bGUsICIgXFx8IENyYWNrZG93biIpKSAlPiUgCiAgc2VwYXJhdGUodGl0bGVfY2xlYW4sIGMoIklzc3VlIiwgIkZ1bmRpbmciKSwgc2VwID0gIiBcXHwgIikgJT4lIAogIG11dGF0ZShJc3N1ZSA9IGZhY3RvcihJc3N1ZSwgbGV2ZWxzID0gYygiSHVtYW4gcmlnaHRzIiwgIkh1bWFuaXRhcmlhbiBhc3Npc3RhbmNlIikpLAogICAgICAgICBGdW5kaW5nID0gZmFjdG9yKEZ1bmRpbmcsIGxldmVscyA9IGMoIkdvdmVybm1lbnQiLCAiUHJpdmF0ZSIpKSkgJT4lIAogIGFycmFuZ2UoSXNzdWUsIEZ1bmRpbmcpICU+JSAKICBtdXRhdGVfYXQodmFycyh0aGV0YV8xLCB0aGV0YV8yLCB0aGV0YV9kaWZmLCBwY3RfY2hhbmdlKSwgCiAgICAgICAgICAgIGxpc3QofnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSguKSkpICU+JSAKICBtdXRhdGUocC5kaWZmLm5vdDAgPSBhcy5jaGFyYWN0ZXIocm91bmQocC5kaWZmLm5vdDAsIDIpKSkgJT4lCiAgbXV0YXRlKEZyYW1lID0gcGFzdGUwKElzc3VlLCAiIGlzc3VlcywgIiwgRnVuZGluZywgIiBmdW5kaW5nIikpICU+JSAKICBzZWxlY3QoYEh+MmF+IGFuZCBIfjNhfiAobmVzdGVkKWAgPSBGcmFtZSwKICAgICAgICAgYCUgbGlrZWx5fkNyYWNrZG93bn5gID0gdGhldGFfMiwgYCUgbGlrZWx5fk5vXFwgY3JhY2tkb3dufmAgPSB0aGV0YV8xLAogICAgICAgICBgJFxcRGVsdGEkYCA9IHRoZXRhX2RpZmYsIGAkXFwlXFxEZWx0YSRgID0gcGN0X2NoYW5nZSwgCiAgICAgICAgIGAkcChcXERlbHRhIFxcbmVxIDApJGAgPSBwLmRpZmYubm90MCkKYGBgCgpgYGB7ciBjb21iaW5lLWxpa2VseS10YWJsZXMsIHJlc3VsdHM9ImFzaXMifQp0YmxfbGlrZWx5XzJfaGVhZGVyIDwtIGVuZnJhbWUoY29sbmFtZXModGJsX2xpa2VseV8yKSkgJT4lIAogIG11dGF0ZSh2YWx1ZSA9ICh2YWx1ZSkpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gbmFtZSwgdmFsdWVzX2Zyb20gPSB2YWx1ZSkgJT4lIAogIHNldF9uYW1lcyhjb2xuYW1lcyh0YmxfbGlrZWx5XzEpKQoKdGJsX2xpa2VseV8zX2hlYWRlciA8LSBlbmZyYW1lKGNvbG5hbWVzKHRibF9saWtlbHlfMykpICU+JSAKICBtdXRhdGUodmFsdWUgPSAodmFsdWUpKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG5hbWUsIHZhbHVlc19mcm9tID0gdmFsdWUpICU+JSAKICBzZXRfbmFtZXMoY29sbmFtZXModGJsX2xpa2VseV8xKSkKCmJpbmRfcm93cyh0YmxfbGlrZWx5XzEsIAogICAgICAgICAgdGJsX2xpa2VseV8yX2hlYWRlciwgCiAgICAgICAgICBzZXRfbmFtZXModGJsX2xpa2VseV8yLCBjb2xuYW1lcyh0YmxfbGlrZWx5XzEpKSwKICAgICAgICAgIHRibF9saWtlbHlfM19oZWFkZXIsCiAgICAgICAgICBzZXRfbmFtZXModGJsX2xpa2VseV8zLCBjb2xuYW1lcyh0YmxfbGlrZWx5XzEpKSkgJT4lIAogIHJlbmFtZShgSH4xYX5gID0gRnJhbWUpICU+JSAKICBwYW5kb2MudGFibGUucmV0dXJuKGNhcHRpb24gPSAnTGlrZWxpaG9vZCBvZiBkb25hdGlvbiBhbmQgZGlmZmVyZW5jZXMgaW4gcHJvcG9ydGlvbnMgaW4gImNyYWNrZG93biIgKHRyZWF0bWVudCkgYW5kICJubyBjcmFja2Rvd24iIChjb250cm9sKSBjb25kaXRpb25zOyB2YWx1ZXMgcmVwcmVzZW50IHBvc3RlcmlvciBtZWRpYW5zIHsjdGJsOmxpa2VseS1kaWZmc30nLAogICAgICAgICAgICAgICAgICAgICAganVzdGlmeSA9ICJsY2NjY2MiKSAlVD4lCiAgY2F0KCkgJT4lCiAgY2F0KGZpbGUgPSBoZXJlKCJhbmFseXNpcyIsICJvdXRwdXQiLCAidGFibGVzIiwgInRibC1saWtlbHktZGlmZnMubWQiKSkKYGBgCgpcCgojIFRyZWF0bWVudCBlZmZlY3RzOiBBbW91bnQgZG9uYXRlZAoKIyMgUHJpb3JzIGFuZCBtb2RlbHMKCkZvbGxvd2luZyBbSm9obiBLcnVzY2hrZSdzICJCYXllc2lhbiBFc3RpbWF0aW9uIFN1cGVyc2VkZXMgdGhlIHQtdGVzdCAoQkVTVCkiIHByb2NlZHVyZV0oaHR0cDovL3d3dy5pbmRpYW5hLmVkdS9+a3J1c2Noa2UvQkVTVC9CRVNULnBkZiksIHdlIGVzdGltYXRlIG1lYW5zIGZvciBlYWNoIGdyb3VwIHdpdGggYSB0LWRpc3RyaWJ1dGlvbi4gV2UgdXNlIHRoZSBmb2xsb3dpbmcgcHJpb3JzIGZvciB0aGUgZGlzdHJpYnV0aW9uIHBhcmFtZXRlcnM6CgokJApcYmVnaW57YWxpZ25lZH0KeF97XHRleHR7Z3JvdXAgMSwgZ3JvdXAgMn19ICZcc2ltIFx0ZXh0e1N0dWRlbnQgfSB0KFxudSwgXG11LCBcc2lnbWEpICZcdGV4dHtbbGlrZWxpaG9vZF19XFwKXHRleHR7RGlmZmVyZW5jZX0gJj0geF97XHRleHR7Z3JvdXAgMn19IC0geF97XHRleHR7Z3JvdXAgMX19ICZcdGV4dHtbZGlmZmVyZW5jZSBpbiBtZWFuc119IFxcCnggJjogXHRleHR7TWVhbiBhbW91bnQgZG9uYXRlZH0gXFwKXFwKXG51ICZcc2ltIFx0ZXh0e0V4cG9uZW50aWFsfSgxIC8gMjkpICZcdGV4dHtbcHJpb3Igbm9ybWFsaXR5XX0gXFwKXG11X3tcdGV4dHtncm91cCAxLCBncm91cCAyfX0gJlxzaW0gXG1hdGhjYWx7Tn0oXGJhcnt4fV97XHRleHR7Z3JvdXAgMSwgZ3JvdXAgMn19LCAxMCkgJlx0ZXh0e1twcmlvciBkb25hdGlvbiBtZWFuIHBlciBncm91cF19XFwKXHNpZ21hX3tcdGV4dHtncm91cCAxLCBncm91cCAyfX0gJlxzaW0gXHRleHR7Q2F1Y2h5fSgwLCAxKSZcdGV4dHtbcHJpb3IgZG9uYXRpb24gc2QgcGVyIGdyb3VwXX0KXGVuZHthbGlnbmVkfQokJAoKYGBge3IgcHJpb3JzLWFtb3VudHMsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTEuNSwgb3V0LndpZHRoPSIxMDAlIn0KYW1vdW50X251IDwtIGdncGxvdChkYXRhID0gdGliYmxlKHggPSBjKDAsIDIwMCkpLCBhZXMoeCA9IHgpKSArCiAgZ2VvbV9hcmVhKHN0YXQgPSAiZnVuY3Rpb24iLCBmdW4gPSBkZXhwLCBhcmdzID0gbGlzdChyYXRlID0gMS8yOSksIAogICAgICAgICAgICBmaWxsID0gImdyZXk4MCIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24oTm9ybWFsaXR5IH4gcGFyYW1ldGVyIH4gKG51KSksIHkgPSAiRGVuc2l0eSIpICsKICBhbm5vdGF0ZShnZW9tID0gImxhYmVsIiwgeCA9IDEwMCwgeSA9IDAuMDA5LCAKICAgICAgICAgICBsYWJlbCA9ICJFeHBvbmVudGlhbCgxLzI5KSIsIHNpemUgPSBwdHMoOSkpICsKICB0aGVtZV9uZ29zKGJhc2Vfc2l6ZSA9IDksIGRlbnNpdHkgPSBUUlVFKQoKYW1vdW50X211IDwtIGdncGxvdChkYXRhID0gdGliYmxlKHggPSBjKDAsIDEwMCkpLCBhZXMoeCA9IHgpKSArCiAgZ2VvbV9hcmVhKHN0YXQgPSAiZnVuY3Rpb24iLCBmdW4gPSBkbm9ybSwgYXJncyA9IGxpc3QobWVhbiA9IDUwLCBzZCA9IDEwKSwKICAgICAgICAgICAgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYyhzZXEoMCwgMTAwLCAyNSkpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCLiiJIkNTAiLCAi4oiSJDI1IiwgIkdyb3VwIGF2ZXJhZ2UiLCAiKyQyNSIsICIrJDUwIikpICsKICBhbm5vdGF0ZShnZW9tID0gImxhYmVsIiwgeCA9IDUwLCB5ID0gMC4wMSwgbGFiZWwgPSAiTihiYXIoeCksIDEwKSIsIAogICAgICAgICAgIHBhcnNlID0gVFJVRSwgc2l6ZSA9IHB0cyg5KSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24oQXZlcmFnZSB+IGRvbmF0ZWQgfiAobXUpKSwgeSA9IE5VTEwpICsKICB0aGVtZV9uZ29zKGJhc2Vfc2l6ZSA9IDksIGRlbnNpdHkgPSBUUlVFKQoKYW1vdW50X3NpZ21hIDwtIGdncGxvdChkYXRhID0gdGliYmxlKHggPSBjKDAsIDEwKSksIGFlcyh4ID0geCkpICsKICBnZW9tX2FyZWEoc3RhdCA9ICJmdW5jdGlvbiIsIGZ1biA9IGRjYXVjaHksIGFyZ3MgPSBsaXN0KGxvY2F0aW9uID0gMCwgc2NhbGUgPSAxKSwKICAgICAgICAgICAgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSArCiAgYW5ub3RhdGUoZ2VvbSA9ICJsYWJlbCIsIHggPSA1LCB5ID0gMC4wOCwgbGFiZWwgPSAiQ2F1Y2h5KDAsIDEpIiwgc2l6ZSA9IHB0cyg5KSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24oU0QgfiBkb25hdGVkIH4gKHNpZ21hKSksIHkgPSBOVUxMKSArCiAgdGhlbWVfbmdvcyhiYXNlX3NpemUgPSA5LCBkZW5zaXR5ID0gVFJVRSkKCmFtb3VudF9wcmlvcnMgPC0gYW1vdW50X251ICsgYW1vdW50X211ICsgYW1vdW50X3NpZ21hCmFtb3VudF9wcmlvcnMKCmFtb3VudF9wcmlvcnMgJVQ+JSAKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJhbmFseXNpcyIsICJvdXRwdXQiLCAiZmlndXJlcyIsICJwcmlvci1hbW91bnQucGRmIiksCiAgICAgICAgIHdpZHRoID0gOCwgaGVpZ2h0ID0gMS41LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lCiAgZ2dzYXZlKC4sIGZpbGVuYW1lID0gaGVyZSgiYW5hbHlzaXMiLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAicHJpb3ItYW1vdW50LnBuZyIpLAogICAgICAgICB3aWR0aCA9IDgsIGhlaWdodCA9IDEuNSwgdW5pdHMgPSAiaW4iLCB0eXBlID0gImNhaXJvIiwgZHBpID0gMzAwKQpgYGAKCgojIyBEaWZmZXJlbmNlcwoKYGBge3IgcnVuLWFtb3VudC1tb2RlbHMsIHJlc3VsdHM9ImhpZGUiLCBjYWNoZT1UUlVFLCB3YXJuaW5nPUZBTFNFfQojIFNhbXBsZSBmcm9tIHRoZSBjb21waWxlZCBtb2RlbAphbGxfbW9kZWxzX2Ftb3VudF9ydW4gPC0gYWxsX21vZGVscyAlPiUgCiAgIyBTaW1wbGlmeSBkYXRhIGZvciBzZW5kaW5nIHRvIFN0YW4KICBtdXRhdGUoc3Rhbl9kYXRhID0gZGYgJT4lIG1hcCh+IHsKICAgIHNlbGVjdCgueCwgYW1vdW50ID0gYW1vdW50X2RvbmF0ZSwgZ3JvdXAgPSBjcmFja2Rvd24pCiAgfSkpICU+JSAKICAjIFJ1biB0aGUgYWN0dWFsIG1vZGVsIG9uIHRoZSBzaW1wbGlmaWVkIGRhdGEKICBtdXRhdGUobW9kZWwgPSBzdGFuX2RhdGEgJT4lIG1hcCh+IHsKICAgIGFtb3VudF9kb25hdGVkX2Jlc3QoZGYgPSAueCwgY2hhaW5zID0gQ0hBSU5TLCBpdGVyID0gSVRFUiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IFdBUk1VUCwgc2VlZCA9IEJBWUVTX1NFRUQpCiAgfSkpIAoKIyBFeHRyYWN0IHN0dWZmCmFsbF9tb2RlbHNfYW1vdW50IDwtIGFsbF9tb2RlbHNfYW1vdW50X3J1biAlPiUgCiAgIyBFeHRyYWN0IHBvc3RlcmlvciBjaGFpbnMKICBtdXRhdGUocG9zdGVyaW9yX2NoYWluc19sb25nID0gbWFwMihtb2RlbCwgc3Rhbl9kYXRhLCB+IHsKICAgIC54ICU+JSAKICAgICAgcmVjb3Zlcl90eXBlcygueSkgJT4lIAogICAgICBnYXRoZXJfZHJhd3MobXVbZ3JvdXBdLCBzaWdtYVtncm91cF0sIG11X2RpZmYsIHBjdF9jaGFuZ2UsIGNvaGVuX2QsIGNsZXMsIG51LCBsb2cxMG51KQogIH0pKSAlPiUgCiAgbXV0YXRlKHBvc3Rlcmlvcl9jaGFpbnNfd2lkZSA9IG1hcDIobW9kZWwsIHN0YW5fZGF0YSwgfiB7CiAgICAueCAlPiUgCiAgICAgIHJlY292ZXJfdHlwZXMoLnkpICU+JSAKICAgICAgc3ByZWFkX2RyYXdzKG11W2dyb3VwXSwgc2lnbWFbZ3JvdXBdLCBtdV9kaWZmLCBwY3RfY2hhbmdlLCBjb2hlbl9kLCBjbGVzLCBudSwgbG9nMTBudSkKICB9KSkgJT4lIAogICMgR2V0IEhESSBtZWRpYW5zIGluIHRpZHkgZm9ybQogIG11dGF0ZSh0aWR5ID0gcG9zdGVyaW9yX2NoYWluc19sb25nICU+JSBtYXAofiB7CiAgICAueCAlPiUgbWVkaWFuX2hkY2koKSAlPiUgdG9fYnJvb21fbmFtZXMoKQogIH0pKQpgYGAKCmBgYHtyIHBsb3QtYW1vdW50LWRpZmZzLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9NC43NSwgZmlnLmhlaWdodD01LjUsIG91dC53aWR0aD0iOTAlIn0KYWxsX21vZGVsc19hbW91bnQgPC0gYWxsX21vZGVsc19hbW91bnQgJT4lIAogICMgVGhlIGBncm91cGAgYW5kIGB0aWR5YCBjb2x1bW5zIGluIGVhY2ggb2YgdGhlc2UgbmVzdGVkIG1vZGVscyBjb250YWluCiAgIyBvcmRlcmVkIGZhY3RvcnMsIGJ1dCB3ZSBjYW4ndCBjb21iaW5lIHRoZW0gd2l0aCB1bm5lc3QoKSBkaXJlY3RseSBiZWNhdXNlCiAgIyB0aGV5IGhhdmUgZGlmZmVyZW50IGxldmVscyAoY3JhY2tkb3duLCBpc3N1ZSwgYW5kIGZ1bmRpbmcpLCBzbyB3ZSBuZWVkIHRvCiAgIyBtYWtlIHRoZW0gdW5vcmRlcmVkIGZhY3RvcnMgYmVmb3JlIHVubmVzdGluZwogIG11dGF0ZShwb3N0ZXJpb3JfY2hhaW5zX2xvbmcgPSBtYXAoCiAgICBwb3N0ZXJpb3JfY2hhaW5zX2xvbmcsIH5tdXRhdGUoLiwgZ3JvdXAgPSBmYWN0b3IoZ3JvdXAsIG9yZGVyZWQgPSBGQUxTRSkpKQogICkgJT4lIAogIG11dGF0ZSh0aWR5ID0gbWFwKAogICAgdGlkeSwgfm11dGF0ZSguLCBncm91cCA9IGZhY3Rvcihncm91cCwgb3JkZXJlZCA9IEZBTFNFKSkpCiAgKQoKdGlkaWVkX2RpZmZzX2Ftb3VudCA8LSBhbGxfbW9kZWxzX2Ftb3VudCAlPiUgCiAgdW5uZXN0KHBvc3Rlcmlvcl9jaGFpbnNfbG9uZykgJT4lIAogIGZpbHRlcigudmFyaWFibGUgPT0gIm11X2RpZmYiKSAlPiUgCiAgbXV0YXRlKGNhdGVnb3J5ID0gY2FzZV93aGVuKAogICAgc3RyX2NvdW50KHRpdGxlLCAiXFx8IikgPT0gMCB+ICJMZXZlbCAxIiwKICAgIHN0cl9jb3VudCh0aXRsZSwgIlxcfCIpID09IDEgfiAiTGV2ZWwgMiIsCiAgICBzdHJfY291bnQodGl0bGUsICJcXHwiKSA9PSAyIH4gIkxldmVsIDMiCiAgKSkgJT4lIAogIG11dGF0ZSh0aXRsZSA9IHN0cl9yZW1vdmUodGl0bGUsICIgXFx8IENyYWNrZG93biIpKQoKbGV2ZWwxX2Ftb3VudCA8LSB0aWRpZWRfZGlmZnNfYW1vdW50ICU+JSAKICBmaWx0ZXIoY2F0ZWdvcnkgPT0gIkxldmVsIDEiKSAlPiUKICBtdXRhdGUodGl0bGUgPSByZWNvZGUodGl0bGUsIAogICAgICAgICAgICAgICAgICAgICAgICBDcmFja2Rvd24gPSAiQ3JhY2tkb3duIOKIklxuTm8gY3JhY2tkb3duIiwKICAgICAgICAgICAgICAgICAgICAgICAgSXNzdWUgPSAiSHVtYW5pdGFyaWFuXG5hc3Npc3RhbmNlIOKIklxuSHVtYW4gcmlnaHRzIiwKICAgICAgICAgICAgICAgICAgICAgICAgRnVuZGluZyA9ICJQcml2YXRlIOKIklxuR292ZXJubWVudFxuZnVuZGluZyIpKSAlPiUgCiAgbXV0YXRlKHRpdGxlID0gZmN0X2lub3JkZXIodGl0bGUpKQoKcGxvdF9kaWZmX2Ftb3VudF9hIDwtIGdncGxvdChsZXZlbDFfYW1vdW50LCBhZXMoeCA9IC52YWx1ZSwgeSA9IGZjdF9yZXYodGl0bGUpLCBmaWxsID0gdGl0bGUpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkgKwogIHN0YXRfaGFsZmV5ZSgud2lkdGggPSBjKDAuOCwgMC45NSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbmdvX2NvbHMoYygiYmx1ZSIsICJyZWQiLCAib3JhbmdlIiksIG5hbWUgPSBGQUxTRSksIGd1aWRlID0gRkFMU0UpICsKICBsYWJzKHggPSAiRGlmZmVyZW5jZSBpbiBhbW91bnQgZG9uYXRlZCIsIHkgPSBOVUxMLCB0YWcgPSAiQSIpICsKICB0aGVtZV9uZ29zKGJhc2Vfc2l6ZSA9IDgpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpsZXZlbDJfYW1vdW50IDwtIHRpZGllZF9kaWZmc19hbW91bnQgJT4lIAogIGZpbHRlcihjYXRlZ29yeSA9PSAiTGV2ZWwgMiIpICU+JQogIG11dGF0ZShjb25kaXRpb24gPSBjYXNlX3doZW4oCiAgICB0aXRsZSAlaW4lIGMoIkh1bWFuIHJpZ2h0cyIsICJIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSIpIH4gIklzc3VlIiwKICAgIHRpdGxlICVpbiUgYygiR292ZXJubWVudCIsICJQcml2YXRlIikgfiAiRnVuZGluZyIKICApKSAlPiUgCiAgbXV0YXRlKGZhY2V0X3RpdGxlID0gY2FzZV93aGVuKAogICAgdGl0bGUgJWluJSBjKCJIdW1hbiByaWdodHMiLCAiSHVtYW5pdGFyaWFuIGFzc2lzdGFuY2UiKSB+IHBhc3RlKHRpdGxlLCAiaXNzdWVzIiksCiAgICB0aXRsZSAlaW4lIGMoIkdvdmVybm1lbnQiLCAiUHJpdmF0ZSIpIH4gcGFzdGUodGl0bGUsICJmdW5kaW5nIikKICApKSAlPiUgCiAgbXV0YXRlKHRpdGxlID0gY2FzZV93aGVuKAogICAgdGl0bGUgJWluJSBjKCJIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSIsICJQcml2YXRlIikgfiAiIiwKICAgIFRSVUUgfiAiQ3JhY2tkb3duIOKIklxuTm8gY3JhY2tkb3duIikKICApCgpwbG90X2RpZmZfYW1vdW50X2IgPC0gZ2dwbG90KGZpbHRlcihsZXZlbDJfYW1vdW50LCBjb25kaXRpb24gPT0gIklzc3VlIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gLnZhbHVlLCB5ID0gZmN0X3Jldih0aXRsZSkpKSArCiAgc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC44LCAwLjk1KSwgZmlsbCA9IG5nb19jb2xzKCJyZWQiLCBuYW1lID0gRkFMU0UpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBkb2xsYXIpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgdGFnID0gIkIiKSArCiAgZmFjZXRfd3JhcCh+IGZhY2V0X3RpdGxlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHRoZW1lX25nb3MoYmFzZV9zaXplID0gOCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKCnBsb3RfZGlmZl9hbW91bnRfYyA8LSBnZ3Bsb3QoZmlsdGVyKGxldmVsMl9hbW91bnQsIGNvbmRpdGlvbiA9PSAiRnVuZGluZyIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IC52YWx1ZSwgeSA9IGZjdF9yZXYodGl0bGUpKSkgKwogIHN0YXRfaGFsZmV5ZSgud2lkdGggPSBjKDAuOCwgMC45NSksIGZpbGwgPSBuZ29fY29scygib3JhbmdlIiwgbmFtZSA9IEZBTFNFKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSArCiAgbGFicyh4ID0gIkRpZmZlcmVuY2UgaW4gYW1vdW50IGRvbmF0ZWQiLCB5ID0gTlVMTCwgdGFnID0gIkMiKSArCiAgZmFjZXRfd3JhcCh+IGZhY2V0X3RpdGxlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHRoZW1lX25nb3MoYmFzZV9zaXplID0gOCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKCmxldmVsM19hbW91bnQgPC0gdGlkaWVkX2RpZmZzX2Ftb3VudCAlPiUgCiAgZmlsdGVyKGNhdGVnb3J5ID09ICJMZXZlbCAzIikgJT4lCiAgc2VwYXJhdGUodGl0bGUsIGMoImlzc3VlIiwgImZ1bmRpbmciKSwgc2VwID0gIiBcXHwgIikgJT4lCiAgbXV0YXRlKGlzc3VlID0gcGFzdGUoaXNzdWUsICJpc3N1ZXMiKSwKICAgICAgICAgZnVuZGluZyA9IHBhc3RlKGZ1bmRpbmcsICJmdW5kaW5nIikpICU+JSAKICBtdXRhdGUoZmFjZXRfdGl0bGUgPSBwYXN0ZTAoaXNzdWUsICJcbiIsIGZ1bmRpbmcpKSAlPiUgCiAgbXV0YXRlKHRpdGxlID0gY2FzZV93aGVuKAogICAgZnVuZGluZyA9PSAiUHJpdmF0ZSBmdW5kaW5nIiB+ICIiLAogICAgVFJVRSB+ICJDcmFja2Rvd24g4oiSXG5ObyBjcmFja2Rvd24iKQogICkKCnBsb3RfZGlmZl9hbW91bnRfZCA8LSBnZ3Bsb3QobGV2ZWwzX2Ftb3VudCwgYWVzKHggPSAudmFsdWUsIHkgPSBmY3RfcmV2KHRpdGxlKSkpICsKICBzdGF0X2hhbGZleWUoLndpZHRoID0gYygwLjgsIDAuOTUpLCBmaWxsID0gbmdvX2NvbHMoImdyZWVuIiwgbmFtZSA9IEZBTFNFKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSArCiAgbGFicyh4ID0gIkRpZmZlcmVuY2UgaW4gYW1vdW50IGRvbmF0ZWQiLCB5ID0gTlVMTCwgdGFnID0gIkQiLAogICAgICAgY2FwdGlvbiA9ICJQb2ludCBzaG93cyBwb3N0ZXJpb3IgbWVkaWFuOyB0aGljayBibGFjayBsaW5lcyBzaG93IDgwJSBjcmVkaWJsZSBpbnRlcnZhbDtcbnRoaW4gYmxhY2sgbGluZXMgc2hvdyA5NSUgY3JlZGlibGUgaW50ZXJ2YWwiKSArCiAgZmFjZXRfd3JhcCh+IGZhY2V0X3RpdGxlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHRoZW1lX25nb3MoYmFzZV9zaXplID0gOCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKCnBsb3RfZGlmZnNfYW1vdW50c19hbGwgPC0gcGxvdF9kaWZmX2Ftb3VudF9hIC8gCiAgKHBsb3RfZGlmZl9hbW91bnRfYiAvIHBsb3RfZGlmZl9hbW91bnRfYykgLyAKICBwbG90X2RpZmZfYW1vdW50X2QKCnBsb3RfZGlmZnNfYW1vdW50c19hbGwKCnBsb3RfZGlmZnNfYW1vdW50c19hbGwgJVQ+JSAKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJhbmFseXNpcyIsICJvdXRwdXQiLCAiZmlndXJlcyIsICJhbW91bnQtZGlmZnMucGRmIiksCiAgICAgICAgIHdpZHRoID0gNC43NSwgaGVpZ2h0ID0gNS41LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lCiAgZ2dzYXZlKC4sIGZpbGVuYW1lID0gaGVyZSgiYW5hbHlzaXMiLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAiYW1vdW50LWRpZmZzLnBuZyIpLAogICAgICAgICB3aWR0aCA9IDQuNzUsIGhlaWdodCA9IDUuNSwgdW5pdHMgPSAiaW4iLCB0eXBlID0gImNhaXJvIiwgZHBpID0gMzAwKQpgYGAKCmBgYHtyIHRibC1hbW91bnQtZGlmZnMtbGV2ZWwxLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0YmxfYW1vdW50c190aWR5IDwtIGFsbF9tb2RlbHNfYW1vdW50ICU+JSAKICB1bm5lc3QodGlkeSkgJT4lIAogIGZpbHRlcih0ZXJtICVpbiUgYygibXUiLCAibXVfZGlmZiIsICJwY3RfY2hhbmdlIikpICU+JSAKICBncm91cF9ieSh0aXRsZSkgJT4lIAogIG11dGF0ZShncm91cF9pZCA9IDE6bigpKSAlPiUgCiAgbXV0YXRlKHRlcm0gPSBjYXNlX3doZW4oCiAgICB0ZXJtID09ICJtdSIgfiBwYXN0ZTAodGVybSwgIl8iLCBncm91cF9pZCksCiAgICBUUlVFIH4gdGVybQogICkpICU+JSAKICBzZWxlY3QodGl0bGUsIHRlcm0sIGVzdGltYXRlKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHRlcm0sIHZhbHVlc19mcm9tID0gZXN0aW1hdGUpICU+JSAKICBtdXRhdGUoY2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICBzdHJfY291bnQodGl0bGUsICJcXHwiKSA9PSAwIH4gIkxldmVsIDEiLAogICAgc3RyX2NvdW50KHRpdGxlLCAiXFx8IikgPT0gMSB+ICJMZXZlbCAyIiwKICAgIHN0cl9jb3VudCh0aXRsZSwgIlxcfCIpID09IDIgfiAiTGV2ZWwgMyIKICApKSAlPiUgCiAgdW5ncm91cCgpCgp0YmxfYW1vdW50c19wcm9icyA8LSBhbGxfbW9kZWxzX2Ftb3VudCAlPiUgCiAgdW5uZXN0KHBvc3Rlcmlvcl9jaGFpbnNfbG9uZykgJT4lIAogIGZpbHRlcigudmFyaWFibGUgPT0gIm11X2RpZmYiKSAlPiUgCiAgZ3JvdXBfYnkodGl0bGUpICU+JSAKICBzdW1tYXJpemUocC5ncmVhdGVyMCA9IG1lYW4oLnZhbHVlID4gMCksCiAgICAgICAgICAgIHAubGVzczAgPSBtZWFuKC52YWx1ZSA8IDApLAogICAgICAgICAgICBwLmRpZmYubm90MCA9IGlmZWxzZShtZWRpYW4oLnZhbHVlKSA+IDAsIHAuZ3JlYXRlcjAsIHAubGVzczApKSAlPiUgCiAgdW5ncm91cCgpCgojIFNhdmUgY29tYmluZWQgdGFibGUgZm9yIGxhdGVyIHVzZSBpbiBtYW51c2NyaXB0CnRibF9hbW91bnRzX3RpZHkgJT4lIAogIGxlZnRfam9pbih0YmxfYW1vdW50c19wcm9icywgYnkgPSAidGl0bGUiKSAlPiUgCiAgc2F2ZVJEUyhoZXJlKCJkYXRhIiwgImRlcml2ZWRfZGF0YSIsICJyZXN1bHRzX21vZGVsc19hbW91bnQucmRzIikpCgp0YmxfYW1vdW50XzEgPC0gdGJsX2Ftb3VudHNfdGlkeSAlPiUgCiAgbGVmdF9qb2luKHRibF9hbW91bnRzX3Byb2JzLCBieSA9ICJ0aXRsZSIpICU+JSAKICBmaWx0ZXIoY2F0ZWdvcnkgPT0gIkxldmVsIDEiKSAlPiUKICBtdXRhdGUodGl0bGUgPSByZWNvZGUodGl0bGUsIAogICAgICAgICAgICAgICAgICAgICAgICBDcmFja2Rvd24gPSAiQ3JhY2tkb3duIOKIkiBObyBjcmFja2Rvd24iLAogICAgICAgICAgICAgICAgICAgICAgICBJc3N1ZSA9ICIqSHVtYW5pdGFyaWFuIGFzc2lzdGFuY2Ug4oiSIEh1bWFuIHJpZ2h0cyoiLAogICAgICAgICAgICAgICAgICAgICAgICBGdW5kaW5nID0gIipQcml2YXRlIOKIkiBHb3Zlcm5tZW50IGZ1bmRpbmcqIikpICU+JSAKICBtdXRhdGVfYXQodmFycyhtdV8xLCBtdV8yLCBtdV9kaWZmLCBwLmRpZmYubm90MCksIGxpc3QofmFzLmNoYXJhY3Rlcihyb3VuZCguLCAyKSkpKSAlPiUgCiAgbXV0YXRlKHBjdF9jaGFuZ2UgPSBwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkocGN0X2NoYW5nZSkpICU+JQogIHNlbGVjdChgRnJhbWVgID0gdGl0bGUsIGBBbW91bnR+VHJlYXRtZW50fmAgPSBtdV8yLCBgQW1vdW50fkNvbnRyb2x+YCA9IG11XzEsCiAgICAgICAgIGAkXFxEZWx0YSRgID0gbXVfZGlmZiwgYCRcXCVcXERlbHRhJGAgPSBwY3RfY2hhbmdlLCAKICAgICAgICAgYCRwKFxcRGVsdGEgXFxuZXEgMCkkYCA9IHAuZGlmZi5ub3QwKQpgYGAKCmBgYHtyIHRibC1hbW91bnQtZGlmZnMtbGV2ZWwyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0YmxfYW1vdW50XzIgPC0gdGJsX2Ftb3VudHNfdGlkeSAlPiUgCiAgbGVmdF9qb2luKHRibF9hbW91bnRzX3Byb2JzLCBieSA9ICJ0aXRsZSIpICU+JSAKICBmaWx0ZXIoY2F0ZWdvcnkgPT0gIkxldmVsIDIiKSAlPiUKICBtdXRhdGUodGl0bGVfY2xlYW4gPSBzdHJfcmVtb3ZlKHRpdGxlLCAiIFxcfCBDcmFja2Rvd24iKSkgJT4lIAogIG11dGF0ZSh0aXRsZV9jbGVhbiA9IGNhc2Vfd2hlbigKICAgIHRpdGxlX2NsZWFuICVpbiUgYygiSHVtYW4gcmlnaHRzIiwgIkh1bWFuaXRhcmlhbiBhc3Npc3RhbmNlIikgfiBwYXN0ZSh0aXRsZV9jbGVhbiwgImlzc3VlcyIpLAogICAgdGl0bGVfY2xlYW4gJWluJSBjKCJHb3Zlcm5tZW50IiwgIlByaXZhdGUiKSB+IHBhc3RlKHRpdGxlX2NsZWFuLCAiZnVuZGluZyIpCiAgKSkgJT4lIAogIG11dGF0ZSh0aXRsZV9jbGVhbiA9IGZhY3Rvcih0aXRsZV9jbGVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkh1bWFuIHJpZ2h0cyBpc3N1ZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSHVtYW5pdGFyaWFuIGFzc2lzdGFuY2UgaXNzdWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdvdmVybm1lbnQgZnVuZGluZyIsICJQcml2YXRlIGZ1bmRpbmciKSkpICU+JSAKICBhcnJhbmdlKHRpdGxlX2NsZWFuKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMobXVfMSwgbXVfMiwgbXVfZGlmZiwgcC5kaWZmLm5vdDApLCBsaXN0KH5hcy5jaGFyYWN0ZXIocm91bmQoLiwgMikpKSkgJT4lIAogIG11dGF0ZShwY3RfY2hhbmdlID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKHBjdF9jaGFuZ2UpKSAlPiUKICBtdXRhdGUodGl0bGVfY2xlYW4gPSBhcy5jaGFyYWN0ZXIodGl0bGVfY2xlYW4pKSAlPiUgCiAgc2VsZWN0KGBIfjJifiBhbmQgSH4zYn5gID0gdGl0bGVfY2xlYW4sIGBBbW91bnR+Q3JhY2tkb3dufmAgPSBtdV8yLCBgQW1vdW50fk5vXFwgY3JhY2tkb3dufmAgPSBtdV8xLAogICAgICAgICBgJFxcRGVsdGEkYCA9IG11X2RpZmYsIGAkXFwlXFxEZWx0YSRgID0gcGN0X2NoYW5nZSwgCiAgICAgICAgIGAkcChcXERlbHRhIFxcbmVxIDApJGAgPSBwLmRpZmYubm90MCkKYGBgCgpgYGB7ciB0YmwtYW1vdW50LWRpZmZzLWxldmVsMywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KdGJsX2Ftb3VudF8zIDwtIHRibF9hbW91bnRzX3RpZHkgJT4lIAogIGxlZnRfam9pbih0YmxfYW1vdW50c19wcm9icywgYnkgPSAidGl0bGUiKSAlPiUgCiAgZmlsdGVyKGNhdGVnb3J5ID09ICJMZXZlbCAzIikgJT4lCiAgbXV0YXRlKHRpdGxlX2NsZWFuID0gc3RyX3JlbW92ZSh0aXRsZSwgIiBcXHwgQ3JhY2tkb3duIikpICU+JSAKICBzZXBhcmF0ZSh0aXRsZV9jbGVhbiwgYygiSXNzdWUiLCAiRnVuZGluZyIpLCBzZXAgPSAiIFxcfCAiKSAlPiUgCiAgbXV0YXRlKElzc3VlID0gZmFjdG9yKElzc3VlLCBsZXZlbHMgPSBjKCJIdW1hbiByaWdodHMiLCAiSHVtYW5pdGFyaWFuIGFzc2lzdGFuY2UiKSksCiAgICAgICAgIEZ1bmRpbmcgPSBmYWN0b3IoRnVuZGluZywgbGV2ZWxzID0gYygiR292ZXJubWVudCIsICJQcml2YXRlIikpKSAlPiUgCiAgYXJyYW5nZShJc3N1ZSwgRnVuZGluZykgJT4lIAogIG11dGF0ZShGcmFtZSA9IHBhc3RlMChJc3N1ZSwgIiBpc3N1ZXMsICIsIEZ1bmRpbmcsICIgZnVuZGluZyIpKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMobXVfMSwgbXVfMiwgbXVfZGlmZiwgcC5kaWZmLm5vdDApLCBsaXN0KH5hcy5jaGFyYWN0ZXIocm91bmQoLiwgMikpKSkgJT4lIAogIG11dGF0ZShwY3RfY2hhbmdlID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKHBjdF9jaGFuZ2UpKSAlPiUKICBzZWxlY3QoYEh+MmJ+IGFuZCBIfjNifiAobmVzdGVkKWAgPSBGcmFtZSwKICAgICAgICAgYEFtb3VudH5DcmFja2Rvd25+YCA9IG11XzIsIGBBbW91bnR+Tm9cXCBjcmFja2Rvd25+YCA9IG11XzEsCiAgICAgICAgIGAkXFxEZWx0YSRgID0gbXVfZGlmZiwgYCRcXCVcXERlbHRhJGAgPSBwY3RfY2hhbmdlLCAKICAgICAgICAgYCRwKFxcRGVsdGEgXFxuZXEgMCkkYCA9IHAuZGlmZi5ub3QwKQpgYGAKCmBgYHtyIGNvbWJpbmUtYW1vdW50LXRhYmxlcywgcmVzdWx0cz0iYXNpcyJ9CnRibF9hbW91bnRfMl9oZWFkZXIgPC0gZW5mcmFtZShjb2xuYW1lcyh0YmxfYW1vdW50XzIpKSAlPiUgCiAgbXV0YXRlKHZhbHVlID0gKHZhbHVlKSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBuYW1lLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKSAlPiUgCiAgc2V0X25hbWVzKGNvbG5hbWVzKHRibF9hbW91bnRfMSkpCgp0YmxfYW1vdW50XzNfaGVhZGVyIDwtIGVuZnJhbWUoY29sbmFtZXModGJsX2Ftb3VudF8zKSkgJT4lIAogIG11dGF0ZSh2YWx1ZSA9ICh2YWx1ZSkpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gbmFtZSwgdmFsdWVzX2Zyb20gPSB2YWx1ZSkgJT4lIAogIHNldF9uYW1lcyhjb2xuYW1lcyh0YmxfYW1vdW50XzEpKQoKYmluZF9yb3dzKHRibF9hbW91bnRfMSwgCiAgICAgICAgICB0YmxfYW1vdW50XzJfaGVhZGVyLCAKICAgICAgICAgIHNldF9uYW1lcyh0YmxfYW1vdW50XzIsIGNvbG5hbWVzKHRibF9hbW91bnRfMSkpLAogICAgICAgICAgdGJsX2Ftb3VudF8zX2hlYWRlciwKICAgICAgICAgIHNldF9uYW1lcyh0YmxfYW1vdW50XzMsIGNvbG5hbWVzKHRibF9hbW91bnRfMSkpKSAlPiUgCiAgcmVuYW1lKGBIfjFifmAgPSBGcmFtZSkgJT4lIAogIHBhbmRvYy50YWJsZS5yZXR1cm4oY2FwdGlvbiA9ICdNZWFuIHZhbHVlcyBhbmQgZGlmZmVyZW5jZXMgaW4gbWVhbnMgZm9yIGFtb3VudCBkb25hdGVkIGluICJjcmFja2Rvd24iICh0cmVhdG1lbnQpIGFuZCAibm8gY3JhY2tkb3duIiAoY29udHJvbCkgY29uZGl0aW9uczsgdmFsdWVzIHJlcHJlc2VudCBwb3N0ZXJpb3IgbWVkaWFucyB7I3RibDphbW91bnQtZGlmZnN9JywKICAgICAgICAgICAgICAgICAgICAgIGp1c3RpZnkgPSAibGNjY2NjIikgJVQ+JQogIGNhdCgpICU+JQogIGNhdChmaWxlID0gaGVyZSgiYW5hbHlzaXMiLCAib3V0cHV0IiwgInRhYmxlcyIsICJ0YmwtYW1vdW50LWRpZmZzLm1kIikpCmBgYAoKIyMgRWZmZWN0IHNpemUKCmBgYHtyIGFtb3VudC1lZmZlY3Qtc2l6ZSwgd2FybmluZz1GQUxTRSwgb3V0LndpZHRoPSI4MCUifQojIEVmZmVjdCBzaXplCiMgKM684oKBIC0gzrzigoIpIC8gc3FydCggKM+D4oKBwrIgKyDPg+KCgsKyKSAvIDIpCnRpZGllZF9lZmZfc2l6ZV9hbW91bnQgPC0gYWxsX21vZGVsc19hbW91bnQgJT4lIAogIHVubmVzdChwb3N0ZXJpb3JfY2hhaW5zX2xvbmcpICU+JSAKICBmaWx0ZXIoLnZhcmlhYmxlID09ICJjb2hlbl9kIikgJT4lIAogIG11dGF0ZShjYXRlZ29yeSA9IGNhc2Vfd2hlbigKICAgIHN0cl9jb3VudCh0aXRsZSwgIlxcfCIpID09IDAgfiAiTGV2ZWwgMSIsCiAgICBzdHJfY291bnQodGl0bGUsICJcXHwiKSA9PSAxIH4gIkxldmVsIDIiLAogICAgc3RyX2NvdW50KHRpdGxlLCAiXFx8IikgPT0gMiB+ICJMZXZlbCAzIgogICkpICU+JSAKICBtdXRhdGUodGl0bGUgPSBzdHJfcmVtb3ZlKHRpdGxlLCAiIFxcfCBDcmFja2Rvd24iKSkgJT4lIAogIG11dGF0ZSh0aXRsZSA9IGZjdF9pbm9yZGVyKHRpdGxlKSkKCmVmZmVjdF9zaXplcyA8LSB0cmliYmxlKAogIH5zaXplLCB+eF9lbmQsCiAgIlNtYWxsIiwgMC4yLAogICJNZWRpdW0iLCAwLjUsCiAgIkxhcmdlIiwgMC44CikgJT4lIAogIG11dGF0ZSh4X3N0YXJ0ID0gLXhfZW5kKQoKZ2dwbG90KHRpZGllZF9lZmZfc2l6ZV9hbW91bnQsIGFlcyh4ID0gLnZhbHVlLCB5ID0gZmN0X3Jldih0aXRsZSkpKSArCiAgc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC44LCAwLjk1KSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygwLjIsIC0wLjIpLCBsaW5ldHlwZSA9ICJkb3R0ZWQiLCBzaXplID0gMC41KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygwLjUsIC0wLjUpLCBsaW5ldHlwZSA9ICJkb3R0ZWQiLCBzaXplID0gMC41KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygwLjUsIC0wLjUpLCBsaW5ldHlwZSA9ICJkb3R0ZWQiLCBzaXplID0gMC41KSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKC0xLCAxKSkgKwogIGxhYnMoeCA9ICJDb2hlbidzIGQgKGVmZmVjdCBzaXplKSIsIHkgPSBOVUxMKSArCiAgdGhlbWVfbmdvcygpCmBgYAoKXAoKIyBPcmlnaW5hbCBjb21wdXRpbmcgZW52aXJvbm1lbnQKCjxidXR0b24gZGF0YS10b2dnbGU9ImNvbGxhcHNlIiBkYXRhLXRhcmdldD0iI3Nlc3Npb25pbmZvIiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IGJ0bi1tZCBidG4taW5mbyI+SGVyZSdzIHdoYXQgd2UgdXNlZCB0aGUgbGFzdCB0aW1lIHdlIGJ1aWx0IHRoaXMgcGFnZTwvYnV0dG9uPgoKPGRpdiBpZD0ic2Vzc2lvbmluZm8iIGNsYXNzPSJjb2xsYXBzZSI+CgpgYGB7ciBzaG93LXNlc3Npb24taW5mbywgZWNobz1UUlVFLCB3aWR0aD0xMDB9CndyaXRlTGluZXMocmVhZExpbmVzKGZpbGUucGF0aChTeXMuZ2V0ZW52KCJIT01FIiksICIuUi9NYWtldmFycyIpKSkKCmRldnRvb2xzOjpzZXNzaW9uX2luZm8oKQpgYGAKCjwvZGl2PiAK