Table of Contents


The methods explanations throughout the notebook are kept short. Please see the paper for more details regarding the decomposition parameters and their estimation.

Click on the “Code” button on the top right of this notebook to “Hide All Code” and see only the results or “Download Rmd” to extract the underlying code.

S.1 Main results

S.1.1 Getting ready

Load packages, project specific functions, and set seed:

# Load required libraries
library(sas7bdat)
library(causalDML)
library(tidyverse)
library(grf)
library(patchwork)
library(dplyr)
library(knitr)
library(viridis)

# Load project specific functions
source("/home/rstudio/code/probs_all_v1.R")

# Set seed
seed = 1234
set.seed(seed)

Load the data that were obtained from impact.sas7bdat, baseline.sas7bdat, key_vars.sas7bdat, and mileston.sas7bdat files from OPENICPSR on March 24, 2025 (usually takes some minutes).

# Load datasets downloaded from https://www.openicpsr.org/openicpsr/project/113269/version/V1/view
impact_raw = read.sas7bdat("/home/rstudio/raw_data/impact.sas7bdat")
baseline_raw = read.sas7bdat("/home/rstudio/raw_data/baseline.sas7bdat")
key_vars_raw = read.sas7bdat("/home/rstudio/raw_data/key_vars.sas7bdat")
mileston_raw = read.sas7bdat("/home/rstudio/raw_data/mileston.sas7bdat")
rand_raw = read.sas7bdat("/home/rstudio/raw_data/rand_dat.sas7bdat")

Prepare data for analysis:

# Extract the relevant variables
impact = select(impact_raw,MPRID,EARNY4,EVERJCH)
impact_temp = select(impact_raw,MPRID,JCVCLERC,JCVHLTH,JCVAUTO,JCVWELD,JCVELTRC,JCVCSTRC,JCVFOOD,JCVETRNC,JCVOTH)
baseline = select(baseline_raw,MPRID,RACE_ETH,HS_D,GED_D,VOC_D,ANY_ED1,HGC,NTV_LANG,WKEARNR,
                  HASCHLD,MARRIAGE,R_HEAD,HHMEMB,HEALTH,PY_CIG,PY_ALCHL,
                  PY_POT,HADWORRY,HEAR_JC,KNEWCNTR,E_MATH,E_READ,E_ALONG,
                  E_CONTRL,E_ESTEEM,E_SPCJOB,E_FRIEND,KNEW_JC,EARN_YR)
key_vars = select(key_vars_raw,MPRID,TREATMNT,FEMALE,AGE_CAT,EDUC_GR,NONRES,IN57)
mileston = select(mileston_raw,MPRID,LIVESPOU,EVERWORK,YR_WORK,CURRJOB,
                  JOB0_3, JOB3_9, JOB9_12, MOSTWELF,GOT_AFDC,GOT_FS,ED0_6,ED6_12,
                  PUBLICH,BADHLTH,HARDUSE,POTUSE,EVARRST,PMSA,MSA,PRARRI)
rand = select(rand_raw,MPRID,RAND_WK)

# Code the versions
versions = rep("Nothing",nrow(impact))
versions[impact_temp[,2] == 1] = "Clerical"
versions[impact_temp[,3] == 1] = "Health"
versions[impact_temp[,4] == 1] = "Auto"
versions[impact_temp[,5] == 1] = "Welding"
versions[impact_temp[,6] == 1 | impact_temp[,9] == 1] = "Electrical"
versions[impact_temp[,7] == 1] = "Construction"
versions[impact_temp[,8] == 1] = "Food"
versions[impact_temp[,10] == 1] = "Other"
versions[rowSums(impact_temp[,2:10],na.rm=T) > 1] = "Multiple"
impact = cbind(impact,versions)

# Merge the data
inner_join(impact,baseline,by="MPRID") %>% inner_join(key_vars,by="MPRID")  %>% inner_join(mileston,by="MPRID") %>% inner_join(rand,by="MPRID") %>%
  mutate(RACE_W = as.numeric(RACE_ETH == 1)) %>%  mutate(RACE_B = as.numeric(RACE_ETH == 2)) %>%
  mutate(RACE_H = as.numeric(RACE_ETH == 3)) %>%  mutate(RACE_O = as.numeric(RACE_ETH == 4)) %>% 
  mutate(WKEARNR = replace(WKEARNR,is.na(WKEARNR),0)) %>%
  mutate(EARN_YR = replace(EARN_YR,is.na(EARN_YR),0)) -> db

# Remove observations with missing values
db %>% na.omit() -> db

# Create main variables
Y = as.matrix(select(db,EARNY4))
D = as.matrix(select(db,TREATMNT))

# Heterogeneity variable
female = select(db,FEMALE)
fem_mat = cbind(1-female,female)
label_fem = c("Male","Female")
colnames(fem_mat) = label_fem
female = factor(ifelse(female == 1, "female", "male"),
                    levels = c("male", "female"))

# Create versions
JC = db$EVERJCH
Tr = rep(NA,length(Y))
Tr[D == 0] = "Control"
Tr[D == 1 & JC == 0] = "No JC"
Tr[D == 1 & JC == 1 & db$versions == "Clerical"] = "Clerical"
Tr[D == 1 & JC == 1 & db$versions == "Health"] = "Health"
Tr[D == 1 & JC == 1 & db$versions == "Auto"] = "Auto"
Tr[D == 1 & JC == 1 & db$versions == "Welding"] = "Welding"
Tr[D == 1 & JC == 1 & db$versions == "Electrical"] = "Electrical"
Tr[D == 1 & JC == 1 & db$versions == "Construction"] = "Construction"
Tr[D == 1 & JC == 1 & db$versions == "Food"] = "Food"
Tr[D == 1 & JC == 1 & db$versions == "Other"] = "Other"
Tr[D == 1 & JC == 1 & db$versions == "Multiple"] = "Multiple"
Tr[is.na(Tr)] = "JC w/o voc"
label_T = c("Control","No JC","JC w/o voc","Clerical","Health","Auto","Welding","Electrical",
            "Construction","Food","Other","Multiple")
Tr = factor(Tr,levels=label_T)


# Create control matrix
X = as.matrix(select(db,FEMALE,AGE_CAT,RACE_W,RACE_B,RACE_H,RACE_O,EDUC_GR,
                     LIVESPOU,EVERWORK,YR_WORK,CURRJOB,JOB0_3, JOB3_9, JOB9_12,
                     MOSTWELF,GOT_AFDC,GOT_FS,ED0_6,ED6_12,PUBLICH,BADHLTH,HARDUSE,POTUSE,EVARRST,PMSA,MSA,
                     HS_D,GED_D,VOC_D,ANY_ED1,HGC,NTV_LANG,WKEARNR,
                     HASCHLD,MARRIAGE,R_HEAD,HHMEMB,HEALTH,PY_CIG,PY_ALCHL,
                     PY_POT,HADWORRY,HEAR_JC,KNEWCNTR,E_MATH,E_READ,E_ALONG,
                     E_CONTRL,E_ESTEEM,E_SPCJOB,E_FRIEND,KNEW_JC,NONRES,PRARRI,EARN_YR,RAND_WK,IN57))

S.1.2 The main analysis

The nuisance parameters are obtained using the multi-valued treatment effect implementation of the causalDML package. For the outcome models, we switch off the honesty option, because sample size in some effective treatments is too small to tune parameters with honesty (ran roughly half an hour).

# Define methods
forest_hon = create_method("forest_grf",args=list(tune.parameters = "all")) # for pscores
forest = create_method("forest_grf",args=list(honesty = F,tune.parameters = "all")) # for outcome b/c too few observations for honest RF

# Run multiple treatment model to get nuisance parameters
aipw = DML_aipw(Y,Tr,X,
                ml_w=list(forest_hon),
                ml_y=list(forest), 
                quiet=T, # Switch off to see progress
                cf = 5)

Run the decomposition:

# Run HK decomp
results = HK2_decomposition(Y,D,female,
                           aipw$APO$w_mat,
                           aipw$APO$e_mat,
                           aipw$APO$m_mat)
# Print the setting
results
================= Setting Summary =================
Effective treatments: Control
Aggregated into: 0

Effective treatments: No JC, JC w/o voc, Clerical, Health, Auto, Welding, Electrical, Construction, Food, Other, Multiple
Aggregated into: 1

Heterogeneity variables: Unconditional, male, female

Print, plot and save results for DiM:

g = plot(results,levels = T, pe_digits = 1,decomposition = "dim")
g
ggsave("/home/rstudio/results/DiM.png",g,width = 7,height=4)

Delta_dim = summary(results,parameter = "dim", t_aggregate = c(3,2),x_aggregate = c(3,2)) # Female - Male
================= HK decomposition results for =================
Parameters dim

Treatment aggregation contrast: 1 - 0

Heterogeneity contrast: female - male 

    Estimate       SE t-value p-value  
DiM -7.61422  7.81877 -0.9738 0.34666  
Δ0   0.00000  0.00000  0.0000 1.00000  
Δ1  -0.33622  7.68273 -0.0438 0.96571  
Δ2  -6.16894  2.33089 -2.6466 0.01916 *
Δ3  -0.40977  0.51961 -0.7886 0.44349  
Δ4  -0.69929  2.70445 -0.2586 0.79973  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Print, plot and save results for adjusted DiM:

g = plot(results,levels = T, pe_digits = 1,decomposition = "adim")
g
ggsave("/home/rstudio/results/ADiM.png",g,width = 7,height=4)

summary(results,parameter = "adim", t_aggregate = c(3,2),x_aggregate = c(3,2)) # Female - Male
================= HK decomposition results for =================
Parameters adim

Treatment aggregation contrast: 1 - 0

Heterogeneity contrast: female - male 

      Estimate        SE t-value p-value  
ADiM -7.993378  7.485126 -1.0679 0.30363  
Δ0    0.000000  0.000000  0.0000 1.00000  
Δ1   -0.336222  7.682731 -0.0438 0.96571  
Δ2   -6.168936  2.330894 -2.6466 0.01916 *
Δ3   -0.409768  0.519608 -0.7886 0.44349  
Δ4'  -1.090668  1.566117 -0.6964 0.49757  
Δ5    0.012215  0.053829  0.2269 0.82377  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Create the condensed figure in the introduction:

res = Delta_dim[3:6,c(1,4)]

# Original labels
base_labels <- c("Effect heterogeneity",
                 "Group targeting of average outcomes",
                 "Group targeting of group outcomes",
                 "Individualized targeting")

# Construct labels with p-values (rounded to 3 decimal places)
full_labels <- paste0(base_labels, " (p-value: ", sprintf("%.3f", res[,2]), ")")

# Create factor with reversed order to preserve top-to-bottom layout
df <- data.frame(
  label = factor(full_labels, levels = rev(full_labels)),
  estimate = res[,1]
)

# Plot without confidence intervals
g = ggplot(df, aes(x = estimate, y = label)) +
  geom_bar(stat = "identity", fill = viridis(1,alpha=0.9, begin=0.3)) +
  geom_vline(xintercept = 0) +
  labs(x = "Estimate in $", y = "") +
  theme_minimal() +
  theme(axis.text.y = element_text(size = 10)) + xlim(-8,0)
