library(tidyverse)
library(rstanarm)
library(broom)
library(ggstance)
library(patchwork)
library(pander)
library(scales)
library(janitor)
library(huxtable)
library(here)

source(here("lib", "graphics.R"))
source(here("lib", "pander_options.R"))
source(here("lib", "modeling.R"))

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


# Helpful functions
safe_mean <- function(x, ...) suppressWarnings(mean(as.numeric(x), ...))
safe_sd <- function(x, ...) suppressWarnings(sd(as.numeric(x), ...))

my_as_numeric <- function(x) {
  is_num <- suppressWarnings(!any(is.na(as.numeric(x))))
  
  if (is_num) {
    as.numeric(x)
  } else {
    x
  }
}

level_summary <- function(x, variable, df = results) {
  variable <- as.character(variable)
  if (is.factor(df[[variable]])) {
    x_levels <- levels(df[[variable]])
  } else {
    x_levels <- unique(df[[variable]])
  }
  
  factor_summary <- data_frame(x) %>% 
    count(x) %>%
    mutate(pct = n / sum(n),
           fancy = paste0(x, " (", n, "; ", percent(pct), ")"),
           x = factor(x, levels = x_levels, ordered = TRUE)) 
  
  inline_summary <- factor_summary %>% arrange(x) %>% 
    pull(fancy) %>% paste(collapse = " | ")
  
  fig_bar <- ggplot(factor_summary, aes(x = x, y = n)) +
    geom_bar(stat = "identity", fill = "grey50") +
    theme_spark()
  
  file_name <- gsub("\\.| ", "_", tolower(variable))
  md_img <- paste0("![](output/figures/summary-table/", file_name, ")")

  ggsave(fig_bar, filename = here("output", "figures", "summary-table",
                                  paste0(file_name, ".pdf")), 
         width = 1, height = 0.2, device = cairo_pdf)
  ggsave(fig_bar, filename = here("output", "figures", "summary-table",
                                  paste0(file_name, ".png")), 
         width = 1, height = 0.2, type = "cairo", bg = "transparent", dpi = 300)

  output <- data_frame(spark = md_img, summary = inline_summary)
  return(output)
}

numeric_summary <- function(x, variable) {
  inline_summary <- paste0("Median: ", round(median(x, na.rm = TRUE), 2),
                           " | Mean: ", round(mean(x, na.rm = TRUE), 2), 
                           " | Std. Dev.: ", round(sd(x, na.rm = TRUE), 2))
  
  fig_hist <- ggplot(as.data.frame(x), aes(x = x)) +
    geom_histogram(fill = "grey50", binwidth = 10) +
    theme_spark()
  
  file_name <- gsub("\\.| ", "_", tolower(variable))
  md_img <- paste0("![](output/figures/summary-table/", file_name, ")")

  ggsave(fig_hist, filename = here("output", "figures", "summary-table",
                                   paste0(file_name, ".pdf")), 
         width = 1, height = 0.2, device = cairo_pdf)
  ggsave(fig_hist, filename = here("output", "figures", "summary-table",
                                   paste0(file_name, ".png")), 
         width = 1, height = 0.2, type = "cairo", bg = "transparent", dpi = 300)
  
  output <- data_frame(spark = md_img, summary = inline_summary)
  return(output)
}

my_summary <- function(x, variable, df) {
  x <- my_as_numeric(x)
  
  if (is.numeric(x)) {
    numeric_summary(x, variable)
  } else {
    level_summary(x, variable, df)
  }
}

Overview of data

Balance of experimental conditions

Crackdown Issue Funding n
No crackdown Human rights Government 68
No crackdown Human rights Private 67
No crackdown Humanitarian assistance Government 69
No crackdown Humanitarian assistance Private 66
Crackdown Human rights Government 66
Crackdown Human rights Private 69
Crackdown Humanitarian assistance Government 70
Crackdown Humanitarian assistance Private 71
Total - - 546

Descriptive statistics table

vars_to_summarize <- tribble(
  ~variable, ~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)) %>% 
  gather(variable, value) %>% 
  group_by(variable) %>% 
  nest() %>% 
  mutate(N = data %>% map_int(~ nrow(.)),
         summary = map2(.x = data, .y = variable, ~ my_summary(.x$value, .y, results))) %>% 
  left_join(vars_to_summarize, by = "variable") %>% 
  mutate(variable = factor(variable, levels = vars_to_summarize$variable, ordered = TRUE)) %>% 
  arrange(variable) %>% 
  select(-data, -variable) %>% 
  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("output", "tables", "tbl-descriptive-stats.md")) %>%
  cat()
