library(ithi.utils)
load_base_libs()

library(ithi.meta)
library(ithi.ihc)
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
tils_for_cluster <- unlist(snakemake@params$tils_for_cluster)
nclusts <- as.numeric(snakemake@params$nclusts)

tils_for_variability <- unlist(snakemake@params$tils_for_variability)
variability_type <- snakemake@params$variability_type

# clone_tree_dir <- snakemake@input$clone_tree_dir
clone_tree_file <- snakemake@input$clone_tree_file
clone_prevalence_file <- snakemake@input$clone_prevalence_file
clone_branch_length_file <- snakemake@input$clone_branch_length_file
clonal_measures_file <- snakemake@input$ith_stats
prevalence_threshold <- as.numeric(snakemake@params$prevalence_threshold)

proportion_subclonality_file <- snakemake@input$subclonality

Metadata

id_type <- "condensed_id"

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

TIL-based clusters

We’ll use the following TIL subsets for clustering E_CD8_density, E_CD4_density, E_CD20_density, E_Plasma_density, S_CD8_density, S_CD4_density, S_CD20_density, S_Plasma_density.

ihc_table <- fread(ihc_table_path)
ihc_data <- subset(ihc_table, select = c(tils_for_cluster))
valid_rows <- apply(ihc_data, 1, function(x) all(!is.na(x)))

patient_ids <- as.data.frame(subset(ihc_table, select = c(patient_id)))
ihc_data <- as.data.frame(ihc_data[valid_rows, ])

patient_ids <- patient_ids[valid_rows, , drop = FALSE]
patient_ids$patient_id <- factor(patient_ids$patient_id)
colnames(patient_ids) <- "Patient"

rownames(ihc_data) <- rownames(patient_ids) <- as.data.frame(ihc_table)[, id_type][valid_rows]
dat_processed <- t(clip_values(scale(ihc_data)))
rownames(dat_processed) <- mapvalues(rownames(dat_processed), from = c("E_CD8_density", 
    "E_CD4_density", "E_CD20_density", "E_Plasma_density", "S_CD8_density", 
    "S_CD4_density", "S_CD20_density", "S_Plasma_density"), to = c("E CD8+", 
    "E CD4+", "E CD20+", "E Plasma", "S CD8+", "S CD4+", "S CD20+", "S Plasma"))

p <- pheatmap(dat_processed, clustering_method = "ward.D", annotation_col = patient_ids, 
    annotation_colors = list(Patient = pal_patient), cluster_rows = FALSE, show_colnames = FALSE, 
    legend = TRUE, cellwidth = 10, cellheight = 10, annotation_legend = FALSE)

clusts <- data.frame(cutree(p$tree_col, nclusts))
setDT(clusts, keep.rownames = TRUE)
clusts <- setNames(clusts, c(id_type, "cluster"))

clusts$cluster <- factor(clusts$cluster)
ihc_table_annotated <- merge(ihc_table, clusts, by = c(id_type))

Clonal diversity

tree_branch_data <- read_clone_tree_data(clone_tree_file, clone_branch_length_file, 
    clone_prevalence_file, db_path)
trees <- lapply(tree_branch_data, function(x) x$tree)
prevalences <- rbind.fill(lapply(tree_branch_data, function(x) x$prevalence_dat))
branch_lengths <- rbind.fill(lapply(tree_branch_data, function(x) x$branch_dat))

ccfs <- compute_ccf(prevalences, trees, id_type = id_type)
ccfs_labeled <- merge(ccfs, branch_lengths, by = c("label", "node", "patient_id"))

clonal_measures <- read_ith_stats(clonal_measures_file, db_path, duplicates = FALSE)
prevalence_indices <- prevalences %>% group_by(condensed_id, patient_id) %>% 
    summarise(shannon = vegan::diversity(clonal_prevalence, index = "shannon"), 
        simpson = vegan::diversity(clonal_prevalence, index = "simpson"))

prevalences_filtered <- subset(prevalences, clonal_prevalence >= prevalence_threshold)
# vafs_filtered <- subset(vafs, prevalence >= prevalence_threshold) ## Not
# exactly right but close enough
divergence <- compute_clone_divergence(prevalences_filtered, trees, id_type)
# divergence_weighted <- compute_clone_divergence(prevalences_filtered,
# vafs_filtered, clone_trees, branch_lengths, id_type, weighted=TRUE)
# colnames(divergence_weighted) <- mapvalues(colnames(divergence_weighted),
# from = 'clone_divergence', to = 'clone_divergence_weighted')
diversity <- Reduce(function(x, y) merge(x, y, by = c(id_type, "patient_id"), 
    all = TRUE), list(prevalence_indices, clonal_measures))

ITH-TIL correlations

Old measures

We’ll use proportion_subclonality as the surrogate.

proportion_subclonal <- fread(proportion_subclonality_file)

res <- plyr::join(clusts, proportion_subclonal)

if (nclusts == 2) {
    corres <- wilcox.test(proportion_subclonal ~ cluster, data = res)
} else {
    corres <- kruskal.test(proportion_subclonal ~ cluster, data = res)
}

pval <- corres$p.value
eq <- substitute(italic(P) == p, list(p = format(pval, digits = 3)))

ggplot(res, aes(x = cluster, y = proportion_subclonal)) + geom_boxplot(aes(fill = cluster)) + 
    theme_bw() + theme_Publication() + scale_fill_Publication() + annotate("text", 
    x = Inf, y = Inf, parse = TRUE, hjust = 1, vjust = 1, label = as.character(as.expression(eq)))

By a Kruskal-Wallis test.

If we instead choose to compare cluster 3 (high epithelial TILs) against everything else, then:

wilcox.test(proportion_subclonal ~ cluster == 3, data = res)

    Wilcoxon rank sum test

data:  proportion_subclonal by cluster == 3
W = 424, p-value = 0.005338
alternative hypothesis: true location shift is not equal to 0

New measures (in progress)

res <- merge(diversity, ihc_table_annotated, by = c(id_type, "patient_id"))

ith_measures <- c("shannon", "entropy", "simpson", "divergence", "postprocessed_divergence", 
    "proportion_subclonal", "combined_ith_normalized", "combined_ith_raw")
res_melted <- reshape2::melt(res, id.vars = c(id_type, "patient_id", "cluster"), 
    measure.vars = ith_measures, variable.name = "ith_type", value.name = "ith")
res_melted$ith_type <- factor(res_melted$ith_type)
stats <- setNames(ddply(res_melted, .(ith_type), function(x) {
    if (nclusts == 2) {
        res <- wilcox.test(ith ~ cluster, data = x)
    } else {
        res <- kruskal.test(ith ~ cluster, data = x)
    }
    pvalue <- res$p.value
    eq <- substitute(italic(P) == p, list(p = format(pvalue, digits = 3)))
    return(as.character(as.expression(eq)))
}), c("ith_type", "p.value"))
ggplot(res_melted, aes(x = cluster, y = ith)) + geom_boxplot(aes(fill = cluster)) + 
    theme_bw() + theme_Publication() + scale_fill_Publication() + facet_wrap(~ith_type, 
    scales = "free") + geom_text(data = stats, aes(x = Inf, y = Inf, label = p.value), 
    hjust = 1.1, vjust = 1.5, size = 3, parse = TRUE)

