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 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=