library(tidyverse)
library(brms)
library(tidybayes)
library(bayesplot)
library(fixest)
library(broom)
library(broom.mixed)
library(modelsummary)
library(patchwork)
library(tictoc)
library(latex2exp)
library(scales)
library(extraDistr)
library(glue)
library(here)

source(here("lib", "graphics.R"))
source(here("lib", "misc_funs.R"))
color_scheme_set("viridisC")

labs_exp_logged <- function(brks) {TeX(paste0("e^{", as.character(log(brks))), "}")}
labs_exp <- function(brks) {TeX(paste0("e^{", as.character(brks)), "}")}

my_seed <- 1234
set.seed(my_seed)

options(mc.cores = parallel::detectCores(),  # Use all possible cores
        brms.backend = "rstan")

CHAINS <- 4
ITER <- 2000
WARMUP <- 1000
BAYES_SEED <- 1234
df_country_aid <- readRDS(here("data", "derived_data", "df_country_aid.rds"))

df_country_aid <- df_country_aid %>% 
  # Winsorize prop_contentious for the two cases that are exactly 1
  mutate(prop_contentious_orig = prop_contentious,
         prop_contentious = ifelse(prop_contentious == 1, 0.999, prop_contentious),
         prop_contentious_lead1_orig = prop_contentious_lead1,
         prop_contentious_lead1 = 
           ifelse(prop_contentious_lead1 == 1, 0.999, prop_contentious_lead1),
         prop_contentious_lead1 = 
           ifelse(prop_contentious_lead1 < 0, 0, prop_contentious_lead1))

df_country_aid_laws <- filter(df_country_aid, laws)

Weight models

  • Numerator is lagged treatment + non-varying confounders
  • Denominator is lagged treatment + lagged outcome + time-varying confounders + non-varying confounders

\[ sw = \prod^t_{t = 1} \frac{\phi(T_{it} | T_{i, t-1}, C_i)}{\phi(T_{it} | T_{i, t-1}, D_{i, t-1}, C_i)} \]

Priors for weight models

We use generic weakly informative priors for our model parameters:

  • Intercept: \(\mathcal{N} (0, 10)\)
  • Coefficients: \(\mathcal{N} (0, 2.5)\)
  • Sigma: \(\operatorname{Cauchy} (0, 1)\)
pri_int <- ggplot() +
  stat_function(fun = dnorm, args = list(mean = 0, sd = 10),
                geom = "area", fill = "grey80", color = "black") +
  labs(x = TeX("\\textbf{Intercept (β_0)}")) +
  annotate(geom = "label", x = 0, y = 0.01, label = "N(0, 10)", size = pts(9)) +
  xlim(-40, 40) +
  theme_donors(prior = TRUE)

pri_coef <- ggplot() +
  stat_function(fun = dnorm, args = list(mean = 0, sd = 2.5),
                geom = "area", fill = "grey80", color = "black") +
  labs(x = TeX("\\textbf{Coefficients (β_x)}")) +
  annotate(geom = "label", x = 0, y = 0.04, label = "N(0, 3)", size = pts(9)) +
  xlim(-10, 10) +
  theme_donors(prior = TRUE)

pri_sigma <- ggplot() +
  stat_function(fun = dcauchy, args = list(location = 0, scale = 1),
                geom = "area", fill = "grey80", color = "black") +
  labs(x = "σ") +
  annotate(geom = "label", x = 5, y = 0.08, label = "Cauchy(0, 1)", size = pts(9)) +
  xlim(0, 10) +
  theme_donors(prior = TRUE)

(pri_int + pri_coef + pri_sigma)

Run weight models

# Numerator ---------------------------------------------------------------
# Formulas
# Treatment ~ lag treatment + non-varying confounders
formula_h2_num_total <- bf(barriers_total ~ barriers_total_lag1 + (1 | gwcode))
formula_h2_num_advocacy <- bf(advocacy ~ advocacy_lag1 + (1 | gwcode))
formula_h2_num_entry <- bf(entry ~ entry_lag1 + (1 | gwcode))
formula_h2_num_funding <- bf(funding ~ funding_lag1 + (1 | gwcode))

# Priors
prior_num <- c(set_prior("normal(0, 10)", class = "Intercept"),
               set_prior("normal(0, 2.5)", class = "b"),
               set_prior("cauchy(0, 1)", class = "sd"))


# Denominator -------------------------------------------------------------
# Formulas
# Treatment ~ lag treatment + lag outcome + varying confounders + non-varying confounders
formula_h2_denom_total <- 
  bf(barriers_total ~ barriers_total_lag1 + prop_contentious_lag1 +
       # Human rights and politics
       v2x_polyarchy + v2x_corr + v2x_rule + v2x_civlib + v2x_clphy + v2x_clpriv +
       # Economics and development
       gdpcap_log + un_trade_pct_gdp + v2peedueq + v2pehealth + e_peinfmor +
       # Conflict and disasters
       internal_conflict_past_5 + natural_dis_count +
       (1 | gwcode))

formula_h2_denom_advocacy <- 
  bf(advocacy ~ advocacy_lag1 + prop_contentious_lag1 +
       v2x_polyarchy + v2x_corr + v2x_rule + v2x_civlib + v2x_clphy + v2x_clpriv +
       gdpcap_log + un_trade_pct_gdp + v2peedueq + v2pehealth + e_peinfmor +
       internal_conflict_past_5 + natural_dis_count +
       (1 | gwcode))

formula_h2_denom_entry <- 
  bf(entry ~ entry_lag1 + prop_contentious_lag1 +
       v2x_polyarchy + v2x_corr + v2x_rule + v2x_civlib + v2x_clphy + v2x_clpriv +
       gdpcap_log + un_trade_pct_gdp + v2peedueq + v2pehealth + e_peinfmor +
       internal_conflict_past_5 + natural_dis_count +
       (1 | gwcode))

formula_h2_denom_funding <- 
  bf(funding ~ funding_lag1 + prop_contentious_lag1 +
       v2x_polyarchy + v2x_corr + v2x_rule + v2x_civlib + v2x_clphy + v2x_clpriv +
       gdpcap_log + un_trade_pct_gdp + v2peedueq + v2pehealth + e_peinfmor +
       internal_conflict_past_5 + natural_dis_count +
       (1 | gwcode))

# Priors
prior_denom <- c(set_prior("normal(0, 10)", class = "Intercept"),
                 set_prior("normal(0, 2.5)", class = "b"),
                 set_prior("normal(0, 2.5)", class = "sd"))


# Run weighting models ----------------------------------------------------
# All models get run inside a tibble using map() magic
all_models_h2 <- tribble(
  ~model_name, ~formula_num, ~formula_denom,
  "h2_total", formula_h2_num_total, formula_h2_denom_total,
  "h2_advocacy", formula_h2_num_advocacy, formula_h2_denom_advocacy,
  "h2_entry", formula_h2_num_entry, formula_h2_denom_entry,
  "h2_funding", formula_h2_num_funding, formula_h2_denom_funding
)

# Fit models
tic()
fit_h2_all_models <- all_models_h2 %>%
  mutate(fit_num = map2(formula_num, model_name, ~brm(
    .x,
    data = df_country_aid_laws,
    prior = prior_num,
    iter = ITER, chains = CHAINS, warmup = WARMUP, seed = BAYES_SEED,
    control = list(adapt_delta = 0.99),
    file = here("analysis", "model_cache", paste0(.y, "_num.rds"))
  ))) %>%
  mutate(fit_denom = map2(formula_denom, model_name, ~brm(
    .x,
    data = df_country_aid_laws,
    prior = prior_denom,
    iter = ITER, chains = CHAINS, warmup = WARMUP, seed = BAYES_SEED,
    control = list(adapt_delta = 0.9),
    file = here("analysis", "model_cache", paste0(.y, "_denom.rds"))
  ))) 
fit_h2_all_models
toc()

Check weight models

We check one of the denominator models for convergence and mixing and fit (not the numerator, since those models are the same as the ones in H1).

check_total_denom <- fit_h2_all_models %>% 
  filter(model_name == "h2_total") %>% pull(fit_denom) %>% first()

pp_check(check_total_denom, type = "dens_overlay", nsamples = 10) +
  theme_donors()

check_total_denom %>% 
  posterior_samples(add_chain = TRUE) %>% 
  select(-starts_with("r_gwcode"), -starts_with("z_"), -lp__, -iter) %>% 
  mcmc_trace() +
  theme_donors() +
  theme(legend.position = "right")

Build weights

tic()
fit_h2_preds <- fit_h2_all_models %>%
  mutate(pred_num = map(fit_num, ~predict(.x, newdata = df_country_aid_laws, allow_new_levels = TRUE)),
         resid_num = map(fit_num, ~residuals(.x, newdata = df_country_aid_laws, allow_new_levels = TRUE)),
         pred_denom = map(fit_denom, ~predict(.x, newdata = df_country_aid_laws, allow_new_levels = TRUE)),
         resid_denom = map(fit_denom, ~residuals(.x, newdata = df_country_aid_laws, allow_new_levels = TRUE)))
toc()
## 108.993 sec elapsed
fit_h2_ipw <- fit_h2_preds %>%
  mutate(num_actual = pmap(list(form = formula_num, pred = pred_num, resid = resid_num), 
                           calc_prob_dist),
         denom_actual = pmap(list(form = formula_denom, pred = pred_denom, resid = resid_denom), 
                          calc_prob_dist)) %>% 
  mutate(df_with_weights = map2(num_actual, denom_actual, ~{
    df_country_aid_laws %>% 
      mutate(weights_sans_time = .x / .y) %>% 
      group_by(gwcode) %>% 
      mutate(ipw = cumprod_na(weights_sans_time)) %>% 
      ungroup()
  }))
fit_h2_ipw
## # A tibble: 4 x 12
##   model_name formula_num formula_denom fit_num fit_denom pred_num resid_num pred_denom
##   <chr>      <list>      <list>        <list>  <list>    <list>   <list>    <list>    
## 1 h2_total   <brmsfrml>  <brmsfrml>    <brmsf… <brmsfit> <dbl[,4… <dbl[,4]… <dbl[,4] …
## 2 h2_advoca… <brmsfrml>  <brmsfrml>    <brmsf… <brmsfit> <dbl[,4… <dbl[,4]… <dbl[,4] …
## 3 h2_entry   <brmsfrml>  <brmsfrml>    <brmsf… <brmsfit> <dbl[,4… <dbl[,4]… <dbl[,4] …
## 4 h2_funding <brmsfrml>  <brmsfrml>    <brmsf… <brmsfit> <dbl[,4… <dbl[,4]… <dbl[,4] …
## # … with 4 more variables: resid_denom <list>, num_actual <list>, denom_actual <list>,
## #   df_with_weights <list>

Outcome models

Modeling choice

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, but it’s possible to 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 model the probability of being 0, being 1, and being somewhere in the middle using different processes. Matti Vuorre has an excellent overview of ZOIB models here.

In the original versions of this project, we used logit-linear models of the ratio of contentious aid to non-contentious aid, like this:

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

That meant we had to compare the ratio of contentious aid to non-contentious aid rather than the direct percent of contentious aid, and it made for some acrobatic interpretations.

Here, we use zero-inflated beta regression instead, since brms and Stan have improved and sped up a ton over the past few years.

The proportion of contentious aid has a bunch of zeroes, and those zeros are close to the distribution of the regular data, so we use zero-inflated models rather than a hurdle process like with did with H1 and total ODA. Something determines whether a country/year receives any contentious aid, and then something else determines what proportion is contentious.

If we don’t take this zero-inflation process into account in the model, our ATE will be wrong. We don’t really care about the exact zero-inflation process—we care most about the ATE of laws/restrictions on contentiousness—but we still need to deal with the multiple processes.

ggplot(df_country_aid_laws, 
       aes(x = prop_contentious, fill = prop_contentious == 0)) +
  geom_histogram(binwidth = 0.05, color = "white", boundary = 0) +
  labs(x = "Proportion of contentious aid", y = "Count") +
  scale_fill_manual(values = c("grey80", "#FF851B"), 
                    labels = c("% > 0", "% = 0"),
                    name = NULL) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  theme_donors()

# Percent where prop_contentious is 0:
df_country_aid_laws %>% 
  count(prop_contentious == 0) %>% 
  mutate(prop = n / sum(n))
## # A tibble: 2 x 3
##   `prop_contentious == 0`     n  prop
## * <lgl>                   <int> <dbl>
## 1 FALSE                    2814 0.819
## 2 TRUE                      621 0.181

We thus fit a zero-inflated beta model, which uses a logit model to predict 0/not 0, then uses a beta family to model the rest of the data.

Beta regression is based on the beta distribution and its two shape parameters, but the parameterization of the distribution in brms/stan uses \(\mu\) and \(\phi\), which are transformed versions of shape 1 and shape 2:

  • \(\text{shape1} = \mu \phi\)
  • \(\text{shape2} = (1 - \mu)\phi\)

This is actually kind of neat, because instead of trying to finagle a beta distribution based on \(\frac{\text{shape1}}{\text{shape1} + \text{shape2}}\), you can specify the average proportion and “spread” similar to a normal distribution.

For instance, if we wanted a beta distribution around 0.3, with some moderate spread, we could play around with shape1 and shape2 and figure that they’re probably something like 3 and 7, based on \(\frac{3}{3 + 7}\). We can get these same numbers with the reparameterized version, using 0.3 as \(\mu\) (i.e. clustered around 0.3) and 10 as \(\phi\). We get the same 3 and 7 values for the two shapes and the distribution looks great! The dprop() function in extraDistr takes these reparameterized arguments directly, too (it calls \(phi\) size).

