Tables

Table 1: Market Share of the Ease of Doing Business Index

Results generated from Harvard Berkman Center, “Media Cloud Database,” 2017.

Not generated with this script.

Table 2: Overview of De Jure Reform Measures

Not generated with this script.

Table 3: Summary of Coefficients for 8 OLS Models

Important: All models only use countries included in the original 2001 report.

These difference models use the lag of the outcome variable and a year indicator variable to determine the change in outcome variable.

Formally, this is defined as:

\[ y_t = \beta_0 + \beta_1 y_{t-1} + \beta_2 X + \epsilon \]

  • t = Year
  • X = {1 if t = cutpoint year, 0 otherwise}
  • β0 = Constant
  • β1 = Change in outcome from the previous year
  • β2 = Effect of the event

Or an example R formula:

sb_proced ~ sb_proced_lag + ranked_2005
# Define all the models that need to be run
# For the paper we just do 2005 and 2006 for all countries. In the appendix we
# run models from 2003-2013 for all countries, countries with EDB committees,
# and countries without EDB committees
models_to_run <- expand.grid(year = 2005:2006,
                             outcome = c("sb_proced", "sb_days_ln",
                                         "sb_cost_ln", "sb_capital_ln"),
                             grouping = "All countries",
                             stringsAsFactors = FALSE)

# This function generates an R model formula based on the name of the dependent
# variable and the year provided. i.e., given "sb_proced" and "2005", it will
# create the formula "sb_proced ~ sb_proced_lag + ranked_2005" and run the model
run_lagged_ols_model <- function(outcome, year, df) {
  outcome_lag <- paste0(outcome, "_lag")
  year_variable <- paste0("ranked_", year)

  form <- as.formula(paste0(outcome, " ~ ", outcome_lag, " + ", year_variable))

  lm(form, data = df)
}

# Run models only on countries that were included in the 2001 report
models_to_run_full <- edb_clean %>%
  filter(in_2001 == 1) %>%
  # Add grouping column so this can be joined with models_to_run
  mutate(grouping = "All countries") %>%
  group_by(grouping) %>%
  nest() %>%
  right_join(models_to_run, by = "grouping")

# Run all the models within the data frame
ols_models_lagged <- models_to_run_full %>%
  mutate(model = pmap(.l = list(outcome, year, data), run_lagged_ols_model),
         # Add robust clustered SEs
         robust_se = pmap(.l = list(model, data, "ccode"), robust_clusterify),
         # Add model summary statistics
         glance = model %>% map(broom::glance),
         # Add a data frame of model parameters with correct SEs
         tidy_robust = robust_se %>% map(~ broom::tidy(.$coef)))

# Extract the ranking coefficients from all models
ols_coefs <- ols_models_lagged %>%
  # Spread out the model results
  unnest(tidy_robust) %>%
  # Only look at the ranked* coefficients
  filter(str_detect(term, "ranked")) %>%
  # Clean up the estimates, labels, and add stars
  mutate(value = paste0(sprintf("%.3f", round(estimate, 3)), p_stars(p.value)),
         term = str_replace(term, "\\.\\d+TRUE", "")) %>%
  # Get rid of extra columns
  select(-c(estimate, std.error, statistic, p.value)) %>%
  spread(outcome, value) %>%
  # Give table clean column names
  select(Subset = grouping, Year = year,
         Procedures = sb_proced, `Cost (log)` = sb_cost_ln,
         `Days (log)` = sb_days_ln, `Capital (log)` = sb_capital_ln)
Summary of β2 coefficients (i.e. “ranked_200x”) for difference models
Subset Year Procedures Cost (log) Days (log) Capital (log)
All countries 2005 -0.176** -0.081*** -0.040* -0.030
All countries 2006 -0.240*** -0.071*** -0.049** -0.097*

Table 4: Summary of Coefficients for 8 ITS Models

These interrupted times series models use an interaction term of the years since an intervention and the intervention itself to determine the change in slope after the intervention.

\[ y_t = \beta_0 + \beta_1 T + \beta_2 X_t + \beta_3 (T \times X_t) + \epsilon \]

  • t = Year
  • T = Years before/after cutpoint
  • X = {1 if t = cutpoint year, 0 otherwise}
  • β0 = Constant: pre-period intercept - baseline pre intervention
  • β1 = pre-period slope - baseline time trend - level of increase prior to intervention
  • β2 = immediate effect of the event - change in intercept at point of experiment
  • β3 = change in slope after the experiment - what happens after

Or an example R formula:

sb_proced ~ year_centered_2005 + ranked_2005 + year_centered_2005 * ranked_2005
# As with run_lagged_ols_model(), this function generates an R model formula and
# runs it. i.e., given "sb_proced" and "2005", it will create the formula
# "sb_proced ~ year_centered_2005 + ranked_2005 + year_centered_2005 * ranked_2005" 
# and run the model
run_its_model <- function(outcome, year, df) {
  year_variable <- paste0("ranked_", year)
  year_centered <- paste0("year_centered_", year)
  
  form <- as.formula(paste0(outcome, " ~ ", year_centered, " + ", year_variable,
                            " + ", year_centered, " * ", year_variable))
  
  lm(form, data = df)
}

# Run all the ITS models within the data frame
its_models <- models_to_run_full %>%
  mutate(model = pmap(.l = list(outcome, year, data), run_its_model),
         robust_se = pmap(.l = list(model, data, "ccode"), robust_clusterify),
         glance = model %>% map(broom::glance),
         tidy_robust = robust_se %>% map(~ broom::tidy(.$coef)))

# Extract the ranking coefficients from ITS models
its_coefs <- its_models %>%
  # Spread out the model results
  unnest(tidy_robust) %>%
  # Only look at the coefficients from interaction terms (they have ":" in their names)
  filter(str_detect(term, ":")) %>%
  # Clean up the estimates, labels, and add stars
  mutate(value = paste0(sprintf("%.3f", round(estimate, 3)), p_stars(p.value)),
         term = str_replace(term, "\\.\\d+TRUE", "")) %>%
  # Get rid of extra columns
  select(-c(estimate, std.error, statistic, p.value)) %>%
  spread(outcome, value) %>%
  # Give table clean column names
  select(Subset = grouping, Year = year,
         Procedures = sb_proced, `Cost (log)` = sb_cost_ln,
         `Days (log)` = sb_days_ln, `Capital (log)` = sb_capital_ln)
Summary of β3 coefficients (i.e. “year.centered.200x × ranked.200x”)
Subset Year Procedures Cost (log) Days (log) Capital (log)
All countries 2005 -0.088 -0.059** 0.009 0.054
All countries 2006 -0.105 -0.041** 0.008 -0.019

Table 5: Countries with Reform Committees Directly Using the EDB Data

Not generated with this script.

Table 6: Experimental Results Status Comparisons on Importance of EBD and Business Climate Improvements

Not generated with this script.

Table 7: Experimental Results of Ranking Differences on Investment Likelihood

Not generated with this script.


Figures

Figure 2: Average change in select subindicators, before and after public ranking (2006)

df_plot_edb_2001 <- edb_clean %>%
  # Only look at countries in the 2001 report
  filter(in_2001 == 1) %>%
  select(year, sb_days, sb_proced, sb_cost, sb_capital, con_days, con_proced) %>%
  # Calculate average of each variable by year
  gather(variable, value, -year) %>%
  group_by(year, variable) %>%
  summarise(avg = mean(value, na.rm = TRUE)) %>%
  filter(!is.nan(avg)) %>%
  # Only use 2004 and beyond
  filter(year >= 2003) %>%
  mutate(variable = fct_recode(variable,
                               `Contract—Days` = "con_days",
                               `Contract—Procedures` = "con_proced",
                               `Starting a business—Capital` = "sb_capital",
                               `Starting a business—Cost` = "sb_cost",
                               `Starting a business—Days` = "sb_days",
                               `Starting a business—Procedures` = "sb_proced"))

# Mark the intervention years
plot_interventions <- data_frame(year = 2005:2006,
                                 intervention = c("2005", "2006"))

# Technically, facets in gpplot are for different aspects of the same value, not
# for separate variables. This function creates a miniature ggplot object which
# then gets combined below with gridExtra::arrangeGrob()
make_faux_facet <- function(x, ymin, ymax, ylab) {
  plot_data <- df_plot_edb_2001 %>%
    filter(variable == x)
  
  faux_facet <- ggplot() +
    geom_vline(data = plot_interventions, aes(xintercept = year,
                                            colour = intervention),
               linetype = "dashed", size = 0.5) +
    geom_line(data = plot_data, aes(x = year, y = avg)) + 
    scale_color_manual(values = c(its_1, its_2), name = NULL) +
    scale_x_continuous(limits = c(2000, 2015), breaks = seq(2000, 2015, 5)) +
    coord_cartesian(xlim = c(2000, 2015), ylim = c(ymin, ymax)) +
    guides(color = FALSE) +
    labs(x = NULL, y = ylab, title = x) +
    theme_edb() + 
    theme(plot.title = element_text(size = rel(1), hjust = 0.5))

  return(faux_facet)
}

# Create a data frame with plotting parameters and then create ggplot objects in a new column
plots_2001 <- tribble(
  ~ymin, ~ymax, ~ylab,        ~variable,
  0,     610,   "Days",       "Contract—Days",
  0,     45,    "Procedures", "Contract—Procedures",
  0,     200,   "Capital",    "Starting a business—Capital",
  0,     100,   "Cost",       "Starting a business—Cost",
  0,     50,    "Days",       "Starting a business—Days",
  0,     10,    "Procedures", "Starting a business—Procedures"
) %>%
  mutate(facet = pmap(.l = list(variable, ymin, ymax, ylab), make_faux_facet))

# Plot all those plots in one big mega plot
plot_edb_2001 <- arrangeGrob(grobs = plots_2001$facet, nrow = 2)
grid::grid.newpage()
grid::grid.draw(plot_edb_2001)

Figure 3: EDB Rankings, 2005 versus 2014, by Committee Status Based on 2015 report

