Setup

library(ithi.utils)
load_base_libs()

library(methods)
library(grid)
library(gridExtra)
library(gridBase)

library(ithi.meta)
library(ithi.figures)
library(ithi.utils)
library(ithi.seq)
library(ithi.clones)
library(ithi.supp)
library(ithi.xcr)
ihc_table_path <- snakemake@input$ihc_table
xcr_table_path <- snakemake@input$xcr_table
neoediting_outdir <- snakemake@input$neoediting_outdir
snv_cluster_files <- snakemake@input$snv_cluster_files
clone_tree_file <- snakemake@input$clone_tree_file
clone_branch_length_file <- snakemake@input$clone_branch_length_file
clone_prevalence_file <- snakemake@input$clone_prevalence_file
tcr_diversity_file <- snakemake@input$tcr_diversity
bcr_diversity_file <- snakemake@input$bcr_diversity
epitopes_unique_file <- snakemake@input$epitopes_unique_filtered

db_path <- snakemake@params$db
annotation_colours <- ithi.figures::get_annotation_colours()

ihc_table <- fread(ihc_table_path)
xcr_table <- read_clonotypes(xcr_table_path, duplicates = FALSE, db_path = db_path)

Read 36.1% of 304822 rows
Read 88.6% of 304822 rows
Read 304822 rows and 18 (of 18) columns from 0.070 GB file in 00:00:04
tree_branch_data <- read_clone_tree_data(clone_tree_file, clone_branch_length_file, 
    clone_prevalence_file, db_path)

neoediting_res <- supp_neoediting(neoediting_outdir, ihc_table, db_path, tree_branch_data, 
    wtfilter = TRUE, full_epitopes = FALSE, snv_cluster_files = snv_cluster_files)
epitopes_unique <- fread(epitopes_unique_file)

Analysis

clonotype_publicity <- xcr_table %>% dplyr::group_by_(.dots = c("id", "type")) %>% 
    dplyr::summarise(npatients = length(unique(patient_id)))

public_clonotypes <- subset(clonotype_publicity, npatients > 1)
xcr_table_public <- subset(xcr_table, id %in% public_clonotypes$id)
xcr_table_public$id_simple <- factor(xcr_table_public$id) %>% as.numeric

xcr_table_public_sorted <- xcr_table_public[order(xcr_table_public$id_simple), 
    ]
xcr_table_public_sorted_subset <- subset(xcr_table_public_sorted, select = c("voa", 
    "patient_id", "condensed_id", "count", "freq", "type", "id_simple"))
ggplot(xcr_table, aes(x = freq)) + geom_histogram() + scale_x_log10() + theme_bw() + 
    theme_Publication() + theme_nature() + facet_wrap(~type, scales = "free")

ggplot(xcr_table_public_sorted, aes(x = freq)) + geom_histogram() + scale_x_log10() + 
    theme_bw() + theme_Publication() + theme_nature() + facet_wrap(~type, scales = "free")

So some of these clonotypes are definitely expanded. We can do a quick and dirty test to see if this is significant:

n <- 10000
segment_types <- unique(xcr_table_public_sorted$type)

empirical_pvals <- sapply(segment_types, function(segment) {
    dat <- subset(xcr_table_public_sorted, type == segment)
    observed_median <- dat$freq %>% median
    
    draws <- nrow(dat)
    null_medians <- sapply(1:n, function(i) sample(subset(xcr_table, type == 
        segment)$freq, size = draws, replace = FALSE) %>% median)
    
    p_empirical <- length(which(null_medians >= observed_median))/n
    
    return(p_empirical)
})
names(empirical_pvals) <- segment_types

empirical_pvals
IGH TRB 
  0   1 

So public TCRs are not expanded, while public BCRs are. This is interesting – but there is a possibility that contamination occurred to a greater degree in the BCR assays compared to the TCR assays. Unfortunately, some low-level contamination is unavoidable with the plate-based layout – even after doing informatic filtering.

So I’m hesitant to over-interpret this finding.

Next we need to see if public TCR clones are more commonly present in patients with public BCR clones.

The patients with public TCR and BCR clones are:

subset(xcr_table_public_sorted_subset, type == "TRB")$patient_id %>% unique %>% 
    sort
 [1]  1  2  3  4  7  8  9 14 17 20 21 22 23
subset(xcr_table_public_sorted_subset, type == "IGH")$patient_id %>% unique %>% 
    sort
 [1]  1  2  3  4  7  8  9 11 12 13 14 15 17 18 19 20 21 22 23

Almost every patient contains a public BCR clone. So instead, we should check if pairs correspond to each other (i.e if there are more patient A-B pairs for both TCR and BCR).

patient_combinations <- xcr_table_public_sorted_subset %>% dplyr::group_by(type, 
    id_simple) %>% do(unique_patients = unique(sort(.$patient_id)))

trb_contamination_combinations <- subset(patient_combinations, type == "TRB")
igh_contamination_combinations <- subset(patient_combinations, type == "IGH")

shared_combinations <- intersect(trb_contamination_combinations$unique_patients, 
    igh_contamination_combinations$unique_patients)

So 3 out of 15 TCR and 19 BCR patient combinations are shared. What shared combinations refers to are cases where patients A and B both share both >= 1 common TCR and BCR clone.