mu <- 0.3
phi <- 10

shape1 <- mu * phi
shape1
## [1] 3
shape2 <- (1 - mu) * phi
shape2
## [1] 7
# With dbeta
plot_beta <- ggplot() +
  stat_function(fun = dbeta, args = list(shape1 = shape1, shape2 = shape2),
                geom = "area", fill = "grey80", color = "black") +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  labs(x = "Proportion", y = NULL, 
       title = "Beta distribution",
       subtitle = glue("shape1 = {shape1}; shape2 = {shape2}")) +
  theme_donors(9) +
  theme(axis.text.y = element_blank())

# With dprop
plot_prop <- ggplot() +
  stat_function(fun = dprop, args = list(size = phi, mean = mu),
                geom = "area", fill = "grey80", color = "black") +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  labs(x = "Proportion", y = NULL, 
       title = "Reparameterized beta distribution",
       subtitle = glue("µ = {mu}; φ = {phi}")) +
  theme_donors(9) +
  theme(axis.text.y = element_blank())

plot_beta + plot_prop

The median proportion of contentious aid for non-zero cases is around 5%, and based on the histogram earlier, it’s not unheard of to go up to 25% or even as high as 50%:

df_country_aid_laws %>% 
  filter(prop_contentious > 0) %>% 
  summarize(median_prop = median(prop_contentious))
## # A tibble: 1 x 1
##   median_prop
##         <dbl>
## 1      0.0466

In the absence of any covariates, we could use a \(mu\) of 0.05 and a \(phi\) of 3:

beta_mu <- 0.05
beta_phi <- 3

# beta_shape1 <- beta_mu * beta_phi
# beta_shape2 <- (1 - beta_mu) * beta_phi

ggplot() +
  stat_function(fun = dprop, args = list(size = beta_phi, mean = beta_mu),
                geom = "area", fill = "grey80", color = "black") +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  labs(x = "Proportion", y = NULL, 
       title = "Reparameterized beta distribution",
       subtitle = glue("µ = {beta_mu}; φ = {beta_phi}")) +
  theme_donors(9) +
  theme(axis.text.y = element_blank())

This gets more complex, though, once we start adding covariates. \(\mu\) is modeled with logistic regression while \(\phi\) is modeled with a log link, and each of these models can get their own covariates.

Priors for outcome models

There are a ton of moving parts in these outcome models. Here’s the full specification for the models and all priors:

\[ \begin{aligned} \text{y}_{i,t} | u_i, \text{Law}_{i, t} &\sim \operatorname{ZIBeta} (Z_i, \text{y}^\star_i, \phi_i) & \text{[likelihood]} \\ \operatorname{logit} (Z_i) &\sim \alpha_Z & \text{[intercept-only logit if } \text{y}_{i, t} = 0 \text{]} \\ \operatorname{logit} (\text{y}^\star_i) &\sim (\beta_0 + \beta_1 \text{Law}_{i, t} + \beta_2 \text{Law}_{i, t-1}, \sigma^2_\epsilon, u_i) \times \text{IPW}_{i, t} & \text{[if } \text{y}_{i, t} > 0 \text{]}\\ \log (\phi_i) &\sim \alpha_\phi & \text{[intercept-only model for precision]} \\ u_i &\sim \mathcal{N} (0, \sigma^2_u) & \text{[country-specific intercepts]} \\ \ \\ \alpha_Z &\sim \operatorname{Logistic}(-1.5, 0.5) & \text{[prior proportion of rows where y = 0]} \\ \alpha_\phi &\sim \operatorname{Gamma} (0.01, 0.01) & \text{[prior Beta precision]} \\ \beta_0 &\sim \mathcal{N} (0, 10) & \text{[prior population intercept]} \\ \beta_1, \beta_2 &\sim \mathcal{N} (0, 3) & \text{[prior population effects]} \\ \sigma^2_e, \sigma^2_u &\sim \operatorname{Cauchy}(0, 1) & \text{[prior sd for population and country]} \\ \ \\ \text{IPW}_{i, t} &= \prod^t_{t = 1} \frac{\phi(T_{it} | T_{i, t-1}, C_i)}{\phi(T_{it} | T_{i, t-1}, D_{i, t-1}, C_i)} & \text{[stabilized weights]} \end{aligned} \] For \(\phi\), we just use Stan’s default Gamma(0.01, 0.01). Here’s what all these prior distributions look like:

z_p <- ggplot() +
  stat_function(fun = dlogis, args = list(location = -1.5, scale = 0.5),
                geom = "area", fill = "grey80", color = "black") +
  labs(x = TeX("\\textbf{Prop. contentious = 0 (α_Z)}")) +
  annotate(geom = "label", x = -2, y = 0.07, label = "Logistic(-1.5, 0.5)", size = pts(9)) +
  xlim(-8, 3) +
  theme_donors(prior = TRUE)

b0_p <- ggplot() +
  stat_function(fun = dnorm, args = list(mean = 0, sd = 10),
                geom = "area", fill = "grey80", color = "black") +
  labs(x = TeX("\\textbf{Population intercept (β_0)}")) +
  annotate(geom = "label", x = 0, y = 0.0042, label = "N(0, 10)", size = pts(9)) +
  xlim(-40, 40) +
  theme_donors(prior = TRUE)

b12_p <- ggplot() +
  stat_function(fun = dnorm, args = list(mean = 0, sd = 3),
                geom = "area", fill = "grey80", color = "black") +
  labs(x = TeX("\\textbf{Population effects (β_1, β_2)}")) +
  annotate(geom = "label", x = 0, y = 0.02, label = "N(0, 3)", size = pts(9)) +
  xlim(-10, 10) +
  theme_donors(prior = TRUE)

sigma_p <- ggplot() +
  stat_function(fun = dcauchy, args = list(location = 0, scale = 1),
                geom = "area", fill = "grey80", color = "black") +
  labs(x = TeX("\\textbf{Population and country SD (σ_e, σ_u)}")) +
  annotate(geom = "label", x = 5, y = 0.04, label = "Cauchy(0, 1)", size = pts(9)) +
  xlim(0, 10) +
  theme_donors(prior = TRUE)

phi_p <- ggplot() +
  stat_function(fun = dgamma, args = list(shape = 0.1, scale = 0.1),
                geom = "area", fill = "grey80", color = "black") +
  labs(x = TeX("\\textbf{Beta precision (φ)}")) +
  annotate(geom = "label", x = 0.25, y = 2, label = "Gamma(0.01, 0.01)", size = pts(9)) +
  xlim(0, 0.5) +
  theme_donors(prior = TRUE)

layout <- "
AAAABBBBCCCC
AAAABBBBCCCC
##DDDDEEEE##
##DDDDEEEE##
"
z_p + sigma_p + phi_p + b0_p + b12_p +
  plot_layout(design = layout)

As with H1, the prior for the zero-inflated part of the model is a little weird. Internally, Stan uses a default of logistic(0, 1). We want to use an informative beta(1.8, 8,1) prior that approximates the proportion of zeroes in the data (but with fairly wide dispersion), but we once again need to translate it into the logistic distribution. Since there’s no easy way to do this, we used brms::logit_scaled to play around with distributional hyperparameters until it looked okay in the logistic distribution.

zi_prior_sim <- tibble(beta = rbeta(10000, 1.8, 8.1)) %>% 
  mutate(beta_logit_scale = brms::logit_scaled(beta)) %>% 
  mutate(logit_betaish_prior = rlogis(10000, -1.5, 0.5)) %>% 
  mutate(prior_probs = plogis(logit_betaish_prior))

zi_prior_plot1 <- ggplot(zi_prior_sim) +
  geom_density(aes(x = beta), fill = "grey80", color = "black") +
  labs(x = "Proportion where prop. contentious = 0",
       subtitle = "Original Beta(1.8, 8.1) distribution") +
  coord_cartesian(xlim = c(0, 1)) +
  theme_donors(prior = TRUE)

zi_prior_plot2 <- ggplot(zi_prior_sim) +
  geom_density(aes(x = beta_logit_scale), fill = "grey80", color = "black") +
  labs(x = "Logistic value where prop. contentious = 0",
       subtitle = "Beta(1.8, 8.1) scaled with brms::logit_scaled") +
  coord_cartesian(xlim = c(-8, 1)) +
  theme_donors(prior = TRUE)

zi_prior_plot3 <- ggplot(zi_prior_sim) +
  geom_density(aes(x = logit_betaish_prior), fill = "grey80", color = "black") +
  labs(x = "Logistic value where prop. contentious = 0",
       subtitle = "Estimated Logistic(-1.5, 0.5)") +
  coord_cartesian(xlim = c(-8, 1)) +
  theme_donors(prior = TRUE)

zi_prior_plot4 <- ggplot(zi_prior_sim) +
  geom_density(aes(x = prior_probs), fill = "grey80", color = "black") +
  labs(x = "Proportion where prop. contentious = 0",
       subtitle = "Logistic(-1.5, 0.5) transformed to probabilities") +
  coord_cartesian(xlim = c(0, 1)) +
  theme_donors(prior = TRUE)

(zi_prior_plot1 + zi_prior_plot2) / (zi_prior_plot3 + zi_prior_plot4)

Run outcome models

Outcome model time!

# Outcome -----------------------------------------------------------------
# Formulas
# Treatment ~ lag treatment + non-varying confounders
formula_h2_out_total <- bf(prop_contentious_lead1 | weights(ipw) ~ 
                             barriers_total + (1 | gwcode),
                           zi ~ 1)
formula_h2_out_advocacy <- bf(prop_contentious_lead1 | weights(ipw) ~ 
                                advocacy + (1 | gwcode),
                              zi ~ 1)
formula_h2_out_entry <- bf(prop_contentious_lead1 | weights(ipw) ~ 
                             entry + (1 | gwcode),
                           zi ~ 1)
formula_h2_out_funding <- bf(prop_contentious_lead1 | weights(ipw) ~ 
                               funding + (1 | gwcode),
                             zi ~ 1)

# Priors
prior_out <- c(set_prior("normal(0, 10)", class = "Intercept"),
               set_prior("normal(0, 3)", class = "b"),
               set_prior("cauchy(0, 1)", class = "sd"),
               set_prior("logistic(-1.5, 0.5)", class = "Intercept", dpar = "zi"),
               set_prior("gamma(0.01, 0.01)", class = "phi"))

# Run outcome models ------------------------------------------------------
tic()
fit_h2_outcomes <- fit_h2_ipw %>%
  mutate(formula_outcome = 
           list(formula_h2_out_total, formula_h2_out_advocacy, 
                formula_h2_out_entry, formula_h2_out_funding)) %>% 
  mutate(fit_outcome = 
           pmap(list(formula_outcome, df_with_weights, model_name),
                ~brm(
                  ..1,
                  data = ..2,
                  prior = prior_out,
                  family = zero_inflated_beta(),
                  iter = ITER * 2, chains = CHAINS, warmup = WARMUP, seed = BAYES_SEED,
                  file = here("analysis", "model_cache", paste0(..3, "_outcome.rds"))
                )))
fit_h2_outcomes
toc()

Check outcome models

check_total_outcome <- fit_h2_outcomes %>% 
  filter(model_name == "h2_total") %>% pull(fit_outcome) %>% first()

pp_check(check_total_outcome, type = "dens_overlay", nsamples = 10) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  theme_donors()

check_total_outcome %>% 
  posterior_samples(add_chain = TRUE) %>% 
  select(-starts_with("r_gwcode"), -starts_with("z_"), -lp__, -iter) %>% 
  mcmc_trace() +
  theme_donors()

Results

# Plots!
plot_total <- fit_h2_outcomes %>% 
  filter(model_name == "h2_total") %>% 
  pull(fit_outcome) %>% nth(1) %>% 
  gather_draws(b_barriers_total) %>%
  mutate(.value = exp(.value) - 1) %>% 
  mutate(.variable = dplyr::recode(.variable, 
                                   b_barriers_total = "Additional law, t - 1")) %>% 
  ggplot(aes(y = fct_rev(.variable), x = .value, fill = fct_rev(.variable))) +
  geom_vline(xintercept = 0) +
  stat_halfeye(.width = c(0.8, 0.95), alpha = 0.8) +
  guides(fill = FALSE) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  scale_fill_manual(values = c("#FF851B", "#FFDC00")) +
  labs(y = NULL, x = NULL) +
  theme_donors()

plot_advocacy <- fit_h2_outcomes %>% 
  filter(model_name == "h2_advocacy") %>% 
  pull(fit_outcome) %>% nth(1) %>% 
  gather_draws(b_advocacy) %>% 
  mutate(.variable = dplyr::recode(.variable, 
                                   b_advocacy = "Additional advocacy law, t - 1")) %>% 
  mutate(.value = exp(.value) - 1) %>% 
  ggplot(aes(y = fct_rev(.variable), x = .value, fill = fct_rev(.variable))) +
  geom_vline(xintercept = 0) +
  stat_halfeye(.width = c(0.8, 0.95), alpha = 0.8) +
  guides(fill = FALSE) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  scale_fill_manual(values = c("#85144b", "#F012BE")) +
  labs(y = NULL, x = NULL) +
  theme_donors()