# Select only 2005 and 2014 rankings
edb_rankings <- edb_clean %>%
  select(ccode, year, p_edb_rank, has_bureau) %>%
  filter(year %in% c(2005, 2014)) %>%
  spread(year, p_edb_rank) %>%
  mutate(countryname = countrycode(ccode, "cown", "country.name"),
         countryname = ifelse(countryname == "Lao People's Democratic Republic", 
                              "Laos", countryname),
         add_label = countryname %in% c("Georgia", "Rwanda", 
                                        "Bangladesh", "Nigeria", "Pakistan",
                                        "Norway", "New Zealand",
                                        "Laos", "Niger"),
         label = ifelse(add_label, countryname, NA))

# Extra stuff that will go on the plot
annotations <- data_frame(x = c(max(edb_rankings$`2005`, na.rm = TRUE), 0),
                          y = c(0, max(edb_rankings$`2014`, na.rm = TRUE)),
                          text = c("Outliers\nimproving", "Outliers\nworsening"),
                          hjust = c("right", "left"),
                          vjust = c("bottom", "top"))

reference_line <- data_frame(x = c(0, max(edb_rankings$`2005`, na.rm = TRUE)),
                             y = c(0, max(edb_rankings$`2014`, na.rm = TRUE)))

# Set the seed every time geom_label_repel is called so the labels are repositioned the same way
set.seed(1234)
fig_rankings_corr <- ggplot(edb_rankings, aes(x = `2005`, y = `2014`, 
                                              colour = has_bureau, label = label)) + 
  # geom_smooth(aes(fill = has_bureau), method = "lm", size = 0.5, alpha = 0.1, fullrange = TRUE) +
  geom_line(data = reference_line, aes(x = x, y = y, label = NULL), colour = "grey70", size = 0.5) +
  geom_point(size = 1) +
  geom_label_repel(aes(fill = has_bureau), colour = "white", 
                   size = 2, alpha = 0.9, segment.color = "grey40") +
  geom_text(data = annotations, aes(x = x, y = y, label = text, hjust = hjust, vjust = vjust),
            colour = "grey40", size = 2, lineheight = 1) +
  scale_color_manual(values = c(color_no_committee, color_committee), name = NULL) +
  scale_fill_manual(values = c(color_no_committee, color_committee), name = NULL, guide = FALSE) +
  coord_cartesian(xlim = c(0, 160), ylim = c(0, 190)) +
  labs(x = "Rank in 2005", y = "Rank in 2014") +
  theme_edb()

set.seed(1234)
fig_rankings_corr

Figure 4: Ranking Gains by Number of Reforms, by Committee Status (95% CI)

Every reform leads to a negative change in rankings (which is good) in the following year for countries with special EDB reform committees. For instance, doing an enforcing contracts reform will move a country down (i.e. to a better position) nearly 6 positions. This is also the case when normalizing rankings to a 0-100 scale to account for the changing number of rank positions over time.

# Add new columns for leaded rankings and changes in rankings
change_in_rankings_norm <- edb_clean %>%
  select(ccode, country_name, year, p_edb_rank, p_edb_rank_normalized, has_bureau) %>%
  mutate(rank0 = p_edb_rank,
         rank1 = lead(rank0, 1),
         rank2 = lead(rank0, 2),
         change1 = rank1 - rank0,
         change2 = rank2 - rank0,
         rank0_norm = p_edb_rank_normalized,
         rank1_norm = lead(rank0_norm, 1),
         rank2_norm = lead(rank0_norm, 2),
         change1_norm = rank1_norm - rank0_norm,
         change2_norm = rank2_norm - rank0_norm) %>%
  filter(year >= 2005)

# Calculate the changes--or bumps--in rankings per reform undertaken
edb_reforms_rankings_bumps <- edb_reforms %>%
  filter(!str_detect(reform_type, "lag")) %>%
  group_by(ccode, year, reform_type_clean) %>%
  summarise(num_reforms = sum(reform_num_no_na)) %>%
  left_join(change_in_rankings_norm, by = c("ccode", "year")) %>%
  filter(num_reforms != 0) %>%
  mutate(change_per_reform1 = change1 / num_reforms,
         change_per_reform2 = change2 / num_reforms,
         change_per_reform1_norm = change1_norm / num_reforms,
         change_per_reform2_norm = change2_norm / num_reforms) 

# Calculate summary statistics of bumps in rankings
edb_reforms_rankings_bumps_summarized <- edb_reforms_rankings_bumps %>%
  group_by(reform_type_clean, has_bureau) %>%
  summarise(avg_bump_norm = mean(change_per_reform1_norm, na.rm = TRUE),
            stderr_bump_norm = sd(change_per_reform1_norm, na.rm = TRUE) / 
              sqrt(length(change_per_reform1_norm)),
            lower_norm = avg_bump_norm + (qnorm(0.025) * stderr_bump_norm),
            upper_norm = avg_bump_norm + (qnorm(0.975) * stderr_bump_norm),
            avg_bump = mean(change_per_reform1, na.rm = TRUE),
            stderr_bump = sd(change_per_reform1, na.rm = TRUE) / 
              sqrt(length(change_per_reform1)),
            lower = avg_bump + (qnorm(0.025) * stderr_bump),
            upper = avg_bump + (qnorm(0.975) * stderr_bump)) %>%
  ungroup() %>%
  arrange(desc(has_bureau), desc(avg_bump)) %>%
  filter(!is.na(reform_type_clean)) %>%
  mutate(reform_type_clean = factor(reform_type_clean, 
                                    levels = unique(reform_type_clean), 
                                    ordered = TRUE))

t-tests for changes in rankings

Differences in average change in EDB rankings by reform, by committee status
Reform Average change in rankings, committee Average change in rankings, no committee Difference in means t
Enforcing contracts -3.2 -0.38 2.8 2.01*
Getting electricity -2.9 -1.2 1.7 1.47
Construction permits -1.9 -0.43 1.4 2.10**
Paying taxes -1.4 -0.3 1.1 1.88*
Resolving insolvency -1.3 0.14 1.4 2.15**
Protecting minority investors -1.2 -1.8 0.55 -0.58
Registering property -1.2 -0.38 0.84 1.03
Starting a business -1.1 -0.072 1.1 1.86*
Trading across borders -1.1 -0.32 0.74 1.11
Getting credit -1 -0.11 0.92 1.36

*p<0.1; **p<0.05; ***p<0.01

Figure 5: Public Assessments of Importance of Improving India’s Business Climate and EDB Rankings, by Exposure to EDB Information

chn_ind_assessments <- read_csv(file.path(here(), "data_raw", "chn-ind-assessments.csv")) %>%
  rename(Frame = X1) %>%
  gather(key, value, -Frame)

# Split into two data frames for faceting, then recombine
chn_ind_both <- chn_ind_assessments %>%
  filter(key %in% c("India Higher", "No Rank", "China Higher")) %>%
  mutate(comparison = "Both")

ind_only <- chn_ind_assessments %>%
  filter(key %in% c("No Rank", "India's Rank Only")) %>%
  mutate(comparison = "India only")

blank_country <- data_frame(Frame = unique(chn_ind_assessments$Frame),
                            key = " ", value = c(0, 0), 
                            comparison = "India only")

chn_ind_plot_data <- bind_rows(chn_ind_both, ind_only, blank_country) %>%
  mutate(key = factor(key, levels = c("India Higher", "India's Rank Only", 
                                      "No Rank", "China Higher", " "),
                      ordered = TRUE),
         Frame = fct_inorder(Frame, ordered = TRUE))

chn_ind_annotations <- data_frame(x = c(4, 5), y = c(0.6, 0.6),
                                  text = c("Lower importance", "Higher importance"),
                                  hjust = c("left", "right"))

# Plot
plot_chn_ind <- ggplot(chn_ind_plot_data, aes(x = value, y = fct_rev(key), 
                                              color = fct_rev(Frame))) +
  geom_pointrangeh(aes(xmin = 0, xmax = value), size = 0.5,
                   position = position_dodgev(height = 0.5)) +
  geom_text(data = chn_ind_annotations, 
            aes(x = x, y = y, label = text, hjust = hjust),
            vjust = "center", color = "grey40", size = 2, lineheight = 1) +
  geom_text(aes(label = value), position = position_dodgev(height = 0.5),
            hjust = -0.4, size = 2.5) +
  scale_color_manual(values = c(edb_importance, climate_importance), name = NULL,
                     guide = guide_legend(reverse = TRUE)) +
  scale_x_continuous(breaks = seq(0, 5, 0.5)) +
  coord_cartesian(xlim = c(4, 5)) +
  labs(x = NULL, y = NULL) +
  theme_edb() +
  theme(strip.text = element_blank(),
        panel.grid.minor = element_blank(),
        panel.grid.major.y = element_blank()) +
  facet_wrap(~ comparison, scales = "free_y")

plot_chn_ind

