Hypothesis 1: Women participation impacts peace durability
# ===== CLEANING: Remove NAs from ALL necessary variables ====
# Define variables of interest
pretreatment_covariates <- c("con_dur", "con_int", "con_iss", "war_par", "gdp", "dem", "hum_rig", "fem_com", "lef_ide", "fem_leg", "start_date_num")
treatnent_var <- c("fem_sig")
outcome_vars <- c("days_of_peace", "pc_nd")
cleaning_vars <- c(treatnent_var, outcome_vars, pretreatment_covariates) # This list includes Y, Tr, and X. We use it ONLY for na.omit.
# Check which columns contain missing values
colSums(is.na(data[, cleaning_vars]))
# Clean the data to enable genetic matching (cannot have NAs)
df_clean_H1 <- na.omit(data[, c("cas_id", cleaning_vars)])
df_clean_H1
cat("Number of control/treatment units in sample (before cleaning):")
table(data$fem_sig)
cat("Number of control/treatment units in sample (after cleaning):")
table(df_clean_H1$fem_sig)
library(rgenoud)
library(Matching)
set.seed(123)
# ====== DEFINE MATCHING OBJECTS ======
# Treatment
Tr <- df_clean_H1$fem_sig
# Matching Matrix (X): ONLY contains pre-treatment covariates.
matching_vars <- pretreatment_covariates
X <- df_clean_H1[, matching_vars]
# Do not use outcome observations until matching is complete
# PREPARE CALIPER (for start_date_num)
# Calculate caliper value for start_date_num
desired_window_days <- 180
sd_date <- sd(df_clean_H1$start_date_num)
caliper_value <- desired_window_days / sd_date
# Create Caliper Vector
# We need a vector of Infs matching the number of columns in X
caliper_vec <- rep(Inf, ncol(X))
# Apply restriction ONLY to the start date column
date_index <- which(colnames(X) == "start_date_num")
caliper_vec[date_index] <- caliper_value
# ========== RUN GENMATCH ==============
genout_H1 <- GenMatch(Tr = Tr, X = X, BalanceMatrix = X,
caliper = caliper_vec,
estimand = "ATT", pop.size = 5000,
print.level = 0)
# ========== RUN MATCH ==============
m_out_H1 <- Match(Tr = Tr, X = X, Weight.matrix = genout_H1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Report on matching summary ======
# Count how many times each treated unit appears in the match list
matches_per_treated <- table(m_out_H1$index.treated)
# Check the distribution (e.g., how many got 1 match, how many got 2, etc.)
table(matches_per_treated)
# Total treated units in original data
total_treated <- sum(Tr)
# Total treated units that successfully found a match
matched_treated <- length(unique(m_out_H1$index.treated))
cat("Original Treated:", total_treated, "\n")
cat("Matched Treated: ", matched_treated, "\n")
cat("Dropped: ", total_treated - matched_treated, "\n")
# ===== Report Balance and Lowest P-Value ======
set.seed(123)
# treatment indicator is the dependent variable, check balance for all covariates
mb_formula_H1 <- fem_sig ~ con_dur + con_int + con_iss + war_par + gdp + dem + hum_rig + fem_leg + fem_com + lef_ide + start_date_num
MatchBalance(mb_formula_H1, data = df_clean_H1, match.out = m_out_H1, nboots = 500)
#install.packages("cobalt")
library(cobalt)
love.plot(mb_formula_H1,
data = df_clean_H1,
weights = m_out_H1, # Use the match object as the source of weights
binary = "std",
thresholds = c(m = .25),
alpha = 0.7,
title = "Covariate Balance (SMD)",
grid = TRUE)
love.plot(mb_formula_H1,
data = df_clean_H1,
weights = m_out_H1, # Use the match object as the source of weights
stats = "ks.statistics", # Change to KS statistics
binary = "std",
thresholds = c(ks = 0.1),
alpha = 0.7,
grid = TRUE,
title = "Covariate Balance (KS Statistics)")
library(ggplot2)
library(gridExtra) # Required for arranging plots
# Panel A: Good Balance (Continuous - ECDF)
p1 <- bal.plot(m_out_H1, treat = Tr, covs = X,
var.name = "start_date_num", type = "ecdf") +
ggtitle("A. Good Balance: Start Date")
# Panel B: Poor Balance (Continuous - ECDF)
p2 <- bal.plot(m_out_H1, treat = Tr, covs = X,
var.name = "gdp", type = "ecdf") +
ggtitle("B. Poor Balance: GDP")
# Panel C: Good Balance (Discrete - Histogram)
p3 <- bal.plot(m_out_H1, treat = Tr, covs = X,
var.name = "dem", type = "histogram") +
ggtitle("C. Good Balance: Democracy")
# Panel D: Poor Balance (Discrete - Histogram)
p4 <- bal.plot(m_out_H1, treat = Tr, covs = X,
var.name = "hum_rig", type = "histogram") +
ggtitle("D. Poor Balance: Human Rights")
# Arrange plots into a 2x2 grid
grid.arrange(p1, p2, p3, p4, nrow = 2)
bal.tab(mb_formula_H1,
data = df_clean_H1,
weights = m_out_H1, # Use the match object as the source of weights
estimand = "ATT",
binary = "std", # <--- Forces binary vars to use SMD
continuous = "std", # <--- Forces continuous vars (default) to use SMD
un = TRUE,
stats = c("m", "v", "ks"), # Mean diffs, Variance ratios, KS stats
thresholds = c(m = 0.25, ks = 0.1))
library(Matching)
get_balance_table <- function(formula, data, match_out, nboots = 500) {
# 1. Run MatchBalance
mb <- MatchBalance(formula, data = data, match.out = match_out, nboots = nboots, print.level = 0)
# 2. Define the "Nested" Null Coalescing Operator
# (This allows us to chain checks: "Try A, if NULL try B, if NULL try C")
`%||%` <- function(a, b) if (is.null(a)) b else a
# 3. Define the Extractors
# T-Test: Simple check
get_tt <- function(x) x$tt$p.value %||% NA
# KS-Test: The "Nested" Approach
# 1. Try nested bootstrap (x$ks$ks.boot.pvalue) <--- PRIORITY
# 2. Try top-level bootstrap (x$ks.boot.pvalue)
# 3. Try standard KS (x$ks$p.value)
get_ks <- function(x) x$ks$ks.boot.pvalue %||% x$ks.boot.pvalue %||% x$ks$p.value %||% NA
# 4. Extract efficiently with sapply
idx <- seq_along(mb$AfterMatching)
vars <- all.vars(formula)[-1]
final_names <- if(length(vars) == length(idx)) vars else paste0("Var_", idx)
df <- data.frame(
Variable = final_names,
Pre_T_P = round(sapply(idx, function(i) get_tt(mb$BeforeMatching[[i]])), 3),
Post_T_P = round(sapply(idx, function(i) get_tt(mb$AfterMatching[[i]])), 3),
Pre_KS_P = round(sapply(idx, function(i) get_ks(mb$BeforeMatching[[i]])), 3),
Post_KS_P = round(sapply(idx, function(i) get_ks(mb$AfterMatching[[i]])), 3)
)
# 5. Status: Pass if (KS is NA or >0.05) AND (T-test > 0.05)
df$Status <- ifelse((is.na(df$Post_KS_P) | df$Post_KS_P > 0.1) & df$Post_T_P > 0.1, "PASS", "FAIL")
return(df)
}
set.seed(123)
# --- Call Function ---
balance_table_H1 <- get_balance_table(
formula = mb_formula_H1,
data = df_clean_H1,
match_out = m_out_H1,
nboots = 500
)
balance_table_H1
Hypothesis 1A: fem-sig on days_of_peace (peace duration)
# Include outcome variable for effect estimate
Y <- df_clean_H1$days_of_peace
m_out_H1A <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_H1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_H1A)
ATT_est <- m_out_H1A$est
ATT_se <- m_out_H1A$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 2)))
print(paste("Standard Error:", round(ATT_se, 2)))
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
Hypothesis 1B: fem-sig on pc_nd (peace ends and conflict
resumes)
# Outcome
Y <- df_clean_H1$pc_nd
m_out_H1B <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_H1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_H1B)
ATT_est <- m_out_H1B$est
ATT_se <- m_out_H1B$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 2)))
print(paste("Standard Error:", round(ATT_se, 2)))
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
Model H1: Rosenbaum Bounds Sensitivity Analysis
# ===== CLEANING: Remove NAs from ALL necessary variables ====
# Define variables of interest
pretreatment_covariates <- c("con_dur", "con_int", "con_iss", "war_par", "gdp", "dem", "hum_rig", "fem_com", "lef_ide", "fem_leg", "start_date_num")
treatnent_var <- c("fem_sig")
outcome_vars <- c("days_of_peace", "pc_nd")
cleaning_vars <- c(treatnent_var, outcome_vars, pretreatment_covariates) # This list includes Y, Tr, and X. We use it ONLY for na.omit.
# Check which columns contain missing values
colSums(is.na(data[, cleaning_vars]))
fem_sig days_of_peace pc_nd con_dur con_int
0 0 0 0 0
con_iss war_par gdp dem hum_rig
0 0 9 0 9
fem_com lef_ide fem_leg start_date_num
9 2 9 0
# Clean the data to enable genetic matching (cannot have NAs)
df_clean_H1 <- na.omit(data[, c("cas_id", cleaning_vars)])
df_clean_H1
cat("Number of control/treatment units in sample (before cleaning):")
Number of control/treatment units in sample (before cleaning):
table(data$fem_sig)
0 1
73 6
cat("Number of control/treatment units in sample (after cleaning):")
Number of control/treatment units in sample (after cleaning):
table(df_clean_H1$fem_sig)
0 1
50 6
library(rgenoud)
library(Matching)
set.seed(123)
# ====== DEFINE MATCHING OBJECTS ======
# Treatment
Tr <- df_clean_H1$fem_sig
# Matching Matrix (X): ONLY contains pre-treatment covariates.
matching_vars <- pretreatment_covariates
X <- df_clean_H1[, matching_vars]
# Do not use outcome observations until matching is complete
# PREPARE CALIPER (for start_date_num)
# Calculate caliper value for start_date_num
desired_window_days <- 180
sd_date <- sd(df_clean_H1$start_date_num)
caliper_value <- desired_window_days / sd_date
# Create Caliper Vector
# We need a vector of Infs matching the number of columns in X
caliper_vec <- rep(Inf, ncol(X))
# Apply restriction ONLY to the start date column
date_index <- which(colnames(X) == "start_date_num")
caliper_vec[date_index] <- caliper_value
# ========== RUN GENMATCH ==============
genout_H1 <- GenMatch(Tr = Tr, X = X, BalanceMatrix = X,
caliper = caliper_vec,
estimand = "ATT", pop.size = 5000,
print.level = 0)
# ========== RUN MATCH ==============
m_out_H1 <- Match(Tr = Tr, X = X, Weight.matrix = genout_H1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Report on matching summary ======
# Count how many times each treated unit appears in the match list
matches_per_treated <- table(m_out_H1$index.treated)
# Check the distribution (e.g., how many got 1 match, how many got 2, etc.)
table(matches_per_treated)
matches_per_treated
1
6
# Total treated units in original data
total_treated <- sum(Tr)
# Total treated units that successfully found a match
matched_treated <- length(unique(m_out_H1$index.treated))
cat("Original Treated:", total_treated, "\n")
Original Treated: 6
cat("Matched Treated: ", matched_treated, "\n")
Matched Treated: 6
cat("Dropped: ", total_treated - matched_treated, "\n")
Dropped: 0
H1: Robustness check
# ============== Remove NAs from ALL necessary variables==================
# Specify variables of interest
pretreatment_covariates <- c("con_dur", "con_int", "con_iss", "war_par", "gdp", "dem", "hum_rig", "fem_com", "lef_ide", "fem_leg", "start_date_num")
treatnent_var <- c("fem_sig")
outcome_vars <- c("days_of_peace", "pc_nd")
# additional covariates for matching (used as controls by Krause et al.)
add_covariates <- c("pow_sha", "quo", "un_pea_con")
cleaning_vars <- c(treatnent_var, outcome_vars, pretreatment_covariates, add_covariates)
# Check which columns contain missing values
colSums(is.na(data[, cleaning_vars]))
# Clean the data to enable genetic matching (cannot have NAs)
df_clean_rb1 <- na.omit(data[, c("cas_id", cleaning_vars)])
df_clean_rb1
# Check for dropped units
cat("Number of control/treatment units in sample (before cleaning):")
table(data$fem_sig)
cat("Number of control/treatment units in sample (after cleaning):")
table(df_clean_rb1$fem_sig)
set.seed(123)
# ============ DEFINE MATCHING OBJECTS ================
# Treatment
Tr <- df_clean_rb1$fem_sig
# Matching Matrix (X)
matching_vars <- c(pretreatment_covariates, add_covariates) #include additional covariates
X <- df_clean_rb1[, matching_vars]
# PREPARE CALIPER (For start_date_num)
desired_window_days <- 180 #90 causes treatment units to be dropped
sd_date <- sd(df_clean_rb1$start_date_num)
caliper_value <- desired_window_days / sd_date
# Create Caliper Vector
# We need a vector of Infs matching the number of columns in X
caliper_vec <- rep(Inf, ncol(X))
# Apply restriction ONLY to the date column
date_index <- which(colnames(X) == "start_date_num")
caliper_vec[date_index] <- caliper_value
# ================ RUN GENMATCH ===============
genout_rb1 <- GenMatch(Tr = Tr, X = X, BalanceMatrix = X,
caliper = caliper_vec,
estimand = "ATT", pop.size = 5000,
print.level = 0)
# ================ RUN MATCH ===================
m_out_rb1 <- Match(Tr = Tr, X = X, Weight.matrix = genout_rb1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Report Summary of Matching Results ======
# Count how many times each treated unit appears in the match list
matches_per_treated <- table(m_out_rb1$index.treated)
# Check the distribution (e.g., how many got 1 match, how many got 2, etc.)
table(matches_per_treated)
# Total treated units in original data
total_treated <- sum(Tr)
# Total treated units that successfully found a match
matched_treated <- length(unique(m_out_rb1$index.treated))
cat("Original Treated:", total_treated, "\n")
cat("Matched Treated: ", matched_treated, "\n")
cat("Dropped: ", total_treated - matched_treated, "\n")
# ===== Report Balance and Lowest P-Value ======
set.seed(123)
# treatment indicator is the dependent variable, check balance for all covariates
mb_formula_rb1 <- fem_sig ~ con_dur + con_int + con_iss + war_par + gdp + dem + hum_rig + fem_leg + fem_com + lef_ide + start_date_num + pow_sha + quo + un_pea_con
MatchBalance(mb_formula_rb1, data = df_clean_rb1, match.out = m_out_rb1, nboots = 500)
#install.packages("cobalt")
library(cobalt)
love.plot(mb_formula_rb1,
data = df_clean_rb1,
weights = m_out_rb1, # Use the match object as the source of weights
binary = "std",
thresholds = c(m = .25),
alpha = 0.7,
title = "Covariate Balance (SMD)",
grid = TRUE)
love.plot(mb_formula_rb1,
data = df_clean_rb1,
weights = m_out_rb1, # Use the match object as the source of weights
stats = "ks.statistics", # Change to KS statistics
binary = "std",
thresholds = c(ks = 0.1),
alpha = 0.7,
grid = TRUE,
title = "Covariate Balance (KS Statistics)")
bal.tab(mb_formula_rb1,
data = df_clean_rb1,
weights = m_out_rb1, # Use the match object as the source of weights
estimand = "ATT",
binary = "std", # <--- Forces binary vars to use SMD
continuous = "std", # <--- Forces continuous vars (default) to use SMD
un = TRUE,
stats = c("m", "v", "ks"), # Mean diffs, Variance ratios, KS stats
thresholds = c(m = 0.25, ks = 0.1))
set.seed(123)
# --- Call Function ---
balance_table_rb1 <- get_balance_table(
formula = mb_formula_rb1,
data = df_clean_rb1,
match_out = m_out_rb1,
nboots = 500
)
balance_table_rb1
H1 vs R1: Comparison of Matching Results
matched_data_H1 <- rbind(
df_clean_H1[m_out_H1$index.treated, ],
df_clean_H1[m_out_H1$index.control, ]
)
n_pairs <- length(m_out_H1$index.treated)
matched_data_H1$pair_id <- c(1:n_pairs, 1:n_pairs)
matched_data_rb1 <- rbind(
df_clean_rb1[m_out_rb1$index.treated, ],
df_clean_rb1[m_out_rb1$index.control, ]
)
n_pairs <- length(m_out_rb1$index.treated)
matched_data_rb1$pair_id <- c(1:n_pairs, 1:n_pairs)
matches <- cbind(Pair_ID = matched_data_H1$pair_id,
Treated = matched_data_H1$cas_id[matched_data_H1$fem_sig == 1],
ModelH1_Matches = matched_data_H1$cas_id[matched_data_H1$fem_sig == 0],
ModelR1_Matches = matched_data_rb1$cas_id[matched_data_rb1$fem_sig == 0])
matches[1:6, ]
# Compare outcome observations of matched units
matchcomp_days <- cbind(Pair_ID = matched_data_H1$pair_id,
cas_id = matched_data_H1$cas_id,
fem_sig = matched_data_H1$fem_sig,
days_of_peace_H1 = matched_data_H1$days_of_peace,
days_of_peace_rb1 = matched_data_rb1$days_of_peace)
matchcomp_pc <- cbind(Pair_ID = matched_data_H1$pair_id,
cas_id = matched_data_H1$cas_id,
fem_sig = matched_data_H1$fem_sig,
pc_nd_H1 = matched_data_H1$pc_nd,
pc_nd_rb1 = matched_data_rb1$pc_nd)
matchcomp_days
matchcomp_pc
H1 vs R1: Comparison of Treatment Effect Estimates
# ======== Run Match() with outcome variable =======
# Outcome
Y <- df_clean_rb1$days_of_peace
m_out_rb1A <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_rb1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_rb1A)
ATT_est <- m_out_rb1A$est
ATT_se <- m_out_rb1A$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 4)))
print(paste("Standard Error:", round(ATT_se, 4)))
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
# ======== Run Match() with outcome variable =======
# Outcome
Y <- df_clean_rb1$pc_nd
m_out_rb1B <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_rb1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Estimate Treatment Effect, SE, and CI ====
summary(m_out_rb1B)
ATT_est <- m_out_rb1B$est
ATT_se <- m_out_rb1B$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 4)))
print(paste("Standard Error:", round(ATT_se, 4)))
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
print ("H1A vs. R1A")
summary(m_out_H1A)
summary(m_out_rb1A)
print ("H1B vs. R1B")
summary(m_out_H1B)
summary(m_out_rb1B)
Hypothesis 1: Survival Analysis
# ===== Report Balance and Lowest P-Value ======
set.seed(123)
# treatment indicator is the dependent variable, check balance for all covariates
mb_formula_H1 <- fem_sig ~ con_dur + con_int + con_iss + war_par + gdp + dem + hum_rig + fem_leg + fem_com + lef_ide + start_date_num
MatchBalance(mb_formula_H1, data = df_clean_H1, match.out = m_out_H1, nboots = 500)
***** (V1) con_dur *****
Before Matching After Matching
mean treatment........ 27.333 27.333
mean control.......... 20.68 19.5
std mean diff......... 47.54 55.971
mean raw eQQ diff..... 6 7.8333
med raw eQQ diff..... 3.5 6.5
max raw eQQ diff..... 16 19
mean eCDF diff........ 0.14162 0.13636
med eCDF diff........ 0.12667 0.16667
max eCDF diff........ 0.35333 0.33333
var ratio (Tr/Co)..... 0.84093 0.76302
T-test p-value........ 0.31464 0.15974
KS Bootstrap p-value.. 0.382 0.826
KS Naive p-value...... 0.39891 0.93074
KS Statistic.......... 0.35333 0.33333
***** (V2) con_int *****
Before Matching After Matching
mean treatment........ 0.11265 0.11265
mean control.......... 0.26814 0.082458
std mean diff......... -86.378 16.77
mean raw eQQ diff..... 0.19184 0.040991
med raw eQQ diff..... 0.14263 0.016204
max raw eQQ diff..... 0.55 0.10729
mean eCDF diff........ 0.18784 0.071429
med eCDF diff........ 0.18333 0
max eCDF diff........ 0.38667 0.16667
var ratio (Tr/Co)..... 0.3793 1.8253
T-test p-value........ 0.099899 0.72072
KS Bootstrap p-value.. 0.244 0.998
KS Naive p-value...... 0.30081 1
KS Statistic.......... 0.38667 0.16667
***** (V3) con_iss *****
Before Matching After Matching
mean treatment........ 0.66667 0.66667
mean control.......... 0.78 0.5
std mean diff......... -21.947 32.275
mean raw eQQ diff..... 0 0.16667
med raw eQQ diff..... 0 0
max raw eQQ diff..... 0 1
mean eCDF diff........ 0.056667 0.083333
med eCDF diff........ 0.056667 0.083333
max eCDF diff........ 0.11333 0.16667
var ratio (Tr/Co)..... 1.5229 0.88889
T-test p-value........ 0.62384 0.57831
***** (V4) war_par *****
Before Matching After Matching
mean treatment........ 5 5
mean control.......... 6.86 6.1667
std mean diff......... -73.523 -46.117
mean raw eQQ diff..... 3 2.1667
med raw eQQ diff..... 0.5 0.5
max raw eQQ diff..... 15 10
mean eCDF diff........ 0.086061 0.071429
med eCDF diff........ 0.1 0
max eCDF diff........ 0.18 0.16667
var ratio (Tr/Co)..... 0.16592 0.17128
T-test p-value........ 0.19153 0.56147
KS Bootstrap p-value.. 0.858 0.994
KS Naive p-value...... 0.85647 1
KS Statistic.......... 0.18 0.16667
***** (V5) gdp *****
Before Matching After Matching
mean treatment........ 3.2898 3.2898
mean control.......... 2.7526 2.7601
std mean diff......... 66.288 65.373
mean raw eQQ diff..... 0.51179 0.5297
med raw eQQ diff..... 0.52796 0.5241
max raw eQQ diff..... 0.82098 0.93254
mean eCDF diff........ 0.20213 0.19444
med eCDF diff........ 0.18667 0.16667
max eCDF diff........ 0.46667 0.5
var ratio (Tr/Co)..... 2.2964 2.0773
T-test p-value........ 0.16866 0.11621
KS Bootstrap p-value.. 0.128 0.354
KS Naive p-value...... 0.13832 0.47403
KS Statistic.......... 0.46667 0.5
***** (V6) dem *****
Before Matching After Matching
mean treatment........ 0.83333 0.83333
mean control.......... 0.32 0.66667
std mean diff......... 68.192 22.14
mean raw eQQ diff..... 0.5 0.16667
med raw eQQ diff..... 0.5 0
max raw eQQ diff..... 1 1
mean eCDF diff........ 0.17111 0.055556
med eCDF diff........ 0.16667 0
max eCDF diff........ 0.34667 0.16667
var ratio (Tr/Co)..... 2.5521 2.125
T-test p-value........ 0.15838 0.57831
KS Bootstrap p-value.. 0.112 0.902
KS Naive p-value...... 0.17238 1
KS Statistic.......... 0.34667 0.16667
***** (V7) hum_rig *****
Before Matching After Matching
mean treatment........ 10.167 10.167
mean control.......... 6.32 8.8333
std mean diff......... 106.82 37.028
mean raw eQQ diff..... 3.8333 2
med raw eQQ diff..... 4 1.5
max raw eQQ diff..... 6 4
mean eCDF diff........ 0.3 0.16667
med eCDF diff........ 0.27333 0.16667
max eCDF diff........ 0.73333 0.5
var ratio (Tr/Co)..... 1.6682 1.4461
T-test p-value........ 0.046585 0.31494
KS Bootstrap p-value.. < 2.22e-16 0.27
KS Naive p-value...... 0.0012302 0.35065
KS Statistic.......... 0.73333 0.5
***** (V8) fem_leg *****
Before Matching After Matching
mean treatment........ 1.1667 1.1667
mean control.......... 1.46 1.6667
std mean diff......... -38.967 -66.421
mean raw eQQ diff..... 0.33333 0.5
med raw eQQ diff..... 0 0.5
max raw eQQ diff..... 1 1
mean eCDF diff........ 0.08 0.125
med eCDF diff........ 0.08 0.083333
max eCDF diff........ 0.16 0.33333
var ratio (Tr/Co)..... 0.59816 0.53125
T-test p-value........ 0.41188 0.45135
KS Bootstrap p-value.. 0.762 0.536
KS Naive p-value...... 0.87781 0.74026
KS Statistic.......... 0.16 0.33333
***** (V9) fem_com *****
Before Matching After Matching
mean treatment........ 1.8333 1.8333
mean control.......... 1.12 0.83333
std mean diff......... 61.018 85.54
mean raw eQQ diff..... 0.83333 1
med raw eQQ diff..... 1 1
max raw eQQ diff..... 2 2
mean eCDF diff........ 0.17833 0.25
med eCDF diff........ 0.22333 0.33333
max eCDF diff........ 0.26667 0.33333
var ratio (Tr/Co)..... 1.1691 1.4138
T-test p-value........ 0.20391 0.11626
KS Bootstrap p-value.. 0.39 0.648
KS Naive p-value...... 0.45736 0.84416
KS Statistic.......... 0.26667 0.33333
***** (V10) lef_ide *****
Before Matching After Matching
mean treatment........ 0.33333 0.33333
mean control.......... 0.04 0
std mean diff......... 56.804 64.55
mean raw eQQ diff..... 0.16667 0.33333
med raw eQQ diff..... 0 0
max raw eQQ diff..... 1 1
mean eCDF diff........ 0.14667 0.16667
med eCDF diff........ 0.14667 0.16667
max eCDF diff........ 0.29333 0.33333
var ratio (Tr/Co)..... 6.8056 Inf
T-test p-value........ 0.22441 0.14381
***** (V11) start_date_num *****
Before Matching After Matching
mean treatment........ 10704 10704
mean control.......... 11066 10666
std mean diff......... -22.292 2.3179
mean raw eQQ diff..... 647.83 83.333
med raw eQQ diff..... 432.5 92.5
max raw eQQ diff..... 1935 129
mean eCDF diff........ 0.1 0.083333
med eCDF diff........ 0.076667 0.083333
max eCDF diff........ 0.34 0.16667
var ratio (Tr/Co)..... 0.82872 1.0209
T-test p-value........ 0.62658 0.32108
KS Bootstrap p-value.. 0.436 1
KS Naive p-value...... 0.46919 1
KS Statistic.......... 0.34 0.16667
Before Matching Minimum p.value: < 2.22e-16
Variable Name(s): hum_rig Number(s): 7
After Matching Minimum p.value: 0.11621
Variable Name(s): gdp Number(s): 5
#install.packages("cobalt")
library(cobalt)
love.plot(mb_formula_H1,
data = df_clean_H1,
weights = m_out_H1, # Use the match object as the source of weights
binary = "std",
thresholds = c(m = .25),
alpha = 0.7,
title = "Covariate Balance (SMD)",
grid = TRUE)

