library(tidyverse)
library(targets)
library(yardstick)
library(broom)
library(patchwork)
library(scales)
library(here)

# Load data
# Need to use this withr thing because tar_read() and tar_load() need to see the
# _targets folder in the current directory, but this .Rmd file is in a subfolder
withr::with_dir(here::here(), {
  source(tar_read(plot_funs))
  
  canary_testing_lagged <- tar_read(panel_testing_lagged)
  
  # Load big list of models
  model_df <- tar_read(model_df) %>% 
    filter(str_detect(model, "baseline") | str_detect(model, "v2csreprss"))
  
  # Load actual model objects
  tar_load(c(m_pts_baseline_train, m_pts_v2csreprss_train,
             m_pts_total_train, m_pts_advocacy_train, 
             m_pts_entry_train, m_pts_funding_train,
             m_pts_baseline_rewb_train, m_pts_v2csreprss_rewb_train, 
             m_clphy_baseline_train, m_clphy_v2csreprss_train, 
             m_clphy_total_train, m_clphy_advocacy_train, 
             m_clphy_entry_train, m_clphy_funding_train,
             m_clpriv_baseline_train, m_clpriv_v2csreprss_train,
             m_clpriv_total_train, m_clpriv_advocacy_train, 
             m_clpriv_entry_train, m_clpriv_funding_train))
})

pts_levels <- levels(canary_testing_lagged$PTS_factor)

# Returns a data frame of predicted probabilities with actual = 1 
# when the response outcome happens
match_actual <- function(x, pred, actual) {
  pred %>% 
    select(fitted = {{x}}) %>% 
    mutate(actual = as.numeric(actual == colnames(pred[x])),
           plot_level = colnames(pred[x]))
}
# OOOOOOOF OH NO for some reason PTS_lead1 and all leaded V-Dem values missing
# for 2013 (i.e. 2014 values) and I don't want to go back and rerun all these
# models yet, so we do a temporary fix here and manually add the values from
# pts_clean and vdem_clean
withr::with_dir(here::here(), {
  tar_load(pts_clean)
  tar_load(vdem_clean)
})

pts_2014 <- pts_clean %>% 
  group_by(gwcode) %>% 
  mutate(across(c(PTS, PTS_factor),
                  list(lead1_2014 = ~lead(., 1)))) %>% 
  ungroup() %>% 
  filter(year == 2013) %>% 
  select(-PTS, -PTS_factor)

vdem_2014 <- vdem_clean %>% 
  group_by(gwcode) %>% 
  mutate(across(c(v2x_clphy, v2x_clpriv),
                  list(lead1_2014 = ~lead(., 1)))) %>% 
  ungroup() %>% 
  filter(year == 2013) %>% 
  select(gwcode, year, v2x_clphy_lead1_2014, v2x_clpriv_lead1_2014)

canary_testing_lagged <- canary_testing_lagged %>% 
  left_join(pts_2014, by = c("year", "gwcode")) %>% 
  left_join(vdem_2014, by = c("year", "gwcode")) %>% 
  mutate(PTS_lead1 = coalesce(PTS_lead1, PTS_lead1_2014),
         PTS_factor_lead1 = coalesce(PTS_factor_lead1, PTS_factor_lead1_2014),
         v2x_clphy_lead1 = coalesce(v2x_clphy_lead1, v2x_clphy_lead1_2014),
         v2x_clpriv_lead1 = coalesce(v2x_clpriv_lead1, v2x_clpriv_lead1_2014)) %>% 
  select(-contains("_2014"))

E1a: NGO laws and political terror

seed_pts_prediction <- 5494  # From random.org

set.seed(seed_pts_prediction)
pred_pts_baseline <- predict(
  m_pts_baseline_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

set.seed(seed_pts_prediction)
pred_pts_total <- predict(
  m_pts_total_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

set.seed(seed_pts_prediction)
pred_pts_advocacy <- predict(
  m_pts_advocacy_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

set.seed(seed_pts_prediction)
pred_pts_entry <- predict(
  m_pts_entry_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

set.seed(seed_pts_prediction)
pred_pts_funding <- predict(
  m_pts_funding_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

Separation plots

Baseline models

# Match each column in pred_mat (predicted probabilities for each response level)
pred_long_list <- lapply(1:ncol(pred_pts_baseline), 
                         FUN = match_actual, 
                         pred = pred_pts_baseline, 
                         actual = as.character(canary_testing_lagged$PTS_factor_lead1))

plot_data <- pred_long_list %>% 
  bind_rows() %>% 
  filter(!is.nan(fitted), !is.na(actual)) %>% 
  group_by(plot_level) %>% 
  arrange(plot_level, fitted) %>% 
  mutate(index = row_number()) %>% 
  ungroup()

markers <- plot_data %>% 
  group_by(plot_level) %>%
  summarize(obs = n(), expected = sum(fitted),
            marker = obs - expected + 1)

n_in_group <- nrow(pred_pts_baseline)

plot_data_condensed <- plot_data %>% 
  # rle(), dplyr-style: https://stackoverflow.com/a/33510765/120898
  mutate(rleid = (actual != lag(actual, 1, default = 0))) %>%
  mutate(rleid = cumsum(rleid)) %>% 
  group_by(plot_level, rleid) %>% 
  slice(1) %>% 
  group_by(plot_level) %>% 
  mutate(xmin = index, xmax = lead(index, default = n_in_group)) %>% 
  ungroup()

ggplot(plot_data_condensed) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = 0, ymax = 1, fill = as.factor(actual))) + 
  geom_line(aes(x = index, y = fitted), size = 0.3) +
  geom_point(data = markers, aes(x = marker, y = -0.05), shape = 17, size = 3) + 
  scale_fill_manual(values = c("grey90", "#2ECC40")) +
  guides(fill = FALSE) +
  facet_wrap(vars(plot_level), ncol = 1, scales = "free_x") +
  theme_void(base_family = "Inter Bold")

Models with NGO laws

Barriers to advocacy

# Match each column in pred_mat (predicted probabilities for each response level)
pred_long_list <- lapply(1:ncol(pred_pts_advocacy), 
                         FUN = match_actual, 
                         pred = pred_pts_advocacy, 
                         actual = as.character(canary_testing_lagged$PTS_factor_lead1))

plot_data <- pred_long_list %>% 
  bind_rows() %>% 
  filter(!is.nan(fitted), !is.na(actual)) %>% 
  group_by(plot_level) %>% 
  arrange(plot_level, fitted) %>% 
  mutate(index = row_number()) %>% 
  ungroup()

markers <- plot_data %>% 
  group_by(plot_level) %>%
  summarize(obs = n(), expected = sum(fitted),
            marker = obs - expected + 1)

n_in_group <- nrow(pred_pts_advocacy)

plot_data_condensed <- plot_data %>% 
  # rle(), dplyr-style: https://stackoverflow.com/a/33510765/120898
  mutate(rleid = (actual != lag(actual, 1, default = 0))) %>%
  mutate(rleid = cumsum(rleid)) %>% 
  group_by(plot_level, rleid) %>% 
  slice(1) %>% 
  group_by(plot_level) %>% 
  mutate(xmin = index, xmax = lead(index, default = n_in_group)) %>% 
  ungroup()

ggplot(plot_data_condensed) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = 0, ymax = 1, fill = as.factor(actual))) + 
  geom_line(aes(x = index, y = fitted), size = 0.3) +
  geom_point(data = markers, aes(x = marker, y = -0.05), shape = 17, size = 3) + 
  scale_fill_manual(values = c("grey90", "#2ECC40")) +
  guides(fill = FALSE) +
  facet_wrap(vars(plot_level), ncol = 1, scales = "free_x") +
  theme_void(base_family = "Inter Bold")

Barriers to entry

# Match each column in pred_mat (predicted probabilities for each response level)
pred_long_list <- lapply(1:ncol(pred_pts_entry), 
                         FUN = match_actual, 
                         pred = pred_pts_entry, 
                         actual = as.character(canary_testing_lagged$PTS_factor_lead1))

plot_data <- pred_long_list %>% 
  bind_rows() %>% 
  filter(!is.nan(fitted), !is.na(actual)) %>% 
  group_by(plot_level) %>% 
  arrange(plot_level, fitted) %>% 
  mutate(index = row_number()) %>% 
  ungroup()

markers <- plot_data %>% 
  group_by(plot_level) %>%
  summarize(obs = n(), expected = sum(fitted),
            marker = obs - expected + 1)

n_in_group <- nrow(pred_pts_entry)

plot_data_condensed <- plot_data %>% 
  # rle(), dplyr-style: https://stackoverflow.com/a/33510765/120898
  mutate(rleid = (actual != lag(actual, 1, default = 0))) %>%
  mutate(rleid = cumsum(rleid)) %>% 
  group_by(plot_level, rleid) %>% 
  slice(1) %>% 
  group_by(plot_level) %>% 
  mutate(xmin = index, xmax = lead(index, default = n_in_group)) %>% 
  ungroup()

ggplot(plot_data_condensed) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = 0, ymax = 1, fill = as.factor(actual))) + 
  geom_line(aes(x = index, y = fitted), size = 0.3) +
  geom_point(data = markers, aes(x = marker, y = -0.05), shape = 17, size = 3) + 
  scale_fill_manual(values = c("grey90", "#2ECC40")) +
  guides(fill = FALSE) +
  facet_wrap(vars(plot_level), ncol = 1, scales = "free_x") +
  theme_void(base_family = "Inter Bold")

Barriers to funding

# Match each column in pred_mat (predicted probabilities for each response level)
pred_long_list <- lapply(1:ncol(pred_pts_funding), 
                         FUN = match_actual, 
                         pred = pred_pts_funding, 
                         actual = as.character(canary_testing_lagged$PTS_factor_lead1))

plot_data <- pred_long_list %>% 
  bind_rows() %>% 
  filter(!is.nan(fitted), !is.na(actual)) %>% 
  group_by(plot_level) %>% 
  arrange(plot_level, fitted) %>% 
  mutate(index = row_number()) %>% 
  ungroup()

markers <- plot_data %>% 
  group_by(plot_level) %>%
  summarize(obs = n(), expected = sum(fitted),
            marker = obs - expected + 1)

n_in_group <- nrow(pred_pts_funding)

plot_data_condensed <- plot_data %>% 
  # rle(), dplyr-style: https://stackoverflow.com/a/33510765/120898
  mutate(rleid = (actual != lag(actual, 1, default = 0))) %>%
  mutate(rleid = cumsum(rleid)) %>% 
  group_by(plot_level, rleid) %>% 
  slice(1) %>% 
  group_by(plot_level) %>% 
  mutate(xmin = index, xmax = lead(index, default = n_in_group)) %>% 
  ungroup()

ggplot(plot_data_condensed) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = 0, ymax = 1, fill = as.factor(actual))) + 
  geom_line(aes(x = index, y = fitted), size = 0.3) +
  geom_point(data = markers, aes(x = marker, y = -0.05), shape = 17, size = 3) + 
  scale_fill_manual(values = c("grey90", "#2ECC40")) +
  guides(fill = FALSE) +
  facet_wrap(vars(plot_level), ncol = 1, scales = "free_x") +
  theme_void(base_family = "Inter Bold")

Prediction diagnostics

pred_pts_baseline_categories <- pred_pts_baseline %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)

pred_pts_total_categories <- pred_pts_total %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)

pred_pts_advocacy_categories <- pred_pts_advocacy %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)

pred_pts_entry_categories <- pred_pts_entry %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)

pred_pts_funding_categories <- pred_pts_funding %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)


pts_cat_preds <- canary_testing_lagged %>% 
  select(country, year, actual = PTS_factor_lead1) %>% 
  mutate(pred_baseline = pred_pts_baseline_categories$predicted,
         pred_total = pred_pts_total_categories$predicted,
         pred_advocacy = pred_pts_advocacy_categories$predicted,
         pred_entry = pred_pts_entry_categories$predicted,
         pred_funding = pred_pts_funding_categories$predicted) %>% 
  filter(!is.na(actual)) %>%
  mutate(is_correct_baseline = actual == pred_baseline,
         is_correct_total = actual == pred_total,
         is_correct_advocacy = actual == pred_advocacy,
         is_correct_entry = actual == pred_entry,
         is_correct_funding = actual == pred_funding)

# Improved predictions
pts_improved_total <- pts_cat_preds %>% 
  filter(!is_correct_baseline & is_correct_total) %>% 
  select(Country = country, Year = year, Actual = actual,
         `CS repression included` = pred_total,
         `Baseline` = pred_baseline)

pts_improved_advocacy <- pts_cat_preds %>% 
  filter(!is_correct_baseline & is_correct_advocacy) %>% 
  select(Country = country, Year = year, Actual = actual,
         `CS repression included` = pred_advocacy,
         `Baseline` = pred_baseline)

pts_improved_entry <- pts_cat_preds %>% 
  filter(!is_correct_baseline & is_correct_entry) %>% 
  select(Country = country, Year = year, Actual = actual,
         `CS repression included` = pred_entry,
         `Baseline` = pred_baseline)

pts_improved_funding <- pts_cat_preds %>% 
  filter(!is_correct_baseline & is_correct_funding) %>% 
  select(Country = country, Year = year, Actual = actual,
         `CS repression included` = pred_funding,
         `Baseline` = pred_baseline)

pts_improved_total %>% 
  kbl(caption = "Cases improved with total legal barriers") %>% 
  kable_styling()
Cases improved with total legal barriers
Country Year Actual CS repression included Baseline
Guatemala 2013 Level 3 Level 3 Level 2
Kosovo 2012 Level 1 Level 1 Level 2
Sierra Leone 2011 Level 3 Level 3 Level 2
Congo - Brazzaville 2011 Level 3 Level 3 Level 2
Somalia 2013 Level 5 Level 5 Level 4
Bahrain 2011 Level 3 Level 3 Level 2
Bahrain 2013 Level 3 Level 3 Level 2
pts_improved_advocacy %>% 
  kbl(caption = "Cases improved with barriers to advocacy") %>% 
  kable_styling()
Cases improved with barriers to advocacy
Country Year Actual CS repression included Baseline
Guatemala 2013 Level 3 Level 3 Level 2
Bulgaria 2012 Level 2 Level 2 Level 1
Congo - Brazzaville 2011 Level 3 Level 3 Level 2
Bahrain 2011 Level 3 Level 3 Level 2
Bahrain 2013 Level 3 Level 3 Level 2
pts_improved_entry %>% 
  kbl(caption = "Cases improved with barriers to entry") %>% 
  kable_styling()
Cases improved with barriers to entry
Country Year Actual CS repression included Baseline
Guatemala 2013 Level 3 Level 3 Level 2
Kosovo 2012 Level 1 Level 1 Level 2
Sierra Leone 2011 Level 3 Level 3 Level 2
Congo - Brazzaville 2011 Level 3 Level 3 Level 2
Bahrain 2011 Level 3 Level 3 Level 2
pts_improved_funding %>% 
  kbl(caption = "Cases improved with barriers to funding") %>% 
  kable_styling()
Cases improved with barriers to funding
Country Year Actual CS repression included Baseline
Guatemala 2013 Level 3 Level 3 Level 2
Bulgaria 2012 Level 2 Level 2 Level 1
Sierra Leone 2011 Level 3 Level 3 Level 2
Congo - Brazzaville 2011 Level 3 Level 3 Level 2
Tunisia 2013 Level 3 Level 3 Level 2
Bahrain 2011 Level 3 Level 3 Level 2
Bahrain 2013 Level 3 Level 3 Level 2
correct_lookup <- tribble(
  ~name, ~nice_name,
  "is_correct_total", "Total legal barriers included",
  "is_correct_advocacy", "Barriers to advocacy included",
  "is_correct_entry", "Barriers to entry included",
  "is_correct_funding", "Barriers to funding included",
  "is_correct_baseline", "Baseline"
) %>% mutate(nice_name = fct_inorder(nice_name, ordered = TRUE))

pts_pred_table <- pts_cat_preds %>% 
  pivot_longer(starts_with("is_correct")) %>% 
  group_by(name, value) %>% 
  summarize(n = n()) %>% 
  ungroup() %>% 
  left_join(correct_lookup, by = "name") %>% 
  mutate(Prediction = ifelse(value == TRUE, "Correct", "Wrong")) %>% 
  arrange(nice_name) %>% 
  select(-name, -value) %>% 
  pivot_wider(names_from = "nice_name", values_from = "n")

pts_pred_table %>% 
  kbl(align = "lccccc") %>% 
  kable_styling()
Prediction Total legal barriers included Barriers to advocacy included Barriers to entry included Barriers to funding included Baseline
Wrong 108 110 108 109 108
Correct 377 375 377 376 377

 

E1b: NGO laws and physical violence

seed_clphy_prediction <- 7285  # From random.org

set.seed(seed_clphy_prediction)
pred_clphy_baseline <- predict(m_clphy_baseline_train, 
                               newdata = select(canary_testing_lagged, -v2x_clphy_lead1),
                               allow_new_levels = TRUE)

set.seed(seed_clphy_prediction)
pred_clphy_total <- predict(m_clphy_total_train, 
                            newdata = select(canary_testing_lagged, -v2x_clphy_lead1),
                            allow_new_levels = TRUE)

set.seed(seed_clphy_prediction)
pred_clphy_advocacy <- predict(m_clphy_advocacy_train, 
                               newdata = select(canary_testing_lagged, -v2x_clphy_lead1),
                               allow_new_levels = TRUE)

set.seed(seed_clphy_prediction)
pred_clphy_entry <- predict(m_clphy_entry_train, 
                            newdata = select(canary_testing_lagged, -v2x_clphy_lead1),
                            allow_new_levels = TRUE)

set.seed(seed_clphy_prediction)
pred_clphy_funding <- predict(m_clphy_funding_train, 
                              newdata = select(canary_testing_lagged, -v2x_clphy_lead1),
                              allow_new_levels = TRUE)

pred_clphy_baseline_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clphy_lead1) %>% 
  bind_cols(as_tibble(pred_clphy_baseline)) %>% 
  filter(!is.na(v2x_clphy_lead1))

pred_clphy_total_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clphy_lead1) %>% 
  bind_cols(as_tibble(pred_clphy_total)) %>% 
  filter(!is.na(v2x_clphy_lead1))

pred_clphy_advocacy_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clphy_lead1) %>% 
  bind_cols(as_tibble(pred_clphy_advocacy)) %>% 
  filter(!is.na(v2x_clphy_lead1))

pred_clphy_entry_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clphy_lead1) %>% 
  bind_cols(as_tibble(pred_clphy_entry)) %>% 
  filter(!is.na(v2x_clphy_lead1))

pred_clphy_funding_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clphy_lead1) %>% 
  bind_cols(as_tibble(pred_clphy_funding)) %>% 
  filter(!is.na(v2x_clphy_lead1))

Improvement from baseline models