LS0tCnRpdGxlOiAiRmlndXJlcyBhbmQgdGFibGVzIGluIHBhcGVyIgphdXRob3I6ICJBbmRyZXcgSGVpc3MiCmRhdGU6ICJMYXN0IHJ1bjogYHIgZm9ybWF0KFN5cy50aW1lKCksICclQiAlZSwgJVknKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgpgYGB7ciBzZXR1cCwgbWVzc2FnZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlID0gRkFMU0UsIGZpZy5yZXRpbmEgPSAyLAogICAgICAgICAgICAgICAgICAgICAgdGlkeS5vcHRzID0gbGlzdCh3aWR0aC5jdXRvZmYgPSAxMjApLCAgIyBGb3IgY29kZQogICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAxMjApICAjIEZvciBvdXRwdXQKYGBgCgpgYGB7ciBsb2FkLWxpYnJhcmllcy1kYXRhLWZ1bmN0aW9ucywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGFuZGVyKQpsaWJyYXJ5KGNvdW50cnljb2RlKQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoZ2dzdGFuY2UpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGhlcmUpCgojIExvYWQgcHJlLWNsZWFuZWQgZGF0YQplZGJfY2xlYW4gPC0gcmVhZF9yZHMoZmlsZS5wYXRoKGhlcmUoKSwgIm91dHB1dCIsICJkYXRhIiwgImVkYl9jbGVhbi5yZHMiKSkKZWRiX3JlZm9ybXMgPC0gcmVhZF9yZHMoZmlsZS5wYXRoKGhlcmUoKSwgIm91dHB1dCIsICJkYXRhIiwgImVkYl9yZWZvcm1zLnJkcyIpKQoKIyBMb2FkIGhlbHBmdWwgZnVuY3Rpb25zCnNvdXJjZShmaWxlLnBhdGgoaGVyZSgpLCAibGliIiwgIm1vZGVsX3N0dWZmLlIiKSkKc291cmNlKGZpbGUucGF0aChoZXJlKCksICJsaWIiLCAiZ3JhcGhpY3Nfc3R1ZmYuUiIpKQpgYGAKCiMgVGFibGVzCgojIyBUYWJsZSAxOiBNYXJrZXQgU2hhcmUgb2YgdGhlIEVhc2Ugb2YgRG9pbmcgQnVzaW5lc3MgSW5kZXgKClJlc3VsdHMgZ2VuZXJhdGVkIGZyb20gSGFydmFyZCBCZXJrbWFuIENlbnRlciwgIk1lZGlhIENsb3VkIERhdGFiYXNlLCIgMjAxNy4KCipOb3QgZ2VuZXJhdGVkIHdpdGggdGhpcyBzY3JpcHQuKgoKCiMjIFRhYmxlIDI6IE92ZXJ2aWV3IG9mIERlIEp1cmUgUmVmb3JtIE1lYXN1cmVzCgoqTm90IGdlbmVyYXRlZCB3aXRoIHRoaXMgc2NyaXB0LioKCgojIyBUYWJsZSAzOiBTdW1tYXJ5IG9mIENvZWZmaWNpZW50cyBmb3IgOCBPTFMgTW9kZWxzCgoqKkltcG9ydGFudCoqOiBBbGwgbW9kZWxzIG9ubHkgdXNlIGNvdW50cmllcyBpbmNsdWRlZCBpbiB0aGUgb3JpZ2luYWwgMjAwMSByZXBvcnQuCgpUaGVzZSBkaWZmZXJlbmNlIG1vZGVscyB1c2UgdGhlIGxhZyBvZiB0aGUgb3V0Y29tZSB2YXJpYWJsZSBhbmQgYSB5ZWFyIGluZGljYXRvciB2YXJpYWJsZSB0byBkZXRlcm1pbmUgdGhlIGNoYW5nZSBpbiBvdXRjb21lIHZhcmlhYmxlLgoKRm9ybWFsbHksIHRoaXMgaXMgZGVmaW5lZCBhczoKCiQkIHlfdCA9IFxiZXRhXzAgKyBcYmV0YV8xIHlfe3QtMX0gKyBcYmV0YV8yIFggKyBcZXBzaWxvbiAkJAoKLSAqdCogPSBZZWFyCi0gKlgqID0gezEgaWYgKnQqID0gY3V0cG9pbnQgeWVhciwgMCBvdGhlcndpc2V9Ci0gzrJ+MH4gPSBDb25zdGFudAotIM6yfjF+ID0gQ2hhbmdlIGluIG91dGNvbWUgZnJvbSB0aGUgcHJldmlvdXMgeWVhcgotIM6yfjJ+ID0gRWZmZWN0IG9mIHRoZSBldmVudAoKT3IgYW4gZXhhbXBsZSBSIGZvcm11bGE6CgogICAgc2JfcHJvY2VkIH4gc2JfcHJvY2VkX2xhZyArIHJhbmtlZF8yMDA1CgoKYGBge3Igb2xzLW1vZGVsc30KIyBEZWZpbmUgYWxsIHRoZSBtb2RlbHMgdGhhdCBuZWVkIHRvIGJlIHJ1bgojIEZvciB0aGUgcGFwZXIgd2UganVzdCBkbyAyMDA1IGFuZCAyMDA2IGZvciBhbGwgY291bnRyaWVzLiBJbiB0aGUgYXBwZW5kaXggd2UKIyBydW4gbW9kZWxzIGZyb20gMjAwMy0yMDEzIGZvciBhbGwgY291bnRyaWVzLCBjb3VudHJpZXMgd2l0aCBFREIgY29tbWl0dGVlcywKIyBhbmQgY291bnRyaWVzIHdpdGhvdXQgRURCIGNvbW1pdHRlZXMKbW9kZWxzX3RvX3J1biA8LSBleHBhbmQuZ3JpZCh5ZWFyID0gMjAwNToyMDA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWUgPSBjKCJzYl9wcm9jZWQiLCAic2JfZGF5c19sbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInNiX2Nvc3RfbG4iLCAic2JfY2FwaXRhbF9sbiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gIkFsbCBjb3VudHJpZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCiMgVGhpcyBmdW5jdGlvbiBnZW5lcmF0ZXMgYW4gUiBtb2RlbCBmb3JtdWxhIGJhc2VkIG9uIHRoZSBuYW1lIG9mIHRoZSBkZXBlbmRlbnQKIyB2YXJpYWJsZSBhbmQgdGhlIHllYXIgcHJvdmlkZWQuIGkuZS4sIGdpdmVuICJzYl9wcm9jZWQiIGFuZCAiMjAwNSIsIGl0IHdpbGwKIyBjcmVhdGUgdGhlIGZvcm11bGEgInNiX3Byb2NlZCB+IHNiX3Byb2NlZF9sYWcgKyByYW5rZWRfMjAwNSIgYW5kIHJ1biB0aGUgbW9kZWwKcnVuX2xhZ2dlZF9vbHNfbW9kZWwgPC0gZnVuY3Rpb24ob3V0Y29tZSwgeWVhciwgZGYpIHsKICBvdXRjb21lX2xhZyA8LSBwYXN0ZTAob3V0Y29tZSwgIl9sYWciKQogIHllYXJfdmFyaWFibGUgPC0gcGFzdGUwKCJyYW5rZWRfIiwgeWVhcikKCiAgZm9ybSA8LSBhcy5mb3JtdWxhKHBhc3RlMChvdXRjb21lLCAiIH4gIiwgb3V0Y29tZV9sYWcsICIgKyAiLCB5ZWFyX3ZhcmlhYmxlKSkKCiAgbG0oZm9ybSwgZGF0YSA9IGRmKQp9CgojIFJ1biBtb2RlbHMgb25seSBvbiBjb3VudHJpZXMgdGhhdCB3ZXJlIGluY2x1ZGVkIGluIHRoZSAyMDAxIHJlcG9ydAptb2RlbHNfdG9fcnVuX2Z1bGwgPC0gZWRiX2NsZWFuICU+JQogIGZpbHRlcihpbl8yMDAxID09IDEpICU+JQogICMgQWRkIGdyb3VwaW5nIGNvbHVtbiBzbyB0aGlzIGNhbiBiZSBqb2luZWQgd2l0aCBtb2RlbHNfdG9fcnVuCiAgbXV0YXRlKGdyb3VwaW5nID0gIkFsbCBjb3VudHJpZXMiKSAlPiUKICBncm91cF9ieShncm91cGluZykgJT4lCiAgbmVzdCgpICU+JQogIHJpZ2h0X2pvaW4obW9kZWxzX3RvX3J1biwgYnkgPSAiZ3JvdXBpbmciKQoKIyBSdW4gYWxsIHRoZSBtb2RlbHMgd2l0aGluIHRoZSBkYXRhIGZyYW1lCm9sc19tb2RlbHNfbGFnZ2VkIDwtIG1vZGVsc190b19ydW5fZnVsbCAlPiUKICBtdXRhdGUobW9kZWwgPSBwbWFwKC5sID0gbGlzdChvdXRjb21lLCB5ZWFyLCBkYXRhKSwgcnVuX2xhZ2dlZF9vbHNfbW9kZWwpLAogICAgICAgICAjIEFkZCByb2J1c3QgY2x1c3RlcmVkIFNFcwogICAgICAgICByb2J1c3Rfc2UgPSBwbWFwKC5sID0gbGlzdChtb2RlbCwgZGF0YSwgImNjb2RlIiksIHJvYnVzdF9jbHVzdGVyaWZ5KSwKICAgICAgICAgIyBBZGQgbW9kZWwgc3VtbWFyeSBzdGF0aXN0aWNzCiAgICAgICAgIGdsYW5jZSA9IG1vZGVsICU+JSBtYXAoYnJvb206OmdsYW5jZSksCiAgICAgICAgICMgQWRkIGEgZGF0YSBmcmFtZSBvZiBtb2RlbCBwYXJhbWV0ZXJzIHdpdGggY29ycmVjdCBTRXMKICAgICAgICAgdGlkeV9yb2J1c3QgPSByb2J1c3Rfc2UgJT4lIG1hcCh+IGJyb29tOjp0aWR5KC4kY29lZikpKQoKIyBFeHRyYWN0IHRoZSByYW5raW5nIGNvZWZmaWNpZW50cyBmcm9tIGFsbCBtb2RlbHMKb2xzX2NvZWZzIDwtIG9sc19tb2RlbHNfbGFnZ2VkICU+JQogICMgU3ByZWFkIG91dCB0aGUgbW9kZWwgcmVzdWx0cwogIHVubmVzdCh0aWR5X3JvYnVzdCkgJT4lCiAgIyBPbmx5IGxvb2sgYXQgdGhlIHJhbmtlZCogY29lZmZpY2llbnRzCiAgZmlsdGVyKHN0cl9kZXRlY3QodGVybSwgInJhbmtlZCIpKSAlPiUKICAjIENsZWFuIHVwIHRoZSBlc3RpbWF0ZXMsIGxhYmVscywgYW5kIGFkZCBzdGFycwogIG11dGF0ZSh2YWx1ZSA9IHBhc3RlMChzcHJpbnRmKCIlLjNmIiwgcm91bmQoZXN0aW1hdGUsIDMpKSwgcF9zdGFycyhwLnZhbHVlKSksCiAgICAgICAgIHRlcm0gPSBzdHJfcmVwbGFjZSh0ZXJtLCAiXFwuXFxkK1RSVUUiLCAiIikpICU+JQogICMgR2V0IHJpZCBvZiBleHRyYSBjb2x1bW5zCiAgc2VsZWN0KC1jKGVzdGltYXRlLCBzdGQuZXJyb3IsIHN0YXRpc3RpYywgcC52YWx1ZSkpICU+JQogIHNwcmVhZChvdXRjb21lLCB2YWx1ZSkgJT4lCiAgIyBHaXZlIHRhYmxlIGNsZWFuIGNvbHVtbiBuYW1lcwogIHNlbGVjdChTdWJzZXQgPSBncm91cGluZywgWWVhciA9IHllYXIsCiAgICAgICAgIFByb2NlZHVyZXMgPSBzYl9wcm9jZWQsIGBDb3N0IChsb2cpYCA9IHNiX2Nvc3RfbG4sCiAgICAgICAgIGBEYXlzIChsb2cpYCA9IHNiX2RheXNfbG4sIGBDYXBpdGFsIChsb2cpYCA9IHNiX2NhcGl0YWxfbG4pCmBgYAoKYGBge3Igb2xzLW1vZGVscy10YWJsZSwgcmVzdWx0cz0iYXNpcyJ9CmNhcHRpb24gPC0gJ1N1bW1hcnkgb2YgzrJ+Mn4gY29lZmZpY2llbnRzIChpLmUuICJyYW5rZWRfMjAweCIpIGZvciBkaWZmZXJlbmNlIG1vZGVscycKCnRibF9vbHMgPC0gcGFuZG9jLnRhYmxlLnJldHVybihmaWx0ZXIob2xzX2NvZWZzLCBZZWFyICVpbiUgYygyMDA1LCAyMDA2KSksCiAgICAgICAgICAgICBjYXB0aW9uID0gY2FwdGlvbikKCmNhdCh0Ymxfb2xzKQpjYXQodGJsX29scywgZmlsZSA9IGZpbGUucGF0aChoZXJlKCksICJvdXRwdXQiLCAidGFibGVzIiwgInRhYmxlX29scy5tZCIpKQpgYGAKCgojIyBUYWJsZSA0OiBTdW1tYXJ5IG9mIENvZWZmaWNpZW50cyBmb3IgOCBJVFMgTW9kZWxzCgpUaGVzZSBpbnRlcnJ1cHRlZCB0aW1lcyBzZXJpZXMgbW9kZWxzIHVzZSBhbiBpbnRlcmFjdGlvbiB0ZXJtIG9mIHRoZSB5ZWFycyBzaW5jZSBhbiBpbnRlcnZlbnRpb24gYW5kIHRoZSBpbnRlcnZlbnRpb24gaXRzZWxmIHRvIGRldGVybWluZSB0aGUgY2hhbmdlIGluIHNsb3BlIGFmdGVyIHRoZSBpbnRlcnZlbnRpb24uCgokJCB5X3QgPSBcYmV0YV8wICsgXGJldGFfMSBUICsgXGJldGFfMiBYX3QgKyBcYmV0YV8zIChUIFx0aW1lcyBYX3QpICsgXGVwc2lsb24gJCQKCi0gKnQqID0gWWVhcgotICpUKiA9IFllYXJzIGJlZm9yZS9hZnRlciBjdXRwb2ludAotICpYKiA9IHsxIGlmICp0KiA9IGN1dHBvaW50IHllYXIsIDAgb3RoZXJ3aXNlfQotIM6yfjB+ID0gQ29uc3RhbnQ6IHByZS1wZXJpb2QgaW50ZXJjZXB0IC0gYmFzZWxpbmUgcHJlIGludGVydmVudGlvbgotIM6yfjF+ID0gcHJlLXBlcmlvZCBzbG9wZSAtIGJhc2VsaW5lIHRpbWUgdHJlbmQgLSBsZXZlbCBvZiBpbmNyZWFzZSBwcmlvciB0byBpbnRlcnZlbnRpb24KLSDOsn4yfiA9IGltbWVkaWF0ZSBlZmZlY3Qgb2YgdGhlIGV2ZW50IC0gY2hhbmdlIGluIGludGVyY2VwdCBhdCBwb2ludCBvZiBleHBlcmltZW50Ci0gzrJ+M34gPSBjaGFuZ2UgaW4gc2xvcGUgYWZ0ZXIgdGhlIGV4cGVyaW1lbnQgLSB3aGF0IGhhcHBlbnMgYWZ0ZXIKCk9yIGFuIGV4YW1wbGUgUiBmb3JtdWxhOgoKICAgIHNiX3Byb2NlZCB+IHllYXJfY2VudGVyZWRfMjAwNSArIHJhbmtlZF8yMDA1ICsgeWVhcl9jZW50ZXJlZF8yMDA1ICogcmFua2VkXzIwMDUKCmBgYHtyIGl0cy1tb2RlbHN9CiMgQXMgd2l0aCBydW5fbGFnZ2VkX29sc19tb2RlbCgpLCB0aGlzIGZ1bmN0aW9uIGdlbmVyYXRlcyBhbiBSIG1vZGVsIGZvcm11bGEgYW5kCiMgcnVucyBpdC4gaS5lLiwgZ2l2ZW4gInNiX3Byb2NlZCIgYW5kICIyMDA1IiwgaXQgd2lsbCBjcmVhdGUgdGhlIGZvcm11bGEKIyAic2JfcHJvY2VkIH4geWVhcl9jZW50ZXJlZF8yMDA1ICsgcmFua2VkXzIwMDUgKyB5ZWFyX2NlbnRlcmVkXzIwMDUgKiByYW5rZWRfMjAwNSIgCiMgYW5kIHJ1biB0aGUgbW9kZWwKcnVuX2l0c19tb2RlbCA8LSBmdW5jdGlvbihvdXRjb21lLCB5ZWFyLCBkZikgewogIHllYXJfdmFyaWFibGUgPC0gcGFzdGUwKCJyYW5rZWRfIiwgeWVhcikKICB5ZWFyX2NlbnRlcmVkIDwtIHBhc3RlMCgieWVhcl9jZW50ZXJlZF8iLCB5ZWFyKQogIAogIGZvcm0gPC0gYXMuZm9ybXVsYShwYXN0ZTAob3V0Y29tZSwgIiB+ICIsIHllYXJfY2VudGVyZWQsICIgKyAiLCB5ZWFyX3ZhcmlhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIiArICIsIHllYXJfY2VudGVyZWQsICIgKiAiLCB5ZWFyX3ZhcmlhYmxlKSkKICAKICBsbShmb3JtLCBkYXRhID0gZGYpCn0KCiMgUnVuIGFsbCB0aGUgSVRTIG1vZGVscyB3aXRoaW4gdGhlIGRhdGEgZnJhbWUKaXRzX21vZGVscyA8LSBtb2RlbHNfdG9fcnVuX2Z1bGwgJT4lCiAgbXV0YXRlKG1vZGVsID0gcG1hcCgubCA9IGxpc3Qob3V0Y29tZSwgeWVhciwgZGF0YSksIHJ1bl9pdHNfbW9kZWwpLAogICAgICAgICByb2J1c3Rfc2UgPSBwbWFwKC5sID0gbGlzdChtb2RlbCwgZGF0YSwgImNjb2RlIiksIHJvYnVzdF9jbHVzdGVyaWZ5KSwKICAgICAgICAgZ2xhbmNlID0gbW9kZWwgJT4lIG1hcChicm9vbTo6Z2xhbmNlKSwKICAgICAgICAgdGlkeV9yb2J1c3QgPSByb2J1c3Rfc2UgJT4lIG1hcCh+IGJyb29tOjp0aWR5KC4kY29lZikpKQoKIyBFeHRyYWN0IHRoZSByYW5raW5nIGNvZWZmaWNpZW50cyBmcm9tIElUUyBtb2RlbHMKaXRzX2NvZWZzIDwtIGl0c19tb2RlbHMgJT4lCiAgIyBTcHJlYWQgb3V0IHRoZSBtb2RlbCByZXN1bHRzCiAgdW5uZXN0KHRpZHlfcm9idXN0KSAlPiUKICAjIE9ubHkgbG9vayBhdCB0aGUgY29lZmZpY2llbnRzIGZyb20gaW50ZXJhY3Rpb24gdGVybXMgKHRoZXkgaGF2ZSAiOiIgaW4gdGhlaXIgbmFtZXMpCiAgZmlsdGVyKHN0cl9kZXRlY3QodGVybSwgIjoiKSkgJT4lCiAgIyBDbGVhbiB1cCB0aGUgZXN0aW1hdGVzLCBsYWJlbHMsIGFuZCBhZGQgc3RhcnMKICBtdXRhdGUodmFsdWUgPSBwYXN0ZTAoc3ByaW50ZigiJS4zZiIsIHJvdW5kKGVzdGltYXRlLCAzKSksIHBfc3RhcnMocC52YWx1ZSkpLAogICAgICAgICB0ZXJtID0gc3RyX3JlcGxhY2UodGVybSwgIlxcLlxcZCtUUlVFIiwgIiIpKSAlPiUKICAjIEdldCByaWQgb2YgZXh0cmEgY29sdW1ucwogIHNlbGVjdCgtYyhlc3RpbWF0ZSwgc3RkLmVycm9yLCBzdGF0aXN0aWMsIHAudmFsdWUpKSAlPiUKICBzcHJlYWQob3V0Y29tZSwgdmFsdWUpICU+JQogICMgR2l2ZSB0YWJsZSBjbGVhbiBjb2x1bW4gbmFtZXMKICBzZWxlY3QoU3Vic2V0ID0gZ3JvdXBpbmcsIFllYXIgPSB5ZWFyLAogICAgICAgICBQcm9jZWR1cmVzID0gc2JfcHJvY2VkLCBgQ29zdCAobG9nKWAgPSBzYl9jb3N0X2xuLAogICAgICAgICBgRGF5cyAobG9nKWAgPSBzYl9kYXlzX2xuLCBgQ2FwaXRhbCAobG9nKWAgPSBzYl9jYXBpdGFsX2xuKQpgYGAKCmBgYHtyIGl0cy1tb2RlbHMtdGFibGUsIHJlc3VsdHM9ImFzaXMifQpjYXB0aW9uIDwtICdTdW1tYXJ5IG9mIM6yfjN+IGNvZWZmaWNpZW50cyAoaS5lLiAieWVhci5jZW50ZXJlZC4yMDB4IMOXIHJhbmtlZC4yMDB4IiknCgp0YmxfaXRzIDwtIHBhbmRvYy50YWJsZS5yZXR1cm4oZmlsdGVyKGl0c19jb2VmcywgWWVhciAlaW4lIGMoMjAwNSwgMjAwNikpLAogICAgICAgICAgICAgY2FwdGlvbiA9IGNhcHRpb24pCgpjYXQodGJsX2l0cykKY2F0KHRibF9pdHMsIGZpbGUgPSBmaWxlLnBhdGgoaGVyZSgpLCAib3V0cHV0IiwgInRhYmxlcyIsICJ0YWJsZV9pdHMubWQiKSkKYGBgCgoKIyMgVGFibGUgNTogQ291bnRyaWVzIHdpdGggUmVmb3JtIENvbW1pdHRlZXMgRGlyZWN0bHkgVXNpbmcgdGhlIEVEQiBEYXRhCgoqTm90IGdlbmVyYXRlZCB3aXRoIHRoaXMgc2NyaXB0LioKCgojIyBUYWJsZSA2OiBFeHBlcmltZW50YWwgUmVzdWx0cyBTdGF0dXMgQ29tcGFyaXNvbnMgb24gSW1wb3J0YW5jZSBvZiBFQkQgYW5kIEJ1c2luZXNzIENsaW1hdGUgSW1wcm92ZW1lbnRzCgoqTm90IGdlbmVyYXRlZCB3aXRoIHRoaXMgc2NyaXB0LioKCgojIyBUYWJsZSA3OiBFeHBlcmltZW50YWwgUmVzdWx0cyBvZiBSYW5raW5nIERpZmZlcmVuY2VzIG9uIEludmVzdG1lbnQgTGlrZWxpaG9vZAoKKk5vdCBnZW5lcmF0ZWQgd2l0aCB0aGlzIHNjcmlwdC4qCgoKLS0tCgojIEZpZ3VyZXMKCiMjIEZpZ3VyZSAxOiBEb2luZyBCdXNpbmVzcyBXZWJzaXRlIFZpc2l0cywgQW5udWFsbHkgKDIwMDMtMjAxNikKCkVzdGltYXRlZCBkYXRhIGJhc2VkIG9uIGEgc2NyZWVuc2hvdCBvZiBpbnRlcm5hbCBFREIgd2ViIHRyYWZmaWMgcmVwb3J0cy4KCmBgYHtyIGZpZy1lZGItd2Vic2l0ZS10cmFmZmljLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0yLjV9CmVkYl93ZWIgPC0gcmVhZF9jc3YoZmlsZS5wYXRoKGhlcmUoKSwgImRhdGFfcmF3IiwgImVkYi10cmFmZmljXzIwMTMtMjAxNi5jc3YiKSwKICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjKCJZZWFyIiwgIlZpc2l0cyIpKQoKZmlnX2VkYl93ZWIgPC0gZ2dwbG90KGVkYl93ZWIsIGFlcyh4ID0gWWVhciwgeSA9IFZpc2l0cykpICsgCiAgZ2VvbV9saW5lKCkgKyAKICBsYWJzKHggPSBOVUxMLCB5ID0gIkFubnVhbCB2aXNpdHMiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDIsIDIwMTYsIDIpKSArCiAgdGhlbWVfZWRiKCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkpCgpmaWdfZWRiX3dlYgoKZ2dzYXZlKGZpZ19lZGJfd2ViLCAKICAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKGhlcmUoKSwgIm91dHB1dCIsICJmaWd1cmVzIiwgImVkYl93ZWJzaXRlX3RyYWZmaWMucGRmIiksCiAgICAgICB3aWR0aCA9IDYsIGhlaWdodCA9IDIuNSwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSBjYWlyb19wZGYpCmdnc2F2ZShmaWdfZWRiX3dlYiwgCiAgICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChoZXJlKCksICJvdXRwdXQiLCAiZmlndXJlcyIsICJlZGJfd2Vic2l0ZV90cmFmZmljLnBuZyIpLAogICAgICAgd2lkdGggPSA2LCBoZWlnaHQgPSAyLjUsIHVuaXRzID0gImluIiwgdHlwZSA9ICJjYWlybyIsIGRwaSA9IDMwMCkKYGBgCgoKIyMgRmlndXJlIDI6IEF2ZXJhZ2UgY2hhbmdlIGluIHNlbGVjdCBzdWJpbmRpY2F0b3JzLCBiZWZvcmUgYW5kIGFmdGVyIHB1YmxpYyByYW5raW5nICgyMDA2KQoKYGBge3IgZmlnLWl0cy0yMDAxLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD00LjV9CmRmX3Bsb3RfZWRiXzIwMDEgPC0gZWRiX2NsZWFuICU+JQogICMgT25seSBsb29rIGF0IGNvdW50cmllcyBpbiB0aGUgMjAwMSByZXBvcnQKICBmaWx0ZXIoaW5fMjAwMSA9PSAxKSAlPiUKICBzZWxlY3QoeWVhciwgc2JfZGF5cywgc2JfcHJvY2VkLCBzYl9jb3N0LCBzYl9jYXBpdGFsLCBjb25fZGF5cywgY29uX3Byb2NlZCkgJT4lCiAgIyBDYWxjdWxhdGUgYXZlcmFnZSBvZiBlYWNoIHZhcmlhYmxlIGJ5IHllYXIKICBnYXRoZXIodmFyaWFibGUsIHZhbHVlLCAteWVhcikgJT4lCiAgZ3JvdXBfYnkoeWVhciwgdmFyaWFibGUpICU+JQogIHN1bW1hcmlzZShhdmcgPSBtZWFuKHZhbHVlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBmaWx0ZXIoIWlzLm5hbihhdmcpKSAlPiUKICAjIE9ubHkgdXNlIDIwMDQgYW5kIGJleW9uZAogIGZpbHRlcih5ZWFyID49IDIwMDMpICU+JQogIG11dGF0ZSh2YXJpYWJsZSA9IGZjdF9yZWNvZGUodmFyaWFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQ29udHJhY3TigJREYXlzYCA9ICJjb25fZGF5cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQ29udHJhY3TigJRQcm9jZWR1cmVzYCA9ICJjb25fcHJvY2VkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBTdGFydGluZyBhIGJ1c2luZXNz4oCUQ2FwaXRhbGAgPSAic2JfY2FwaXRhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgU3RhcnRpbmcgYSBidXNpbmVzc+KAlENvc3RgID0gInNiX2Nvc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFN0YXJ0aW5nIGEgYnVzaW5lc3PigJREYXlzYCA9ICJzYl9kYXlzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBTdGFydGluZyBhIGJ1c2luZXNz4oCUUHJvY2VkdXJlc2AgPSAic2JfcHJvY2VkIikpCgojIE1hcmsgdGhlIGludGVydmVudGlvbiB5ZWFycwpwbG90X2ludGVydmVudGlvbnMgPC0gZGF0YV9mcmFtZSh5ZWFyID0gMjAwNToyMDA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnZlbnRpb24gPSBjKCIyMDA1IiwgIjIwMDYiKSkKCiMgVGVjaG5pY2FsbHksIGZhY2V0cyBpbiBncHBsb3QgYXJlIGZvciBkaWZmZXJlbnQgYXNwZWN0cyBvZiB0aGUgc2FtZSB2YWx1ZSwgbm90CiMgZm9yIHNlcGFyYXRlIHZhcmlhYmxlcy4gVGhpcyBmdW5jdGlvbiBjcmVhdGVzIGEgbWluaWF0dXJlIGdncGxvdCBvYmplY3Qgd2hpY2gKIyB0aGVuIGdldHMgY29tYmluZWQgYmVsb3cgd2l0aCBncmlkRXh0cmE6OmFycmFuZ2VHcm9iKCkKbWFrZV9mYXV4X2ZhY2V0IDwtIGZ1bmN0aW9uKHgsIHltaW4sIHltYXgsIHlsYWIpIHsKICBwbG90X2RhdGEgPC0gZGZfcGxvdF9lZGJfMjAwMSAlPiUKICAgIGZpbHRlcih2YXJpYWJsZSA9PSB4KQogIAogIGZhdXhfZmFjZXQgPC0gZ2dwbG90KCkgKwogICAgZ2VvbV92bGluZShkYXRhID0gcGxvdF9pbnRlcnZlbnRpb25zLCBhZXMoeGludGVyY2VwdCA9IHllYXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gaW50ZXJ2ZW50aW9uKSwKICAgICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDAuNSkgKwogICAgZ2VvbV9saW5lKGRhdGEgPSBwbG90X2RhdGEsIGFlcyh4ID0geWVhciwgeSA9IGF2ZykpICsgCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYyhpdHNfMSwgaXRzXzIpLCBuYW1lID0gTlVMTCkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMjAwMCwgMjAxNSksIGJyZWFrcyA9IHNlcSgyMDAwLCAyMDE1LCA1KSkgKwogICAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDIwMDAsIDIwMTUpLCB5bGltID0gYyh5bWluLCB5bWF4KSkgKwogICAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpICsKICAgIGxhYnMoeCA9IE5VTEwsIHkgPSB5bGFiLCB0aXRsZSA9IHgpICsKICAgIHRoZW1lX2VkYigpICsgCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksIGhqdXN0ID0gMC41KSkKCiAgcmV0dXJuKGZhdXhfZmFjZXQpCn0KCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIHBsb3R0aW5nIHBhcmFtZXRlcnMgYW5kIHRoZW4gY3JlYXRlIGdncGxvdCBvYmplY3RzIGluIGEgbmV3IGNvbHVtbgpwbG90c18yMDAxIDwtIHRyaWJibGUoCiAgfnltaW4sIH55bWF4LCB+eWxhYiwgICAgICAgIH52YXJpYWJsZSwKICAwLCAgICAgNjEwLCAgICJEYXlzIiwgICAgICAgIkNvbnRyYWN04oCURGF5cyIsCiAgMCwgICAgIDQ1LCAgICAiUHJvY2VkdXJlcyIsICJDb250cmFjdOKAlFByb2NlZHVyZXMiLAogIDAsICAgICAyMDAsICAgIkNhcGl0YWwiLCAgICAiU3RhcnRpbmcgYSBidXNpbmVzc+KAlENhcGl0YWwiLAogIDAsICAgICAxMDAsICAgIkNvc3QiLCAgICAgICAiU3RhcnRpbmcgYSBidXNpbmVzc+KAlENvc3QiLAogIDAsICAgICA1MCwgICAgIkRheXMiLCAgICAgICAiU3RhcnRpbmcgYSBidXNpbmVzc+KAlERheXMiLAogIDAsICAgICAxMCwgICAgIlByb2NlZHVyZXMiLCAiU3RhcnRpbmcgYSBidXNpbmVzc+KAlFByb2NlZHVyZXMiCikgJT4lCiAgbXV0YXRlKGZhY2V0ID0gcG1hcCgubCA9IGxpc3QodmFyaWFibGUsIHltaW4sIHltYXgsIHlsYWIpLCBtYWtlX2ZhdXhfZmFjZXQpKQoKIyBQbG90IGFsbCB0aG9zZSBwbG90cyBpbiBvbmUgYmlnIG1lZ2EgcGxvdApwbG90X2VkYl8yMDAxIDwtIGFycmFuZ2VHcm9iKGdyb2JzID0gcGxvdHNfMjAwMSRmYWNldCwgbnJvdyA9IDIpCmdyaWQ6OmdyaWQubmV3cGFnZSgpCmdyaWQ6OmdyaWQuZHJhdyhwbG90X2VkYl8yMDAxKQoKZ2dzYXZlKHBsb3RfZWRiXzIwMDEsIAogICAgICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoaGVyZSgpLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAiZWRiX2l0c18yMDAxLnBkZiIpLAogICAgICAgd2lkdGggPSA5LCBoZWlnaHQgPSA0LjUsIHVuaXRzID0gImluIiwgZGV2aWNlID0gY2Fpcm9fcGRmKQpnZ3NhdmUocGxvdF9lZGJfMjAwMSwgCiAgICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChoZXJlKCksICJvdXRwdXQiLCAiZmlndXJlcyIsICJlZGJfaXRzXzIwMDEucG5nIiksCiAgICAgICB3aWR0aCA9IDksIGhlaWdodCA9IDQuNSwgdW5pdHMgPSAiaW4iLCB0eXBlID0gImNhaXJvIiwgZHBpID0gMzAwKQpgYGAKCgojIyBGaWd1cmUgMzogRURCIFJhbmtpbmdzLCAyMDA1IHZlcnN1cyAyMDE0LCBieSBDb21taXR0ZWUgU3RhdHVzIEJhc2VkIG9uIDIwMTUgcmVwb3J0CgpgYGB7ciBmaWctZWRiLXJhbmtpbmdzLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00fQojIFNlbGVjdCBvbmx5IDIwMDUgYW5kIDIwMTQgcmFua2luZ3MKZWRiX3JhbmtpbmdzIDwtIGVkYl9jbGVhbiAlPiUKICBzZWxlY3QoY2NvZGUsIHllYXIsIHBfZWRiX3JhbmssIGhhc19idXJlYXUpICU+JQogIGZpbHRlcih5ZWFyICVpbiUgYygyMDA1LCAyMDE0KSkgJT4lCiAgc3ByZWFkKHllYXIsIHBfZWRiX3JhbmspICU+JQogIG11dGF0ZShjb3VudHJ5bmFtZSA9IGNvdW50cnljb2RlKGNjb2RlLCAiY293biIsICJjb3VudHJ5Lm5hbWUiKSwKICAgICAgICAgY291bnRyeW5hbWUgPSBpZmVsc2UoY291bnRyeW5hbWUgPT0gIkxhbyBQZW9wbGUncyBEZW1vY3JhdGljIFJlcHVibGljIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMYW9zIiwgY291bnRyeW5hbWUpLAogICAgICAgICBhZGRfbGFiZWwgPSBjb3VudHJ5bmFtZSAlaW4lIGMoIkdlb3JnaWEiLCAiUndhbmRhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFuZ2xhZGVzaCIsICJOaWdlcmlhIiwgIlBha2lzdGFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb3J3YXkiLCAiTmV3IFplYWxhbmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhb3MiLCAiTmlnZXIiKSwKICAgICAgICAgbGFiZWwgPSBpZmVsc2UoYWRkX2xhYmVsLCBjb3VudHJ5bmFtZSwgTkEpKQoKIyBFeHRyYSBzdHVmZiB0aGF0IHdpbGwgZ28gb24gdGhlIHBsb3QKYW5ub3RhdGlvbnMgPC0gZGF0YV9mcmFtZSh4ID0gYyhtYXgoZWRiX3JhbmtpbmdzJGAyMDA1YCwgbmEucm0gPSBUUlVFKSwgMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGMoMCwgbWF4KGVkYl9yYW5raW5ncyRgMjAxNGAsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBjKCJPdXRsaWVyc1xuaW1wcm92aW5nIiwgIk91dGxpZXJzXG53b3JzZW5pbmciKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IGMoInJpZ2h0IiwgImxlZnQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IGMoImJvdHRvbSIsICJ0b3AiKSkKCnJlZmVyZW5jZV9saW5lIDwtIGRhdGFfZnJhbWUoeCA9IGMoMCwgbWF4KGVkYl9yYW5raW5ncyRgMjAwNWAsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBjKDAsIG1heChlZGJfcmFua2luZ3MkYDIwMTRgLCBuYS5ybSA9IFRSVUUpKSkKCiMgU2V0IHRoZSBzZWVkIGV2ZXJ5IHRpbWUgZ2VvbV9sYWJlbF9yZXBlbCBpcyBjYWxsZWQgc28gdGhlIGxhYmVscyBhcmUgcmVwb3NpdGlvbmVkIHRoZSBzYW1lIHdheQpzZXQuc2VlZCgxMjM0KQpmaWdfcmFua2luZ3NfY29yciA8LSBnZ3Bsb3QoZWRiX3JhbmtpbmdzLCBhZXMoeCA9IGAyMDA1YCwgeSA9IGAyMDE0YCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBoYXNfYnVyZWF1LCBsYWJlbCA9IGxhYmVsKSkgKyAKICAjIGdlb21fc21vb3RoKGFlcyhmaWxsID0gaGFzX2J1cmVhdSksIG1ldGhvZCA9ICJsbSIsIHNpemUgPSAwLjUsIGFscGhhID0gMC4xLCBmdWxscmFuZ2UgPSBUUlVFKSArCiAgZ2VvbV9saW5lKGRhdGEgPSByZWZlcmVuY2VfbGluZSwgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSBOVUxMKSwgY29sb3VyID0gImdyZXk3MCIsIHNpemUgPSAwLjUpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgZ2VvbV9sYWJlbF9yZXBlbChhZXMoZmlsbCA9IGhhc19idXJlYXUpLCBjb2xvdXIgPSAid2hpdGUiLCAKICAgICAgICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuOSwgc2VnbWVudC5jb2xvciA9ICJncmV5NDAiKSArCiAgZ2VvbV90ZXh0KGRhdGEgPSBhbm5vdGF0aW9ucywgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSB0ZXh0LCBoanVzdCA9IGhqdXN0LCB2anVzdCA9IHZqdXN0KSwKICAgICAgICAgICAgY29sb3VyID0gImdyZXk0MCIsIHNpemUgPSAyLCBsaW5laGVpZ2h0ID0gMSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKGNvbG9yX25vX2NvbW1pdHRlZSwgY29sb3JfY29tbWl0dGVlKSwgbmFtZSA9IE5VTEwpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKGNvbG9yX25vX2NvbW1pdHRlZSwgY29sb3JfY29tbWl0dGVlKSwgbmFtZSA9IE5VTEwsIGd1aWRlID0gRkFMU0UpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMTYwKSwgeWxpbSA9IGMoMCwgMTkwKSkgKwogIGxhYnMoeCA9ICJSYW5rIGluIDIwMDUiLCB5ID0gIlJhbmsgaW4gMjAxNCIpICsKICB0aGVtZV9lZGIoKQoKc2V0LnNlZWQoMTIzNCkKZmlnX3JhbmtpbmdzX2NvcnIKCnNldC5zZWVkKDEyMzQpCmdnc2F2ZShmaWdfcmFua2luZ3NfY29yciwgCiAgICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChoZXJlKCksICJvdXRwdXQiLCAiZmlndXJlcyIsICJidXJlYXVfcmFua2luZ3MucGRmIiksCiAgICAgICB3aWR0aCA9IDYsIGhlaWdodCA9IDQsIHVuaXRzID0gImluIiwgZGV2aWNlID0gY2Fpcm9fcGRmKQpzZXQuc2VlZCgxMjM0KQpnZ3NhdmUoZmlnX3JhbmtpbmdzX2NvcnIsIAogICAgICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoaGVyZSgpLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAiYnVyZWF1X3JhbmtpbmdzLnBuZyIpLAogICAgICAgd2lkdGggPSA2LCBoZWlnaHQgPSA0LCB1bml0cyA9ICJpbiIsIHR5cGUgPSAiY2Fpcm8iLCBkcGkgPSAzMDApCmBgYAoKCiMjIEZpZ3VyZSA0OiBSYW5raW5nIEdhaW5zIGJ5IE51bWJlciBvZiBSZWZvcm1zLCBieSBDb21taXR0ZWUgU3RhdHVzICg5NSUgQ0kpCgpFdmVyeSByZWZvcm0gbGVhZHMgdG8gYSBuZWdhdGl2ZSBjaGFuZ2UgaW4gcmFua2luZ3MgKHdoaWNoIGlzIGdvb2QpIGluIHRoZSBmb2xsb3dpbmcgeWVhciBmb3IgY291bnRyaWVzIHdpdGggc3BlY2lhbCBFREIgcmVmb3JtIGNvbW1pdHRlZXMuIEZvciBpbnN0YW5jZSwgZG9pbmcgYW4gZW5mb3JjaW5nIGNvbnRyYWN0cyByZWZvcm0gd2lsbCBtb3ZlIGEgY291bnRyeSBkb3duIChpLmUuIHRvIGEgYmV0dGVyIHBvc2l0aW9uKSBuZWFybHkgNiBwb3NpdGlvbnMuIFRoaXMgaXMgYWxzbyB0aGUgY2FzZSB3aGVuIG5vcm1hbGl6aW5nIHJhbmtpbmdzIHRvIGEgMC0xMDAgc2NhbGUgdG8gYWNjb3VudCBmb3IgdGhlIGNoYW5naW5nIG51bWJlciBvZiByYW5rIHBvc2l0aW9ucyBvdmVyIHRpbWUuIAoKYGBge3IgY2FsY3VsYXRlLWNoYW5nZS1yYW5raW5nc30KIyBBZGQgbmV3IGNvbHVtbnMgZm9yIGxlYWRlZCByYW5raW5ncyBhbmQgY2hhbmdlcyBpbiByYW5raW5ncwpjaGFuZ2VfaW5fcmFua2luZ3Nfbm9ybSA8LSBlZGJfY2xlYW4gJT4lCiAgc2VsZWN0KGNjb2RlLCBjb3VudHJ5X25hbWUsIHllYXIsIHBfZWRiX3JhbmssIHBfZWRiX3Jhbmtfbm9ybWFsaXplZCwgaGFzX2J1cmVhdSkgJT4lCiAgbXV0YXRlKHJhbmswID0gcF9lZGJfcmFuaywKICAgICAgICAgcmFuazEgPSBsZWFkKHJhbmswLCAxKSwKICAgICAgICAgcmFuazIgPSBsZWFkKHJhbmswLCAyKSwKICAgICAgICAgY2hhbmdlMSA9IHJhbmsxIC0gcmFuazAsCiAgICAgICAgIGNoYW5nZTIgPSByYW5rMiAtIHJhbmswLAogICAgICAgICByYW5rMF9ub3JtID0gcF9lZGJfcmFua19ub3JtYWxpemVkLAogICAgICAgICByYW5rMV9ub3JtID0gbGVhZChyYW5rMF9ub3JtLCAxKSwKICAgICAgICAgcmFuazJfbm9ybSA9IGxlYWQocmFuazBfbm9ybSwgMiksCiAgICAgICAgIGNoYW5nZTFfbm9ybSA9IHJhbmsxX25vcm0gLSByYW5rMF9ub3JtLAogICAgICAgICBjaGFuZ2UyX25vcm0gPSByYW5rMl9ub3JtIC0gcmFuazBfbm9ybSkgJT4lCiAgZmlsdGVyKHllYXIgPj0gMjAwNSkKCiMgQ2FsY3VsYXRlIHRoZSBjaGFuZ2VzLS1vciBidW1wcy0taW4gcmFua2luZ3MgcGVyIHJlZm9ybSB1bmRlcnRha2VuCmVkYl9yZWZvcm1zX3JhbmtpbmdzX2J1bXBzIDwtIGVkYl9yZWZvcm1zICU+JQogIGZpbHRlcighc3RyX2RldGVjdChyZWZvcm1fdHlwZSwgImxhZyIpKSAlPiUKICBncm91cF9ieShjY29kZSwgeWVhciwgcmVmb3JtX3R5cGVfY2xlYW4pICU+JQogIHN1bW1hcmlzZShudW1fcmVmb3JtcyA9IHN1bShyZWZvcm1fbnVtX25vX25hKSkgJT4lCiAgbGVmdF9qb2luKGNoYW5nZV9pbl9yYW5raW5nc19ub3JtLCBieSA9IGMoImNjb2RlIiwgInllYXIiKSkgJT4lCiAgZmlsdGVyKG51bV9yZWZvcm1zICE9IDApICU+JQogIG11dGF0ZShjaGFuZ2VfcGVyX3JlZm9ybTEgPSBjaGFuZ2UxIC8gbnVtX3JlZm9ybXMsCiAgICAgICAgIGNoYW5nZV9wZXJfcmVmb3JtMiA9IGNoYW5nZTIgLyBudW1fcmVmb3JtcywKICAgICAgICAgY2hhbmdlX3Blcl9yZWZvcm0xX25vcm0gPSBjaGFuZ2UxX25vcm0gLyBudW1fcmVmb3JtcywKICAgICAgICAgY2hhbmdlX3Blcl9yZWZvcm0yX25vcm0gPSBjaGFuZ2UyX25vcm0gLyBudW1fcmVmb3JtcykgCgojIENhbGN1bGF0ZSBzdW1tYXJ5IHN0YXRpc3RpY3Mgb2YgYnVtcHMgaW4gcmFua2luZ3MKZWRiX3JlZm9ybXNfcmFua2luZ3NfYnVtcHNfc3VtbWFyaXplZCA8LSBlZGJfcmVmb3Jtc19yYW5raW5nc19idW1wcyAlPiUKICBncm91cF9ieShyZWZvcm1fdHlwZV9jbGVhbiwgaGFzX2J1cmVhdSkgJT4lCiAgc3VtbWFyaXNlKGF2Z19idW1wX25vcm0gPSBtZWFuKGNoYW5nZV9wZXJfcmVmb3JtMV9ub3JtLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBzdGRlcnJfYnVtcF9ub3JtID0gc2QoY2hhbmdlX3Blcl9yZWZvcm0xX25vcm0sIG5hLnJtID0gVFJVRSkgLyAKICAgICAgICAgICAgICBzcXJ0KGxlbmd0aChjaGFuZ2VfcGVyX3JlZm9ybTFfbm9ybSkpLAogICAgICAgICAgICBsb3dlcl9ub3JtID0gYXZnX2J1bXBfbm9ybSArIChxbm9ybSgwLjAyNSkgKiBzdGRlcnJfYnVtcF9ub3JtKSwKICAgICAgICAgICAgdXBwZXJfbm9ybSA9IGF2Z19idW1wX25vcm0gKyAocW5vcm0oMC45NzUpICogc3RkZXJyX2J1bXBfbm9ybSksCiAgICAgICAgICAgIGF2Z19idW1wID0gbWVhbihjaGFuZ2VfcGVyX3JlZm9ybTEsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHN0ZGVycl9idW1wID0gc2QoY2hhbmdlX3Blcl9yZWZvcm0xLCBuYS5ybSA9IFRSVUUpIC8gCiAgICAgICAgICAgICAgc3FydChsZW5ndGgoY2hhbmdlX3Blcl9yZWZvcm0xKSksCiAgICAgICAgICAgIGxvd2VyID0gYXZnX2J1bXAgKyAocW5vcm0oMC4wMjUpICogc3RkZXJyX2J1bXApLAogICAgICAgICAgICB1cHBlciA9IGF2Z19idW1wICsgKHFub3JtKDAuOTc1KSAqIHN0ZGVycl9idW1wKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2UoZGVzYyhoYXNfYnVyZWF1KSwgZGVzYyhhdmdfYnVtcCkpICU+JQogIGZpbHRlcighaXMubmEocmVmb3JtX3R5cGVfY2xlYW4pKSAlPiUKICBtdXRhdGUocmVmb3JtX3R5cGVfY2xlYW4gPSBmYWN0b3IocmVmb3JtX3R5cGVfY2xlYW4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB1bmlxdWUocmVmb3JtX3R5cGVfY2xlYW4pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKQpgYGAKCmBgYHtyIGZpZy1ub3JtYWxpemVkLWJ1bXBzLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00fQpwbG90X3JhbmtpbmdfYnVtcHNfbm9ybSA8LSBnZ3Bsb3QoZWRiX3JlZm9ybXNfcmFua2luZ3NfYnVtcHNfc3VtbWFyaXplZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IGF2Z19idW1wX25vcm0sIHkgPSByZWZvcm1fdHlwZV9jbGVhbiwgY29sb3VyID0gaGFzX2J1cmVhdSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMC41KSArCiAgZ2VvbV9wb2ludHJhbmdlaChhZXMoeG1pbiA9IGxvd2VyX25vcm0sIHhtYXggPSB1cHBlcl9ub3JtKSwgc2l6ZSA9IDAuNSwKICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2V2KDAuNSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYyhjb2xvcl9ub19jb21taXR0ZWUsIGNvbG9yX2NvbW1pdHRlZSksIG5hbWUgPSBOVUxMKSArCiAgbGFicyh4ID0gIkF2ZXJhZ2UgY2hhbmdlIGluIEVEQiByYW5raW5ncyBvbmUgeWVhciBhZnRlciByZWZvcm0gKG5vcm1hbGl6ZWQgcmFua2luZ3MpIiwgCiAgICAgICB5ID0gIlR5cGUgb2YgcmVmb3JtIikgKwogIHRoZW1lX2VkYigpCnBsb3RfcmFua2luZ19idW1wc19ub3JtCgpnZ3NhdmUocGxvdF9yYW5raW5nX2J1bXBzX25vcm0sIAogICAgICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoaGVyZSgpLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAiYnVyZWF1X3JhbmtpbmdzX2J1bXBzLnBkZiIpLAogICAgICAgd2lkdGggPSA2LCBoZWlnaHQgPSA0LCB1bml0cyA9ICJpbiIsIGRldmljZSA9IGNhaXJvX3BkZikKZ2dzYXZlKHBsb3RfcmFua2luZ19idW1wc19ub3JtLCAKICAgICAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKGhlcmUoKSwgIm91dHB1dCIsICJmaWd1cmVzIiwgImJ1cmVhdV9yYW5raW5nc19idW1wcy5wbmciKSwKICAgICAgIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCwgdW5pdHMgPSAiaW4iLCB0eXBlID0gImNhaXJvIiwgZHBpID0gMzAwKQpgYGAKCiMjIyAqdCotdGVzdHMgZm9yIGNoYW5nZXMgaW4gcmFua2luZ3MKCmBgYHtyIHRibC1jaGFuZ2UtcmFua2luZ3MsIHJlc3VsdHM9ImFzaXMifQplZGJfcmVmb3Jtc19yYW5raW5nc19idW1wc190ZXN0cyA8LSBlZGJfcmVmb3Jtc19yYW5raW5nc19idW1wcyAlPiUKICB1bmdyb3VwKCkgJT4lCiAgc2VsZWN0KGhhc19idXJlYXUsIHJlZm9ybV90eXBlX2NsZWFuLCBjaGFuZ2VfcGVyX3JlZm9ybTFfbm9ybSkgJT4lCiAgZ2F0aGVyKHZhcmlhYmxlLCB2YWx1ZSwgLWhhc19idXJlYXUsIC1yZWZvcm1fdHlwZV9jbGVhbikgJT4lCiAgZ3JvdXBfYnkocmVmb3JtX3R5cGVfY2xlYW4sIGhhc19idXJlYXUpICU+JQogIHN1bW1hcmlzZShkYXRhID0gbGlzdCh2YWx1ZSkpICU+JQogIHNwcmVhZChoYXNfYnVyZWF1LCBkYXRhKSAlPiUKICBtdXRhdGUodF90ZXN0ID0gbGlzdCh0LnRlc3QodW5saXN0KGBObyBFREIgcmVmb3JtIGNvbW1pdHRlZWApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmxpc3QoYFNwZWNpYWwgRURCIHJlZm9ybSBjb21taXR0ZWVgKSkpLAogICAgICAgICB0X3ZhbHVlID0gdF90ZXN0ICU+JSBtYXBfZGJsKCJzdGF0aXN0aWMiKSwKICAgICAgICAgcF92YWx1ZSA9IHRfdGVzdCAlPiUgbWFwX2RibCgicC52YWx1ZSIpLAogICAgICAgICBlc3RpbWF0ZSA9IHRfdGVzdCAlPiUgbWFwKCJlc3RpbWF0ZSIpLAogICAgICAgICBtZWFuX2NvbW1pdHRlZSA9IGVzdGltYXRlICU+JSBtYXBfZGJsKH4gLnhbMl0pLAogICAgICAgICBtZWFuX25vX2NvbW1pdHRlZSA9IGVzdGltYXRlICU+JSBtYXBfZGJsKH4gLnhbMV0pLAogICAgICAgICBkaWZmX2luX21lYW5zID0gZXN0aW1hdGUgJT4lIG1hcF9kYmwofiBhYnMoLnhbMl0gLSAueFsxXSkpKSAlPiUKICBtdXRhdGUodCA9IHBhc3RlMChzcHJpbnRmKCIlLjJmIiwgcm91bmQodF92YWx1ZSwgMikpLCBwX3N0YXJzKHBfdmFsdWUpKSkgJT4lCiAgYXJyYW5nZShtZWFuX2NvbW1pdHRlZSkgJT4lCiAgc2VsZWN0KFJlZm9ybSA9IHJlZm9ybV90eXBlX2NsZWFuLCAKICAgICAgICAgYEF2ZXJhZ2UgY2hhbmdlIGluIHJhbmtpbmdzLCBjb21taXR0ZWVgID0gbWVhbl9jb21taXR0ZWUsCiAgICAgICAgIGBBdmVyYWdlIGNoYW5nZSBpbiByYW5raW5ncywgbm8gY29tbWl0dGVlYCA9IG1lYW5fbm9fY29tbWl0dGVlLAogICAgICAgICBgRGlmZmVyZW5jZSBpbiBtZWFuc2AgPSBkaWZmX2luX21lYW5zLCBgKnQqYCA9IHQpCgpjYXB0aW9uIDwtICdEaWZmZXJlbmNlcyBpbiBhdmVyYWdlIGNoYW5nZSBpbiBFREIgcmFua2luZ3MgYnkgcmVmb3JtLCBieSBjb21taXR0ZWUgc3RhdHVzJwoKdGJsX2VkYl9yZWZvcm1zX2RpZmZzIDwtIHBhbmRvYy50YWJsZS5yZXR1cm4oZWRiX3JlZm9ybXNfcmFua2luZ3NfYnVtcHNfdGVzdHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBjYXB0aW9uLCBzcGxpdC50YWJsZXMgPSBJbmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIsIGp1c3RpZnkgPSAibGNjY2MiKQoKY2F0KHRibF9lZGJfcmVmb3Jtc19kaWZmcykKY2F0KHRibF9lZGJfcmVmb3Jtc19kaWZmcywgCiAgICBmaWxlID0gZmlsZS5wYXRoKGhlcmUoKSwgIm91dHB1dCIsICJ0YWJsZXMiLCAidGFibGVfZWRiX3JlZm9ybXNfZGlmZnMubWQiKSkKYGBgCgpcKnA8MC4xOyBcKlwqcDwwLjA1OyBcKlwqXCpwPDAuMDEKCgojIyBGaWd1cmUgNTogUHVibGljIEFzc2Vzc21lbnRzIG9mIEltcG9ydGFuY2Ugb2YgSW1wcm92aW5nIEluZGlhJ3MgQnVzaW5lc3MgQ2xpbWF0ZSBhbmQgRURCIFJhbmtpbmdzLCBieSBFeHBvc3VyZSB0byBFREIgSW5mb3JtYXRpb24KCmBgYHtyIGZpZy1leHBvc3VyZS1hc3Nlc3NtZW50LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0zfQpjaG5faW5kX2Fzc2Vzc21lbnRzIDwtIHJlYWRfY3N2KGZpbGUucGF0aChoZXJlKCksICJkYXRhX3JhdyIsICJjaG4taW5kLWFzc2Vzc21lbnRzLmNzdiIpKSAlPiUKICByZW5hbWUoRnJhbWUgPSBYMSkgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUsIC1GcmFtZSkKCiMgU3BsaXQgaW50byB0d28gZGF0YSBmcmFtZXMgZm9yIGZhY2V0aW5nLCB0aGVuIHJlY29tYmluZQpjaG5faW5kX2JvdGggPC0gY2huX2luZF9hc3Nlc3NtZW50cyAlPiUKICBmaWx0ZXIoa2V5ICVpbiUgYygiSW5kaWEgSGlnaGVyIiwgIk5vIFJhbmsiLCAiQ2hpbmEgSGlnaGVyIikpICU+JQogIG11dGF0ZShjb21wYXJpc29uID0gIkJvdGgiKQoKaW5kX29ubHkgPC0gY2huX2luZF9hc3Nlc3NtZW50cyAlPiUKICBmaWx0ZXIoa2V5ICVpbiUgYygiTm8gUmFuayIsICJJbmRpYSdzIFJhbmsgT25seSIpKSAlPiUKICBtdXRhdGUoY29tcGFyaXNvbiA9ICJJbmRpYSBvbmx5IikKCmJsYW5rX2NvdW50cnkgPC0gZGF0YV9mcmFtZShGcmFtZSA9IHVuaXF1ZShjaG5faW5kX2Fzc2Vzc21lbnRzJEZyYW1lKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleSA9ICIgIiwgdmFsdWUgPSBjKDAsIDApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBhcmlzb24gPSAiSW5kaWEgb25seSIpCgpjaG5faW5kX3Bsb3RfZGF0YSA8LSBiaW5kX3Jvd3MoY2huX2luZF9ib3RoLCBpbmRfb25seSwgYmxhbmtfY291bnRyeSkgJT4lCiAgbXV0YXRlKGtleSA9IGZhY3RvcihrZXksIGxldmVscyA9IGMoIkluZGlhIEhpZ2hlciIsICJJbmRpYSdzIFJhbmsgT25seSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJObyBSYW5rIiwgIkNoaW5hIEhpZ2hlciIsICIgIiksCiAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSksCiAgICAgICAgIEZyYW1lID0gZmN0X2lub3JkZXIoRnJhbWUsIG9yZGVyZWQgPSBUUlVFKSkKCmNobl9pbmRfYW5ub3RhdGlvbnMgPC0gZGF0YV9mcmFtZSh4ID0gYyg0LCA1KSwgeSA9IGMoMC42LCAwLjYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IGMoIkxvd2VyIGltcG9ydGFuY2UiLCAiSGlnaGVyIGltcG9ydGFuY2UiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gYygibGVmdCIsICJyaWdodCIpKQoKIyBQbG90CnBsb3RfY2huX2luZCA8LSBnZ3Bsb3QoY2huX2luZF9wbG90X2RhdGEsIGFlcyh4ID0gdmFsdWUsIHkgPSBmY3RfcmV2KGtleSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBmY3RfcmV2KEZyYW1lKSkpICsKICBnZW9tX3BvaW50cmFuZ2VoKGFlcyh4bWluID0gMCwgeG1heCA9IHZhbHVlKSwgc2l6ZSA9IDAuNSwKICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2V2KGhlaWdodCA9IDAuNSkpICsKICBnZW9tX3RleHQoZGF0YSA9IGNobl9pbmRfYW5ub3RhdGlvbnMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBsYWJlbCA9IHRleHQsIGhqdXN0ID0gaGp1c3QpLAogICAgICAgICAgICB2anVzdCA9ICJjZW50ZXIiLCBjb2xvciA9ICJncmV5NDAiLCBzaXplID0gMiwgbGluZWhlaWdodCA9IDEpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gdmFsdWUpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdldihoZWlnaHQgPSAwLjUpLAogICAgICAgICAgICBoanVzdCA9IC0wLjQsIHNpemUgPSAyLjUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYyhlZGJfaW1wb3J0YW5jZSwgY2xpbWF0ZV9pbXBvcnRhbmNlKSwgbmFtZSA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgIGd1aWRlID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNSwgMC41KSkgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYyg0LCA1KSkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMKSArCiAgdGhlbWVfZWRiKCkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBmYWNldF93cmFwKH4gY29tcGFyaXNvbiwgc2NhbGVzID0gImZyZWVfeSIpCgpwbG90X2Nobl9pbmQKCmdnc2F2ZShwbG90X2Nobl9pbmQsIAogICAgICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoaGVyZSgpLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAiY2huX2luZF9leHBvc3VyZS5wZGYiKSwKICAgICAgIHdpZHRoID0gNiwgaGVpZ2h0ID0gMywgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSBjYWlyb19wZGYpCmdnc2F2ZShwbG90X2Nobl9pbmQsIAogICAgICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoaGVyZSgpLCAib3V0cHV0IiwgImZpZ3VyZXMiLCAiY2huX2luZF9leHBvc3VyZS5wbmciKSwKICAgICAgIHdpZHRoID0gNiwgaGVpZ2h0ID0gMywgdW5pdHMgPSAiaW4iLCB0eXBlID0gImNhaXJvIiwgZHBpID0gMzAwKQpgYGAK