love.plot(mb_formula_H1,
data = df_clean_H1,
weights = m_out_H1, # Use the match object as the source of weights
stats = "ks.statistics", # Change to KS statistics
binary = "std",
thresholds = c(ks = 0.1),
alpha = 0.7,
grid = TRUE,
title = "Covariate Balance (KS Statistics)")

library(ggplot2)
library(gridExtra) # Required for arranging plots
# Panel A: Good Balance (Continuous - ECDF)
p1 <- bal.plot(m_out_H1, treat = Tr, covs = X,
var.name = "start_date_num", type = "ecdf") +
ggtitle("A. Good Balance: Start Date")
# Panel B: Poor Balance (Continuous - ECDF)
p2 <- bal.plot(m_out_H1, treat = Tr, covs = X,
var.name = "gdp", type = "ecdf") +
ggtitle("B. Poor Balance: GDP")
# Panel C: Good Balance (Discrete - Histogram)
p3 <- bal.plot(m_out_H1, treat = Tr, covs = X,
var.name = "dem", type = "histogram") +
ggtitle("C. Good Balance: Democracy")
# Panel D: Poor Balance (Discrete - Histogram)
p4 <- bal.plot(m_out_H1, treat = Tr, covs = X,
var.name = "hum_rig", type = "histogram") +
ggtitle("D. Poor Balance: Human Rights")
# Arrange plots into a 2x2 grid
grid.arrange(p1, p2, p3, p4, nrow = 2)

