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
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
molecular_subtype_file <- snakemake@input$molsubtypes
clonal_measures_file <- snakemake@input$ith_stats_file
mutsig_dir <- snakemake@input$mutsig_dir
ith_icgc_bc_file <- snakemake@input$ith_icgc_bc
nanostring_annotations_path <- snakemake@input$nanostring_annotations
icgc_subtype_file <- snakemake@input$icgc_subtypes
icgc_specimen_file <- snakemake@input$icgc_specimen
master_variant_file <- snakemake@input$snv_table
master_breakpoint_file <- snakemake@input$breakpoint_table

db_path <- snakemake@params$db
tils_for_cluster <- snakemake@params$tils_for_cluster
stat_types <- snakemake@params$ith_stat_types
nclusts <- 3

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 19.7% of 304822 rows
Read 62.3% 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:05
molsubtypes <- fread(molecular_subtype_file)

tree_branch_data <- read_clone_tree_data(clone_tree_file, clone_branch_length_file, 
    clone_prevalence_file, db_path)

xcr_diversity <- ithi.supp::get_xcr_diversity(tcr_diversity_file, bcr_diversity_file, 
    db_path, xcr_table)

clonal_measures <- ithi.clones::read_ith_stats(clonal_measures_file, db_path, 
    duplicates = FALSE)

ith_icgc_bc <- fread(ith_icgc_bc_file)
icgc_specimen_data <- fread(icgc_specimen_file)

nanostring_labels <- fread(nanostring_annotations_path)

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

master_variant_table <- read_variant_file(master_variant_file, db_path)
master_breakpoint_table <- read_variant_file(master_breakpoint_file, db_path)

sig_results <- produce_signature_results(mutsig_dir, master_variant_table, master_breakpoint_table, 
    db_path)
sig_results_snv <- sig_results$snv
sig_results_sv <- sig_results$sv

Analysis

Reviewer 3 has several comments about statistical tests made in the manuscript. These are all valid + easy to address – some are mistakes/typos on my part, others are things we could/should have done, etc.

Fig S4B

Fixed to only show patients with samples in both groups.

cor_tilsubtype_clonal_res <- supp_cor_tilsubtype_clonal(ihc_table, tree_branch_data, 
    tils_for_cluster, nclusts, molsubtypes, db_path)
grid.newpage()
grid.draw(cor_tilsubtype_clonal_res$plots$tilclust_clonalsim)

There, no more ‘orphaned’ points.

Permutation test

Q: What analysis was performed in the sentence “(p > 0.3, permutation test, Figure S4B)” on page 6, which permutation test? Figure S4B is not a permutation test.

This was actually a nested ranks test. It is incorrectly noted as a Wilcoxon signed-rank within the figure legend – this needs to be fixed.

I can see why this would be confused for a MW test, though. What isn’t clearly noted here is that I plot the MEANS for each patient. In fact, all pairwise comparisons in each patient are being compared, not just the mean by cluster equality.

The reason why a Wilcoxon signed-rank is because, to make that type of comparison, patient needs to be accounted for as a random effect. The nested ranks test is one possible extension of a MW/Wilcoxon-type test that uses bootstrapping to compute p-values. See the R package nestedRanksTest.

Tumour purity vs. ITH

Q: In figure S4A, the correlation between “proportion sub-clonal” and “cellularity” is significant (p=0.0169), yet in the manuscript the authors say: “and none of the clonal measures were confounded by tumor purity (all p > 0.2, Figure S4A)”. Page 6.

This is a wording issue. Technically we’re right, but we should make it more obvious by listing out the CLONAL measures, i.e. not including proportion subclonal CN. This is a valid point though – we want to avoid using ambiguous wording wherever possible – not worth saving a few characters to make things more confusing.

Figure 1C

Q: Figure 1C does not say which statistical test was used, and if a Kruskal-Wallis was used, a post hoc analysis should be employed.

Point taken. We’ll do some post-hoc tests to compare pairwise significance between groups.

Since this is a Kruskal-Wallis, the most appropriate post-hoc test to use is the Dunn test.

May also be a good idea to annotate on the plot itself.

nonalpha_cluster_colours <- stringr::str_extract(annotation_colours$til_cluster_colours, 
    "#[0-9A-Z]{6}")
ith_boxplots <- ithi.figures:::plot_ith_boxplots(clonal_measures, stat_types, 
    til_clusters, nonalpha_cluster_colours, force_font = FALSE, scale_factor = 7/18, 
    orientation = "wide", post_hoc = TRUE)
grid.newpage()
grid.draw(ith_boxplots)

TODO: Add a legend for the asterisks. Two asterisks corresponds to 0.05, one to 0.1, and 3 to 0.001.

As per the results above, all measures except clone divergence show a significant difference between all other classes and ES-TIL.

Figure 6B

Q: Statistical analysis of 6B should include post hoc test.

This is going to be removed from the text (because the entire mutation signatures section is going to go poof), but let’s do it anyways for interest (and because I need this for a slide).

label_file <- Sys.glob(file.path(mutsig_dir, "output", "*_labels.tsv"))
labels <- data.table::fread(label_file)
labels <- subset(labels, select = c(library, project, histotype))
labels$library <- stringr::str_replace(labels$library, "^patient_", "")
labels <- labels %>% plyr::rename(c(library = "patient_id"))

signature_labels <- stringr::str_extract(c(colnames(sig_results_snv), colnames(sig_results_sv)), 
    "SN?V-[0-9]+")
