Setup

library(ithi.utils)
load_base_libs()

library(methods)
library(bedr)
library(biomaRt)
library(BSgenome.Hsapiens.UCSC.hg19)

library(ithi.meta)
library(ithi.figures)
library(ithi.utils)
library(ithi.expr)
library(ithi.seq)
library(ithi.bed)
library(ithi.supp)
nanostring_data_path <- snakemake@input$nanostring_data
nanostring_annotations_path <- snakemake@input$nanostring_annotations
ihc_table_path <- snakemake@input$ihc_table
master_variant_file <- snakemake@input$snv_table
master_breakpoint_file <- snakemake@input$breakpoint_table
somatic_coding_result_dir <- snakemake@input$somatic_coding_result_dir
molecular_subtype_file <- snakemake@input$molsubtypes

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

mart <- useDataset("hsapiens_gene_ensembl", useMart(biomart = "ENSEMBL_MART_ENSEMBL", 
    host = "feb2014.archive.ensembl.org"))

ihc_table <- fread(ihc_table_path)
master_variant_table <- read_variant_file(master_variant_file, db_path)

Read 5.9% of 682516 rows
Read 682516 rows and 9 (of 9) columns from 0.026 GB file in 00:00:04
master_breakpoint_table <- read_variant_file(master_breakpoint_file, db_path)

titan_file <- file.path(somatic_coding_result_dir, "somatic_cnv_titan.tsv")
somatic_snv_file <- file.path(somatic_coding_result_dir, "somatic_snvs.tsv")
somatic_indel_file <- file.path(somatic_coding_result_dir, "somatic_indels.tsv")
titan_cnv <- fread(titan_file)
somatic_snvs <- fread(somatic_snv_file)
somatic_indels <- fread(somatic_indel_file)

exprs <- fread(nanostring_data_path)
nanostring_labels <- fread(nanostring_annotations_path)
molsubtypes <- fread(molecular_subtype_file)

til_clusters <- ithi.figures:::get_til_clusters(ihc_table, molsubtypes, tils_for_cluster = tils_for_cluster, 
    nclusts = 3)

Pathways immunoediting analysis

The purpose of this analysis is to show whether or not immune checkpoint or other immunosuppressive factors may be present and associated with TIL densities/our N/S/ES-TIL clusters. If so, this reviewer thinks they may interfere with any immunoediting that we claim may be taking place.

In actuality, I think this reviewer’s argument is flawed – we’re measuring the current state of the tumour, not the past. Even if checkpoint molecules are present – and interfering with immunoediting now – this may not have been the case in the tumour’s history.

Expression-level

# antigen-processing machinery APM_genes <- c('CANX', 'HSPA5', 'B2M',
# 'HLA-A', 'HLA-B', 'HLA-C', 'TAP1', 'TAP2', 'TAPBP', 'CALR', 'PDIA3')
APM_genes <- c("HLA-A", "HLA-B", "HLA-C", "TAP1", "TAP2", "TAPBP", "PSMB9")  #, 'PSMB7')
checkpoint_genes <- subset(nanostring_labels, str_detect(gene_class, "Checkpoint"))$Gene
immune_suppression <- c("IDO1")  #, 'IDO2', 'ALOX') # p53 excluded because p53 loss is ubiquituous in HGSC; others are absent
ifng_genes <- c("IFNG")

mutation_genes <- c(APM_genes, ifng_genes)
plot_cluster_expression <- function(expr, genes, ihc_table) {
    expr_subset <- subset(expr, Name %in% genes) %>% as.data.frame %>% column_to_rownames(var = "Name")
    
    sample_filter <- intersect(ihc_table$voa, colnames(expr_subset))
    expr_subset <- expr_subset[, sample_filter]
    
    expr_df <- melt(as.matrix(expr_subset)) %>% plyr::rename(c(Var1 = "Name", 
        Var2 = "voa"))
    expr_ihc <- plyr::join(expr_df, ihc_table)
    expr_ihc$patient_id <- factor(as.character(expr_ihc$patient_id))
    
    
    pvals <- setNames(ddply(expr_ihc, .(Name), function(x) {
        df <- as.data.frame(x)
        corres <- with(df, cor.test(value, E_CD8_density, method = "spearman"))
        
        pval <- corres$p.value
        return(pval)
    }), c("Name", "p.value"))
    pvals$p.adj <- p.adjust(pvals$p.value, method = "fdr")
    
    pvals$p.adj.text <- sapply(pvals$p.adj, function(x) as.character(as.expression(substitute(italic(P) == 
        p, list(p = format(x, digits = 3))))))
    
    p <- ggplot(expr_ihc, aes(x = E_CD8_density, y = value)) + geom_point(aes(colour = patient_id)) + 
        facet_wrap(~Name, scales = "free") + scale_x_continuous(trans = "log10") + 
        theme_bw() + ithi.utils::theme_Publication() + ithi.utils::theme_nature() + 
        scale_colour_manual(values = annotation_colours$patient_id) + geom_text(data = pvals, 
        aes(x = Inf, y = Inf, label = p.adj.text), hjust = 1.1, vjust = 1.5, 
        size = 2.5, parse = TRUE)
    
    return(p)
}
plot_cluster_expression(exprs, APM_genes, ihc_table)

plot_cluster_expression(exprs, checkpoint_genes, ihc_table)

plot_cluster_expression(exprs, ifng_genes, ihc_table)

plot_cluster_expression(exprs, immune_suppression, ihc_table)

So the expression of these genes is positively correlated with epithelial CD8+ TIL density.

What does this mean?

  • APM genes: Antigen processing machinery is not underexpressed in samples with high epithelial CD8+ TIL, and therefore does not likely prevent immunoediting.
  • IFNG and checkpoint genes: Interferon-gamma is known to stimulate PD1 (Benci et al. 2016). Higher levels of checkpoint inhibitors, e.g. PD-1, would theoretically interfere with immunoediting. However, contrary to many other settings, in HGSC PD1+CD8+ TIL (which typically coexpress CD103+ according to Webb et al. 2014 and Komdeur et al. 2016) are associated with superior outcomes and retain functional competence, i.e. produce robust amounts of TNF-alpha and IFN-gamma (Webb et al. 2014, Webb et al. 2015).
  • Immune suppression genes: From Rooney – we found that CYT was best correlated with immunosuppressive factors (Spranger et al., 2013), such as PDCD1LG2 (PDL2), IDO1/2, DOK3 (Lemay et al., 2000), GMCSF receptor (CSF2RA, CSF2RB) and the C1Q complex (Figure 1B).