g
ggsave("/home/rstudio/results/Intro_graph_p.png",g,width = 7,height=2)

Save image.

save.image("/home/rstudio/results/Image.RData")

S.2 Supplementary material

S.2.1 Descriptives

We plot fractions of effective treatments by gender to illustrate how different the Job Corps experience is with respect to vocational training received:

g1 = data.frame(x=factor(female), Version=factor(Tr,levels=rev(label_T))) %>% 
  ggplot(aes(x=x, fill=Version))+geom_bar(position = "fill", colour="black",linewidth=0.01) +
  ylab("Fraction") + scale_fill_grey(start = 0, end = 1) + theme_bw() + 
  theme(axis.title.x = element_blank())

g2 = data.frame(x=factor(female), Version=factor(Tr,levels=rev(label_T))) %>%
  filter(Version != "Control") %>% filter(Version != "No JC") %>% filter(Version != "JC without voc") %>% 
  ggplot(aes(x=x, fill=Version)) + geom_bar(position = "fill", colour="black",linewidth=0.01) + 
  ylab("Fraction conditional on vocational training") + scale_fill_grey(start = 0, end = 0.9) + 
  theme_bw() + theme(axis.title.x = element_blank(), legend.position = "none") 

g = g1 + g2
g

See also the numbers here:

# Create a data frame with the relevant variables
df = data.frame(female = female, Tr = Tr)

# Compute the percentage shares
tab_female = prop.table(table(df$Tr[df$female == "female"])) * 100
tab_male   = prop.table(table(df$Tr[df$female == "male"])) * 100
tab_all    = prop.table(table(df$Tr)) * 100

# Combine the results into a table with formatted percentages
table_shares = cbind(
  Female = sprintf("%1.1f", tab_female),
  Male   = sprintf("%1.1f", tab_male),
  All    = sprintf("%1.1f", tab_all)
)

# Ensure the row names are consistent with the overall table
rownames(table_shares) = names(tab_all)

# Print the table as a data frame
as.data.frame(table_shares)

S.2.2 Scaled p-score distributions

The main text discusses how the weak effective overlap assumption A.4 can be inspected by checking scaled propensity scores. Here we plot the scaled distributions:

# Convert the matrix to a data frame and add an identifier for rows
df <- as.data.frame(aipw$APO$e_mat[,-1]) %>% 
  mutate(id = row_number()) %>% 
  pivot_longer(cols = -id, names_to = "variable", values_to = "value") %>% 
  group_by(variable) %>% 
  # Divide each value by the mean of its respective column
  mutate(norm_value = value / mean(value)) %>% 
  ungroup()

# Plot histograms with density on the y-axis and shared x-axis across facets
ggplot(df, aes(x = norm_value)) +
  geom_histogram(aes(y = after_stat(density)), bins = 30, fill = "blue", color = "black") +
  facet_wrap(~ variable) +  # no scales = "free_x"
  labs(x = "Scaled p-score", y = "Density") +
  theme_minimal()

The minimum scaled propensity score is 0.21 and therefore much larger than what usually would be considered as problematic in standard settings. For most of the trainings, we observe a bimodal shape. This is because gender is the most important predictor of vocational training and random forests are capable of capturing this pattern.

S.2.3 Sampling weights

Using sampling weights to account for the not completely random sampling procedure of the Job Corps evaluation shows no qualitative differences to main results:

# Create sampling weights
sampling_weights = props_all(db)$weights_Rx

# For comparison purposes run with sampling weights
resultsw = HK2_decomposition(Y,D,female,
                            aipw$APO$w_mat,
                            aipw$APO$e_mat,
                            aipw$APO$m_mat,
                            sampling_weights = sampling_weights)

g = plot(resultsw,levels = T, pe_digits = 1,decomposition = "dim",
         t_aggregate = c(3,2),x_aggregate = c(3,2))
g
ggsave("/home/rstudio/results/DiMw.png",g,width = 7,height=4)

g = plot(resultsw,levels = T, pe_digits = 1,decomposition = "adim",
         t_aggregate = c(3,2),x_aggregate = c(3,2))
g
ggsave("/home/rstudio/results/ADiMw.png",g,width = 7,height=4)


summary(resultsw,parameter = "dim", t_aggregate = c(3,2),x_aggregate = c(3,2))
================= HK decomposition results for =================
Parameters dim

Treatment aggregation contrast: 1 - 0

Heterogeneity contrast: female - male 

    Estimate       SE t-value p-value  
DiM -5.96499  7.77516 -0.7672 0.45572  
Δ0   0.00000  0.00000  0.0000 1.00000  
Δ1   0.75562  7.88379  0.0958 0.92500  
Δ2  -5.89218  2.35030 -2.5070 0.02512 *
Δ3  -0.26037  0.41460 -0.6280 0.54011  
Δ4  -0.11920  2.73299 -0.0436 0.96583  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
summary(resultsw,parameter = "adim", t_aggregate = c(3,2),x_aggregate = c(3,2))
================= HK decomposition results for =================
Parameters adim

Treatment aggregation contrast: 1 - 0

Heterogeneity contrast: female - male 

       Estimate         SE t-value p-value  
ADiM -7.0276905  7.4421474 -0.9443 0.36102  
Δ0    0.0000000  0.0000000  0.0000 1.00000  
Δ1    0.7556183  7.8837863  0.0958 0.92500  
Δ2   -5.8921751  2.3502972 -2.5070 0.02512 *
Δ3   -0.2603703  0.4145969 -0.6280 0.54011  
Δ4'  -1.1843630  1.5535925 -0.7623 0.45851  
Δ5   -0.0071592  0.0646172 -0.1108 0.91335  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

S.2.4 Testing strong group effect homogeneity

The decomposition indicates that there is no real effect heterogeneity at the level of the effective treatment. However, \(\Delta_1\) is only a necessary test for strong group effect homogeneity as discussed in Section 4.6 of the paper. Thus, we investigate effect heterogeneity for each effective treatment to see whether significant effect heterogeneity is masked by the decomposition estimand.

GATE difference point estimates

First, we estimate group average treatment effect (GATE) differences, i.e. \(E[Y(t)-Y(0)|female] - E[Y(t)-Y(0)|male]\), for each treatment version:

# Initialize DiM for each effective treatment and IFs for inference later
n = length(Y)
J = length(label_T)-1
G = (female == "female")*1
dGATEs = matrix(NA,J,5)
rownames(dGATEs) = label_T[-1]
colnames(dGATEs) = c("GATE","S.E.","t-value","pointwise p-value","uniform p-value")
IFs = matrix(NA,length(Y),J)
for (j in 1:J) {
  dGATEs[j,1] = mean(aipw$ATE$delta[,j] * G / mean(G) - aipw$ATE$delta[,j] * (1-G) / mean(1-G))
  IFs[,j] = aipw$ATE$delta[,j] * G / mean(G) - aipw$ATE$delta[,j] * (1-G) / mean(1-G) - dGATEs[j]
}

# Estimate the covariance matrix via IF
Sigma_hat = var(IFs)

# Collect point estimates and SEs
dGATEs[,2] = sqrt(diag(Sigma_hat) / n)
dGATEs[,3] = dGATEs[,1] / dGATEs[,2]
dGATEs[,4] = 2 * (1 - pt(abs(dGATEs[,3]), n))

sup_t = function(dimj0,Ytilde,G,alpha = 0.05,reps = 10000) {
  n = nrow(Ytilde)
  J = ncol(Ytilde)
  # browser()
  largest_ts = rep(0,reps)
  
  for (i in 1:reps) {
    # Generate bootstrap indices
    bootstrap_indices = sample(1:n, size = n, replace = TRUE)
    
    # Bootstrap samples
    bootstrap_Ytilde = Ytilde[bootstrap_indices,]
    bootstrap_G = G[bootstrap_indices] 
    
    for (j in 1:J) {
      mean_1 = mean(bootstrap_Ytilde[bootstrap_G == 1,j])
      mean_0 = mean(bootstrap_Ytilde[bootstrap_G == 0,j])
      dim_boot = mean_1 - mean_0
      var_1 = var(bootstrap_Ytilde[bootstrap_G == 1,j])
      var_0 = var(bootstrap_Ytilde[bootstrap_G == 0,j])
      n_1 = sum(bootstrap_G == 1)
      n_0 = sum(bootstrap_G == 0)
      se_boot = sqrt(var_1 / n_1 + var_0 / n_0)
      t_val = abs((dim_boot - dimj0[j]) / se_boot)
      if (is.na(t_val)) next
      else if (t_val > largest_ts[i]) largest_ts[i] = t_val
    }
  }
  CV = quantile(largest_ts, probs = 1 - alpha)
  
  return(list("CritVal" = CV, "largest_ts" = largest_ts))
}

supt = sup_t(dGATEs[,1],aipw$ATE$delta[,1:J],G)

for (j in 1:J) {
  dGATEs[j,5] = mean(supt$largest_ts > abs(dGATEs[j,3]))
}

dGATEs
                    GATE     S.E.    t-value pointwise p-value uniform p-value
No JC          0.4345983 11.52285  0.0377162         0.9699147          1.0000
JC w/o voc    -7.3774050 12.83993 -0.5745675         0.5655972          0.9998
Clerical     -23.7203674 19.70356 -1.2038621         0.2286722          0.9358
Health        21.3105338 23.75711  0.8970169         0.3697321          0.9917
Auto          40.0176808 33.99475  1.1771724         0.2391556          0.9450
Welding       14.3231329 32.94165  0.4348031         0.6637150          1.0000
Electrical   -15.6003258 46.98573 -0.3320226         0.7398793          1.0000
Construction   9.0027448 23.12807  0.3892562         0.6970952          1.0000
Food          27.7936581 24.47049  1.1358031         0.2560670          0.9558
Other          3.0522618 16.03259  0.1903786         0.8490164          1.0000
Multiple     -25.7210440 18.79120 -1.3687815         0.1710993          0.8654

We observe that each estimate is imprecisely estimated and even the pointwise p-values are quite large.

Test if differences are jointly zero

Finally, we test the joint hypothesis of all GATE differences being zero using a Wald and a supremum test:

# Compute the Wald statistic and p-value
W = t(dGATEs[,1]) %*% solve(Sigma_hat / n) %*% dGATEs[,1]
W_p_value = 1 - pchisq(W, df = J)
# Compute supt p-value
supt_p_value = mean(supt$largest_ts > max(abs(dGATEs[,3])))
# Use sprintf to align numbers
output = sprintf("Wald p-value: %.4f\nSupremum p-value: %.4f", W_p_value, supt_p_value)
cat(output)
Wald p-value: 0.6942
Supremum p-value: 0.8654

Like \(\Delta_1\), the direct tests of strong group effect homogeneity are insignificant.

S.2.5 More parameter estimates

First plot the underlying average potential outcomes:

plot(aipw$APO)

Not surprisingly they are imprecisely estimated. However, we observe a pattern that the training in which women are overrepresented - clerical, health and food - have relatively low estimated average potential outcomes. This is driving the gender differences.