signature_labels <- signature_labels[!is.na(signature_labels)]

sigheat_patient_res <- ithi.supp:::get_formal_clusters(sig_results, labels, 
    signature_labels, annotation_colours)

col_clust <- sigheat_patient_res$hc
sample_order <- col_clust$labels[col_clust$order]
clusters <- cutree(col_clust, 3)
general_labels <- as.data.frame(clusters) %>% tibble::rownames_to_column(var = "patient_id") %>% 
    plyr::rename(c(clusters = "cluster"))
general_labels$cluster <- as.character(general_labels$cluster)

message("Plotting boxplots ...")
nonalpha_cluster_colours <- stringr::str_extract(annotation_colours$mutsig_clusters, 
    "#[0-9A-Z]{6}")

# Technically icgc_subtypes hasn't been assigned, but we don't use it
# anymore so w/e
immune_boxplot_fig <- ithi.figures:::plot_immune_boxplot(ith_icgc_bc, level = "patient", 
    nanostring_labels, general_labels, molsubtypes, icgc_specimen_data, annotation_colours, 
    sample_order, db_path, icgc_subtypes, nonalpha_cluster_colours, force_font = FALSE, 
    post_hoc = TRUE)
grid.newpage()
grid.draw(immune_boxplot_fig)

TODO: Modify text to acknowledge that there is significant difference between H-HRD and H-FBI-2 in SOME immune pathways. Or alternatively just be more specific in saying that there isn’t significance in the other categories (instead of saying that they’re similar overall).