Check with Andrew as to how he computed clone divergence – my computations based on what I believe the definition is are different. Perhaps it’s a 1-minus issue?

ITH-TIL variability

ihc_table_slide <- fread(ihc_table_slide_path)

ihc_slide_data <- subset(ihc_table_slide, select = c("condensed_id", "patient_id", 
    "slide", tils_for_variability))
ihc_melted <- melt(ihc_slide_data, id.vars = c("condensed_id", "patient_id", 
    "slide"), measure.vars = tils_for_variability, variable.name = "tiltype", 
    value.name = "density")
ihc_melted$tiltype <- as.character(ihc_melted$tiltype)

intersect_samples <- intersect(unique(ihc_melted$condensed_id), unique(ccfs_labeled$condensed_id))

til_var <- compute_ihc_var(ihc_melted, ihc_table, samples = intersect_samples, 
    til_variance_option = variability_type, tils_for_variability)

clonedists <- clone_distances(ccfs_labeled, normalize = FALSE, id_type = id_type)
clonedists$patient_id <- as.character(clonedists$patient_id)

variabilities <- inner_join(til_var, subset(clonedists, select = -c(dist_clones_weighted)), 
    by = c("patient_id"))
variabilities_melted <- melt(variabilities, id.vars = c("patient_id", "mean_weighted_dist"), 
    measure.vars = tils_for_variability, variable.name = "tiltype", value.name = "tilvar")
variabilities_melted$patient_id <- factor(variabilities_melted$patient_id)
stats <- setNames(ddply(variabilities_melted, .(tiltype), function(x) {
    res <- with(x, cor.test(mean_weighted_dist, tilvar, method = "spearman"))
    pvalue <- res$p.value
    eq <- substitute(italic(P) == p, list(p = format(pvalue, digits = 3)))
    return(as.character(as.expression(eq)))
}), c("tiltype", "p.value"))
p <- ggplot(variabilities_melted, aes(x = mean_weighted_dist, y = tilvar)) + 
    geom_point(aes(colour = patient_id)) + theme_bw() + theme_Publication()
p <- p + facet_wrap(~tiltype, scales = "free", nrow = 1)
p <- p + theme(axis.text.x = element_text(size = 6, family = "Helvetica"), legend.text = element_text(size = 6, 
    family = "Helvetica"), axis.text.y = element_text(size = 6, family = "Helvetica"), 
    axis.title = element_text(size = 8, family = "Helvetica"), strip.text = element_text(size = 7, 
        family = "Helvetica"), strip.background = element_rect(fill = "white"))
p <- p + ylab("Variability") + xlab("Mean clonal distance")
p <- p + geom_text(data = stats, aes(x = Inf, y = Inf, label = p.value), hjust = 1.1, 
    vjust = 1.5, size = 3, parse = TRUE)
p <- p + scale_colour_manual(values = pal_patient) + guides(colour = guide_legend(title = "Patient"))

plot(p)

