library(ithi.utils)
load_base_libs()

library(ithi.meta)
library(ithi.ihc)
library(ithi.xcr)
library(ithi.clones)

Colour palettes

pal_patient <- select_palette("patient")

Parameters

db_path <- snakemake@params$db
ihc_table_path <- snakemake@input$ihc_table
ihc_table_slide_path <- snakemake@input$ihc_table_slide

spatial_results_file <- snakemake@input$spatial_results_file

tcr_diversity_file <- snakemake@input$tcr_diversity
bcr_diversity_file <- snakemake@input$bcr_diversity

nanostring_data_path <- snakemake@input$nanostring_data
nanostring_annotations_path <- snakemake@input$nanostring_annotations

clonal_measures_file <- snakemake@input$ith_stats

Metadata

db <- src_sqlite(db_path, create = FALSE)
samples <- collect(tbl(db, "samples"))

id_cols <- c("voa", "patient_id", "condensed_id", "field", "tissue")
id_cols_sample <- c("voa", "patient_id", "condensed_id", "tissue")

Analysis

rename_field <- function(field) {
    voa_portion <- str_replace(field, "_HP_IM3.*$", "")
    voa_portion <- str_replace(voa_portion, "_", " ")
    field_portion <- str_extract(field, "_HP_IM3.*$")
    field_portion <- str_replace(field_portion, "__", "_[")
    field_portion <- paste0(field_portion, "]", sep = "")
    field <- paste(voa_portion, field_portion, sep = "")
    return(field)
}

fudge_cols <- function(ihc_slide_subset) {
    count_cols <- colnames(ihc_slide_subset)[str_detect(colnames(ihc_slide_subset), 
        "count")]
    ## JOIN WITH UNDERSCORES, THEN USE RESHAPE new_cols <-
    ## lapply(strsplit(str_replace_all(count_cols, '_count', ''), '_'),
    ## function(x) paste(rev(x), collapse='_')) colnames(ihc_slide_subset) <-
    ## mapvalues(colnames(ihc_slide_subset), count_cols, unlist(new_cols))
    df_melted <- melt(ihc_slide_subset, id.vars = c("voa", "field", "condensed_id"), 
        measure.vars = run1_cols, variable.name = "type", value.name = "count")
    df_melted$tissue <- mapvalues(str_extract(df_melted$type, "^(E|S)"), from = c("E", 
        "S"), to = c("epithelial", "stroma"))
    df_melted$type <- tolower(str_replace_all(df_melted$type, "(^(E|S)_|_count$)", 
        ""))
    df_cast <- dcast(df_melted, voa + field + condensed_id + tissue ~ type, 
        fun.aggregate = sum, value.var = "count")
    df_fudge <- df_cast %>% mutate(cd8_cd8 = cd8 * cd8, cd4_cd8 = cd4 * cd8, 
        cd4_cd4 = cd4 * cd4, cd20_cd4 = cd20 * cd4, cd20_cd8 = cd20 * cd8, cd20_cd20 = cd20 * 
            cd20)
    return(df_fudge)
}
spatial_data <- fread(spatial_results_file)

Read 0.0% of 1650000 rows
Read 12.1% of 1650000 rows
Read 22.4% of 1650000 rows
Read 34.5% of 1650000 rows
Read 46.7% of 1650000 rows
Read 58.2% of 1650000 rows
Read 69.7% of 1650000 rows
Read 80.6% of 1650000 rows
Read 91.5% of 1650000 rows
Read 1650000 rows and 28 (of 28) columns from 0.532 GB file in 00:00:15
if ("tissue.1" %in% colnames(spatial_data)) {
    spatial_data <- subset(spatial_data, select = -c(tissue.1))
}
spatial_data$field <- rename_field(spatial_data$field)

ihc_table_slide <- fread(ihc_table_slide_path)
ihc_table_slide$field <- str_replace(ihc_table_slide$slide, "\\.im3$", "")
ihc_table_slide <- subset(ihc_table_slide, select = -c(slide))

run1_tils <- c("CD8_count", "CD4_count", "CD20_count")
run1_cols <- c(paste0("E_", run1_tils), paste0("S_", run1_tils))
ihc_slide_subset <- subset(ihc_table_slide, select = c("voa", "field", "condensed_id", 
    run1_cols))
ihc_slide_fudge <- fudge_cols(ihc_slide_subset)

INTERACTION_VARS <- c("cd8_cd8", "cd4_cd8", "cd4_cd4", "cd20_cd4", "cd20_cd8", 
    "cd20_cd20")

ihc_slide_fudge_melted <- melt(ihc_slide_fudge, id.vars = c("voa", "field", 
    "condensed_id", "tissue"), measure.vars = INTERACTION_VARS, variable.name = "type", 
    value.name = "count")
spatial_data_melted <- melt(spatial_data, id.vars = c("voa", "field", "tissue", 
    "weight", "condensed_id", "patient_id"), measure.vars = INTERACTION_VARS, 
    variable.name = "type", value.name = "gamma")
spatial_data_merge <- merge(spatial_data_melted, ihc_slide_fudge_melted, by = c("voa", 
    "field", "tissue", "condensed_id", "type"))

THRESHOLD <- 10

spatial_data_merge <- subset(spatial_data_merge, count >= THRESHOLD)

spatial_summary_melted <- spatial_data_merge %>% group_by_(.dots = c(id_cols, 
    "type")) %>% summarise(gamma = weighted.mean(gamma, weight))

Remove super-outliers

spatial_summary_melted_filtered <- spatial_summary_melted %>% group_by(type, 
    tissue) %>% filter(!(abs(gamma - median(gamma, na.rm = TRUE)) > 10 * IQR(gamma, 
    na.rm = TRUE)))

Posterior distributions

ggplot(spatial_summary_melted_filtered, aes(x = gamma)) + geom_histogram(aes(fill = tissue), 
    bins = 30) + theme_bw() + theme_Publication() + facet_wrap(~type, scales = "free")

Correlations with TIL densities

Slide level

spatial_summary_filtered <- dcast(spatial_summary_melted_filtered, field + tissue ~ 
    type, value.var = "gamma")

spatial_ihc <- merge(ihc_table_slide, spatial_summary_filtered, by = c("field"))

IHC_VARS <- c("T_CD8_density", "T_CD4_density", "T_CD20_density", "T_Plasma_density", 
    "E_CD8_density", "E_CD4_density", "E_CD20_density", "E_Plasma_density", 
    "S_CD8_density", "S_CD4_density", "S_CD20_density", "S_Plasma_density", 
    "RUN1_E_area_pct", "RUN1_S_area_pct")
