df.country.aid <- readRDS(here("Data", "data_clean",
                               "df_country_aid_no_imputation.rds"))

df.country.aid.impute <- readRDS(here("Data", "data_clean",
                                      "df_country_aid_imputation.rds"))

df.country.aid.impute.m10 <- readRDS(here("Data", "data_clean",
                                          "df_country_aid_imputation_m10.rds"))

dcjw.questions.clean <- read_csv(here("Data", "data_manual", "dcjw_questions.csv"))
dcjw.responses.clean <- read_csv(here("Data", "data_manual", "dcjw_responses.csv"))

# Load clean coefficient names and append "within" and "between" to them,
# resulting in a giant table of possible coefficient names
coef.names <- read_csv(here("Data", "data_manual", "coef_names.csv"))

coef.names.within <- coef.names %>%
  mutate(term = paste0(term, "_within"),
         term_plot = paste0(term_clean, "\n(within)"),
         term_plot_short = term_clean,
         term_clean = paste0(term_clean, "~within~"))

coef.names.between <- coef.names %>%
  mutate(term = paste0(term, "_between"),
         term_plot = paste0(term_clean, "\n(between)"),
         term_plot_short = paste0(term_clean, ""),
         term_clean = paste0(term_clean, "~between~"))

coef.names.all <- bind_rows(coef.names, coef.names.within, coef.names.between) %>%
  mutate_at(vars(term_plot, term_plot_short),
            funs(ifelse(is.na(.), term_clean, .))) %>% 
  mutate(term_plot_short = recode(term_plot_short,
                                  `Civil society reg. env. (CSRE)` = "CSRE"))

# Load clean model names
model.names <- read_csv(here("Data", "data_manual", "model_names.csv"))


# Combine original data and imputed data so calculations can happen at the same time
df.country.aid.both <- bind_rows(df.country.aid, df.country.aid.impute)

# Combine m=10 imputed data too since we use it in some robustness checks.
# Imputations 6-10 are later removed
df.country.aid.all <- bind_rows(df.country.aid, df.country.aid.impute.m10)

# All the missing values have been taken care of, but final years for leaded
# variables *are* still missing (i.e. there's no aid data for 2014, so
# total.oda_log_next_year will be NA in 2013). For this fancy random effects
# regression to work, the demeaned variables have to be based on the means of
# all rows included in the regression, so they can't include rows that are
# dropped because of missingness. This means we have to make separate demeaned
# datasets for *_after_2 and *_after_5, but ¯\_(ツ)_/¯
df.country.aid.demean.next_year.all <- df.country.aid.all %>%
  filter(!is.na(total.oda_log_next_year)) %>%
  group_by(m, cowcode) %>%
  mutate_at(vars(barriers.total, advocacy, entry, funding, 
                 polity, gdp.capita_log, gdp.capita, trade.pct.gdp, corruption, csre,
                 total.oda_log),
            funs(between = mean(., na.rm = TRUE),  # meaned
                 within = . - mean(., na.rm = TRUE))) %>%  # demeaned
  ungroup()

df.country.aid.us.demean.next_year.all <- df.country.aid.all %>%
  filter(!is.na(prop.ngo.dom_logit_next_year)) %>%
  filter(year > 1999) %>%
  group_by(m, cowcode) %>%
  mutate_at(vars(barriers.total, advocacy, entry, funding, 
                 polity, gdp.capita_log, gdp.capita, trade.pct.gdp, corruption, csre,
                 total.oda_log),
            funs(between = mean(., na.rm = TRUE),  # meaned
                 within = . - mean(., na.rm = TRUE))) %>%  # demeaned
  ungroup()

# Divide demeaned data into separate data frames: original, imputed (m=5), and imputed (m=10)
df.country.aid.demean.next_year.both <- 
  filter(df.country.aid.demean.next_year.all, !(m %in% paste0("imp", 6:10)))

df.country.aid.demean.next_year <- 
  filter(df.country.aid.demean.next_year.all, m == "original")

df.country.aid.us.demean.next_year.both <- 
  filter(df.country.aid.us.demean.next_year.all, !(m %in% paste0("imp", 6:10)))

df.country.aid.us.demean.next_year <- 
  filter(df.country.aid.us.demean.next_year.all, m == "original")

df.country.aid.demean.next_year.impute <- 
  filter(df.country.aid.demean.next_year.all, 
         m != "original", !(m %in% paste0("imp", 6:10)))

df.country.aid.demean.next_year.impute.m10 <- 
  filter(df.country.aid.demean.next_year.all, m != "original")

# Demean data with total.oda_log leaded by 2 years and 5 years
# After 2 years
df.country.aid.demean.after_2.both <- df.country.aid.both %>%
  filter(!is.na(total.oda_log_after_2)) %>%
  group_by(m, cowcode) %>%
  mutate_at(vars(barriers.total, advocacy, entry, funding, 
                 polity, gdp.capita_log, gdp.capita, trade.pct.gdp, corruption, csre,
                 total.oda_log),
            funs(between = mean(., na.rm = TRUE),  # meaned
                 within = . - mean(., na.rm = TRUE))) %>%  # demeaned
  ungroup()

df.country.aid.demean.after_2 <- 
  filter(df.country.aid.demean.after_2.both, m == "original")

df.country.aid.demean.after_2.impute <- 
  filter(df.country.aid.demean.after_2.both, m != "original")

# After 5 years
df.country.aid.demean.after_5.both <- df.country.aid.both %>%
  filter(!is.na(total.oda_log_after_5)) %>%
  group_by(m, cowcode) %>%
  mutate_at(vars(barriers.total, advocacy, entry, funding, 
                 polity, gdp.capita_log, gdp.capita, trade.pct.gdp, corruption, csre,
                 total.oda_log),
            funs(between = mean(., na.rm = TRUE),  # meaned
                 within = . - mean(., na.rm = TRUE))) %>%  # demeaned
  ungroup()

df.country.aid.demean.after_5 <- 
  filter(df.country.aid.demean.after_5.both, m == "original")

df.country.aid.demean.after_5.impute <- 
  filter(df.country.aid.demean.after_5.both, m != "original")
stars <- function(p) {
  out <- symnum(p, cutpoints = c(0, 0.01, 0.05, 0.1, 1),
                symbols = c("***", "**", "*", ""))
  as.character(out)
}

fixed.digits <- function(x, digits = 2) {
  formatC(x, digits = digits, format = "f")
}

# Use 2 significant digits only on the decimal part of the number, ignoring the
# integer part. See my question here: http://stackoverflow.com/q/43050903/120898
# fixed.digits <- function(x, digits = 2) {
#   as.character(floor(x) + signif(x %% 1, digits))
# }

# Inverse logit, with the ability to account for adjustments
# via http://stackoverflow.com/a/23845527/120898
inv.logit <- function(f, a) {
  a <- (1 - 2 * a)
  (a * (1 + exp(f)) + (exp(f) - 1)) / (2 * a * (1 + exp(f)))
}

# Take apart the pieces of a random effects formula and rebuild it
build.formula <- function(DV, IVs) {
  terms.all <- attr(terms(IVs), "term.labels")
  terms.fixed <- terms.all[!stringr::str_detect(terms.all, "\\|")]
  terms.rand <- sapply(findbars(formula(IVs)),function(x) paste0("(", deparse(x), ")"))
  
  reformulate(c(terms.fixed, terms.rand), response = DV)
}

get.rhs <- function(x) rhs.vars(x) %>% str_replace_all("1 \\| ", "")
get.lhs <- function(x) lhs.vars(x)
is_scaled <- function(x) "scaled:scale" %in% names(attributes(x))
get_scale <- function(x) attr(x, "scaled:scale")


# Meld a bunch of imputed models
meld.imputed.models <- function(model.data, exponentiate = FALSE) {
  models.df <- model.data$glance[[1]]$df.residual
  
  models.tidy <- model.data %>%
    select(tidy) %>%
    unnest(.id = "imputation")
  
  just.estimates <- models.tidy %>% 
    filter(group == "fixed") %>%
    select(imputation, term, estimate) %>%
    spread(term, estimate) %>%
    select(-imputation)
  
  just.ses <- models.tidy %>%
    filter(group == "fixed") %>%
    select(imputation, term, std.error) %>%
    spread(term, std.error) %>%
    select(-imputation)
  
  # If no imputed data was passed in, use the actual estimates and SEs
  if (nrow(just.estimates) > 1) {
    melded <- Amelia::mi.meld(just.estimates, just.ses)
  } else {
    melded <- list(q.mi = just.estimates, se.mi = just.ses)
  }
  
  melded.tidy <- as.data.frame(cbind(t(melded$q.mi), 
                                     t(melded$se.mi))) %>%
    magrittr::set_colnames(c("estimate", "std.error")) %>%
    mutate(term = rownames(.)) %>%
    select(term, everything()) %>%
    mutate(statistic = estimate / std.error,
           conf.low = estimate + std.error * qt(0.025, models.df),
           conf.high = estimate + std.error * qt(0.975, models.df),
           p.value = 2 * pt(abs(statistic), models.df, lower.tail = FALSE),
           stars = stars(p.value))
  
  if (exponentiate) {
    # Convert SEs to odds ratios. This isn't entirely 100% accurate, since the
    # melded coefficient variances (i.e. diag(vcov(.))) are just averaged, not
    # melded with Amelia's fancy mi.meld(), but ¯\_(ツ)_/¯
    #
    # https://www.andrewheiss.com/blog/2016/04/25/convert-logistic-regression-standard-errors-to-odds-ratios-with-r/
    fixed.coefs.var <- model.data %>%
      mutate(var.diag = model %>% map(~ diag(vcov(.)))) %>%
      select(var.diag, model) %>% unnest(var.diag)
    
    just.var <- models.tidy %>%
      filter(group == "fixed") %>%
      select(imputation, term) %>%
      bind_cols(fixed.coefs.var) %>%
      group_by(term) %>%
      summarise(var.diag = mean(var.diag))
    
    melded.tidy <- melded.tidy %>%
      left_join(just.var, by = "term") %>%
      mutate(or = exp(estimate),
             or.se = sqrt(or^2 * var.diag),
             or.upper = or + (qnorm(0.975) * or.se),
             or.lower = or + (qnorm(0.025) * or.se))
  }
  
  melded.tidy
}

# Expects a data frame with a column named tidy.melded and a row for model
# names. Term names are based on the first model in the data column for each
# row, and are filtered through stargazer to get the correct row order.
stargazer.fake <- function(df, caption = NULL, note = NULL, exponentiate = FALSE) {
  # Create a blank row with a bolded row name
  header.row <- function(header) {
    data_frame(term = paste0("**", header, "**"), 
               models = df$model.name, value = "") %>%
      spread(models, value)
  }
  
  note.row <- function(note) {
    crossing(term = note,
             models = df$model.name, value = "") %>%
      spread(models, value) %>%
      # Sort based on original note order
      slice(match(note, term))
  }
  
  coef.order.models <- df %>%
    # Select just the first row of each model
    unnest(data) %>%
    # Sometimes there are duplicate column names
    # magrittr::set_colnames(make.unique(colnames(.))) %>%
    # Keep order of model.name
    mutate(model.name = ordered(fct_inorder(model.name))) %>%
    group_by(model.name) %>%
    slice(1) %>% ungroup() %>%
    select(model) %>% as.list()
  
  # Use stargazer to get the coefficient order. I tried recreating stargazer's
  # coefficient ordering algorithm but it's way too complicated. So instead, we
  # cheat and let stargazer do the heavy lifting, save the output to a string,
  # and then extract the coefficient names with str_extract. Super super hacky,
  # but it works.
  #
  # See http://stackoverflow.com/a/41801861/120898
  capture.output({
    stargazer.coefs <- stargazer::stargazer(coef.order.models, 
                                            type = "text", table.layout = "t")
  }, file = "/dev/null")
  
  coef.order <- setdiff(stringr::str_extract(stargazer.coefs, "^[\\w\\.]*"), c(""))
  
  # Fixed parts
  fixed.tidy <- df %>%
    unnest(tidy.melded)
  
  if (exponentiate) {
    fixed.coefs <- fixed.tidy %>%
      mutate(fancy = paste0(fixed.digits(or, 3),
                            stars, "\\ \n(",
                            fixed.digits(or.se, 3),
                            ")"))
  } else {
    fixed.coefs <- fixed.tidy %>%
      mutate(fancy = paste0(fixed.digits(estimate, 3),
                            stars, "\\ \n(",
                            fixed.digits(std.error, 3),
                            ")"))
  }
  
  fixed.coefs <- fixed.coefs %>%
    select(model.name, term, fancy) %>%
    spread(model.name, fancy, fill = "") %>%
    # Clean up term names
    mutate(term = stringr::str_replace(term, "TRUE$|FALSE$", ""),
           term = recode(term, `(Intercept)` = "Constant")) %>%
    # Use stargazer's coefficient order
    mutate(term = factor(term, levels = coef.order, ordered = TRUE)) %>%
    arrange(term) %>%
    mutate(term = as.character(term)) %>%
    left_join(coef.names.all, by = "term") %>%
    mutate(term_clean = ifelse(term == "Constant", "Constant", term_clean)) %>%
    select(-term) %>% rename(term = term_clean) %>%
    select_(.dots = c("term", df$model.name))
  
  # Random parts
  random.coef.order.raw <- df %>%
    unnest(data) %>%
    # unnest(data) %>% magrittr::set_colnames(make.unique(colnames(.))) %>%
    select(model.name, model) %>%
    mutate(ranef = model %>% map(~ as.data.frame(VarCorr(.)))) %>%
    unnest(ranef)
  random.coef.order <- c(setdiff(unique(random.coef.order.raw$grp), "Residual"), "Residual")
  
  random.coefs <- df %>%
    unnest(data) %>%
    unnest(tidy) %>%
    filter(group != "fixed") %>%
    rename(term.raw = term, term = group) %>%
    group_by(model.name, term) %>%
    summarise(avg.random.sd = mean(estimate),
              sd.random.sd = sd(estimate)) %>%
    mutate(fancy = paste0(fixed.digits(avg.random.sd, 3),
                          "\\ \n(",
                          ifelse(is.na(sd.random.sd), "NA", fixed.digits(sd.random.sd, 3)),
                          ")")) %>%
    select(model.name, term, fancy) %>%
    spread(model.name, fancy, fill = "") %>%
    mutate(term = factor(term, levels = random.coef.order, ordered = TRUE)) %>%
    arrange(term) %>% mutate(term = as.character(term)) %>%
    left_join(coef.names.all, by = "term") %>%
    mutate(term_clean = ifelse(term == "Residual", 
                               "Residual random error ($\\sigma$)", term_clean)) %>%
    select(-term) %>% select(term = term_clean, everything())
  
  # Create the bottom half of the table
  # Calculate the average log likelihood for all imputed models
  avg.loglik <- df %>%
    unnest(data) %>% unnest(glance) %>%
    group_by(model.name) %>%
    summarise(avg.loglik = as.character(round(mean(logLik), 2))) %>%
    mutate(term = "Log likelihood (mean)") %>%
    spread(model.name, avg.loglik)
  
  # Imputation frames
  n.obs <- df %>%
    unnest(data) %>%
    mutate(n = model %>% map_int(~ nrow(.@frame))) %>%
    select(model.name, n) %>%
    group_by(model.name) %>% slice(1) %>% ungroup() %>%
    mutate(term = "Observations",
           n = scales::comma(n)) %>%
    spread(model.name, n)
  
  n.m <- df %>%
    mutate(m.new = data %>% map_int(~ nrow(.))) %>%
    select(model.name, m.new) %>% 
    mutate(m.new = ifelse(m.new == 1, 0, m.new),
           m.new = as.character(m.new)) %>%
    mutate(term = "Imputed datasets (*m*)") %>%
    spread(model.name, m.new)
  
  bottom.details <- bind_rows(n.obs, avg.loglik, n.m)
  
  if (exponentiate) {
    fixed.title <- "Fixed part (odds ratios)"
    random.title <- "Random part (original coefficients)"
  } else {
    fixed.title <- "Fixed part"
    random.title <- "Random part"
  }
  
  if (!is.null(note)) {
    notes <- bind_rows(header.row("Notes"), note.row(note))
  } else {
    notes <- NULL
  }
  
  nice.top.bottom <- bind_rows(header.row(fixed.title), fixed.coefs, 
                               header.row(random.title), random.coefs,
                               header.row("Model details"), bottom.details,
                               notes) %>%
    select_(.dots = c("term", df$model.name))
  
  # Make column names (1), (2), etc.
  # TODO: Allow for custom column names
  colnames(nice.top.bottom) <- c(" ", paste0("(", 1:length(df$model.name), ")"))
  
  # All columns are centered except the first
  # TODO: MAYBE: Let this be user configurable
  table.align <- paste0(c("l", rep("c", length(df$model.name))), collapse = "")
  
  pandoc.table.return(nice.top.bottom, keep.line.breaks = TRUE,
                      justify = table.align, caption = caption)
}

H1: Donors reduce aid in response to legislation

H1: In response to restrictive NGO legislation, bilateral, multilateral, and private donors may reduce their aid to repressive countries.

\[ln( \text{ODA}_{\text{OECD}} )_{i, t+1} = \text{NGO legislation}_{it} + \text{controls}_{it}\]

Our dependent variable for this hypothesis is the log of ODA (constant 2011 dollars), leaded by one year so we don’t have to lag every other independent variable. As a robustness check, we also include models with log ODA leaded by 2 years and 5 years to account the implementation period following the passage of a law.

We look at NGO legislation in a few different ways:

  • barriers.total: Number of anti-NGO legal barriers in a country-year
  • advocacy + entry + funding: Number of anti-NGO legal barriers by type of barrier
  • csre: Civil society regulatory environment index (CSRE), ranging from roughly -4 to 4 (higher values = better civil society regulations)

MCMC diagnostics

Check fit

We use one of the imputed models (mod.h1.barriers.total) to check for fit and convergence.

How well does the posterior predictive distribution fit the observed outcome? Not great, but not perfectly. The actual distribution is bimodal, with a bunch of zeros, and the model gets the two peaks, but they’re shallow. We can live with it, though.

Check convergence

What about chain convergence? These should look like tops if everything converges, with no observations at 0 in the mean Metropolis-Hastings aceptance panel.

Merging MCMC chains

Merging the MCMC chains is relatively easy, but then working with the 20,000 rows of simulations is trickier, since merging makes the model a data_frame intead of a stanreg object, meaning all the convenience funcions like posterior_predict() don’t work anymore. That means lots of math. Ugh.

So instead, we do two things. We calculate the posterior median and MD by just merging all the MCMC chains from all imputations. Becuase posterior_predict() doesn’t work on merged chains like this, we run posterior_predict() on each imputation and then take the mean of each imputation’s credible intervals. This should be okay—taking the median of medians (or mean of means) will yield the same value if the group sizes are the same (thus avoiding Simpson’s Paradox). Like this:

## [1] 4.5
## [1] 4.5

If it’s a little off, it should be okay—it’ll be off by an order of 0.001ish.

Results

Coefficients

vars.to.plot <- c("barriers.total_within", "barriers.total_between",
                  "advocacy_within", "advocacy_between", 
                  "entry_within", "entry_between", 
                  "funding_within", "funding_between",
                  "csre_within", "csre_between")

mods.h1.melded <- bayes.meld(mods.h1.next_year.bayes,
                             vars.to.plot)$melded.summary

plot.data <- mods.h1.melded %>%
  left_join(coef.names.all, by = "term") %>%
  left_join(model.names, by = c("model.name" = "model")) %>% 
  mutate(coef.type = case_when(
    str_detect(term, "_within") ~ "Within",
    str_detect(term, "_between") ~ "Between",
  )) %>% 
  mutate(term = factor(term, levels = vars.to.plot, ordered = TRUE)) %>%
  arrange(desc(term)) %>%
  mutate(term_plot_short = fct_inorder(term_plot_short, ordered = TRUE)) %>%
  mutate(coef.type = factor(coef.type, levels = c("Within", "Between"),
                            ordered = TRUE)) %>%
  mutate(model_clean = factor(model_clean, levels = rev(unique(model_clean)), ordered = TRUE))

fig.coefs.h1 <- ggplot(plot.data, aes(x = med, y = term_plot_short, 
                                      xmin = `2.5%`, xmax = `97.5%`, colour = model_clean)) +
  geom_vline(xintercept = 0, colour = "black", size = 0.5) + 
  geom_pointrangeh(size = 0.5, fatten = 3) +
  labs(x = "Posterior median change in log ODA in following year", y = NULL) +
  scale_colour_manual(values = model.colors, name = NULL) +
  expand_limits(x = c(-2, 1)) +
  guides(color = guide_legend(override.aes = list(size = 0.25))) +
  theme_donors() + 
  theme(legend.justification = "left",
        legend.box.margin = margin(l = -0.75, t = -0.5, unit = "lines"),
        axis.title.x = element_text(hjust = 0)) +
  facet_wrap(~ coef.type, scales = "free", ncol = 2)
fig.coefs.h1

Complete results in a table