Mutation-level

Here, our goal is just to look for the presence of mutations in those immune-associated genes. For example, if there are mutations in antigen presenting machinery genes, these may interfere with antigen recognition and therefore immunoediting.

titan_bed <- convert_to_bed(titan_cnv)
refseq_bed <- read_bed(refseq_gene_file)

gene_names <- getBM(attributes = c("refseq_mrna", "hgnc_symbol"), values = refseq_bed$refseq_id, 
    mart = mart)

refseq_bed_annotated <- merge(refseq_bed, gene_names %>% subset(refseq_mrna != 
    "") %>% plyr::rename(c(refseq_mrna = "refseq_id")), by = c("refseq_id"))

refseq_bed_annotated <- subset(refseq_bed_annotated, select = c("chr", "start", 
    "end", "hgnc_symbol", "refseq_id"))
refseq_bed_annotated <- bedr.sort.region(refseq_bed_annotated)

titan_merged <- bedr(engine = "bedtools", input = list(a = titan_bed, b = refseq_bed_annotated), 
    method = "intersect", params = "-loj")
titan_merged <- data.frame(titan_merged)
titan_merged$median_logR <- as.numeric(titan_merged$median_logR)
titan_merged$total <- as.numeric(titan_merged$total)
titan_merged$major <- as.numeric(titan_merged$major)
titan_merged$minor <- as.numeric(titan_merged$minor)

titan_merged_filtered <- subset(titan_merged, (median_logR < -1) | (median_logR > 
    1))
somatic_snvs_filtered <- plyr::join(somatic_snvs, master_variant_table %>% subset(is_present == 
    1), type = "inner")
somatic_indels_filtered <- subset(somatic_indels, mappability == 1)
titan_merged_filtered_immune <- subset(titan_merged_filtered, hgnc_symbol %in% 
    mutation_genes)
somatic_snvs_immune <- subset(somatic_snvs_filtered, gene_name %in% mutation_genes)
somatic_indels_immune <- subset(somatic_indels_filtered, gene_name %in% mutation_genes)

print(somatic_snvs_immune)
Empty data.table (0 rows) of 23 cols: chrom,coord,ref,alt,ref_counts,alt_counts...
NULL
print(somatic_indels_immune)
   chrom    coord ref       alt strelka_score gene_name      effect
1:     6 32797776   C CCTTATCAT            34      TAP2 FRAME_SHIFT
   effect_impact mappability patient_id condensed_id
1:          HIGH           1          3        3_Om1
## Because we have LOHHLA and that's more accurate in polymorphic regions
titan_merged_filtered_immune_nohla <- subset(titan_merged_filtered_immune, !hgnc_symbol %in% 
    c("HLA-A", "HLA-B", "HLA-C"))

print(titan_merged_filtered_immune_nohla)
          chr    start      end patient_id clone prevalence major_1
611155  chr12 68187399 73184855          9     1       0.93       4
2020099  chr6 32692061 32939785         11     1          1       3
2020103  chr6 32692061 32939785         11     1          1       3
2020104  chr6 32692061 32939785         11     1          1       3
2020105  chr6 32692061 32939785         11     1          1       3
2021547  chr6 32721019 35100159         17     1          1       2
2021586  chr6 32721019 35100159         17     1          1       2
2021587  chr6 32721019 35100159         17     1          1       2
2021588  chr6 32721019 35100159         17     1          1       2
2021604  chr6 32721019 35100159         17     1          1       2
2021605  chr6 32721019 35100159         17     1          1       2
2021606  chr6 32721019 35100159         17     1          1       2
        total_1 median_logR minor_1 major minor total tumour_content
611155        5        1.18       1     4     1     5         2.5334
2020099       4        1.03       1     3     1     4         0.9996
2020103       4        1.03       1     3     1     4         0.9996
2020104       4        1.03       1     3     1     4         0.9996
2020105       4        1.03       1     3     1     4         0.9996
2021547       4        1.03       2     2     2     4         0.9992
2021586       4        1.03       2     2     2     4         0.9992
2021587       4        1.03       2     2     2     4         0.9992
2021588       4        1.03       2     2     2     4         0.9992
2021604       4        1.03       2     2     2     4         0.9992
2021605       4        1.03       2     2     2     4         0.9992
2021606       4        1.03       2     2     2     4         0.9992
        condensed_id chr.b  start.b    end.b hgnc_symbol refseq_id
611155        9_LOv1 chr12 68548549 68553521        IFNG NM_000619
2020099      11_Rct2  chr6 32821937 32827628       PSMB9 NM_002800
2020103      11_Rct2  chr6 32789609 32806547        TAP2 NM_018833
2020104      11_Rct2  chr6 32793186 32806547        TAP2 NM_000544
2020105      11_Rct2  chr6 32812985 32821748        TAP1 NM_000593
2021547       17_Om3  chr6 32821937 32827628       PSMB9 NM_002800
2021586       17_Om3  chr6 32789609 32806547        TAP2 NM_018833
2021587       17_Om3  chr6 32793186 32806547        TAP2 NM_000544
2021588       17_Om3  chr6 32812985 32821748        TAP1 NM_000593
2021604       17_Om3  chr6 33267471 33282164       TAPBP NM_003190
2021605       17_Om3  chr6 33267471 33282164       TAPBP NM_172209
2021606       17_Om3  chr6 33271409 33282164       TAPBP NM_172208

The reason there are no SNVs left is because of the mappability threshold.

There’s one indel – in TAP, for sample 3_Om1. This sample is TIL subtype S-TIL.

There are CN high-level amplifications in IFNG/PSMB9/TAP1/TAP2/TAPBP. No deletions that might be interfering with antigen processing machinery.