plot_entry <- fit_h2_outcomes %>% 
  filter(model_name == "h2_entry") %>% 
  pull(fit_outcome) %>% nth(1) %>% 
  gather_draws(b_entry) %>% 
  mutate(.variable = dplyr::recode(.variable, 
                                   b_entry = "Additional entry law, t - 1")) %>% 
  mutate(.value = exp(.value) - 1) %>% 
  ggplot(aes(y = fct_rev(.variable), x = .value, fill = fct_rev(.variable))) +
  geom_vline(xintercept = 0) +
  stat_halfeye(.width = c(0.8, 0.95), alpha = 0.8) +
  guides(fill = FALSE) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  scale_fill_manual(values = c("#3D9970", "#2ECC40")) +
  labs(y = NULL, x = "% change in proportion of contentious aid") +
  theme_donors()

plot_funding <- fit_h2_outcomes %>% 
  filter(model_name == "h2_funding") %>% 
  pull(fit_outcome) %>% nth(1) %>% 
  gather_draws(b_funding) %>% 
  mutate(.variable = dplyr::recode(.variable, 
                                   b_funding = "Additional funding law, t - 1")) %>% 
  mutate(.value = exp(.value) - 1) %>% 
  ggplot(aes(y = fct_rev(.variable), x = .value, fill = fct_rev(.variable))) +
  geom_vline(xintercept = 0) +
  stat_halfeye(.width = c(0.8, 0.95), alpha = 0.8) +
  guides(fill = FALSE) +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  scale_fill_manual(values = c("#001f3f", "#0074D9")) +
  labs(y = NULL, x = "% change in proportion of contentious aid") +
  theme_donors()

(plot_total + plot_advocacy) / (plot_entry + plot_funding)

A one-unit change in X results in a relative change of \(e^\beta\) in \(\frac{\text{E(Proportion)}}{1 - \text{E(Proportion)}}\) - see https://stats.stackexchange.com/questions/297659/interpretation-of-betareg-coef - the ratio of contentious to non-contentious aid? the ratio of of contentious aid?

See also https://stats.stackexchange.com/a/230679/3025 and https://static1.squarespace.com/static/58a7d1e52994ca398697a621/t/5a2ebc43e4966b0fab6b02de/1513012293857/betareg_politics.pdf

fit_h2_outcomes %>% 
  filter(model_name == "h2_total") %>% 
  pull(fit_outcome) %>% nth(1) %>% 
  conditional_effects()

fit_h2_outcomes %>% 
  filter(model_name == "h2_advocacy") %>% 
  pull(fit_outcome) %>% nth(1) %>% 
  conditional_effects()

fit_h2_outcomes %>% 
  filter(model_name == "h2_entry") %>% 
  pull(fit_outcome) %>% nth(1) %>% 
  conditional_effects()

fit_h2_outcomes %>% 
  filter(model_name == "h2_funding") %>% 
  pull(fit_outcome) %>% nth(1) %>% 
  conditional_effects()