LS0tCnRpdGxlOiAiU3RhdGlzdGljYWwgZXJyYXRhIGFuZCBwb3N0LWhvYyB0ZXN0cyIKLS0tCiAgICAgICAgICAgICAgICAgICAgICAgIGBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjIyMjIyMgU25ha2VtYWtlIGhlYWRlciAjIyMjIyMjIwpsaWJyYXJ5KG1ldGhvZHMpClNuYWtlbWFrZSA8LSBzZXRDbGFzcygKICAgICJTbmFrZW1ha2UiLAogICAgc2xvdHMgPSBjKAogICAgICAgIGlucHV0ID0gImxpc3QiLAogICAgICAgIG91dHB1dCA9ICJsaXN0IiwKICAgICAgICBwYXJhbXMgPSAibGlzdCIsCiAgICAgICAgd2lsZGNhcmRzID0gImxpc3QiLAogICAgICAgIHRocmVhZHMgPSAibnVtZXJpYyIsCiAgICAgICAgbG9nID0gImxpc3QiLAogICAgICAgIHJlc291cmNlcyA9ICJsaXN0IiwKICAgICAgICBjb25maWcgPSAibGlzdCIsCiAgICAgICAgcnVsZSA9ICJjaGFyYWN0ZXIiCiAgICApCikKc25ha2VtYWtlIDwtIFNuYWtlbWFrZSgKICAgIGlucHV0ID0gbGlzdCgnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX3NudnMudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9icmFuY2hfZGF0YS50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIveGNyX3RhYmxlLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGUudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vbmFub3N0cmluZy9wYW5jYW5jZXJfYW5ub3RhdGlvbnMudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2l0aF9zdGF0aXN0aWNzLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9tb2xzdWJ0eXBlcy50c3YnLCAnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX2JyZWFrcG9pbnRzLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvdHJlZV9kYXRhLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvSUdIL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9pdGhfaWNnY19tZXJnZWRfYmMudHN2JywgJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL3NwZWNpbWVuLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvVFJCL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvY2xvbmVfZGF0YS50c3YnLCAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvaWNnY19wcmltYXJ5X3R1bW91cl9zdWJ0eXBlcy50c3YnLCAnbm90ZWJvb2tzL3N0YXRpc3RpY2FsX2VycmF0YV9wb3N0aG9jLlJtZCcsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1wYXRpZW50X3dpdGgtb3YnLCAic252X3RhYmxlIiA9ICcvc2hhaGxhYi9hbWNwaGVyc29uL3Byb2plY3RzL2l0aDMvaXRoMy9ub3RlYm9va3MvYmVzcG9rZS9pdGhfc252cy50c3YnLCAiY2xvbmVfYnJhbmNoX2xlbmd0aF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvYnJhbmNoX2RhdGEudHN2JywgInhjcl90YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIveGNyX3RhYmxlLnRzdicsICJpaGNfdGFibGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2loY190YWJsZS50c3YnLCAibmFub3N0cmluZ19hbm5vdGF0aW9ucyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9uYW5vc3RyaW5nL3BhbmNhbmNlcl9hbm5vdGF0aW9ucy50c3YnLCAiaXRoX3N0YXRzX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2l0aF9zdGF0aXN0aWNzLnRzdicsICJtb2xzdWJ0eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvbW9sc3VidHlwZXMudHN2JywgImJyZWFrcG9pbnRfdGFibGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9icmVha3BvaW50cy50c3YnLCAiY2xvbmVfdHJlZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvdHJlZV9kYXRhLnRzdicsICJiY3JfZGl2ZXJzaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvSUdIL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICJpdGhfaWNnY19iYyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvaXRoX2ljZ2NfbWVyZ2VkX2JjLnRzdicsICJpY2djX3NwZWNpbWVuIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9zcGVjaW1lbi50c3YnLCAidGNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL1RSQi9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAiY2xvbmVfcHJldmFsZW5jZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvY2xvbmVfZGF0YS50c3YnLCAiaWNnY19zdWJ0eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvaWNnY19wcmltYXJ5X3R1bW91cl9zdWJ0eXBlcy50c3YnLCAibm90ZWJvb2siID0gJ25vdGVib29rcy9zdGF0aXN0aWNhbF9lcnJhdGFfcG9zdGhvYy5SbWQnLCAibXV0c2lnX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudF93aXRoLW92JyksCiAgICBvdXRwdXQgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9yZXZpZXcvbm90ZWJvb2tzL3J1bjIvc3RhdGlzdGljYWxfZXJyYXRhX3Bvc3Rob2MubmIuaHRtbCcpLAogICAgcGFyYW1zID0gbGlzdChjKCdlbnRyb3B5JywgJ3Bvc3Rwcm9jZXNzZWRfZGl2ZXJnZW5jZScsICdjb21iaW5lZF9pdGhfbm9ybWFsaXplZCcsICdwcm9wb3J0aW9uX3N1YmNsb25hbCcpLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL21ldGFkYXRhL2RiL2ltbXVuZV9wcm9qZWN0LnNxbGl0ZTMnLCAnc3RhdGlzdGljYWxfZXJyYXRhX3Bvc3Rob2NfYW5hbHlzaXMnLCBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAiaXRoX3N0YXRfdHlwZXMiID0gYygnZW50cm9weScsICdwb3N0cHJvY2Vzc2VkX2RpdmVyZ2VuY2UnLCAnY29tYmluZWRfaXRoX25vcm1hbGl6ZWQnLCAncHJvcG9ydGlvbl9zdWJjbG9uYWwnKSwgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJ0aWxzX2Zvcl9jbHVzdGVyIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJuYW1lIiA9ICdzdGF0aXN0aWNhbF9lcnJhdGFfcG9zdGhvY19hbmFseXNpcycpLAogICAgd2lsZGNhcmRzID0gbGlzdCgpLAogICAgdGhyZWFkcyA9IDEsCiAgICBsb2cgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL2NsdXN0dG1wL3BhcGVycmV2aWV3Mi9ub3RlYm9va3Mvc3RhdGlzdGljYWxfZXJyYXRhX3Bvc3Rob2NfYW5hbHlzaXMubG9nJyksCiAgICByZXNvdXJjZXMgPSBsaXN0KCksCiAgICBjb25maWcgPSBsaXN0KCJrbm93bl9zdWJ0eXBlc19hcnJheSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9hcnJheS9zdWJ0eXBlcy9rbm93bl9zdWJ0eXBlcy50c3YnLCAiaW1hZ2Vfc3VtbWFyeSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL2l0aGkveXVhbl9oZWNyX2ltYWdlX3Jlc3VsdHMuY3N2JywgInNvbWF0aWNfY29kaW5nX3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL3NvbWF0aWNfY29kaW5nX3ZhcmlhbnRzJywgIm5vdGVib29rX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvcmV2aWV3L25vdGVib29rcy9ydW4yJywgInByZXZhbGVuY2VfdGhyZXNob2xkIiA9IDAuMDEsICJzbnZfY2x1c3Rlcl9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9zbnZfY2x1c3RlcicsICJhcnJheV9leHByZXNzaW9uX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vYXJyYXkvZ2VuZV9leHByc19ybWFfYmF0Y2hfY29ycmVjdGVkLnR4dCcsICJzbnZfdGFibGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9zbnZzLnRzdicsICJmaW5uaGVfcGlwZWxpbmVfcmVzdWx0c19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2Zpbm5oZS9ydW4xJywgInRpbHNfZm9yX2NsdXN0ZXIiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknKSwgImNsb25lX3ByZXZhbGVuY2VzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvY2xvbmVfZGF0YS50c3YnLCAicGF0aWVudHNfZm9yX2Nsb25hbCIgPSBjKDEsIDIsIDMsIDQsIDcsIDksIDEwLCAxMSwgMTIsIDEzLCAxNCwgMTUsIDE2LCAxNyksICJpaGNfZmVhdHVyZXNfb3V0cHV0IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIvaWhjX2ZlYXR1cmVzX291dHB1dC50eHQnLCAiYWxsX3RpbHR5cGVzIiA9IGMoJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JywgJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJjbG9uZV9icmFuY2hfbGVuZ3RocyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL2JyYW5jaF9kYXRhLnRzdicsICJyZWZzZXFfZ2VuZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvZ2Vub21lL2hnMTkvcmVmc2VxX2dlbmVzLmJlZCcsICJ2YXJpYWJpbGl0eV90eXBlIiA9ICdzdGFiaWxpemUnLCAidGlsc19mb3JfdmFyaWFiaWxpdHkiID0gYygnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgImJjcl9kaXZlcnNpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9JR0gvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgInhjcl90YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIveGNyX3RhYmxlLnRzdicsICJiZW5jaG1hcmtkaXIiID0gJy9zaGFobGFiL2FsemhhbmcvYmVuY2htYXJrcy9wYXBlcnJldmlldzInLCAiaWhjX3RhYmxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9paGNfdGFibGUudHN2JywgImJyZWFrcG9pbnRfdGFibGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9icmVha3BvaW50cy50c3YnLCAiZGIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJywgImVwaXRvcGVzX3VuaXF1ZV9maWx0ZXJlZCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvZXBpdG9wZXNfdW5pcXVlX2ZpbHRlcmVkLnRzdicsICJjbG9uZV90cmVlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3RyZWVfZGF0YS50c3YnLCAiaWdwYXJ0aXRpb25fb3V0ZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9pZ3BhcnRpdGlvbi9ydW4yMicsICJpY2djX3NwZWNpbWVuIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9zcGVjaW1lbi50c3YnLCAiaGVfcmVzdWx0c19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9pdGhpL2Zpbm5fcmVzdWx0cy9oZV9vdXRwdXRfTm92MjknLCAiY29weW51bWJlcl90YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL2l0aGkvbWFzdGVyX2NvcHludW1iZXJfZmlsZS50c3YnLCAidGFibGVfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9yZXZpZXcvdGFibGVzL3J1bjInLCAiaWNnY19zdWJ0eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvaWNnY19wcmltYXJ5X3R1bW91cl9zdWJ0eXBlcy50c3YnLCAicm9vbmV5X211dHNpZ2N2X2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9leHRlcm5hbC9vdGhlcl9wYXBlcnMvbW1jNi54bHN4JywgInR1bW91cl9wdXJpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL3R1bW91cl9wdXJpdHkudHN2JywgIm5lb2VkaXRpbmdfb3V0ZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9uZW9lZGl0aW5nL3J1bjYnLCAibG9nZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2NsdXN0dG1wL3BhcGVycmV2aWV3MicsICJpdGhfc3RhdF90eXBlcyIgPSBjKCdlbnRyb3B5JywgJ3Bvc3Rwcm9jZXNzZWRfZGl2ZXJnZW5jZScsICdjb21iaW5lZF9pdGhfbm9ybWFsaXplZCcsICdwcm9wb3J0aW9uX3N1YmNsb25hbCcpLCAidGNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL1RSQi9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAidGlsX2NsdXN0ZXJzX291dHB1dCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yL3RpbF9jbHVzdGVyc19vdXRwdXQudHh0JywgInJlbWl4dF9jZWxsdWxhcml0eV9wbG9pZHkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL3JlbWl4dF9jZWxsdWxhcml0eV9wbG9pZHkudHN2JywgIm5hbm9zdHJpbmdfYW5ub3RhdGlvbnMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vbmFub3N0cmluZy9wYW5jYW5jZXJfYW5ub3RhdGlvbnMudHN2JywgImRpc3RhbmNlX21ldGhvZCIgPSAnaG9ybicsICJtb2xzdWJ0eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvbW9sc3VidHlwZXMudHN2JywgIm1tY3RtX2ZpbmFsX3BhdGllbnRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1wYXRpZW50X3dpdGgtb3YnLCAiaXRoX2ljZ2NfYmMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2l0aF9pY2djX21lcmdlZF9iYy50c3YnLCAibmFub3N0cmluZ19kYXRhIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9uYW5vc3RyaW5nX3Jlc3VsdHMvaXRoX2Z1bGwvcWMvbGltbWFfcXVhbnRpbGUvbm9ybWFsaXplZF9leHByZXNzaW9uX3ZvYV9sYWJlbHNfZmlsdGVyZWQudHN2JywgInRpbGNsdXN0ZXJfc3VwZXJ2aXNlZF9pcHluYiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jldmlldy9pcHkvdGlsY2x1c3Rlcl9zdXBlcnZpc2VkbXVsdGljbGFzcy5pcHluYicsICJjbG9sYV9yZXN1bHRfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvY2xvbGEvcnVuNC9jbG9sYV9jb25kZW5zZWRfcmVzdWx0cy9iZXRhL2Nsb2xhX3Jlc3VsdHMudHN2JywgInRvdGFsX3RpbHR5cGVzIiA9IGMoJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JyksICJpdGhfc3RhdHMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2l0aF9zdGF0aXN0aWNzLnRzdicsICJpbWFnZV9zdW1tYXJ5MiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL2l0aGkveXVhbl9oZWNyX2ltYWdlX3Jlc3VsdHNfMi5jc3YnKSwKICAgIHJ1bGUgPSAnc3RhdGlzdGljYWxfZXJyYXRhX3Bvc3Rob2NfYW5hbHlzaXMnCikKIyMjIyMjIyMgT3JpZ2luYWwgc2NyaXB0ICMjIyMjIyMjIwoKICAgICAgICAgICAgICAgICAgICAgICAgYGBgCgoKIyMgU2V0dXAKCmBgYHtyIGdsb2JhbF9jaHVua19vcHRpb25zLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHRpZHk9VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRSkgI2NhY2hlPVRSVUUKYGBgCgpgYGB7cn0KbGlicmFyeShpdGhpLnV0aWxzKQpsb2FkX2Jhc2VfbGlicygpCgpsaWJyYXJ5KG1ldGhvZHMpCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ3JpZEJhc2UpCgpsaWJyYXJ5KGl0aGkubWV0YSkKbGlicmFyeShpdGhpLmZpZ3VyZXMpCmxpYnJhcnkoaXRoaS51dGlscykKbGlicmFyeShpdGhpLnNlcSkKbGlicmFyeShpdGhpLmNsb25lcykKbGlicmFyeShpdGhpLnN1cHApCmxpYnJhcnkoaXRoaS54Y3IpCmBgYAoKYGBge3J9CmloY190YWJsZV9wYXRoIDwtIHNuYWtlbWFrZUBpbnB1dCRpaGNfdGFibGUKeGNyX3RhYmxlX3BhdGggPC0gc25ha2VtYWtlQGlucHV0JHhjcl90YWJsZQpjbG9uZV90cmVlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX3RyZWVfZmlsZQpjbG9uZV9icmFuY2hfbGVuZ3RoX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZQpjbG9uZV9wcmV2YWxlbmNlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX3ByZXZhbGVuY2VfZmlsZQp0Y3JfZGl2ZXJzaXR5X2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JHRjcl9kaXZlcnNpdHkKYmNyX2RpdmVyc2l0eV9maWxlIDwtIHNuYWtlbWFrZUBpbnB1dCRiY3JfZGl2ZXJzaXR5Cm1vbGVjdWxhcl9zdWJ0eXBlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JG1vbHN1YnR5cGVzCmNsb25hbF9tZWFzdXJlc19maWxlIDwtIHNuYWtlbWFrZUBpbnB1dCRpdGhfc3RhdHNfZmlsZQptdXRzaWdfZGlyIDwtIHNuYWtlbWFrZUBpbnB1dCRtdXRzaWdfZGlyCml0aF9pY2djX2JjX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGl0aF9pY2djX2JjCm5hbm9zdHJpbmdfYW5ub3RhdGlvbnNfcGF0aCA8LSBzbmFrZW1ha2VAaW5wdXQkbmFub3N0cmluZ19hbm5vdGF0aW9ucwppY2djX3N1YnR5cGVfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkaWNnY19zdWJ0eXBlcwppY2djX3NwZWNpbWVuX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGljZ2Nfc3BlY2ltZW4KbWFzdGVyX3ZhcmlhbnRfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkc252X3RhYmxlCm1hc3Rlcl9icmVha3BvaW50X2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGJyZWFrcG9pbnRfdGFibGUKCmRiX3BhdGggPC0gc25ha2VtYWtlQHBhcmFtcyRkYgp0aWxzX2Zvcl9jbHVzdGVyIDwtIHNuYWtlbWFrZUBwYXJhbXMkdGlsc19mb3JfY2x1c3RlcgpzdGF0X3R5cGVzIDwtIHNuYWtlbWFrZUBwYXJhbXMkaXRoX3N0YXRfdHlwZXMKYGBgCgpgYGB7cn0KbmNsdXN0cyA8LSAzCgphbm5vdGF0aW9uX2NvbG91cnMgPC0gaXRoaS5maWd1cmVzOjpnZXRfYW5ub3RhdGlvbl9jb2xvdXJzKCkKCmloY190YWJsZSA8LSBmcmVhZChpaGNfdGFibGVfcGF0aCkKeGNyX3RhYmxlIDwtIHJlYWRfY2xvbm90eXBlcyh4Y3JfdGFibGVfcGF0aCwgZHVwbGljYXRlcyA9IEZBTFNFLCBkYl9wYXRoID0gZGJfcGF0aCkKbW9sc3VidHlwZXMgPC0gZnJlYWQobW9sZWN1bGFyX3N1YnR5cGVfZmlsZSkKCnRyZWVfYnJhbmNoX2RhdGEgPC0gcmVhZF9jbG9uZV90cmVlX2RhdGEoY2xvbmVfdHJlZV9maWxlLCBjbG9uZV9icmFuY2hfbGVuZ3RoX2ZpbGUsIGNsb25lX3ByZXZhbGVuY2VfZmlsZSwgZGJfcGF0aCkKCnhjcl9kaXZlcnNpdHkgPC0gaXRoaS5zdXBwOjpnZXRfeGNyX2RpdmVyc2l0eSh0Y3JfZGl2ZXJzaXR5X2ZpbGUsIGJjcl9kaXZlcnNpdHlfZmlsZSwgZGJfcGF0aCwgeGNyX3RhYmxlKQoKY2xvbmFsX21lYXN1cmVzIDwtIGl0aGkuY2xvbmVzOjpyZWFkX2l0aF9zdGF0cyhjbG9uYWxfbWVhc3VyZXNfZmlsZSwgZGJfcGF0aCwgZHVwbGljYXRlcyA9IEZBTFNFKQoKaXRoX2ljZ2NfYmMgPC0gZnJlYWQoaXRoX2ljZ2NfYmNfZmlsZSkKaWNnY19zcGVjaW1lbl9kYXRhIDwtIGZyZWFkKGljZ2Nfc3BlY2ltZW5fZmlsZSkKCm5hbm9zdHJpbmdfbGFiZWxzIDwtIGZyZWFkKG5hbm9zdHJpbmdfYW5ub3RhdGlvbnNfcGF0aCkKCnRpbF9jbHVzdGVycyA8LSBpdGhpLmZpZ3VyZXM6OjpnZXRfdGlsX2NsdXN0ZXJzKGloY190YWJsZSwgbW9sc3VidHlwZXMsIHRpbHNfZm9yX2NsdXN0ZXIgPSB0aWxzX2Zvcl9jbHVzdGVyLCBuY2x1c3RzID0gMykKCm1hc3Rlcl92YXJpYW50X3RhYmxlIDwtIHJlYWRfdmFyaWFudF9maWxlKG1hc3Rlcl92YXJpYW50X2ZpbGUsIGRiX3BhdGgpCm1hc3Rlcl9icmVha3BvaW50X3RhYmxlIDwtIHJlYWRfdmFyaWFudF9maWxlKG1hc3Rlcl9icmVha3BvaW50X2ZpbGUsIGRiX3BhdGgpCgpzaWdfcmVzdWx0cyA8LSBwcm9kdWNlX3NpZ25hdHVyZV9yZXN1bHRzKG11dHNpZ19kaXIsIG1hc3Rlcl92YXJpYW50X3RhYmxlLCBtYXN0ZXJfYnJlYWtwb2ludF90YWJsZSwgZGJfcGF0aCkKc2lnX3Jlc3VsdHNfc252IDwtIHNpZ19yZXN1bHRzJHNudgpzaWdfcmVzdWx0c19zdiA8LSBzaWdfcmVzdWx0cyRzdgpgYGAKCiMjIEFuYWx5c2lzCgpSZXZpZXdlciAzIGhhcyBzZXZlcmFsIGNvbW1lbnRzIGFib3V0IHN0YXRpc3RpY2FsIHRlc3RzIG1hZGUgaW4gdGhlIG1hbnVzY3JpcHQuIFRoZXNlIGFyZSBhbGwgdmFsaWQgKyBlYXN5IHRvIGFkZHJlc3MgLS0gc29tZSBhcmUgbWlzdGFrZXMvdHlwb3Mgb24gbXkgcGFydCwgb3RoZXJzIGFyZSB0aGluZ3Mgd2UgY291bGQvc2hvdWxkIGhhdmUgZG9uZSwgZXRjLiAKCiMjIyBGaWcgUzRCCgpGaXhlZCB0byBvbmx5IHNob3cgcGF0aWVudHMgd2l0aCBzYW1wbGVzIGluIGJvdGggZ3JvdXBzLiAKCmBgYHtyfQpjb3JfdGlsc3VidHlwZV9jbG9uYWxfcmVzIDwtIHN1cHBfY29yX3RpbHN1YnR5cGVfY2xvbmFsKGloY190YWJsZSwgdHJlZV9icmFuY2hfZGF0YSwgdGlsc19mb3JfY2x1c3RlciwgbmNsdXN0cywgbW9sc3VidHlwZXMsIGRiX3BhdGgpCmBgYAoKCmBgYHtyfQpncmlkLm5ld3BhZ2UoKQpncmlkLmRyYXcoY29yX3RpbHN1YnR5cGVfY2xvbmFsX3JlcyRwbG90cyR0aWxjbHVzdF9jbG9uYWxzaW0pCmBgYAoKVGhlcmUsIG5vIG1vcmUgJ29ycGhhbmVkJyBwb2ludHMuIAoKIyMjIFBlcm11dGF0aW9uIHRlc3QKCioqUTogV2hhdCBhbmFseXNpcyB3YXMgcGVyZm9ybWVkIGluIHRoZSBzZW50ZW5jZSAiKHAgPiAwLjMsIHBlcm11dGF0aW9uIHRlc3QsIEZpZ3VyZSBTNEIpIiBvbiBwYWdlIDYsIHdoaWNoIHBlcm11dGF0aW9uIHRlc3Q/IEZpZ3VyZSBTNEIgaXMgbm90IGEgcGVybXV0YXRpb24gdGVzdC4qKgoKVGhpcyB3YXMgYWN0dWFsbHkgYSBuZXN0ZWQgcmFua3MgdGVzdC4gSXQgaXMgaW5jb3JyZWN0bHkgbm90ZWQgYXMgYSBXaWxjb3hvbiBzaWduZWQtcmFuayB3aXRoaW4gdGhlIGZpZ3VyZSBsZWdlbmQgLS0gdGhpcyBuZWVkcyB0byBiZSBmaXhlZC4gCgpJIGNhbiBzZWUgd2h5IHRoaXMgd291bGQgYmUgY29uZnVzZWQgZm9yIGEgTVcgdGVzdCwgdGhvdWdoLiBXaGF0IGlzbid0IGNsZWFybHkgbm90ZWQgaGVyZSBpcyB0aGF0IEkgcGxvdCB0aGUgTUVBTlMgZm9yIGVhY2ggcGF0aWVudC4gSW4gZmFjdCwgYWxsIHBhaXJ3aXNlIGNvbXBhcmlzb25zIGluIGVhY2ggcGF0aWVudCBhcmUgYmVpbmcgY29tcGFyZWQsIG5vdCBqdXN0IHRoZSBtZWFuIGJ5IGNsdXN0ZXIgZXF1YWxpdHkuIAoKVGhlIHJlYXNvbiB3aHkgYSBXaWxjb3hvbiBzaWduZWQtcmFuayBpcyBiZWNhdXNlLCB0byBtYWtlIHRoYXQgdHlwZSBvZiBjb21wYXJpc29uLCBwYXRpZW50IG5lZWRzIHRvIGJlIGFjY291bnRlZCBmb3IgYXMgYSByYW5kb20gZWZmZWN0LiBUaGUgbmVzdGVkIHJhbmtzIHRlc3QgaXMgb25lIHBvc3NpYmxlIGV4dGVuc2lvbiBvZiBhIE1XL1dpbGNveG9uLXR5cGUgdGVzdCB0aGF0IHVzZXMgYm9vdHN0cmFwcGluZyB0byBjb21wdXRlIHAtdmFsdWVzLiBTZWUgdGhlIFIgcGFja2FnZSBuZXN0ZWRSYW5rc1Rlc3QuIAoKIyMjIFR1bW91ciBwdXJpdHkgdnMuIElUSAoKKipROiBJbiBmaWd1cmUgUzRBLCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiAicHJvcG9ydGlvbiBzdWItY2xvbmFsIiBhbmQgImNlbGx1bGFyaXR5IiBpcyBzaWduaWZpY2FudCAocD0wLjAxNjkpLCB5ZXQgaW4gdGhlIG1hbnVzY3JpcHQgdGhlIGF1dGhvcnMgc2F5OiAiYW5kIG5vbmUgb2YgdGhlIGNsb25hbCBtZWFzdXJlcyB3ZXJlIGNvbmZvdW5kZWQgYnkgdHVtb3IgcHVyaXR5IChhbGwgcCA+IDAuMiwgRmlndXJlIFM0QSkiLiBQYWdlIDYuKioKClRoaXMgaXMgYSB3b3JkaW5nIGlzc3VlLiBUZWNobmljYWxseSB3ZSdyZSByaWdodCwgYnV0IHdlIHNob3VsZCBtYWtlIGl0IG1vcmUgb2J2aW91cyBieSBsaXN0aW5nIG91dCB0aGUgQ0xPTkFMIG1lYXN1cmVzLCBpLmUuIG5vdCBpbmNsdWRpbmcgcHJvcG9ydGlvbiBzdWJjbG9uYWwgQ04uIFRoaXMgaXMgYSB2YWxpZCBwb2ludCB0aG91Z2ggLS0gd2Ugd2FudCB0byBhdm9pZCB1c2luZyBhbWJpZ3VvdXMgd29yZGluZyB3aGVyZXZlciBwb3NzaWJsZSAtLSBub3Qgd29ydGggc2F2aW5nIGEgZmV3IGNoYXJhY3RlcnMgdG8gbWFrZSB0aGluZ3MgbW9yZSBjb25mdXNpbmcuIAoKIyMjIEZpZ3VyZSAxQwoKKipROiBGaWd1cmUgMUMgZG9lcyBub3Qgc2F5IHdoaWNoIHN0YXRpc3RpY2FsIHRlc3Qgd2FzIHVzZWQsIGFuZCBpZiBhIEtydXNrYWwtV2FsbGlzIHdhcyB1c2VkLCBhIHBvc3QgaG9jIGFuYWx5c2lzIHNob3VsZCBiZSBlbXBsb3llZC4qKgoKUG9pbnQgdGFrZW4uIFdlJ2xsIGRvIHNvbWUgcG9zdC1ob2MgdGVzdHMgdG8gY29tcGFyZSBwYWlyd2lzZSBzaWduaWZpY2FuY2UgYmV0d2VlbiBncm91cHMuICAKClNpbmNlIHRoaXMgaXMgYSBLcnVza2FsLVdhbGxpcywgdGhlIG1vc3QgYXBwcm9wcmlhdGUgcG9zdC1ob2MgdGVzdCB0byB1c2UgaXMgdGhlIER1bm4gdGVzdC4KCk1heSBhbHNvIGJlIGEgZ29vZCBpZGVhIHRvIGFubm90YXRlIG9uIHRoZSBwbG90IGl0c2VsZi4gCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9Cm5vbmFscGhhX2NsdXN0ZXJfY29sb3VycyA8LSBzdHJpbmdyOjpzdHJfZXh0cmFjdChhbm5vdGF0aW9uX2NvbG91cnMkdGlsX2NsdXN0ZXJfY29sb3VycywgIiNbMC05QS1aXXs2fSIpCml0aF9ib3hwbG90cyA8LSBpdGhpLmZpZ3VyZXM6OjpwbG90X2l0aF9ib3hwbG90cyhjbG9uYWxfbWVhc3VyZXMsIHN0YXRfdHlwZXMsIHRpbF9jbHVzdGVycywgbm9uYWxwaGFfY2x1c3Rlcl9jb2xvdXJzLCBmb3JjZV9mb250ID0gRkFMU0UsIHNjYWxlX2ZhY3RvciA9IDcvMTgsIG9yaWVudGF0aW9uID0gIndpZGUiLCBwb3N0X2hvYyA9IFRSVUUpCmBgYAoKYGBge3J9CmdyaWQubmV3cGFnZSgpCmdyaWQuZHJhdyhpdGhfYm94cGxvdHMpCmBgYAoKVE9ETzogQWRkIGEgbGVnZW5kIGZvciB0aGUgYXN0ZXJpc2tzLiBUd28gYXN0ZXJpc2tzIGNvcnJlc3BvbmRzIHRvIDAuMDUsIG9uZSB0byAwLjEsIGFuZCAzIHRvIDAuMDAxLiAKCkFzIHBlciB0aGUgcmVzdWx0cyBhYm92ZSwgYWxsIG1lYXN1cmVzIGV4Y2VwdCBjbG9uZSBkaXZlcmdlbmNlIHNob3cgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gYWxsIG90aGVyIGNsYXNzZXMgYW5kIEVTLVRJTC4gCgojIyMgRmlndXJlIDZCCgoqKlE6IFN0YXRpc3RpY2FsIGFuYWx5c2lzIG9mIDZCIHNob3VsZCBpbmNsdWRlIHBvc3QgaG9jIHRlc3QuKioKClRoaXMgaXMgZ29pbmcgdG8gYmUgcmVtb3ZlZCBmcm9tIHRoZSB0ZXh0IChiZWNhdXNlIHRoZSBlbnRpcmUgbXV0YXRpb24gc2lnbmF0dXJlcyBzZWN0aW9uIGlzIGdvaW5nIHRvIGdvIHBvb2YpLCBidXQgbGV0J3MgZG8gaXQgYW55d2F5cyBmb3IgaW50ZXJlc3QgKGFuZCBiZWNhdXNlIEkgbmVlZCB0aGlzIGZvciBhIHNsaWRlKS4gCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CmxhYmVsX2ZpbGUgPC0gU3lzLmdsb2IoZmlsZS5wYXRoKG11dHNpZ19kaXIsICJvdXRwdXQiLCAiKl9sYWJlbHMudHN2IikpCmxhYmVscyA8LSBkYXRhLnRhYmxlOjpmcmVhZChsYWJlbF9maWxlKQpsYWJlbHMgPC0gc3Vic2V0KGxhYmVscywgc2VsZWN0PWMobGlicmFyeSwgcHJvamVjdCwgaGlzdG90eXBlKSkKbGFiZWxzJGxpYnJhcnkgPC0gc3RyaW5ncjo6c3RyX3JlcGxhY2UobGFiZWxzJGxpYnJhcnksICJecGF0aWVudF8iLCAiIikKbGFiZWxzIDwtIGxhYmVscyAlPiUgcGx5cjo6cmVuYW1lKGMoImxpYnJhcnkiPSJwYXRpZW50X2lkIikpCgpzaWduYXR1cmVfbGFiZWxzIDwtIHN0cmluZ3I6OnN0cl9leHRyYWN0KGMoY29sbmFtZXMoc2lnX3Jlc3VsdHNfc252KSwgY29sbmFtZXMoc2lnX3Jlc3VsdHNfc3YpKSwgIlNOP1YtWzAtOV0rIikKc2lnbmF0dXJlX2xhYmVscyA8LSBzaWduYXR1cmVfbGFiZWxzWyFpcy5uYShzaWduYXR1cmVfbGFiZWxzKV0KCnNpZ2hlYXRfcGF0aWVudF9yZXMgPC0gIGl0aGkuc3VwcDo6OmdldF9mb3JtYWxfY2x1c3RlcnMoc2lnX3Jlc3VsdHMsIGxhYmVscywgc2lnbmF0dXJlX2xhYmVscywgYW5ub3RhdGlvbl9jb2xvdXJzKQoKY29sX2NsdXN0IDwtIHNpZ2hlYXRfcGF0aWVudF9yZXMkaGMKc2FtcGxlX29yZGVyIDwtIGNvbF9jbHVzdCRsYWJlbHNbY29sX2NsdXN0JG9yZGVyXQpjbHVzdGVycyA8LSBjdXRyZWUoY29sX2NsdXN0LCAzKQpnZW5lcmFsX2xhYmVscyA8LSBhcy5kYXRhLmZyYW1lKGNsdXN0ZXJzKSAlPiUgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4odmFyID0gInBhdGllbnRfaWQiKSAlPiUgcGx5cjo6cmVuYW1lKGMoImNsdXN0ZXJzIj0iY2x1c3RlciIpKQpnZW5lcmFsX2xhYmVscyRjbHVzdGVyIDwtIGFzLmNoYXJhY3RlcihnZW5lcmFsX2xhYmVscyRjbHVzdGVyKQoKbWVzc2FnZSgiUGxvdHRpbmcgYm94cGxvdHMgLi4uIikKbm9uYWxwaGFfY2x1c3Rlcl9jb2xvdXJzIDwtIHN0cmluZ3I6OnN0cl9leHRyYWN0KGFubm90YXRpb25fY29sb3VycyRtdXRzaWdfY2x1c3RlcnMsICIjWzAtOUEtWl17Nn0iKQoKIyBUZWNobmljYWxseSBpY2djX3N1YnR5cGVzIGhhc24ndCBiZWVuIGFzc2lnbmVkLCBidXQgd2UgZG9uJ3QgdXNlIGl0IGFueW1vcmUgc28gdy9lCmltbXVuZV9ib3hwbG90X2ZpZyA8LSBpdGhpLmZpZ3VyZXM6OjpwbG90X2ltbXVuZV9ib3hwbG90KGl0aF9pY2djX2JjLCBsZXZlbCA9ICJwYXRpZW50IiwgbmFub3N0cmluZ19sYWJlbHMsIGdlbmVyYWxfbGFiZWxzLCBtb2xzdWJ0eXBlcywgaWNnY19zcGVjaW1lbl9kYXRhLCBhbm5vdGF0aW9uX2NvbG91cnMsIHNhbXBsZV9vcmRlciwgZGJfcGF0aCwgaWNnY19zdWJ0eXBlcywgbm9uYWxwaGFfY2x1c3Rlcl9jb2xvdXJzLCBmb3JjZV9mb250ID0gRkFMU0UsIHBvc3RfaG9jID0gVFJVRSkKYGBgCgpgYGB7cn0KZ3JpZC5uZXdwYWdlKCkKZ3JpZC5kcmF3KGltbXVuZV9ib3hwbG90X2ZpZykKYGBgCgpUT0RPOiBNb2RpZnkgdGV4dCB0byBhY2tub3dsZWRnZSB0aGF0IHRoZXJlIGlzIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiBILUhSRCBhbmQgSC1GQkktMiBpbiBTT01FIGltbXVuZSBwYXRod2F5cy4gT3IgYWx0ZXJuYXRpdmVseSBqdXN0IGJlIG1vcmUgc3BlY2lmaWMgaW4gc2F5aW5nIHRoYXQgdGhlcmUgaXNuJ3Qgc2lnbmlmaWNhbmNlIGluIHRoZSBvdGhlciBjYXRlZ29yaWVzIChpbnN0ZWFkIG9mIHNheWluZyB0aGF0IHRoZXkncmUgc2ltaWxhciBvdmVyYWxsKS4=