bal.tab(mb_formula_H1,
data = df_clean_H1,
weights = m_out_H1, # Use the match object as the source of weights
estimand = "ATT",
binary = "std", # <--- Forces binary vars to use SMD
continuous = "std", # <--- Forces continuous vars (default) to use SMD
un = TRUE,
stats = c("m", "v", "ks"), # Mean diffs, Variance ratios, KS stats
thresholds = c(m = 0.25, ks = 0.1))
Balance Measures
Type Diff.Un V.Ratio.Un KS.Un Diff.Adj M.Threshold V.Ratio.Adj KS.Adj
con_dur Contin. 0.4754 0.8409 0.3533 0.5597 Not Balanced, >0.25 0.7630 0.3333
con_int Contin. -0.8638 0.3793 0.3867 0.1677 Balanced, <0.25 1.8253 0.1667
con_iss Binary -0.2404 . 0.1133 0.3536 Not Balanced, >0.25 . 0.1667
war_par Contin. -0.7352 0.1659 0.1800 -0.4612 Not Balanced, >0.25 0.1713 0.1667
gdp Contin. 0.6629 2.2964 0.4667 0.6537 Not Balanced, >0.25 2.0773 0.5000
dem Contin. 0.6819 2.5521 0.3467 0.2214 Balanced, <0.25 2.1250 0.1667
hum_rig Contin. 1.0682 1.6682 0.7333 0.3703 Not Balanced, >0.25 1.4461 0.5000
fem_leg Contin. -0.3897 0.5982 0.1600 -0.6642 Not Balanced, >0.25 0.5312 0.3333
fem_com Contin. 0.6102 1.1691 0.2667 0.8554 Not Balanced, >0.25 1.4138 0.3333
lef_ide Binary 0.6223 . 0.2933 0.7071 Not Balanced, >0.25 . 0.3333
start_date_num Contin. -0.2229 0.8287 0.3400 0.0232 Balanced, <0.25 1.0209 0.1667
KS.Threshold
con_dur Not Balanced, >0.1
con_int Not Balanced, >0.1
con_iss Not Balanced, >0.1
war_par Not Balanced, >0.1
gdp Not Balanced, >0.1
dem Not Balanced, >0.1
hum_rig Not Balanced, >0.1
fem_leg Not Balanced, >0.1
fem_com Not Balanced, >0.1
lef_ide Not Balanced, >0.1
start_date_num Not Balanced, >0.1
Balance tally for mean differences
count
Balanced, <0.25 3
Not Balanced, >0.25 8
Variable with the greatest mean difference
Variable Diff.Adj M.Threshold
fem_com 0.8554 Not Balanced, >0.25
Balance tally for KS statistics
count
Balanced, <0.1 0
Not Balanced, >0.1 11
Variable with the greatest KS statistic
Variable KS.Adj KS.Threshold
gdp 0.5 Not Balanced, >0.1
Effective sample sizes
Control Treated
Unadjusted 50 6
Adjusted 6 6
library(Matching)
get_balance_table <- function(formula, data, match_out, nboots = 500) {
# 1. Run MatchBalance
mb <- MatchBalance(formula, data = data, match.out = match_out, nboots = nboots, print.level = 0)
# 2. Define the "Nested" Null Coalescing Operator
# (This allows us to chain checks: "Try A, if NULL try B, if NULL try C")
`%||%` <- function(a, b) if (is.null(a)) b else a
# 3. Define the Extractors
# T-Test: Simple check
get_tt <- function(x) x$tt$p.value %||% NA
# KS-Test: The "Nested" Approach
# 1. Try nested bootstrap (x$ks$ks.boot.pvalue) <--- PRIORITY
# 2. Try top-level bootstrap (x$ks.boot.pvalue)
# 3. Try standard KS (x$ks$p.value)
get_ks <- function(x) x$ks$ks.boot.pvalue %||% x$ks.boot.pvalue %||% x$ks$p.value %||% NA
# 4. Extract efficiently with sapply
idx <- seq_along(mb$AfterMatching)
vars <- all.vars(formula)[-1]
final_names <- if(length(vars) == length(idx)) vars else paste0("Var_", idx)
df <- data.frame(
Variable = final_names,
Pre_T_P = round(sapply(idx, function(i) get_tt(mb$BeforeMatching[[i]])), 3),
Post_T_P = round(sapply(idx, function(i) get_tt(mb$AfterMatching[[i]])), 3),
Pre_KS_P = round(sapply(idx, function(i) get_ks(mb$BeforeMatching[[i]])), 3),
Post_KS_P = round(sapply(idx, function(i) get_ks(mb$AfterMatching[[i]])), 3)
)
# 5. Status: Pass if (KS is NA or >0.05) AND (T-test > 0.05)
df$Status <- ifelse((is.na(df$Post_KS_P) | df$Post_KS_P > 0.1) & df$Post_T_P > 0.1, "PASS", "FAIL")
return(df)
}
sensmaker Sensitivity Test for Survival Analysis
set.seed(123)
# --- Call Function ---
balance_table_H1 <- get_balance_table(
formula = mb_formula_H1,
data = df_clean_H1,
match_out = m_out_H1,
nboots = 500
)
balance_table_H1
# Include outcome variable for effect estimate
Y <- df_clean_H1$days_of_peace
m_out_H1A <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_H1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_H1A)
Estimate... 2624.2
AI SE...... 1031.8
T-stat..... 2.5433
p.val...... 0.01098
Original number of observations.............. 56
Original number of treated obs............... 6
Matched number of observations............... 6
Matched number of observations (unweighted). 6
Caliper (SDs)........................................ Inf Inf Inf Inf Inf Inf Inf Inf Inf Inf 0.1023685
Number of obs dropped by 'exact' or 'caliper' 0
ATT_est <- m_out_H1A$est
ATT_se <- m_out_H1A$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 2)))
[1] "Estimated ATT: 2624.17"
print(paste("Standard Error:", round(ATT_se, 2)))
[1] "Standard Error: 1031.78"
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
[1] "95% CI: [ 601.876 , 4646.458 ]"
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
[1] "99% CI: [ -33.701 , 5282.035 ]"
Hypothesis 2: Women participation and quality of peace agreement
(content)
# ============ Remove NAs from ALL necessary variables =============
treatnent_var <- c("fem_sig")
outcome_vars <- c("cpa", "civ_soc")
pretreatment_covariates <- c("con_dur", "con_int", "con_iss", "war_par", "gdp", "dem", "hum_rig", "fem_com", "lef_ide", "fem_leg", "start_date_num")
cleaning_vars <- c(treatnent_var, outcome_vars, pretreatment_covariates)
# Check which columns contain missing values
colSums(is.na(data[, cleaning_vars]))
# Clean the data to enable genetic matching (cannot have NAs)
df_clean_H2 <- na.omit(data[, c("cas_id", cleaning_vars)])
df_clean_H2
#Check how many rows have been dropped
cat("Number of control/treatment units in sample (before cleaning):")
table(data$fem_sig)
cat("Number of control/treatment units in sample (after cleaning):")
table(df_clean_H2$fem_sig)
set.seed(123)
# ============== DEFINE MATCHING OBJECTS =============
# Treatment
Tr <- df_clean_H2$fem_sig
# Matching Matrix (X)
matching_vars <- pretreatment_covariates
X <- df_clean_H2[, matching_vars]
# do not include outcomes
# ============= RUN GENMATCH ===============
genout_H2 <- GenMatch(Tr = Tr, X = X, BalanceMatrix = X,
estimand = "ATT", pop.size = 5000,
replace=FALSE,
print.level = 0)
# ============= RUN MATCH ===============
m_out_H2 <- Match(Tr = Tr, X = X, Weight.matrix = genout_H2,
estimand = "ATT",
replace=FALSE)
# ===== Report on matching summary ======
# Count how many times each treated unit appears in the match list
matches_per_treated <- table(m_out_H2$index.treated)
# Check the distribution (e.g., how many got 1 match, how many got 2, etc.)
table(matches_per_treated)
# Total treated units in original data
total_treated <- sum(Tr)
# Total treated units that successfully found a match
matched_treated <- length(unique(m_out_H2$index.treated)) #all treated units have been matched
cat("Original Treated:", total_treated, "\n")
cat("Matched Treated: ", matched_treated, "\n")
cat("Dropped: ", total_treated - matched_treated, "\n")
# ===== Report Balance and Lowest P-Value ======
set.seed(123)
# treatment indicator is the dependent variable, check balance for all covariates
mb_formula_H2 <- fem_sig ~ con_dur + con_int + con_iss + war_par + gdp + dem + hum_rig + fem_leg + fem_com + lef_ide + start_date_num
MatchBalance(mb_formula_H2, data = df_clean_H2, match.out = m_out_H2, nboots = 500)
#install.packages("cobalt")
library(cobalt)
love.plot(mb_formula_H2,
data = df_clean_H2,
weights = m_out_H2, # Use the match object as the source of weights
binary = "std",
thresholds = c(m = .25),
alpha = 0.7,
title = "Covariate Balance (SMD)",
grid = TRUE)
love.plot(mb_formula_H2,
data = df_clean_H2,
weights = m_out_H2, # Use the match object as the source of weights
stats = "ks.statistics", # Change to KS statistics
binary = "std",
thresholds = c(ks = 0.1),
alpha = 0.7,
grid = TRUE,
title = "Covariate Balance (KS Statistics)")
bal.tab(mb_formula_H2,
data = df_clean_H2,
weights = m_out_H2, # Use the match object as the source of weights
estimand = "ATT",
binary = "std", # <--- Forces binary vars to use SMD
continuous = "std", # <--- Forces continuous vars (default) to use SMD
un = TRUE,
stats = c("m", "v", "ks"), # Mean diffs, Variance ratios, KS stats
thresholds = c(m = 0.25, ks = 0.1))
set.seed(123)
# --- Call Function ---
balance_table_H2 <- get_balance_table(
formula = mb_formula_H2,
data = df_clean_H2,
match_out = m_out_H2,
nboots = 500
)
balance_table_H2
Hypothesis 2A: fem_sig on cpa
set.seed(123)
# ========== Run Match() with outcome variable =======
Y <- df_clean_H2$cpa # Outcome
m_out_H2A <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_H2, estimand = "ATT")
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_H2A)
ATT_est <- m_out_H2A$est
ATT_se <- m_out_H2A$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 4)))
print(paste("Standard Error:", round(ATT_se, 4)))
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
Hypothesis 2B: fem_sig on civ_soc
set.seed(123)
# ========== Run Match() with outcome variable =======
Y <- df_clean_H2$civ_soc # Outcome
m_out_H2B <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_H2, estimand = "ATT")
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_H2B)
ATT_est <- m_out_H2B$est
ATT_se <- m_out_H2B$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 2)))
print(paste("Standard Error:", round(ATT_se, 2)))
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
Model H2: Rosenbaum Bounds Sensitivity Analysis
# Outcome
Y <- df_clean_H1$pc_nd
m_out_H1B <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_H1,
caliper = caliper_vec,
estimand = "ATT")
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_H1B)
Estimate... -0.5
AI SE...... 0.20412
T-stat..... -2.4495
p.val...... 0.014306
Original number of observations.............. 56
Original number of treated obs............... 6
Matched number of observations............... 6
Matched number of observations (unweighted). 6
Caliper (SDs)........................................ Inf Inf Inf Inf Inf Inf Inf Inf Inf Inf 0.1023685
Number of obs dropped by 'exact' or 'caliper' 0
ATT_est <- m_out_H1B$est
ATT_se <- m_out_H1B$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 2)))
[1] "Estimated ATT: -0.5"
print(paste("Standard Error:", round(ATT_se, 2)))
[1] "Standard Error: 0.2"
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
[1] "95% CI: [ -0.9 , -0.1 ]"
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
[1] "99% CI: [ -1.026 , 0.026 ]"
# Run Sensitivity Analysis on Durability (Days of Peace)
#install.packages("rbounds")
library(rbounds)
# Obtain indexes for matched treatment and control units
treated_indices <- m_out_H1$index.treated
control_indices <- m_out_H1$index.control
# Extract 'Days of Peace' for both groups
days_Tr <- as.numeric(df_clean_H1$days_of_peace[m_out_H1$index.treated])
days_Co <- as.numeric(df_clean_H1$days_of_peace[m_out_H1$index.control])
# P-Value
psens_H1A <- psens(x = days_Tr,
y = days_Co,
Gamma = 3, # We check up to a "tripling" of the odds of hidden bias
GammaInc = 0.5) # We move in steps of 0.5
# The probability of assignment to treatment under hidden bias Gamma
# For Upper Bound (worst case), we assume bias helps the observed effect
# Hodges-Lehmann Estimate (non-parametric)
hlsens_H1A <- hlsens(x = days_Tr,
y = days_Co,
pr = 0.5,
Gamma = 10,
GammaInc = 1)
psens_H1A
Rosenbaum Sensitivity Test for Wilcoxon Signed Rank P-Value
Unconfounded estimate .... 0.0579
Note: Gamma is Odds of Differential Assignment To
Treatment Due to Unobserved Factors
# result is only "marginally significant" (p=0.06) assuming no hidden bias
# statistical significance disappears with even a tiny amount of hidden bias
hlsens_H1A
Rosenbaum Sensitivity Test for Hodges-Lehmann Point Estimate
Unconfounded estimate .... 2661
Note: Gamma is Odds of Differential Assignment To
Treatment Due to Unobserved Factors
# magnitude of the effect point estimate is quite robust
#it would take a massive amount of unobserved bias (Gamma = 7) to reduce the estimated effect to zero
# even if unobserved factors caused massive selection bias, the underlying signal still suggests a positive effect on duration
Robustness Check
# ============ Remove NAs from ALL necessary variables =============
# Check which columns contain missing values
colSums(is.na(data[, cleaning_vars]))
# Clean the data to enable genetic matching (cannot have NAs)
pretreatment_covariates <- c("con_dur", "con_int", "con_iss", "war_par", "gdp", "dem", "hum_rig", "fem_com", "lef_ide", "fem_leg", "start_date_num")
treatnent_var <- c("fem_sig")
outcome_vars <- c("cpa", "civ_soc")
add_covariates <- c("pow_sha", "quo", "un_pea_con") # additional covariates
# This list includes Y, Tr, and X. We use it ONLY for na.omit.
cleaning_vars <- c(treatnent_var, outcome_vars, pretreatment_covariates, add_covariates)
df_clean_rb2 <- na.omit(data[, c("cas_id", cleaning_vars)])
df_clean_rb2
# Check how many rows have been dropped
cat("Number of control/treatment units in sample (before cleaning):")
table(data$fem_sig)
cat("Number of control/treatment units in sample (after cleaning):")
table(df_clean_rb2$fem_sig)
# ========== DEFINE MATCHING OBJECTS ===============
set.seed(123)
# Treatment
Tr <- df_clean_rb2$fem_sig
# Matching Matrix (X)
matching_vars <- c(pretreatment_covariates, add_covariates) # include additional covariates
X <- df_clean_rb2[, matching_vars]
# =========== RUN GENMATCH =================
genout_rb2 <- GenMatch(Tr = Tr, X = X, BalanceMatrix = X,
replace=FALSE,
estimand = "ATT", pop.size = 5000,
print.level = 0)
# =============== RUN MATCH ===============
m_out_rb2 <- Match(Tr = Tr, X = X, Weight.matrix = genout_rb2, estimand = "ATT", replace=FALSE)
# ========== Report on matching summary =========
# Count how many times each treated unit appears in the match list
matches_per_treated <- table(m_out_rb2 $index.treated)
# Check the distribution (e.g., how many got 1 match, how many got 2, etc.)
table(matches_per_treated)
# Total treated units in original data
total_treated <- sum(Tr)
# Total treated units that successfully found a match
matched_treated <- length(unique(m_out_rb2 $index.treated)) #all treated units have been matched
cat("Original Treated:", total_treated, "\n")
cat("Matched Treated: ", matched_treated, "\n")
cat("Dropped: ", total_treated - matched_treated, "\n")
set.seed(123)
# ===== Report Balance and Lowest P-Value ======
# treatment indicator is the dependent variable, check balance for all covariates
mb_formula_rb2 <- fem_sig ~ con_dur + con_int + con_iss + war_par + gdp + dem + hum_rig + fem_leg + fem_com + lef_ide + pow_sha + quo + un_pea_con + start_date_num
MatchBalance(mb_formula_rb2, data = df_clean_rb2, match.out = m_out_rb2, nboots = 500)
H2 vs R2: Comparison of Matching Results
bal.tab(mb_formula_rb2,
data = df_clean_rb2,
weights = m_out_rb2, # Use the match object as the source of weights
estimand = "ATT",
binary = "std", # <--- Forces binary vars to use SMD
continuous = "std", # <--- Forces continuous vars (default) to use SMD
un = TRUE,
stats = c("m", "v", "ks"), # Mean diffs, Variance ratios, KS stats
thresholds = c(m = 0.25, ks = 0.1))
set.seed(123)
# --- Call Function ---
balance_table_rb2 <- get_balance_table(
formula = mb_formula_rb2,
data = df_clean_rb2,
match_out = m_out_rb2,
nboots = 500
)
balance_table_rb2
matched_data_H2 <- rbind(
df_clean_H2[m_out_H2$index.treated, ],
df_clean_H2[m_out_H2$index.control, ]
)
n_pairs <- length(m_out_H2$index.treated)
matched_data_H2$pair_id <- c(1:n_pairs, 1:n_pairs)
matched_data_rb2 <- rbind(
df_clean_rb2[m_out_rb2$index.treated, ],
df_clean_rb2[m_out_rb2$index.control, ]
)
n_pairs <- length(m_out_rb2$index.treated)
matched_data_rb2$pair_id <- c(1:n_pairs, 1:n_pairs)
matches <- cbind(Pair_ID = matched_data_H2$pair_id,
Treated = matched_data_H2$cas_id[matched_data_H2$fem_sig == 1],
ModelH2_Matches = matched_data_H2$cas_id[matched_data_H2$fem_sig == 0],
ModelR2_Matches = matched_data_rb2$cas_id[matched_data_rb2$fem_sig == 0])
matches[1:6, ]
# Compare outcome observations of matched units
matchcomp_cpa <- cbind(Pair_ID = matched_data_H2$pair_id,
cas_id = matched_data_H2$cas_id,
fem_sig = matched_data_H2$fem_sig,
cpa_H2 = matched_data_H2$cpa,
cpa_rb2 = matched_data_rb2$cpa)
matchcomp_civ_soc <- cbind(Pair_ID = matched_data_H2$pair_id,
cas_id = matched_data_H2$cas_id,
fem_sig = matched_data_H2$fem_sig,
civ_soc_H2 = matched_data_H2$civ_soc,
civ_soc_rb2 = matched_data_rb2$civ_soc)
matchcomp_cpa
matchcomp_civ_soc
H2 vs R2: Comparison of Treatment Effect Estimates
# ========== Run Match() with outome variable (cpa) ==============
set.seed(123)
# Outcome
Y <- df_clean_rb2$cpa
m_out_rb2A <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_rb2, estimand = "ATT", replace = FALSE)
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_rb2A)
ATT_est <- m_out_rb2A$est
ATT_se <- 0.20412#m_out_rb2A$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 2)))
print(paste("Standard Error:", round(ATT_se, 2)))
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
set.seed(123)
# ========== Run Match() with outome variable (civ_soc) ==============
# Outcome
Y <- df_clean_rb2$civ_soc
m_out_rb2B <- Match(Y = Y, Tr = Tr, X = X, Weight.matrix = genout_rb2, estimand = "ATT", replace = FALSE)
# ===== Estimate Treatment Effect, SE, and CI ======
summary(m_out_rb2B)
ATT_est <- m_out_rb2B$est
ATT_se <- 0.15215 #m_out_rb2B$se
#----- Get Confidence Intervals ------
# CI bounds given by point estimate +/- margin of error
# CV for 95% interval is 1.96
ci_lower95 <- ATT_est - 1.96 * ATT_se
ci_upper95 <- ATT_est + 1.96 * ATT_se
# CV for 99% interval is 2.576
ci_lower99 <- ATT_est - 2.576 * ATT_se
ci_upper99 <- ATT_est + 2.576 * ATT_se
print(paste("Estimated ATT:", round(ATT_est, 3)))
print(paste("Standard Error:", round(ATT_se, 3)))
print(paste("95% CI: [", round(ci_lower95, 3), ",", round(ci_upper95, 3), "]"))
print(paste("99% CI: [", round(ci_lower99, 3), ",", round(ci_upper99, 3), "]"))
print ("H2A vs. R2A")
summary(m_out_H2A)
summary(m_out_rb2A)
print ("H2B vs. R2B")
summary(m_out_H2B)
summary(m_out_rb2B)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgSW5pdGlhbCBEYXRhIFByZXBhcmF0aW9uCgpgYGB7cn0KcmF3X2RhdGEgPC0gcmVhZC5jc3YoImh0dHBzOi8vdGlueXVybC5jb20vNDczNnhqbXciKQoKbGlicmFyeShkcGx5cikKCiMgQ29sbGFwc2UgdGhlIGRhdGFzZXQgdG8gb25lIG9ic2VydmF0aW9uIHBlciBhZ3JlZW1lbnQgKGNhc19pZCkKIyBXZSBrZWVwIHRoZSByb3cgd2l0aCB0aGUgbGF0ZXN0ICd5ZWFyJyB0byBjYXB0dXJlIHRoZSBmaW5hbCBvdXRjb21lLgpkYXRhIDwtIHJhd19kYXRhICU+JQogIGdyb3VwX2J5KGNhc19pZCkgJT4lCiAgc2xpY2VfbWF4KG9yZGVyX2J5ID0geWVhciwgbiA9IDEpICU+JSAjIFNlbGVjdHMgdGhlIHJvdyB3aXRoIHRoZSBoaWdoZXN0IHllYXIKICB1bmdyb3VwKCkKCiMgPT09PT09PT09PT09IFBSRVAgVkFSSUFCTEVTIElOIE9SSUdJTkFMIERBVEEgPT09PT09PT09PT09PT09PT0KZGF0YSRzdGFydF9kYXRlX29iaiA8LSBhcy5EYXRlKGRhdGEkc3RydF9wYSkKZGF0YSRlbmRfZGF0ZV9vYmogICA8LSBhcy5EYXRlKGRhdGEkbmRfcGEpCmRhdGEkc3RhcnRfZGF0ZV9udW0gPC0gYXMubnVtZXJpYyhkYXRhJHN0YXJ0X2RhdGVfb2JqKQpkYXRhJHdlZWtzX29mX3BlYWNlIDwtIGFzLm51bWVyaWMoZGlmZnRpbWUoZGF0YSRlbmRfZGF0ZV9vYmosIGRhdGEkc3RhcnRfZGF0ZV9vYmosIHVuaXRzID0gIndlZWtzIikpCmRhdGEkZGF5c19vZl9wZWFjZSAgPC0gYXMubnVtZXJpYyhkYXRhJGVuZF9kYXRlX29iaiAtIGRhdGEkc3RhcnRfZGF0ZV9vYmopCgojIENoZWNrIHRoZSBuZXcgZGltZW5zaW9ucwpzdHIoZGF0YSkKYGBgCgojIyBIeXBvdGhlc2lzIDE6IFdvbWVuIHBhcnRpY2lwYXRpb24gaW1wYWN0cyBwZWFjZSBkdXJhYmlsaXR5CgpgYGB7ciwgTW9kZWwgSDE6IERhdGEgUHJlcH0KCiMgPT09PT0gQ0xFQU5JTkc6IFJlbW92ZSBOQXMgZnJvbSBBTEwgbmVjZXNzYXJ5IHZhcmlhYmxlcyA9PT09CgojIERlZmluZSB2YXJpYWJsZXMgb2YgaW50ZXJlc3QKCnByZXRyZWF0bWVudF9jb3ZhcmlhdGVzIDwtIGMoImNvbl9kdXIiLCAiY29uX2ludCIsICJjb25faXNzIiwgIndhcl9wYXIiLCAiZ2RwIiwgImRlbSIsICJodW1fcmlnIiwgImZlbV9jb20iLCAibGVmX2lkZSIsICJmZW1fbGVnIiwgInN0YXJ0X2RhdGVfbnVtIikKCnRyZWF0bmVudF92YXIgPC0gYygiZmVtX3NpZyIpCm91dGNvbWVfdmFycyA8LSBjKCJkYXlzX29mX3BlYWNlIiwgInBjX25kIikKCmNsZWFuaW5nX3ZhcnMgPC0gYyh0cmVhdG5lbnRfdmFyLCBvdXRjb21lX3ZhcnMsIHByZXRyZWF0bWVudF9jb3ZhcmlhdGVzKSAjIFRoaXMgbGlzdCBpbmNsdWRlcyBZLCBUciwgYW5kIFguIFdlIHVzZSBpdCBPTkxZIGZvciBuYS5vbWl0LgoKIyBDaGVjayB3aGljaCBjb2x1bW5zIGNvbnRhaW4gbWlzc2luZyB2YWx1ZXMKY29sU3Vtcyhpcy5uYShkYXRhWywgY2xlYW5pbmdfdmFyc10pKSAKCiMgQ2xlYW4gdGhlIGRhdGEgdG8gZW5hYmxlIGdlbmV0aWMgbWF0Y2hpbmcgKGNhbm5vdCBoYXZlIE5BcykKZGZfY2xlYW5fSDEgPC0gbmEub21pdChkYXRhWywgYygiY2FzX2lkIiwgY2xlYW5pbmdfdmFycyldKQpkZl9jbGVhbl9IMQoKY2F0KCJOdW1iZXIgb2YgY29udHJvbC90cmVhdG1lbnQgdW5pdHMgaW4gc2FtcGxlIChiZWZvcmUgY2xlYW5pbmcpOiIpCnRhYmxlKGRhdGEkZmVtX3NpZykKCmNhdCgiTnVtYmVyIG9mIGNvbnRyb2wvdHJlYXRtZW50IHVuaXRzIGluIHNhbXBsZSAoYWZ0ZXIgY2xlYW5pbmcpOiIpCnRhYmxlKGRmX2NsZWFuX0gxJGZlbV9zaWcpCmBgYAoKYGBge3IsIE1vZGVsIEgxOiBHZW5ldGljIE1hdGNoaW5nfQpsaWJyYXJ5KHJnZW5vdWQpCmxpYnJhcnkoTWF0Y2hpbmcpCgpzZXQuc2VlZCgxMjMpCgojID09PT09PSBERUZJTkUgTUFUQ0hJTkcgT0JKRUNUUyA9PT09PT0KCiMgVHJlYXRtZW50IApUciA8LSBkZl9jbGVhbl9IMSRmZW1fc2lnCgojIE1hdGNoaW5nIE1hdHJpeCAoWCk6IE9OTFkgY29udGFpbnMgcHJlLXRyZWF0bWVudCBjb3ZhcmlhdGVzLgptYXRjaGluZ192YXJzIDwtIHByZXRyZWF0bWVudF9jb3ZhcmlhdGVzClggPC0gZGZfY2xlYW5fSDFbLCBtYXRjaGluZ192YXJzXQojIERvIG5vdCB1c2Ugb3V0Y29tZSBvYnNlcnZhdGlvbnMgdW50aWwgbWF0Y2hpbmcgaXMgY29tcGxldGUKCgojIFBSRVBBUkUgQ0FMSVBFUiAoZm9yIHN0YXJ0X2RhdGVfbnVtKQojIENhbGN1bGF0ZSBjYWxpcGVyIHZhbHVlIGZvciBzdGFydF9kYXRlX251bQpkZXNpcmVkX3dpbmRvd19kYXlzIDwtIDE4MApzZF9kYXRlIDwtIHNkKGRmX2NsZWFuX0gxJHN0YXJ0X2RhdGVfbnVtKQpjYWxpcGVyX3ZhbHVlIDwtIGRlc2lyZWRfd2luZG93X2RheXMgLyBzZF9kYXRlCgojIENyZWF0ZSBDYWxpcGVyIFZlY3RvcgojIFdlIG5lZWQgYSB2ZWN0b3Igb2YgSW5mcyBtYXRjaGluZyB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gWApjYWxpcGVyX3ZlYyA8LSByZXAoSW5mLCBuY29sKFgpKQoKIyBBcHBseSByZXN0cmljdGlvbiBPTkxZIHRvIHRoZSBzdGFydCBkYXRlIGNvbHVtbgpkYXRlX2luZGV4IDwtIHdoaWNoKGNvbG5hbWVzKFgpID09ICJzdGFydF9kYXRlX251bSIpCmNhbGlwZXJfdmVjW2RhdGVfaW5kZXhdIDwtIGNhbGlwZXJfdmFsdWUKCiMgPT09PT09PT09PSBSVU4gR0VOTUFUQ0ggPT09PT09PT09PT09PT0KZ2Vub3V0X0gxIDwtIEdlbk1hdGNoKFRyID0gVHIsIFggPSBYLCBCYWxhbmNlTWF0cml4ID0gWCwgCiAgICAgICAgICAgICAgICAgICBjYWxpcGVyID0gY2FsaXBlcl92ZWMsCiAgICAgICAgICAgICAgICAgICBlc3RpbWFuZCA9ICJBVFQiLCBwb3Auc2l6ZSA9IDUwMDAsIAogICAgICAgICAgICAgICAgICAgcHJpbnQubGV2ZWwgPSAwKQoKIyA9PT09PT09PT09IFJVTiBNQVRDSCA9PT09PT09PT09PT09PQoKbV9vdXRfSDEgPC0gTWF0Y2goVHIgPSBUciwgWCA9IFgsIFdlaWdodC5tYXRyaXggPSBnZW5vdXRfSDEsIAogICAgICAgICAgICAgICBjYWxpcGVyID0gY2FsaXBlcl92ZWMsIAogICAgICAgICAgICAgICBlc3RpbWFuZCA9ICJBVFQiKQoKIyA9PT09PSBSZXBvcnQgb24gbWF0Y2hpbmcgc3VtbWFyeSA9PT09PT0KCiMgQ291bnQgaG93IG1hbnkgdGltZXMgZWFjaCB0cmVhdGVkIHVuaXQgYXBwZWFycyBpbiB0aGUgbWF0Y2ggbGlzdAptYXRjaGVzX3Blcl90cmVhdGVkIDwtIHRhYmxlKG1fb3V0X0gxJGluZGV4LnRyZWF0ZWQpCgojIENoZWNrIHRoZSBkaXN0cmlidXRpb24gKGUuZy4sIGhvdyBtYW55IGdvdCAxIG1hdGNoLCBob3cgbWFueSBnb3QgMiwgZXRjLikKdGFibGUobWF0Y2hlc19wZXJfdHJlYXRlZCkKCiMgVG90YWwgdHJlYXRlZCB1bml0cyBpbiBvcmlnaW5hbCBkYXRhCnRvdGFsX3RyZWF0ZWQgPC0gc3VtKFRyKQoKIyBUb3RhbCB0cmVhdGVkIHVuaXRzIHRoYXQgc3VjY2Vzc2Z1bGx5IGZvdW5kIGEgbWF0Y2gKbWF0Y2hlZF90cmVhdGVkIDwtIGxlbmd0aCh1bmlxdWUobV9vdXRfSDEkaW5kZXgudHJlYXRlZCkpCgpjYXQoIk9yaWdpbmFsIFRyZWF0ZWQ6IiwgdG90YWxfdHJlYXRlZCwgIlxuIikKY2F0KCJNYXRjaGVkIFRyZWF0ZWQ6ICIsIG1hdGNoZWRfdHJlYXRlZCwgIlxuIikKY2F0KCJEcm9wcGVkOiAgICAgICAgICIsIHRvdGFsX3RyZWF0ZWQgLSBtYXRjaGVkX3RyZWF0ZWQsICJcbiIpCmBgYAoKYGBge3IsIE1vZGVsIEgxOiBHZW5ldGljIE1hdGNoaW5nIFJlc3VsdHN9CiMgPT09PT0gUmVwb3J0IEJhbGFuY2UgYW5kIExvd2VzdCBQLVZhbHVlID09PT09PQpzZXQuc2VlZCgxMjMpCiMgdHJlYXRtZW50IGluZGljYXRvciBpcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLCBjaGVjayBiYWxhbmNlIGZvciBhbGwgY292YXJpYXRlcwptYl9mb3JtdWxhX0gxIDwtIGZlbV9zaWcgfiBjb25fZHVyICsgY29uX2ludCArIGNvbl9pc3MgKyAgd2FyX3BhciArIGdkcCArIGRlbSArIGh1bV9yaWcgKyBmZW1fbGVnICsgZmVtX2NvbSArIGxlZl9pZGUgKyBzdGFydF9kYXRlX251bQoKTWF0Y2hCYWxhbmNlKG1iX2Zvcm11bGFfSDEsIGRhdGEgPSBkZl9jbGVhbl9IMSwgbWF0Y2gub3V0ID0gbV9vdXRfSDEsIG5ib290cyA9IDUwMCkKYGBgCgpgYGB7ciwgTW9kZWwgSDE6IExvdmUgUGxvdHN9CiNpbnN0YWxsLnBhY2thZ2VzKCJjb2JhbHQiKQpsaWJyYXJ5KGNvYmFsdCkKCmxvdmUucGxvdChtYl9mb3JtdWxhX0gxLCAKICAgICAgICAgIGRhdGEgPSBkZl9jbGVhbl9IMSwgCiAgICAgICAgICB3ZWlnaHRzID0gbV9vdXRfSDEsICMgVXNlIHRoZSBtYXRjaCBvYmplY3QgYXMgdGhlIHNvdXJjZSBvZiB3ZWlnaHRzCiAgICAgICAgICBiaW5hcnkgPSAic3RkIiwKICAgICAgICAgIHRocmVzaG9sZHMgPSBjKG0gPSAuMjUpLAogICAgICAgICAgYWxwaGEgPSAwLjcsCiAgICAgICAgICB0aXRsZSA9ICJDb3ZhcmlhdGUgQmFsYW5jZSAoU01EKSIsCiAgICAgICAgICBncmlkID0gVFJVRSkKCmxvdmUucGxvdChtYl9mb3JtdWxhX0gxLCAKICAgICAgICAgIGRhdGEgPSBkZl9jbGVhbl9IMSwgCiAgICAgICAgICB3ZWlnaHRzID0gbV9vdXRfSDEsICMgVXNlIHRoZSBtYXRjaCBvYmplY3QgYXMgdGhlIHNvdXJjZSBvZiB3ZWlnaHRzCiAgICAgICAgICBzdGF0cyA9ICJrcy5zdGF0aXN0aWNzIiwgIyBDaGFuZ2UgdG8gS1Mgc3RhdGlzdGljcwogICAgICAgICAgYmluYXJ5ID0gInN0ZCIsCiAgICAgICAgICB0aHJlc2hvbGRzID0gYyhrcyA9IDAuMSksIAogICAgICAgICAgYWxwaGEgPSAwLjcsCiAgICAgICAgICBncmlkID0gVFJVRSwKICAgICAgICAgIHRpdGxlID0gIkNvdmFyaWF0ZSBCYWxhbmNlIChLUyBTdGF0aXN0aWNzKSIpCmBgYAoKYGBge3IsIE1vZGVsIEgxOiBDb3ZhcmlhdGUgRGlzdHJpYnV0aW9uYWwgQmFsYW5jZX0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWRFeHRyYSkgIyBSZXF1aXJlZCBmb3IgYXJyYW5naW5nIHBsb3RzCgojIFBhbmVsIEE6IEdvb2QgQmFsYW5jZSAoQ29udGludW91cyAtIEVDREYpCnAxIDwtIGJhbC5wbG90KG1fb3V0X0gxLCB0cmVhdCA9IFRyLCBjb3ZzID0gWCwgCiAgICAgICAgICAgICAgIHZhci5uYW1lID0gInN0YXJ0X2RhdGVfbnVtIiwgdHlwZSA9ICJlY2RmIikgKyAKICAgICAgZ2d0aXRsZSgiQS4gR29vZCBCYWxhbmNlOiBTdGFydCBEYXRlIikKCiMgUGFuZWwgQjogUG9vciBCYWxhbmNlIChDb250aW51b3VzIC0gRUNERikKcDIgPC0gYmFsLnBsb3QobV9vdXRfSDEsIHRyZWF0ID0gVHIsIGNvdnMgPSBYLCAKICAgICAgICAgICAgICAgdmFyLm5hbWUgPSAiZ2RwIiwgdHlwZSA9ICJlY2RmIikgKyAKICAgICAgZ2d0aXRsZSgiQi4gUG9vciBCYWxhbmNlOiBHRFAiKQoKIyBQYW5lbCBDOiBHb29kIEJhbGFuY2UgKERpc2NyZXRlIC0gSGlzdG9ncmFtKQpwMyA8LSBiYWwucGxvdChtX291dF9IMSwgdHJlYXQgPSBUciwgY292cyA9IFgsIAogICAgICAgICAgICAgICB2YXIubmFtZSA9ICJkZW0iLCB0eXBlID0gImhpc3RvZ3JhbSIpICsgCiAgICAgIGdndGl0bGUoIkMuIEdvb2QgQmFsYW5jZTogRGVtb2NyYWN5IikKCiMgUGFuZWwgRDogUG9vciBCYWxhbmNlIChEaXNjcmV0ZSAtIEhpc3RvZ3JhbSkKcDQgPC0gYmFsLnBsb3QobV9vdXRfSDEsIHRyZWF0ID0gVHIsIGNvdnMgPSBYLCAKICAgICAgICAgICAgICAgdmFyLm5hbWUgPSAiaHVtX3JpZyIsIHR5cGUgPSAiaGlzdG9ncmFtIikgKyAKICAgICAgZ2d0aXRsZSgiRC4gUG9vciBCYWxhbmNlOiBIdW1hbiBSaWdodHMiKQoKIyBBcnJhbmdlIHBsb3RzIGludG8gYSAyeDIgZ3JpZApncmlkLmFycmFuZ2UocDEsIHAyLCBwMywgcDQsIG5yb3cgPSAyKQpgYGAKCmBgYHtyLCBNb2RlbCBIMTogQ2hlY2sgQmFsYW5jZSBTdW1tYXJ5fQpiYWwudGFiKG1iX2Zvcm11bGFfSDEsIAogICAgICAgIGRhdGEgPSBkZl9jbGVhbl9IMSwgCiAgICAgICAgd2VpZ2h0cyA9IG1fb3V0X0gxLCAjIFVzZSB0aGUgbWF0Y2ggb2JqZWN0IGFzIHRoZSBzb3VyY2Ugb2Ygd2VpZ2h0cwogICAgICAgIGVzdGltYW5kID0gIkFUVCIsCiAgICAgICAgYmluYXJ5ID0gInN0ZCIsICAgICAgIyA8LS0tIEZvcmNlcyBiaW5hcnkgdmFycyB0byB1c2UgU01ECiAgICAgICAgY29udGludW91cyA9ICJzdGQiLCAgIyA8LS0tIEZvcmNlcyBjb250aW51b3VzIHZhcnMgKGRlZmF1bHQpIHRvIHVzZSBTTUQKICAgICAgICB1biA9IFRSVUUsCiAgICAgICAgc3RhdHMgPSBjKCJtIiwgInYiLCAia3MiKSwgICAjIE1lYW4gZGlmZnMsIFZhcmlhbmNlIHJhdGlvcywgS1Mgc3RhdHMKICAgICAgICB0aHJlc2hvbGRzID0gYyhtID0gMC4yNSwga3MgPSAwLjEpKQpgYGAKCmBgYHtyLCBGdW5jdGlvbiBmb3IgTWF0Y2hCYWxhbmNlIFAtdmFsdWUgVGFibGV9CmxpYnJhcnkoTWF0Y2hpbmcpCgpnZXRfYmFsYW5jZV90YWJsZSA8LSBmdW5jdGlvbihmb3JtdWxhLCBkYXRhLCBtYXRjaF9vdXQsIG5ib290cyA9IDUwMCkgewogIAogICMgMS4gUnVuIE1hdGNoQmFsYW5jZQogIG1iIDwtIE1hdGNoQmFsYW5jZShmb3JtdWxhLCBkYXRhID0gZGF0YSwgbWF0Y2gub3V0ID0gbWF0Y2hfb3V0LCBuYm9vdHMgPSBuYm9vdHMsIHByaW50LmxldmVsID0gMCkKICAKICAjIDIuIERlZmluZSB0aGUgIk5lc3RlZCIgTnVsbCBDb2FsZXNjaW5nIE9wZXJhdG9yIAogICMgICAgKFRoaXMgYWxsb3dzIHVzIHRvIGNoYWluIGNoZWNrczogIlRyeSBBLCBpZiBOVUxMIHRyeSBCLCBpZiBOVUxMIHRyeSBDIikKICBgJXx8JWAgPC0gZnVuY3Rpb24oYSwgYikgaWYgKGlzLm51bGwoYSkpIGIgZWxzZSBhCgogICMgMy4gRGVmaW5lIHRoZSBFeHRyYWN0b3JzCiAgIyAgICBULVRlc3Q6IFNpbXBsZSBjaGVjawogIGdldF90dCA8LSBmdW5jdGlvbih4KSB4JHR0JHAudmFsdWUgJXx8JSBOQQogIAogICMgICAgS1MtVGVzdDogVGhlICJOZXN0ZWQiIEFwcHJvYWNoCiAgIyAgICAxLiBUcnkgbmVzdGVkIGJvb3RzdHJhcCAoeCRrcyRrcy5ib290LnB2YWx1ZSkgPC0tLSBQUklPUklUWQogICMgICAgMi4gVHJ5IHRvcC1sZXZlbCBib290c3RyYXAgKHgka3MuYm9vdC5wdmFsdWUpCiAgIyAgICAzLiBUcnkgc3RhbmRhcmQgS1MgKHgka3MkcC52YWx1ZSkKICBnZXRfa3MgPC0gZnVuY3Rpb24oeCkgeCRrcyRrcy5ib290LnB2YWx1ZSAlfHwlIHgka3MuYm9vdC5wdmFsdWUgJXx8JSB4JGtzJHAudmFsdWUgJXx8JSBOQQoKICAjIDQuIEV4dHJhY3QgZWZmaWNpZW50bHkgd2l0aCBzYXBwbHkKICBpZHggPC0gc2VxX2Fsb25nKG1iJEFmdGVyTWF0Y2hpbmcpCiAgdmFycyA8LSBhbGwudmFycyhmb3JtdWxhKVstMV0KICBmaW5hbF9uYW1lcyA8LSBpZihsZW5ndGgodmFycykgPT0gbGVuZ3RoKGlkeCkpIHZhcnMgZWxzZSBwYXN0ZTAoIlZhcl8iLCBpZHgpCgogIGRmIDwtIGRhdGEuZnJhbWUoCiAgICBWYXJpYWJsZSAgPSBmaW5hbF9uYW1lcywKICAgIFByZV9UX1AgICA9IHJvdW5kKHNhcHBseShpZHgsIGZ1bmN0aW9uKGkpIGdldF90dChtYiRCZWZvcmVNYXRjaGluZ1tbaV1dKSksIDMpLAogICAgUG9zdF9UX1AgID0gcm91bmQoc2FwcGx5KGlkeCwgZnVuY3Rpb24oaSkgZ2V0X3R0KG1iJEFmdGVyTWF0Y2hpbmdbW2ldXSkpLCAzKSwKICAgIFByZV9LU19QICA9IHJvdW5kKHNhcHBseShpZHgsIGZ1bmN0aW9uKGkpIGdldF9rcyhtYiRCZWZvcmVNYXRjaGluZ1tbaV1dKSksIDMpLAogICAgUG9zdF9LU19QID0gcm91bmQoc2FwcGx5KGlkeCwgZnVuY3Rpb24oaSkgZ2V0X2tzKG1iJEFmdGVyTWF0Y2hpbmdbW2ldXSkpLCAzKQogICkKICAKICAjIDUuIFN0YXR1czogUGFzcyBpZiAoS1MgaXMgTkEgb3IgPjAuMDUpIEFORCAoVC10ZXN0ID4gMC4wNSkKICBkZiRTdGF0dXMgPC0gaWZlbHNlKChpcy5uYShkZiRQb3N0X0tTX1ApIHwgZGYkUG9zdF9LU19QID4gMC4xKSAmIGRmJFBvc3RfVF9QID4gMC4xLCAiUEFTUyIsICJGQUlMIikKICAKICByZXR1cm4oZGYpCn0KYGBgCgpgYGB7ciwgTW9kZWwgSDE6IE1hdGNoQmFsYW5jZSBwLXZhbHVlc30Kc2V0LnNlZWQoMTIzKQojIC0tLSBDYWxsIEZ1bmN0aW9uIC0tLQpiYWxhbmNlX3RhYmxlX0gxIDwtIGdldF9iYWxhbmNlX3RhYmxlKAogIGZvcm11bGEgPSBtYl9mb3JtdWxhX0gxLCAKICBkYXRhID0gZGZfY2xlYW5fSDEsIAogIG1hdGNoX291dCA9IG1fb3V0X0gxLCAKICBuYm9vdHMgPSA1MDAKKQoKYmFsYW5jZV90YWJsZV9IMQpgYGAKCiMjIyBIeXBvdGhlc2lzIDFBOiBmZW0tc2lnIG9uIGRheXNfb2ZfcGVhY2UgKHBlYWNlIGR1cmF0aW9uKQoKYGBge3IsIE1vZGVsIEgxQTogVHJlYXRtZW50IGVmZmVjdCBlc3RpbWF0ZX0KIyBJbmNsdWRlIG91dGNvbWUgdmFyaWFibGUgZm9yIGVmZmVjdCBlc3RpbWF0ZQpZICA8LSBkZl9jbGVhbl9IMSRkYXlzX29mX3BlYWNlCm1fb3V0X0gxQSA8LSBNYXRjaChZID0gWSwgVHIgPSBUciwgWCA9IFgsIFdlaWdodC5tYXRyaXggPSBnZW5vdXRfSDEsIAogICAgICAgICAgICAgICBjYWxpcGVyID0gY2FsaXBlcl92ZWMsIAogICAgICAgICAgICAgICBlc3RpbWFuZCA9ICJBVFQiKQoKIyA9PT09PSBFc3RpbWF0ZSBUcmVhdG1lbnQgRWZmZWN0LCBTRSwgYW5kIENJID09PT09PQpzdW1tYXJ5KG1fb3V0X0gxQSkKCkFUVF9lc3QgPC0gbV9vdXRfSDFBJGVzdApBVFRfc2UgPC0gbV9vdXRfSDFBJHNlCgojLS0tLS0gR2V0IENvbmZpZGVuY2UgSW50ZXJ2YWxzIC0tLS0tLQojIENJIGJvdW5kcyBnaXZlbiBieSBwb2ludCBlc3RpbWF0ZSArLy0gbWFyZ2luIG9mIGVycm9yCiMgQ1YgZm9yIDk1JSBpbnRlcnZhbCBpcyAxLjk2CmNpX2xvd2VyOTUgPC0gQVRUX2VzdCAtIDEuOTYgKiBBVFRfc2UKY2lfdXBwZXI5NSA8LSBBVFRfZXN0ICsgMS45NiAqIEFUVF9zZQojIENWIGZvciA5OSUgaW50ZXJ2YWwgaXMgMi41NzYKY2lfbG93ZXI5OSA8LSBBVFRfZXN0IC0gMi41NzYgKiBBVFRfc2UKY2lfdXBwZXI5OSA8LSBBVFRfZXN0ICsgMi41NzYgKiBBVFRfc2UKCnByaW50KHBhc3RlKCJFc3RpbWF0ZWQgQVRUOiIsIHJvdW5kKEFUVF9lc3QsIDIpKSkKcHJpbnQocGFzdGUoIlN0YW5kYXJkIEVycm9yOiIsIHJvdW5kKEFUVF9zZSwgMikpKQpwcmludChwYXN0ZSgiOTUlIENJOiBbIiwgcm91bmQoY2lfbG93ZXI5NSwgMyksICIsIiwgcm91bmQoY2lfdXBwZXI5NSwgMyksICJdIikpCnByaW50KHBhc3RlKCI5OSUgQ0k6IFsiLCByb3VuZChjaV9sb3dlcjk5LCAzKSwgIiwiLCByb3VuZChjaV91cHBlcjk5LCAzKSwgIl0iKSkKYGBgCgojIyMgSHlwb3RoZXNpcyAxQjogZmVtLXNpZyBvbiBwY19uZCAocGVhY2UgZW5kcyBhbmQgY29uZmxpY3QgcmVzdW1lcykKCmBgYHtyLCBNb2RlbCBIMUI6IFRyZWF0bWVudCBlZmZlY3QgZXN0aW1hdGV9CiMgT3V0Y29tZQpZICA8LSBkZl9jbGVhbl9IMSRwY19uZAptX291dF9IMUIgPC0gTWF0Y2goWSA9IFksIFRyID0gVHIsIFggPSBYLCBXZWlnaHQubWF0cml4ID0gZ2Vub3V0X0gxLCAKICAgICAgICAgICAgICAgY2FsaXBlciA9IGNhbGlwZXJfdmVjLCAKICAgICAgICAgICAgICAgZXN0aW1hbmQgPSAiQVRUIikKCiMgPT09PT0gRXN0aW1hdGUgVHJlYXRtZW50IEVmZmVjdCwgU0UsIGFuZCBDSSA9PT09PT0KCnN1bW1hcnkobV9vdXRfSDFCKQoKQVRUX2VzdCA8LSBtX291dF9IMUIkZXN0CkFUVF9zZSA8LSBtX291dF9IMUIkc2UKCiMtLS0tLSBHZXQgQ29uZmlkZW5jZSBJbnRlcnZhbHMgLS0tLS0tCiMgQ0kgYm91bmRzIGdpdmVuIGJ5IHBvaW50IGVzdGltYXRlICsvLSBtYXJnaW4gb2YgZXJyb3IKIyBDViBmb3IgOTUlIGludGVydmFsIGlzIDEuOTYKY2lfbG93ZXI5NSA8LSBBVFRfZXN0IC0gMS45NiAqIEFUVF9zZQpjaV91cHBlcjk1IDwtIEFUVF9lc3QgKyAxLjk2ICogQVRUX3NlCiMgQ1YgZm9yIDk5JSBpbnRlcnZhbCBpcyAyLjU3NgpjaV9sb3dlcjk5IDwtIEFUVF9lc3QgLSAyLjU3NiAqIEFUVF9zZQpjaV91cHBlcjk5IDwtIEFUVF9lc3QgKyAyLjU3NiAqIEFUVF9zZQoKcHJpbnQocGFzdGUoIkVzdGltYXRlZCBBVFQ6Iiwgcm91bmQoQVRUX2VzdCwgMikpKQpwcmludChwYXN0ZSgiU3RhbmRhcmQgRXJyb3I6Iiwgcm91bmQoQVRUX3NlLCAyKSkpCnByaW50KHBhc3RlKCI5NSUgQ0k6IFsiLCByb3VuZChjaV9sb3dlcjk1LCAzKSwgIiwiLCByb3VuZChjaV91cHBlcjk1LCAzKSwgIl0iKSkKcHJpbnQocGFzdGUoIjk5JSBDSTogWyIsIHJvdW5kKGNpX2xvd2VyOTksIDMpLCAiLCIsIHJvdW5kKGNpX3VwcGVyOTksIDMpLCAiXSIpKQpgYGAKCiMjIyBNb2RlbCBIMTogUm9zZW5iYXVtIEJvdW5kcyBTZW5zaXRpdml0eSBBbmFseXNpcwoKYGBge3J9CiMgUnVuIFNlbnNpdGl2aXR5IEFuYWx5c2lzIG9uIER1cmFiaWxpdHkgKERheXMgb2YgUGVhY2UpCiNpbnN0YWxsLnBhY2thZ2VzKCJyYm91bmRzIikKbGlicmFyeShyYm91bmRzKQoKIyBPYnRhaW4gaW5kZXhlcyBmb3IgbWF0Y2hlZCB0cmVhdG1lbnQgYW5kIGNvbnRyb2wgdW5pdHMKdHJlYXRlZF9pbmRpY2VzIDwtIG1fb3V0X0gxJGluZGV4LnRyZWF0ZWQKY29udHJvbF9pbmRpY2VzIDwtIG1fb3V0X0gxJGluZGV4LmNvbnRyb2wKCiMgRXh0cmFjdCAnRGF5cyBvZiBQZWFjZScgZm9yIGJvdGggZ3JvdXBzCmRheXNfVHIgPC0gYXMubnVtZXJpYyhkZl9jbGVhbl9IMSRkYXlzX29mX3BlYWNlW21fb3V0X0gxJGluZGV4LnRyZWF0ZWRdKQpkYXlzX0NvIDwtIGFzLm51bWVyaWMoZGZfY2xlYW5fSDEkZGF5c19vZl9wZWFjZVttX291dF9IMSRpbmRleC5jb250cm9sXSkKCiMgUC1WYWx1ZQpwc2Vuc19IMUEgPC0gcHNlbnMoeCA9IGRheXNfVHIsIAogICAgICAgICAgICAgICAgICAgeSA9IGRheXNfQ28sIAogICAgICAgICAgICAgICAgICAgR2FtbWEgPSAzLCAjIFdlIGNoZWNrIHVwIHRvIGEgInRyaXBsaW5nIiBvZiB0aGUgb2RkcyBvZiBoaWRkZW4gYmlhcwogICAgICAgICAgICAgICAgICAgR2FtbWFJbmMgPSAwLjUpICMgV2UgbW92ZSBpbiBzdGVwcyBvZiAwLjUKIyBUaGUgcHJvYmFiaWxpdHkgb2YgYXNzaWdubWVudCB0byB0cmVhdG1lbnQgdW5kZXIgaGlkZGVuIGJpYXMgR2FtbWEKIyBGb3IgVXBwZXIgQm91bmQgKHdvcnN0IGNhc2UpLCB3ZSBhc3N1bWUgYmlhcyBoZWxwcyB0aGUgb2JzZXJ2ZWQgZWZmZWN0CgojIEhvZGdlcy1MZWhtYW5uIEVzdGltYXRlIChub24tcGFyYW1ldHJpYykKaGxzZW5zX0gxQSA8LSBobHNlbnMoeCA9IGRheXNfVHIsIAogICAgICAgICAgICAgICAgICAgeSA9IGRheXNfQ28sIAogICAgICAgICAgICAgICAgICAgcHIgPSAwLjUsCiAgICAgICAgICAgICAgICAgICBHYW1tYSA9IDEwLCAKICAgICAgICAgICAgICAgICAgIEdhbW1hSW5jID0gMSkgCnBzZW5zX0gxQQojIHJlc3VsdCBpcyBvbmx5ICJtYXJnaW5hbGx5IHNpZ25pZmljYW50IiAocD0wLjA2KSBhc3N1bWluZyBubyBoaWRkZW4gYmlhcwojIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBkaXNhcHBlYXJzIHdpdGggZXZlbiBhIHRpbnkgYW1vdW50IG9mIGhpZGRlbiBiaWFzCmhsc2Vuc19IMUEKIyBtYWduaXR1ZGUgb2YgdGhlIGVmZmVjdCBwb2ludCBlc3RpbWF0ZSBpcyBxdWl0ZSByb2J1c3QKI2l0IHdvdWxkIHRha2UgYSBtYXNzaXZlIGFtb3VudCBvZiB1bm9ic2VydmVkIGJpYXMgKEdhbW1hID0gNykgdG8gcmVkdWNlIHRoZSBlc3RpbWF0ZWQgZWZmZWN0IHRvIHplcm8KIyBldmVuIGlmIHVub2JzZXJ2ZWQgZmFjdG9ycyBjYXVzZWQgbWFzc2l2ZSBzZWxlY3Rpb24gYmlhcywgdGhlIHVuZGVybHlpbmcgc2lnbmFsIHN0aWxsIHN1Z2dlc3RzIGEgcG9zaXRpdmUgZWZmZWN0IG9uIGR1cmF0aW9uCgpgYGAKCmBgYHtyfQojIFJ1biBTZW5zaXRpdml0eSBBbmFseXNpcyBvbiBEdXJhYmlsaXR5IChQZWFjZSBFbmRlZCkKCiMgT2J0YWluIGluZGV4ZXMgZm9yIG1hdGNoZWQgdHJlYXRtZW50IGFuZCBjb250cm9sIHVuaXRzCnRyZWF0ZWRfaW5kaWNlcyA8LSBtX291dF9IMSRpbmRleC50cmVhdGVkCmNvbnRyb2xfaW5kaWNlcyA8LSBtX291dF9IMSRpbmRleC5jb250cm9sCgojIDIuIEV4dHJhY3QgJ1BlYWNlIEVuZGVkJyBmb3IgYm90aCBncm91cHMKcGNfVHIgPC0gYXMubnVtZXJpYyhkZl9jbGVhbl9IMSRwY19uZFttX291dF9IMSRpbmRleC50cmVhdGVkXSkKcGNfQ28gPC0gYXMubnVtZXJpYyhkZl9jbGVhbl9IMSRwY19uZFttX291dF9IMSRpbmRleC5jb250cm9sXSkKCmRpc19UMV9DMCA8LSBzdW0ocGNfVHIgPT0gMSAmIHBjX0NvID09IDApCmRpc19UMF9DMSA8LSBzdW0ocGNfVHIgPT0gMCAmIHBjX0NvID09IDEpCgpjYXQoIkRpc2NvcmRhbnQgUGFpcnMgKFRyZWF0PTEsIENvbnQ9MCk6IiwgZGlzX1QxX0MwLCAiXG4iKQpjYXQoIkRpc2NvcmRhbnQgUGFpcnMgKFRyZWF0PTAsIENvbnQ9MSk6IiwgZGlzX1QwX0MxLCAiXG4iKQoKIyBVc2UgYmluYXJ5c2VucyB3aXRoIHRoZSBjb3VudHMKIyBHYW1tYSAzLCBzdGVwIDAuMQpiaW5hcnlzZW5zKGRpc19UMV9DMCwgZGlzX1QwX0MxLCBHYW1tYT0zLCBHYW1tYUluYz0wLjUpCgojIHVuZGVycG93ZXJlZCBkdWUgdG8gc21hbGwgbnVtYmVyIG9mIGRpc2NvcmRhbnQgcGFpcnMKCmBgYAoKIyMjIEgxOiBSb2J1c3RuZXNzIGNoZWNrCgpgYGB7ciwgTW9kZWwgUjE6IERhdGEgUHJlcGFyYXRpb259CiMgPT09PT09PT09PT09PT0gUmVtb3ZlIE5BcyBmcm9tIEFMTCBuZWNlc3NhcnkgdmFyaWFibGVzPT09PT09PT09PT09PT09PT09CgojIFNwZWNpZnkgdmFyaWFibGVzIG9mIGludGVyZXN0CnByZXRyZWF0bWVudF9jb3ZhcmlhdGVzIDwtIGMoImNvbl9kdXIiLCAiY29uX2ludCIsICJjb25faXNzIiwgIndhcl9wYXIiLCAiZ2RwIiwgImRlbSIsICJodW1fcmlnIiwgImZlbV9jb20iLCAibGVmX2lkZSIsICJmZW1fbGVnIiwgInN0YXJ0X2RhdGVfbnVtIikKdHJlYXRuZW50X3ZhciA8LSBjKCJmZW1fc2lnIikKb3V0Y29tZV92YXJzIDwtIGMoImRheXNfb2ZfcGVhY2UiLCAicGNfbmQiKQoKIyBhZGRpdGlvbmFsIGNvdmFyaWF0ZXMgZm9yIG1hdGNoaW5nICh1c2VkIGFzIGNvbnRyb2xzIGJ5IEtyYXVzZSBldCBhbC4pCmFkZF9jb3ZhcmlhdGVzIDwtIGMoInBvd19zaGEiLCAicXVvIiwgInVuX3BlYV9jb24iKSAKCmNsZWFuaW5nX3ZhcnMgPC0gYyh0cmVhdG5lbnRfdmFyLCBvdXRjb21lX3ZhcnMsIHByZXRyZWF0bWVudF9jb3ZhcmlhdGVzLCBhZGRfY292YXJpYXRlcykKCiMgQ2hlY2sgd2hpY2ggY29sdW1ucyBjb250YWluIG1pc3NpbmcgdmFsdWVzCmNvbFN1bXMoaXMubmEoZGF0YVssIGNsZWFuaW5nX3ZhcnNdKSkgCgojIENsZWFuIHRoZSBkYXRhIHRvIGVuYWJsZSBnZW5ldGljIG1hdGNoaW5nIChjYW5ub3QgaGF2ZSBOQXMpCmRmX2NsZWFuX3JiMSA8LSBuYS5vbWl0KGRhdGFbLCBjKCJjYXNfaWQiLCBjbGVhbmluZ192YXJzKV0pCmRmX2NsZWFuX3JiMQoKIyBDaGVjayBmb3IgZHJvcHBlZCB1bml0cwpjYXQoIk51bWJlciBvZiBjb250cm9sL3RyZWF0bWVudCB1bml0cyBpbiBzYW1wbGUgKGJlZm9yZSBjbGVhbmluZyk6IikKdGFibGUoZGF0YSRmZW1fc2lnKQoKY2F0KCJOdW1iZXIgb2YgY29udHJvbC90cmVhdG1lbnQgdW5pdHMgaW4gc2FtcGxlIChhZnRlciBjbGVhbmluZyk6IikKdGFibGUoZGZfY2xlYW5fcmIxJGZlbV9zaWcpCmBgYAoKYGBge3IsIE1vZGVsIFIxOiBHZW5ldGljIE1hdGNoaW5nfQpzZXQuc2VlZCgxMjMpCiMgPT09PT09PT09PT09IERFRklORSBNQVRDSElORyBPQkpFQ1RTID09PT09PT09PT09PT09PT0KCiMgVHJlYXRtZW50IApUciA8LSBkZl9jbGVhbl9yYjEkZmVtX3NpZwoKIyBNYXRjaGluZyBNYXRyaXggKFgpCm1hdGNoaW5nX3ZhcnMgPC0gYyhwcmV0cmVhdG1lbnRfY292YXJpYXRlcywgYWRkX2NvdmFyaWF0ZXMpICNpbmNsdWRlIGFkZGl0aW9uYWwgY292YXJpYXRlcwpYIDwtIGRmX2NsZWFuX3JiMVssIG1hdGNoaW5nX3ZhcnNdCgoKIyBQUkVQQVJFIENBTElQRVIgKEZvciBzdGFydF9kYXRlX251bSkKZGVzaXJlZF93aW5kb3dfZGF5cyA8LSAxODAgIzkwIGNhdXNlcyB0cmVhdG1lbnQgdW5pdHMgdG8gYmUgZHJvcHBlZApzZF9kYXRlIDwtIHNkKGRmX2NsZWFuX3JiMSRzdGFydF9kYXRlX251bSkKY2FsaXBlcl92YWx1ZSA8LSBkZXNpcmVkX3dpbmRvd19kYXlzIC8gc2RfZGF0ZQoKIyBDcmVhdGUgQ2FsaXBlciBWZWN0b3IKIyBXZSBuZWVkIGEgdmVjdG9yIG9mIEluZnMgbWF0Y2hpbmcgdGhlIG51bWJlciBvZiBjb2x1bW5zIGluIFgKY2FsaXBlcl92ZWMgPC0gcmVwKEluZiwgbmNvbChYKSkKCiMgQXBwbHkgcmVzdHJpY3Rpb24gT05MWSB0byB0aGUgZGF0ZSBjb2x1bW4KZGF0ZV9pbmRleCA8LSB3aGljaChjb2xuYW1lcyhYKSA9PSAic3RhcnRfZGF0ZV9udW0iKQpjYWxpcGVyX3ZlY1tkYXRlX2luZGV4XSA8LSBjYWxpcGVyX3ZhbHVlCgojID09PT09PT09PT09PT09PT0gUlVOIEdFTk1BVENIID09PT09PT09PT09PT09PQpnZW5vdXRfcmIxIDwtIEdlbk1hdGNoKFRyID0gVHIsIFggPSBYLCBCYWxhbmNlTWF0cml4ID0gWCwKICAgICAgICAgICAgICAgICAgIGNhbGlwZXIgPSBjYWxpcGVyX3ZlYywKICAgICAgICAgICAgICAgICAgIGVzdGltYW5kID0gIkFUVCIsIHBvcC5zaXplID0gNTAwMCwgCiAgICAgICAgICAgICAgICAgICBwcmludC5sZXZlbCA9IDApCgojID09PT09PT09PT09PT09PT0gUlVOIE1BVENIID09PT09PT09PT09PT09PT09PT0KbV9vdXRfcmIxIDwtIE1hdGNoKFRyID0gVHIsIFggPSBYLCBXZWlnaHQubWF0cml4ID0gZ2Vub3V0X3JiMSwgCiAgICAgICAgICAgICAgIGNhbGlwZXIgPSBjYWxpcGVyX3ZlYywgCiAgICAgICAgICAgICAgIGVzdGltYW5kID0gIkFUVCIpCgojID09PT09IFJlcG9ydCBTdW1tYXJ5IG9mIE1hdGNoaW5nIFJlc3VsdHMgPT09PT09CiMgQ291bnQgaG93IG1hbnkgdGltZXMgZWFjaCB0cmVhdGVkIHVuaXQgYXBwZWFycyBpbiB0aGUgbWF0Y2ggbGlzdAptYXRjaGVzX3Blcl90cmVhdGVkIDwtIHRhYmxlKG1fb3V0X3JiMSRpbmRleC50cmVhdGVkKQojIENoZWNrIHRoZSBkaXN0cmlidXRpb24gKGUuZy4sIGhvdyBtYW55IGdvdCAxIG1hdGNoLCBob3cgbWFueSBnb3QgMiwgZXRjLikKdGFibGUobWF0Y2hlc19wZXJfdHJlYXRlZCkKCiMgVG90YWwgdHJlYXRlZCB1bml0cyBpbiBvcmlnaW5hbCBkYXRhCnRvdGFsX3RyZWF0ZWQgPC0gc3VtKFRyKQoKIyBUb3RhbCB0cmVhdGVkIHVuaXRzIHRoYXQgc3VjY2Vzc2Z1bGx5IGZvdW5kIGEgbWF0Y2gKbWF0Y2hlZF90cmVhdGVkIDwtIGxlbmd0aCh1bmlxdWUobV9vdXRfcmIxJGluZGV4LnRyZWF0ZWQpKQoKY2F0KCJPcmlnaW5hbCBUcmVhdGVkOiIsIHRvdGFsX3RyZWF0ZWQsICJcbiIpCmNhdCgiTWF0Y2hlZCBUcmVhdGVkOiAiLCBtYXRjaGVkX3RyZWF0ZWQsICJcbiIpCmNhdCgiRHJvcHBlZDogICAgICAgICAiLCB0b3RhbF90cmVhdGVkIC0gbWF0Y2hlZF90cmVhdGVkLCAiXG4iKQpgYGAKCmBgYHtyLCBNb2RlbCBSMTogR2VuZXRpYyBNYXRjaGluZyBSZXN1bHRzfQojID09PT09IFJlcG9ydCBCYWxhbmNlIGFuZCBMb3dlc3QgUC1WYWx1ZSA9PT09PT0Kc2V0LnNlZWQoMTIzKQojIHRyZWF0bWVudCBpbmRpY2F0b3IgaXMgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSwgY2hlY2sgYmFsYW5jZSBmb3IgYWxsIGNvdmFyaWF0ZXMKbWJfZm9ybXVsYV9yYjEgPC0gZmVtX3NpZyB+IGNvbl9kdXIgKyBjb25faW50ICsgY29uX2lzcyArICB3YXJfcGFyICsgZ2RwICsgZGVtICsgaHVtX3JpZyArIGZlbV9sZWcgKyBmZW1fY29tICsgbGVmX2lkZSArIHN0YXJ0X2RhdGVfbnVtICsgcG93X3NoYSArIHF1byArIHVuX3BlYV9jb24KCk1hdGNoQmFsYW5jZShtYl9mb3JtdWxhX3JiMSwgZGF0YSA9IGRmX2NsZWFuX3JiMSwgbWF0Y2gub3V0ID0gbV9vdXRfcmIxLCBuYm9vdHMgPSA1MDApCmBgYAoKYGBge3IsIE1vZGVsIFIxOiBMb3ZlIFBsb3RzfQojaW5zdGFsbC5wYWNrYWdlcygiY29iYWx0IikKbGlicmFyeShjb2JhbHQpCgpsb3ZlLnBsb3QobWJfZm9ybXVsYV9yYjEsIAogICAgICAgICAgZGF0YSA9IGRmX2NsZWFuX3JiMSwgCiAgICAgICAgICB3ZWlnaHRzID0gbV9vdXRfcmIxLCAjIFVzZSB0aGUgbWF0Y2ggb2JqZWN0IGFzIHRoZSBzb3VyY2Ugb2Ygd2VpZ2h0cwogICAgICAgICAgYmluYXJ5ID0gInN0ZCIsCiAgICAgICAgICB0aHJlc2hvbGRzID0gYyhtID0gLjI1KSwKICAgICAgICAgIGFscGhhID0gMC43LAogICAgICAgICAgdGl0bGUgPSAiQ292YXJpYXRlIEJhbGFuY2UgKFNNRCkiLAogICAgICAgICAgZ3JpZCA9IFRSVUUpCgpsb3ZlLnBsb3QobWJfZm9ybXVsYV9yYjEsIAogICAgICAgICAgZGF0YSA9IGRmX2NsZWFuX3JiMSwgCiAgICAgICAgICB3ZWlnaHRzID0gbV9vdXRfcmIxLCAjIFVzZSB0aGUgbWF0Y2ggb2JqZWN0IGFzIHRoZSBzb3VyY2Ugb2Ygd2VpZ2h0cwogICAgICAgICAgc3RhdHMgPSAia3Muc3RhdGlzdGljcyIsICMgQ2hhbmdlIHRvIEtTIHN0YXRpc3RpY3MKICAgICAgICAgIGJpbmFyeSA9ICJzdGQiLAogICAgICAgICAgdGhyZXNob2xkcyA9IGMoa3MgPSAwLjEpLCAKICAgICAgICAgIGFscGhhID0gMC43LAogICAgICAgICAgZ3JpZCA9IFRSVUUsCiAgICAgICAgICB0aXRsZSA9ICJDb3ZhcmlhdGUgQmFsYW5jZSAoS1MgU3RhdGlzdGljcykiKQpgYGAKCmBgYHtyLCBNb2RlbCBSMTogQ2hlY2sgQmFsYW5jZSBTdW1tYXJ5fQpiYWwudGFiKG1iX2Zvcm11bGFfcmIxLCAKICAgICAgICBkYXRhID0gZGZfY2xlYW5fcmIxLCAKICAgICAgICB3ZWlnaHRzID0gbV9vdXRfcmIxLCAjIFVzZSB0aGUgbWF0Y2ggb2JqZWN0IGFzIHRoZSBzb3VyY2Ugb2Ygd2VpZ2h0cwogICAgICAgIGVzdGltYW5kID0gIkFUVCIsCiAgICAgICAgYmluYXJ5ID0gInN0ZCIsICAgICAgIyA8LS0tIEZvcmNlcyBiaW5hcnkgdmFycyB0byB1c2UgU01ECiAgICAgICAgY29udGludW91cyA9ICJzdGQiLCAgIyA8LS0tIEZvcmNlcyBjb250aW51b3VzIHZhcnMgKGRlZmF1bHQpIHRvIHVzZSBTTUQKICAgICAgICB1biA9IFRSVUUsCiAgICAgICAgc3RhdHMgPSBjKCJtIiwgInYiLCAia3MiKSwgICAjIE1lYW4gZGlmZnMsIFZhcmlhbmNlIHJhdGlvcywgS1Mgc3RhdHMKICAgICAgICB0aHJlc2hvbGRzID0gYyhtID0gMC4yNSwga3MgPSAwLjEpKQpgYGAKCmBgYHtyLCBNb2RlbCBSMTogTWF0Y2hCYWxhbmNlIHAtdmFsdWVzfQpzZXQuc2VlZCgxMjMpCiMgLS0tIENhbGwgRnVuY3Rpb24gLS0tCmJhbGFuY2VfdGFibGVfcmIxIDwtIGdldF9iYWxhbmNlX3RhYmxlKAogIGZvcm11bGEgPSBtYl9mb3JtdWxhX3JiMSwgCiAgZGF0YSA9IGRmX2NsZWFuX3JiMSwgCiAgbWF0Y2hfb3V0ID0gbV9vdXRfcmIxLCAKICBuYm9vdHMgPSA1MDAKKQoKYmFsYW5jZV90YWJsZV9yYjEKYGBgCgojIyMjIEgxIHZzIFIxOiBDb21wYXJpc29uIG9mIE1hdGNoaW5nIFJlc3VsdHMKCmBgYHtyLCBSb2J1c3RuZXNzIENoZWNrIEgxIHZzLiBSMTogQ29tcGFyZSBNYXRjaGluZyBSZXN1bHRzfQoKbWF0Y2hlZF9kYXRhX0gxIDwtIHJiaW5kKAogIGRmX2NsZWFuX0gxW21fb3V0X0gxJGluZGV4LnRyZWF0ZWQsIF0sCiAgZGZfY2xlYW5fSDFbbV9vdXRfSDEkaW5kZXguY29udHJvbCwgXQopCm5fcGFpcnMgPC0gbGVuZ3RoKG1fb3V0X0gxJGluZGV4LnRyZWF0ZWQpCm1hdGNoZWRfZGF0YV9IMSRwYWlyX2lkIDwtIGMoMTpuX3BhaXJzLCAxOm5fcGFpcnMpCgptYXRjaGVkX2RhdGFfcmIxIDwtIHJiaW5kKAogIGRmX2NsZWFuX3JiMVttX291dF9yYjEkaW5kZXgudHJlYXRlZCwgXSwKICBkZl9jbGVhbl9yYjFbbV9vdXRfcmIxJGluZGV4LmNvbnRyb2wsIF0KKQpuX3BhaXJzIDwtIGxlbmd0aChtX291dF9yYjEkaW5kZXgudHJlYXRlZCkKbWF0Y2hlZF9kYXRhX3JiMSRwYWlyX2lkIDwtIGMoMTpuX3BhaXJzLCAxOm5fcGFpcnMpCgptYXRjaGVzIDwtIGNiaW5kKFBhaXJfSUQgPSBtYXRjaGVkX2RhdGFfSDEkcGFpcl9pZCwgCiAgICAgICAgICAgICAgICAgVHJlYXRlZCA9IG1hdGNoZWRfZGF0YV9IMSRjYXNfaWRbbWF0Y2hlZF9kYXRhX0gxJGZlbV9zaWcgPT0gMV0sIAogICAgICAgICAgICAgICAgIE1vZGVsSDFfTWF0Y2hlcyA9IG1hdGNoZWRfZGF0YV9IMSRjYXNfaWRbbWF0Y2hlZF9kYXRhX0gxJGZlbV9zaWcgPT0gMF0sIAogICAgICAgICAgICAgICAgIE1vZGVsUjFfTWF0Y2hlcyA9IG1hdGNoZWRfZGF0YV9yYjEkY2FzX2lkW21hdGNoZWRfZGF0YV9yYjEkZmVtX3NpZyA9PSAwXSkKbWF0Y2hlc1sxOjYsIF0KCiMgQ29tcGFyZSBvdXRjb21lIG9ic2VydmF0aW9ucyBvZiBtYXRjaGVkIHVuaXRzCm1hdGNoY29tcF9kYXlzIDwtIGNiaW5kKFBhaXJfSUQgPSBtYXRjaGVkX2RhdGFfSDEkcGFpcl9pZCwKICAgICAgICAgICAgICAgICAgICAgICAgY2FzX2lkID0gbWF0Y2hlZF9kYXRhX0gxJGNhc19pZCwKICAgICAgICAgICAgICAgICAgICAgICAgZmVtX3NpZyA9IG1hdGNoZWRfZGF0YV9IMSRmZW1fc2lnLAogICAgICAgICAgICAgICAgICAgICAgICBkYXlzX29mX3BlYWNlX0gxID0gbWF0Y2hlZF9kYXRhX0gxJGRheXNfb2ZfcGVhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgIGRheXNfb2ZfcGVhY2VfcmIxID0gbWF0Y2hlZF9kYXRhX3JiMSRkYXlzX29mX3BlYWNlKQptYXRjaGNvbXBfcGMgPC0gY2JpbmQoUGFpcl9JRCA9IG1hdGNoZWRfZGF0YV9IMSRwYWlyX2lkLAogICAgICAgICAgICAgICAgICAgICAgY2FzX2lkID0gbWF0Y2hlZF9kYXRhX0gxJGNhc19pZCwKICAgICAgICAgICAgICAgICAgICAgIGZlbV9zaWcgPSBtYXRjaGVkX2RhdGFfSDEkZmVtX3NpZywKICAgICAgICAgICAgICAgICAgICAgIHBjX25kX0gxID0gbWF0Y2hlZF9kYXRhX0gxJHBjX25kLAogICAgICAgICAgICAgICAgICAgICAgcGNfbmRfcmIxID0gbWF0Y2hlZF9kYXRhX3JiMSRwY19uZCkKbWF0Y2hjb21wX2RheXMKbWF0Y2hjb21wX3BjCmBgYAoKIyMjIyBIMSB2cyBSMTogQ29tcGFyaXNvbiBvZiBUcmVhdG1lbnQgRWZmZWN0IEVzdGltYXRlcwoKYGBge3IsIE1vZGVsIFIxQTogVHJlYXRtZW50IGVmZmVjdCBlc3RpbWF0ZSAoZGF5c19vZl9wZWFjZSl9CgojID09PT09PT09IFJ1biBNYXRjaCgpIHdpdGggb3V0Y29tZSB2YXJpYWJsZSA9PT09PT09CgojIE91dGNvbWUKWSAgPC0gZGZfY2xlYW5fcmIxJGRheXNfb2ZfcGVhY2UKbV9vdXRfcmIxQSA8LSBNYXRjaChZID0gWSwgVHIgPSBUciwgWCA9IFgsIFdlaWdodC5tYXRyaXggPSBnZW5vdXRfcmIxLCAKICAgICAgICAgICAgICAgY2FsaXBlciA9IGNhbGlwZXJfdmVjLCAKICAgICAgICAgICAgICAgZXN0aW1hbmQgPSAiQVRUIikKCiMgPT09PT0gRXN0aW1hdGUgVHJlYXRtZW50IEVmZmVjdCwgU0UsIGFuZCBDSSA9PT09PT0KCnN1bW1hcnkobV9vdXRfcmIxQSkKCkFUVF9lc3QgPC0gbV9vdXRfcmIxQSRlc3QKQVRUX3NlIDwtIG1fb3V0X3JiMUEkc2UKCiMtLS0tLSBHZXQgQ29uZmlkZW5jZSBJbnRlcnZhbHMgLS0tLS0tCiMgQ0kgYm91bmRzIGdpdmVuIGJ5IHBvaW50IGVzdGltYXRlICsvLSBtYXJnaW4gb2YgZXJyb3IKIyBDViBmb3IgOTUlIGludGVydmFsIGlzIDEuOTYKY2lfbG93ZXI5NSA8LSBBVFRfZXN0IC0gMS45NiAqIEFUVF9zZQpjaV91cHBlcjk1IDwtIEFUVF9lc3QgKyAxLjk2ICogQVRUX3NlCiMgQ1YgZm9yIDk5JSBpbnRlcnZhbCBpcyAyLjU3NgpjaV9sb3dlcjk5IDwtIEFUVF9lc3QgLSAyLjU3NiAqIEFUVF9zZQpjaV91cHBlcjk5IDwtIEFUVF9lc3QgKyAyLjU3NiAqIEFUVF9zZQoKcHJpbnQocGFzdGUoIkVzdGltYXRlZCBBVFQ6Iiwgcm91bmQoQVRUX2VzdCwgNCkpKQpwcmludChwYXN0ZSgiU3RhbmRhcmQgRXJyb3I6Iiwgcm91bmQoQVRUX3NlLCA0KSkpCnByaW50KHBhc3RlKCI5NSUgQ0k6IFsiLCByb3VuZChjaV9sb3dlcjk1LCAzKSwgIiwiLCByb3VuZChjaV91cHBlcjk1LCAzKSwgIl0iKSkKcHJpbnQocGFzdGUoIjk5JSBDSTogWyIsIHJvdW5kKGNpX2xvd2VyOTksIDMpLCAiLCIsIHJvdW5kKGNpX3VwcGVyOTksIDMpLCAiXSIpKQpgYGAKCmBgYHtyLCBNb2RlbCBSMUI6IFRyZWF0bWVudCBlZmZlY3QgZXN0aW1hdGUgKHBjX25kKX0KCiMgPT09PT09PT0gUnVuIE1hdGNoKCkgd2l0aCBvdXRjb21lIHZhcmlhYmxlID09PT09PT0KIyBPdXRjb21lClkgIDwtIGRmX2NsZWFuX3JiMSRwY19uZAptX291dF9yYjFCIDwtIE1hdGNoKFkgPSBZLCBUciA9IFRyLCBYID0gWCwgV2VpZ2h0Lm1hdHJpeCA9IGdlbm91dF9yYjEsIAogICAgICAgICAgICAgICBjYWxpcGVyID0gY2FsaXBlcl92ZWMsIAogICAgICAgICAgICAgICBlc3RpbWFuZCA9ICJBVFQiKQoKIyA9PT09PSBFc3RpbWF0ZSBUcmVhdG1lbnQgRWZmZWN0LCBTRSwgYW5kIENJID09PT0KCnN1bW1hcnkobV9vdXRfcmIxQikKCkFUVF9lc3QgPC0gbV9vdXRfcmIxQiRlc3QKQVRUX3NlIDwtIG1fb3V0X3JiMUIkc2UKCiMtLS0tLSBHZXQgQ29uZmlkZW5jZSBJbnRlcnZhbHMgLS0tLS0tCiMgQ0kgYm91bmRzIGdpdmVuIGJ5IHBvaW50IGVzdGltYXRlICsvLSBtYXJnaW4gb2YgZXJyb3IKIyBDViBmb3IgOTUlIGludGVydmFsIGlzIDEuOTYKY2lfbG93ZXI5NSA8LSBBVFRfZXN0IC0gMS45NiAqIEFUVF9zZQpjaV91cHBlcjk1IDwtIEFUVF9lc3QgKyAxLjk2ICogQVRUX3NlCiMgQ1YgZm9yIDk5JSBpbnRlcnZhbCBpcyAyLjU3NgpjaV9sb3dlcjk5IDwtIEFUVF9lc3QgLSAyLjU3NiAqIEFUVF9zZQpjaV91cHBlcjk5IDwtIEFUVF9lc3QgKyAyLjU3NiAqIEFUVF9zZQoKcHJpbnQocGFzdGUoIkVzdGltYXRlZCBBVFQ6Iiwgcm91bmQoQVRUX2VzdCwgNCkpKQpwcmludChwYXN0ZSgiU3RhbmRhcmQgRXJyb3I6Iiwgcm91bmQoQVRUX3NlLCA0KSkpCnByaW50KHBhc3RlKCI5NSUgQ0k6IFsiLCByb3VuZChjaV9sb3dlcjk1LCAzKSwgIiwiLCByb3VuZChjaV91cHBlcjk1LCAzKSwgIl0iKSkKcHJpbnQocGFzdGUoIjk5JSBDSTogWyIsIHJvdW5kKGNpX2xvd2VyOTksIDMpLCAiLCIsIHJvdW5kKGNpX3VwcGVyOTksIDMpLCAiXSIpKQpgYGAKCmBgYHtyLCBSb2J1c3RuZXNzIENoZWNrIEgxIHZzLiBSMTogQ29tcGFyZSBFc3RpbWF0ZXN9CnByaW50ICgiSDFBIHZzLiBSMUEiKQpzdW1tYXJ5KG1fb3V0X0gxQSkKc3VtbWFyeShtX291dF9yYjFBKQpwcmludCAoIkgxQiB2cy4gUjFCIikKc3VtbWFyeShtX291dF9IMUIpCnN1bW1hcnkobV9vdXRfcmIxQikKYGBgCgojIyMgSHlwb3RoZXNpcyAxOiBTdXJ2aXZhbCBBbmFseXNpcwoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJzdXJ2aXZhbCIsICJzdXJ2bWluZXIiKQoKbGlicmFyeShzdXJ2aXZhbCkKbGlicmFyeShzdXJ2bWluZXIpCiMgMS4gRXh0cmFjdCBpbmRpY2VzIGZyb20gdGhlIE1hdGNoIG9iamVjdAojIGluZGV4LnRyZWF0ZWQgY29udGFpbnMgdGhlIHJvdyBudW1iZXJzIG9mIHRyZWF0ZWQgdW5pdHMKIyBpbmRleC5jb250cm9sIGNvbnRhaW5zIHRoZSByb3cgbnVtYmVycyBvZiB0aGUgbWF0Y2hlZCBjb250cm9sIHVuaXRzCm1hdGNoZXNfdHIgPC0gZGZfY2xlYW5fSDFbbV9vdXRfSDEkaW5kZXgudHJlYXRlZCwgXQptYXRjaGVzX2NvIDwtIGRmX2NsZWFuX0gxW21fb3V0X0gxJGluZGV4LmNvbnRyb2wsIF0KCiMgMi4gQ29tYmluZSB0aGVtIGludG8gYSBuZXcgbWF0Y2hlZCBkYXRhZnJhbWUKbWF0Y2hlZF9kYXRhIDwtIHJiaW5kKG1hdGNoZXNfdHIsIG1hdGNoZXNfY28pCgojIDMuIENyZWF0ZSBhICJwYWlyX2lkIiB0byBoYW5kbGUgY2x1c3RlcmluZwojIFRoaXMgaGVscHMgdGhlIG1vZGVsIHVuZGVyc3RhbmQgd2hpY2ggdHJlYXRlZCB1bml0IGdvZXMgd2l0aCB3aGljaCBjb250cm9sIHVuaXQKbWF0Y2hlZF9kYXRhJHBhaXJfaWQgPC0gcmVwKDE6bGVuZ3RoKG1fb3V0X0gxJGluZGV4LnRyZWF0ZWQpLCAyKQpgYGAKCmBgYHtyfQojIENvbnZlcnQgdGhlIHRpYmJsZSB0byBhIHN0YW5kYXJkIGRhdGEgZnJhbWUKbWF0Y2hlZF9kYXRhIDwtIGFzLmRhdGEuZnJhbWUobWF0Y2hlZF9kYXRhKQoKbWF0Y2hlZF9kYXRhJGZlbV9zaWcgPC0gYXMuZmFjdG9yKG1hdGNoZWRfZGF0YSRmZW1fc2lnKQoKIyAzLiBGaXQgdGhlIG1vZGVsIHdpdGggdGhlIFN1cnYoKSBjYWxsIElOU0lERSB0aGUgZm9ybXVsYQojIERvIG5vdCB1c2UgYW4gZXh0ZXJuYWwgJ3Nfb2JqJy4gUHV0IHRoZSB2YXJpYWJsZXMgZGlyZWN0bHkgaGVyZS4Kc19maXQgPC0gc3VydmZpdChTdXJ2KGRheXNfb2ZfcGVhY2UsIHBjX25kKSB+IGZlbV9zaWcsIGRhdGEgPSBtYXRjaGVkX2RhdGEpCgojIEthcGxhbi1NZWllciBDdXJ2ZQpnZ3N1cnZwbG90KAogIHNfZml0LAogIGRhdGEgPSBtYXRjaGVkX2RhdGEsCiAgcHZhbCA9IFRSVUUsCiAgY29uZi5pbnQgPSBUUlVFLCAKICBwYWxldHRlID0gYygiI0U3QjgwMCIsICIjMkU5RkRGIiksCiAgbGVnZW5kLmxhYnMgPSBjKCJDb250cm9sIiwgIlRyZWF0ZWQiKSwKICB0aXRsZSA9ICJFZmZlY3Qgb2YgRmVtX1NpZyBvbiBEdXJhYmlsaXR5IG9mIFBlYWNlIiwKICB4bGFiID0gIkRheXMgb2YgUGVhY2UiLAogIHlsYWIgPSAiU3Vydml2YWwgUHJvYmFiaWxpdHkiCikKCiMgVHJlYXRlZCBjdXJ2ZSAoQmx1ZSkgc3RheXMgbmVhcmx5IGZsYXQgYXQgdGhlIHRvcCAoaW5kaWNhdGluZyBoaWdoIHN1cnZpdmFsL3BlYWNlIGR1cmF0aW9uKSwgIyBDb250cm9sIGN1cnZlIChZZWxsb3cpIGRyb3BzIHN0ZWVwbHkKYGBgCgpgYGB7cn0KIyBMb2ctUmFuayBUZXN0CnN1cnZkaWZmKFN1cnYoZGF5c19vZl9wZWFjZSwgcGNfbmQpIH4gZmVtX3NpZywgZGF0YSA9IG1hdGNoZWRfZGF0YSkKCiMgQ29udHJvbCBHcm91cCAoTm8gRmVtYWxlcyk6IG9ic2VydmUgNCBwZWFjZSBmYWlsdXJlcywgYnV0IGV4cGVjdGVkIGlzIDEuOTQuIFBlYWNlIGNvbGxhcHNlZCB0d2ljZSBhcyBvZnRlbiBhcyBleHBlY3RlZC4KCiNUcmVhdGVkIEdyb3VwIChGZW1hbGVzKTogb2JzZXJ2ZSBvbmx5IDEgcGVhY2UgZmFpbHVyZSwgYnV0IGV4cGVjdGVkIDMuMDYuIFBlYWNlIGNvbGxhcHNlZCBtdWNoIGxlc3Mgb2Z0ZW4gdGhhbiBleHBlY3RlZC4KYGBgCgpgYGB7cn0KIyBGaXQgdGhlIENveCBtb2RlbAojIFdlIGNsdXN0ZXIgYnkgJ3BhaXJfaWQnIGJlY2F1c2UgdGhlIHRyZWF0ZWQgYW5kIGNvbnRyb2wgdW5pdHMgYXJlIGxpbmtlZCBieSB0aGUgbWF0Y2gKY294X21vZGVsIDwtIGNveHBoKFN1cnYoZGF5c19vZl9wZWFjZSwgcGNfbmQpIH4gZmVtX3NpZywgCiAgICAgICAgICAgICAgICAgICBkYXRhID0gbWF0Y2hlZF9kYXRhLCAKICAgICAgICAgICAgICAgICAgIGNsdXN0ZXIgPSBwYWlyX2lkKSAKCiMgVmlldyB0aGUgcmVzdWx0cwpzdW1tYXJ5KGNveF9tb2RlbCkKCiMgVGhlIHByZXNlbmNlIG9mIGZlbWFsZSBzaWduYXRvcmllcyBpcyBhc3NvY2lhdGVkIHdpdGggYSByZWR1Y2VkIHJpc2sgb2YgcGVhY2UgZmFpbHVyZS4KIyBIYXphcmQgcmF0aW86IDAuMTQ4NTogSW5jbHVkaW5nIGZlbWFsZSBzaWduYXRvcmllcyByZWR1Y2VzIHRoZSByaXNrIG9mIHRoZSBwZWFjZSBhZ3JlZW1lbnQgY29sbGFwc2luZyBieSBhcHByb3hpbWF0ZWx5IDg1JSAoMSAtIDAuMTQ4NSA9IDAuODUxNSkKCiMgcCA9IDAuMDE5IChzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IHJlc3VsdHMgYWNjb3JkaW5nIHRvIHRoZSBjb3ggbW9kZWwpCgpgYGAKCmBgYHtyfQojID09PT09IENoZWNrIHZhbGlkaXR5IG9mIG1vZGVsID09PT09PQojIFRlc3QgZm9yIFByb3BvcnRpb25hbCBIYXphcmRzIGFzc3VtcHRpb24KdGVzdF9waCA8LSBjb3guenBoKGNveF9tb2RlbCkKcHJpbnQodGVzdF9waCkKIyBTY2hvZW5mZWxkIFJlc2lkdWFscyB0ZXN0OiBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRpbWUgYW5kIHRoZSByZXNpZHVhbHMKIyBOdWxsIEh5cDogaGF6YXJkcyBhcmUgcHJvcG9ydGlvbmFsIGFuZCBlZmZlY3QgaXMgY29uc3RhbnQKIyBsYXJnZSBwIHZhbHVlIGluZGljYXRlcyBubyBldmlkZW5jZSB0aGF0IGFzc3VtcHRpb25zIGFyZSB2aW9sYXRlZAoKCiMgUGxvdCB0aGUgU2Nob2VuZmVsZCByZXNpZHVhbHMKZ2djb3h6cGgodGVzdF9waCkKCiMgY2hlY2sgdGhhdCBlZmZlY3Qgb2YgdGhlIHRyZWF0bWVudCBpcyBjb25zdGFudCBvdmVyIHRpbWUKIyBFZmZlY3Qgc2l6ZSByZW1haW5zIHJlbGF0aXZlbHkgc3RhYmxlIG92ZXIgdGltZQoKYGBgCgojIyMjIHNlbnNtYWtlciBTZW5zaXRpdml0eSBUZXN0IGZvciBTdXJ2aXZhbCBBbmFseXNpcwoKYGBge3J9CmxpYnJhcnkoc2Vuc2VtYWtyKQojIDEuIEZpdCBhIHNpbXBsZSBsaW5lYXIgbW9kZWwgb24gdGhlIG1hdGNoZWQgZGF0YQojIChSZWdyZXNzaW5nIE91dGNvbWUgfiBUcmVhdG1lbnQpCmRheXNfbW9kZWwgPC0gbG0oZGF5c19vZl9wZWFjZSB+IGZlbV9zaWcsIGRhdGEgPSBkZl9jbGVhbl9IMSkKCiMgMi4gUnVuIFNlbnNlbWFrcgojIENoZWNrcyBob3cgc3Ryb25nIGhpZGRlbiBiaWFzIG11c3QgYmUgdG8gZXhwbGFpbiBhd2F5IHRoZSBlZmZlY3Qgc2l6ZQpzZW5zaXRpdml0eSA8LSBzZW5zZW1ha3IobW9kZWwgPSBkYXlzX21vZGVsLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0bWVudCA9ICJmZW1fc2lnIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGtkID0gMTozKSAjIENoZWNrIGJpYXMgMXgsIDJ4LCAzeCBhcyBzdHJvbmcKCiMgMy4gUGxvdCBhbmQgU3VtbWFyeQpwbG90KHNlbnNpdGl2aXR5KQpzdW1tYXJ5KHNlbnNpdGl2aXR5KQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHNlbnNlbWFrcikKIyAxLiBGaXQgYSBzaW1wbGUgbGluZWFyIG1vZGVsIG9uIHRoZSBtYXRjaGVkIGRhdGEKIyAoUmVncmVzc2luZyBPdXRjb21lIH4gVHJlYXRtZW50KQpwY19tb2RlbCA8LSBsbShwY19uZCB+IGZlbV9zaWcsIGRhdGEgPSBkZl9jbGVhbl9IMSkKCiMgMi4gUnVuIFNlbnNlbWFrcgojIENoZWNrcyBob3cgc3Ryb25nIGhpZGRlbiBiaWFzIG11c3QgYmUgdG8gZXhwbGFpbiBhd2F5IHRoZSBlZmZlY3Qgc2l6ZQpzZW5zaXRpdml0eSA8LSBzZW5zZW1ha3IobW9kZWwgPSBwY19tb2RlbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmVhdG1lbnQgPSAiZmVtX3NpZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBrZCA9IDE6MykgIyBDaGVjayBiaWFzIDF4LCAyeCwgM3ggYXMgc3Ryb25nCgojIDMuIFBsb3QgYW5kIFN1bW1hcnkKcGxvdChzZW5zaXRpdml0eSkKc3VtbWFyeShzZW5zaXRpdml0eSkKYGBgCgojIyBIeXBvdGhlc2lzIDI6IFdvbWVuIHBhcnRpY2lwYXRpb24gYW5kIHF1YWxpdHkgb2YgcGVhY2UgYWdyZWVtZW50IChjb250ZW50KQoKYGBge3IsIE1vZGVsIEgyOiBEYXRhIFByZXBhcmF0aW9ufQoKIyA9PT09PT09PT09PT0gUmVtb3ZlIE5BcyBmcm9tIEFMTCBuZWNlc3NhcnkgdmFyaWFibGVzID09PT09PT09PT09PT0KCnRyZWF0bmVudF92YXIgPC0gYygiZmVtX3NpZyIpCm91dGNvbWVfdmFycyA8LSBjKCJjcGEiLCAiY2l2X3NvYyIpCnByZXRyZWF0bWVudF9jb3ZhcmlhdGVzIDwtIGMoImNvbl9kdXIiLCAiY29uX2ludCIsICJjb25faXNzIiwgIndhcl9wYXIiLCAiZ2RwIiwgImRlbSIsICJodW1fcmlnIiwgImZlbV9jb20iLCAibGVmX2lkZSIsICJmZW1fbGVnIiwgInN0YXJ0X2RhdGVfbnVtIikgCgpjbGVhbmluZ192YXJzIDwtIGModHJlYXRuZW50X3Zhciwgb3V0Y29tZV92YXJzLCBwcmV0cmVhdG1lbnRfY292YXJpYXRlcykKCiMgQ2hlY2sgd2hpY2ggY29sdW1ucyBjb250YWluIG1pc3NpbmcgdmFsdWVzCmNvbFN1bXMoaXMubmEoZGF0YVssIGNsZWFuaW5nX3ZhcnNdKSkgCgojIENsZWFuIHRoZSBkYXRhIHRvIGVuYWJsZSBnZW5ldGljIG1hdGNoaW5nIChjYW5ub3QgaGF2ZSBOQXMpCmRmX2NsZWFuX0gyIDwtIG5hLm9taXQoZGF0YVssIGMoImNhc19pZCIsIGNsZWFuaW5nX3ZhcnMpXSkKZGZfY2xlYW5fSDIKCiNDaGVjayBob3cgbWFueSByb3dzIGhhdmUgYmVlbiBkcm9wcGVkCmNhdCgiTnVtYmVyIG9mIGNvbnRyb2wvdHJlYXRtZW50IHVuaXRzIGluIHNhbXBsZSAoYmVmb3JlIGNsZWFuaW5nKToiKQp0YWJsZShkYXRhJGZlbV9zaWcpCgpjYXQoIk51bWJlciBvZiBjb250cm9sL3RyZWF0bWVudCB1bml0cyBpbiBzYW1wbGUgKGFmdGVyIGNsZWFuaW5nKToiKQp0YWJsZShkZl9jbGVhbl9IMiRmZW1fc2lnKQpgYGAKCmBgYHtyLCBNb2RlbCBIMjogR2VuZXRpYyBNYXRjaGluZ30Kc2V0LnNlZWQoMTIzKQoKIyA9PT09PT09PT09PT09PSBERUZJTkUgTUFUQ0hJTkcgT0JKRUNUUyA9PT09PT09PT09PT09CiMgVHJlYXRtZW50IApUciA8LSBkZl9jbGVhbl9IMiRmZW1fc2lnCgojIE1hdGNoaW5nIE1hdHJpeCAoWCkKbWF0Y2hpbmdfdmFycyA8LSBwcmV0cmVhdG1lbnRfY292YXJpYXRlcwpYIDwtIGRmX2NsZWFuX0gyWywgbWF0Y2hpbmdfdmFyc10KIyBkbyBub3QgaW5jbHVkZSBvdXRjb21lcwoKIyA9PT09PT09PT09PT09IFJVTiBHRU5NQVRDSCA9PT09PT09PT09PT09PT0KCmdlbm91dF9IMiA8LSBHZW5NYXRjaChUciA9IFRyLCBYID0gWCwgQmFsYW5jZU1hdHJpeCA9IFgsIAogICAgICAgICAgICAgICAgICAgZXN0aW1hbmQgPSAiQVRUIiwgcG9wLnNpemUgPSA1MDAwLCAKICAgICAgICAgICAgICAgICAgIHJlcGxhY2U9RkFMU0UsCiAgICAgICAgICAgICAgICAgICBwcmludC5sZXZlbCA9IDApCgojID09PT09PT09PT09PT0gUlVOIE1BVENIID09PT09PT09PT09PT09PQoKbV9vdXRfSDIgPC0gTWF0Y2goVHIgPSBUciwgWCA9IFgsIFdlaWdodC5tYXRyaXggPSBnZW5vdXRfSDIsIAogICAgICAgICAgICAgICAgICBlc3RpbWFuZCA9ICJBVFQiLAogICAgICAgICAgICAgICAgICByZXBsYWNlPUZBTFNFKQoKCiMgPT09PT0gUmVwb3J0IG9uIG1hdGNoaW5nIHN1bW1hcnkgPT09PT09CgojIENvdW50IGhvdyBtYW55IHRpbWVzIGVhY2ggdHJlYXRlZCB1bml0IGFwcGVhcnMgaW4gdGhlIG1hdGNoIGxpc3QKbWF0Y2hlc19wZXJfdHJlYXRlZCA8LSB0YWJsZShtX291dF9IMiRpbmRleC50cmVhdGVkKQojIENoZWNrIHRoZSBkaXN0cmlidXRpb24gKGUuZy4sIGhvdyBtYW55IGdvdCAxIG1hdGNoLCBob3cgbWFueSBnb3QgMiwgZXRjLikKdGFibGUobWF0Y2hlc19wZXJfdHJlYXRlZCkKCiMgVG90YWwgdHJlYXRlZCB1bml0cyBpbiBvcmlnaW5hbCBkYXRhCnRvdGFsX3RyZWF0ZWQgPC0gc3VtKFRyKQoKIyBUb3RhbCB0cmVhdGVkIHVuaXRzIHRoYXQgc3VjY2Vzc2Z1bGx5IGZvdW5kIGEgbWF0Y2gKbWF0Y2hlZF90cmVhdGVkIDwtIGxlbmd0aCh1bmlxdWUobV9vdXRfSDIkaW5kZXgudHJlYXRlZCkpICNhbGwgdHJlYXRlZCB1bml0cyBoYXZlIGJlZW4gbWF0Y2hlZAoKY2F0KCJPcmlnaW5hbCBUcmVhdGVkOiIsIHRvdGFsX3RyZWF0ZWQsICJcbiIpCmNhdCgiTWF0Y2hlZCBUcmVhdGVkOiAiLCBtYXRjaGVkX3RyZWF0ZWQsICJcbiIpCmNhdCgiRHJvcHBlZDogICAgICAgICAiLCB0b3RhbF90cmVhdGVkIC0gbWF0Y2hlZF90cmVhdGVkLCAiXG4iKQoKYGBgCgpgYGB7ciwgTW9kZWwgSDI6IE1hdGNoQmFsYW5jZSBSZXN1bHRzfQoKIyA9PT09PSBSZXBvcnQgQmFsYW5jZSBhbmQgTG93ZXN0IFAtVmFsdWUgPT09PT09CnNldC5zZWVkKDEyMykKIyB0cmVhdG1lbnQgaW5kaWNhdG9yIGlzIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUsIGNoZWNrIGJhbGFuY2UgZm9yIGFsbCBjb3ZhcmlhdGVzCm1iX2Zvcm11bGFfSDIgPC0gZmVtX3NpZyB+IGNvbl9kdXIgKyBjb25faW50ICsgY29uX2lzcyArICB3YXJfcGFyICsgZ2RwICsgZGVtICsgaHVtX3JpZyArIGZlbV9sZWcgKyBmZW1fY29tICsgbGVmX2lkZSArIHN0YXJ0X2RhdGVfbnVtCgpNYXRjaEJhbGFuY2UobWJfZm9ybXVsYV9IMiwgZGF0YSA9IGRmX2NsZWFuX0gyLCBtYXRjaC5vdXQgPSBtX291dF9IMiwgbmJvb3RzID0gNTAwKQpgYGAKCmBgYHtyLCBNb2RlbCBIMjogTG92ZSBQbG90c30KCiNpbnN0YWxsLnBhY2thZ2VzKCJjb2JhbHQiKQpsaWJyYXJ5KGNvYmFsdCkKCmxvdmUucGxvdChtYl9mb3JtdWxhX0gyLCAKICAgICAgICAgIGRhdGEgPSBkZl9jbGVhbl9IMiwgCiAgICAgICAgICB3ZWlnaHRzID0gbV9vdXRfSDIsICMgVXNlIHRoZSBtYXRjaCBvYmplY3QgYXMgdGhlIHNvdXJjZSBvZiB3ZWlnaHRzCiAgICAgICAgICBiaW5hcnkgPSAic3RkIiwKICAgICAgICAgIHRocmVzaG9sZHMgPSBjKG0gPSAuMjUpLAogICAgICAgICAgYWxwaGEgPSAwLjcsCiAgICAgICAgICB0aXRsZSA9ICJDb3ZhcmlhdGUgQmFsYW5jZSAoU01EKSIsCiAgICAgICAgICBncmlkID0gVFJVRSkKCmxvdmUucGxvdChtYl9mb3JtdWxhX0gyLCAKICAgICAgICAgIGRhdGEgPSBkZl9jbGVhbl9IMiwgCiAgICAgICAgICB3ZWlnaHRzID0gbV9vdXRfSDIsICMgVXNlIHRoZSBtYXRjaCBvYmplY3QgYXMgdGhlIHNvdXJjZSBvZiB3ZWlnaHRzCiAgICAgICAgICBzdGF0cyA9ICJrcy5zdGF0aXN0aWNzIiwgIyBDaGFuZ2UgdG8gS1Mgc3RhdGlzdGljcwogICAgICAgICAgYmluYXJ5ID0gInN0ZCIsCiAgICAgICAgICB0aHJlc2hvbGRzID0gYyhrcyA9IDAuMSksIAogICAgICAgICAgYWxwaGEgPSAwLjcsCiAgICAgICAgICBncmlkID0gVFJVRSwKICAgICAgICAgIHRpdGxlID0gIkNvdmFyaWF0ZSBCYWxhbmNlIChLUyBTdGF0aXN0aWNzKSIpCmBgYAoKYGBge3IsIE1vZGVsIEgyOiBDaGVjayBCYWxhbmNlIFN1bW1hcnl9CmJhbC50YWIobWJfZm9ybXVsYV9IMiwgCiAgICAgICAgZGF0YSA9IGRmX2NsZWFuX0gyLCAKICAgICAgICB3ZWlnaHRzID0gbV9vdXRfSDIsICMgVXNlIHRoZSBtYXRjaCBvYmplY3QgYXMgdGhlIHNvdXJjZSBvZiB3ZWlnaHRzCiAgICAgICAgZXN0aW1hbmQgPSAiQVRUIiwKICAgICAgICBiaW5hcnkgPSAic3RkIiwgICAgICAjIDwtLS0gRm9yY2VzIGJpbmFyeSB2YXJzIHRvIHVzZSBTTUQKICAgICAgICBjb250aW51b3VzID0gInN0ZCIsICAjIDwtLS0gRm9yY2VzIGNvbnRpbnVvdXMgdmFycyAoZGVmYXVsdCkgdG8gdXNlIFNNRAogICAgICAgIHVuID0gVFJVRSwKICAgICAgICBzdGF0cyA9IGMoIm0iLCAidiIsICJrcyIpLCAgICMgTWVhbiBkaWZmcywgVmFyaWFuY2UgcmF0aW9zLCBLUyBzdGF0cwogICAgICAgIHRocmVzaG9sZHMgPSBjKG0gPSAwLjI1LCBrcyA9IDAuMSkpCmBgYAoKYGBge3IsIE1vZGVsIEgyOiBNYXRjaEJhbGFuY2UgcC12YWx1ZXN9CnNldC5zZWVkKDEyMykKIyAtLS0gQ2FsbCBGdW5jdGlvbiAtLS0KYmFsYW5jZV90YWJsZV9IMiA8LSBnZXRfYmFsYW5jZV90YWJsZSgKICBmb3JtdWxhID0gbWJfZm9ybXVsYV9IMiwgCiAgZGF0YSA9IGRmX2NsZWFuX0gyLCAKICBtYXRjaF9vdXQgPSBtX291dF9IMiwgCiAgbmJvb3RzID0gNTAwCikKCmJhbGFuY2VfdGFibGVfSDIKYGBgCgojIyMgSHlwb3RoZXNpcyAyQTogZmVtX3NpZyBvbiBjcGEKCmBgYHtyLCBNb2RlbCBIMkE6IFRyZWF0bWVudCBlZmZlY3QgZXN0aW1hdGUgKGNwYSl9CnNldC5zZWVkKDEyMykKCiMgPT09PT09PT09PSBSdW4gTWF0Y2goKSB3aXRoIG91dGNvbWUgdmFyaWFibGUgPT09PT09PQoKWSAgPC0gZGZfY2xlYW5fSDIkY3BhICMgT3V0Y29tZQptX291dF9IMkEgPC0gTWF0Y2goWSA9IFksIFRyID0gVHIsIFggPSBYLCBXZWlnaHQubWF0cml4ID0gZ2Vub3V0X0gyLCBlc3RpbWFuZCA9ICJBVFQiKQoKIyA9PT09PSBFc3RpbWF0ZSBUcmVhdG1lbnQgRWZmZWN0LCBTRSwgYW5kIENJID09PT09PQpzdW1tYXJ5KG1fb3V0X0gyQSkKCkFUVF9lc3QgPC0gbV9vdXRfSDJBJGVzdApBVFRfc2UgPC0gbV9vdXRfSDJBJHNlCgojLS0tLS0gR2V0IENvbmZpZGVuY2UgSW50ZXJ2YWxzIC0tLS0tLQojIENJIGJvdW5kcyBnaXZlbiBieSBwb2ludCBlc3RpbWF0ZSArLy0gbWFyZ2luIG9mIGVycm9yCiMgQ1YgZm9yIDk1JSBpbnRlcnZhbCBpcyAxLjk2CmNpX2xvd2VyOTUgPC0gQVRUX2VzdCAtIDEuOTYgKiBBVFRfc2UKY2lfdXBwZXI5NSA8LSBBVFRfZXN0ICsgMS45NiAqIEFUVF9zZQojIENWIGZvciA5OSUgaW50ZXJ2YWwgaXMgMi41NzYKY2lfbG93ZXI5OSA8LSBBVFRfZXN0IC0gMi41NzYgKiBBVFRfc2UKY2lfdXBwZXI5OSA8LSBBVFRfZXN0ICsgMi41NzYgKiBBVFRfc2UKCnByaW50KHBhc3RlKCJFc3RpbWF0ZWQgQVRUOiIsIHJvdW5kKEFUVF9lc3QsIDQpKSkKcHJpbnQocGFzdGUoIlN0YW5kYXJkIEVycm9yOiIsIHJvdW5kKEFUVF9zZSwgNCkpKQpwcmludChwYXN0ZSgiOTUlIENJOiBbIiwgcm91bmQoY2lfbG93ZXI5NSwgMyksICIsIiwgcm91bmQoY2lfdXBwZXI5NSwgMyksICJdIikpCnByaW50KHBhc3RlKCI5OSUgQ0k6IFsiLCByb3VuZChjaV9sb3dlcjk5LCAzKSwgIiwiLCByb3VuZChjaV91cHBlcjk5LCAzKSwgIl0iKSkKYGBgCgojIyMgSHlwb3RoZXNpcyAyQjogZmVtX3NpZyBvbiBjaXZfc29jCgpgYGB7ciwgTW9kZWwgSDJBOiBUcmVhdG1lbnQgZWZmZWN0IGVzdGltYXRlIChjaXZfc29jKX0KCnNldC5zZWVkKDEyMykKIyA9PT09PT09PT09IFJ1biBNYXRjaCgpIHdpdGggb3V0Y29tZSB2YXJpYWJsZSA9PT09PT09CgpZICA8LSBkZl9jbGVhbl9IMiRjaXZfc29jICMgT3V0Y29tZQptX291dF9IMkIgPC0gTWF0Y2goWSA9IFksIFRyID0gVHIsIFggPSBYLCBXZWlnaHQubWF0cml4ID0gZ2Vub3V0X0gyLCBlc3RpbWFuZCA9ICJBVFQiKQoKCiMgPT09PT0gRXN0aW1hdGUgVHJlYXRtZW50IEVmZmVjdCwgU0UsIGFuZCBDSSA9PT09PT0Kc3VtbWFyeShtX291dF9IMkIpCgpBVFRfZXN0IDwtIG1fb3V0X0gyQiRlc3QKQVRUX3NlIDwtIG1fb3V0X0gyQiRzZQoKIy0tLS0tIEdldCBDb25maWRlbmNlIEludGVydmFscyAtLS0tLS0KIyBDSSBib3VuZHMgZ2l2ZW4gYnkgcG9pbnQgZXN0aW1hdGUgKy8tIG1hcmdpbiBvZiBlcnJvcgojIENWIGZvciA5NSUgaW50ZXJ2YWwgaXMgMS45NgpjaV9sb3dlcjk1IDwtIEFUVF9lc3QgLSAxLjk2ICogQVRUX3NlCmNpX3VwcGVyOTUgPC0gQVRUX2VzdCArIDEuOTYgKiBBVFRfc2UKIyBDViBmb3IgOTklIGludGVydmFsIGlzIDIuNTc2CmNpX2xvd2VyOTkgPC0gQVRUX2VzdCAtIDIuNTc2ICogQVRUX3NlCmNpX3VwcGVyOTkgPC0gQVRUX2VzdCArIDIuNTc2ICogQVRUX3NlCgpwcmludChwYXN0ZSgiRXN0aW1hdGVkIEFUVDoiLCByb3VuZChBVFRfZXN0LCAyKSkpCnByaW50KHBhc3RlKCJTdGFuZGFyZCBFcnJvcjoiLCByb3VuZChBVFRfc2UsIDIpKSkKcHJpbnQocGFzdGUoIjk1JSBDSTogWyIsIHJvdW5kKGNpX2xvd2VyOTUsIDMpLCAiLCIsIHJvdW5kKGNpX3VwcGVyOTUsIDMpLCAiXSIpKQpwcmludChwYXN0ZSgiOTklIENJOiBbIiwgcm91bmQoY2lfbG93ZXI5OSwgMyksICIsIiwgcm91bmQoY2lfdXBwZXI5OSwgMyksICJdIikpCgpgYGAKCiMjIyBNb2RlbCBIMjogUm9zZW5iYXVtIEJvdW5kcyBTZW5zaXRpdml0eSBBbmFseXNpcwoKYGBge3J9CiMgUnVuIFNlbnNpdGl2aXR5IEFuYWx5c2lzIG9uIEFncmVlbWVudCBRdWFsaXR5IChjcGEpCgojIE9idGFpbiBpbmRleGVzIGZvciBtYXRjaGVkIHRyZWF0bWVudCBhbmQgY29udHJvbCB1bml0cwp0cmVhdGVkX2luZGljZXMgPC0gbV9vdXRfSDIkaW5kZXgudHJlYXRlZApjb250cm9sX2luZGljZXMgPC0gbV9vdXRfSDIkaW5kZXguY29udHJvbAoKIyAyLiBFeHRyYWN0ICdQZWFjZSBFbmRlZCcgZm9yIGJvdGggZ3JvdXBzCmNwYV9UciA8LSBhcy5udW1lcmljKGRmX2NsZWFuX0gyJGNwYVttX291dF9IMiRpbmRleC50cmVhdGVkXSkKY3BhX0NvIDwtIGFzLm51bWVyaWMoZGZfY2xlYW5fSDIkY3BhW21fb3V0X0gyJGluZGV4LmNvbnRyb2xdKQoKZGlzX1QxX0MwIDwtIHN1bShjcGFfVHIgPT0gMSAmIGNwYV9DbyA9PSAwKQpkaXNfVDBfQzEgPC0gc3VtKGNwYV9UciA9PSAwICYgY3BhX0NvID09IDEpCgpjYXQoIkRpc2NvcmRhbnQgUGFpcnMgKFRyZWF0PTEsIENvbnQ9MCk6IiwgZGlzX1QxX0MwLCAiXG4iKQpjYXQoIkRpc2NvcmRhbnQgUGFpcnMgKFRyZWF0PTAsIENvbnQ9MSk6IiwgZGlzX1QwX0MxLCAiXG4iKQoKIyBVc2UgYmluYXJ5c2VucyB3aXRoIHRoZSBjb3VudHMKIyBHYW1tYSAzLCBzdGVwIDAuMQpiaW5hcnlzZW5zKGRpc19UMV9DMCwgZGlzX1QwX0MxLCBHYW1tYT0zLCBHYW1tYUluYz0wLjUpCgojIHVuZGVycG93ZXJlZCBkdWUgdG8gc21hbGwgbnVtYmVyIG9mIGRpc2NvcmRhbnQgcGFpcnMKIyBtYW55IG1hdGNoZXMgYW5kIHNtYWxsIHNhbXBsZSBzaXplCmBgYAoKYGBge3J9CiMgUnVuIFNlbnNpdGl2aXR5IEFuYWx5c2lzIG9uIEFncmVlbWVudCBRdWFsaXR5IChjaXZfc29jKQoKIyBPYnRhaW4gaW5kZXhlcyBmb3IgbWF0Y2hlZCB0cmVhdG1lbnQgYW5kIGNvbnRyb2wgdW5pdHMKdHJlYXRlZF9pbmRpY2VzIDwtIG1fb3V0X0gyJGluZGV4LnRyZWF0ZWQKY29udHJvbF9pbmRpY2VzIDwtIG1fb3V0X0gyJGluZGV4LmNvbnRyb2wKCiMgMi4gRXh0cmFjdCAnUGVhY2UgRW5kZWQnIGZvciBib3RoIGdyb3VwcwpjaXZfc29jX1RyIDwtIGFzLm51bWVyaWMoZGZfY2xlYW5fSDIkY2l2X3NvY1ttX291dF9IMiRpbmRleC50cmVhdGVkXSkKY2l2X3NvY19DbyA8LSBhcy5udW1lcmljKGRmX2NsZWFuX0gyJGNpdl9zb2NbbV9vdXRfSDIkaW5kZXguY29udHJvbF0pCgpkaXNfVDFfQzAgPC0gc3VtKGNpdl9zb2NfVHIgPT0gMSAmIGNpdl9zb2NfQ28gPT0gMCkKZGlzX1QwX0MxIDwtIHN1bShjaXZfc29jX1RyID09IDAgJiBjaXZfc29jX0NvID09IDEpCgpjYXQoIkRpc2NvcmRhbnQgUGFpcnMgKFRyZWF0PTEsIENvbnQ9MCk6IiwgZGlzX1QxX0MwLCAiXG4iKQpjYXQoIkRpc2NvcmRhbnQgUGFpcnMgKFRyZWF0PTAsIENvbnQ9MSk6IiwgZGlzX1QwX0MxLCAiXG4iKQoKIyBVc2UgYmluYXJ5c2VucyB3aXRoIHRoZSBjb3VudHMKIyBHYW1tYSAzLCBzdGVwIDAuMQpiaW5hcnlzZW5zKGRpc19UMV9DMCwgZGlzX1QwX0MxLCBHYW1tYT0zLCBHYW1tYUluYz0wLjUpCgojIHVuZGVycG93ZXJlZCBkdWUgdG8gc21hbGwgbnVtYmVyIG9mIGRpc2NvcmRhbnQgcGFpcnMKIyBtYW55IG1hdGNoZXMgYW5kIHNtYWxsIHNhbXBsZSBzaXplCmBgYAoKIyMjIFJvYnVzdG5lc3MgQ2hlY2sKCmBgYHtyLCBNb2RlbCBSMjogRGF0YSBQcmVwYXJhdGlvbn0KIyA9PT09PT09PT09PT0gUmVtb3ZlIE5BcyBmcm9tIEFMTCBuZWNlc3NhcnkgdmFyaWFibGVzID09PT09PT09PT09PT0KCiMgQ2hlY2sgd2hpY2ggY29sdW1ucyBjb250YWluIG1pc3NpbmcgdmFsdWVzCmNvbFN1bXMoaXMubmEoZGF0YVssIGNsZWFuaW5nX3ZhcnNdKSkgCgojIENsZWFuIHRoZSBkYXRhIHRvIGVuYWJsZSBnZW5ldGljIG1hdGNoaW5nIChjYW5ub3QgaGF2ZSBOQXMpCnByZXRyZWF0bWVudF9jb3ZhcmlhdGVzIDwtIGMoImNvbl9kdXIiLCAiY29uX2ludCIsICJjb25faXNzIiwgIndhcl9wYXIiLCAiZ2RwIiwgImRlbSIsICJodW1fcmlnIiwgImZlbV9jb20iLCAibGVmX2lkZSIsICJmZW1fbGVnIiwgInN0YXJ0X2RhdGVfbnVtIikKdHJlYXRuZW50X3ZhciA8LSBjKCJmZW1fc2lnIikKb3V0Y29tZV92YXJzIDwtIGMoImNwYSIsICJjaXZfc29jIikKCmFkZF9jb3ZhcmlhdGVzIDwtIGMoInBvd19zaGEiLCAicXVvIiwgInVuX3BlYV9jb24iKSAjIGFkZGl0aW9uYWwgY292YXJpYXRlcwoKIyBUaGlzIGxpc3QgaW5jbHVkZXMgWSwgVHIsIGFuZCBYLiBXZSB1c2UgaXQgT05MWSBmb3IgbmEub21pdC4KY2xlYW5pbmdfdmFycyA8LSBjKHRyZWF0bmVudF92YXIsIG91dGNvbWVfdmFycywgcHJldHJlYXRtZW50X2NvdmFyaWF0ZXMsIGFkZF9jb3ZhcmlhdGVzKQoKZGZfY2xlYW5fcmIyIDwtIG5hLm9taXQoZGF0YVssIGMoImNhc19pZCIsIGNsZWFuaW5nX3ZhcnMpXSkKZGZfY2xlYW5fcmIyCgojIENoZWNrIGhvdyBtYW55IHJvd3MgaGF2ZSBiZWVuIGRyb3BwZWQKY2F0KCJOdW1iZXIgb2YgY29udHJvbC90cmVhdG1lbnQgdW5pdHMgaW4gc2FtcGxlIChiZWZvcmUgY2xlYW5pbmcpOiIpCnRhYmxlKGRhdGEkZmVtX3NpZykKY2F0KCJOdW1iZXIgb2YgY29udHJvbC90cmVhdG1lbnQgdW5pdHMgaW4gc2FtcGxlIChhZnRlciBjbGVhbmluZyk6IikKdGFibGUoZGZfY2xlYW5fcmIyJGZlbV9zaWcpCgpgYGAKCmBgYHtyLCBNb2RlbCBSMjogR2VuZXRpYyBNYXRjaGluZ30KIyA9PT09PT09PT09IERFRklORSBNQVRDSElORyBPQkpFQ1RTID09PT09PT09PT09PT09PQoKc2V0LnNlZWQoMTIzKQoKIyBUcmVhdG1lbnQgClRyIDwtIGRmX2NsZWFuX3JiMiRmZW1fc2lnCgojIE1hdGNoaW5nIE1hdHJpeCAoWCkKbWF0Y2hpbmdfdmFycyA8LSBjKHByZXRyZWF0bWVudF9jb3ZhcmlhdGVzLCBhZGRfY292YXJpYXRlcykgIyBpbmNsdWRlIGFkZGl0aW9uYWwgY292YXJpYXRlcwpYIDwtIGRmX2NsZWFuX3JiMlssIG1hdGNoaW5nX3ZhcnNdCgojID09PT09PT09PT09IFJVTiBHRU5NQVRDSCA9PT09PT09PT09PT09PT09PQoKZ2Vub3V0X3JiMiA8LSBHZW5NYXRjaChUciA9IFRyLCBYID0gWCwgQmFsYW5jZU1hdHJpeCA9IFgsCiAgICAgICAgICAgICAgICAgICByZXBsYWNlPUZBTFNFLCAKICAgICAgICAgICAgICAgICAgIGVzdGltYW5kID0gIkFUVCIsIHBvcC5zaXplID0gNTAwMCwgCiAgICAgICAgICAgICAgICAgICBwcmludC5sZXZlbCA9IDApCgojID09PT09PT09PT09PT09PSBSVU4gTUFUQ0ggPT09PT09PT09PT09PT09CgptX291dF9yYjIgPC0gTWF0Y2goVHIgPSBUciwgWCA9IFgsIFdlaWdodC5tYXRyaXggPSBnZW5vdXRfcmIyLCBlc3RpbWFuZCA9ICJBVFQiLCByZXBsYWNlPUZBTFNFKQoKCiMgPT09PT09PT09PSBSZXBvcnQgb24gbWF0Y2hpbmcgc3VtbWFyeSA9PT09PT09PT0KIyBDb3VudCBob3cgbWFueSB0aW1lcyBlYWNoIHRyZWF0ZWQgdW5pdCBhcHBlYXJzIGluIHRoZSBtYXRjaCBsaXN0Cm1hdGNoZXNfcGVyX3RyZWF0ZWQgPC0gdGFibGUobV9vdXRfcmIyICRpbmRleC50cmVhdGVkKQojIENoZWNrIHRoZSBkaXN0cmlidXRpb24gKGUuZy4sIGhvdyBtYW55IGdvdCAxIG1hdGNoLCBob3cgbWFueSBnb3QgMiwgZXRjLikKdGFibGUobWF0Y2hlc19wZXJfdHJlYXRlZCkKCiMgVG90YWwgdHJlYXRlZCB1bml0cyBpbiBvcmlnaW5hbCBkYXRhCnRvdGFsX3RyZWF0ZWQgPC0gc3VtKFRyKQoKIyBUb3RhbCB0cmVhdGVkIHVuaXRzIHRoYXQgc3VjY2Vzc2Z1bGx5IGZvdW5kIGEgbWF0Y2gKbWF0Y2hlZF90cmVhdGVkIDwtIGxlbmd0aCh1bmlxdWUobV9vdXRfcmIyICRpbmRleC50cmVhdGVkKSkgI2FsbCB0cmVhdGVkIHVuaXRzIGhhdmUgYmVlbiBtYXRjaGVkCgpjYXQoIk9yaWdpbmFsIFRyZWF0ZWQ6IiwgdG90YWxfdHJlYXRlZCwgIlxuIikKY2F0KCJNYXRjaGVkIFRyZWF0ZWQ6ICIsIG1hdGNoZWRfdHJlYXRlZCwgIlxuIikKY2F0KCJEcm9wcGVkOiAgICAgICAgICIsIHRvdGFsX3RyZWF0ZWQgLSBtYXRjaGVkX3RyZWF0ZWQsICJcbiIpCgoKYGBgCgpgYGB7ciwgTW9kZWwgUjI6IE1hdGNoQmFsYW5jZSgpfQpzZXQuc2VlZCgxMjMpCiMgPT09PT0gUmVwb3J0IEJhbGFuY2UgYW5kIExvd2VzdCBQLVZhbHVlID09PT09PQoKIyB0cmVhdG1lbnQgaW5kaWNhdG9yIGlzIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUsIGNoZWNrIGJhbGFuY2UgZm9yIGFsbCBjb3ZhcmlhdGVzCm1iX2Zvcm11bGFfcmIyIDwtIGZlbV9zaWcgfiBjb25fZHVyICsgY29uX2ludCArIGNvbl9pc3MgKyAgd2FyX3BhciArIGdkcCArIGRlbSArIGh1bV9yaWcgKyBmZW1fbGVnICsgZmVtX2NvbSArIGxlZl9pZGUgKyBwb3dfc2hhICsgcXVvICsgdW5fcGVhX2NvbiArIHN0YXJ0X2RhdGVfbnVtCgpNYXRjaEJhbGFuY2UobWJfZm9ybXVsYV9yYjIsIGRhdGEgPSBkZl9jbGVhbl9yYjIsIG1hdGNoLm91dCA9IG1fb3V0X3JiMiwgbmJvb3RzID0gNTAwKQpgYGAKCiMjIyMgSDIgdnMgUjI6IENvbXBhcmlzb24gb2YgTWF0Y2hpbmcgUmVzdWx0cwoKYGBge3IsIE1vZGVsIFIyOiBDaGVjayBCYWxhbmNlIFN1bW1hcnl9CmJhbC50YWIobWJfZm9ybXVsYV9yYjIsIAogICAgICAgIGRhdGEgPSBkZl9jbGVhbl9yYjIsIAogICAgICAgIHdlaWdodHMgPSBtX291dF9yYjIsICMgVXNlIHRoZSBtYXRjaCBvYmplY3QgYXMgdGhlIHNvdXJjZSBvZiB3ZWlnaHRzCiAgICAgICAgZXN0aW1hbmQgPSAiQVRUIiwKICAgICAgICBiaW5hcnkgPSAic3RkIiwgICAgICAjIDwtLS0gRm9yY2VzIGJpbmFyeSB2YXJzIHRvIHVzZSBTTUQKICAgICAgICBjb250aW51b3VzID0gInN0ZCIsICAjIDwtLS0gRm9yY2VzIGNvbnRpbnVvdXMgdmFycyAoZGVmYXVsdCkgdG8gdXNlIFNNRAogICAgICAgIHVuID0gVFJVRSwKICAgICAgICBzdGF0cyA9IGMoIm0iLCAidiIsICJrcyIpLCAgICMgTWVhbiBkaWZmcywgVmFyaWFuY2UgcmF0aW9zLCBLUyBzdGF0cwogICAgICAgIHRocmVzaG9sZHMgPSBjKG0gPSAwLjI1LCBrcyA9IDAuMSkpCmBgYAoKYGBge3IsIE1vZGVsIFIyOiBNYXRjaEJhbGFuY2UgcC12YWx1ZXN9CnNldC5zZWVkKDEyMykKIyAtLS0gQ2FsbCBGdW5jdGlvbiAtLS0KYmFsYW5jZV90YWJsZV9yYjIgPC0gZ2V0X2JhbGFuY2VfdGFibGUoCiAgZm9ybXVsYSA9IG1iX2Zvcm11bGFfcmIyLCAKICBkYXRhID0gZGZfY2xlYW5fcmIyLCAKICBtYXRjaF9vdXQgPSBtX291dF9yYjIsIAogIG5ib290cyA9IDUwMAopCgpiYWxhbmNlX3RhYmxlX3JiMgpgYGAKCmBgYHtyLCBNb2RlbCBIMiB2cyBSMjogQ29tcGFyZSBNYXRjaGluZyBSZXN1bHRzfQptYXRjaGVkX2RhdGFfSDIgPC0gcmJpbmQoCiAgZGZfY2xlYW5fSDJbbV9vdXRfSDIkaW5kZXgudHJlYXRlZCwgXSwKICBkZl9jbGVhbl9IMlttX291dF9IMiRpbmRleC5jb250cm9sLCBdCikKbl9wYWlycyA8LSBsZW5ndGgobV9vdXRfSDIkaW5kZXgudHJlYXRlZCkKbWF0Y2hlZF9kYXRhX0gyJHBhaXJfaWQgPC0gYygxOm5fcGFpcnMsIDE6bl9wYWlycykKCm1hdGNoZWRfZGF0YV9yYjIgPC0gcmJpbmQoCiAgZGZfY2xlYW5fcmIyW21fb3V0X3JiMiRpbmRleC50cmVhdGVkLCBdLAogIGRmX2NsZWFuX3JiMlttX291dF9yYjIkaW5kZXguY29udHJvbCwgXQopCm5fcGFpcnMgPC0gbGVuZ3RoKG1fb3V0X3JiMiRpbmRleC50cmVhdGVkKQptYXRjaGVkX2RhdGFfcmIyJHBhaXJfaWQgPC0gYygxOm5fcGFpcnMsIDE6bl9wYWlycykKCm1hdGNoZXMgPC0gY2JpbmQoUGFpcl9JRCA9IG1hdGNoZWRfZGF0YV9IMiRwYWlyX2lkLCAKICAgICAgICAgICAgICAgICBUcmVhdGVkID0gbWF0Y2hlZF9kYXRhX0gyJGNhc19pZFttYXRjaGVkX2RhdGFfSDIkZmVtX3NpZyA9PSAxXSwgCiAgICAgICAgICAgICAgICAgTW9kZWxIMl9NYXRjaGVzID0gbWF0Y2hlZF9kYXRhX0gyJGNhc19pZFttYXRjaGVkX2RhdGFfSDIkZmVtX3NpZyA9PSAwXSwgCiAgICAgICAgICAgICAgICAgTW9kZWxSMl9NYXRjaGVzID0gbWF0Y2hlZF9kYXRhX3JiMiRjYXNfaWRbbWF0Y2hlZF9kYXRhX3JiMiRmZW1fc2lnID09IDBdKQptYXRjaGVzWzE6NiwgXQoKIyBDb21wYXJlIG91dGNvbWUgb2JzZXJ2YXRpb25zIG9mIG1hdGNoZWQgdW5pdHMKbWF0Y2hjb21wX2NwYSA8LSBjYmluZChQYWlyX0lEID0gbWF0Y2hlZF9kYXRhX0gyJHBhaXJfaWQsCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc19pZCA9IG1hdGNoZWRfZGF0YV9IMiRjYXNfaWQsCiAgICAgICAgICAgICAgICAgICAgICAgIGZlbV9zaWcgPSBtYXRjaGVkX2RhdGFfSDIkZmVtX3NpZywKICAgICAgICAgICAgICAgICAgICAgICAgY3BhX0gyID0gbWF0Y2hlZF9kYXRhX0gyJGNwYSwKICAgICAgICAgICAgICAgICAgICAgICAgY3BhX3JiMiA9IG1hdGNoZWRfZGF0YV9yYjIkY3BhKQptYXRjaGNvbXBfY2l2X3NvYyA8LSBjYmluZChQYWlyX0lEID0gbWF0Y2hlZF9kYXRhX0gyJHBhaXJfaWQsCiAgICAgICAgICAgICAgICAgICAgICBjYXNfaWQgPSBtYXRjaGVkX2RhdGFfSDIkY2FzX2lkLAogICAgICAgICAgICAgICAgICAgICAgZmVtX3NpZyA9IG1hdGNoZWRfZGF0YV9IMiRmZW1fc2lnLAogICAgICAgICAgICAgICAgICAgICAgY2l2X3NvY19IMiA9IG1hdGNoZWRfZGF0YV9IMiRjaXZfc29jLAogICAgICAgICAgICAgICAgICAgICAgY2l2X3NvY19yYjIgPSBtYXRjaGVkX2RhdGFfcmIyJGNpdl9zb2MpCm1hdGNoY29tcF9jcGEKbWF0Y2hjb21wX2Npdl9zb2MKYGBgCgojIyMjIEgyIHZzIFIyOiBDb21wYXJpc29uIG9mIFRyZWF0bWVudCBFZmZlY3QgRXN0aW1hdGVzCgpgYGB7ciwgTW9kZWwgUjI6IFRyZWF0bWVudCBlZmZlY3QgZXN0aW1hdGUgKGNwYSl9CgojID09PT09PT09PT0gUnVuIE1hdGNoKCkgd2l0aCBvdXRvbWUgdmFyaWFibGUgKGNwYSkgPT09PT09PT09PT09PT0Kc2V0LnNlZWQoMTIzKQojIE91dGNvbWUKWSAgPC0gZGZfY2xlYW5fcmIyJGNwYQptX291dF9yYjJBIDwtIE1hdGNoKFkgPSBZLCBUciA9IFRyLCBYID0gWCwgV2VpZ2h0Lm1hdHJpeCA9IGdlbm91dF9yYjIsIGVzdGltYW5kID0gIkFUVCIsIHJlcGxhY2UgPSBGQUxTRSkKCiMgPT09PT0gRXN0aW1hdGUgVHJlYXRtZW50IEVmZmVjdCwgU0UsIGFuZCBDSSA9PT09PT0KCnN1bW1hcnkobV9vdXRfcmIyQSkKCkFUVF9lc3QgPC0gbV9vdXRfcmIyQSRlc3QKQVRUX3NlIDwtIDAuMjA0MTIjbV9vdXRfcmIyQSRzZQoKIy0tLS0tIEdldCBDb25maWRlbmNlIEludGVydmFscyAtLS0tLS0KIyBDSSBib3VuZHMgZ2l2ZW4gYnkgcG9pbnQgZXN0aW1hdGUgKy8tIG1hcmdpbiBvZiBlcnJvcgojIENWIGZvciA5NSUgaW50ZXJ2YWwgaXMgMS45NgpjaV9sb3dlcjk1IDwtIEFUVF9lc3QgLSAxLjk2ICogQVRUX3NlCmNpX3VwcGVyOTUgPC0gQVRUX2VzdCArIDEuOTYgKiBBVFRfc2UKIyBDViBmb3IgOTklIGludGVydmFsIGlzIDIuNTc2CmNpX2xvd2VyOTkgPC0gQVRUX2VzdCAtIDIuNTc2ICogQVRUX3NlCmNpX3VwcGVyOTkgPC0gQVRUX2VzdCArIDIuNTc2ICogQVRUX3NlCgpwcmludChwYXN0ZSgiRXN0aW1hdGVkIEFUVDoiLCByb3VuZChBVFRfZXN0LCAyKSkpCnByaW50KHBhc3RlKCJTdGFuZGFyZCBFcnJvcjoiLCByb3VuZChBVFRfc2UsIDIpKSkKcHJpbnQocGFzdGUoIjk1JSBDSTogWyIsIHJvdW5kKGNpX2xvd2VyOTUsIDMpLCAiLCIsIHJvdW5kKGNpX3VwcGVyOTUsIDMpLCAiXSIpKQpwcmludChwYXN0ZSgiOTklIENJOiBbIiwgcm91bmQoY2lfbG93ZXI5OSwgMyksICIsIiwgcm91bmQoY2lfdXBwZXI5OSwgMyksICJdIikpCmBgYAoKYGBge3IsIE1vZGVsIFIyOiBUcmVhdG1lbnQgZWZmZWN0IGVzdGltYXRlIChjaXZfc29jKX0Kc2V0LnNlZWQoMTIzKQojID09PT09PT09PT0gUnVuIE1hdGNoKCkgd2l0aCBvdXRvbWUgdmFyaWFibGUgKGNpdl9zb2MpID09PT09PT09PT09PT09CiMgT3V0Y29tZQpZICA8LSBkZl9jbGVhbl9yYjIkY2l2X3NvYwptX291dF9yYjJCIDwtIE1hdGNoKFkgPSBZLCBUciA9IFRyLCBYID0gWCwgV2VpZ2h0Lm1hdHJpeCA9IGdlbm91dF9yYjIsIGVzdGltYW5kID0gIkFUVCIsIHJlcGxhY2UgPSBGQUxTRSkKCiMgPT09PT0gRXN0aW1hdGUgVHJlYXRtZW50IEVmZmVjdCwgU0UsIGFuZCBDSSA9PT09PT0Kc3VtbWFyeShtX291dF9yYjJCKQoKQVRUX2VzdCA8LSBtX291dF9yYjJCJGVzdApBVFRfc2UgPC0gMC4xNTIxNSAjbV9vdXRfcmIyQiRzZQoKIy0tLS0tIEdldCBDb25maWRlbmNlIEludGVydmFscyAtLS0tLS0KIyBDSSBib3VuZHMgZ2l2ZW4gYnkgcG9pbnQgZXN0aW1hdGUgKy8tIG1hcmdpbiBvZiBlcnJvcgojIENWIGZvciA5NSUgaW50ZXJ2YWwgaXMgMS45NgpjaV9sb3dlcjk1IDwtIEFUVF9lc3QgLSAxLjk2ICogQVRUX3NlCmNpX3VwcGVyOTUgPC0gQVRUX2VzdCArIDEuOTYgKiBBVFRfc2UKIyBDViBmb3IgOTklIGludGVydmFsIGlzIDIuNTc2CmNpX2xvd2VyOTkgPC0gQVRUX2VzdCAtIDIuNTc2ICogQVRUX3NlCmNpX3VwcGVyOTkgPC0gQVRUX2VzdCArIDIuNTc2ICogQVRUX3NlCgpwcmludChwYXN0ZSgiRXN0aW1hdGVkIEFUVDoiLCByb3VuZChBVFRfZXN0LCAzKSkpCnByaW50KHBhc3RlKCJTdGFuZGFyZCBFcnJvcjoiLCByb3VuZChBVFRfc2UsIDMpKSkKcHJpbnQocGFzdGUoIjk1JSBDSTogWyIsIHJvdW5kKGNpX2xvd2VyOTUsIDMpLCAiLCIsIHJvdW5kKGNpX3VwcGVyOTUsIDMpLCAiXSIpKQpwcmludChwYXN0ZSgiOTklIENJOiBbIiwgcm91bmQoY2lfbG93ZXI5OSwgMyksICIsIiwgcm91bmQoY2lfdXBwZXI5OSwgMyksICJdIikpCmBgYAoKYGBge3IsIFJvYnVzdG5lc3MgQ2hlY2sgSDIgdnMuIFIyOiBDb21wYXJlIEVzdGltYXRlc30KcHJpbnQgKCJIMkEgdnMuIFIyQSIpCnN1bW1hcnkobV9vdXRfSDJBKQpzdW1tYXJ5KG1fb3V0X3JiMkEpCnByaW50ICgiSDJCIHZzLiBSMkIiKQpzdW1tYXJ5KG1fb3V0X0gyQikKc3VtbWFyeShtX291dF9yYjJCKQpgYGAK