plot_correlation_heatmap <- function(dat, id_cols, VARS) {
    spatial_ihc_subset <- subset(dat, select = c(id_cols, VARS))
    spatial_ihc_subset_mat <- subset(spatial_ihc_subset, select = c(VARS))
    
    corres <- corr.test(spatial_ihc_subset_mat, adjust = "fdr", method = "spearman")
    corres.r <- corres$r
    corres.p <- corres$p
    hc <- hclust(dist(corres.r), method = "ward.D")
    
    diag(corres.r) <- NA
    diag(corres.p) <- NA
    
    corres.labels <- format(signif(corres.p, 2), 2)
    
    cols <- colorRampPalette(c("#95cbee", "#ffd73e", "#ce472e"))(100)
    pheatmap(corres.r[hc$order, hc$order], display_numbers = corres.labels, 
        color = cols, number_color = "black", cluster_rows = TRUE, cluster_cols = TRUE)
}
## Will fail due to filtering plot_correlation_heatmap(subset(spatial_ihc,
## tissue == 'epithelial'), id_cols, c(IHC_VARS, INTERACTION_VARS))
# plot_correlation_heatmap(subset(spatial_ihc, tissue == 'stroma'), id_cols,
# c(IHC_VARS, INTERACTION_VARS))

Sample level

ihc_table <- fread(ihc_table_path)

N_THRESHOLD <- 0

spatial_summary_melted_filtered_sample <- spatial_summary_melted_filtered %>% 
    group_by(voa, patient_id, condensed_id, tissue, type) %>% summarise(gamma = mean(gamma, 
    na.rm = TRUE), n = n())
spatial_summary_melted_filtered_sample <- subset(spatial_summary_melted_filtered_sample, 
    n >= N_THRESHOLD)

spatial_summary_filtered_sample <- dcast(spatial_summary_melted_filtered_sample, 
    voa + condensed_id + tissue ~ type, value.var = "gamma")

spatial_ihc_sample <- merge(ihc_table, spatial_summary_filtered_sample, by = c("voa", 
    "condensed_id"))
plot_correlation_heatmap(subset(spatial_ihc_sample, tissue == "epithelial"), 
    id_cols_sample, c(IHC_VARS, INTERACTION_VARS))

plot_correlation_heatmap(subset(spatial_ihc_sample, tissue == "stroma"), id_cols_sample, 
    c(IHC_VARS, INTERACTION_VARS))

Correlations with ITH

clonal_measures <- read_ith_stats(clonal_measures_file, db_path, duplicates = FALSE)

ITH_VARS <- c("entropy", "divergence", "postprocessed_divergence", "combined_ith_raw", 
    "combined_ith_normalized", "proportion_subclonal")
spatial_ith <- merge(clonal_measures, spatial_summary_filtered_sample, by = c("condensed_id"))
plot_correlation_heatmap(subset(spatial_ith, tissue == "epithelial"), id_cols_sample, 
    c(ITH_VARS, INTERACTION_VARS))

plot_correlation_heatmap(subset(spatial_ith, tissue == "stroma"), id_cols_sample, 
    c(ITH_VARS, INTERACTION_VARS))

spatial_ith_melted <- melt(spatial_ith, id.vars = colnames(spatial_ith)[!colnames(spatial_ith) %in% 
    ITH_VARS], measure.vars = ITH_VARS, variable.name = "ithtype", value.name = "ith")

spatial_ith_melted$patient_id <- factor(spatial_ith_melted$patient_id)

pvals <- setNames(ddply(spatial_ith_melted, .(tissue, ithtype), function(x) {
    df <- x
    corres <- with(df, cor.test(cd8_cd8, ith, method = "spearman"))
    
    pval <- corres$p.value
    eq <- substitute(italic(P) == p, list(p = format(pval, digits = 3)))
    return(as.character(as.expression(eq)))
}), c("tissue", "ithtype", "p.value"))

ggplot(spatial_ith_melted, aes(x = cd8_cd8, y = ith)) + geom_point(aes(colour = patient_id)) + 
    scale_colour_manual(values = pal_patient) + theme_bw() + theme_Publication() + 
    facet_wrap(tissue ~ ithtype, scales = "free") + geom_text(data = pvals, 
    aes(x = Inf, y = Inf, label = p.value), hjust = 1.1, vjust = 1.5, size = 3, 
    parse = TRUE)