LS0tCnRpdGxlOiAiUGF0aHdheXMgaW1tdW5vZWRpdGluZyBhbmFseXNpcyIKLS0tCiAgICAgICAgICAgICAgICAgICAgICAgIGBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjIyMjIyMgU25ha2VtYWtlIGhlYWRlciAjIyMjIyMjIwpsaWJyYXJ5KG1ldGhvZHMpClNuYWtlbWFrZSA8LSBzZXRDbGFzcygKICAgICJTbmFrZW1ha2UiLAogICAgc2xvdHMgPSBjKAogICAgICAgIGlucHV0ID0gImxpc3QiLAogICAgICAgIG91dHB1dCA9ICJsaXN0IiwKICAgICAgICBwYXJhbXMgPSAibGlzdCIsCiAgICAgICAgd2lsZGNhcmRzID0gImxpc3QiLAogICAgICAgIHRocmVhZHMgPSAibnVtZXJpYyIsCiAgICAgICAgbG9nID0gImxpc3QiLAogICAgICAgIHJlc291cmNlcyA9ICJsaXN0IiwKICAgICAgICBjb25maWcgPSAibGlzdCIsCiAgICAgICAgcnVsZSA9ICJjaGFyYWN0ZXIiCiAgICApCikKc25ha2VtYWtlIDwtIFNuYWtlbWFrZSgKICAgIGlucHV0ID0gbGlzdCgnbm90ZWJvb2tzL3BhdGh3YXlzX2ltbXVub2VkaXRpbmcuUm1kJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2loY190YWJsZS50c3YnLCAnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX3NudnMudHN2JywgJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9icmVha3BvaW50cy50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbmFub3N0cmluZ19yZXN1bHRzL2l0aF9mdWxsL3FjL2xpbW1hX3F1YW50aWxlL25vcm1hbGl6ZWRfZXhwcmVzc2lvbl92b2FfbGFiZWxzX2ZpbHRlcmVkLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9zb21hdGljX2NvZGluZ192YXJpYW50cycsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9tb2xzdWJ0eXBlcy50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9uYW5vc3RyaW5nL3BhbmNhbmNlcl9hbm5vdGF0aW9ucy50c3YnLCAibW9sc3VidHlwZXMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL21vbHN1YnR5cGVzLnRzdicsICJub3RlYm9vayIgPSAnbm90ZWJvb2tzL3BhdGh3YXlzX2ltbXVub2VkaXRpbmcuUm1kJywgImloY190YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvaWhjX3RhYmxlLnRzdicsICJzbnZfdGFibGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9zbnZzLnRzdicsICJicmVha3BvaW50X3RhYmxlIiA9ICcvc2hhaGxhYi9hbWNwaGVyc29uL3Byb2plY3RzL2l0aDMvaXRoMy9ub3RlYm9va3MvYmVzcG9rZS9pdGhfYnJlYWtwb2ludHMudHN2JywgIm5hbm9zdHJpbmdfZGF0YSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbmFub3N0cmluZ19yZXN1bHRzL2l0aF9mdWxsL3FjL2xpbW1hX3F1YW50aWxlL25vcm1hbGl6ZWRfZXhwcmVzc2lvbl92b2FfbGFiZWxzX2ZpbHRlcmVkLnRzdicsICJzb21hdGljX2NvZGluZ19yZXN1bHRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9zb21hdGljX2NvZGluZ192YXJpYW50cycsICJuYW5vc3RyaW5nX2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL25hbm9zdHJpbmcvcGFuY2FuY2VyX2Fubm90YXRpb25zLnRzdicpLAogICAgb3V0cHV0ID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvcmV2aWV3L25vdGVib29rcy9ydW4yL3BhdGh3YXlzX2ltbXVub2VkaXRpbmcubmIuaHRtbCcpLAogICAgcGFyYW1zID0gbGlzdChjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL2dlbm9tZS9oZzE5L3JlZnNlcV9nZW5lcy5iZWQnLCAncGF0aHdheXNfaW1tdW5vZWRpdGluZ19hbmFseXNpcycsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJ0aWxzX2Zvcl9jbHVzdGVyIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJyZWZzZXFfZ2VuZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvZ2Vub21lL2hnMTkvcmVmc2VxX2dlbmVzLmJlZCcsICJuYW1lIiA9ICdwYXRod2F5c19pbW11bm9lZGl0aW5nX2FuYWx5c2lzJywgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycpLAogICAgd2lsZGNhcmRzID0gbGlzdCgpLAogICAgdGhyZWFkcyA9IDEsCiAgICBsb2cgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL2NsdXN0dG1wL3BhcGVycmV2aWV3Mi9ub3RlYm9va3MvcGF0aHdheXNfaW1tdW5vZWRpdGluZ19hbmFseXNpcy5sb2cnKSwKICAgIHJlc291cmNlcyA9IGxpc3QoKSwKICAgIGNvbmZpZyA9IGxpc3QoIml0aF9zdGF0cyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvaXRoX3N0YXRpc3RpY3MudHN2JywgInJlZnNlcV9nZW5lX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9nZW5vbWUvaGcxOS9yZWZzZXFfZ2VuZXMuYmVkJywgInhjcl90YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIveGNyX3RhYmxlLnRzdicsICJtbWN0bV9maW5hbF9wYXRpZW50X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudF93aXRoLW92JywgIm5hbm9zdHJpbmdfZGF0YSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbmFub3N0cmluZ19yZXN1bHRzL2l0aF9mdWxsL3FjL2xpbW1hX3F1YW50aWxlL25vcm1hbGl6ZWRfZXhwcmVzc2lvbl92b2FfbGFiZWxzX2ZpbHRlcmVkLnRzdicsICJuZW9lZGl0aW5nX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbmVvZWRpdGluZy9ydW42JywgImNvcHludW1iZXJfdGFibGUiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9pdGhpL21hc3Rlcl9jb3B5bnVtYmVyX2ZpbGUudHN2JywgImJjcl9kaXZlcnNpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9JR0gvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgImhlX3Jlc3VsdHNfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvaXRoaS9maW5uX3Jlc3VsdHMvaGVfb3V0cHV0X05vdjI5JywgImFycmF5X2V4cHJlc3Npb25fZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9hcnJheS9nZW5lX2V4cHJzX3JtYV9iYXRjaF9jb3JyZWN0ZWQudHh0JywgInNudl9jbHVzdGVyX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3Nudl9jbHVzdGVyJywgInRpbHNfZm9yX2NsdXN0ZXIiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknKSwgInRvdGFsX3RpbHR5cGVzIiA9IGMoJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JyksICJsb2dkaXIiID0gJy9zaGFobGFiL2FsemhhbmcvY2x1c3R0bXAvcGFwZXJyZXZpZXcyJywgIml0aF9pY2djX2JjIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9pdGhfaWNnY19tZXJnZWRfYmMudHN2JywgInBhdGllbnRzX2Zvcl9jbG9uYWwiID0gYygxLCAyLCAzLCA0LCA3LCA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcpLCAidmFyaWFiaWxpdHlfdHlwZSIgPSAnc3RhYmlsaXplJywgInRhYmxlX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvcmV2aWV3L3RhYmxlcy9ydW4yJywgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJzbnZfdGFibGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9zbnZzLnRzdicsICJlcGl0b3Blc191bmlxdWVfZmlsdGVyZWQiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2VwaXRvcGVzX3VuaXF1ZV9maWx0ZXJlZC50c3YnLCAiYmVuY2htYXJrZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2JlbmNobWFya3MvcGFwZXJyZXZpZXcyJywgInRpbGNsdXN0ZXJfc3VwZXJ2aXNlZF9pcHluYiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jldmlldy9pcHkvdGlsY2x1c3Rlcl9zdXBlcnZpc2VkbXVsdGljbGFzcy5pcHluYicsICJpbWFnZV9zdW1tYXJ5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvaXRoaS95dWFuX2hlY3JfaW1hZ2VfcmVzdWx0cy5jc3YnLCAiaWhjX2ZlYXR1cmVzX291dHB1dCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yL2loY19mZWF0dXJlc19vdXRwdXQudHh0JywgImNsb25lX2JyYW5jaF9sZW5ndGhzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvYnJhbmNoX2RhdGEudHN2JywgImRpc3RhbmNlX21ldGhvZCIgPSAnaG9ybicsICJjbG9uZV9wcmV2YWxlbmNlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL2Nsb25lX2RhdGEudHN2JywgInRpbF9jbHVzdGVyc19vdXRwdXQiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL2ludGVybWVkaWF0ZXMvcnVuMi90aWxfY2x1c3RlcnNfb3V0cHV0LnR4dCcsICJ0dW1vdXJfcHVyaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi90dW1vdXJfcHVyaXR5LnRzdicsICJwcmV2YWxlbmNlX3RocmVzaG9sZCIgPSAwLjAxLCAibm90ZWJvb2tfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9yZXZpZXcvbm90ZWJvb2tzL3J1bjInLCAic29tYXRpY19jb2RpbmdfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvc29tYXRpY19jb2RpbmdfdmFyaWFudHMnLCAiaW1hZ2Vfc3VtbWFyeTIiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9pdGhpL3l1YW5faGVjcl9pbWFnZV9yZXN1bHRzXzIuY3N2JywgImtub3duX3N1YnR5cGVzX2FycmF5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL2FycmF5L3N1YnR5cGVzL2tub3duX3N1YnR5cGVzLnRzdicsICJpdGhfc3RhdF90eXBlcyIgPSBjKCdlbnRyb3B5JywgJ3Bvc3Rwcm9jZXNzZWRfZGl2ZXJnZW5jZScsICdjb21iaW5lZF9pdGhfbm9ybWFsaXplZCcsICdwcm9wb3J0aW9uX3N1YmNsb25hbCcpLCAibmFub3N0cmluZ19hbm5vdGF0aW9ucyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9uYW5vc3RyaW5nL3BhbmNhbmNlcl9hbm5vdGF0aW9ucy50c3YnLCAiaWhjX3RhYmxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGUudHN2JywgImlncGFydGl0aW9uX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMjInLCAiYWxsX3RpbHR5cGVzIiA9IGMoJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JywgJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJyZW1peHRfY2VsbHVsYXJpdHlfcGxvaWR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9yZW1peHRfY2VsbHVsYXJpdHlfcGxvaWR5LnRzdicsICJicmVha3BvaW50X3RhYmxlIiA9ICcvc2hhaGxhYi9hbWNwaGVyc29uL3Byb2plY3RzL2l0aDMvaXRoMy9ub3RlYm9va3MvYmVzcG9rZS9pdGhfYnJlYWtwb2ludHMudHN2JywgImNsb2xhX3Jlc3VsdF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9jbG9sYS9ydW40L2Nsb2xhX2NvbmRlbnNlZF9yZXN1bHRzL2JldGEvY2xvbGFfcmVzdWx0cy50c3YnLCAiY2xvbmVfdHJlZXMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy90cmVlX2RhdGEudHN2JywgInJvb25leV9tdXRzaWdjdl9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZXh0ZXJuYWwvb3RoZXJfcGFwZXJzL21tYzYueGxzeCcsICJtb2xzdWJ0eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvbW9sc3VidHlwZXMudHN2JywgImZpbm5oZV9waXBlbGluZV9yZXN1bHRzX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvZmlubmhlL3J1bjEnLCAiaWNnY19zcGVjaW1lbiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0Mvc3BlY2ltZW4udHN2JywgImljZ2Nfc3VidHlwZXMiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL2ljZ2NfcHJpbWFyeV90dW1vdXJfc3VidHlwZXMudHN2JywgInRjcl9kaXZlcnNpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9UUkIvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgInRpbHNfZm9yX3ZhcmlhYmlsaXR5IiA9IGMoJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JykpLAogICAgcnVsZSA9ICdwYXRod2F5c19pbW11bm9lZGl0aW5nX2FuYWx5c2lzJwopCiMjIyMjIyMjIE9yaWdpbmFsIHNjcmlwdCAjIyMjIyMjIyMKCiAgICAgICAgICAgICAgICAgICAgICAgIGBgYAoKCgojIyBTZXR1cAoKYGBge3IgZ2xvYmFsX2NodW5rX29wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgdGlkeT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFKSAjY2FjaGU9VFJVRQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGl0aGkudXRpbHMpCmxvYWRfYmFzZV9saWJzKCkKCmxpYnJhcnkobWV0aG9kcykKbGlicmFyeShiZWRyKQpsaWJyYXJ5KGJpb21hUnQpCmxpYnJhcnkoQlNnZW5vbWUuSHNhcGllbnMuVUNTQy5oZzE5KQoKbGlicmFyeShpdGhpLm1ldGEpCmxpYnJhcnkoaXRoaS5maWd1cmVzKQpsaWJyYXJ5KGl0aGkudXRpbHMpCmxpYnJhcnkoaXRoaS5leHByKQpsaWJyYXJ5KGl0aGkuc2VxKQpsaWJyYXJ5KGl0aGkuYmVkKQpsaWJyYXJ5KGl0aGkuc3VwcCkKYGBgCgpgYGB7cn0KbmFub3N0cmluZ19kYXRhX3BhdGggPC0gc25ha2VtYWtlQGlucHV0JG5hbm9zdHJpbmdfZGF0YQpuYW5vc3RyaW5nX2Fubm90YXRpb25zX3BhdGggPC0gc25ha2VtYWtlQGlucHV0JG5hbm9zdHJpbmdfYW5ub3RhdGlvbnMKaWhjX3RhYmxlX3BhdGggPC0gc25ha2VtYWtlQGlucHV0JGloY190YWJsZQptYXN0ZXJfdmFyaWFudF9maWxlIDwtIHNuYWtlbWFrZUBpbnB1dCRzbnZfdGFibGUKbWFzdGVyX2JyZWFrcG9pbnRfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkYnJlYWtwb2ludF90YWJsZQpzb21hdGljX2NvZGluZ19yZXN1bHRfZGlyIDwtIHNuYWtlbWFrZUBpbnB1dCRzb21hdGljX2NvZGluZ19yZXN1bHRfZGlyCm1vbGVjdWxhcl9zdWJ0eXBlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JG1vbHN1YnR5cGVzCgpyZWZzZXFfZ2VuZV9maWxlIDwtIHNuYWtlbWFrZUBwYXJhbXMkcmVmc2VxX2dlbmVfZmlsZQp0aWxzX2Zvcl9jbHVzdGVyIDwtIHNuYWtlbWFrZUBwYXJhbXMkdGlsc19mb3JfY2x1c3RlcgpkYl9wYXRoIDwtIHNuYWtlbWFrZUBwYXJhbXMkZGIKYGBgCgpgYGB7cn0KYW5ub3RhdGlvbl9jb2xvdXJzIDwtIGl0aGkuZmlndXJlczo6Z2V0X2Fubm90YXRpb25fY29sb3VycygpCgptYXJ0IDwtIHVzZURhdGFzZXQoImhzYXBpZW5zX2dlbmVfZW5zZW1ibCIsIHVzZU1hcnQoYmlvbWFydCA9ICJFTlNFTUJMX01BUlRfRU5TRU1CTCIsIGhvc3QgPSAiZmViMjAxNC5hcmNoaXZlLmVuc2VtYmwub3JnIikpCgppaGNfdGFibGUgPC0gZnJlYWQoaWhjX3RhYmxlX3BhdGgpCm1hc3Rlcl92YXJpYW50X3RhYmxlIDwtIHJlYWRfdmFyaWFudF9maWxlKG1hc3Rlcl92YXJpYW50X2ZpbGUsIGRiX3BhdGgpCm1hc3Rlcl9icmVha3BvaW50X3RhYmxlIDwtIHJlYWRfdmFyaWFudF9maWxlKG1hc3Rlcl9icmVha3BvaW50X2ZpbGUsIGRiX3BhdGgpCgp0aXRhbl9maWxlIDwtIGZpbGUucGF0aChzb21hdGljX2NvZGluZ19yZXN1bHRfZGlyLCAic29tYXRpY19jbnZfdGl0YW4udHN2IikKc29tYXRpY19zbnZfZmlsZSA8LSBmaWxlLnBhdGgoc29tYXRpY19jb2RpbmdfcmVzdWx0X2RpciwgInNvbWF0aWNfc252cy50c3YiKQpzb21hdGljX2luZGVsX2ZpbGUgPC0gZmlsZS5wYXRoKHNvbWF0aWNfY29kaW5nX3Jlc3VsdF9kaXIsICJzb21hdGljX2luZGVscy50c3YiKQp0aXRhbl9jbnYgPC0gZnJlYWQodGl0YW5fZmlsZSkKc29tYXRpY19zbnZzIDwtIGZyZWFkKHNvbWF0aWNfc252X2ZpbGUpCnNvbWF0aWNfaW5kZWxzIDwtIGZyZWFkKHNvbWF0aWNfaW5kZWxfZmlsZSkKCmV4cHJzIDwtIGZyZWFkKG5hbm9zdHJpbmdfZGF0YV9wYXRoKQpuYW5vc3RyaW5nX2xhYmVscyA8LSBmcmVhZChuYW5vc3RyaW5nX2Fubm90YXRpb25zX3BhdGgpCm1vbHN1YnR5cGVzIDwtIGZyZWFkKG1vbGVjdWxhcl9zdWJ0eXBlX2ZpbGUpCgp0aWxfY2x1c3RlcnMgPC0gaXRoaS5maWd1cmVzOjo6Z2V0X3RpbF9jbHVzdGVycyhpaGNfdGFibGUsIG1vbHN1YnR5cGVzLCB0aWxzX2Zvcl9jbHVzdGVyID0gdGlsc19mb3JfY2x1c3RlciwgbmNsdXN0cyA9IDMpCmBgYAoKIyMgUGF0aHdheXMgaW1tdW5vZWRpdGluZyBhbmFseXNpcwoKVGhlIHB1cnBvc2Ugb2YgdGhpcyBhbmFseXNpcyBpcyB0byBzaG93IHdoZXRoZXIgb3Igbm90IGltbXVuZSBjaGVja3BvaW50IG9yIG90aGVyIGltbXVub3N1cHByZXNzaXZlIGZhY3RvcnMgbWF5IGJlIHByZXNlbnQgYW5kIGFzc29jaWF0ZWQgd2l0aCBUSUwgZGVuc2l0aWVzL291ciBOL1MvRVMtVElMIGNsdXN0ZXJzLiBJZiBzbywgdGhpcyByZXZpZXdlciB0aGlua3MgdGhleSBtYXkgaW50ZXJmZXJlIHdpdGggYW55IGltbXVub2VkaXRpbmcgdGhhdCB3ZSBjbGFpbSBtYXkgYmUgdGFraW5nIHBsYWNlLiAKCkluIGFjdHVhbGl0eSwgSSB0aGluayB0aGlzIHJldmlld2VyJ3MgYXJndW1lbnQgaXMgZmxhd2VkIC0tIHdlJ3JlIG1lYXN1cmluZyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgdHVtb3VyLCBub3QgdGhlIHBhc3QuIEV2ZW4gaWYgY2hlY2twb2ludCBtb2xlY3VsZXMgYXJlIHByZXNlbnQgLS0gYW5kIGludGVyZmVyaW5nIHdpdGggaW1tdW5vZWRpdGluZyBub3cgLS0gdGhpcyBtYXkgbm90IGhhdmUgYmVlbiB0aGUgY2FzZSBpbiB0aGUgdHVtb3VyJ3MgaGlzdG9yeS4gCgojIyMgRXhwcmVzc2lvbi1sZXZlbAoKYGBge3J9CiMgYW50aWdlbi1wcm9jZXNzaW5nIG1hY2hpbmVyeQojIEFQTV9nZW5lcyA8LSBjKCJDQU5YIiwgIkhTUEE1IiwgIkIyTSIsICJITEEtQSIsICJITEEtQiIsICJITEEtQyIsICJUQVAxIiwgIlRBUDIiLCAiVEFQQlAiLCAiQ0FMUiIsICJQRElBMyIpCkFQTV9nZW5lcyA8LSBjKCJITEEtQSIsICJITEEtQiIsICJITEEtQyIsICJUQVAxIiwgIlRBUDIiLCAiVEFQQlAiLCAiUFNNQjkiKSMsICJQU01CNyIpCmNoZWNrcG9pbnRfZ2VuZXMgPC0gc3Vic2V0KG5hbm9zdHJpbmdfbGFiZWxzLCBzdHJfZGV0ZWN0KGdlbmVfY2xhc3MsICJDaGVja3BvaW50IikpJEdlbmUKaW1tdW5lX3N1cHByZXNzaW9uIDwtIGMoIklETzEiKSMsICJJRE8yIiwgIkFMT1giKSAjIHA1MyBleGNsdWRlZCBiZWNhdXNlIHA1MyBsb3NzIGlzIHViaXF1aXR1b3VzIGluIEhHU0M7IG90aGVycyBhcmUgYWJzZW50CmlmbmdfZ2VuZXMgPC0gYygiSUZORyIpCgptdXRhdGlvbl9nZW5lcyA8LSBjKEFQTV9nZW5lcywgaWZuZ19nZW5lcykKYGBgCgpgYGB7cn0KcGxvdF9jbHVzdGVyX2V4cHJlc3Npb24gPC0gZnVuY3Rpb24oZXhwciwgZ2VuZXMsIGloY190YWJsZSkgewogIGV4cHJfc3Vic2V0IDwtIHN1YnNldChleHByLCBOYW1lICVpbiUgZ2VuZXMpICU+JSBhcy5kYXRhLmZyYW1lICU+JSBjb2x1bW5fdG9fcm93bmFtZXModmFyID0gIk5hbWUiKQogIAogIHNhbXBsZV9maWx0ZXIgPC0gaW50ZXJzZWN0KGloY190YWJsZSR2b2EsIGNvbG5hbWVzKGV4cHJfc3Vic2V0KSkKICBleHByX3N1YnNldCA8LSBleHByX3N1YnNldFssc2FtcGxlX2ZpbHRlcl0KICAKICBleHByX2RmIDwtIG1lbHQoYXMubWF0cml4KGV4cHJfc3Vic2V0KSkgJT4lIHBseXI6OnJlbmFtZShjKCdWYXIxJz0nTmFtZScsICdWYXIyJz0ndm9hJykpCiAgZXhwcl9paGMgPC0gcGx5cjo6am9pbihleHByX2RmLCBpaGNfdGFibGUpCiAgZXhwcl9paGMkcGF0aWVudF9pZCA8LSBmYWN0b3IoYXMuY2hhcmFjdGVyKGV4cHJfaWhjJHBhdGllbnRfaWQpKQogIAogIAogIHB2YWxzIDwtIHNldE5hbWVzKGRkcGx5KGV4cHJfaWhjLCAuKE5hbWUpLCBmdW5jdGlvbih4KSB7CiAgICBkZiA8LSBhcy5kYXRhLmZyYW1lKHgpCiAgICBjb3JyZXMgPC0gd2l0aChkZiwgY29yLnRlc3QodmFsdWUsIEVfQ0Q4X2RlbnNpdHksIG1ldGhvZCA9ICJzcGVhcm1hbiIpKQogICAgCiAgICBwdmFsIDwtIGNvcnJlcyRwLnZhbHVlCiAgICByZXR1cm4ocHZhbCkKICB9KSwgYygiTmFtZSIsICJwLnZhbHVlIikpCiAgcHZhbHMkcC5hZGogPC0gcC5hZGp1c3QocHZhbHMkcC52YWx1ZSwgbWV0aG9kID0gImZkciIpCiAgCiAgcHZhbHMkcC5hZGoudGV4dCA8LSBzYXBwbHkocHZhbHMkcC5hZGosIGZ1bmN0aW9uKHgpIGFzLmNoYXJhY3Rlcihhcy5leHByZXNzaW9uKHN1YnN0aXR1dGUoaXRhbGljKFApPT1wLCBsaXN0KHA9Zm9ybWF0KHgsIGRpZ2l0cz0zKSkpKSkpCiAgCiAgcCA8LSBnZ3Bsb3QoZXhwcl9paGMsIGFlcyh4PUVfQ0Q4X2RlbnNpdHksIHk9dmFsdWUpKSArIGdlb21fcG9pbnQoYWVzKGNvbG91cj1wYXRpZW50X2lkKSkgKyBmYWNldF93cmFwKH4gTmFtZSwgc2NhbGVzID0gImZyZWUiKSArIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpICsgdGhlbWVfYncoKSArIGl0aGkudXRpbHM6OnRoZW1lX1B1YmxpY2F0aW9uKCkgKyBpdGhpLnV0aWxzOjp0aGVtZV9uYXR1cmUoKSArIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYW5ub3RhdGlvbl9jb2xvdXJzJHBhdGllbnRfaWQpICsgZ2VvbV90ZXh0KGRhdGE9cHZhbHMsIGFlcyh4PUluZiwgeT1JbmYsIGxhYmVsPXAuYWRqLnRleHQpLCBoanVzdD0xLjEsIHZqdXN0PTEuNSxzaXplPTIuNSxwYXJzZT1UUlVFKSAKICAKICByZXR1cm4ocCkKfQpgYGAKCmBgYHtyLCBjYWNoZT1UUlVFfQpwbG90X2NsdXN0ZXJfZXhwcmVzc2lvbihleHBycywgQVBNX2dlbmVzLCBpaGNfdGFibGUpCnBsb3RfY2x1c3Rlcl9leHByZXNzaW9uKGV4cHJzLCBjaGVja3BvaW50X2dlbmVzLCBpaGNfdGFibGUpCnBsb3RfY2x1c3Rlcl9leHByZXNzaW9uKGV4cHJzLCBpZm5nX2dlbmVzLCBpaGNfdGFibGUpCnBsb3RfY2x1c3Rlcl9leHByZXNzaW9uKGV4cHJzLCBpbW11bmVfc3VwcHJlc3Npb24sIGloY190YWJsZSkKYGBgCgpTbyB0aGUgZXhwcmVzc2lvbiBvZiB0aGVzZSBnZW5lcyBpcyBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQgd2l0aCBlcGl0aGVsaWFsIENEOCsgVElMIGRlbnNpdHkuIAoKV2hhdCBkb2VzIHRoaXMgbWVhbj8gCgoqIEFQTSBnZW5lczogQW50aWdlbiBwcm9jZXNzaW5nIG1hY2hpbmVyeSBpcyBub3QgdW5kZXJleHByZXNzZWQgaW4gc2FtcGxlcyB3aXRoIGhpZ2ggZXBpdGhlbGlhbCBDRDgrIFRJTCwgYW5kIHRoZXJlZm9yZSBkb2VzIG5vdCBsaWtlbHkgcHJldmVudCBpbW11bm9lZGl0aW5nLiAKKiBJRk5HIGFuZCBjaGVja3BvaW50IGdlbmVzOiBJbnRlcmZlcm9uLWdhbW1hIGlzIGtub3duIHRvIHN0aW11bGF0ZSBQRDEgKEJlbmNpIGV0IGFsLiAyMDE2KS4gSGlnaGVyIGxldmVscyBvZiBjaGVja3BvaW50IGluaGliaXRvcnMsIGUuZy4gUEQtMSwgd291bGQgdGhlb3JldGljYWxseSBpbnRlcmZlcmUgd2l0aCBpbW11bm9lZGl0aW5nLiBIb3dldmVyLCBjb250cmFyeSB0byBtYW55IG90aGVyIHNldHRpbmdzLCBpbiBIR1NDIFBEMStDRDgrIFRJTCAod2hpY2ggdHlwaWNhbGx5IGNvZXhwcmVzcyBDRDEwMysgYWNjb3JkaW5nIHRvIFdlYmIgZXQgYWwuIDIwMTQgYW5kIEtvbWRldXIgZXQgYWwuIDIwMTYpIGFyZSBhc3NvY2lhdGVkIHdpdGggc3VwZXJpb3Igb3V0Y29tZXMgYW5kIHJldGFpbiBmdW5jdGlvbmFsIGNvbXBldGVuY2UsIGkuZS4gcHJvZHVjZSByb2J1c3QgYW1vdW50cyBvZiBUTkYtYWxwaGEgYW5kIElGTi1nYW1tYSAoV2ViYiBldCBhbC4gMjAxNCwgV2ViYiBldCBhbC4gMjAxNSkuIAoqIEltbXVuZSBzdXBwcmVzc2lvbiBnZW5lczogRnJvbSBSb29uZXkgLS0gd2UgZm91bmQgdGhhdCBDWVQgd2FzIGJlc3QgY29ycmVsYXRlZCB3aXRoIGltbXVub3N1cHByZXNzaXZlIGZhY3RvcnMgKFNwcmFuZ2VyIGV0IGFsLiwgMjAxMyksIHN1Y2ggYXMgUERDRDFMRzIgKFBETDIpLCBJRE8xLzIsIERPSzMgKExlbWF5IGV0IGFsLiwgMjAwMCksIEdNQ1NGIHJlY2VwdG9yIChDU0YyUkEsIENTRjJSQikgYW5kIHRoZSBDMVEgY29tcGxleCAoRmlndXJlIDFCKS4KCiMjIyBNdXRhdGlvbi1sZXZlbAoKSGVyZSwgb3VyIGdvYWwgaXMganVzdCB0byBsb29rIGZvciB0aGUgcHJlc2VuY2Ugb2YgbXV0YXRpb25zIGluIHRob3NlIGltbXVuZS1hc3NvY2lhdGVkIGdlbmVzLiBGb3IgZXhhbXBsZSwgaWYgdGhlcmUgYXJlIG11dGF0aW9ucyBpbiBhbnRpZ2VuIHByZXNlbnRpbmcgbWFjaGluZXJ5IGdlbmVzLCB0aGVzZSBtYXkgaW50ZXJmZXJlIHdpdGggYW50aWdlbiByZWNvZ25pdGlvbiBhbmQgdGhlcmVmb3JlIGltbXVub2VkaXRpbmcuIAoKYGBge3IsIHJlc3VsdHM9J2hpZGUnLCBjYWNoZT1UUlVFfQp0aXRhbl9iZWQgPC0gY29udmVydF90b19iZWQodGl0YW5fY252KQpyZWZzZXFfYmVkIDwtIHJlYWRfYmVkKHJlZnNlcV9nZW5lX2ZpbGUpCgpnZW5lX25hbWVzIDwtIGdldEJNKGF0dHJpYnV0ZXMgPSBjKCJyZWZzZXFfbXJuYSIsICJoZ25jX3N5bWJvbCIpLCB2YWx1ZXMgPSByZWZzZXFfYmVkJHJlZnNlcV9pZCwgbWFydCA9IG1hcnQpCgpyZWZzZXFfYmVkX2Fubm90YXRlZCA8LSBtZXJnZShyZWZzZXFfYmVkLCBnZW5lX25hbWVzICU+JSBzdWJzZXQocmVmc2VxX21ybmEgIT0gIiIpICU+JSBwbHlyOjpyZW5hbWUoYygncmVmc2VxX21ybmEnPSdyZWZzZXFfaWQnKSksIGJ5ID0gYygncmVmc2VxX2lkJykpCgpyZWZzZXFfYmVkX2Fubm90YXRlZCA8LSBzdWJzZXQocmVmc2VxX2JlZF9hbm5vdGF0ZWQsIHNlbGVjdD1jKCJjaHIiLCAic3RhcnQiLCAiZW5kIiwgImhnbmNfc3ltYm9sIiwgInJlZnNlcV9pZCIpKQpyZWZzZXFfYmVkX2Fubm90YXRlZCA8LSBiZWRyLnNvcnQucmVnaW9uKHJlZnNlcV9iZWRfYW5ub3RhdGVkKQoKdGl0YW5fbWVyZ2VkIDwtIGJlZHIoZW5naW5lID0gImJlZHRvb2xzIiwgaW5wdXQgPSBsaXN0KGE9dGl0YW5fYmVkLCBiPXJlZnNlcV9iZWRfYW5ub3RhdGVkKSwgbWV0aG9kID0gImludGVyc2VjdCIsIHBhcmFtcyA9ICItbG9qIikKYGBgCgpgYGB7cn0KdGl0YW5fbWVyZ2VkIDwtIGRhdGEuZnJhbWUodGl0YW5fbWVyZ2VkKQp0aXRhbl9tZXJnZWQkbWVkaWFuX2xvZ1IgPC0gYXMubnVtZXJpYyh0aXRhbl9tZXJnZWQkbWVkaWFuX2xvZ1IpCnRpdGFuX21lcmdlZCR0b3RhbCA8LSBhcy5udW1lcmljKHRpdGFuX21lcmdlZCR0b3RhbCkKdGl0YW5fbWVyZ2VkJG1ham9yIDwtIGFzLm51bWVyaWModGl0YW5fbWVyZ2VkJG1ham9yKQp0aXRhbl9tZXJnZWQkbWlub3IgPC0gYXMubnVtZXJpYyh0aXRhbl9tZXJnZWQkbWlub3IpCgp0aXRhbl9tZXJnZWRfZmlsdGVyZWQgPC0gc3Vic2V0KHRpdGFuX21lcmdlZCwgKG1lZGlhbl9sb2dSIDwgLTEpIHwgKG1lZGlhbl9sb2dSID4gMSkpCmBgYAoKCmBgYHtyfQpzb21hdGljX3NudnNfZmlsdGVyZWQgPC0gcGx5cjo6am9pbihzb21hdGljX3NudnMsIG1hc3Rlcl92YXJpYW50X3RhYmxlICU+JSBzdWJzZXQoaXNfcHJlc2VudCA9PSAxKSwgdHlwZSA9ICdpbm5lcicpCnNvbWF0aWNfaW5kZWxzX2ZpbHRlcmVkIDwtIHN1YnNldChzb21hdGljX2luZGVscywgbWFwcGFiaWxpdHkgPT0gMSkKYGBgCgpgYGB7cn0KdGl0YW5fbWVyZ2VkX2ZpbHRlcmVkX2ltbXVuZSA8LSBzdWJzZXQodGl0YW5fbWVyZ2VkX2ZpbHRlcmVkLCBoZ25jX3N5bWJvbCAlaW4lIG11dGF0aW9uX2dlbmVzKQpzb21hdGljX3NudnNfaW1tdW5lIDwtIHN1YnNldChzb21hdGljX3NudnNfZmlsdGVyZWQsIGdlbmVfbmFtZSAlaW4lIG11dGF0aW9uX2dlbmVzKQpzb21hdGljX2luZGVsc19pbW11bmUgPC0gc3Vic2V0KHNvbWF0aWNfaW5kZWxzX2ZpbHRlcmVkLCBnZW5lX25hbWUgJWluJSBtdXRhdGlvbl9nZW5lcykKCnByaW50KHNvbWF0aWNfc252c19pbW11bmUpCnByaW50KHNvbWF0aWNfaW5kZWxzX2ltbXVuZSkKYGBgCgpgYGB7cn0KIyMgQmVjYXVzZSB3ZSBoYXZlIExPSEhMQSBhbmQgdGhhdCdzIG1vcmUgYWNjdXJhdGUgaW4gcG9seW1vcnBoaWMgcmVnaW9ucwp0aXRhbl9tZXJnZWRfZmlsdGVyZWRfaW1tdW5lX25vaGxhIDwtIHN1YnNldCh0aXRhbl9tZXJnZWRfZmlsdGVyZWRfaW1tdW5lLCAhaGduY19zeW1ib2wgJWluJSBjKCJITEEtQSIsICJITEEtQiIsICJITEEtQyIpKQoKcHJpbnQodGl0YW5fbWVyZ2VkX2ZpbHRlcmVkX2ltbXVuZV9ub2hsYSkKYGBgCgpUaGUgcmVhc29uIHRoZXJlIGFyZSBubyBTTlZzIGxlZnQgaXMgYmVjYXVzZSBvZiB0aGUgbWFwcGFiaWxpdHkgdGhyZXNob2xkLiAKClRoZXJlJ3Mgb25lIGluZGVsIC0tIGluIFRBUCwgZm9yIHNhbXBsZSBgciBzb21hdGljX2luZGVsc19pbW11bmUkY29uZGVuc2VkX2lkYC4gVGhpcyBzYW1wbGUgaXMgVElMIHN1YnR5cGUgYHIgc3Vic2V0KHRpbF9jbHVzdGVycywgY29uZGVuc2VkX2lkID09IHNvbWF0aWNfaW5kZWxzX2ltbXVuZSRjb25kZW5zZWRfaWQpJGNsdXN0ZXJgLiAKClRoZXJlIGFyZSBDTiBoaWdoLWxldmVsIGFtcGxpZmljYXRpb25zIGluIElGTkcvUFNNQjkvVEFQMS9UQVAyL1RBUEJQLiBObyBkZWxldGlvbnMgdGhhdCBtaWdodCBiZSBpbnRlcmZlcmluZyB3aXRoIGFudGlnZW4gcHJvY2Vzc2luZyBtYWNoaW5lcnkuIAo=