Then, we can print estimates of all parameters discussed throughout the manucript for completeness.

# Define parameters to be displays and their order
param_select = c(1,2,4,5,6,3,7,8,9,11,13,14)

First, outcome levels for men

summary(results,parameter = param_select, t_aggregate = 2,x_aggregate = 2) # A = 0
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation level: 0

Heterogeneity level: male

     Estimate        SE t-value   p-value    
CM  221.16570   3.96844 55.7312 < 2.2e-16 ***
ACM 221.91192   3.95426 56.1197 < 2.2e-16 ***
s1  221.91192   3.95426 56.1197 < 2.2e-16 ***
s2  195.78072   2.91088 67.2583 < 2.2e-16 ***
s3  221.91192   3.95426 56.1197 < 2.2e-16 ***
d0  195.78072   2.91088 67.2583 < 2.2e-16 ***
d1   26.13120   2.48265 10.5255 4.935e-08 ***
d2    0.00000   0.00000  0.0000    1.0000    
d3    0.00000   0.00000  0.0000    1.0000    
d4   -0.74623   0.87780 -0.8501    0.4096    
d4'   0.00000   0.00000  0.0000    1.0000    
d5    0.00000   0.00000  0.0000    1.0000    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
summary(results,parameter = param_select, t_aggregate = 3,x_aggregate = 2) # A = 1
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation level: 1

Heterogeneity level: male

      Estimate         SE t-value   p-value    
CM  241.074985   3.921212 61.4797 < 2.2e-16 ***
ACM 240.063266   3.805680 63.0803 < 2.2e-16 ***
s1  238.375842   3.988827 59.7609 < 2.2e-16 ***
s2  214.913643   2.870742 74.8634 < 2.2e-16 ***
s3  240.513381   3.999296 60.1389 < 2.2e-16 ***
d0  212.101366   2.746747 77.2191 < 2.2e-16 ***
d1   26.274477   2.274935 11.5495 1.526e-08 ***
d2    2.812278   1.063576  2.6442   0.01925 *  
d3   -0.674739   0.853093 -0.7909   0.44218    
d4    0.561604   1.275787  0.4402   0.66651    
d4'  -0.466254   1.124392 -0.4147   0.68467    
d5    0.016139   0.034817  0.4635   0.65011    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

and their contrast

# Male contrast in treatment aggregations
summary(results,parameter = param_select, t_aggregate = c(3,2),x_aggregate = 2)
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation contrast: 1 - 0

Heterogeneity level: male

      Estimate        SE t-value   p-value    
DiM  19.909288  5.578924  3.5687 0.0030845 ** 
ADiM 18.151343  5.368024  3.3814 0.0044756 ** 
s1   16.463920  5.498158  2.9944 0.0096573 ** 
s2   19.132919  3.989715  4.7956 0.0002849 ***
s3   18.601458  5.505695  3.3786 0.0045006 ** 
δ0   16.320641  3.898079  4.1868 0.0009136 ***
δ1    0.143279  3.273949  0.0438 0.9657112    
δ2    2.812278  1.063576  2.6442 0.0192468 *  
δ3   -0.674739  0.853093 -0.7909 0.4421771    
δ4    1.307830  1.800249  0.7265 0.4795208    
δ4'  -0.466254  1.124392 -0.4147 0.6846659    
δ5    0.016139  0.034817  0.4635 0.6501077    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Second, outcome levels for women

summary(results,parameter = param_select, t_aggregate = 2,x_aggregate = 3) # A = 0
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation level: 0

Heterogeneity level: female

    Estimate       SE  t-value   p-value    
CM  159.5534   4.4309  36.0094 3.339e-15 ***
ACM 160.5917   4.2170  38.0823 1.536e-15 ***
s1  160.5917   4.2170  38.0823 1.536e-15 ***
s2  195.7807   2.9109  67.2583 < 2.2e-16 ***
s3  160.5917   4.2170  38.0823 1.536e-15 ***
d0  195.7807   2.9109  67.2583 < 2.2e-16 ***
d1  -35.1890   3.3317 -10.5620 4.726e-08 ***
d2    0.0000   0.0000   0.0000    1.0000    
d3    0.0000   0.0000   0.0000    1.0000    
d4   -1.0383   1.1759  -0.8831    0.3921    
d4'   0.0000   0.0000   0.0000    1.0000    
d5    0.0000   0.0000   0.0000    1.0000    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
summary(results,parameter = param_select, t_aggregate = 3,x_aggregate = 3) # A = 1
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation level: 1

Heterogeneity level: female

      Estimate         SE  t-value   p-value    
CM  171.848444   3.221199  53.3492 < 2.2e-16 ***
ACM 170.749687   3.234096  52.7967 < 2.2e-16 ***
s1  176.719420   3.470609  50.9188 < 2.2e-16 ***
s2  208.744708   3.099585  67.3460 < 2.2e-16 ***
s3  172.278255   3.479212  49.5165 < 2.2e-16 ***
d0  212.101366   2.746747  77.2191 < 2.2e-16 ***
d1  -35.381946   3.048336 -11.6070 1.432e-08 ***
d2   -3.356658   1.268724  -2.6457   0.01919 *  
d3   -1.084507   1.371320  -0.7908   0.44222    
d4   -0.429812   1.243008  -0.3458   0.73465    
d4'  -1.556922   1.090167  -1.4281   0.17518    
d5    0.028353   0.041053   0.6907   0.50108    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

and their contrast

# Male contrast in treatment aggregations
summary(results,parameter = param_select, t_aggregate = c(3,2),x_aggregate = 3)
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation contrast: 1 - 0

Heterogeneity level: female

      Estimate        SE t-value   p-value    
DiM  12.295069  5.478033  2.2444 0.0414871 *  
ADiM 10.157964  5.216458  1.9473 0.0718435 .  
s1   16.127698  5.368436  3.0042 0.0094729 ** 
s2   12.963983  4.154303  3.1206 0.0075181 ** 
s3   11.686533  5.369378  2.1765 0.0471270 *  
δ0   16.320641  3.898079  4.1868 0.0009136 ***
δ1   -0.192943  4.408783 -0.0438 0.9657111    
δ2   -3.356658  1.268724 -2.6457 0.0191897 *  
δ3   -1.084507  1.371320 -0.7908 0.4422242    
δ4    0.608536  2.018202  0.3015 0.7674475    
δ4'  -1.556922  1.090167 -1.4281 0.1751764    
δ5    0.028353  0.041053  0.6907 0.5010756    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

S.2.6 Unconditional results

For completeness also check the unconditional estimands that naturally do not represent a heterogeneity but rather decompose average estimands for average potential outcomes:

# Unconditional levels
summary(results,parameter = param_select, t_aggregate = 2,x_aggregate = 1) # A = 0
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation level: 0

Heterogeneity level: Unconditional

     Estimate        SE t-value p-value    
CM  197.63124   3.01814 65.4812 < 2e-16 ***
ACM 195.78072   2.91088 67.2583 < 2e-16 ***
s1  195.78072   2.91088 67.2583 < 2e-16 ***
s2  195.78072   2.91088 67.2583 < 2e-16 ***
s3  195.78072   2.91088 67.2583 < 2e-16 ***
d0  195.78072   2.91088 67.2583 < 2e-16 ***
d1    0.00000   0.00000  0.0000 1.00000    
d2    0.00000   0.00000  0.0000 1.00000    
d3    0.00000   0.00000  0.0000 1.00000    
d4    1.85052   0.77287  2.3943 0.03121 *  
d4'   0.00000   0.00000  0.0000 1.00000    
d5    0.00000   0.00000  0.0000 1.00000    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
summary(results,parameter = param_select, t_aggregate = 3,x_aggregate = 1) # A = 1
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation level: 1

Heterogeneity level: Unconditional

      Estimate         SE t-value p-value    
CM  209.516178   2.629379 79.6828 < 2e-16 ***
ACM 210.525742   2.605745 80.7929 < 2e-16 ***
s1  212.101366   2.746747 77.2191 < 2e-16 ***
s2  212.101366   2.746747 77.2191 < 2e-16 ***
s3  212.101366   2.746747 77.2191 < 2e-16 ***
d0  212.101366   2.746747 77.2191 < 2e-16 ***
d1    0.000000   0.000000  0.0000 1.00000    
d2    0.000000   0.000000  0.0000 1.00000    
d3    0.000000   0.000000  0.0000 1.00000    
d4   -2.585188   1.249083 -2.0697 0.05746 .  
d4'  -1.781477   1.158354 -1.5379 0.14635    
d5    0.205853   0.074312  2.7701 0.01504 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Similarly for the average treatment effect:

summary(results,parameter = param_select, t_aggregate = c(3,2),x_aggregate = 1) # A = 1 - A = 0
================= HK decomposition results for =================
Parameters 1, 2, 4, 5, 6, 3, 7, 8, 9, 11, 13, 14

Treatment aggregation contrast: 1 - 0

Heterogeneity level: Unconditional

      Estimate        SE t-value   p-value    