LS0tCnRpdGxlOiAiU3BhdGlhbCBhbmFseXNpcyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDUKICAgIHRvY19mbG9hdDogdHJ1ZQpwYXJhbXM6CiAgcm1kOiAic3BhdGlhbF9hbmFseXNpcy5SbWQiCi0tLQogICAgICAgICAgICAgICAgICAgICAgICBgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMjIyMjIyMjIFNuYWtlbWFrZSBoZWFkZXIgIyMjIyMjIyMKbGlicmFyeShtZXRob2RzKQpTbmFrZW1ha2UgPC0gc2V0Q2xhc3MoCiAgICAiU25ha2VtYWtlIiwKICAgIHNsb3RzID0gYygKICAgICAgICBpbnB1dCA9ICJsaXN0IiwKICAgICAgICBvdXRwdXQgPSAibGlzdCIsCiAgICAgICAgcGFyYW1zID0gImxpc3QiLAogICAgICAgIHdpbGRjYXJkcyA9ICJsaXN0IiwKICAgICAgICB0aHJlYWRzID0gIm51bWVyaWMiLAogICAgICAgIGxvZyA9ICJsaXN0IiwKICAgICAgICByZXNvdXJjZXMgPSAibGlzdCIsCiAgICAgICAgY29uZmlnID0gImxpc3QiLAogICAgICAgIHJ1bGUgPSAiY2hhcmFjdGVyIgogICAgKQopCnNuYWtlbWFrZSA8LSBTbmFrZW1ha2UoCiAgICBpbnB1dCA9IGxpc3QoJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9UUkIvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2l0aF9zdGF0aXN0aWNzLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGVfc2xpZGUudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL3NwYXRpYWxfdGFibGUudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2loY190YWJsZS50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL2FuYWx5c2lzL1JtZC9fc2l0ZS55bWwnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9uYW5vc3RyaW5nL3BhbmNhbmNlcl9hbm5vdGF0aW9ucy50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbmFub3N0cmluZ19yZXN1bHRzL2l0aF9mdWxsL3FjL2xpbW1hX3F1YW50aWxlL25vcm1hbGl6ZWRfZXhwcmVzc2lvbl92b2FfbGFiZWxzX2ZpbHRlcmVkLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvSUdIL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICdSbWQvc3BhdGlhbF9hbmFseXNpcy5SbWQnLCAiaXRoX3N0YXRzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9pdGhfc3RhdGlzdGljcy50c3YnLCAiaWhjX3RhYmxlX3NsaWRlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGVfc2xpZGUudHN2JywgInNwYXRpYWxfcmVzdWx0c19maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9zcGF0aWFsX3RhYmxlLnRzdicsICJpaGNfdGFibGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2loY190YWJsZS50c3YnLCAic2l0ZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvYW5hbHlzaXMvUm1kL19zaXRlLnltbCcsICJuYW5vc3RyaW5nX2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL25hbm9zdHJpbmcvcGFuY2FuY2VyX2Fubm90YXRpb25zLnRzdicsICJ0Y3JfZGl2ZXJzaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvVFJCL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICJiY3JfZGl2ZXJzaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvSUdIL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICJuYW5vc3RyaW5nX2RhdGEiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL25hbm9zdHJpbmdfcmVzdWx0cy9pdGhfZnVsbC9xYy9saW1tYV9xdWFudGlsZS9ub3JtYWxpemVkX2V4cHJlc3Npb25fdm9hX2xhYmVsc19maWx0ZXJlZC50c3YnLCAibm90ZWJvb2siID0gJ1JtZC9zcGF0aWFsX2FuYWx5c2lzLlJtZCcpLAogICAgb3V0cHV0ID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvd2ViL3NwYXRpYWxfYW5hbHlzaXMubmIuaHRtbCcpLAogICAgcGFyYW1zID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL21ldGFkYXRhL2RiL2ltbXVuZV9wcm9qZWN0LnNxbGl0ZTMnLCAnaXRoaS1hbmFseXNpcy1zcGF0aWFsLWNvcnJlbGF0aW9ucycsICJkYiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL21ldGFkYXRhL2RiL2ltbXVuZV9wcm9qZWN0LnNxbGl0ZTMnLCAibmFtZSIgPSAnaXRoaS1hbmFseXNpcy1zcGF0aWFsLWNvcnJlbGF0aW9ucycpLAogICAgd2lsZGNhcmRzID0gbGlzdCgpLAogICAgdGhyZWFkcyA9IDEsCiAgICBsb2cgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL2NsdXN0dG1wL3BhcGVyYW5hbHlzaXMyL3NwYXRpYWxfY29ycmVsYXRpb25zLmxvZycpLAogICAgcmVzb3VyY2VzID0gbGlzdCgpLAogICAgY29uZmlnID0gbGlzdCgiY2xhc3NpZmllcl90eXBlIiA9ICdrbm4nLCAiZXhhbXBsZV9tc2FfcGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMTMvb2xkL2FsaWdubWVudF9wbG90cy9tc2EvaXRoMl8yL2NsdXN0OS9pbmRlbF9yZXZlcnNlZC5odG1sJywgIml0aF9zdGF0aXN0aWNzX25vdGVib29rIiA9ICdSbWQvaXRoX3N0YXRpc3RpY3MuUm1kJywgInRjZ2Ffb3ZfYW5ub3RhdGlvbnMiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9UQ0dBL3RjZ2Ffb3ZfYW5ub3RhdGlvbl9zdXAxMy50eHQnLCAidGNnYV9leHByX21hdHJpeCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0EvZXhwcl9tYXRyaXhfbm9ybWFsaXplX3N0YW5kYXJkaXplX25vZHVwbGljYXRlcy50c3YnLCAiYmVuY2htYXJrZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2JlbmNobWFya3MvcGFwZXJhbmFseXNpczInLCAidGlsc19mb3JfY2x1c3RlciIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAiZXhhbXBsZV9hbm5vdGF0aW9ucyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMTMvZmluYWxfcGFydGl0aW9ucy9pdGgyXzIvY2x1c3Q5L2Fubm90YXRpb25zX2ZsYWdnZWQudHN2JywgImxpYnJhcnlfc2l6ZXMiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9saWJyYXJ5X3NpemVzLnRzdicsICJ0Y3JfZGl2ZXJzaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvVFJCL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICJtbWN0bV9zYW1wbGVfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktc2FtcGxlL291dHB1dCcsICJ2YXJpYWJpbGl0eV90eXBlIiA9ICdzdGFiaWxpemUnLCAic2l0ZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvYW5hbHlzaXMvUm1kL19zaXRlLnltbCcsICJ4Y3JfcWNfbm90ZWJvb2siID0gJ1JtZC9yZXBsaWNhdGVzLlJtZCcsICJkcml2ZXJfbWFwIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvc3VicHJvamVjdHMvZHJpdmVycy9kYXRhL2dlbmVfbGlzdF9tYXBwZWQuYmVkJywgIm5lb2VkaXRpbmdfb3V0ZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9uZW9lZGl0aW5nL3J1bjQnLCAibXZjbHVzdF90aWx0eXBlcyIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAiaW50ZXJtZWRpYXRlX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yJywgInhjcl9tYXBwaW5nX25vdGVib29rIiA9ICdSbWQveGNyX21hcHBpbmcuUm1kJywgImljZ2NfZXhwcl9tZWx0ZWQiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL09WQVVfZXhwcl9tZWx0ZWQudHN2JywgImJjcl9kaXZlcnNpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9JR0gvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgIm1tY3RtX2FuY2VzdHJhbF9kZXNjZW5kYW50X3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LWFuY2VzdHJ5LXNhbXBsZS9vdXRwdXQnLCAia25vd25fc3VidHlwZXNfbWVyZ2VkIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL2tub3duX3N1YnR5cGVzX21lcmdlZC50c3YnLCAibW1jdG1fZmluYWxfcGF0aWVudF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnRfd2l0aC1vdicsICJpbW11bmVfdmFyaWFiaWxpdHlfbm90ZWJvb2siID0gJ1JtZC9pbW11bmVfdmFyaWFiaWxpdHkuUm1kJywgInhjcl9kaXN0YW5jZV9tZXRob2QiID0gJ2hvcm4nLCAiZHJpdmVyX2FuYWx5c2lzX25vdGVib29rIiA9ICdSbWQvZHJpdmVyX2FuYWx5c2lzLlJtZCcsICJtbWN0bV9zYW1wbGVfYWRfc2lncGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktYW5jZXN0cnktc2FtcGxlL3Bsb3RzL2l0aC1ieS1hbmNlc3RyYWwtc2FtcGxlX3Nudi1zdl9zaWdzX211bHRpcGFuZWwucGRmJywgIm1tY3RtX292X2NvbWJpbmVkX3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvY29tYmluZWRfb3ZfbW1jdG0vb3V0cHV0JywgImRlZmF1bHRfc2FtcGxlciIgPSAnSE1DJywgInRjcl9jbG9ub3R5cGVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvY2xvbm90eXBlcy9UUkJfY2xvbm90eXBlc19maWx0ZXJlZC50eHQnLCAiaXRoX3RpbF9ub3RlYm9vayIgPSAnUm1kL2l0aF90aWxfZGVuc2l0aWVzLlJtZCcsICJtdXRhdGlvbl9zaWduYXR1cmVfbm90ZWJvb2siID0gJ1JtZC9tdXRhdGlvbl9zaWduYXR1cmVzLlJtZCcsICJtbWN0bV9vdl9jb21iaW5lZF9zaWdwbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2NvbWJpbmVkX292X21tY3RtL3Bsb3RzL292X3Nudi1zdl9zaWdzX211bHRpcGFuZWwucGRmJywgIm1vbHN1YnR5cGVfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknKSwgImljZ2Nfc3BlY2ltZW5fZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0Mvc3BlY2ltZW4udHN2JywgInNwYXRpYWxfcmVzdWx0X2RpcnMiID0gbGlzdCgiZXBpdGhlbGlhbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvc3BhdHNpbS9pdGgzL2FiYycsICJzdHJvbWFsIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9zcGF0c2ltL2l0aDUvYWJjJyksICJQTkdfUVVBTElUWSIgPSAzMDAsICJ4Y3JtYXBzY2FwZV9ub3RlYm9vayIgPSAnUm1kL3hjcm1hcHNjYXBlLlJtZCcsICJtbWN0bV9wYXRpZW50X2FkX3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnQtYW5jZXN0cnkvcGxvdHMvaXRoLWJ5LXBhdGllbnQtYW5jZXN0cnlfc252LXN2X3NpZ3NfbXVsdGlwYW5lbC5wZGYnLCAibXVsdGl2aWV3Y2x1c3RlcmluZ19ub3RlYm9vayIgPSAnUm1kL211bHRpdmlld2NsdXN0ZXJpbmcuUm1kJywgIm1tY3RtX3NhbXBsZV9zaWdwbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1zYW1wbGUvcGxvdHMvaXRoLWJ5LXNhbXBsZV9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJtYXBzY2FwZV9ub3RlYm9vayIgPSAnUm1kL21hcHNjYXBlLlJtZCcsICJtbWN0bV9maW5hbF9wYXRpZW50X3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnRfd2l0aC1vdi9wbG90cy9pdGgtYnktcGF0aWVudF9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJpY2djX2NsaW5pY2FsIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9kb25vci5PVi1BVS50c3YnLCAibXZjbHVzdF9uY2x1c3QiID0gMywgImloY194Y3Jfc3RhdHNfbm90ZWJvb2siID0gJ1JtZC9paGNfeGNyX3N0YXRzLlJtZCcsICJzYWRfbm90ZWJvb2siID0gJ1JtZC9zcGVjaWVzX2FidW5kYW5jZV9kaXN0cmlidXRpb25zLlJtZCcsICJwYXRpZW50c19mb3JfY2xvbmFsIiA9IGMoMSwgMiwgMywgNCwgNywgOSwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNSwgMTYsIDE3KSwgInN1YnR5cGVfbWFya2VyX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vbmFub3N0cmluZy9zdWJ0eXBlX21hcmtlcnMudHN2JywgInRhYmxlX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjInLCAiZGIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJywgImNsb25lX3RyZWVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaXRoL2NvbXBsZXRlL3RyZWVfZGF0YS50c3YnLCAiaWhjX3J1bjIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2loYy9jZDc5Y2QxMzhjZDY4L3ZhbGlkYXRlZF9zdGF0c193ZWlnaHRlZC5yZGF0YScsICJuY2x1c3RzIiA9IDMsICJzcGF0aWFsX25vdGVib29rIiA9ICdSbWQvc3BhdGlhbF9hbmFseXNpcy5SbWQnLCAiYmNycGh5bG9fY29ycmVsYXRpb25zX25vdGVib29rIiA9ICdSbWQvYmNyX3BoeWxvX2NvcnJlbGF0aW9ucy5SbWQnLCAiY2xvbmVfYnJhbmNoX2xlbmd0aF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvYnJhbmNoX2RhdGEudHN2JywgIm1tY3RtX3BhdGllbnRfYW5jZXN0cmFsX2Rlc2NlbmRhbnRfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudC1hbmNlc3RyeS9vdXRwdXQnLCAibmVvYW50aWdlbl9lZGl0aW5nX25vdGVib29rIiA9ICdSbWQvaW1tdW5vZWRpdGluZy5SbWQnLCAiaWNnY19tb2xlY3VsYXJfc3VidHlwZXMiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL2ljZ2NfcHJpbWFyeV90dW1vdXJfc3VidHlwZXMudHN2JywgIm1hc3Rlcl9icmVha3BvaW50X2ZpbGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9icmVha3BvaW50cy50c3YnLCAicHJldmFsZW5jZV90aHJlc2hvbGQiID0gMC4wMSwgImlncGFydGl0aW9uX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMjInLCAidGNnYV9jbGluaWNhbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0Evc3luYXBzZV9jbGluQWxsX2RhdGEudHN2JywgIm5hbm9zdHJpbmdfZGF0YSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbmFub3N0cmluZ19yZXN1bHRzL2l0aF9mdWxsL3FjL2xpbW1hX3F1YW50aWxlL25vcm1hbGl6ZWRfZXhwcmVzc2lvbl92b2FfbGFiZWxzX2ZpbHRlcmVkLnRzdicsICJtdXRzaWdfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgImloY19ydW4xIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9paGMvY2Q4Y2QzY2QyMC92YWxpZGF0ZWRfc3RhdHNfd2VpZ2h0ZWRfbmV3LnJkYXRhJywgIm5hbm9zdHJpbmdfc2lnbmF0dXJlX25vdGVib29rIiA9ICdSbWQvbmFub3N0cmluZ19zaWduYXR1cmVzLlJtZCcsICJub3RlYm9va19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3dlYicsICJpbW10eXBlcl9sZW5ndGhzIiA9ICcxMSAxMiAxMyAxNCAxNSAxNiAxNyAxOCcsICJjbG9uYWxfc2FtcGxlcnMiID0gYygnSE1DJywgJ05VVFMnKSwgImloY194Y3JfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgImtub3duX3N1YnR5cGVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9hcnJheS9zdWJ0eXBlcy9rbm93bl9zdWJ0eXBlcy50c3YnLCAiYmNycGh5bG9fdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgIm5hbm9zdHJpbmdfYW5ub3RhdGlvbnMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vbmFub3N0cmluZy9wYW5jYW5jZXJfYW5ub3RhdGlvbnMudHN2JywgIml0aF9zdGF0c19maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvY2xvbmFsX21lYXN1cmVzLnRzdicsICJwcm9wb3J0aW9uX3N1YmNsb25hbF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvb2xkX3Byb3BvcnRpb25fc3ViY2xvbmFsLnRzdicsICJQTkdfREVOU0lUWSIgPSAzMDAsICJ0aWxfY2xhc3NpZmllcl9ub3RlYm9vayIgPSAnUm1kL3RpbF9jbGFzc2lmaWVyLlJtZCcsICJpbmRleF9ub3RlYm9vayIgPSAnUm1kL2luZGV4LlJtZCcsICJpdGhfc3RhdF90eXBlcyIgPSBjKCdlbnRyb3B5JywgJ3Bvc3Rwcm9jZXNzZWRfZGl2ZXJnZW5jZScsICdjb21iaW5lZF9pdGhfbm9ybWFsaXplZCcsICdwcm9wb3J0aW9uX3N1YmNsb25hbCcpLCAial9kaWN0aW9uYXJ5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvc3VicHJvamVjdHMvaW1tdHlwZXIvbWV0YWRhdGEvaW1ndC9Ib21vX3NhcGllbnNfVFJCSi5mYXN0YScsICJ0aWxzX2Zvcl92YXJpYWJpbGl0eSIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAibW9sc3VidHlwZV9ub3RlYm9vayIgPSAnUm1kL21vbGVjdWxhcl9zdWJ0eXBlcy5SbWQnLCAiYmNycGh5bG9fZXhhbXBsZXNfbm90ZWJvb2siID0gJ1JtZC9iY3JfcGh5bG9fZXhhbXBsZXMuUm1kJywgImJjcl9jbG9ub3R5cGVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvY2xvbm90eXBlcy9JR0hfY2xvbm90eXBlc19maWx0ZXJlZC50eHQnLCAibWFzdGVyX3ZhcmlhbnRfZmlsZSIgPSAnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX3NudnMudHN2JywgInZfZGljdGlvbmFyeSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3N1YnByb2plY3RzL2ltbXR5cGVyL21ldGFkYXRhL2ltZ3QvSG9tb19zYXBpZW5zX1RSQlYuZmFzdGEnLCAicGhlbm90eXBlX3RocmVzaG9sZCIgPSAwLjg1LCAiY2xvbmVfcHJldmFsZW5jZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvY2xvbmVfZGF0YS50c3YnLCAiaXRoX3Byb2plY3RfcmVzdWx0cyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9pdGgzL2RhdGEvcmVzdWx0cycsICJ4Y3JfY2xvbmVzX25vdGVib29rIiA9ICdSbWQveGNyX2Nsb25lc19hbmFseXNpcy5SbWQnLCAiZmlndXJlX2dhbGxlcnlfbm90ZWJvb2siID0gJ1JtZC9maWd1cmVzLlJtZCcsICJsb2dkaXIiID0gJy9zaGFobGFiL2FsemhhbmcvY2x1c3R0bXAvcGFwZXJhbmFseXNpczInLCAid2FuZ19mYmlfc3RhdHVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9uZy4zODQ5LVMxMi50eHQnLCAiaW1tdHlwZXJfbW9kZWxzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9pbW10eXBlcl9yZXN1bHRzL2tsYXJlbmJlZWsvYWFfdmovZ3JhZGJvb3N0JywgImljZ2Nfbm9ybWFsaXplZF9yZWFkc19tYXRyaXgiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL09WQVVfZXhwcl9tYXRyaXgudHN2JyksCiAgICBydWxlID0gJ3NwYXRpYWxfY29ycmVsYXRpb25zJwopCiMjIyMjIyMjIE9yaWdpbmFsIHNjcmlwdCAjIyMjIyMjIyMKCiAgICAgICAgICAgICAgICAgICAgICAgIGBgYAoKCgpgYGB7ciBnbG9iYWxfY2h1bmtfb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB0aWR5PVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGl0aGkudXRpbHMpCmxvYWRfYmFzZV9saWJzKCkKCmxpYnJhcnkoaXRoaS5tZXRhKQpsaWJyYXJ5KGl0aGkuaWhjKQpsaWJyYXJ5KGl0aGkueGNyKQpsaWJyYXJ5KGl0aGkuY2xvbmVzKQpgYGAKCiMjIENvbG91ciBwYWxldHRlcwoKYGBge3J9CnBhbF9wYXRpZW50IDwtIHNlbGVjdF9wYWxldHRlKCJwYXRpZW50IikKYGBgCgojIyBQYXJhbWV0ZXJzCgpgYGB7cn0KZGJfcGF0aCA8LSBzbmFrZW1ha2VAcGFyYW1zJGRiCmloY190YWJsZV9wYXRoIDwtIHNuYWtlbWFrZUBpbnB1dCRpaGNfdGFibGUKaWhjX3RhYmxlX3NsaWRlX3BhdGggPC0gc25ha2VtYWtlQGlucHV0JGloY190YWJsZV9zbGlkZQoKc3BhdGlhbF9yZXN1bHRzX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JHNwYXRpYWxfcmVzdWx0c19maWxlCgp0Y3JfZGl2ZXJzaXR5X2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JHRjcl9kaXZlcnNpdHkKYmNyX2RpdmVyc2l0eV9maWxlIDwtIHNuYWtlbWFrZUBpbnB1dCRiY3JfZGl2ZXJzaXR5CgpuYW5vc3RyaW5nX2RhdGFfcGF0aCA8LSBzbmFrZW1ha2VAaW5wdXQkbmFub3N0cmluZ19kYXRhCm5hbm9zdHJpbmdfYW5ub3RhdGlvbnNfcGF0aCA8LSBzbmFrZW1ha2VAaW5wdXQkbmFub3N0cmluZ19hbm5vdGF0aW9ucwoKY2xvbmFsX21lYXN1cmVzX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGl0aF9zdGF0cwpgYGAKCiMjIE1ldGFkYXRhCgpgYGB7cn0KZGIgPC0gc3JjX3NxbGl0ZShkYl9wYXRoLCBjcmVhdGU9RkFMU0UpCnNhbXBsZXMgPC0gY29sbGVjdCh0YmwoZGIsICJzYW1wbGVzIikpCgppZF9jb2xzIDwtIGMoInZvYSIsICJwYXRpZW50X2lkIiwgImNvbmRlbnNlZF9pZCIsICJmaWVsZCIsICJ0aXNzdWUiKQppZF9jb2xzX3NhbXBsZSA8LSBjKCJ2b2EiLCAicGF0aWVudF9pZCIsICJjb25kZW5zZWRfaWQiLCAidGlzc3VlIikKYGBgCgojIyBBbmFseXNpcwoKYGBge3J9CnJlbmFtZV9maWVsZCA8LSBmdW5jdGlvbihmaWVsZCkgewogIHZvYV9wb3J0aW9uIDwtIHN0cl9yZXBsYWNlKGZpZWxkLCAiX0hQX0lNMy4qJCIsICIiKQogIHZvYV9wb3J0aW9uIDwtIHN0cl9yZXBsYWNlKHZvYV9wb3J0aW9uLCAiXyIsICIgIikKICBmaWVsZF9wb3J0aW9uIDwtIHN0cl9leHRyYWN0KGZpZWxkLCAiX0hQX0lNMy4qJCIpCiAgZmllbGRfcG9ydGlvbiA8LSBzdHJfcmVwbGFjZShmaWVsZF9wb3J0aW9uLCAiX18iLCAiX1siKQogIGZpZWxkX3BvcnRpb24gPC0gcGFzdGUwKGZpZWxkX3BvcnRpb24sICJdIiwgc2VwPSIiKQogIGZpZWxkIDwtIHBhc3RlKHZvYV9wb3J0aW9uLCBmaWVsZF9wb3J0aW9uLCBzZXA9IiIpCiAgcmV0dXJuKGZpZWxkKQp9CgpmdWRnZV9jb2xzIDwtIGZ1bmN0aW9uKGloY19zbGlkZV9zdWJzZXQpIHsKICBjb3VudF9jb2xzIDwtIGNvbG5hbWVzKGloY19zbGlkZV9zdWJzZXQpW3N0cl9kZXRlY3QoY29sbmFtZXMoaWhjX3NsaWRlX3N1YnNldCksICJjb3VudCIpXQogICMjIEpPSU4gV0lUSCBVTkRFUlNDT1JFUywgVEhFTiBVU0UgUkVTSEFQRQogICNuZXdfY29scyA8LSBsYXBwbHkoc3Ryc3BsaXQoc3RyX3JlcGxhY2VfYWxsKGNvdW50X2NvbHMsICJfY291bnQiLCAiIiksICJfIiksIGZ1bmN0aW9uKHgpIHBhc3RlKHJldih4KSwgY29sbGFwc2U9Il8iKSkKICAjY29sbmFtZXMoaWhjX3NsaWRlX3N1YnNldCkgPC0gbWFwdmFsdWVzKGNvbG5hbWVzKGloY19zbGlkZV9zdWJzZXQpLCBjb3VudF9jb2xzLCB1bmxpc3QobmV3X2NvbHMpKQogIGRmX21lbHRlZCA8LSBtZWx0KGloY19zbGlkZV9zdWJzZXQsCiAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoInZvYSIsICJmaWVsZCIsICJjb25kZW5zZWRfaWQiKSwKICAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSBydW4xX2NvbHMsIHZhcmlhYmxlLm5hbWUgPSAidHlwZSIsIHZhbHVlLm5hbWUgPSAiY291bnQiKQogIGRmX21lbHRlZCR0aXNzdWUgPC0gbWFwdmFsdWVzKHN0cl9leHRyYWN0KGRmX21lbHRlZCR0eXBlLCAiXihFfFMpIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbSA9IGMoIkUiLCAiUyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvID0gYygiZXBpdGhlbGlhbCIsICJzdHJvbWEiKSkKICBkZl9tZWx0ZWQkdHlwZSA8LSB0b2xvd2VyKHN0cl9yZXBsYWNlX2FsbChkZl9tZWx0ZWQkdHlwZSwgIiheKEV8UylffF9jb3VudCQpIiwgIiIpKQogIGRmX2Nhc3QgPC0gZGNhc3QoZGZfbWVsdGVkLCB2b2ErZmllbGQrY29uZGVuc2VkX2lkK3Rpc3N1ZSB+IHR5cGUsIGZ1bi5hZ2dyZWdhdGUgPSBzdW0sIHZhbHVlLnZhciA9ICJjb3VudCIpCiAgZGZfZnVkZ2UgPC0gZGZfY2FzdCAlPiUgbXV0YXRlKAogICAgY2Q4X2NkOD1jZDgqY2Q4LAogICAgY2Q0X2NkOD1jZDQqY2Q4LAogICAgY2Q0X2NkND1jZDQqY2Q0LAogICAgY2QyMF9jZDQ9Y2QyMCpjZDQsCiAgICBjZDIwX2NkOD1jZDIwKmNkOCwKICAgIGNkMjBfY2QyMD1jZDIwKmNkMjAKICApCiAgcmV0dXJuKGRmX2Z1ZGdlKQp9CmBgYAoKYGBge3J9CnNwYXRpYWxfZGF0YSA8LSBmcmVhZChzcGF0aWFsX3Jlc3VsdHNfZmlsZSkKaWYgKCJ0aXNzdWUuMSIgJWluJSBjb2xuYW1lcyhzcGF0aWFsX2RhdGEpKSB7CiAgc3BhdGlhbF9kYXRhIDwtIHN1YnNldChzcGF0aWFsX2RhdGEsIHNlbGVjdD0tYyh0aXNzdWUuMSkpCn0Kc3BhdGlhbF9kYXRhJGZpZWxkIDwtIHJlbmFtZV9maWVsZChzcGF0aWFsX2RhdGEkZmllbGQpCgppaGNfdGFibGVfc2xpZGUgPC0gZnJlYWQoaWhjX3RhYmxlX3NsaWRlX3BhdGgpCmloY190YWJsZV9zbGlkZSRmaWVsZCA8LSBzdHJfcmVwbGFjZShpaGNfdGFibGVfc2xpZGUkc2xpZGUsICJcXC5pbTMkIiwgIiIpCmloY190YWJsZV9zbGlkZSA8LSBzdWJzZXQoaWhjX3RhYmxlX3NsaWRlLCBzZWxlY3Q9LWMoc2xpZGUpKQoKcnVuMV90aWxzIDwtIGMoIkNEOF9jb3VudCIsICJDRDRfY291bnQiLCAiQ0QyMF9jb3VudCIpCnJ1bjFfY29scyA8LSBjKHBhc3RlMCgiRV8iLCBydW4xX3RpbHMpLCBwYXN0ZTAoIlNfIiwgcnVuMV90aWxzKSkKaWhjX3NsaWRlX3N1YnNldCA8LSBzdWJzZXQoaWhjX3RhYmxlX3NsaWRlLCBzZWxlY3Q9Yygidm9hIiwgImZpZWxkIiwgImNvbmRlbnNlZF9pZCIsIHJ1bjFfY29scykpCmBgYAoKYGBge3J9CmloY19zbGlkZV9mdWRnZSA8LSBmdWRnZV9jb2xzKGloY19zbGlkZV9zdWJzZXQpCgpJTlRFUkFDVElPTl9WQVJTIDwtIGMoImNkOF9jZDgiLCAiY2Q0X2NkOCIsICJjZDRfY2Q0IiwgImNkMjBfY2Q0IiwgImNkMjBfY2Q4IiwgImNkMjBfY2QyMCIpCgppaGNfc2xpZGVfZnVkZ2VfbWVsdGVkIDwtIG1lbHQoaWhjX3NsaWRlX2Z1ZGdlLCBpZC52YXJzID0gYygidm9hIiwgImZpZWxkIiwgImNvbmRlbnNlZF9pZCIsICJ0aXNzdWUiKSwgCiAgICAgbWVhc3VyZS52YXJzID0gSU5URVJBQ1RJT05fVkFSUywKICAgICB2YXJpYWJsZS5uYW1lID0gInR5cGUiLCB2YWx1ZS5uYW1lID0gImNvdW50IikKc3BhdGlhbF9kYXRhX21lbHRlZCA8LSBtZWx0KHNwYXRpYWxfZGF0YSwgaWQudmFycyA9IGMoInZvYSIsICJmaWVsZCIsICJ0aXNzdWUiLCAid2VpZ2h0IiwgImNvbmRlbnNlZF9pZCIsICJwYXRpZW50X2lkIiksIG1lYXN1cmUudmFycyA9IElOVEVSQUNUSU9OX1ZBUlMsIHZhcmlhYmxlLm5hbWUgPSAidHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gImdhbW1hIikKYGBgCgpgYGB7cn0Kc3BhdGlhbF9kYXRhX21lcmdlIDwtIG1lcmdlKHNwYXRpYWxfZGF0YV9tZWx0ZWQsIGloY19zbGlkZV9mdWRnZV9tZWx0ZWQsIGJ5PWMoInZvYSIsICJmaWVsZCIsICJ0aXNzdWUiLCAiY29uZGVuc2VkX2lkIiwgInR5cGUiKSkKClRIUkVTSE9MRCA8LSAxMAoKc3BhdGlhbF9kYXRhX21lcmdlIDwtIHN1YnNldChzcGF0aWFsX2RhdGFfbWVyZ2UsIGNvdW50ID49IFRIUkVTSE9MRCkKCnNwYXRpYWxfc3VtbWFyeV9tZWx0ZWQgPC0gc3BhdGlhbF9kYXRhX21lcmdlICU+JSBncm91cF9ieV8oLmRvdHMgPSBjKGlkX2NvbHMsICJ0eXBlIikpICU+JSBzdW1tYXJpc2UoZ2FtbWE9d2VpZ2h0ZWQubWVhbihnYW1tYSwgd2VpZ2h0KSkKYGBgCgojIyMgUmVtb3ZlIHN1cGVyLW91dGxpZXJzCgpgYGB7cn0Kc3BhdGlhbF9zdW1tYXJ5X21lbHRlZF9maWx0ZXJlZCA8LSBzcGF0aWFsX3N1bW1hcnlfbWVsdGVkICU+JSBncm91cF9ieSh0eXBlLCB0aXNzdWUpICU+JSBmaWx0ZXIoIShhYnMoZ2FtbWEtbWVkaWFuKGdhbW1hLG5hLnJtPVRSVUUpKSA+IDEwKklRUihnYW1tYSxuYS5ybT1UUlVFKSkpCmBgYAoKIyMjIFBvc3RlcmlvciBkaXN0cmlidXRpb25zCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQpnZ3Bsb3Qoc3BhdGlhbF9zdW1tYXJ5X21lbHRlZF9maWx0ZXJlZCwgYWVzKHg9Z2FtbWEpKSArIGdlb21faGlzdG9ncmFtKGFlcyhmaWxsPXRpc3N1ZSksIGJpbnM9MzApICsgdGhlbWVfYncoKSArIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyBmYWNldF93cmFwKH4gdHlwZSwgc2NhbGVzPSJmcmVlIikKYGBgCgojIyMgQ29ycmVsYXRpb25zIHdpdGggVElMIGRlbnNpdGllcwoKIyMjIyBTbGlkZSBsZXZlbAoKYGBge3J9CnNwYXRpYWxfc3VtbWFyeV9maWx0ZXJlZCA8LSBkY2FzdChzcGF0aWFsX3N1bW1hcnlfbWVsdGVkX2ZpbHRlcmVkLCBmaWVsZCt0aXNzdWUgfiB0eXBlLHZhbHVlLnZhciA9ICJnYW1tYSIpCgpzcGF0aWFsX2loYyA8LSBtZXJnZShpaGNfdGFibGVfc2xpZGUsIHNwYXRpYWxfc3VtbWFyeV9maWx0ZXJlZCwgYnk9YygiZmllbGQiKSkKCklIQ19WQVJTIDwtIGMoIlRfQ0Q4X2RlbnNpdHkiLCAiVF9DRDRfZGVuc2l0eSIsICJUX0NEMjBfZGVuc2l0eSIsICJUX1BsYXNtYV9kZW5zaXR5IiwKICAgICAgICAgICAgICAiRV9DRDhfZGVuc2l0eSIsICJFX0NENF9kZW5zaXR5IiwgIkVfQ0QyMF9kZW5zaXR5IiwgIkVfUGxhc21hX2RlbnNpdHkiLAogICAgICAgICAgICAgICJTX0NEOF9kZW5zaXR5IiwgIlNfQ0Q0X2RlbnNpdHkiLCAiU19DRDIwX2RlbnNpdHkiLCAiU19QbGFzbWFfZGVuc2l0eSIsCiAgICAgICAgICAgICAgIlJVTjFfRV9hcmVhX3BjdCIsICJSVU4xX1NfYXJlYV9wY3QiKQpgYGAKCmBgYHtyfQpwbG90X2NvcnJlbGF0aW9uX2hlYXRtYXAgPC0gZnVuY3Rpb24oZGF0LCBpZF9jb2xzLCBWQVJTKSB7CiAgc3BhdGlhbF9paGNfc3Vic2V0IDwtIHN1YnNldChkYXQsIHNlbGVjdD1jKGlkX2NvbHMsIFZBUlMpKQogIHNwYXRpYWxfaWhjX3N1YnNldF9tYXQgPC0gc3Vic2V0KHNwYXRpYWxfaWhjX3N1YnNldCwgc2VsZWN0PWMoVkFSUykpCiAgCiAgY29ycmVzIDwtIGNvcnIudGVzdChzcGF0aWFsX2loY19zdWJzZXRfbWF0LCBhZGp1c3Q9ImZkciIsIG1ldGhvZD0ic3BlYXJtYW4iKQogIGNvcnJlcy5yIDwtIGNvcnJlcyRyCiAgY29ycmVzLnAgPC0gY29ycmVzJHAKICBoYyA8LSBoY2x1c3QoZGlzdChjb3JyZXMuciksIG1ldGhvZD0id2FyZC5EIikKICAKICBkaWFnKGNvcnJlcy5yKSA8LSBOQQogIGRpYWcoY29ycmVzLnApIDwtIE5BCiAgCiAgY29ycmVzLmxhYmVscyA8LSBmb3JtYXQoc2lnbmlmKGNvcnJlcy5wLCAyKSwgMikKICAKICBjb2xzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiIzk1Y2JlZSIsICIjZmZkNzNlIiwiI2NlNDcyZSIpKSgxMDApCiAgcGhlYXRtYXAoY29ycmVzLnJbaGMkb3JkZXIsaGMkb3JkZXJdLCBkaXNwbGF5X251bWJlcnMgPSBjb3JyZXMubGFiZWxzLCAKICAgICAgICAgICBjb2xvciA9IGNvbHMsIG51bWJlcl9jb2xvciA9ICJibGFjayIsIAogICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsIGNsdXN0ZXJfY29scz1UUlVFKQp9CmBgYAoKYGBge3IgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEwfQojIyBXaWxsIGZhaWwgZHVlIHRvIGZpbHRlcmluZwojcGxvdF9jb3JyZWxhdGlvbl9oZWF0bWFwKHN1YnNldChzcGF0aWFsX2loYywgdGlzc3VlID09ICJlcGl0aGVsaWFsIiksIGlkX2NvbHMsIGMoSUhDX1ZBUlMsIElOVEVSQUNUSU9OX1ZBUlMpKQpgYGAKCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xMH0KI3Bsb3RfY29ycmVsYXRpb25faGVhdG1hcChzdWJzZXQoc3BhdGlhbF9paGMsIHRpc3N1ZSA9PSAic3Ryb21hIiksIGlkX2NvbHMsIGMoSUhDX1ZBUlMsIElOVEVSQUNUSU9OX1ZBUlMpKQpgYGAKCiMjIyMgU2FtcGxlIGxldmVsCgpgYGB7cn0KaWhjX3RhYmxlIDwtIGZyZWFkKGloY190YWJsZV9wYXRoKQoKTl9USFJFU0hPTEQgPC0gMAoKc3BhdGlhbF9zdW1tYXJ5X21lbHRlZF9maWx0ZXJlZF9zYW1wbGUgPC0gc3BhdGlhbF9zdW1tYXJ5X21lbHRlZF9maWx0ZXJlZCAlPiUgZ3JvdXBfYnkodm9hLCBwYXRpZW50X2lkLCBjb25kZW5zZWRfaWQsIHRpc3N1ZSwgdHlwZSkgJT4lIHN1bW1hcmlzZShnYW1tYT1tZWFuKGdhbW1hLCBuYS5ybT1UUlVFKSwgbj1uKCkpCnNwYXRpYWxfc3VtbWFyeV9tZWx0ZWRfZmlsdGVyZWRfc2FtcGxlIDwtIHN1YnNldChzcGF0aWFsX3N1bW1hcnlfbWVsdGVkX2ZpbHRlcmVkX3NhbXBsZSwgbiA+PSBOX1RIUkVTSE9MRCkKCnNwYXRpYWxfc3VtbWFyeV9maWx0ZXJlZF9zYW1wbGUgPC0gZGNhc3Qoc3BhdGlhbF9zdW1tYXJ5X21lbHRlZF9maWx0ZXJlZF9zYW1wbGUsIHZvYStjb25kZW5zZWRfaWQrdGlzc3VlIH4gdHlwZSx2YWx1ZS52YXIgPSAiZ2FtbWEiKQoKc3BhdGlhbF9paGNfc2FtcGxlIDwtIG1lcmdlKGloY190YWJsZSwgc3BhdGlhbF9zdW1tYXJ5X2ZpbHRlcmVkX3NhbXBsZSwgYnk9Yygidm9hIiwgImNvbmRlbnNlZF9pZCIpKQpgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTB9CnBsb3RfY29ycmVsYXRpb25faGVhdG1hcChzdWJzZXQoc3BhdGlhbF9paGNfc2FtcGxlLCB0aXNzdWUgPT0gImVwaXRoZWxpYWwiKSwgaWRfY29sc19zYW1wbGUsIGMoSUhDX1ZBUlMsIElOVEVSQUNUSU9OX1ZBUlMpKQpgYGAKCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xMH0KcGxvdF9jb3JyZWxhdGlvbl9oZWF0bWFwKHN1YnNldChzcGF0aWFsX2loY19zYW1wbGUsIHRpc3N1ZSA9PSAic3Ryb21hIiksIGlkX2NvbHNfc2FtcGxlLCBjKElIQ19WQVJTLCBJTlRFUkFDVElPTl9WQVJTKSkKYGBgCgoKIyMjIENvcnJlbGF0aW9ucyB3aXRoIElUSAoKYGBge3J9CmNsb25hbF9tZWFzdXJlcyA8LSByZWFkX2l0aF9zdGF0cyhjbG9uYWxfbWVhc3VyZXNfZmlsZSwgZGJfcGF0aCwgZHVwbGljYXRlcz1GQUxTRSkKCklUSF9WQVJTIDwtIGMoImVudHJvcHkiLCAiZGl2ZXJnZW5jZSIsICJwb3N0cHJvY2Vzc2VkX2RpdmVyZ2VuY2UiLCAiY29tYmluZWRfaXRoX3JhdyIsICJjb21iaW5lZF9pdGhfbm9ybWFsaXplZCIsICJwcm9wb3J0aW9uX3N1YmNsb25hbCIpCmBgYAoKYGBge3J9CnNwYXRpYWxfaXRoIDwtIG1lcmdlKGNsb25hbF9tZWFzdXJlcywgc3BhdGlhbF9zdW1tYXJ5X2ZpbHRlcmVkX3NhbXBsZSwgYnk9YygiY29uZGVuc2VkX2lkIikpCmBgYAoKYGBge3J9CnBsb3RfY29ycmVsYXRpb25faGVhdG1hcChzdWJzZXQoc3BhdGlhbF9pdGgsIHRpc3N1ZSA9PSAiZXBpdGhlbGlhbCIpLCBpZF9jb2xzX3NhbXBsZSwgYyhJVEhfVkFSUywgSU5URVJBQ1RJT05fVkFSUykpCmBgYAoKYGBge3J9CnBsb3RfY29ycmVsYXRpb25faGVhdG1hcChzdWJzZXQoc3BhdGlhbF9pdGgsIHRpc3N1ZSA9PSAic3Ryb21hIiksIGlkX2NvbHNfc2FtcGxlLCBjKElUSF9WQVJTLCBJTlRFUkFDVElPTl9WQVJTKSkKYGBgCgpgYGB7cn0Kc3BhdGlhbF9pdGhfbWVsdGVkIDwtIG1lbHQoc3BhdGlhbF9pdGgsIGlkLnZhcnMgPSBjb2xuYW1lcyhzcGF0aWFsX2l0aClbIWNvbG5hbWVzKHNwYXRpYWxfaXRoKSAlaW4lIElUSF9WQVJTXSwgbWVhc3VyZS52YXJzID0gSVRIX1ZBUlMsIHZhcmlhYmxlLm5hbWUgPSAiaXRodHlwZSIsIHZhbHVlLm5hbWUgPSAiaXRoIikKCnNwYXRpYWxfaXRoX21lbHRlZCRwYXRpZW50X2lkIDwtIGZhY3RvcihzcGF0aWFsX2l0aF9tZWx0ZWQkcGF0aWVudF9pZCkKCnB2YWxzIDwtIHNldE5hbWVzKGRkcGx5KHNwYXRpYWxfaXRoX21lbHRlZCwgLih0aXNzdWUsaXRodHlwZSksIGZ1bmN0aW9uKHgpIHsKICBkZiA8LSB4CiAgY29ycmVzIDwtIHdpdGgoZGYsIGNvci50ZXN0KGNkOF9jZDgsIGl0aCwgbWV0aG9kPSJzcGVhcm1hbiIpKQogIAogIHB2YWwgPC0gY29ycmVzJHAudmFsdWUKICBlcSA8LSBzdWJzdGl0dXRlKGl0YWxpYyhQKT09cCwgbGlzdChwPWZvcm1hdChwdmFsLCBkaWdpdHM9MykpKQogIHJldHVybihhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpKQp9KSwgYygidGlzc3VlIiwgIml0aHR5cGUiLCAicC52YWx1ZSIpKQoKZ2dwbG90KHNwYXRpYWxfaXRoX21lbHRlZCwgYWVzKHg9Y2Q4X2NkOCwgeT1pdGgpKSArIGdlb21fcG9pbnQoYWVzKGNvbG91cj1wYXRpZW50X2lkKSkgKyBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbF9wYXRpZW50KSArIHRoZW1lX2J3KCkgKyB0aGVtZV9QdWJsaWNhdGlvbigpICsgZmFjZXRfd3JhcCh0aXNzdWUgfiBpdGh0eXBlLCBzY2FsZXM9ImZyZWUiKSArIGdlb21fdGV4dChkYXRhPXB2YWxzLCBhZXMoeD1JbmYsIHk9SW5mLCBsYWJlbD1wLnZhbHVlKSwgaGp1c3Q9MS4xLCB2anVzdD0xLjUsc2l6ZT0zLHBhcnNlPVRSVUUpIApgYGAKCgo=