While this is probably higher than what’s expected purely by chance – and perhaps you could argue that publicity in TCRs correlates with publicity in BCRs – do keep in mind that contamination would have the same type of signal (patients w/ samples that have been contaminated could be contaminated in both TCRs and BCRs. Furthermore, if contamination occurs at a high level in TCRs – which makes it hard to filter out – it is also more likely to occur at a high level in BCRs.) So the potential biological interest of this finding is obscured by the very real – and quite probable – possibility that this is all just due to rare instances of contamination that couldn’t be adequately filtered out.

# epitopes_annotated <- neoediting_res$nonsynonymous
epitopes_annotated <- epitopes_unique
neoantigen_table <- subset(epitopes_annotated, `NetMHCpan MT Percentile` <= 
    2)

neoantigen_table$mutant_epitope_id <- factor(neoantigen_table$`MT Epitope Seq`) %>% 
    as.numeric

mutant_epitope_publicity <- neoantigen_table %>% dplyr::group_by(mutant_epitope_id, 
    `MT Epitope Seq`) %>% dplyr::summarise(npatient = length(unique(patient_id)))

nrow(subset(mutant_epitope_publicity, npatient > 1))
[1] 0

So there are no public neoepitopes. Nevertheless, as the relationship between TCRs/BCRs and antigens is many-to-many, this is not surprising and does not rule out the possibility of tumour-reactive, public clonotypes.

That being said, there is an aspect of the plate-based layout that is vulnerable to cross-sample contamination. Unfortunately this is unavoidable; and despite bioinformatic filters employed to eliminate this (Supp Methods), there is the possibility that public clonotypes are the result of contamination. As this probability is non-zero, we should perhaps acknowledge this in the main text?

Summary

We have public TCR and BCR clonotypes in many patients. Only patients 10 and 16 lack public BCR clonotypes. They also lack public TCR clonotypes, but the significance of these 2 patients is likely just because TIL densities are very low in these 2 patients.

However, the most likely source of public clonotypes is due to contamination, as a result of the plate-based layout of library preparation. We’ve taken steps to eliminate what appear to be likely incidences of contamination (see Supplementary Methods), but we cannot claim to capture all instances. As such, I’m hesitant to over-interpret any such findings – even if we find that certain samples that share more public TCR clonotypes also share more public BCR clonotypes – this would also be consistent with a pattern due to contamination, where samples that are contaminated for TCRs are more likely to be contaminated for BCRs (and vice versa), as the library prep for both is done with the same layout of samples on the plate(s).

We can confidently say that no neoepitopes are shared between patients.