LS0tCnRpdGxlOiAiSH4yfjogRWZmZWN0IG9mIGFudGktTkdPIGNyYWNrZG93biBvbiBhaWQgY29udGVudGlvdXNuZXNzIgphdXRob3I6ICJTdXBhcm5hIENoYXVkaHJ5IGFuZCBBbmRyZXcgSGVpc3MiCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVGJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcucmV0aW5hID0gMywKICAgICAgICAgICAgICAgICAgICAgIHRpZHkub3B0cyA9IGxpc3Qod2lkdGguY3V0b2ZmID0gMTIwKSwgICMgRm9yIGNvZGUKICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMod2lkdGggPSA5MCksICAjIEZvciBvdXRwdXQKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hc3AgPSAwLjYxOCwgZmlnLndpZHRoID0gNywgCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIiwgb3V0LndpZHRoID0gIjg1JSIpCgpvcHRpb25zKGRwbHlyLnN1bW1hcmlzZS5pbmZvcm0gPSBGQUxTRSkKYGBgCgpgYGB7ciBsb2FkLWxpYnJhcmllcywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoYnJtcykKbGlicmFyeSh0aWR5YmF5ZXMpCmxpYnJhcnkoYmF5ZXNwbG90KQpsaWJyYXJ5KGZpeGVzdCkKbGlicmFyeShicm9vbSkKbGlicmFyeShicm9vbS5taXhlZCkKbGlicmFyeShtb2RlbHN1bW1hcnkpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHRpY3RvYykKbGlicmFyeShsYXRleDJleHApCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGV4dHJhRGlzdHIpCmxpYnJhcnkoZ2x1ZSkKbGlicmFyeShoZXJlKQoKc291cmNlKGhlcmUoImxpYiIsICJncmFwaGljcy5SIikpCnNvdXJjZShoZXJlKCJsaWIiLCAibWlzY19mdW5zLlIiKSkKY29sb3Jfc2NoZW1lX3NldCgidmlyaWRpc0MiKQoKbGFic19leHBfbG9nZ2VkIDwtIGZ1bmN0aW9uKGJya3MpIHtUZVgocGFzdGUwKCJlXnsiLCBhcy5jaGFyYWN0ZXIobG9nKGJya3MpKSksICJ9Iil9CmxhYnNfZXhwIDwtIGZ1bmN0aW9uKGJya3MpIHtUZVgocGFzdGUwKCJlXnsiLCBhcy5jaGFyYWN0ZXIoYnJrcykpLCAifSIpfQoKbXlfc2VlZCA8LSAxMjM0CnNldC5zZWVkKG15X3NlZWQpCgpvcHRpb25zKG1jLmNvcmVzID0gcGFyYWxsZWw6OmRldGVjdENvcmVzKCksICAjIFVzZSBhbGwgcG9zc2libGUgY29yZXMKICAgICAgICBicm1zLmJhY2tlbmQgPSAicnN0YW4iKQoKQ0hBSU5TIDwtIDQKSVRFUiA8LSAyMDAwCldBUk1VUCA8LSAxMDAwCkJBWUVTX1NFRUQgPC0gMTIzNApgYGAKCmBgYHtyIGxvYWQtZGF0YS1hZGQtbGFnc30KZGZfY291bnRyeV9haWQgPC0gcmVhZFJEUyhoZXJlKCJkYXRhIiwgImRlcml2ZWRfZGF0YSIsICJkZl9jb3VudHJ5X2FpZC5yZHMiKSkKCmRmX2NvdW50cnlfYWlkIDwtIGRmX2NvdW50cnlfYWlkICU+JSAKICAjIFdpbnNvcml6ZSBwcm9wX2NvbnRlbnRpb3VzIGZvciB0aGUgdHdvIGNhc2VzIHRoYXQgYXJlIGV4YWN0bHkgMQogIG11dGF0ZShwcm9wX2NvbnRlbnRpb3VzX29yaWcgPSBwcm9wX2NvbnRlbnRpb3VzLAogICAgICAgICBwcm9wX2NvbnRlbnRpb3VzID0gaWZlbHNlKHByb3BfY29udGVudGlvdXMgPT0gMSwgMC45OTksIHByb3BfY29udGVudGlvdXMpLAogICAgICAgICBwcm9wX2NvbnRlbnRpb3VzX2xlYWQxX29yaWcgPSBwcm9wX2NvbnRlbnRpb3VzX2xlYWQxLAogICAgICAgICBwcm9wX2NvbnRlbnRpb3VzX2xlYWQxID0gCiAgICAgICAgICAgaWZlbHNlKHByb3BfY29udGVudGlvdXNfbGVhZDEgPT0gMSwgMC45OTksIHByb3BfY29udGVudGlvdXNfbGVhZDEpLAogICAgICAgICBwcm9wX2NvbnRlbnRpb3VzX2xlYWQxID0gCiAgICAgICAgICAgaWZlbHNlKHByb3BfY29udGVudGlvdXNfbGVhZDEgPCAwLCAwLCBwcm9wX2NvbnRlbnRpb3VzX2xlYWQxKSkKCmRmX2NvdW50cnlfYWlkX2xhd3MgPC0gZmlsdGVyKGRmX2NvdW50cnlfYWlkLCBsYXdzKQpgYGAKCiMjIFdlaWdodCBtb2RlbHMKCi0gTnVtZXJhdG9yIGlzIGxhZ2dlZCB0cmVhdG1lbnQgKyBub24tdmFyeWluZyBjb25mb3VuZGVycwotIERlbm9taW5hdG9yIGlzIGxhZ2dlZCB0cmVhdG1lbnQgKyBsYWdnZWQgb3V0Y29tZSArIHRpbWUtdmFyeWluZyBjb25mb3VuZGVycyArIG5vbi12YXJ5aW5nIGNvbmZvdW5kZXJzCgokJApzdyA9IFxwcm9kXnRfe3QgPSAxfSBcZnJhY3tccGhpKFRfe2l0fSB8IFRfe2ksIHQtMX0sIENfaSl9e1xwaGkoVF97aXR9IHwgVF97aSwgdC0xfSwgRF97aSwgdC0xfSwgQ19pKX0KJCQKCiMjIyBQcmlvcnMgZm9yIHdlaWdodCBtb2RlbHMKCldlIHVzZSBbZ2VuZXJpYyB3ZWFrbHkgaW5mb3JtYXRpdmUgcHJpb3JzXSgpIGZvciBvdXIgbW9kZWwgcGFyYW1ldGVyczoKCi0gSW50ZXJjZXB0OiAkXG1hdGhjYWx7Tn0gKDAsIDEwKSQKLSBDb2VmZmljaWVudHM6ICRcbWF0aGNhbHtOfSAoMCwgMi41KSQKLSBTaWdtYTogJFxvcGVyYXRvcm5hbWV7Q2F1Y2h5fSAoMCwgMSkkCgpgYGB7ciBwbG90LXdlaWdodC1wcmlvcnMsIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTYsIGZpZy5hc3A9TlVMTH0KcHJpX2ludCA8LSBnZ3Bsb3QoKSArCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgYXJncyA9IGxpc3QobWVhbiA9IDAsIHNkID0gMTApLAogICAgICAgICAgICAgICAgZ2VvbSA9ICJhcmVhIiwgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHggPSBUZVgoIlxcdGV4dGJme0ludGVyY2VwdCAozrJfMCl9IikpICsKICBhbm5vdGF0ZShnZW9tID0gImxhYmVsIiwgeCA9IDAsIHkgPSAwLjAxLCBsYWJlbCA9ICJOKDAsIDEwKSIsIHNpemUgPSBwdHMoOSkpICsKICB4bGltKC00MCwgNDApICsKICB0aGVtZV9kb25vcnMocHJpb3IgPSBUUlVFKQoKcHJpX2NvZWYgPC0gZ2dwbG90KCkgKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBsaXN0KG1lYW4gPSAwLCBzZCA9IDIuNSksCiAgICAgICAgICAgICAgICBnZW9tID0gImFyZWEiLCBmaWxsID0gImdyZXk4MCIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnMoeCA9IFRlWCgiXFx0ZXh0YmZ7Q29lZmZpY2llbnRzICjOsl94KX0iKSkgKwogIGFubm90YXRlKGdlb20gPSAibGFiZWwiLCB4ID0gMCwgeSA9IDAuMDQsIGxhYmVsID0gIk4oMCwgMykiLCBzaXplID0gcHRzKDkpKSArCiAgeGxpbSgtMTAsIDEwKSArCiAgdGhlbWVfZG9ub3JzKHByaW9yID0gVFJVRSkKCnByaV9zaWdtYSA8LSBnZ3Bsb3QoKSArCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBkY2F1Y2h5LCBhcmdzID0gbGlzdChsb2NhdGlvbiA9IDAsIHNjYWxlID0gMSksCiAgICAgICAgICAgICAgICBnZW9tID0gImFyZWEiLCBmaWxsID0gImdyZXk4MCIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnMoeCA9ICLPgyIpICsKICBhbm5vdGF0ZShnZW9tID0gImxhYmVsIiwgeCA9IDUsIHkgPSAwLjA4LCBsYWJlbCA9ICJDYXVjaHkoMCwgMSkiLCBzaXplID0gcHRzKDkpKSArCiAgeGxpbSgwLCAxMCkgKwogIHRoZW1lX2Rvbm9ycyhwcmlvciA9IFRSVUUpCgoocHJpX2ludCArIHByaV9jb2VmICsgcHJpX3NpZ21hKQpgYGAKCiMjIyBSdW4gd2VpZ2h0IG1vZGVscwoKYGBge3IgaDItd2VpZ2h0LW1vZGVscywgcmVzdWx0cz0iaGlkZSIsIG1lc3NhZ2U9RkFMU0V9CiMgTnVtZXJhdG9yIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEZvcm11bGFzCiMgVHJlYXRtZW50IH4gbGFnIHRyZWF0bWVudCArIG5vbi12YXJ5aW5nIGNvbmZvdW5kZXJzCmZvcm11bGFfaDJfbnVtX3RvdGFsIDwtIGJmKGJhcnJpZXJzX3RvdGFsIH4gYmFycmllcnNfdG90YWxfbGFnMSArICgxIHwgZ3djb2RlKSkKZm9ybXVsYV9oMl9udW1fYWR2b2NhY3kgPC0gYmYoYWR2b2NhY3kgfiBhZHZvY2FjeV9sYWcxICsgKDEgfCBnd2NvZGUpKQpmb3JtdWxhX2gyX251bV9lbnRyeSA8LSBiZihlbnRyeSB+IGVudHJ5X2xhZzEgKyAoMSB8IGd3Y29kZSkpCmZvcm11bGFfaDJfbnVtX2Z1bmRpbmcgPC0gYmYoZnVuZGluZyB+IGZ1bmRpbmdfbGFnMSArICgxIHwgZ3djb2RlKSkKCiMgUHJpb3JzCnByaW9yX251bSA8LSBjKHNldF9wcmlvcigibm9ybWFsKDAsIDEwKSIsIGNsYXNzID0gIkludGVyY2VwdCIpLAogICAgICAgICAgICAgICBzZXRfcHJpb3IoIm5vcm1hbCgwLCAyLjUpIiwgY2xhc3MgPSAiYiIpLAogICAgICAgICAgICAgICBzZXRfcHJpb3IoImNhdWNoeSgwLCAxKSIsIGNsYXNzID0gInNkIikpCgoKIyBEZW5vbWluYXRvciAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgRm9ybXVsYXMKIyBUcmVhdG1lbnQgfiBsYWcgdHJlYXRtZW50ICsgbGFnIG91dGNvbWUgKyB2YXJ5aW5nIGNvbmZvdW5kZXJzICsgbm9uLXZhcnlpbmcgY29uZm91bmRlcnMKZm9ybXVsYV9oMl9kZW5vbV90b3RhbCA8LSAKICBiZihiYXJyaWVyc190b3RhbCB+IGJhcnJpZXJzX3RvdGFsX2xhZzEgKyBwcm9wX2NvbnRlbnRpb3VzX2xhZzEgKwogICAgICAgIyBIdW1hbiByaWdodHMgYW5kIHBvbGl0aWNzCiAgICAgICB2MnhfcG9seWFyY2h5ICsgdjJ4X2NvcnIgKyB2MnhfcnVsZSArIHYyeF9jaXZsaWIgKyB2MnhfY2xwaHkgKyB2MnhfY2xwcml2ICsKICAgICAgICMgRWNvbm9taWNzIGFuZCBkZXZlbG9wbWVudAogICAgICAgZ2RwY2FwX2xvZyArIHVuX3RyYWRlX3BjdF9nZHAgKyB2MnBlZWR1ZXEgKyB2MnBlaGVhbHRoICsgZV9wZWluZm1vciArCiAgICAgICAjIENvbmZsaWN0IGFuZCBkaXNhc3RlcnMKICAgICAgIGludGVybmFsX2NvbmZsaWN0X3Bhc3RfNSArIG5hdHVyYWxfZGlzX2NvdW50ICsKICAgICAgICgxIHwgZ3djb2RlKSkKCmZvcm11bGFfaDJfZGVub21fYWR2b2NhY3kgPC0gCiAgYmYoYWR2b2NhY3kgfiBhZHZvY2FjeV9sYWcxICsgcHJvcF9jb250ZW50aW91c19sYWcxICsKICAgICAgIHYyeF9wb2x5YXJjaHkgKyB2MnhfY29yciArIHYyeF9ydWxlICsgdjJ4X2NpdmxpYiArIHYyeF9jbHBoeSArIHYyeF9jbHByaXYgKwogICAgICAgZ2RwY2FwX2xvZyArIHVuX3RyYWRlX3BjdF9nZHAgKyB2MnBlZWR1ZXEgKyB2MnBlaGVhbHRoICsgZV9wZWluZm1vciArCiAgICAgICBpbnRlcm5hbF9jb25mbGljdF9wYXN0XzUgKyBuYXR1cmFsX2Rpc19jb3VudCArCiAgICAgICAoMSB8IGd3Y29kZSkpCgpmb3JtdWxhX2gyX2Rlbm9tX2VudHJ5IDwtIAogIGJmKGVudHJ5IH4gZW50cnlfbGFnMSArIHByb3BfY29udGVudGlvdXNfbGFnMSArCiAgICAgICB2MnhfcG9seWFyY2h5ICsgdjJ4X2NvcnIgKyB2MnhfcnVsZSArIHYyeF9jaXZsaWIgKyB2MnhfY2xwaHkgKyB2MnhfY2xwcml2ICsKICAgICAgIGdkcGNhcF9sb2cgKyB1bl90cmFkZV9wY3RfZ2RwICsgdjJwZWVkdWVxICsgdjJwZWhlYWx0aCArIGVfcGVpbmZtb3IgKwogICAgICAgaW50ZXJuYWxfY29uZmxpY3RfcGFzdF81ICsgbmF0dXJhbF9kaXNfY291bnQgKwogICAgICAgKDEgfCBnd2NvZGUpKQoKZm9ybXVsYV9oMl9kZW5vbV9mdW5kaW5nIDwtIAogIGJmKGZ1bmRpbmcgfiBmdW5kaW5nX2xhZzEgKyBwcm9wX2NvbnRlbnRpb3VzX2xhZzEgKwogICAgICAgdjJ4X3BvbHlhcmNoeSArIHYyeF9jb3JyICsgdjJ4X3J1bGUgKyB2MnhfY2l2bGliICsgdjJ4X2NscGh5ICsgdjJ4X2NscHJpdiArCiAgICAgICBnZHBjYXBfbG9nICsgdW5fdHJhZGVfcGN0X2dkcCArIHYycGVlZHVlcSArIHYycGVoZWFsdGggKyBlX3BlaW5mbW9yICsKICAgICAgIGludGVybmFsX2NvbmZsaWN0X3Bhc3RfNSArIG5hdHVyYWxfZGlzX2NvdW50ICsKICAgICAgICgxIHwgZ3djb2RlKSkKCiMgUHJpb3JzCnByaW9yX2Rlbm9tIDwtIGMoc2V0X3ByaW9yKCJub3JtYWwoMCwgMTApIiwgY2xhc3MgPSAiSW50ZXJjZXB0IiksCiAgICAgICAgICAgICAgICAgc2V0X3ByaW9yKCJub3JtYWwoMCwgMi41KSIsIGNsYXNzID0gImIiKSwKICAgICAgICAgICAgICAgICBzZXRfcHJpb3IoIm5vcm1hbCgwLCAyLjUpIiwgY2xhc3MgPSAic2QiKSkKCgojIFJ1biB3ZWlnaHRpbmcgbW9kZWxzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBBbGwgbW9kZWxzIGdldCBydW4gaW5zaWRlIGEgdGliYmxlIHVzaW5nIG1hcCgpIG1hZ2ljCmFsbF9tb2RlbHNfaDIgPC0gdHJpYmJsZSgKICB+bW9kZWxfbmFtZSwgfmZvcm11bGFfbnVtLCB+Zm9ybXVsYV9kZW5vbSwKICAiaDJfdG90YWwiLCBmb3JtdWxhX2gyX251bV90b3RhbCwgZm9ybXVsYV9oMl9kZW5vbV90b3RhbCwKICAiaDJfYWR2b2NhY3kiLCBmb3JtdWxhX2gyX251bV9hZHZvY2FjeSwgZm9ybXVsYV9oMl9kZW5vbV9hZHZvY2FjeSwKICAiaDJfZW50cnkiLCBmb3JtdWxhX2gyX251bV9lbnRyeSwgZm9ybXVsYV9oMl9kZW5vbV9lbnRyeSwKICAiaDJfZnVuZGluZyIsIGZvcm11bGFfaDJfbnVtX2Z1bmRpbmcsIGZvcm11bGFfaDJfZGVub21fZnVuZGluZwopCgojIEZpdCBtb2RlbHMKdGljKCkKZml0X2gyX2FsbF9tb2RlbHMgPC0gYWxsX21vZGVsc19oMiAlPiUKICBtdXRhdGUoZml0X251bSA9IG1hcDIoZm9ybXVsYV9udW0sIG1vZGVsX25hbWUsIH5icm0oCiAgICAueCwKICAgIGRhdGEgPSBkZl9jb3VudHJ5X2FpZF9sYXdzLAogICAgcHJpb3IgPSBwcmlvcl9udW0sCiAgICBpdGVyID0gSVRFUiwgY2hhaW5zID0gQ0hBSU5TLCB3YXJtdXAgPSBXQVJNVVAsIHNlZWQgPSBCQVlFU19TRUVELAogICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5KSwKICAgIGZpbGUgPSBoZXJlKCJhbmFseXNpcyIsICJtb2RlbF9jYWNoZSIsIHBhc3RlMCgueSwgIl9udW0ucmRzIikpCiAgKSkpICU+JQogIG11dGF0ZShmaXRfZGVub20gPSBtYXAyKGZvcm11bGFfZGVub20sIG1vZGVsX25hbWUsIH5icm0oCiAgICAueCwKICAgIGRhdGEgPSBkZl9jb3VudHJ5X2FpZF9sYXdzLAogICAgcHJpb3IgPSBwcmlvcl9kZW5vbSwKICAgIGl0ZXIgPSBJVEVSLCBjaGFpbnMgPSBDSEFJTlMsIHdhcm11cCA9IFdBUk1VUCwgc2VlZCA9IEJBWUVTX1NFRUQsCiAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOSksCiAgICBmaWxlID0gaGVyZSgiYW5hbHlzaXMiLCAibW9kZWxfY2FjaGUiLCBwYXN0ZTAoLnksICJfZGVub20ucmRzIikpCiAgKSkpIApmaXRfaDJfYWxsX21vZGVscwp0b2MoKQpgYGAKCiMjIyBDaGVjayB3ZWlnaHQgbW9kZWxzCgpXZSBjaGVjayBvbmUgb2YgdGhlIGRlbm9taW5hdG9yIG1vZGVscyBmb3IgY29udmVyZ2VuY2UgYW5kIG1peGluZyBhbmQgZml0IChub3QgdGhlIG51bWVyYXRvciwgc2luY2UgdGhvc2UgbW9kZWxzIGFyZSB0aGUgc2FtZSBhcyB0aGUgb25lcyBpbiBIMSkuCgpgYGB7ciBoMi1jaGVjay1kZW5vbWluYXRvcn0KY2hlY2tfdG90YWxfZGVub20gPC0gZml0X2gyX2FsbF9tb2RlbHMgJT4lIAogIGZpbHRlcihtb2RlbF9uYW1lID09ICJoMl90b3RhbCIpICU+JSBwdWxsKGZpdF9kZW5vbSkgJT4lIGZpcnN0KCkKCnBwX2NoZWNrKGNoZWNrX3RvdGFsX2Rlbm9tLCB0eXBlID0gImRlbnNfb3ZlcmxheSIsIG5zYW1wbGVzID0gMTApICsKICB0aGVtZV9kb25vcnMoKQoKY2hlY2tfdG90YWxfZGVub20gJT4lIAogIHBvc3Rlcmlvcl9zYW1wbGVzKGFkZF9jaGFpbiA9IFRSVUUpICU+JSAKICBzZWxlY3QoLXN0YXJ0c193aXRoKCJyX2d3Y29kZSIpLCAtc3RhcnRzX3dpdGgoInpfIiksIC1scF9fLCAtaXRlcikgJT4lIAogIG1jbWNfdHJhY2UoKSArCiAgdGhlbWVfZG9ub3JzKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKIyMgQnVpbGQgd2VpZ2h0cwoKYGBge3IgaDItYnVpbGQtd2VpZ2h0cywgY2FjaGU9VFJVRX0KdGljKCkKZml0X2gyX3ByZWRzIDwtIGZpdF9oMl9hbGxfbW9kZWxzICU+JQogIG11dGF0ZShwcmVkX251bSA9IG1hcChmaXRfbnVtLCB+cHJlZGljdCgueCwgbmV3ZGF0YSA9IGRmX2NvdW50cnlfYWlkX2xhd3MsIGFsbG93X25ld19sZXZlbHMgPSBUUlVFKSksCiAgICAgICAgIHJlc2lkX251bSA9IG1hcChmaXRfbnVtLCB+cmVzaWR1YWxzKC54LCBuZXdkYXRhID0gZGZfY291bnRyeV9haWRfbGF3cywgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUpKSwKICAgICAgICAgcHJlZF9kZW5vbSA9IG1hcChmaXRfZGVub20sIH5wcmVkaWN0KC54LCBuZXdkYXRhID0gZGZfY291bnRyeV9haWRfbGF3cywgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUpKSwKICAgICAgICAgcmVzaWRfZGVub20gPSBtYXAoZml0X2Rlbm9tLCB+cmVzaWR1YWxzKC54LCBuZXdkYXRhID0gZGZfY291bnRyeV9haWRfbGF3cywgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUpKSkKdG9jKCkKCmZpdF9oMl9pcHcgPC0gZml0X2gyX3ByZWRzICU+JQogIG11dGF0ZShudW1fYWN0dWFsID0gcG1hcChsaXN0KGZvcm0gPSBmb3JtdWxhX251bSwgcHJlZCA9IHByZWRfbnVtLCByZXNpZCA9IHJlc2lkX251bSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxjX3Byb2JfZGlzdCksCiAgICAgICAgIGRlbm9tX2FjdHVhbCA9IHBtYXAobGlzdChmb3JtID0gZm9ybXVsYV9kZW5vbSwgcHJlZCA9IHByZWRfZGVub20sIHJlc2lkID0gcmVzaWRfZGVub20pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxjX3Byb2JfZGlzdCkpICU+JSAKICBtdXRhdGUoZGZfd2l0aF93ZWlnaHRzID0gbWFwMihudW1fYWN0dWFsLCBkZW5vbV9hY3R1YWwsIH57CiAgICBkZl9jb3VudHJ5X2FpZF9sYXdzICU+JSAKICAgICAgbXV0YXRlKHdlaWdodHNfc2Fuc190aW1lID0gLnggLyAueSkgJT4lIAogICAgICBncm91cF9ieShnd2NvZGUpICU+JSAKICAgICAgbXV0YXRlKGlwdyA9IGN1bXByb2RfbmEod2VpZ2h0c19zYW5zX3RpbWUpKSAlPiUgCiAgICAgIHVuZ3JvdXAoKQogIH0pKQpmaXRfaDJfaXB3CmBgYAoKCiMjIE91dGNvbWUgbW9kZWxzCgojIyMgTW9kZWxpbmcgY2hvaWNlCgpPdXIgZGVwZW5kZW50IHZhcmlhYmxlIGZvciB0aGlzIGh5cG90aGVzaXMgaXMgdGhlIHBlcmNlbnRhZ2Ugb2YgT0RBIChzdGlsbCBpbiBjb25zdGFudCAyMDExIGRvbGxhcnMpIGFsbG9jYXRlZCBmb3IgY29udGVudGlvdXMgcHVycG9zZXMsIGFnYWluIGxlYWRlZCBieSBvbmUgeWVhci4gV2UgY2xhc3NpZnkgY29udGVudGlvdXMgYWlkIGFzIGFueSBwcm9qZWN0IGZvY3VzZWQgb24gZ292ZXJubWVudCBhbmQgY2l2aWwgc29jaWV0eSAoREFDIGNvZGVzIDE1MCBhbmQgMTUxKSBvciBjb25mbGljdCBwcmV2ZW50aW9uIGFuZCByZXNvbHV0aW9uLCBwZWFjZSBhbmQgc2VjdXJpdHkgKERBQyBjb2RlIDE1MikuCgpXb3JraW5nIHdpdGggcHJvcG9ydGlvbiBkYXRhLCBob3dldmVyLCBwb3NlcyBpbnRlcmVzdGluZyBtYXRoZW1hdGljYWwgYW5kIG1ldGhvZG9sb2dpY2FsIGNoYWxsZW5nZXMsIHNpbmNlIHRoZSByYW5nZSBvZiBwb3NzaWJsZSBvdXRjb21lcyBpcyBsaW1pdGVkIHRvIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxLiBUcmVhdGluZyBwcm9wb3J0aW9uIHZhcmlhYmxlcyBpbiBhIG1peGVkIG1vZGVsIGlzIHRlY2huaWNhbGx5IHBvc3NpYmxlLCBidXQgaXQgeWllbGRzIHByZWRpY2l0aW9ucyB0aGF0IGdvIGJleW9uZCB0aGUgYWxsb3dhYmxlIHJhbmdlIG9mIHZhbHVlcyAoMS4xMywgLTAuNSwgZXRjLikuIFRyZWF0aW5nIHRoZSBwcm9wb3J0aW9uIGFzIGEgYmlub21pYWwgdmFyaWFibGUgaXMgYWxzbyBwb3NzaWJsZSBhbmQgaXMgaW5kZWVkIFtvbmUgb2YgdGhlIHdheXMgdG8gdXNlIHRoZSBgZ2xtKClgIGZ1bmN0aW9uXShodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS85MTExOTA0LzEyMDg5OCkgaW4gUi4gSG93ZXZlciwgdGhpcyBlbnRhaWxzIGNvbnNpZGVyaW5nIHRoZSBwcm9wb3J0aW9uIGFzIGEgcmF0aW8gb2Ygc3VjY2VzcyBhbmQgZmFpbHVyZXMuIEluIHRoaXMgY2FzZSwgdHJlYXRpbmcgYSBkb2xsYXIgb2YgY29udGVudGlvdXMgYWlkIGFzIGEgc3VjY2VzcyBmZWVscyBvZmYsIGVzcGVjaWFsbHkgc2luY2UgYWlkIGFtb3VudHMgYXJlbid0IGluZGVwZW5kZW50IGV2ZW50c+KAlGl0J3Mgbm90IGxpa2UgZWFjaCBkb2xsYXIgb2YgYWlkIGdvZXMgdGhyb3VnaCBhIHByb2JhYmFsaXN0aWMgcHJvY2VzcyBsaWtlIGEgY29pbiBmbGlwLiAKCltPbmUgcmVjb21tZW5kYXRpb24gYnkgQmVuIEJvbGtlcl0oaHR0cHM6Ly9zdGF0LmV0aHouY2gvcGlwZXJtYWlsL3Itc2lnLW1peGVkLW1vZGVscy8yMDExcTEvMDE1NDIyLmh0bWwpLCB0aGUgbWFpbnRhaW5lciBvZiBbYGxtZTRgXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy9wYWNrYWdlPWxtZTQpLCBpcyB0byB1c2UgYSBsb2dpdCB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGluIGBsbWVyKClgIG1vZGVscy4gVGhpcyBzZWVtcyB0byBiZSBbc3RhbmRhcmQgcHJhY3RpY2UgaW4gcG9saXRpY2FsIHNjaWVuY2UgcmVzZWFyY2hdKGh0dHBzOi8vYWNyb3dpbmdoZW4uY29tLzIwMTQvMDQvMjQvaW50ZXJwcmV0aW5nLWNvZWZmaWNpZW50cy1mcm9tLWEtbG9naXQtbGluZWFyLW1vZGVsLXdpdGgtYS1wcm9wb3J0aW9uYWwtZGVwZW5kZW50LXZhcmlhYmxlLyksIHRvby4gTG9naXQgdHJhbnNmb3JtYXRpb25zIHN0aWxsIGNhbid0IGhhbmRsZSB2YWx1ZXMgb2YgZXhhY3RseSAwIG9yIDEsIHRob3VnaCwgYnV0IGl0J3MgcG9zc2libGUgdG8gW3dpbnNvcml6ZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2luc29yaXppbmcpIHRob3NlIHZhbHVlcyBieSBhZGRpbmcgb3Igc3VidHJhY3RpbmcgMC4wMDEgdG8gdGhlIGV4dHJlbWVzLgoKQW5vdGhlciBzb2x1dGlvbiBpcyB0byB1c2UgW2JldGEgcmVncmVzc2lvbl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT1iZXRhcmVnKSwgd2hpY2ggW2NvbnN0cmFpbnMgdGhlIG91dGNvbWUgdmFyaWFibGUgdG8gdmFsdWVzIGJldHdlZW4gMCBhbmQgMV0oaHR0cDovL3d3dy50aGVhbmFseXNpc2ZhY3Rvci5jb20vemVyby1vbmUtaW5mbGF0ZWQtYmV0YS1tb2RlbHMtZm9yLXByb3BvcnRpb24tZGF0YS8pLCBidXQgdW5mb3J0dW5hdGVseSBkb2VzIG5vdCBhbGxvdyBmb3IgdmFsdWVzIG9mIGV4YWN0bHkgMCBvciAxLiBaZXJvLWFuZC1vbmUgaW5mbGF0ZWQgYmV0YSByZWdyZXNzaW9uIG1vZGVscywgaG93ZXZlciwgbWFrZSBhZGp1c3RtZW50cyBmb3IgdGhpcyBhbmQgbW9kZWwgdGhlIHByb2JhYmlsaXR5IG9mIGJlaW5nIDAsIGJlaW5nIDEsIGFuZCBiZWluZyBzb21ld2hlcmUgaW4gdGhlIG1pZGRsZSB1c2luZyBkaWZmZXJlbnQgcHJvY2Vzc2VzLiBNYXR0aSBWdW9ycmUgaGFzIFthbiBleGNlbGxlbnQgb3ZlcnZpZXcgb2YgWk9JQiBtb2RlbHMgaGVyZV0oaHR0cHM6Ly92dW9ycmUubmV0bGlmeS5hcHAvcG9zdC8yMDE5LzAyLzE4L2FuYWx5emUtYW5hbG9nLXNjYWxlLXJhdGluZ3Mtd2l0aC16ZXJvLW9uZS1pbmZsYXRlZC1iZXRhLW1vZGVscy8pLgoKSW4gdGhlIG9yaWdpbmFsIHZlcnNpb25zIG9mIHRoaXMgcHJvamVjdCwgd2UgdXNlZCBsb2dpdC1saW5lYXIgbW9kZWxzIG9mIHRoZSByYXRpbyBvZiBjb250ZW50aW91cyBhaWQgdG8gbm9uLWNvbnRlbnRpb3VzIGFpZCwgbGlrZSB0aGlzOiAKCiQkbG4oIFxmcmFje1x0ZXh0e2NvbnRlbnRpb3VzIE9EQX1fe1x0ZXh0e09FQ0R9fX17XHRleHR7bm9uY29udGVudGlvdXMgT0RBfV97XHRleHR7T0VDRH19fSApX3tpLCB0KzF9ID0gXHRleHR7TkdPIGxlZ2lzbGF0aW9ufV97aXR9ICsgXHRleHR7Y29udHJvbHN9X3tpdH0kJAoKVGhhdCBtZWFudCB3ZSBoYWQgdG8gY29tcGFyZSB0aGUgcmF0aW8gb2YgY29udGVudGlvdXMgYWlkIHRvIG5vbi1jb250ZW50aW91cyBhaWQgcmF0aGVyIHRoYW4gdGhlIGRpcmVjdCBwZXJjZW50IG9mIGNvbnRlbnRpb3VzIGFpZCwgYW5kIGl0IG1hZGUgZm9yIHNvbWUgYWNyb2JhdGljIGludGVycHJldGF0aW9ucy4KCkhlcmUsIHdlIHVzZSB6ZXJvLWluZmxhdGVkIGJldGEgcmVncmVzc2lvbiBpbnN0ZWFkLCBzaW5jZSAqKmJybXMqKiBhbmQgU3RhbiBoYXZlIGltcHJvdmVkIGFuZCBzcGVkIHVwICphIHRvbiogb3ZlciB0aGUgcGFzdCBmZXcgeWVhcnMuCgpUaGUgcHJvcG9ydGlvbiBvZiBjb250ZW50aW91cyBhaWQgaGFzIGEgYnVuY2ggb2YgemVyb2VzLCBhbmQgdGhvc2UgemVyb3MgYXJlIGNsb3NlIHRvIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHJlZ3VsYXIgZGF0YSwgc28gd2UgdXNlIHplcm8taW5mbGF0ZWQgbW9kZWxzIHJhdGhlciB0aGFuIGEgaHVyZGxlIHByb2Nlc3MgbGlrZSB3aXRoIGRpZCB3aXRoIEh+MX4gYW5kIHRvdGFsIE9EQS4gU29tZXRoaW5nIGRldGVybWluZXMgd2hldGhlciBhIGNvdW50cnkveWVhciByZWNlaXZlcyBhbnkgY29udGVudGlvdXMgYWlkLCBhbmQgdGhlbiBzb21ldGhpbmcgZWxzZSBkZXRlcm1pbmVzIHdoYXQgcHJvcG9ydGlvbiBpcyBjb250ZW50aW91cy4KCklmIHdlIGRvbid0IHRha2UgdGhpcyB6ZXJvLWluZmxhdGlvbiBwcm9jZXNzIGludG8gYWNjb3VudCBpbiB0aGUgbW9kZWwsIG91ciBBVEUgd2lsbCBiZSB3cm9uZy4gV2UgZG9uJ3QgcmVhbGx5IGNhcmUgYWJvdXQgdGhlIGV4YWN0IHplcm8taW5mbGF0aW9uIHByb2Nlc3PigJR3ZSBjYXJlIG1vc3QgYWJvdXQgdGhlIEFURSBvZiBsYXdzL3Jlc3RyaWN0aW9ucyBvbiBjb250ZW50aW91c25lc3PigJRidXQgd2Ugc3RpbGwgbmVlZCB0byBkZWFsIHdpdGggdGhlIG11bHRpcGxlIHByb2Nlc3Nlcy4KCmBgYHtyIHNob3ctb3V0Y29tZS1kaXN0fQpnZ3Bsb3QoZGZfY291bnRyeV9haWRfbGF3cywgCiAgICAgICBhZXMoeCA9IHByb3BfY29udGVudGlvdXMsIGZpbGwgPSBwcm9wX2NvbnRlbnRpb3VzID09IDApKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjA1LCBjb2xvciA9ICJ3aGl0ZSIsIGJvdW5kYXJ5ID0gMCkgKwogIGxhYnMoeCA9ICJQcm9wb3J0aW9uIG9mIGNvbnRlbnRpb3VzIGFpZCIsIHkgPSAiQ291bnQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZ3JleTgwIiwgIiNGRjg1MUIiKSwgCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiJSA+IDAiLCAiJSA9IDAiKSwKICAgICAgICAgICAgICAgICAgICBuYW1lID0gTlVMTCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgdGhlbWVfZG9ub3JzKCkKCiMgUGVyY2VudCB3aGVyZSBwcm9wX2NvbnRlbnRpb3VzIGlzIDA6CmRmX2NvdW50cnlfYWlkX2xhd3MgJT4lIAogIGNvdW50KHByb3BfY29udGVudGlvdXMgPT0gMCkgJT4lIAogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSkKYGBgCgpXZSB0aHVzIGZpdCBhIHplcm8taW5mbGF0ZWQgYmV0YSBtb2RlbCwgd2hpY2ggdXNlcyBhIGxvZ2l0IG1vZGVsIHRvIHByZWRpY3QgMC9ub3QgMCwgdGhlbiB1c2VzIGEgYmV0YSBmYW1pbHkgdG8gbW9kZWwgdGhlIHJlc3Qgb2YgdGhlIGRhdGEuIAoKQmV0YSByZWdyZXNzaW9uIGlzIGJhc2VkIG9uIHRoZSBiZXRhIGRpc3RyaWJ1dGlvbiBhbmQgaXRzIHR3byBzaGFwZSBwYXJhbWV0ZXJzLCBidXQgdGhlIHBhcmFtZXRlcml6YXRpb24gb2YgdGhlIGRpc3RyaWJ1dGlvbiBpbiBicm1zL3N0YW4gdXNlcyAkXG11JCBhbmQgJFxwaGkkLCB3aGljaCBhcmUgdHJhbnNmb3JtZWQgdmVyc2lvbnMgb2Ygc2hhcGUgMSBhbmQgc2hhcGUgMjoKCi0gJFx0ZXh0e3NoYXBlMX0gPSBcbXUgXHBoaSQKLSAkXHRleHR7c2hhcGUyfSA9ICgxIC0gXG11KVxwaGkkCgpUaGlzIGlzIGFjdHVhbGx5IGtpbmQgb2YgbmVhdCwgYmVjYXVzZSBpbnN0ZWFkIG9mIHRyeWluZyB0byBmaW5hZ2xlIGEgYmV0YSBkaXN0cmlidXRpb24gYmFzZWQgb24gJFxmcmFje1x0ZXh0e3NoYXBlMX19e1x0ZXh0e3NoYXBlMX0gKyBcdGV4dHtzaGFwZTJ9fSQsIHlvdSBjYW4gc3BlY2lmeSB0aGUgYXZlcmFnZSBwcm9wb3J0aW9uIGFuZCAic3ByZWFkIiBzaW1pbGFyIHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KCkZvciBpbnN0YW5jZSwgaWYgd2Ugd2FudGVkIGEgYmV0YSBkaXN0cmlidXRpb24gYXJvdW5kIDAuMywgd2l0aCBzb21lIG1vZGVyYXRlIHNwcmVhZCwgd2UgY291bGQgcGxheSBhcm91bmQgd2l0aCBgc2hhcGUxYCBhbmQgYHNoYXBlMmAgYW5kIGZpZ3VyZSB0aGF0IHRoZXkncmUgcHJvYmFibHkgc29tZXRoaW5nIGxpa2UgMyBhbmQgNywgYmFzZWQgb24gJFxmcmFjezN9ezMgKyA3fSQuIFdlIGNhbiBnZXQgdGhlc2Ugc2FtZSBudW1iZXJzIHdpdGggdGhlIHJlcGFyYW1ldGVyaXplZCB2ZXJzaW9uLCB1c2luZyAwLjMgYXMgJFxtdSQgKGkuZS4gY2x1c3RlcmVkIGFyb3VuZCAwLjMpIGFuZCAxMCBhcyAkXHBoaSQuIFdlIGdldCB0aGUgc2FtZSAzIGFuZCA3IHZhbHVlcyBmb3IgdGhlIHR3byBzaGFwZXMgYW5kIHRoZSBkaXN0cmlidXRpb24gbG9va3MgZ3JlYXQhIFRoZSBgZHByb3AoKWAgZnVuY3Rpb24gaW4gKipleHRyYURpc3RyKiogdGFrZXMgdGhlc2UgcmVwYXJhbWV0ZXJpemVkIGFyZ3VtZW50cyBkaXJlY3RseSwgdG9vIChpdCBjYWxscyAkcGhpJCBgc2l6ZWApLgoKYGBge3IgYmV0YS1yZXBhcmFtZXRlcml6ZWQtZXhhbXBsZSwgZmlnLndpZHRoPTYuNSwgZmlnLmhlaWdodD0yLjUsIGZpZy5hc3A9TlVMTH0KbXUgPC0gMC4zCnBoaSA8LSAxMAoKc2hhcGUxIDwtIG11ICogcGhpCnNoYXBlMQoKc2hhcGUyIDwtICgxIC0gbXUpICogcGhpCnNoYXBlMgoKIyBXaXRoIGRiZXRhCnBsb3RfYmV0YSA8LSBnZ3Bsb3QoKSArCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBkYmV0YSwgYXJncyA9IGxpc3Qoc2hhcGUxID0gc2hhcGUxLCBzaGFwZTIgPSBzaGFwZTIpLAogICAgICAgICAgICAgICAgZ2VvbSA9ICJhcmVhIiwgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnMoeCA9ICJQcm9wb3J0aW9uIiwgeSA9IE5VTEwsIAogICAgICAgdGl0bGUgPSAiQmV0YSBkaXN0cmlidXRpb24iLAogICAgICAgc3VidGl0bGUgPSBnbHVlKCJzaGFwZTEgPSB7c2hhcGUxfTsgc2hhcGUyID0ge3NoYXBlMn0iKSkgKwogIHRoZW1lX2Rvbm9ycyg5KSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpCgojIFdpdGggZHByb3AKcGxvdF9wcm9wIDwtIGdncGxvdCgpICsKICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRwcm9wLCBhcmdzID0gbGlzdChzaXplID0gcGhpLCBtZWFuID0gbXUpLAogICAgICAgICAgICAgICAgZ2VvbSA9ICJhcmVhIiwgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnMoeCA9ICJQcm9wb3J0aW9uIiwgeSA9IE5VTEwsIAogICAgICAgdGl0bGUgPSAiUmVwYXJhbWV0ZXJpemVkIGJldGEgZGlzdHJpYnV0aW9uIiwKICAgICAgIHN1YnRpdGxlID0gZ2x1ZSgiwrUgPSB7bXV9OyDPhiA9IHtwaGl9IikpICsKICB0aGVtZV9kb25vcnMoOSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKQoKcGxvdF9iZXRhICsgcGxvdF9wcm9wCmBgYAoKVGhlIG1lZGlhbiBwcm9wb3J0aW9uIG9mIGNvbnRlbnRpb3VzIGFpZCBmb3Igbm9uLXplcm8gY2FzZXMgaXMgYXJvdW5kIDUlLCBhbmQgYmFzZWQgb24gdGhlIGhpc3RvZ3JhbSBlYXJsaWVyLCBpdCdzIG5vdCB1bmhlYXJkIG9mIHRvIGdvIHVwIHRvIDI1JSBvciBldmVuIGFzIGhpZ2ggYXMgNTAlOgoKYGBge3IgZmluZC1tZWRpYW4tY29udGVuc2lvdXNuZXNzfQpkZl9jb3VudHJ5X2FpZF9sYXdzICU+JSAKICBmaWx0ZXIocHJvcF9jb250ZW50aW91cyA+IDApICU+JSAKICBzdW1tYXJpemUobWVkaWFuX3Byb3AgPSBtZWRpYW4ocHJvcF9jb250ZW50aW91cykpCmBgYAoKSW4gdGhlIGFic2VuY2Ugb2YgYW55IGNvdmFyaWF0ZXMsIHdlIGNvdWxkIHVzZSBhICRtdSQgb2YgMC4wNSBhbmQgYSAkcGhpJCBvZiAzOgoKYGBge3IgbXUtcGhpLW91ci1kYXRhLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00LCBmaWcuYXNwPU5VTEx9CmJldGFfbXUgPC0gMC4wNQpiZXRhX3BoaSA8LSAzCgojIGJldGFfc2hhcGUxIDwtIGJldGFfbXUgKiBiZXRhX3BoaQojIGJldGFfc2hhcGUyIDwtICgxIC0gYmV0YV9tdSkgKiBiZXRhX3BoaQoKZ2dwbG90KCkgKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZHByb3AsIGFyZ3MgPSBsaXN0KHNpemUgPSBiZXRhX3BoaSwgbWVhbiA9IGJldGFfbXUpLAogICAgICAgICAgICAgICAgZ2VvbSA9ICJhcmVhIiwgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnMoeCA9ICJQcm9wb3J0aW9uIiwgeSA9IE5VTEwsIAogICAgICAgdGl0bGUgPSAiUmVwYXJhbWV0ZXJpemVkIGJldGEgZGlzdHJpYnV0aW9uIiwKICAgICAgIHN1YnRpdGxlID0gZ2x1ZSgiwrUgPSB7YmV0YV9tdX07IM+GID0ge2JldGFfcGhpfSIpKSArCiAgdGhlbWVfZG9ub3JzKDkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgpUaGlzIGdldHMgbW9yZSBjb21wbGV4LCB0aG91Z2gsIG9uY2Ugd2Ugc3RhcnQgYWRkaW5nIGNvdmFyaWF0ZXMuICRcbXUkIGlzIG1vZGVsZWQgd2l0aCBsb2dpc3RpYyByZWdyZXNzaW9uIHdoaWxlICRccGhpJCBpcyBtb2RlbGVkIHdpdGggYSBsb2cgbGluaywgYW5kIGVhY2ggb2YgdGhlc2UgbW9kZWxzIGNhbiBnZXQgdGhlaXIgb3duIGNvdmFyaWF0ZXMuCgojIyMgUHJpb3JzIGZvciBvdXRjb21lIG1vZGVscwoKVGhlcmUgYXJlIGEgKnRvbiogb2YgbW92aW5nIHBhcnRzIGluIHRoZXNlIG91dGNvbWUgbW9kZWxzLiBIZXJlJ3MgdGhlIGZ1bGwgc3BlY2lmaWNhdGlvbiBmb3IgdGhlIG1vZGVscyBhbmQgYWxsIHByaW9yczoKCiQkClxiZWdpbnthbGlnbmVkfQpcdGV4dHt5fV97aSx0fSB8IHVfaSwgXHRleHR7TGF3fV97aSwgdH0gJlxzaW0gXG9wZXJhdG9ybmFtZXtaSUJldGF9IChaX2ksIFx0ZXh0e3l9XlxzdGFyX2ksIFxwaGlfaSkgJiBcdGV4dHtbbGlrZWxpaG9vZF19IFxcClxvcGVyYXRvcm5hbWV7bG9naXR9IChaX2kpICZcc2ltIFxhbHBoYV9aICYgXHRleHR7W2ludGVyY2VwdC1vbmx5IGxvZ2l0IGlmIH0gXHRleHR7eX1fe2ksIHR9ID0gMCBcdGV4dHtdfSBcXApcb3BlcmF0b3JuYW1le2xvZ2l0fSAoXHRleHR7eX1eXHN0YXJfaSkgJlxzaW0gKFxiZXRhXzAgKyBcYmV0YV8xIFx0ZXh0e0xhd31fe2ksIHR9ICsgXGJldGFfMiBcdGV4dHtMYXd9X3tpLCB0LTF9LCBcc2lnbWFeMl9cZXBzaWxvbiwgdV9pKSBcdGltZXMgXHRleHR7SVBXfV97aSwgdH0gJiBcdGV4dHtbaWYgfSBcdGV4dHt5fV97aSwgdH0gPiAwIFx0ZXh0e119XFwKXGxvZyAoXHBoaV9pKSAmXHNpbSBcYWxwaGFfXHBoaSAmIFx0ZXh0e1tpbnRlcmNlcHQtb25seSBtb2RlbCBmb3IgcHJlY2lzaW9uXX0gXFwKdV9pICZcc2ltIFxtYXRoY2Fse059ICgwLCBcc2lnbWFeMl91KSAmIFx0ZXh0e1tjb3VudHJ5LXNwZWNpZmljIGludGVyY2VwdHNdfSBcXApcIFxcClxhbHBoYV9aICZcc2ltIFxvcGVyYXRvcm5hbWV7TG9naXN0aWN9KC0xLjUsIDAuNSkgJiBcdGV4dHtbcHJpb3IgcHJvcG9ydGlvbiBvZiByb3dzIHdoZXJlIHkgPSAwXX0gXFwKXGFscGhhX1xwaGkgJlxzaW0gXG9wZXJhdG9ybmFtZXtHYW1tYX0gKDAuMDEsIDAuMDEpICYgXHRleHR7W3ByaW9yIEJldGEgcHJlY2lzaW9uXX0gXFwKXGJldGFfMCAmXHNpbSBcbWF0aGNhbHtOfSAoMCwgMTApICYgXHRleHR7W3ByaW9yIHBvcHVsYXRpb24gaW50ZXJjZXB0XX0gXFwKXGJldGFfMSwgXGJldGFfMiAmXHNpbSBcbWF0aGNhbHtOfSAoMCwgMykgJiBcdGV4dHtbcHJpb3IgcG9wdWxhdGlvbiBlZmZlY3RzXX0gXFwKXHNpZ21hXjJfZSwgXHNpZ21hXjJfdSAmXHNpbSBcb3BlcmF0b3JuYW1le0NhdWNoeX0oMCwgMSkgJiBcdGV4dHtbcHJpb3Igc2QgZm9yIHBvcHVsYXRpb24gYW5kIGNvdW50cnldfSBcXApcIFxcClx0ZXh0e0lQV31fe2ksIHR9ICY9IFxwcm9kXnRfe3QgPSAxfSBcZnJhY3tccGhpKFRfe2l0fSB8IFRfe2ksIHQtMX0sIENfaSl9e1xwaGkoVF97aXR9IHwgVF97aSwgdC0xfSwgRF97aSwgdC0xfSwgQ19pKX0gJiBcdGV4dHtbc3RhYmlsaXplZCB3ZWlnaHRzXX0KXGVuZHthbGlnbmVkfQokJApGb3IgJFxwaGkkLCB3ZSBqdXN0IHVzZSBTdGFuJ3MgZGVmYXVsdCBgR2FtbWEoMC4wMSwgMC4wMSlgLiBIZXJlJ3Mgd2hhdCBhbGwgdGhlc2UgcHJpb3IgZGlzdHJpYnV0aW9ucyBsb29rIGxpa2U6CgpgYGB7ciBoMi1zaG93LXByaW9ycywgZmlnLndpZHRoPTh9CnpfcCA8LSBnZ3Bsb3QoKSArCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbG9naXMsIGFyZ3MgPSBsaXN0KGxvY2F0aW9uID0gLTEuNSwgc2NhbGUgPSAwLjUpLAogICAgICAgICAgICAgICAgZ2VvbSA9ICJhcmVhIiwgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHggPSBUZVgoIlxcdGV4dGJme1Byb3AuIGNvbnRlbnRpb3VzID0gMCAozrFfWil9IikpICsKICBhbm5vdGF0ZShnZW9tID0gImxhYmVsIiwgeCA9IC0yLCB5ID0gMC4wNywgbGFiZWwgPSAiTG9naXN0aWMoLTEuNSwgMC41KSIsIHNpemUgPSBwdHMoOSkpICsKICB4bGltKC04LCAzKSArCiAgdGhlbWVfZG9ub3JzKHByaW9yID0gVFJVRSkKCmIwX3AgPC0gZ2dwbG90KCkgKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBsaXN0KG1lYW4gPSAwLCBzZCA9IDEwKSwKICAgICAgICAgICAgICAgIGdlb20gPSAiYXJlYSIsIGZpbGwgPSAiZ3JleTgwIiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh4ID0gVGVYKCJcXHRleHRiZntQb3B1bGF0aW9uIGludGVyY2VwdCAozrJfMCl9IikpICsKICBhbm5vdGF0ZShnZW9tID0gImxhYmVsIiwgeCA9IDAsIHkgPSAwLjAwNDIsIGxhYmVsID0gIk4oMCwgMTApIiwgc2l6ZSA9IHB0cyg5KSkgKwogIHhsaW0oLTQwLCA0MCkgKwogIHRoZW1lX2Rvbm9ycyhwcmlvciA9IFRSVUUpCgpiMTJfcCA8LSBnZ3Bsb3QoKSArCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgYXJncyA9IGxpc3QobWVhbiA9IDAsIHNkID0gMyksCiAgICAgICAgICAgICAgICBnZW9tID0gImFyZWEiLCBmaWxsID0gImdyZXk4MCIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnMoeCA9IFRlWCgiXFx0ZXh0YmZ7UG9wdWxhdGlvbiBlZmZlY3RzICjOsl8xLCDOsl8yKX0iKSkgKwogIGFubm90YXRlKGdlb20gPSAibGFiZWwiLCB4ID0gMCwgeSA9IDAuMDIsIGxhYmVsID0gIk4oMCwgMykiLCBzaXplID0gcHRzKDkpKSArCiAgeGxpbSgtMTAsIDEwKSArCiAgdGhlbWVfZG9ub3JzKHByaW9yID0gVFJVRSkKCnNpZ21hX3AgPC0gZ2dwbG90KCkgKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZGNhdWNoeSwgYXJncyA9IGxpc3QobG9jYXRpb24gPSAwLCBzY2FsZSA9IDEpLAogICAgICAgICAgICAgICAgZ2VvbSA9ICJhcmVhIiwgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHggPSBUZVgoIlxcdGV4dGJme1BvcHVsYXRpb24gYW5kIGNvdW50cnkgU0QgKM+DX2UsIM+DX3UpfSIpKSArCiAgYW5ub3RhdGUoZ2VvbSA9ICJsYWJlbCIsIHggPSA1LCB5ID0gMC4wNCwgbGFiZWwgPSAiQ2F1Y2h5KDAsIDEpIiwgc2l6ZSA9IHB0cyg5KSkgKwogIHhsaW0oMCwgMTApICsKICB0aGVtZV9kb25vcnMocHJpb3IgPSBUUlVFKQoKcGhpX3AgPC0gZ2dwbG90KCkgKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZGdhbW1hLCBhcmdzID0gbGlzdChzaGFwZSA9IDAuMSwgc2NhbGUgPSAwLjEpLAogICAgICAgICAgICAgICAgZ2VvbSA9ICJhcmVhIiwgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHggPSBUZVgoIlxcdGV4dGJme0JldGEgcHJlY2lzaW9uICjPhil9IikpICsKICBhbm5vdGF0ZShnZW9tID0gImxhYmVsIiwgeCA9IDAuMjUsIHkgPSAyLCBsYWJlbCA9ICJHYW1tYSgwLjAxLCAwLjAxKSIsIHNpemUgPSBwdHMoOSkpICsKICB4bGltKDAsIDAuNSkgKwogIHRoZW1lX2Rvbm9ycyhwcmlvciA9IFRSVUUpCgpsYXlvdXQgPC0gIgpBQUFBQkJCQkNDQ0MKQUFBQUJCQkJDQ0NDCiMjREREREVFRUUjIwojI0RERERFRUVFIyMKIgp6X3AgKyBzaWdtYV9wICsgcGhpX3AgKyBiMF9wICsgYjEyX3AgKwogIHBsb3RfbGF5b3V0KGRlc2lnbiA9IGxheW91dCkKYGBgCgpBcyB3aXRoIEh+MX4sIHRoZSBwcmlvciBmb3IgdGhlIHplcm8taW5mbGF0ZWQgcGFydCBvZiB0aGUgbW9kZWwgaXMgYSBsaXR0bGUgd2VpcmQuIEludGVybmFsbHksIFN0YW4gdXNlcyBhIGRlZmF1bHQgb2YgYGxvZ2lzdGljKDAsIDEpYC4gV2Ugd2FudCB0byB1c2UgYW4gaW5mb3JtYXRpdmUgYGJldGEoMS44LCA4LDEpYCBwcmlvciB0aGF0IGFwcHJveGltYXRlcyB0aGUgcHJvcG9ydGlvbiBvZiB6ZXJvZXMgaW4gdGhlIGRhdGEgKGJ1dCB3aXRoIGZhaXJseSB3aWRlIGRpc3BlcnNpb24pLCBidXQgd2Ugb25jZSBhZ2FpbiBuZWVkIHRvIHRyYW5zbGF0ZSBpdCBpbnRvIHRoZSBsb2dpc3RpYyBkaXN0cmlidXRpb24uIFNpbmNlIHRoZXJlJ3Mgbm8gZWFzeSB3YXkgdG8gZG8gdGhpcywgd2UgdXNlZCBgYnJtczo6bG9naXRfc2NhbGVkYCB0byBwbGF5IGFyb3VuZCB3aXRoIGRpc3RyaWJ1dGlvbmFsIGh5cGVycGFyYW1ldGVycyB1bnRpbCBpdCBsb29rZWQgb2theSBpbiB0aGUgbG9naXN0aWMgZGlzdHJpYnV0aW9uLgoKYGBge3IgemktcHJpb3Itd2VpcmRuZXNzfQp6aV9wcmlvcl9zaW0gPC0gdGliYmxlKGJldGEgPSByYmV0YSgxMDAwMCwgMS44LCA4LjEpKSAlPiUgCiAgbXV0YXRlKGJldGFfbG9naXRfc2NhbGUgPSBicm1zOjpsb2dpdF9zY2FsZWQoYmV0YSkpICU+JSAKICBtdXRhdGUobG9naXRfYmV0YWlzaF9wcmlvciA9IHJsb2dpcygxMDAwMCwgLTEuNSwgMC41KSkgJT4lIAogIG11dGF0ZShwcmlvcl9wcm9icyA9IHBsb2dpcyhsb2dpdF9iZXRhaXNoX3ByaW9yKSkKCnppX3ByaW9yX3Bsb3QxIDwtIGdncGxvdCh6aV9wcmlvcl9zaW0pICsKICBnZW9tX2RlbnNpdHkoYWVzKHggPSBiZXRhKSwgZmlsbCA9ICJncmV5ODAiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHggPSAiUHJvcG9ydGlvbiB3aGVyZSBwcm9wLiBjb250ZW50aW91cyA9IDAiLAogICAgICAgc3VidGl0bGUgPSAiT3JpZ2luYWwgQmV0YSgxLjgsIDguMSkgZGlzdHJpYnV0aW9uIikgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAxKSkgKwogIHRoZW1lX2Rvbm9ycyhwcmlvciA9IFRSVUUpCgp6aV9wcmlvcl9wbG90MiA8LSBnZ3Bsb3QoemlfcHJpb3Jfc2ltKSArCiAgZ2VvbV9kZW5zaXR5KGFlcyh4ID0gYmV0YV9sb2dpdF9zY2FsZSksIGZpbGwgPSAiZ3JleTgwIiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh4ID0gIkxvZ2lzdGljIHZhbHVlIHdoZXJlIHByb3AuIGNvbnRlbnRpb3VzID0gMCIsCiAgICAgICBzdWJ0aXRsZSA9ICJCZXRhKDEuOCwgOC4xKSBzY2FsZWQgd2l0aCBicm1zOjpsb2dpdF9zY2FsZWQiKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKC04LCAxKSkgKwogIHRoZW1lX2Rvbm9ycyhwcmlvciA9IFRSVUUpCgp6aV9wcmlvcl9wbG90MyA8LSBnZ3Bsb3QoemlfcHJpb3Jfc2ltKSArCiAgZ2VvbV9kZW5zaXR5KGFlcyh4ID0gbG9naXRfYmV0YWlzaF9wcmlvciksIGZpbGwgPSAiZ3JleTgwIiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh4ID0gIkxvZ2lzdGljIHZhbHVlIHdoZXJlIHByb3AuIGNvbnRlbnRpb3VzID0gMCIsCiAgICAgICBzdWJ0aXRsZSA9ICJFc3RpbWF0ZWQgTG9naXN0aWMoLTEuNSwgMC41KSIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTgsIDEpKSArCiAgdGhlbWVfZG9ub3JzKHByaW9yID0gVFJVRSkKCnppX3ByaW9yX3Bsb3Q0IDwtIGdncGxvdCh6aV9wcmlvcl9zaW0pICsKICBnZW9tX2RlbnNpdHkoYWVzKHggPSBwcmlvcl9wcm9icyksIGZpbGwgPSAiZ3JleTgwIiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh4ID0gIlByb3BvcnRpb24gd2hlcmUgcHJvcC4gY29udGVudGlvdXMgPSAwIiwKICAgICAgIHN1YnRpdGxlID0gIkxvZ2lzdGljKC0xLjUsIDAuNSkgdHJhbnNmb3JtZWQgdG8gcHJvYmFiaWxpdGllcyIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMSkpICsKICB0aGVtZV9kb25vcnMocHJpb3IgPSBUUlVFKQoKKHppX3ByaW9yX3Bsb3QxICsgemlfcHJpb3JfcGxvdDIpIC8gKHppX3ByaW9yX3Bsb3QzICsgemlfcHJpb3JfcGxvdDQpCmBgYAoKCiMjIyBSdW4gb3V0Y29tZSBtb2RlbHMKCk91dGNvbWUgbW9kZWwgdGltZSEKCmBgYHtyIGgyLW91dGNvbWUtbW9kZWxzLCByZXN1bHRzPSJoaWRlIiwgbWVzc2FnZT1GQUxTRX0KIyBPdXRjb21lIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgRm9ybXVsYXMKIyBUcmVhdG1lbnQgfiBsYWcgdHJlYXRtZW50ICsgbm9uLXZhcnlpbmcgY29uZm91bmRlcnMKZm9ybXVsYV9oMl9vdXRfdG90YWwgPC0gYmYocHJvcF9jb250ZW50aW91c19sZWFkMSB8IHdlaWdodHMoaXB3KSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcnJpZXJzX3RvdGFsICsgKDEgfCBnd2NvZGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICB6aSB+IDEpCmZvcm11bGFfaDJfb3V0X2Fkdm9jYWN5IDwtIGJmKHByb3BfY29udGVudGlvdXNfbGVhZDEgfCB3ZWlnaHRzKGlwdykgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZHZvY2FjeSArICgxIHwgZ3djb2RlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgemkgfiAxKQpmb3JtdWxhX2gyX291dF9lbnRyeSA8LSBiZihwcm9wX2NvbnRlbnRpb3VzX2xlYWQxIHwgd2VpZ2h0cyhpcHcpIH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW50cnkgKyAoMSB8IGd3Y29kZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHppIH4gMSkKZm9ybXVsYV9oMl9vdXRfZnVuZGluZyA8LSBiZihwcm9wX2NvbnRlbnRpb3VzX2xlYWQxIHwgd2VpZ2h0cyhpcHcpIH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5kaW5nICsgKDEgfCBnd2NvZGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHppIH4gMSkKCiMgUHJpb3JzCnByaW9yX291dCA8LSBjKHNldF9wcmlvcigibm9ybWFsKDAsIDEwKSIsIGNsYXNzID0gIkludGVyY2VwdCIpLAogICAgICAgICAgICAgICBzZXRfcHJpb3IoIm5vcm1hbCgwLCAzKSIsIGNsYXNzID0gImIiKSwKICAgICAgICAgICAgICAgc2V0X3ByaW9yKCJjYXVjaHkoMCwgMSkiLCBjbGFzcyA9ICJzZCIpLAogICAgICAgICAgICAgICBzZXRfcHJpb3IoImxvZ2lzdGljKC0xLjUsIDAuNSkiLCBjbGFzcyA9ICJJbnRlcmNlcHQiLCBkcGFyID0gInppIiksCiAgICAgICAgICAgICAgIHNldF9wcmlvcigiZ2FtbWEoMC4wMSwgMC4wMSkiLCBjbGFzcyA9ICJwaGkiKSkKCiMgUnVuIG91dGNvbWUgbW9kZWxzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp0aWMoKQpmaXRfaDJfb3V0Y29tZXMgPC0gZml0X2gyX2lwdyAlPiUKICBtdXRhdGUoZm9ybXVsYV9vdXRjb21lID0gCiAgICAgICAgICAgbGlzdChmb3JtdWxhX2gyX291dF90b3RhbCwgZm9ybXVsYV9oMl9vdXRfYWR2b2NhY3ksIAogICAgICAgICAgICAgICAgZm9ybXVsYV9oMl9vdXRfZW50cnksIGZvcm11bGFfaDJfb3V0X2Z1bmRpbmcpKSAlPiUgCiAgbXV0YXRlKGZpdF9vdXRjb21lID0gCiAgICAgICAgICAgcG1hcChsaXN0KGZvcm11bGFfb3V0Y29tZSwgZGZfd2l0aF93ZWlnaHRzLCBtb2RlbF9uYW1lKSwKICAgICAgICAgICAgICAgIH5icm0oCiAgICAgICAgICAgICAgICAgIC4uMSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IC4uMiwKICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvcl9vdXQsCiAgICAgICAgICAgICAgICAgIGZhbWlseSA9IHplcm9faW5mbGF0ZWRfYmV0YSgpLAogICAgICAgICAgICAgICAgICBpdGVyID0gSVRFUiAqIDIsIGNoYWlucyA9IENIQUlOUywgd2FybXVwID0gV0FSTVVQLCBzZWVkID0gQkFZRVNfU0VFRCwKICAgICAgICAgICAgICAgICAgZmlsZSA9IGhlcmUoImFuYWx5c2lzIiwgIm1vZGVsX2NhY2hlIiwgcGFzdGUwKC4uMywgIl9vdXRjb21lLnJkcyIpKQogICAgICAgICAgICAgICAgKSkpCmZpdF9oMl9vdXRjb21lcwp0b2MoKQpgYGAKCiMjIyBDaGVjayBvdXRjb21lIG1vZGVscwoKYGBge3IgaDItY2hlY2stb3V0Y29tZX0KY2hlY2tfdG90YWxfb3V0Y29tZSA8LSBmaXRfaDJfb3V0Y29tZXMgJT4lIAogIGZpbHRlcihtb2RlbF9uYW1lID09ICJoMl90b3RhbCIpICU+JSBwdWxsKGZpdF9vdXRjb21lKSAlPiUgZmlyc3QoKQoKcHBfY2hlY2soY2hlY2tfdG90YWxfb3V0Y29tZSwgdHlwZSA9ICJkZW5zX292ZXJsYXkiLCBuc2FtcGxlcyA9IDEwKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICB0aGVtZV9kb25vcnMoKQoKY2hlY2tfdG90YWxfb3V0Y29tZSAlPiUgCiAgcG9zdGVyaW9yX3NhbXBsZXMoYWRkX2NoYWluID0gVFJVRSkgJT4lIAogIHNlbGVjdCgtc3RhcnRzX3dpdGgoInJfZ3djb2RlIiksIC1zdGFydHNfd2l0aCgiel8iKSwgLWxwX18sIC1pdGVyKSAlPiUgCiAgbWNtY190cmFjZSgpICsKICB0aGVtZV9kb25vcnMoKQpgYGAKCiMjIyBSZXN1bHRzCgpgYGB7ciBoMi1wbG90cywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NSwgZmlnLmFzcD1OVUxMfQojIFBsb3RzIQpwbG90X3RvdGFsIDwtIGZpdF9oMl9vdXRjb21lcyAlPiUgCiAgZmlsdGVyKG1vZGVsX25hbWUgPT0gImgyX3RvdGFsIikgJT4lIAogIHB1bGwoZml0X291dGNvbWUpICU+JSBudGgoMSkgJT4lIAogIGdhdGhlcl9kcmF3cyhiX2JhcnJpZXJzX3RvdGFsKSAlPiUKICBtdXRhdGUoLnZhbHVlID0gZXhwKC52YWx1ZSkgLSAxKSAlPiUgCiAgbXV0YXRlKC52YXJpYWJsZSA9IGRwbHlyOjpyZWNvZGUoLnZhcmlhYmxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiX2JhcnJpZXJzX3RvdGFsID0gIkFkZGl0aW9uYWwgbGF3LCB0IC0gMSIpKSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gZmN0X3JldigudmFyaWFibGUpLCB4ID0gLnZhbHVlLCBmaWxsID0gZmN0X3JldigudmFyaWFibGUpKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsKICBzdGF0X2hhbGZleWUoLndpZHRoID0gYygwLjgsIDAuOTUpLCBhbHBoYSA9IDAuOCkgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNGRjg1MUIiLCAiI0ZGREMwMCIpKSArCiAgbGFicyh5ID0gTlVMTCwgeCA9IE5VTEwpICsKICB0aGVtZV9kb25vcnMoKQoKcGxvdF9hZHZvY2FjeSA8LSBmaXRfaDJfb3V0Y29tZXMgJT4lIAogIGZpbHRlcihtb2RlbF9uYW1lID09ICJoMl9hZHZvY2FjeSIpICU+JSAKICBwdWxsKGZpdF9vdXRjb21lKSAlPiUgbnRoKDEpICU+JSAKICBnYXRoZXJfZHJhd3MoYl9hZHZvY2FjeSkgJT4lIAogIG11dGF0ZSgudmFyaWFibGUgPSBkcGx5cjo6cmVjb2RlKC52YXJpYWJsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYl9hZHZvY2FjeSA9ICJBZGRpdGlvbmFsIGFkdm9jYWN5IGxhdywgdCAtIDEiKSkgJT4lIAogIG11dGF0ZSgudmFsdWUgPSBleHAoLnZhbHVlKSAtIDEpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBmY3RfcmV2KC52YXJpYWJsZSksIHggPSAudmFsdWUsIGZpbGwgPSBmY3RfcmV2KC52YXJpYWJsZSkpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkgKwogIHN0YXRfaGFsZmV5ZSgud2lkdGggPSBjKDAuOCwgMC45NSksIGFscGhhID0gMC44KSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzg1MTQ0YiIsICIjRjAxMkJFIikpICsKICBsYWJzKHkgPSBOVUxMLCB4ID0gTlVMTCkgKwogIHRoZW1lX2Rvbm9ycygpCgpwbG90X2VudHJ5IDwtIGZpdF9oMl9vdXRjb21lcyAlPiUgCiAgZmlsdGVyKG1vZGVsX25hbWUgPT0gImgyX2VudHJ5IikgJT4lIAogIHB1bGwoZml0X291dGNvbWUpICU+JSBudGgoMSkgJT4lIAogIGdhdGhlcl9kcmF3cyhiX2VudHJ5KSAlPiUgCiAgbXV0YXRlKC52YXJpYWJsZSA9IGRwbHlyOjpyZWNvZGUoLnZhcmlhYmxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiX2VudHJ5ID0gIkFkZGl0aW9uYWwgZW50cnkgbGF3LCB0IC0gMSIpKSAlPiUgCiAgbXV0YXRlKC52YWx1ZSA9IGV4cCgudmFsdWUpIC0gMSkgJT4lIAogIGdncGxvdChhZXMoeSA9IGZjdF9yZXYoLnZhcmlhYmxlKSwgeCA9IC52YWx1ZSwgZmlsbCA9IGZjdF9yZXYoLnZhcmlhYmxlKSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArCiAgc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC44LCAwLjk1KSwgYWxwaGEgPSAwLjgpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjM0Q5OTcwIiwgIiMyRUNDNDAiKSkgKwogIGxhYnMoeSA9IE5VTEwsIHggPSAiJSBjaGFuZ2UgaW4gcHJvcG9ydGlvbiBvZiBjb250ZW50aW91cyBhaWQiKSArCiAgdGhlbWVfZG9ub3JzKCkKCnBsb3RfZnVuZGluZyA8LSBmaXRfaDJfb3V0Y29tZXMgJT4lIAogIGZpbHRlcihtb2RlbF9uYW1lID09ICJoMl9mdW5kaW5nIikgJT4lIAogIHB1bGwoZml0X291dGNvbWUpICU+JSBudGgoMSkgJT4lIAogIGdhdGhlcl9kcmF3cyhiX2Z1bmRpbmcpICU+JSAKICBtdXRhdGUoLnZhcmlhYmxlID0gZHBseXI6OnJlY29kZSgudmFyaWFibGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJfZnVuZGluZyA9ICJBZGRpdGlvbmFsIGZ1bmRpbmcgbGF3LCB0IC0gMSIpKSAlPiUgCiAgbXV0YXRlKC52YWx1ZSA9IGV4cCgudmFsdWUpIC0gMSkgJT4lIAogIGdncGxvdChhZXMoeSA9IGZjdF9yZXYoLnZhcmlhYmxlKSwgeCA9IC52YWx1ZSwgZmlsbCA9IGZjdF9yZXYoLnZhcmlhYmxlKSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArCiAgc3RhdF9oYWxmZXllKC53aWR0aCA9IGMoMC44LCAwLjk1KSwgYWxwaGEgPSAwLjgpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDAxZjNmIiwgIiMwMDc0RDkiKSkgKwogIGxhYnMoeSA9IE5VTEwsIHggPSAiJSBjaGFuZ2UgaW4gcHJvcG9ydGlvbiBvZiBjb250ZW50aW91cyBhaWQiKSArCiAgdGhlbWVfZG9ub3JzKCkKCihwbG90X3RvdGFsICsgcGxvdF9hZHZvY2FjeSkgLyAocGxvdF9lbnRyeSArIHBsb3RfZnVuZGluZykKYGBgCgpBIG9uZS11bml0IGNoYW5nZSBpbiBYIHJlc3VsdHMgaW4gYSByZWxhdGl2ZSBjaGFuZ2Ugb2YgJGVeXGJldGEkIGluICRcZnJhY3tcdGV4dHtFKFByb3BvcnRpb24pfX17MSAtIFx0ZXh0e0UoUHJvcG9ydGlvbil9fSQgLSBzZWUgPGh0dHBzOi8vc3RhdHMuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzI5NzY1OS9pbnRlcnByZXRhdGlvbi1vZi1iZXRhcmVnLWNvZWY+IC0gdGhlIHJhdGlvIG9mIGNvbnRlbnRpb3VzIHRvIG5vbi1jb250ZW50aW91cyBhaWQ/IHRoZSByYXRpbyBvZiBvZiBjb250ZW50aW91cyBhaWQ/CgpTZWUgYWxzbyA8aHR0cHM6Ly9zdGF0cy5zdGFja2V4Y2hhbmdlLmNvbS9hLzIzMDY3OS8zMDI1PiBhbmQgPGh0dHBzOi8vc3RhdGljMS5zcXVhcmVzcGFjZS5jb20vc3RhdGljLzU4YTdkMWU1Mjk5NGNhMzk4Njk3YTYyMS90LzVhMmViYzQzZTQ5NjZiMGZhYjZiMDJkZS8xNTEzMDEyMjkzODU3L2JldGFyZWdfcG9saXRpY3MucGRmPgoKYGBge3IgaDItY29uZGl0aW9uYWwtZWZmZWN0c30KZml0X2gyX291dGNvbWVzICU+JSAKICBmaWx0ZXIobW9kZWxfbmFtZSA9PSAiaDJfdG90YWwiKSAlPiUgCiAgcHVsbChmaXRfb3V0Y29tZSkgJT4lIG50aCgxKSAlPiUgCiAgY29uZGl0aW9uYWxfZWZmZWN0cygpCgpmaXRfaDJfb3V0Y29tZXMgJT4lIAogIGZpbHRlcihtb2RlbF9uYW1lID09ICJoMl9hZHZvY2FjeSIpICU+JSAKICBwdWxsKGZpdF9vdXRjb21lKSAlPiUgbnRoKDEpICU+JSAKICBjb25kaXRpb25hbF9lZmZlY3RzKCkKCmZpdF9oMl9vdXRjb21lcyAlPiUgCiAgZmlsdGVyKG1vZGVsX25hbWUgPT0gImgyX2VudHJ5IikgJT4lIAogIHB1bGwoZml0X291dGNvbWUpICU+JSBudGgoMSkgJT4lIAogIGNvbmRpdGlvbmFsX2VmZmVjdHMoKQoKZml0X2gyX291dGNvbWVzICU+JSAKICBmaWx0ZXIobW9kZWxfbmFtZSA9PSAiaDJfZnVuZGluZyIpICU+JSAKICBwdWxsKGZpdF9vdXRjb21lKSAlPiUgbnRoKDEpICU+JSAKICBjb25kaXRpb25hbF9lZmZlY3RzKCkKYGBgCg==