The effect of anti-NGO legislation on OECD overseas development assistance (ODA) in the following year (H1), full models. Each cell contains the parameter’s posterior median, the 95% credible interval, and the probability that the parameter is greater than zero (in italics). {#tbl:h1-coefs}
(1) (2) (3)
Fixed part
Total legal barrierswithin -0.06
(-0.17, 0.05); 0.15
Total legal barriersbetween -0.05
(-0.13, 0.02); 0.09
Barriers to advocacywithin -0.43
(-0.92, 0.05); 0.04
Barriers to advocacybetween -0.09
(-0.41, 0.22); 0.28
Barriers to entrywithin 0.10
(-0.13, 0.34); 0.79
Barriers to entrybetween 0.12
(-0.02, 0.26); 0.96
Barriers to fundingwithin -0.03
(-0.30, 0.25); 0.42
Barriers to fundingbetween -0.17
(-0.31, -0.03); 0.01
Civil society reg. env. (CSRE)within -0.02
(-0.09, 0.06); 0.33
Civil society reg. env. (CSRE)between 0.06
(-0.01, 0.13); 0.95
Polity IV (0–10)within -0.06
(-0.11, -0.00); 0.02
-0.06
(-0.12, -0.00); 0.02
-0.04
(-0.11, 0.03); 0.14
Polity IV (0–10)between 0.01
(-0.03, 0.05); 0.69
0.01
(-0.04, 0.05); 0.60
-0.02
(-0.08, 0.04); 0.27
GDP per capita (log)within -0.41
(-0.75, -0.14); 0.01
-0.42
(-0.75, -0.16); 0.01
-0.42
(-0.76, -0.15); 0.01
GDP per capita (log)between -0.18
(-0.26, -0.10); 0.00
-0.17
(-0.25, -0.09); 0.00
-0.18
(-0.26, -0.10); 0.00
Trade as % of GDPwithin -0.00
(-0.01, 0.00); 0.04
-0.00
(-0.01, 0.00); 0.04
-0.00
(-0.01, 0.00); 0.04
Trade as % of GDPbetween -0.00
(-0.00, 0.00); 0.05
-0.00
(-0.00, 0.00); 0.05
-0.00
(-0.00, 0.00); 0.08
Corruptionwithin 0.05
(-0.04, 0.14); 0.88
0.05
(-0.04, 0.14); 0.89
0.05
(-0.04, 0.14); 0.89
Corruptionbetween 0.05
(0.00, 0.10); 0.98
0.05
(0.00, 0.09); 0.98
0.05
(0.01, 0.10); 0.99
Total aid in present year (log) 0.87
(0.85, 0.88); 1.00
0.86
(0.85, 0.88); 1.00
0.87
(0.85, 0.88); 1.00
Internal conflict in last 5 years 0.08
(-0.12, 0.28); 0.78
0.07
(-0.13, 0.27); 0.75
0.11
(-0.09, 0.31); 0.86
Natural disasters 0.04
(0.01, 0.06); 0.99
0.03
(0.01, 0.06); 0.99
0.03
(0.01, 0.06); 0.99
After 1989 0.58
(0.26, 0.88); 1.00
0.60
(0.30, 0.90); 1.00
0.56
(0.23, 0.86); 1.00
Constant 3.17
(2.26, 4.07); 1.00
3.07
(2.18, 3.95); 1.00
3.15
(2.26, 4.03); 1.00
Random part
Within-country variability 0.09 0.09 0.08
Within-year variability 0.26 0.26 0.28
Residual random error 2.69 2.69 2.69
Model details
Imputed datasets (m) 5 5 5
N 4480 4480 4480
Posterior sample size 4000 4000 4000
Notes
Dependent variable log transformed.

Complete results (nonimputed)

(1) (2) (3)
Total legal barriers~within~ 0.008             
(-0.095, 0.112)            
Total legal barriers~between~ -0.004             
(-0.097, 0.093)            
Barriers to advocacy~within~       -0.143       
      (-0.579, 0.300)      
Barriers to advocacy~between~       -0.073       
      (-0.493, 0.342)      
Barriers to entry~within~       0.221       
      (0.008, 0.440)      
Barriers to entry~between~       0.009       
      (-0.175, 0.187)      
Barriers to funding~within~       -0.117       
      (-0.371, 0.130)      
Barriers to funding~between~       0.012       
      (-0.184, 0.213)      
Civil society reg. env. (CSRE)~within~             0.117 
            (0.039, 0.198)
Civil society reg. env. (CSRE)~between~             -0.015 
            (-0.110, 0.080)
Polity IV (0–10)~within~ 0.056  0.053  -0.016 
(0.002, 0.109) (0.001, 0.104) (-0.086, 0.054)
Polity IV (0–10)~between~ 0.045  0.046  0.059 
(-0.005, 0.095) (-0.007, 0.095) (-0.027, 0.139)
GDP per capita (log)~within~ -0.290  -0.273  -0.277 
(-0.621, 0.033) (-0.591, 0.046) (-0.600, 0.048)
GDP per capita (log)~between~ -0.273  -0.272  -0.275 
(-0.376, -0.171) (-0.373, -0.169) (-0.375, -0.176)
Trade as % of GDP~within~ -0.004  -0.003  -0.004 
(-0.007, 0.000) (-0.007, 0.000) (-0.008, 0.000)
Trade as % of GDP~between~ -0.002  -0.002  -0.002 
(-0.005, 0.001) (-0.005, 0.001) (-0.005, 0.000)
Corruption~within~ 0.144  0.146  0.147 
(0.060, 0.231) (0.057, 0.232) (0.061, 0.232)
Corruption~between~ 0.122  0.123  0.125 
(0.065, 0.181) (0.065, 0.180) (0.070, 0.183)
Total aid in present year (log) 0.745  0.744  0.739 
(0.723, 0.768) (0.722, 0.768) (0.716, 0.761)
Internal conflict in last 5 years -0.051  -0.052  -0.033 
(-0.252, 0.151) (-0.261, 0.163) (-0.245, 0.172)
Natural disasters 0.049  0.047  0.045 
(0.018, 0.079) (0.015, 0.079) (0.014, 0.076)
After 1989 -0.059  -0.062  -0.198 
(-0.416, 0.290) (-0.419, 0.295) (-0.577, 0.162)
Constant 6.177  6.172  6.345 
(5.010, 7.399) (5.030, 7.331) (5.169, 7.507)
N 4067      4067      4067     
.

Model diagnostics

Country intercepts vary with an SD of 0.09 (etc.), year intercepts vary with an SD of 0.26 (etc.), and the SD of error not accounted for by either within-country or within-year variability is 2.69 (etc.)

Predicted ODA

Here, for the sake of computational efficiency and speed, we only use one of the imputed datasets for predictions. Technically we should base the predictions on all the merged chains, but (1) there’s no function that can handle that, (2) it would take forever to run predictions on each individual imputation and then combine the predictions, and (3) these are posterior medians anyway from ostensibly the same-ish distribution—quintupling the number of chains to simulate is overkill for drawing a picture.

barriers.indiv.clean.names <- tribble(
  ~barrier, ~barrier.clean,
  "advocacy_within", "Barriers to advocacy",
  "entry_within", "Barriers to entry",
  "funding_within", "Barriers to funding"
)

model <- mods.h1.next_year.bayes %>%
  filter(m == "imp1", model.name == "mod.h1.type.total") %>%
  select(model) %>% .[[1]] %>% .[[1]]

hypothetical.bounds <- get_all_vars(model$formula, data = model$data) %>%
  select(advocacy_within, entry_within, funding_within) %>%
  summarise_all(funs(min, max)) %>%
  gather(key, value) %>%
  mutate(value = round(value, 0)) %>%
  # Have to separate on _m because of multiple _s, then re-add the m
  separate(key, into = c("term", "variable"), sep = "_m") %>%
  mutate(variable = paste0("m", variable)) %>%
  spread(variable, value)

new.data.hypothetical.nested <- hypothetical.bounds %>%
  nest(-term) %>%
  mutate(newdata = map2(.x = data, .y = term,
                        ~ expand.grid(term = seq(.x$min, .x$max, by = 0.5),
                                      cowcode = 1000:1049,
                                      year = 1981:2012,
                                      id = 1) %>%
                          # Rename the term column to the actual term name
                          magrittr::set_colnames(c(.y, colnames(.)[-1]))))

new.data.hypothetical <- as_tibble(bind_rows(new.data.hypothetical.nested$newdata)) %>%
  mutate_at(vars(contains("within")), funs(ifelse(is.na(.), 0, .)))

new.data <- get_all_vars(model$formula, data = model$data) %>%
  select(-c(advocacy_within, entry_within, funding_within, year, cowcode)) %>%
  summarise_all(typical) %>%
  mutate(id = 1) %>%
  right_join(new.data.hypothetical, by = "id") %>% select(-id)

predicted.h1.barriers.individual <- new.data %>%
  nest(-cowcode) %>%
  mutate(predicted = future_map(.x = data, ~ generate_predictions(.x))) %>%
  unnest()

df.plot.data.indiv.h1 <- predicted.h1.barriers.individual %>%
  gather(barrier, barrier.value, c(advocacy_within, entry_within, funding_within)) %>%
  group_by(cowcode, barrier.value, barrier) %>%
  summarise_at(vars(predicted), funs(mean(.))) %>%
  left_join(barriers.indiv.clean.names, by = "barrier")

df.plot.data.mean.indiv.h1 <- df.plot.data.indiv.h1 %>%
  group_by(barrier, barrier.value) %>%
  summarise(predicted = mean(predicted)) %>%
  mutate(cowcode = 1) %>%  # Fake country so the line plots
  left_join(barriers.indiv.clean.names, by = "barrier")
# Combine the two plot data frames
df.plot.data.both.h1 <- df.plot.data.h1 %>%
  mutate(barrier = "barriers.total_within", barrier.clean = "Total barriers") %>%
  rename(barrier.value = barriers.total_within) %>%
  bind_rows(df.plot.data.indiv.h1) %>%
  mutate(barrier.clean = ordered(fct_inorder(barrier.clean)),
         highlight = ifelse(barrier.clean == "Total barriers", TRUE, FALSE))

df.plot.data.mean.both.h1 <- df.plot.data.mean.h1 %>%
  mutate(barrier = "barriers.total_within", barrier.clean = "Total barriers") %>%
  rename(barrier.value = barriers.total_within) %>%
  bind_rows(df.plot.data.mean.indiv.h1) %>%
  mutate(barrier.clean = ordered(fct_inorder(barrier.clean)))

# Create data frame for highlighting the total panel
df.panel.highlight.h1 <- df.plot.data.both.h1 %>%
  distinct(barrier.clean, highlight)

fig.predicted.h1.barriers.both <- ggplot(df.plot.data.both.h1, 
                                         aes(x = barrier.value, y = expm1(predicted), 
                                             group = cowcode)) + 
  geom_rect(data = df.panel.highlight.h1, aes(fill = highlight), inherit.aes = FALSE,
            xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, alpha = 0.15) +
  geom_vline(xintercept = 0, colour = "black", size = 0.5) + 
  geom_smooth(method = "lm", size = 0.1, alpha = 0.1, 
              colour = simulation.individual) +
  geom_smooth(data = df.plot.data.mean.both.h1, size = 1.5, 
              method = "lm", colour = simulation.mean) +
  labs(x = "Difference from average number of anti-NGO barriers in country (within effects)",
       y = "Predicted ODA in the following year") +
  scale_y_continuous(labels = dollar, trans = log1p_trans()) +
  scale_fill_manual(values = c(NA, "grey50"), guide = FALSE) +
  facet_wrap(~ barrier.clean, scales = "free_x") +
  theme_donors() +
  theme(axis.title.x = element_text(hjust = 0))
fig.predicted.h1.barriers.both


H2: Donors shift aid to tamer causes

H2: As restrictive laws against NGOs are enacted, donors start increasing funds for ‘tamer’ causes, and decreasing funds for politically sensitive causes.

Our dependent variable for this hypothesis is the percentage of ODA (still in constant 2011 dollars) allocated for contentious purposes, again leaded by one year. We classify contentious aid as any project focused on government and civil society (DAC codes 150 and 151) or conflict prevention and resolution, peace and security (DAC code 152).

Working with proportion data, however, poses interesting mathematical and methodological challenges, since the range of possible outcomes is limited to a value between 0 and 1. Treating proportion variables in a mixed model is technically possible, but it yields predicitions that go beyond the allowable range of values (1.13, -0.5, etc.). Treating the proportion as a binomial variable is also possible and is indeed one of the ways to use the glm() function in R. However, this entails considering the proportion as a ratio of success and failures. In this case, treating a dollar of contentious aid as a success feels off, especially since aid amounts aren’t independent events—it’s not like each dollar of aid goes through a probabalistic process like a coin flip.

One recommendation by Ben Bolker, the maintainer of lme4, is to use a logit transformation of the dependent variable in lmer() models. This seems to be standard practice in political science research, too. Logit transformations still can’t handle values of exactly 0 or 1, though, so we winsorize those values by adding or subtracting 0.001 to the extremes.

Another solution is to use beta regression, which constrains the outcome variable to values between 0 and 1, but unfortunately does not allow for values of exactly 0 or 1. Zero-and-one inflated beta regression models, however, make adjustments for this, and we include a set of these models as a robustness check. We stick with logit-linear models, though, since we want to compare the ratio of contentious aid to non-contentious aid (rather than the percent of contentious aid) and keep the comparison parallel with our H3 models, which only compare the ratio of aid channeled through all NGOs.

We thus use a logit-linear model of the ratio of contentious aid to non-contentious aid:

\[ln( \frac{\text{contentious ODA}_{\text{OECD}}}{\text{noncontentious ODA}_{\text{OECD}}} )_{i, t+1} = \text{NGO legislation}_{it} + \text{controls}_{it}\]

We look at NGO legislation in the same ways as H1 and use the same controls.

MCMC diagnostics

Check fit

Again, use one of the imputed models (mod.h2.barriers.total) to check for fit and convergence.

Posterior predictive distribution vs. observed outcome?

Results

Coefficients

vars.to.plot <- c("barriers.total_within", "barriers.total_between",
                  "advocacy_within", "advocacy_between", 
                  "entry_within", "entry_between", 
                  "funding_within", "funding_between",
                  "csre_within", "csre_between")

mods.h2.melded <- bayes.meld(mods.h2.next_year.bayes,
                             vars.to.plot, exponentiate = TRUE)$melded.summary

plot.data <- mods.h2.melded %>%
  left_join(coef.names.all, by = "term") %>%
  left_join(model.names, by = c("model.name" = "model")) %>% 
  mutate(term = factor(term, levels = vars.to.plot, ordered = TRUE)) %>%
  arrange(desc(term)) %>%
  mutate(term_plot = ordered(fct_inorder(term_plot_short))) %>%
  mutate(coef.type = case_when(
    str_detect(.$term, "_within") ~ "Within",
    str_detect(.$term, "_between") ~ "Between",
  )) %>% 
  mutate(coef.type = factor(coef.type, levels = c("Within", "Between"),
                            ordered = TRUE)) %>%
  mutate(model_clean = factor(model_clean, levels = rev(unique(model_clean)), ordered = TRUE))

fig.coefs.h2 <- ggplot(plot.data, aes(x = med, y = term_plot, colour = model_clean)) +
  geom_vline(xintercept = 1, colour = "black", size = 0.5) +  
  geom_pointrangeh(aes(xmin = `2.5%`, xmax = `97.5%`), size = 0.5, fatten = 3) + 
  labs(x = "Percent change in ratio of contentious aid (odds ratio)", y = NULL) +
  scale_colour_manual(values = model.colors, name = NULL) +
  expand_limits(x = c(0.6, 1.3)) +
  guides(color = guide_legend(override.aes = list(size = 0.25))) +
  theme_donors() + 
  theme(legend.justification = "left",
        legend.box.margin = margin(l = -0.75, t = -0.5, unit = "lines"),
        axis.title.x = element_text(hjust = 0)) +
  facet_wrap(~ coef.type, scales = "free", ncol = 2)
fig.coefs.h2

Complete results in a table

The effect of anti-NGO legislation on the proportion of OECD overseas development assistance (ODA) committed to contentious purposes in the following year (H2), full models. Each cell contains the parameter’s posterior median, the 95% credible interval, and the probability that the parameter is greater than one (in italics). {#tbl:h2-coefs}
(1) (2) (3)
Fixed part (odds ratios)
Total legal barrierswithin 1.04
(0.98, 1.10); 0.90
Total legal barriersbetween 0.98
(0.90, 1.08); 0.36
Barriers to advocacywithin 0.80
(0.62, 1.02); 0.04
Barriers to advocacybetween 0.93
(0.65, 1.32); 0.34
Barriers to entrywithin 1.09
(0.96, 1.24); 0.90
Barriers to entrybetween 1.09
(0.92, 1.29); 0.85
Barriers to fundingwithin 1.13
(0.98, 1.30); 0.95
Barriers to fundingbetween 0.91
(0.75, 1.09); 0.14
Civil society reg. env. (CSRE)within 1.08
(1.03, 1.13); 1.00
Civil society reg. env. (CSRE)between 1.05
(0.96, 1.14); 0.85
Polity IV (0–10)within 1.03
(1.00, 1.06); 0.97
1.03
(1.00, 1.06); 0.97
0.99
(0.95, 1.03); 0.25
Polity IV (0–10)between 1.09
(1.04, 1.14); 1.00
1.08
(1.03, 1.13); 1.00
1.06
(0.98, 1.14); 0.92
GDP per capita (log)within 0.97
(0.81, 1.16); 0.36
0.96
(0.80, 1.15); 0.34
0.99
(0.82, 1.18); 0.45
GDP per capita (log)between 0.71
(0.64, 0.77); 0.00
0.71
(0.65, 0.78); 0.00
0.71
(0.64, 0.77); 0.00
Trade as % of GDPwithin 1.00
(1.00, 1.00); 0.04
1.00
(1.00, 1.00); 0.05
1.00
(1.00, 1.00); 0.03
Trade as % of GDPbetween 1.00
(1.00, 1.00); 0.95
1.00
(1.00, 1.00); 0.95
1.00
(1.00, 1.00); 0.95
Corruptionwithin 1.05
(1.00, 1.10); 0.98
1.05
(1.00, 1.11); 0.98
1.06
(1.01, 1.11); 0.99
Corruptionbetween 1.07
(1.01, 1.13); 0.99
1.06
(1.01, 1.12); 0.99
1.07
(1.02, 1.13); 1.00
Proportion of contentious aid in present year (logit) 1.28
(1.24, 1.32); 1.00
1.28
(1.24, 1.32); 1.00
1.27
(1.23, 1.31); 1.00
Internal conflict in last 5 years 1.07
(0.94, 1.21); 0.84
1.06
(0.93, 1.20); 0.80
1.09
(0.96, 1.24); 0.91
Natural disasters 0.99
(0.97, 1.01); 0.22
0.99
(0.97, 1.01); 0.22
0.99
(0.97, 1.01); 0.16
After 1989 4.61
(3.02, 7.05); 1.00
4.69
(3.08, 7.22); 1.00
4.34
(2.87, 6.72); 1.00
Constant 0.09
(0.03, 0.25); 0.00
0.08
(0.03, 0.23); 0.00
0.10
(0.04, 0.27); 0.00
Random part (original coefficients)
Within-country variability 0.50 0.50 0.50
Within-year variability 0.52 0.52 0.52
Residual random error 1.33 1.33 1.33
Model details
Imputed datasets (m) 5 5 5
N 3922 3922 3922
Posterior sample size 4000 4000 4000
Notes
Logit-linear models. Percent change odds ratios reported.

Complete results (nonimputed)

(1) (2) (3)
Total legal barriers~within~ 1.060             
(0.999, 1.121)            
Total legal barriers~between~ 1.005             
(0.923, 1.093)            
Barriers to advocacy~within~       0.873       
      (0.672, 1.135)      
Barriers to advocacy~between~       1.082       
      (0.759, 1.546)      
Barriers to entry~within~       1.080       
      (0.953, 1.230)      
Barriers to entry~between~       1.092       
      (0.935, 1.278)      
Barriers to funding~within~       1.134       
      (0.981, 1.309)      
Barriers to funding~between~       0.899       
      (0.748, 1.075)      
Civil society reg. env. (CSRE)~within~             1.081 
            (1.034, 1.131)
Civil society reg. env. (CSRE)~between~             1.041 
            (0.956, 1.133)
Polity IV (0–10)~within~ 1.033  1.031  0.984 
(1.001, 1.067) (1.001, 1.063) (0.945, 1.023)
Polity IV (0–10)~between~ 1.091  1.089  1.058 
(1.041, 1.141) (1.040, 1.141) (0.982, 1.137)
GDP per capita (log)~within~ 0.948  0.944  0.978 
(0.788, 1.143) (0.787, 1.130) (0.810, 1.178)
GDP per capita (log)~between~ 0.704  0.705  0.705 
(0.643, 0.768) (0.646, 0.770) (0.644, 0.770)
Trade as % of GDP~within~ 0.998  0.998  0.998 
(0.996, 1.000) (0.996, 1.000) (0.996, 1.000)
Trade as % of GDP~between~ 1.003  1.003  1.003 
(1.000, 1.005) (1.000, 1.005) (1.000, 1.005)
Corruption~within~ 1.040  1.041  1.048 
(0.987, 1.095) (0.990, 1.095) (0.996, 1.104)
Corruption~between~ 1.064  1.062  1.066 
(1.010, 1.117) (1.010, 1.116) (1.014, 1.118)
Proportion of contentious aid in present year (logit) 1.271  1.269  1.267 
(1.231, 1.311) (1.229, 1.311) (1.226, 1.310)
Internal conflict in last 5 years 1.069  1.064  1.091 
(0.938, 1.211) (0.938, 1.202) (0.964, 1.240)
Natural disasters 0.992  0.991  0.989 
(0.972, 1.013) (0.970, 1.011) (0.970, 1.010)
After 1989 4.729  4.758  4.520 
(3.103, 7.250) (3.088, 7.332) (2.908, 7.033)
Constant 0.084  0.077  0.095 
(0.031, 0.229) (0.029, 0.198) (0.037, 0.239)
N 3826      3826      3826     
.

Predicted proportion of contentious aid

barriers.indiv.clean.names <- tribble(
  ~barrier, ~barrier.clean,
  "advocacy_within", "Barriers to advocacy",
  "entry_within", "Barriers to entry",
  "funding_within", "Barriers to funding"
)

model <- mods.h2.next_year.bayes %>%
  filter(m == "imp1", model.name == "mod.h2.type.total") %>%
  select(model) %>% .[[1]] %>% .[[1]]

hypothetical.bounds <- get_all_vars(model$formula, data = model$data) %>%
  select(advocacy_within, entry_within, funding_within) %>%
  summarise_all(funs(min, max)) %>%
  gather(key, value) %>%
  mutate(value = round(value, 0)) %>%
  # Have to separate on _m because of multiple _s, then re-add the m
  separate(key, into = c("term", "variable"), sep = "_m") %>%
  mutate(variable = paste0("m", variable)) %>%
  spread(variable, value)

new.data.hypothetical.nested <- hypothetical.bounds %>%
  nest(-term) %>%
  mutate(newdata = map2(.x = data, .y = term,
                        ~ expand.grid(term = seq(.x$min, .x$max, by = 0.5),
                                      cowcode = 1000:1049,
                                      year = 1981:2012,
                                      id = 1) %>%
                          # Rename the term column to the actual term name
                          magrittr::set_colnames(c(.y, colnames(.)[-1]))))

new.data.hypothetical <- as_tibble(bind_rows(new.data.hypothetical.nested$newdata)) %>%
  mutate_at(vars(contains("within")), funs(ifelse(is.na(.), 0, .)))

new.data <- get_all_vars(model$formula, data = model$data) %>%
  select(-c(advocacy_within, entry_within, funding_within, year, cowcode)) %>%
  summarise_all(typical) %>%
  mutate(id = 1) %>%
  right_join(new.data.hypothetical, by = "id") %>% select(-id)

predicted.h2.barriers.individual <- new.data %>%
  nest(-cowcode) %>%
  mutate(predicted = future_map(.x = data, ~ generate_predictions(.x))) %>%
  unnest()

df.plot.data.indiv.h2 <- predicted.h2.barriers.individual %>%
  gather(barrier, barrier.value, c(advocacy_within, entry_within, funding_within)) %>%
  group_by(cowcode, barrier.value, barrier) %>%
  summarise_at(vars(predicted), funs(mean(.))) %>%
  mutate(value.fixed = inv.logit(predicted, a = 0.001)) %>% 
  left_join(barriers.indiv.clean.names, by = "barrier")

df.plot.data.mean.indiv.h2 <- df.plot.data.indiv.h2 %>%
  group_by(barrier, barrier.value) %>%
  summarise(predicted = mean(predicted)) %>%
  mutate(cowcode = 1) %>%  # Fake country so the line plots
  mutate(value.fixed = inv.logit(predicted, a = 0.001)) %>% 
  left_join(barriers.indiv.clean.names, by = "barrier")
# Combine the two plot data frames
df.plot.data.both.h2 <- df.plot.data.h2 %>%
  mutate(barrier = "barriers.total_within", barrier.clean = "Total barriers") %>%
  rename(barrier.value = barriers.total_within) %>%
  bind_rows(df.plot.data.indiv.h2) %>%
  mutate(barrier.clean = ordered(fct_inorder(barrier.clean)),
         highlight = ifelse(barrier.clean == "Total barriers", TRUE, FALSE))

df.plot.data.mean.both.h2 <- df.plot.data.mean.h2 %>%
  mutate(barrier = "barriers.total_within", barrier.clean = "Total barriers") %>%
  rename(barrier.value = barriers.total_within) %>%
  bind_rows(df.plot.data.mean.indiv.h2) %>%
  mutate(barrier.clean = ordered(fct_inorder(barrier.clean)))

# Create data frame for highlighting the total panel
df.panel.highlight.h2 <- df.plot.data.both.h2 %>%
  distinct(barrier.clean, highlight)

fig.predicted.h2.barriers.both <- ggplot(df.plot.data.both.h2, 
                                         aes(x = barrier.value,
                                             y = value.fixed, group = cowcode)) + 
  geom_rect(data = df.panel.highlight.h2, aes(fill = highlight), inherit.aes = FALSE,
            xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, alpha = 0.15) +
  geom_vline(xintercept = 0, colour = "black", size = 0.5) + 
  geom_smooth(method = "lm", size = 0.1, alpha = 0.1, colour = simulation.individual) +
  geom_smooth(data = df.plot.data.mean.both.h2, size = 1.5, 
              method = "lm", colour = simulation.mean) +
  labs(x = "Difference from average level of NGO legislation in country (within effect)",
       y = "Predicted proportion of\ncontentious aid in the following year") +
  scale_y_continuous(labels = percent_format(accuracy = 1)) +
  scale_fill_manual(values = c(NA, "grey50"), guide = FALSE) +
  facet_wrap(~ barrier.clean, scales = "free_x") +
  theme_donors() + 
  theme(axis.title.x = element_text(hjust = 0))
fig.predicted.h2.barriers.both


H3: Donors shift aid to international NGOs

H3: As restrictive laws against local NGOs increase, states should be more likely to provide aid to INGOs rather than local NGOs.

We use two dependent variables for this hypothesis: the proportion of aid channeled through either (1) domestic or (2) international or US-based (or foreign) NGOs, once again leaded by one year. The OECD and AidData do not track the channels of aid delivery, so we cannot see how aid is distributed on a global scale. USAID, however, does track channels, so we can measure how much aid goes to domestic NGOs (and also US-based and international NGOs). USAID didn’t start tracking this until 2001, though, so we have to limit our models to 2001–2013. (Boo.)

It would be cool to model the ratio aid channeled through domestic to foreign NGOs, but doing that causes weird mathematical issues with logit transformations, since the ratios can exceed 1.

Because the DVs are proportions, we have to make the same assumptions and weird interpretive tricks as H2, building a logit-linear model of the ratio of domestic or foreign NGO aid to all other channels:

\[ln( \frac{\text{Aid to (domestic or foreign) NGOs}_{\text{USAID}}}{\text{Aid to other channels}_{\text{USAID}}} )_{i, t+1} = \text{NGO legislation}_{it} + \text{controls}_{it}\]

We also include zero-one-inflated beta regression models as robustness checks.

Again, we use the same NGO legislation variables as H1 and H2 and use the same controls, except we omit “After 1989” since no observations actually occur after 1989.

MCMC diagnostics

Check fit

Again, use one of the imputed models (mod.h3.barriers.total) to check for fit and convergence.

Posterior predictive distribution vs. observed outcome?

Results

Proportion to domestic NGOs

The effect of anti-NGO legislation on the proportion of US aid channeled through domestic NGOs in the following year (H3), full models. Each cell contains the parameter’s posterior median, the 95% credible interval, and the probability that the parameter is greater than one (in italics) {#tbl:h3-domestic-coefs}
(1) (2) (3)
Fixed part (odds ratios)
Total legal barrierswithin 1.15
(1.03, 1.29); 0.99
Total legal barriersbetween 1.04
(0.93, 1.16); 0.75
Barriers to advocacywithin 0.99
(0.56, 1.76); 0.49
Barriers to advocacybetween 1.10
(0.73, 1.67); 0.68
Barriers to entrywithin 1.01
(0.75, 1.35); 0.53
Barriers to entrybetween 1.14
(0.94, 1.39); 0.91
Barriers to fundingwithin 1.34
(1.01, 1.78); 0.98
Barriers to fundingbetween 0.92
(0.73, 1.16); 0.24
Civil society reg. env. (CSRE)within 0.92
(0.80, 1.07); 0.14
Civil society reg. env. (CSRE)between 1.04
(0.92, 1.18); 0.74
Polity IV (0–10)within 0.88
(0.79, 0.98); 0.01
0.88
(0.80, 0.98); 0.01
0.91
(0.80, 1.02); 0.06
Polity IV (0–10)between 1.01
(0.94, 1.08); 0.58
1.00
(0.94, 1.07); 0.53
0.96
(0.86, 1.07); 0.25
GDP per capita (log)within 1.89
(1.06, 3.27); 0.98
1.93
(1.08, 3.35); 0.99
2.01
(1.12, 3.49); 0.99
GDP per capita (log)between 1.04
(0.91, 1.20); 0.74
1.05
(0.91, 1.20); 0.75
1.05
(0.92, 1.21); 0.77
Trade as % of GDPwithin 1.00
(0.99, 1.01); 0.55
1.00
(0.99, 1.01); 0.55
1.00
(0.99, 1.01); 0.48
Trade as % of GDPbetween 1.00
(0.99, 1.00); 0.00
1.00
(0.99, 1.00); 0.01
0.99
(0.99, 1.00); 0.00
Corruptionwithin 1.19
(1.04, 1.41); 0.98
1.20
(1.05, 1.42); 0.99
1.18
(1.03, 1.39); 0.97
Corruptionbetween 1.15
(1.06, 1.24); 1.00
1.14
(1.05, 1.23); 1.00
1.14
(1.06, 1.23); 1.00
Proportion of aid to domestic NGOs in present year (logit) 1.39
(1.32, 1.46); 1.00
1.38
(1.31, 1.45); 1.00
1.39
(1.32, 1.46); 1.00
Internal conflict in last 5 years 1.23
(0.94, 1.59); 0.94
1.24
(0.95, 1.62); 0.95
1.22
(0.94, 1.59); 0.93
Natural disasters 0.99
(0.96, 1.02); 0.24
0.99
(0.96, 1.02); 0.21
0.99
(0.96, 1.02); 0.29
Constant 0.02
(0.00, 0.09); 0.00
0.02
(0.00, 0.08); 0.00
0.02
(0.01, 0.11); 0.00
Random part (original coefficients)
Within-country variability 0.72 0.73 0.71
Within-year variability 0.18 0.18 0.19
Residual random error 1.55 1.55 1.55
Model details
Imputed datasets (m) 5 5 5
N 1751 1751 1751
Posterior sample size 4000 4000 4000
Notes
Logit-linear models. Percent change odds ratios reported.

Proportion to foreign NGOs

The effect of anti-NGO legislation on the proportion of US aid channeled through US-based and international NGOs in the following year (H3), full models. Each cell contains the parameter’s posterior median, the 95% credible interval, and the probability that the parameter is greater than one (in italics) {#tbl:h3-foreign-coefs}
(1) (2) (3)
Fixed part (odds ratios)
Total legal barrierswithin 0.95
(0.83, 1.08); 0.20
Total legal barriersbetween 1.02
(0.89, 1.16); 0.60
Barriers to advocacywithin 1.04
(0.53, 1.99); 0.54
Barriers to advocacybetween 0.96
(0.59, 1.54); 0.44
Barriers to entrywithin 1.36
(0.98, 1.90); 0.97
Barriers to entrybetween 1.07
(0.84, 1.35); 0.71
Barriers to fundingwithin 0.71
(0.52, 0.97); 0.01
Barriers to fundingbetween 0.99
(0.76, 1.30); 0.48
Civil society reg. env. (CSRE)within 1.11
(0.95, 1.30); 0.89
Civil society reg. env. (CSRE)between 1.03
(0.89, 1.19); 0.66
Polity IV (0–10)within 1.04
(0.93, 1.18); 0.75
1.04
(0.93, 1.18); 0.74
1.00
(0.87, 1.14); 0.52
Polity IV (0–10)between 0.98
(0.91, 1.06); 0.32
0.98
(0.90, 1.06); 0.30
0.95
(0.84, 1.08); 0.23
GDP per capita (log)within 0.29
(0.17, 0.48); 0.00
0.28
(0.16, 0.47); 0.00
0.28
(0.16, 0.46); 0.00
GDP per capita (log)between 0.72
(0.62, 0.85); 0.00
0.72
(0.62, 0.85); 0.00
0.73
(0.62, 0.85); 0.00
Trade as % of GDPwithin 1.00
(0.99, 1.00); 0.15
1.00
(0.99, 1.00); 0.14
1.00
(0.99, 1.00); 0.17
Trade as % of GDPbetween 1.00
(0.99, 1.00); 0.36
1.00
(0.99, 1.00); 0.39
1.00
(0.99, 1.00); 0.36
Corruptionwithin 1.13
(0.96, 1.31); 0.93
1.12
(0.94, 1.31); 0.91
1.16
(0.97, 1.36); 0.95
Corruptionbetween 1.30
(1.19, 1.42); 1.00
1.29
(1.18, 1.42); 1.00
1.30
(1.18, 1.42); 1.00
Proportion of aid to foreign NGOs in present year (logit) 1.39
(1.33, 1.45); 1.00
1.38
(1.32, 1.45); 1.00
1.39
(1.33, 1.45); 1.00
Internal conflict in last 5 years 1.18
(0.88, 1.58); 0.86
1.18
(0.88, 1.60); 0.87
1.20
(0.90, 1.62); 0.89
Natural disasters 1.03
(1.00, 1.07); 0.97
1.03
(1.00, 1.07); 0.97
1.03
(1.00, 1.07); 0.97
Constant 0.56
(0.09, 3.33); 0.26
0.52
(0.09, 3.31); 0.24
0.62
(0.11, 3.38); 0.29
Random part (original coefficients)
Within-country variability 0.86 0.87 0.86
Within-year variability 0.11 0.11 0.11
Residual random error 1.70 1.70 1.70
Model details
Imputed datasets (m) 5 5 5
N 1751 1751 1751
Posterior sample size 4000 4000 4000
Notes
Logit-linear models. Percent change odds ratios reported.

Plot of proportion to domestic and foreign NGOs

vars.to.plot <- c("barriers.total_within", "barriers.total_between",
                  "advocacy_within", "advocacy_between", 
                  "entry_within", "entry_between", 
                  "funding_within", "funding_between",
                  "csre_within", "csre_between")

mods.h3.dom.melded <- bayes.meld(mods.h3.dom.next_year.bayes,
                                 vars.to.plot, exponentiate = TRUE)$melded.summary

coefs.raw.h3.dom <- mods.h3.dom.melded %>%
  left_join(coef.names.all, by = "term") %>%
  left_join(model.names, by = c("model.name" = "model")) %>% 
  mutate(term = factor(term, levels = vars.to.plot, ordered = TRUE)) %>%
  arrange(desc(term)) %>%
  mutate(term_plot = ordered(fct_inorder(term_plot_short))) %>%
  mutate(coef.type = case_when(
    str_detect(.$term, "_within") ~ "Within",
    str_detect(.$term, "_between") ~ "Between",
  )) %>% 
  mutate(coef.type = factor(coef.type, levels = c("Within", "Between"),
                            ordered = TRUE)) %>%
  mutate(model_clean = factor(model_clean, levels = rev(unique(model_clean)), ordered = TRUE))

mods.h3.foreign.melded <- bayes.meld(mods.h3.foreign.next_year.bayes,
                                     vars.to.plot, exponentiate = TRUE)$melded.summary

coefs.raw.h3.foreign <- mods.h3.foreign.melded %>%
  left_join(coef.names.all, by = "term") %>%
  left_join(model.names, by = c("model.name" = "model")) %>% 
  mutate(term = factor(term, levels = vars.to.plot, ordered = TRUE)) %>%
  arrange(desc(term)) %>%
  mutate(term_plot = ordered(fct_inorder(term_plot_short))) %>%
  mutate(coef.type = case_when(
    str_detect(.$term, "_within") ~ "Within",
    str_detect(.$term, "_between") ~ "Between",
  )) %>% 
  mutate(coef.type = factor(coef.type, levels = c("Within", "Between"),
                            ordered = TRUE)) %>%
  mutate(model_clean = factor(model_clean, levels = rev(unique(model_clean)), ordered = TRUE))

coefs.h3.both <- bind_rows(`Domestic NGOs` = coefs.raw.h3.dom,
                           `Foreign NGOs` = coefs.raw.h3.foreign,
                           .id = "channel")

fig.coefs.h3 <- ggplot(coefs.h3.both, aes(y = term_plot, x = med, 
                                          colour = model_clean)) + 
  geom_vline(xintercept = 1, colour = "black", size = 0.5) + 
  geom_pointrangeh(aes(xmin = `2.5%`, xmax = `97.5%`, shape = channel), 
                   size = 0.5, fatten = 3,
                   position = position_dodgev(height = 0.5)) + 
  labs(x = "Percent change in ratio of aid channeled to NGO type (odds ratio)", y = NULL) +
  scale_colour_manual(values = model.colors) +
  expand_limits(x = c(0.5, 2)) +
  guides(color = guide_legend(override.aes = list(size = 0.25),
                              title = NULL, nrow = 2, order = 2),
         shape = guide_legend(override.aes = list(size = 0.5, linetype = 0),
                              title = NULL, nrow = 2, reverse = TRUE, order = 1)) +
  theme_donors() + 
  theme(legend.justification = "left",
        legend.box.margin = margin(l = -0.75, t = -0.5, unit = "lines"),
        axis.title.x = element_text(hjust = 0)) +
  facet_wrap(~ coef.type, scales = "free", ncol = 2)
fig.coefs.h3

Proportion to domestic NGOs (nonimputed)

(1) (2) (3)
Total legal barriers~within~ 1.151             
(1.028, 1.295)            
Total legal barriers~between~ 1.034             
(0.924, 1.154)            
Barriers to advocacy~within~       1.140       
      (0.623, 2.114)      
Barriers to advocacy~between~       1.136       
      (0.762, 1.708)      
Barriers to entry~within~       1.001       
      (0.757, 1.335)      
Barriers to entry~between~       1.133       
      (0.928, 1.382)      
Barriers to funding~within~       1.278       
      (0.968, 1.706)      
Barriers to funding~between~       0.906       
      (0.729, 1.131)      
Civil society reg. env. (CSRE)~within~             0.913 
            (0.786, 1.057)
Civil society reg. env. (CSRE)~between~             1.025 
            (0.908, 1.162)
Polity IV (0–10)~within~ 0.878  0.881  0.908 
(0.789, 0.976) (0.791, 0.987) (0.799, 1.024)
Polity IV (0–10)~between~ 1.012  1.008  0.980 
(0.945, 1.086) (0.936, 1.080) (0.882, 1.089)
GDP per capita (log)~within~ 1.847  1.889  1.942 
(1.024, 3.239) (1.057, 3.330) (1.047, 3.544)
GDP per capita (log)~between~ 1.033  1.034  1.036 
(0.898, 1.183) (0.903, 1.185) (0.902, 1.185)
Trade as % of GDP~within~ 0.999  0.999  0.998 
(0.993, 1.005) (0.993, 1.005) (0.993, 1.004)
Trade as % of GDP~between~ 0.995  0.995  0.995 
(0.991, 0.999) (0.991, 0.999) (0.992, 0.999)
Corruption~within~ 1.208  1.214  1.186 
(1.036, 1.396) (1.045, 1.411) (1.015, 1.392)
Corruption~between~ 1.140  1.134  1.136 
(1.058, 1.231) (1.048, 1.227) (1.052, 1.227)
Proportion of aid to domestic NGOs in present year (logit) 1.411  1.406  1.415 
(1.337, 1.488) (1.330, 1.484) (1.344, 1.491)
Internal conflict in last 5 years 1.225  1.248  1.210 
(0.942, 1.585) (0.959, 1.625) (0.932, 1.543)
Natural disasters 0.990  0.988  0.992 
(0.961, 1.020) (0.960, 1.017) (0.963, 1.022)
Constant 0.022  0.021  0.028 
(0.005, 0.107) (0.004, 0.109) (0.007, 0.125)
N 1700      1700      1700     
.

Proportion to foreign NGOs (nonimputed)

(1) (2) (3)
Total legal barriers~within~ 0.950             
(0.836, 1.077)            
Total legal barriers~between~ 1.029             
(0.907, 1.168)            
Barriers to advocacy~within~       1.068       
      (0.550, 2.044)      
Barriers to advocacy~between~       0.980       
      (0.592, 1.609)      
Barriers to entry~within~       1.360       
      (0.991, 1.839)      
Barriers to entry~between~       1.075       
      (0.857, 1.373)      
Barriers to funding~within~       0.705       
      (0.524, 0.954)      
Barriers to funding~between~       0.997       
      (0.766, 1.300)      
Civil society reg. env. (CSRE)~within~             1.146 
            (0.974, 1.355)
Civil society reg. env. (CSRE)~between~             1.034 
            (0.901, 1.194)
Polity IV (0–10)~within~ 1.054  1.054  1.002 
(0.934, 1.187) (0.938, 1.189) (0.873, 1.153)
Polity IV (0–10)~between~ 0.991  0.985  0.957 
(0.915, 1.066) (0.907, 1.068) (0.843, 1.079)
GDP per capita (log)~within~ 0.262  0.253  0.251 
(0.154, 0.433) (0.147, 0.435) (0.148, 0.415)
GDP per capita (log)~between~ 0.724  0.721  0.725 
(0.626, 0.843) (0.618, 0.845) (0.623, 0.847)
Trade as % of GDP~within~ 0.996  0.996  0.997 
(0.990, 1.002) (0.991, 1.002) (0.991, 1.003)
Trade as % of GDP~between~ 0.999  0.999  0.999 
(0.995, 1.004) (0.995, 1.004) (0.995, 1.004)
Corruption~within~ 1.105  1.095  1.147 
(0.939, 1.307) (0.926, 1.293) (0.966, 1.364)
Corruption~between~ 1.293  1.288  1.288 
(1.183, 1.415) (1.177, 1.408) (1.180, 1.410)
Proportion of aid to foreign NGOs in present year (logit) 1.414  1.406  1.414 
(1.355, 1.480) (1.346, 1.472) (1.353, 1.481)
Internal conflict in last 5 years 1.180  1.196  1.217 
(0.882, 1.589) (0.899, 1.613) (0.906, 1.625)
Natural disasters 1.030  1.030  1.030 
(0.997, 1.064) (0.997, 1.065) (0.997, 1.065)
Constant 0.524  0.543  0.640 
(0.088, 3.142) (0.091, 3.286) (0.124, 3.333)
N 1700      1700      1700     
.

Predicted proportion of aid channeled to domestic or foreign NGOs

model <- mods.h3.foreign.next_year.bayes %>%
  filter(m == "imp1", model.name == "mod.h3.foreign.barriers.total") %>%
  select(model) %>% .[[1]] %>% .[[1]]

new.data <- get_all_vars(model$formula, data = model$data) %>%
  select(-c(barriers.total_within, year, cowcode)) %>%
  summarise_all(typical) %>%
  mutate(id = 1) %>%
  right_join(expand.grid(barriers.total_within = seq(-3, 4, 0.5),
                         cowcode = 1000:1049,
                         year = 2000:2012,
                         id = 1), by = "id") %>% select(-id)

predicted.h3.foreign.barriers.total <- new.data %>%
  nest(-cowcode) %>%
  mutate(predicted = future_map(.x = data, ~ generate_predictions(.x))) %>%
  unnest() %>% 
  mutate(ngo_type = "Foreign NGOs")

model <- mods.h3.dom.next_year.bayes %>%
  filter(m == "imp1", model.name == "mod.h3.barriers.total") %>%
  select(model) %>% .[[1]] %>% .[[1]]

new.data <- get_all_vars(model$formula, data = model$data) %>%
  select(-c(barriers.total_within, year, cowcode)) %>%
  summarise_all(typical) %>%
  mutate(id = 1) %>%
  right_join(expand.grid(barriers.total_within = seq(-3, 4, 0.5),
                         cowcode = 1000:1049,
                         year = 2000:2012,
                         id = 1), by = "id") %>% select(-id)

predicted.h3.dom.barriers.total <- new.data %>%
  nest(-cowcode) %>%
  mutate(predicted = future_map(.x = data, ~ generate_predictions(.x))) %>%
  unnest() %>% 
  mutate(ngo_type = "Domestic NGOs")

df.plot.data.h3 <- bind_rows(predicted.h3.foreign.barriers.total,
                             predicted.h3.dom.barriers.total) %>%
  group_by(cowcode, ngo_type, barriers.total_within) %>%
  summarise_at(vars(predicted), funs(mean(.))) %>%
  ungroup() %>% 
  mutate(value.fixed = inv.logit(predicted, a = 0.001))

df.plot.data.mean.h3 <- df.plot.data.h3 %>%
  group_by(ngo_type, barriers.total_within) %>%
  summarise(predicted = mean(predicted)) %>%
  mutate(value.fixed = inv.logit(predicted, a = 0.001)) %>%
  mutate(cowcode = 1)  # Fake country so the line plots
barriers.indiv.clean.names <- tribble(
  ~barrier, ~barrier.clean,
  "advocacy_within", "Barriers to advocacy",
  "entry_within", "Barriers to entry",
  "funding_within", "Barriers to funding"
)

model <- mods.h3.foreign.next_year.bayes %>%
  filter(m == "imp1", model.name == "mod.h3.foreign.type.total") %>%
  select(model) %>% .[[1]] %>% .[[1]]

hypothetical.bounds <- get_all_vars(model$formula, data = model$data) %>%
  select(advocacy_within, entry_within, funding_within) %>%
  summarise_all(funs(min, max)) %>%
  gather(key, value) %>%
  mutate(value = round(value, 0)) %>%
  # Have to separate on _m because of multiple _s, then re-add the m
  separate(key, into = c("term", "variable"), sep = "_m") %>%
  mutate(variable = paste0("m", variable)) %>%
  spread(variable, value)

new.data.hypothetical.nested <- hypothetical.bounds %>%
  nest(-term) %>%
  mutate(newdata = map2(.x = data, .y = term,
                        ~ expand.grid(term = seq(.x$min, .x$max, by = 0.5),
                                      cowcode = 1000:1049,
                                      year = 2000:2012,
                                      id = 1) %>%
                          # Rename the term column to the actual term name
                          magrittr::set_colnames(c(.y, colnames(.)[-1]))))

new.data.hypothetical <- as_tibble(bind_rows(new.data.hypothetical.nested$newdata)) %>%
  mutate_at(vars(contains("within")), funs(ifelse(is.na(.), 0, .)))

# Foreign NGOs
new.data <- get_all_vars(model$formula, data = model$data) %>%
  select(-c(advocacy_within, entry_within, funding_within, year, cowcode)) %>%
  summarise_all(typical) %>%
  mutate(id = 1) %>%
  right_join(new.data.hypothetical, by = "id") %>% select(-id)

predicted.h3.foreign.barriers.individual <- new.data %>%
  nest(-cowcode) %>%
  mutate(predicted = future_map(.x = data, ~ generate_predictions(.x))) %>%
  unnest() %>% 
  mutate(ngo_type = "Foreign NGOs")

# Domestic NGOs
model <- mods.h3.dom.next_year.bayes %>%
  filter(m == "imp1", model.name == "mod.h3.type.total") %>%
  select(model) %>% .[[1]] %>% .[[1]]

new.data <- get_all_vars(model$formula, data = model$data) %>%
  select(-c(advocacy_within, entry_within, funding_within, year, cowcode)) %>%
  summarise_all(typical) %>%
  mutate(id = 1) %>%
  right_join(new.data.hypothetical, by = "id") %>% select(-id)

predicted.h3.dom.barriers.individual <- new.data %>%
  nest(-cowcode) %>%
  mutate(predicted = future_map(.x = data, ~ generate_predictions(.x))) %>%
  unnest() %>% 
  mutate(ngo_type = "Domestic NGOs")

df.plot.data.indiv.h3 <- bind_rows(predicted.h3.foreign.barriers.individual,
                                   predicted.h3.dom.barriers.individual) %>%
  gather(barrier, barrier.value, c(advocacy_within, entry_within, funding_within)) %>%
  group_by(cowcode, ngo_type, barrier.value, barrier) %>%
  summarise_at(vars(predicted), funs(mean(.))) %>%
  mutate(value.fixed = inv.logit(predicted, a = 0.001)) %>% 
  left_join(barriers.indiv.clean.names, by = "barrier")

df.plot.data.mean.indiv.h3 <- df.plot.data.indiv.h3 %>%
  group_by(ngo_type, barrier, barrier.value) %>%
  summarise(predicted = mean(predicted)) %>%
  mutate(cowcode = 1) %>%  # Fake country so the line plots
  mutate(value.fixed = inv.logit(predicted, a = 0.001)) %>% 
  left_join(barriers.indiv.clean.names, by = "barrier")
# Combine the two plot data frames
df.plot.data.both.h3 <- df.plot.data.h3 %>%
  mutate(barrier = "barriers.total_within", barrier.clean = "Total barriers") %>%
  rename(barrier.value = barriers.total_within) %>%
  bind_rows(df.plot.data.indiv.h3) %>%
  mutate(barrier.clean = ordered(fct_inorder(barrier.clean)),
         highlight = ifelse(barrier.clean == "Total barriers", TRUE, FALSE)) %>% 
  mutate(ngo_type = recode(ngo_type,
                           `Domestic NGOs` = "Proportion channeled to domestic NGOs",
                           `Foreign NGOs` = "… to foreign NGOs"),
         ngo_type = fct_inorder(ngo_type, ordered = TRUE))

df.plot.data.mean.both.h3 <- df.plot.data.mean.h3 %>%
  mutate(barrier = "barriers.total_within", barrier.clean = "Total barriers") %>%
  rename(barrier.value = barriers.total_within) %>%
  bind_rows(df.plot.data.mean.indiv.h3) %>%
  mutate(barrier.clean = ordered(fct_inorder(barrier.clean))) %>% 
  ungroup() %>% 
  mutate(ngo_type = recode(ngo_type,
                           `Domestic NGOs` = "Proportion channeled to domestic NGOs",
                           `Foreign NGOs` = "… to foreign NGOs"),
         ngo_type = fct_inorder(ngo_type, ordered = TRUE))

# Create data frame for highlighting the total panel
df.panel.highlight.h3 <- df.plot.data.both.h3 %>%
  distinct(barrier.clean, highlight)

fig.predicted.h3.barriers.both <- 
  ggplot(df.plot.data.both.h3, 
         aes(x = barrier.value, y = value.fixed, color = ngo_type,
             group = interaction(ngo_type, cowcode))) + 
  geom_rect(data = df.panel.highlight.h3, aes(fill = highlight), inherit.aes = FALSE,
            xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, alpha = 0.15) +
  geom_vline(xintercept = 0, colour = "black", size = 0.5) + 
  geom_smooth(method = "lm", size = 0.1, alpha = 0.1) +
  geom_smooth(data = df.plot.data.mean.both.h3, size = 1, method = "lm") +
  labs(x = "Difference from average level of NGO legislation in country (within effect)",
       y = "Predicted proportion of\naid channeled to type of NGO\nin the following year") +
  scale_y_continuous(labels = percent_format(accuracy = 1)) +
  scale_fill_manual(values = c(NA, "grey50"), guide = FALSE) +
  scale_color_manual(values = c("grey60", "black"), name = NULL) + 
  facet_wrap(~ barrier.clean, scales = "free_x", ncol = 2) +
  theme_donors() + 
  theme(axis.title.x = element_text(hjust = 0),
        legend.justification = "left",
        legend.margin = margin(l = 0))
fig.predicted.h3.barriers.both

H2: Zero-one-inflated beta

The big caveat here is that we can’t do a 1:1 mapping of these coefficients to the fractional logit models, since the coefficients here only apply to the non-zero and non-one parts of the model. What’s important for robustness is that the coefficients all go in the same direction as the fractional logit model (though with less significance, since different parts of the model explain the presence/absence significance).

MCMC diagnostics

Check fit

Again, use one of the imputed models (mod.h2.barriers.total.zoib) to check for fit and convergence.

Posterior predictive distribution vs. observed outcome?

Results

Coefficients

vars.to.plot <- c("barriers.total_within", "barriers.total_between",
                  "advocacy_within", "advocacy_between", 
                  "entry_within", "entry_between", 
                  "funding_within", "funding_between",
                  "csre_within", "csre_between")

mods.h2.melded.zoib <- bayes.meld(mods.h2.next_year.bayes.zoib,
                                  vars.to.plot, exponentiate = TRUE)$melded.summary

plot.data <- mods.h2.melded.zoib %>%
  left_join(coef.names.all, by = "term") %>%
  left_join(model.names, by = c("model.name" = "model")) %>% 
  mutate(term = factor(term, levels = vars.to.plot, ordered = TRUE)) %>%
  arrange(desc(term)) %>%
  mutate(term_plot = ordered(fct_inorder(term_plot_short))) %>%
  mutate(coef.type = case_when(
    str_detect(.$term, "_within") ~ "Within",
    str_detect(.$term, "_between") ~ "Between",
  )) %>% 
  mutate(coef.type = factor(coef.type, levels = c("Within", "Between"),
                            ordered = TRUE)) %>%
  mutate(model_clean = factor(model_clean, levels = rev(unique(model_clean)), ordered = TRUE))

fig.coefs.h2.zoib <- ggplot(plot.data, aes(x = med, y = term_plot, colour = model_clean)) +
  geom_vline(xintercept = 1, colour = "black", size = 0.5) +  
  geom_pointrangeh(aes(xmin = `2.5%`, xmax = `97.5%`), size = 0.5, fatten = 3) + 
  labs(x = "Odds ratio ", y = NULL) +
  scale_colour_manual(values = model.colors, name = NULL) +
  expand_limits(x = c(0.6, 1.3)) +
  guides(color = guide_legend(override.aes = list(size = 0.25))) +
  theme_donors() + 
  theme(legend.justification = "left",
        legend.box.margin = margin(l = -0.75, t = -0.5, unit = "lines"),
        axis.title.x = element_text(hjust = 0)) +
  facet_wrap(~ coef.type, scales = "free", ncol = 2)
fig.coefs.h2.zoib

Complete results in a table

The effect of anti-NGO legislation on the proportion of OECD overseas development assistance (ODA) committed to contentious purposes in the following year (H2), full models. Each cell contains the parameter’s posterior median, the 95% credible interval, and the probability that the parameter is greater than one (in italics). {#tbl:h2-coefs-zoib}
(1) (2) (3)
Fixed part (odds ratios)
Total legal barrierswithin 1.01
(0.97, 1.05); 0.74
Total legal barriersbetween 1.00
(0.94, 1.07); 0.54
Barriers to advocacywithin 0.96
(0.80, 1.15); 0.33
Barriers to advocacybetween 0.94
(0.72, 1.21); 0.32
Barriers to entrywithin 1.03
(0.94, 1.12); 0.73
Barriers to entrybetween 1.07
(0.95, 1.20); 0.85
Barriers to fundingwithin 1.02
(0.93, 1.12); 0.68
Barriers to fundingbetween 0.97
(0.85, 1.11); 0.32
0.18
(0.17, 0.20); 0.00
0.18
(0.17, 0.20); 0.00
0.18
(0.17, 0.20); 0.00
0.03
(0.02, 0.04); 0.00
0.03
(0.02, 0.04); 0.00
0.03
(0.02, 0.04); 0.00
Civil society reg. env. (CSRE)within 1.06
(1.02, 1.09); 1.00
Civil society reg. env. (CSRE)between 1.02
(0.97, 1.08); 0.78
Polity IV (0–10)within 1.03
(1.00, 1.05); 0.99
1.03
(1.00, 1.05); 0.98
0.99
(0.96, 1.02); 0.34
Polity IV (0–10)between 1.04
(1.01, 1.08); 0.99
1.04
(1.00, 1.07); 0.98
1.02
(0.97, 1.08); 0.79
GDP per capita (log)within 0.90
(0.78, 1.02); 0.05
0.89
(0.78, 1.02); 0.05
0.90
(0.78, 1.03); 0.06
GDP per capita (log)between 0.84
(0.78, 0.89); 0.00
0.84
(0.78, 0.90); 0.00
0.84
(0.79, 0.89); 0.00
Trade as % of GDPwithin 1.00
(1.00, 1.00); 0.11
1.00
(1.00, 1.00); 0.11
1.00
(1.00, 1.00); 0.10
Trade as % of GDPbetween 1.00
(1.00, 1.00); 0.99
1.00
(1.00, 1.00); 0.99
1.00
(1.00, 1.00); 0.99
Corruptionwithin 1.00
(0.97, 1.04); 0.57
1.00
(0.97, 1.04); 0.56
1.01
(0.97, 1.05); 0.69
Corruptionbetween 1.04
(1.00, 1.08); 0.97
1.04
(1.00, 1.07); 0.96
1.04
(1.00, 1.08); 0.98
Proportion of contentious aid 4.83
(3.61, 6.43); 1.00
4.78
(3.55, 6.38); 1.00
4.80
(3.56, 6.40); 1.00
Internal conflict in last 5 years 1.01
(0.93, 1.10); 0.61
1.01
(0.93, 1.10); 0.59
1.03
(0.94, 1.12); 0.71
Natural disasters 0.99
(0.98, 1.01); 0.19
0.99
(0.98, 1.01); 0.20
0.99
(0.98, 1.01); 0.12
After 1989 2.35
(1.75, 3.18); 1.00
2.36
(1.75, 3.18); 1.00
2.21
(1.64, 2.94); 1.00
Constant 0.06
(0.03, 0.13); 0.00
0.06
(0.03, 0.12); 0.00
0.07
(0.03, 0.13); 0.00
Random part (original coefficients)
Within-country variability 0.35 0.36 0.35
Within-year variability 0.35 0.36 0.35
Model details
Imputed datasets (m) 5 5 5
N 3922 3922 3922
Posterior sample size 4000 4000 4000
Notes
Zero-one-inflated beta models. Odds ratios reported.

H3: Zero-one-inflated beta

MCMC diagnostics

Check fit

Again, use one of the imputed models (mod.h3.barriers.total.zoib) to check for fit and convergence.

Posterior predictive distribution vs. observed outcome?

Results

Proportion to domestic NGOs

The effect of anti-NGO legislation on the proportion of US aid channeled through domestic NGOs in the following year (H3), full models. Each cell contains the parameter’s posterior median, the 95% credible interval, and the probability that the parameter is greater than one (in italics) {#tbl:h3-domestic-coefs-zoib}
(1) (2) (3)
Fixed part (odds ratios)
Total legal barrierswithin 1.08
(0.99, 1.17); 0.96
Total legal barriersbetween 1.06
(0.97, 1.16); 0.90
Barriers to advocacywithin 1.01
(0.70, 1.45); 0.53
Barriers to advocacybetween 1.35
(0.97, 1.86); 0.96
Barriers to entrywithin 0.85
(0.71, 1.02); 0.04
Barriers to entrybetween 1.11
(0.95, 1.30); 0.91
Barriers to fundingwithin 1.34
(1.11, 1.61); 1.00
Barriers to fundingbetween 0.91
(0.76, 1.09); 0.15
0.38
(0.35, 0.43); 0.00
0.39
(0.35, 0.43); 0.00
0.39
(0.35, 0.43); 0.00
0.05
(0.03, 0.07); 0.00
0.05
(0.03, 0.07); 0.00
0.05
(0.03, 0.07); 0.00
Civil society reg. env. (CSRE)within 0.94
(0.87, 1.04); 0.11
Civil society reg. env. (CSRE)between 0.98
(0.89, 1.08); 0.36
Polity IV (0–10)within 0.94
(0.88, 1.01); 0.05
0.94
(0.88, 1.02); 0.06
0.96
(0.88, 1.04); 0.15
Polity IV (0–10)between 1.01
(0.95, 1.07); 0.62
1.01
(0.95, 1.07); 0.58
1.00
(0.92, 1.09); 0.52
GDP per capita (log)within 1.57
(1.02, 2.28); 0.98
1.55
(1.01, 2.28); 0.98
1.72
(1.10, 2.50); 0.99
GDP per capita (log)between 1.17
(1.05, 1.29); 1.00
1.17
(1.05, 1.30); 1.00
1.17
(1.05, 1.30); 1.00
Trade as % of GDPwithin 1.00
(1.00, 1.01); 0.70
1.00
(1.00, 1.00); 0.69
1.00
(1.00, 1.01); 0.71
Trade as % of GDPbetween 1.00
(0.99, 1.00); 0.06
1.00
(0.99, 1.00); 0.03
1.00
(0.99, 1.00); 0.04
Corruptionwithin 1.05
(0.97, 1.14); 0.88
1.06
(0.98, 1.16); 0.92
1.03
(0.95, 1.12); 0.76
Corruptionbetween 1.02
(0.96, 1.09); 0.75
1.02
(0.95, 1.09); 0.69
1.02
(0.95, 1.08); 0.69
Proportion of aid to domestic NGOs 4.79
(3.34, 6.90); 1.00
4.51
(3.12, 6.47); 1.00
4.58
(3.15, 6.61); 1.00
Internal conflict in last 5 years 1.03
(0.87, 1.22); 0.63
1.03
(0.87, 1.23); 0.64
1.02
(0.86, 1.22); 0.60
Natural disasters 0.98
(0.96, 1.00); 0.05
0.98
(0.96, 1.00); 0.02
0.98
(0.96, 1.00); 0.06
Constant 0.01
(0.00, 0.04); 0.00
0.01
(0.00, 0.04); 0.00
0.01
(0.00, 0.05); 0.00
Random part (original coefficients)
Within-country variability 0.59 0.59 0.60
Within-year variability 0.10 0.10 0.10
Model details
Imputed datasets (m) 5 5 5
N 1751 1751 1751
Posterior sample size 4000 4000 4000
Notes
Zero-one-inflated beta models. Odds ratios reported.

Proportion to foreign NGOs

The effect of anti-NGO legislation on the proportion of US aid channeled through US-based and international NGOs in the following year (H3), full models. Each cell contains the parameter’s posterior median, the 95% credible interval, and the probability that the parameter is greater than one (in italics) {#tbl:h3-foreign-coefs-zoib}
(1) (2) (3)
Fixed part (odds ratios)
Total legal barrierswithin 0.99
(0.93, 1.06); 0.41
Total legal barriersbetween 1.02
(0.94, 1.11); 0.71
Barriers to advocacywithin 0.91
(0.65, 1.28); 0.31
Barriers to advocacybetween 1.07
(0.81, 1.42); 0.68
Barriers to entrywithin 1.10
(0.95, 1.27); 0.89
Barriers to entrybetween 1.00
(0.86, 1.16); 0.51
Barriers to fundingwithin 0.94
(0.80, 1.10); 0.22
Barriers to fundingbetween 1.03
(0.87, 1.21); 0.64
0.27
(0.24, 0.30); 0.00
0.27
(0.24, 0.30); 0.00
0.27
(0.24, 0.30); 0.00
0.06
(0.04, 0.09); 0.00
0.06
(0.04, 0.09); 0.00
0.06
(0.04, 0.09); 0.00
Civil society reg. env. (CSRE)within 1.02
(0.94, 1.10); 0.69
Civil society reg. env. (CSRE)between 0.99
(0.91, 1.08); 0.41
Polity IV (0–10)within 0.92
(0.87, 0.97); 0.00
0.91
(0.86, 0.97); 0.00
0.91
(0.86, 0.97); 0.00
Polity IV (0–10)between 0.94
(0.89, 0.99); 0.01
0.94
(0.89, 0.99); 0.01
0.94
(0.87, 1.02); 0.06
GDP per capita (log)within 0.56
(0.44, 0.73); 0.00
0.56
(0.44, 0.71); 0.00
0.56
(0.44, 0.71); 0.00
GDP per capita (log)between 0.91
(0.83, 1.01); 0.03
0.91
(0.83, 1.00); 0.03
0.91
(0.83, 1.00); 0.03
Trade as % of GDPwithin 1.00
(0.99, 1.00); 0.05
1.00
(0.99, 1.00); 0.05
1.00
(0.99, 1.00); 0.05
Trade as % of GDPbetween 1.00
(1.00, 1.00); 0.84
1.00
(1.00, 1.01); 0.83
1.00
(1.00, 1.00); 0.82
Corruptionwithin 1.06
(0.98, 1.15); 0.93
1.06
(0.98, 1.15); 0.91
1.07
(0.99, 1.16); 0.94
Corruptionbetween 1.06
(1.00, 1.12); 0.97
1.06
(1.00, 1.13); 0.97
1.05
(1.00, 1.12); 0.96
Proportion of aid to foreign NGOs 3.61
(2.78, 4.67); 1.00
3.57
(2.75, 4.64); 1.00
3.62
(2.80, 4.71); 1.00
Internal conflict in last 5 years 1.09
(0.95, 1.26); 0.88
1.09
(0.95, 1.26); 0.89
1.09
(0.95, 1.25); 0.87
Natural disasters 1.01
(0.99, 1.02); 0.79
1.01
(0.99, 1.02); 0.78
1.01
(0.99, 1.02); 0.80
Constant 0.37
(0.12, 1.08); 0.03
0.37
(0.12, 1.10); 0.04
0.41
(0.15, 1.10); 0.04
Random part (original coefficients)
Within-country variability 0.53 0.54 0.53
Within-year variability 0.04 0.04 0.04
Model details
Imputed datasets (m) 5 5 5
N 1751 1751 1751
Posterior sample size 4000 4000 4000
Notes
Zero-one-inflated beta models. Odds ratios reported.

Plot of proportion to domestic and foreign NGOs

vars.to.plot <- c("barriers.total_within", "barriers.total_between",
                  "advocacy_within", "advocacy_between", 
                  "entry_within", "entry_between", 
                  "funding_within", "funding_between",
                  "csre_within", "csre_between")

mods.h3.dom.melded.zoib <- bayes.meld(mods.h3.dom.next_year.bayes.zoib,
                                      vars.to.plot, exponentiate = TRUE)$melded.summary

coefs.raw.h3.dom.zoib <- mods.h3.dom.melded.zoib %>%
  left_join(coef.names.all, by = "term") %>%
  left_join(model.names, by = c("model.name" = "model")) %>% 
  mutate(term = factor(term, levels = vars.to.plot, ordered = TRUE)) %>%
  arrange(desc(term)) %>%
  mutate(term_plot = ordered(fct_inorder(term_plot_short))) %>%
  mutate(coef.type = case_when(
    str_detect(.$term, "_within") ~ "Within",
    str_detect(.$term, "_between") ~ "Between",
  )) %>% 
  mutate(coef.type = factor(coef.type, levels = c("Within", "Between"),
                            ordered = TRUE)) %>%
  mutate(model_clean = factor(model_clean, levels = rev(unique(model_clean)), ordered = TRUE))

mods.h3.foreign.melded.zoib <- bayes.meld(mods.h3.foreign.next_year.bayes.zoib,
                                          vars.to.plot, exponentiate = TRUE)$melded.summary

coefs.raw.h3.foreign.zoib <- mods.h3.foreign.melded.zoib %>%
  left_join(coef.names.all, by = "term") %>%
  left_join(model.names, by = c("model.name" = "model")) %>% 
  mutate(term = factor(term, levels = vars.to.plot, ordered = TRUE)) %>%
  arrange(desc(term)) %>%
  mutate(term_plot = ordered(fct_inorder(term_plot_short))) %>%
  mutate(coef.type = case_when(
    str_detect(.$term, "_within") ~ "Within",
    str_detect(.$term, "_between") ~ "Between",
  )) %>% 
  mutate(coef.type = factor(coef.type, levels = c("Within", "Between"),
                            ordered = TRUE)) %>%
  mutate(model_clean = factor(model_clean, levels = rev(unique(model_clean)), ordered = TRUE))

coefs.h3.both.zoib <- bind_rows(`Domestic NGOs` = coefs.raw.h3.dom.zoib,
                                `Foreign NGOs` = coefs.raw.h3.foreign.zoib,
                                .id = "channel")

fig.coefs.h3.zoib <- ggplot(coefs.h3.both.zoib, aes(y = term_plot, x = med, 
                                                    colour = model_clean)) + 
  geom_vline(xintercept = 1, colour = "black", size = 0.5) + 
  geom_pointrangeh(aes(xmin = `2.5%`, xmax = `97.5%`, shape = channel), 
                   size = 0.5, fatten = 3,
                   position = position_dodgev(height = 0.5)) + 
  labs(x = "Odd ratio", y = NULL) +
  scale_colour_manual(values = model.colors) +
  expand_limits(x = c(0.5, 2)) +
  guides(color = guide_legend(override.aes = list(size = 0.25),
                              title = NULL, nrow = 2, order = 2),
         shape = guide_legend(override.aes = list(size = 0.5, linetype = 0),
                              title = NULL, nrow = 2, reverse = TRUE, order = 1)) +
  theme_donors() + 
  theme(legend.justification = "left",
        legend.box.margin = margin(l = -0.75, t = -0.5, unit = "lines"),
        axis.title.x = element_text(hjust = 0)) +
  facet_wrap(~ coef.type, scales = "free", ncol = 2)
fig.coefs.h3.zoib

LS0tCnRpdGxlOiAiQmF5ZXNpYW4gbW9kZWxzIgphdXRob3I6ICJTdXBhcm5hIENoYXVkaHJ5IGFuZCBBbmRyZXcgSGVpc3MiCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVGJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmlmIChpc1RSVUUoZ2V0T3B0aW9uKCdrbml0ci5pbi5wcm9ncmVzcycpKSkgewogIGtuaXRyOjpyZWFkX2NodW5rKGhlcmU6OmhlcmUoImxpYiIsICJtb2RlbHMtY2h1bmtzLlIiKSkKfSBlbHNlIHsKICBzb3VyY2UoaGVyZTo6aGVyZSgibGliIiwgIm1vZGVscy1jaHVua3MuUiIpKQogICMgcXdyYXBzMjo6bGF6eWxvYWRfY2FjaGVfZGlyKCIwNF9iYXllc2lhbi1tb2RlbHNfY2FjaGUvaHRtbCIpCn0KYGBgCgpgYGB7ciBsb2FkLWxpYnJhcmllcywgbWVzc2FnZT1GQUxTRX0KYGBgCgpgYGB7ciBsb2FkLWRhdGEsIGNhY2hlPVRSVUUsIG1lc3NhZ2U9RkFMU0V9CmBgYAoKYGBge3IgbG9hZC1iYXllc2lhbi1tb2RlbHMsIGNhY2hlPVRSVUV9CmgxLnJhdyA8LSBoZXJlKCJEYXRhIiwgImRhdGFfY2FjaGUiLCAibW9kZWxzX2JheWVzX2gxLnJkcyIpCgpoMi5yYXcgPC0gaGVyZSgiRGF0YSIsICJkYXRhX2NhY2hlIiwgIm1vZGVsc19iYXllc19oMi5yZHMiKQpoMi5yYXcuem9pYiA8LSBoZXJlKCJEYXRhIiwgImRhdGFfY2FjaGUiLCAibW9kZWxzX2JheWVzX2gyX3pvaWIucmRzIikKCmgzLmRvbWVzdGljLnJhdyA8LSBoZXJlKCJEYXRhIiwgImRhdGFfY2FjaGUiLCAibW9kZWxzX2JheWVzX2gzX2RvbWVzdGljLnJkcyIpCmgzLmRvbWVzdGljLnJhdy56b2liIDwtIGhlcmUoIkRhdGEiLCAiZGF0YV9jYWNoZSIsICJtb2RlbHNfYmF5ZXNfaDNfZG9tZXN0aWNfem9pYi5yZHMiKQoKaDMuZm9yZWlnbi5yYXcgPC0gaGVyZSgiRGF0YSIsICJkYXRhX2NhY2hlIiwgIm1vZGVsc19iYXllc19oM19mb3JlaWduLnJkcyIpCmgzLmZvcmVpZ24ucmF3LnpvaWIgPC0gaGVyZSgiRGF0YSIsICJkYXRhX2NhY2hlIiwgIm1vZGVsc19iYXllc19oM19mb3JlaWduX3pvaWIucmRzIikKCmlmIChmaWxlLmV4aXN0cyhoMS5yYXcpICYgZmlsZS5leGlzdHMoaDIucmF3KSAmIAogICAgZmlsZS5leGlzdHMoaDMuZG9tZXN0aWMucmF3KSAmIGZpbGUuZXhpc3RzKGgzLmZvcmVpZ24ucmF3KSkgewogIG1vZHMuaDEubmV4dF95ZWFyLnJhdy5iYXllcyA8LSByZWFkX3JkcyhoMS5yYXcpCiAgCiAgbW9kcy5oMi5uZXh0X3llYXIucmF3LmJheWVzIDwtIHJlYWRfcmRzKGgyLnJhdykKICBtb2RzLmgyLm5leHRfeWVhci5yYXcuYmF5ZXMuem9pYiA8LSByZWFkX3JkcyhoMi5yYXcuem9pYikKICAKICBtb2RzLmgzLmRvbS5uZXh0X3llYXIucmF3IDwtIHJlYWRfcmRzKGgzLmRvbWVzdGljLnJhdykKICBtb2RzLmgzLmRvbS5uZXh0X3llYXIucmF3LnpvaWIgPC0gcmVhZF9yZHMoaDMuZG9tZXN0aWMucmF3LnpvaWIpCiAgCiAgbW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5yYXcgPC0gcmVhZF9yZHMoaDMuZm9yZWlnbi5yYXcpCiAgbW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5yYXcuem9pYiA8LSByZWFkX3JkcyhoMy5mb3JlaWduLnJhdy56b2liKQp9IGVsc2UgewogIHN0b3AoIlJ1biBEYXRhL3J1bl9iYXllc19yZW1vdGUuUiB0byBnZW5lcmF0ZSB0aGUgbW9kZWwgZGF0YSIpCn0KYGBgCgpgYGB7ciBmdXJyciwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShmdXJycikKcGxhbihtdWx0aXByb2Nlc3MpCmBgYAoKYGBge3IgaGVscGZ1bC1mdW5jdGlvbnN9CmBgYAoKYGBge3IgaHV4cmVnLWZ1bmN0aW9uc30KIyBXcmFwcGVycyBhcm91bmQgdGlkeS5zdGFucmVnIGFuZCBnbGFuY2Uuc3RhbnJlZyBzbyB0aGF0IHdlIGNhbiByZXNjYWxlIGFuZAojIGV4cG9uZW50aWF0ZSBjb2VmZmljaWVudHMgaW4gaHV4cmVnCnRpZHkuc2NhbGVtY21jIDwtIGZ1bmN0aW9uKHgsIHNjYWxpbmdzID0gTlVMTCwgZXhwb25lbnRpYXRlID0gRkFMU0UsIC4uLikgewogICMgVGhpcyBpcyBoYWNreSwgYnV0IGl0IHdvcmtzLiBSZW1vdmUgdGhlIGN1c3RvbSAic2NhbGVtY21jIiBjbGFzcyBzbyB0aGF0CiAgIyByZWd1bGFyIGJyb29tIGZ1bmN0aW9ucyB3b3JrIG9uIHgKICBjbGFzcyh4KSA8LSBjbGFzcyh4KVtjbGFzcyh4KSAhPSAic2NhbGVtY21jIl0KCiAgbm9uX3NjYWxlZCA8LSB0aWR5KHgsIC4uLikKICAKICBhZGp1c3RlZCA8LSBub25fc2NhbGVkICU+JSAKICAgIGxlZnRfam9pbihzY2FsaW5ncywgYnkgPSAidGVybSIpICU+JSAKICAgIGdhdGhlcihjb2x1bW4sIHZhbHVlLCAtdGVybSwgLXNjYWxlZCkgJT4lIAogICAgbXV0YXRlKHZhbHVlX3Jlc2NhbGVkID0gaWZlbHNlKCFpcy5uYShzY2FsZWQpLCB2YWx1ZSAvIHNjYWxlZCwgdmFsdWUpKSAlPiUgCiAgICBzZWxlY3QodGVybSwgY29sdW1uLCB2YWx1ZV9yZXNjYWxlZCkgJT4lIAogICAgc3ByZWFkKGNvbHVtbiwgdmFsdWVfcmVzY2FsZWQpCiAgCiAgaWYgKGV4cG9uZW50aWF0ZSkgewogICAgYWRqdXN0ZWQgPC0gYWRqdXN0ZWQgJT4lCiAgICAgIG11dGF0ZV9hdCh2YXJzKC10ZXJtLCAtc3RkLmVycm9yKSwgZXhwKQogIH0KICAKICByZXR1cm4oYWRqdXN0ZWQpCn0KCmdsYW5jZS5zY2FsZW1jbWMgPC0gZnVuY3Rpb24oeCwgLi4uKSB7CiAgY2xhc3MoeCkgPC0gY2xhc3MoeClbY2xhc3MoeCkgIT0gInNjYWxlbWNtYyJdCiAgcmV0dXJuKGdsYW5jZSh4LCAuLi4pKQp9CgphZGRfc2NhbGVtY21jIDwtIGZ1bmN0aW9uKHgpIHsKICBjbGFzcyh4KSA8LSBjKCJzY2FsZW1jbWMiLCBjbGFzcyh4KSkKICByZXR1cm4oeCkKfQpgYGAKCi0tLQoKIyMgSH4xfjogRG9ub3JzIHJlZHVjZSBhaWQgaW4gcmVzcG9uc2UgdG8gbGVnaXNsYXRpb24KCj4gKipIfjF+Kio6IEluIHJlc3BvbnNlIHRvIHJlc3RyaWN0aXZlIE5HTyBsZWdpc2xhdGlvbiwgYmlsYXRlcmFsLCBtdWx0aWxhdGVyYWwsIGFuZCBwcml2YXRlIGRvbm9ycyBtYXkgcmVkdWNlIHRoZWlyIGFpZCB0byByZXByZXNzaXZlIGNvdW50cmllcy4KCiQkbG4oIFx0ZXh0e09EQX1fe1x0ZXh0e09FQ0R9fSApX3tpLCB0KzF9ID0gXHRleHR7TkdPIGxlZ2lzbGF0aW9ufV97aXR9ICsgXHRleHR7Y29udHJvbHN9X3tpdH0kJAoKT3VyIGRlcGVuZGVudCB2YXJpYWJsZSBmb3IgdGhpcyBoeXBvdGhlc2lzIGlzIHRoZSBsb2cgb2YgT0RBIChjb25zdGFudCAyMDExIGRvbGxhcnMpLCBsZWFkZWQgYnkgb25lIHllYXIgc28gd2UgZG9uJ3QgaGF2ZSB0byBsYWcgZXZlcnkgb3RoZXIgaW5kZXBlbmRlbnQgdmFyaWFibGUuIEFzIGEgcm9idXN0bmVzcyBjaGVjaywgd2UgYWxzbyBpbmNsdWRlIG1vZGVscyB3aXRoIGxvZyBPREEgbGVhZGVkIGJ5IDIgeWVhcnMgYW5kIDUgeWVhcnMgdG8gYWNjb3VudCB0aGUgaW1wbGVtZW50YXRpb24gcGVyaW9kIGZvbGxvd2luZyB0aGUgcGFzc2FnZSBvZiBhIGxhdy4KCldlIGxvb2sgYXQgTkdPIGxlZ2lzbGF0aW9uIGluIGEgZmV3IGRpZmZlcmVudCB3YXlzOgoKLSBgYmFycmllcnMudG90YWxgOiBOdW1iZXIgb2YgYW50aS1OR08gbGVnYWwgYmFycmllcnMgaW4gYSBjb3VudHJ5LXllYXIKLSBgYWR2b2NhY3kgKyBlbnRyeSArIGZ1bmRpbmdgOiBOdW1iZXIgb2YgYW50aS1OR08gbGVnYWwgYmFycmllcnMgYnkgdHlwZSBvZiBiYXJyaWVyCi0gYGNzcmVgOiBDaXZpbCBzb2NpZXR5IHJlZ3VsYXRvcnkgZW52aXJvbm1lbnQgaW5kZXggKENTUkUpLCByYW5naW5nIGZyb20gcm91Z2hseSAtNCB0byA0IChoaWdoZXIgdmFsdWVzID0gYmV0dGVyIGNpdmlsIHNvY2lldHkgcmVndWxhdGlvbnMpCgpgYGB7ciBoMS1tb2RlbHMtYmF5ZXMtMSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRX0KIyBHZXQgc2NhbGluZyBmYWN0b3JzCnNjYWxlcy5oMS5uZXh0X3llYXIgPC0gbW9kcy5oMS5uZXh0X3llYXIucmF3LmJheWVzICU+JSAKICBmaWx0ZXIobSAhPSAib3JpZ2luYWwiKSAlPiUgCiAgc2VsZWN0KG0sIHN0YXJ0c193aXRoKCJzY2FsZXMiKSkgJT4lIAogIGdhdGhlcihzY2FsZXMubmFtZSwgc2NhbGVzLCAtbSkKCiMgR2V0IG1vZGVsIGRldGFpbHMgYW5kIHBhcmFtZXRlcnMKbW9kcy5oMS5uZXh0X3llYXIuYmF5ZXMgPC0gbW9kcy5oMS5uZXh0X3llYXIucmF3LmJheWVzICU+JQogIGZpbHRlcihtICE9ICJvcmlnaW5hbCIpICU+JSAKICBzZWxlY3QobSwgc3RhcnRzX3dpdGgoIm1vZCIpKSAlPiUgCiAgZ2F0aGVyKG1vZGVsLm5hbWUsIG1vZGVsLCAtbSkgJT4lCiAgIyBGT1IgU09NRSBSRUFTT04gZ2xhbmNlIHRha2VzIGZvcmV2ZXIgdG8gY2FsY3VsYXRlIHRocmVlIG51bWJlcnMKICBtdXRhdGUoZ2xhbmNlID0gbW9kZWwgJT4lIG1hcChnbGFuY2UpLAogICAgICAgICB0aWR5ID0gbW9kZWwgJT4lIG1hcCh0aWR5KSkgJT4lIAogIGJpbmRfY29scyhzZWxlY3Qoc2NhbGVzLmgxLm5leHRfeWVhciwgLW0pKQpgYGAKCgojIyMgTUNNQyBkaWFnbm9zdGljcyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCiMjIyMgQ2hlY2sgZml0CgpXZSB1c2Ugb25lIG9mIHRoZSBpbXB1dGVkIG1vZGVscyAoYG1vZC5oMS5iYXJyaWVycy50b3RhbGApIHRvIGNoZWNrIGZvciBmaXQgYW5kIGNvbnZlcmdlbmNlLgoKYGBge3IgaDEtZGlhZ25vc3RpY3MtYmF5ZXN9Cm1vZGVsLnRvLmNoZWNrIDwtIG1vZHMuaDEubmV4dF95ZWFyLmJheWVzICU+JQogIGZpbHRlcihtID09ICJpbXAxIiwgbW9kZWwubmFtZSA9PSAibW9kLmgxLmJhcnJpZXJzLnRvdGFsIikgJT4lCiAgc2VsZWN0KG1vZGVsKSAlPiUgLltbMV1dICU+JSAuW1sxXV0KYGBgCgpIb3cgd2VsbCBkb2VzIHRoZSBwb3N0ZXJpb3IgcHJlZGljdGl2ZSBkaXN0cmlidXRpb24gZml0IHRoZSBvYnNlcnZlZCBvdXRjb21lPyBOb3QgZ3JlYXQsIGJ1dCBub3QgcGVyZmVjdGx5LiBUaGUgYWN0dWFsIGRpc3RyaWJ1dGlvbiBpcyBiaW1vZGFsLCB3aXRoIGEgYnVuY2ggb2YgemVyb3MsIGFuZCB0aGUgbW9kZWwgZ2V0cyB0aGUgdHdvIHBlYWtzLCBidXQgdGhleSdyZSBzaGFsbG93LiBXZSBjYW4gbGl2ZSB3aXRoIGl0LCB0aG91Z2guCgpgYGB7ciBoMS1kaWFnLWRlbnNpdHl9CnBwX2NoZWNrKG1vZGVsLnRvLmNoZWNrLCB0eXBlID0gImRlbnNfb3ZlcmxheSIsIG5zYW1wbGVzID0gMTApICsgCiAgdGhlbWVfZG9ub3JzKCkKYGBgCgojIyMjIENoZWNrIGNvbnZlcmdlbmNlCgpXaGF0IGFib3V0IGNoYWluIGNvbnZlcmdlbmNlPyBUaGVzZSBzaG91bGQgbG9vayBsaWtlIHRvcHMgaWYgZXZlcnl0aGluZyBjb252ZXJnZXMsIHdpdGggbm8gb2JzZXJ2YXRpb25zIGF0IDAgaW4gdGhlIG1lYW4gTWV0cm9wb2xpcy1IYXN0aW5ncyBhY2VwdGFuY2UgcGFuZWwuCgpgYGB7ciBoMS1kaWFnLWRpdmVyZ2VuY2V9CnJzdGFuOjpzdGFuX2RpYWcobW9kZWwudG8uY2hlY2skZml0LCBpbmZvcm1hdGlvbiA9ICJkaXZlcmdlbmNlIikKYGBgCgoKIyMjIE1lcmdpbmcgTUNNQyBjaGFpbnMKCk1lcmdpbmcgdGhlIE1DTUMgY2hhaW5zIGlzIHJlbGF0aXZlbHkgZWFzeSwgYnV0IHRoZW4gd29ya2luZyB3aXRoIHRoZSAyMCwwMDAgcm93cyBvZiBzaW11bGF0aW9ucyBpcyB0cmlja2llciwgc2luY2UgbWVyZ2luZyBtYWtlcyB0aGUgbW9kZWwgYSBgZGF0YV9mcmFtZWAgaW50ZWFkIG9mIGEgYHN0YW5yZWdgIG9iamVjdCwgbWVhbmluZyBhbGwgdGhlIGNvbnZlbmllbmNlIGZ1bmNpb25zIGxpa2UgYHBvc3Rlcmlvcl9wcmVkaWN0KClgIGRvbid0IHdvcmsgYW55bW9yZS4gVGhhdCBtZWFucyBsb3RzIG9mIG1hdGguIFVnaC4KClNvIGluc3RlYWQsIHdlIGRvIHR3byB0aGluZ3MuIFdlIGNhbGN1bGF0ZSB0aGUgcG9zdGVyaW9yIG1lZGlhbiBhbmQgTUQgYnkganVzdCBtZXJnaW5nIGFsbCB0aGUgTUNNQyBjaGFpbnMgZnJvbSBhbGwgaW1wdXRhdGlvbnMuIEJlY3Vhc2UgYHBvc3Rlcmlvcl9wcmVkaWN0KClgIGRvZXNuJ3Qgd29yayBvbiBtZXJnZWQgY2hhaW5zIGxpa2UgdGhpcywgd2UgcnVuIGBwb3N0ZXJpb3JfcHJlZGljdCgpYCBvbiBlYWNoIGltcHV0YXRpb24gYW5kIHRoZW4gdGFrZSB0aGUgbWVhbiBvZiBlYWNoIGltcHV0YXRpb24ncyBjcmVkaWJsZSBpbnRlcnZhbHMuIFRoaXMgc2hvdWxkIGJlIG9rYXnigJR0YWtpbmcgdGhlIG1lZGlhbiBvZiBtZWRpYW5zIChvciBbbWVhbiBvZiBtZWFuc10oaHR0cDovL3N0YXRzLnN0YWNrZXhjaGFuZ2UuY29tL3EvMTMzMTM4LzMwMjUpKSB3aWxsIHlpZWxkIHRoZSBzYW1lIHZhbHVlIGlmIHRoZSBncm91cCBzaXplcyBhcmUgdGhlIHNhbWUgKHRodXMgYXZvaWRpbmcgU2ltcHNvbidzIFBhcmFkb3gpLiBMaWtlIHRoaXM6CgpgYGB7ciBtZWRpYW4tb2YtbWVkaWFuc30KZ3JvdXAxID0gYygxLCAyLCAzLCA0KQpncm91cDIgPSBjKDUsIDYsIDcsIDgpCgptZWRpYW4oYyhncm91cDEsIGdyb3VwMikpCm1lZGlhbihjKG1lZGlhbihncm91cDEpLCBtZWRpYW4oZ3JvdXAyKSkpCmBgYAoKSWYgaXQncyBhIGxpdHRsZSBvZmYsIGl0IHNob3VsZCBiZSBva2F54oCUaXQnbGwgYmUgb2ZmIGJ5IGFuIG9yZGVyIG9mIDAuMDAxaXNoLiAKCgojIyMgUmVzdWx0cyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCiMjIyMgQ29lZmZpY2llbnRzCgpgYGB7ciBoMS1wbG90LWNvZWZzLCBmaWcud2lkdGg9NS41LCBmaWcuaGVpZ2h0PTIuNX0KdmFycy50by5wbG90IDwtIGMoImJhcnJpZXJzLnRvdGFsX3dpdGhpbiIsICJiYXJyaWVycy50b3RhbF9iZXR3ZWVuIiwKICAgICAgICAgICAgICAgICAgImFkdm9jYWN5X3dpdGhpbiIsICJhZHZvY2FjeV9iZXR3ZWVuIiwgCiAgICAgICAgICAgICAgICAgICJlbnRyeV93aXRoaW4iLCAiZW50cnlfYmV0d2VlbiIsIAogICAgICAgICAgICAgICAgICAiZnVuZGluZ193aXRoaW4iLCAiZnVuZGluZ19iZXR3ZWVuIiwKICAgICAgICAgICAgICAgICAgImNzcmVfd2l0aGluIiwgImNzcmVfYmV0d2VlbiIpCgptb2RzLmgxLm1lbGRlZCA8LSBiYXllcy5tZWxkKG1vZHMuaDEubmV4dF95ZWFyLmJheWVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcnMudG8ucGxvdCkkbWVsZGVkLnN1bW1hcnkKCnBsb3QuZGF0YSA8LSBtb2RzLmgxLm1lbGRlZCAlPiUKICBsZWZ0X2pvaW4oY29lZi5uYW1lcy5hbGwsIGJ5ID0gInRlcm0iKSAlPiUKICBsZWZ0X2pvaW4obW9kZWwubmFtZXMsIGJ5ID0gYygibW9kZWwubmFtZSIgPSAibW9kZWwiKSkgJT4lIAogIG11dGF0ZShjb2VmLnR5cGUgPSBjYXNlX3doZW4oCiAgICBzdHJfZGV0ZWN0KHRlcm0sICJfd2l0aGluIikgfiAiV2l0aGluIiwKICAgIHN0cl9kZXRlY3QodGVybSwgIl9iZXR3ZWVuIikgfiAiQmV0d2VlbiIsCiAgKSkgJT4lIAogIG11dGF0ZSh0ZXJtID0gZmFjdG9yKHRlcm0sIGxldmVscyA9IHZhcnMudG8ucGxvdCwgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKGRlc2ModGVybSkpICU+JQogIG11dGF0ZSh0ZXJtX3Bsb3Rfc2hvcnQgPSBmY3RfaW5vcmRlcih0ZXJtX3Bsb3Rfc2hvcnQsIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgbXV0YXRlKGNvZWYudHlwZSA9IGZhY3Rvcihjb2VmLnR5cGUsIGxldmVscyA9IGMoIldpdGhpbiIsICJCZXR3ZWVuIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpICU+JQogIG11dGF0ZShtb2RlbF9jbGVhbiA9IGZhY3Rvcihtb2RlbF9jbGVhbiwgbGV2ZWxzID0gcmV2KHVuaXF1ZShtb2RlbF9jbGVhbikpLCBvcmRlcmVkID0gVFJVRSkpCgpmaWcuY29lZnMuaDEgPC0gZ2dwbG90KHBsb3QuZGF0YSwgYWVzKHggPSBtZWQsIHkgPSB0ZXJtX3Bsb3Rfc2hvcnQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhtaW4gPSBgMi41JWAsIHhtYXggPSBgOTcuNSVgLCBjb2xvdXIgPSBtb2RlbF9jbGVhbikpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMC41KSArIAogIGdlb21fcG9pbnRyYW5nZWgoc2l6ZSA9IDAuNSwgZmF0dGVuID0gMykgKwogIGxhYnMoeCA9ICJQb3N0ZXJpb3IgbWVkaWFuIGNoYW5nZSBpbiBsb2cgT0RBIGluIGZvbGxvd2luZyB5ZWFyIiwgeSA9IE5VTEwpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IG1vZGVsLmNvbG9ycywgbmFtZSA9IE5VTEwpICsKICBleHBhbmRfbGltaXRzKHggPSBjKC0yLCAxKSkgKwogIGd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAwLjI1KSkpICsKICB0aGVtZV9kb25vcnMoKSArIAogIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gImxlZnQiLAogICAgICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKGwgPSAtMC43NSwgdCA9IC0wLjUsIHVuaXQgPSAibGluZXMiKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwKSkgKwogIGZhY2V0X3dyYXAofiBjb2VmLnR5cGUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDIpCmZpZy5jb2Vmcy5oMQoKZmlnLnNhdmUuY2Fpcm8oZmlnLmNvZWZzLmgxLCBmaWxlbmFtZSA9ICJmaWctY29lZnMtaDEtYmF5ZXMiLAogICAgICAgICAgICAgICB3aWR0aCA9IDUuNSwgaGVpZ2h0ID0gMi41KQpgYGAKCiMjIyMgQ29tcGxldGUgcmVzdWx0cyBpbiBhIHRhYmxlCgpgYGB7ciBoMS10YWJsZSwgcmVzdWx0cz0iYXNpcyIsIHdhcm5pbmc9RkFMU0V9CmNhcHRpb24gPC0gIlRoZSBlZmZlY3Qgb2YgYW50aS1OR08gbGVnaXNsYXRpb24gb24gT0VDRCBvdmVyc2VhcyBkZXZlbG9wbWVudCBhc3Npc3RhbmNlIChPREEpIGluIHRoZSBmb2xsb3dpbmcgeWVhciAoSH4xfiksIGZ1bGwgbW9kZWxzLiBFYWNoIGNlbGwgY29udGFpbnMgdGhlIHBhcmFtZXRlcidzIHBvc3RlcmlvciBtZWRpYW4sIHRoZSA5NSUgY3JlZGlibGUgaW50ZXJ2YWwsIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgcGFyYW1ldGVyIGlzIGdyZWF0ZXIgdGhhbiB6ZXJvIChpbiBpdGFsaWNzKS4geyN0Ymw6aDEtY29lZnN9Igpub3RlIDwtIGMoIkRlcGVuZGVudCB2YXJpYWJsZSBsb2cgdHJhbnNmb3JtZWQuIikKdGFibGUuaDEgPC0gYmF5ZXNnYXplcihtb2RzLmgxLm5leHRfeWVhci5iYXllcywKICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gY2FwdGlvbiwgbm90ZSA9IG5vdGUpCgpjYXQodGFibGUuaDEpCmNhdCh0YWJsZS5oMSwgZmlsZSA9IGhlcmUoIk91dHB1dCIsICJ0YmwtaDEtY29lZnMtYmF5ZXMubWQiKSkKYGBgCgojIyMjIENvbXBsZXRlIHJlc3VsdHMgKG5vbmltcHV0ZWQpCgpgYGB7ciBoMS1uby1pbXB1dGF0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIFRoZSBzY2FsaW5nIGZhY3RvcnMgYXJlIGFsbCB0aGUgc2FtZSBhY3Jvc3MgdGhlIHRocmVlIG1vZGVscywgc2luY2UgdGhleSB1c2UKIyB0aGUgc2FtZSBkYXRhc2V0LCBzbyB3ZSBvbmx5IG5lZWQgc2NhbGVzX2gxLjEKc2NhbGVzLmgxLm5leHRfeWVhci5uby5pbXAgPC0gbW9kcy5oMS5uZXh0X3llYXIucmF3LmJheWVzICU+JSAKICBmaWx0ZXIobSA9PSAib3JpZ2luYWwiKSAlPiUgCiAgc2VsZWN0KG0sIHN0YXJ0c193aXRoKCJzY2FsZXMiKSkgJT4lIAogIHB1bGwoc2NhbGVzX2gxLjEpICU+JSAuW1sxXV0KCiMgR2V0IG1vZGVsIGRldGFpbHMgYW5kIHBhcmFtZXRlcnMKbW9kcy5oMS5uZXh0X3llYXIuYmF5ZXMubm8uaW1wIDwtIG1vZHMuaDEubmV4dF95ZWFyLnJhdy5iYXllcyAlPiUKICBzZWxlY3QoLWNvbnRhaW5zKCJzY2FsZXMiKSkgJT4lIAogIGZpbHRlcihtID09ICJvcmlnaW5hbCIpICU+JSAKICBnYXRoZXIobW9kZWwubmFtZSwgbW9kZWwsIC1tKSAlPiUKICBtdXRhdGUoZ2xhbmNlID0gbW9kZWwgJT4lIG1hcChnbGFuY2UpLAogICAgICAgICB0aWR5ID0gbW9kZWwgJT4lIG1hcCh0aWR5LCBlZmZlY3RzID0gImZpeGVkIikpICU+JSAKICBtdXRhdGUobW9kZWxfc2NhbGUgPSBtb2RlbCAlPiUgbWFwKGFkZF9zY2FsZW1jbWMpKQoKaDFfY29lZnMgPC0gbW9kcy5oMS5uZXh0X3llYXIuYmF5ZXMubm8uaW1wICU+JQogIHVubmVzdCh0aWR5KSAlPiUgCiAgZmlsdGVyKCFkdXBsaWNhdGVkKHRlcm0sIGZyb21MYXN0ID0gVFJVRSkpICU+JQogIG11dGF0ZSh0ZXJtX2pvaW4gPSBzdHJfcmVwbGFjZSh0ZXJtLCAiVFJVRSIsICIiKSkgJT4lIAogIGxlZnRfam9pbihjb2VmLm5hbWVzLmFsbCwgYnkgPSBjKCJ0ZXJtX2pvaW4iID0gInRlcm0iKSkgJT4lIAogIGZpbHRlcih0ZXJtICE9ICJJbnRlcmNlcHQiKQoKaDFfY29lZnNfbmFtZWQgPC0gaDFfY29lZnMgJT4lIHB1bGwodGVybSkgJT4lIAogIHNldF9uYW1lcyhoMV9jb2VmcyR0ZXJtX2NsZWFuKQoKaHV4cmVnKG1vZHMuaDEubmV4dF95ZWFyLmJheWVzLm5vLmltcCRtb2RlbF9zY2FsZSwKICAgICAgIGNvZWZzID0gYyhoMV9jb2Vmc19uYW1lZCwgQ29uc3RhbnQgPSAiSW50ZXJjZXB0IiksCiAgICAgICBzdGFycyA9IE5VTEwsIHN0YXRpc3RpY3MgPSBjKE4gPSAibm9icyIpLAogICAgICAgIyBBTEwgT1RIRVIgTUNNQyBvYmplY3RzIHVzZSBjb25mLmxldmVsIHRvIGRldGVybWluZSBjb25maWRlbmNlIGxldmVsLAogICAgICAgIyBidXQgYnJtcyB1c2VzIHByb2IgZm9yIG15c3RlcmlvdXMgcmVhc29ucwogICAgICAgdGlkeV9hcmdzID0gbGlzdChjb25mLmludCA9IFRSVUUsIHByb2IgPSAwLjk1LAogICAgICAgICAgICAgICAgICAgICAgICBlZmZlY3RzID0gImZpeGVkIiwgc2NhbGluZ3MgPSBzY2FsZXMuaDEubmV4dF95ZWFyLm5vLmltcCksCiAgICAgICBlcnJvcl9mb3JtYXQgPSAiKHtjb25mLmxvd30sIHtjb25mLmhpZ2h9KSIpCmBgYAoKIyMjIE1vZGVsIGRpYWdub3N0aWNzCgpDb3VudHJ5IGludGVyY2VwdHMgdmFyeSB3aXRoIGFuIFNEIG9mIDAuMDkgKGV0Yy4pLCB5ZWFyIGludGVyY2VwdHMgdmFyeSB3aXRoIGFuIFNEIG9mIDAuMjYgKGV0Yy4pLCBhbmQgdGhlIFNEIG9mIGVycm9yIG5vdCBhY2NvdW50ZWQgZm9yIGJ5IGVpdGhlciB3aXRoaW4tY291bnRyeSBvciB3aXRoaW4teWVhciB2YXJpYWJpbGl0eSBpcyAyLjY5IChldGMuKQoKCiMjIyBQcmVkaWN0ZWQgT0RBCgpIZXJlLCBmb3IgdGhlIHNha2Ugb2YgY29tcHV0YXRpb25hbCBlZmZpY2llbmN5IGFuZCBzcGVlZCwgd2Ugb25seSB1c2Ugb25lIG9mIHRoZSBpbXB1dGVkIGRhdGFzZXRzIGZvciBwcmVkaWN0aW9ucy4gVGVjaG5pY2FsbHkgd2Ugc2hvdWxkIGJhc2UgdGhlIHByZWRpY3Rpb25zIG9uIGFsbCB0aGUgbWVyZ2VkIGNoYWlucywgYnV0ICgxKSB0aGVyZSdzIG5vIGZ1bmN0aW9uIHRoYXQgY2FuIGhhbmRsZSB0aGF0LCAoMikgaXQgd291bGQgdGFrZSBmb3JldmVyIHRvIHJ1biBwcmVkaWN0aW9ucyBvbiBlYWNoIGluZGl2aWR1YWwgaW1wdXRhdGlvbiBhbmQgdGhlbiBjb21iaW5lIHRoZSBwcmVkaWN0aW9ucywgYW5kICgzKSB0aGVzZSBhcmUgcG9zdGVyaW9yIG1lZGlhbnMgYW55d2F5IGZyb20gb3N0ZW5zaWJseSB0aGUgc2FtZS1pc2ggZGlzdHJpYnV0aW9u4oCUcXVpbnR1cGxpbmcgdGhlIG51bWJlciBvZiBjaGFpbnMgdG8gc2ltdWxhdGUgaXMgb3ZlcmtpbGwgZm9yIGRyYXdpbmcgYSBwaWN0dXJlLgoKYGBge3IgaDEtcHJlZGljdC10b3RhbCwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRX0KbW9kZWwgPC0gbW9kcy5oMS5uZXh0X3llYXIuYmF5ZXMgJT4lCiAgZmlsdGVyKG0gPT0gImltcDEiLCBtb2RlbC5uYW1lID09ICJtb2QuaDEuYmFycmllcnMudG90YWwiKSAlPiUKICBwdWxsKG1vZGVsKSAlPiUgLltbMV1dCgojIEZvciB3aGF0ZXZlciByZWFzb24sIHN0YW5yZWcgb2JqZWN0cyByZXR1cm4gdGhlIGZ1bGwgZGF0YSBmcmFtZSB1c2VkIGluIHRoZQojIG1vZGVsLCBub3QganVzdCB0aGUgbW9kZWwgbWF0cml4LCB3aGVuIGNhbGxpbmcgb2JqZWN0JGRhdGEuIG1vZGVsLmZyYW1lKCkKIyBjaG9rZXMgb24gb2JqZWN0JGZvcm11bGEgYmVjYXVzZSBvZiAoMSB8IHgpIGdyb3VwaW5nIHRlcm1zLCBidXQKIyBnZXRfYWxsX3ZhcnMoKSB3b3Jrcy4KbmV3LmRhdGEgPC0gZ2V0X2FsbF92YXJzKG1vZGVsJGZvcm11bGEsIGRhdGEgPSBtb2RlbCRkYXRhKSAlPiUKICBzZWxlY3QoLWMoYmFycmllcnMudG90YWxfd2l0aGluLCB5ZWFyLCBjb3djb2RlKSkgJT4lCiAgc3VtbWFyaXNlX2FsbCh0eXBpY2FsKSAlPiUKICBtdXRhdGUoaWQgPSAxKSAlPiUKICByaWdodF9qb2luKGV4cGFuZC5ncmlkKGJhcnJpZXJzLnRvdGFsX3dpdGhpbiA9IHNlcSgtMywgNCwgMC41KSwKICAgICAgICAgICAgICAgICAgICAgICAgIGNvd2NvZGUgPSAxMDAwOjEwNDksCiAgICAgICAgICAgICAgICAgICAgICAgICB5ZWFyID0gMTk4MToyMDEyLAogICAgICAgICAgICAgICAgICAgICAgICAgaWQgPSAxKSwgYnkgPSAiaWQiKSAlPiUgc2VsZWN0KC1pZCkKCnByZWRpY3RlZC5oMS5iYXJyaWVycy50b3RhbCA8LSBuZXcuZGF0YSAlPiUKICBuZXN0KC1jb3djb2RlKSAlPiUKICBtdXRhdGUocHJlZGljdGVkID0gZnV0dXJlX21hcCgueCA9IGRhdGEsIH4gZ2VuZXJhdGVfcHJlZGljdGlvbnMoLngpKSkgJT4lCiAgdW5uZXN0KCkKCmRmLnBsb3QuZGF0YS5oMSA8LSBwcmVkaWN0ZWQuaDEuYmFycmllcnMudG90YWwgJT4lCiAgZ3JvdXBfYnkoY293Y29kZSwgYmFycmllcnMudG90YWxfd2l0aGluKSAlPiUKICBzdW1tYXJpc2VfYXQodmFycyhwcmVkaWN0ZWQpLCBmdW5zKG1lYW4oLikpKSAlPiUKICB1bmdyb3VwKCkKCmRmLnBsb3QuZGF0YS5tZWFuLmgxIDwtIGRmLnBsb3QuZGF0YS5oMSAlPiUKICBncm91cF9ieShiYXJyaWVycy50b3RhbF93aXRoaW4pICU+JQogIHN1bW1hcmlzZShwcmVkaWN0ZWQgPSBtZWFuKHByZWRpY3RlZCkpICU+JQogIG11dGF0ZShjb3djb2RlID0gMSkgICMgRmFrZSBjb3VudHJ5IHNvIHRoZSBsaW5lIHBsb3RzCmBgYAoKYGBge3IgaDEtcHJlZGljdC1pbmRpdmlkdWFsLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQpiYXJyaWVycy5pbmRpdi5jbGVhbi5uYW1lcyA8LSB0cmliYmxlKAogIH5iYXJyaWVyLCB+YmFycmllci5jbGVhbiwKICAiYWR2b2NhY3lfd2l0aGluIiwgIkJhcnJpZXJzIHRvIGFkdm9jYWN5IiwKICAiZW50cnlfd2l0aGluIiwgIkJhcnJpZXJzIHRvIGVudHJ5IiwKICAiZnVuZGluZ193aXRoaW4iLCAiQmFycmllcnMgdG8gZnVuZGluZyIKKQoKbW9kZWwgPC0gbW9kcy5oMS5uZXh0X3llYXIuYmF5ZXMgJT4lCiAgZmlsdGVyKG0gPT0gImltcDEiLCBtb2RlbC5uYW1lID09ICJtb2QuaDEudHlwZS50b3RhbCIpICU+JQogIHNlbGVjdChtb2RlbCkgJT4lIC5bWzFdXSAlPiUgLltbMV1dCgpoeXBvdGhldGljYWwuYm91bmRzIDwtIGdldF9hbGxfdmFycyhtb2RlbCRmb3JtdWxhLCBkYXRhID0gbW9kZWwkZGF0YSkgJT4lCiAgc2VsZWN0KGFkdm9jYWN5X3dpdGhpbiwgZW50cnlfd2l0aGluLCBmdW5kaW5nX3dpdGhpbikgJT4lCiAgc3VtbWFyaXNlX2FsbChmdW5zKG1pbiwgbWF4KSkgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUpICU+JQogIG11dGF0ZSh2YWx1ZSA9IHJvdW5kKHZhbHVlLCAwKSkgJT4lCiAgIyBIYXZlIHRvIHNlcGFyYXRlIG9uIF9tIGJlY2F1c2Ugb2YgbXVsdGlwbGUgX3MsIHRoZW4gcmUtYWRkIHRoZSBtCiAgc2VwYXJhdGUoa2V5LCBpbnRvID0gYygidGVybSIsICJ2YXJpYWJsZSIpLCBzZXAgPSAiX20iKSAlPiUKICBtdXRhdGUodmFyaWFibGUgPSBwYXN0ZTAoIm0iLCB2YXJpYWJsZSkpICU+JQogIHNwcmVhZCh2YXJpYWJsZSwgdmFsdWUpCgpuZXcuZGF0YS5oeXBvdGhldGljYWwubmVzdGVkIDwtIGh5cG90aGV0aWNhbC5ib3VuZHMgJT4lCiAgbmVzdCgtdGVybSkgJT4lCiAgbXV0YXRlKG5ld2RhdGEgPSBtYXAyKC54ID0gZGF0YSwgLnkgPSB0ZXJtLAogICAgICAgICAgICAgICAgICAgICAgICB+IGV4cGFuZC5ncmlkKHRlcm0gPSBzZXEoLngkbWluLCAueCRtYXgsIGJ5ID0gMC41KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3djb2RlID0gMTAwMDoxMDQ5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllYXIgPSAxOTgxOjIwMTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQgPSAxKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJlbmFtZSB0aGUgdGVybSBjb2x1bW4gdG8gdGhlIGFjdHVhbCB0ZXJtIG5hbWUKICAgICAgICAgICAgICAgICAgICAgICAgICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKGMoLnksIGNvbG5hbWVzKC4pWy0xXSkpKSkKCm5ldy5kYXRhLmh5cG90aGV0aWNhbCA8LSBhc190aWJibGUoYmluZF9yb3dzKG5ldy5kYXRhLmh5cG90aGV0aWNhbC5uZXN0ZWQkbmV3ZGF0YSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKGNvbnRhaW5zKCJ3aXRoaW4iKSksIGZ1bnMoaWZlbHNlKGlzLm5hKC4pLCAwLCAuKSkpCgpuZXcuZGF0YSA8LSBnZXRfYWxsX3ZhcnMobW9kZWwkZm9ybXVsYSwgZGF0YSA9IG1vZGVsJGRhdGEpICU+JQogIHNlbGVjdCgtYyhhZHZvY2FjeV93aXRoaW4sIGVudHJ5X3dpdGhpbiwgZnVuZGluZ193aXRoaW4sIHllYXIsIGNvd2NvZGUpKSAlPiUKICBzdW1tYXJpc2VfYWxsKHR5cGljYWwpICU+JQogIG11dGF0ZShpZCA9IDEpICU+JQogIHJpZ2h0X2pvaW4obmV3LmRhdGEuaHlwb3RoZXRpY2FsLCBieSA9ICJpZCIpICU+JSBzZWxlY3QoLWlkKQoKcHJlZGljdGVkLmgxLmJhcnJpZXJzLmluZGl2aWR1YWwgPC0gbmV3LmRhdGEgJT4lCiAgbmVzdCgtY293Y29kZSkgJT4lCiAgbXV0YXRlKHByZWRpY3RlZCA9IGZ1dHVyZV9tYXAoLnggPSBkYXRhLCB+IGdlbmVyYXRlX3ByZWRpY3Rpb25zKC54KSkpICU+JQogIHVubmVzdCgpCgpkZi5wbG90LmRhdGEuaW5kaXYuaDEgPC0gcHJlZGljdGVkLmgxLmJhcnJpZXJzLmluZGl2aWR1YWwgJT4lCiAgZ2F0aGVyKGJhcnJpZXIsIGJhcnJpZXIudmFsdWUsIGMoYWR2b2NhY3lfd2l0aGluLCBlbnRyeV93aXRoaW4sIGZ1bmRpbmdfd2l0aGluKSkgJT4lCiAgZ3JvdXBfYnkoY293Y29kZSwgYmFycmllci52YWx1ZSwgYmFycmllcikgJT4lCiAgc3VtbWFyaXNlX2F0KHZhcnMocHJlZGljdGVkKSwgZnVucyhtZWFuKC4pKSkgJT4lCiAgbGVmdF9qb2luKGJhcnJpZXJzLmluZGl2LmNsZWFuLm5hbWVzLCBieSA9ICJiYXJyaWVyIikKCmRmLnBsb3QuZGF0YS5tZWFuLmluZGl2LmgxIDwtIGRmLnBsb3QuZGF0YS5pbmRpdi5oMSAlPiUKICBncm91cF9ieShiYXJyaWVyLCBiYXJyaWVyLnZhbHVlKSAlPiUKICBzdW1tYXJpc2UocHJlZGljdGVkID0gbWVhbihwcmVkaWN0ZWQpKSAlPiUKICBtdXRhdGUoY293Y29kZSA9IDEpICU+JSAgIyBGYWtlIGNvdW50cnkgc28gdGhlIGxpbmUgcGxvdHMKICBsZWZ0X2pvaW4oYmFycmllcnMuaW5kaXYuY2xlYW4ubmFtZXMsIGJ5ID0gImJhcnJpZXIiKQpgYGAKCmBgYHtyIGgxLXByZWRpY3QtYm90aCwgd2FybmluZz1GQUxTRSwgZmlnLndpZHRoPTUuNSwgZmlnLmhlaWdodD0zLjV9CiMgQ29tYmluZSB0aGUgdHdvIHBsb3QgZGF0YSBmcmFtZXMKZGYucGxvdC5kYXRhLmJvdGguaDEgPC0gZGYucGxvdC5kYXRhLmgxICU+JQogIG11dGF0ZShiYXJyaWVyID0gImJhcnJpZXJzLnRvdGFsX3dpdGhpbiIsIGJhcnJpZXIuY2xlYW4gPSAiVG90YWwgYmFycmllcnMiKSAlPiUKICByZW5hbWUoYmFycmllci52YWx1ZSA9IGJhcnJpZXJzLnRvdGFsX3dpdGhpbikgJT4lCiAgYmluZF9yb3dzKGRmLnBsb3QuZGF0YS5pbmRpdi5oMSkgJT4lCiAgbXV0YXRlKGJhcnJpZXIuY2xlYW4gPSBvcmRlcmVkKGZjdF9pbm9yZGVyKGJhcnJpZXIuY2xlYW4pKSwKICAgICAgICAgaGlnaGxpZ2h0ID0gaWZlbHNlKGJhcnJpZXIuY2xlYW4gPT0gIlRvdGFsIGJhcnJpZXJzIiwgVFJVRSwgRkFMU0UpKQoKZGYucGxvdC5kYXRhLm1lYW4uYm90aC5oMSA8LSBkZi5wbG90LmRhdGEubWVhbi5oMSAlPiUKICBtdXRhdGUoYmFycmllciA9ICJiYXJyaWVycy50b3RhbF93aXRoaW4iLCBiYXJyaWVyLmNsZWFuID0gIlRvdGFsIGJhcnJpZXJzIikgJT4lCiAgcmVuYW1lKGJhcnJpZXIudmFsdWUgPSBiYXJyaWVycy50b3RhbF93aXRoaW4pICU+JQogIGJpbmRfcm93cyhkZi5wbG90LmRhdGEubWVhbi5pbmRpdi5oMSkgJT4lCiAgbXV0YXRlKGJhcnJpZXIuY2xlYW4gPSBvcmRlcmVkKGZjdF9pbm9yZGVyKGJhcnJpZXIuY2xlYW4pKSkKCiMgQ3JlYXRlIGRhdGEgZnJhbWUgZm9yIGhpZ2hsaWdodGluZyB0aGUgdG90YWwgcGFuZWwKZGYucGFuZWwuaGlnaGxpZ2h0LmgxIDwtIGRmLnBsb3QuZGF0YS5ib3RoLmgxICU+JQogIGRpc3RpbmN0KGJhcnJpZXIuY2xlYW4sIGhpZ2hsaWdodCkKCmZpZy5wcmVkaWN0ZWQuaDEuYmFycmllcnMuYm90aCA8LSBnZ3Bsb3QoZGYucGxvdC5kYXRhLmJvdGguaDEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gYmFycmllci52YWx1ZSwgeSA9IGV4cG0xKHByZWRpY3RlZCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCA9IGNvd2NvZGUpKSArIAogIGdlb21fcmVjdChkYXRhID0gZGYucGFuZWwuaGlnaGxpZ2h0LmgxLCBhZXMoZmlsbCA9IGhpZ2hsaWdodCksIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgYWxwaGEgPSAwLjE1KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzaXplID0gMC4xLCBhbHBoYSA9IDAuMSwgCiAgICAgICAgICAgICAgY29sb3VyID0gc2ltdWxhdGlvbi5pbmRpdmlkdWFsKSArCiAgZ2VvbV9zbW9vdGgoZGF0YSA9IGRmLnBsb3QuZGF0YS5tZWFuLmJvdGguaDEsIHNpemUgPSAxLjUsIAogICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsIGNvbG91ciA9IHNpbXVsYXRpb24ubWVhbikgKwogIGxhYnMoeCA9ICJEaWZmZXJlbmNlIGZyb20gYXZlcmFnZSBudW1iZXIgb2YgYW50aS1OR08gYmFycmllcnMgaW4gY291bnRyeSAod2l0aGluIGVmZmVjdHMpIiwKICAgICAgIHkgPSAiUHJlZGljdGVkIE9EQSBpbiB0aGUgZm9sbG93aW5nIHllYXIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGRvbGxhciwgdHJhbnMgPSBsb2cxcF90cmFucygpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyhOQSwgImdyZXk1MCIpLCBndWlkZSA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh+IGJhcnJpZXIuY2xlYW4sIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgdGhlbWVfZG9ub3JzKCkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApKQpmaWcucHJlZGljdGVkLmgxLmJhcnJpZXJzLmJvdGgKCmZpZy5zYXZlLmNhaXJvKGZpZy5wcmVkaWN0ZWQuaDEuYmFycmllcnMuYm90aCwgZmlsZW5hbWUgPSAiZmlnLXByZWRpY3RlZC1oMSIsCiAgICAgICAgICAgICAgIHdpZHRoID0gNS41LCBoZWlnaHQgPSAzLjUpCmBgYAoKCi0tLQoKIyMgSH4yfjogRG9ub3JzIHNoaWZ0IGFpZCB0byB0YW1lciBjYXVzZXMKCj4gKipIfjJ+Kio6IEFzIHJlc3RyaWN0aXZlIGxhd3MgYWdhaW5zdCBOR09zIGFyZSBlbmFjdGVkLCBkb25vcnMgc3RhcnQgaW5jcmVhc2luZyBmdW5kcyBmb3IgJ3RhbWVyJyBjYXVzZXMsIGFuZCBkZWNyZWFzaW5nIGZ1bmRzIGZvciBwb2xpdGljYWxseSBzZW5zaXRpdmUgY2F1c2VzLgoKT3VyIGRlcGVuZGVudCB2YXJpYWJsZSBmb3IgdGhpcyBoeXBvdGhlc2lzIGlzIHRoZSBwZXJjZW50YWdlIG9mIE9EQSAoc3RpbGwgaW4gY29uc3RhbnQgMjAxMSBkb2xsYXJzKSBhbGxvY2F0ZWQgZm9yIGNvbnRlbnRpb3VzIHB1cnBvc2VzLCBhZ2FpbiBsZWFkZWQgYnkgb25lIHllYXIuIFdlIGNsYXNzaWZ5IGNvbnRlbnRpb3VzIGFpZCBhcyBhbnkgcHJvamVjdCBmb2N1c2VkIG9uIGdvdmVybm1lbnQgYW5kIGNpdmlsIHNvY2lldHkgKERBQyBjb2RlcyAxNTAgYW5kIDE1MSkgb3IgY29uZmxpY3QgcHJldmVudGlvbiBhbmQgcmVzb2x1dGlvbiwgcGVhY2UgYW5kIHNlY3VyaXR5IChEQUMgY29kZSAxNTIpLgoKV29ya2luZyB3aXRoIHByb3BvcnRpb24gZGF0YSwgaG93ZXZlciwgcG9zZXMgaW50ZXJlc3RpbmcgbWF0aGVtYXRpY2FsIGFuZCBtZXRob2RvbG9naWNhbCBjaGFsbGVuZ2VzLCBzaW5jZSB0aGUgcmFuZ2Ugb2YgcG9zc2libGUgb3V0Y29tZXMgaXMgbGltaXRlZCB0byBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMS4gVHJlYXRpbmcgcHJvcG9ydGlvbiB2YXJpYWJsZXMgaW4gYSBtaXhlZCBtb2RlbCBpcyB0ZWNobmljYWxseSBwb3NzaWJsZSwgYnV0IGl0IHlpZWxkcyBwcmVkaWNpdGlvbnMgdGhhdCBnbyBiZXlvbmQgdGhlIGFsbG93YWJsZSByYW5nZSBvZiB2YWx1ZXMgKDEuMTMsIC0wLjUsIGV0Yy4pLiBUcmVhdGluZyB0aGUgcHJvcG9ydGlvbiBhcyBhIGJpbm9taWFsIHZhcmlhYmxlIGlzIGFsc28gcG9zc2libGUgYW5kIGlzIGluZGVlZCBbb25lIG9mIHRoZSB3YXlzIHRvIHVzZSB0aGUgYGdsbSgpYCBmdW5jdGlvbl0oaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvOTExMTkwNC8xMjA4OTgpIGluIFIuIEhvd2V2ZXIsIHRoaXMgZW50YWlscyBjb25zaWRlcmluZyB0aGUgcHJvcG9ydGlvbiBhcyBhIHJhdGlvIG9mIHN1Y2Nlc3MgYW5kIGZhaWx1cmVzLiBJbiB0aGlzIGNhc2UsIHRyZWF0aW5nIGEgZG9sbGFyIG9mIGNvbnRlbnRpb3VzIGFpZCBhcyBhIHN1Y2Nlc3MgZmVlbHMgb2ZmLCBlc3BlY2lhbGx5IHNpbmNlIGFpZCBhbW91bnRzIGFyZW4ndCBpbmRlcGVuZGVudCBldmVudHPigJRpdCdzIG5vdCBsaWtlIGVhY2ggZG9sbGFyIG9mIGFpZCBnb2VzIHRocm91Z2ggYSBwcm9iYWJhbGlzdGljIHByb2Nlc3MgbGlrZSBhIGNvaW4gZmxpcC4gCgpbT25lIHJlY29tbWVuZGF0aW9uIGJ5IEJlbiBCb2xrZXJdKGh0dHBzOi8vc3RhdC5ldGh6LmNoL3BpcGVybWFpbC9yLXNpZy1taXhlZC1tb2RlbHMvMjAxMXExLzAxNTQyMi5odG1sKSwgdGhlIG1haW50YWluZXIgb2YgW2BsbWU0YF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT1sbWU0KSwgaXMgdG8gdXNlIGEgbG9naXQgdHJhbnNmb3JtYXRpb24gb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBpbiBgbG1lcigpYCBtb2RlbHMuIFRoaXMgc2VlbXMgdG8gYmUgW3N0YW5kYXJkIHByYWN0aWNlIGluIHBvbGl0aWNhbCBzY2llbmNlIHJlc2VhcmNoXShodHRwczovL2Fjcm93aW5naGVuLmNvbS8yMDE0LzA0LzI0L2ludGVycHJldGluZy1jb2VmZmljaWVudHMtZnJvbS1hLWxvZ2l0LWxpbmVhci1tb2RlbC13aXRoLWEtcHJvcG9ydGlvbmFsLWRlcGVuZGVudC12YXJpYWJsZS8pLCB0b28uIExvZ2l0IHRyYW5zZm9ybWF0aW9ucyBzdGlsbCBjYW4ndCBoYW5kbGUgdmFsdWVzIG9mIGV4YWN0bHkgMCBvciAxLCB0aG91Z2gsIHNvIHdlIFt3aW5zb3JpemVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dpbnNvcml6aW5nKSB0aG9zZSB2YWx1ZXMgYnkgYWRkaW5nIG9yIHN1YnRyYWN0aW5nIDAuMDAxIHRvIHRoZSBleHRyZW1lcy4KCkFub3RoZXIgc29sdXRpb24gaXMgdG8gdXNlIFtiZXRhIHJlZ3Jlc3Npb25dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3BhY2thZ2U9YmV0YXJlZyksIHdoaWNoIFtjb25zdHJhaW5zIHRoZSBvdXRjb21lIHZhcmlhYmxlIHRvIHZhbHVlcyBiZXR3ZWVuIDAgYW5kIDFdKGh0dHA6Ly93d3cudGhlYW5hbHlzaXNmYWN0b3IuY29tL3plcm8tb25lLWluZmxhdGVkLWJldGEtbW9kZWxzLWZvci1wcm9wb3J0aW9uLWRhdGEvKSwgYnV0IHVuZm9ydHVuYXRlbHkgZG9lcyBub3QgYWxsb3cgZm9yIHZhbHVlcyBvZiBleGFjdGx5IDAgb3IgMS4gWmVyby1hbmQtb25lIGluZmxhdGVkIGJldGEgcmVncmVzc2lvbiBtb2RlbHMsIGhvd2V2ZXIsIG1ha2UgYWRqdXN0bWVudHMgZm9yIHRoaXMsIGFuZCB3ZSBpbmNsdWRlIGEgc2V0IG9mIHRoZXNlIG1vZGVscyBhcyBhIHJvYnVzdG5lc3MgY2hlY2suIFdlIHN0aWNrIHdpdGggbG9naXQtbGluZWFyIG1vZGVscywgdGhvdWdoLCBzaW5jZSB3ZSB3YW50IHRvIGNvbXBhcmUgdGhlIHJhdGlvIG9mIGNvbnRlbnRpb3VzIGFpZCB0byBub24tY29udGVudGlvdXMgYWlkIChyYXRoZXIgdGhhbiB0aGUgcGVyY2VudCBvZiBjb250ZW50aW91cyBhaWQpIGFuZCBrZWVwIHRoZSBjb21wYXJpc29uIHBhcmFsbGVsIHdpdGggb3VyIEgzIG1vZGVscywgd2hpY2ggb25seSBjb21wYXJlIHRoZSByYXRpbyBvZiBhaWQgY2hhbm5lbGVkIHRocm91Z2ggYWxsIE5HT3MuCgpXZSB0aHVzIHVzZSBhIGxvZ2l0LWxpbmVhciBtb2RlbCBvZiB0aGUgcmF0aW8gb2YgY29udGVudGlvdXMgYWlkIHRvIG5vbi1jb250ZW50aW91cyBhaWQ6CgokJGxuKCBcZnJhY3tcdGV4dHtjb250ZW50aW91cyBPREF9X3tcdGV4dHtPRUNEfX19e1x0ZXh0e25vbmNvbnRlbnRpb3VzIE9EQX1fe1x0ZXh0e09FQ0R9fX0gKV97aSwgdCsxfSA9IFx0ZXh0e05HTyBsZWdpc2xhdGlvbn1fe2l0fSArIFx0ZXh0e2NvbnRyb2xzfV97aXR9JCQKCldlIGxvb2sgYXQgTkdPIGxlZ2lzbGF0aW9uIGluIHRoZSBzYW1lIHdheXMgYXMgSH4xfiBhbmQgdXNlIHRoZSBzYW1lIGNvbnRyb2xzLgoKYGBge3IgaDItbW9kZWxzLWJheWVzLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQojIEdldCBzY2FsaW5nIGZhY3RvcnMKc2NhbGVzLmgyLm5leHRfeWVhciA8LSBtb2RzLmgyLm5leHRfeWVhci5yYXcuYmF5ZXMgJT4lIAogIGZpbHRlcihtICE9ICJvcmlnaW5hbCIpICU+JSAKICBzZWxlY3QobSwgc3RhcnRzX3dpdGgoInNjYWxlcyIpKSAlPiUgCiAgZ2F0aGVyKHNjYWxlcy5uYW1lLCBzY2FsZXMsIC1tKQoKIyBHZXQgbW9kZWwgZGV0YWlscyBhbmQgcGFyYW1ldGVycwptb2RzLmgyLm5leHRfeWVhci5iYXllcyA8LSBtb2RzLmgyLm5leHRfeWVhci5yYXcuYmF5ZXMgJT4lCiAgZmlsdGVyKG0gIT0gIm9yaWdpbmFsIikgJT4lIAogIHNlbGVjdChtLCBzdGFydHNfd2l0aCgibW9kIikpICU+JSAKICBnYXRoZXIobW9kZWwubmFtZSwgbW9kZWwsIC1tKSAlPiUKICBtdXRhdGUoZ2xhbmNlID0gbW9kZWwgJT4lIG1hcChnbGFuY2UpLAogICAgICAgICB0aWR5ID0gbW9kZWwgJT4lIG1hcCh0aWR5KSkgJT4lIAogIGJpbmRfY29scyhzZWxlY3Qoc2NhbGVzLmgyLm5leHRfeWVhciwgLW0pKQpgYGAKCgojIyMgTUNNQyBkaWFnbm9zdGljcyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCiMjIyMgQ2hlY2sgZml0CgpBZ2FpbiwgdXNlIG9uZSBvZiB0aGUgaW1wdXRlZCBtb2RlbHMgKGBtb2QuaDIuYmFycmllcnMudG90YWxgKSB0byBjaGVjayBmb3IgZml0IGFuZCBjb252ZXJnZW5jZS4KCmBgYHtyIGgyLWRpYWdub3N0aWNzLWJheWVzfQptb2RlbC50by5jaGVjayA8LSBtb2RzLmgyLm5leHRfeWVhci5iYXllcyAlPiUKICBmaWx0ZXIobSA9PSAiaW1wMSIsIG1vZGVsLm5hbWUgPT0gIm1vZC5oMi5iYXJyaWVycy50b3RhbCIpICU+JQogIHNlbGVjdChtb2RlbCkgJT4lIC5bWzFdXSAlPiUgLltbMV1dCmBgYAoKUG9zdGVyaW9yIHByZWRpY3RpdmUgZGlzdHJpYnV0aW9uIHZzLiBvYnNlcnZlZCBvdXRjb21lPwoKYGBge3IgaDItZGlhZy1kZW5zaXR5fQpwcF9jaGVjayhtb2RlbC50by5jaGVjaywgdHlwZSA9ICJkZW5zX292ZXJsYXkiLCBuc2FtcGxlcyA9IDEwKSArIAogIHRoZW1lX2Rvbm9ycygpCmBgYAoKIyMjIyBDaGVjayBjb252ZXJnZW5jZQoKQ2hhaW4gY29udmVyZ2VuY2U6CgpgYGB7ciBoMi1kaWFnLWRpdmVyZ2VuY2V9CnJzdGFuOjpzdGFuX2RpYWcobW9kZWwudG8uY2hlY2skZml0LCBpbmZvcm1hdGlvbiA9ICJkaXZlcmdlbmNlIikKYGBgCgoKIyMjIFJlc3VsdHMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgojIyMjIENvZWZmaWNpZW50cwoKYGBge3IgaDItcGxvdC1jb2VmcywgZmlnLndpZHRoPTUuNSwgZmlnLmhlaWdodD0yLjV9CnZhcnMudG8ucGxvdCA8LSBjKCJiYXJyaWVycy50b3RhbF93aXRoaW4iLCAiYmFycmllcnMudG90YWxfYmV0d2VlbiIsCiAgICAgICAgICAgICAgICAgICJhZHZvY2FjeV93aXRoaW4iLCAiYWR2b2NhY3lfYmV0d2VlbiIsIAogICAgICAgICAgICAgICAgICAiZW50cnlfd2l0aGluIiwgImVudHJ5X2JldHdlZW4iLCAKICAgICAgICAgICAgICAgICAgImZ1bmRpbmdfd2l0aGluIiwgImZ1bmRpbmdfYmV0d2VlbiIsCiAgICAgICAgICAgICAgICAgICJjc3JlX3dpdGhpbiIsICJjc3JlX2JldHdlZW4iKQoKbW9kcy5oMi5tZWxkZWQgPC0gYmF5ZXMubWVsZChtb2RzLmgyLm5leHRfeWVhci5iYXllcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJzLnRvLnBsb3QsIGV4cG9uZW50aWF0ZSA9IFRSVUUpJG1lbGRlZC5zdW1tYXJ5CgpwbG90LmRhdGEgPC0gbW9kcy5oMi5tZWxkZWQgJT4lCiAgbGVmdF9qb2luKGNvZWYubmFtZXMuYWxsLCBieSA9ICJ0ZXJtIikgJT4lCiAgbGVmdF9qb2luKG1vZGVsLm5hbWVzLCBieSA9IGMoIm1vZGVsLm5hbWUiID0gIm1vZGVsIikpICU+JSAKICBtdXRhdGUodGVybSA9IGZhY3Rvcih0ZXJtLCBsZXZlbHMgPSB2YXJzLnRvLnBsb3QsIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgYXJyYW5nZShkZXNjKHRlcm0pKSAlPiUKICBtdXRhdGUodGVybV9wbG90ID0gb3JkZXJlZChmY3RfaW5vcmRlcih0ZXJtX3Bsb3Rfc2hvcnQpKSkgJT4lCiAgbXV0YXRlKGNvZWYudHlwZSA9IGNhc2Vfd2hlbigKICAgIHN0cl9kZXRlY3QoLiR0ZXJtLCAiX3dpdGhpbiIpIH4gIldpdGhpbiIsCiAgICBzdHJfZGV0ZWN0KC4kdGVybSwgIl9iZXR3ZWVuIikgfiAiQmV0d2VlbiIsCiAgKSkgJT4lIAogIG11dGF0ZShjb2VmLnR5cGUgPSBmYWN0b3IoY29lZi50eXBlLCBsZXZlbHMgPSBjKCJXaXRoaW4iLCAiQmV0d2VlbiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBtdXRhdGUobW9kZWxfY2xlYW4gPSBmYWN0b3IobW9kZWxfY2xlYW4sIGxldmVscyA9IHJldih1bmlxdWUobW9kZWxfY2xlYW4pKSwgb3JkZXJlZCA9IFRSVUUpKQoKZmlnLmNvZWZzLmgyIDwtIGdncGxvdChwbG90LmRhdGEsIGFlcyh4ID0gbWVkLCB5ID0gdGVybV9wbG90LCBjb2xvdXIgPSBtb2RlbF9jbGVhbikpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMC41KSArICAKICBnZW9tX3BvaW50cmFuZ2VoKGFlcyh4bWluID0gYDIuNSVgLCB4bWF4ID0gYDk3LjUlYCksIHNpemUgPSAwLjUsIGZhdHRlbiA9IDMpICsgCiAgbGFicyh4ID0gIlBlcmNlbnQgY2hhbmdlIGluIHJhdGlvIG9mIGNvbnRlbnRpb3VzIGFpZCAob2RkcyByYXRpbykiLCB5ID0gTlVMTCkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gbW9kZWwuY29sb3JzLCBuYW1lID0gTlVMTCkgKwogIGV4cGFuZF9saW1pdHMoeCA9IGMoMC42LCAxLjMpKSArCiAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDAuMjUpKSkgKwogIHRoZW1lX2Rvbm9ycygpICsgCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSAibGVmdCIsCiAgICAgICAgbGVnZW5kLmJveC5tYXJnaW4gPSBtYXJnaW4obCA9IC0wLjc1LCB0ID0gLTAuNSwgdW5pdCA9ICJsaW5lcyIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApKSArCiAgZmFjZXRfd3JhcCh+IGNvZWYudHlwZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMikKZmlnLmNvZWZzLmgyCgpmaWcuc2F2ZS5jYWlybyhmaWcuY29lZnMuaDIsIGZpbGVuYW1lID0gImZpZy1jb2Vmcy1oMi1iYXllcyIsCiAgICAgICAgICAgICAgIHdpZHRoID0gNS41LCBoZWlnaHQgPSAyLjUpCmBgYAoKIyMjIyBDb21wbGV0ZSByZXN1bHRzIGluIGEgdGFibGUKCmBgYHtyIGgyLXRhYmxlLCByZXN1bHRzPSJhc2lzIiwgd2FybmluZz1GQUxTRX0KY2FwdGlvbiA8LSAiVGhlIGVmZmVjdCBvZiBhbnRpLU5HTyBsZWdpc2xhdGlvbiBvbiB0aGUgcHJvcG9ydGlvbiBvZiBPRUNEIG92ZXJzZWFzIGRldmVsb3BtZW50IGFzc2lzdGFuY2UgKE9EQSkgY29tbWl0dGVkIHRvIGNvbnRlbnRpb3VzIHB1cnBvc2VzIGluIHRoZSBmb2xsb3dpbmcgeWVhciAoSH4yfiksIGZ1bGwgbW9kZWxzLiBFYWNoIGNlbGwgY29udGFpbnMgdGhlIHBhcmFtZXRlcidzIHBvc3RlcmlvciBtZWRpYW4sIHRoZSA5NSUgY3JlZGlibGUgaW50ZXJ2YWwsIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgcGFyYW1ldGVyIGlzIGdyZWF0ZXIgdGhhbiBvbmUgKGluIGl0YWxpY3MpLiB7I3RibDpoMi1jb2Vmc30iCm5vdGUgPC0gYygiTG9naXQtbGluZWFyIG1vZGVscy4gUGVyY2VudCBjaGFuZ2Ugb2RkcyByYXRpb3MgcmVwb3J0ZWQuIikKCnRhYmxlLmgyIDwtIGJheWVzZ2F6ZXIobW9kcy5oMi5uZXh0X3llYXIuYmF5ZXMsIGV4cG9uZW50aWF0ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IGNhcHRpb24sIG5vdGUgPSBub3RlKQoKY2F0KHRhYmxlLmgyKQpjYXQodGFibGUuaDIsIGZpbGUgPSBoZXJlKCJPdXRwdXQiLCAidGJsLWgyLWNvZWZzLWJheWVzLm1kIikpCmBgYAoKIyMjIyBDb21wbGV0ZSByZXN1bHRzIChub25pbXB1dGVkKQoKYGBge3IgaDItbm8taW1wdXRhdGlvbiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBUaGUgc2NhbGluZyBmYWN0b3JzIGFyZSBhbGwgdGhlIHNhbWUgYWNyb3NzIHRoZSB0aHJlZSBtb2RlbHMsIHNpbmNlIHRoZXkgdXNlCiMgdGhlIHNhbWUgZGF0YXNldCwgc28gd2Ugb25seSBuZWVkIHNjYWxlc19oMS4xCnNjYWxlcy5oMi5uZXh0X3llYXIubm8uaW1wIDwtIG1vZHMuaDIubmV4dF95ZWFyLnJhdy5iYXllcyAlPiUgCiAgZmlsdGVyKG0gPT0gIm9yaWdpbmFsIikgJT4lIAogIHNlbGVjdChtLCBzdGFydHNfd2l0aCgic2NhbGVzIikpICU+JSAKICBwdWxsKHNjYWxlc19oMi4xKSAlPiUgLltbMV1dCgojIEdldCBtb2RlbCBkZXRhaWxzIGFuZCBwYXJhbWV0ZXJzCm1vZHMuaDIubmV4dF95ZWFyLmJheWVzLm5vLmltcCA8LSBtb2RzLmgyLm5leHRfeWVhci5yYXcuYmF5ZXMgJT4lCiAgc2VsZWN0KC1jb250YWlucygic2NhbGVzIikpICU+JSAKICBmaWx0ZXIobSA9PSAib3JpZ2luYWwiKSAlPiUgCiAgZ2F0aGVyKG1vZGVsLm5hbWUsIG1vZGVsLCAtbSkgJT4lCiAgbXV0YXRlKGdsYW5jZSA9IG1vZGVsICU+JSBtYXAoZ2xhbmNlKSwKICAgICAgICAgdGlkeSA9IG1vZGVsICU+JSBtYXAodGlkeSwgZWZmZWN0cyA9ICJmaXhlZCIpKSAlPiUgCiAgbXV0YXRlKG1vZGVsX3NjYWxlID0gbW9kZWwgJT4lIG1hcChhZGRfc2NhbGVtY21jKSkKCmgyX2NvZWZzIDwtIG1vZHMuaDIubmV4dF95ZWFyLmJheWVzLm5vLmltcCAlPiUKICB1bm5lc3QodGlkeSkgJT4lIAogIGZpbHRlcighZHVwbGljYXRlZCh0ZXJtLCBmcm9tTGFzdCA9IFRSVUUpKSAlPiUKICBtdXRhdGUodGVybV9qb2luID0gc3RyX3JlcGxhY2UodGVybSwgIlRSVUUiLCAiIikpICU+JSAKICBsZWZ0X2pvaW4oY29lZi5uYW1lcy5hbGwsIGJ5ID0gYygidGVybV9qb2luIiA9ICJ0ZXJtIikpICU+JSAKICBmaWx0ZXIodGVybSAhPSAiSW50ZXJjZXB0IikKCmgyX2NvZWZzX25hbWVkIDwtIGgyX2NvZWZzICU+JSBwdWxsKHRlcm0pICU+JSAKICBzZXRfbmFtZXMoaDJfY29lZnMkdGVybV9jbGVhbikKCmh1eHJlZyhtb2RzLmgyLm5leHRfeWVhci5iYXllcy5uby5pbXAkbW9kZWxfc2NhbGUsCiAgICAgICBjb2VmcyA9IGMoaDJfY29lZnNfbmFtZWQsIENvbnN0YW50ID0gIkludGVyY2VwdCIpLAogICAgICAgc3RhcnMgPSBOVUxMLCBzdGF0aXN0aWNzID0gYyhOID0gIm5vYnMiKSwKICAgICAgIHRpZHlfYXJncyA9IGxpc3QoY29uZi5pbnQgPSBUUlVFLCBwcm9iID0gMC45NSwgZXhwb25lbnRpYXRlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgZWZmZWN0cyA9ICJmaXhlZCIsIHNjYWxpbmdzID0gc2NhbGVzLmgyLm5leHRfeWVhci5uby5pbXApLAogICAgICAgZXJyb3JfZm9ybWF0ID0gIih7Y29uZi5sb3d9LCB7Y29uZi5oaWdofSkiKQpgYGAKCiMjIyBQcmVkaWN0ZWQgcHJvcG9ydGlvbiBvZiBjb250ZW50aW91cyBhaWQKCmBgYHtyIGgyLXByZWRpY3QtdG90YWwsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUV9Cm1vZGVsIDwtIG1vZHMuaDIubmV4dF95ZWFyLmJheWVzICU+JQogIGZpbHRlcihtID09ICJpbXAxIiwgbW9kZWwubmFtZSA9PSAibW9kLmgyLmJhcnJpZXJzLnRvdGFsIikgJT4lCiAgc2VsZWN0KG1vZGVsKSAlPiUgLltbMV1dICU+JSAuW1sxXV0KCm5ldy5kYXRhIDwtIGdldF9hbGxfdmFycyhtb2RlbCRmb3JtdWxhLCBkYXRhID0gbW9kZWwkZGF0YSkgJT4lCiAgc2VsZWN0KC1jKGJhcnJpZXJzLnRvdGFsX3dpdGhpbiwgeWVhciwgY293Y29kZSkpICU+JQogIHN1bW1hcmlzZV9hbGwodHlwaWNhbCkgJT4lCiAgbXV0YXRlKGlkID0gMSkgJT4lCiAgcmlnaHRfam9pbihleHBhbmQuZ3JpZChiYXJyaWVycy50b3RhbF93aXRoaW4gPSBzZXEoLTMsIDQsIDAuNSksCiAgICAgICAgICAgICAgICAgICAgICAgICBjb3djb2RlID0gMTAwMDoxMDQ5LAogICAgICAgICAgICAgICAgICAgICAgICAgeWVhciA9IDE5ODE6MjAxMiwKICAgICAgICAgICAgICAgICAgICAgICAgIGlkID0gMSksIGJ5ID0gImlkIikgJT4lIHNlbGVjdCgtaWQpCgpwcmVkaWN0ZWQuaDIuYmFycmllcnMudG90YWwgPC0gbmV3LmRhdGEgJT4lCiAgbmVzdCgtY293Y29kZSkgJT4lCiAgbXV0YXRlKHByZWRpY3RlZCA9IGZ1dHVyZV9tYXAoLnggPSBkYXRhLCB+IGdlbmVyYXRlX3ByZWRpY3Rpb25zKC54KSkpICU+JQogIHVubmVzdCgpCgpkZi5wbG90LmRhdGEuaDIgPC0gcHJlZGljdGVkLmgyLmJhcnJpZXJzLnRvdGFsICU+JQogIGdyb3VwX2J5KGNvd2NvZGUsIGJhcnJpZXJzLnRvdGFsX3dpdGhpbikgJT4lCiAgc3VtbWFyaXNlX2F0KHZhcnMocHJlZGljdGVkKSwgZnVucyhtZWFuKC4pKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUodmFsdWUuZml4ZWQgPSBpbnYubG9naXQocHJlZGljdGVkLCBhID0gMC4wMDEpKQoKZGYucGxvdC5kYXRhLm1lYW4uaDIgPC0gZGYucGxvdC5kYXRhLmgyICU+JQogIGdyb3VwX2J5KGJhcnJpZXJzLnRvdGFsX3dpdGhpbikgJT4lCiAgc3VtbWFyaXNlKHByZWRpY3RlZCA9IG1lYW4ocHJlZGljdGVkKSkgJT4lCiAgbXV0YXRlKHZhbHVlLmZpeGVkID0gaW52LmxvZ2l0KHByZWRpY3RlZCwgYSA9IDAuMDAxKSkgJT4lCiAgbXV0YXRlKGNvd2NvZGUgPSAxKSAgIyBGYWtlIGNvdW50cnkgc28gdGhlIGxpbmUgcGxvdHMKYGBgCgpgYGB7ciBoMi1wcmVkaWN0LWluZGl2aWR1YWwsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUV9CmJhcnJpZXJzLmluZGl2LmNsZWFuLm5hbWVzIDwtIHRyaWJibGUoCiAgfmJhcnJpZXIsIH5iYXJyaWVyLmNsZWFuLAogICJhZHZvY2FjeV93aXRoaW4iLCAiQmFycmllcnMgdG8gYWR2b2NhY3kiLAogICJlbnRyeV93aXRoaW4iLCAiQmFycmllcnMgdG8gZW50cnkiLAogICJmdW5kaW5nX3dpdGhpbiIsICJCYXJyaWVycyB0byBmdW5kaW5nIgopCgptb2RlbCA8LSBtb2RzLmgyLm5leHRfeWVhci5iYXllcyAlPiUKICBmaWx0ZXIobSA9PSAiaW1wMSIsIG1vZGVsLm5hbWUgPT0gIm1vZC5oMi50eXBlLnRvdGFsIikgJT4lCiAgc2VsZWN0KG1vZGVsKSAlPiUgLltbMV1dICU+JSAuW1sxXV0KCmh5cG90aGV0aWNhbC5ib3VuZHMgPC0gZ2V0X2FsbF92YXJzKG1vZGVsJGZvcm11bGEsIGRhdGEgPSBtb2RlbCRkYXRhKSAlPiUKICBzZWxlY3QoYWR2b2NhY3lfd2l0aGluLCBlbnRyeV93aXRoaW4sIGZ1bmRpbmdfd2l0aGluKSAlPiUKICBzdW1tYXJpc2VfYWxsKGZ1bnMobWluLCBtYXgpKSAlPiUKICBnYXRoZXIoa2V5LCB2YWx1ZSkgJT4lCiAgbXV0YXRlKHZhbHVlID0gcm91bmQodmFsdWUsIDApKSAlPiUKICAjIEhhdmUgdG8gc2VwYXJhdGUgb24gX20gYmVjYXVzZSBvZiBtdWx0aXBsZSBfcywgdGhlbiByZS1hZGQgdGhlIG0KICBzZXBhcmF0ZShrZXksIGludG8gPSBjKCJ0ZXJtIiwgInZhcmlhYmxlIiksIHNlcCA9ICJfbSIpICU+JQogIG11dGF0ZSh2YXJpYWJsZSA9IHBhc3RlMCgibSIsIHZhcmlhYmxlKSkgJT4lCiAgc3ByZWFkKHZhcmlhYmxlLCB2YWx1ZSkKCm5ldy5kYXRhLmh5cG90aGV0aWNhbC5uZXN0ZWQgPC0gaHlwb3RoZXRpY2FsLmJvdW5kcyAlPiUKICBuZXN0KC10ZXJtKSAlPiUKICBtdXRhdGUobmV3ZGF0YSA9IG1hcDIoLnggPSBkYXRhLCAueSA9IHRlcm0sCiAgICAgICAgICAgICAgICAgICAgICAgIH4gZXhwYW5kLmdyaWQodGVybSA9IHNlcSgueCRtaW4sIC54JG1heCwgYnkgPSAwLjUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvd2NvZGUgPSAxMDAwOjEwNDksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWVhciA9IDE5ODE6MjAxMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZCA9IDEpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICMgUmVuYW1lIHRoZSB0ZXJtIGNvbHVtbiB0byB0aGUgYWN0dWFsIHRlcm0gbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMoYygueSwgY29sbmFtZXMoLilbLTFdKSkpKQoKbmV3LmRhdGEuaHlwb3RoZXRpY2FsIDwtIGFzX3RpYmJsZShiaW5kX3Jvd3MobmV3LmRhdGEuaHlwb3RoZXRpY2FsLm5lc3RlZCRuZXdkYXRhKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoY29udGFpbnMoIndpdGhpbiIpKSwgZnVucyhpZmVsc2UoaXMubmEoLiksIDAsIC4pKSkKCm5ldy5kYXRhIDwtIGdldF9hbGxfdmFycyhtb2RlbCRmb3JtdWxhLCBkYXRhID0gbW9kZWwkZGF0YSkgJT4lCiAgc2VsZWN0KC1jKGFkdm9jYWN5X3dpdGhpbiwgZW50cnlfd2l0aGluLCBmdW5kaW5nX3dpdGhpbiwgeWVhciwgY293Y29kZSkpICU+JQogIHN1bW1hcmlzZV9hbGwodHlwaWNhbCkgJT4lCiAgbXV0YXRlKGlkID0gMSkgJT4lCiAgcmlnaHRfam9pbihuZXcuZGF0YS5oeXBvdGhldGljYWwsIGJ5ID0gImlkIikgJT4lIHNlbGVjdCgtaWQpCgpwcmVkaWN0ZWQuaDIuYmFycmllcnMuaW5kaXZpZHVhbCA8LSBuZXcuZGF0YSAlPiUKICBuZXN0KC1jb3djb2RlKSAlPiUKICBtdXRhdGUocHJlZGljdGVkID0gZnV0dXJlX21hcCgueCA9IGRhdGEsIH4gZ2VuZXJhdGVfcHJlZGljdGlvbnMoLngpKSkgJT4lCiAgdW5uZXN0KCkKCmRmLnBsb3QuZGF0YS5pbmRpdi5oMiA8LSBwcmVkaWN0ZWQuaDIuYmFycmllcnMuaW5kaXZpZHVhbCAlPiUKICBnYXRoZXIoYmFycmllciwgYmFycmllci52YWx1ZSwgYyhhZHZvY2FjeV93aXRoaW4sIGVudHJ5X3dpdGhpbiwgZnVuZGluZ193aXRoaW4pKSAlPiUKICBncm91cF9ieShjb3djb2RlLCBiYXJyaWVyLnZhbHVlLCBiYXJyaWVyKSAlPiUKICBzdW1tYXJpc2VfYXQodmFycyhwcmVkaWN0ZWQpLCBmdW5zKG1lYW4oLikpKSAlPiUKICBtdXRhdGUodmFsdWUuZml4ZWQgPSBpbnYubG9naXQocHJlZGljdGVkLCBhID0gMC4wMDEpKSAlPiUgCiAgbGVmdF9qb2luKGJhcnJpZXJzLmluZGl2LmNsZWFuLm5hbWVzLCBieSA9ICJiYXJyaWVyIikKCmRmLnBsb3QuZGF0YS5tZWFuLmluZGl2LmgyIDwtIGRmLnBsb3QuZGF0YS5pbmRpdi5oMiAlPiUKICBncm91cF9ieShiYXJyaWVyLCBiYXJyaWVyLnZhbHVlKSAlPiUKICBzdW1tYXJpc2UocHJlZGljdGVkID0gbWVhbihwcmVkaWN0ZWQpKSAlPiUKICBtdXRhdGUoY293Y29kZSA9IDEpICU+JSAgIyBGYWtlIGNvdW50cnkgc28gdGhlIGxpbmUgcGxvdHMKICBtdXRhdGUodmFsdWUuZml4ZWQgPSBpbnYubG9naXQocHJlZGljdGVkLCBhID0gMC4wMDEpKSAlPiUgCiAgbGVmdF9qb2luKGJhcnJpZXJzLmluZGl2LmNsZWFuLm5hbWVzLCBieSA9ICJiYXJyaWVyIikKYGBgCgpgYGB7ciBoMi1wcmVkaWN0LWJvdGgtcGxvdCwgZmlnLndpZHRoPTUuNSwgZmlnLmhlaWdodD0zLjV9CiMgQ29tYmluZSB0aGUgdHdvIHBsb3QgZGF0YSBmcmFtZXMKZGYucGxvdC5kYXRhLmJvdGguaDIgPC0gZGYucGxvdC5kYXRhLmgyICU+JQogIG11dGF0ZShiYXJyaWVyID0gImJhcnJpZXJzLnRvdGFsX3dpdGhpbiIsIGJhcnJpZXIuY2xlYW4gPSAiVG90YWwgYmFycmllcnMiKSAlPiUKICByZW5hbWUoYmFycmllci52YWx1ZSA9IGJhcnJpZXJzLnRvdGFsX3dpdGhpbikgJT4lCiAgYmluZF9yb3dzKGRmLnBsb3QuZGF0YS5pbmRpdi5oMikgJT4lCiAgbXV0YXRlKGJhcnJpZXIuY2xlYW4gPSBvcmRlcmVkKGZjdF9pbm9yZGVyKGJhcnJpZXIuY2xlYW4pKSwKICAgICAgICAgaGlnaGxpZ2h0ID0gaWZlbHNlKGJhcnJpZXIuY2xlYW4gPT0gIlRvdGFsIGJhcnJpZXJzIiwgVFJVRSwgRkFMU0UpKQoKZGYucGxvdC5kYXRhLm1lYW4uYm90aC5oMiA8LSBkZi5wbG90LmRhdGEubWVhbi5oMiAlPiUKICBtdXRhdGUoYmFycmllciA9ICJiYXJyaWVycy50b3RhbF93aXRoaW4iLCBiYXJyaWVyLmNsZWFuID0gIlRvdGFsIGJhcnJpZXJzIikgJT4lCiAgcmVuYW1lKGJhcnJpZXIudmFsdWUgPSBiYXJyaWVycy50b3RhbF93aXRoaW4pICU+JQogIGJpbmRfcm93cyhkZi5wbG90LmRhdGEubWVhbi5pbmRpdi5oMikgJT4lCiAgbXV0YXRlKGJhcnJpZXIuY2xlYW4gPSBvcmRlcmVkKGZjdF9pbm9yZGVyKGJhcnJpZXIuY2xlYW4pKSkKCiMgQ3JlYXRlIGRhdGEgZnJhbWUgZm9yIGhpZ2hsaWdodGluZyB0aGUgdG90YWwgcGFuZWwKZGYucGFuZWwuaGlnaGxpZ2h0LmgyIDwtIGRmLnBsb3QuZGF0YS5ib3RoLmgyICU+JQogIGRpc3RpbmN0KGJhcnJpZXIuY2xlYW4sIGhpZ2hsaWdodCkKCmZpZy5wcmVkaWN0ZWQuaDIuYmFycmllcnMuYm90aCA8LSBnZ3Bsb3QoZGYucGxvdC5kYXRhLmJvdGguaDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gYmFycmllci52YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHZhbHVlLmZpeGVkLCBncm91cCA9IGNvd2NvZGUpKSArIAogIGdlb21fcmVjdChkYXRhID0gZGYucGFuZWwuaGlnaGxpZ2h0LmgyLCBhZXMoZmlsbCA9IGhpZ2hsaWdodCksIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgYWxwaGEgPSAwLjE1KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzaXplID0gMC4xLCBhbHBoYSA9IDAuMSwgY29sb3VyID0gc2ltdWxhdGlvbi5pbmRpdmlkdWFsKSArCiAgZ2VvbV9zbW9vdGgoZGF0YSA9IGRmLnBsb3QuZGF0YS5tZWFuLmJvdGguaDIsIHNpemUgPSAxLjUsIAogICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsIGNvbG91ciA9IHNpbXVsYXRpb24ubWVhbikgKwogIGxhYnMoeCA9ICJEaWZmZXJlbmNlIGZyb20gYXZlcmFnZSBsZXZlbCBvZiBOR08gbGVnaXNsYXRpb24gaW4gY291bnRyeSAod2l0aGluIGVmZmVjdCkiLAogICAgICAgeSA9ICJQcmVkaWN0ZWQgcHJvcG9ydGlvbiBvZlxuY29udGVudGlvdXMgYWlkIGluIHRoZSBmb2xsb3dpbmcgeWVhciIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoTkEsICJncmV5NTAiKSwgZ3VpZGUgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAofiBiYXJyaWVyLmNsZWFuLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHRoZW1lX2Rvbm9ycygpICsgCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkpCmZpZy5wcmVkaWN0ZWQuaDIuYmFycmllcnMuYm90aAoKZmlnLnNhdmUuY2Fpcm8oZmlnLnByZWRpY3RlZC5oMi5iYXJyaWVycy5ib3RoLCBmaWxlbmFtZSA9ICJmaWctcHJlZGljdGVkLWgyIiwKICAgICAgICAgICAgICAgd2lkdGggPSA1LjUsIGhlaWdodCA9IDMuNSkKYGBgCgoKLS0tCgojIyBIfjN+OiBEb25vcnMgc2hpZnQgYWlkIHRvIGludGVybmF0aW9uYWwgTkdPcwoKPiAqKkh+M34qKjogQXMgcmVzdHJpY3RpdmUgbGF3cyBhZ2FpbnN0IGxvY2FsIE5HT3MgaW5jcmVhc2UsIHN0YXRlcyBzaG91bGQgYmUgbW9yZSBsaWtlbHkgdG8gcHJvdmlkZSBhaWQgdG8gSU5HT3MgcmF0aGVyIHRoYW4gbG9jYWwgTkdPcy4KCldlIHVzZSB0d28gZGVwZW5kZW50IHZhcmlhYmxlcyBmb3IgdGhpcyBoeXBvdGhlc2lzOiB0aGUgcHJvcG9ydGlvbiBvZiBhaWQgY2hhbm5lbGVkIHRocm91Z2ggZWl0aGVyICgxKSBkb21lc3RpYyBvciAoMikgaW50ZXJuYXRpb25hbCBvciBVUy1iYXNlZCAob3IgZm9yZWlnbikgTkdPcywgb25jZSBhZ2FpbiBsZWFkZWQgYnkgb25lIHllYXIuIFRoZSBPRUNEIGFuZCBBaWREYXRhIGRvIG5vdCB0cmFjayB0aGUgY2hhbm5lbHMgb2YgYWlkIGRlbGl2ZXJ5LCBzbyB3ZSBjYW5ub3Qgc2VlIGhvdyBhaWQgaXMgZGlzdHJpYnV0ZWQgb24gYSBnbG9iYWwgc2NhbGUuIFVTQUlELCBob3dldmVyLCBkb2VzIHRyYWNrIGNoYW5uZWxzLCBzbyB3ZSBjYW4gbWVhc3VyZSBob3cgbXVjaCBhaWQgZ29lcyB0byBkb21lc3RpYyBOR09zIChhbmQgYWxzbyBVUy1iYXNlZCBhbmQgaW50ZXJuYXRpb25hbCBOR09zKS4gVVNBSUQgZGlkbid0IHN0YXJ0IHRyYWNraW5nIHRoaXMgdW50aWwgMjAwMSwgdGhvdWdoLCBzbyB3ZSBoYXZlIHRvIGxpbWl0IG91ciBtb2RlbHMgdG8gMjAwMeKAkzIwMTMuIChCb28uKQoKSXQgd291bGQgYmUgY29vbCB0byBtb2RlbCB0aGUgcmF0aW8gYWlkIGNoYW5uZWxlZCB0aHJvdWdoIGRvbWVzdGljIHRvIGZvcmVpZ24gTkdPcywgYnV0IGRvaW5nIHRoYXQgY2F1c2VzIHdlaXJkIG1hdGhlbWF0aWNhbCBpc3N1ZXMgd2l0aCBsb2dpdCB0cmFuc2Zvcm1hdGlvbnMsIHNpbmNlIHRoZSByYXRpb3MgY2FuIGV4Y2VlZCAxLiAKCkJlY2F1c2UgdGhlIERWcyBhcmUgcHJvcG9ydGlvbnMsIHdlIGhhdmUgdG8gbWFrZSB0aGUgc2FtZSBhc3N1bXB0aW9ucyBhbmQgd2VpcmQgaW50ZXJwcmV0aXZlIHRyaWNrcyBhcyBIfjJ+LCBidWlsZGluZyBhIGxvZ2l0LWxpbmVhciBtb2RlbCBvZiB0aGUgcmF0aW8gb2YgZG9tZXN0aWMgb3IgZm9yZWlnbiBOR08gYWlkIHRvIGFsbCBvdGhlciBjaGFubmVsczoKCiQkbG4oIFxmcmFje1x0ZXh0e0FpZCB0byAoZG9tZXN0aWMgb3IgZm9yZWlnbikgTkdPc31fe1x0ZXh0e1VTQUlEfX19e1x0ZXh0e0FpZCB0byBvdGhlciBjaGFubmVsc31fe1x0ZXh0e1VTQUlEfX19IClfe2ksIHQrMX0gPSBcdGV4dHtOR08gbGVnaXNsYXRpb259X3tpdH0gKyBcdGV4dHtjb250cm9sc31fe2l0fSQkCgpXZSBhbHNvIGluY2x1ZGUgemVyby1vbmUtaW5mbGF0ZWQgYmV0YSByZWdyZXNzaW9uIG1vZGVscyBhcyByb2J1c3RuZXNzIGNoZWNrcy4KCkFnYWluLCB3ZSB1c2UgdGhlIHNhbWUgTkdPIGxlZ2lzbGF0aW9uIHZhcmlhYmxlcyBhcyBIfjF+IGFuZCBIfjJ+IGFuZCB1c2UgdGhlIHNhbWUgY29udHJvbHMsIGV4Y2VwdCB3ZSBvbWl0ICJBZnRlciAxOTg5IiBzaW5jZSBubyBvYnNlcnZhdGlvbnMgYWN0dWFsbHkgb2NjdXIgYWZ0ZXIgMTk4OS4KCmBgYHtyIGgzLW1vZGVscy1iYXllcy1kb21lc3RpYywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRX0KIyBHZXQgc2NhbGluZyBmYWN0b3JzCnNjYWxlcy5oMy5kb20ubmV4dF95ZWFyIDwtIG1vZHMuaDMuZG9tLm5leHRfeWVhci5yYXcgJT4lIAogIGZpbHRlcihtICE9ICJvcmlnaW5hbCIpICU+JSAKICBzZWxlY3QobSwgc3RhcnRzX3dpdGgoInNjYWxlcyIpKSAlPiUgCiAgZ2F0aGVyKHNjYWxlcy5uYW1lLCBzY2FsZXMsIC1tKQoKIyBHZXQgbW9kZWwgZGV0YWlscyBhbmQgcGFyYW1ldGVycwptb2RzLmgzLmRvbS5uZXh0X3llYXIuYmF5ZXMgPC0gbW9kcy5oMy5kb20ubmV4dF95ZWFyLnJhdyAlPiUKICBmaWx0ZXIobSAhPSAib3JpZ2luYWwiKSAlPiUgCiAgc2VsZWN0KG0sIHN0YXJ0c193aXRoKCJtb2QiKSkgJT4lIAogIGdhdGhlcihtb2RlbC5uYW1lLCBtb2RlbCwgLW0pICU+JQogIG11dGF0ZShnbGFuY2UgPSBtb2RlbCAlPiUgbWFwKGdsYW5jZSksCiAgICAgICAgIHRpZHkgPSBtb2RlbCAlPiUgbWFwKHRpZHkpKSAlPiUgCiAgYmluZF9jb2xzKHNlbGVjdChzY2FsZXMuaDMuZG9tLm5leHRfeWVhciwgLW0pKQpgYGAKCmBgYHtyIGgzLW1vZGVscy1iYXllcy1mb3JlaWduLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQojIEdldCBzY2FsaW5nIGZhY3RvcnMKc2NhbGVzLmgzLmZvcmVpZ24ubmV4dF95ZWFyIDwtIG1vZHMuaDMuZm9yZWlnbi5uZXh0X3llYXIucmF3ICU+JSAKICBmaWx0ZXIobSAhPSAib3JpZ2luYWwiKSAlPiUgCiAgc2VsZWN0KG0sIHN0YXJ0c193aXRoKCJzY2FsZXMiKSkgJT4lIAogIGdhdGhlcihzY2FsZXMubmFtZSwgc2NhbGVzLCAtbSkKCiMgR2V0IG1vZGVsIGRldGFpbHMgYW5kIHBhcmFtZXRlcnMKbW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5iYXllcyA8LSBtb2RzLmgzLmZvcmVpZ24ubmV4dF95ZWFyLnJhdyAlPiUKICBmaWx0ZXIobSAhPSAib3JpZ2luYWwiKSAlPiUgCiAgc2VsZWN0KG0sIHN0YXJ0c193aXRoKCJtb2QiKSkgJT4lIAogIGdhdGhlcihtb2RlbC5uYW1lLCBtb2RlbCwgLW0pICU+JQogIG11dGF0ZShnbGFuY2UgPSBtb2RlbCAlPiUgbWFwKGdsYW5jZSksCiAgICAgICAgIHRpZHkgPSBtb2RlbCAlPiUgbWFwKHRpZHkpKSAlPiUgCiAgYmluZF9jb2xzKHNlbGVjdChzY2FsZXMuaDMuZm9yZWlnbi5uZXh0X3llYXIsIC1tKSkKYGBgCgojIyMgTUNNQyBkaWFnbm9zdGljcyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCiMjIyMgQ2hlY2sgZml0CgpBZ2FpbiwgdXNlIG9uZSBvZiB0aGUgaW1wdXRlZCBtb2RlbHMgKGBtb2QuaDMuYmFycmllcnMudG90YWxgKSB0byBjaGVjayBmb3IgZml0IGFuZCBjb252ZXJnZW5jZS4KCmBgYHtyIGgzLWRpYWdub3N0aWNzLWJheWVzfQptb2RlbC50by5jaGVjayA8LSBtb2RzLmgzLmRvbS5uZXh0X3llYXIuYmF5ZXMgJT4lCiAgZmlsdGVyKG0gPT0gImltcDEiLCBtb2RlbC5uYW1lID09ICJtb2QuaDMuYmFycmllcnMudG90YWwiKSAlPiUKICBzZWxlY3QobW9kZWwpICU+JSAuW1sxXV0gJT4lIC5bWzFdXQpgYGAKClBvc3RlcmlvciBwcmVkaWN0aXZlIGRpc3RyaWJ1dGlvbiB2cy4gb2JzZXJ2ZWQgb3V0Y29tZT8KCmBgYHtyIGgzLWRpYWctZGVuc2l0eX0KcHBfY2hlY2sobW9kZWwudG8uY2hlY2ssIHR5cGUgPSAiZGVuc19vdmVybGF5IiwgbnNhbXBsZXMgPSAxMCkgKyAKICB0aGVtZV9kb25vcnMoKQpgYGAKCiMjIyMgQ2hlY2sgY29udmVyZ2VuY2UKCkNoYWluIGNvbnZlcmdlbmNlOgoKYGBge3IgaDMtZGlhZy1kaXZlcmdlbmNlfQpyc3Rhbjo6c3Rhbl9kaWFnKG1vZGVsLnRvLmNoZWNrJGZpdCwgaW5mb3JtYXRpb24gPSAiZGl2ZXJnZW5jZSIpCmBgYAoKCiMjIyBSZXN1bHRzIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKIyMjIyBQcm9wb3J0aW9uIHRvIGRvbWVzdGljIE5HT3MKCmBgYHtyIGgzLXRhYmxlLWRvbWVzdGljLCByZXN1bHRzPSJhc2lzIiwgd2FybmluZz1GQUxTRX0KY2FwdGlvbiA8LSAiVGhlIGVmZmVjdCBvZiBhbnRpLU5HTyBsZWdpc2xhdGlvbiBvbiB0aGUgcHJvcG9ydGlvbiBvZiBVUyBhaWQgY2hhbm5lbGVkIHRocm91Z2ggKmRvbWVzdGljKiBOR09zIGluIHRoZSBmb2xsb3dpbmcgeWVhciAoSH4zfiksIGZ1bGwgbW9kZWxzLiBFYWNoIGNlbGwgY29udGFpbnMgdGhlIHBhcmFtZXRlcidzIHBvc3RlcmlvciBtZWRpYW4sIHRoZSA5NSUgY3JlZGlibGUgaW50ZXJ2YWwsIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgcGFyYW1ldGVyIGlzIGdyZWF0ZXIgdGhhbiBvbmUgKGluIGl0YWxpY3MpIHsjdGJsOmgzLWRvbWVzdGljLWNvZWZzfSIKbm90ZSA8LSBjKCJMb2dpdC1saW5lYXIgbW9kZWxzLiBQZXJjZW50IGNoYW5nZSBvZGRzIHJhdGlvcyByZXBvcnRlZC4iKQoKdGFibGUuaDMuZG9tZXN0aWMgPC0gYmF5ZXNnYXplcihtb2RzLmgzLmRvbS5uZXh0X3llYXIuYmF5ZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IGNhcHRpb24sIG5vdGUgPSBub3RlLCBleHBvbmVudGlhdGUgPSBUUlVFKQoKY2F0KHRhYmxlLmgzLmRvbWVzdGljKQpjYXQodGFibGUuaDMuZG9tZXN0aWMsIGZpbGUgPSBoZXJlKCJPdXRwdXQiLCAidGJsLWgzLWRvbWVzdGljLWNvZWZzLWJheWVzLm1kIikpCmBgYAoKIyMjIyBQcm9wb3J0aW9uIHRvIGZvcmVpZ24gTkdPcwoKYGBge3IgaDMtdGFibGUtZm9yZWlnbiwgcmVzdWx0cz0iYXNpcyIsIHdhcm5pbmc9RkFMU0V9CmNhcHRpb24gPC0gIlRoZSBlZmZlY3Qgb2YgYW50aS1OR08gbGVnaXNsYXRpb24gb24gdGhlIHByb3BvcnRpb24gb2YgVVMgYWlkIGNoYW5uZWxlZCB0aHJvdWdoICpVUy1iYXNlZCBhbmQgaW50ZXJuYXRpb25hbCogTkdPcyBpbiB0aGUgZm9sbG93aW5nIHllYXIgKEh+M34pLCBmdWxsIG1vZGVscy4gRWFjaCBjZWxsIGNvbnRhaW5zIHRoZSBwYXJhbWV0ZXIncyBwb3N0ZXJpb3IgbWVkaWFuLCB0aGUgOTUlIGNyZWRpYmxlIGludGVydmFsLCBhbmQgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIHBhcmFtZXRlciBpcyBncmVhdGVyIHRoYW4gb25lIChpbiBpdGFsaWNzKSB7I3RibDpoMy1mb3JlaWduLWNvZWZzfSIKbm90ZSA8LSBjKCJMb2dpdC1saW5lYXIgbW9kZWxzLiBQZXJjZW50IGNoYW5nZSBvZGRzIHJhdGlvcyByZXBvcnRlZC4iKQoKdGFibGUuaDMuZG9tZXN0aWMgPC0gYmF5ZXNnYXplcihtb2RzLmgzLmZvcmVpZ24ubmV4dF95ZWFyLmJheWVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBjYXB0aW9uLCBub3RlID0gbm90ZSwgZXhwb25lbnRpYXRlID0gVFJVRSkKCmNhdCh0YWJsZS5oMy5kb21lc3RpYykKY2F0KHRhYmxlLmgzLmRvbWVzdGljLCBmaWxlID0gaGVyZSgiT3V0cHV0IiwgInRibC1oMy1mb3JlaWduLWNvZWZzLWJheWVzLm1kIikpCmBgYAoKIyMjIyBQbG90IG9mIHByb3BvcnRpb24gdG8gZG9tZXN0aWMgYW5kIGZvcmVpZ24gTkdPcyB7LmFjdGl2ZX0KCmBgYHtyIHBsb3QtaDMtY29lZnMtYm90aCwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZmlnLndpZHRoPTUuNSwgZmlnLmhlaWdodD0zfQp2YXJzLnRvLnBsb3QgPC0gYygiYmFycmllcnMudG90YWxfd2l0aGluIiwgImJhcnJpZXJzLnRvdGFsX2JldHdlZW4iLAogICAgICAgICAgICAgICAgICAiYWR2b2NhY3lfd2l0aGluIiwgImFkdm9jYWN5X2JldHdlZW4iLCAKICAgICAgICAgICAgICAgICAgImVudHJ5X3dpdGhpbiIsICJlbnRyeV9iZXR3ZWVuIiwgCiAgICAgICAgICAgICAgICAgICJmdW5kaW5nX3dpdGhpbiIsICJmdW5kaW5nX2JldHdlZW4iLAogICAgICAgICAgICAgICAgICAiY3NyZV93aXRoaW4iLCAiY3NyZV9iZXR3ZWVuIikKCm1vZHMuaDMuZG9tLm1lbGRlZCA8LSBiYXllcy5tZWxkKG1vZHMuaDMuZG9tLm5leHRfeWVhci5iYXllcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFycy50by5wbG90LCBleHBvbmVudGlhdGUgPSBUUlVFKSRtZWxkZWQuc3VtbWFyeQoKY29lZnMucmF3LmgzLmRvbSA8LSBtb2RzLmgzLmRvbS5tZWxkZWQgJT4lCiAgbGVmdF9qb2luKGNvZWYubmFtZXMuYWxsLCBieSA9ICJ0ZXJtIikgJT4lCiAgbGVmdF9qb2luKG1vZGVsLm5hbWVzLCBieSA9IGMoIm1vZGVsLm5hbWUiID0gIm1vZGVsIikpICU+JSAKICBtdXRhdGUodGVybSA9IGZhY3Rvcih0ZXJtLCBsZXZlbHMgPSB2YXJzLnRvLnBsb3QsIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgYXJyYW5nZShkZXNjKHRlcm0pKSAlPiUKICBtdXRhdGUodGVybV9wbG90ID0gb3JkZXJlZChmY3RfaW5vcmRlcih0ZXJtX3Bsb3Rfc2hvcnQpKSkgJT4lCiAgbXV0YXRlKGNvZWYudHlwZSA9IGNhc2Vfd2hlbigKICAgIHN0cl9kZXRlY3QoLiR0ZXJtLCAiX3dpdGhpbiIpIH4gIldpdGhpbiIsCiAgICBzdHJfZGV0ZWN0KC4kdGVybSwgIl9iZXR3ZWVuIikgfiAiQmV0d2VlbiIsCiAgKSkgJT4lIAogIG11dGF0ZShjb2VmLnR5cGUgPSBmYWN0b3IoY29lZi50eXBlLCBsZXZlbHMgPSBjKCJXaXRoaW4iLCAiQmV0d2VlbiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBtdXRhdGUobW9kZWxfY2xlYW4gPSBmYWN0b3IobW9kZWxfY2xlYW4sIGxldmVscyA9IHJldih1bmlxdWUobW9kZWxfY2xlYW4pKSwgb3JkZXJlZCA9IFRSVUUpKQoKbW9kcy5oMy5mb3JlaWduLm1lbGRlZCA8LSBiYXllcy5tZWxkKG1vZHMuaDMuZm9yZWlnbi5uZXh0X3llYXIuYmF5ZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJzLnRvLnBsb3QsIGV4cG9uZW50aWF0ZSA9IFRSVUUpJG1lbGRlZC5zdW1tYXJ5Cgpjb2Vmcy5yYXcuaDMuZm9yZWlnbiA8LSBtb2RzLmgzLmZvcmVpZ24ubWVsZGVkICU+JQogIGxlZnRfam9pbihjb2VmLm5hbWVzLmFsbCwgYnkgPSAidGVybSIpICU+JQogIGxlZnRfam9pbihtb2RlbC5uYW1lcywgYnkgPSBjKCJtb2RlbC5uYW1lIiA9ICJtb2RlbCIpKSAlPiUgCiAgbXV0YXRlKHRlcm0gPSBmYWN0b3IodGVybSwgbGV2ZWxzID0gdmFycy50by5wbG90LCBvcmRlcmVkID0gVFJVRSkpICU+JQogIGFycmFuZ2UoZGVzYyh0ZXJtKSkgJT4lCiAgbXV0YXRlKHRlcm1fcGxvdCA9IG9yZGVyZWQoZmN0X2lub3JkZXIodGVybV9wbG90X3Nob3J0KSkpICU+JQogIG11dGF0ZShjb2VmLnR5cGUgPSBjYXNlX3doZW4oCiAgICBzdHJfZGV0ZWN0KC4kdGVybSwgIl93aXRoaW4iKSB+ICJXaXRoaW4iLAogICAgc3RyX2RldGVjdCguJHRlcm0sICJfYmV0d2VlbiIpIH4gIkJldHdlZW4iLAogICkpICU+JSAKICBtdXRhdGUoY29lZi50eXBlID0gZmFjdG9yKGNvZWYudHlwZSwgbGV2ZWxzID0gYygiV2l0aGluIiwgIkJldHdlZW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgbXV0YXRlKG1vZGVsX2NsZWFuID0gZmFjdG9yKG1vZGVsX2NsZWFuLCBsZXZlbHMgPSByZXYodW5pcXVlKG1vZGVsX2NsZWFuKSksIG9yZGVyZWQgPSBUUlVFKSkKCmNvZWZzLmgzLmJvdGggPC0gYmluZF9yb3dzKGBEb21lc3RpYyBOR09zYCA9IGNvZWZzLnJhdy5oMy5kb20sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGBGb3JlaWduIE5HT3NgID0gY29lZnMucmF3LmgzLmZvcmVpZ24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5pZCA9ICJjaGFubmVsIikKCmZpZy5jb2Vmcy5oMyA8LSBnZ3Bsb3QoY29lZnMuaDMuYm90aCwgYWVzKHkgPSB0ZXJtX3Bsb3QsIHggPSBtZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBtb2RlbF9jbGVhbikpICsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKyAKICBnZW9tX3BvaW50cmFuZ2VoKGFlcyh4bWluID0gYDIuNSVgLCB4bWF4ID0gYDk3LjUlYCwgc2hhcGUgPSBjaGFubmVsKSwgCiAgICAgICAgICAgICAgICAgICBzaXplID0gMC41LCBmYXR0ZW4gPSAzLAogICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZXYoaGVpZ2h0ID0gMC41KSkgKyAKICBsYWJzKHggPSAiUGVyY2VudCBjaGFuZ2UgaW4gcmF0aW8gb2YgYWlkIGNoYW5uZWxlZCB0byBOR08gdHlwZSAob2RkcyByYXRpbykiLCB5ID0gTlVMTCkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gbW9kZWwuY29sb3JzKSArCiAgZXhwYW5kX2xpbWl0cyh4ID0gYygwLjUsIDIpKSArCiAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDAuMjUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9IE5VTEwsIG5yb3cgPSAyLCBvcmRlciA9IDIpLAogICAgICAgICBzaGFwZSA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAwLjUsIGxpbmV0eXBlID0gMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gTlVMTCwgbnJvdyA9IDIsIHJldmVyc2UgPSBUUlVFLCBvcmRlciA9IDEpKSArCiAgdGhlbWVfZG9ub3JzKCkgKyAKICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJsZWZ0IiwKICAgICAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbihsID0gLTAuNzUsIHQgPSAtMC41LCB1bml0ID0gImxpbmVzIiksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkpICsKICBmYWNldF93cmFwKH4gY29lZi50eXBlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAyKQpmaWcuY29lZnMuaDMKCmZpZy5zYXZlLmNhaXJvKGZpZy5jb2Vmcy5oMywgZmlsZW5hbWUgPSAiZmlnLWNvZWZzLWgzLWJheWVzIiwKICAgICAgICAgICAgICAgd2lkdGggPSA1LjUsIGhlaWdodCA9IDMpCmBgYAoKIyMjIyBQcm9wb3J0aW9uIHRvIGRvbWVzdGljIE5HT3MgKG5vbmltcHV0ZWQpCgpgYGB7ciBoMy1kb21lc3RpYy1uby1pbXB1dGF0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzY2FsZXMuaDMuZG9tLm5leHRfeWVhci5uby5pbXAgPC0gbW9kcy5oMy5kb20ubmV4dF95ZWFyLnJhdyAlPiUgCiAgZmlsdGVyKG0gPT0gIm9yaWdpbmFsIikgJT4lIAogIHNlbGVjdChtLCBzdGFydHNfd2l0aCgic2NhbGVzIikpICU+JSAKICBwdWxsKHNjYWxlc19oM19kb20uMSkgJT4lIC5bWzFdXQoKIyBHZXQgbW9kZWwgZGV0YWlscyBhbmQgcGFyYW1ldGVycwptb2RzLmgzLmRvbS5uZXh0X3llYXIuYmF5ZXMubm8uaW1wIDwtIG1vZHMuaDMuZG9tLm5leHRfeWVhci5yYXcgJT4lCiAgc2VsZWN0KC1jb250YWlucygic2NhbGVzIikpICU+JSAKICBmaWx0ZXIobSA9PSAib3JpZ2luYWwiKSAlPiUgCiAgZ2F0aGVyKG1vZGVsLm5hbWUsIG1vZGVsLCAtbSkgJT4lCiAgbXV0YXRlKGdsYW5jZSA9IG1vZGVsICU+JSBtYXAoZ2xhbmNlKSwKICAgICAgICAgdGlkeSA9IG1vZGVsICU+JSBtYXAodGlkeSwgZWZmZWN0cyA9ICJmaXhlZCIpKSAlPiUgCiAgbXV0YXRlKG1vZGVsX3NjYWxlID0gbW9kZWwgJT4lIG1hcChhZGRfc2NhbGVtY21jKSkKCmgzX2RvbV9jb2VmcyA8LSBtb2RzLmgzLmRvbS5uZXh0X3llYXIuYmF5ZXMubm8uaW1wICU+JQogIHVubmVzdCh0aWR5KSAlPiUgCiAgZmlsdGVyKCFkdXBsaWNhdGVkKHRlcm0sIGZyb21MYXN0ID0gVFJVRSkpICU+JQogIG11dGF0ZSh0ZXJtX2pvaW4gPSBzdHJfcmVwbGFjZSh0ZXJtLCAiVFJVRSIsICIiKSkgJT4lIAogIGxlZnRfam9pbihjb2VmLm5hbWVzLmFsbCwgYnkgPSBjKCJ0ZXJtX2pvaW4iID0gInRlcm0iKSkgJT4lIAogIGZpbHRlcih0ZXJtICE9ICJJbnRlcmNlcHQiKQoKaDNfZG9tX2NvZWZzX25hbWVkIDwtIGgzX2RvbV9jb2VmcyAlPiUgcHVsbCh0ZXJtKSAlPiUgCiAgc2V0X25hbWVzKGgzX2RvbV9jb2VmcyR0ZXJtX2NsZWFuKQoKaHV4cmVnKG1vZHMuaDMuZG9tLm5leHRfeWVhci5iYXllcy5uby5pbXAkbW9kZWxfc2NhbGUsCiAgICAgICBjb2VmcyA9IGMoaDNfZG9tX2NvZWZzX25hbWVkLCBDb25zdGFudCA9ICJJbnRlcmNlcHQiKSwKICAgICAgIHN0YXJzID0gTlVMTCwgc3RhdGlzdGljcyA9IGMoTiA9ICJub2JzIiksCiAgICAgICB0aWR5X2FyZ3MgPSBsaXN0KGNvbmYuaW50ID0gVFJVRSwgcHJvYiA9IDAuOTUsIGV4cG9uZW50aWF0ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdHMgPSAiZml4ZWQiLCBzY2FsaW5ncyA9IHNjYWxlcy5oMy5kb20ubmV4dF95ZWFyLm5vLmltcCksCiAgICAgICBlcnJvcl9mb3JtYXQgPSAiKHtjb25mLmxvd30sIHtjb25mLmhpZ2h9KSIpCmBgYAoKIyMjIyBQcm9wb3J0aW9uIHRvIGZvcmVpZ24gTkdPcyAobm9uaW1wdXRlZCkKCmBgYHtyIGgzLWZvcmVpZ24tbm8taW1wdXRhdGlvbiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc2NhbGVzLmgzLmZvcmVpZ24ubmV4dF95ZWFyLm5vLmltcCA8LSBtb2RzLmgzLmZvcmVpZ24ubmV4dF95ZWFyLnJhdyAlPiUgCiAgZmlsdGVyKG0gPT0gIm9yaWdpbmFsIikgJT4lIAogIHNlbGVjdChtLCBzdGFydHNfd2l0aCgic2NhbGVzIikpICU+JSAKICBwdWxsKHNjYWxlc19oM19mb3JlaWduLjEpICU+JSAuW1sxXV0KCiMgR2V0IG1vZGVsIGRldGFpbHMgYW5kIHBhcmFtZXRlcnMKbW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5iYXllcy5uby5pbXAgPC0gbW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5yYXcgJT4lCiAgc2VsZWN0KC1jb250YWlucygic2NhbGVzIikpICU+JSAKICBmaWx0ZXIobSA9PSAib3JpZ2luYWwiKSAlPiUgCiAgZ2F0aGVyKG1vZGVsLm5hbWUsIG1vZGVsLCAtbSkgJT4lCiAgbXV0YXRlKGdsYW5jZSA9IG1vZGVsICU+JSBtYXAoZ2xhbmNlKSwKICAgICAgICAgdGlkeSA9IG1vZGVsICU+JSBtYXAodGlkeSwgZWZmZWN0cyA9ICJmaXhlZCIpKSAlPiUgCiAgbXV0YXRlKG1vZGVsX3NjYWxlID0gbW9kZWwgJT4lIG1hcChhZGRfc2NhbGVtY21jKSkKCmgzX2ZvcmVpZ25fY29lZnMgPC0gbW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5iYXllcy5uby5pbXAgJT4lCiAgdW5uZXN0KHRpZHkpICU+JSAKICBmaWx0ZXIoIWR1cGxpY2F0ZWQodGVybSwgZnJvbUxhc3QgPSBUUlVFKSkgJT4lCiAgbXV0YXRlKHRlcm1fam9pbiA9IHN0cl9yZXBsYWNlKHRlcm0sICJUUlVFIiwgIiIpKSAlPiUgCiAgbGVmdF9qb2luKGNvZWYubmFtZXMuYWxsLCBieSA9IGMoInRlcm1fam9pbiIgPSAidGVybSIpKSAlPiUgCiAgZmlsdGVyKHRlcm0gIT0gIkludGVyY2VwdCIpCgpoM19mb3JlaWduX2NvZWZzX25hbWVkIDwtIGgzX2ZvcmVpZ25fY29lZnMgJT4lIHB1bGwodGVybSkgJT4lIAogIHNldF9uYW1lcyhoM19mb3JlaWduX2NvZWZzJHRlcm1fY2xlYW4pCgpodXhyZWcobW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5iYXllcy5uby5pbXAkbW9kZWxfc2NhbGUsCiAgICAgICBjb2VmcyA9IGMoaDNfZm9yZWlnbl9jb2Vmc19uYW1lZCwgQ29uc3RhbnQgPSAiSW50ZXJjZXB0IiksCiAgICAgICBzdGFycyA9IE5VTEwsIHN0YXRpc3RpY3MgPSBjKE4gPSAibm9icyIpLAogICAgICAgdGlkeV9hcmdzID0gbGlzdChjb25mLmludCA9IFRSVUUsIHByb2IgPSAwLjk1LCBleHBvbmVudGlhdGUgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICBlZmZlY3RzID0gImZpeGVkIiwgc2NhbGluZ3MgPSBzY2FsZXMuaDMuZm9yZWlnbi5uZXh0X3llYXIubm8uaW1wKSwKICAgICAgIGVycm9yX2Zvcm1hdCA9ICIoe2NvbmYubG93fSwge2NvbmYuaGlnaH0pIikKYGBgCgojIyMgUHJlZGljdGVkIHByb3BvcnRpb24gb2YgYWlkIGNoYW5uZWxlZCB0byBkb21lc3RpYyBvciBmb3JlaWduIE5HT3MKCmBgYHtyIGgzLXByZWRpY3QtdG90YWwsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUV9Cm1vZGVsIDwtIG1vZHMuaDMuZm9yZWlnbi5uZXh0X3llYXIuYmF5ZXMgJT4lCiAgZmlsdGVyKG0gPT0gImltcDEiLCBtb2RlbC5uYW1lID09ICJtb2QuaDMuZm9yZWlnbi5iYXJyaWVycy50b3RhbCIpICU+JQogIHNlbGVjdChtb2RlbCkgJT4lIC5bWzFdXSAlPiUgLltbMV1dCgpuZXcuZGF0YSA8LSBnZXRfYWxsX3ZhcnMobW9kZWwkZm9ybXVsYSwgZGF0YSA9IG1vZGVsJGRhdGEpICU+JQogIHNlbGVjdCgtYyhiYXJyaWVycy50b3RhbF93aXRoaW4sIHllYXIsIGNvd2NvZGUpKSAlPiUKICBzdW1tYXJpc2VfYWxsKHR5cGljYWwpICU+JQogIG11dGF0ZShpZCA9IDEpICU+JQogIHJpZ2h0X2pvaW4oZXhwYW5kLmdyaWQoYmFycmllcnMudG90YWxfd2l0aGluID0gc2VxKC0zLCA0LCAwLjUpLAogICAgICAgICAgICAgICAgICAgICAgICAgY293Y29kZSA9IDEwMDA6MTA0OSwKICAgICAgICAgICAgICAgICAgICAgICAgIHllYXIgPSAyMDAwOjIwMTIsCiAgICAgICAgICAgICAgICAgICAgICAgICBpZCA9IDEpLCBieSA9ICJpZCIpICU+JSBzZWxlY3QoLWlkKQoKcHJlZGljdGVkLmgzLmZvcmVpZ24uYmFycmllcnMudG90YWwgPC0gbmV3LmRhdGEgJT4lCiAgbmVzdCgtY293Y29kZSkgJT4lCiAgbXV0YXRlKHByZWRpY3RlZCA9IGZ1dHVyZV9tYXAoLnggPSBkYXRhLCB+IGdlbmVyYXRlX3ByZWRpY3Rpb25zKC54KSkpICU+JQogIHVubmVzdCgpICU+JSAKICBtdXRhdGUobmdvX3R5cGUgPSAiRm9yZWlnbiBOR09zIikKCm1vZGVsIDwtIG1vZHMuaDMuZG9tLm5leHRfeWVhci5iYXllcyAlPiUKICBmaWx0ZXIobSA9PSAiaW1wMSIsIG1vZGVsLm5hbWUgPT0gIm1vZC5oMy5iYXJyaWVycy50b3RhbCIpICU+JQogIHNlbGVjdChtb2RlbCkgJT4lIC5bWzFdXSAlPiUgLltbMV1dCgpuZXcuZGF0YSA8LSBnZXRfYWxsX3ZhcnMobW9kZWwkZm9ybXVsYSwgZGF0YSA9IG1vZGVsJGRhdGEpICU+JQogIHNlbGVjdCgtYyhiYXJyaWVycy50b3RhbF93aXRoaW4sIHllYXIsIGNvd2NvZGUpKSAlPiUKICBzdW1tYXJpc2VfYWxsKHR5cGljYWwpICU+JQogIG11dGF0ZShpZCA9IDEpICU+JQogIHJpZ2h0X2pvaW4oZXhwYW5kLmdyaWQoYmFycmllcnMudG90YWxfd2l0aGluID0gc2VxKC0zLCA0LCAwLjUpLAogICAgICAgICAgICAgICAgICAgICAgICAgY293Y29kZSA9IDEwMDA6MTA0OSwKICAgICAgICAgICAgICAgICAgICAgICAgIHllYXIgPSAyMDAwOjIwMTIsCiAgICAgICAgICAgICAgICAgICAgICAgICBpZCA9IDEpLCBieSA9ICJpZCIpICU+JSBzZWxlY3QoLWlkKQoKcHJlZGljdGVkLmgzLmRvbS5iYXJyaWVycy50b3RhbCA8LSBuZXcuZGF0YSAlPiUKICBuZXN0KC1jb3djb2RlKSAlPiUKICBtdXRhdGUocHJlZGljdGVkID0gZnV0dXJlX21hcCgueCA9IGRhdGEsIH4gZ2VuZXJhdGVfcHJlZGljdGlvbnMoLngpKSkgJT4lCiAgdW5uZXN0KCkgJT4lIAogIG11dGF0ZShuZ29fdHlwZSA9ICJEb21lc3RpYyBOR09zIikKCmRmLnBsb3QuZGF0YS5oMyA8LSBiaW5kX3Jvd3MocHJlZGljdGVkLmgzLmZvcmVpZ24uYmFycmllcnMudG90YWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdGVkLmgzLmRvbS5iYXJyaWVycy50b3RhbCkgJT4lCiAgZ3JvdXBfYnkoY293Y29kZSwgbmdvX3R5cGUsIGJhcnJpZXJzLnRvdGFsX3dpdGhpbikgJT4lCiAgc3VtbWFyaXNlX2F0KHZhcnMocHJlZGljdGVkKSwgZnVucyhtZWFuKC4pKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUodmFsdWUuZml4ZWQgPSBpbnYubG9naXQocHJlZGljdGVkLCBhID0gMC4wMDEpKQoKZGYucGxvdC5kYXRhLm1lYW4uaDMgPC0gZGYucGxvdC5kYXRhLmgzICU+JQogIGdyb3VwX2J5KG5nb190eXBlLCBiYXJyaWVycy50b3RhbF93aXRoaW4pICU+JQogIHN1bW1hcmlzZShwcmVkaWN0ZWQgPSBtZWFuKHByZWRpY3RlZCkpICU+JQogIG11dGF0ZSh2YWx1ZS5maXhlZCA9IGludi5sb2dpdChwcmVkaWN0ZWQsIGEgPSAwLjAwMSkpICU+JQogIG11dGF0ZShjb3djb2RlID0gMSkgICMgRmFrZSBjb3VudHJ5IHNvIHRoZSBsaW5lIHBsb3RzCmBgYAoKYGBge3IgaDMtcHJlZGljdC1pbmRpdmlkdWFsLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQpiYXJyaWVycy5pbmRpdi5jbGVhbi5uYW1lcyA8LSB0cmliYmxlKAogIH5iYXJyaWVyLCB+YmFycmllci5jbGVhbiwKICAiYWR2b2NhY3lfd2l0aGluIiwgIkJhcnJpZXJzIHRvIGFkdm9jYWN5IiwKICAiZW50cnlfd2l0aGluIiwgIkJhcnJpZXJzIHRvIGVudHJ5IiwKICAiZnVuZGluZ193aXRoaW4iLCAiQmFycmllcnMgdG8gZnVuZGluZyIKKQoKbW9kZWwgPC0gbW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5iYXllcyAlPiUKICBmaWx0ZXIobSA9PSAiaW1wMSIsIG1vZGVsLm5hbWUgPT0gIm1vZC5oMy5mb3JlaWduLnR5cGUudG90YWwiKSAlPiUKICBzZWxlY3QobW9kZWwpICU+JSAuW1sxXV0gJT4lIC5bWzFdXQoKaHlwb3RoZXRpY2FsLmJvdW5kcyA8LSBnZXRfYWxsX3ZhcnMobW9kZWwkZm9ybXVsYSwgZGF0YSA9IG1vZGVsJGRhdGEpICU+JQogIHNlbGVjdChhZHZvY2FjeV93aXRoaW4sIGVudHJ5X3dpdGhpbiwgZnVuZGluZ193aXRoaW4pICU+JQogIHN1bW1hcmlzZV9hbGwoZnVucyhtaW4sIG1heCkpICU+JQogIGdhdGhlcihrZXksIHZhbHVlKSAlPiUKICBtdXRhdGUodmFsdWUgPSByb3VuZCh2YWx1ZSwgMCkpICU+JQogICMgSGF2ZSB0byBzZXBhcmF0ZSBvbiBfbSBiZWNhdXNlIG9mIG11bHRpcGxlIF9zLCB0aGVuIHJlLWFkZCB0aGUgbQogIHNlcGFyYXRlKGtleSwgaW50byA9IGMoInRlcm0iLCAidmFyaWFibGUiKSwgc2VwID0gIl9tIikgJT4lCiAgbXV0YXRlKHZhcmlhYmxlID0gcGFzdGUwKCJtIiwgdmFyaWFibGUpKSAlPiUKICBzcHJlYWQodmFyaWFibGUsIHZhbHVlKQoKbmV3LmRhdGEuaHlwb3RoZXRpY2FsLm5lc3RlZCA8LSBoeXBvdGhldGljYWwuYm91bmRzICU+JQogIG5lc3QoLXRlcm0pICU+JQogIG11dGF0ZShuZXdkYXRhID0gbWFwMigueCA9IGRhdGEsIC55ID0gdGVybSwKICAgICAgICAgICAgICAgICAgICAgICAgfiBleHBhbmQuZ3JpZCh0ZXJtID0gc2VxKC54JG1pbiwgLngkbWF4LCBieSA9IDAuNSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY293Y29kZSA9IDEwMDA6MTA0OSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ZWFyID0gMjAwMDoyMDEyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkID0gMSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSZW5hbWUgdGhlIHRlcm0gY29sdW1uIHRvIHRoZSBhY3R1YWwgdGVybSBuYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWFncml0dHI6OnNldF9jb2xuYW1lcyhjKC55LCBjb2xuYW1lcyguKVstMV0pKSkpCgpuZXcuZGF0YS5oeXBvdGhldGljYWwgPC0gYXNfdGliYmxlKGJpbmRfcm93cyhuZXcuZGF0YS5oeXBvdGhldGljYWwubmVzdGVkJG5ld2RhdGEpKSAlPiUKICBtdXRhdGVfYXQodmFycyhjb250YWlucygid2l0aGluIikpLCBmdW5zKGlmZWxzZShpcy5uYSguKSwgMCwgLikpKQoKIyBGb3JlaWduIE5HT3MKbmV3LmRhdGEgPC0gZ2V0X2FsbF92YXJzKG1vZGVsJGZvcm11bGEsIGRhdGEgPSBtb2RlbCRkYXRhKSAlPiUKICBzZWxlY3QoLWMoYWR2b2NhY3lfd2l0aGluLCBlbnRyeV93aXRoaW4sIGZ1bmRpbmdfd2l0aGluLCB5ZWFyLCBjb3djb2RlKSkgJT4lCiAgc3VtbWFyaXNlX2FsbCh0eXBpY2FsKSAlPiUKICBtdXRhdGUoaWQgPSAxKSAlPiUKICByaWdodF9qb2luKG5ldy5kYXRhLmh5cG90aGV0aWNhbCwgYnkgPSAiaWQiKSAlPiUgc2VsZWN0KC1pZCkKCnByZWRpY3RlZC5oMy5mb3JlaWduLmJhcnJpZXJzLmluZGl2aWR1YWwgPC0gbmV3LmRhdGEgJT4lCiAgbmVzdCgtY293Y29kZSkgJT4lCiAgbXV0YXRlKHByZWRpY3RlZCA9IGZ1dHVyZV9tYXAoLnggPSBkYXRhLCB+IGdlbmVyYXRlX3ByZWRpY3Rpb25zKC54KSkpICU+JQogIHVubmVzdCgpICU+JSAKICBtdXRhdGUobmdvX3R5cGUgPSAiRm9yZWlnbiBOR09zIikKCiMgRG9tZXN0aWMgTkdPcwptb2RlbCA8LSBtb2RzLmgzLmRvbS5uZXh0X3llYXIuYmF5ZXMgJT4lCiAgZmlsdGVyKG0gPT0gImltcDEiLCBtb2RlbC5uYW1lID09ICJtb2QuaDMudHlwZS50b3RhbCIpICU+JQogIHNlbGVjdChtb2RlbCkgJT4lIC5bWzFdXSAlPiUgLltbMV1dCgpuZXcuZGF0YSA8LSBnZXRfYWxsX3ZhcnMobW9kZWwkZm9ybXVsYSwgZGF0YSA9IG1vZGVsJGRhdGEpICU+JQogIHNlbGVjdCgtYyhhZHZvY2FjeV93aXRoaW4sIGVudHJ5X3dpdGhpbiwgZnVuZGluZ193aXRoaW4sIHllYXIsIGNvd2NvZGUpKSAlPiUKICBzdW1tYXJpc2VfYWxsKHR5cGljYWwpICU+JQogIG11dGF0ZShpZCA9IDEpICU+JQogIHJpZ2h0X2pvaW4obmV3LmRhdGEuaHlwb3RoZXRpY2FsLCBieSA9ICJpZCIpICU+JSBzZWxlY3QoLWlkKQoKcHJlZGljdGVkLmgzLmRvbS5iYXJyaWVycy5pbmRpdmlkdWFsIDwtIG5ldy5kYXRhICU+JQogIG5lc3QoLWNvd2NvZGUpICU+JQogIG11dGF0ZShwcmVkaWN0ZWQgPSBmdXR1cmVfbWFwKC54ID0gZGF0YSwgfiBnZW5lcmF0ZV9wcmVkaWN0aW9ucygueCkpKSAlPiUKICB1bm5lc3QoKSAlPiUgCiAgbXV0YXRlKG5nb190eXBlID0gIkRvbWVzdGljIE5HT3MiKQoKZGYucGxvdC5kYXRhLmluZGl2LmgzIDwtIGJpbmRfcm93cyhwcmVkaWN0ZWQuaDMuZm9yZWlnbi5iYXJyaWVycy5pbmRpdmlkdWFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RlZC5oMy5kb20uYmFycmllcnMuaW5kaXZpZHVhbCkgJT4lCiAgZ2F0aGVyKGJhcnJpZXIsIGJhcnJpZXIudmFsdWUsIGMoYWR2b2NhY3lfd2l0aGluLCBlbnRyeV93aXRoaW4sIGZ1bmRpbmdfd2l0aGluKSkgJT4lCiAgZ3JvdXBfYnkoY293Y29kZSwgbmdvX3R5cGUsIGJhcnJpZXIudmFsdWUsIGJhcnJpZXIpICU+JQogIHN1bW1hcmlzZV9hdCh2YXJzKHByZWRpY3RlZCksIGZ1bnMobWVhbiguKSkpICU+JQogIG11dGF0ZSh2YWx1ZS5maXhlZCA9IGludi5sb2dpdChwcmVkaWN0ZWQsIGEgPSAwLjAwMSkpICU+JSAKICBsZWZ0X2pvaW4oYmFycmllcnMuaW5kaXYuY2xlYW4ubmFtZXMsIGJ5ID0gImJhcnJpZXIiKQoKZGYucGxvdC5kYXRhLm1lYW4uaW5kaXYuaDMgPC0gZGYucGxvdC5kYXRhLmluZGl2LmgzICU+JQogIGdyb3VwX2J5KG5nb190eXBlLCBiYXJyaWVyLCBiYXJyaWVyLnZhbHVlKSAlPiUKICBzdW1tYXJpc2UocHJlZGljdGVkID0gbWVhbihwcmVkaWN0ZWQpKSAlPiUKICBtdXRhdGUoY293Y29kZSA9IDEpICU+JSAgIyBGYWtlIGNvdW50cnkgc28gdGhlIGxpbmUgcGxvdHMKICBtdXRhdGUodmFsdWUuZml4ZWQgPSBpbnYubG9naXQocHJlZGljdGVkLCBhID0gMC4wMDEpKSAlPiUgCiAgbGVmdF9qb2luKGJhcnJpZXJzLmluZGl2LmNsZWFuLm5hbWVzLCBieSA9ICJiYXJyaWVyIikKYGBgCgpgYGB7ciBoMy1wcmVkaWN0LWJvdGgtcGxvdCwgZmlnLndpZHRoPTUuNSwgZmlnLmhlaWdodD00fQojIENvbWJpbmUgdGhlIHR3byBwbG90IGRhdGEgZnJhbWVzCmRmLnBsb3QuZGF0YS5ib3RoLmgzIDwtIGRmLnBsb3QuZGF0YS5oMyAlPiUKICBtdXRhdGUoYmFycmllciA9ICJiYXJyaWVycy50b3RhbF93aXRoaW4iLCBiYXJyaWVyLmNsZWFuID0gIlRvdGFsIGJhcnJpZXJzIikgJT4lCiAgcmVuYW1lKGJhcnJpZXIudmFsdWUgPSBiYXJyaWVycy50b3RhbF93aXRoaW4pICU+JQogIGJpbmRfcm93cyhkZi5wbG90LmRhdGEuaW5kaXYuaDMpICU+JQogIG11dGF0ZShiYXJyaWVyLmNsZWFuID0gb3JkZXJlZChmY3RfaW5vcmRlcihiYXJyaWVyLmNsZWFuKSksCiAgICAgICAgIGhpZ2hsaWdodCA9IGlmZWxzZShiYXJyaWVyLmNsZWFuID09ICJUb3RhbCBiYXJyaWVycyIsIFRSVUUsIEZBTFNFKSkgJT4lIAogIG11dGF0ZShuZ29fdHlwZSA9IHJlY29kZShuZ29fdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYERvbWVzdGljIE5HT3NgID0gIlByb3BvcnRpb24gY2hhbm5lbGVkIHRvIGRvbWVzdGljIE5HT3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBgRm9yZWlnbiBOR09zYCA9ICLigKYgdG8gZm9yZWlnbiBOR09zIiksCiAgICAgICAgIG5nb190eXBlID0gZmN0X2lub3JkZXIobmdvX3R5cGUsIG9yZGVyZWQgPSBUUlVFKSkKCmRmLnBsb3QuZGF0YS5tZWFuLmJvdGguaDMgPC0gZGYucGxvdC5kYXRhLm1lYW4uaDMgJT4lCiAgbXV0YXRlKGJhcnJpZXIgPSAiYmFycmllcnMudG90YWxfd2l0aGluIiwgYmFycmllci5jbGVhbiA9ICJUb3RhbCBiYXJyaWVycyIpICU+JQogIHJlbmFtZShiYXJyaWVyLnZhbHVlID0gYmFycmllcnMudG90YWxfd2l0aGluKSAlPiUKICBiaW5kX3Jvd3MoZGYucGxvdC5kYXRhLm1lYW4uaW5kaXYuaDMpICU+JQogIG11dGF0ZShiYXJyaWVyLmNsZWFuID0gb3JkZXJlZChmY3RfaW5vcmRlcihiYXJyaWVyLmNsZWFuKSkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShuZ29fdHlwZSA9IHJlY29kZShuZ29fdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYERvbWVzdGljIE5HT3NgID0gIlByb3BvcnRpb24gY2hhbm5lbGVkIHRvIGRvbWVzdGljIE5HT3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBgRm9yZWlnbiBOR09zYCA9ICLigKYgdG8gZm9yZWlnbiBOR09zIiksCiAgICAgICAgIG5nb190eXBlID0gZmN0X2lub3JkZXIobmdvX3R5cGUsIG9yZGVyZWQgPSBUUlVFKSkKCiMgQ3JlYXRlIGRhdGEgZnJhbWUgZm9yIGhpZ2hsaWdodGluZyB0aGUgdG90YWwgcGFuZWwKZGYucGFuZWwuaGlnaGxpZ2h0LmgzIDwtIGRmLnBsb3QuZGF0YS5ib3RoLmgzICU+JQogIGRpc3RpbmN0KGJhcnJpZXIuY2xlYW4sIGhpZ2hsaWdodCkKCmZpZy5wcmVkaWN0ZWQuaDMuYmFycmllcnMuYm90aCA8LSAKICBnZ3Bsb3QoZGYucGxvdC5kYXRhLmJvdGguaDMsIAogICAgICAgICBhZXMoeCA9IGJhcnJpZXIudmFsdWUsIHkgPSB2YWx1ZS5maXhlZCwgY29sb3IgPSBuZ29fdHlwZSwKICAgICAgICAgICAgIGdyb3VwID0gaW50ZXJhY3Rpb24obmdvX3R5cGUsIGNvd2NvZGUpKSkgKyAKICBnZW9tX3JlY3QoZGF0YSA9IGRmLnBhbmVsLmhpZ2hsaWdodC5oMywgYWVzKGZpbGwgPSBoaWdobGlnaHQpLCBpbmhlcml0LmFlcyA9IEZBTFNFLAogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGFscGhhID0gMC4xNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAwLjUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2l6ZSA9IDAuMSwgYWxwaGEgPSAwLjEpICsKICBnZW9tX3Ntb290aChkYXRhID0gZGYucGxvdC5kYXRhLm1lYW4uYm90aC5oMywgc2l6ZSA9IDEsIG1ldGhvZCA9ICJsbSIpICsKICBsYWJzKHggPSAiRGlmZmVyZW5jZSBmcm9tIGF2ZXJhZ2UgbGV2ZWwgb2YgTkdPIGxlZ2lzbGF0aW9uIGluIGNvdW50cnkgKHdpdGhpbiBlZmZlY3QpIiwKICAgICAgIHkgPSAiUHJlZGljdGVkIHByb3BvcnRpb24gb2ZcbmFpZCBjaGFubmVsZWQgdG8gdHlwZSBvZiBOR09cbmluIHRoZSBmb2xsb3dpbmcgeWVhciIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoTkEsICJncmV5NTAiKSwgZ3VpZGUgPSBGQUxTRSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJncmV5NjAiLCAiYmxhY2siKSwgbmFtZSA9IE5VTEwpICsgCiAgZmFjZXRfd3JhcCh+IGJhcnJpZXIuY2xlYW4sIHNjYWxlcyA9ICJmcmVlX3giLCBuY29sID0gMikgKwogIHRoZW1lX2Rvbm9ycygpICsgCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCksCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAibGVmdCIsCiAgICAgICAgbGVnZW5kLm1hcmdpbiA9IG1hcmdpbihsID0gMCkpCmZpZy5wcmVkaWN0ZWQuaDMuYmFycmllcnMuYm90aAoKZmlnLnNhdmUuY2Fpcm8oZmlnLnByZWRpY3RlZC5oMy5iYXJyaWVycy5ib3RoLCBmaWxlbmFtZSA9ICJmaWctcHJlZGljdGVkLWgzIiwKICAgICAgICAgICAgICAgd2lkdGggPSA1LjUsIGhlaWdodCA9IDQpCmBgYAoKCiMjIFNhdmUgZGF0YQoKU2F2ZSBDU1ZzIG9mIHByZWRpY3RlZCBkYXRhIGZvciB1c2UgaW4gb3RoZXIgcHJvamVjdHMKCmBgYHtyIHNhdmUtcHJlZGljdGVkfQpwcmVkaWN0aW9ucyA8LSB0cmliYmxlKAogIH5wcmVkaWN0aW9uLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH5maWxlbmFtZSwKICBwcmVkaWN0ZWQuaDEuYmFycmllcnMudG90YWwsICAgICAgICAgICAgICAicHJlZGljdGVkX2gxX2JhcnJpZXJzX3RvdGFsIiwKICBwcmVkaWN0ZWQuaDEuYmFycmllcnMuaW5kaXZpZHVhbCwgICAgICAgICAicHJlZGljdGVkX2gxX2JhcnJpZXJzX2luZGl2aWR1YWwiLAogIHByZWRpY3RlZC5oMi5iYXJyaWVycy50b3RhbCwgICAgICAgICAgICAgICJwcmVkaWN0ZWRfaDJfYmFycmllcnNfdG90YWwiLAogIHByZWRpY3RlZC5oMi5iYXJyaWVycy5pbmRpdmlkdWFsLCAgICAgICAgICJwcmVkaWN0ZWRfaDJfYmFycmllcnNfaW5kaXZpZHVhbCIsCiAgcHJlZGljdGVkLmgzLmRvbS5iYXJyaWVycy50b3RhbCwgICAgICAgICAgInByZWRpY3RlZF9oM19kb21fYmFycmllcnNfdG90YWwiLAogIHByZWRpY3RlZC5oMy5kb20uYmFycmllcnMuaW5kaXZpZHVhbCwgICAgICJwcmVkaWN0ZWRfaDNfZG9tX2JhcnJpZXJzX2luZGl2aWR1YWwiLAogIHByZWRpY3RlZC5oMy5mb3JlaWduLmJhcnJpZXJzLnRvdGFsLCAgICAgICJwcmVkaWN0ZWRfaDNfZm9yZWlnbl9iYXJyaWVyc190b3RhbCIsCiAgcHJlZGljdGVkLmgzLmZvcmVpZ24uYmFycmllcnMuaW5kaXZpZHVhbCwgInByZWRpY3RlZF9oM19mb3JlaWduX2JhcnJpZXJzX2luZGl2aWR1YWwiCikgJT4lIAogIHdhbGsyKC54ID0gLiRwcmVkaWN0aW9uLCAueSA9IC4kZmlsZW5hbWUsIAogICAgICAgIC5mID0gfiB3cml0ZV9jc3YoLngsIHBhdGggPSBoZXJlKCJEYXRhIiwgImRhdGFfZXhwb3J0IiwgcGFzdGUwKC55LCAiLmNzdiIpKSkpCmBgYAoKCiMjIEgyOiBaZXJvLW9uZS1pbmZsYXRlZCBiZXRhCgpUaGUgYmlnIGNhdmVhdCBoZXJlIGlzIHRoYXQgd2UgY2FuJ3QgZG8gYSAxOjEgbWFwcGluZyBvZiB0aGVzZSBjb2VmZmljaWVudHMgdG8gdGhlIGZyYWN0aW9uYWwgbG9naXQgbW9kZWxzLCBzaW5jZSB0aGUgY29lZmZpY2llbnRzIGhlcmUgb25seSBhcHBseSB0byB0aGUgbm9uLXplcm8gYW5kIG5vbi1vbmUgcGFydHMgb2YgdGhlIG1vZGVsLiBXaGF0J3MgaW1wb3J0YW50IGZvciByb2J1c3RuZXNzIGlzIHRoYXQgdGhlIGNvZWZmaWNpZW50cyBhbGwgZ28gaW4gdGhlIHNhbWUgZGlyZWN0aW9uIGFzIHRoZSBmcmFjdGlvbmFsIGxvZ2l0IG1vZGVsICh0aG91Z2ggd2l0aCBsZXNzIHNpZ25pZmljYW5jZSwgc2luY2UgZGlmZmVyZW50IHBhcnRzIG9mIHRoZSBtb2RlbCBleHBsYWluIHRoZSBwcmVzZW5jZS9hYnNlbmNlIHNpZ25pZmljYW5jZSkuCgpgYGB7ciBoMi1tb2RlbHMtYmF5ZXMtem9pYiwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRX0KIyBHZXQgc2NhbGluZyBmYWN0b3JzCnNjYWxlcy5oMi5uZXh0X3llYXIuem9pYiA8LSBtb2RzLmgyLm5leHRfeWVhci5yYXcuYmF5ZXMuem9pYiAlPiUgCiAgZmlsdGVyKG0gIT0gIm9yaWdpbmFsIikgJT4lIAogIHNlbGVjdChtLCBzdGFydHNfd2l0aCgic2NhbGVzIikpICU+JSAKICBnYXRoZXIoc2NhbGVzLm5hbWUsIHNjYWxlcywgLW0pCgojIEdldCBtb2RlbCBkZXRhaWxzIGFuZCBwYXJhbWV0ZXJzCm1vZHMuaDIubmV4dF95ZWFyLmJheWVzLnpvaWIgPC0gbW9kcy5oMi5uZXh0X3llYXIucmF3LmJheWVzLnpvaWIgJT4lCiAgZmlsdGVyKG0gIT0gIm9yaWdpbmFsIikgJT4lIAogIHNlbGVjdChtLCBzdGFydHNfd2l0aCgibW9kIikpICU+JSAKICBnYXRoZXIobW9kZWwubmFtZSwgbW9kZWwsIC1tKSAlPiUKICBtdXRhdGUoZ2xhbmNlID0gbW9kZWwgJT4lIG1hcChnbGFuY2UpLAogICAgICAgICB0aWR5ID0gbW9kZWwgJT4lIG1hcCh0aWR5KSkgJT4lIAogIGJpbmRfY29scyhzZWxlY3Qoc2NhbGVzLmgyLm5leHRfeWVhci56b2liLCAtbSkpCmBgYAoKCiMjIyBNQ01DIGRpYWdub3N0aWNzIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKIyMjIyBDaGVjayBmaXQKCkFnYWluLCB1c2Ugb25lIG9mIHRoZSBpbXB1dGVkIG1vZGVscyAoYG1vZC5oMi5iYXJyaWVycy50b3RhbC56b2liYCkgdG8gY2hlY2sgZm9yIGZpdCBhbmQgY29udmVyZ2VuY2UuCgpgYGB7ciBoMi1kaWFnbm9zdGljcy1iYXllcy16b2lifQptb2RlbC50by5jaGVjayA8LSBtb2RzLmgyLm5leHRfeWVhci5iYXllcy56b2liICU+JQogIGZpbHRlcihtID09ICJpbXAxIiwgbW9kZWwubmFtZSA9PSAibW9kLmgyLmJhcnJpZXJzLnRvdGFsLnpvaWIiKSAlPiUKICBzZWxlY3QobW9kZWwpICU+JSAuW1sxXV0gJT4lIC5bWzFdXQpgYGAKClBvc3RlcmlvciBwcmVkaWN0aXZlIGRpc3RyaWJ1dGlvbiB2cy4gb2JzZXJ2ZWQgb3V0Y29tZT8KCmBgYHtyIGgyLWRpYWctZGVuc2l0eS16b2lifQpwcF9jaGVjayhtb2RlbC50by5jaGVjaywgdHlwZSA9ICJkZW5zX292ZXJsYXkiLCBuc2FtcGxlcyA9IDEwKSArIAogIHRoZW1lX2Rvbm9ycygpCmBgYAoKIyMjIyBDaGVjayBjb252ZXJnZW5jZQoKQ2hhaW4gY29udmVyZ2VuY2U6CgpgYGB7ciBoMi1kaWFnLWRpdmVyZ2VuY2Utem9pYn0KcnN0YW46OnN0YW5fZGlhZyhtb2RlbC50by5jaGVjayRmaXQsIGluZm9ybWF0aW9uID0gImRpdmVyZ2VuY2UiKQpgYGAKCgojIyMgUmVzdWx0cyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCiMjIyMgQ29lZmZpY2llbnRzCgpgYGB7ciBoMi1wbG90LWNvZWZzLXpvaWIsIGZpZy53aWR0aD01LjUsIGZpZy5oZWlnaHQ9Mi41fQp2YXJzLnRvLnBsb3QgPC0gYygiYmFycmllcnMudG90YWxfd2l0aGluIiwgImJhcnJpZXJzLnRvdGFsX2JldHdlZW4iLAogICAgICAgICAgICAgICAgICAiYWR2b2NhY3lfd2l0aGluIiwgImFkdm9jYWN5X2JldHdlZW4iLCAKICAgICAgICAgICAgICAgICAgImVudHJ5X3dpdGhpbiIsICJlbnRyeV9iZXR3ZWVuIiwgCiAgICAgICAgICAgICAgICAgICJmdW5kaW5nX3dpdGhpbiIsICJmdW5kaW5nX2JldHdlZW4iLAogICAgICAgICAgICAgICAgICAiY3NyZV93aXRoaW4iLCAiY3NyZV9iZXR3ZWVuIikKCm1vZHMuaDIubWVsZGVkLnpvaWIgPC0gYmF5ZXMubWVsZChtb2RzLmgyLm5leHRfeWVhci5iYXllcy56b2liLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFycy50by5wbG90LCBleHBvbmVudGlhdGUgPSBUUlVFKSRtZWxkZWQuc3VtbWFyeQoKcGxvdC5kYXRhIDwtIG1vZHMuaDIubWVsZGVkLnpvaWIgJT4lCiAgbGVmdF9qb2luKGNvZWYubmFtZXMuYWxsLCBieSA9ICJ0ZXJtIikgJT4lCiAgbGVmdF9qb2luKG1vZGVsLm5hbWVzLCBieSA9IGMoIm1vZGVsLm5hbWUiID0gIm1vZGVsIikpICU+JSAKICBtdXRhdGUodGVybSA9IGZhY3Rvcih0ZXJtLCBsZXZlbHMgPSB2YXJzLnRvLnBsb3QsIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgYXJyYW5nZShkZXNjKHRlcm0pKSAlPiUKICBtdXRhdGUodGVybV9wbG90ID0gb3JkZXJlZChmY3RfaW5vcmRlcih0ZXJtX3Bsb3Rfc2hvcnQpKSkgJT4lCiAgbXV0YXRlKGNvZWYudHlwZSA9IGNhc2Vfd2hlbigKICAgIHN0cl9kZXRlY3QoLiR0ZXJtLCAiX3dpdGhpbiIpIH4gIldpdGhpbiIsCiAgICBzdHJfZGV0ZWN0KC4kdGVybSwgIl9iZXR3ZWVuIikgfiAiQmV0d2VlbiIsCiAgKSkgJT4lIAogIG11dGF0ZShjb2VmLnR5cGUgPSBmYWN0b3IoY29lZi50eXBlLCBsZXZlbHMgPSBjKCJXaXRoaW4iLCAiQmV0d2VlbiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBtdXRhdGUobW9kZWxfY2xlYW4gPSBmYWN0b3IobW9kZWxfY2xlYW4sIGxldmVscyA9IHJldih1bmlxdWUobW9kZWxfY2xlYW4pKSwgb3JkZXJlZCA9IFRSVUUpKQoKZmlnLmNvZWZzLmgyLnpvaWIgPC0gZ2dwbG90KHBsb3QuZGF0YSwgYWVzKHggPSBtZWQsIHkgPSB0ZXJtX3Bsb3QsIGNvbG91ciA9IG1vZGVsX2NsZWFuKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAwLjUpICsgIAogIGdlb21fcG9pbnRyYW5nZWgoYWVzKHhtaW4gPSBgMi41JWAsIHhtYXggPSBgOTcuNSVgKSwgc2l6ZSA9IDAuNSwgZmF0dGVuID0gMykgKyAKICBsYWJzKHggPSAiT2RkcyByYXRpbyAiLCB5ID0gTlVMTCkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gbW9kZWwuY29sb3JzLCBuYW1lID0gTlVMTCkgKwogIGV4cGFuZF9saW1pdHMoeCA9IGMoMC42LCAxLjMpKSArCiAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDAuMjUpKSkgKwogIHRoZW1lX2Rvbm9ycygpICsgCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSAibGVmdCIsCiAgICAgICAgbGVnZW5kLmJveC5tYXJnaW4gPSBtYXJnaW4obCA9IC0wLjc1LCB0ID0gLTAuNSwgdW5pdCA9ICJsaW5lcyIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApKSArCiAgZmFjZXRfd3JhcCh+IGNvZWYudHlwZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMikKZmlnLmNvZWZzLmgyLnpvaWIKCmZpZy5zYXZlLmNhaXJvKGZpZy5jb2Vmcy5oMi56b2liLCBmaWxlbmFtZSA9ICJmaWctY29lZnMtaDItYmF5ZXMtem9pYiIsCiAgICAgICAgICAgICAgIHdpZHRoID0gNS41LCBoZWlnaHQgPSAyLjUpCmBgYAoKIyMjIyBDb21wbGV0ZSByZXN1bHRzIGluIGEgdGFibGUKCmBgYHtyIGgyLXRhYmxlLXpvaWIsIHJlc3VsdHM9ImFzaXMiLCB3YXJuaW5nPUZBTFNFfQpjYXB0aW9uIDwtICJUaGUgZWZmZWN0IG9mIGFudGktTkdPIGxlZ2lzbGF0aW9uIG9uIHRoZSBwcm9wb3J0aW9uIG9mIE9FQ0Qgb3ZlcnNlYXMgZGV2ZWxvcG1lbnQgYXNzaXN0YW5jZSAoT0RBKSBjb21taXR0ZWQgdG8gY29udGVudGlvdXMgcHVycG9zZXMgaW4gdGhlIGZvbGxvd2luZyB5ZWFyIChIfjJ+KSwgZnVsbCBtb2RlbHMuIEVhY2ggY2VsbCBjb250YWlucyB0aGUgcGFyYW1ldGVyJ3MgcG9zdGVyaW9yIG1lZGlhbiwgdGhlIDk1JSBjcmVkaWJsZSBpbnRlcnZhbCwgYW5kIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBwYXJhbWV0ZXIgaXMgZ3JlYXRlciB0aGFuIG9uZSAoaW4gaXRhbGljcykuIHsjdGJsOmgyLWNvZWZzLXpvaWJ9Igpub3RlIDwtIGMoIlplcm8tb25lLWluZmxhdGVkIGJldGEgbW9kZWxzLiBPZGRzIHJhdGlvcyByZXBvcnRlZC4iKQoKdGFibGUuaDIuem9pYiA8LSBiYXllc2dhemVyKG1vZHMuaDIubmV4dF95ZWFyLmJheWVzLnpvaWIsIGV4cG9uZW50aWF0ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gY2FwdGlvbiwgbm90ZSA9IG5vdGUpCgpjYXQodGFibGUuaDIuem9pYikKY2F0KHRhYmxlLmgyLnpvaWIsIGZpbGUgPSBoZXJlKCJPdXRwdXQiLCAidGJsLWgyLWNvZWZzLWJheWVzLXpvaWIubWQiKSkKYGBgCgoKIyMgSDM6IFplcm8tb25lLWluZmxhdGVkIGJldGEKCmBgYHtyIGgzLW1vZGVscy1iYXllcy1kb21lc3RpYy16b2liLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQojIEdldCBzY2FsaW5nIGZhY3RvcnMKc2NhbGVzLmgzLmRvbS5uZXh0X3llYXIuem9pYiA8LSBtb2RzLmgzLmRvbS5uZXh0X3llYXIucmF3LnpvaWIgJT4lIAogIGZpbHRlcihtICE9ICJvcmlnaW5hbCIpICU+JSAKICBzZWxlY3QobSwgc3RhcnRzX3dpdGgoInNjYWxlcyIpKSAlPiUgCiAgZ2F0aGVyKHNjYWxlcy5uYW1lLCBzY2FsZXMsIC1tKQoKIyBHZXQgbW9kZWwgZGV0YWlscyBhbmQgcGFyYW1ldGVycwptb2RzLmgzLmRvbS5uZXh0X3llYXIuYmF5ZXMuem9pYiA8LSBtb2RzLmgzLmRvbS5uZXh0X3llYXIucmF3LnpvaWIgJT4lCiAgZmlsdGVyKG0gIT0gIm9yaWdpbmFsIikgJT4lIAogIHNlbGVjdChtLCBzdGFydHNfd2l0aCgibW9kIikpICU+JSAKICBnYXRoZXIobW9kZWwubmFtZSwgbW9kZWwsIC1tKSAlPiUKICBtdXRhdGUoZ2xhbmNlID0gbW9kZWwgJT4lIG1hcChnbGFuY2UpLAogICAgICAgICB0aWR5ID0gbW9kZWwgJT4lIG1hcCh0aWR5KSkgJT4lIAogIGJpbmRfY29scyhzZWxlY3Qoc2NhbGVzLmgzLmRvbS5uZXh0X3llYXIuem9pYiwgLW0pKQpgYGAKCmBgYHtyIGgzLW1vZGVscy1iYXllcy1mb3JlaWduLXpvaWIsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUV9CiMgR2V0IHNjYWxpbmcgZmFjdG9ycwpzY2FsZXMuaDMuZm9yZWlnbi5uZXh0X3llYXIuem9pYiA8LSBtb2RzLmgzLmZvcmVpZ24ubmV4dF95ZWFyLnJhdy56b2liICU+JSAKICBmaWx0ZXIobSAhPSAib3JpZ2luYWwiKSAlPiUgCiAgc2VsZWN0KG0sIHN0YXJ0c193aXRoKCJzY2FsZXMiKSkgJT4lIAogIGdhdGhlcihzY2FsZXMubmFtZSwgc2NhbGVzLCAtbSkKCiMgR2V0IG1vZGVsIGRldGFpbHMgYW5kIHBhcmFtZXRlcnMKbW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5iYXllcy56b2liIDwtIG1vZHMuaDMuZm9yZWlnbi5uZXh0X3llYXIucmF3LnpvaWIgJT4lCiAgZmlsdGVyKG0gIT0gIm9yaWdpbmFsIikgJT4lIAogIHNlbGVjdChtLCBzdGFydHNfd2l0aCgibW9kIikpICU+JSAKICBnYXRoZXIobW9kZWwubmFtZSwgbW9kZWwsIC1tKSAlPiUKICBtdXRhdGUoZ2xhbmNlID0gbW9kZWwgJT4lIG1hcChnbGFuY2UpLAogICAgICAgICB0aWR5ID0gbW9kZWwgJT4lIG1hcCh0aWR5KSkgJT4lIAogIGJpbmRfY29scyhzZWxlY3Qoc2NhbGVzLmgzLmZvcmVpZ24ubmV4dF95ZWFyLnpvaWIsIC1tKSkKYGBgCgojIyMgTUNNQyBkaWFnbm9zdGljcyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCiMjIyMgQ2hlY2sgZml0CgpBZ2FpbiwgdXNlIG9uZSBvZiB0aGUgaW1wdXRlZCBtb2RlbHMgKGBtb2QuaDMuYmFycmllcnMudG90YWwuem9pYmApIHRvIGNoZWNrIGZvciBmaXQgYW5kIGNvbnZlcmdlbmNlLgoKYGBge3IgaDMtZGlhZ25vc3RpY3MtYmF5ZXMtem9pYn0KbW9kZWwudG8uY2hlY2sgPC0gbW9kcy5oMy5kb20ubmV4dF95ZWFyLmJheWVzLnpvaWIgJT4lCiAgZmlsdGVyKG0gPT0gImltcDEiLCBtb2RlbC5uYW1lID09ICJtb2QuaDMuYmFycmllcnMudG90YWwiKSAlPiUKICBzZWxlY3QobW9kZWwpICU+JSAuW1sxXV0gJT4lIC5bWzFdXQpgYGAKClBvc3RlcmlvciBwcmVkaWN0aXZlIGRpc3RyaWJ1dGlvbiB2cy4gb2JzZXJ2ZWQgb3V0Y29tZT8KCmBgYHtyIGgzLWRpYWctZGVuc2l0eS16b2lifQpwcF9jaGVjayhtb2RlbC50by5jaGVjaywgdHlwZSA9ICJkZW5zX292ZXJsYXkiLCBuc2FtcGxlcyA9IDEwKSArIAogIHRoZW1lX2Rvbm9ycygpCmBgYAoKIyMjIyBDaGVjayBjb252ZXJnZW5jZQoKQ2hhaW4gY29udmVyZ2VuY2U6CgpgYGB7ciBoMy1kaWFnLWRpdmVyZ2VuY2Utem9pYn0KcnN0YW46OnN0YW5fZGlhZyhtb2RlbC50by5jaGVjayRmaXQsIGluZm9ybWF0aW9uID0gImRpdmVyZ2VuY2UiKQpgYGAKCgojIyMgUmVzdWx0cyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCiMjIyMgUHJvcG9ydGlvbiB0byBkb21lc3RpYyBOR09zCgpgYGB7ciBoMy10YWJsZS1kb21lc3RpYy16b2liLCByZXN1bHRzPSJhc2lzIiwgd2FybmluZz1GQUxTRX0KY2FwdGlvbiA8LSAiVGhlIGVmZmVjdCBvZiBhbnRpLU5HTyBsZWdpc2xhdGlvbiBvbiB0aGUgcHJvcG9ydGlvbiBvZiBVUyBhaWQgY2hhbm5lbGVkIHRocm91Z2ggKmRvbWVzdGljKiBOR09zIGluIHRoZSBmb2xsb3dpbmcgeWVhciAoSH4zfiksIGZ1bGwgbW9kZWxzLiBFYWNoIGNlbGwgY29udGFpbnMgdGhlIHBhcmFtZXRlcidzIHBvc3RlcmlvciBtZWRpYW4sIHRoZSA5NSUgY3JlZGlibGUgaW50ZXJ2YWwsIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgcGFyYW1ldGVyIGlzIGdyZWF0ZXIgdGhhbiBvbmUgKGluIGl0YWxpY3MpIHsjdGJsOmgzLWRvbWVzdGljLWNvZWZzLXpvaWJ9Igpub3RlIDwtIGMoIlplcm8tb25lLWluZmxhdGVkIGJldGEgbW9kZWxzLiBPZGRzIHJhdGlvcyByZXBvcnRlZC4iKQoKdGFibGUuaDMuZG9tZXN0aWMuem9pYiA8LSBiYXllc2dhemVyKG1vZHMuaDMuZG9tLm5leHRfeWVhci5iYXllcy56b2liLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IGNhcHRpb24sIG5vdGUgPSBub3RlLCBleHBvbmVudGlhdGUgPSBUUlVFKQoKY2F0KHRhYmxlLmgzLmRvbWVzdGljLnpvaWIpCmNhdCh0YWJsZS5oMy5kb21lc3RpYy56b2liLCBmaWxlID0gaGVyZSgiT3V0cHV0IiwgInRibC1oMy1kb21lc3RpYy1jb2Vmcy1iYXllcy16b2liLm1kIikpCmBgYAoKIyMjIyBQcm9wb3J0aW9uIHRvIGZvcmVpZ24gTkdPcwoKYGBge3IgaDMtdGFibGUtZm9yZWlnbi16b2liLCByZXN1bHRzPSJhc2lzIiwgd2FybmluZz1GQUxTRX0KY2FwdGlvbiA8LSAiVGhlIGVmZmVjdCBvZiBhbnRpLU5HTyBsZWdpc2xhdGlvbiBvbiB0aGUgcHJvcG9ydGlvbiBvZiBVUyBhaWQgY2hhbm5lbGVkIHRocm91Z2ggKlVTLWJhc2VkIGFuZCBpbnRlcm5hdGlvbmFsKiBOR09zIGluIHRoZSBmb2xsb3dpbmcgeWVhciAoSH4zfiksIGZ1bGwgbW9kZWxzLiBFYWNoIGNlbGwgY29udGFpbnMgdGhlIHBhcmFtZXRlcidzIHBvc3RlcmlvciBtZWRpYW4sIHRoZSA5NSUgY3JlZGlibGUgaW50ZXJ2YWwsIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgcGFyYW1ldGVyIGlzIGdyZWF0ZXIgdGhhbiBvbmUgKGluIGl0YWxpY3MpIHsjdGJsOmgzLWZvcmVpZ24tY29lZnMtem9pYn0iCm5vdGUgPC0gYygiWmVyby1vbmUtaW5mbGF0ZWQgYmV0YSBtb2RlbHMuIE9kZHMgcmF0aW9zIHJlcG9ydGVkLiIpCgp0YWJsZS5oMy5kb21lc3RpYy56b2liIDwtIGJheWVzZ2F6ZXIobW9kcy5oMy5mb3JlaWduLm5leHRfeWVhci5iYXllcy56b2liLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IGNhcHRpb24sIG5vdGUgPSBub3RlLCBleHBvbmVudGlhdGUgPSBUUlVFKQoKY2F0KHRhYmxlLmgzLmRvbWVzdGljLnpvaWIpCmNhdCh0YWJsZS5oMy5kb21lc3RpYy56b2liLCBmaWxlID0gaGVyZSgiT3V0cHV0IiwgInRibC1oMy1mb3JlaWduLWNvZWZzLWJheWVzLXpvaWIubWQiKSkKYGBgCgojIyMjIFBsb3Qgb2YgcHJvcG9ydGlvbiB0byBkb21lc3RpYyBhbmQgZm9yZWlnbiBOR09zIHsuYWN0aXZlfQoKYGBge3IgcGxvdC1oMy1jb2Vmcy1ib3RoLXpvaWIsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy53aWR0aD01LjUsIGZpZy5oZWlnaHQ9M30KdmFycy50by5wbG90IDwtIGMoImJhcnJpZXJzLnRvdGFsX3dpdGhpbiIsICJiYXJyaWVycy50b3RhbF9iZXR3ZWVuIiwKICAgICAgICAgICAgICAgICAgImFkdm9jYWN5X3dpdGhpbiIsICJhZHZvY2FjeV9iZXR3ZWVuIiwgCiAgICAgICAgICAgICAgICAgICJlbnRyeV93aXRoaW4iLCAiZW50cnlfYmV0d2VlbiIsIAogICAgICAgICAgICAgICAgICAiZnVuZGluZ193aXRoaW4iLCAiZnVuZGluZ19iZXR3ZWVuIiwKICAgICAgICAgICAgICAgICAgImNzcmVfd2l0aGluIiwgImNzcmVfYmV0d2VlbiIpCgptb2RzLmgzLmRvbS5tZWxkZWQuem9pYiA8LSBiYXllcy5tZWxkKG1vZHMuaDMuZG9tLm5leHRfeWVhci5iYXllcy56b2liLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcnMudG8ucGxvdCwgZXhwb25lbnRpYXRlID0gVFJVRSkkbWVsZGVkLnN1bW1hcnkKCmNvZWZzLnJhdy5oMy5kb20uem9pYiA8LSBtb2RzLmgzLmRvbS5tZWxkZWQuem9pYiAlPiUKICBsZWZ0X2pvaW4oY29lZi5uYW1lcy5hbGwsIGJ5ID0gInRlcm0iKSAlPiUKICBsZWZ0X2pvaW4obW9kZWwubmFtZXMsIGJ5ID0gYygibW9kZWwubmFtZSIgPSAibW9kZWwiKSkgJT4lIAogIG11dGF0ZSh0ZXJtID0gZmFjdG9yKHRlcm0sIGxldmVscyA9IHZhcnMudG8ucGxvdCwgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKGRlc2ModGVybSkpICU+JQogIG11dGF0ZSh0ZXJtX3Bsb3QgPSBvcmRlcmVkKGZjdF9pbm9yZGVyKHRlcm1fcGxvdF9zaG9ydCkpKSAlPiUKICBtdXRhdGUoY29lZi50eXBlID0gY2FzZV93aGVuKAogICAgc3RyX2RldGVjdCguJHRlcm0sICJfd2l0aGluIikgfiAiV2l0aGluIiwKICAgIHN0cl9kZXRlY3QoLiR0ZXJtLCAiX2JldHdlZW4iKSB+ICJCZXR3ZWVuIiwKICApKSAlPiUgCiAgbXV0YXRlKGNvZWYudHlwZSA9IGZhY3Rvcihjb2VmLnR5cGUsIGxldmVscyA9IGMoIldpdGhpbiIsICJCZXR3ZWVuIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpICU+JQogIG11dGF0ZShtb2RlbF9jbGVhbiA9IGZhY3Rvcihtb2RlbF9jbGVhbiwgbGV2ZWxzID0gcmV2KHVuaXF1ZShtb2RlbF9jbGVhbikpLCBvcmRlcmVkID0gVFJVRSkpCgptb2RzLmgzLmZvcmVpZ24ubWVsZGVkLnpvaWIgPC0gYmF5ZXMubWVsZChtb2RzLmgzLmZvcmVpZ24ubmV4dF95ZWFyLmJheWVzLnpvaWIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcnMudG8ucGxvdCwgZXhwb25lbnRpYXRlID0gVFJVRSkkbWVsZGVkLnN1bW1hcnkKCmNvZWZzLnJhdy5oMy5mb3JlaWduLnpvaWIgPC0gbW9kcy5oMy5mb3JlaWduLm1lbGRlZC56b2liICU+JQogIGxlZnRfam9pbihjb2VmLm5hbWVzLmFsbCwgYnkgPSAidGVybSIpICU+JQogIGxlZnRfam9pbihtb2RlbC5uYW1lcywgYnkgPSBjKCJtb2RlbC5uYW1lIiA9ICJtb2RlbCIpKSAlPiUgCiAgbXV0YXRlKHRlcm0gPSBmYWN0b3IodGVybSwgbGV2ZWxzID0gdmFycy50by5wbG90LCBvcmRlcmVkID0gVFJVRSkpICU+JQogIGFycmFuZ2UoZGVzYyh0ZXJtKSkgJT4lCiAgbXV0YXRlKHRlcm1fcGxvdCA9IG9yZGVyZWQoZmN0X2lub3JkZXIodGVybV9wbG90X3Nob3J0KSkpICU+JQogIG11dGF0ZShjb2VmLnR5cGUgPSBjYXNlX3doZW4oCiAgICBzdHJfZGV0ZWN0KC4kdGVybSwgIl93aXRoaW4iKSB+ICJXaXRoaW4iLAogICAgc3RyX2RldGVjdCguJHRlcm0sICJfYmV0d2VlbiIpIH4gIkJldHdlZW4iLAogICkpICU+JSAKICBtdXRhdGUoY29lZi50eXBlID0gZmFjdG9yKGNvZWYudHlwZSwgbGV2ZWxzID0gYygiV2l0aGluIiwgIkJldHdlZW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgbXV0YXRlKG1vZGVsX2NsZWFuID0gZmFjdG9yKG1vZGVsX2NsZWFuLCBsZXZlbHMgPSByZXYodW5pcXVlKG1vZGVsX2NsZWFuKSksIG9yZGVyZWQgPSBUUlVFKSkKCmNvZWZzLmgzLmJvdGguem9pYiA8LSBiaW5kX3Jvd3MoYERvbWVzdGljIE5HT3NgID0gY29lZnMucmF3LmgzLmRvbS56b2liLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBGb3JlaWduIE5HT3NgID0gY29lZnMucmF3LmgzLmZvcmVpZ24uem9pYiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuaWQgPSAiY2hhbm5lbCIpCgpmaWcuY29lZnMuaDMuem9pYiA8LSBnZ3Bsb3QoY29lZnMuaDMuYm90aC56b2liLCBhZXMoeSA9IHRlcm1fcGxvdCwgeCA9IG1lZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBtb2RlbF9jbGVhbikpICsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKyAKICBnZW9tX3BvaW50cmFuZ2VoKGFlcyh4bWluID0gYDIuNSVgLCB4bWF4ID0gYDk3LjUlYCwgc2hhcGUgPSBjaGFubmVsKSwgCiAgICAgICAgICAgICAgICAgICBzaXplID0gMC41LCBmYXR0ZW4gPSAzLAogICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZXYoaGVpZ2h0ID0gMC41KSkgKyAKICBsYWJzKHggPSAiT2RkIHJhdGlvIiwgeSA9IE5VTEwpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IG1vZGVsLmNvbG9ycykgKwogIGV4cGFuZF9saW1pdHMoeCA9IGMoMC41LCAyKSkgKwogIGd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAwLjI1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSBOVUxMLCBucm93ID0gMiwgb3JkZXIgPSAyKSwKICAgICAgICAgc2hhcGUgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gMC41LCBsaW5ldHlwZSA9IDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9IE5VTEwsIG5yb3cgPSAyLCByZXZlcnNlID0gVFJVRSwgb3JkZXIgPSAxKSkgKwogIHRoZW1lX2Rvbm9ycygpICsgCiAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSAibGVmdCIsCiAgICAgICAgbGVnZW5kLmJveC5tYXJnaW4gPSBtYXJnaW4obCA9IC0wLjc1LCB0ID0gLTAuNSwgdW5pdCA9ICJsaW5lcyIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApKSArCiAgZmFjZXRfd3JhcCh+IGNvZWYudHlwZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMikKZmlnLmNvZWZzLmgzLnpvaWIKCmZpZy5zYXZlLmNhaXJvKGZpZy5jb2Vmcy5oMy56b2liLCBmaWxlbmFtZSA9ICJmaWctY29lZnMtaDMtYmF5ZXMtem9pYiIsCiAgICAgICAgICAgICAgIHdpZHRoID0gNS41LCBoZWlnaHQgPSAzKQpgYGAK