LS0tCnRpdGxlOiAiUHVibGljIGNsb25vdHlwZS9uZW9hbnRpZ2VuIGFuYWx5c2lzIgotLS0KICAgICAgICAgICAgICAgICAgICAgICAgYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIyMjIyMjIyBTbmFrZW1ha2UgaGVhZGVyICMjIyMjIyMjCmxpYnJhcnkobWV0aG9kcykKU25ha2VtYWtlIDwtIHNldENsYXNzKAogICAgIlNuYWtlbWFrZSIsCiAgICBzbG90cyA9IGMoCiAgICAgICAgaW5wdXQgPSAibGlzdCIsCiAgICAgICAgb3V0cHV0ID0gImxpc3QiLAogICAgICAgIHBhcmFtcyA9ICJsaXN0IiwKICAgICAgICB3aWxkY2FyZHMgPSAibGlzdCIsCiAgICAgICAgdGhyZWFkcyA9ICJudW1lcmljIiwKICAgICAgICBsb2cgPSAibGlzdCIsCiAgICAgICAgcmVzb3VyY2VzID0gImxpc3QiLAogICAgICAgIGNvbmZpZyA9ICJsaXN0IiwKICAgICAgICBydWxlID0gImNoYXJhY3RlciIKICAgICkKKQpzbmFrZW1ha2UgPC0gU25ha2VtYWtlKAogICAgaW5wdXQgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi94Y3JfdGFibGUudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL25lb2VkaXRpbmcvcnVuNicsICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvSUdIL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8xLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8yLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8zLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF80LnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF83LnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF85LnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8xMC50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3Nudl9jbHVzdGVyL3BhdGllbnRfMTEudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzEyLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8xMy50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3Nudl9jbHVzdGVyL3BhdGllbnRfMTQudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzE1LnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8xNi50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3Nudl9jbHVzdGVyL3BhdGllbnRfMTcudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9jbG9uZV9kYXRhLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGUudHN2JywgJ25vdGVib29rcy9wdWJsaWNfY2xvbm90eXBlcy5SbWQnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvZXBpdG9wZXNfdW5pcXVlX2ZpbHRlcmVkLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvVFJCL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvYnJhbmNoX2RhdGEudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy90cmVlX2RhdGEudHN2JywgInhjcl90YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIveGNyX3RhYmxlLnRzdicsICJuZW9lZGl0aW5nX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbmVvZWRpdGluZy9ydW42JywgImJjcl9kaXZlcnNpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9JR0gvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgInNudl9jbHVzdGVyX2ZpbGVzIiA9IGMoJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzEudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzIudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzMudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzQudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzcudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzkudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzEwLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8xMS50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3Nudl9jbHVzdGVyL3BhdGllbnRfMTIudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzEzLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8xNC50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3Nudl9jbHVzdGVyL3BhdGllbnRfMTUudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3Rlci9wYXRpZW50XzE2LnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXIvcGF0aWVudF8xNy50c3YnKSwgImNsb25lX3ByZXZhbGVuY2VfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL2Nsb25lX2RhdGEudHN2JywgImloY190YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvaWhjX3RhYmxlLnRzdicsICJub3RlYm9vayIgPSAnbm90ZWJvb2tzL3B1YmxpY19jbG9ub3R5cGVzLlJtZCcsICJlcGl0b3Blc191bmlxdWVfZmlsdGVyZWQiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2VwaXRvcGVzX3VuaXF1ZV9maWx0ZXJlZC50c3YnLCAidGNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL1RSQi9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAiY2xvbmVfYnJhbmNoX2xlbmd0aF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvYnJhbmNoX2RhdGEudHN2JywgImNsb25lX3RyZWVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3RyZWVfZGF0YS50c3YnKSwKICAgIG91dHB1dCA9IGxpc3QoJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3Jldmlldy9ub3RlYm9va3MvcnVuMi9wdWJsaWNfY2xvbm90eXBlcy5uYi5odG1sJyksCiAgICBwYXJhbXMgPSBsaXN0KCdwdWJsaWNfY2xvbm90eXBlX2FuYWx5c2lzJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJywgIm5hbWUiID0gJ3B1YmxpY19jbG9ub3R5cGVfYW5hbHlzaXMnLCAiZGIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJyksCiAgICB3aWxkY2FyZHMgPSBsaXN0KCksCiAgICB0aHJlYWRzID0gMSwKICAgIGxvZyA9IGxpc3QoJy9zaGFobGFiL2FsemhhbmcvY2x1c3R0bXAvcGFwZXJyZXZpZXcyL25vdGVib29rcy9wdWJsaWNfY2xvbm90eXBlX2FuYWx5c2lzLmxvZycpLAogICAgcmVzb3VyY2VzID0gbGlzdCgpLAogICAgY29uZmlnID0gbGlzdCgibmFub3N0cmluZ19kYXRhIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9uYW5vc3RyaW5nX3Jlc3VsdHMvaXRoX2Z1bGwvcWMvbGltbWFfcXVhbnRpbGUvbm9ybWFsaXplZF9leHByZXNzaW9uX3ZvYV9sYWJlbHNfZmlsdGVyZWQudHN2JywgInRpbHNfZm9yX3ZhcmlhYmlsaXR5IiA9IGMoJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JyksICJuZW9lZGl0aW5nX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbmVvZWRpdGluZy9ydW42JywgInNudl90YWJsZSIgPSAnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX3NudnMudHN2JywgInRvdGFsX3RpbHR5cGVzIiA9IGMoJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JyksICJpdGhfc3RhdF90eXBlcyIgPSBjKCdlbnRyb3B5JywgJ3Bvc3Rwcm9jZXNzZWRfZGl2ZXJnZW5jZScsICdjb21iaW5lZF9pdGhfbm9ybWFsaXplZCcsICdwcm9wb3J0aW9uX3N1YmNsb25hbCcpLCAiY2xvbGFfcmVzdWx0X2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2Nsb2xhL3J1bjQvY2xvbGFfY29uZGVuc2VkX3Jlc3VsdHMvYmV0YS9jbG9sYV9yZXN1bHRzLnRzdicsICJsb2dkaXIiID0gJy9zaGFobGFiL2FsemhhbmcvY2x1c3R0bXAvcGFwZXJyZXZpZXcyJywgInRpbGNsdXN0ZXJfc3VwZXJ2aXNlZF9pcHluYiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jldmlldy9pcHkvdGlsY2x1c3Rlcl9zdXBlcnZpc2VkbXVsdGljbGFzcy5pcHluYicsICJpY2djX3N1YnR5cGVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9pY2djX3ByaW1hcnlfdHVtb3VyX3N1YnR5cGVzLnRzdicsICJlcGl0b3Blc191bmlxdWVfZmlsdGVyZWQiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2VwaXRvcGVzX3VuaXF1ZV9maWx0ZXJlZC50c3YnLCAiYmVuY2htYXJrZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2JlbmNobWFya3MvcGFwZXJyZXZpZXcyJywgIml0aF9zdGF0cyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvaXRoX3N0YXRpc3RpY3MudHN2JywgImlncGFydGl0aW9uX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMjInLCAiaWNnY19zcGVjaW1lbiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0Mvc3BlY2ltZW4udHN2JywgInByZXZhbGVuY2VfdGhyZXNob2xkIiA9IDAuMDEsICJwYXRpZW50c19mb3JfY2xvbmFsIiA9IGMoMSwgMiwgMywgNCwgNywgOSwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNSwgMTYsIDE3KSwgImloY19mZWF0dXJlc19vdXRwdXQiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL2ludGVybWVkaWF0ZXMvcnVuMi9paGNfZmVhdHVyZXNfb3V0cHV0LnR4dCcsICJ0aWxfY2x1c3RlcnNfb3V0cHV0IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIvdGlsX2NsdXN0ZXJzX291dHB1dC50eHQnLCAicm9vbmV5X211dHNpZ2N2X2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9leHRlcm5hbC9vdGhlcl9wYXBlcnMvbW1jNi54bHN4JywgInhjcl90YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIveGNyX3RhYmxlLnRzdicsICJpbWFnZV9zdW1tYXJ5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvaXRoaS95dWFuX2hlY3JfaW1hZ2VfcmVzdWx0cy5jc3YnLCAic252X2NsdXN0ZXJfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvc252X2NsdXN0ZXInLCAidGlsc19mb3JfY2x1c3RlciIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAiaXRoX2ljZ2NfYmMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2l0aF9pY2djX21lcmdlZF9iYy50c3YnLCAiZGlzdGFuY2VfbWV0aG9kIiA9ICdob3JuJywgInJlbWl4dF9jZWxsdWxhcml0eV9wbG9pZHkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL3JlbWl4dF9jZWxsdWxhcml0eV9wbG9pZHkudHN2JywgInJlZnNlcV9nZW5lX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9nZW5vbWUvaGcxOS9yZWZzZXFfZ2VuZXMuYmVkJywgImNsb25lX3RyZWVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvdHJlZV9kYXRhLnRzdicsICJtb2xzdWJ0eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvbW9sc3VidHlwZXMudHN2JywgIm5hbm9zdHJpbmdfYW5ub3RhdGlvbnMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vbmFub3N0cmluZy9wYW5jYW5jZXJfYW5ub3RhdGlvbnMudHN2JywgImFsbF90aWx0eXBlcyIgPSBjKCdUX0NEOF9kZW5zaXR5JywgJ1RfQ0Q0X2RlbnNpdHknLCAnVF9DRDIwX2RlbnNpdHknLCAnVF9QbGFzbWFfZGVuc2l0eScsICdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAibW1jdG1fZmluYWxfcGF0aWVudF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnRfd2l0aC1vdicsICJ0YWJsZV9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3Jldmlldy90YWJsZXMvcnVuMicsICJpbWFnZV9zdW1tYXJ5MiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL2l0aGkveXVhbl9oZWNyX2ltYWdlX3Jlc3VsdHNfMi5jc3YnLCAidHVtb3VyX3B1cml0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvdHVtb3VyX3B1cml0eS50c3YnLCAiYmNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL0lHSC9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAiaWhjX3RhYmxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGUudHN2JywgImNsb25lX2JyYW5jaF9sZW5ndGhzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvYnJhbmNoX2RhdGEudHN2JywgImNsb25lX3ByZXZhbGVuY2VzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvY2xvbmVfZGF0YS50c3YnLCAiY29weW51bWJlcl90YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL2l0aGkvbWFzdGVyX2NvcHludW1iZXJfZmlsZS50c3YnLCAiaGVfcmVzdWx0c19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9pdGhpL2Zpbm5fcmVzdWx0cy9oZV9vdXRwdXRfTm92MjknLCAiZGIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJywgInNvbWF0aWNfY29kaW5nX3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL3NvbWF0aWNfY29kaW5nX3ZhcmlhbnRzJywgImFycmF5X2V4cHJlc3Npb25fZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9hcnJheS9nZW5lX2V4cHJzX3JtYV9iYXRjaF9jb3JyZWN0ZWQudHh0JywgIm5vdGVib29rX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvcmV2aWV3L25vdGVib29rcy9ydW4yJywgImtub3duX3N1YnR5cGVzX2FycmF5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL2FycmF5L3N1YnR5cGVzL2tub3duX3N1YnR5cGVzLnRzdicsICJ2YXJpYWJpbGl0eV90eXBlIiA9ICdzdGFiaWxpemUnLCAidGNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL1RSQi9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAiYnJlYWtwb2ludF90YWJsZSIgPSAnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX2JyZWFrcG9pbnRzLnRzdicsICJmaW5uaGVfcGlwZWxpbmVfcmVzdWx0c19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2Zpbm5oZS9ydW4xJyksCiAgICBydWxlID0gJ3B1YmxpY19jbG9ub3R5cGVfYW5hbHlzaXMnCikKIyMjIyMjIyMgT3JpZ2luYWwgc2NyaXB0ICMjIyMjIyMjIwoKICAgICAgICAgICAgICAgICAgICAgICAgYGBgCgoKIyMgU2V0dXAKCmBgYHtyIGdsb2JhbF9jaHVua19vcHRpb25zLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHRpZHk9VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRSkgI2NhY2hlPVRSVUUKYGBgCgpgYGB7cn0KbGlicmFyeShpdGhpLnV0aWxzKQpsb2FkX2Jhc2VfbGlicygpCgpsaWJyYXJ5KG1ldGhvZHMpCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ3JpZEJhc2UpCgpsaWJyYXJ5KGl0aGkubWV0YSkKbGlicmFyeShpdGhpLmZpZ3VyZXMpCmxpYnJhcnkoaXRoaS51dGlscykKbGlicmFyeShpdGhpLnNlcSkKbGlicmFyeShpdGhpLmNsb25lcykKbGlicmFyeShpdGhpLnN1cHApCmxpYnJhcnkoaXRoaS54Y3IpCmBgYAoKYGBge3J9CmloY190YWJsZV9wYXRoIDwtIHNuYWtlbWFrZUBpbnB1dCRpaGNfdGFibGUKeGNyX3RhYmxlX3BhdGggPC0gc25ha2VtYWtlQGlucHV0JHhjcl90YWJsZQpuZW9lZGl0aW5nX291dGRpciA8LSBzbmFrZW1ha2VAaW5wdXQkbmVvZWRpdGluZ19vdXRkaXIKc252X2NsdXN0ZXJfZmlsZXMgPC0gc25ha2VtYWtlQGlucHV0JHNudl9jbHVzdGVyX2ZpbGVzCmNsb25lX3RyZWVfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkY2xvbmVfdHJlZV9maWxlCmNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkY2xvbmVfYnJhbmNoX2xlbmd0aF9maWxlCmNsb25lX3ByZXZhbGVuY2VfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkY2xvbmVfcHJldmFsZW5jZV9maWxlCnRjcl9kaXZlcnNpdHlfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkdGNyX2RpdmVyc2l0eQpiY3JfZGl2ZXJzaXR5X2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGJjcl9kaXZlcnNpdHkKZXBpdG9wZXNfdW5pcXVlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGVwaXRvcGVzX3VuaXF1ZV9maWx0ZXJlZCAKCmRiX3BhdGggPC0gc25ha2VtYWtlQHBhcmFtcyRkYgpgYGAKCmBgYHtyfQphbm5vdGF0aW9uX2NvbG91cnMgPC0gaXRoaS5maWd1cmVzOjpnZXRfYW5ub3RhdGlvbl9jb2xvdXJzKCkKCmloY190YWJsZSA8LSBmcmVhZChpaGNfdGFibGVfcGF0aCkKeGNyX3RhYmxlIDwtIHJlYWRfY2xvbm90eXBlcyh4Y3JfdGFibGVfcGF0aCwgZHVwbGljYXRlcyA9IEZBTFNFLCBkYl9wYXRoID0gZGJfcGF0aCkKCnRyZWVfYnJhbmNoX2RhdGEgPC0gcmVhZF9jbG9uZV90cmVlX2RhdGEoY2xvbmVfdHJlZV9maWxlLCBjbG9uZV9icmFuY2hfbGVuZ3RoX2ZpbGUsIGNsb25lX3ByZXZhbGVuY2VfZmlsZSwgZGJfcGF0aCkKCm5lb2VkaXRpbmdfcmVzIDwtIHN1cHBfbmVvZWRpdGluZyhuZW9lZGl0aW5nX291dGRpciwgaWhjX3RhYmxlLCBkYl9wYXRoLCB0cmVlX2JyYW5jaF9kYXRhLCB3dGZpbHRlciA9IFRSVUUsIGZ1bGxfZXBpdG9wZXMgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbnZfY2x1c3Rlcl9maWxlcyA9IHNudl9jbHVzdGVyX2ZpbGVzKQplcGl0b3Blc191bmlxdWUgPC0gZnJlYWQoZXBpdG9wZXNfdW5pcXVlX2ZpbGUpCmBgYAoKIyMgQW5hbHlzaXMKCmBgYHtyfQpjbG9ub3R5cGVfcHVibGljaXR5IDwtIHhjcl90YWJsZSAlPiUgZHBseXI6Omdyb3VwX2J5XyguZG90cyA9IGMoImlkIiwgInR5cGUiKSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpc2UobnBhdGllbnRzPWxlbmd0aCh1bmlxdWUocGF0aWVudF9pZCkpKQoKcHVibGljX2Nsb25vdHlwZXMgPC0gc3Vic2V0KGNsb25vdHlwZV9wdWJsaWNpdHksIG5wYXRpZW50cyA+IDEpCnhjcl90YWJsZV9wdWJsaWMgPC0gc3Vic2V0KHhjcl90YWJsZSwgaWQgJWluJSBwdWJsaWNfY2xvbm90eXBlcyRpZCkKeGNyX3RhYmxlX3B1YmxpYyRpZF9zaW1wbGUgPC0gZmFjdG9yKHhjcl90YWJsZV9wdWJsaWMkaWQpICU+JSBhcy5udW1lcmljCgp4Y3JfdGFibGVfcHVibGljX3NvcnRlZCA8LSB4Y3JfdGFibGVfcHVibGljW29yZGVyKHhjcl90YWJsZV9wdWJsaWMkaWRfc2ltcGxlKSxdCnhjcl90YWJsZV9wdWJsaWNfc29ydGVkX3N1YnNldCA8LSBzdWJzZXQoeGNyX3RhYmxlX3B1YmxpY19zb3J0ZWQsIHNlbGVjdCA9IGMoInZvYSIsICJwYXRpZW50X2lkIiwgImNvbmRlbnNlZF9pZCIsICJjb3VudCIsICJmcmVxIiwgInR5cGUiLCAiaWRfc2ltcGxlIikpCmBgYAoKYGBge3J9CmdncGxvdCh4Y3JfdGFibGUsIGFlcyh4PWZyZXEpKSArIGdlb21faGlzdG9ncmFtKCkgKyBzY2FsZV94X2xvZzEwKCkgKyB0aGVtZV9idygpICsgdGhlbWVfUHVibGljYXRpb24oKSArIHRoZW1lX25hdHVyZSgpICsgZmFjZXRfd3JhcCh+IHR5cGUsIHNjYWxlcyA9ICJmcmVlIikKYGBgCgpgYGB7cn0KZ2dwbG90KHhjcl90YWJsZV9wdWJsaWNfc29ydGVkLCBhZXMoeD1mcmVxKSkgKyBnZW9tX2hpc3RvZ3JhbSgpICsgc2NhbGVfeF9sb2cxMCgpICsgdGhlbWVfYncoKSArIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyB0aGVtZV9uYXR1cmUoKSArIGZhY2V0X3dyYXAofiB0eXBlLCBzY2FsZXMgPSAiZnJlZSIpCmBgYAoKU28gc29tZSBvZiB0aGVzZSBjbG9ub3R5cGVzIGFyZSBkZWZpbml0ZWx5IGV4cGFuZGVkLiBXZSBjYW4gZG8gYSBxdWljayBhbmQgZGlydHkgdGVzdCB0byBzZWUgaWYgdGhpcyBpcyBzaWduaWZpY2FudDoKCmBgYHtyfQpuIDwtIDEwMDAwCnNlZ21lbnRfdHlwZXMgPC0gdW5pcXVlKHhjcl90YWJsZV9wdWJsaWNfc29ydGVkJHR5cGUpCgplbXBpcmljYWxfcHZhbHMgPC0gc2FwcGx5KHNlZ21lbnRfdHlwZXMsIGZ1bmN0aW9uKHNlZ21lbnQpIHsKICBkYXQgPC0gc3Vic2V0KHhjcl90YWJsZV9wdWJsaWNfc29ydGVkLCB0eXBlID09IHNlZ21lbnQpCiAgb2JzZXJ2ZWRfbWVkaWFuIDwtIGRhdCRmcmVxICU+JSBtZWRpYW4KICAKICBkcmF3cyA8LSBucm93KGRhdCkKICBudWxsX21lZGlhbnMgPC0gc2FwcGx5KDE6biwgZnVuY3Rpb24oaSkgc2FtcGxlKHN1YnNldCh4Y3JfdGFibGUsIHR5cGUgPT0gc2VnbWVudCkkZnJlcSwgc2l6ZSA9IGRyYXdzLCByZXBsYWNlID0gRkFMU0UpICU+JSBtZWRpYW4pCiAgCiAgcF9lbXBpcmljYWwgPC0gbGVuZ3RoKHdoaWNoKG51bGxfbWVkaWFucyA+PSBvYnNlcnZlZF9tZWRpYW4pKS9uCiAgCiAgcmV0dXJuKHBfZW1waXJpY2FsKQp9KQpuYW1lcyhlbXBpcmljYWxfcHZhbHMpIDwtIHNlZ21lbnRfdHlwZXMKCmVtcGlyaWNhbF9wdmFscwpgYGAKClNvIHB1YmxpYyBUQ1JzIGFyZSBub3QgZXhwYW5kZWQsIHdoaWxlIHB1YmxpYyBCQ1JzIGFyZS4gVGhpcyBpcyBpbnRlcmVzdGluZyAtLSBidXQgdGhlcmUgaXMgYSBwb3NzaWJpbGl0eSB0aGF0IGNvbnRhbWluYXRpb24gb2NjdXJyZWQgdG8gYSBncmVhdGVyIGRlZ3JlZSBpbiB0aGUgQkNSIGFzc2F5cyBjb21wYXJlZCB0byB0aGUgVENSIGFzc2F5cy4gVW5mb3J0dW5hdGVseSwgc29tZSBsb3ctbGV2ZWwgY29udGFtaW5hdGlvbiBpcyB1bmF2b2lkYWJsZSB3aXRoIHRoZSBwbGF0ZS1iYXNlZCBsYXlvdXQgLS0gZXZlbiBhZnRlciBkb2luZyBpbmZvcm1hdGljIGZpbHRlcmluZy4gCgpTbyBJJ20gaGVzaXRhbnQgdG8gb3Zlci1pbnRlcnByZXQgdGhpcyBmaW5kaW5nLiAKCgpOZXh0IHdlIG5lZWQgdG8gc2VlIGlmIHB1YmxpYyBUQ1IgY2xvbmVzIGFyZSBtb3JlIGNvbW1vbmx5IHByZXNlbnQgaW4gcGF0aWVudHMgd2l0aCBwdWJsaWMgQkNSIGNsb25lcy4gCgpUaGUgcGF0aWVudHMgd2l0aCBwdWJsaWMgVENSIGFuZCBCQ1IgY2xvbmVzIGFyZToKCmBgYHtyfQpzdWJzZXQoeGNyX3RhYmxlX3B1YmxpY19zb3J0ZWRfc3Vic2V0LCB0eXBlID09ICJUUkIiKSRwYXRpZW50X2lkICU+JSB1bmlxdWUgJT4lIHNvcnQKYGBgCgpgYGB7cn0Kc3Vic2V0KHhjcl90YWJsZV9wdWJsaWNfc29ydGVkX3N1YnNldCwgdHlwZSA9PSAiSUdIIikkcGF0aWVudF9pZCAlPiUgdW5pcXVlICU+JSBzb3J0CmBgYAoKQWxtb3N0IGV2ZXJ5IHBhdGllbnQgY29udGFpbnMgYSBwdWJsaWMgQkNSIGNsb25lLiBTbyBpbnN0ZWFkLCB3ZSBzaG91bGQgY2hlY2sgaWYgcGFpcnMgY29ycmVzcG9uZCB0byBlYWNoIG90aGVyIChpLmUgaWYgdGhlcmUgYXJlIG1vcmUgcGF0aWVudCBBLUIgcGFpcnMgZm9yIGJvdGggVENSIGFuZCBCQ1IpLgoKYGBge3J9CnBhdGllbnRfY29tYmluYXRpb25zIDwtIHhjcl90YWJsZV9wdWJsaWNfc29ydGVkX3N1YnNldCAlPiUgZHBseXI6Omdyb3VwX2J5KHR5cGUsIGlkX3NpbXBsZSkgJT4lIGRvKHVuaXF1ZV9wYXRpZW50cz11bmlxdWUoc29ydCguJHBhdGllbnRfaWQpKSkKCnRyYl9jb250YW1pbmF0aW9uX2NvbWJpbmF0aW9ucyA8LSBzdWJzZXQocGF0aWVudF9jb21iaW5hdGlvbnMsIHR5cGUgPT0gJ1RSQicpCmlnaF9jb250YW1pbmF0aW9uX2NvbWJpbmF0aW9ucyA8LSBzdWJzZXQocGF0aWVudF9jb21iaW5hdGlvbnMsIHR5cGUgPT0gIklHSCIpCgpzaGFyZWRfY29tYmluYXRpb25zIDwtIGludGVyc2VjdCh0cmJfY29udGFtaW5hdGlvbl9jb21iaW5hdGlvbnMkdW5pcXVlX3BhdGllbnRzLCBpZ2hfY29udGFtaW5hdGlvbl9jb21iaW5hdGlvbnMkdW5pcXVlX3BhdGllbnRzKQpgYGAKClNvIGByIGxlbmd0aChzaGFyZWRfY29tYmluYXRpb25zKWAgb3V0IG9mIGByIHRyYl9jb250YW1pbmF0aW9uX2NvbWJpbmF0aW9ucyR1bmlxdWVfcGF0aWVudHMgJT4lIHVuaXF1ZSAlPiUgbGVuZ3RoYCBUQ1IgYW5kIGByIGlnaF9jb250YW1pbmF0aW9uX2NvbWJpbmF0aW9ucyR1bmlxdWVfcGF0aWVudHMgJT4lIHVuaXF1ZSAlPiUgbGVuZ3RoYCBCQ1IgcGF0aWVudCBjb21iaW5hdGlvbnMgYXJlIHNoYXJlZC4gV2hhdCBzaGFyZWQgY29tYmluYXRpb25zIHJlZmVycyB0byBhcmUgY2FzZXMgd2hlcmUgcGF0aWVudHMgQSBhbmQgQiBib3RoIHNoYXJlIGJvdGggPj0gMSBjb21tb24gVENSICphbmQqIEJDUiBjbG9uZS4gCgpXaGlsZSB0aGlzIGlzIHByb2JhYmx5IGhpZ2hlciB0aGFuIHdoYXQncyBleHBlY3RlZCBwdXJlbHkgYnkgY2hhbmNlIC0tIGFuZCBwZXJoYXBzIHlvdSBjb3VsZCBhcmd1ZSB0aGF0IHB1YmxpY2l0eSBpbiBUQ1JzIGNvcnJlbGF0ZXMgd2l0aCBwdWJsaWNpdHkgaW4gQkNScyAtLSBkbyBrZWVwIGluIG1pbmQgdGhhdCBjb250YW1pbmF0aW9uIHdvdWxkIGhhdmUgdGhlIHNhbWUgdHlwZSBvZiBzaWduYWwgKHBhdGllbnRzIHcvIHNhbXBsZXMgdGhhdCBoYXZlIGJlZW4gY29udGFtaW5hdGVkIGNvdWxkIGJlIGNvbnRhbWluYXRlZCBpbiBib3RoIFRDUnMgYW5kIEJDUnMuIEZ1cnRoZXJtb3JlLCBpZiBjb250YW1pbmF0aW9uIG9jY3VycyBhdCBhIGhpZ2ggbGV2ZWwgaW4gVENScyAtLSB3aGljaCBtYWtlcyBpdCBoYXJkIHRvIGZpbHRlciBvdXQgLS0gaXQgaXMgYWxzbyBtb3JlIGxpa2VseSB0byBvY2N1ciBhdCBhIGhpZ2ggbGV2ZWwgaW4gQkNScy4pIFNvIHRoZSBwb3RlbnRpYWwgYmlvbG9naWNhbCBpbnRlcmVzdCBvZiB0aGlzIGZpbmRpbmcgaXMgb2JzY3VyZWQgYnkgdGhlIHZlcnkgcmVhbCAtLSBhbmQgcXVpdGUgcHJvYmFibGUgLS0gcG9zc2liaWxpdHkgdGhhdCB0aGlzIGlzIGFsbCBqdXN0IGR1ZSB0byByYXJlIGluc3RhbmNlcyBvZiBjb250YW1pbmF0aW9uIHRoYXQgY291bGRuJ3QgYmUgYWRlcXVhdGVseSBmaWx0ZXJlZCBvdXQuICAKCmBgYHtyfQojZXBpdG9wZXNfYW5ub3RhdGVkIDwtIG5lb2VkaXRpbmdfcmVzJG5vbnN5bm9ueW1vdXMKZXBpdG9wZXNfYW5ub3RhdGVkIDwtIGVwaXRvcGVzX3VuaXF1ZQpuZW9hbnRpZ2VuX3RhYmxlIDwtIHN1YnNldChlcGl0b3Blc19hbm5vdGF0ZWQsIGBOZXRNSENwYW4gTVQgUGVyY2VudGlsZWAgPD0gMikKCm5lb2FudGlnZW5fdGFibGUkbXV0YW50X2VwaXRvcGVfaWQgPC0gZmFjdG9yKG5lb2FudGlnZW5fdGFibGUkYE1UIEVwaXRvcGUgU2VxYCkgJT4lIGFzLm51bWVyaWMKCm11dGFudF9lcGl0b3BlX3B1YmxpY2l0eSA8LSBuZW9hbnRpZ2VuX3RhYmxlICU+JSBkcGx5cjo6Z3JvdXBfYnkobXV0YW50X2VwaXRvcGVfaWQsIGBNVCBFcGl0b3BlIFNlcWApICU+JSBkcGx5cjo6c3VtbWFyaXNlKG5wYXRpZW50PWxlbmd0aCh1bmlxdWUocGF0aWVudF9pZCkpKQoKbnJvdyhzdWJzZXQobXV0YW50X2VwaXRvcGVfcHVibGljaXR5LCBucGF0aWVudCA+IDEpKQpgYGAKClNvIHRoZXJlIGFyZSBubyBwdWJsaWMgbmVvZXBpdG9wZXMuIE5ldmVydGhlbGVzcywgYXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIFRDUnMvQkNScyBhbmQgYW50aWdlbnMgaXMgbWFueS10by1tYW55LCB0aGlzIGlzIG5vdCBzdXJwcmlzaW5nIGFuZCBkb2VzIG5vdCBydWxlIG91dCB0aGUgcG9zc2liaWxpdHkgb2YgdHVtb3VyLXJlYWN0aXZlLCBwdWJsaWMgY2xvbm90eXBlcy4gCgpUaGF0IGJlaW5nIHNhaWQsIHRoZXJlIGlzIGFuIGFzcGVjdCBvZiB0aGUgcGxhdGUtYmFzZWQgbGF5b3V0IHRoYXQgaXMgdnVsbmVyYWJsZSB0byBjcm9zcy1zYW1wbGUgY29udGFtaW5hdGlvbi4gVW5mb3J0dW5hdGVseSB0aGlzIGlzIHVuYXZvaWRhYmxlOyBhbmQgZGVzcGl0ZSBiaW9pbmZvcm1hdGljIGZpbHRlcnMgZW1wbG95ZWQgdG8gZWxpbWluYXRlIHRoaXMgKFN1cHAgTWV0aG9kcyksIHRoZXJlIGlzIHRoZSBwb3NzaWJpbGl0eSB0aGF0IHB1YmxpYyBjbG9ub3R5cGVzIGFyZSB0aGUgcmVzdWx0IG9mIGNvbnRhbWluYXRpb24uIEFzIHRoaXMgcHJvYmFiaWxpdHkgaXMgbm9uLXplcm8sIHdlIHNob3VsZCBwZXJoYXBzIGFja25vd2xlZGdlIHRoaXMgaW4gdGhlIG1haW4gdGV4dD8gCgojIyBTdW1tYXJ5CgpXZSBoYXZlIHB1YmxpYyBUQ1IgYW5kIEJDUiBjbG9ub3R5cGVzIGluIG1hbnkgcGF0aWVudHMuIE9ubHkgcGF0aWVudHMgMTAgYW5kIDE2IGxhY2sgcHVibGljIEJDUiBjbG9ub3R5cGVzLiBUaGV5IGFsc28gbGFjayBwdWJsaWMgVENSIGNsb25vdHlwZXMsIGJ1dCB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZXNlIDIgcGF0aWVudHMgaXMgbGlrZWx5IGp1c3QgYmVjYXVzZSBUSUwgZGVuc2l0aWVzIGFyZSB2ZXJ5IGxvdyBpbiB0aGVzZSAyIHBhdGllbnRzLiAKCkhvd2V2ZXIsIHRoZSBtb3N0IGxpa2VseSBzb3VyY2Ugb2YgcHVibGljIGNsb25vdHlwZXMgaXMgZHVlIHRvIGNvbnRhbWluYXRpb24sIGFzIGEgcmVzdWx0IG9mIHRoZSBwbGF0ZS1iYXNlZCBsYXlvdXQgb2YgbGlicmFyeSBwcmVwYXJhdGlvbi4gV2UndmUgdGFrZW4gc3RlcHMgdG8gZWxpbWluYXRlIHdoYXQgYXBwZWFyIHRvIGJlIGxpa2VseSBpbmNpZGVuY2VzIG9mIGNvbnRhbWluYXRpb24gKHNlZSBTdXBwbGVtZW50YXJ5IE1ldGhvZHMpLCBidXQgd2UgY2Fubm90IGNsYWltIHRvIGNhcHR1cmUgYWxsIGluc3RhbmNlcy4gQXMgc3VjaCwgSSdtIGhlc2l0YW50IHRvIG92ZXItaW50ZXJwcmV0IGFueSBzdWNoIGZpbmRpbmdzIC0tIGV2ZW4gaWYgd2UgZmluZCB0aGF0IGNlcnRhaW4gc2FtcGxlcyB0aGF0IHNoYXJlIG1vcmUgcHVibGljIFRDUiBjbG9ub3R5cGVzIGFsc28gc2hhcmUgbW9yZSBwdWJsaWMgQkNSIGNsb25vdHlwZXMgLS0gdGhpcyB3b3VsZCBhbHNvIGJlIGNvbnNpc3RlbnQgd2l0aCBhIHBhdHRlcm4gZHVlIHRvIGNvbnRhbWluYXRpb24sIHdoZXJlIHNhbXBsZXMgdGhhdCBhcmUgY29udGFtaW5hdGVkIGZvciBUQ1JzIGFyZSBtb3JlIGxpa2VseSB0byBiZSBjb250YW1pbmF0ZWQgZm9yIEJDUnMgKGFuZCB2aWNlIHZlcnNhKSwgYXMgdGhlIGxpYnJhcnkgcHJlcCBmb3IgYm90aCBpcyBkb25lIHdpdGggdGhlIHNhbWUgbGF5b3V0IG9mIHNhbXBsZXMgb24gdGhlIHBsYXRlKHMpLiAKCldlIGNhbiBjb25maWRlbnRseSBzYXkgdGhhdCBubyBuZW9lcGl0b3BlcyBhcmUgc2hhcmVkIGJldHdlZW4gcGF0aWVudHMuIAo=