DiM  11.884936  4.002846  2.9691 0.0101541 *  
ADiM 14.745017  3.799012  3.8813 0.0016619 ** 
s1   16.320641  3.898079  4.1868 0.0009136 ***
s2   16.320641  3.898079  4.1868 0.0009136 ***
s3   16.320641  3.898079  4.1868 0.0009136 ***
δ0   16.320641  3.898079  4.1868 0.0009136 ***
δ1    0.000000  0.000000  0.0000 1.0000000    
δ2    0.000000  0.000000  0.0000 1.0000000    
δ3    0.000000  0.000000  0.0000 1.0000000    
δ4   -4.435705  1.637275 -2.7092 0.0169484 *  
δ4'  -1.781477  1.158354 -1.5379 0.1463543    
δ5    0.205853  0.074312  2.7701 0.0150384 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
LS0tCnRpdGxlOiAiU3VwcGxlbWVudGFyeSBSIE5vdGVib29rIgpzdWJ0aXRsZTogIkhldGVyb2dlbmVpdHkgQW5hbHlzaXMgd2l0aCBIZXRlcm9nZW5lb3VzIFRyZWF0bWVudHMiCmF1dGhvcjogIlBoaWxsaXAgSGVpbGVyIGFuZCBNaWNoYWVsIEMuIEtuYXVzIgpkYXRlOiAiMDQvMjUiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgoqKlRhYmxlIG9mIENvbnRlbnRzKioKCi0gW1MuMSBNYWluIHJlc3VsdHNdKCNTMS1NYWluLXJlc3VsdHMpOiBNYWluIGFuYWx5c2lzIHByb2R1Y2luZyB0aGUgcmVzdWx0cyBwcmVzZW50ZWQgaW4gdGhlIHBhcGVyLgogIC0gW1MuMS4xIEdldHRpbmcgcmVhZHldKCNTMS0xLUdldHRpbmctcmVhZHkpOiBMb2FkaW5nIHBhY2thZ2VzLCBmdW5jdGlvbnMsIGFuZCBkYXRhIHByZXBhcmF0aW9uLgogIC0gW1MuMS4yIFRoZSBtYWluIGFuYWx5c2lzXSgjUzEtMi1UaGUtbWFpbi1hbmFseXNpcyk6IFJ1bm5pbmcgdGhlIGVzdGltYXRvciBhbmQgcGxvdHRpbmcgdGhlIHJlc3VsdHMuCi0gW1MuMiBTdXBwbGVtZW50YXJ5IG1hdGVyaWFsXSgjUzItU3VwcGxlbWVudGFyeS1tYXRlcmlhbCk6IEFkZGl0aW9uYWwgYW5hbHlzZXMgYW5kIHJvYnVzdG5lc3MgY2hlY2tzLgogIC0gW1MuMi4xIERlc2NyaXB0aXZlc10oI1MyLTEtRGVzY3JpcHRpdmVzKTogVHJlYXRtZW50IHNoYXJlcyBzaGFyZXMgYnkgZ2VuZGVyLgogIC0gW1MuMi4yIFNjYWxlZCBwLXNjb3JlIGRpc3RyaWJ1dGlvbnNdKCNTMi0yLVNjYWxlZC1wLXNjb3JlLWRpc3RyaWJ1dGlvbnMpOiBBbmFseXNpcyBvZiB0aGUgc2NhbGVkIHByb3BlbnNpdHkgc2NvcmUgaGlzdG9ncmFtcy4KICAtIFtTLjIuMyBTYW1wbGluZyB3ZWlnaHRzXSgjUzItMy1TYW1wbGluZy13ZWlnaHRzKTogUm9idXN0bmVzcyBjaGVjayB3aXRoIHNhbXBsaW5nIHdlaWdodHMuCiAgLSBbUy4yLjQgVGVzdGluZyBzdHJvbmcgZ3JvdXAgZWZmZWN0IGhvbW9nZW5laXR5XSgjUzItNC1UZXN0aW5nLXN0cm9uZy1ncm91cC1lZmZlY3QtaG9tb2dlbmVpdHkpOiBXYWxkIGFuZCBhIHN1cHJlbXVtIHRlc3QuCiAgLSBbUy4yLjUgTW9yZSBwYXJhbWV0ZXJzIGVzdGltYXRlc10oI1MyLTUtTW9yZS1wYXJhbWV0ZXJzLWVzdGltYXRlcyk6IFByaW50aW5nIGFkZGl0aW9uYWwgcGFyYW1ldGVyIGVzdGltYXRlcyBmb3IgY29tcGxldGVuZXNzLgogIC0gW1MuMi42IFVuY29uZGl0aW9uYWwgcmVzdWx0c10oI1VuY29uZGl0aW9uYWwtcmVzdWx0cyk6IERlY29tcG9zaXRpb24gb2YgdW5jb25kaXRpb25hbCBhdmVyYWdlIHBvdGVudGlhbCBvdXRjb21lcyBhbmQgdGhlaXIgZGlmZmVyZW5jZS4KCi0tLQoKVGhlIG1ldGhvZHMgZXhwbGFuYXRpb25zIHRocm91Z2hvdXQgdGhlIG5vdGVib29rIGFyZSBrZXB0IHNob3J0LiBQbGVhc2Ugc2VlIHRoZSBwYXBlciBmb3IgbW9yZSBkZXRhaWxzIHJlZ2FyZGluZyB0aGUgZGVjb21wb3NpdGlvbiBwYXJhbWV0ZXJzIGFuZCB0aGVpciBlc3RpbWF0aW9uLgoKQ2xpY2sgb24gdGhlIOKAnENvZGXigJ0gYnV0dG9uIG9uIHRoZSB0b3AgcmlnaHQgb2YgdGhpcyBub3RlYm9vayB0byDigJxIaWRlIEFsbCBDb2Rl4oCdIGFuZCBzZWUgb25seSB0aGUgcmVzdWx0cyBvciAiRG93bmxvYWQgUm1kIiB0byBleHRyYWN0IHRoZSB1bmRlcmx5aW5nIGNvZGUuCgojIFMuMSBNYWluIHJlc3VsdHMgeyNTMS1NYWluLXJlc3VsdHN9CgojIyBTLjEuMSBHZXR0aW5nIHJlYWR5IHsjUzEtMS1HZXR0aW5nLXJlYWR5fQoKTG9hZCBwYWNrYWdlcywgcHJvamVjdCBzcGVjaWZpYyBmdW5jdGlvbnMsIGFuZCBzZXQgc2VlZDoKCmBgYHtyLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CiMgTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShzYXM3YmRhdCkKbGlicmFyeShjYXVzYWxETUwpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdyZikKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkodmlyaWRpcykKCiMgTG9hZCBwcm9qZWN0IHNwZWNpZmljIGZ1bmN0aW9ucwpzb3VyY2UoIi9ob21lL3JzdHVkaW8vY29kZS9wcm9ic19hbGxfdjEuUiIpCgojIFNldCBzZWVkCnNlZWQgPSAxMjM0CnNldC5zZWVkKHNlZWQpCmBgYAoKTG9hZCB0aGUgZGF0YSB0aGF0IHdlcmUgb2J0YWluZWQgZnJvbSAqaW1wYWN0LnNhczdiZGF0LCBiYXNlbGluZS5zYXM3YmRhdCwga2V5X3ZhcnMuc2FzN2JkYXQsIGFuZCBtaWxlc3Rvbi5zYXM3YmRhdCogZmlsZXMgZnJvbSBbT1BFTklDUFNSXShodHRwczovL3d3dy5vcGVuaWNwc3Iub3JnL29wZW5pY3Bzci9wcm9qZWN0LzExMzI2OS92ZXJzaW9uL1YxL3ZpZXcpIG9uIE1hcmNoIDI0LCAyMDI1ICh1c3VhbGx5IHRha2VzIHNvbWUgbWludXRlcykuCgpgYGB7cn0KIyBMb2FkIGRhdGFzZXRzIGRvd25sb2FkZWQgZnJvbSBodHRwczovL3d3dy5vcGVuaWNwc3Iub3JnL29wZW5pY3Bzci9wcm9qZWN0LzExMzI2OS92ZXJzaW9uL1YxL3ZpZXcKaW1wYWN0X3JhdyA9IHJlYWQuc2FzN2JkYXQoIi9ob21lL3JzdHVkaW8vcmF3X2RhdGEvaW1wYWN0LnNhczdiZGF0IikKYmFzZWxpbmVfcmF3ID0gcmVhZC5zYXM3YmRhdCgiL2hvbWUvcnN0dWRpby9yYXdfZGF0YS9iYXNlbGluZS5zYXM3YmRhdCIpCmtleV92YXJzX3JhdyA9IHJlYWQuc2FzN2JkYXQoIi9ob21lL3JzdHVkaW8vcmF3X2RhdGEva2V5X3ZhcnMuc2FzN2JkYXQiKQptaWxlc3Rvbl9yYXcgPSByZWFkLnNhczdiZGF0KCIvaG9tZS9yc3R1ZGlvL3Jhd19kYXRhL21pbGVzdG9uLnNhczdiZGF0IikKcmFuZF9yYXcgPSByZWFkLnNhczdiZGF0KCIvaG9tZS9yc3R1ZGlvL3Jhd19kYXRhL3JhbmRfZGF0LnNhczdiZGF0IikKYGBgCgpQcmVwYXJlIGRhdGEgZm9yIGFuYWx5c2lzOgoKYGBge3J9CiMgRXh0cmFjdCB0aGUgcmVsZXZhbnQgdmFyaWFibGVzCmltcGFjdCA9IHNlbGVjdChpbXBhY3RfcmF3LE1QUklELEVBUk5ZNCxFVkVSSkNIKQppbXBhY3RfdGVtcCA9IHNlbGVjdChpbXBhY3RfcmF3LE1QUklELEpDVkNMRVJDLEpDVkhMVEgsSkNWQVVUTyxKQ1ZXRUxELEpDVkVMVFJDLEpDVkNTVFJDLEpDVkZPT0QsSkNWRVRSTkMsSkNWT1RIKQpiYXNlbGluZSA9IHNlbGVjdChiYXNlbGluZV9yYXcsTVBSSUQsUkFDRV9FVEgsSFNfRCxHRURfRCxWT0NfRCxBTllfRUQxLEhHQyxOVFZfTEFORyxXS0VBUk5SLAogICAgICAgICAgICAgICAgICBIQVNDSExELE1BUlJJQUdFLFJfSEVBRCxISE1FTUIsSEVBTFRILFBZX0NJRyxQWV9BTENITCwKICAgICAgICAgICAgICAgICAgUFlfUE9ULEhBRFdPUlJZLEhFQVJfSkMsS05FV0NOVFIsRV9NQVRILEVfUkVBRCxFX0FMT05HLAogICAgICAgICAgICAgICAgICBFX0NPTlRSTCxFX0VTVEVFTSxFX1NQQ0pPQixFX0ZSSUVORCxLTkVXX0pDLEVBUk5fWVIpCmtleV92YXJzID0gc2VsZWN0KGtleV92YXJzX3JhdyxNUFJJRCxUUkVBVE1OVCxGRU1BTEUsQUdFX0NBVCxFRFVDX0dSLE5PTlJFUyxJTjU3KQptaWxlc3RvbiA9IHNlbGVjdChtaWxlc3Rvbl9yYXcsTVBSSUQsTElWRVNQT1UsRVZFUldPUkssWVJfV09SSyxDVVJSSk9CLAogICAgICAgICAgICAgICAgICBKT0IwXzMsIEpPQjNfOSwgSk9COV8xMiwgTU9TVFdFTEYsR09UX0FGREMsR09UX0ZTLEVEMF82LEVENl8xMiwKICAgICAgICAgICAgICAgICAgUFVCTElDSCxCQURITFRILEhBUkRVU0UsUE9UVVNFLEVWQVJSU1QsUE1TQSxNU0EsUFJBUlJJKQpyYW5kID0gc2VsZWN0KHJhbmRfcmF3LE1QUklELFJBTkRfV0spCgojIENvZGUgdGhlIHZlcnNpb25zCnZlcnNpb25zID0gcmVwKCJOb3RoaW5nIixucm93KGltcGFjdCkpCnZlcnNpb25zW2ltcGFjdF90ZW1wWywyXSA9PSAxXSA9ICJDbGVyaWNhbCIKdmVyc2lvbnNbaW1wYWN0X3RlbXBbLDNdID09IDFdID0gIkhlYWx0aCIKdmVyc2lvbnNbaW1wYWN0X3RlbXBbLDRdID09IDFdID0gIkF1dG8iCnZlcnNpb25zW2ltcGFjdF90ZW1wWyw1XSA9PSAxXSA9ICJXZWxkaW5nIgp2ZXJzaW9uc1tpbXBhY3RfdGVtcFssNl0gPT0gMSB8IGltcGFjdF90ZW1wWyw5XSA9PSAxXSA9ICJFbGVjdHJpY2FsIgp2ZXJzaW9uc1tpbXBhY3RfdGVtcFssN10gPT0gMV0gPSAiQ29uc3RydWN0aW9uIgp2ZXJzaW9uc1tpbXBhY3RfdGVtcFssOF0gPT0gMV0gPSAiRm9vZCIKdmVyc2lvbnNbaW1wYWN0X3RlbXBbLDEwXSA9PSAxXSA9ICJPdGhlciIKdmVyc2lvbnNbcm93U3VtcyhpbXBhY3RfdGVtcFssMjoxMF0sbmEucm09VCkgPiAxXSA9ICJNdWx0aXBsZSIKaW1wYWN0ID0gY2JpbmQoaW1wYWN0LHZlcnNpb25zKQoKIyBNZXJnZSB0aGUgZGF0YQppbm5lcl9qb2luKGltcGFjdCxiYXNlbGluZSxieT0iTVBSSUQiKSAlPiUgaW5uZXJfam9pbihrZXlfdmFycyxieT0iTVBSSUQiKSAgJT4lIGlubmVyX2pvaW4obWlsZXN0b24sYnk9Ik1QUklEIikgJT4lIGlubmVyX2pvaW4ocmFuZCxieT0iTVBSSUQiKSAlPiUKICBtdXRhdGUoUkFDRV9XID0gYXMubnVtZXJpYyhSQUNFX0VUSCA9PSAxKSkgJT4lICBtdXRhdGUoUkFDRV9CID0gYXMubnVtZXJpYyhSQUNFX0VUSCA9PSAyKSkgJT4lCiAgbXV0YXRlKFJBQ0VfSCA9IGFzLm51bWVyaWMoUkFDRV9FVEggPT0gMykpICU+JSAgbXV0YXRlKFJBQ0VfTyA9IGFzLm51bWVyaWMoUkFDRV9FVEggPT0gNCkpICU+JSAKICBtdXRhdGUoV0tFQVJOUiA9IHJlcGxhY2UoV0tFQVJOUixpcy5uYShXS0VBUk5SKSwwKSkgJT4lCiAgbXV0YXRlKEVBUk5fWVIgPSByZXBsYWNlKEVBUk5fWVIsaXMubmEoRUFSTl9ZUiksMCkpIC0+IGRiCgojIFJlbW92ZSBvYnNlcnZhdGlvbnMgd2l0aCBtaXNzaW5nIHZhbHVlcwpkYiAlPiUgbmEub21pdCgpIC0+IGRiCgojIENyZWF0ZSBtYWluIHZhcmlhYmxlcwpZID0gYXMubWF0cml4KHNlbGVjdChkYixFQVJOWTQpKQpEID0gYXMubWF0cml4KHNlbGVjdChkYixUUkVBVE1OVCkpCgojIEhldGVyb2dlbmVpdHkgdmFyaWFibGUKZmVtYWxlID0gc2VsZWN0KGRiLEZFTUFMRSkKZmVtX21hdCA9IGNiaW5kKDEtZmVtYWxlLGZlbWFsZSkKbGFiZWxfZmVtID0gYygiTWFsZSIsIkZlbWFsZSIpCmNvbG5hbWVzKGZlbV9tYXQpID0gbGFiZWxfZmVtCmZlbWFsZSA9IGZhY3RvcihpZmVsc2UoZmVtYWxlID09IDEsICJmZW1hbGUiLCAibWFsZSIpLAogICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIm1hbGUiLCAiZmVtYWxlIikpCgojIENyZWF0ZSB2ZXJzaW9ucwpKQyA9IGRiJEVWRVJKQ0gKVHIgPSByZXAoTkEsbGVuZ3RoKFkpKQpUcltEID09IDBdID0gIkNvbnRyb2wiClRyW0QgPT0gMSAmIEpDID09IDBdID0gIk5vIEpDIgpUcltEID09IDEgJiBKQyA9PSAxICYgZGIkdmVyc2lvbnMgPT0gIkNsZXJpY2FsIl0gPSAiQ2xlcmljYWwiClRyW0QgPT0gMSAmIEpDID09IDEgJiBkYiR2ZXJzaW9ucyA9PSAiSGVhbHRoIl0gPSAiSGVhbHRoIgpUcltEID09IDEgJiBKQyA9PSAxICYgZGIkdmVyc2lvbnMgPT0gIkF1dG8iXSA9ICJBdXRvIgpUcltEID09IDEgJiBKQyA9PSAxICYgZGIkdmVyc2lvbnMgPT0gIldlbGRpbmciXSA9ICJXZWxkaW5nIgpUcltEID09IDEgJiBKQyA9PSAxICYgZGIkdmVyc2lvbnMgPT0gIkVsZWN0cmljYWwiXSA9ICJFbGVjdHJpY2FsIgpUcltEID09IDEgJiBKQyA9PSAxICYgZGIkdmVyc2lvbnMgPT0gIkNvbnN0cnVjdGlvbiJdID0gIkNvbnN0cnVjdGlvbiIKVHJbRCA9PSAxICYgSkMgPT0gMSAmIGRiJHZlcnNpb25zID09ICJGb29kIl0gPSAiRm9vZCIKVHJbRCA9PSAxICYgSkMgPT0gMSAmIGRiJHZlcnNpb25zID09ICJPdGhlciJdID0gIk90aGVyIgpUcltEID09IDEgJiBKQyA9PSAxICYgZGIkdmVyc2lvbnMgPT0gIk11bHRpcGxlIl0gPSAiTXVsdGlwbGUiClRyW2lzLm5hKFRyKV0gPSAiSkMgdy9vIHZvYyIKbGFiZWxfVCA9IGMoIkNvbnRyb2wiLCJObyBKQyIsIkpDIHcvbyB2b2MiLCJDbGVyaWNhbCIsIkhlYWx0aCIsIkF1dG8iLCJXZWxkaW5nIiwiRWxlY3RyaWNhbCIsCiAgICAgICAgICAgICJDb25zdHJ1Y3Rpb24iLCJGb29kIiwiT3RoZXIiLCJNdWx0aXBsZSIpClRyID0gZmFjdG9yKFRyLGxldmVscz1sYWJlbF9UKQoKCiMgQ3JlYXRlIGNvbnRyb2wgbWF0cml4ClggPSBhcy5tYXRyaXgoc2VsZWN0KGRiLEZFTUFMRSxBR0VfQ0FULFJBQ0VfVyxSQUNFX0IsUkFDRV9ILFJBQ0VfTyxFRFVDX0dSLAogICAgICAgICAgICAgICAgICAgICBMSVZFU1BPVSxFVkVSV09SSyxZUl9XT1JLLENVUlJKT0IsSk9CMF8zLCBKT0IzXzksIEpPQjlfMTIsCiAgICAgICAgICAgICAgICAgICAgIE1PU1RXRUxGLEdPVF9BRkRDLEdPVF9GUyxFRDBfNixFRDZfMTIsUFVCTElDSCxCQURITFRILEhBUkRVU0UsUE9UVVNFLEVWQVJSU1QsUE1TQSxNU0EsCiAgICAgICAgICAgICAgICAgICAgIEhTX0QsR0VEX0QsVk9DX0QsQU5ZX0VEMSxIR0MsTlRWX0xBTkcsV0tFQVJOUiwKICAgICAgICAgICAgICAgICAgICAgSEFTQ0hMRCxNQVJSSUFHRSxSX0hFQUQsSEhNRU1CLEhFQUxUSCxQWV9DSUcsUFlfQUxDSEwsCiAgICAgICAgICAgICAgICAgICAgIFBZX1BPVCxIQURXT1JSWSxIRUFSX0pDLEtORVdDTlRSLEVfTUFUSCxFX1JFQUQsRV9BTE9ORywKICAgICAgICAgICAgICAgICAgICAgRV9DT05UUkwsRV9FU1RFRU0sRV9TUENKT0IsRV9GUklFTkQsS05FV19KQyxOT05SRVMsUFJBUlJJLEVBUk5fWVIsUkFORF9XSyxJTjU3KSkKYGBgCgoKIyMgUy4xLjIgVGhlIG1haW4gYW5hbHlzaXMgeyNTMS0yLVRoZS1tYWluLWFuYWx5c2lzfQoKVGhlIG51aXNhbmNlIHBhcmFtZXRlcnMgYXJlIG9idGFpbmVkIHVzaW5nIHRoZSBtdWx0aS12YWx1ZWQgdHJlYXRtZW50IGVmZmVjdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgW2NhdXNhbERNTF0oaHR0cHM6Ly9naXRodWIuY29tL01DS25hdXMvY2F1c2FsRE1MKSBwYWNrYWdlLiBGb3IgdGhlIG91dGNvbWUgbW9kZWxzLCB3ZSBzd2l0Y2ggb2ZmIHRoZSBob25lc3R5IG9wdGlvbiwgYmVjYXVzZSBzYW1wbGUgc2l6ZSBpbiBzb21lIGVmZmVjdGl2ZSB0cmVhdG1lbnRzIGlzIHRvbyBzbWFsbCB0byB0dW5lIHBhcmFtZXRlcnMgd2l0aCBob25lc3R5IChyYW4gcm91Z2hseSBoYWxmIGFuIGhvdXIpLgoKYGBge3J9CiMgRGVmaW5lIG1ldGhvZHMKZm9yZXN0X2hvbiA9IGNyZWF0ZV9tZXRob2QoImZvcmVzdF9ncmYiLGFyZ3M9bGlzdCh0dW5lLnBhcmFtZXRlcnMgPSAiYWxsIikpICMgZm9yIHBzY29yZXMKZm9yZXN0ID0gY3JlYXRlX21ldGhvZCgiZm9yZXN0X2dyZiIsYXJncz1saXN0KGhvbmVzdHkgPSBGLHR1bmUucGFyYW1ldGVycyA9ICJhbGwiKSkgIyBmb3Igb3V0Y29tZSBiL2MgdG9vIGZldyBvYnNlcnZhdGlvbnMgZm9yIGhvbmVzdCBSRgoKIyBSdW4gbXVsdGlwbGUgdHJlYXRtZW50IG1vZGVsIHRvIGdldCBudWlzYW5jZSBwYXJhbWV0ZXJzCmFpcHcgPSBETUxfYWlwdyhZLFRyLFgsCiAgICAgICAgICAgICAgICBtbF93PWxpc3QoZm9yZXN0X2hvbiksCiAgICAgICAgICAgICAgICBtbF95PWxpc3QoZm9yZXN0KSwgCiAgICAgICAgICAgICAgICBxdWlldD1ULCAjIFN3aXRjaCBvZmYgdG8gc2VlIHByb2dyZXNzCiAgICAgICAgICAgICAgICBjZiA9IDUpCmBgYAoKUnVuIHRoZSBkZWNvbXBvc2l0aW9uOgoKYGBge3J9CiMgUnVuIEhLIGRlY29tcApyZXN1bHRzID0gSEsyX2RlY29tcG9zaXRpb24oWSxELGZlbWFsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYWlwdyRBUE8kd19tYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcHckQVBPJGVfbWF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICBhaXB3JEFQTyRtX21hdCkKIyBQcmludCB0aGUgc2V0dGluZwpyZXN1bHRzCmBgYAoKUHJpbnQsIHBsb3QgYW5kIHNhdmUgcmVzdWx0cyBmb3IgRGlNOgpgYGB7cn0KZyA9IHBsb3QocmVzdWx0cyxsZXZlbHMgPSBULCBwZV9kaWdpdHMgPSAxLGRlY29tcG9zaXRpb24gPSAiZGltIikKZwpnZ3NhdmUoIi9ob21lL3JzdHVkaW8vcmVzdWx0cy9EaU0ucG5nIixnLHdpZHRoID0gNyxoZWlnaHQ9NCkKRGVsdGFfZGltID0gc3VtbWFyeShyZXN1bHRzLHBhcmFtZXRlciA9ICJkaW0iLCB0X2FnZ3JlZ2F0ZSA9IGMoMywyKSx4X2FnZ3JlZ2F0ZSA9IGMoMywyKSkgIyBGZW1hbGUgLSBNYWxlCmBgYAoKUHJpbnQsIHBsb3QgYW5kIHNhdmUgcmVzdWx0cyBmb3IgYWRqdXN0ZWQgRGlNOgpgYGB7cn0KZyA9IHBsb3QocmVzdWx0cyxsZXZlbHMgPSBULCBwZV9kaWdpdHMgPSAxLGRlY29tcG9zaXRpb24gPSAiYWRpbSIpCmcKZ2dzYXZlKCIvaG9tZS9yc3R1ZGlvL3Jlc3VsdHMvQURpTS5wbmciLGcsd2lkdGggPSA3LGhlaWdodD00KQpzdW1tYXJ5KHJlc3VsdHMscGFyYW1ldGVyID0gImFkaW0iLCB0X2FnZ3JlZ2F0ZSA9IGMoMywyKSx4X2FnZ3JlZ2F0ZSA9IGMoMywyKSkgIyBGZW1hbGUgLSBNYWxlCmBgYAoKQ3JlYXRlIHRoZSBjb25kZW5zZWQgZmlndXJlIGluIHRoZSBpbnRyb2R1Y3Rpb246CgpgYGB7cn0KcmVzID0gRGVsdGFfZGltWzM6NixjKDEsNCldCgojIE9yaWdpbmFsIGxhYmVscwpiYXNlX2xhYmVscyA8LSBjKCJFZmZlY3QgaGV0ZXJvZ2VuZWl0eSIsCiAgICAgICAgICAgICAgICAgIkdyb3VwIHRhcmdldGluZyBvZiBhdmVyYWdlIG91dGNvbWVzIiwKICAgICAgICAgICAgICAgICAiR3JvdXAgdGFyZ2V0aW5nIG9mIGdyb3VwIG91dGNvbWVzIiwKICAgICAgICAgICAgICAgICAiSW5kaXZpZHVhbGl6ZWQgdGFyZ2V0aW5nIikKCiMgQ29uc3RydWN0IGxhYmVscyB3aXRoIHAtdmFsdWVzIChyb3VuZGVkIHRvIDMgZGVjaW1hbCBwbGFjZXMpCmZ1bGxfbGFiZWxzIDwtIHBhc3RlMChiYXNlX2xhYmVscywgIiAocC12YWx1ZTogIiwgc3ByaW50ZigiJS4zZiIsIHJlc1ssMl0pLCAiKSIpCgojIENyZWF0ZSBmYWN0b3Igd2l0aCByZXZlcnNlZCBvcmRlciB0byBwcmVzZXJ2ZSB0b3AtdG8tYm90dG9tIGxheW91dApkZiA8LSBkYXRhLmZyYW1lKAogIGxhYmVsID0gZmFjdG9yKGZ1bGxfbGFiZWxzLCBsZXZlbHMgPSByZXYoZnVsbF9sYWJlbHMpKSwKICBlc3RpbWF0ZSA9IHJlc1ssMV0KKQoKIyBQbG90IHdpdGhvdXQgY29uZmlkZW5jZSBpbnRlcnZhbHMKZyA9IGdncGxvdChkZiwgYWVzKHggPSBlc3RpbWF0ZSwgeSA9IGxhYmVsKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gdmlyaWRpcygxLGFscGhhPTAuOSwgYmVnaW49MC4zKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsKICBsYWJzKHggPSAiRXN0aW1hdGUgaW4gJCIsIHkgPSAiIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKyB4bGltKC04LDApCmcKZ2dzYXZlKCIvaG9tZS9yc3R1ZGlvL3Jlc3VsdHMvSW50cm9fZ3JhcGhfcC5wbmciLGcsd2lkdGggPSA3LGhlaWdodD0yKQpgYGAKCgoKU2F2ZSBpbWFnZS4KYGBge3J9CnNhdmUuaW1hZ2UoIi9ob21lL3JzdHVkaW8vcmVzdWx0cy9JbWFnZS5SRGF0YSIpCmBgYAoKCiMgUy4yIFN1cHBsZW1lbnRhcnkgbWF0ZXJpYWwgeyNTMi1TdXBwbGVtZW50YXJ5LW1hdGVyaWFsfQoKIyMgUy4yLjEgRGVzY3JpcHRpdmVzIHsjUzItMS1EZXNjcmlwdGl2ZXN9CgpXZSBwbG90IGZyYWN0aW9ucyBvZiBlZmZlY3RpdmUgdHJlYXRtZW50cyBieSBnZW5kZXIgdG8gaWxsdXN0cmF0ZSBob3cgZGlmZmVyZW50IHRoZSBKb2IgQ29ycHMgZXhwZXJpZW5jZSBpcyB3aXRoIHJlc3BlY3QgdG8gdm9jYXRpb25hbCB0cmFpbmluZyByZWNlaXZlZDoKCmBgYHtyfQpnMSA9IGRhdGEuZnJhbWUoeD1mYWN0b3IoZmVtYWxlKSwgVmVyc2lvbj1mYWN0b3IoVHIsbGV2ZWxzPXJldihsYWJlbF9UKSkpICU+JSAKICBnZ3Bsb3QoYWVzKHg9eCwgZmlsbD1WZXJzaW9uKSkrZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIsIGNvbG91cj0iYmxhY2siLGxpbmV3aWR0aD0wLjAxKSArCiAgeWxhYigiRnJhY3Rpb24iKSArIHNjYWxlX2ZpbGxfZ3JleShzdGFydCA9IDAsIGVuZCA9IDEpICsgdGhlbWVfYncoKSArIAogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCmcyID0gZGF0YS5mcmFtZSh4PWZhY3RvcihmZW1hbGUpLCBWZXJzaW9uPWZhY3RvcihUcixsZXZlbHM9cmV2KGxhYmVsX1QpKSkgJT4lCiAgZmlsdGVyKFZlcnNpb24gIT0gIkNvbnRyb2wiKSAlPiUgZmlsdGVyKFZlcnNpb24gIT0gIk5vIEpDIikgJT4lIGZpbHRlcihWZXJzaW9uICE9ICJKQyB3aXRob3V0IHZvYyIpICU+JSAKICBnZ3Bsb3QoYWVzKHg9eCwgZmlsbD1WZXJzaW9uKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgY29sb3VyPSJibGFjayIsbGluZXdpZHRoPTAuMDEpICsgCiAgeWxhYigiRnJhY3Rpb24gY29uZGl0aW9uYWwgb24gdm9jYXRpb25hbCB0cmFpbmluZyIpICsgc2NhbGVfZmlsbF9ncmV5KHN0YXJ0ID0gMCwgZW5kID0gMC45KSArIAogIHRoZW1lX2J3KCkgKyB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgCgpnID0gZzEgKyBnMgpnCmBgYApTZWUgYWxzbyB0aGUgbnVtYmVycyBoZXJlOgoKYGBge3J9CiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIHRoZSByZWxldmFudCB2YXJpYWJsZXMKZGYgPSBkYXRhLmZyYW1lKGZlbWFsZSA9IGZlbWFsZSwgVHIgPSBUcikKCiMgQ29tcHV0ZSB0aGUgcGVyY2VudGFnZSBzaGFyZXMKdGFiX2ZlbWFsZSA9IHByb3AudGFibGUodGFibGUoZGYkVHJbZGYkZmVtYWxlID09ICJmZW1hbGUiXSkpICogMTAwCnRhYl9tYWxlICAgPSBwcm9wLnRhYmxlKHRhYmxlKGRmJFRyW2RmJGZlbWFsZSA9PSAibWFsZSJdKSkgKiAxMDAKdGFiX2FsbCAgICA9IHByb3AudGFibGUodGFibGUoZGYkVHIpKSAqIDEwMAoKIyBDb21iaW5lIHRoZSByZXN1bHRzIGludG8gYSB0YWJsZSB3aXRoIGZvcm1hdHRlZCBwZXJjZW50YWdlcwp0YWJsZV9zaGFyZXMgPSBjYmluZCgKICBGZW1hbGUgPSBzcHJpbnRmKCIlMS4xZiIsIHRhYl9mZW1hbGUpLAogIE1hbGUgICA9IHNwcmludGYoIiUxLjFmIiwgdGFiX21hbGUpLAogIEFsbCAgICA9IHNwcmludGYoIiUxLjFmIiwgdGFiX2FsbCkKKQoKIyBFbnN1cmUgdGhlIHJvdyBuYW1lcyBhcmUgY29uc2lzdGVudCB3aXRoIHRoZSBvdmVyYWxsIHRhYmxlCnJvd25hbWVzKHRhYmxlX3NoYXJlcykgPSBuYW1lcyh0YWJfYWxsKQoKIyBQcmludCB0aGUgdGFibGUgYXMgYSBkYXRhIGZyYW1lCmFzLmRhdGEuZnJhbWUodGFibGVfc2hhcmVzKQpgYGAKCgojIyBTLjIuMiBTY2FsZWQgcC1zY29yZSBkaXN0cmlidXRpb25zIHsjUzItMi1TY2FsZWQtcC1zY29yZS1kaXN0cmlidXRpb25zfQoKVGhlIG1haW4gdGV4dCBkaXNjdXNzZXMgaG93IHRoZSB3ZWFrIGVmZmVjdGl2ZSBvdmVybGFwIGFzc3VtcHRpb24gQS40IGNhbiBiZSBpbnNwZWN0ZWQgYnkgY2hlY2tpbmcgc2NhbGVkIHByb3BlbnNpdHkgc2NvcmVzLiBIZXJlIHdlIHBsb3QgdGhlIHNjYWxlZCBkaXN0cmlidXRpb25zOgoKYGBge3J9CiMgQ29udmVydCB0aGUgbWF0cml4IHRvIGEgZGF0YSBmcmFtZSBhbmQgYWRkIGFuIGlkZW50aWZpZXIgZm9yIHJvd3MKZGYgPC0gYXMuZGF0YS5mcmFtZShhaXB3JEFQTyRlX21hdFssLTFdKSAlPiUgCiAgbXV0YXRlKGlkID0gcm93X251bWJlcigpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtaWQsIG5hbWVzX3RvID0gInZhcmlhYmxlIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lIAogIGdyb3VwX2J5KHZhcmlhYmxlKSAlPiUgCiAgIyBEaXZpZGUgZWFjaCB2YWx1ZSBieSB0aGUgbWVhbiBvZiBpdHMgcmVzcGVjdGl2ZSBjb2x1bW4KICBtdXRhdGUobm9ybV92YWx1ZSA9IHZhbHVlIC8gbWVhbih2YWx1ZSkpICU+JSAKICB1bmdyb3VwKCkKCiMgUGxvdCBoaXN0b2dyYW1zIHdpdGggZGVuc2l0eSBvbiB0aGUgeS1heGlzIGFuZCBzaGFyZWQgeC1heGlzIGFjcm9zcyBmYWNldHMKZ2dwbG90KGRmLCBhZXMoeCA9IG5vcm1fdmFsdWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwgYmlucyA9IDMwLCBmaWxsID0gImJsdWUiLCBjb2xvciA9ICJibGFjayIpICsKICBmYWNldF93cmFwKH4gdmFyaWFibGUpICsgICMgbm8gc2NhbGVzID0gImZyZWVfeCIKICBsYWJzKHggPSAiU2NhbGVkIHAtc2NvcmUiLCB5ID0gIkRlbnNpdHkiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKVGhlIG1pbmltdW0gc2NhbGVkIHByb3BlbnNpdHkgc2NvcmUgaXMgYHIgc3ByaW50ZigiJS4yZiIsIG1pbihkZiRub3JtX3ZhbHVlKSlgIGFuZCB0aGVyZWZvcmUgbXVjaCBsYXJnZXIgdGhhbiB3aGF0IHVzdWFsbHkgd291bGQgYmUgY29uc2lkZXJlZCBhcyBwcm9ibGVtYXRpYyBpbiBzdGFuZGFyZCBzZXR0aW5ncy4gRm9yIG1vc3Qgb2YgdGhlIHRyYWluaW5ncywgd2Ugb2JzZXJ2ZSBhIGJpbW9kYWwgc2hhcGUuIFRoaXMgaXMgYmVjYXVzZSBnZW5kZXIgaXMgdGhlIG1vc3QgaW1wb3J0YW50IHByZWRpY3RvciBvZiB2b2NhdGlvbmFsIHRyYWluaW5nIGFuZCByYW5kb20gZm9yZXN0cyBhcmUgY2FwYWJsZSBvZiBjYXB0dXJpbmcgdGhpcyBwYXR0ZXJuLgoKCiMjIFMuMi4zIFNhbXBsaW5nIHdlaWdodHMgeyNTMi0zLVNhbXBsaW5nLXdlaWdodHN9CgpVc2luZyBzYW1wbGluZyB3ZWlnaHRzIHRvIGFjY291bnQgZm9yIHRoZSBub3QgY29tcGxldGVseSByYW5kb20gc2FtcGxpbmcgcHJvY2VkdXJlIG9mIHRoZSBKb2IgQ29ycHMgZXZhbHVhdGlvbiBzaG93cyBubyBxdWFsaXRhdGl2ZSBkaWZmZXJlbmNlcyB0byBtYWluIHJlc3VsdHM6CgpgYGB7cn0KIyBDcmVhdGUgc2FtcGxpbmcgd2VpZ2h0cwpzYW1wbGluZ193ZWlnaHRzID0gcHJvcHNfYWxsKGRiKSR3ZWlnaHRzX1J4CgojIEZvciBjb21wYXJpc29uIHB1cnBvc2VzIHJ1biB3aXRoIHNhbXBsaW5nIHdlaWdodHMKcmVzdWx0c3cgPSBISzJfZGVjb21wb3NpdGlvbihZLEQsZmVtYWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWlwdyRBUE8kd19tYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhaXB3JEFQTyRlX21hdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcHckQVBPJG1fbWF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxpbmdfd2VpZ2h0cyA9IHNhbXBsaW5nX3dlaWdodHMpCgpnID0gcGxvdChyZXN1bHRzdyxsZXZlbHMgPSBULCBwZV9kaWdpdHMgPSAxLGRlY29tcG9zaXRpb24gPSAiZGltIiwKICAgICAgICAgdF9hZ2dyZWdhdGUgPSBjKDMsMikseF9hZ2dyZWdhdGUgPSBjKDMsMikpCmcKZ2dzYXZlKCIvaG9tZS9yc3R1ZGlvL3Jlc3VsdHMvRGlNdy5wbmciLGcsd2lkdGggPSA3LGhlaWdodD00KQpnID0gcGxvdChyZXN1bHRzdyxsZXZlbHMgPSBULCBwZV9kaWdpdHMgPSAxLGRlY29tcG9zaXRpb24gPSAiYWRpbSIsCiAgICAgICAgIHRfYWdncmVnYXRlID0gYygzLDIpLHhfYWdncmVnYXRlID0gYygzLDIpKQpnCmdnc2F2ZSgiL2hvbWUvcnN0dWRpby9yZXN1bHRzL0FEaU13LnBuZyIsZyx3aWR0aCA9IDcsaGVpZ2h0PTQpCgpzdW1tYXJ5KHJlc3VsdHN3LHBhcmFtZXRlciA9ICJkaW0iLCB0X2FnZ3JlZ2F0ZSA9IGMoMywyKSx4X2FnZ3JlZ2F0ZSA9IGMoMywyKSkKc3VtbWFyeShyZXN1bHRzdyxwYXJhbWV0ZXIgPSAiYWRpbSIsIHRfYWdncmVnYXRlID0gYygzLDIpLHhfYWdncmVnYXRlID0gYygzLDIpKQpgYGAKCgoKIyMgUy4yLjQgVGVzdGluZyBzdHJvbmcgZ3JvdXAgZWZmZWN0IGhvbW9nZW5laXR5IHsjUzItNC1UZXN0aW5nLXN0cm9uZy1ncm91cC1lZmZlY3QtaG9tb2dlbmVpdHl9CgpUaGUgZGVjb21wb3NpdGlvbiBpbmRpY2F0ZXMgdGhhdCB0aGVyZSBpcyBubyByZWFsIGVmZmVjdCBoZXRlcm9nZW5laXR5IGF0IHRoZSBsZXZlbCBvZiB0aGUgZWZmZWN0aXZlIHRyZWF0bWVudC4gSG93ZXZlciwgJFxEZWx0YV8xJCBpcyBvbmx5IGEgbmVjZXNzYXJ5IHRlc3QgZm9yIHN0cm9uZyBncm91cCBlZmZlY3QgaG9tb2dlbmVpdHkgYXMgZGlzY3Vzc2VkIGluIFNlY3Rpb24gNC42IG9mIHRoZSBwYXBlci4gVGh1cywgd2UgaW52ZXN0aWdhdGUgZWZmZWN0IGhldGVyb2dlbmVpdHkgZm9yIGVhY2ggZWZmZWN0aXZlIHRyZWF0bWVudCB0byBzZWUgd2hldGhlciBzaWduaWZpY2FudCBlZmZlY3QgaGV0ZXJvZ2VuZWl0eSBpcyBtYXNrZWQgYnkgdGhlIGRlY29tcG9zaXRpb24gZXN0aW1hbmQuCgojIyMgR0FURSBkaWZmZXJlbmNlIHBvaW50IGVzdGltYXRlcwoKRmlyc3QsIHdlIGVzdGltYXRlIGdyb3VwIGF2ZXJhZ2UgdHJlYXRtZW50IGVmZmVjdCAoR0FURSkgZGlmZmVyZW5jZXMsIGkuZS4gJEVbWSh0KS1ZKDApfGZlbWFsZV0gLSBFW1kodCktWSgwKXxtYWxlXSQsIGZvciBlYWNoIHRyZWF0bWVudCB2ZXJzaW9uOgoKYGBge3J9CiMgSW5pdGlhbGl6ZSBEaU0gZm9yIGVhY2ggZWZmZWN0aXZlIHRyZWF0bWVudCBhbmQgSUZzIGZvciBpbmZlcmVuY2UgbGF0ZXIKbiA9IGxlbmd0aChZKQpKID0gbGVuZ3RoKGxhYmVsX1QpLTEKRyA9IChmZW1hbGUgPT0gImZlbWFsZSIpKjEKZEdBVEVzID0gbWF0cml4KE5BLEosNSkKcm93bmFtZXMoZEdBVEVzKSA9IGxhYmVsX1RbLTFdCmNvbG5hbWVzKGRHQVRFcykgPSBjKCJHQVRFIiwiUy5FLiIsInQtdmFsdWUiLCJwb2ludHdpc2UgcC12YWx1ZSIsInVuaWZvcm0gcC12YWx1ZSIpCklGcyA9IG1hdHJpeChOQSxsZW5ndGgoWSksSikKZm9yIChqIGluIDE6SikgewogIGRHQVRFc1tqLDFdID0gbWVhbihhaXB3JEFURSRkZWx0YVssal0gKiBHIC8gbWVhbihHKSAtIGFpcHckQVRFJGRlbHRhWyxqXSAqICgxLUcpIC8gbWVhbigxLUcpKQogIElGc1ssal0gPSBhaXB3JEFURSRkZWx0YVssal0gKiBHIC8gbWVhbihHKSAtIGFpcHckQVRFJGRlbHRhWyxqXSAqICgxLUcpIC8gbWVhbigxLUcpIC0gZEdBVEVzW2pdCn0KCiMgRXN0aW1hdGUgdGhlIGNvdmFyaWFuY2UgbWF0cml4IHZpYSBJRgpTaWdtYV9oYXQgPSB2YXIoSUZzKQoKIyBDb2xsZWN0IHBvaW50IGVzdGltYXRlcyBhbmQgU0VzCmRHQVRFc1ssMl0gPSBzcXJ0KGRpYWcoU2lnbWFfaGF0KSAvIG4pCmRHQVRFc1ssM10gPSBkR0FURXNbLDFdIC8gZEdBVEVzWywyXQpkR0FURXNbLDRdID0gMiAqICgxIC0gcHQoYWJzKGRHQVRFc1ssM10pLCBuKSkKCnN1cF90ID0gZnVuY3Rpb24oZGltajAsWXRpbGRlLEcsYWxwaGEgPSAwLjA1LHJlcHMgPSAxMDAwMCkgewogIG4gPSBucm93KFl0aWxkZSkKICBKID0gbmNvbChZdGlsZGUpCiAgIyBicm93c2VyKCkKICBsYXJnZXN0X3RzID0gcmVwKDAscmVwcykKICAKICBmb3IgKGkgaW4gMTpyZXBzKSB7CiAgICAjIEdlbmVyYXRlIGJvb3RzdHJhcCBpbmRpY2VzCiAgICBib290c3RyYXBfaW5kaWNlcyA9IHNhbXBsZSgxOm4sIHNpemUgPSBuLCByZXBsYWNlID0gVFJVRSkKICAgIAogICAgIyBCb290c3RyYXAgc2FtcGxlcwogICAgYm9vdHN0cmFwX1l0aWxkZSA9IFl0aWxkZVtib290c3RyYXBfaW5kaWNlcyxdCiAgICBib290c3RyYXBfRyA9IEdbYm9vdHN0cmFwX2luZGljZXNdIAogICAgCiAgICBmb3IgKGogaW4gMTpKKSB7CiAgICAgIG1lYW5fMSA9IG1lYW4oYm9vdHN0cmFwX1l0aWxkZVtib290c3RyYXBfRyA9PSAxLGpdKQogICAgICBtZWFuXzAgPSBtZWFuKGJvb3RzdHJhcF9ZdGlsZGVbYm9vdHN0cmFwX0cgPT0gMCxqXSkKICAgICAgZGltX2Jvb3QgPSBtZWFuXzEgLSBtZWFuXzAKICAgICAgdmFyXzEgPSB2YXIoYm9vdHN0cmFwX1l0aWxkZVtib290c3RyYXBfRyA9PSAxLGpdKQogICAgICB2YXJfMCA9IHZhcihib290c3RyYXBfWXRpbGRlW2Jvb3RzdHJhcF9HID09IDAsal0pCiAgICAgIG5fMSA9IHN1bShib290c3RyYXBfRyA9PSAxKQogICAgICBuXzAgPSBzdW0oYm9vdHN0cmFwX0cgPT0gMCkKICAgICAgc2VfYm9vdCA9IHNxcnQodmFyXzEgLyBuXzEgKyB2YXJfMCAvIG5fMCkKICAgICAgdF92YWwgPSBhYnMoKGRpbV9ib290IC0gZGltajBbal0pIC8gc2VfYm9vdCkKICAgICAgaWYgKGlzLm5hKHRfdmFsKSkgbmV4dAogICAgICBlbHNlIGlmICh0X3ZhbCA+IGxhcmdlc3RfdHNbaV0pIGxhcmdlc3RfdHNbaV0gPSB0X3ZhbAogICAgfQogIH0KICBDViA9IHF1YW50aWxlKGxhcmdlc3RfdHMsIHByb2JzID0gMSAtIGFscGhhKQogIAogIHJldHVybihsaXN0KCJDcml0VmFsIiA9IENWLCAibGFyZ2VzdF90cyIgPSBsYXJnZXN0X3RzKSkKfQoKc3VwdCA9IHN1cF90KGRHQVRFc1ssMV0sYWlwdyRBVEUkZGVsdGFbLDE6Sl0sRykKCmZvciAoaiBpbiAxOkopIHsKICBkR0FURXNbaiw1XSA9IG1lYW4oc3VwdCRsYXJnZXN0X3RzID4gYWJzKGRHQVRFc1tqLDNdKSkKfQoKZEdBVEVzCmBgYAoKV2Ugb2JzZXJ2ZSB0aGF0IGVhY2ggZXN0aW1hdGUgaXMgaW1wcmVjaXNlbHkgZXN0aW1hdGVkIGFuZCBldmVuIHRoZSBwb2ludHdpc2UgcC12YWx1ZXMgYXJlIHF1aXRlIGxhcmdlLgoKIyMjIFRlc3QgaWYgZGlmZmVyZW5jZXMgYXJlIGpvaW50bHkgemVybwoKRmluYWxseSwgd2UgdGVzdCB0aGUgam9pbnQgaHlwb3RoZXNpcyBvZiBhbGwgR0FURSBkaWZmZXJlbmNlcyBiZWluZyB6ZXJvIHVzaW5nIGEgV2FsZCBhbmQgYSBzdXByZW11bSB0ZXN0OgoKYGBge3J9CiMgQ29tcHV0ZSB0aGUgV2FsZCBzdGF0aXN0aWMgYW5kIHAtdmFsdWUKVyA9IHQoZEdBVEVzWywxXSkgJSolIHNvbHZlKFNpZ21hX2hhdCAvIG4pICUqJSBkR0FURXNbLDFdCldfcF92YWx1ZSA9IDEgLSBwY2hpc3EoVywgZGYgPSBKKQojIENvbXB1dGUgc3VwdCBwLXZhbHVlCnN1cHRfcF92YWx1ZSA9IG1lYW4oc3VwdCRsYXJnZXN0X3RzID4gbWF4KGFicyhkR0FURXNbLDNdKSkpCiMgVXNlIHNwcmludGYgdG8gYWxpZ24gbnVtYmVycwpvdXRwdXQgPSBzcHJpbnRmKCJXYWxkIHAtdmFsdWU6ICUuNGZcblN1cHJlbXVtIHAtdmFsdWU6ICUuNGYiLCBXX3BfdmFsdWUsIHN1cHRfcF92YWx1ZSkKY2F0KG91dHB1dCkKYGBgCgpMaWtlICRcRGVsdGFfMSQsIHRoZSBkaXJlY3QgdGVzdHMgb2Ygc3Ryb25nIGdyb3VwIGVmZmVjdCBob21vZ2VuZWl0eSBhcmUgaW5zaWduaWZpY2FudC4KCgojIyBTLjIuNSBNb3JlIHBhcmFtZXRlciBlc3RpbWF0ZXMgeyNTMi01LU1vcmUtcGFyYW1ldGVycy1lc3RpbWF0ZXN9CgpGaXJzdCBwbG90IHRoZSB1bmRlcmx5aW5nIGF2ZXJhZ2UgcG90ZW50aWFsIG91dGNvbWVzOgoKYGBge3J9CnBsb3QoYWlwdyRBUE8pCmBgYAoKTm90IHN1cnByaXNpbmdseSB0aGV5IGFyZSBpbXByZWNpc2VseSBlc3RpbWF0ZWQuIEhvd2V2ZXIsIHdlIG9ic2VydmUgYSBwYXR0ZXJuIHRoYXQgdGhlIHRyYWluaW5nIGluIHdoaWNoIHdvbWVuIGFyZSBvdmVycmVwcmVzZW50ZWQgLSBjbGVyaWNhbCwgaGVhbHRoIGFuZCBmb29kIC0gaGF2ZSByZWxhdGl2ZWx5IGxvdyBlc3RpbWF0ZWQgYXZlcmFnZSBwb3RlbnRpYWwgb3V0Y29tZXMuIFRoaXMgaXMgZHJpdmluZyB0aGUgZ2VuZGVyIGRpZmZlcmVuY2VzLgoKVGhlbiwgd2UgY2FuIHByaW50IGVzdGltYXRlcyBvZiBhbGwgcGFyYW1ldGVycyBkaXNjdXNzZWQgdGhyb3VnaG91dCB0aGUgbWFudWNyaXB0IGZvciBjb21wbGV0ZW5lc3MuCgpgYGB7cn0KIyBEZWZpbmUgcGFyYW1ldGVycyB0byBiZSBkaXNwbGF5cyBhbmQgdGhlaXIgb3JkZXIKcGFyYW1fc2VsZWN0ID0gYygxLDIsNCw1LDYsMyw3LDgsOSwxMSwxMywxNCkKYGBgCgpGaXJzdCwgb3V0Y29tZSBsZXZlbHMgZm9yIG1lbgpgYGB7cn0Kc3VtbWFyeShyZXN1bHRzLHBhcmFtZXRlciA9IHBhcmFtX3NlbGVjdCwgdF9hZ2dyZWdhdGUgPSAyLHhfYWdncmVnYXRlID0gMikgIyBBID0gMApzdW1tYXJ5KHJlc3VsdHMscGFyYW1ldGVyID0gcGFyYW1fc2VsZWN0LCB0X2FnZ3JlZ2F0ZSA9IDMseF9hZ2dyZWdhdGUgPSAyKSAjIEEgPSAxCmBgYAoKYW5kIHRoZWlyIGNvbnRyYXN0CmBgYHtyfQojIE1hbGUgY29udHJhc3QgaW4gdHJlYXRtZW50IGFnZ3JlZ2F0aW9ucwpzdW1tYXJ5KHJlc3VsdHMscGFyYW1ldGVyID0gcGFyYW1fc2VsZWN0LCB0X2FnZ3JlZ2F0ZSA9IGMoMywyKSx4X2FnZ3JlZ2F0ZSA9IDIpCmBgYAoKU2Vjb25kLCBvdXRjb21lIGxldmVscyBmb3Igd29tZW4KYGBge3J9CnN1bW1hcnkocmVzdWx0cyxwYXJhbWV0ZXIgPSBwYXJhbV9zZWxlY3QsIHRfYWdncmVnYXRlID0gMix4X2FnZ3JlZ2F0ZSA9IDMpICMgQSA9IDAKc3VtbWFyeShyZXN1bHRzLHBhcmFtZXRlciA9IHBhcmFtX3NlbGVjdCwgdF9hZ2dyZWdhdGUgPSAzLHhfYWdncmVnYXRlID0gMykgIyBBID0gMQpgYGAKCmFuZCB0aGVpciBjb250cmFzdApgYGB7cn0KIyBNYWxlIGNvbnRyYXN0IGluIHRyZWF0bWVudCBhZ2dyZWdhdGlvbnMKc3VtbWFyeShyZXN1bHRzLHBhcmFtZXRlciA9IHBhcmFtX3NlbGVjdCwgdF9hZ2dyZWdhdGUgPSBjKDMsMikseF9hZ2dyZWdhdGUgPSAzKQpgYGAKCgojIyBTLjIuNiBVbmNvbmRpdGlvbmFsIHJlc3VsdHMgeyNVbmNvbmRpdGlvbmFsLXJlc3VsdHN9CgpGb3IgY29tcGxldGVuZXNzIGFsc28gY2hlY2sgdGhlIHVuY29uZGl0aW9uYWwgZXN0aW1hbmRzIHRoYXQgbmF0dXJhbGx5IGRvIG5vdCByZXByZXNlbnQgYSBoZXRlcm9nZW5laXR5IGJ1dCByYXRoZXIgZGVjb21wb3NlIGF2ZXJhZ2UgZXN0aW1hbmRzIGZvciBhdmVyYWdlIHBvdGVudGlhbCBvdXRjb21lczoKCmBgYHtyfQojIFVuY29uZGl0aW9uYWwgbGV2ZWxzCnN1bW1hcnkocmVzdWx0cyxwYXJhbWV0ZXIgPSBwYXJhbV9zZWxlY3QsIHRfYWdncmVnYXRlID0gMix4X2FnZ3JlZ2F0ZSA9IDEpICMgQSA9IDAKc3VtbWFyeShyZXN1bHRzLHBhcmFtZXRlciA9IHBhcmFtX3NlbGVjdCwgdF9hZ2dyZWdhdGUgPSAzLHhfYWdncmVnYXRlID0gMSkgIyBBID0gMQpgYGAKClNpbWlsYXJseSBmb3IgdGhlIGF2ZXJhZ2UgdHJlYXRtZW50IGVmZmVjdDoKCmBgYHtyfQpzdW1tYXJ5KHJlc3VsdHMscGFyYW1ldGVyID0gcGFyYW1fc2VsZWN0LCB0X2FnZ3JlZ2F0ZSA9IGMoMywyKSx4X2FnZ3JlZ2F0ZSA9IDEpICMgQSA9IDEgLSBBID0gMApgYGAK