LS0tCnRpdGxlOiAiSVRILVRJTCBhbmFseXNpcyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDUKICAgIHRvY19mbG9hdDogdHJ1ZQpwYXJhbXM6CiAgcm1kOiAiaXRoX3RpbF9kZW5zaXRpZXMuUm1kIgotLS0KICAgICAgICAgICAgICAgICAgICAgICAgYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIyMjIyMjIyBTbmFrZW1ha2UgaGVhZGVyICMjIyMjIyMjCmxpYnJhcnkobWV0aG9kcykKU25ha2VtYWtlIDwtIHNldENsYXNzKAogICAgIlNuYWtlbWFrZSIsCiAgICBzbG90cyA9IGMoCiAgICAgICAgaW5wdXQgPSAibGlzdCIsCiAgICAgICAgb3V0cHV0ID0gImxpc3QiLAogICAgICAgIHBhcmFtcyA9ICJsaXN0IiwKICAgICAgICB3aWxkY2FyZHMgPSAibGlzdCIsCiAgICAgICAgdGhyZWFkcyA9ICJudW1lcmljIiwKICAgICAgICBsb2cgPSAibGlzdCIsCiAgICAgICAgcmVzb3VyY2VzID0gImxpc3QiLAogICAgICAgIGNvbmZpZyA9ICJsaXN0IiwKICAgICAgICBydWxlID0gImNoYXJhY3RlciIKICAgICkKKQpzbmFrZW1ha2UgPC0gU25ha2VtYWtlKAogICAgaW5wdXQgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGVfc2xpZGUudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2loY190YWJsZS50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL2JyYW5jaF9kYXRhLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9pdGhfc3RhdGlzdGljcy50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL2FuYWx5c2lzL1JtZC9fc2l0ZS55bWwnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3RyZWVfZGF0YS50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL2Nsb25lX2RhdGEudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2l0aC9jb21wbGV0ZS9vbGRfcHJvcG9ydGlvbl9zdWJjbG9uYWwudHN2JywgJ1JtZC9pdGhfdGlsX2RlbnNpdGllcy5SbWQnLCAiY2xvbmVfdHJlZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvdHJlZV9kYXRhLnRzdicsICJpaGNfdGFibGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2loY190YWJsZS50c3YnLCAiY2xvbmVfYnJhbmNoX2xlbmd0aF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvYnJhbmNoX2RhdGEudHN2JywgIml0aF9zdGF0cyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvaXRoX3N0YXRpc3RpY3MudHN2JywgInNpdGVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL2FuYWx5c2lzL1JtZC9fc2l0ZS55bWwnLCAiY2xvbmVfcHJldmFsZW5jZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvY2xvbmVfZGF0YS50c3YnLCAiaWhjX3RhYmxlX3NsaWRlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGVfc2xpZGUudHN2JywgInN1YmNsb25hbGl0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaXRoL2NvbXBsZXRlL29sZF9wcm9wb3J0aW9uX3N1YmNsb25hbC50c3YnLCAibm90ZWJvb2siID0gJ1JtZC9pdGhfdGlsX2RlbnNpdGllcy5SbWQnKSwKICAgIG91dHB1dCA9IGxpc3QoJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3dlYi9pdGhfdGlsX2RlbnNpdGllcy5uYi5odG1sJyksCiAgICBwYXJhbXMgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsIGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksIDMsIGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICdpdGhpLWFuYWx5c2lzLWl0aC10aWwtYW5hbHlzaXMnLCAwLjAxLCAnc3RhYmlsaXplJywgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJ0aWxzX2Zvcl92YXJpYWJpbGl0eSIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAibmNsdXN0cyIgPSAzLCAidGlsc19mb3JfY2x1c3RlciIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAibmFtZSIgPSAnaXRoaS1hbmFseXNpcy1pdGgtdGlsLWFuYWx5c2lzJywgInByZXZhbGVuY2VfdGhyZXNob2xkIiA9IDAuMDEsICJ2YXJpYWJpbGl0eV90eXBlIiA9ICdzdGFiaWxpemUnKSwKICAgIHdpbGRjYXJkcyA9IGxpc3QoKSwKICAgIHRocmVhZHMgPSAxLAogICAgbG9nID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9jbHVzdHRtcC9wYXBlcmFuYWx5c2lzMi9pdGhfdGlsX2FuYWx5c2lzLmxvZycpLAogICAgcmVzb3VyY2VzID0gbGlzdCgpLAogICAgY29uZmlnID0gbGlzdCgibW1jdG1fZmluYWxfcGF0aWVudF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnRfd2l0aC1vdicsICJrbm93bl9zdWJ0eXBlX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vYXJyYXkvc3VidHlwZXMva25vd25fc3VidHlwZXMudHN2JywgInRpbHNfZm9yX3ZhcmlhYmlsaXR5IiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJpaGNfcnVuMiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaWhjL2NkNzljZDEzOGNkNjgvdmFsaWRhdGVkX3N0YXRzX3dlaWdodGVkLnJkYXRhJywgIm5lb2VkaXRpbmdfb3V0ZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9uZW9lZGl0aW5nL3J1bjQnLCAia25vd25fc3VidHlwZXNfbWVyZ2VkIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL2tub3duX3N1YnR5cGVzX21lcmdlZC50c3YnLCAibmFub3N0cmluZ19kYXRhIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9uYW5vc3RyaW5nX3Jlc3VsdHMvaXRoX2Z1bGwvcWMvbGltbWFfcXVhbnRpbGUvbm9ybWFsaXplZF9leHByZXNzaW9uX3ZvYV9sYWJlbHNfZmlsdGVyZWQudHN2JywgInRjcl9jbG9ub3R5cGVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvY2xvbm90eXBlcy9UUkJfY2xvbm90eXBlc19maWx0ZXJlZC50eHQnLCAiaXRoX3Byb2plY3RfcmVzdWx0cyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9pdGgzL2RhdGEvcmVzdWx0cycsICJpaGNfeGNyX3RpbHR5cGVzIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JywgJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JyksICJwcmV2YWxlbmNlX3RocmVzaG9sZCIgPSAwLjAxLCAiY2xvbmFsX3NhbXBsZXJzIiA9IGMoJ0hNQycsICdOVVRTJyksICJtYXN0ZXJfYnJlYWtwb2ludF9maWxlIiA9ICcvc2hhaGxhYi9hbWNwaGVyc29uL3Byb2plY3RzL2l0aDMvaXRoMy9ub3RlYm9va3MvYmVzcG9rZS9pdGhfYnJlYWtwb2ludHMudHN2JywgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJtdWx0aXZpZXdjbHVzdGVyaW5nX25vdGVib29rIiA9ICdSbWQvbXVsdGl2aWV3Y2x1c3RlcmluZy5SbWQnLCAiYmVuY2htYXJrZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2JlbmNobWFya3MvcGFwZXJhbmFseXNpczInLCAibXV0YXRpb25fc2lnbmF0dXJlX25vdGVib29rIiA9ICdSbWQvbXV0YXRpb25fc2lnbmF0dXJlcy5SbWQnLCAiaWNnY19zcGVjaW1lbl9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9zcGVjaW1lbi50c3YnLCAibm90ZWJvb2tfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy93ZWInLCAiY2xhc3NpZmllcl90eXBlIiA9ICdrbm4nLCAic2l0ZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvYW5hbHlzaXMvUm1kL19zaXRlLnltbCcsICJwcm9wb3J0aW9uX3N1YmNsb25hbF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvb2xkX3Byb3BvcnRpb25fc3ViY2xvbmFsLnRzdicsICJ2YXJpYWJpbGl0eV90eXBlIiA9ICdzdGFiaWxpemUnLCAidGNnYV9leHByX21hdHJpeCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0EvZXhwcl9tYXRyaXhfbm9ybWFsaXplX3N0YW5kYXJkaXplX25vZHVwbGljYXRlcy50c3YnLCAiUE5HX0RFTlNJVFkiID0gMzAwLCAiUE5HX1FVQUxJVFkiID0gMzAwLCAiaWNnY19ub3JtYWxpemVkX3JlYWRzX21hdHJpeCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvT1ZBVV9leHByX21hdHJpeC50c3YnLCAic2FkX25vdGVib29rIiA9ICdSbWQvc3BlY2llc19hYnVuZGFuY2VfZGlzdHJpYnV0aW9ucy5SbWQnLCAiaWdwYXJ0aXRpb25fb3V0ZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9pZ3BhcnRpdGlvbi9ydW4yMicsICJ4Y3JtYXBzY2FwZV9ub3RlYm9vayIgPSAnUm1kL3hjcm1hcHNjYXBlLlJtZCcsICJ0Y2dhX2NsaW5pY2FsIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvVENHQS9zeW5hcHNlX2NsaW5BbGxfZGF0YS50c3YnLCAibW9sc3VidHlwZV90aWx0eXBlcyIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAic3BhdGlhbF9ub3RlYm9vayIgPSAnUm1kL3NwYXRpYWxfYW5hbHlzaXMuUm1kJywgImloY194Y3Jfc3RhdHNfbm90ZWJvb2siID0gJ1JtZC9paGNfeGNyX3N0YXRzLlJtZCcsICJtdmNsdXN0X3RpbHR5cGVzIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJpbmRleF9ub3RlYm9vayIgPSAnUm1kL2luZGV4LlJtZCcsICJleGFtcGxlX21zYV9wbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9pZ3BhcnRpdGlvbi9ydW4xMy9vbGQvYWxpZ25tZW50X3Bsb3RzL21zYS9pdGgyXzIvY2x1c3Q5L2luZGVsX3JldmVyc2VkLmh0bWwnLCAiaWNnY19tb2xlY3VsYXJfc3VidHlwZXMiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL2ljZ2NfcHJpbWFyeV90dW1vdXJfc3VidHlwZXMudHN2JywgIm1tY3RtX3BhdGllbnRfYW5jZXN0cmFsX2Rlc2NlbmRhbnRfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudC1hbmNlc3RyeS9vdXRwdXQnLCAiY2xvbmVfdHJlZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvdHJlZV9kYXRhLnRzdicsICJuYW5vc3RyaW5nX2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL25hbm9zdHJpbmcvcGFuY2FuY2VyX2Fubm90YXRpb25zLnRzdicsICJleGFtcGxlX2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9pZ3BhcnRpdGlvbi9ydW4xMy9maW5hbF9wYXJ0aXRpb25zL2l0aDJfMi9jbHVzdDkvYW5ub3RhdGlvbnNfZmxhZ2dlZC50c3YnLCAibW1jdG1fc2FtcGxlX3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXNhbXBsZS9wbG90cy9pdGgtYnktc2FtcGxlX3Nudi1zdl9zaWdzX211bHRpcGFuZWwucGRmJywgIm5jbHVzdHMiID0gMywgInNwYXRpYWxfcmVzdWx0X2RpcnMiID0gbGlzdCgiZXBpdGhlbGlhbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvc3BhdHNpbS9pdGgzL2FiYycsICJzdHJvbWFsIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9zcGF0c2ltL2l0aDUvYWJjJyksICJ0Y3JfZGl2ZXJzaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvVFJCL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICJqX2RpY3Rpb25hcnkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9zdWJwcm9qZWN0cy9pbW10eXBlci9tZXRhZGF0YS9pbWd0L0hvbW9fc2FwaWVuc19UUkJKLmZhc3RhJywgInhjcl9xY19ub3RlYm9vayIgPSAnUm1kL3JlcGxpY2F0ZXMuUm1kJywgImNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaXRoL2NvbXBsZXRlL2JyYW5jaF9kYXRhLnRzdicsICJkcml2ZXJfbWFwIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvc3VicHJvamVjdHMvZHJpdmVycy9kYXRhL2dlbmVfbGlzdF9tYXBwZWQuYmVkJywgInhjcl9jbG9uZXNfbm90ZWJvb2siID0gJ1JtZC94Y3JfY2xvbmVzX2FuYWx5c2lzLlJtZCcsICJtdmNsdXN0X25jbHVzdCIgPSAzLCAiaW1tdW5lX3ZhcmlhYmlsaXR5X25vdGVib29rIiA9ICdSbWQvaW1tdW5lX3ZhcmlhYmlsaXR5LlJtZCcsICJtbWN0bV9vdl9jb21iaW5lZF9yZXN1bHRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2NvbWJpbmVkX292X21tY3RtL291dHB1dCcsICJuZW9hbnRpZ2VuX2VkaXRpbmdfbm90ZWJvb2siID0gJ1JtZC9pbW11bm9lZGl0aW5nLlJtZCcsICJtbWN0bV9zYW1wbGVfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktc2FtcGxlL291dHB1dCcsICJ2X2RpY3Rpb25hcnkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9zdWJwcm9qZWN0cy9pbW10eXBlci9tZXRhZGF0YS9pbWd0L0hvbW9fc2FwaWVuc19UUkJWLmZhc3RhJywgInhjcl9kaXN0YW5jZV9tZXRob2QiID0gJ2hvcm4nLCAibW9sc3VidHlwZV9ub3RlYm9vayIgPSAnUm1kL21vbGVjdWxhcl9zdWJ0eXBlcy5SbWQnLCAieGNyX21hcHBpbmdfbm90ZWJvb2siID0gJ1JtZC94Y3JfbWFwcGluZy5SbWQnLCAiaXRoX3RpbF9ub3RlYm9vayIgPSAnUm1kL2l0aF90aWxfZGVuc2l0aWVzLlJtZCcsICJtdXRzaWdfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgImRyaXZlcl9hbmFseXNpc19ub3RlYm9vayIgPSAnUm1kL2RyaXZlcl9hbmFseXNpcy5SbWQnLCAiaW50ZXJtZWRpYXRlX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yJywgImltbXR5cGVyX21vZGVscyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvaW1tdHlwZXJfcmVzdWx0cy9rbGFyZW5iZWVrL2FhX3ZqL2dyYWRib29zdCcsICJ3YW5nX2ZiaV9zdGF0dXMiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL25nLjM4NDktUzEyLnR4dCcsICJtbWN0bV9hbmNlc3RyYWxfZGVzY2VuZGFudF9yZXN1bHRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1hbmNlc3RyeS1zYW1wbGUvb3V0cHV0JywgImxvZ2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9jbHVzdHRtcC9wYXBlcmFuYWx5c2lzMicsICJ0aWxzX2Zvcl9jbHVzdGVyIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJjbG9uZV9wcmV2YWxlbmNlX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2l0aC9jb21wbGV0ZS9jbG9uZV9kYXRhLnRzdicsICJiY3JwaHlsb19leGFtcGxlc19ub3RlYm9vayIgPSAnUm1kL2Jjcl9waHlsb19leGFtcGxlcy5SbWQnLCAiaXRoX3N0YXRfdHlwZXMiID0gYygnZW50cm9weScsICdwb3N0cHJvY2Vzc2VkX2RpdmVyZ2VuY2UnLCAnY29tYmluZWRfaXRoX25vcm1hbGl6ZWQnLCAncHJvcG9ydGlvbl9zdWJjbG9uYWwnKSwgInBhdGllbnRzX2Zvcl9jbG9uYWwiID0gYygxLCAyLCAzLCA0LCA3LCA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcpLCAiYmNycGh5bG9fdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgIm1tY3RtX292X2NvbWJpbmVkX3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvY29tYmluZWRfb3ZfbW1jdG0vcGxvdHMvb3Zfc252LXN2X3NpZ3NfbXVsdGlwYW5lbC5wZGYnLCAiaWNnY19jbGluaWNhbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvZG9ub3IuT1YtQVUudHN2JywgInN1YnR5cGVfbWFya2VyX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vbmFub3N0cmluZy9zdWJ0eXBlX21hcmtlcnMudHN2JywgIm1hcHNjYXBlX25vdGVib29rIiA9ICdSbWQvbWFwc2NhcGUuUm1kJywgImJjcl9kaXZlcnNpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9JR0gvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgIm1tY3RtX2ZpbmFsX3BhdGllbnRfc2lncGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudF93aXRoLW92L3Bsb3RzL2l0aC1ieS1wYXRpZW50X3Nudi1zdl9zaWdzX211bHRpcGFuZWwucGRmJywgImZpZ3VyZV9nYWxsZXJ5X25vdGVib29rIiA9ICdSbWQvZmlndXJlcy5SbWQnLCAibWFzdGVyX3ZhcmlhbnRfZmlsZSIgPSAnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX3NudnMudHN2JywgImJjcnBoeWxvX2NvcnJlbGF0aW9uc19ub3RlYm9vayIgPSAnUm1kL2Jjcl9waHlsb19jb3JyZWxhdGlvbnMuUm1kJywgIm5hbm9zdHJpbmdfc2lnbmF0dXJlX25vdGVib29rIiA9ICdSbWQvbmFub3N0cmluZ19zaWduYXR1cmVzLlJtZCcsICJ0Y2dhX292X2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvVENHQS90Y2dhX292X2Fubm90YXRpb25fc3VwMTMudHh0JywgImltbXR5cGVyX2xlbmd0aHMiID0gJzExIDEyIDEzIDE0IDE1IDE2IDE3IDE4JywgInRpbF9jbGFzc2lmaWVyX25vdGVib29rIiA9ICdSbWQvdGlsX2NsYXNzaWZpZXIuUm1kJywgIml0aF9zdGF0c19maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvY2xvbmFsX21lYXN1cmVzLnRzdicsICJtbWN0bV9zYW1wbGVfYWRfc2lncGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktYW5jZXN0cnktc2FtcGxlL3Bsb3RzL2l0aC1ieS1hbmNlc3RyYWwtc2FtcGxlX3Nudi1zdl9zaWdzX211bHRpcGFuZWwucGRmJywgImJjcl9jbG9ub3R5cGVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvY2xvbm90eXBlcy9JR0hfY2xvbm90eXBlc19maWx0ZXJlZC50eHQnLCAiaWhjX3J1bjEiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2loYy9jZDhjZDNjZDIwL3ZhbGlkYXRlZF9zdGF0c193ZWlnaHRlZF9uZXcucmRhdGEnLCAiaXRoX3N0YXRpc3RpY3Nfbm90ZWJvb2siID0gJ1JtZC9pdGhfc3RhdGlzdGljcy5SbWQnLCAibGlicmFyeV9zaXplcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L2xpYnJhcnlfc2l6ZXMudHN2JywgImRlZmF1bHRfc2FtcGxlciIgPSAnSE1DJywgIm1tY3RtX3BhdGllbnRfYWRfc2lncGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudC1hbmNlc3RyeS9wbG90cy9pdGgtYnktcGF0aWVudC1hbmNlc3RyeV9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJpY2djX2V4cHJfbWVsdGVkIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9PVkFVX2V4cHJfbWVsdGVkLnRzdicsICJwaGVub3R5cGVfdGhyZXNob2xkIiA9IDAuODUsICJ0YWJsZV9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yJyksCiAgICBydWxlID0gJ2l0aF90aWxfYW5hbHlzaXMnCikKIyMjIyMjIyMgT3JpZ2luYWwgc2NyaXB0ICMjIyMjIyMjIwoKICAgICAgICAgICAgICAgICAgICAgICAgYGBgCgoKYGBge3IgZ2xvYmFsX2NodW5rX29wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgdGlkeT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFKQpgYGAKCgpgYGB7cn0KbGlicmFyeShpdGhpLnV0aWxzKQpsb2FkX2Jhc2VfbGlicygpCgpsaWJyYXJ5KGl0aGkubWV0YSkKbGlicmFyeShpdGhpLmloYykKbGlicmFyeShpdGhpLmNsb25lcykKYGBgCgojIyBDb2xvdXIgcGFsZXR0ZXMKCmBgYHtyfQpwYWxfcGF0aWVudCA8LSBzZWxlY3RfcGFsZXR0ZSgicGF0aWVudCIpCmBgYAoKIyMgUGFyYW1ldGVycwoKYGBge3J9CmRiX3BhdGggPC0gc25ha2VtYWtlQHBhcmFtcyRkYgoKaWhjX3RhYmxlX3BhdGggPC0gc25ha2VtYWtlQGlucHV0JGloY190YWJsZQppaGNfdGFibGVfc2xpZGVfcGF0aCA8LSBzbmFrZW1ha2VAaW5wdXQkaWhjX3RhYmxlX3NsaWRlCnRpbHNfZm9yX2NsdXN0ZXIgPC0gdW5saXN0KHNuYWtlbWFrZUBwYXJhbXMkdGlsc19mb3JfY2x1c3RlcikKbmNsdXN0cyA8LSBhcy5udW1lcmljKHNuYWtlbWFrZUBwYXJhbXMkbmNsdXN0cykKCnRpbHNfZm9yX3ZhcmlhYmlsaXR5IDwtIHVubGlzdChzbmFrZW1ha2VAcGFyYW1zJHRpbHNfZm9yX3ZhcmlhYmlsaXR5KQp2YXJpYWJpbGl0eV90eXBlIDwtIHNuYWtlbWFrZUBwYXJhbXMkdmFyaWFiaWxpdHlfdHlwZQoKI2Nsb25lX3RyZWVfZGlyIDwtIHNuYWtlbWFrZUBpbnB1dCRjbG9uZV90cmVlX2RpcgpjbG9uZV90cmVlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX3RyZWVfZmlsZQpjbG9uZV9wcmV2YWxlbmNlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX3ByZXZhbGVuY2VfZmlsZQpjbG9uZV9icmFuY2hfbGVuZ3RoX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZQpjbG9uYWxfbWVhc3VyZXNfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkaXRoX3N0YXRzCnByZXZhbGVuY2VfdGhyZXNob2xkIDwtIGFzLm51bWVyaWMoc25ha2VtYWtlQHBhcmFtcyRwcmV2YWxlbmNlX3RocmVzaG9sZCkKCnByb3BvcnRpb25fc3ViY2xvbmFsaXR5X2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JHN1YmNsb25hbGl0eQpgYGAKCiMjIE1ldGFkYXRhCgpgYGB7cn0KaWRfdHlwZSA8LSAiY29uZGVuc2VkX2lkIgoKZGIgPC0gc3JjX3NxbGl0ZShkYl9wYXRoLCBjcmVhdGU9RkFMU0UpCmR1cGxpY2F0ZXMgPC0gY29sbGVjdCh0YmwoZGIsICJkdXBsaWNhdGVzIikpCmBgYAoKIyMgVElMLWJhc2VkIGNsdXN0ZXJzCgpXZSdsbCB1c2UgdGhlIGZvbGxvd2luZyBUSUwgc3Vic2V0cyBmb3IgY2x1c3RlcmluZyBgciB0aWxzX2Zvcl9jbHVzdGVyYC4KCmBgYHtyfQppaGNfdGFibGUgPC0gZnJlYWQoaWhjX3RhYmxlX3BhdGgpCmBgYAoKYGBge3J9CmloY19kYXRhIDwtIHN1YnNldChpaGNfdGFibGUsIHNlbGVjdD1jKHRpbHNfZm9yX2NsdXN0ZXIpKQp2YWxpZF9yb3dzIDwtIGFwcGx5KGloY19kYXRhLCAxLCBmdW5jdGlvbih4KSBhbGwoIWlzLm5hKHgpKSkKCnBhdGllbnRfaWRzIDwtIGFzLmRhdGEuZnJhbWUoc3Vic2V0KGloY190YWJsZSwgc2VsZWN0PWMocGF0aWVudF9pZCkpKQppaGNfZGF0YSA8LSBhcy5kYXRhLmZyYW1lKGloY19kYXRhW3ZhbGlkX3Jvd3MsXSkKCnBhdGllbnRfaWRzIDwtIHBhdGllbnRfaWRzW3ZhbGlkX3Jvd3MsLGRyb3A9RkFMU0VdCnBhdGllbnRfaWRzJHBhdGllbnRfaWQgPC0gZmFjdG9yKHBhdGllbnRfaWRzJHBhdGllbnRfaWQpCmNvbG5hbWVzKHBhdGllbnRfaWRzKSA8LSAiUGF0aWVudCIKCnJvd25hbWVzKGloY19kYXRhKSA8LSByb3duYW1lcyhwYXRpZW50X2lkcykgPC0gYXMuZGF0YS5mcmFtZShpaGNfdGFibGUpWyxpZF90eXBlXVt2YWxpZF9yb3dzXQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MTgsIGZpZy5oZWlnaHQ9NH0KZGF0X3Byb2Nlc3NlZCA8LSB0KGNsaXBfdmFsdWVzKHNjYWxlKGloY19kYXRhKSkpCnJvd25hbWVzKGRhdF9wcm9jZXNzZWQpIDwtIG1hcHZhbHVlcyhyb3duYW1lcyhkYXRfcHJvY2Vzc2VkKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tID0gYygiRV9DRDhfZGVuc2l0eSIsICJFX0NENF9kZW5zaXR5IiwgIkVfQ0QyMF9kZW5zaXR5IiwgIkVfUGxhc21hX2RlbnNpdHkiLCAiU19DRDhfZGVuc2l0eSIsICJTX0NENF9kZW5zaXR5IiwgIlNfQ0QyMF9kZW5zaXR5IiwgIlNfUGxhc21hX2RlbnNpdHkiKSwKICAgICAgICAgIHRvPWMoIkUgQ0Q4KyIsICJFIENENCsiLCAiRSBDRDIwKyIsICJFIFBsYXNtYSIsICJTIENEOCsiLCAiUyBDRDQrIiwgIlMgQ0QyMCsiLCAiUyBQbGFzbWEiKSkKCnAgPC0gcGhlYXRtYXAoZGF0X3Byb2Nlc3NlZCwgY2x1c3RlcmluZ19tZXRob2QgPSAid2FyZC5EIiwgYW5ub3RhdGlvbl9jb2wgPSBwYXRpZW50X2lkcywgCiAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnMgPSBsaXN0KFBhdGllbnQ9cGFsX3BhdGllbnQpLCBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwKICAgICAgICAgICAgICBzaG93X2NvbG5hbWVzID0gRkFMU0UsIGxlZ2VuZCA9IFRSVUUsIGNlbGx3aWR0aD0xMCwgY2VsbGhlaWdodD0xMCwKICAgICAgICAgICAgICBhbm5vdGF0aW9uX2xlZ2VuZCA9IEZBTFNFKQpgYGAKCgoKYGBge3J9CmNsdXN0cyA8LSBkYXRhLmZyYW1lKGN1dHJlZShwJHRyZWVfY29sLCBuY2x1c3RzKSkKc2V0RFQoY2x1c3RzLCBrZWVwLnJvd25hbWVzID0gVFJVRSkKY2x1c3RzIDwtIHNldE5hbWVzKGNsdXN0cywgYyhpZF90eXBlLCAiY2x1c3RlciIpKQoKY2x1c3RzJGNsdXN0ZXIgPC0gZmFjdG9yKGNsdXN0cyRjbHVzdGVyKQppaGNfdGFibGVfYW5ub3RhdGVkIDwtIG1lcmdlKGloY190YWJsZSwgY2x1c3RzLCBieT1jKGlkX3R5cGUpKQpgYGAKCiMjIENsb25hbCBkaXZlcnNpdHkKCmBgYHtyfQp0cmVlX2JyYW5jaF9kYXRhIDwtIHJlYWRfY2xvbmVfdHJlZV9kYXRhKGNsb25lX3RyZWVfZmlsZSwgY2xvbmVfYnJhbmNoX2xlbmd0aF9maWxlLCBjbG9uZV9wcmV2YWxlbmNlX2ZpbGUsIGRiX3BhdGgpCnRyZWVzIDwtIGxhcHBseSh0cmVlX2JyYW5jaF9kYXRhLCBmdW5jdGlvbih4KSB4JHRyZWUpCnByZXZhbGVuY2VzIDwtIHJiaW5kLmZpbGwobGFwcGx5KHRyZWVfYnJhbmNoX2RhdGEsIGZ1bmN0aW9uKHgpIHgkcHJldmFsZW5jZV9kYXQpKQpicmFuY2hfbGVuZ3RocyA8LSByYmluZC5maWxsKGxhcHBseSh0cmVlX2JyYW5jaF9kYXRhLCBmdW5jdGlvbih4KSB4JGJyYW5jaF9kYXQpKQoKY2NmcyA8LSBjb21wdXRlX2NjZihwcmV2YWxlbmNlcywgdHJlZXMsIGlkX3R5cGUgPSBpZF90eXBlKQpjY2ZzX2xhYmVsZWQgPC0gbWVyZ2UoY2NmcywgYnJhbmNoX2xlbmd0aHMsIGJ5PWMoImxhYmVsIiwgIm5vZGUiLCAicGF0aWVudF9pZCIpKQoKY2xvbmFsX21lYXN1cmVzIDwtIHJlYWRfaXRoX3N0YXRzKGNsb25hbF9tZWFzdXJlc19maWxlLCBkYl9wYXRoLCBkdXBsaWNhdGVzID0gRkFMU0UpCmBgYAoKYGBge3J9CnByZXZhbGVuY2VfaW5kaWNlcyA8LSBwcmV2YWxlbmNlcyAlPiUgZ3JvdXBfYnkoY29uZGVuc2VkX2lkLCBwYXRpZW50X2lkKSAlPiUgc3VtbWFyaXNlKHNoYW5ub249dmVnYW46OmRpdmVyc2l0eShjbG9uYWxfcHJldmFsZW5jZSwgaW5kZXg9InNoYW5ub24iKSwgc2ltcHNvbj12ZWdhbjo6ZGl2ZXJzaXR5KGNsb25hbF9wcmV2YWxlbmNlLCBpbmRleD0ic2ltcHNvbiIpKQoKcHJldmFsZW5jZXNfZmlsdGVyZWQgPC0gc3Vic2V0KHByZXZhbGVuY2VzLCBjbG9uYWxfcHJldmFsZW5jZSA+PSBwcmV2YWxlbmNlX3RocmVzaG9sZCkKI3ZhZnNfZmlsdGVyZWQgPC0gc3Vic2V0KHZhZnMsIHByZXZhbGVuY2UgPj0gcHJldmFsZW5jZV90aHJlc2hvbGQpICMjIE5vdCBleGFjdGx5IHJpZ2h0IGJ1dCBjbG9zZSBlbm91Z2gKZGl2ZXJnZW5jZSA8LSBjb21wdXRlX2Nsb25lX2RpdmVyZ2VuY2UocHJldmFsZW5jZXNfZmlsdGVyZWQsIHRyZWVzLCBpZF90eXBlKQojZGl2ZXJnZW5jZV93ZWlnaHRlZCA8LSBjb21wdXRlX2Nsb25lX2RpdmVyZ2VuY2UocHJldmFsZW5jZXNfZmlsdGVyZWQsIHZhZnNfZmlsdGVyZWQsIGNsb25lX3RyZWVzLCBicmFuY2hfbGVuZ3RocywgaWRfdHlwZSwgd2VpZ2h0ZWQ9VFJVRSkKI2NvbG5hbWVzKGRpdmVyZ2VuY2Vfd2VpZ2h0ZWQpIDwtIG1hcHZhbHVlcyhjb2xuYW1lcyhkaXZlcmdlbmNlX3dlaWdodGVkKSwgZnJvbSA9ICJjbG9uZV9kaXZlcmdlbmNlIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG8gPSAiY2xvbmVfZGl2ZXJnZW5jZV93ZWlnaHRlZCIpCmRpdmVyc2l0eSA8LSBSZWR1Y2UoZnVuY3Rpb24oeCx5KSBtZXJnZSh4LHksYnk9YyhpZF90eXBlLCAicGF0aWVudF9pZCIpLCBhbGw9VFJVRSksCiAgICAgICAgICAgICAgICAgICAgbGlzdChwcmV2YWxlbmNlX2luZGljZXMsIGNsb25hbF9tZWFzdXJlcykpCmBgYAoKIyMgSVRILVRJTCBjb3JyZWxhdGlvbnMKCiMjIyBPbGQgbWVhc3VyZXMgCgpXZSdsbCB1c2UgcHJvcG9ydGlvbl9zdWJjbG9uYWxpdHkgYXMgdGhlIHN1cnJvZ2F0ZS4gCgpgYGB7cn0KcHJvcG9ydGlvbl9zdWJjbG9uYWwgPC0gZnJlYWQocHJvcG9ydGlvbl9zdWJjbG9uYWxpdHlfZmlsZSkKCnJlcyA8LSBwbHlyOjpqb2luKGNsdXN0cywgcHJvcG9ydGlvbl9zdWJjbG9uYWwpCgppZiAobmNsdXN0cyA9PSAyKSB7CiAgY29ycmVzIDwtIHdpbGNveC50ZXN0KHByb3BvcnRpb25fc3ViY2xvbmFsIH4gY2x1c3RlciwgZGF0YT1yZXMpCn0gZWxzZSB7CiAgY29ycmVzIDwtIGtydXNrYWwudGVzdChwcm9wb3J0aW9uX3N1YmNsb25hbCB+IGNsdXN0ZXIsIGRhdGE9cmVzKQp9CgpwdmFsIDwtIGNvcnJlcyRwLnZhbHVlCmVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKFApPT1wLCBsaXN0KHA9Zm9ybWF0KHB2YWwsIGRpZ2l0cz0zKSkpCgpnZ3Bsb3QocmVzLCBhZXMoeD1jbHVzdGVyLCB5PXByb3BvcnRpb25fc3ViY2xvbmFsKSkgKyBnZW9tX2JveHBsb3QoYWVzKGZpbGw9Y2x1c3RlcikpICsgdGhlbWVfYncoKSArIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyBzY2FsZV9maWxsX1B1YmxpY2F0aW9uKCkgKyBhbm5vdGF0ZSgndGV4dCcsIHg9SW5mLCB5PUluZiwgcGFyc2U9VFJVRSwgaGp1c3Q9MSwgdmp1c3Q9MSwgbGFiZWw9YXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpKSkKYGBgCgpCeSBhIEtydXNrYWwtV2FsbGlzIHRlc3QuCgpJZiB3ZSBpbnN0ZWFkIGNob29zZSB0byBjb21wYXJlIGNsdXN0ZXIgMyAoaGlnaCBlcGl0aGVsaWFsIFRJTHMpIGFnYWluc3QgZXZlcnl0aGluZyBlbHNlLCB0aGVuOgoKYGBge3J9CndpbGNveC50ZXN0KHByb3BvcnRpb25fc3ViY2xvbmFsIH4gY2x1c3RlciA9PSAzLCBkYXRhPXJlcykKYGBgCgojIyMgTmV3IG1lYXN1cmVzIChpbiBwcm9ncmVzcykKCmBgYHtyfQpyZXMgPC0gbWVyZ2UoZGl2ZXJzaXR5LCBpaGNfdGFibGVfYW5ub3RhdGVkLCBieT1jKGlkX3R5cGUsICJwYXRpZW50X2lkIikpCgppdGhfbWVhc3VyZXMgPC0gYygic2hhbm5vbiIsICJlbnRyb3B5IiwgInNpbXBzb24iLCAiZGl2ZXJnZW5jZSIsICJwb3N0cHJvY2Vzc2VkX2RpdmVyZ2VuY2UiLCAicHJvcG9ydGlvbl9zdWJjbG9uYWwiLAogICAgICAgICAgICAgICAgICAiY29tYmluZWRfaXRoX25vcm1hbGl6ZWQiLCAiY29tYmluZWRfaXRoX3JhdyIpCnJlc19tZWx0ZWQgPC0gcmVzaGFwZTI6Om1lbHQocmVzLCBpZC52YXJzID0gYyhpZF90eXBlLCAicGF0aWVudF9pZCIsICJjbHVzdGVyIiksCiAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSBpdGhfbWVhc3VyZXMsIHZhcmlhYmxlLm5hbWUgPSAiaXRoX3R5cGUiLCB2YWx1ZS5uYW1lID0gIml0aCIpCnJlc19tZWx0ZWQkaXRoX3R5cGUgPC0gZmFjdG9yKHJlc19tZWx0ZWQkaXRoX3R5cGUpCmBgYAoKYGBge3J9CnN0YXRzIDwtIHNldE5hbWVzKGRkcGx5KHJlc19tZWx0ZWQsIC4oaXRoX3R5cGUpLCBmdW5jdGlvbih4KSB7CiAgaWYgKG5jbHVzdHMgPT0gMikgewogICAgcmVzIDwtIHdpbGNveC50ZXN0KGl0aCB+IGNsdXN0ZXIsIGRhdGE9eCkKICB9IGVsc2UgewogICAgcmVzIDwtIGtydXNrYWwudGVzdChpdGggfiBjbHVzdGVyLCBkYXRhPXgpCiAgfQogIHB2YWx1ZSA8LSByZXMkcC52YWx1ZQogIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKFApPT1wLCBsaXN0KHA9Zm9ybWF0KHB2YWx1ZSwgZGlnaXRzPTMpKSkKICByZXR1cm4oYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpKSkKfSksIGMoIml0aF90eXBlIiwgInAudmFsdWUiKSkKYGBgCgpgYGB7cn0KZ2dwbG90KHJlc19tZWx0ZWQsIGFlcyh4PWNsdXN0ZXIsIHk9aXRoKSkgKyBnZW9tX2JveHBsb3QoYWVzKGZpbGw9Y2x1c3RlcikpICsgdGhlbWVfYncoKSArIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyBzY2FsZV9maWxsX1B1YmxpY2F0aW9uKCkgKyBmYWNldF93cmFwKH4gaXRoX3R5cGUsIHNjYWxlcz0iZnJlZSIpICsgZ2VvbV90ZXh0KGRhdGE9c3RhdHMsIGFlcyh4PUluZiwgeT1JbmYsIGxhYmVsPXAudmFsdWUpLCBoanVzdD0xLjEsIHZqdXN0PTEuNSwgc2l6ZT0zLCBwYXJzZT1UUlVFKQpgYGAKCkNoZWNrIHdpdGggQW5kcmV3IGFzIHRvIGhvdyBoZSBjb21wdXRlZCBjbG9uZSBkaXZlcmdlbmNlIC0tIG15IGNvbXB1dGF0aW9ucyBiYXNlZCBvbiB3aGF0IEkgYmVsaWV2ZSB0aGUgZGVmaW5pdGlvbiBpcyBhcmUgZGlmZmVyZW50LiBQZXJoYXBzIGl0J3MgYSAxLW1pbnVzIGlzc3VlPyAKCgojIyBJVEgtVElMIHZhcmlhYmlsaXR5CgpgYGB7cn0KaWhjX3RhYmxlX3NsaWRlIDwtIGZyZWFkKGloY190YWJsZV9zbGlkZV9wYXRoKQoKaWhjX3NsaWRlX2RhdGEgPC0gc3Vic2V0KGloY190YWJsZV9zbGlkZSwgc2VsZWN0PWMoImNvbmRlbnNlZF9pZCIsICJwYXRpZW50X2lkIiwgInNsaWRlIiwgdGlsc19mb3JfdmFyaWFiaWxpdHkpKQppaGNfbWVsdGVkIDwtIG1lbHQoaWhjX3NsaWRlX2RhdGEsIGlkLnZhcnMgPSBjKCJjb25kZW5zZWRfaWQiLCAicGF0aWVudF9pZCIsICJzbGlkZSIpLAogICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gdGlsc19mb3JfdmFyaWFiaWxpdHksIHZhcmlhYmxlLm5hbWUgPSAidGlsdHlwZSIsCiAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gImRlbnNpdHkiKQppaGNfbWVsdGVkJHRpbHR5cGUgPC0gYXMuY2hhcmFjdGVyKGloY19tZWx0ZWQkdGlsdHlwZSkKCmludGVyc2VjdF9zYW1wbGVzIDwtIGludGVyc2VjdCh1bmlxdWUoaWhjX21lbHRlZCRjb25kZW5zZWRfaWQpLCB1bmlxdWUoY2Nmc19sYWJlbGVkJGNvbmRlbnNlZF9pZCkpCgp0aWxfdmFyIDwtIGNvbXB1dGVfaWhjX3ZhcihpaGNfbWVsdGVkLCBpaGNfdGFibGUsIHNhbXBsZXMgPSBpbnRlcnNlY3Rfc2FtcGxlcywgdGlsX3ZhcmlhbmNlX29wdGlvbiA9IHZhcmlhYmlsaXR5X3R5cGUsIHRpbHNfZm9yX3ZhcmlhYmlsaXR5KQoKY2xvbmVkaXN0cyA8LSBjbG9uZV9kaXN0YW5jZXMoY2Nmc19sYWJlbGVkLCBub3JtYWxpemUgPSBGQUxTRSwgaWRfdHlwZSA9IGlkX3R5cGUpCmNsb25lZGlzdHMkcGF0aWVudF9pZCA8LSBhcy5jaGFyYWN0ZXIoY2xvbmVkaXN0cyRwYXRpZW50X2lkKQoKdmFyaWFiaWxpdGllcyA8LSBpbm5lcl9qb2luKHRpbF92YXIsIHN1YnNldChjbG9uZWRpc3RzLCBzZWxlY3Q9LWMoZGlzdF9jbG9uZXNfd2VpZ2h0ZWQpKSwgYnk9YygicGF0aWVudF9pZCIpKQp2YXJpYWJpbGl0aWVzX21lbHRlZCA8LSBtZWx0KHZhcmlhYmlsaXRpZXMsIGlkLnZhcnMgPSBjKCJwYXRpZW50X2lkIiwgIm1lYW5fd2VpZ2h0ZWRfZGlzdCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUudmFycyA9IHRpbHNfZm9yX3ZhcmlhYmlsaXR5LCB2YXJpYWJsZS5uYW1lID0gInRpbHR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLm5hbWUgPSAidGlsdmFyIikKdmFyaWFiaWxpdGllc19tZWx0ZWQkcGF0aWVudF9pZCA8LSBmYWN0b3IodmFyaWFiaWxpdGllc19tZWx0ZWQkcGF0aWVudF9pZCkKYGBgCgpgYGB7cn0Kc3RhdHMgPC0gc2V0TmFtZXMoZGRwbHkodmFyaWFiaWxpdGllc19tZWx0ZWQsIC4odGlsdHlwZSksIGZ1bmN0aW9uKHgpIHsKICByZXMgPC0gd2l0aCh4LCBjb3IudGVzdChtZWFuX3dlaWdodGVkX2Rpc3QsIHRpbHZhciwgbWV0aG9kPSJzcGVhcm1hbiIpKQogIHB2YWx1ZSA8LSByZXMkcC52YWx1ZQogIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKFApPT1wLCBsaXN0KHA9Zm9ybWF0KHB2YWx1ZSwgZGlnaXRzPTMpKSkKICByZXR1cm4oYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpKSkKfSksIGMoInRpbHR5cGUiLCAicC52YWx1ZSIpKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9M30KcCA8LSBnZ3Bsb3QodmFyaWFiaWxpdGllc19tZWx0ZWQsIGFlcyh4PW1lYW5fd2VpZ2h0ZWRfZGlzdCwgeT10aWx2YXIpKSArIGdlb21fcG9pbnQoYWVzKGNvbG91cj1wYXRpZW50X2lkKSkgKyAKICB0aGVtZV9idygpICsgdGhlbWVfUHVibGljYXRpb24oKQpwIDwtIHAgKyBmYWNldF93cmFwKH4gdGlsdHlwZSwgc2NhbGVzID0gImZyZWUiLCBucm93PTEpCnAgPC0gcCArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9NiwgZmFtaWx5PSJIZWx2ZXRpY2EiKSwKICAgICAgICAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NixmYW1pbHk9IkhlbHZldGljYSIpLAogICAgICAgICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02LGZhbWlseT0iSGVsdmV0aWNhIiksCiAgICAgICAgICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCxmYW1pbHk9IkhlbHZldGljYSIpLAogICAgICAgICAgICAgICBzdHJpcC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcsZmFtaWx5PSJIZWx2ZXRpY2EiKSwKICAgICAgICAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ3aGl0ZSIpKQpwIDwtIHAgKyB5bGFiKCJWYXJpYWJpbGl0eSIpICsgeGxhYigiTWVhbiBjbG9uYWwgZGlzdGFuY2UiKQpwIDwtIHAgKyBnZW9tX3RleHQoZGF0YT1zdGF0cywgYWVzKHg9SW5mLCB5PUluZiwgbGFiZWw9cC52YWx1ZSksIGhqdXN0PTEuMSwgdmp1c3Q9MS41LCAKICAgICAgICAgICAgICAgICAgIHNpemU9MywgcGFyc2U9VFJVRSkKcCA8LSBwICsgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxfcGF0aWVudCkgKyAKICBndWlkZXMoY29sb3VyPWd1aWRlX2xlZ2VuZCh0aXRsZT0iUGF0aWVudCIpKQoKcGxvdChwKQpgYGAKCgoK