Descriptive statistics {#tbl:descriptive-stats}
Variable Details
Likelihood of donation Extremely unlikely (49; 9.0%) | Somewhat unlikely (114; 20.9%) | Neither likely nor unlikely (141; 25.8%) | Somewhat likely (195; 35.7%) | Extremely likely (47; 8.6%)
Likelihood of donation (binary) Not likely (304; 55.7%) | Likely (242; 44.3%)
Amount hypothetically donated ($) Median: 10 | Mean: 22.15 | Std. Dev.: 25.56
Gender Female (297; 54.4%) | Male (246; 45.1%) | Other (1; 0.2%) | Prefer not to say (2; 0.4%)
Age Under 18 (1; 0.2%) | 18 – 24 (47; 8.6%) | 25 – 34 (214; 39.2%) | 35 – 44 (131; 24.0%) | 45 – 54 (92; 16.8%) | 55 – 64 (44; 8.1%) | 65 – 74 (16; 2.9%) | 75 – 84 (1; 0.2%)
Income Less than $10,000 (35; 6.4%) | $10,000 – $19,999 (43; 7.9%) | $20,000 – $29,999 (51; 9.3%) | $30,000 – $39,999 (81; 14.8%) | $40,000 – $49,999 (60; 11.0%) | $50,000 – $59,999 (56; 10.3%) | $60,000 – $69,999 (44; 8.1%) | $70,000 – $79,999 (39; 7.1%) | $80,000 – $89,999 (25; 4.6%) | $90,000 – $99,999 (30; 5.5%) | $100,000 – $149,999 (47; 8.6%) | More than $150,000 (22; 4.0%) | Prefer not to say (13; 2.4%)
Education Less than high school (2; 0.4%) | High school graduate (48; 8.8%) | Some college (130; 23.8%) | 2 year degree (70; 12.8%) | 4 year degree (221; 40.5%) | Graduate or professional degree (66; 12.1%) | Doctorate (9; 1.6%)
Frequency of attending religious services More than once a week (19; 3.5%) | Once a week (76; 13.9%) | Once or twice a month (50; 9.2%) | A few times a year (72; 13.2%) | Seldom (99; 18.1%) | Never (226; 41.4%) | Don’t know (4; 0.7%)
Political views Strong liberal (80; 14.7%) | Liberal (151; 27.7%) | Independent, leaning liberal (86; 15.8%) | Independent (85; 15.6%) | Independent, leaning conservative (60; 11.0%) | Conservative (62; 11.4%) | Very conservative (22; 4.0%)
Frequency of following public affairs Most of the time (222; 40.7%) | Some of the time (217; 39.7%) | Only now and then (87; 15.9%) | Hardly at all (20; 3.7%)
Frequency of charitable donations Once a week (38; 7.0%) | Once a month (107; 19.6%) | Once every three months (107; 19.6%) | Once every six months (106; 19.4%) | Once a year (92; 16.8%) | Once every few years (57; 10.4%) | Never (39; 7.1%)
Volunteered in past 12 months No (296; 54.21%) | Yes (250; 45.79%)
Prior favorability towards humanitarian NGOs Very unfavorable (2; 0.4%) | Unfavorable (6; 1.1%) | Neutral (43; 7.9%) | Favorable (240; 44.0%) | Very favorable (255; 46.7%)
Prior favorability towards humanitarian NGOs (binary) Not favorable (51; 9.3%) | Favorable (495; 90.7%)
Prior favorability towards human rights NGOs Very unfavorable (5; 0.9%) | Unfavorable (12; 2.2%) | Neutral (64; 11.7%) | Favorable (233; 42.7%) | Very favorable (232; 42.5%)
Prior favorability towards human rights NGOs (binary) Not favorable (81; 14.8%) | Favorable (465; 85.2%)
Prior favorability towards development NGOs Very unfavorable (5; 0.9%) | Unfavorable (8; 1.5%) | Neutral (48; 8.8%) | Favorable (241; 44.1%) | Very favorable (244; 44.7%)
Prior favorability towards development NGOs (binary) Not favorable (61; 11.2%) | Favorable (485; 88.8%)
Attention check 2 Correct (544; 99.6%) | Incorrect (2; 0.4%)

Average likelihood and amount donated across conditions

Crackdown condition Issue condition Funding condition % likely to donate Amount donated (mean) Amount donated (sd) N
No crackdown Human rights Government 47.1% 22.4 24.8 68
Private 38.8% 18.9 22.1 67
Total 43.0% 20.6 23.5 135
Humanitarian assistance Government 43.5% 17.8 21.3 69
Private 40.9% 21.8 26.7 66
Total 42.2% 19.8 24.1 135
Total 42.6% 20.2 23.8 270
Crackdown Human rights Government 28.8% 19.1 25.7 66
Private 58.0% 27.3 26.1 69
Total 43.7% 23.3 26.1 135
Humanitarian assistance Government 50.0% 30.5 32.8 70
Private 46.5% 19.1 21.4 71
Total 48.2% 24.8 28.1 141
Total 46.0% 24 27.1 276
Total 44.3% 22.1 25.6 546


Visualize important variables

Prior favorability towards NGOs

favorability_cols <- data_frame(value = c("Very unfavorable", "Unfavorable", "Neutral",
                                          "Favorable", "Very favorable"),
                                color = ngo_pal("ordered")(5))

ngo_favorability_raw <- results %>%
  select(favor_humanitarian, favor_human_rights, favor_development) %>% 
  gather(variable, value) %>% 
  count(variable, value) %>% 
  left_join(vars_to_summarize, by = "variable") %>% 
  left_join(favorability_cols, by = "value") %>%
  mutate(clean_name = str_replace(clean_name, "towards", "towards\n")) %>% 
  mutate(value = factor(value, levels = levels(results$favor_humanitarian), ordered = TRUE),
         clean_name = fct_inorder(clean_name, ordered = TRUE)) %>%
  arrange(value) %>% 
  mutate(color = fct_inorder(color, ordered = TRUE))

ngo_favorability_high <- ngo_favorability_raw %>% 
  filter(!str_detect(value, "nfav")) %>% 
  mutate(n = ifelse(value == "Neutral", n / 2, n),
         n_plot = n,
         value = fct_rev(value), color = fct_rev(color))

ngo_favorability_low <- ngo_favorability_raw %>% 
  filter(str_detect(value, "nfav") | value == "Neutral") %>% 
  mutate(n = ifelse(value == "Neutral", n / 2, n),
         n_plot = -n)

ggplot(mapping = aes(x = n_plot, y = clean_name, fill = color)) +
  geom_barh(data = ngo_favorability_high, stat = "identity") +
  geom_barh(data = ngo_favorability_low, stat = "identity") +
  geom_vline(xintercept = 0, color = "black") +
  scale_x_continuous(labels = abs) +
  scale_fill_identity(labels = levels(ngo_favorability_raw$value),
                      breaks = levels(ngo_favorability_raw$color),
                      guide = "legend", name = NULL) +
  labs(x = NULL, y = NULL) +
  theme_ngos() +
  theme(panel.grid.minor = element_blank(),
        panel.grid.major.y = element_blank())

Interpreting interactions in models

Ordinarily, people use ANOVA to analyze 3-way, 2 × 2 × 2 factorial designs, like this. A more flexible (yet identical!) way to do this is to use a regular regression model with interaction terms for each of the conditions, like so (here we use three, since we can use simper models to get averages for the larger umbrella groups, like just crackdowns and crackdown + issue):

  • Model 1:

    \[ y = \beta_0 + \beta_1 \text{Crackdown} \]

  • Model 2:

    \[ \begin{aligned} y =& \beta_0 + \beta_1 \text{Crackdown} + \beta_2 \text{Issue } + \\ & \beta_3 \text{Crackdown} \times \text{Issue} \end{aligned} \]

  • Model 3:

    \[ \begin{aligned} y =& \beta_0 + \beta_1 \text{Crackdown} + \beta_2 \text{Issue} + \beta_3 \text{Funding } + \\ & \beta_4 \text{Crackdown} \times \text{Issue } + \\ & \beta_5 \text{Crackdown} \times \text{Funding } + \\ & \beta_6 \text{Issue} \times \text{Funding } + \\ & \beta_7 \text{Crackdown} \times \text{Issue} \times \text{Funding} \end{aligned} \]

Adding different combinations of the coefficients provides the average values for each combination of factors, which corresponds to the average likelihood and amount donated table above.

Crackdown condition Issue condition Funding condition Model Coefficients to add together
No crackdown Human rights Government 3 Intercept
Private 3 Intercept + Funding
Total 2 Intercept
Humanitarian assistance Government 3 Intercept + Issue
Private 3 Intercept + Issue + Funding + (Issue × Funding)
Total 2 Intercept + Issue
Total 1 Intercept
Crackdown Human rights Government 3 Intercept + Crackdown
Private 3 Intercept + Crackdown + Funding + (Crackdown × Funding)
Total 2 Intercept + Crackdown
Humanitarian assistance Government 3 Intercept + Crackdown + Issue + (Crackdown × Issue)
Private 3 Intercept + Crackdown + Issue + Funding + (Crackdown × Issue) + (Crackdown × Funding) + (Issue × Funding) + (Crackdown × Issue × Funding)
Total 2 Intercept + Crackdown + Issue + (Crackdown × Issue)
Total 1 Intercept + Crackdown


Amount donated

Models

(1) (2) (3)
Intercept 20.207  20.641  22.033 
(1.597) (2.239) (3.049)
Crackdown (yes) 3.797  2.636  -2.692 
(2.254) (3.055) (4.337)
Issue (humanitarian)       -0.993  -4.030 
      (3.094) (4.312)
Funding (private)             -2.867 
            (4.444)
Crackdown × Issue       2.418  15.090 
      (4.366) (5.969)
Crackdown × Funding             10.831 
            (6.274)
Issue × Funding             6.595 
            (6.013)
Crackdown × Issue × Funding             -25.544 
            (8.628)
Observations 546      546      546     
Posterior sample size 4000.000  4000.000  4000.000 
Sigma 25.517  25.569  25.386 
.

Predicted medians

The Stan people really really don’t like posterior_linepred(), since it throws away a lot of the uncertainty that comes from actually getting a posterior distribution (like, they didn’t even want to invent it, and then when they did they wanted to hide it, and it has a big warning in the documentation). But this approach here mirrors using predict() to combine all the coefficients and intercept terms in a regular frequentist linear model and it’s probably appropriate for this situation because all the coefficients are actually linked together behind the scenes and create group mean estimates. If I use the full force of posterior_predict(), I add more uncertainty with each added coefficient (so in a 2×2×2 version, the 8th condition is actually the sum of all 8 coefficients, which means it gets 8 levels of uncertainity, which is probably excessive). But we do it both ways too, just to be on the safe side.

Differences in medians

# Nest each fitted chain into a single row that corresponds to each newdata_condition
chains_nested_ci <- chains_fitted_ci %>% 
  as_data_frame() %>% 
  mutate(id = 1:n()) %>% 
  gather(condition, value, -id) %>% 
  group_by(condition) %>% 
  nest()

# Add the fitted chains to the conditions, spread the main crackdown condition
# into two columns, then nest everything by issue
all_chains_ci <- bind_cols(newdata_conditions_ci, chains_nested_ci) %>% 
  unnest(data) %>% 
  select(-condition) %>% 
  group_by(issue) %>% 
  spread(crackdown, value) %>% 
  select(-id) %>% 
  nest()

# All the pairwise differences in a single data frame, grouped by issue
pairs_conditions_ci <- all_chains_ci %>% 
  mutate(diffs_coef_pairs = data %>% map(~ mcmc_pairwise_diffs(.)),
         diffs_coef_pairs_detail = diffs_coef_pairs %>% map(~ tidy_diffs(.)),
         diffs_coefs = diffs_coef_pairs %>% map(~ .$mcmc_diffs))

# Extract coefficient details and plot data
diffs_coef_pairs_detail_ci <- pairs_conditions_ci %>% 
  unnest(diffs_coef_pairs_detail) %>% 
  select(-data, -diffs_coef_pairs, -diffs_coefs) #%>% 
  #mutate(pair = "Hey")

pairs_plot_data_ci <- pairs_conditions_ci %>% 
  select(issue, diffs_coefs) %>% 
  unnest(diffs_coefs) %>%
  gather(pair, value, -issue) %>%
  mutate(pair1 = pair) %>%
  separate(pair1, into = c("group1", "group2"), sep = " - ") %>%
  mutate(pair = ifelse(nchar(pair) > 25,
                       str_replace(pair, "-", "-\n"),
                       pair))

plot_diffs_ci <- ggplot() + 
  geom_density(data = pairs_plot_data_ci, aes(x = value),
               fill = ngo_cols("blue"), colour = NA, alpha = 0.4) + 
  geom_segment(data = diffs_coef_pairs_detail_ci,
               aes(x = q5, xend = q95, y = 0, yend = 0),
               size = 3) +
  geom_vline(data = diffs_coef_pairs_detail_ci, aes(xintercept = median), size = 0.25) +
  geom_vline(xintercept = 0, linetype = "dotted") +
  guides(fill = FALSE, color = FALSE) +
  labs(x = "Difference in medians") +
  theme_ngos(density = TRUE) +
  facet_wrap(~ issue + pair)
# Nest each fitted chain into a single row that corresponds to each newdata_condition
chains_nested_cif <- chains_fitted_cif %>% 
  as_data_frame() %>% 
  mutate(id = 1:n()) %>% 
  gather(condition, value, -id) %>% 
  group_by(condition) %>% 
  nest()

# Add the fitted chains to the conditions, spread the main crackdown condition
# into two columns, then nest everything by issue
all_chains_cif <- bind_cols(newdata_conditions_cif, chains_nested_cif) %>% 
  unnest(data) %>% 
  select(-condition) %>% 
  group_by(issue, funding) %>% 
  spread(crackdown, value) %>% 
  select(-id) %>% 
  nest()

# All the pairwise differences in a single data frame, grouped by issue
pairs_conditions_cif <- all_chains_cif %>% 
  mutate(diffs_coef_pairs = data %>% map(~ mcmc_pairwise_diffs(.)),
         diffs_coef_pairs_detail = diffs_coef_pairs %>% map(~ tidy_diffs(.)),
         diffs_coefs = diffs_coef_pairs %>% map(~ .$mcmc_diffs))

# Extract coefficient details and plot data
diffs_coef_pairs_detail_cif <- pairs_conditions_cif %>% 
  unnest(diffs_coef_pairs_detail) %>% 
  select(-data, -diffs_coef_pairs, -diffs_coefs)

pairs_plot_data_cif <- pairs_conditions_cif %>% 
  select(issue, funding, diffs_coefs) %>% 
  unnest(diffs_coefs) %>%
  gather(pair, value, -issue, -funding) %>%
  mutate(pair1 = pair) %>%
  separate(pair1, into = c("group1", "group2"), sep = " - ") %>%
  mutate(pair = ifelse(nchar(pair) > 25,
                       str_replace(pair, "-", "-\n"),
                       pair))

plot_diffs_cif <- ggplot() + 
  geom_density(data = pairs_plot_data_cif, aes(x = value),
               fill = ngo_cols("red"), colour = NA, alpha = 0.4) + 
  geom_segment(data = diffs_coef_pairs_detail_cif, 
               aes(x = q5, xend = q95, y = 0, yend = 0),
               size = 3) +
  geom_vline(data = diffs_coef_pairs_detail_cif, aes(xintercept = median), size = 0.25) +
  geom_vline(xintercept = 0, linetype = "dotted") +
  guides(fill = FALSE, color = FALSE) +
  labs(x = "Difference in medians") +
  theme_ngos(density = TRUE) +
  facet_wrap(~ issue + funding + pair)

Compare only individual conditions:

Median difference between likelihood to donate across single conditions {#tbl:amount-single-diffs}
Frame median %∆median p(∆ > 0) p(∆ < 0) p(∆ ≠ 0)
Crackdown - No crackdown 3.8 0.188 0.958 0.042 0.958
Humanitarian assistance - Human rights 0.387 0.018 0.559 0.441 0.559
Private - Government -0.709 -0.031 0.368 0.632 0.632


Compare nested conditions (what we’re really most concerned about):

Median difference between amounts donated in “crackdown” (treatment) and “no crackdown” (control) conditions {#tbl:amount-diffs}
Issue Funding median %∆median p(∆ > 0) p(∆ < 0) p(∆ ≠ 0)
3.8 0.188 0.958 0.042 0.958
Human rights 2.64 0.128 0.802 0.198 0.802
Humanitarian assistance 5 0.255 0.945 0.055 0.945
Human rights Government -2.69 -0.123 0.261 0.739 0.739
Human rights Private 8.2 0.434 0.975 0.025 0.975
Humanitarian assistance Government 12.2 0.677 0.998 0.002 0.998
Humanitarian assistance Private -2.33 -0.108 0.291 0.709 0.709


Likelihood of donation

Models

(1) (2) (3)
Intercept -0.299  -0.283  -0.170 
(0.120) (0.171) (0.234)
Crackdown (yes) 0.140  0.020  -0.681 
(0.166) (0.239) (0.340)
Issue (humanitarian)       -0.034  -0.061 
      (0.236) (0.312)
Funding (private)             -0.241 
            (0.337)
Crackdown × Issue       0.227  0.898 
      (0.335) (0.452)
Crackdown × Funding             1.399 
            (0.464)
Issue × Funding             0.086 
            (0.462)
Crackdown × Issue × Funding             -1.343 
            (0.641)
Observations 546      546      546     
Posterior sample size 4000.000  4000.000  4000.000 
Sigma 1.000  1.000  1.000 
.

Predicted medians

Differences in medians

# Nest each fitted chain into a single row that corresponds to each newdata_condition
chains_nested_likely_ci <- chains_fitted_likely_ci %>% 
  as_data_frame() %>% 
  mutate(id = 1:n()) %>% 
  gather(condition, value, -id) %>% 
  group_by(condition) %>% 
  nest()

# Add the fitted chains to the conditions, spread the main crackdown condition
# into two columns, then nest everything by issue
all_chains_likely_ci <- bind_cols(newdata_conditions_ci, 
                                  chains_nested_likely_ci) %>% 
  unnest(data) %>% 
  select(-condition) %>% 
  group_by(issue) %>% 
  spread(crackdown, value) %>% 
  select(-id) %>% 
  nest()

# All the pairwise differences in a single data frame, grouped by issue
pairs_likely_conditions_ci <- all_chains_likely_ci %>% 
  mutate(diffs_coef_pairs = data %>% map(~ mcmc_pairwise_diffs(.)),
         diffs_coef_pairs_detail = diffs_coef_pairs %>% map(~ tidy_diffs(.)),
         diffs_coefs = diffs_coef_pairs %>% map(~ .$mcmc_diffs))

# Extract coefficient details and plot data
diffs_coef_likely_pairs_detail_ci <- pairs_likely_conditions_ci %>% 
  unnest(diffs_coef_pairs_detail) %>% 
  select(-data, -diffs_coef_pairs)

pairs_likely_plot_data_ci <- pairs_likely_conditions_ci %>% 
  select(issue, diffs_coefs) %>% 
  unnest(diffs_coefs) %>%
  gather(pair, value, -issue) %>%
  mutate(pair1 = pair) %>%
  separate(pair1, into = c("group1", "group2"), sep = " - ") %>%
  mutate(pair = ifelse(nchar(pair) > 25,
                       str_replace(pair, "-", "-\n"),
                       pair))

plot_diffs_likely_ci <- ggplot() + 
  geom_density(data = pairs_likely_plot_data_ci, aes(x = value),
               fill = ngo_cols("blue"), colour = NA, alpha = 0.4) + 
  geom_segment(data = diffs_coef_likely_pairs_detail_ci, 
               aes(x = q5, xend = q95, y = 0, yend = 0),
               size = 3) +
  geom_vline(data = diffs_coef_likely_pairs_detail_ci, 
             aes(xintercept = median), size = 0.25) +
  geom_vline(xintercept = 0, linetype = "dotted") +
  guides(fill = FALSE, color = FALSE) +
  scale_x_continuous(labels = percent) +
  labs(x = "Difference in medians") +
  theme_ngos(density = TRUE) +
  facet_wrap(~ issue + pair)
# Nest each fitted chain into a single row that corresponds to each newdata_condition
chains_nested_likely_cif <- chains_fitted_likely_cif %>% 
  as_data_frame() %>% 
  mutate(id = 1:n()) %>% 
  gather(condition, value, -id) %>% 
  group_by(condition) %>% 
  nest()

# Add the fitted chains to the conditions, spread the main crackdown condition
# into two columns, then nest everything by issue
all_chains_likely_cif <- bind_cols(newdata_conditions_cif, 
                                   chains_nested_likely_cif) %>% 
  unnest(data) %>% 
  select(-condition) %>% 
  group_by(issue, funding) %>% 
  spread(crackdown, value) %>% 
  select(-id) %>% 
  nest()

# All the pairwise differences in a single data frame, grouped by issue
pairs_likely_conditions_cif <- all_chains_likely_cif %>% 
  mutate(diffs_coef_pairs = data %>% map(~ mcmc_pairwise_diffs(.)),
         diffs_coef_pairs_detail = diffs_coef_pairs %>% map(~ tidy_diffs(.)),
         diffs_coefs = diffs_coef_pairs %>% map(~ .$mcmc_diffs))

# Extract coefficient details and plot data
diffs_coef_likely_pairs_detail_cif <- pairs_likely_conditions_cif %>% 
  unnest(diffs_coef_pairs_detail) %>% 
  select(-data, -diffs_coef_pairs, -diffs_coefs)

pairs_likely_plot_data_cif <- pairs_likely_conditions_cif %>% 
  select(issue, funding, diffs_coefs) %>% 
  unnest(diffs_coefs) %>%
  gather(pair, value, -issue, -funding) %>%
  mutate(pair1 = pair) %>%
  separate(pair1, into = c("group1", "group2"), sep = " - ") %>%
  mutate(pair = ifelse(nchar(pair) > 25,
                       str_replace(pair, "-", "-\n"),
                       pair))

plot_diffs_likely_cif <- ggplot() +
  geom_density(data = pairs_likely_plot_data_cif, aes(x = value),
               fill = ngo_cols("red"), colour = NA, alpha = 0.4) +
  geom_segment(data = diffs_coef_likely_pairs_detail_cif,
               aes(x = q5, xend = q95, y = 0, yend = 0),
               size = 3) +
  geom_vline(data = diffs_coef_likely_pairs_detail_cif,
             aes(xintercept = `median`), size = 0.25) +
  geom_vline(xintercept = 0, linetype = "dotted") +
  guides(fill = FALSE, color = FALSE) +
  scale_x_continuous(labels = percent) +
  labs(x = "Difference in medians") +
  theme_ngos(density = TRUE) +
  facet_wrap(~ issue + funding + pair)

Compare only individual conditions:

Median difference between likelihood to donate across single conditions {#tbl:likelihood-single-diffs}
Frame median %∆median p(∆ > 0) p(∆ < 0) p(∆ ≠ 0)
Crackdown - No crackdown 0.034 0.08 0.794 0.206 0.794
Humanitarian assistance - Human rights 0.021 0.049 0.694 0.306 0.694
Private - Government 0.038 0.089 0.8 0.2 0.8


Compare nested conditions (what we’re really most concerned about):

Median difference between likelihood to donate in “crackdown” (treatment) and “crackdown” (control) conditions {#tbl:likelihood-diffs}
Issue Funding median %∆median p(∆ > 0) p(∆ < 0) p(∆ ≠ 0)
0.034 0.08 0.794 0.206 0.794
Human rights 0.005 0.011 0.536 0.464 0.536
Humanitarian assistance 0.063 0.15 0.857 0.143 0.857
Human rights Government -0.158 -0.344 0.025 0.975 0.975
Human rights Private 0.176 0.443 0.982 0.018 0.982
Humanitarian assistance Government 0.052 0.117 0.743 0.257 0.743
Humanitarian assistance Private 0.064 0.158 0.771 0.229 0.771

Summary of hypotheses

hypotheses <- tribble(
  ~dv, ~hypothesis, ~summary,
  "Likelihood", "H1a: Donors more likely\nto give to NGOs\nfacing crackdown", diffs_coef_likely_pairs_detail_c,
  "Likelihood", "H2a: Donors more likely\nto give to humanitarian\nNGOs facing crackdown", diffs_coef_likely_pairs_detail_ci,
  "Likelihood", "H3a: Donors more likely\nto give to privately funded\nNGOs facing crackdown", diffs_coef_likely_pairs_detail_cif,
  "Amount", "H1b: Donors give more \nto NGOs facing crackdown", diffs_coef_pairs_detail_c,
  "Amount", "H2b: Donors give more \nto humanitarian NGOs\nfacing crackdown", diffs_coef_pairs_detail_ci,
  "Amount", "H3b: Donors give more \nto privately funded NGOs\nfacing crackdown", diffs_coef_pairs_detail_cif
)

plot_hypotheses <- hypotheses %>% 
  unnest(summary) %>% 
  select(-diffs_coefs) %>% 
  mutate(condition = paste0(issue, " + ", funding),
         condition = recode(condition, 
                            `Human rights + NA` = "Human rights",
                            `Humanitarian assistance + NA` = "Humanitarian assistance",
                            `NA + NA` = "Crackdown only")) %>% 
  mutate(hypothesis_custom = case_when(
    .$condition == "Human rights + Government" ~ paste(hypothesis, "\n(government funding condition)"),
    .$condition == "Humanitarian assistance + Government" ~ paste(hypothesis, "\n(government funding condition)"),
    .$condition == "Human rights + Private" ~ paste(hypothesis, "\n(private funding condition)"),
    .$condition == "Humanitarian assistance + Private" ~ paste(hypothesis, "\n(private funding condition)"),
    TRUE ~ hypothesis
  )) %>% 
  mutate(issue = fct_rev(fct_explicit_na(issue, na_level = "Crackdown only")),
         hypothesis_facet = ifelse(str_detect(hypothesis, "H3"), 2, 1),
         p_lab = case_when(
           .$dv == "Likelihood" ~ sprintf("∆ = %.2f; p(∆ ≠ 0) = %.2f", .$median, .$p.diff.not0),
           .$dv == "Amount" ~ sprintf("∆ = $%.2f; p(∆ ≠ 0) = %.2f", .$median, .$p.diff.not0)
         ))

plot_hypotheses_likely <- filter(plot_hypotheses, dv == "Likelihood")
plot_hypotheses_amount <- filter(plot_hypotheses, dv == "Amount")

plot_summary_likely <- ggplot(plot_hypotheses_likely, 
                              aes(x = median, y = fct_rev(hypothesis_custom))) +
  geom_pointrangeh(aes(xmin = q5, xmax = q95, color = issue),
                   position = position_dodgev(height = 0.5)) +
  geom_vline(xintercept = 0, size = 0.25, linetype = "dashed") +
  geom_label(data = filter(plot_hypotheses_likely, issue == "Human rights"), 
             aes(label = p_lab, color = issue), size = 3, nudge_y = 0.35, show.legend = FALSE) +
  geom_label(data = filter(plot_hypotheses_likely, issue == "Humanitarian assistance"), 
             aes(label = p_lab, color = issue), size = 3, nudge_y = -0.35, show.legend = FALSE) +
  geom_label(data = filter(plot_hypotheses_likely, issue == "Crackdown only"), 
             aes(label = p_lab, color = issue), size = 3, nudge_y = 0.2, show.legend = FALSE) +
  labs(x = expression(paste("Effect of crackdown: (Crackdown - No crackdown)"["median"])),
       y = NULL, subtitle = "Likelihood of donation") +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  scale_color_manual(values = ngo_cols("dark grey", "blue", "red", name = FALSE), name = NULL) +
  coord_cartesian(clip = "off") +
  theme_ngos() + 
  theme(strip.text = element_blank(),
        panel.grid.minor = element_blank(),
        plot.subtitle = element_text(size = rel(1.2), face = "plain", #hjust = 0.5,
                                    family = "Encode Sans Condensed Medium")) +
  facet_wrap(~ hypothesis_facet, nrow = 1, scales = "free")

plot_summary_amount <- ggplot(plot_hypotheses_amount, 
                              aes(x = median, y = fct_rev(hypothesis_custom))) +
  geom_pointrangeh(aes(xmin = q5, xmax = q95, color = issue),
                   position = position_dodgev(height = 0.5)) +
  geom_vline(xintercept = 0, size = 0.25, linetype = "dashed") +
  geom_label(data = filter(plot_hypotheses_amount, issue == "Human rights"), 
             aes(label = p_lab, color = issue), size = 3, nudge_y = 0.35, show.legend = FALSE) +
  geom_label(data = filter(plot_hypotheses_amount, issue == "Humanitarian assistance"), 
             aes(label = p_lab, color = issue), size = 3, nudge_y = -0.35, show.legend = FALSE) +
  geom_label(data = filter(plot_hypotheses_amount, issue == "Crackdown only"), 
             aes(label = p_lab, color = issue), size = 3, nudge_y = 0.2, show.legend = FALSE) +
  labs(x = expression(paste("Effect of crackdown: (Crackdown - No crackdown)"["median"])),
       y = NULL, subtitle = "Amount donated",
       caption = "90% credible intervals shown around each point") +
  scale_x_continuous(labels = dollar_format()) +
  scale_color_manual(values = ngo_cols("dark grey", "blue", "red", name = FALSE), guide = FALSE) +
  coord_cartesian(clip = "off") +
  theme_ngos() + 
  theme(strip.text = element_blank(),
        panel.grid.minor = element_blank(),
        plot.subtitle = element_text(size = rel(1.2), face = "plain", #hjust = 0.5,
                                    family = "Encode Sans Condensed Medium")) +
  facet_wrap(~ hypothesis_facet, nrow = 1, scales = "free")

plot_summary_diffs <- plot_summary_likely + plot_summary_amount +
  plot_layout(ncol = 1)

plot_summary_diffs

Original computing environment

## # http://dirk.eddelbuettel.com/blog/2017/11/27/#011_faster_package_installation_one
## VER=
## CCACHE=ccache
## CC=$(CCACHE) gcc$(VER)
## CXX=$(CCACHE) g++$(VER)
## CXXFLAGS=-Wno-unused-variable -Wno-unused-function -Wno-unused-local-typedefs
## CXX11=$(CCACHE) g++$(VER)
## CXX14=$(CCACHE) g++$(VER)
## FLIBS = -L`gfortran -print-file-name=libgfortran.dylib | xargs dirname`
## FC=$(CCACHE) gfortran$(VER)
## F77=$(CCACHE) gfortran$(VER)
## Session info -------------------------------------------------------------
##  setting  value                       
##  version  R version 3.5.1 (2018-07-02)
##  system   x86_64, darwin15.6.0        
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  tz       America/Denver              
##  date     2018-07-19
## Packages -----------------------------------------------------------------
##  package      * version    date       source                              
##  assertthat     0.2.0      2017-04-11 CRAN (R 3.5.0)                      
##  backports      1.1.2      2017-12-13 CRAN (R 3.5.0)                      
##  base         * 3.5.1      2018-07-05 local                               
##  base64enc      0.1-3      2015-07-28 CRAN (R 3.5.0)                      
##  bayesplot      1.5.0      2018-03-30 CRAN (R 3.5.0)                      
##  bindr          0.1.1      2018-03-13 CRAN (R 3.5.0)                      
##  bindrcpp     * 0.2.2      2018-03-29 CRAN (R 3.5.0)                      
##  broom        * 0.4.5      2018-07-03 CRAN (R 3.5.0)                      
##  cellranger     1.1.0      2016-07-27 CRAN (R 3.5.0)                      
##  cli            1.0.0      2017-11-05 CRAN (R 3.5.0)                      
##  coda           0.19-1     2016-12-08 CRAN (R 3.5.0)                      
##  codetools      0.2-15     2016-10-05 CRAN (R 3.5.1)                      
##  colorspace     1.3-2      2016-12-14 CRAN (R 3.5.0)                      
##  colourpicker   1.0        2017-09-27 CRAN (R 3.5.0)                      
##  compiler       3.5.1      2018-07-05 local                               
##  crayon         1.3.4      2017-09-16 CRAN (R 3.5.0)                      
##  crosstalk      1.0.0      2016-12-21 CRAN (R 3.5.0)                      
##  datasets     * 3.5.1      2018-07-05 local                               
##  devtools       1.13.5     2018-02-18 CRAN (R 3.5.0)                      
##  digest         0.6.15     2018-01-28 CRAN (R 3.5.0)                      
##  dplyr        * 0.7.6      2018-06-29 CRAN (R 3.5.1)                      
##  DT             0.4        2018-01-30 CRAN (R 3.5.0)                      
##  dygraphs       1.1.1.4    2017-01-04 CRAN (R 3.5.0)                      
##  evaluate       0.10.1     2017-06-24 CRAN (R 3.5.0)                      
##  forcats      * 0.3.0      2018-02-19 CRAN (R 3.5.0)                      
##  foreign        0.8-70     2017-11-28 CRAN (R 3.5.1)                      
##  ggplot2      * 3.0.0      2018-07-03 CRAN (R 3.5.0)                      
##  ggridges       0.5.0      2018-04-05 CRAN (R 3.5.0)                      
##  ggstance     * 0.3        2016-11-16 CRAN (R 3.5.0)                      
##  glue           1.2.0.9000 2018-04-30 Github (tidyverse/glue@b538962)     
##  graphics     * 3.5.1      2018-07-05 local                               
##  grDevices    * 3.5.1      2018-07-05 local                               
##  grid           3.5.1      2018-07-05 local                               
##  gridExtra      2.3        2017-09-09 CRAN (R 3.5.0)                      
##  gtable         0.2.0      2016-02-26 CRAN (R 3.5.0)                      
##  gtools         3.5.0      2015-05-29 CRAN (R 3.5.0)                      
##  haven          1.1.2      2018-06-27 CRAN (R 3.5.0)                      
##  here         * 0.1        2017-05-28 CRAN (R 3.5.0)                      
##  hms            0.4.2      2018-03-10 CRAN (R 3.5.0)                      
##  htmltools      0.3.6      2017-04-28 CRAN (R 3.5.0)                      
##  htmlwidgets    1.2        2018-04-19 CRAN (R 3.5.0)                      
##  httpuv         1.4.3      2018-05-10 cran (@1.4.3)                       
##  httr           1.3.1      2017-08-20 CRAN (R 3.5.0)                      
##  huxtable     * 4.0.1      2018-07-03 CRAN (R 3.5.0)                      
##  igraph         1.2.1      2018-03-10 CRAN (R 3.5.0)                      
##  inline         0.3.14     2015-04-13 CRAN (R 3.5.0)                      
##  janitor      * 1.0.0      2018-03-22 CRAN (R 3.5.0)                      
##  jsonlite       1.5        2017-06-01 CRAN (R 3.5.0)                      
##  knitr          1.20       2018-02-20 CRAN (R 3.5.0)                      
##  labeling       0.3        2014-08-23 CRAN (R 3.5.0)                      
##  later          0.7.3      2018-06-08 cran (@0.7.3)                       
##  lattice        0.20-35    2017-03-25 CRAN (R 3.5.1)                      
##  lazyeval       0.2.1      2017-10-29 CRAN (R 3.5.0)                      
##  lme4           1.1-17     2018-04-03 CRAN (R 3.5.0)                      
##  loo            2.0.0      2018-04-11 CRAN (R 3.5.0)                      
##  lubridate      1.7.4      2018-04-11 CRAN (R 3.5.0)                      
##  magrittr       1.5        2014-11-22 CRAN (R 3.5.0)                      
##  markdown       0.8        2017-04-20 CRAN (R 3.5.0)                      
##  MASS           7.3-50     2018-04-30 CRAN (R 3.5.1)                      
##  Matrix         1.2-14     2018-04-13 CRAN (R 3.5.1)                      
##  matrixStats    0.53.1     2018-02-11 CRAN (R 3.5.0)                      
##  memoise        1.1.0      2017-04-21 CRAN (R 3.5.0)                      
##  methods      * 3.5.1      2018-07-05 local                               
##  mime           0.5        2016-07-07 CRAN (R 3.5.0)                      
##  miniUI         0.1.1      2016-01-15 CRAN (R 3.5.0)                      
##  minqa          1.2.4      2014-10-09 CRAN (R 3.5.0)                      
##  mnormt         1.5-5      2016-10-15 CRAN (R 3.5.0)                      
##  modelr         0.1.2      2018-05-11 CRAN (R 3.5.0)                      
##  munsell        0.5.0      2018-06-12 cran (@0.5.0)                       
##  nlme           3.1-137    2018-04-07 CRAN (R 3.5.1)                      
##  nloptr         1.0.4      2017-08-22 CRAN (R 3.5.0)                      
##  pander       * 0.6.1      2017-08-06 CRAN (R 3.5.0)                      
##  parallel       3.5.1      2018-07-05 local                               
##  patchwork    * 0.0.1      2018-07-16 Github (thomasp85/patchwork@7fb35b1)
##  pillar         1.2.3      2018-05-25 CRAN (R 3.5.0)                      
##  pkgconfig      2.0.1      2017-03-21 CRAN (R 3.5.0)                      
##  plyr           1.8.4      2016-06-08 CRAN (R 3.5.0)                      
##  promises       1.0.1      2018-04-13 CRAN (R 3.5.0)                      
##  psych          1.8.4      2018-05-06 cran (@1.8.4)                       
##  purrr        * 0.2.5      2018-05-29 cran (@0.2.5)                       
##  R6             2.2.2      2017-06-17 CRAN (R 3.5.0)                      
##  Rcpp         * 0.12.17    2018-05-18 cran (@0.12.17)                     
##  readr        * 1.1.1      2017-05-16 CRAN (R 3.5.0)                      
##  readxl         1.1.0      2018-04-20 CRAN (R 3.5.0)                      
##  reshape2       1.4.3      2017-12-11 CRAN (R 3.5.0)                      
##  rlang          0.2.1      2018-05-30 CRAN (R 3.5.0)                      
##  rmarkdown      1.10       2018-06-11 CRAN (R 3.5.0)                      
##  rprojroot      1.3-2      2018-01-03 CRAN (R 3.5.0)                      
##  rsconnect      0.8.8      2018-03-09 CRAN (R 3.5.0)                      
##  rstan          2.17.3     2018-01-20 CRAN (R 3.5.0)                      
##  rstanarm     * 2.17.4     2018-04-13 CRAN (R 3.5.0)                      
##  rstantools     1.5.0      2018-04-17 CRAN (R 3.5.0)                      
##  rstudioapi     0.7        2017-09-07 CRAN (R 3.5.0)                      
##  rvest          0.3.2      2016-06-17 CRAN (R 3.5.0)                      
##  scales       * 0.5.0.9000 2018-07-16 Github (hadley/scales@419236a)      
##  shiny          1.0.5      2017-08-23 CRAN (R 3.5.0)                      
##  shinyjs        1.0        2018-01-08 CRAN (R 3.5.0)                      
##  shinystan      2.5.0      2018-05-01 CRAN (R 3.5.0)                      
##  shinythemes    1.1.1      2016-10-12 CRAN (R 3.5.0)                      
##  splines        3.5.1      2018-07-05 local                               
##  StanHeaders    2.17.2     2018-01-20 CRAN (R 3.5.0)                      
##  stats        * 3.5.1      2018-07-05 local                               
##  stats4         3.5.1      2018-07-05 local                               
##  stringi        1.2.3      2018-06-12 CRAN (R 3.5.0)                      
##  stringr      * 1.3.1      2018-05-10 CRAN (R 3.5.0)                      
##  survival       2.42-3     2018-04-16 CRAN (R 3.5.1)                      
##  threejs        0.3.1      2017-08-13 CRAN (R 3.5.0)                      
##  tibble       * 1.4.2      2018-01-22 CRAN (R 3.5.0)                      
##  tidyr        * 0.8.1      2018-05-18 CRAN (R 3.5.0)                      
##  tidyselect     0.2.4      2018-02-26 CRAN (R 3.5.0)                      
##  tidyverse    * 1.2.1      2017-11-14 CRAN (R 3.5.0)                      
##  tools          3.5.1      2018-07-05 local                               
##  utils        * 3.5.1      2018-07-05 local                               
##  withr          2.1.2      2018-07-16 Github (jimhester/withr@fe56f20)    
##  xml2           1.2.0      2018-01-24 CRAN (R 3.5.0)                      
##  xtable         1.8-2      2016-02-05 CRAN (R 3.5.0)                      
##  xts            0.10-2     2018-03-14 CRAN (R 3.5.0)                      
##  yaml           2.1.19     2018-05-01 CRAN (R 3.5.0)                      
##  zoo            1.8-1      2018-01-08 CRAN (R 3.5.0)
LS0tCnRpdGxlOiAiUmVzdWx0cyIKYXV0aG9yOiAiQW5kcmV3IEhlaXNzIGFuZCBTdXBhcm5hIENoYXVkaHJ5IgpkYXRlOiAiTGFzdCBydW46IGByIGZvcm1hdChTeXMudGltZSgpLCAnJUIgJWUsICVZJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHBhbmRvY19hcmdzOiBbCiAgICAgICItLWRlZmF1bHQtaW1hZ2UtZXh0ZW5zaW9uPXBuZyIKICAgIF0KZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3IgbG9hZC1saWJyYXJpZXMtZGF0YSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocnN0YW5hcm0pCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkoZ2dzdGFuY2UpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHBhbmRlcikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoamFuaXRvcikKbGlicmFyeShodXh0YWJsZSkKbGlicmFyeShoZXJlKQoKc291cmNlKGhlcmUoImxpYiIsICJncmFwaGljcy5SIikpCnNvdXJjZShoZXJlKCJsaWIiLCAicGFuZGVyX29wdGlvbnMuUiIpKQpzb3VyY2UoaGVyZSgibGliIiwgIm1vZGVsaW5nLlIiKSkKCiMgTG9hZCBkYXRhCnJlc3VsdHMgPC0gcmVhZFJEUyhoZXJlKCJkYXRhIiwgInJlc3VsdHNfY2xlYW4ucmRzIikpCiMgcXdyYXBzMjo6bGF6eWxvYWRfY2FjaGVfZGlyKCIwMl9hbmFseXNpc19jYWNoZS9odG1sIikKCgojIEhlbHBmdWwgZnVuY3Rpb25zCnNhZmVfbWVhbiA8LSBmdW5jdGlvbih4LCAuLi4pIHN1cHByZXNzV2FybmluZ3MobWVhbihhcy5udW1lcmljKHgpLCAuLi4pKQpzYWZlX3NkIDwtIGZ1bmN0aW9uKHgsIC4uLikgc3VwcHJlc3NXYXJuaW5ncyhzZChhcy5udW1lcmljKHgpLCAuLi4pKQoKbXlfYXNfbnVtZXJpYyA8LSBmdW5jdGlvbih4KSB7CiAgaXNfbnVtIDwtIHN1cHByZXNzV2FybmluZ3MoIWFueShpcy5uYShhcy5udW1lcmljKHgpKSkpCiAgCiAgaWYgKGlzX251bSkgewogICAgYXMubnVtZXJpYyh4KQogIH0gZWxzZSB7CiAgICB4CiAgfQp9CgpsZXZlbF9zdW1tYXJ5IDwtIGZ1bmN0aW9uKHgsIHZhcmlhYmxlLCBkZiA9IHJlc3VsdHMpIHsKICB2YXJpYWJsZSA8LSBhcy5jaGFyYWN0ZXIodmFyaWFibGUpCiAgaWYgKGlzLmZhY3RvcihkZltbdmFyaWFibGVdXSkpIHsKICAgIHhfbGV2ZWxzIDwtIGxldmVscyhkZltbdmFyaWFibGVdXSkKICB9IGVsc2UgewogICAgeF9sZXZlbHMgPC0gdW5pcXVlKGRmW1t2YXJpYWJsZV1dKQogIH0KICAKICBmYWN0b3Jfc3VtbWFyeSA8LSBkYXRhX2ZyYW1lKHgpICU+JSAKICAgIGNvdW50KHgpICU+JQogICAgbXV0YXRlKHBjdCA9IG4gLyBzdW0obiksCiAgICAgICAgICAgZmFuY3kgPSBwYXN0ZTAoeCwgIiAoIiwgbiwgIjsgIiwgcGVyY2VudChwY3QpLCAiKSIpLAogICAgICAgICAgIHggPSBmYWN0b3IoeCwgbGV2ZWxzID0geF9sZXZlbHMsIG9yZGVyZWQgPSBUUlVFKSkgCiAgCiAgaW5saW5lX3N1bW1hcnkgPC0gZmFjdG9yX3N1bW1hcnkgJT4lIGFycmFuZ2UoeCkgJT4lIAogICAgcHVsbChmYW5jeSkgJT4lIHBhc3RlKGNvbGxhcHNlID0gIiB8ICIpCiAgCiAgZmlnX2JhciA8LSBnZ3Bsb3QoZmFjdG9yX3N1bW1hcnksIGFlcyh4ID0geCwgeSA9IG4pKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJncmV5NTAiKSArCiAgICB0aGVtZV9zcGFyaygpCiAgCiAgZmlsZV9uYW1lIDwtIGdzdWIoIlxcLnwgIiwgIl8iLCB0b2xvd2VyKHZhcmlhYmxlKSkKICBtZF9pbWcgPC0gcGFzdGUwKCIhW10ob3V0cHV0L2ZpZ3VyZXMvc3VtbWFyeS10YWJsZS8iLCBmaWxlX25hbWUsICIpIikKCiAgZ2dzYXZlKGZpZ19iYXIsIGZpbGVuYW1lID0gaGVyZSgib3V0cHV0IiwgImZpZ3VyZXMiLCAic3VtbWFyeS10YWJsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoZmlsZV9uYW1lLCAiLnBkZiIpKSwgCiAgICAgICAgIHdpZHRoID0gMSwgaGVpZ2h0ID0gMC4yLCBkZXZpY2UgPSBjYWlyb19wZGYpCiAgZ2dzYXZlKGZpZ19iYXIsIGZpbGVuYW1lID0gaGVyZSgib3V0cHV0IiwgImZpZ3VyZXMiLCAic3VtbWFyeS10YWJsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoZmlsZV9uYW1lLCAiLnBuZyIpKSwgCiAgICAgICAgIHdpZHRoID0gMSwgaGVpZ2h0ID0gMC4yLCB0eXBlID0gImNhaXJvIiwgYmcgPSAidHJhbnNwYXJlbnQiLCBkcGkgPSAzMDApCgogIG91dHB1dCA8LSBkYXRhX2ZyYW1lKHNwYXJrID0gbWRfaW1nLCBzdW1tYXJ5ID0gaW5saW5lX3N1bW1hcnkpCiAgcmV0dXJuKG91dHB1dCkKfQoKbnVtZXJpY19zdW1tYXJ5IDwtIGZ1bmN0aW9uKHgsIHZhcmlhYmxlKSB7CiAgaW5saW5lX3N1bW1hcnkgPC0gcGFzdGUwKCJNZWRpYW46ICIsIHJvdW5kKG1lZGlhbih4LCBuYS5ybSA9IFRSVUUpLCAyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiB8IE1lYW46ICIsIHJvdW5kKG1lYW4oeCwgbmEucm0gPSBUUlVFKSwgMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAiIHwgU3RkLiBEZXYuOiAiLCByb3VuZChzZCh4LCBuYS5ybSA9IFRSVUUpLCAyKSkKICAKICBmaWdfaGlzdCA8LSBnZ3Bsb3QoYXMuZGF0YS5mcmFtZSh4KSwgYWVzKHggPSB4KSkgKwogICAgZ2VvbV9oaXN0b2dyYW0oZmlsbCA9ICJncmV5NTAiLCBiaW53aWR0aCA9IDEwKSArCiAgICB0aGVtZV9zcGFyaygpCiAgCiAgZmlsZV9uYW1lIDwtIGdzdWIoIlxcLnwgIiwgIl8iLCB0b2xvd2VyKHZhcmlhYmxlKSkKICBtZF9pbWcgPC0gcGFzdGUwKCIhW10ob3V0cHV0L2ZpZ3VyZXMvc3VtbWFyeS10YWJsZS8iLCBmaWxlX25hbWUsICIpIikKCiAgZ2dzYXZlKGZpZ19oaXN0LCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgInN1bW1hcnktdGFibGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMChmaWxlX25hbWUsICIucGRmIikpLCAKICAgICAgICAgd2lkdGggPSAxLCBoZWlnaHQgPSAwLjIsIGRldmljZSA9IGNhaXJvX3BkZikKICBnZ3NhdmUoZmlnX2hpc3QsIGZpbGVuYW1lID0gaGVyZSgib3V0cHV0IiwgImZpZ3VyZXMiLCAic3VtbWFyeS10YWJsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKGZpbGVfbmFtZSwgIi5wbmciKSksIAogICAgICAgICB3aWR0aCA9IDEsIGhlaWdodCA9IDAuMiwgdHlwZSA9ICJjYWlybyIsIGJnID0gInRyYW5zcGFyZW50IiwgZHBpID0gMzAwKQogIAogIG91dHB1dCA8LSBkYXRhX2ZyYW1lKHNwYXJrID0gbWRfaW1nLCBzdW1tYXJ5ID0gaW5saW5lX3N1bW1hcnkpCiAgcmV0dXJuKG91dHB1dCkKfQoKbXlfc3VtbWFyeSA8LSBmdW5jdGlvbih4LCB2YXJpYWJsZSwgZGYpIHsKICB4IDwtIG15X2FzX251bWVyaWMoeCkKICAKICBpZiAoaXMubnVtZXJpYyh4KSkgewogICAgbnVtZXJpY19zdW1tYXJ5KHgsIHZhcmlhYmxlKQogIH0gZWxzZSB7CiAgICBsZXZlbF9zdW1tYXJ5KHgsIHZhcmlhYmxlLCBkZikKICB9Cn0KYGBgCgoKIyBPdmVydmlldyBvZiBkYXRhCgojIyBCYWxhbmNlIG9mIGV4cGVyaW1lbnRhbCBjb25kaXRpb25zCgpgYGB7ciBjaGVjay1jb25kaXRpb25zLCByZXN1bHRzPSJhc2lzIn0KcmVzdWx0cyAlPiUgY291bnQoY3JhY2tkb3duLCBpc3N1ZSwgZnVuZGluZykgJT4lIAogIHJlbmFtZShDcmFja2Rvd24gPSBjcmFja2Rvd24sIElzc3VlID0gaXNzdWUsIEZ1bmRpbmcgPSBmdW5kaW5nKSAlPiUgCiAgamFuaXRvcjo6YWRvcm5fdG90YWxzKC4sIHdoZXJlID0gInJvdyIpICVUPiUgCiAgcGFuZG9jLnRhYmxlKCkgJT4lIAogIHBhbmRvYy50YWJsZS5yZXR1cm4oY2FwdGlvbiA9ICJCYWxhbmNlIG9mIGV4cGVyaW1lbnRhbCBjb25kaXRpb25zIHsjdGJsOmV4cGVyaW1lbnRhbC1jb25kaXRpb25zfSIpICU+JSAKICBjYXQoZmlsZSA9IGhlcmUoIm91dHB1dCIsICJ0YWJsZXMiLCAidGJsLWV4cGVyaW1lbnRhbC1jb25kaXRpb25zLm1kIikpCmBgYAoKIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcyB0YWJsZQoKYGBge3IgdGJsLWRlc2NyaXB0aXZlLXN0YXRpc3RpY3MsIHJlc3VsdHM9ImFzaXMiLCB3YXJuaW5nPUZBTFNFfQp2YXJzX3RvX3N1bW1hcml6ZSA8LSB0cmliYmxlKAogIH52YXJpYWJsZSwgfmNsZWFuX25hbWUsCiAgImRvbmF0ZV9saWtlbHkiLCAiTGlrZWxpaG9vZCBvZiBkb25hdGlvbiIsCiAgImRvbmF0ZV9saWtlbHlfYmluIiwgIkxpa2VsaWhvb2Qgb2YgZG9uYXRpb24gKGJpbmFyeSkiLAogICJhbW91bnRfZG9uYXRlIiwgIkFtb3VudCBoeXBvdGhldGljYWxseSBkb25hdGVkICgkKSIsCiAgImdlbmRlciIsICJHZW5kZXIiLAogICJhZ2UiLCAiQWdlIiwKICAiaW5jb21lIiwgIkluY29tZSIsCiAgImVkdWNhdGlvbiIsICJFZHVjYXRpb24iLAogICJyZWxpZ2lvc2l0eSIsICJGcmVxdWVuY3kgb2YgYXR0ZW5kaW5nIHJlbGlnaW91cyBzZXJ2aWNlcyIsCiAgImlkZW9sb2d5IiwgIlBvbGl0aWNhbCB2aWV3cyIsCiAgInBvbGl0aWNhbF9rbm93bGVkZ2UiLCAiRnJlcXVlbmN5IG9mIGZvbGxvd2luZyBwdWJsaWMgYWZmYWlycyIsCiAgImdpdmVfY2hhcml0eSIsICJGcmVxdWVuY3kgb2YgY2hhcml0YWJsZSBkb25hdGlvbnMiLAogICJ2b2x1bnRlZXIiLCAiVm9sdW50ZWVyZWQgaW4gcGFzdCAxMiBtb250aHMiLAogICJmYXZvcl9odW1hbml0YXJpYW4iLCAiUHJpb3IgZmF2b3JhYmlsaXR5IHRvd2FyZHMgaHVtYW5pdGFyaWFuIE5HT3MiLAogICJmYXZvcl9odW1hbml0YXJpYW5fYmluIiwgIlByaW9yIGZhdm9yYWJpbGl0eSB0b3dhcmRzIGh1bWFuaXRhcmlhbiBOR09zIChiaW5hcnkpIiwKICAiZmF2b3JfaHVtYW5fcmlnaHRzIiwgIlByaW9yIGZhdm9yYWJpbGl0eSB0b3dhcmRzIGh1bWFuIHJpZ2h0cyBOR09zIiwKICAiZmF2b3JfaHVtYW5fcmlnaHRzX2JpbiIsICJQcmlvciBmYXZvcmFiaWxpdHkgdG93YXJkcyBodW1hbiByaWdodHMgTkdPcyAoYmluYXJ5KSIsCiAgImZhdm9yX2RldmVsb3BtZW50IiwgIlByaW9yIGZhdm9yYWJpbGl0eSB0b3dhcmRzIGRldmVsb3BtZW50IE5HT3MiLAogICJmYXZvcl9kZXZlbG9wbWVudF9iaW4iLCAiUHJpb3IgZmF2b3JhYmlsaXR5IHRvd2FyZHMgZGV2ZWxvcG1lbnQgTkdPcyAoYmluYXJ5KSIsCiAgImNoZWNrMiIsICJBdHRlbnRpb24gY2hlY2sgMiIKKQoKcmVzdWx0c19zdW1tYXJ5X3N0YXRzIDwtIHJlc3VsdHMgJT4lIAogIHNlbGVjdChvbmVfb2YodmFyc190b19zdW1tYXJpemUkdmFyaWFibGUpKSAlPiUgCiAgZ2F0aGVyKHZhcmlhYmxlLCB2YWx1ZSkgJT4lIAogIGdyb3VwX2J5KHZhcmlhYmxlKSAlPiUgCiAgbmVzdCgpICU+JSAKICBtdXRhdGUoTiA9IGRhdGEgJT4lIG1hcF9pbnQofiBucm93KC4pKSwKICAgICAgICAgc3VtbWFyeSA9IG1hcDIoLnggPSBkYXRhLCAueSA9IHZhcmlhYmxlLCB+IG15X3N1bW1hcnkoLngkdmFsdWUsIC55LCByZXN1bHRzKSkpICU+JSAKICBsZWZ0X2pvaW4odmFyc190b19zdW1tYXJpemUsIGJ5ID0gInZhcmlhYmxlIikgJT4lIAogIG11dGF0ZSh2YXJpYWJsZSA9IGZhY3Rvcih2YXJpYWJsZSwgbGV2ZWxzID0gdmFyc190b19zdW1tYXJpemUkdmFyaWFibGUsIG9yZGVyZWQgPSBUUlVFKSkgJT4lIAogIGFycmFuZ2UodmFyaWFibGUpICU+JSAKICBzZWxlY3QoLWRhdGEsIC12YXJpYWJsZSkgJT4lIAogIHVubmVzdChzdW1tYXJ5KSAlPiUgCiAgc2VsZWN0KFZhcmlhYmxlID0gY2xlYW5fbmFtZSwgTiwgYCBgID0gc3BhcmssIERldGFpbHMgPSBzdW1tYXJ5KQoKcmVzdWx0c19zdW1tYXJ5X3N0YXRzICU+JSAKICBzZWxlY3QoLU4pICU+JSAKICBwYW5kb2MudGFibGUucmV0dXJuKGNhcHRpb24gPSAiRGVzY3JpcHRpdmUgc3RhdGlzdGljcyB7I3RibDpkZXNjcmlwdGl2ZS1zdGF0c30iLAogICAgICAgICAgICAgICAgICAgICAgc3BsaXQuY2VsbCA9IDgwLCBzcGxpdC50YWJsZSA9IEluZikgJVQ+JSAKICBjYXQoZmlsZSA9IGhlcmUoIm91dHB1dCIsICJ0YWJsZXMiLCAidGJsLWRlc2NyaXB0aXZlLXN0YXRzLm1kIikpICU+JQogIGNhdCgpCmBgYAoKIyMgQXZlcmFnZSBsaWtlbGlob29kIGFuZCBhbW91bnQgZG9uYXRlZCBhY3Jvc3MgY29uZGl0aW9ucwoKYGBge3IgdGJsLXJlc3VsdHMtY29uZGl0aW9ucywgcmVzdWx0cz0iYXNpcyJ9CmNvbmRpdGlvbnNfc3VtbWFyeSA8LSBiaW5kX3Jvd3MoZ3JvdXBfYnkocmVzdWx0cywgY3JhY2tkb3duLCBpc3N1ZSwgZnVuZGluZykgJT4lIG5lc3QoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShyZXN1bHRzLCBjcmFja2Rvd24sIGlzc3VlKSAlPiUgbmVzdCgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KHJlc3VsdHMsIGNyYWNrZG93bikgJT4lIG5lc3QoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzICU+JSBuZXN0KCkpICU+JSAKICBhcnJhbmdlKGNyYWNrZG93biwgaXNzdWUsIGZ1bmRpbmcpICU+JSAKICBtdXRhdGUoc3VtbWFyeSA9IGRhdGEgJT4lCiAgICAgICAgICAgbWFwKH4gc3VtbWFyaXplKC4sIHBjdF9saWtlbHkgPSB0YWJsZShkb25hdGVfbGlrZWx5X2JpbilbWyJMaWtlbHkiXV0gLwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aChkb25hdGVfbGlrZWx5X2JpbiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW5fZG9uYXRpb24gPSBtZWFuKGFtb3VudF9kb25hdGUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX2RvbmF0aW9uID0gc2QoYW1vdW50X2RvbmF0ZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgTiA9IG5yb3coLikpKSkgJT4lIAogIHVubmVzdChzdW1tYXJ5KSAlPiUgc2VsZWN0KC1kYXRhKQoKY29uZGl0aW9uc19zdW1tYXJ5X2NsZWFuIDwtIGNvbmRpdGlvbnNfc3VtbWFyeSAlPiUgCiAgbXV0YXRlKGZ1bmRpbmcgPSBpZmVsc2UoaXMubmEoZnVuZGluZykgJiAhaXMubmEoaXNzdWUpICwgIipUb3RhbCoiLCBhcy5jaGFyYWN0ZXIoZnVuZGluZykpLAogICAgICAgICBpc3N1ZSA9IGlmZWxzZShpcy5uYShpc3N1ZSkgJiAhaXMubmEoY3JhY2tkb3duKSwgIipUb3RhbCoiLCBhcy5jaGFyYWN0ZXIoaXNzdWUpKSwKICAgICAgICAgY3JhY2tkb3duID0gaWZlbHNlKGlzLm5hKGNyYWNrZG93biksICIqVG90YWwqIiwgYXMuY2hhcmFjdGVyKGNyYWNrZG93bikpKSAlPiUgCiAgZ3JvdXBfYnkoY3JhY2tkb3duKSAlPiUgCiAgbXV0YXRlKGlzc3VlID0gcmVwbGFjZShpc3N1ZSwgZHVwbGljYXRlZChpc3N1ZSksIE5BKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgbXV0YXRlKGNyYWNrZG93biA9IHJlcGxhY2UoY3JhY2tkb3duLCBkdXBsaWNhdGVkKGNyYWNrZG93biksIE5BKSkgJT4lIAogIG11dGF0ZShwY3RfbGlrZWx5ID0gcGVyY2VudChwY3RfbGlrZWx5KSkgJT4lIAogIHJlbmFtZShgQ3JhY2tkb3duIGNvbmRpdGlvbmAgPSBjcmFja2Rvd24sIGBJc3N1ZSBjb25kaXRpb25gID0gaXNzdWUsCiAgICAgICAgIGBGdW5kaW5nIGNvbmRpdGlvbmAgPSBmdW5kaW5nLCBgJSBsaWtlbHkgdG8gZG9uYXRlYCA9IHBjdF9saWtlbHksCiAgICAgICAgIGBBbW91bnQgZG9uYXRlZCAobWVhbilgID0gbWVhbl9kb25hdGlvbiwgYEFtb3VudCBkb25hdGVkIChzZClgID0gc2RfZG9uYXRpb24pCgpjb25kaXRpb25zX3N1bW1hcnlfY2xlYW4gJVQ+JSAKICBwYW5kb2MudGFibGUoKSAlPiUgCiAgcGFuZG9jLnRhYmxlLnJldHVybihjYXB0aW9uID0gIkF2ZXJhZ2UgbGlrZWxpaG9vZCBhbmQgYW1vdW50IGRvbmF0ZWQgYWNyb3NzIGV4cGVyaW1lbnRhbCBjb25kaXRpb25zIHsjdGJsOmF2Zy1yZXN1bHRzfSIpICU+JSAKICBjYXQoZmlsZSA9IGhlcmUoIm91dHB1dCIsICJ0YWJsZXMiLCAidGJsLWF2Zy1yZXN1bHRzLm1kIikpCmBgYAoKXAoKIyBWaXN1YWxpemUgaW1wb3J0YW50IHZhcmlhYmxlcwoKIyMgUHJpb3IgZmF2b3JhYmlsaXR5IHRvd2FyZHMgTkdPcwoKYGBge3IgZmlnLW5nby1mYXZvcmFiaWxpdHksIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTR9CmZhdm9yYWJpbGl0eV9jb2xzIDwtIGRhdGFfZnJhbWUodmFsdWUgPSBjKCJWZXJ5IHVuZmF2b3JhYmxlIiwgIlVuZmF2b3JhYmxlIiwgIk5ldXRyYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmF2b3JhYmxlIiwgIlZlcnkgZmF2b3JhYmxlIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBuZ29fcGFsKCJvcmRlcmVkIikoNSkpCgpuZ29fZmF2b3JhYmlsaXR5X3JhdyA8LSByZXN1bHRzICU+JQogIHNlbGVjdChmYXZvcl9odW1hbml0YXJpYW4sIGZhdm9yX2h1bWFuX3JpZ2h0cywgZmF2b3JfZGV2ZWxvcG1lbnQpICU+JSAKICBnYXRoZXIodmFyaWFibGUsIHZhbHVlKSAlPiUgCiAgY291bnQodmFyaWFibGUsIHZhbHVlKSAlPiUgCiAgbGVmdF9qb2luKHZhcnNfdG9fc3VtbWFyaXplLCBieSA9ICJ2YXJpYWJsZSIpICU+JSAKICBsZWZ0X2pvaW4oZmF2b3JhYmlsaXR5X2NvbHMsIGJ5ID0gInZhbHVlIikgJT4lCiAgbXV0YXRlKGNsZWFuX25hbWUgPSBzdHJfcmVwbGFjZShjbGVhbl9uYW1lLCAidG93YXJkcyIsICJ0b3dhcmRzXG4iKSkgJT4lIAogIG11dGF0ZSh2YWx1ZSA9IGZhY3Rvcih2YWx1ZSwgbGV2ZWxzID0gbGV2ZWxzKHJlc3VsdHMkZmF2b3JfaHVtYW5pdGFyaWFuKSwgb3JkZXJlZCA9IFRSVUUpLAogICAgICAgICBjbGVhbl9uYW1lID0gZmN0X2lub3JkZXIoY2xlYW5fbmFtZSwgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKHZhbHVlKSAlPiUgCiAgbXV0YXRlKGNvbG9yID0gZmN0X2lub3JkZXIoY29sb3IsIG9yZGVyZWQgPSBUUlVFKSkKCm5nb19mYXZvcmFiaWxpdHlfaGlnaCA8LSBuZ29fZmF2b3JhYmlsaXR5X3JhdyAlPiUgCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KHZhbHVlLCAibmZhdiIpKSAlPiUgCiAgbXV0YXRlKG4gPSBpZmVsc2UodmFsdWUgPT0gIk5ldXRyYWwiLCBuIC8gMiwgbiksCiAgICAgICAgIG5fcGxvdCA9IG4sCiAgICAgICAgIHZhbHVlID0gZmN0X3Jldih2YWx1ZSksIGNvbG9yID0gZmN0X3Jldihjb2xvcikpCgpuZ29fZmF2b3JhYmlsaXR5X2xvdyA8LSBuZ29fZmF2b3JhYmlsaXR5X3JhdyAlPiUgCiAgZmlsdGVyKHN0cl9kZXRlY3QodmFsdWUsICJuZmF2IikgfCB2YWx1ZSA9PSAiTmV1dHJhbCIpICU+JSAKICBtdXRhdGUobiA9IGlmZWxzZSh2YWx1ZSA9PSAiTmV1dHJhbCIsIG4gLyAyLCBuKSwKICAgICAgICAgbl9wbG90ID0gLW4pCgpnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gbl9wbG90LCB5ID0gY2xlYW5fbmFtZSwgZmlsbCA9IGNvbG9yKSkgKwogIGdlb21fYmFyaChkYXRhID0gbmdvX2Zhdm9yYWJpbGl0eV9oaWdoLCBzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fYmFyaChkYXRhID0gbmdvX2Zhdm9yYWJpbGl0eV9sb3csIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IGFicykgKwogIHNjYWxlX2ZpbGxfaWRlbnRpdHkobGFiZWxzID0gbGV2ZWxzKG5nb19mYXZvcmFiaWxpdHlfcmF3JHZhbHVlKSwKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGxldmVscyhuZ29fZmF2b3JhYmlsaXR5X3JhdyRjb2xvciksCiAgICAgICAgICAgICAgICAgICAgICBndWlkZSA9ICJsZWdlbmQiLCBuYW1lID0gTlVMTCkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMKSArCiAgdGhlbWVfbmdvcygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgojIyBMaWtlbGlob29kIG9mIGRvbmF0aW9uCgpgYGB7ciBmaWctbGlrZWxpaG9vZC1iYXJzLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD00fQpkb25hdGVfc3VtbWFyeSA8LSByZXN1bHRzICU+JSAKICBjb3VudChkb25hdGVfbGlrZWx5KSAlPiUgCiAgbXV0YXRlKHBlcmMgPSBuIC8gc3VtKG4pKSAlPiUgCiAgbXV0YXRlKGhpZ2hsaWdodCA9IGlmZWxzZShkb25hdGVfbGlrZWx5ICVpbiUgYygiRXh0cmVtZWx5IGxpa2VseSIsICJTb21ld2hhdCBsaWtlbHkiKSwgVFJVRSwgRkFMU0UpKQoKcGxvdF9kb25hdGVfc3VtbWFyeSA8LSBnZ3Bsb3QoZG9uYXRlX3N1bW1hcnksIGFlcyh4ID0gbiwgeSA9IGRvbmF0ZV9saWtlbHksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBoaWdobGlnaHQpKSArCiAgZ2VvbV9iYXJoKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXMofiAuIC8gc3VtKGRvbmF0ZV9zdW1tYXJ5JG4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHBlcmNlbnQpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbmdvX2NvbHMoImdyZWVuIiwgImJsdWUiLCBuYW1lID0gRkFMU0UpLCBndWlkZSA9IEZBTFNFKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwpICsKICB0aGVtZV9uZ29zKCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKCnBsb3RfZG9uYXRlX3N1bW1hcnkgJVQ+JSAKICBwcmludCgpICVUPiUKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJkb25hdGVfc3VtbWFyeS5wZGYiKSwKICAgICAgICAgd2lkdGggPSA5LCBoZWlnaHQgPSA0LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lIAogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgImRvbmF0ZV9zdW1tYXJ5LnBuZyIpLAogICAgICAgICB3aWR0aCA9IDksIGhlaWdodCA9IDQsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgojIyBBbW91bnQgZG9uYXRlZAoKYGBge3IgZmlnLWFtb3VudC1iYXJzLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD0yLjc1fQpwbG90X2Ftb3VudF9zdW1tYXJ5IDwtIGdncGxvdChyZXN1bHRzLCBhZXMoeCA9IGFtb3VudF9kb25hdGUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDIwLCBmaWxsID0gbmdvX2NvbHMoImJsdWUiKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBkb2xsYXIpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCkgKwogIHRoZW1lX25nb3MoKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSkKCnBsb3RfYW1vdW50X3N1bW1hcnkgJVQ+JSAKICBwcmludCgpICVUPiUKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJhbW91bnRfc3VtbWFyeS5wZGYiKSwKICAgICAgICAgd2lkdGggPSA5LCBoZWlnaHQgPSAyLjc1LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lIAogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgImFtb3VudF9zdW1tYXJ5LnBuZyIpLAogICAgICAgICB3aWR0aCA9IDksIGhlaWdodCA9IDIuNzUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgpcCgojIEludGVycHJldGluZyBpbnRlcmFjdGlvbnMgaW4gbW9kZWxzCgpPcmRpbmFyaWx5LCBwZW9wbGUgdXNlIEFOT1ZBIHRvIGFuYWx5emUgMy13YXksIDIgw5cgMiDDlyAyIGZhY3RvcmlhbCBkZXNpZ25zLCBbbGlrZSB0aGlzXShodHRwczovL215cGFnZXMudmFsZG9zdGEuZWR1L213aGF0bGV5LzM2MDAvMngyeDIuaHRtKS4gQSBtb3JlIGZsZXhpYmxlIChbeWV0IGlkZW50aWNhbCFdKGh0dHBzOi8vd3d3LnRoZWFuYWx5c2lzZmFjdG9yLmNvbS93aHktYW5vdmEtYW5kLWxpbmVhci1yZWdyZXNzaW9uLWFyZS10aGUtc2FtZS1hbmFseXNpcy8pKSB3YXkgdG8gZG8gdGhpcyBpcyB0byB1c2UgYSByZWd1bGFyIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBpbnRlcmFjdGlvbiB0ZXJtcyBmb3IgZWFjaCBvZiB0aGUgY29uZGl0aW9ucywgbGlrZSBzbyAoaGVyZSB3ZSB1c2UgdGhyZWUsIHNpbmNlIHdlIGNhbiB1c2Ugc2ltcGVyIG1vZGVscyB0byBnZXQgYXZlcmFnZXMgZm9yIHRoZSBsYXJnZXIgdW1icmVsbGEgZ3JvdXBzLCBsaWtlIGp1c3QgY3JhY2tkb3ducyBhbmQgY3JhY2tkb3duICsgaXNzdWUpOgoKLSBNb2RlbCAxOiAKCiAgICAkJAogICAgeSA9IFxiZXRhXzAgKyBcYmV0YV8xIFx0ZXh0e0NyYWNrZG93bn0KICAgICQkCgotIE1vZGVsIDI6IAoKICAgICQkCiAgICBcYmVnaW57YWxpZ25lZH0KICAgIHkgPSYgXGJldGFfMCArIFxiZXRhXzEgXHRleHR7Q3JhY2tkb3dufSArIFxiZXRhXzIgXHRleHR7SXNzdWUgfSArIFxcCiAgICAmIFxiZXRhXzMgXHRleHR7Q3JhY2tkb3dufSBcdGltZXMgXHRleHR7SXNzdWV9CiAgICBcZW5ke2FsaWduZWR9CiAgICAkJAoKLSBNb2RlbCAzOiAKCiAgICAkJAogICAgXGJlZ2lue2FsaWduZWR9CiAgICB5ID0mIFxiZXRhXzAgKyBcYmV0YV8xIFx0ZXh0e0NyYWNrZG93bn0gKyBcYmV0YV8yIFx0ZXh0e0lzc3VlfSArIFxiZXRhXzMgXHRleHR7RnVuZGluZyB9ICsgXFwKICAgICYgXGJldGFfNCBcdGV4dHtDcmFja2Rvd259IFx0aW1lcyBcdGV4dHtJc3N1ZSB9ICsgXFwKICAgICYgXGJldGFfNSBcdGV4dHtDcmFja2Rvd259IFx0aW1lcyBcdGV4dHtGdW5kaW5nIH0gKyBcXAogICAgJiBcYmV0YV82IFx0ZXh0e0lzc3VlfSBcdGltZXMgXHRleHR7RnVuZGluZyB9ICsgXFwKICAgICYgXGJldGFfNyBcdGV4dHtDcmFja2Rvd259IFx0aW1lcyBcdGV4dHtJc3N1ZX0gXHRpbWVzIFx0ZXh0e0Z1bmRpbmd9CiAgICBcZW5ke2FsaWduZWR9CiAgICAkJAoKQWRkaW5nIGRpZmZlcmVudCBjb21iaW5hdGlvbnMgb2YgdGhlIGNvZWZmaWNpZW50cyBwcm92aWRlcyB0aGUgYXZlcmFnZSB2YWx1ZXMgZm9yIGVhY2ggY29tYmluYXRpb24gb2YgZmFjdG9ycywgd2hpY2ggY29ycmVzcG9uZHMgdG8gdGhlIGF2ZXJhZ2UgbGlrZWxpaG9vZCBhbmQgYW1vdW50IGRvbmF0ZWQgdGFibGUgYWJvdmUuIAoKYGBge3IgaW50ZXJhY3Rpb24taW50ZXJwcmV0YXRpb24sIHJlc3VsdHM9ImFzaXMifQptb2RlbDEgPC0gIjEiCm1vZGVsMiA8LSAiMiIKbW9kZWwzIDwtICIzIgoKaW50ZXJwcmV0YXRpb24gPC0gdHJpYmJsZSgKICB+TW9kZWwsIH5gQ29lZmZpY2llbnRzIHRvIGFkZCB0b2dldGhlcmAsCiAgbW9kZWwzLCAiSW50ZXJjZXB0IiwKICBtb2RlbDMsICJJbnRlcmNlcHQgKyBGdW5kaW5nIiwKICBtb2RlbDIsICJJbnRlcmNlcHQiLAogIG1vZGVsMywgIkludGVyY2VwdCArIElzc3VlIiwKICBtb2RlbDMsICJJbnRlcmNlcHQgKyBJc3N1ZSArIEZ1bmRpbmcgKyAoSXNzdWUgw5cgRnVuZGluZykiLAogIG1vZGVsMiwgIkludGVyY2VwdCArIElzc3VlIiwKICBtb2RlbDEsICJJbnRlcmNlcHQiLAogIG1vZGVsMywgIkludGVyY2VwdCArIENyYWNrZG93biIsCiAgbW9kZWwzLCAiSW50ZXJjZXB0ICsgQ3JhY2tkb3duICsgRnVuZGluZyArIChDcmFja2Rvd24gw5cgRnVuZGluZykiLAogIG1vZGVsMiwgIkludGVyY2VwdCArIENyYWNrZG93biIsCiAgbW9kZWwzLCAiSW50ZXJjZXB0ICsgQ3JhY2tkb3duICsgSXNzdWUgKyAoQ3JhY2tkb3duIMOXIElzc3VlKSIsCiAgbW9kZWwzLCAiSW50ZXJjZXB0ICsgQ3JhY2tkb3duICsgSXNzdWUgKyBGdW5kaW5nICsgKENyYWNrZG93biDDlyBJc3N1ZSkgKyAoQ3JhY2tkb3duIMOXIEZ1bmRpbmcpICsgKElzc3VlIMOXIEZ1bmRpbmcpICsgKENyYWNrZG93biDDlyBJc3N1ZSDDlyBGdW5kaW5nKSIsCiAgbW9kZWwyLCAiSW50ZXJjZXB0ICsgQ3JhY2tkb3duICsgSXNzdWUgKyAoQ3JhY2tkb3duIMOXIElzc3VlKSIsCiAgbW9kZWwxLCAiSW50ZXJjZXB0ICsgQ3JhY2tkb3duIgopCgpjb25kaXRpb25zX3N1bW1hcnlfY2xlYW4gJT4lIAogIHNlbGVjdCgxOjMpICU+JSAKICBzbGljZSgtbigpKSAlPiUgCiAgYmluZF9jb2xzKGludGVycHJldGF0aW9uKSAlVD4lIAogIHBhbmRvYy50YWJsZSgpICU+JSAKICBwYW5kb2MudGFibGUucmV0dXJuKGNhcHRpb24gPSAiQ29tYmluYXRpb25zIG9mIGNvZWZmaWNpZW50cyB0byBhZGQgdG8gZGV0ZXJtaW5lIG1lYW5zIGFjcm9zcyBleHBlcmltZW50YWwgY29uZGl0aW9ucyB7I3RibDpjb2VmZmljaWVudHMtdG8tYWRkfSIpICU+JSAKICBjYXQoZmlsZSA9IGhlcmUoIm91dHB1dCIsICJ0YWJsZXMiLCAidGJsLWNvZWZmaWNpZW50cy10by1hZGQubWQiKSkKYGBgCgpcCgojIEFtb3VudCBkb25hdGVkCgojIyBNb2RlbHMKCmBgYHtyIGJ1aWxkLW1vZGVscy1hbW91bnQsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUV9CiMgQmFzaWMgaW50ZXJhY3Rpb24gbW9kZWxzCm1fYW1vdW50X2MgPC0gc3Rhbl9nbG0oYW1vdW50X2RvbmF0ZSB+IGNyYWNrZG93biwKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gcmVzdWx0cywgZmFtaWx5ID0gZ2F1c3NpYW4oKSwKICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IGNhdWNoeShsb2NhdGlvbiA9IDAsIHNjYWxlID0gMi41KSwKICAgICAgICAgICAgICAgICAgICAgICBwcmlvcl9pbnRlcmNlcHQgPSBjYXVjaHkobG9jYXRpb24gPSAwLCBzY2FsZSA9IDEwKSwKICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSBDSEFJTlMsIGl0ZXIgPSBJVEVSLCB3YXJtdXAgPSBXQVJNVVAsIHNlZWQgPSBCQVlFU19TRUVEKQoKbV9hbW91bnRfY2kgPC0gdXBkYXRlKG1fYW1vdW50X2MsIC4gfiAuICsgaXNzdWUgKyBjcmFja2Rvd24gKiBpc3N1ZSkKCm1fYW1vdW50X2NpZiA8LSB1cGRhdGUobV9hbW91bnRfYywgLiB+IC4gKyAKICAgICAgICAgICAgICAgICAgICAgICAgIGlzc3VlICsgZnVuZGluZyArIGNyYWNrZG93biAqIGlzc3VlICsgY3JhY2tkb3duICogZnVuZGluZyArIAogICAgICAgICAgICAgICAgICAgICAgICAgaXNzdWUgKiBmdW5kaW5nICsgY3JhY2tkb3duICogaXNzdWUgKiBmdW5kaW5nKQoKIyBNb2RlbHMgd2l0aCBqdXN0IGlzc3VlIGFuZCBqdXN0IGZ1bmRpbmcKbV9hbW91bnRfaSA8LSB1cGRhdGUobV9hbW91bnRfYywgLiB+IGlzc3VlKQptX2Ftb3VudF9mIDwtIHVwZGF0ZShtX2Ftb3VudF9jLCAuIH4gZnVuZGluZykKYGBgCgpgYGB7ciB0YmwtbW9kZWxzLWFtb3VudCwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0iYXNpcyJ9CiMgR2V0IHN1YnNldCBvZiBjb2VmZmljaWVudHMKY29lZnNfdG9faW5jbHVkZSA8LSBsaXN0KG1fYW1vdW50X2MsIG1fYW1vdW50X2NpLCBtX2Ftb3VudF9jaWYpICU+JSAKICBtYXAofiB0aWR5KC4pKSAlPiUgYmluZF9yb3dzKCkgJT4lIGRpc3RpbmN0KHRlcm0pICU+JSBwdWxsKHRlcm0pCgpodXhyZWcobV9hbW91bnRfYywgbV9hbW91bnRfY2ksIG1fYW1vdW50X2NpZiwgCiAgICAgICBjb2VmcyA9IGNsZWFuX2NvZWZzX25hbWVkW2NsZWFuX2NvZWZzX25hbWVkICVpbiUgY29lZnNfdG9faW5jbHVkZV0sCiAgICAgICBzdGF0aXN0aWNzID0gbW9kZWxfc3RhdHNfYmF5ZXMsCiAgICAgICBzdGFycyA9IE5VTEwpICVUPiUgCiAgcHJpbnRfaHV4KCkgJT4lIAogIHRvX21kKG1heF93aWR0aCA9IDEwMCkgJT4lIAogIGNhdChmaWxlID0gaGVyZSgib3V0cHV0IiwgInRhYmxlcyIsICJ0YmwtbW9kZWxzLWFtb3VudC5tZCIpKQpgYGAKCiMjIFByZWRpY3RlZCBtZWRpYW5zCgpUaGUgU3RhbiBwZW9wbGUgcmVhbGx5IHJlYWxseSBkb24ndCBsaWtlIGBwb3N0ZXJpb3JfbGluZXByZWQoKWAsIHNpbmNlIGl0IHRocm93cyBhd2F5IGEgbG90IG9mIHRoZSB1bmNlcnRhaW50eSB0aGF0IGNvbWVzIGZyb20gYWN0dWFsbHkgZ2V0dGluZyBhIHBvc3RlcmlvciBkaXN0cmlidXRpb24gKGxpa2UsIFt0aGV5IGRpZG4ndCBldmVuIHdhbnQgdG8gaW52ZW50IGl0LCBhbmQgdGhlbiB3aGVuIHRoZXkgZGlkIHRoZXkgd2FudGVkIHRvIGhpZGUgaXRdKGh0dHBzOi8vZ2l0aHViLmNvbS9zdGFuLWRldi9yc3RhbmFybS9pc3N1ZXMvODUpLCBhbmQgaXQgaGFzIGEgYmlnIHdhcm5pbmcgaW4gdGhlIGRvY3VtZW50YXRpb24pLiBCdXQgdGhpcyBhcHByb2FjaCBoZXJlIG1pcnJvcnMgdXNpbmcgYHByZWRpY3QoKWAgdG8gY29tYmluZSBhbGwgdGhlIGNvZWZmaWNpZW50cyBhbmQgaW50ZXJjZXB0IHRlcm1zIGluIGEgcmVndWxhciBmcmVxdWVudGlzdCBsaW5lYXIgbW9kZWwgYW5kIGl0J3MgcHJvYmFibHkgYXBwcm9wcmlhdGUgZm9yIHRoaXMgc2l0dWF0aW9uIGJlY2F1c2UgYWxsIHRoZSBjb2VmZmljaWVudHMgYXJlIGFjdHVhbGx5IGxpbmtlZCB0b2dldGhlciBiZWhpbmQgdGhlIHNjZW5lcyBhbmQgY3JlYXRlIGdyb3VwIG1lYW4gZXN0aW1hdGVzLiBJZiBJIHVzZSB0aGUgZnVsbCBmb3JjZSBvZiBgcG9zdGVyaW9yX3ByZWRpY3QoKWAsIEkgYWRkIG1vcmUgdW5jZXJ0YWludHkgd2l0aCBlYWNoIGFkZGVkIGNvZWZmaWNpZW50IChzbyBpbiBhIDLDlzLDlzIgdmVyc2lvbiwgdGhlIDh0aCBjb25kaXRpb24gaXMgYWN0dWFsbHkgdGhlIHN1bSBvZiBhbGwgOCBjb2VmZmljaWVudHMsIHdoaWNoIG1lYW5zIGl0IGdldHMgOCBsZXZlbHMgb2YgdW5jZXJ0YWluaXR5LCB3aGljaCBpcyBwcm9iYWJseSBleGNlc3NpdmUpLiBCdXQgd2UgZG8gaXQgYm90aCB3YXlzIHRvbywganVzdCB0byBiZSBvbiB0aGUgc2FmZSBzaWRlLgoKYGBge3IgYW1vdW50LW1lZGlhbi1jfQpuZXdkYXRhX2NvbmRpdGlvbnNfYyA8LSByZXN1bHRzICU+JSBleHBhbmQobmVzdGluZyhjcmFja2Rvd24pKQoKY2hhaW5zX2ZpdHRlZF9jIDwtIHBvc3Rlcmlvcl9saW5wcmVkKG1fYW1vdW50X2MsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5ld2RhdGFfY29uZGl0aW9uc19jKQoKIyBwb3N0ZXJpb3JfZml0IDwtIHBvc3Rlcmlvcl9wcmVkaWN0KG1fYW1vdW50X2MsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5ld2RhdGFfY29uZGl0aW9uc19jLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhd3MgPSA1MCwgc2VlZCA9IEJBWUVTX1NFRUQpCgpjb2VmX3N1bW1hcnlfYyA8LSBuZXdkYXRhX2NvbmRpdGlvbnNfYyAlPiUgCiAgYmluZF9jb2xzKHRpZHlNQ01DKGNoYWluc19maXR0ZWRfYywgZXN0aW1hdGUubWV0aG9kID0gIm1lZGlhbiIsCiAgICAgICAgICAgICAgICAgICAgIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOSwgY29uZi5tZXRob2QgPSAiSFBEaW50ZXJ2YWwiKSkKCiMgbmV3ZGF0YSA8LSBuZXdkYXRhX2NvbmRpdGlvbnMgJT4lIAojICAgYmluZF9jb2xzKHRpZHlNQ01DKHBvc3Rlcmlvcl9maXQsIGVzdGltYXRlLm1ldGhvZCA9ICJtZWRpYW4iLAojICAgICAgICAgICAgICAgICAgICAgIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOSwgY29uZi5tZXRob2QgPSAiSFBEaW50ZXJ2YWwiKSkKCnBsb3RfYW1vdW50X2MgPC0gZ2dwbG90KGNvZWZfc3VtbWFyeV9jLCBhZXMoeSA9IGVzdGltYXRlLCB4ID0gY3JhY2tkb3duKSkgKyAKICAjIGdlb21fcG9pbnQoZGF0YSA9IHJlc3VsdHMsIGFlcyh5ID0gYW1vdW50X2RvbmF0ZSwgeCA9IGNyYWNrZG93biksCiAgIyAgICAgICAgICAgIGNvbG9yID0gImdyZXk1MCIsIHNpemUgPSAwLjUsIGFscGhhID0gMC4yNSkgKwogIGdlb21fcG9pbnRyYW5nZShhZXMoeW1pbiA9IGNvbmYubG93LCB5bWF4ID0gY29uZi5oaWdoKSwgY29sb3IgPSBuZ29fY29scygiZ3JlZW4iKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9ICJNZWRpYW4gYW1vdW50IGRvbmF0ZWQiKSArCiAgIyBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTAwKSkgKwogIHRoZW1lX25nb3MoKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyIGFtb3VudC1tZWRpYW4taX0KbmV3ZGF0YV9jb25kaXRpb25zX2kgPC0gcmVzdWx0cyAlPiUgZXhwYW5kKG5lc3RpbmcoaXNzdWUpKQoKY2hhaW5zX2ZpdHRlZF9pIDwtIHBvc3Rlcmlvcl9saW5wcmVkKG1fYW1vdW50X2ksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5ld2RhdGFfY29uZGl0aW9uc19pKQoKY29lZl9zdW1tYXJ5X2kgPC0gbmV3ZGF0YV9jb25kaXRpb25zX2kgJT4lIAogIGJpbmRfY29scyh0aWR5TUNNQyhjaGFpbnNfZml0dGVkX2ksIGVzdGltYXRlLm1ldGhvZCA9ICJtZWRpYW4iLAogICAgICAgICAgICAgICAgICAgICBjb25mLmludCA9IFRSVUUsIGNvbmYubGV2ZWwgPSAwLjksIGNvbmYubWV0aG9kID0gIkhQRGludGVydmFsIikpCmBgYAoKYGBge3IgYW1vdW50LW1lZGlhbi1mfQpuZXdkYXRhX2NvbmRpdGlvbnNfZiA8LSByZXN1bHRzICU+JSBleHBhbmQobmVzdGluZyhmdW5kaW5nKSkKCmNoYWluc19maXR0ZWRfZiA8LSBwb3N0ZXJpb3JfbGlucHJlZChtX2Ftb3VudF9mLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBuZXdkYXRhX2NvbmRpdGlvbnNfZikKCmNvZWZfc3VtbWFyeV9mIDwtIG5ld2RhdGFfY29uZGl0aW9uc19mICU+JSAKICBiaW5kX2NvbHModGlkeU1DTUMoY2hhaW5zX2ZpdHRlZF9mLCBlc3RpbWF0ZS5tZXRob2QgPSAibWVkaWFuIiwKICAgICAgICAgICAgICAgICAgICAgY29uZi5pbnQgPSBUUlVFLCBjb25mLmxldmVsID0gMC45LCBjb25mLm1ldGhvZCA9ICJIUERpbnRlcnZhbCIpKQpgYGAKCmBgYHtyIGFtb3VudC1tZWRpYW4tY2l9Cm5ld2RhdGFfY29uZGl0aW9uc19jaSA8LSByZXN1bHRzICU+JSBleHBhbmQobmVzdGluZyhjcmFja2Rvd24sIGlzc3VlKSkKCmNoYWluc19maXR0ZWRfY2kgPC0gcG9zdGVyaW9yX2xpbnByZWQobV9hbW91bnRfY2ksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBuZXdkYXRhX2NvbmRpdGlvbnNfY2kpCgpjb2VmX3N1bW1hcnlfY2kgPC0gbmV3ZGF0YV9jb25kaXRpb25zX2NpICU+JSAKICBiaW5kX2NvbHModGlkeU1DTUMoY2hhaW5zX2ZpdHRlZF9jaSwgZXN0aW1hdGUubWV0aG9kID0gIm1lZGlhbiIsCiAgICAgICAgICAgICAgICAgICAgIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOSwgY29uZi5tZXRob2QgPSAiSFBEaW50ZXJ2YWwiKSkKCnBsb3RfYW1vdW50X2NpIDwtIGdncGxvdChjb2VmX3N1bW1hcnlfY2ksIGFlcyh5ID0gZXN0aW1hdGUsIHggPSBjcmFja2Rvd24pKSArIAogICMgZ2VvbV9wb2ludChkYXRhID0gcmVzdWx0cywgYWVzKHkgPSBhbW91bnRfZG9uYXRlLCB4ID0gY3JhY2tkb3duKSwKICAjICAgICAgICAgICAgY29sb3IgPSAiZ3JleTUwIiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjI1KSArCiAgZ2VvbV9wb2ludHJhbmdlKGFlcyh5bWluID0gY29uZi5sb3csIHltYXggPSBjb25mLmhpZ2gpLCBjb2xvciA9IG5nb19jb2xzKCJibHVlIikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGRvbGxhcikgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSAiTWVkaWFuIGFtb3VudCBkb25hdGVkIikgKwogICMgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsIDEwMCkpICsKICB0aGVtZV9uZ29zKCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbig1LCAwLCAyLCAwLCAicHQiKSkpICsKICBmYWNldF93cmFwKH4gaXNzdWUpCmBgYAoKYGBge3IgYW1vdW50LW1lZGlhbi1jaWZ9Cm5ld2RhdGFfY29uZGl0aW9uc19jaWYgPC0gcmVzdWx0cyAlPiUgZXhwYW5kKG5lc3RpbmcoY3JhY2tkb3duLCBpc3N1ZSwgZnVuZGluZykpCgpjaGFpbnNfZml0dGVkX2NpZiA8LSBwb3N0ZXJpb3JfbGlucHJlZChtX2Ftb3VudF9jaWYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gbmV3ZGF0YV9jb25kaXRpb25zX2NpZikKCmNvZWZfc3VtbWFyeV9jaWYgPC0gbmV3ZGF0YV9jb25kaXRpb25zX2NpZiAlPiUgCiAgYmluZF9jb2xzKHRpZHlNQ01DKGNoYWluc19maXR0ZWRfY2lmLCBlc3RpbWF0ZS5tZXRob2QgPSAibWVkaWFuIiwKICAgICAgICAgICAgICAgICAgICAgY29uZi5pbnQgPSBUUlVFLCBjb25mLmxldmVsID0gMC45LCBjb25mLm1ldGhvZCA9ICJIUERpbnRlcnZhbCIpKQoKcGxvdF9hbW91bnRfY2lmIDwtIGdncGxvdChjb2VmX3N1bW1hcnlfY2lmLCBhZXMoeSA9IGVzdGltYXRlLCB4ID0gY3JhY2tkb3duKSkgKyAKICAjIGdlb21fcG9pbnQoZGF0YSA9IHJlc3VsdHMsIGFlcyh5ID0gYW1vdW50X2RvbmF0ZSwgeCA9IGNyYWNrZG93biksCiAgIyAgICAgICAgICAgIGNvbG9yID0gImdyZXk1MCIsIHNpemUgPSAwLjUsIGFscGhhID0gMC41KSArCiAgZ2VvbV9wb2ludHJhbmdlKGFlcyh5bWluID0gY29uZi5sb3csIHltYXggPSBjb25mLmhpZ2gpLCBjb2xvciA9IG5nb19jb2xzKCJyZWQiKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBkb2xsYXIpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gIk1lZGlhbiBhbW91bnQgZG9uYXRlZCIpICsKICB0aGVtZV9uZ29zKCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbig1LCAwLCAyLCAwLCAicHQiKSkpICsKICBmYWNldF93cmFwKH4gaXNzdWUgKyBmdW5kaW5nKQpgYGAKCmBgYHtyIHBsb3Qtc2luZ2xlLWFtb3VudC1tZWRpYW5zLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0yLjV9CmNvZWZfc3VtbWFyeV9zaW5nbGVzIDwtIGJpbmRfcm93cyhjb2VmX3N1bW1hcnlfYywgY29lZl9zdW1tYXJ5X2ksIGNvZWZfc3VtbWFyeV9mKSAlPiUgCiAgZ2F0aGVyKGNvbmRpdGlvbiwgdmFsdWUsIGNyYWNrZG93biwgaXNzdWUsIGZ1bmRpbmcpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHZhbHVlKSkgJT4lIAogIG11dGF0ZSh2YWx1ZSA9IGZjdF9pbm9yZGVyKHZhbHVlLCBvcmRlcmVkID0gVFJVRSksCiAgICAgICAgIGNvbmRpdGlvbiA9IGZjdF9pbm9yZGVyKHN0cl90b190aXRsZShjb25kaXRpb24pLCBvcmRlcmVkID0gVFJVRSkpCgpwbG90X2Ftb3VudF9zaW5nbGVzIDwtIGdncGxvdChjb2VmX3N1bW1hcnlfc2luZ2xlcywgYWVzKHkgPSBlc3RpbWF0ZSwgeCA9IHZhbHVlKSkgKyAKICBnZW9tX3BvaW50cmFuZ2UoYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCwgY29sb3IgPSBjb25kaXRpb24pKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGRvbGxhcikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBuZ29fY29scygiZ3JlZW4iLCAiYmx1ZSIsICJyZWQiLCBuYW1lID0gRkFMU0UpLCBndWlkZSA9IEZBTFNFKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9ICJNZWRpYW4gYW1vdW50IGRvbmF0ZWQiKSArCiAgdGhlbWVfbmdvcygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4oNSwgMCwgMiwgMCwgInB0IikpKSArCiAgZmFjZXRfd3JhcCh+IGNvbmRpdGlvbiwgc2NhbGVzID0gImZyZWVfeCIpCgpwbG90X2Ftb3VudF9zaW5nbGVzICVUPiUKICBwcmludCgpICVUPiUKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJhbW91bnRfc2luZ2xlX3N1bW1hcnkucGRmIiksCiAgICAgICAgIHdpZHRoID0gNywgaGVpZ2h0ID0gMi41LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lIAogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgImFtb3VudF9zaW5nbGVfc3VtbWFyeS5wbmciKSwKICAgICAgICAgd2lkdGggPSA3LCBoZWlnaHQgPSAyLjUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgpgYGB7ciBwbG90LWFsbC1hbW91bnQtbWVkaWFucywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KcGxvdF9hbW91bnRfYWxsIDwtIAogIChwbG90X2Ftb3VudF9jIC8gcGxvdF9hbW91bnRfY2kpIHwgCiAgcGxvdF9hbW91bnRfY2lmCgpwbG90X2Ftb3VudF9hbGwgKwogIHBsb3RfYW5ub3RhdGlvbih0aXRsZSA9ICJNZWRpYW4gZG9uYXRpb24gaW4gY29udHJvbCBhbmQgY3JhY2tkb3duIGdyb3VwcyxcbmNvbmRpdGlvbmVkIGJ5IG90aGVyIGV4cGVyaW1lbnRhbCBncm91cHMiLAogICAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICI5MCUgY3JlZGlibGUgaW50ZXJ2YWxzIHNob3duIGFyb3VuZCBlYWNoIHBvaW50IiwKICAgICAgICAgICAgICAgICAgdGFnX2xldmVscyA9ICJBIiwgdGhlbWUgPSB0aGVtZV9uZ29zKCkpCgoocGxvdF9hbW91bnRfYWxsICsgCiAgICBwbG90X2Fubm90YXRpb24oY2FwdGlvbiA9ICI5MCUgY3JlZGlibGUgaW50ZXJ2YWxzIHNob3duIGFyb3VuZCBlYWNoIHBvaW50IiwKICAgICAgICAgICAgICAgICAgICB0YWdfbGV2ZWxzID0gIkEiLCB0aGVtZSA9IHRoZW1lX25nb3MoKSkpICVUPiUgCiAgZ2dzYXZlKC4sIGZpbGVuYW1lID0gaGVyZSgib3V0cHV0IiwgImZpZ3VyZXMiLCAiYW1vdW50LW1lZGlhbnMucGRmIiksCiAgICAgICAgIHdpZHRoID0gOCwgaGVpZ2h0ID0gNC4yNSwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSBjYWlyb19wZGYpICU+JSAKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJhbW91bnQtbWVkaWFucy5wbmciKSwKICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSA0LjI1LCB1bml0cyA9ICJpbiIsIHR5cGUgPSAiY2Fpcm8iLCBkcGkgPSAzMDApCmBgYAoKCiMjIERpZmZlcmVuY2VzIGluIG1lZGlhbnMKCmBgYHtyIGFtb3VudC1kaWZmcy1jfQpkaWZmc19jb2VmX3BhaXJzX2MgPC0gY2hhaW5zX2ZpdHRlZF9jICU+JSAKICBhc19kYXRhX2ZyYW1lKCkgJT4lIAogIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMobGV2ZWxzKG5ld2RhdGFfY29uZGl0aW9uc19jJGNyYWNrZG93bikpICU+JSAKICBtY21jX3BhaXJ3aXNlX2RpZmZzKCkKCmRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsX2MgPC0gdGlkeV9kaWZmcyhkaWZmc19jb2VmX3BhaXJzX2MpCgpwYWlyc19wbG90X2RhdGFfYyA8LSBkaWZmc19jb2VmX3BhaXJzX2MkbWNtY19kaWZmcyAlPiUKICBnYXRoZXIocGFpciwgdmFsdWUpICU+JQogIG11dGF0ZShwYWlyMSA9IHBhaXIpICU+JQogIHNlcGFyYXRlKHBhaXIxLCBpbnRvID0gYygiZ3JvdXAxIiwgImdyb3VwMiIpLCBzZXAgPSAiIC0gIikgJT4lCiAgbXV0YXRlKHBhaXIgPSBpZmVsc2UobmNoYXIocGFpcikgPiAyNSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJfcmVwbGFjZShwYWlyLCAiLSIsICItXG4iKSwKICAgICAgICAgICAgICAgICAgICAgICBwYWlyKSkKICAKcGxvdF9kaWZmc19jIDwtIGdncGxvdCgpICsgCiAgZ2VvbV9kZW5zaXR5KGRhdGEgPSBwYWlyc19wbG90X2RhdGFfYywgYWVzKHggPSB2YWx1ZSksCiAgICAgICAgICAgICAgIGZpbGwgPSBuZ29fY29scygiZ3JlZW4iKSwgY29sb3VyID0gTkEsIGFscGhhID0gMC40KSArIAogIGdlb21fc2VnbWVudChkYXRhID0gZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfYywgCiAgICAgICAgICAgICAgIGFlcyh4ID0gcTUsIHhlbmQgPSBxOTUsIHkgPSAwLCB5ZW5kID0gMCksCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV92bGluZShkYXRhID0gZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfYywgYWVzKHhpbnRlcmNlcHQgPSBtZWRpYW4pLCBzaXplID0gMC4yNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFLCBjb2xvciA9IEZBTFNFKSArCiAgbGFicyh4ID0gIkRpZmZlcmVuY2UgaW4gbWVkaWFucyIpICsKICB0aGVtZV9uZ29zKGRlbnNpdHkgPSBUUlVFKSArCiAgZmFjZXRfd3JhcCh+IHBhaXIpCmBgYAoKYGBge3IgYW1vdW50LWRpZmZzLWl9CmRpZmZzX2NvZWZfcGFpcnNfaSA8LSBjaGFpbnNfZml0dGVkX2kgJT4lIAogIGFzX2RhdGFfZnJhbWUoKSAlPiUgCiAgbWFncml0dHI6OnNldF9jb2xuYW1lcyhsZXZlbHMobmV3ZGF0YV9jb25kaXRpb25zX2kkaXNzdWUpKSAlPiUgCiAgbWNtY19wYWlyd2lzZV9kaWZmcygpCgpkaWZmc19jb2VmX3BhaXJzX2RldGFpbF9pIDwtIHRpZHlfZGlmZnMoZGlmZnNfY29lZl9wYWlyc19pKQoKcGFpcnNfcGxvdF9kYXRhX2kgPC0gZGlmZnNfY29lZl9wYWlyc19pJG1jbWNfZGlmZnMgJT4lCiAgZ2F0aGVyKHBhaXIsIHZhbHVlKSAlPiUKICBtdXRhdGUocGFpcjEgPSBwYWlyKSAlPiUKICBzZXBhcmF0ZShwYWlyMSwgaW50byA9IGMoImdyb3VwMSIsICJncm91cDIiKSwgc2VwID0gIiAtICIpICU+JQogIG11dGF0ZShwYWlyID0gaWZlbHNlKG5jaGFyKHBhaXIpID4gMjUsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyX3JlcGxhY2UocGFpciwgIi0iLCAiLVxuIiksCiAgICAgICAgICAgICAgICAgICAgICAgcGFpcikpCmBgYAoKYGBge3IgYW1vdW50LWRpZmZzLWZ9CmRpZmZzX2NvZWZfcGFpcnNfZiA8LSBjaGFpbnNfZml0dGVkX2YgJT4lIAogIGFzX2RhdGFfZnJhbWUoKSAlPiUgCiAgbWFncml0dHI6OnNldF9jb2xuYW1lcyhsZXZlbHMobmV3ZGF0YV9jb25kaXRpb25zX2YkZnVuZGluZykpICU+JSAKICBtY21jX3BhaXJ3aXNlX2RpZmZzKCkKCmRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsX2YgPC0gdGlkeV9kaWZmcyhkaWZmc19jb2VmX3BhaXJzX2YpCgpwYWlyc19wbG90X2RhdGFfZiA8LSBkaWZmc19jb2VmX3BhaXJzX2YkbWNtY19kaWZmcyAlPiUKICBnYXRoZXIocGFpciwgdmFsdWUpICU+JQogIG11dGF0ZShwYWlyMSA9IHBhaXIpICU+JQogIHNlcGFyYXRlKHBhaXIxLCBpbnRvID0gYygiZ3JvdXAxIiwgImdyb3VwMiIpLCBzZXAgPSAiIC0gIikgJT4lCiAgbXV0YXRlKHBhaXIgPSBpZmVsc2UobmNoYXIocGFpcikgPiAyNSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJfcmVwbGFjZShwYWlyLCAiLSIsICItXG4iKSwKICAgICAgICAgICAgICAgICAgICAgICBwYWlyKSkKYGBgCgpgYGB7ciBhbW91bnQtZGlmZnMtY2l9CiMgTmVzdCBlYWNoIGZpdHRlZCBjaGFpbiBpbnRvIGEgc2luZ2xlIHJvdyB0aGF0IGNvcnJlc3BvbmRzIHRvIGVhY2ggbmV3ZGF0YV9jb25kaXRpb24KY2hhaW5zX25lc3RlZF9jaSA8LSBjaGFpbnNfZml0dGVkX2NpICU+JSAKICBhc19kYXRhX2ZyYW1lKCkgJT4lIAogIG11dGF0ZShpZCA9IDE6bigpKSAlPiUgCiAgZ2F0aGVyKGNvbmRpdGlvbiwgdmFsdWUsIC1pZCkgJT4lIAogIGdyb3VwX2J5KGNvbmRpdGlvbikgJT4lIAogIG5lc3QoKQoKIyBBZGQgdGhlIGZpdHRlZCBjaGFpbnMgdG8gdGhlIGNvbmRpdGlvbnMsIHNwcmVhZCB0aGUgbWFpbiBjcmFja2Rvd24gY29uZGl0aW9uCiMgaW50byB0d28gY29sdW1ucywgdGhlbiBuZXN0IGV2ZXJ5dGhpbmcgYnkgaXNzdWUKYWxsX2NoYWluc19jaSA8LSBiaW5kX2NvbHMobmV3ZGF0YV9jb25kaXRpb25zX2NpLCBjaGFpbnNfbmVzdGVkX2NpKSAlPiUgCiAgdW5uZXN0KGRhdGEpICU+JSAKICBzZWxlY3QoLWNvbmRpdGlvbikgJT4lIAogIGdyb3VwX2J5KGlzc3VlKSAlPiUgCiAgc3ByZWFkKGNyYWNrZG93biwgdmFsdWUpICU+JSAKICBzZWxlY3QoLWlkKSAlPiUgCiAgbmVzdCgpCgojIEFsbCB0aGUgcGFpcndpc2UgZGlmZmVyZW5jZXMgaW4gYSBzaW5nbGUgZGF0YSBmcmFtZSwgZ3JvdXBlZCBieSBpc3N1ZQpwYWlyc19jb25kaXRpb25zX2NpIDwtIGFsbF9jaGFpbnNfY2kgJT4lIAogIG11dGF0ZShkaWZmc19jb2VmX3BhaXJzID0gZGF0YSAlPiUgbWFwKH4gbWNtY19wYWlyd2lzZV9kaWZmcyguKSksCiAgICAgICAgIGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsID0gZGlmZnNfY29lZl9wYWlycyAlPiUgbWFwKH4gdGlkeV9kaWZmcyguKSksCiAgICAgICAgIGRpZmZzX2NvZWZzID0gZGlmZnNfY29lZl9wYWlycyAlPiUgbWFwKH4gLiRtY21jX2RpZmZzKSkKCiMgRXh0cmFjdCBjb2VmZmljaWVudCBkZXRhaWxzIGFuZCBwbG90IGRhdGEKZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfY2kgPC0gcGFpcnNfY29uZGl0aW9uc19jaSAlPiUgCiAgdW5uZXN0KGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsKSAlPiUgCiAgc2VsZWN0KC1kYXRhLCAtZGlmZnNfY29lZl9wYWlycywgLWRpZmZzX2NvZWZzKSAjJT4lIAogICNtdXRhdGUocGFpciA9ICJIZXkiKQoKcGFpcnNfcGxvdF9kYXRhX2NpIDwtIHBhaXJzX2NvbmRpdGlvbnNfY2kgJT4lIAogIHNlbGVjdChpc3N1ZSwgZGlmZnNfY29lZnMpICU+JSAKICB1bm5lc3QoZGlmZnNfY29lZnMpICU+JQogIGdhdGhlcihwYWlyLCB2YWx1ZSwgLWlzc3VlKSAlPiUKICBtdXRhdGUocGFpcjEgPSBwYWlyKSAlPiUKICBzZXBhcmF0ZShwYWlyMSwgaW50byA9IGMoImdyb3VwMSIsICJncm91cDIiKSwgc2VwID0gIiAtICIpICU+JQogIG11dGF0ZShwYWlyID0gaWZlbHNlKG5jaGFyKHBhaXIpID4gMjUsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyX3JlcGxhY2UocGFpciwgIi0iLCAiLVxuIiksCiAgICAgICAgICAgICAgICAgICAgICAgcGFpcikpCgpwbG90X2RpZmZzX2NpIDwtIGdncGxvdCgpICsgCiAgZ2VvbV9kZW5zaXR5KGRhdGEgPSBwYWlyc19wbG90X2RhdGFfY2ksIGFlcyh4ID0gdmFsdWUpLAogICAgICAgICAgICAgICBmaWxsID0gbmdvX2NvbHMoImJsdWUiKSwgY29sb3VyID0gTkEsIGFscGhhID0gMC40KSArIAogIGdlb21fc2VnbWVudChkYXRhID0gZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfY2ksCiAgICAgICAgICAgICAgIGFlcyh4ID0gcTUsIHhlbmQgPSBxOTUsIHkgPSAwLCB5ZW5kID0gMCksCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV92bGluZShkYXRhID0gZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfY2ksIGFlcyh4aW50ZXJjZXB0ID0gbWVkaWFuKSwgc2l6ZSA9IDAuMjUpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSwgY29sb3IgPSBGQUxTRSkgKwogIGxhYnMoeCA9ICJEaWZmZXJlbmNlIGluIG1lZGlhbnMiKSArCiAgdGhlbWVfbmdvcyhkZW5zaXR5ID0gVFJVRSkgKwogIGZhY2V0X3dyYXAofiBpc3N1ZSArIHBhaXIpCmBgYAoKYGBge3IgYW1vdW50LWRpZmZzLWNpZn0KIyBOZXN0IGVhY2ggZml0dGVkIGNoYWluIGludG8gYSBzaW5nbGUgcm93IHRoYXQgY29ycmVzcG9uZHMgdG8gZWFjaCBuZXdkYXRhX2NvbmRpdGlvbgpjaGFpbnNfbmVzdGVkX2NpZiA8LSBjaGFpbnNfZml0dGVkX2NpZiAlPiUgCiAgYXNfZGF0YV9mcmFtZSgpICU+JSAKICBtdXRhdGUoaWQgPSAxOm4oKSkgJT4lIAogIGdhdGhlcihjb25kaXRpb24sIHZhbHVlLCAtaWQpICU+JSAKICBncm91cF9ieShjb25kaXRpb24pICU+JSAKICBuZXN0KCkKCiMgQWRkIHRoZSBmaXR0ZWQgY2hhaW5zIHRvIHRoZSBjb25kaXRpb25zLCBzcHJlYWQgdGhlIG1haW4gY3JhY2tkb3duIGNvbmRpdGlvbgojIGludG8gdHdvIGNvbHVtbnMsIHRoZW4gbmVzdCBldmVyeXRoaW5nIGJ5IGlzc3VlCmFsbF9jaGFpbnNfY2lmIDwtIGJpbmRfY29scyhuZXdkYXRhX2NvbmRpdGlvbnNfY2lmLCBjaGFpbnNfbmVzdGVkX2NpZikgJT4lIAogIHVubmVzdChkYXRhKSAlPiUgCiAgc2VsZWN0KC1jb25kaXRpb24pICU+JSAKICBncm91cF9ieShpc3N1ZSwgZnVuZGluZykgJT4lIAogIHNwcmVhZChjcmFja2Rvd24sIHZhbHVlKSAlPiUgCiAgc2VsZWN0KC1pZCkgJT4lIAogIG5lc3QoKQoKIyBBbGwgdGhlIHBhaXJ3aXNlIGRpZmZlcmVuY2VzIGluIGEgc2luZ2xlIGRhdGEgZnJhbWUsIGdyb3VwZWQgYnkgaXNzdWUKcGFpcnNfY29uZGl0aW9uc19jaWYgPC0gYWxsX2NoYWluc19jaWYgJT4lIAogIG11dGF0ZShkaWZmc19jb2VmX3BhaXJzID0gZGF0YSAlPiUgbWFwKH4gbWNtY19wYWlyd2lzZV9kaWZmcyguKSksCiAgICAgICAgIGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsID0gZGlmZnNfY29lZl9wYWlycyAlPiUgbWFwKH4gdGlkeV9kaWZmcyguKSksCiAgICAgICAgIGRpZmZzX2NvZWZzID0gZGlmZnNfY29lZl9wYWlycyAlPiUgbWFwKH4gLiRtY21jX2RpZmZzKSkKCiMgRXh0cmFjdCBjb2VmZmljaWVudCBkZXRhaWxzIGFuZCBwbG90IGRhdGEKZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfY2lmIDwtIHBhaXJzX2NvbmRpdGlvbnNfY2lmICU+JSAKICB1bm5lc3QoZGlmZnNfY29lZl9wYWlyc19kZXRhaWwpICU+JSAKICBzZWxlY3QoLWRhdGEsIC1kaWZmc19jb2VmX3BhaXJzLCAtZGlmZnNfY29lZnMpCgpwYWlyc19wbG90X2RhdGFfY2lmIDwtIHBhaXJzX2NvbmRpdGlvbnNfY2lmICU+JSAKICBzZWxlY3QoaXNzdWUsIGZ1bmRpbmcsIGRpZmZzX2NvZWZzKSAlPiUgCiAgdW5uZXN0KGRpZmZzX2NvZWZzKSAlPiUKICBnYXRoZXIocGFpciwgdmFsdWUsIC1pc3N1ZSwgLWZ1bmRpbmcpICU+JQogIG11dGF0ZShwYWlyMSA9IHBhaXIpICU+JQogIHNlcGFyYXRlKHBhaXIxLCBpbnRvID0gYygiZ3JvdXAxIiwgImdyb3VwMiIpLCBzZXAgPSAiIC0gIikgJT4lCiAgbXV0YXRlKHBhaXIgPSBpZmVsc2UobmNoYXIocGFpcikgPiAyNSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJfcmVwbGFjZShwYWlyLCAiLSIsICItXG4iKSwKICAgICAgICAgICAgICAgICAgICAgICBwYWlyKSkKCnBsb3RfZGlmZnNfY2lmIDwtIGdncGxvdCgpICsgCiAgZ2VvbV9kZW5zaXR5KGRhdGEgPSBwYWlyc19wbG90X2RhdGFfY2lmLCBhZXMoeCA9IHZhbHVlKSwKICAgICAgICAgICAgICAgZmlsbCA9IG5nb19jb2xzKCJyZWQiKSwgY29sb3VyID0gTkEsIGFscGhhID0gMC40KSArIAogIGdlb21fc2VnbWVudChkYXRhID0gZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfY2lmLCAKICAgICAgICAgICAgICAgYWVzKHggPSBxNSwgeGVuZCA9IHE5NSwgeSA9IDAsIHllbmQgPSAwKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBnZW9tX3ZsaW5lKGRhdGEgPSBkaWZmc19jb2VmX3BhaXJzX2RldGFpbF9jaWYsIGFlcyh4aW50ZXJjZXB0ID0gbWVkaWFuKSwgc2l6ZSA9IDAuMjUpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSwgY29sb3IgPSBGQUxTRSkgKwogIGxhYnMoeCA9ICJEaWZmZXJlbmNlIGluIG1lZGlhbnMiKSArCiAgdGhlbWVfbmdvcyhkZW5zaXR5ID0gVFJVRSkgKwogIGZhY2V0X3dyYXAofiBpc3N1ZSArIGZ1bmRpbmcgKyBwYWlyKQpgYGAKCioqQ29tcGFyZSBvbmx5IGluZGl2aWR1YWwgY29uZGl0aW9uczoqKgoKYGBge3IgcGxvdC1zaW5nbGUtYW1vdW50LWRpZmZzLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0yLjV9CmRpZmZzX3Bsb3RfZGF0YV9zaW5nbGVzIDwtIGJpbmRfcm93cyhwYWlyc19wbG90X2RhdGFfYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhaXJzX3Bsb3RfZGF0YV9pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFpcnNfcGxvdF9kYXRhX2YpICU+JSAKICBtdXRhdGUocGFpciA9IGZjdF9pbm9yZGVyKHBhaXIsIG9yZGVyZWQgPSBUUlVFKSkKCmRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsX3NpbmdsZXMgPC0gYmluZF9yb3dzKGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsX2MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsX2ksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsX2YpICU+JQogIG11dGF0ZShwYWlyID0gaWZlbHNlKG5jaGFyKHBhaXIpID4gMjUsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyX3JlcGxhY2UocGFpciwgIi0iLCAiLVxuIiksCiAgICAgICAgICAgICAgICAgICAgICAgcGFpciksCiAgICAgICAgIHBhaXIgPSBmY3RfaW5vcmRlcihwYWlyLCBvcmRlcmVkID0gVFJVRSkpCgpwbG90X2RpZmZzX3NpbmdsZXMgPC0gZ2dwbG90KCkgKwogIGdlb21fZGVuc2l0eShkYXRhID0gZGlmZnNfcGxvdF9kYXRhX3NpbmdsZXMsIAogICAgICAgICAgICAgICBhZXMoeCA9IHZhbHVlLCBmaWxsID0gcGFpciksCiAgICAgICAgICAgICAgIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuNCkgKwogIGdlb21fc2VnbWVudChkYXRhID0gZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfc2luZ2xlcywgCiAgICAgICAgICAgICAgIGFlcyh4ID0gcTUsIHhlbmQgPSBxOTUsIHkgPSAwLCB5ZW5kID0gMCwgZ3JvdXAgPSBwYWlyKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBnZW9tX3ZsaW5lKGRhdGEgPSBkaWZmc19jb2VmX3BhaXJzX2RldGFpbF9zaW5nbGVzLCAKICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gbWVkaWFuKSwgc2l6ZSA9IDAuMjUpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IGRvbGxhcikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG5nb19jb2xzKCJncmVlbiIsICJibHVlIiwgInJlZCIsIG5hbWUgPSBGQUxTRSksIGd1aWRlID0gRkFMU0UpICsKICBsYWJzKHggPSAiRGlmZmVyZW5jZSBpbiBtZWRpYW5zIikgKwogIHRoZW1lX25nb3MoZGVuc2l0eSA9IFRSVUUpICsKICBmYWNldF93cmFwKH4gcGFpcikKCnBsb3RfZGlmZnNfc2luZ2xlcyAlVD4lCiAgcHJpbnQoKSAlVD4lIAogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgImFtb3VudC1zaW5nbGVzLWRpZmZzLnBkZiIpLAogICAgICAgICB3aWR0aCA9IDcsIGhlaWdodCA9IDIuNSwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSBjYWlyb19wZGYpICU+JSAKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJhbW91bnQtc2luZ2xlcy1kaWZmcy5wbmciKSwKICAgICAgICAgd2lkdGggPSA3LCBoZWlnaHQgPSAyLjUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgpgYGB7ciB0Ymwtc2luZ2xlLWFtb3VudC1kaWZmcywgcmVzdWx0cz0iYXNpcyJ9CmJpbmRfcm93cyhkaWZmc19jb2VmX3BhaXJzX2RldGFpbF9jLAogICAgICAgICAgZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfaSwKICAgICAgICAgIGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsX2YpICU+JSAKICBzZWxlY3QoYEZyYW1lYCA9IHBhaXIsIGDiiIZ+bWVkaWFufmAgPSBtZWRpYW4sIAogICAgICAgICBgJeKIhn5tZWRpYW5+YCA9IG1lZGlhbl9wY3RfY2hhbmdlLAogICAgICAgICBgcCjiiIYgPiAwKWAgPSBwLmdyZWF0ZXIwLCBgcCjiiIYgPCAwKWAgPSBwLmxlc3MwLCBgcCjiiIYg4omgIDApYCA9IHAuZGlmZi5ub3QwKSAlPiUgCiAgcGFuZG9jLnRhYmxlLnJldHVybihtaXNzaW5nID0gIuKAlCIsIAogICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJNZWRpYW4gZGlmZmVyZW5jZSBiZXR3ZWVuIGxpa2VsaWhvb2QgdG8gZG9uYXRlIGFjcm9zcyBzaW5nbGUgY29uZGl0aW9ucyB7I3RibDphbW91bnQtc2luZ2xlLWRpZmZzfSIpICVUPiUKICBjYXQoKSAlPiUgCiAgY2F0KGZpbGUgPSBoZXJlKCJvdXRwdXQiLCAidGFibGVzIiwgInRibC1hbW91bnQtc2luZ2xlLWRpZmZzLm1kIikpCmBgYAoKXAoKKipDb21wYXJlIG5lc3RlZCBjb25kaXRpb25zICh3aGF0IHdlJ3JlIHJlYWxseSBtb3N0IGNvbmNlcm5lZCBhYm91dCk6KioKCmBgYHtyIHBsb3QtYWxsLWFtb3VudC1kaWZmcywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KcGxvdF9kaWZmc19hbGwgPC0gCiAgKHBsb3RfZGlmZnNfYyAvIHBsb3RfZGlmZnNfY2kpIHwgCiAgcGxvdF9kaWZmc19jaWYKCnBsb3RfZGlmZnNfYWxsICsKICBwbG90X2Fubm90YXRpb24odGl0bGUgPSAiRGlmZmVyZW5jZXMgaW4gbWVkaWFuIGFtb3VudCBkb25hdGVkIGluIGNvbnRyb2wgYW5kIGNyYWNrZG93biBncm91cHMsXG5jb25kaXRpb25lZCBieSBvdGhlciBleHBlcmltZW50YWwgZ3JvdXBzIiwKICAgICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiOTAlIGNyZWRpYmxlIGludGVydmFscyBzaG93biBpbiBibGFjay4gU29saWQgdmVydGljYWwgbGluZSA9IG1lZGlhbjsgZG90dGVkIHZlcnRpY2FsIGxpbmUgPSAwIiwKICAgICAgICAgICAgICAgICAgdGFnX2xldmVscyA9ICJBIiwgdGhlbWUgPSB0aGVtZV9uZ29zKCkpCgoocGxvdF9kaWZmc19hbGwgKwogIHBsb3RfYW5ub3RhdGlvbihjYXB0aW9uID0gIjkwJSBjcmVkaWJsZSBpbnRlcnZhbHMgc2hvd24gaW4gYmxhY2suIFNvbGlkIHZlcnRpY2FsIGxpbmUgPSBtZWRpYW47IGRvdHRlZCB2ZXJ0aWNhbCBsaW5lID0gMCIsCiAgICAgICAgICAgICAgICAgIHRhZ19sZXZlbHMgPSAiQSIsIHRoZW1lID0gdGhlbWVfbmdvcygpKSkgJVQ+JQogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgImFtb3VudC1kaWZmcy5wZGYiKSwKICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSA1LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lCiAgZ2dzYXZlKC4sIGZpbGVuYW1lID0gaGVyZSgib3V0cHV0IiwgImZpZ3VyZXMiLCAiYW1vdW50LWRpZmZzLnBuZyIpLAogICAgICAgICB3aWR0aCA9IDgsIGhlaWdodCA9IDUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgpgYGB7ciB0YmwtYWxsLWFtb3VudC1kaWZmcywgcmVzdWx0cz0iYXNpcyJ9CmJpbmRfcm93cyhkaWZmc19jb2VmX3BhaXJzX2RldGFpbF9jLAogICAgICAgICAgZGlmZnNfY29lZl9wYWlyc19kZXRhaWxfY2ksCiAgICAgICAgICBkaWZmc19jb2VmX3BhaXJzX2RldGFpbF9jaWYpICU+JSAKICBzZWxlY3QoSXNzdWUgPSBpc3N1ZSwgRnVuZGluZyA9IGZ1bmRpbmcsIAogICAgICAgICBg4oiGfm1lZGlhbn5gID0gbWVkaWFuLCAKICAgICAgICAgYCXiiIZ+bWVkaWFufmAgPSBtZWRpYW5fcGN0X2NoYW5nZSwKICAgICAgICAgYHAo4oiGID4gMClgID0gcC5ncmVhdGVyMCwgYHAo4oiGIDwgMClgID0gcC5sZXNzMCwgYHAo4oiGIOKJoCAwKWAgPSBwLmRpZmYubm90MCkgJT4lIAogIHBhbmRvYy50YWJsZS5yZXR1cm4obWlzc2luZyA9ICLigJQiLCAKICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAnTWVkaWFuIGRpZmZlcmVuY2UgYmV0d2VlbiBhbW91bnRzIGRvbmF0ZWQgaW4gImNyYWNrZG93biIgKHRyZWF0bWVudCkgYW5kICJubyBjcmFja2Rvd24iIChjb250cm9sKSBjb25kaXRpb25zIHsjdGJsOmFtb3VudC1kaWZmc30nKSAlVD4lCiAgY2F0KCkgJT4lIAogIGNhdChmaWxlID0gaGVyZSgib3V0cHV0IiwgInRhYmxlcyIsICJ0YmwtYW1vdW50LWRpZmZzLm1kIikpCmBgYAoKXAoKIyBMaWtlbGlob29kIG9mIGRvbmF0aW9uCgojIyBNb2RlbHMKCmBgYHtyIGJ1aWxkLW1vZGVscy1saWtlbHksIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUV9CiMgQmFzaWMgaW50ZXJhY3Rpb24gbW9kZWxzCiMgV2Vha2x5IGluZm9ybWF0aXZlIHN0dWRlbnQgdCBwcmlvcnMsIHNpbmNlIHRoZXNlIGNvZWZmaWNpZW50cyBhcmUgbG9nLW9kZHMKIyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3N0YW4tZGV2L3N0YW4vd2lraS9Qcmlvci1DaG9pY2UtUmVjb21tZW5kYXRpb25zI3ByaW9yLWZvci10aGUtcmVncmVzc2lvbi1jb2VmZmljaWVudHMtaW4tbG9naXN0aWMtcmVncmVzc2lvbi1ub24tc3BhcnNlLWNhc2UgYW5kIGh0dHBzOi8vYXJ4aXYub3JnL2Ficy8xNTA3LjA3MTcwCm1fbGlrZWx5X2MgPC0gc3Rhbl9nbG0oZG9uYXRlX2xpa2VseV9iaW4gfiBjcmFja2Rvd24sCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHJlc3VsdHMsIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSwKICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHN0dWRlbnRfdCgzLCAwLCAyLjUpLAogICAgICAgICAgICAgICAgICAgICAgIHByaW9yX2ludGVyY2VwdCA9IHN0dWRlbnRfdCgzLCAwLCAxMCksCiAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gQ0hBSU5TLCBpdGVyID0gSVRFUiwgd2FybXVwID0gV0FSTVVQLCBzZWVkID0gQkFZRVNfU0VFRCkKCm1fbGlrZWx5X2NpIDwtIHVwZGF0ZShtX2xpa2VseV9jLCAuIH4gLiArIGlzc3VlICsgY3JhY2tkb3duICogaXNzdWUpCgptX2xpa2VseV9jaWYgPC0gdXBkYXRlKG1fbGlrZWx5X2MsIC4gfiAuICsgCiAgICAgICAgICAgICAgICAgICAgICAgICBpc3N1ZSArIGZ1bmRpbmcgKyBjcmFja2Rvd24gKiBpc3N1ZSArIGNyYWNrZG93biAqIGZ1bmRpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgIGlzc3VlICogZnVuZGluZyArIGNyYWNrZG93biAqIGlzc3VlICogZnVuZGluZykKCiMgTW9kZWxzIHdpdGgganVzdCBpc3N1ZSBhbmQganVzdCBmdW5kaW5nCm1fbGlrZWx5X2kgPC0gdXBkYXRlKG1fbGlrZWx5X2MsIC4gfiBpc3N1ZSkKbV9saWtlbHlfZiA8LSB1cGRhdGUobV9saWtlbHlfYywgLiB+IGZ1bmRpbmcpCmBgYAoKYGBge3IgdGJsLW1vZGVscy1saWtlbHksIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9ImFzaXMifQojIEdldCBzdWJzZXQgb2YgY29lZmZpY2llbnRzCmNvZWZzX3RvX2luY2x1ZGUgPC0gbGlzdChtX2xpa2VseV9jLCBtX2xpa2VseV9jaSwgbV9saWtlbHlfY2lmKSAlPiUgCiAgbWFwKH4gdGlkeSguKSkgJT4lIGJpbmRfcm93cygpICU+JSBkaXN0aW5jdCh0ZXJtKSAlPiUgcHVsbCh0ZXJtKQoKaHV4cmVnKG1fbGlrZWx5X2MsIG1fbGlrZWx5X2NpLCBtX2xpa2VseV9jaWYsIAogICAgICAgY29lZnMgPSBjbGVhbl9jb2Vmc19uYW1lZFtjbGVhbl9jb2Vmc19uYW1lZCAlaW4lIGNvZWZzX3RvX2luY2x1ZGVdLAogICAgICAgc3RhdGlzdGljcyA9IG1vZGVsX3N0YXRzX2JheWVzLAogICAgICAgc3RhcnMgPSBOVUxMKSAlVD4lIAogIHByaW50X2h1eCgpICU+JSAKICB0b19tZChtYXhfd2lkdGggPSAxMDApICU+JSAKICBjYXQoZmlsZSA9IGhlcmUoIm91dHB1dCIsICJ0YWJsZXMiLCAidGJsLW1vZGVscy1saWtlbGlob29kLm1kIikpCmBgYAoKIyMgUHJlZGljdGVkIG1lZGlhbnMKCmBgYHtyIGxpa2VseS1tZWRpYW4tY30KbmV3ZGF0YV9jb25kaXRpb25zX2MgPC0gcmVzdWx0cyAlPiUgZXhwYW5kKG5lc3RpbmcoY3JhY2tkb3duKSkKCiMgdHJhbnNmb3JtID0gVFJVRSBkb2VzIHRoZSBzYW1lIHRoaW5nIGFzIHBsb2dpcyhhcy5tYXRyaXgobV9saWtlbHlfYykpCmNoYWluc19maXR0ZWRfbGlrZWx5X2MgPC0gcG9zdGVyaW9yX2xpbnByZWQobV9saWtlbHlfYywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5ld2RhdGFfY29uZGl0aW9uc19jLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSBUUlVFKQoKY29lZl9zdW1tYXJ5X2xpa2VseV9jIDwtIG5ld2RhdGFfY29uZGl0aW9uc19jICU+JSAKICBiaW5kX2NvbHModGlkeU1DTUMoY2hhaW5zX2ZpdHRlZF9saWtlbHlfYywgZXN0aW1hdGUubWV0aG9kID0gIm1lZGlhbiIsCiAgICAgICAgICAgICAgICAgICAgIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOSwgY29uZi5tZXRob2QgPSAiSFBEaW50ZXJ2YWwiKSkKCnBsb3RfbGlrZWx5X2MgPC0gZ2dwbG90KGNvZWZfc3VtbWFyeV9saWtlbHlfYywgYWVzKHkgPSBlc3RpbWF0ZSwgeCA9IGNyYWNrZG93bikpICsgCiAgIyBnZW9tX3BvaW50KGRhdGEgPSByZXN1bHRzLCBhZXMoeSA9IGFtb3VudF9kb25hdGUsIHggPSBjcmFja2Rvd24pLAogICMgICAgICAgICAgICBjb2xvciA9ICJncmV5NTAiLCBzaXplID0gMC41LCBhbHBoYSA9IDAuMjUpICsKICBnZW9tX3BvaW50cmFuZ2UoYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCksIGNvbG9yID0gbmdvX2NvbHMoImdyZWVuIikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gIlByb2JhYmlsaXR5IG9mIGRvbmF0aW5nIikgKwogICMgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsIDEwMCkpICsKICB0aGVtZV9uZ29zKCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgpgYGB7ciBsaWtlbHktbWVkaWFuLWl9Cm5ld2RhdGFfY29uZGl0aW9uc19pIDwtIHJlc3VsdHMgJT4lIGV4cGFuZChuZXN0aW5nKGlzc3VlKSkKCmNoYWluc19maXR0ZWRfbGlrZWx5X2kgPC0gcG9zdGVyaW9yX2xpbnByZWQobV9saWtlbHlfaSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5ld2RhdGFfY29uZGl0aW9uc19pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSBUUlVFKQoKY29lZl9zdW1tYXJ5X2xpa2VseV9pIDwtIG5ld2RhdGFfY29uZGl0aW9uc19pICU+JSAKICBiaW5kX2NvbHModGlkeU1DTUMoY2hhaW5zX2ZpdHRlZF9saWtlbHlfaSwgZXN0aW1hdGUubWV0aG9kID0gIm1lZGlhbiIsCiAgICAgICAgICAgICAgICAgICAgIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOSwgY29uZi5tZXRob2QgPSAiSFBEaW50ZXJ2YWwiKSkKCnBsb3RfbGlrZWx5X2kgPC0gZ2dwbG90KGNvZWZfc3VtbWFyeV9saWtlbHlfaSwgYWVzKHkgPSBlc3RpbWF0ZSwgeCA9IGlzc3VlKSkgKyAKICBnZW9tX3BvaW50cmFuZ2UoYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCksIGNvbG9yID0gbmdvX2NvbHMoImdyZWVuIikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gIlByb2JhYmlsaXR5IG9mIGRvbmF0aW5nIikgKwogIHRoZW1lX25nb3MoKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyIGxpa2VseS1tZWRpYW4tZn0KbmV3ZGF0YV9jb25kaXRpb25zX2YgPC0gcmVzdWx0cyAlPiUgZXhwYW5kKG5lc3RpbmcoZnVuZGluZykpCgpjaGFpbnNfZml0dGVkX2xpa2VseV9mIDwtIHBvc3Rlcmlvcl9saW5wcmVkKG1fbGlrZWx5X2YsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBuZXdkYXRhX2NvbmRpdGlvbnNfZiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gVFJVRSkKCmNvZWZfc3VtbWFyeV9saWtlbHlfZiA8LSBuZXdkYXRhX2NvbmRpdGlvbnNfZiAlPiUgCiAgYmluZF9jb2xzKHRpZHlNQ01DKGNoYWluc19maXR0ZWRfbGlrZWx5X2YsIGVzdGltYXRlLm1ldGhvZCA9ICJtZWRpYW4iLAogICAgICAgICAgICAgICAgICAgICBjb25mLmludCA9IFRSVUUsIGNvbmYubGV2ZWwgPSAwLjksIGNvbmYubWV0aG9kID0gIkhQRGludGVydmFsIikpCgpwbG90X2xpa2VseV9mIDwtIGdncGxvdChjb2VmX3N1bW1hcnlfbGlrZWx5X2YsIGFlcyh5ID0gZXN0aW1hdGUsIHggPSBmdW5kaW5nKSkgKyAKICBnZW9tX3BvaW50cmFuZ2UoYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCksIGNvbG9yID0gbmdvX2NvbHMoImdyZWVuIikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gIlByb2JhYmlsaXR5IG9mIGRvbmF0aW5nIikgKwogIHRoZW1lX25nb3MoKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyIGxpa2VseS1tZWRpYW4tY2l9Cm5ld2RhdGFfY29uZGl0aW9uc19jaSA8LSByZXN1bHRzICU+JSBleHBhbmQobmVzdGluZyhjcmFja2Rvd24sIGlzc3VlKSkKCmNoYWluc19maXR0ZWRfbGlrZWx5X2NpIDwtIHBvc3Rlcmlvcl9saW5wcmVkKG1fbGlrZWx5X2NpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5ld2RhdGFfY29uZGl0aW9uc19jaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gVFJVRSkKCmNvZWZfc3VtbWFyeV9saWtlbHlfY2kgPC0gbmV3ZGF0YV9jb25kaXRpb25zX2NpICU+JSAKICBiaW5kX2NvbHModGlkeU1DTUMoY2hhaW5zX2ZpdHRlZF9saWtlbHlfY2ksIGVzdGltYXRlLm1ldGhvZCA9ICJtZWRpYW4iLAogICAgICAgICAgICAgICAgICAgICBjb25mLmludCA9IFRSVUUsIGNvbmYubGV2ZWwgPSAwLjksIGNvbmYubWV0aG9kID0gIkhQRGludGVydmFsIikpCgpwbG90X2xpa2VseV9jaSA8LSBnZ3Bsb3QoY29lZl9zdW1tYXJ5X2xpa2VseV9jaSwgYWVzKHkgPSBlc3RpbWF0ZSwgeCA9IGNyYWNrZG93bikpICsgCiAgIyBnZW9tX3BvaW50KGRhdGEgPSByZXN1bHRzLCBhZXMoeSA9IGFtb3VudF9kb25hdGUsIHggPSBjcmFja2Rvd24pLAogICMgICAgICAgICAgICBjb2xvciA9ICJncmV5NTAiLCBzaXplID0gMC41LCBhbHBoYSA9IDAuMjUpICsKICBnZW9tX3BvaW50cmFuZ2UoYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCksIGNvbG9yID0gbmdvX2NvbHMoImJsdWUiKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSAiUHJvYmFiaWxpdHkgb2YgZG9uYXRpbmciKSArCiAgIyBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgMTAwKSkgKwogIHRoZW1lX25nb3MoKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKDUsIDAsIDIsIDAsICJwdCIpKSkgKwogIGZhY2V0X3dyYXAofiBpc3N1ZSkKYGBgCgpgYGB7ciBsaWtlbHktbWVkaWFuLWNpZn0KbmV3ZGF0YV9jb25kaXRpb25zX2NpZiA8LSByZXN1bHRzICU+JSBleHBhbmQobmVzdGluZyhjcmFja2Rvd24sIGlzc3VlLCBmdW5kaW5nKSkKCmNoYWluc19maXR0ZWRfbGlrZWx5X2NpZiA8LSBwb3N0ZXJpb3JfbGlucHJlZChtX2xpa2VseV9jaWYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5ld2RhdGFfY29uZGl0aW9uc19jaWYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSBUUlVFKQoKY29lZl9zdW1tYXJ5X2xpa2VseV9jaWYgPC0gbmV3ZGF0YV9jb25kaXRpb25zX2NpZiAlPiUgCiAgYmluZF9jb2xzKHRpZHlNQ01DKGNoYWluc19maXR0ZWRfbGlrZWx5X2NpZiwgZXN0aW1hdGUubWV0aG9kID0gIm1lZGlhbiIsCiAgICAgICAgICAgICAgICAgICAgIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOSwgY29uZi5tZXRob2QgPSAiSFBEaW50ZXJ2YWwiKSkKCnBsb3RfbGlrZWx5X2NpZiA8LSBnZ3Bsb3QoY29lZl9zdW1tYXJ5X2xpa2VseV9jaWYsIGFlcyh5ID0gZXN0aW1hdGUsIHggPSBjcmFja2Rvd24pKSArIAogICMgZ2VvbV9wb2ludChkYXRhID0gcmVzdWx0cywgYWVzKHkgPSBhbW91bnRfZG9uYXRlLCB4ID0gY3JhY2tkb3duKSwKICAjICAgICAgICAgICAgY29sb3IgPSAiZ3JleTUwIiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjUpICsKICBnZW9tX3BvaW50cmFuZ2UoYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCksIGNvbG9yID0gbmdvX2NvbHMoInJlZCIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gIlByb2JhYmlsaXR5IG9mIGRvbmF0aW5nIikgKwogIHRoZW1lX25nb3MoKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKDUsIDAsIDIsIDAsICJwdCIpKSkgKwogIGZhY2V0X3dyYXAofiBpc3N1ZSArIGZ1bmRpbmcpCmBgYAoKYGBge3IgcGxvdC1hbGwtbGlrZWx5LW1lZGlhbnMsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9CnBsb3RfbGlrZWx5X2FsbCA8LSAKICAocGxvdF9saWtlbHlfYyAvIHBsb3RfbGlrZWx5X2NpKSB8IAogIHBsb3RfbGlrZWx5X2NpZgoKcGxvdF9saWtlbHlfYWxsICsKICBwbG90X2Fubm90YXRpb24odGl0bGUgPSAiTWVkaWFuIGxpa2VsaWhvb2Qgb2YgZG9uYXRpb24gaW4gY29udHJvbCBhbmQgY3JhY2tkb3duIGdyb3VwcyxcbmNvbmRpdGlvbmVkIGJ5IG90aGVyIGV4cGVyaW1lbnRhbCBncm91cHMiLAogICAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICI5MCUgY3JlZGlibGUgaW50ZXJ2YWxzIHNob3duIGFyb3VuZCBlYWNoIHBvaW50IiwKICAgICAgICAgICAgICAgICAgdGFnX2xldmVscyA9ICJBIiwgdGhlbWUgPSB0aGVtZV9uZ29zKCkpCgoocGxvdF9saWtlbHlfYWxsICsKICBwbG90X2Fubm90YXRpb24oY2FwdGlvbiA9ICI5MCUgY3JlZGlibGUgaW50ZXJ2YWxzIHNob3duIGFyb3VuZCBlYWNoIHBvaW50IiwKICAgICAgICAgICAgICAgICAgdGFnX2xldmVscyA9ICJBIiwgdGhlbWUgPSB0aGVtZV9uZ29zKCkpKSAlVD4lIAogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgImxpa2VsaWhvb2QtbWVkaWFucy5wZGYiKSwKICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSA0LjI1LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lIAogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgImxpa2VsaWhvb2QtbWVkaWFucy5wbmciKSwKICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSA0LjI1LCB1bml0cyA9ICJpbiIsIHR5cGUgPSAiY2Fpcm8iLCBkcGkgPSAzMDApCmBgYAoKCiMjIERpZmZlcmVuY2VzIGluIG1lZGlhbnMKCmBgYHtyIGxpa2VseS1kaWZmcy1jfQpkaWZmc19jb2VmX2xpa2VseV9wYWlyc19jIDwtIGNoYWluc19maXR0ZWRfbGlrZWx5X2MgJT4lIAogIGFzX2RhdGFfZnJhbWUoKSAlPiUgCiAgbWFncml0dHI6OnNldF9jb2xuYW1lcyhsZXZlbHMobmV3ZGF0YV9jb25kaXRpb25zX2MkY3JhY2tkb3duKSkgJT4lIAogIG1jbWNfcGFpcndpc2VfZGlmZnMoKQoKZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX2MgPC0gdGlkeV9kaWZmcyhkaWZmc19jb2VmX2xpa2VseV9wYWlyc19jKQoKcGFpcnNfbGlrZWx5X3Bsb3RfZGF0YV9jIDwtIGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2MkbWNtY19kaWZmcyAlPiUKICBnYXRoZXIocGFpciwgdmFsdWUpICU+JQogIG11dGF0ZShwYWlyMSA9IHBhaXIpICU+JQogIHNlcGFyYXRlKHBhaXIxLCBpbnRvID0gYygiZ3JvdXAxIiwgImdyb3VwMiIpLCBzZXAgPSAiIC0gIikgJT4lCiAgbXV0YXRlKHBhaXIgPSBpZmVsc2UobmNoYXIocGFpcikgPiAyNSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJfcmVwbGFjZShwYWlyLCAiLSIsICItXG4iKSwKICAgICAgICAgICAgICAgICAgICAgICBwYWlyKSkKICAKcGxvdF9kaWZmc19saWtlbHlfYyA8LSBnZ3Bsb3QoKSArIAogIGdlb21fZGVuc2l0eShkYXRhID0gcGFpcnNfbGlrZWx5X3Bsb3RfZGF0YV9jLCBhZXMoeCA9IHZhbHVlKSwKICAgICAgICAgICAgICAgZmlsbCA9IG5nb19jb2xzKCJncmVlbiIpLCBjb2xvdXIgPSBOQSwgYWxwaGEgPSAwLjQpICsgCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBkaWZmc19jb2VmX2xpa2VseV9wYWlyc19kZXRhaWxfYywgCiAgICAgICAgICAgICAgIGFlcyh4ID0gcTUsIHhlbmQgPSBxOTUsIHkgPSAwLCB5ZW5kID0gMCksCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV92bGluZShkYXRhID0gZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX2MsIAogICAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQgPSBtZWRpYW4pLCBzaXplID0gMC4yNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFLCBjb2xvciA9IEZBTFNFKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsKICBsYWJzKHggPSAiRGlmZmVyZW5jZSBpbiBtZWRpYW5zIikgKwogIHRoZW1lX25nb3MoZGVuc2l0eSA9IFRSVUUpICsKICBmYWNldF93cmFwKH4gcGFpcikKYGBgCgpgYGB7ciBsaWtlbHktZGlmZnMtaX0KZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfaSA8LSBjaGFpbnNfZml0dGVkX2xpa2VseV9pICU+JSAKICBhc19kYXRhX2ZyYW1lKCkgJT4lIAogIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMobGV2ZWxzKG5ld2RhdGFfY29uZGl0aW9uc19pJGlzc3VlKSkgJT4lIAogIG1jbWNfcGFpcndpc2VfZGlmZnMoKQoKZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX2kgPC0gdGlkeV9kaWZmcyhkaWZmc19jb2VmX2xpa2VseV9wYWlyc19pKQoKcGFpcnNfbGlrZWx5X3Bsb3RfZGF0YV9pIDwtIGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2kkbWNtY19kaWZmcyAlPiUKICBnYXRoZXIocGFpciwgdmFsdWUpICU+JQogIG11dGF0ZShwYWlyMSA9IHBhaXIpICU+JQogIHNlcGFyYXRlKHBhaXIxLCBpbnRvID0gYygiZ3JvdXAxIiwgImdyb3VwMiIpLCBzZXAgPSAiIC0gIikgJT4lCiAgbXV0YXRlKHBhaXIgPSBpZmVsc2UobmNoYXIocGFpcikgPiAyNSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJfcmVwbGFjZShwYWlyLCAiLSIsICItXG4iKSwKICAgICAgICAgICAgICAgICAgICAgICBwYWlyKSkKYGBgCgpgYGB7ciBsaWtlbHktZGlmZnMtZn0KZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZiA8LSBjaGFpbnNfZml0dGVkX2xpa2VseV9mICU+JSAKICBhc19kYXRhX2ZyYW1lKCkgJT4lIAogIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMobGV2ZWxzKG5ld2RhdGFfY29uZGl0aW9uc19mJGZ1bmRpbmcpKSAlPiUgCiAgbWNtY19wYWlyd2lzZV9kaWZmcygpCgpkaWZmc19jb2VmX2xpa2VseV9wYWlyc19kZXRhaWxfZiA8LSB0aWR5X2RpZmZzKGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2YpCgpwYWlyc19saWtlbHlfcGxvdF9kYXRhX2YgPC0gZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZiRtY21jX2RpZmZzICU+JQogIGdhdGhlcihwYWlyLCB2YWx1ZSkgJT4lCiAgbXV0YXRlKHBhaXIxID0gcGFpcikgJT4lCiAgc2VwYXJhdGUocGFpcjEsIGludG8gPSBjKCJncm91cDEiLCAiZ3JvdXAyIiksIHNlcCA9ICIgLSAiKSAlPiUKICBtdXRhdGUocGFpciA9IGlmZWxzZShuY2hhcihwYWlyKSA+IDI1LAogICAgICAgICAgICAgICAgICAgICAgIHN0cl9yZXBsYWNlKHBhaXIsICItIiwgIi1cbiIpLAogICAgICAgICAgICAgICAgICAgICAgIHBhaXIpKQpgYGAKCmBgYHtyIGxpa2VseS1kaWZmcy1jaX0KIyBOZXN0IGVhY2ggZml0dGVkIGNoYWluIGludG8gYSBzaW5nbGUgcm93IHRoYXQgY29ycmVzcG9uZHMgdG8gZWFjaCBuZXdkYXRhX2NvbmRpdGlvbgpjaGFpbnNfbmVzdGVkX2xpa2VseV9jaSA8LSBjaGFpbnNfZml0dGVkX2xpa2VseV9jaSAlPiUgCiAgYXNfZGF0YV9mcmFtZSgpICU+JSAKICBtdXRhdGUoaWQgPSAxOm4oKSkgJT4lIAogIGdhdGhlcihjb25kaXRpb24sIHZhbHVlLCAtaWQpICU+JSAKICBncm91cF9ieShjb25kaXRpb24pICU+JSAKICBuZXN0KCkKCiMgQWRkIHRoZSBmaXR0ZWQgY2hhaW5zIHRvIHRoZSBjb25kaXRpb25zLCBzcHJlYWQgdGhlIG1haW4gY3JhY2tkb3duIGNvbmRpdGlvbgojIGludG8gdHdvIGNvbHVtbnMsIHRoZW4gbmVzdCBldmVyeXRoaW5nIGJ5IGlzc3VlCmFsbF9jaGFpbnNfbGlrZWx5X2NpIDwtIGJpbmRfY29scyhuZXdkYXRhX2NvbmRpdGlvbnNfY2ksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zX25lc3RlZF9saWtlbHlfY2kpICU+JSAKICB1bm5lc3QoZGF0YSkgJT4lIAogIHNlbGVjdCgtY29uZGl0aW9uKSAlPiUgCiAgZ3JvdXBfYnkoaXNzdWUpICU+JSAKICBzcHJlYWQoY3JhY2tkb3duLCB2YWx1ZSkgJT4lIAogIHNlbGVjdCgtaWQpICU+JSAKICBuZXN0KCkKCiMgQWxsIHRoZSBwYWlyd2lzZSBkaWZmZXJlbmNlcyBpbiBhIHNpbmdsZSBkYXRhIGZyYW1lLCBncm91cGVkIGJ5IGlzc3VlCnBhaXJzX2xpa2VseV9jb25kaXRpb25zX2NpIDwtIGFsbF9jaGFpbnNfbGlrZWx5X2NpICU+JSAKICBtdXRhdGUoZGlmZnNfY29lZl9wYWlycyA9IGRhdGEgJT4lIG1hcCh+IG1jbWNfcGFpcndpc2VfZGlmZnMoLikpLAogICAgICAgICBkaWZmc19jb2VmX3BhaXJzX2RldGFpbCA9IGRpZmZzX2NvZWZfcGFpcnMgJT4lIG1hcCh+IHRpZHlfZGlmZnMoLikpLAogICAgICAgICBkaWZmc19jb2VmcyA9IGRpZmZzX2NvZWZfcGFpcnMgJT4lIG1hcCh+IC4kbWNtY19kaWZmcykpCgojIEV4dHJhY3QgY29lZmZpY2llbnQgZGV0YWlscyBhbmQgcGxvdCBkYXRhCmRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9jaSA8LSBwYWlyc19saWtlbHlfY29uZGl0aW9uc19jaSAlPiUgCiAgdW5uZXN0KGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsKSAlPiUgCiAgc2VsZWN0KC1kYXRhLCAtZGlmZnNfY29lZl9wYWlycykKCnBhaXJzX2xpa2VseV9wbG90X2RhdGFfY2kgPC0gcGFpcnNfbGlrZWx5X2NvbmRpdGlvbnNfY2kgJT4lIAogIHNlbGVjdChpc3N1ZSwgZGlmZnNfY29lZnMpICU+JSAKICB1bm5lc3QoZGlmZnNfY29lZnMpICU+JQogIGdhdGhlcihwYWlyLCB2YWx1ZSwgLWlzc3VlKSAlPiUKICBtdXRhdGUocGFpcjEgPSBwYWlyKSAlPiUKICBzZXBhcmF0ZShwYWlyMSwgaW50byA9IGMoImdyb3VwMSIsICJncm91cDIiKSwgc2VwID0gIiAtICIpICU+JQogIG11dGF0ZShwYWlyID0gaWZlbHNlKG5jaGFyKHBhaXIpID4gMjUsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyX3JlcGxhY2UocGFpciwgIi0iLCAiLVxuIiksCiAgICAgICAgICAgICAgICAgICAgICAgcGFpcikpCgpwbG90X2RpZmZzX2xpa2VseV9jaSA8LSBnZ3Bsb3QoKSArIAogIGdlb21fZGVuc2l0eShkYXRhID0gcGFpcnNfbGlrZWx5X3Bsb3RfZGF0YV9jaSwgYWVzKHggPSB2YWx1ZSksCiAgICAgICAgICAgICAgIGZpbGwgPSBuZ29fY29scygiYmx1ZSIpLCBjb2xvdXIgPSBOQSwgYWxwaGEgPSAwLjQpICsgCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBkaWZmc19jb2VmX2xpa2VseV9wYWlyc19kZXRhaWxfY2ksIAogICAgICAgICAgICAgICBhZXMoeCA9IHE1LCB4ZW5kID0gcTk1LCB5ID0gMCwgeWVuZCA9IDApLAogICAgICAgICAgICAgICBzaXplID0gMykgKwogIGdlb21fdmxpbmUoZGF0YSA9IGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9jaSwgCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IG1lZGlhbiksIHNpemUgPSAwLjI1KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZG90dGVkIikgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UsIGNvbG9yID0gRkFMU0UpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKwogIGxhYnMoeCA9ICJEaWZmZXJlbmNlIGluIG1lZGlhbnMiKSArCiAgdGhlbWVfbmdvcyhkZW5zaXR5ID0gVFJVRSkgKwogIGZhY2V0X3dyYXAofiBpc3N1ZSArIHBhaXIpCmBgYAoKYGBge3IgbGlrZWx5LWRpZmZzLWNpZn0KIyBOZXN0IGVhY2ggZml0dGVkIGNoYWluIGludG8gYSBzaW5nbGUgcm93IHRoYXQgY29ycmVzcG9uZHMgdG8gZWFjaCBuZXdkYXRhX2NvbmRpdGlvbgpjaGFpbnNfbmVzdGVkX2xpa2VseV9jaWYgPC0gY2hhaW5zX2ZpdHRlZF9saWtlbHlfY2lmICU+JSAKICBhc19kYXRhX2ZyYW1lKCkgJT4lIAogIG11dGF0ZShpZCA9IDE6bigpKSAlPiUgCiAgZ2F0aGVyKGNvbmRpdGlvbiwgdmFsdWUsIC1pZCkgJT4lIAogIGdyb3VwX2J5KGNvbmRpdGlvbikgJT4lIAogIG5lc3QoKQoKIyBBZGQgdGhlIGZpdHRlZCBjaGFpbnMgdG8gdGhlIGNvbmRpdGlvbnMsIHNwcmVhZCB0aGUgbWFpbiBjcmFja2Rvd24gY29uZGl0aW9uCiMgaW50byB0d28gY29sdW1ucywgdGhlbiBuZXN0IGV2ZXJ5dGhpbmcgYnkgaXNzdWUKYWxsX2NoYWluc19saWtlbHlfY2lmIDwtIGJpbmRfY29scyhuZXdkYXRhX2NvbmRpdGlvbnNfY2lmLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnNfbmVzdGVkX2xpa2VseV9jaWYpICU+JSAKICB1bm5lc3QoZGF0YSkgJT4lIAogIHNlbGVjdCgtY29uZGl0aW9uKSAlPiUgCiAgZ3JvdXBfYnkoaXNzdWUsIGZ1bmRpbmcpICU+JSAKICBzcHJlYWQoY3JhY2tkb3duLCB2YWx1ZSkgJT4lIAogIHNlbGVjdCgtaWQpICU+JSAKICBuZXN0KCkKCiMgQWxsIHRoZSBwYWlyd2lzZSBkaWZmZXJlbmNlcyBpbiBhIHNpbmdsZSBkYXRhIGZyYW1lLCBncm91cGVkIGJ5IGlzc3VlCnBhaXJzX2xpa2VseV9jb25kaXRpb25zX2NpZiA8LSBhbGxfY2hhaW5zX2xpa2VseV9jaWYgJT4lIAogIG11dGF0ZShkaWZmc19jb2VmX3BhaXJzID0gZGF0YSAlPiUgbWFwKH4gbWNtY19wYWlyd2lzZV9kaWZmcyguKSksCiAgICAgICAgIGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsID0gZGlmZnNfY29lZl9wYWlycyAlPiUgbWFwKH4gdGlkeV9kaWZmcyguKSksCiAgICAgICAgIGRpZmZzX2NvZWZzID0gZGlmZnNfY29lZl9wYWlycyAlPiUgbWFwKH4gLiRtY21jX2RpZmZzKSkKCiMgRXh0cmFjdCBjb2VmZmljaWVudCBkZXRhaWxzIGFuZCBwbG90IGRhdGEKZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX2NpZiA8LSBwYWlyc19saWtlbHlfY29uZGl0aW9uc19jaWYgJT4lIAogIHVubmVzdChkaWZmc19jb2VmX3BhaXJzX2RldGFpbCkgJT4lIAogIHNlbGVjdCgtZGF0YSwgLWRpZmZzX2NvZWZfcGFpcnMsIC1kaWZmc19jb2VmcykKCnBhaXJzX2xpa2VseV9wbG90X2RhdGFfY2lmIDwtIHBhaXJzX2xpa2VseV9jb25kaXRpb25zX2NpZiAlPiUgCiAgc2VsZWN0KGlzc3VlLCBmdW5kaW5nLCBkaWZmc19jb2VmcykgJT4lIAogIHVubmVzdChkaWZmc19jb2VmcykgJT4lCiAgZ2F0aGVyKHBhaXIsIHZhbHVlLCAtaXNzdWUsIC1mdW5kaW5nKSAlPiUKICBtdXRhdGUocGFpcjEgPSBwYWlyKSAlPiUKICBzZXBhcmF0ZShwYWlyMSwgaW50byA9IGMoImdyb3VwMSIsICJncm91cDIiKSwgc2VwID0gIiAtICIpICU+JQogIG11dGF0ZShwYWlyID0gaWZlbHNlKG5jaGFyKHBhaXIpID4gMjUsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyX3JlcGxhY2UocGFpciwgIi0iLCAiLVxuIiksCiAgICAgICAgICAgICAgICAgICAgICAgcGFpcikpCgpwbG90X2RpZmZzX2xpa2VseV9jaWYgPC0gZ2dwbG90KCkgKwogIGdlb21fZGVuc2l0eShkYXRhID0gcGFpcnNfbGlrZWx5X3Bsb3RfZGF0YV9jaWYsIGFlcyh4ID0gdmFsdWUpLAogICAgICAgICAgICAgICBmaWxsID0gbmdvX2NvbHMoInJlZCIpLCBjb2xvdXIgPSBOQSwgYWxwaGEgPSAwLjQpICsKICBnZW9tX3NlZ21lbnQoZGF0YSA9IGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9jaWYsCiAgICAgICAgICAgICAgIGFlcyh4ID0gcTUsIHhlbmQgPSBxOTUsIHkgPSAwLCB5ZW5kID0gMCksCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV92bGluZShkYXRhID0gZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX2NpZiwKICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gYG1lZGlhbmApLCBzaXplID0gMC4yNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFLCBjb2xvciA9IEZBTFNFKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsKICBsYWJzKHggPSAiRGlmZmVyZW5jZSBpbiBtZWRpYW5zIikgKwogIHRoZW1lX25nb3MoZGVuc2l0eSA9IFRSVUUpICsKICBmYWNldF93cmFwKH4gaXNzdWUgKyBmdW5kaW5nICsgcGFpcikKYGBgCgoqKkNvbXBhcmUgb25seSBpbmRpdmlkdWFsIGNvbmRpdGlvbnM6KioKCmBgYHtyIHBsb3Qtc2luZ2xlLWxpa2VseS1kaWZmcywgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9Mi41fQpkaWZmc19saWtlbHlfcGxvdF9kYXRhX3NpbmdsZXMgPC0gYmluZF9yb3dzKHBhaXJzX2xpa2VseV9wbG90X2RhdGFfYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWlyc19saWtlbHlfcGxvdF9kYXRhX2ksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFpcnNfbGlrZWx5X3Bsb3RfZGF0YV9mKSAlPiUgCiAgbXV0YXRlKHBhaXIgPSBmY3RfaW5vcmRlcihwYWlyLCBvcmRlcmVkID0gVFJVRSkpCgpkaWZmc19jb2VmX2xpa2VseV9wYWlyc19kZXRhaWxfc2luZ2xlcyA8LSBiaW5kX3Jvd3MoZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX2MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmc19jb2VmX2xpa2VseV9wYWlyc19kZXRhaWxfaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9mKSAlPiUKICBtdXRhdGUocGFpciA9IGlmZWxzZShuY2hhcihwYWlyKSA+IDI1LAogICAgICAgICAgICAgICAgICAgICAgIHN0cl9yZXBsYWNlKHBhaXIsICItIiwgIi1cbiIpLAogICAgICAgICAgICAgICAgICAgICAgIHBhaXIpLAogICAgICAgICBwYWlyID0gZmN0X2lub3JkZXIocGFpciwgb3JkZXJlZCA9IFRSVUUpKQoKcGxvdF9kaWZmc19saWtlbHlfc2luZ2xlcyA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9kZW5zaXR5KGRhdGEgPSBkaWZmc19saWtlbHlfcGxvdF9kYXRhX3NpbmdsZXMsIAogICAgICAgICAgICAgICBhZXMoeCA9IHZhbHVlLCBmaWxsID0gcGFpciksCiAgICAgICAgICAgICAgIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuNCkgKwogIGdlb21fc2VnbWVudChkYXRhID0gZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX3NpbmdsZXMsIAogICAgICAgICAgICAgICBhZXMoeCA9IHE1LCB4ZW5kID0gcTk1LCB5ID0gMCwgeWVuZCA9IDAsIGdyb3VwID0gcGFpciksCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV92bGluZShkYXRhID0gZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX3NpbmdsZXMsIAogICAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQgPSBtZWRpYW4pLCBzaXplID0gMC4yNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG5nb19jb2xzKCJncmVlbiIsICJibHVlIiwgInJlZCIsIG5hbWUgPSBGQUxTRSksIGd1aWRlID0gRkFMU0UpICsKICBsYWJzKHggPSAiRGlmZmVyZW5jZSBpbiBtZWRpYW5zIikgKwogIHRoZW1lX25nb3MoZGVuc2l0eSA9IFRSVUUpICsKICBmYWNldF93cmFwKH4gcGFpcikKCnBsb3RfZGlmZnNfbGlrZWx5X3NpbmdsZXMgJVQ+JQogIHByaW50KCkgJVQ+JSAKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJsaWtlbGlob29kLXNpbmdsZXMtZGlmZnMucGRmIiksCiAgICAgICAgIHdpZHRoID0gNywgaGVpZ2h0ID0gMi41LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikgJT4lIAogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgImxpa2VsaWhvb2Qtc2luZ2xlcy1kaWZmcy5wbmciKSwKICAgICAgICAgd2lkdGggPSA3LCBoZWlnaHQgPSAyLjUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgpgYGB7ciB0Ymwtc2luZ2xlLWxpa2VseS1kaWZmcywgcmVzdWx0cz0iYXNpcyJ9CmJpbmRfcm93cyhkaWZmc19jb2VmX2xpa2VseV9wYWlyc19kZXRhaWxfYywKICAgICAgICAgIGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9pLAogICAgICAgICAgZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX2YpICU+JSAKICBzZWxlY3QoYEZyYW1lYCA9IHBhaXIsIGDiiIZ+bWVkaWFufmAgPSBtZWRpYW4sIAogICAgICAgICBgJeKIhn5tZWRpYW5+YCA9IG1lZGlhbl9wY3RfY2hhbmdlLAogICAgICAgICBgcCjiiIYgPiAwKWAgPSBwLmdyZWF0ZXIwLCBgcCjiiIYgPCAwKWAgPSBwLmxlc3MwLCBgcCjiiIYg4omgIDApYCA9IHAuZGlmZi5ub3QwKSAlPiUgCiAgcGFuZG9jLnRhYmxlLnJldHVybihtaXNzaW5nID0gIuKAlCIsIAogICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJNZWRpYW4gZGlmZmVyZW5jZSBiZXR3ZWVuIGxpa2VsaWhvb2QgdG8gZG9uYXRlIGFjcm9zcyBzaW5nbGUgY29uZGl0aW9ucyB7I3RibDpsaWtlbGlob29kLXNpbmdsZS1kaWZmc30iKSAlVD4lCiAgY2F0KCkgJT4lIAogIGNhdChmaWxlID0gaGVyZSgib3V0cHV0IiwgInRhYmxlcyIsICJ0YmwtbGlrZWxpaG9vZC1zaW5nbGUtZGlmZnMubWQiKSkKYGBgCgpcCgoqKkNvbXBhcmUgbmVzdGVkIGNvbmRpdGlvbnMgKHdoYXQgd2UncmUgcmVhbGx5IG1vc3QgY29uY2VybmVkIGFib3V0KToqKgoKYGBge3IgcGxvdC1hbGwtbGlrZWx5LWRpZmZzLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQpwbG90X2RpZmZzX2xpa2VseV9hbGwgPC0gCiAgKHBsb3RfZGlmZnNfbGlrZWx5X2MgLyBwbG90X2RpZmZzX2xpa2VseV9jaSkgfCAKICBwbG90X2RpZmZzX2xpa2VseV9jaWYKCnBsb3RfZGlmZnNfbGlrZWx5X2FsbCArCiAgcGxvdF9hbm5vdGF0aW9uKHRpdGxlID0gIkRpZmZlcmVuY2VzIGluIGRvbmF0aW9uIGxpa2VsaWhvb2QgaW4gY29udHJvbCBhbmQgY3JhY2tkb3duIGdyb3VwcyxcbmNvbmRpdGlvbmVkIGJ5IG90aGVyIGV4cGVyaW1lbnRhbCBncm91cHMiLAogICAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICI5MCUgY3JlZGlibGUgaW50ZXJ2YWxzIHNob3duIGluIGJsYWNrLiBTb2xpZCB2ZXJ0aWNhbCBsaW5lID0gbWVkaWFuOyBkb3R0ZWQgdmVydGljYWwgbGluZSA9IDAiLAogICAgICAgICAgICAgICAgICB0YWdfbGV2ZWxzID0gIkEiLCB0aGVtZSA9IHRoZW1lX25nb3MoKSkKCihwbG90X2RpZmZzX2xpa2VseV9hbGwgKwogICAgcGxvdF9hbm5vdGF0aW9uKGNhcHRpb24gPSAiOTAlIGNyZWRpYmxlIGludGVydmFscyBzaG93biBpbiBibGFjay4gU29saWQgdmVydGljYWwgbGluZSA9IG1lZGlhbjsgZG90dGVkIHZlcnRpY2FsIGxpbmUgPSAwIiwKICAgICAgICAgICAgICAgICAgICB0YWdfbGV2ZWxzID0gIkEiLCB0aGVtZSA9IHRoZW1lX25nb3MoKSkpICVUPiUKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJsaWtlbGlob29kLWRpZmZzLnBkZiIpLAogICAgICAgICB3aWR0aCA9IDgsIGhlaWdodCA9IDUsIHVuaXRzID0gImluIiwgZGV2aWNlID0gY2Fpcm9fcGRmKSAlPiUKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJsaWtlbGlob29kLWRpZmZzLnBuZyIpLAogICAgICAgICB3aWR0aCA9IDgsIGhlaWdodCA9IDUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgpgYGB7ciB0YmwtYWxsLWxpa2VseS1kaWZmcywgcmVzdWx0cz0iYXNpcyJ9CmJpbmRfcm93cyhkaWZmc19jb2VmX2xpa2VseV9wYWlyc19kZXRhaWxfYywKICAgICAgICAgIGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9jaSwKICAgICAgICAgIGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9jaWYpICU+JSAKICBzZWxlY3QoSXNzdWUgPSBpc3N1ZSwgRnVuZGluZyA9IGZ1bmRpbmcsIAogICAgICAgICBg4oiGfm1lZGlhbn5gID0gbWVkaWFuLCAKICAgICAgICAgYCXiiIZ+bWVkaWFufmAgPSBtZWRpYW5fcGN0X2NoYW5nZSwKICAgICAgICAgYHAo4oiGID4gMClgID0gcC5ncmVhdGVyMCwgYHAo4oiGIDwgMClgID0gcC5sZXNzMCwgYHAo4oiGIOKJoCAwKWAgPSBwLmRpZmYubm90MCkgJT4lIAogIHBhbmRvYy50YWJsZS5yZXR1cm4obWlzc2luZyA9ICLigJQiLCAKICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAnTWVkaWFuIGRpZmZlcmVuY2UgYmV0d2VlbiBsaWtlbGlob29kIHRvIGRvbmF0ZSBpbiAiY3JhY2tkb3duIiAodHJlYXRtZW50KSBhbmQgImNyYWNrZG93biIgKGNvbnRyb2wpIGNvbmRpdGlvbnMgeyN0Ymw6bGlrZWxpaG9vZC1kaWZmc30nKSAlVD4lCiAgY2F0KCkgJT4lIAogIGNhdChmaWxlID0gaGVyZSgib3V0cHV0IiwgInRhYmxlcyIsICJ0YmwtbGlrZWxpaG9vZC1kaWZmcy5tZCIpKQpgYGAKCgojIFN1bW1hcnkgb2YgaHlwb3RoZXNlcwoKYGBge3IgaHlwb3RoZXNlcy1zdW1tYXJ5LWZpZ3VyZSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Ni41fQpoeXBvdGhlc2VzIDwtIHRyaWJibGUoCiAgfmR2LCB+aHlwb3RoZXNpcywgfnN1bW1hcnksCiAgIkxpa2VsaWhvb2QiLCAiSDFhOiBEb25vcnMgbW9yZSBsaWtlbHlcbnRvIGdpdmUgdG8gTkdPc1xuZmFjaW5nIGNyYWNrZG93biIsIGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9jLAogICJMaWtlbGlob29kIiwgIkgyYTogRG9ub3JzIG1vcmUgbGlrZWx5XG50byBnaXZlIHRvIGh1bWFuaXRhcmlhblxuTkdPcyBmYWNpbmcgY3JhY2tkb3duIiwgZGlmZnNfY29lZl9saWtlbHlfcGFpcnNfZGV0YWlsX2NpLAogICJMaWtlbGlob29kIiwgIkgzYTogRG9ub3JzIG1vcmUgbGlrZWx5XG50byBnaXZlIHRvIHByaXZhdGVseSBmdW5kZWRcbk5HT3MgZmFjaW5nIGNyYWNrZG93biIsIGRpZmZzX2NvZWZfbGlrZWx5X3BhaXJzX2RldGFpbF9jaWYsCiAgIkFtb3VudCIsICJIMWI6IERvbm9ycyBnaXZlIG1vcmUgXG50byBOR09zIGZhY2luZyBjcmFja2Rvd24iLCBkaWZmc19jb2VmX3BhaXJzX2RldGFpbF9jLAogICJBbW91bnQiLCAiSDJiOiBEb25vcnMgZ2l2ZSBtb3JlIFxudG8gaHVtYW5pdGFyaWFuIE5HT3NcbmZhY2luZyBjcmFja2Rvd24iLCBkaWZmc19jb2VmX3BhaXJzX2RldGFpbF9jaSwKICAiQW1vdW50IiwgIkgzYjogRG9ub3JzIGdpdmUgbW9yZSBcbnRvIHByaXZhdGVseSBmdW5kZWQgTkdPc1xuZmFjaW5nIGNyYWNrZG93biIsIGRpZmZzX2NvZWZfcGFpcnNfZGV0YWlsX2NpZgopCgpwbG90X2h5cG90aGVzZXMgPC0gaHlwb3RoZXNlcyAlPiUgCiAgdW5uZXN0KHN1bW1hcnkpICU+JSAKICBzZWxlY3QoLWRpZmZzX2NvZWZzKSAlPiUgCiAgbXV0YXRlKGNvbmRpdGlvbiA9IHBhc3RlMChpc3N1ZSwgIiArICIsIGZ1bmRpbmcpLAogICAgICAgICBjb25kaXRpb24gPSByZWNvZGUoY29uZGl0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBIdW1hbiByaWdodHMgKyBOQWAgPSAiSHVtYW4gcmlnaHRzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSArIE5BYCA9ICJIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTkEgKyBOQWAgPSAiQ3JhY2tkb3duIG9ubHkiKSkgJT4lIAogIG11dGF0ZShoeXBvdGhlc2lzX2N1c3RvbSA9IGNhc2Vfd2hlbigKICAgIC4kY29uZGl0aW9uID09ICJIdW1hbiByaWdodHMgKyBHb3Zlcm5tZW50IiB+IHBhc3RlKGh5cG90aGVzaXMsICJcbihnb3Zlcm5tZW50IGZ1bmRpbmcgY29uZGl0aW9uKSIpLAogICAgLiRjb25kaXRpb24gPT0gIkh1bWFuaXRhcmlhbiBhc3Npc3RhbmNlICsgR292ZXJubWVudCIgfiBwYXN0ZShoeXBvdGhlc2lzLCAiXG4oZ292ZXJubWVudCBmdW5kaW5nIGNvbmRpdGlvbikiKSwKICAgIC4kY29uZGl0aW9uID09ICJIdW1hbiByaWdodHMgKyBQcml2YXRlIiB+IHBhc3RlKGh5cG90aGVzaXMsICJcbihwcml2YXRlIGZ1bmRpbmcgY29uZGl0aW9uKSIpLAogICAgLiRjb25kaXRpb24gPT0gIkh1bWFuaXRhcmlhbiBhc3Npc3RhbmNlICsgUHJpdmF0ZSIgfiBwYXN0ZShoeXBvdGhlc2lzLCAiXG4ocHJpdmF0ZSBmdW5kaW5nIGNvbmRpdGlvbikiKSwKICAgIFRSVUUgfiBoeXBvdGhlc2lzCiAgKSkgJT4lIAogIG11dGF0ZShpc3N1ZSA9IGZjdF9yZXYoZmN0X2V4cGxpY2l0X25hKGlzc3VlLCBuYV9sZXZlbCA9ICJDcmFja2Rvd24gb25seSIpKSwKICAgICAgICAgaHlwb3RoZXNpc19mYWNldCA9IGlmZWxzZShzdHJfZGV0ZWN0KGh5cG90aGVzaXMsICJIMyIpLCAyLCAxKSwKICAgICAgICAgcF9sYWIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgLiRkdiA9PSAiTGlrZWxpaG9vZCIgfiBzcHJpbnRmKCLiiIYgPSAlLjJmOyBwKOKIhiDiiaAgMCkgPSAlLjJmIiwgLiRtZWRpYW4sIC4kcC5kaWZmLm5vdDApLAogICAgICAgICAgIC4kZHYgPT0gIkFtb3VudCIgfiBzcHJpbnRmKCLiiIYgPSAkJS4yZjsgcCjiiIYg4omgIDApID0gJS4yZiIsIC4kbWVkaWFuLCAuJHAuZGlmZi5ub3QwKQogICAgICAgICApKQoKcGxvdF9oeXBvdGhlc2VzX2xpa2VseSA8LSBmaWx0ZXIocGxvdF9oeXBvdGhlc2VzLCBkdiA9PSAiTGlrZWxpaG9vZCIpCnBsb3RfaHlwb3RoZXNlc19hbW91bnQgPC0gZmlsdGVyKHBsb3RfaHlwb3RoZXNlcywgZHYgPT0gIkFtb3VudCIpCgpwbG90X3N1bW1hcnlfbGlrZWx5IDwtIGdncGxvdChwbG90X2h5cG90aGVzZXNfbGlrZWx5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBtZWRpYW4sIHkgPSBmY3RfcmV2KGh5cG90aGVzaXNfY3VzdG9tKSkpICsKICBnZW9tX3BvaW50cmFuZ2VoKGFlcyh4bWluID0gcTUsIHhtYXggPSBxOTUsIGNvbG9yID0gaXNzdWUpLAogICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZXYoaGVpZ2h0ID0gMC41KSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIHNpemUgPSAwLjI1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9sYWJlbChkYXRhID0gZmlsdGVyKHBsb3RfaHlwb3RoZXNlc19saWtlbHksIGlzc3VlID09ICJIdW1hbiByaWdodHMiKSwgCiAgICAgICAgICAgICBhZXMobGFiZWwgPSBwX2xhYiwgY29sb3IgPSBpc3N1ZSksIHNpemUgPSAzLCBudWRnZV95ID0gMC4zNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fbGFiZWwoZGF0YSA9IGZpbHRlcihwbG90X2h5cG90aGVzZXNfbGlrZWx5LCBpc3N1ZSA9PSAiSHVtYW5pdGFyaWFuIGFzc2lzdGFuY2UiKSwgCiAgICAgICAgICAgICBhZXMobGFiZWwgPSBwX2xhYiwgY29sb3IgPSBpc3N1ZSksIHNpemUgPSAzLCBudWRnZV95ID0gLTAuMzUsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX2xhYmVsKGRhdGEgPSBmaWx0ZXIocGxvdF9oeXBvdGhlc2VzX2xpa2VseSwgaXNzdWUgPT0gIkNyYWNrZG93biBvbmx5IiksIAogICAgICAgICAgICAgYWVzKGxhYmVsID0gcF9sYWIsIGNvbG9yID0gaXNzdWUpLCBzaXplID0gMywgbnVkZ2VfeSA9IDAuMiwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24ocGFzdGUoIkVmZmVjdCBvZiBjcmFja2Rvd246IChDcmFja2Rvd24gLSBObyBjcmFja2Rvd24pIlsibWVkaWFuIl0pKSwKICAgICAgIHkgPSBOVUxMLCBzdWJ0aXRsZSA9ICJMaWtlbGlob29kIG9mIGRvbmF0aW9uIikgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG5nb19jb2xzKCJkYXJrIGdyZXkiLCAiYmx1ZSIsICJyZWQiLCBuYW1lID0gRkFMU0UpLCBuYW1lID0gTlVMTCkgKwogIGNvb3JkX2NhcnRlc2lhbihjbGlwID0gIm9mZiIpICsKICB0aGVtZV9uZ29zKCkgKyAKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuMiksIGZhY2UgPSAicGxhaW4iLCAjaGp1c3QgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9ICJFbmNvZGUgU2FucyBDb25kZW5zZWQgTWVkaXVtIikpICsKICBmYWNldF93cmFwKH4gaHlwb3RoZXNpc19mYWNldCwgbnJvdyA9IDEsIHNjYWxlcyA9ICJmcmVlIikKCnBsb3Rfc3VtbWFyeV9hbW91bnQgPC0gZ2dwbG90KHBsb3RfaHlwb3RoZXNlc19hbW91bnQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IG1lZGlhbiwgeSA9IGZjdF9yZXYoaHlwb3RoZXNpc19jdXN0b20pKSkgKwogIGdlb21fcG9pbnRyYW5nZWgoYWVzKHhtaW4gPSBxNSwgeG1heCA9IHE5NSwgY29sb3IgPSBpc3N1ZSksCiAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdldihoZWlnaHQgPSAwLjUpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgc2l6ZSA9IDAuMjUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xhYmVsKGRhdGEgPSBmaWx0ZXIocGxvdF9oeXBvdGhlc2VzX2Ftb3VudCwgaXNzdWUgPT0gIkh1bWFuIHJpZ2h0cyIpLCAKICAgICAgICAgICAgIGFlcyhsYWJlbCA9IHBfbGFiLCBjb2xvciA9IGlzc3VlKSwgc2l6ZSA9IDMsIG51ZGdlX3kgPSAwLjM1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZ2VvbV9sYWJlbChkYXRhID0gZmlsdGVyKHBsb3RfaHlwb3RoZXNlc19hbW91bnQsIGlzc3VlID09ICJIdW1hbml0YXJpYW4gYXNzaXN0YW5jZSIpLCAKICAgICAgICAgICAgIGFlcyhsYWJlbCA9IHBfbGFiLCBjb2xvciA9IGlzc3VlKSwgc2l6ZSA9IDMsIG51ZGdlX3kgPSAtMC4zNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fbGFiZWwoZGF0YSA9IGZpbHRlcihwbG90X2h5cG90aGVzZXNfYW1vdW50LCBpc3N1ZSA9PSAiQ3JhY2tkb3duIG9ubHkiKSwgCiAgICAgICAgICAgICBhZXMobGFiZWwgPSBwX2xhYiwgY29sb3IgPSBpc3N1ZSksIHNpemUgPSAzLCBudWRnZV95ID0gMC4yLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgbGFicyh4ID0gZXhwcmVzc2lvbihwYXN0ZSgiRWZmZWN0IG9mIGNyYWNrZG93bjogKENyYWNrZG93biAtIE5vIGNyYWNrZG93bikiWyJtZWRpYW4iXSkpLAogICAgICAgeSA9IE5VTEwsIHN1YnRpdGxlID0gIkFtb3VudCBkb25hdGVkIiwKICAgICAgIGNhcHRpb24gPSAiOTAlIGNyZWRpYmxlIGludGVydmFscyBzaG93biBhcm91bmQgZWFjaCBwb2ludCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyX2Zvcm1hdCgpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG5nb19jb2xzKCJkYXJrIGdyZXkiLCAiYmx1ZSIsICJyZWQiLCBuYW1lID0gRkFMU0UpLCBndWlkZSA9IEZBTFNFKSArCiAgY29vcmRfY2FydGVzaWFuKGNsaXAgPSAib2ZmIikgKwogIHRoZW1lX25nb3MoKSArIAogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMS4yKSwgZmFjZSA9ICJwbGFpbiIsICNoanVzdCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gIkVuY29kZSBTYW5zIENvbmRlbnNlZCBNZWRpdW0iKSkgKwogIGZhY2V0X3dyYXAofiBoeXBvdGhlc2lzX2ZhY2V0LCBucm93ID0gMSwgc2NhbGVzID0gImZyZWUiKQoKcGxvdF9zdW1tYXJ5X2RpZmZzIDwtIHBsb3Rfc3VtbWFyeV9saWtlbHkgKyBwbG90X3N1bW1hcnlfYW1vdW50ICsKICBwbG90X2xheW91dChuY29sID0gMSkKCnBsb3Rfc3VtbWFyeV9kaWZmcwoKcGxvdF9zdW1tYXJ5X2RpZmZzICVUPiUKICBnZ3NhdmUoLiwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXQiLCAiZmlndXJlcyIsICJzdW1tYXJ5LWRpZmZzLnBkZiIpLAogICAgICAgICB3aWR0aCA9IDgsIGhlaWdodCA9IDYuNSwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSBjYWlyb19wZGYpICU+JQogIGdnc2F2ZSguLCBmaWxlbmFtZSA9IGhlcmUoIm91dHB1dCIsICJmaWd1cmVzIiwgInN1bW1hcnktZGlmZnMucG5nIiksCiAgICAgICAgIHdpZHRoID0gOCwgaGVpZ2h0ID0gNi41LCB1bml0cyA9ICJpbiIsIHR5cGUgPSAiY2Fpcm8iLCBkcGkgPSAzMDApCmBgYAoKCiMgT3JpZ2luYWwgY29tcHV0aW5nIGVudmlyb25tZW50Cgo8YnV0dG9uIGRhdGEtdG9nZ2xlPSJjb2xsYXBzZSIgZGF0YS10YXJnZXQ9IiNzZXNzaW9uaW5mbyIgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSBidG4tbWQgYnRuLWluZm8iPkhlcmUncyB3aGF0IHdlIHVzZWQgdGhlIGxhc3QgdGltZSB3ZSBidWlsdCB0aGlzIHBhZ2U8L2J1dHRvbj4KCjxkaXYgaWQ9InNlc3Npb25pbmZvIiBjbGFzcz0iY29sbGFwc2UiPgoKYGBge3Igc2hvdy1zZXNzaW9uLWluZm8sIGVjaG89VFJVRX0Kd3JpdGVMaW5lcyhyZWFkTGluZXMoZmlsZS5wYXRoKFN5cy5nZXRlbnYoIkhPTUUiKSwgIi5SL01ha2V2YXJzIikpKQoKZGV2dG9vbHM6OnNlc3Npb25faW5mbygpCmBgYAoKPC9kaXY+IAo=