plot_baseline <- ggplot(pred_clphy_baseline_test, 
                        aes(x = v2x_clphy_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Baseline",
       x = "Actual physical violence index (t + 1)",
       y = "Predicted physical violence index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_total <- ggplot(pred_clphy_total_test, 
                     aes(x = v2x_clphy_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Total legal barriers",
       x = "Actual physical violence index (t + 1)",
       y = "Predicted physical violence index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_advocacy <- ggplot(pred_clphy_advocacy_test, 
                        aes(x = v2x_clphy_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Barriers to advocacy",
       x = "Actual physical violence index (t + 1)",
       y = "Predicted physical violence index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_entry <- ggplot(pred_clphy_entry_test, 
                     aes(x = v2x_clphy_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Barriers to entry",
       x = "Actual physical violence index (t + 1)",
       y = "Predicted physical violence index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_funding <- ggplot(pred_clphy_funding_test, 
                       aes(x = v2x_clphy_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Barriers to funding",
       x = "Actual physical violence index (t + 1)",
       y = "Predicted physical violence index (t + 1)") +
  coord_equal() +
  theme_ngo()

(plot_baseline | plot_total) / (plot_advocacy | plot_entry | plot_funding)

lotsa_metrics <- metric_set(rmse, rsq, mae, ccc)

bind_rows(lotsa_metrics(pred_clphy_baseline_test, 
                        truth = v2x_clphy_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Baseline"),
          lotsa_metrics(pred_clphy_total_test, 
                        truth = v2x_clphy_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Total legal barriers"),
          lotsa_metrics(pred_clphy_advocacy_test, 
                        truth = v2x_clphy_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Barriers to advocacy"),
          lotsa_metrics(pred_clphy_entry_test, 
                        truth = v2x_clphy_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Barriers to entry"),
          lotsa_metrics(pred_clphy_funding_test, 
                        truth = v2x_clphy_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Barriers to funding")) %>% 
  select(Model, .metric, .estimate) %>% 
  pivot_wider(names_from = ".metric", values_from = ".estimate")
Model rmse rsq mae ccc
Baseline 0.0462298 0.9707000 0.0217192 0.9826965
Total legal barriers 0.0460839 0.9705974 0.0218036 0.9828507
Barriers to advocacy 0.0460425 0.9707562 0.0218699 0.9828543
Barriers to entry 0.0461553 0.9706090 0.0217330 0.9827806
Barriers to funding 0.0462081 0.9704927 0.0218077 0.9827586

Most improved countries

Barriers to advocacy

most_improved_clphy_advocacy <- bind_cols(
  pred_clphy_baseline_test %>% 
    mutate(error_baseline = Estimate - v2x_clphy_lead1) %>% 
    select(country, gwcode, year, v2x_clphy_lead1, 
           estimate_baseline = Estimate, error_baseline),
  pred_clphy_advocacy_test %>% 
    mutate(error_advocacy = Estimate - v2x_clphy_lead1) %>% 
    select(estimate_advocacy = Estimate, error_advocacy)
) %>% 
  mutate(improved = error_advocacy < 0 & abs(error_advocacy) < abs(error_baseline)) %>% 
  mutate(diff = error_advocacy - error_baseline) %>% 
  mutate(abs_diff = abs(diff)) %>% 
  filter(improved) %>% 
  arrange(desc(abs_diff))

nrow(most_improved_clphy_advocacy)
## [1] 90
most_improved_clphy_advocacy %>% 
  select(Country = country, Year = year, 
         `Actual physical violence index (t + 1)` =  v2x_clphy_lead1,
         `Predicted (baseline)` = estimate_baseline,
         `Predicted (CS repression)` = estimate_advocacy,
         `|CS repression − baseline|` = abs_diff) %>% 
  head(5) %>% 
  kbl(digits = 3, align = "lccccc") %>% 
  kable_styling()
Country Year Actual physical violence index (t + 1) Predicted (baseline) Predicted (CS repression) |CS repression − baseline|
Ethiopia 2011 0.353 0.361 0.350 0.011
Ethiopia 2013 0.317 0.327 0.316 0.011
India 2011 0.669 0.674 0.664 0.011
Egypt 2011 0.344 0.321 0.326 0.005
Australia 2011 0.957 0.959 0.955 0.004

Barriers to entry

most_improved_clphy_entry <- bind_cols(
  pred_clphy_baseline_test %>% 
    mutate(error_baseline = Estimate - v2x_clphy_lead1) %>% 
    select(country, gwcode, year, v2x_clphy_lead1, 
           estimate_baseline = Estimate, error_baseline),
  pred_clphy_entry_test %>% 
    mutate(error_entry = Estimate - v2x_clphy_lead1) %>% 
    select(estimate_entry = Estimate, error_entry)
) %>% 
  mutate(improved = error_entry < 0 & abs(error_entry) < abs(error_baseline)) %>% 
  mutate(diff = error_entry - error_baseline) %>% 
  mutate(abs_diff = abs(diff)) %>% 
  filter(improved) %>% 
  arrange(desc(abs_diff))

nrow(most_improved_clphy_entry)
## [1] 66
most_improved_clphy_entry %>% 
  select(Country = country, Year = year, 
         `Actual physical violence index (t + 1)` =  v2x_clphy_lead1,
         `Predicted (baseline)` = estimate_baseline,
         `Predicted (CS repression)` = estimate_entry,
         `|CS repression − baseline|` = abs_diff) %>% 
  head(5) %>% 
  kbl(digits = 3, align = "lccccc") %>% 
  kable_styling()
Country Year Actual physical violence index (t + 1) Predicted (baseline) Predicted (CS repression) |CS repression − baseline|
Sierra Leone 2013 0.727 0.731 0.727 0.005
Rwanda 2012 0.598 0.601 0.597 0.004
Somalia 2011 0.163 0.166 0.162 0.004
Cambodia 2012 0.430 0.433 0.430 0.004
Mauritania 2013 0.546 0.547 0.545 0.002

Barriers to funding

most_improved_clphy_funding <- bind_cols(
  pred_clphy_baseline_test %>% 
    mutate(error_baseline = Estimate - v2x_clphy_lead1) %>% 
    select(country, gwcode, year, v2x_clphy_lead1, 
           estimate_baseline = Estimate, error_baseline),
  pred_clphy_funding_test %>% 
    mutate(error_funding = Estimate - v2x_clphy_lead1) %>% 
    select(estimate_funding = Estimate, error_funding)
) %>% 
  mutate(improved = error_funding < 0 & abs(error_funding) < abs(error_baseline)) %>% 
  mutate(diff = error_funding - error_baseline) %>% 
  mutate(abs_diff = abs(diff)) %>% 
  filter(improved) %>% 
  arrange(desc(abs_diff))

nrow(most_improved_clphy_funding)
## [1] 89
most_improved_clphy_funding %>% 
  select(Country = country, Year = year, 
         `Actual physical violence index (t + 1)` =  v2x_clphy_lead1,
         `Predicted (baseline)` = estimate_baseline,
         `Predicted (CS repression)` = estimate_funding,
         `|CS repression − baseline|` = abs_diff) %>% 
  head(5) %>% 
  kbl(digits = 3, align = "lccccc") %>% 
  kable_styling()
Country Year Actual physical violence index (t + 1) Predicted (baseline) Predicted (CS repression) |CS repression − baseline|
North Korea 2012 0.052 0.060 0.049 0.012
India 2011 0.669 0.674 0.664 0.011
China 2013 0.390 0.395 0.387 0.008
Peru 2013 0.810 0.815 0.808 0.007
Peru 2012 0.810 0.814 0.808 0.006

 

E1c: NGO laws and civil liberties

seed_clpriv_prediction <- 6670  # From random.org

set.seed(seed_clpriv_prediction)
pred_clpriv_baseline <- predict(m_clpriv_baseline_train, 
                                newdata = select(canary_testing_lagged, -v2x_clpriv_lead1),
                                allow_new_levels = TRUE)

set.seed(seed_clpriv_prediction)
pred_clpriv_total <- predict(m_clpriv_total_train, 
                             newdata = select(canary_testing_lagged, -v2x_clpriv_lead1),
                             allow_new_levels = TRUE)

set.seed(seed_clpriv_prediction)
pred_clpriv_advocacy <- predict(m_clpriv_advocacy_train, 
                                newdata = select(canary_testing_lagged, -v2x_clpriv_lead1),
                                allow_new_levels = TRUE)

set.seed(seed_clpriv_prediction)
pred_clpriv_entry <- predict(m_clpriv_entry_train, 
                             newdata = select(canary_testing_lagged, -v2x_clpriv_lead1),
                             allow_new_levels = TRUE)

set.seed(seed_clpriv_prediction)
pred_clpriv_funding <- predict(m_clpriv_funding_train, 
                               newdata = select(canary_testing_lagged, -v2x_clpriv_lead1),
                               allow_new_levels = TRUE)

pred_clpriv_baseline_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clpriv_lead1) %>% 
  bind_cols(as_tibble(pred_clpriv_baseline)) %>% 
  filter(!is.na(v2x_clpriv_lead1))

pred_clpriv_total_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clpriv_lead1) %>% 
  bind_cols(as_tibble(pred_clpriv_total)) %>% 
  filter(!is.na(v2x_clpriv_lead1))

pred_clpriv_advocacy_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clpriv_lead1) %>% 
  bind_cols(as_tibble(pred_clpriv_advocacy)) %>% 
  filter(!is.na(v2x_clpriv_lead1))

pred_clpriv_entry_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clpriv_lead1) %>% 
  bind_cols(as_tibble(pred_clpriv_entry)) %>% 
  filter(!is.na(v2x_clpriv_lead1))

pred_clpriv_funding_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clpriv_lead1) %>% 
  bind_cols(as_tibble(pred_clpriv_funding)) %>% 
  filter(!is.na(v2x_clpriv_lead1))

Improvement from baseline models

plot_baseline <- ggplot(pred_clpriv_baseline_test, 
                        aes(x = v2x_clpriv_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Baseline",
       x = "Actual private civil liberties index (t + 1)",
       y = "Predicted private civil liberties index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_total <- ggplot(pred_clpriv_total_test, 
                     aes(x = v2x_clpriv_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Total legal barriers",
       x = "Actual private civil liberties index (t + 1)",
       y = "Predicted private civil liberties index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_advocacy <- ggplot(pred_clpriv_advocacy_test, 
                        aes(x = v2x_clpriv_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Barriers to advocacy",
       x = "Actual private civil liberties index (t + 1)",
       y = "Predicted private civil liberties index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_entry <- ggplot(pred_clpriv_entry_test, 
                     aes(x = v2x_clpriv_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Barriers to entry",
       x = "Actual private civil liberties index (t + 1)",
       y = "Predicted private civil liberties index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_funding <- ggplot(pred_clpriv_funding_test, 
                       aes(x = v2x_clpriv_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Barriers to funding",
       x = "Actual private civil liberties index (t + 1)",
       y = "Predicted private civil liberties index (t + 1)") +
  coord_equal() +
  theme_ngo()

(plot_baseline | plot_total) / (plot_advocacy | plot_entry | plot_funding)

lotsa_metrics <- metric_set(rmse, rsq, mae, ccc)

bind_rows(lotsa_metrics(pred_clpriv_baseline_test, 
                        truth = v2x_clpriv_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Baseline"),
          lotsa_metrics(pred_clpriv_total_test, 
                        truth = v2x_clpriv_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Total legal barriers"),
          lotsa_metrics(pred_clpriv_advocacy_test, 
                        truth = v2x_clpriv_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Barriers to advocacy"),
          lotsa_metrics(pred_clpriv_entry_test, 
                        truth = v2x_clpriv_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Barriers to entry"),
          lotsa_metrics(pred_clpriv_funding_test, 
                        truth = v2x_clpriv_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Barriers to funding")) %>% 
  select(Model, .metric, .estimate) %>% 
  pivot_wider(names_from = ".metric", values_from = ".estimate")
Model rmse rsq mae ccc
Baseline 0.0339090 0.9822248 0.0202861 0.9884043
Total legal barriers 0.0333961 0.9822554 0.0195166 0.9886965
Barriers to advocacy 0.0336028 0.9821524 0.0198032 0.9885643
Barriers to entry 0.0334257 0.9823587 0.0196743 0.9886645
Barriers to funding 0.0335855 0.9821239 0.0196915 0.9885792

Most improved countries

Barriers to advocacy

most_improved_clpriv_advocacy <- bind_cols(
  pred_clpriv_baseline_test %>% 
    mutate(error_baseline = Estimate - v2x_clpriv_lead1) %>% 
    select(country, gwcode, year, v2x_clpriv_lead1, 
           estimate_baseline = Estimate, error_baseline),
  pred_clpriv_advocacy_test %>% 
    mutate(error_advocacy = Estimate - v2x_clpriv_lead1) %>% 
    select(estimate_advocacy = Estimate, error_advocacy)
) %>% 
  mutate(improved = error_advocacy < 0 & abs(error_advocacy) < abs(error_baseline)) %>% 
  mutate(diff = error_advocacy - error_baseline) %>% 
  mutate(abs_diff = abs(diff)) %>% 
  filter(improved) %>% 
  arrange(desc(abs_diff))

nrow(most_improved_clpriv_advocacy)
## [1] 87
most_improved_clpriv_advocacy %>% 
  select(Country = country, Year = year, 
         `Actual physical violence index (t + 1)` =  v2x_clpriv_lead1,
         `Predicted (baseline)` = estimate_baseline,
         `Predicted (CS repression)` = estimate_advocacy,
         `|CS repression − baseline|` = abs_diff) %>% 
  head(5) %>% 
  kbl(digits = 3, align = "lccccc") %>% 
  kable_styling()
Country Year Actual physical violence index (t + 1) Predicted (baseline) Predicted (CS repression) |CS repression − baseline|
Sudan 2013 0.120 0.124 0.118 0.006
Colombia 2011 0.827 0.833 0.827 0.006
Zimbabwe 2012 0.638 0.643 0.638 0.006
Benin 2012 0.920 0.923 0.919 0.004
South Korea 2013 0.896 0.899 0.895 0.004

Barriers to entry

most_improved_clpriv_entry <- bind_cols(
  pred_clpriv_baseline_test %>% 
    mutate(error_baseline = Estimate - v2x_clpriv_lead1) %>% 
    select(country, gwcode, year, v2x_clpriv_lead1, 
           estimate_baseline = Estimate, error_baseline),
  pred_clpriv_entry_test %>% 
    mutate(error_entry = Estimate - v2x_clpriv_lead1) %>% 
    select(estimate_entry = Estimate, error_entry)
) %>% 
  mutate(improved = error_entry < 0 & abs(error_entry) < abs(error_baseline)) %>% 
  mutate(diff = error_entry - error_baseline) %>% 
  mutate(abs_diff = abs(diff)) %>% 
  filter(improved) %>% 
  arrange(desc(abs_diff))

nrow(most_improved_clpriv_entry)
## [1] 83
most_improved_clpriv_entry %>% 
  select(Country = country, Year = year, 
         `Actual physical violence index (t + 1)` =  v2x_clpriv_lead1,
         `Predicted (baseline)` = estimate_baseline,
         `Predicted (CS repression)` = estimate_entry,
         `|CS repression − baseline|` = abs_diff) %>% 
  head(5) %>% 
  kbl(digits = 3, align = "lccccc") %>% 
  kable_styling()
Country Year Actual physical violence index (t + 1) Predicted (baseline) Predicted (CS repression) |CS repression − baseline|
Iran 2013 0.407 0.409 0.405 0.004
Croatia 2012 0.925 0.928 0.924 0.004
Madagascar 2013 0.763 0.712 0.716 0.003
Montenegro 2013 0.906 0.900 0.903 0.003
Bangladesh 2013 0.661 0.663 0.660 0.003

Barriers to funding

most_improved_clpriv_funding <- bind_cols(
  pred_clpriv_baseline_test %>% 
    mutate(error_baseline = Estimate - v2x_clpriv_lead1) %>% 
    select(country, gwcode, year, v2x_clpriv_lead1, 
           estimate_baseline = Estimate, error_baseline),
  pred_clpriv_funding_test %>% 
    mutate(error_funding = Estimate - v2x_clpriv_lead1) %>% 
    select(estimate_funding = Estimate, error_funding)
) %>% 
  mutate(improved = error_funding < 0 & abs(error_funding) < abs(error_baseline)) %>% 
  mutate(diff = error_funding - error_baseline) %>% 
  mutate(abs_diff = abs(diff)) %>% 
  filter(improved) %>% 
  arrange(desc(abs_diff))

nrow(most_improved_clpriv_funding)
## [1] 96
most_improved_clpriv_funding %>% 
  select(Country = country, Year = year, 
         `Actual physical violence index (t + 1)` =  v2x_clpriv_lead1,
         `Predicted (baseline)` = estimate_baseline,
         `Predicted (CS repression)` = estimate_funding,
         `|CS repression − baseline|` = abs_diff) %>% 
  head(5) %>% 
  kbl(digits = 3, align = "lccccc") %>% 
  kable_styling()
Country Year Actual physical violence index (t + 1) Predicted (baseline) Predicted (CS repression) |CS repression − baseline|
Eritrea 2011 0.013 0.021 0.012 0.009
Eritrea 2013 0.012 0.020 0.011 0.009
China 2012 0.219 0.227 0.219 0.008
Burkina Faso 2012 0.846 0.851 0.845 0.006
Madagascar 2013 0.763 0.712 0.716 0.004

 


 

E2a: Civil society environment and political terror

seed_pts_prediction <- 5494  # From random.org

set.seed(seed_pts_prediction)
pred_pts_baseline <- predict(
  m_pts_baseline_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

set.seed(seed_pts_prediction)
pred_pts_v2csreprss <- predict(
  m_pts_v2csreprss_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

set.seed(seed_pts_prediction)
pred_pts_baseline_rewb <- predict(
  m_pts_baseline_rewb_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

set.seed(seed_pts_prediction)
pred_pts_v2csreprss_rewb <- predict(
  m_pts_v2csreprss_rewb_train, 
  newdata = select(canary_testing_lagged, -PTS_factor_lead1),
  allow_new_levels = TRUE
) %>% 
  as_tibble() %>% 
  magrittr::set_colnames(pts_levels)

Separation plots

Baseline model

# Match each column in pred_mat (predicted probabilities for each response level)
pred_long_list <- lapply(1:ncol(pred_pts_baseline), 
                         FUN = match_actual, 
                         pred = pred_pts_baseline, 
                         actual = as.character(canary_testing_lagged$PTS_factor_lead1))

plot_data <- pred_long_list %>% 
  bind_rows() %>% 
  filter(!is.nan(fitted), !is.na(actual)) %>% 
  group_by(plot_level) %>% 
  arrange(plot_level, fitted) %>% 
  mutate(index = row_number()) %>% 
  ungroup()

markers <- plot_data %>% 
  group_by(plot_level) %>%
  summarize(obs = n(), expected = sum(fitted),
            marker = obs - expected + 1)

n_in_group <- nrow(pred_pts_baseline)

plot_data_condensed <- plot_data %>% 
  # rle(), dplyr-style: https://stackoverflow.com/a/33510765/120898
  mutate(rleid = (actual != lag(actual, 1, default = 0))) %>%
  mutate(rleid = cumsum(rleid)) %>% 
  group_by(plot_level, rleid) %>% 
  slice(1) %>% 
  group_by(plot_level) %>% 
  mutate(xmin = index, xmax = lead(index, default = n_in_group)) %>% 
  ungroup()

ggplot(plot_data_condensed) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = 0, ymax = 1, fill = as.factor(actual))) + 
  geom_line(aes(x = index, y = fitted), size = 0.3) +
  geom_point(data = markers, aes(x = marker, y = -0.05), shape = 17, size = 3) + 
  scale_fill_manual(values = c("grey90", "#2ECC40")) +
  guides(fill = FALSE) +
  facet_wrap(vars(plot_level), ncol = 1, scales = "free_x") +
  theme_void(base_family = "Inter Bold")

Model with civil society repression

pred_long_list <- lapply(1:ncol(pred_pts_v2csreprss), 
                         FUN = match_actual, 
                         pred = pred_pts_v2csreprss, 
                         actual = as.character(canary_testing_lagged$PTS_factor_lead1))

plot_data <- pred_long_list %>% 
  bind_rows() %>% 
  filter(!is.nan(fitted), !is.na(actual)) %>% 
  group_by(plot_level) %>% 
  arrange(plot_level, fitted) %>% 
  mutate(index = row_number()) %>% 
  ungroup()

markers <- plot_data %>% 
  group_by(plot_level) %>%
  summarize(obs = n(), expected = sum(fitted),
            marker = obs - expected + 1)

n_in_group <- nrow(pred_pts_v2csreprss)

plot_data_condensed <- plot_data %>% 
  # rle(), dplyr-style: https://stackoverflow.com/a/33510765/120898
  mutate(rleid = (actual != lag(actual, 1, default = 0))) %>%
  mutate(rleid = cumsum(rleid)) %>% 
  group_by(plot_level, rleid) %>% 
  slice(1) %>% 
  group_by(plot_level) %>% 
  mutate(xmin = index, xmax = lead(index, default = n_in_group)) %>% 
  ungroup()

ggplot(plot_data_condensed) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = 0, ymax = 1, fill = as.factor(actual))) + 
  geom_line(aes(x = index, y = fitted), size = 0.3) +
  geom_point(data = markers, aes(x = marker, y = -0.05), shape = 17, size = 3) + 
  scale_fill_manual(values = c("grey90", "#2ECC40")) +
  guides(fill = FALSE) +
  facet_wrap(vars(plot_level), ncol = 1, scales = "free_x") +
  theme_void(base_family = "Inter Bold")

Baseline model (REWB)

# Match each column in pred_mat (predicted probabilities for each response level)
pred_long_list <- lapply(1:ncol(pred_pts_baseline_rewb), 
                         FUN = match_actual, 
                         pred = pred_pts_baseline_rewb, 
                         actual = as.character(canary_testing_lagged$PTS_factor_lead1))

plot_data <- pred_long_list %>% 
  bind_rows() %>% 
  filter(!is.nan(fitted), !is.na(actual)) %>% 
  group_by(plot_level) %>% 
  arrange(plot_level, fitted) %>% 
  mutate(index = row_number()) %>% 
  ungroup()

markers <- plot_data %>% 
  group_by(plot_level) %>%
  summarize(obs = n(), expected = sum(fitted),
            marker = obs - expected + 1)

n_in_group <- nrow(pred_pts_baseline_rewb)

plot_data_condensed <- plot_data %>% 
  # rle(), dplyr-style: https://stackoverflow.com/a/33510765/120898
  mutate(rleid = (actual != lag(actual, 1, default = 0))) %>%
  mutate(rleid = cumsum(rleid)) %>% 
  group_by(plot_level, rleid) %>% 
  slice(1) %>% 
  group_by(plot_level) %>% 
  mutate(xmin = index, xmax = lead(index, default = n_in_group)) %>% 
  ungroup()

ggplot(plot_data_condensed) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = 0, ymax = 1, fill = as.factor(actual))) + 
  geom_line(aes(x = index, y = fitted), size = 0.3) +
  geom_point(data = markers, aes(x = marker, y = -0.05), shape = 17, size = 3) + 
  scale_fill_manual(values = c("grey90", "#2ECC40")) +
  guides(fill = FALSE) +
  facet_wrap(vars(plot_level), ncol = 1, scales = "free_x") +
  theme_void(base_family = "Inter Bold")

Model with civil society repression (REWB)

pred_long_list <- lapply(1:ncol(pred_pts_v2csreprss_rewb), 
                         FUN = match_actual, 
                         pred = pred_pts_v2csreprss_rewb, 
                         actual = as.character(canary_testing_lagged$PTS_factor_lead1))

plot_data <- pred_long_list %>% 
  bind_rows() %>% 
  filter(!is.nan(fitted), !is.na(actual)) %>% 
  group_by(plot_level) %>% 
  arrange(plot_level, fitted) %>% 
  mutate(index = row_number()) %>% 
  ungroup()

markers <- plot_data %>% 
  group_by(plot_level) %>%
  summarize(obs = n(), expected = sum(fitted),
            marker = obs - expected + 1)

n_in_group <- nrow(pred_pts_v2csreprss_rewb)

plot_data_condensed <- plot_data %>% 
  # rle(), dplyr-style: https://stackoverflow.com/a/33510765/120898
  mutate(rleid = (actual != lag(actual, 1, default = 0))) %>%
  mutate(rleid = cumsum(rleid)) %>% 
  group_by(plot_level, rleid) %>% 
  slice(1) %>% 
  group_by(plot_level) %>% 
  mutate(xmin = index, xmax = lead(index, default = n_in_group)) %>% 
  ungroup()

ggplot(plot_data_condensed) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = 0, ymax = 1, fill = as.factor(actual))) + 
  geom_line(aes(x = index, y = fitted), size = 0.3) +
  geom_point(data = markers, aes(x = marker, y = -0.05), shape = 17, size = 3) + 
  scale_fill_manual(values = c("grey90", "#2ECC40")) +
  guides(fill = FALSE) +
  facet_wrap(vars(plot_level), ncol = 1, scales = "free_x") +
  theme_void(base_family = "Inter Bold")

Prediction diagnostics

pred_pts_baseline_categories <- pred_pts_baseline %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)

pred_pts_v2csreprss_categories <- pred_pts_v2csreprss %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)

pred_pts_baseline_categories_rewb <- pred_pts_baseline_rewb %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)

pred_pts_v2csreprss_categories_rewb <- pred_pts_v2csreprss_rewb %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  group_by(rowname) %>% 
  filter(rank(-value, ties.method = "last") == 1) %>% 
  ungroup() %>% 
  select(predicted = name)

pts_cat_preds <- canary_testing_lagged %>% 
  select(country, year, actual = PTS_factor_lead1) %>% 
  mutate(pred_baseline = pred_pts_baseline_categories$predicted,
         pred_v2csreprss = pred_pts_v2csreprss_categories$predicted) %>% 
  filter(!is.na(actual)) %>%
  mutate(is_correct_baseline = actual == pred_baseline,
         is_correct_v2csreprss = actual == pred_v2csreprss)

pts_cat_preds_rewb <- canary_testing_lagged %>% 
  select(country, year, actual = PTS_factor_lead1) %>% 
  mutate(pred_baseline = pred_pts_baseline_categories_rewb$predicted,
         pred_v2csreprss = pred_pts_v2csreprss_categories_rewb$predicted) %>% 
  filter(!is.na(actual)) %>%
  mutate(is_correct_baseline = actual == pred_baseline,
         is_correct_v2csreprss = actual == pred_v2csreprss)

# Improved predictions
pts_improved <- pts_cat_preds %>% 
  filter(!is_correct_baseline & is_correct_v2csreprss) %>% 
  select(Country = country, Year = year, Actual = actual,
         `CS repression included` = pred_v2csreprss,
         `Baseline` = pred_baseline)

pts_improved_rewb <- pts_cat_preds_rewb %>% 
  filter(!is_correct_baseline & is_correct_v2csreprss) %>% 
  select(Country = country, Year = year, Actual = actual,
         `CS repression included` = pred_v2csreprss,
         `Baseline` = pred_baseline)

pts_improved %>% 
  kbl() %>% 
  kable_styling()
Country Year Actual CS repression included Baseline
Guatemala 2013 Level 3 Level 3 Level 2
Kosovo 2012 Level 1 Level 1 Level 2
Congo - Brazzaville 2011 Level 3 Level 3 Level 2
Libya 2011 Level 4 Level 4 Level 5
Bahrain 2011 Level 3 Level 3 Level 2
Bahrain 2013 Level 3 Level 3 Level 2
correct_lookup <- tribble(
  ~name, ~nice_name,
  "is_correct_v2csreprss", "CS repression included",
  "is_correct_baseline", "Baseline"
) %>% mutate(nice_name = fct_inorder(nice_name, ordered = TRUE))

pts_pred_table <- pts_cat_preds %>% 
  pivot_longer(starts_with("is_correct")) %>% 
  group_by(name, value) %>% 
  summarize(n = n()) %>% 
  ungroup() %>% 
  left_join(correct_lookup, by = "name") %>% 
  mutate(Prediction = ifelse(value == TRUE, "Correct", "Wrong")) %>% 
  arrange(nice_name) %>% 
  select(-name, -value) %>% 
  pivot_wider(names_from = "nice_name", values_from = "n")

pts_pred_table_rewb <- pts_cat_preds_rewb %>% 
  pivot_longer(starts_with("is_correct")) %>% 
  group_by(name, value) %>% 
  summarize(n = n()) %>% 
  ungroup() %>% 
  left_join(correct_lookup, by = "name") %>% 
  mutate(Prediction = ifelse(value == TRUE, "Correct", "Wrong")) %>% 
  arrange(nice_name) %>% 
  select(-name, -value) %>% 
  pivot_wider(names_from = "nice_name", values_from = "n")

pts_pred_table %>% 
  kbl(align = "lcc") %>% 
  kable_styling()
Prediction CS repression included Baseline
Wrong 111 108
Correct 374 377
pts_pred_table_rewb %>% 
  kbl(align = "lcc") %>% 
  kable_styling()
Prediction CS repression included Baseline
Wrong 108 106
Correct 377 379

 

E2b: Civil society environment and physical violence

seed_clphy_prediction <- 7285  # From random.org

set.seed(seed_clphy_prediction)
pred_clphy_baseline <- predict(m_clphy_baseline_train, 
                          newdata = select(canary_testing_lagged, -v2x_clphy_lead1),
                          allow_new_levels = TRUE)

set.seed(seed_clphy_prediction)
pred_clphy_v2csreprss <- predict(m_clphy_v2csreprss_train, 
                 newdata = select(canary_testing_lagged, -v2x_clphy_lead1),
                 allow_new_levels = TRUE)

pred_clphy_baseline_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clphy_lead1) %>% 
  bind_cols(as_tibble(pred_clphy_baseline)) %>% 
  filter(!is.na(v2x_clphy_lead1))

pred_clphy_v2csreprss_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clphy_lead1) %>% 
  bind_cols(as_tibble(pred_clphy_v2csreprss)) %>% 
  filter(!is.na(v2x_clphy_lead1))

Improvement from baseline models

plot_baseline <- ggplot(pred_clphy_baseline_test, 
                        aes(x = v2x_clphy_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Baseline",
       x = "Actual physical violence index (t + 1)",
       y = "Predicted physical violence index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_v2csreprss <- ggplot(pred_clphy_v2csreprss_test, 
                          aes(x = v2x_clphy_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Added predictor",
       x = "Actual physical violence index (t + 1)",
       y = "Predicted physical violence index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_baseline | plot_v2csreprss

lotsa_metrics <- metric_set(rmse, rsq, mae, ccc)

bind_rows(lotsa_metrics(pred_clphy_baseline_test, 
                        truth = v2x_clphy_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Baseline"),
          lotsa_metrics(pred_clphy_v2csreprss_test, 
                        truth = v2x_clphy_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Added predictor")) %>% 
  select(Model, .metric, .estimate) %>% 
  pivot_wider(names_from = ".metric", values_from = ".estimate")
Model rmse rsq mae ccc
Baseline 0.0462298 0.9707000 0.0217192 0.9826965
Added predictor 0.0461750 0.9705902 0.0228861 0.9827102

Most improved countries

most_improved_clphy <- bind_cols(
  pred_clphy_baseline_test %>% 
    mutate(error_baseline = Estimate - v2x_clphy_lead1) %>% 
    select(country, gwcode, year, v2x_clphy_lead1, 
           estimate_baseline = Estimate, error_baseline),
  pred_clphy_v2csreprss_test %>% 
    mutate(error_v2csreprss = Estimate - v2x_clphy_lead1) %>% 
    select(estimate_v2csreprss = Estimate, error_v2csreprss)
) %>% 
  # mutate(across(starts_with("error"), ~round(., 4))) %>% 
  mutate(improved = error_v2csreprss < 0 & abs(error_v2csreprss) < abs(error_baseline)) %>% 
  mutate(diff = error_v2csreprss - error_baseline) %>% 
  mutate(abs_diff = abs(diff)) %>% 
  filter(improved) %>% 
  arrange(desc(abs_diff))

nrow(most_improved_clphy)
## [1] 69
most_improved_clphy %>% 
  select(Country = country, Year = year, 
         `Actual physical violence index (t + 1)` =  v2x_clphy_lead1,
         `Predicted (baseline)` = estimate_baseline,
         `Predicted (CS repression)` = estimate_v2csreprss,
         `|CS repression − baseline|` = abs_diff) %>% 
  head(5) %>% 
  kbl(digits = 3, align = "lccccc") %>% 
  kable_styling()
Country Year Actual physical violence index (t + 1) Predicted (baseline) Predicted (CS repression) |CS repression − baseline|
Libya 2011 0.329 0.202 0.277 0.075
Madagascar 2013 0.610 0.572 0.602 0.030
Fiji 2013 0.811 0.771 0.794 0.023
El Salvador 2013 0.740 0.754 0.739 0.015
Burkina Faso 2013 0.651 0.663 0.650 0.013

 

E2c: Civil society environment and civil liberties

seed_clpriv_prediction <- 6670  # From random.org

set.seed(seed_clpriv_prediction)
pred_clpriv_baseline <- predict(m_clpriv_baseline_train, 
                                newdata = select(canary_testing_lagged, -v2x_clpriv_lead1),
                                allow_new_levels = TRUE)

set.seed(seed_clpriv_prediction)
pred_clpriv_v2csreprss <- predict(m_clpriv_v2csreprss_train, 
                                  newdata = select(canary_testing_lagged, -v2x_clpriv_lead1),
                                  allow_new_levels = TRUE)

pred_clpriv_baseline_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clpriv_lead1) %>% 
  bind_cols(as_tibble(pred_clpriv_baseline)) %>% 
  filter(!is.na(v2x_clpriv_lead1))

pred_clpriv_v2csreprss_test <- canary_testing_lagged %>% 
  select(country, gwcode, year, v2x_clpriv_lead1) %>% 
  bind_cols(as_tibble(pred_clpriv_v2csreprss)) %>% 
  filter(!is.na(v2x_clpriv_lead1))

Improvement from baseline models

plot_baseline <- ggplot(pred_clpriv_baseline_test, 
                        aes(x = v2x_clpriv_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Baseline",
       x = "Actual private civil liberties index (t + 1)",
       y = "Predicted private civil liberties index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_v2csreprss <- ggplot(pred_clpriv_v2csreprss_test, 
                          aes(x = v2x_clpriv_lead1, y = Estimate)) +
  geom_abline(lty = 2) +
  geom_point(alpha = 0.5) +
  labs(title = "Added predictor",
       x = "Actual private civil liberties index (t + 1)",
       y = "Predicted private civil liberties index (t + 1)") +
  coord_equal() +
  theme_ngo()

plot_baseline | plot_v2csreprss

lotsa_metrics <- metric_set(rmse, rsq, mae, ccc)

bind_rows(lotsa_metrics(pred_clpriv_baseline_test, 
                        truth = v2x_clpriv_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Baseline"),
          lotsa_metrics(pred_clpriv_v2csreprss_test, 
                        truth = v2x_clpriv_lead1, 
                        estimate = Estimate) %>% 
            mutate(Model = "Added predictor")) %>% 
  select(Model, .metric, .estimate) %>% 
  pivot_wider(names_from = ".metric", values_from = ".estimate")
Model rmse rsq mae ccc
Baseline 0.0339090 0.9822248 0.0202861 0.9884043
Added predictor 0.0332081 0.9826801 0.0201937 0.9887388

Hey! This one has a somewhat better change in MSE!

percent_format(accuracy = 0.01)((0.0332 - 0.0339) / 0.0339)
## [1] "-2.06%"

Most improved countries

most_improved_clpriv <- bind_cols(
  pred_clpriv_baseline_test %>% 
    mutate(error_baseline = Estimate - v2x_clpriv_lead1) %>% 
    select(country, gwcode, year, v2x_clpriv_lead1, 
           estimate_baseline = Estimate, error_baseline),
  pred_clpriv_v2csreprss_test %>% 
    mutate(error_v2csreprss = Estimate - v2x_clpriv_lead1) %>% 
    select(estimate_v2csreprss = Estimate, error_v2csreprss)
) %>% 
  # mutate(across(starts_with("error"), ~round(., 4))) %>% 
  mutate(improved = error_v2csreprss < 0 & abs(error_v2csreprss) < abs(error_baseline)) %>% 
  mutate(diff = error_v2csreprss - error_baseline) %>% 
  mutate(abs_diff = abs(diff)) %>% 
  filter(improved) %>% 
  arrange(desc(abs_diff))

nrow(most_improved_clpriv)
## [1] 77
most_improved_clpriv %>% 
  select(Country = country, Year = year, 
         `Actual private civil liberties index (t + 1)` =  v2x_clpriv_lead1,
         `Predicted (baseline)` = estimate_baseline,
         `Predicted (CS repression)` = estimate_v2csreprss,
         `|CS repression − baseline|` = abs_diff) %>% 
  head(5) %>% 
  kbl(digits = 3, align = "lccccc") %>% 
  kable_styling()
Country Year Actual private civil liberties index (t + 1) Predicted (baseline) Predicted (CS repression) |CS repression − baseline|
Libya 2011 0.344 0.227 0.287 0.060
Madagascar 2013 0.763 0.712 0.739 0.026
South Africa 2013 0.886 0.898 0.876 0.022
Italy 2013 0.930 0.944 0.921 0.022
El Salvador 2013 0.830 0.845 0.827 0.018
LS0tCnRpdGxlOiAiUHJlZGljdGlvbnMiCmF1dGhvcjogIlN1cGFybmEgQ2hhdWRocnkgYW5kIEFuZHJldyBIZWlzcyIKZGF0ZTogIkxhc3QgcnVuOiBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVGJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKa25pdF9wcmludC5kYXRhLmZyYW1lIDwtIGZ1bmN0aW9uKHgsIC4uLikgewogIHJlcyA8LSBwYXN0ZShjKCcnLCAnJywga2FibGVfc3R5bGluZyhrYWJsZSh4LCBib29rdGFicyA9IFRSVUUpKSksIGNvbGxhcHNlID0gJ1xuJykKICBhc2lzX291dHB1dChyZXMpCn0KCnJlZ2lzdGVyUzNtZXRob2QoImtuaXRfcHJpbnQiLCAiZGF0YS5mcmFtZSIsIGtuaXRfcHJpbnQuZGF0YS5mcmFtZSkKcmVnaXN0ZXJTM21ldGhvZCgia25pdF9wcmludCIsICJncm91cGVkX2RmIiwga25pdF9wcmludC5kYXRhLmZyYW1lKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5yZXRpbmEgPSAzLAogICAgICAgICAgICAgICAgICAgICAgdGlkeS5vcHRzID0gbGlzdCh3aWR0aC5jdXRvZmYgPSAxMjApLCAgIyBGb3IgY29kZQogICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyh3aWR0aCA9IDkwKSwgICMgRm9yIG91dHB1dAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFzcCA9IDAuNjE4LCBmaWcud2lkdGggPSA3LCAKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAiODUlIikKCm9wdGlvbnMoZHBseXIuc3VtbWFyaXNlLmluZm9ybSA9IEZBTFNFLAogICAgICAgIGtuaXRyLmthYmxlLk5BID0gIiIpCmBgYAoKYGBge3IgbG9hZC1saWJyYXJpZXMtZGF0YSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodGFyZ2V0cykKbGlicmFyeSh5YXJkc3RpY2spCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShoZXJlKQoKIyBMb2FkIGRhdGEKIyBOZWVkIHRvIHVzZSB0aGlzIHdpdGhyIHRoaW5nIGJlY2F1c2UgdGFyX3JlYWQoKSBhbmQgdGFyX2xvYWQoKSBuZWVkIHRvIHNlZSB0aGUKIyBfdGFyZ2V0cyBmb2xkZXIgaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5LCBidXQgdGhpcyAuUm1kIGZpbGUgaXMgaW4gYSBzdWJmb2xkZXIKd2l0aHI6OndpdGhfZGlyKGhlcmU6OmhlcmUoKSwgewogIHNvdXJjZSh0YXJfcmVhZChwbG90X2Z1bnMpKQogIAogIGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCA8LSB0YXJfcmVhZChwYW5lbF90ZXN0aW5nX2xhZ2dlZCkKICAKICAjIExvYWQgYmlnIGxpc3Qgb2YgbW9kZWxzCiAgbW9kZWxfZGYgPC0gdGFyX3JlYWQobW9kZWxfZGYpICU+JSAKICAgIGZpbHRlcihzdHJfZGV0ZWN0KG1vZGVsLCAiYmFzZWxpbmUiKSB8IHN0cl9kZXRlY3QobW9kZWwsICJ2MmNzcmVwcnNzIikpCiAgCiAgIyBMb2FkIGFjdHVhbCBtb2RlbCBvYmplY3RzCiAgdGFyX2xvYWQoYyhtX3B0c19iYXNlbGluZV90cmFpbiwgbV9wdHNfdjJjc3JlcHJzc190cmFpbiwKICAgICAgICAgICAgIG1fcHRzX3RvdGFsX3RyYWluLCBtX3B0c19hZHZvY2FjeV90cmFpbiwgCiAgICAgICAgICAgICBtX3B0c19lbnRyeV90cmFpbiwgbV9wdHNfZnVuZGluZ190cmFpbiwKICAgICAgICAgICAgIG1fcHRzX2Jhc2VsaW5lX3Jld2JfdHJhaW4sIG1fcHRzX3YyY3NyZXByc3NfcmV3Yl90cmFpbiwgCiAgICAgICAgICAgICBtX2NscGh5X2Jhc2VsaW5lX3RyYWluLCBtX2NscGh5X3YyY3NyZXByc3NfdHJhaW4sIAogICAgICAgICAgICAgbV9jbHBoeV90b3RhbF90cmFpbiwgbV9jbHBoeV9hZHZvY2FjeV90cmFpbiwgCiAgICAgICAgICAgICBtX2NscGh5X2VudHJ5X3RyYWluLCBtX2NscGh5X2Z1bmRpbmdfdHJhaW4sCiAgICAgICAgICAgICBtX2NscHJpdl9iYXNlbGluZV90cmFpbiwgbV9jbHByaXZfdjJjc3JlcHJzc190cmFpbiwKICAgICAgICAgICAgIG1fY2xwcml2X3RvdGFsX3RyYWluLCBtX2NscHJpdl9hZHZvY2FjeV90cmFpbiwgCiAgICAgICAgICAgICBtX2NscHJpdl9lbnRyeV90cmFpbiwgbV9jbHByaXZfZnVuZGluZ190cmFpbikpCn0pCgpwdHNfbGV2ZWxzIDwtIGxldmVscyhjYW5hcnlfdGVzdGluZ19sYWdnZWQkUFRTX2ZhY3RvcikKCiMgUmV0dXJucyBhIGRhdGEgZnJhbWUgb2YgcHJlZGljdGVkIHByb2JhYmlsaXRpZXMgd2l0aCBhY3R1YWwgPSAxIAojIHdoZW4gdGhlIHJlc3BvbnNlIG91dGNvbWUgaGFwcGVucwptYXRjaF9hY3R1YWwgPC0gZnVuY3Rpb24oeCwgcHJlZCwgYWN0dWFsKSB7CiAgcHJlZCAlPiUgCiAgICBzZWxlY3QoZml0dGVkID0ge3t4fX0pICU+JSAKICAgIG11dGF0ZShhY3R1YWwgPSBhcy5udW1lcmljKGFjdHVhbCA9PSBjb2xuYW1lcyhwcmVkW3hdKSksCiAgICAgICAgICAgcGxvdF9sZXZlbCA9IGNvbG5hbWVzKHByZWRbeF0pKQp9CmBgYAoKYGBge3Iga2x1ZGd5LWJhbmRhaWQtZm9yLXdlaXJkLWRhdGEtaXNzdWVzfQojIE9PT09PT09GIE9IIE5PIGZvciBzb21lIHJlYXNvbiBQVFNfbGVhZDEgYW5kIGFsbCBsZWFkZWQgVi1EZW0gdmFsdWVzIG1pc3NpbmcKIyBmb3IgMjAxMyAoaS5lLiAyMDE0IHZhbHVlcykgYW5kIEkgZG9uJ3Qgd2FudCB0byBnbyBiYWNrIGFuZCByZXJ1biBhbGwgdGhlc2UKIyBtb2RlbHMgeWV0LCBzbyB3ZSBkbyBhIHRlbXBvcmFyeSBmaXggaGVyZSBhbmQgbWFudWFsbHkgYWRkIHRoZSB2YWx1ZXMgZnJvbQojIHB0c19jbGVhbiBhbmQgdmRlbV9jbGVhbgp3aXRocjo6d2l0aF9kaXIoaGVyZTo6aGVyZSgpLCB7CiAgdGFyX2xvYWQocHRzX2NsZWFuKQogIHRhcl9sb2FkKHZkZW1fY2xlYW4pCn0pCgpwdHNfMjAxNCA8LSBwdHNfY2xlYW4gJT4lIAogIGdyb3VwX2J5KGd3Y29kZSkgJT4lIAogIG11dGF0ZShhY3Jvc3MoYyhQVFMsIFBUU19mYWN0b3IpLAogICAgICAgICAgICAgICAgICBsaXN0KGxlYWQxXzIwMTQgPSB+bGVhZCguLCAxKSkpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoeWVhciA9PSAyMDEzKSAlPiUgCiAgc2VsZWN0KC1QVFMsIC1QVFNfZmFjdG9yKQoKdmRlbV8yMDE0IDwtIHZkZW1fY2xlYW4gJT4lIAogIGdyb3VwX2J5KGd3Y29kZSkgJT4lIAogIG11dGF0ZShhY3Jvc3MoYyh2MnhfY2xwaHksIHYyeF9jbHByaXYpLAogICAgICAgICAgICAgICAgICBsaXN0KGxlYWQxXzIwMTQgPSB+bGVhZCguLCAxKSkpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoeWVhciA9PSAyMDEzKSAlPiUgCiAgc2VsZWN0KGd3Y29kZSwgeWVhciwgdjJ4X2NscGh5X2xlYWQxXzIwMTQsIHYyeF9jbHByaXZfbGVhZDFfMjAxNCkKCmNhbmFyeV90ZXN0aW5nX2xhZ2dlZCA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIGxlZnRfam9pbihwdHNfMjAxNCwgYnkgPSBjKCJ5ZWFyIiwgImd3Y29kZSIpKSAlPiUgCiAgbGVmdF9qb2luKHZkZW1fMjAxNCwgYnkgPSBjKCJ5ZWFyIiwgImd3Y29kZSIpKSAlPiUgCiAgbXV0YXRlKFBUU19sZWFkMSA9IGNvYWxlc2NlKFBUU19sZWFkMSwgUFRTX2xlYWQxXzIwMTQpLAogICAgICAgICBQVFNfZmFjdG9yX2xlYWQxID0gY29hbGVzY2UoUFRTX2ZhY3Rvcl9sZWFkMSwgUFRTX2ZhY3Rvcl9sZWFkMV8yMDE0KSwKICAgICAgICAgdjJ4X2NscGh5X2xlYWQxID0gY29hbGVzY2UodjJ4X2NscGh5X2xlYWQxLCB2MnhfY2xwaHlfbGVhZDFfMjAxNCksCiAgICAgICAgIHYyeF9jbHByaXZfbGVhZDEgPSBjb2FsZXNjZSh2MnhfY2xwcml2X2xlYWQxLCB2MnhfY2xwcml2X2xlYWQxXzIwMTQpKSAlPiUgCiAgc2VsZWN0KC1jb250YWlucygiXzIwMTQiKSkKYGBgCgojIEV+MWF+OiBOR08gbGF3cyBhbmQgcG9saXRpY2FsIHRlcnJvcgoKYGBge3IgZTFhLXByZWRpY3Rpb25zLCB3YXJuaW5nPUZBTFNFfQpzZWVkX3B0c19wcmVkaWN0aW9uIDwtIDU0OTQgICMgRnJvbSByYW5kb20ub3JnCgpzZXQuc2VlZChzZWVkX3B0c19wcmVkaWN0aW9uKQpwcmVkX3B0c19iYXNlbGluZSA8LSBwcmVkaWN0KAogIG1fcHRzX2Jhc2VsaW5lX3RyYWluLCAKICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLVBUU19mYWN0b3JfbGVhZDEpLAogIGFsbG93X25ld19sZXZlbHMgPSBUUlVFCikgJT4lIAogIGFzX3RpYmJsZSgpICU+JSAKICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKHB0c19sZXZlbHMpCgpzZXQuc2VlZChzZWVkX3B0c19wcmVkaWN0aW9uKQpwcmVkX3B0c190b3RhbCA8LSBwcmVkaWN0KAogIG1fcHRzX3RvdGFsX3RyYWluLCAKICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLVBUU19mYWN0b3JfbGVhZDEpLAogIGFsbG93X25ld19sZXZlbHMgPSBUUlVFCikgJT4lIAogIGFzX3RpYmJsZSgpICU+JSAKICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKHB0c19sZXZlbHMpCgpzZXQuc2VlZChzZWVkX3B0c19wcmVkaWN0aW9uKQpwcmVkX3B0c19hZHZvY2FjeSA8LSBwcmVkaWN0KAogIG1fcHRzX2Fkdm9jYWN5X3RyYWluLCAKICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLVBUU19mYWN0b3JfbGVhZDEpLAogIGFsbG93X25ld19sZXZlbHMgPSBUUlVFCikgJT4lIAogIGFzX3RpYmJsZSgpICU+JSAKICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKHB0c19sZXZlbHMpCgpzZXQuc2VlZChzZWVkX3B0c19wcmVkaWN0aW9uKQpwcmVkX3B0c19lbnRyeSA8LSBwcmVkaWN0KAogIG1fcHRzX2VudHJ5X3RyYWluLCAKICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLVBUU19mYWN0b3JfbGVhZDEpLAogIGFsbG93X25ld19sZXZlbHMgPSBUUlVFCikgJT4lIAogIGFzX3RpYmJsZSgpICU+JSAKICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKHB0c19sZXZlbHMpCgpzZXQuc2VlZChzZWVkX3B0c19wcmVkaWN0aW9uKQpwcmVkX3B0c19mdW5kaW5nIDwtIHByZWRpY3QoCiAgbV9wdHNfZnVuZGluZ190cmFpbiwgCiAgbmV3ZGF0YSA9IHNlbGVjdChjYW5hcnlfdGVzdGluZ19sYWdnZWQsIC1QVFNfZmFjdG9yX2xlYWQxKSwKICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRQopICU+JSAKICBhc190aWJibGUoKSAlPiUgCiAgbWFncml0dHI6OnNldF9jb2xuYW1lcyhwdHNfbGV2ZWxzKQpgYGAKCiMjIFNlcGFyYXRpb24gcGxvdHMKCiMjIyBCYXNlbGluZSBtb2RlbHMKCmBgYHtyIGUxYS1zZXBhcmF0aW9uLWJhc2VsaW5lfQojIE1hdGNoIGVhY2ggY29sdW1uIGluIHByZWRfbWF0IChwcmVkaWN0ZWQgcHJvYmFiaWxpdGllcyBmb3IgZWFjaCByZXNwb25zZSBsZXZlbCkKcHJlZF9sb25nX2xpc3QgPC0gbGFwcGx5KDE6bmNvbChwcmVkX3B0c19iYXNlbGluZSksIAogICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gbWF0Y2hfYWN0dWFsLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHByZWQgPSBwcmVkX3B0c19iYXNlbGluZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBhY3R1YWwgPSBhcy5jaGFyYWN0ZXIoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkJFBUU19mYWN0b3JfbGVhZDEpKQoKcGxvdF9kYXRhIDwtIHByZWRfbG9uZ19saXN0ICU+JSAKICBiaW5kX3Jvd3MoKSAlPiUgCiAgZmlsdGVyKCFpcy5uYW4oZml0dGVkKSwgIWlzLm5hKGFjdHVhbCkpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsKSAlPiUgCiAgYXJyYW5nZShwbG90X2xldmVsLCBmaXR0ZWQpICU+JSAKICBtdXRhdGUoaW5kZXggPSByb3dfbnVtYmVyKCkpICU+JSAKICB1bmdyb3VwKCkKCm1hcmtlcnMgPC0gcGxvdF9kYXRhICU+JSAKICBncm91cF9ieShwbG90X2xldmVsKSAlPiUKICBzdW1tYXJpemUob2JzID0gbigpLCBleHBlY3RlZCA9IHN1bShmaXR0ZWQpLAogICAgICAgICAgICBtYXJrZXIgPSBvYnMgLSBleHBlY3RlZCArIDEpCgpuX2luX2dyb3VwIDwtIG5yb3cocHJlZF9wdHNfYmFzZWxpbmUpCgpwbG90X2RhdGFfY29uZGVuc2VkIDwtIHBsb3RfZGF0YSAlPiUgCiAgIyBybGUoKSwgZHBseXItc3R5bGU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zMzUxMDc2NS8xMjA4OTgKICBtdXRhdGUocmxlaWQgPSAoYWN0dWFsICE9IGxhZyhhY3R1YWwsIDEsIGRlZmF1bHQgPSAwKSkpICU+JQogIG11dGF0ZShybGVpZCA9IGN1bXN1bShybGVpZCkpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsLCBybGVpZCkgJT4lIAogIHNsaWNlKDEpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsKSAlPiUgCiAgbXV0YXRlKHhtaW4gPSBpbmRleCwgeG1heCA9IGxlYWQoaW5kZXgsIGRlZmF1bHQgPSBuX2luX2dyb3VwKSkgJT4lIAogIHVuZ3JvdXAoKQoKZ2dwbG90KHBsb3RfZGF0YV9jb25kZW5zZWQpICsKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSB4bWluLCB4bWF4ID0geG1heCwgeW1pbiA9IDAsIHltYXggPSAxLCBmaWxsID0gYXMuZmFjdG9yKGFjdHVhbCkpKSArIAogIGdlb21fbGluZShhZXMoeCA9IGluZGV4LCB5ID0gZml0dGVkKSwgc2l6ZSA9IDAuMykgKwogIGdlb21fcG9pbnQoZGF0YSA9IG1hcmtlcnMsIGFlcyh4ID0gbWFya2VyLCB5ID0gLTAuMDUpLCBzaGFwZSA9IDE3LCBzaXplID0gMykgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJncmV5OTAiLCAiIzJFQ0M0MCIpKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAodmFycyhwbG90X2xldmVsKSwgbmNvbCA9IDEsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgdGhlbWVfdm9pZChiYXNlX2ZhbWlseSA9ICJJbnRlciBCb2xkIikKYGBgCgojIyMgTW9kZWxzIHdpdGggTkdPIGxhd3MKCiMjIyMgVG90YWwgbGVnYWwgYmFycmllcnMKCmBgYHtyIGUxYS1zZXBhcmF0aW9uLXRvdGFsfQojIE1hdGNoIGVhY2ggY29sdW1uIGluIHByZWRfbWF0IChwcmVkaWN0ZWQgcHJvYmFiaWxpdGllcyBmb3IgZWFjaCByZXNwb25zZSBsZXZlbCkKcHJlZF9sb25nX2xpc3QgPC0gbGFwcGx5KDE6bmNvbChwcmVkX3B0c190b3RhbCksIAogICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gbWF0Y2hfYWN0dWFsLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHByZWQgPSBwcmVkX3B0c190b3RhbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBhY3R1YWwgPSBhcy5jaGFyYWN0ZXIoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkJFBUU19mYWN0b3JfbGVhZDEpKQoKcGxvdF9kYXRhIDwtIHByZWRfbG9uZ19saXN0ICU+JSAKICBiaW5kX3Jvd3MoKSAlPiUgCiAgZmlsdGVyKCFpcy5uYW4oZml0dGVkKSwgIWlzLm5hKGFjdHVhbCkpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsKSAlPiUgCiAgYXJyYW5nZShwbG90X2xldmVsLCBmaXR0ZWQpICU+JSAKICBtdXRhdGUoaW5kZXggPSByb3dfbnVtYmVyKCkpICU+JSAKICB1bmdyb3VwKCkKCm1hcmtlcnMgPC0gcGxvdF9kYXRhICU+JSAKICBncm91cF9ieShwbG90X2xldmVsKSAlPiUKICBzdW1tYXJpemUob2JzID0gbigpLCBleHBlY3RlZCA9IHN1bShmaXR0ZWQpLAogICAgICAgICAgICBtYXJrZXIgPSBvYnMgLSBleHBlY3RlZCArIDEpCgpuX2luX2dyb3VwIDwtIG5yb3cocHJlZF9wdHNfdG90YWwpCgpwbG90X2RhdGFfY29uZGVuc2VkIDwtIHBsb3RfZGF0YSAlPiUgCiAgIyBybGUoKSwgZHBseXItc3R5bGU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zMzUxMDc2NS8xMjA4OTgKICBtdXRhdGUocmxlaWQgPSAoYWN0dWFsICE9IGxhZyhhY3R1YWwsIDEsIGRlZmF1bHQgPSAwKSkpICU+JQogIG11dGF0ZShybGVpZCA9IGN1bXN1bShybGVpZCkpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsLCBybGVpZCkgJT4lIAogIHNsaWNlKDEpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsKSAlPiUgCiAgbXV0YXRlKHhtaW4gPSBpbmRleCwgeG1heCA9IGxlYWQoaW5kZXgsIGRlZmF1bHQgPSBuX2luX2dyb3VwKSkgJT4lIAogIHVuZ3JvdXAoKQoKZ2dwbG90KHBsb3RfZGF0YV9jb25kZW5zZWQpICsKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSB4bWluLCB4bWF4ID0geG1heCwgeW1pbiA9IDAsIHltYXggPSAxLCBmaWxsID0gYXMuZmFjdG9yKGFjdHVhbCkpKSArIAogIGdlb21fbGluZShhZXMoeCA9IGluZGV4LCB5ID0gZml0dGVkKSwgc2l6ZSA9IDAuMykgKwogIGdlb21fcG9pbnQoZGF0YSA9IG1hcmtlcnMsIGFlcyh4ID0gbWFya2VyLCB5ID0gLTAuMDUpLCBzaGFwZSA9IDE3LCBzaXplID0gMykgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJncmV5OTAiLCAiIzJFQ0M0MCIpKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAodmFycyhwbG90X2xldmVsKSwgbmNvbCA9IDEsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgdGhlbWVfdm9pZChiYXNlX2ZhbWlseSA9ICJJbnRlciBCb2xkIikKYGBgCgojIyMjIEJhcnJpZXJzIHRvIGFkdm9jYWN5CgpgYGB7ciBlMWEtc2VwYXJhdGlvbi1hZHZvY2FjeX0KIyBNYXRjaCBlYWNoIGNvbHVtbiBpbiBwcmVkX21hdCAocHJlZGljdGVkIHByb2JhYmlsaXRpZXMgZm9yIGVhY2ggcmVzcG9uc2UgbGV2ZWwpCnByZWRfbG9uZ19saXN0IDwtIGxhcHBseSgxOm5jb2wocHJlZF9wdHNfYWR2b2NhY3kpLCAKICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9IG1hdGNoX2FjdHVhbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkID0gcHJlZF9wdHNfYWR2b2NhY3ksIAogICAgICAgICAgICAgICAgICAgICAgICAgYWN0dWFsID0gYXMuY2hhcmFjdGVyKGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCRQVFNfZmFjdG9yX2xlYWQxKSkKCnBsb3RfZGF0YSA8LSBwcmVkX2xvbmdfbGlzdCAlPiUgCiAgYmluZF9yb3dzKCkgJT4lIAogIGZpbHRlcighaXMubmFuKGZpdHRlZCksICFpcy5uYShhY3R1YWwpKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lIAogIGFycmFuZ2UocGxvdF9sZXZlbCwgZml0dGVkKSAlPiUgCiAgbXV0YXRlKGluZGV4ID0gcm93X251bWJlcigpKSAlPiUgCiAgdW5ncm91cCgpCgptYXJrZXJzIDwtIHBsb3RfZGF0YSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lCiAgc3VtbWFyaXplKG9icyA9IG4oKSwgZXhwZWN0ZWQgPSBzdW0oZml0dGVkKSwKICAgICAgICAgICAgbWFya2VyID0gb2JzIC0gZXhwZWN0ZWQgKyAxKQoKbl9pbl9ncm91cCA8LSBucm93KHByZWRfcHRzX2Fkdm9jYWN5KQoKcGxvdF9kYXRhX2NvbmRlbnNlZCA8LSBwbG90X2RhdGEgJT4lIAogICMgcmxlKCksIGRwbHlyLXN0eWxlOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzM1MTA3NjUvMTIwODk4CiAgbXV0YXRlKHJsZWlkID0gKGFjdHVhbCAhPSBsYWcoYWN0dWFsLCAxLCBkZWZhdWx0ID0gMCkpKSAlPiUKICBtdXRhdGUocmxlaWQgPSBjdW1zdW0ocmxlaWQpKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCwgcmxlaWQpICU+JSAKICBzbGljZSgxKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lIAogIG11dGF0ZSh4bWluID0gaW5kZXgsIHhtYXggPSBsZWFkKGluZGV4LCBkZWZhdWx0ID0gbl9pbl9ncm91cCkpICU+JSAKICB1bmdyb3VwKCkKCmdncGxvdChwbG90X2RhdGFfY29uZGVuc2VkKSArCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0geG1pbiwgeG1heCA9IHhtYXgsIHltaW4gPSAwLCB5bWF4ID0gMSwgZmlsbCA9IGFzLmZhY3RvcihhY3R1YWwpKSkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBpbmRleCwgeSA9IGZpdHRlZCksIHNpemUgPSAwLjMpICsKICBnZW9tX3BvaW50KGRhdGEgPSBtYXJrZXJzLCBhZXMoeCA9IG1hcmtlciwgeSA9IC0wLjA1KSwgc2hhcGUgPSAxNywgc2l6ZSA9IDMpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZ3JleTkwIiwgIiMyRUNDNDAiKSkgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UpICsKICBmYWNldF93cmFwKHZhcnMocGxvdF9sZXZlbCksIG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHRoZW1lX3ZvaWQoYmFzZV9mYW1pbHkgPSAiSW50ZXIgQm9sZCIpCmBgYAoKIyMjIyBCYXJyaWVycyB0byBlbnRyeQoKYGBge3IgZTFhLXNlcGFyYXRpb24tZW50cnl9CiMgTWF0Y2ggZWFjaCBjb2x1bW4gaW4gcHJlZF9tYXQgKHByZWRpY3RlZCBwcm9iYWJpbGl0aWVzIGZvciBlYWNoIHJlc3BvbnNlIGxldmVsKQpwcmVkX2xvbmdfbGlzdCA8LSBsYXBwbHkoMTpuY29sKHByZWRfcHRzX2VudHJ5KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSBtYXRjaF9hY3R1YWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgcHJlZCA9IHByZWRfcHRzX2VudHJ5LCAKICAgICAgICAgICAgICAgICAgICAgICAgIGFjdHVhbCA9IGFzLmNoYXJhY3RlcihjYW5hcnlfdGVzdGluZ19sYWdnZWQkUFRTX2ZhY3Rvcl9sZWFkMSkpCgpwbG90X2RhdGEgPC0gcHJlZF9sb25nX2xpc3QgJT4lIAogIGJpbmRfcm93cygpICU+JSAKICBmaWx0ZXIoIWlzLm5hbihmaXR0ZWQpLCAhaXMubmEoYWN0dWFsKSkgJT4lIAogIGdyb3VwX2J5KHBsb3RfbGV2ZWwpICU+JSAKICBhcnJhbmdlKHBsb3RfbGV2ZWwsIGZpdHRlZCkgJT4lIAogIG11dGF0ZShpbmRleCA9IHJvd19udW1iZXIoKSkgJT4lIAogIHVuZ3JvdXAoKQoKbWFya2VycyA8LSBwbG90X2RhdGEgJT4lIAogIGdyb3VwX2J5KHBsb3RfbGV2ZWwpICU+JQogIHN1bW1hcml6ZShvYnMgPSBuKCksIGV4cGVjdGVkID0gc3VtKGZpdHRlZCksCiAgICAgICAgICAgIG1hcmtlciA9IG9icyAtIGV4cGVjdGVkICsgMSkKCm5faW5fZ3JvdXAgPC0gbnJvdyhwcmVkX3B0c19lbnRyeSkKCnBsb3RfZGF0YV9jb25kZW5zZWQgPC0gcGxvdF9kYXRhICU+JSAKICAjIHJsZSgpLCBkcGx5ci1zdHlsZTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzMzNTEwNzY1LzEyMDg5OAogIG11dGF0ZShybGVpZCA9IChhY3R1YWwgIT0gbGFnKGFjdHVhbCwgMSwgZGVmYXVsdCA9IDApKSkgJT4lCiAgbXV0YXRlKHJsZWlkID0gY3Vtc3VtKHJsZWlkKSkgJT4lIAogIGdyb3VwX2J5KHBsb3RfbGV2ZWwsIHJsZWlkKSAlPiUgCiAgc2xpY2UoMSkgJT4lIAogIGdyb3VwX2J5KHBsb3RfbGV2ZWwpICU+JSAKICBtdXRhdGUoeG1pbiA9IGluZGV4LCB4bWF4ID0gbGVhZChpbmRleCwgZGVmYXVsdCA9IG5faW5fZ3JvdXApKSAlPiUgCiAgdW5ncm91cCgpCgpnZ3Bsb3QocGxvdF9kYXRhX2NvbmRlbnNlZCkgKwogIGdlb21fcmVjdChhZXMoeG1pbiA9IHhtaW4sIHhtYXggPSB4bWF4LCB5bWluID0gMCwgeW1heCA9IDEsIGZpbGwgPSBhcy5mYWN0b3IoYWN0dWFsKSkpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0gaW5kZXgsIHkgPSBmaXR0ZWQpLCBzaXplID0gMC4zKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbWFya2VycywgYWVzKHggPSBtYXJrZXIsIHkgPSAtMC4wNSksIHNoYXBlID0gMTcsIHNpemUgPSAzKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImdyZXk5MCIsICIjMkVDQzQwIikpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh2YXJzKHBsb3RfbGV2ZWwpLCBuY29sID0gMSwgc2NhbGVzID0gImZyZWVfeCIpICsKICB0aGVtZV92b2lkKGJhc2VfZmFtaWx5ID0gIkludGVyIEJvbGQiKQpgYGAKCiMjIyMgQmFycmllcnMgdG8gZnVuZGluZwoKYGBge3IgZTFhLXNlcGFyYXRpb24tZnVuZGluZ30KIyBNYXRjaCBlYWNoIGNvbHVtbiBpbiBwcmVkX21hdCAocHJlZGljdGVkIHByb2JhYmlsaXRpZXMgZm9yIGVhY2ggcmVzcG9uc2UgbGV2ZWwpCnByZWRfbG9uZ19saXN0IDwtIGxhcHBseSgxOm5jb2wocHJlZF9wdHNfZnVuZGluZyksIAogICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gbWF0Y2hfYWN0dWFsLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHByZWQgPSBwcmVkX3B0c19mdW5kaW5nLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGFjdHVhbCA9IGFzLmNoYXJhY3RlcihjYW5hcnlfdGVzdGluZ19sYWdnZWQkUFRTX2ZhY3Rvcl9sZWFkMSkpCgpwbG90X2RhdGEgPC0gcHJlZF9sb25nX2xpc3QgJT4lIAogIGJpbmRfcm93cygpICU+JSAKICBmaWx0ZXIoIWlzLm5hbihmaXR0ZWQpLCAhaXMubmEoYWN0dWFsKSkgJT4lIAogIGdyb3VwX2J5KHBsb3RfbGV2ZWwpICU+JSAKICBhcnJhbmdlKHBsb3RfbGV2ZWwsIGZpdHRlZCkgJT4lIAogIG11dGF0ZShpbmRleCA9IHJvd19udW1iZXIoKSkgJT4lIAogIHVuZ3JvdXAoKQoKbWFya2VycyA8LSBwbG90X2RhdGEgJT4lIAogIGdyb3VwX2J5KHBsb3RfbGV2ZWwpICU+JQogIHN1bW1hcml6ZShvYnMgPSBuKCksIGV4cGVjdGVkID0gc3VtKGZpdHRlZCksCiAgICAgICAgICAgIG1hcmtlciA9IG9icyAtIGV4cGVjdGVkICsgMSkKCm5faW5fZ3JvdXAgPC0gbnJvdyhwcmVkX3B0c19mdW5kaW5nKQoKcGxvdF9kYXRhX2NvbmRlbnNlZCA8LSBwbG90X2RhdGEgJT4lIAogICMgcmxlKCksIGRwbHlyLXN0eWxlOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzM1MTA3NjUvMTIwODk4CiAgbXV0YXRlKHJsZWlkID0gKGFjdHVhbCAhPSBsYWcoYWN0dWFsLCAxLCBkZWZhdWx0ID0gMCkpKSAlPiUKICBtdXRhdGUocmxlaWQgPSBjdW1zdW0ocmxlaWQpKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCwgcmxlaWQpICU+JSAKICBzbGljZSgxKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lIAogIG11dGF0ZSh4bWluID0gaW5kZXgsIHhtYXggPSBsZWFkKGluZGV4LCBkZWZhdWx0ID0gbl9pbl9ncm91cCkpICU+JSAKICB1bmdyb3VwKCkKCmdncGxvdChwbG90X2RhdGFfY29uZGVuc2VkKSArCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0geG1pbiwgeG1heCA9IHhtYXgsIHltaW4gPSAwLCB5bWF4ID0gMSwgZmlsbCA9IGFzLmZhY3RvcihhY3R1YWwpKSkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBpbmRleCwgeSA9IGZpdHRlZCksIHNpemUgPSAwLjMpICsKICBnZW9tX3BvaW50KGRhdGEgPSBtYXJrZXJzLCBhZXMoeCA9IG1hcmtlciwgeSA9IC0wLjA1KSwgc2hhcGUgPSAxNywgc2l6ZSA9IDMpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZ3JleTkwIiwgIiMyRUNDNDAiKSkgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UpICsKICBmYWNldF93cmFwKHZhcnMocGxvdF9sZXZlbCksIG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHRoZW1lX3ZvaWQoYmFzZV9mYW1pbHkgPSAiSW50ZXIgQm9sZCIpCmBgYAoKIyMgUHJlZGljdGlvbiBkaWFnbm9zdGljcwoKYGBge3IgZTFhLWltcHJvdmVkLWNhc2VzfQpwcmVkX3B0c19iYXNlbGluZV9jYXRlZ29yaWVzIDwtIHByZWRfcHRzX2Jhc2VsaW5lICU+JSAKICByb3duYW1lc190b19jb2x1bW4oKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKC1yb3duYW1lKSAlPiUgCiAgZ3JvdXBfYnkocm93bmFtZSkgJT4lIAogIGZpbHRlcihyYW5rKC12YWx1ZSwgdGllcy5tZXRob2QgPSAibGFzdCIpID09IDEpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdChwcmVkaWN0ZWQgPSBuYW1lKQoKcHJlZF9wdHNfdG90YWxfY2F0ZWdvcmllcyA8LSBwcmVkX3B0c190b3RhbCAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKCkgJT4lIAogIHBpdm90X2xvbmdlcigtcm93bmFtZSkgJT4lIAogIGdyb3VwX2J5KHJvd25hbWUpICU+JSAKICBmaWx0ZXIocmFuaygtdmFsdWUsIHRpZXMubWV0aG9kID0gImxhc3QiKSA9PSAxKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3QocHJlZGljdGVkID0gbmFtZSkKCnByZWRfcHRzX2Fkdm9jYWN5X2NhdGVnb3JpZXMgPC0gcHJlZF9wdHNfYWR2b2NhY3kgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigpICU+JSAKICBwaXZvdF9sb25nZXIoLXJvd25hbWUpICU+JSAKICBncm91cF9ieShyb3duYW1lKSAlPiUgCiAgZmlsdGVyKHJhbmsoLXZhbHVlLCB0aWVzLm1ldGhvZCA9ICJsYXN0IikgPT0gMSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KHByZWRpY3RlZCA9IG5hbWUpCgpwcmVkX3B0c19lbnRyeV9jYXRlZ29yaWVzIDwtIHByZWRfcHRzX2VudHJ5ICU+JSAKICByb3duYW1lc190b19jb2x1bW4oKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKC1yb3duYW1lKSAlPiUgCiAgZ3JvdXBfYnkocm93bmFtZSkgJT4lIAogIGZpbHRlcihyYW5rKC12YWx1ZSwgdGllcy5tZXRob2QgPSAibGFzdCIpID09IDEpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdChwcmVkaWN0ZWQgPSBuYW1lKQoKcHJlZF9wdHNfZnVuZGluZ19jYXRlZ29yaWVzIDwtIHByZWRfcHRzX2Z1bmRpbmcgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigpICU+JSAKICBwaXZvdF9sb25nZXIoLXJvd25hbWUpICU+JSAKICBncm91cF9ieShyb3duYW1lKSAlPiUgCiAgZmlsdGVyKHJhbmsoLXZhbHVlLCB0aWVzLm1ldGhvZCA9ICJsYXN0IikgPT0gMSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KHByZWRpY3RlZCA9IG5hbWUpCgoKcHRzX2NhdF9wcmVkcyA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCB5ZWFyLCBhY3R1YWwgPSBQVFNfZmFjdG9yX2xlYWQxKSAlPiUgCiAgbXV0YXRlKHByZWRfYmFzZWxpbmUgPSBwcmVkX3B0c19iYXNlbGluZV9jYXRlZ29yaWVzJHByZWRpY3RlZCwKICAgICAgICAgcHJlZF90b3RhbCA9IHByZWRfcHRzX3RvdGFsX2NhdGVnb3JpZXMkcHJlZGljdGVkLAogICAgICAgICBwcmVkX2Fkdm9jYWN5ID0gcHJlZF9wdHNfYWR2b2NhY3lfY2F0ZWdvcmllcyRwcmVkaWN0ZWQsCiAgICAgICAgIHByZWRfZW50cnkgPSBwcmVkX3B0c19lbnRyeV9jYXRlZ29yaWVzJHByZWRpY3RlZCwKICAgICAgICAgcHJlZF9mdW5kaW5nID0gcHJlZF9wdHNfZnVuZGluZ19jYXRlZ29yaWVzJHByZWRpY3RlZCkgJT4lIAogIGZpbHRlcighaXMubmEoYWN0dWFsKSkgJT4lCiAgbXV0YXRlKGlzX2NvcnJlY3RfYmFzZWxpbmUgPSBhY3R1YWwgPT0gcHJlZF9iYXNlbGluZSwKICAgICAgICAgaXNfY29ycmVjdF90b3RhbCA9IGFjdHVhbCA9PSBwcmVkX3RvdGFsLAogICAgICAgICBpc19jb3JyZWN0X2Fkdm9jYWN5ID0gYWN0dWFsID09IHByZWRfYWR2b2NhY3ksCiAgICAgICAgIGlzX2NvcnJlY3RfZW50cnkgPSBhY3R1YWwgPT0gcHJlZF9lbnRyeSwKICAgICAgICAgaXNfY29ycmVjdF9mdW5kaW5nID0gYWN0dWFsID09IHByZWRfZnVuZGluZykKCiMgSW1wcm92ZWQgcHJlZGljdGlvbnMKcHRzX2ltcHJvdmVkX3RvdGFsIDwtIHB0c19jYXRfcHJlZHMgJT4lIAogIGZpbHRlcighaXNfY29ycmVjdF9iYXNlbGluZSAmIGlzX2NvcnJlY3RfdG90YWwpICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCBBY3R1YWwgPSBhY3R1YWwsCiAgICAgICAgIGBDUyByZXByZXNzaW9uIGluY2x1ZGVkYCA9IHByZWRfdG90YWwsCiAgICAgICAgIGBCYXNlbGluZWAgPSBwcmVkX2Jhc2VsaW5lKQoKcHRzX2ltcHJvdmVkX2Fkdm9jYWN5IDwtIHB0c19jYXRfcHJlZHMgJT4lIAogIGZpbHRlcighaXNfY29ycmVjdF9iYXNlbGluZSAmIGlzX2NvcnJlY3RfYWR2b2NhY3kpICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCBBY3R1YWwgPSBhY3R1YWwsCiAgICAgICAgIGBDUyByZXByZXNzaW9uIGluY2x1ZGVkYCA9IHByZWRfYWR2b2NhY3ksCiAgICAgICAgIGBCYXNlbGluZWAgPSBwcmVkX2Jhc2VsaW5lKQoKcHRzX2ltcHJvdmVkX2VudHJ5IDwtIHB0c19jYXRfcHJlZHMgJT4lIAogIGZpbHRlcighaXNfY29ycmVjdF9iYXNlbGluZSAmIGlzX2NvcnJlY3RfZW50cnkpICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCBBY3R1YWwgPSBhY3R1YWwsCiAgICAgICAgIGBDUyByZXByZXNzaW9uIGluY2x1ZGVkYCA9IHByZWRfZW50cnksCiAgICAgICAgIGBCYXNlbGluZWAgPSBwcmVkX2Jhc2VsaW5lKQoKcHRzX2ltcHJvdmVkX2Z1bmRpbmcgPC0gcHRzX2NhdF9wcmVkcyAlPiUgCiAgZmlsdGVyKCFpc19jb3JyZWN0X2Jhc2VsaW5lICYgaXNfY29ycmVjdF9mdW5kaW5nKSAlPiUgCiAgc2VsZWN0KENvdW50cnkgPSBjb3VudHJ5LCBZZWFyID0geWVhciwgQWN0dWFsID0gYWN0dWFsLAogICAgICAgICBgQ1MgcmVwcmVzc2lvbiBpbmNsdWRlZGAgPSBwcmVkX2Z1bmRpbmcsCiAgICAgICAgIGBCYXNlbGluZWAgPSBwcmVkX2Jhc2VsaW5lKQoKcHRzX2ltcHJvdmVkX3RvdGFsICU+JSAKICBrYmwoY2FwdGlvbiA9ICJDYXNlcyBpbXByb3ZlZCB3aXRoIHRvdGFsIGxlZ2FsIGJhcnJpZXJzIikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQoKcHRzX2ltcHJvdmVkX2Fkdm9jYWN5ICU+JSAKICBrYmwoY2FwdGlvbiA9ICJDYXNlcyBpbXByb3ZlZCB3aXRoIGJhcnJpZXJzIHRvIGFkdm9jYWN5IikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQoKcHRzX2ltcHJvdmVkX2VudHJ5ICU+JSAKICBrYmwoY2FwdGlvbiA9ICJDYXNlcyBpbXByb3ZlZCB3aXRoIGJhcnJpZXJzIHRvIGVudHJ5IikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQoKcHRzX2ltcHJvdmVkX2Z1bmRpbmcgJT4lIAogIGtibChjYXB0aW9uID0gIkNhc2VzIGltcHJvdmVkIHdpdGggYmFycmllcnMgdG8gZnVuZGluZyIpICU+JSAKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpgYGB7ciBlMWEtY29ycmVjdC1ub3QtY29ycmVjdH0KY29ycmVjdF9sb29rdXAgPC0gdHJpYmJsZSgKICB+bmFtZSwgfm5pY2VfbmFtZSwKICAiaXNfY29ycmVjdF90b3RhbCIsICJUb3RhbCBsZWdhbCBiYXJyaWVycyBpbmNsdWRlZCIsCiAgImlzX2NvcnJlY3RfYWR2b2NhY3kiLCAiQmFycmllcnMgdG8gYWR2b2NhY3kgaW5jbHVkZWQiLAogICJpc19jb3JyZWN0X2VudHJ5IiwgIkJhcnJpZXJzIHRvIGVudHJ5IGluY2x1ZGVkIiwKICAiaXNfY29ycmVjdF9mdW5kaW5nIiwgIkJhcnJpZXJzIHRvIGZ1bmRpbmcgaW5jbHVkZWQiLAogICJpc19jb3JyZWN0X2Jhc2VsaW5lIiwgIkJhc2VsaW5lIgopICU+JSBtdXRhdGUobmljZV9uYW1lID0gZmN0X2lub3JkZXIobmljZV9uYW1lLCBvcmRlcmVkID0gVFJVRSkpCgpwdHNfcHJlZF90YWJsZSA8LSBwdHNfY2F0X3ByZWRzICU+JSAKICBwaXZvdF9sb25nZXIoc3RhcnRzX3dpdGgoImlzX2NvcnJlY3QiKSkgJT4lIAogIGdyb3VwX2J5KG5hbWUsIHZhbHVlKSAlPiUgCiAgc3VtbWFyaXplKG4gPSBuKCkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGxlZnRfam9pbihjb3JyZWN0X2xvb2t1cCwgYnkgPSAibmFtZSIpICU+JSAKICBtdXRhdGUoUHJlZGljdGlvbiA9IGlmZWxzZSh2YWx1ZSA9PSBUUlVFLCAiQ29ycmVjdCIsICJXcm9uZyIpKSAlPiUgCiAgYXJyYW5nZShuaWNlX25hbWUpICU+JSAKICBzZWxlY3QoLW5hbWUsIC12YWx1ZSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAibmljZV9uYW1lIiwgdmFsdWVzX2Zyb20gPSAibiIpCgpwdHNfcHJlZF90YWJsZSAlPiUgCiAga2JsKGFsaWduID0gImxjY2NjYyIpICU+JSAKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpcIAoKIyBFfjFifjogTkdPIGxhd3MgYW5kIHBoeXNpY2FsIHZpb2xlbmNlCgpgYGB7ciBlMWItcHJlZGljdGlvbnMsIHdhcm5pbmc9RkFMU0V9CnNlZWRfY2xwaHlfcHJlZGljdGlvbiA8LSA3Mjg1ICAjIEZyb20gcmFuZG9tLm9yZwoKc2V0LnNlZWQoc2VlZF9jbHBoeV9wcmVkaWN0aW9uKQpwcmVkX2NscGh5X2Jhc2VsaW5lIDwtIHByZWRpY3QobV9jbHBoeV9iYXNlbGluZV90cmFpbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLXYyeF9jbHBoeV9sZWFkMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRSkKCnNldC5zZWVkKHNlZWRfY2xwaHlfcHJlZGljdGlvbikKcHJlZF9jbHBoeV90b3RhbCA8LSBwcmVkaWN0KG1fY2xwaHlfdG90YWxfdHJhaW4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IHNlbGVjdChjYW5hcnlfdGVzdGluZ19sYWdnZWQsIC12MnhfY2xwaHlfbGVhZDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUpCgpzZXQuc2VlZChzZWVkX2NscGh5X3ByZWRpY3Rpb24pCnByZWRfY2xwaHlfYWR2b2NhY3kgPC0gcHJlZGljdChtX2NscGh5X2Fkdm9jYWN5X3RyYWluLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBzZWxlY3QoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkLCAtdjJ4X2NscGh5X2xlYWQxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93X25ld19sZXZlbHMgPSBUUlVFKQoKc2V0LnNlZWQoc2VlZF9jbHBoeV9wcmVkaWN0aW9uKQpwcmVkX2NscGh5X2VudHJ5IDwtIHByZWRpY3QobV9jbHBoeV9lbnRyeV90cmFpbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLXYyeF9jbHBoeV9sZWFkMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRSkKCnNldC5zZWVkKHNlZWRfY2xwaHlfcHJlZGljdGlvbikKcHJlZF9jbHBoeV9mdW5kaW5nIDwtIHByZWRpY3QobV9jbHBoeV9mdW5kaW5nX3RyYWluLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IHNlbGVjdChjYW5hcnlfdGVzdGluZ19sYWdnZWQsIC12MnhfY2xwaHlfbGVhZDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRSkKCnByZWRfY2xwaHlfYmFzZWxpbmVfdGVzdCA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSkgJT4lIAogIGJpbmRfY29scyhhc190aWJibGUocHJlZF9jbHBoeV9iYXNlbGluZSkpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHYyeF9jbHBoeV9sZWFkMSkpCgpwcmVkX2NscGh5X3RvdGFsX3Rlc3QgPC0gY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkICU+JSAKICBzZWxlY3QoY291bnRyeSwgZ3djb2RlLCB5ZWFyLCB2MnhfY2xwaHlfbGVhZDEpICU+JSAKICBiaW5kX2NvbHMoYXNfdGliYmxlKHByZWRfY2xwaHlfdG90YWwpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYSh2MnhfY2xwaHlfbGVhZDEpKQoKcHJlZF9jbHBoeV9hZHZvY2FjeV90ZXN0IDwtIGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCAlPiUgCiAgc2VsZWN0KGNvdW50cnksIGd3Y29kZSwgeWVhciwgdjJ4X2NscGh5X2xlYWQxKSAlPiUgCiAgYmluZF9jb2xzKGFzX3RpYmJsZShwcmVkX2NscGh5X2Fkdm9jYWN5KSkgJT4lIAogIGZpbHRlcighaXMubmEodjJ4X2NscGh5X2xlYWQxKSkKCnByZWRfY2xwaHlfZW50cnlfdGVzdCA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSkgJT4lIAogIGJpbmRfY29scyhhc190aWJibGUocHJlZF9jbHBoeV9lbnRyeSkpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHYyeF9jbHBoeV9sZWFkMSkpCgpwcmVkX2NscGh5X2Z1bmRpbmdfdGVzdCA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSkgJT4lIAogIGJpbmRfY29scyhhc190aWJibGUocHJlZF9jbHBoeV9mdW5kaW5nKSkgJT4lIAogIGZpbHRlcighaXMubmEodjJ4X2NscGh5X2xlYWQxKSkKYGBgCgojIyBJbXByb3ZlbWVudCBmcm9tIGJhc2VsaW5lIG1vZGVscwoKYGBge3IgZTFiLXByZWQtcGxvdHMsIHdhcm5pbmc9RkFMU0V9CnBsb3RfYmFzZWxpbmUgPC0gZ2dwbG90KHByZWRfY2xwaHlfYmFzZWxpbmVfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdjJ4X2NscGh5X2xlYWQxLCB5ID0gRXN0aW1hdGUpKSArCiAgZ2VvbV9hYmxpbmUobHR5ID0gMikgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIkJhc2VsaW5lIiwKICAgICAgIHggPSAiQWN0dWFsIHBoeXNpY2FsIHZpb2xlbmNlIGluZGV4ICh0ICsgMSkiLAogICAgICAgeSA9ICJQcmVkaWN0ZWQgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKSIpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV9uZ28oKQoKcGxvdF90b3RhbCA8LSBnZ3Bsb3QocHJlZF9jbHBoeV90b3RhbF90ZXN0LCAKICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB2MnhfY2xwaHlfbGVhZDEsIHkgPSBFc3RpbWF0ZSkpICsKICBnZW9tX2FibGluZShsdHkgPSAyKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiVG90YWwgbGVnYWwgYmFycmllcnMiLAogICAgICAgeCA9ICJBY3R1YWwgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKSIsCiAgICAgICB5ID0gIlByZWRpY3RlZCBwaHlzaWNhbCB2aW9sZW5jZSBpbmRleCAodCArIDEpIikgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lX25nbygpCgpwbG90X2Fkdm9jYWN5IDwtIGdncGxvdChwcmVkX2NscGh5X2Fkdm9jYWN5X3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHYyeF9jbHBoeV9sZWFkMSwgeSA9IEVzdGltYXRlKSkgKwogIGdlb21fYWJsaW5lKGx0eSA9IDIpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgbGFicyh0aXRsZSA9ICJCYXJyaWVycyB0byBhZHZvY2FjeSIsCiAgICAgICB4ID0gIkFjdHVhbCBwaHlzaWNhbCB2aW9sZW5jZSBpbmRleCAodCArIDEpIiwKICAgICAgIHkgPSAiUHJlZGljdGVkIHBoeXNpY2FsIHZpb2xlbmNlIGluZGV4ICh0ICsgMSkiKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfbmdvKCkKCnBsb3RfZW50cnkgPC0gZ2dwbG90KHByZWRfY2xwaHlfZW50cnlfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdjJ4X2NscGh5X2xlYWQxLCB5ID0gRXN0aW1hdGUpKSArCiAgZ2VvbV9hYmxpbmUobHR5ID0gMikgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIkJhcnJpZXJzIHRvIGVudHJ5IiwKICAgICAgIHggPSAiQWN0dWFsIHBoeXNpY2FsIHZpb2xlbmNlIGluZGV4ICh0ICsgMSkiLAogICAgICAgeSA9ICJQcmVkaWN0ZWQgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKSIpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV9uZ28oKQoKcGxvdF9mdW5kaW5nIDwtIGdncGxvdChwcmVkX2NscGh5X2Z1bmRpbmdfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB2MnhfY2xwaHlfbGVhZDEsIHkgPSBFc3RpbWF0ZSkpICsKICBnZW9tX2FibGluZShsdHkgPSAyKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiQmFycmllcnMgdG8gZnVuZGluZyIsCiAgICAgICB4ID0gIkFjdHVhbCBwaHlzaWNhbCB2aW9sZW5jZSBpbmRleCAodCArIDEpIiwKICAgICAgIHkgPSAiUHJlZGljdGVkIHBoeXNpY2FsIHZpb2xlbmNlIGluZGV4ICh0ICsgMSkiKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfbmdvKCkKCihwbG90X2Jhc2VsaW5lIHwgcGxvdF90b3RhbCkgLyAocGxvdF9hZHZvY2FjeSB8IHBsb3RfZW50cnkgfCBwbG90X2Z1bmRpbmcpCmBgYAoKYGBge3IgZTFiLW1ldHJpY3N9CmxvdHNhX21ldHJpY3MgPC0gbWV0cmljX3NldChybXNlLCByc3EsIG1hZSwgY2NjKQoKYmluZF9yb3dzKGxvdHNhX21ldHJpY3MocHJlZF9jbHBoeV9iYXNlbGluZV90ZXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgdHJ1dGggPSB2MnhfY2xwaHlfbGVhZDEsIAogICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlKSAlPiUgCiAgICAgICAgICAgIG11dGF0ZShNb2RlbCA9ICJCYXNlbGluZSIpLAogICAgICAgICAgbG90c2FfbWV0cmljcyhwcmVkX2NscGh5X3RvdGFsX3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICB0cnV0aCA9IHYyeF9jbHBoeV9sZWFkMSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGVzdGltYXRlID0gRXN0aW1hdGUpICU+JSAKICAgICAgICAgICAgbXV0YXRlKE1vZGVsID0gIlRvdGFsIGxlZ2FsIGJhcnJpZXJzIiksCiAgICAgICAgICBsb3RzYV9tZXRyaWNzKHByZWRfY2xwaHlfYWR2b2NhY3lfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIHRydXRoID0gdjJ4X2NscGh5X2xlYWQxLCAKICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdGUgPSBFc3RpbWF0ZSkgJT4lIAogICAgICAgICAgICBtdXRhdGUoTW9kZWwgPSAiQmFycmllcnMgdG8gYWR2b2NhY3kiKSwKICAgICAgICAgIGxvdHNhX21ldHJpY3MocHJlZF9jbHBoeV9lbnRyeV90ZXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgdHJ1dGggPSB2MnhfY2xwaHlfbGVhZDEsIAogICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlKSAlPiUgCiAgICAgICAgICAgIG11dGF0ZShNb2RlbCA9ICJCYXJyaWVycyB0byBlbnRyeSIpLAogICAgICAgICAgbG90c2FfbWV0cmljcyhwcmVkX2NscGh5X2Z1bmRpbmdfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIHRydXRoID0gdjJ4X2NscGh5X2xlYWQxLCAKICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdGUgPSBFc3RpbWF0ZSkgJT4lIAogICAgICAgICAgICBtdXRhdGUoTW9kZWwgPSAiQmFycmllcnMgdG8gZnVuZGluZyIpKSAlPiUgCiAgc2VsZWN0KE1vZGVsLCAubWV0cmljLCAuZXN0aW1hdGUpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gIi5tZXRyaWMiLCB2YWx1ZXNfZnJvbSA9ICIuZXN0aW1hdGUiKQpgYGAKCiMjIE1vc3QgaW1wcm92ZWQgY291bnRyaWVzCgojIyMgVG90YWwgbGVnYWwgYmFycmllcnMKCmBgYHtyIGUxYi1tb3N0LWltcHJvdmVkLXRvdGFsfQptb3N0X2ltcHJvdmVkX2NscGh5X3RvdGFsIDwtIGJpbmRfY29scygKICBwcmVkX2NscGh5X2Jhc2VsaW5lX3Rlc3QgJT4lIAogICAgbXV0YXRlKGVycm9yX2Jhc2VsaW5lID0gRXN0aW1hdGUgLSB2MnhfY2xwaHlfbGVhZDEpICU+JSAKICAgIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSwgCiAgICAgICAgICAgZXN0aW1hdGVfYmFzZWxpbmUgPSBFc3RpbWF0ZSwgZXJyb3JfYmFzZWxpbmUpLAogIHByZWRfY2xwaHlfdG90YWxfdGVzdCAlPiUgCiAgICBtdXRhdGUoZXJyb3JfdG90YWwgPSBFc3RpbWF0ZSAtIHYyeF9jbHBoeV9sZWFkMSkgJT4lIAogICAgc2VsZWN0KGVzdGltYXRlX3RvdGFsID0gRXN0aW1hdGUsIGVycm9yX3RvdGFsKQopICU+JSAKICBtdXRhdGUoaW1wcm92ZWQgPSBlcnJvcl90b3RhbCA8IDAgJiBhYnMoZXJyb3JfdG90YWwpIDwgYWJzKGVycm9yX2Jhc2VsaW5lKSkgJT4lIAogIG11dGF0ZShkaWZmID0gZXJyb3JfdG90YWwgLSBlcnJvcl9iYXNlbGluZSkgJT4lIAogIG11dGF0ZShhYnNfZGlmZiA9IGFicyhkaWZmKSkgJT4lIAogIGZpbHRlcihpbXByb3ZlZCkgJT4lIAogIGFycmFuZ2UoZGVzYyhhYnNfZGlmZikpCgpucm93KG1vc3RfaW1wcm92ZWRfY2xwaHlfdG90YWwpCgptb3N0X2ltcHJvdmVkX2NscGh5X3RvdGFsICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCAKICAgICAgICAgYEFjdHVhbCBwaHlzaWNhbCB2aW9sZW5jZSBpbmRleCAodCArIDEpYCA9ICB2MnhfY2xwaHlfbGVhZDEsCiAgICAgICAgIGBQcmVkaWN0ZWQgKGJhc2VsaW5lKWAgPSBlc3RpbWF0ZV9iYXNlbGluZSwKICAgICAgICAgYFByZWRpY3RlZCAoQ1MgcmVwcmVzc2lvbilgID0gZXN0aW1hdGVfdG90YWwsCiAgICAgICAgIGB8Q1MgcmVwcmVzc2lvbiDiiJIgYmFzZWxpbmV8YCA9IGFic19kaWZmKSAlPiUgCiAgaGVhZCg1KSAlPiUgCiAga2JsKGRpZ2l0cyA9IDMsIGFsaWduID0gImxjY2NjYyIpICU+JSAKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgojIyMgQmFycmllcnMgdG8gYWR2b2NhY3kKCmBgYHtyIGUxYi1tb3N0LWltcHJvdmVkLWFkdm9jYWN5fQptb3N0X2ltcHJvdmVkX2NscGh5X2Fkdm9jYWN5IDwtIGJpbmRfY29scygKICBwcmVkX2NscGh5X2Jhc2VsaW5lX3Rlc3QgJT4lIAogICAgbXV0YXRlKGVycm9yX2Jhc2VsaW5lID0gRXN0aW1hdGUgLSB2MnhfY2xwaHlfbGVhZDEpICU+JSAKICAgIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSwgCiAgICAgICAgICAgZXN0aW1hdGVfYmFzZWxpbmUgPSBFc3RpbWF0ZSwgZXJyb3JfYmFzZWxpbmUpLAogIHByZWRfY2xwaHlfYWR2b2NhY3lfdGVzdCAlPiUgCiAgICBtdXRhdGUoZXJyb3JfYWR2b2NhY3kgPSBFc3RpbWF0ZSAtIHYyeF9jbHBoeV9sZWFkMSkgJT4lIAogICAgc2VsZWN0KGVzdGltYXRlX2Fkdm9jYWN5ID0gRXN0aW1hdGUsIGVycm9yX2Fkdm9jYWN5KQopICU+JSAKICBtdXRhdGUoaW1wcm92ZWQgPSBlcnJvcl9hZHZvY2FjeSA8IDAgJiBhYnMoZXJyb3JfYWR2b2NhY3kpIDwgYWJzKGVycm9yX2Jhc2VsaW5lKSkgJT4lIAogIG11dGF0ZShkaWZmID0gZXJyb3JfYWR2b2NhY3kgLSBlcnJvcl9iYXNlbGluZSkgJT4lIAogIG11dGF0ZShhYnNfZGlmZiA9IGFicyhkaWZmKSkgJT4lIAogIGZpbHRlcihpbXByb3ZlZCkgJT4lIAogIGFycmFuZ2UoZGVzYyhhYnNfZGlmZikpCgpucm93KG1vc3RfaW1wcm92ZWRfY2xwaHlfYWR2b2NhY3kpCgptb3N0X2ltcHJvdmVkX2NscGh5X2Fkdm9jYWN5ICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCAKICAgICAgICAgYEFjdHVhbCBwaHlzaWNhbCB2aW9sZW5jZSBpbmRleCAodCArIDEpYCA9ICB2MnhfY2xwaHlfbGVhZDEsCiAgICAgICAgIGBQcmVkaWN0ZWQgKGJhc2VsaW5lKWAgPSBlc3RpbWF0ZV9iYXNlbGluZSwKICAgICAgICAgYFByZWRpY3RlZCAoQ1MgcmVwcmVzc2lvbilgID0gZXN0aW1hdGVfYWR2b2NhY3ksCiAgICAgICAgIGB8Q1MgcmVwcmVzc2lvbiDiiJIgYmFzZWxpbmV8YCA9IGFic19kaWZmKSAlPiUgCiAgaGVhZCg1KSAlPiUgCiAga2JsKGRpZ2l0cyA9IDMsIGFsaWduID0gImxjY2NjYyIpICU+JSAKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgojIyMgQmFycmllcnMgdG8gZW50cnkKCmBgYHtyIGUxYi1tb3N0LWltcHJvdmVkLWVudHJ5fQptb3N0X2ltcHJvdmVkX2NscGh5X2VudHJ5IDwtIGJpbmRfY29scygKICBwcmVkX2NscGh5X2Jhc2VsaW5lX3Rlc3QgJT4lIAogICAgbXV0YXRlKGVycm9yX2Jhc2VsaW5lID0gRXN0aW1hdGUgLSB2MnhfY2xwaHlfbGVhZDEpICU+JSAKICAgIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSwgCiAgICAgICAgICAgZXN0aW1hdGVfYmFzZWxpbmUgPSBFc3RpbWF0ZSwgZXJyb3JfYmFzZWxpbmUpLAogIHByZWRfY2xwaHlfZW50cnlfdGVzdCAlPiUgCiAgICBtdXRhdGUoZXJyb3JfZW50cnkgPSBFc3RpbWF0ZSAtIHYyeF9jbHBoeV9sZWFkMSkgJT4lIAogICAgc2VsZWN0KGVzdGltYXRlX2VudHJ5ID0gRXN0aW1hdGUsIGVycm9yX2VudHJ5KQopICU+JSAKICBtdXRhdGUoaW1wcm92ZWQgPSBlcnJvcl9lbnRyeSA8IDAgJiBhYnMoZXJyb3JfZW50cnkpIDwgYWJzKGVycm9yX2Jhc2VsaW5lKSkgJT4lIAogIG11dGF0ZShkaWZmID0gZXJyb3JfZW50cnkgLSBlcnJvcl9iYXNlbGluZSkgJT4lIAogIG11dGF0ZShhYnNfZGlmZiA9IGFicyhkaWZmKSkgJT4lIAogIGZpbHRlcihpbXByb3ZlZCkgJT4lIAogIGFycmFuZ2UoZGVzYyhhYnNfZGlmZikpCgpucm93KG1vc3RfaW1wcm92ZWRfY2xwaHlfZW50cnkpCgptb3N0X2ltcHJvdmVkX2NscGh5X2VudHJ5ICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCAKICAgICAgICAgYEFjdHVhbCBwaHlzaWNhbCB2aW9sZW5jZSBpbmRleCAodCArIDEpYCA9ICB2MnhfY2xwaHlfbGVhZDEsCiAgICAgICAgIGBQcmVkaWN0ZWQgKGJhc2VsaW5lKWAgPSBlc3RpbWF0ZV9iYXNlbGluZSwKICAgICAgICAgYFByZWRpY3RlZCAoQ1MgcmVwcmVzc2lvbilgID0gZXN0aW1hdGVfZW50cnksCiAgICAgICAgIGB8Q1MgcmVwcmVzc2lvbiDiiJIgYmFzZWxpbmV8YCA9IGFic19kaWZmKSAlPiUgCiAgaGVhZCg1KSAlPiUgCiAga2JsKGRpZ2l0cyA9IDMsIGFsaWduID0gImxjY2NjYyIpICU+JSAKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgojIyMgQmFycmllcnMgdG8gZnVuZGluZwoKYGBge3IgZTFiLW1vc3QtaW1wcm92ZWQtZnVuZGluZ30KbW9zdF9pbXByb3ZlZF9jbHBoeV9mdW5kaW5nIDwtIGJpbmRfY29scygKICBwcmVkX2NscGh5X2Jhc2VsaW5lX3Rlc3QgJT4lIAogICAgbXV0YXRlKGVycm9yX2Jhc2VsaW5lID0gRXN0aW1hdGUgLSB2MnhfY2xwaHlfbGVhZDEpICU+JSAKICAgIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSwgCiAgICAgICAgICAgZXN0aW1hdGVfYmFzZWxpbmUgPSBFc3RpbWF0ZSwgZXJyb3JfYmFzZWxpbmUpLAogIHByZWRfY2xwaHlfZnVuZGluZ190ZXN0ICU+JSAKICAgIG11dGF0ZShlcnJvcl9mdW5kaW5nID0gRXN0aW1hdGUgLSB2MnhfY2xwaHlfbGVhZDEpICU+JSAKICAgIHNlbGVjdChlc3RpbWF0ZV9mdW5kaW5nID0gRXN0aW1hdGUsIGVycm9yX2Z1bmRpbmcpCikgJT4lIAogIG11dGF0ZShpbXByb3ZlZCA9IGVycm9yX2Z1bmRpbmcgPCAwICYgYWJzKGVycm9yX2Z1bmRpbmcpIDwgYWJzKGVycm9yX2Jhc2VsaW5lKSkgJT4lIAogIG11dGF0ZShkaWZmID0gZXJyb3JfZnVuZGluZyAtIGVycm9yX2Jhc2VsaW5lKSAlPiUgCiAgbXV0YXRlKGFic19kaWZmID0gYWJzKGRpZmYpKSAlPiUgCiAgZmlsdGVyKGltcHJvdmVkKSAlPiUgCiAgYXJyYW5nZShkZXNjKGFic19kaWZmKSkKCm5yb3cobW9zdF9pbXByb3ZlZF9jbHBoeV9mdW5kaW5nKQoKbW9zdF9pbXByb3ZlZF9jbHBoeV9mdW5kaW5nICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCAKICAgICAgICAgYEFjdHVhbCBwaHlzaWNhbCB2aW9sZW5jZSBpbmRleCAodCArIDEpYCA9ICB2MnhfY2xwaHlfbGVhZDEsCiAgICAgICAgIGBQcmVkaWN0ZWQgKGJhc2VsaW5lKWAgPSBlc3RpbWF0ZV9iYXNlbGluZSwKICAgICAgICAgYFByZWRpY3RlZCAoQ1MgcmVwcmVzc2lvbilgID0gZXN0aW1hdGVfZnVuZGluZywKICAgICAgICAgYHxDUyByZXByZXNzaW9uIOKIkiBiYXNlbGluZXxgID0gYWJzX2RpZmYpICU+JSAKICBoZWFkKDUpICU+JSAKICBrYmwoZGlnaXRzID0gMywgYWxpZ24gPSAibGNjY2NjIikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQpgYGAKClwgCgojIEV+MWN+OiBOR08gbGF3cyBhbmQgY2l2aWwgbGliZXJ0aWVzCgpgYGB7ciBlMWMtcHJlZGljdGlvbnMsIHdhcm5pbmc9RkFMU0V9CnNlZWRfY2xwcml2X3ByZWRpY3Rpb24gPC0gNjY3MCAgIyBGcm9tIHJhbmRvbS5vcmcKCnNldC5zZWVkKHNlZWRfY2xwcml2X3ByZWRpY3Rpb24pCnByZWRfY2xwcml2X2Jhc2VsaW5lIDwtIHByZWRpY3QobV9jbHByaXZfYmFzZWxpbmVfdHJhaW4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBzZWxlY3QoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkLCAtdjJ4X2NscHJpdl9sZWFkMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUpCgpzZXQuc2VlZChzZWVkX2NscHJpdl9wcmVkaWN0aW9uKQpwcmVkX2NscHJpdl90b3RhbCA8LSBwcmVkaWN0KG1fY2xwcml2X3RvdGFsX3RyYWluLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLXYyeF9jbHByaXZfbGVhZDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93X25ld19sZXZlbHMgPSBUUlVFKQoKc2V0LnNlZWQoc2VlZF9jbHByaXZfcHJlZGljdGlvbikKcHJlZF9jbHByaXZfYWR2b2NhY3kgPC0gcHJlZGljdChtX2NscHJpdl9hZHZvY2FjeV90cmFpbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IHNlbGVjdChjYW5hcnlfdGVzdGluZ19sYWdnZWQsIC12MnhfY2xwcml2X2xlYWQxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRSkKCnNldC5zZWVkKHNlZWRfY2xwcml2X3ByZWRpY3Rpb24pCnByZWRfY2xwcml2X2VudHJ5IDwtIHByZWRpY3QobV9jbHByaXZfZW50cnlfdHJhaW4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBzZWxlY3QoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkLCAtdjJ4X2NscHJpdl9sZWFkMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUpCgpzZXQuc2VlZChzZWVkX2NscHJpdl9wcmVkaWN0aW9uKQpwcmVkX2NscHJpdl9mdW5kaW5nIDwtIHByZWRpY3QobV9jbHByaXZfZnVuZGluZ190cmFpbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLXYyeF9jbHByaXZfbGVhZDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUpCgpwcmVkX2NscHJpdl9iYXNlbGluZV90ZXN0IDwtIGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCAlPiUgCiAgc2VsZWN0KGNvdW50cnksIGd3Y29kZSwgeWVhciwgdjJ4X2NscHJpdl9sZWFkMSkgJT4lIAogIGJpbmRfY29scyhhc190aWJibGUocHJlZF9jbHByaXZfYmFzZWxpbmUpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYSh2MnhfY2xwcml2X2xlYWQxKSkKCnByZWRfY2xwcml2X3RvdGFsX3Rlc3QgPC0gY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkICU+JSAKICBzZWxlY3QoY291bnRyeSwgZ3djb2RlLCB5ZWFyLCB2MnhfY2xwcml2X2xlYWQxKSAlPiUgCiAgYmluZF9jb2xzKGFzX3RpYmJsZShwcmVkX2NscHJpdl90b3RhbCkpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHYyeF9jbHByaXZfbGVhZDEpKQoKcHJlZF9jbHByaXZfYWR2b2NhY3lfdGVzdCA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHByaXZfbGVhZDEpICU+JSAKICBiaW5kX2NvbHMoYXNfdGliYmxlKHByZWRfY2xwcml2X2Fkdm9jYWN5KSkgJT4lIAogIGZpbHRlcighaXMubmEodjJ4X2NscHJpdl9sZWFkMSkpCgpwcmVkX2NscHJpdl9lbnRyeV90ZXN0IDwtIGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCAlPiUgCiAgc2VsZWN0KGNvdW50cnksIGd3Y29kZSwgeWVhciwgdjJ4X2NscHJpdl9sZWFkMSkgJT4lIAogIGJpbmRfY29scyhhc190aWJibGUocHJlZF9jbHByaXZfZW50cnkpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYSh2MnhfY2xwcml2X2xlYWQxKSkKCnByZWRfY2xwcml2X2Z1bmRpbmdfdGVzdCA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHByaXZfbGVhZDEpICU+JSAKICBiaW5kX2NvbHMoYXNfdGliYmxlKHByZWRfY2xwcml2X2Z1bmRpbmcpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYSh2MnhfY2xwcml2X2xlYWQxKSkKYGBgCgojIyBJbXByb3ZlbWVudCBmcm9tIGJhc2VsaW5lIG1vZGVscwoKYGBge3IgZTFjLXByZWQtcGxvdHMsIHdhcm5pbmc9RkFMU0V9CnBsb3RfYmFzZWxpbmUgPC0gZ2dwbG90KHByZWRfY2xwcml2X2Jhc2VsaW5lX3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHYyeF9jbHByaXZfbGVhZDEsIHkgPSBFc3RpbWF0ZSkpICsKICBnZW9tX2FibGluZShsdHkgPSAyKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiQmFzZWxpbmUiLAogICAgICAgeCA9ICJBY3R1YWwgcHJpdmF0ZSBjaXZpbCBsaWJlcnRpZXMgaW5kZXggKHQgKyAxKSIsCiAgICAgICB5ID0gIlByZWRpY3RlZCBwcml2YXRlIGNpdmlsIGxpYmVydGllcyBpbmRleCAodCArIDEpIikgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lX25nbygpCgpwbG90X3RvdGFsIDwtIGdncGxvdChwcmVkX2NscHJpdl90b3RhbF90ZXN0LCAKICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB2MnhfY2xwcml2X2xlYWQxLCB5ID0gRXN0aW1hdGUpKSArCiAgZ2VvbV9hYmxpbmUobHR5ID0gMikgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIGxlZ2FsIGJhcnJpZXJzIiwKICAgICAgIHggPSAiQWN0dWFsIHByaXZhdGUgY2l2aWwgbGliZXJ0aWVzIGluZGV4ICh0ICsgMSkiLAogICAgICAgeSA9ICJQcmVkaWN0ZWQgcHJpdmF0ZSBjaXZpbCBsaWJlcnRpZXMgaW5kZXggKHQgKyAxKSIpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV9uZ28oKQoKcGxvdF9hZHZvY2FjeSA8LSBnZ3Bsb3QocHJlZF9jbHByaXZfYWR2b2NhY3lfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdjJ4X2NscHJpdl9sZWFkMSwgeSA9IEVzdGltYXRlKSkgKwogIGdlb21fYWJsaW5lKGx0eSA9IDIpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgbGFicyh0aXRsZSA9ICJCYXJyaWVycyB0byBhZHZvY2FjeSIsCiAgICAgICB4ID0gIkFjdHVhbCBwcml2YXRlIGNpdmlsIGxpYmVydGllcyBpbmRleCAodCArIDEpIiwKICAgICAgIHkgPSAiUHJlZGljdGVkIHByaXZhdGUgY2l2aWwgbGliZXJ0aWVzIGluZGV4ICh0ICsgMSkiKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfbmdvKCkKCnBsb3RfZW50cnkgPC0gZ2dwbG90KHByZWRfY2xwcml2X2VudHJ5X3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHYyeF9jbHByaXZfbGVhZDEsIHkgPSBFc3RpbWF0ZSkpICsKICBnZW9tX2FibGluZShsdHkgPSAyKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiQmFycmllcnMgdG8gZW50cnkiLAogICAgICAgeCA9ICJBY3R1YWwgcHJpdmF0ZSBjaXZpbCBsaWJlcnRpZXMgaW5kZXggKHQgKyAxKSIsCiAgICAgICB5ID0gIlByZWRpY3RlZCBwcml2YXRlIGNpdmlsIGxpYmVydGllcyBpbmRleCAodCArIDEpIikgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lX25nbygpCgpwbG90X2Z1bmRpbmcgPC0gZ2dwbG90KHByZWRfY2xwcml2X2Z1bmRpbmdfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB2MnhfY2xwcml2X2xlYWQxLCB5ID0gRXN0aW1hdGUpKSArCiAgZ2VvbV9hYmxpbmUobHR5ID0gMikgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIkJhcnJpZXJzIHRvIGZ1bmRpbmciLAogICAgICAgeCA9ICJBY3R1YWwgcHJpdmF0ZSBjaXZpbCBsaWJlcnRpZXMgaW5kZXggKHQgKyAxKSIsCiAgICAgICB5ID0gIlByZWRpY3RlZCBwcml2YXRlIGNpdmlsIGxpYmVydGllcyBpbmRleCAodCArIDEpIikgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lX25nbygpCgoocGxvdF9iYXNlbGluZSB8IHBsb3RfdG90YWwpIC8gKHBsb3RfYWR2b2NhY3kgfCBwbG90X2VudHJ5IHwgcGxvdF9mdW5kaW5nKQpgYGAKCmBgYHtyIGUxYy1tZXRyaWNzfQpsb3RzYV9tZXRyaWNzIDwtIG1ldHJpY19zZXQocm1zZSwgcnNxLCBtYWUsIGNjYykKCmJpbmRfcm93cyhsb3RzYV9tZXRyaWNzKHByZWRfY2xwcml2X2Jhc2VsaW5lX3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICB0cnV0aCA9IHYyeF9jbHByaXZfbGVhZDEsIAogICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlKSAlPiUgCiAgICAgICAgICAgIG11dGF0ZShNb2RlbCA9ICJCYXNlbGluZSIpLAogICAgICAgICAgbG90c2FfbWV0cmljcyhwcmVkX2NscHJpdl90b3RhbF90ZXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgdHJ1dGggPSB2MnhfY2xwcml2X2xlYWQxLCAKICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdGUgPSBFc3RpbWF0ZSkgJT4lIAogICAgICAgICAgICBtdXRhdGUoTW9kZWwgPSAiVG90YWwgbGVnYWwgYmFycmllcnMiKSwKICAgICAgICAgIGxvdHNhX21ldHJpY3MocHJlZF9jbHByaXZfYWR2b2NhY3lfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIHRydXRoID0gdjJ4X2NscHJpdl9sZWFkMSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGVzdGltYXRlID0gRXN0aW1hdGUpICU+JSAKICAgICAgICAgICAgbXV0YXRlKE1vZGVsID0gIkJhcnJpZXJzIHRvIGFkdm9jYWN5IiksCiAgICAgICAgICBsb3RzYV9tZXRyaWNzKHByZWRfY2xwcml2X2VudHJ5X3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICB0cnV0aCA9IHYyeF9jbHByaXZfbGVhZDEsIAogICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlKSAlPiUgCiAgICAgICAgICAgIG11dGF0ZShNb2RlbCA9ICJCYXJyaWVycyB0byBlbnRyeSIpLAogICAgICAgICAgbG90c2FfbWV0cmljcyhwcmVkX2NscHJpdl9mdW5kaW5nX3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICB0cnV0aCA9IHYyeF9jbHByaXZfbGVhZDEsIAogICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlKSAlPiUgCiAgICAgICAgICAgIG11dGF0ZShNb2RlbCA9ICJCYXJyaWVycyB0byBmdW5kaW5nIikpICU+JSAKICBzZWxlY3QoTW9kZWwsIC5tZXRyaWMsIC5lc3RpbWF0ZSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAiLm1ldHJpYyIsIHZhbHVlc19mcm9tID0gIi5lc3RpbWF0ZSIpCmBgYAoKIyMgTW9zdCBpbXByb3ZlZCBjb3VudHJpZXMKCiMjIyBUb3RhbCBsZWdhbCBiYXJyaWVycwoKYGBge3IgZTFjLW1vc3QtaW1wcm92ZWQtdG90YWx9Cm1vc3RfaW1wcm92ZWRfY2xwcml2X3RvdGFsIDwtIGJpbmRfY29scygKICBwcmVkX2NscHJpdl9iYXNlbGluZV90ZXN0ICU+JSAKICAgIG11dGF0ZShlcnJvcl9iYXNlbGluZSA9IEVzdGltYXRlIC0gdjJ4X2NscHJpdl9sZWFkMSkgJT4lIAogICAgc2VsZWN0KGNvdW50cnksIGd3Y29kZSwgeWVhciwgdjJ4X2NscHJpdl9sZWFkMSwgCiAgICAgICAgICAgZXN0aW1hdGVfYmFzZWxpbmUgPSBFc3RpbWF0ZSwgZXJyb3JfYmFzZWxpbmUpLAogIHByZWRfY2xwcml2X3RvdGFsX3Rlc3QgJT4lIAogICAgbXV0YXRlKGVycm9yX3RvdGFsID0gRXN0aW1hdGUgLSB2MnhfY2xwcml2X2xlYWQxKSAlPiUgCiAgICBzZWxlY3QoZXN0aW1hdGVfdG90YWwgPSBFc3RpbWF0ZSwgZXJyb3JfdG90YWwpCikgJT4lIAogIG11dGF0ZShpbXByb3ZlZCA9IGVycm9yX3RvdGFsIDwgMCAmIGFicyhlcnJvcl90b3RhbCkgPCBhYnMoZXJyb3JfYmFzZWxpbmUpKSAlPiUgCiAgbXV0YXRlKGRpZmYgPSBlcnJvcl90b3RhbCAtIGVycm9yX2Jhc2VsaW5lKSAlPiUgCiAgbXV0YXRlKGFic19kaWZmID0gYWJzKGRpZmYpKSAlPiUgCiAgZmlsdGVyKGltcHJvdmVkKSAlPiUgCiAgYXJyYW5nZShkZXNjKGFic19kaWZmKSkKCm5yb3cobW9zdF9pbXByb3ZlZF9jbHByaXZfdG90YWwpCgptb3N0X2ltcHJvdmVkX2NscHJpdl90b3RhbCAlPiUgCiAgc2VsZWN0KENvdW50cnkgPSBjb3VudHJ5LCBZZWFyID0geWVhciwgCiAgICAgICAgIGBBY3R1YWwgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKWAgPSAgdjJ4X2NscHJpdl9sZWFkMSwKICAgICAgICAgYFByZWRpY3RlZCAoYmFzZWxpbmUpYCA9IGVzdGltYXRlX2Jhc2VsaW5lLAogICAgICAgICBgUHJlZGljdGVkIChDUyByZXByZXNzaW9uKWAgPSBlc3RpbWF0ZV90b3RhbCwKICAgICAgICAgYHxDUyByZXByZXNzaW9uIOKIkiBiYXNlbGluZXxgID0gYWJzX2RpZmYpICU+JSAKICBoZWFkKDUpICU+JSAKICBrYmwoZGlnaXRzID0gMywgYWxpZ24gPSAibGNjY2NjIikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQpgYGAKCiMjIyBCYXJyaWVycyB0byBhZHZvY2FjeQoKYGBge3IgZTFjLW1vc3QtaW1wcm92ZWQtYWR2b2NhY3l9Cm1vc3RfaW1wcm92ZWRfY2xwcml2X2Fkdm9jYWN5IDwtIGJpbmRfY29scygKICBwcmVkX2NscHJpdl9iYXNlbGluZV90ZXN0ICU+JSAKICAgIG11dGF0ZShlcnJvcl9iYXNlbGluZSA9IEVzdGltYXRlIC0gdjJ4X2NscHJpdl9sZWFkMSkgJT4lIAogICAgc2VsZWN0KGNvdW50cnksIGd3Y29kZSwgeWVhciwgdjJ4X2NscHJpdl9sZWFkMSwgCiAgICAgICAgICAgZXN0aW1hdGVfYmFzZWxpbmUgPSBFc3RpbWF0ZSwgZXJyb3JfYmFzZWxpbmUpLAogIHByZWRfY2xwcml2X2Fkdm9jYWN5X3Rlc3QgJT4lIAogICAgbXV0YXRlKGVycm9yX2Fkdm9jYWN5ID0gRXN0aW1hdGUgLSB2MnhfY2xwcml2X2xlYWQxKSAlPiUgCiAgICBzZWxlY3QoZXN0aW1hdGVfYWR2b2NhY3kgPSBFc3RpbWF0ZSwgZXJyb3JfYWR2b2NhY3kpCikgJT4lIAogIG11dGF0ZShpbXByb3ZlZCA9IGVycm9yX2Fkdm9jYWN5IDwgMCAmIGFicyhlcnJvcl9hZHZvY2FjeSkgPCBhYnMoZXJyb3JfYmFzZWxpbmUpKSAlPiUgCiAgbXV0YXRlKGRpZmYgPSBlcnJvcl9hZHZvY2FjeSAtIGVycm9yX2Jhc2VsaW5lKSAlPiUgCiAgbXV0YXRlKGFic19kaWZmID0gYWJzKGRpZmYpKSAlPiUgCiAgZmlsdGVyKGltcHJvdmVkKSAlPiUgCiAgYXJyYW5nZShkZXNjKGFic19kaWZmKSkKCm5yb3cobW9zdF9pbXByb3ZlZF9jbHByaXZfYWR2b2NhY3kpCgptb3N0X2ltcHJvdmVkX2NscHJpdl9hZHZvY2FjeSAlPiUgCiAgc2VsZWN0KENvdW50cnkgPSBjb3VudHJ5LCBZZWFyID0geWVhciwgCiAgICAgICAgIGBBY3R1YWwgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKWAgPSAgdjJ4X2NscHJpdl9sZWFkMSwKICAgICAgICAgYFByZWRpY3RlZCAoYmFzZWxpbmUpYCA9IGVzdGltYXRlX2Jhc2VsaW5lLAogICAgICAgICBgUHJlZGljdGVkIChDUyByZXByZXNzaW9uKWAgPSBlc3RpbWF0ZV9hZHZvY2FjeSwKICAgICAgICAgYHxDUyByZXByZXNzaW9uIOKIkiBiYXNlbGluZXxgID0gYWJzX2RpZmYpICU+JSAKICBoZWFkKDUpICU+JSAKICBrYmwoZGlnaXRzID0gMywgYWxpZ24gPSAibGNjY2NjIikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQpgYGAKCiMjIyBCYXJyaWVycyB0byBlbnRyeQoKYGBge3IgZTFjLW1vc3QtaW1wcm92ZWQtZW50cnl9Cm1vc3RfaW1wcm92ZWRfY2xwcml2X2VudHJ5IDwtIGJpbmRfY29scygKICBwcmVkX2NscHJpdl9iYXNlbGluZV90ZXN0ICU+JSAKICAgIG11dGF0ZShlcnJvcl9iYXNlbGluZSA9IEVzdGltYXRlIC0gdjJ4X2NscHJpdl9sZWFkMSkgJT4lIAogICAgc2VsZWN0KGNvdW50cnksIGd3Y29kZSwgeWVhciwgdjJ4X2NscHJpdl9sZWFkMSwgCiAgICAgICAgICAgZXN0aW1hdGVfYmFzZWxpbmUgPSBFc3RpbWF0ZSwgZXJyb3JfYmFzZWxpbmUpLAogIHByZWRfY2xwcml2X2VudHJ5X3Rlc3QgJT4lIAogICAgbXV0YXRlKGVycm9yX2VudHJ5ID0gRXN0aW1hdGUgLSB2MnhfY2xwcml2X2xlYWQxKSAlPiUgCiAgICBzZWxlY3QoZXN0aW1hdGVfZW50cnkgPSBFc3RpbWF0ZSwgZXJyb3JfZW50cnkpCikgJT4lIAogIG11dGF0ZShpbXByb3ZlZCA9IGVycm9yX2VudHJ5IDwgMCAmIGFicyhlcnJvcl9lbnRyeSkgPCBhYnMoZXJyb3JfYmFzZWxpbmUpKSAlPiUgCiAgbXV0YXRlKGRpZmYgPSBlcnJvcl9lbnRyeSAtIGVycm9yX2Jhc2VsaW5lKSAlPiUgCiAgbXV0YXRlKGFic19kaWZmID0gYWJzKGRpZmYpKSAlPiUgCiAgZmlsdGVyKGltcHJvdmVkKSAlPiUgCiAgYXJyYW5nZShkZXNjKGFic19kaWZmKSkKCm5yb3cobW9zdF9pbXByb3ZlZF9jbHByaXZfZW50cnkpCgptb3N0X2ltcHJvdmVkX2NscHJpdl9lbnRyeSAlPiUgCiAgc2VsZWN0KENvdW50cnkgPSBjb3VudHJ5LCBZZWFyID0geWVhciwgCiAgICAgICAgIGBBY3R1YWwgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKWAgPSAgdjJ4X2NscHJpdl9sZWFkMSwKICAgICAgICAgYFByZWRpY3RlZCAoYmFzZWxpbmUpYCA9IGVzdGltYXRlX2Jhc2VsaW5lLAogICAgICAgICBgUHJlZGljdGVkIChDUyByZXByZXNzaW9uKWAgPSBlc3RpbWF0ZV9lbnRyeSwKICAgICAgICAgYHxDUyByZXByZXNzaW9uIOKIkiBiYXNlbGluZXxgID0gYWJzX2RpZmYpICU+JSAKICBoZWFkKDUpICU+JSAKICBrYmwoZGlnaXRzID0gMywgYWxpZ24gPSAibGNjY2NjIikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQpgYGAKCiMjIyBCYXJyaWVycyB0byBmdW5kaW5nCgpgYGB7ciBlMWMtbW9zdC1pbXByb3ZlZC1mdW5kaW5nfQptb3N0X2ltcHJvdmVkX2NscHJpdl9mdW5kaW5nIDwtIGJpbmRfY29scygKICBwcmVkX2NscHJpdl9iYXNlbGluZV90ZXN0ICU+JSAKICAgIG11dGF0ZShlcnJvcl9iYXNlbGluZSA9IEVzdGltYXRlIC0gdjJ4X2NscHJpdl9sZWFkMSkgJT4lIAogICAgc2VsZWN0KGNvdW50cnksIGd3Y29kZSwgeWVhciwgdjJ4X2NscHJpdl9sZWFkMSwgCiAgICAgICAgICAgZXN0aW1hdGVfYmFzZWxpbmUgPSBFc3RpbWF0ZSwgZXJyb3JfYmFzZWxpbmUpLAogIHByZWRfY2xwcml2X2Z1bmRpbmdfdGVzdCAlPiUgCiAgICBtdXRhdGUoZXJyb3JfZnVuZGluZyA9IEVzdGltYXRlIC0gdjJ4X2NscHJpdl9sZWFkMSkgJT4lIAogICAgc2VsZWN0KGVzdGltYXRlX2Z1bmRpbmcgPSBFc3RpbWF0ZSwgZXJyb3JfZnVuZGluZykKKSAlPiUgCiAgbXV0YXRlKGltcHJvdmVkID0gZXJyb3JfZnVuZGluZyA8IDAgJiBhYnMoZXJyb3JfZnVuZGluZykgPCBhYnMoZXJyb3JfYmFzZWxpbmUpKSAlPiUgCiAgbXV0YXRlKGRpZmYgPSBlcnJvcl9mdW5kaW5nIC0gZXJyb3JfYmFzZWxpbmUpICU+JSAKICBtdXRhdGUoYWJzX2RpZmYgPSBhYnMoZGlmZikpICU+JSAKICBmaWx0ZXIoaW1wcm92ZWQpICU+JSAKICBhcnJhbmdlKGRlc2MoYWJzX2RpZmYpKQoKbnJvdyhtb3N0X2ltcHJvdmVkX2NscHJpdl9mdW5kaW5nKQoKbW9zdF9pbXByb3ZlZF9jbHByaXZfZnVuZGluZyAlPiUgCiAgc2VsZWN0KENvdW50cnkgPSBjb3VudHJ5LCBZZWFyID0geWVhciwgCiAgICAgICAgIGBBY3R1YWwgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKWAgPSAgdjJ4X2NscHJpdl9sZWFkMSwKICAgICAgICAgYFByZWRpY3RlZCAoYmFzZWxpbmUpYCA9IGVzdGltYXRlX2Jhc2VsaW5lLAogICAgICAgICBgUHJlZGljdGVkIChDUyByZXByZXNzaW9uKWAgPSBlc3RpbWF0ZV9mdW5kaW5nLAogICAgICAgICBgfENTIHJlcHJlc3Npb24g4oiSIGJhc2VsaW5lfGAgPSBhYnNfZGlmZikgJT4lIAogIGhlYWQoNSkgJT4lIAogIGtibChkaWdpdHMgPSAzLCBhbGlnbiA9ICJsY2NjY2MiKSAlPiUgCiAga2FibGVfc3R5bGluZygpCmBgYAoKXCAKCi0tLQoKXCAKCiMgRX4yYX46IENpdmlsIHNvY2lldHkgZW52aXJvbm1lbnQgYW5kIHBvbGl0aWNhbCB0ZXJyb3IKCmBgYHtyIGUyYS1wcmVkaWN0aW9ucywgd2FybmluZz1GQUxTRX0Kc2VlZF9wdHNfcHJlZGljdGlvbiA8LSA1NDk0ICAjIEZyb20gcmFuZG9tLm9yZwoKc2V0LnNlZWQoc2VlZF9wdHNfcHJlZGljdGlvbikKcHJlZF9wdHNfYmFzZWxpbmUgPC0gcHJlZGljdCgKICBtX3B0c19iYXNlbGluZV90cmFpbiwgCiAgbmV3ZGF0YSA9IHNlbGVjdChjYW5hcnlfdGVzdGluZ19sYWdnZWQsIC1QVFNfZmFjdG9yX2xlYWQxKSwKICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRQopICU+JSAKICBhc190aWJibGUoKSAlPiUgCiAgbWFncml0dHI6OnNldF9jb2xuYW1lcyhwdHNfbGV2ZWxzKQoKc2V0LnNlZWQoc2VlZF9wdHNfcHJlZGljdGlvbikKcHJlZF9wdHNfdjJjc3JlcHJzcyA8LSBwcmVkaWN0KAogIG1fcHRzX3YyY3NyZXByc3NfdHJhaW4sIAogIG5ld2RhdGEgPSBzZWxlY3QoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkLCAtUFRTX2ZhY3Rvcl9sZWFkMSksCiAgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUKKSAlPiUgCiAgYXNfdGliYmxlKCkgJT4lIAogIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMocHRzX2xldmVscykKCnNldC5zZWVkKHNlZWRfcHRzX3ByZWRpY3Rpb24pCnByZWRfcHRzX2Jhc2VsaW5lX3Jld2IgPC0gcHJlZGljdCgKICBtX3B0c19iYXNlbGluZV9yZXdiX3RyYWluLCAKICBuZXdkYXRhID0gc2VsZWN0KGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCwgLVBUU19mYWN0b3JfbGVhZDEpLAogIGFsbG93X25ld19sZXZlbHMgPSBUUlVFCikgJT4lIAogIGFzX3RpYmJsZSgpICU+JSAKICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKHB0c19sZXZlbHMpCgpzZXQuc2VlZChzZWVkX3B0c19wcmVkaWN0aW9uKQpwcmVkX3B0c192MmNzcmVwcnNzX3Jld2IgPC0gcHJlZGljdCgKICBtX3B0c192MmNzcmVwcnNzX3Jld2JfdHJhaW4sIAogIG5ld2RhdGEgPSBzZWxlY3QoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkLCAtUFRTX2ZhY3Rvcl9sZWFkMSksCiAgYWxsb3dfbmV3X2xldmVscyA9IFRSVUUKKSAlPiUgCiAgYXNfdGliYmxlKCkgJT4lIAogIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMocHRzX2xldmVscykKYGBgCgoKIyMgU2VwYXJhdGlvbiBwbG90cwoKIyMjIEJhc2VsaW5lIG1vZGVsCgpgYGB7ciBlMmEtc2VwYXJhdGlvbi1iYXNlbGluZX0KIyBNYXRjaCBlYWNoIGNvbHVtbiBpbiBwcmVkX21hdCAocHJlZGljdGVkIHByb2JhYmlsaXRpZXMgZm9yIGVhY2ggcmVzcG9uc2UgbGV2ZWwpCnByZWRfbG9uZ19saXN0IDwtIGxhcHBseSgxOm5jb2wocHJlZF9wdHNfYmFzZWxpbmUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9IG1hdGNoX2FjdHVhbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkID0gcHJlZF9wdHNfYmFzZWxpbmUsIAogICAgICAgICAgICAgICAgICAgICAgICAgYWN0dWFsID0gYXMuY2hhcmFjdGVyKGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCRQVFNfZmFjdG9yX2xlYWQxKSkKCnBsb3RfZGF0YSA8LSBwcmVkX2xvbmdfbGlzdCAlPiUgCiAgYmluZF9yb3dzKCkgJT4lIAogIGZpbHRlcighaXMubmFuKGZpdHRlZCksICFpcy5uYShhY3R1YWwpKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lIAogIGFycmFuZ2UocGxvdF9sZXZlbCwgZml0dGVkKSAlPiUgCiAgbXV0YXRlKGluZGV4ID0gcm93X251bWJlcigpKSAlPiUgCiAgdW5ncm91cCgpCgptYXJrZXJzIDwtIHBsb3RfZGF0YSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lCiAgc3VtbWFyaXplKG9icyA9IG4oKSwgZXhwZWN0ZWQgPSBzdW0oZml0dGVkKSwKICAgICAgICAgICAgbWFya2VyID0gb2JzIC0gZXhwZWN0ZWQgKyAxKQoKbl9pbl9ncm91cCA8LSBucm93KHByZWRfcHRzX2Jhc2VsaW5lKQoKcGxvdF9kYXRhX2NvbmRlbnNlZCA8LSBwbG90X2RhdGEgJT4lIAogICMgcmxlKCksIGRwbHlyLXN0eWxlOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzM1MTA3NjUvMTIwODk4CiAgbXV0YXRlKHJsZWlkID0gKGFjdHVhbCAhPSBsYWcoYWN0dWFsLCAxLCBkZWZhdWx0ID0gMCkpKSAlPiUKICBtdXRhdGUocmxlaWQgPSBjdW1zdW0ocmxlaWQpKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCwgcmxlaWQpICU+JSAKICBzbGljZSgxKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lIAogIG11dGF0ZSh4bWluID0gaW5kZXgsIHhtYXggPSBsZWFkKGluZGV4LCBkZWZhdWx0ID0gbl9pbl9ncm91cCkpICU+JSAKICB1bmdyb3VwKCkKCmdncGxvdChwbG90X2RhdGFfY29uZGVuc2VkKSArCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0geG1pbiwgeG1heCA9IHhtYXgsIHltaW4gPSAwLCB5bWF4ID0gMSwgZmlsbCA9IGFzLmZhY3RvcihhY3R1YWwpKSkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBpbmRleCwgeSA9IGZpdHRlZCksIHNpemUgPSAwLjMpICsKICBnZW9tX3BvaW50KGRhdGEgPSBtYXJrZXJzLCBhZXMoeCA9IG1hcmtlciwgeSA9IC0wLjA1KSwgc2hhcGUgPSAxNywgc2l6ZSA9IDMpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZ3JleTkwIiwgIiMyRUNDNDAiKSkgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UpICsKICBmYWNldF93cmFwKHZhcnMocGxvdF9sZXZlbCksIG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHRoZW1lX3ZvaWQoYmFzZV9mYW1pbHkgPSAiSW50ZXIgQm9sZCIpCmBgYAoKIyMjIE1vZGVsIHdpdGggY2l2aWwgc29jaWV0eSByZXByZXNzaW9uCgpgYGB7ciBlMmEtc2VwYXJhdGlvbi1jc30KcHJlZF9sb25nX2xpc3QgPC0gbGFwcGx5KDE6bmNvbChwcmVkX3B0c192MmNzcmVwcnNzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSBtYXRjaF9hY3R1YWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgcHJlZCA9IHByZWRfcHRzX3YyY3NyZXByc3MsIAogICAgICAgICAgICAgICAgICAgICAgICAgYWN0dWFsID0gYXMuY2hhcmFjdGVyKGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCRQVFNfZmFjdG9yX2xlYWQxKSkKCnBsb3RfZGF0YSA8LSBwcmVkX2xvbmdfbGlzdCAlPiUgCiAgYmluZF9yb3dzKCkgJT4lIAogIGZpbHRlcighaXMubmFuKGZpdHRlZCksICFpcy5uYShhY3R1YWwpKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lIAogIGFycmFuZ2UocGxvdF9sZXZlbCwgZml0dGVkKSAlPiUgCiAgbXV0YXRlKGluZGV4ID0gcm93X251bWJlcigpKSAlPiUgCiAgdW5ncm91cCgpCgptYXJrZXJzIDwtIHBsb3RfZGF0YSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lCiAgc3VtbWFyaXplKG9icyA9IG4oKSwgZXhwZWN0ZWQgPSBzdW0oZml0dGVkKSwKICAgICAgICAgICAgbWFya2VyID0gb2JzIC0gZXhwZWN0ZWQgKyAxKQoKbl9pbl9ncm91cCA8LSBucm93KHByZWRfcHRzX3YyY3NyZXByc3MpCgpwbG90X2RhdGFfY29uZGVuc2VkIDwtIHBsb3RfZGF0YSAlPiUgCiAgIyBybGUoKSwgZHBseXItc3R5bGU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zMzUxMDc2NS8xMjA4OTgKICBtdXRhdGUocmxlaWQgPSAoYWN0dWFsICE9IGxhZyhhY3R1YWwsIDEsIGRlZmF1bHQgPSAwKSkpICU+JQogIG11dGF0ZShybGVpZCA9IGN1bXN1bShybGVpZCkpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsLCBybGVpZCkgJT4lIAogIHNsaWNlKDEpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsKSAlPiUgCiAgbXV0YXRlKHhtaW4gPSBpbmRleCwgeG1heCA9IGxlYWQoaW5kZXgsIGRlZmF1bHQgPSBuX2luX2dyb3VwKSkgJT4lIAogIHVuZ3JvdXAoKQoKZ2dwbG90KHBsb3RfZGF0YV9jb25kZW5zZWQpICsKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSB4bWluLCB4bWF4ID0geG1heCwgeW1pbiA9IDAsIHltYXggPSAxLCBmaWxsID0gYXMuZmFjdG9yKGFjdHVhbCkpKSArIAogIGdlb21fbGluZShhZXMoeCA9IGluZGV4LCB5ID0gZml0dGVkKSwgc2l6ZSA9IDAuMykgKwogIGdlb21fcG9pbnQoZGF0YSA9IG1hcmtlcnMsIGFlcyh4ID0gbWFya2VyLCB5ID0gLTAuMDUpLCBzaGFwZSA9IDE3LCBzaXplID0gMykgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJncmV5OTAiLCAiIzJFQ0M0MCIpKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAodmFycyhwbG90X2xldmVsKSwgbmNvbCA9IDEsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgdGhlbWVfdm9pZChiYXNlX2ZhbWlseSA9ICJJbnRlciBCb2xkIikKYGBgCgojIyMgQmFzZWxpbmUgbW9kZWwgKFJFV0IpCgpgYGB7ciBlMmEtc2VwYXJhdGlvbi1iYXNlbGluZS1yZXdifQojIE1hdGNoIGVhY2ggY29sdW1uIGluIHByZWRfbWF0IChwcmVkaWN0ZWQgcHJvYmFiaWxpdGllcyBmb3IgZWFjaCByZXNwb25zZSBsZXZlbCkKcHJlZF9sb25nX2xpc3QgPC0gbGFwcGx5KDE6bmNvbChwcmVkX3B0c19iYXNlbGluZV9yZXdiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSBtYXRjaF9hY3R1YWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgcHJlZCA9IHByZWRfcHRzX2Jhc2VsaW5lX3Jld2IsIAogICAgICAgICAgICAgICAgICAgICAgICAgYWN0dWFsID0gYXMuY2hhcmFjdGVyKGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCRQVFNfZmFjdG9yX2xlYWQxKSkKCnBsb3RfZGF0YSA8LSBwcmVkX2xvbmdfbGlzdCAlPiUgCiAgYmluZF9yb3dzKCkgJT4lIAogIGZpbHRlcighaXMubmFuKGZpdHRlZCksICFpcy5uYShhY3R1YWwpKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lIAogIGFycmFuZ2UocGxvdF9sZXZlbCwgZml0dGVkKSAlPiUgCiAgbXV0YXRlKGluZGV4ID0gcm93X251bWJlcigpKSAlPiUgCiAgdW5ncm91cCgpCgptYXJrZXJzIDwtIHBsb3RfZGF0YSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lCiAgc3VtbWFyaXplKG9icyA9IG4oKSwgZXhwZWN0ZWQgPSBzdW0oZml0dGVkKSwKICAgICAgICAgICAgbWFya2VyID0gb2JzIC0gZXhwZWN0ZWQgKyAxKQoKbl9pbl9ncm91cCA8LSBucm93KHByZWRfcHRzX2Jhc2VsaW5lX3Jld2IpCgpwbG90X2RhdGFfY29uZGVuc2VkIDwtIHBsb3RfZGF0YSAlPiUgCiAgIyBybGUoKSwgZHBseXItc3R5bGU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zMzUxMDc2NS8xMjA4OTgKICBtdXRhdGUocmxlaWQgPSAoYWN0dWFsICE9IGxhZyhhY3R1YWwsIDEsIGRlZmF1bHQgPSAwKSkpICU+JQogIG11dGF0ZShybGVpZCA9IGN1bXN1bShybGVpZCkpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsLCBybGVpZCkgJT4lIAogIHNsaWNlKDEpICU+JSAKICBncm91cF9ieShwbG90X2xldmVsKSAlPiUgCiAgbXV0YXRlKHhtaW4gPSBpbmRleCwgeG1heCA9IGxlYWQoaW5kZXgsIGRlZmF1bHQgPSBuX2luX2dyb3VwKSkgJT4lIAogIHVuZ3JvdXAoKQoKZ2dwbG90KHBsb3RfZGF0YV9jb25kZW5zZWQpICsKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSB4bWluLCB4bWF4ID0geG1heCwgeW1pbiA9IDAsIHltYXggPSAxLCBmaWxsID0gYXMuZmFjdG9yKGFjdHVhbCkpKSArIAogIGdlb21fbGluZShhZXMoeCA9IGluZGV4LCB5ID0gZml0dGVkKSwgc2l6ZSA9IDAuMykgKwogIGdlb21fcG9pbnQoZGF0YSA9IG1hcmtlcnMsIGFlcyh4ID0gbWFya2VyLCB5ID0gLTAuMDUpLCBzaGFwZSA9IDE3LCBzaXplID0gMykgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJncmV5OTAiLCAiIzJFQ0M0MCIpKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAodmFycyhwbG90X2xldmVsKSwgbmNvbCA9IDEsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgdGhlbWVfdm9pZChiYXNlX2ZhbWlseSA9ICJJbnRlciBCb2xkIikKYGBgCgojIyMgTW9kZWwgd2l0aCBjaXZpbCBzb2NpZXR5IHJlcHJlc3Npb24gKFJFV0IpCgpgYGB7ciBlMmEtc2VwYXJhdGlvbi1jcy1yZXdifQpwcmVkX2xvbmdfbGlzdCA8LSBsYXBwbHkoMTpuY29sKHByZWRfcHRzX3YyY3NyZXByc3NfcmV3YiksIAogICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gbWF0Y2hfYWN0dWFsLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHByZWQgPSBwcmVkX3B0c192MmNzcmVwcnNzX3Jld2IsIAogICAgICAgICAgICAgICAgICAgICAgICAgYWN0dWFsID0gYXMuY2hhcmFjdGVyKGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCRQVFNfZmFjdG9yX2xlYWQxKSkKCnBsb3RfZGF0YSA8LSBwcmVkX2xvbmdfbGlzdCAlPiUgCiAgYmluZF9yb3dzKCkgJT4lIAogIGZpbHRlcighaXMubmFuKGZpdHRlZCksICFpcy5uYShhY3R1YWwpKSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lIAogIGFycmFuZ2UocGxvdF9sZXZlbCwgZml0dGVkKSAlPiUgCiAgbXV0YXRlKGluZGV4ID0gcm93X251bWJlcigpKSAlPiUgCiAgdW5ncm91cCgpCgptYXJrZXJzIDwtIHBsb3RfZGF0YSAlPiUgCiAgZ3JvdXBfYnkocGxvdF9sZXZlbCkgJT4lCiAgc3VtbWFyaXplKG9icyA9IG4oKSwgZXhwZWN0ZWQgPSBzdW0oZml0dGVkKSwKICAgICAgICAgICAgbWFya2VyID0gb2JzIC0gZXhwZWN0ZWQgKyAxKQoKbl9pbl9ncm91cCA8LSBucm93KHByZWRfcHRzX3YyY3NyZXByc3NfcmV3YikKCnBsb3RfZGF0YV9jb25kZW5zZWQgPC0gcGxvdF9kYXRhICU+JSAKICAjIHJsZSgpLCBkcGx5ci1zdHlsZTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzMzNTEwNzY1LzEyMDg5OAogIG11dGF0ZShybGVpZCA9IChhY3R1YWwgIT0gbGFnKGFjdHVhbCwgMSwgZGVmYXVsdCA9IDApKSkgJT4lCiAgbXV0YXRlKHJsZWlkID0gY3Vtc3VtKHJsZWlkKSkgJT4lIAogIGdyb3VwX2J5KHBsb3RfbGV2ZWwsIHJsZWlkKSAlPiUgCiAgc2xpY2UoMSkgJT4lIAogIGdyb3VwX2J5KHBsb3RfbGV2ZWwpICU+JSAKICBtdXRhdGUoeG1pbiA9IGluZGV4LCB4bWF4ID0gbGVhZChpbmRleCwgZGVmYXVsdCA9IG5faW5fZ3JvdXApKSAlPiUgCiAgdW5ncm91cCgpCgpnZ3Bsb3QocGxvdF9kYXRhX2NvbmRlbnNlZCkgKwogIGdlb21fcmVjdChhZXMoeG1pbiA9IHhtaW4sIHhtYXggPSB4bWF4LCB5bWluID0gMCwgeW1heCA9IDEsIGZpbGwgPSBhcy5mYWN0b3IoYWN0dWFsKSkpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0gaW5kZXgsIHkgPSBmaXR0ZWQpLCBzaXplID0gMC4zKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbWFya2VycywgYWVzKHggPSBtYXJrZXIsIHkgPSAtMC4wNSksIHNoYXBlID0gMTcsIHNpemUgPSAzKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImdyZXk5MCIsICIjMkVDQzQwIikpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh2YXJzKHBsb3RfbGV2ZWwpLCBuY29sID0gMSwgc2NhbGVzID0gImZyZWVfeCIpICsKICB0aGVtZV92b2lkKGJhc2VfZmFtaWx5ID0gIkludGVyIEJvbGQiKQpgYGAKCgojIyBQcmVkaWN0aW9uIGRpYWdub3N0aWNzCgpgYGB7ciBlMmEtaW1wcm92ZWQtY2FzZXN9CnByZWRfcHRzX2Jhc2VsaW5lX2NhdGVnb3JpZXMgPC0gcHJlZF9wdHNfYmFzZWxpbmUgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigpICU+JSAKICBwaXZvdF9sb25nZXIoLXJvd25hbWUpICU+JSAKICBncm91cF9ieShyb3duYW1lKSAlPiUgCiAgZmlsdGVyKHJhbmsoLXZhbHVlLCB0aWVzLm1ldGhvZCA9ICJsYXN0IikgPT0gMSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KHByZWRpY3RlZCA9IG5hbWUpCgpwcmVkX3B0c192MmNzcmVwcnNzX2NhdGVnb3JpZXMgPC0gcHJlZF9wdHNfdjJjc3JlcHJzcyAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKCkgJT4lIAogIHBpdm90X2xvbmdlcigtcm93bmFtZSkgJT4lIAogIGdyb3VwX2J5KHJvd25hbWUpICU+JSAKICBmaWx0ZXIocmFuaygtdmFsdWUsIHRpZXMubWV0aG9kID0gImxhc3QiKSA9PSAxKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3QocHJlZGljdGVkID0gbmFtZSkKCnByZWRfcHRzX2Jhc2VsaW5lX2NhdGVnb3JpZXNfcmV3YiA8LSBwcmVkX3B0c19iYXNlbGluZV9yZXdiICU+JSAKICByb3duYW1lc190b19jb2x1bW4oKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKC1yb3duYW1lKSAlPiUgCiAgZ3JvdXBfYnkocm93bmFtZSkgJT4lIAogIGZpbHRlcihyYW5rKC12YWx1ZSwgdGllcy5tZXRob2QgPSAibGFzdCIpID09IDEpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdChwcmVkaWN0ZWQgPSBuYW1lKQoKcHJlZF9wdHNfdjJjc3JlcHJzc19jYXRlZ29yaWVzX3Jld2IgPC0gcHJlZF9wdHNfdjJjc3JlcHJzc19yZXdiICU+JSAKICByb3duYW1lc190b19jb2x1bW4oKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKC1yb3duYW1lKSAlPiUgCiAgZ3JvdXBfYnkocm93bmFtZSkgJT4lIAogIGZpbHRlcihyYW5rKC12YWx1ZSwgdGllcy5tZXRob2QgPSAibGFzdCIpID09IDEpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdChwcmVkaWN0ZWQgPSBuYW1lKQoKcHRzX2NhdF9wcmVkcyA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCB5ZWFyLCBhY3R1YWwgPSBQVFNfZmFjdG9yX2xlYWQxKSAlPiUgCiAgbXV0YXRlKHByZWRfYmFzZWxpbmUgPSBwcmVkX3B0c19iYXNlbGluZV9jYXRlZ29yaWVzJHByZWRpY3RlZCwKICAgICAgICAgcHJlZF92MmNzcmVwcnNzID0gcHJlZF9wdHNfdjJjc3JlcHJzc19jYXRlZ29yaWVzJHByZWRpY3RlZCkgJT4lIAogIGZpbHRlcighaXMubmEoYWN0dWFsKSkgJT4lCiAgbXV0YXRlKGlzX2NvcnJlY3RfYmFzZWxpbmUgPSBhY3R1YWwgPT0gcHJlZF9iYXNlbGluZSwKICAgICAgICAgaXNfY29ycmVjdF92MmNzcmVwcnNzID0gYWN0dWFsID09IHByZWRfdjJjc3JlcHJzcykKCnB0c19jYXRfcHJlZHNfcmV3YiA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCB5ZWFyLCBhY3R1YWwgPSBQVFNfZmFjdG9yX2xlYWQxKSAlPiUgCiAgbXV0YXRlKHByZWRfYmFzZWxpbmUgPSBwcmVkX3B0c19iYXNlbGluZV9jYXRlZ29yaWVzX3Jld2IkcHJlZGljdGVkLAogICAgICAgICBwcmVkX3YyY3NyZXByc3MgPSBwcmVkX3B0c192MmNzcmVwcnNzX2NhdGVnb3JpZXNfcmV3YiRwcmVkaWN0ZWQpICU+JSAKICBmaWx0ZXIoIWlzLm5hKGFjdHVhbCkpICU+JQogIG11dGF0ZShpc19jb3JyZWN0X2Jhc2VsaW5lID0gYWN0dWFsID09IHByZWRfYmFzZWxpbmUsCiAgICAgICAgIGlzX2NvcnJlY3RfdjJjc3JlcHJzcyA9IGFjdHVhbCA9PSBwcmVkX3YyY3NyZXByc3MpCgojIEltcHJvdmVkIHByZWRpY3Rpb25zCnB0c19pbXByb3ZlZCA8LSBwdHNfY2F0X3ByZWRzICU+JSAKICBmaWx0ZXIoIWlzX2NvcnJlY3RfYmFzZWxpbmUgJiBpc19jb3JyZWN0X3YyY3NyZXByc3MpICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCBBY3R1YWwgPSBhY3R1YWwsCiAgICAgICAgIGBDUyByZXByZXNzaW9uIGluY2x1ZGVkYCA9IHByZWRfdjJjc3JlcHJzcywKICAgICAgICAgYEJhc2VsaW5lYCA9IHByZWRfYmFzZWxpbmUpCgpwdHNfaW1wcm92ZWRfcmV3YiA8LSBwdHNfY2F0X3ByZWRzX3Jld2IgJT4lIAogIGZpbHRlcighaXNfY29ycmVjdF9iYXNlbGluZSAmIGlzX2NvcnJlY3RfdjJjc3JlcHJzcykgJT4lIAogIHNlbGVjdChDb3VudHJ5ID0gY291bnRyeSwgWWVhciA9IHllYXIsIEFjdHVhbCA9IGFjdHVhbCwKICAgICAgICAgYENTIHJlcHJlc3Npb24gaW5jbHVkZWRgID0gcHJlZF92MmNzcmVwcnNzLAogICAgICAgICBgQmFzZWxpbmVgID0gcHJlZF9iYXNlbGluZSkKCnB0c19pbXByb3ZlZCAlPiUgCiAga2JsKCkgJT4lIAogIGthYmxlX3N0eWxpbmcoKQpgYGAKCmBgYHtyIGUyYS1jb3JyZWN0LW5vdC1jb3JyZWN0fQpjb3JyZWN0X2xvb2t1cCA8LSB0cmliYmxlKAogIH5uYW1lLCB+bmljZV9uYW1lLAogICJpc19jb3JyZWN0X3YyY3NyZXByc3MiLCAiQ1MgcmVwcmVzc2lvbiBpbmNsdWRlZCIsCiAgImlzX2NvcnJlY3RfYmFzZWxpbmUiLCAiQmFzZWxpbmUiCikgJT4lIG11dGF0ZShuaWNlX25hbWUgPSBmY3RfaW5vcmRlcihuaWNlX25hbWUsIG9yZGVyZWQgPSBUUlVFKSkKCnB0c19wcmVkX3RhYmxlIDwtIHB0c19jYXRfcHJlZHMgJT4lIAogIHBpdm90X2xvbmdlcihzdGFydHNfd2l0aCgiaXNfY29ycmVjdCIpKSAlPiUgCiAgZ3JvdXBfYnkobmFtZSwgdmFsdWUpICU+JSAKICBzdW1tYXJpemUobiA9IG4oKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgbGVmdF9qb2luKGNvcnJlY3RfbG9va3VwLCBieSA9ICJuYW1lIikgJT4lIAogIG11dGF0ZShQcmVkaWN0aW9uID0gaWZlbHNlKHZhbHVlID09IFRSVUUsICJDb3JyZWN0IiwgIldyb25nIikpICU+JSAKICBhcnJhbmdlKG5pY2VfbmFtZSkgJT4lIAogIHNlbGVjdCgtbmFtZSwgLXZhbHVlKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJuaWNlX25hbWUiLCB2YWx1ZXNfZnJvbSA9ICJuIikKCnB0c19wcmVkX3RhYmxlX3Jld2IgPC0gcHRzX2NhdF9wcmVkc19yZXdiICU+JSAKICBwaXZvdF9sb25nZXIoc3RhcnRzX3dpdGgoImlzX2NvcnJlY3QiKSkgJT4lIAogIGdyb3VwX2J5KG5hbWUsIHZhbHVlKSAlPiUgCiAgc3VtbWFyaXplKG4gPSBuKCkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGxlZnRfam9pbihjb3JyZWN0X2xvb2t1cCwgYnkgPSAibmFtZSIpICU+JSAKICBtdXRhdGUoUHJlZGljdGlvbiA9IGlmZWxzZSh2YWx1ZSA9PSBUUlVFLCAiQ29ycmVjdCIsICJXcm9uZyIpKSAlPiUgCiAgYXJyYW5nZShuaWNlX25hbWUpICU+JSAKICBzZWxlY3QoLW5hbWUsIC12YWx1ZSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAibmljZV9uYW1lIiwgdmFsdWVzX2Zyb20gPSAibiIpCgpwdHNfcHJlZF90YWJsZSAlPiUgCiAga2JsKGFsaWduID0gImxjYyIpICU+JSAKICBrYWJsZV9zdHlsaW5nKCkKCnB0c19wcmVkX3RhYmxlX3Jld2IgJT4lIAogIGtibChhbGlnbiA9ICJsY2MiKSAlPiUgCiAga2FibGVfc3R5bGluZygpCmBgYAoKXCAKCiMgRX4yYn46IENpdmlsIHNvY2lldHkgZW52aXJvbm1lbnQgYW5kIHBoeXNpY2FsIHZpb2xlbmNlCgpgYGB7ciBlMmItcHJlZGljdGlvbnMsIHdhcm5pbmc9RkFMU0V9CnNlZWRfY2xwaHlfcHJlZGljdGlvbiA8LSA3Mjg1ICAjIEZyb20gcmFuZG9tLm9yZwoKc2V0LnNlZWQoc2VlZF9jbHBoeV9wcmVkaWN0aW9uKQpwcmVkX2NscGh5X2Jhc2VsaW5lIDwtIHByZWRpY3QobV9jbHBoeV9iYXNlbGluZV90cmFpbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IHNlbGVjdChjYW5hcnlfdGVzdGluZ19sYWdnZWQsIC12MnhfY2xwaHlfbGVhZDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93X25ld19sZXZlbHMgPSBUUlVFKQoKc2V0LnNlZWQoc2VlZF9jbHBoeV9wcmVkaWN0aW9uKQpwcmVkX2NscGh5X3YyY3NyZXByc3MgPC0gcHJlZGljdChtX2NscGh5X3YyY3NyZXByc3NfdHJhaW4sIAogICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBzZWxlY3QoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkLCAtdjJ4X2NscGh5X2xlYWQxKSwKICAgICAgICAgICAgICAgICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRSkKCnByZWRfY2xwaHlfYmFzZWxpbmVfdGVzdCA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSkgJT4lIAogIGJpbmRfY29scyhhc190aWJibGUocHJlZF9jbHBoeV9iYXNlbGluZSkpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHYyeF9jbHBoeV9sZWFkMSkpCgpwcmVkX2NscGh5X3YyY3NyZXByc3NfdGVzdCA8LSBjYW5hcnlfdGVzdGluZ19sYWdnZWQgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBnd2NvZGUsIHllYXIsIHYyeF9jbHBoeV9sZWFkMSkgJT4lIAogIGJpbmRfY29scyhhc190aWJibGUocHJlZF9jbHBoeV92MmNzcmVwcnNzKSkgJT4lIAogIGZpbHRlcighaXMubmEodjJ4X2NscGh5X2xlYWQxKSkKYGBgCgojIyBJbXByb3ZlbWVudCBmcm9tIGJhc2VsaW5lIG1vZGVscwoKYGBge3IgZTJiLXByZWQtcGxvdHMsIHdhcm5pbmc9RkFMU0V9CnBsb3RfYmFzZWxpbmUgPC0gZ2dwbG90KHByZWRfY2xwaHlfYmFzZWxpbmVfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdjJ4X2NscGh5X2xlYWQxLCB5ID0gRXN0aW1hdGUpKSArCiAgZ2VvbV9hYmxpbmUobHR5ID0gMikgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIkJhc2VsaW5lIiwKICAgICAgIHggPSAiQWN0dWFsIHBoeXNpY2FsIHZpb2xlbmNlIGluZGV4ICh0ICsgMSkiLAogICAgICAgeSA9ICJQcmVkaWN0ZWQgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKSIpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV9uZ28oKQoKcGxvdF92MmNzcmVwcnNzIDwtIGdncGxvdChwcmVkX2NscGh5X3YyY3NyZXByc3NfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB2MnhfY2xwaHlfbGVhZDEsIHkgPSBFc3RpbWF0ZSkpICsKICBnZW9tX2FibGluZShsdHkgPSAyKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiQWRkZWQgcHJlZGljdG9yIiwKICAgICAgIHggPSAiQWN0dWFsIHBoeXNpY2FsIHZpb2xlbmNlIGluZGV4ICh0ICsgMSkiLAogICAgICAgeSA9ICJQcmVkaWN0ZWQgcGh5c2ljYWwgdmlvbGVuY2UgaW5kZXggKHQgKyAxKSIpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV9uZ28oKQoKcGxvdF9iYXNlbGluZSB8IHBsb3RfdjJjc3JlcHJzcwpgYGAKCmBgYHtyIGUyYi1tZXRyaWNzfQpsb3RzYV9tZXRyaWNzIDwtIG1ldHJpY19zZXQocm1zZSwgcnNxLCBtYWUsIGNjYykKCmJpbmRfcm93cyhsb3RzYV9tZXRyaWNzKHByZWRfY2xwaHlfYmFzZWxpbmVfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIHRydXRoID0gdjJ4X2NscGh5X2xlYWQxLCAKICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdGUgPSBFc3RpbWF0ZSkgJT4lIAogICAgICAgICAgICBtdXRhdGUoTW9kZWwgPSAiQmFzZWxpbmUiKSwKICAgICAgICAgIGxvdHNhX21ldHJpY3MocHJlZF9jbHBoeV92MmNzcmVwcnNzX3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICB0cnV0aCA9IHYyeF9jbHBoeV9sZWFkMSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGVzdGltYXRlID0gRXN0aW1hdGUpICU+JSAKICAgICAgICAgICAgbXV0YXRlKE1vZGVsID0gIkFkZGVkIHByZWRpY3RvciIpKSAlPiUgCiAgc2VsZWN0KE1vZGVsLCAubWV0cmljLCAuZXN0aW1hdGUpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gIi5tZXRyaWMiLCB2YWx1ZXNfZnJvbSA9ICIuZXN0aW1hdGUiKQpgYGAKCiMjIE1vc3QgaW1wcm92ZWQgY291bnRyaWVzCgpgYGB7ciBlMmItbW9zdC1pbXByb3ZlZH0KbW9zdF9pbXByb3ZlZF9jbHBoeSA8LSBiaW5kX2NvbHMoCiAgcHJlZF9jbHBoeV9iYXNlbGluZV90ZXN0ICU+JSAKICAgIG11dGF0ZShlcnJvcl9iYXNlbGluZSA9IEVzdGltYXRlIC0gdjJ4X2NscGh5X2xlYWQxKSAlPiUgCiAgICBzZWxlY3QoY291bnRyeSwgZ3djb2RlLCB5ZWFyLCB2MnhfY2xwaHlfbGVhZDEsIAogICAgICAgICAgIGVzdGltYXRlX2Jhc2VsaW5lID0gRXN0aW1hdGUsIGVycm9yX2Jhc2VsaW5lKSwKICBwcmVkX2NscGh5X3YyY3NyZXByc3NfdGVzdCAlPiUgCiAgICBtdXRhdGUoZXJyb3JfdjJjc3JlcHJzcyA9IEVzdGltYXRlIC0gdjJ4X2NscGh5X2xlYWQxKSAlPiUgCiAgICBzZWxlY3QoZXN0aW1hdGVfdjJjc3JlcHJzcyA9IEVzdGltYXRlLCBlcnJvcl92MmNzcmVwcnNzKQopICU+JSAKICAjIG11dGF0ZShhY3Jvc3Moc3RhcnRzX3dpdGgoImVycm9yIiksIH5yb3VuZCguLCA0KSkpICU+JSAKICBtdXRhdGUoaW1wcm92ZWQgPSBlcnJvcl92MmNzcmVwcnNzIDwgMCAmIGFicyhlcnJvcl92MmNzcmVwcnNzKSA8IGFicyhlcnJvcl9iYXNlbGluZSkpICU+JSAKICBtdXRhdGUoZGlmZiA9IGVycm9yX3YyY3NyZXByc3MgLSBlcnJvcl9iYXNlbGluZSkgJT4lIAogIG11dGF0ZShhYnNfZGlmZiA9IGFicyhkaWZmKSkgJT4lIAogIGZpbHRlcihpbXByb3ZlZCkgJT4lIAogIGFycmFuZ2UoZGVzYyhhYnNfZGlmZikpCgpucm93KG1vc3RfaW1wcm92ZWRfY2xwaHkpCgptb3N0X2ltcHJvdmVkX2NscGh5ICU+JSAKICBzZWxlY3QoQ291bnRyeSA9IGNvdW50cnksIFllYXIgPSB5ZWFyLCAKICAgICAgICAgYEFjdHVhbCBwaHlzaWNhbCB2aW9sZW5jZSBpbmRleCAodCArIDEpYCA9ICB2MnhfY2xwaHlfbGVhZDEsCiAgICAgICAgIGBQcmVkaWN0ZWQgKGJhc2VsaW5lKWAgPSBlc3RpbWF0ZV9iYXNlbGluZSwKICAgICAgICAgYFByZWRpY3RlZCAoQ1MgcmVwcmVzc2lvbilgID0gZXN0aW1hdGVfdjJjc3JlcHJzcywKICAgICAgICAgYHxDUyByZXByZXNzaW9uIOKIkiBiYXNlbGluZXxgID0gYWJzX2RpZmYpICU+JSAKICBoZWFkKDUpICU+JSAKICBrYmwoZGlnaXRzID0gMywgYWxpZ24gPSAibGNjY2NjIikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQpgYGAKClwgCgojIEV+MmN+OiBDaXZpbCBzb2NpZXR5IGVudmlyb25tZW50IGFuZCBjaXZpbCBsaWJlcnRpZXMKCmBgYHtyIGUyYy1wcmVkaWN0aW9ucywgd2FybmluZz1GQUxTRX0Kc2VlZF9jbHByaXZfcHJlZGljdGlvbiA8LSA2NjcwICAjIEZyb20gcmFuZG9tLm9yZwoKc2V0LnNlZWQoc2VlZF9jbHByaXZfcHJlZGljdGlvbikKcHJlZF9jbHByaXZfYmFzZWxpbmUgPC0gcHJlZGljdChtX2NscHJpdl9iYXNlbGluZV90cmFpbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IHNlbGVjdChjYW5hcnlfdGVzdGluZ19sYWdnZWQsIC12MnhfY2xwcml2X2xlYWQxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRSkKCnNldC5zZWVkKHNlZWRfY2xwcml2X3ByZWRpY3Rpb24pCnByZWRfY2xwcml2X3YyY3NyZXByc3MgPC0gcHJlZGljdChtX2NscHJpdl92MmNzcmVwcnNzX3RyYWluLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBzZWxlY3QoY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkLCAtdjJ4X2NscHJpdl9sZWFkMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvd19uZXdfbGV2ZWxzID0gVFJVRSkKCnByZWRfY2xwcml2X2Jhc2VsaW5lX3Rlc3QgPC0gY2FuYXJ5X3Rlc3RpbmdfbGFnZ2VkICU+JSAKICBzZWxlY3QoY291bnRyeSwgZ3djb2RlLCB5ZWFyLCB2MnhfY2xwcml2X2xlYWQxKSAlPiUgCiAgYmluZF9jb2xzKGFzX3RpYmJsZShwcmVkX2NscHJpdl9iYXNlbGluZSkpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHYyeF9jbHByaXZfbGVhZDEpKQoKcHJlZF9jbHByaXZfdjJjc3JlcHJzc190ZXN0IDwtIGNhbmFyeV90ZXN0aW5nX2xhZ2dlZCAlPiUgCiAgc2VsZWN0KGNvdW50cnksIGd3Y29kZSwgeWVhciwgdjJ4X2NscHJpdl9sZWFkMSkgJT4lIAogIGJpbmRfY29scyhhc190aWJibGUocHJlZF9jbHByaXZfdjJjc3JlcHJzcykpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHYyeF9jbHByaXZfbGVhZDEpKQpgYGAKCiMjIEltcHJvdmVtZW50IGZyb20gYmFzZWxpbmUgbW9kZWxzCgpgYGB7ciBlMmMtcHJlZC1wbG90cywgd2FybmluZz1GQUxTRX0KcGxvdF9iYXNlbGluZSA8LSBnZ3Bsb3QocHJlZF9jbHByaXZfYmFzZWxpbmVfdGVzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdjJ4X2NscHJpdl9sZWFkMSwgeSA9IEVzdGltYXRlKSkgKwogIGdlb21fYWJsaW5lKGx0eSA9IDIpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgbGFicyh0aXRsZSA9ICJCYXNlbGluZSIsCiAgICAgICB4ID0gIkFjdHVhbCBwcml2YXRlIGNpdmlsIGxpYmVydGllcyBpbmRleCAodCArIDEpIiwKICAgICAgIHkgPSAiUHJlZGljdGVkIHByaXZhdGUgY2l2aWwgbGliZXJ0aWVzIGluZGV4ICh0ICsgMSkiKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfbmdvKCkKCnBsb3RfdjJjc3JlcHJzcyA8LSBnZ3Bsb3QocHJlZF9jbHByaXZfdjJjc3JlcHJzc190ZXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHYyeF9jbHByaXZfbGVhZDEsIHkgPSBFc3RpbWF0ZSkpICsKICBnZW9tX2FibGluZShsdHkgPSAyKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiQWRkZWQgcHJlZGljdG9yIiwKICAgICAgIHggPSAiQWN0dWFsIHByaXZhdGUgY2l2aWwgbGliZXJ0aWVzIGluZGV4ICh0ICsgMSkiLAogICAgICAgeSA9ICJQcmVkaWN0ZWQgcHJpdmF0ZSBjaXZpbCBsaWJlcnRpZXMgaW5kZXggKHQgKyAxKSIpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV9uZ28oKQoKcGxvdF9iYXNlbGluZSB8IHBsb3RfdjJjc3JlcHJzcwpgYGAKCmBgYHtyIGUyYy1tZXRyaWNzfQpsb3RzYV9tZXRyaWNzIDwtIG1ldHJpY19zZXQocm1zZSwgcnNxLCBtYWUsIGNjYykKCmJpbmRfcm93cyhsb3RzYV9tZXRyaWNzKHByZWRfY2xwcml2X2Jhc2VsaW5lX3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICB0cnV0aCA9IHYyeF9jbHByaXZfbGVhZDEsIAogICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlKSAlPiUgCiAgICAgICAgICAgIG11dGF0ZShNb2RlbCA9ICJCYXNlbGluZSIpLAogICAgICAgICAgbG90c2FfbWV0cmljcyhwcmVkX2NscHJpdl92MmNzcmVwcnNzX3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICB0cnV0aCA9IHYyeF9jbHByaXZfbGVhZDEsIAogICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0ZSA9IEVzdGltYXRlKSAlPiUgCiAgICAgICAgICAgIG11dGF0ZShNb2RlbCA9ICJBZGRlZCBwcmVkaWN0b3IiKSkgJT4lIAogIHNlbGVjdChNb2RlbCwgLm1ldHJpYywgLmVzdGltYXRlKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICIubWV0cmljIiwgdmFsdWVzX2Zyb20gPSAiLmVzdGltYXRlIikKYGBgCgpIZXkhIFRoaXMgb25lIGhhcyBhIHNvbWV3aGF0IGJldHRlciBjaGFuZ2UgaW4gTVNFISAKCmBgYHtyfQpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDAuMDEpKCgwLjAzMzIgLSAwLjAzMzkpIC8gMC4wMzM5KQpgYGAKCiMjIE1vc3QgaW1wcm92ZWQgY291bnRyaWVzCgpgYGB7ciBlMmMtbW9zdC1pbXByb3ZlZH0KbW9zdF9pbXByb3ZlZF9jbHByaXYgPC0gYmluZF9jb2xzKAogIHByZWRfY2xwcml2X2Jhc2VsaW5lX3Rlc3QgJT4lIAogICAgbXV0YXRlKGVycm9yX2Jhc2VsaW5lID0gRXN0aW1hdGUgLSB2MnhfY2xwcml2X2xlYWQxKSAlPiUgCiAgICBzZWxlY3QoY291bnRyeSwgZ3djb2RlLCB5ZWFyLCB2MnhfY2xwcml2X2xlYWQxLCAKICAgICAgICAgICBlc3RpbWF0ZV9iYXNlbGluZSA9IEVzdGltYXRlLCBlcnJvcl9iYXNlbGluZSksCiAgcHJlZF9jbHByaXZfdjJjc3JlcHJzc190ZXN0ICU+JSAKICAgIG11dGF0ZShlcnJvcl92MmNzcmVwcnNzID0gRXN0aW1hdGUgLSB2MnhfY2xwcml2X2xlYWQxKSAlPiUgCiAgICBzZWxlY3QoZXN0aW1hdGVfdjJjc3JlcHJzcyA9IEVzdGltYXRlLCBlcnJvcl92MmNzcmVwcnNzKQopICU+JSAKICAjIG11dGF0ZShhY3Jvc3Moc3RhcnRzX3dpdGgoImVycm9yIiksIH5yb3VuZCguLCA0KSkpICU+JSAKICBtdXRhdGUoaW1wcm92ZWQgPSBlcnJvcl92MmNzcmVwcnNzIDwgMCAmIGFicyhlcnJvcl92MmNzcmVwcnNzKSA8IGFicyhlcnJvcl9iYXNlbGluZSkpICU+JSAKICBtdXRhdGUoZGlmZiA9IGVycm9yX3YyY3NyZXByc3MgLSBlcnJvcl9iYXNlbGluZSkgJT4lIAogIG11dGF0ZShhYnNfZGlmZiA9IGFicyhkaWZmKSkgJT4lIAogIGZpbHRlcihpbXByb3ZlZCkgJT4lIAogIGFycmFuZ2UoZGVzYyhhYnNfZGlmZikpCgpucm93KG1vc3RfaW1wcm92ZWRfY2xwcml2KQoKbW9zdF9pbXByb3ZlZF9jbHByaXYgJT4lIAogIHNlbGVjdChDb3VudHJ5ID0gY291bnRyeSwgWWVhciA9IHllYXIsIAogICAgICAgICBgQWN0dWFsIHByaXZhdGUgY2l2aWwgbGliZXJ0aWVzIGluZGV4ICh0ICsgMSlgID0gIHYyeF9jbHByaXZfbGVhZDEsCiAgICAgICAgIGBQcmVkaWN0ZWQgKGJhc2VsaW5lKWAgPSBlc3RpbWF0ZV9iYXNlbGluZSwKICAgICAgICAgYFByZWRpY3RlZCAoQ1MgcmVwcmVzc2lvbilgID0gZXN0aW1hdGVfdjJjc3JlcHJzcywKICAgICAgICAgYHxDUyByZXByZXNzaW9uIOKIkiBiYXNlbGluZXxgID0gYWJzX2RpZmYpICU+JSAKICBoZWFkKDUpICU+JSAKICBrYmwoZGlnaXRzID0gMywgYWxpZ24gPSAibGNjY2NjIikgJT4lIAogIGthYmxlX3N0eWxpbmcoKQpgYGAK