library(ithi.utils)
load_base_libs()

library(ithi.meta)
library(ithi.xcr)
library(ithi.clones)

Colour palettes

pal_patient <- select_palette("patient")

Parameters

db_path <- snakemake@params$db

xcr_table_path <- snakemake@input$xcr_table
prevalence_option <- snakemake@params$prevalence_option
distance_method <- snakemake@params$xcr_distance_method

clone_tree_file <- snakemake@input$clone_tree_file
clone_prevalence_file <- snakemake@input$clone_prevalence_file
clone_branch_length_file <- snakemake@input$clone_branch_length_file

Metadata

db <- src_sqlite(db_path, create = FALSE)

duplicates <- collect(tbl(db, "duplicates"))

Analysis

XCR repertoire similarity

xcr_table <- read_clonotypes(xcr_table_path, duplicates = FALSE, db_path, verbose = 1)

Read 19.7% of 304822 rows
Read 59.1% of 304822 rows
Read 91.9% of 304822 rows
Read 304822 rows and 18 (of 18) columns from 0.070 GB file in 00:00:05
tcr_segment_type <- "TRB"
bcr_segment_type <- "IGH"

id_type <- "condensed_id"
patients <- unique(xcr_table$patient_id)

dists <- lapply(patients, function(patient) {
    tcr_clonotypes <- subset(xcr_table, type == tcr_segment_type & patient_id == 
        patient)
    bcr_clonotypes <- subset(xcr_table, type == bcr_segment_type & patient_id == 
        patient)
    tcr_cross_table <- cross_tabulate(tcr_clonotypes, id_type = id_type)
    bcr_cross_table <- cross_tabulate(bcr_clonotypes, id_type = id_type)
    
    cross_tables <- list(tcr = tcr_cross_table, bcr = bcr_cross_table)
    
    distance_matrices <- lapply(cross_tables, function(cross_table) {
        distmat <- compute_immune_distance_matrix(cross_table, method = distance_method)
        mat <- as.matrix(distmat)
        return(mat)
    })
    return(distance_matrices)
})
tcr_dists <- lapply(dists, function(x) x$tcr)
bcr_dists <- lapply(dists, function(x) x$bcr)

xcr_dists <- tibble(patient_id = patients, tcr = tcr_dists, bcr = bcr_dists)
xcr_dists$patient_id <- factor(xcr_dists$patient_id)
xcr_dists <- xcr_dists[order(xcr_dists$patient_id), ]

The distance metric being used is horn.

Tumour clones

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

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

## Need non-normalized distances
clone_dists <- clone_distances(ccfs_labeled, normalize = FALSE, id_type = "condensed_id")

Combination

clone_dists$patient_id <- factor(clone_dists$patient_id)

total_dists <- inner_join(clone_dists, xcr_dists)
compute_overlap_similarities <- function(vals) {
    common_samples <- lapply(vals, function(x) {
        colnames(x)
    })
    common_samples <- Reduce(intersect, common_samples)
    
    sim_dfs <- lapply(names(vals), function(category) {
        mat <- vals[[category]]
        mat <- mat[common_samples, common_samples]
        
        res <- setNames(melt(as.matrix(mat)), c("sample1", "sample2", category))
        return(res)
    })
    similarities <- Reduce(merge, sim_dfs)
    result <- subset(similarities, as.numeric(sample1) < as.numeric(sample2))
    return(result)
}
pairwise_similarities <- rbind.fill(lapply(1:nrow(total_dists), function(i) {
    clone_distmat <- total_dists[i, ]$dist_clones_weighted[[1]]
    tcr_distmat <- total_dists[i, ]$tcr[[1]]
    bcr_distmat <- total_dists[i, ]$bcr[[1]]
    
    inputs <- list(clone_distmat, tcr_distmat, bcr_distmat)
    names(inputs) <- c("clones", "tcr", "bcr")
    
    patient_id <- total_dists[i, ]$patient_id
    
    pairwise_sims <- cbind(patient_id = patient_id, compute_overlap_similarities(inputs))
    return(pairwise_sims)
}))
pairwise_similarities$patient_id <- factor(pairwise_similarities$patient_id)

patient_counts <- pairwise_similarities %>% group_by(patient_id) %>% summarise(n = n())
singletons <- subset(patient_counts, n == 1)$patient_id
pairwise_similarities <- subset(pairwise_similarities, !patient_id %in% singletons)

TCR-clones

stats <- setNames(ddply(pairwise_similarities, .(patient_id), function(x) {
    res <- with(x, cor.test(clones, tcr, method = "pearson"))
    pvalue <- res$p.value
    eq <- substitute(italic(P) == p, list(p = format(pvalue, digits = 3)))
    return(as.character(as.expression(eq)))
}), c("patient_id", "p.value"))

summary(lmer(tcr ~ clones + (1 | patient_id), data = pairwise_similarities))
Linear mixed model fit by REML t-tests use Satterthwaite approximations
  to degrees of freedom [lmerMod]
Formula: tcr ~ clones + (1 | patient_id)
   Data: pairwise_similarities

REML criterion at convergence: -66.5

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.2035 -0.3406  0.1428  0.4982  1.7980 

Random effects:
 Groups     Name        Variance Std.Dev.
 patient_id (Intercept) 0.03909  0.1977  
 Residual               0.01950  0.1396  
Number of obs: 116, groups:  patient_id, 13

Fixed effects:
             Estimate Std. Error        df t value Pr(>|t|)    
(Intercept) 7.045e-01  5.957e-02 1.417e+01   11.83 9.86e-09 ***
clones      2.708e-05  7.941e-06 1.136e+02    3.41 0.000901 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
       (Intr)
clones -0.313
fit warnings:
Some predictor variables are on very different scales: consider rescaling
ggplot(pairwise_similarities, aes(x = clones, y = tcr)) + geom_point(aes(colour = patient_id)) + 
    theme_bw() + theme_Publication() + scale_color_manual(values = pal_patient) + 
    xlab("Clone distance") + ylab("TCR distance") + facet_wrap(~patient_id, 
    scales = "free") + geom_text(data = stats, aes(x = Inf, y = Inf, label = p.value), 
    hjust = 1.1, vjust = 1.5, size = 3, parse = TRUE)

BCR-clones

stats <- setNames(ddply(pairwise_similarities, .(patient_id), function(x) {
    res <- with(x, cor.test(clones, bcr, method = "pearson"))
    pvalue <- res$p.value
    eq <- substitute(italic(P) == p, list(p = format(pvalue, digits = 3)))
    return(as.character(as.expression(eq)))
}), c("patient_id", "p.value"))

summary(lmer(bcr ~ clones + (1 | patient_id), data = pairwise_similarities))
Linear mixed model fit by REML t-tests use Satterthwaite approximations
  to degrees of freedom [lmerMod]
Formula: bcr ~ clones + (1 | patient_id)
   Data: pairwise_similarities

REML criterion at convergence: -88.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-5.2307 -0.3481  0.1803  0.4483  1.6530 

Random effects:
 Groups     Name        Variance Std.Dev.
 patient_id (Intercept) 0.01768  0.1330  
 Residual               0.01720  0.1312  
Number of obs: 116, groups:  patient_id, 13

Fixed effects:
             Estimate Std. Error        df t value Pr(>|t|)    
(Intercept) 7.949e-01  4.254e-02 1.532e+01  18.688 5.86e-12 ***
clones      2.192e-05  7.205e-06 1.121e+02   3.043  0.00292 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
       (Intr)
clones -0.394
fit warnings:
Some predictor variables are on very different scales: consider rescaling
ggplot(pairwise_similarities, aes(x = clones, y = bcr)) + geom_point(aes(colour = patient_id)) + 
    theme_bw() + theme_Publication() + scale_color_manual(values = pal_patient) + 
    xlab("Clone distance") + ylab("BCR distance") + facet_wrap(~patient_id, 
    scales = "free") + geom_text(data = stats, aes(x = Inf, y = Inf, label = p.value), 
    hjust = 1.1, vjust = 1.5, size = 3, parse = TRUE)

TCR-clone correlations are good for most patients, while BCR-clone correlations are poor for most patients. Patient 1 has good correlations for both – not exactly surprising as patient 1 is very immunoreactive (highest out of the ITH2 cohort). Patient 4 is a clear opposite to this trend. Is it possible that patient 4 harbors a B-cell driven response, rather than a T-cell driven one?

Do we have corroborating evidence for this?

Supports:

  • Patient 4 has the highest intrapatient BCR similarity across the entire cohort (immune responses highly similar from site-to-site could imply that there’s a widespread antigen, and tends to be associated with higher CD20+ TIL)
  • Patient 4 has relatively high CD20+ TIL density (see the Immune Variability page) – tied for 3rd/21

Does not support:

  • Patient 3 also has high CD20+ TIL density (tied for 3rd/21), but does not exhibit this pattern
LS0tCnRpdGxlOiAiWENScyBhbmQgdHVtb3VyIGNsb25lcyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDUKICAgIHRvY19mbG9hdDogdHJ1ZQpwYXJhbXM6CiAgcm1kOiAieGNyX2Nsb25lc19hbmFseXNpcy5SbWQiCi0tLQogICAgICAgICAgICAgICAgICAgICAgICBgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMjIyMjIyMjIFNuYWtlbWFrZSBoZWFkZXIgIyMjIyMjIyMKbGlicmFyeShtZXRob2RzKQpTbmFrZW1ha2UgPC0gc2V0Q2xhc3MoCiAgICAiU25ha2VtYWtlIiwKICAgIHNsb3RzID0gYygKICAgICAgICBpbnB1dCA9ICJsaXN0IiwKICAgICAgICBvdXRwdXQgPSAibGlzdCIsCiAgICAgICAgcGFyYW1zID0gImxpc3QiLAogICAgICAgIHdpbGRjYXJkcyA9ICJsaXN0IiwKICAgICAgICB0aHJlYWRzID0gIm51bWVyaWMiLAogICAgICAgIGxvZyA9ICJsaXN0IiwKICAgICAgICByZXNvdXJjZXMgPSAibGlzdCIsCiAgICAgICAgY29uZmlnID0gImxpc3QiLAogICAgICAgIHJ1bGUgPSAiY2hhcmFjdGVyIgogICAgKQopCnNuYWtlbWFrZSA8LSBTbmFrZW1ha2UoCiAgICBpbnB1dCA9IGxpc3QoJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9hbmFseXNpcy9SbWQvX3NpdGUueW1sJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9jbG9uZV9kYXRhLnRzdicsICdSbWQveGNyX2Nsb25lc19hbmFseXNpcy5SbWQnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL2JyYW5jaF9kYXRhLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi94Y3JfdGFibGUudHN2JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy90cmVlX2RhdGEudHN2JywgInNpdGVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL2FuYWx5c2lzL1JtZC9fc2l0ZS55bWwnLCAiY2xvbmVfcHJldmFsZW5jZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvY2xvbmVfZGF0YS50c3YnLCAibm90ZWJvb2siID0gJ1JtZC94Y3JfY2xvbmVzX2FuYWx5c2lzLlJtZCcsICJjbG9uZV9icmFuY2hfbGVuZ3RoX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9icmFuY2hfZGF0YS50c3YnLCAieGNyX3RhYmxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi94Y3JfdGFibGUudHN2JywgImNsb25lX3RyZWVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3RyZWVfZGF0YS50c3YnKSwKICAgIG91dHB1dCA9IGxpc3QoJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3dlYi94Y3JfY2xvbmVzX2FuYWx5c2lzLm5iLmh0bWwnKSwKICAgIHBhcmFtcyA9IGxpc3QoJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJywgJ2Nsb25lcycsICdob3JuJywgJ2l0aGktYW5hbHlzaXMteGNyLXRyYWNraW5nJywgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJwcmV2YWxlbmNlX29wdGlvbiIgPSAnY2xvbmVzJywgInhjcl9kaXN0YW5jZV9tZXRob2QiID0gJ2hvcm4nLCAibmFtZSIgPSAnaXRoaS1hbmFseXNpcy14Y3ItdHJhY2tpbmcnKSwKICAgIHdpbGRjYXJkcyA9IGxpc3QoKSwKICAgIHRocmVhZHMgPSAxLAogICAgbG9nID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9jbHVzdHRtcC9wYXBlcmFuYWx5c2lzMi94Y3JfdHJhY2tpbmcubG9nJyksCiAgICByZXNvdXJjZXMgPSBsaXN0KCksCiAgICBjb25maWcgPSBsaXN0KCJpY2djX3NwZWNpbWVuX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL3NwZWNpbWVuLnRzdicsICJ2YXJpYWJpbGl0eV90eXBlIiA9ICdzdGFiaWxpemUnLCAiaW1tdHlwZXJfbGVuZ3RocyIgPSAnMTEgMTIgMTMgMTQgMTUgMTYgMTcgMTgnLCAiZHJpdmVyX21hcCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3N1YnByb2plY3RzL2RyaXZlcnMvZGF0YS9nZW5lX2xpc3RfbWFwcGVkLmJlZCcsICJtdWx0aXZpZXdjbHVzdGVyaW5nX25vdGVib29rIiA9ICdSbWQvbXVsdGl2aWV3Y2x1c3RlcmluZy5SbWQnLCAieGNyX2Rpc3RhbmNlX21ldGhvZCIgPSAnaG9ybicsICJtbWN0bV9zYW1wbGVfYWRfc2lncGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktYW5jZXN0cnktc2FtcGxlL3Bsb3RzL2l0aC1ieS1hbmNlc3RyYWwtc2FtcGxlX3Nudi1zdl9zaWdzX211bHRpcGFuZWwucGRmJywgIm1tY3RtX2FuY2VzdHJhbF9kZXNjZW5kYW50X3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LWFuY2VzdHJ5LXNhbXBsZS9vdXRwdXQnLCAidGlsc19mb3JfY2x1c3RlciIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAiYmNycGh5bG9fdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgInNtb290aF90eXBlIiA9ICdsb2VzcycsICJ4Y3JtYXBzY2FwZV9maWxlcyIgPSBjKCcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIveGNybWFwc2NhcGUvMS5zdmcnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yL3hjcm1hcHNjYXBlLzIuc3ZnJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL2ludGVybWVkaWF0ZXMvcnVuMi94Y3JtYXBzY2FwZS8zLnN2ZycsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIveGNybWFwc2NhcGUvNC5zdmcnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yL3hjcm1hcHNjYXBlLzcuc3ZnJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL2ludGVybWVkaWF0ZXMvcnVuMi94Y3JtYXBzY2FwZS85LnN2ZycsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIveGNybWFwc2NhcGUvMTAuc3ZnJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL2ludGVybWVkaWF0ZXMvcnVuMi94Y3JtYXBzY2FwZS8xMS5zdmcnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yL3hjcm1hcHNjYXBlLzEyLnN2ZycsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIveGNybWFwc2NhcGUvMTMuc3ZnJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL2ludGVybWVkaWF0ZXMvcnVuMi94Y3JtYXBzY2FwZS8xNC5zdmcnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yL3hjcm1hcHNjYXBlLzE1LnN2ZycsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIveGNybWFwc2NhcGUvMTYuc3ZnJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL2ludGVybWVkaWF0ZXMvcnVuMi94Y3JtYXBzY2FwZS8xNy5zdmcnKSwgIml0aF9wcm9qZWN0X3Jlc3VsdHMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvaXRoMy9kYXRhL3Jlc3VsdHMnLCAiaWhjX3J1bjIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2loYy9jZDc5Y2QxMzhjZDY4L3ZhbGlkYXRlZF9zdGF0c193ZWlnaHRlZC5yZGF0YScsICJuYW5vc3RyaW5nX2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL25hbm9zdHJpbmcvcGFuY2FuY2VyX2Fubm90YXRpb25zLnRzdicsICJpY2djX2NsaW5pY2FsIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9kb25vci5PVi1BVS50c3YnLCAiY2xvbmFsX2ZpZ3VyZV90ZW1wbGF0ZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL2FuYWx5c2lzL3RlbXBsYXRlcy9jbG9uYWxfZmlndXJlLnN2ZycsICJuYW5vc3RyaW5nX3NpZ25hdHVyZV9ub3RlYm9vayIgPSAnUm1kL25hbm9zdHJpbmdfc2lnbmF0dXJlcy5SbWQnLCAiUE5HX0RFTlNJVFkiID0gMzAwLCAidGNnYV9jbGluaWNhbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0Evc3luYXBzZV9jbGluQWxsX2RhdGEudHN2JywgImNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaXRoL2NvbXBsZXRlL2JyYW5jaF9kYXRhLnRzdicsICJ0Y3JfZGl2ZXJzaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvVFJCL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICJtbWN0bV9maW5hbF9wYXRpZW50X3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnRfd2l0aC1vdi9wbG90cy9pdGgtYnktcGF0aWVudF9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJtdXRhdGlvbl9zaWduYXR1cmVfbm90ZWJvb2siID0gJ1JtZC9tdXRhdGlvbl9zaWduYXR1cmVzLlJtZCcsICJuY2x1c3RzIiA9IDMsICJtbWN0bV9wYXRpZW50X2FuY2VzdHJhbF9kZXNjZW5kYW50X3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnQtYW5jZXN0cnkvb3V0cHV0JywgIm1hc3Rlcl9icmVha3BvaW50X2ZpbGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9icmVha3BvaW50cy50c3YnLCAiaXRoX3RpbF9ub3RlYm9vayIgPSAnUm1kL2l0aF90aWxfZGVuc2l0aWVzLlJtZCcsICJtbWN0bV9zYW1wbGVfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktc2FtcGxlL291dHB1dCcsICJtbWN0bV9maW5hbF9wYXRpZW50X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudF93aXRoLW92JywgInZfZGljdGlvbmFyeSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3N1YnByb2plY3RzL2ltbXR5cGVyL21ldGFkYXRhL2ltZ3QvSG9tb19zYXBpZW5zX1RSQlYuZmFzdGEnLCAiY2xvbmFsX3NhbXBsZXJzIiA9IGMoJ0hNQycsICdOVVRTJyksICJwaGVub3R5cGVfdGhyZXNob2xkIiA9IDAuODUsICJ0Y2dhX2V4cHJfbWF0cml4IiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvVENHQS9leHByX21hdHJpeF9ub3JtYWxpemVfc3RhbmRhcmRpemVfbm9kdXBsaWNhdGVzLnRzdicsICJtbWN0bV9vdl9jb21iaW5lZF9zaWdwbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2NvbWJpbmVkX292X21tY3RtL3Bsb3RzL292X3Nudi1zdl9zaWdzX211bHRpcGFuZWwucGRmJywgImxvZ2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9jbHVzdHRtcC9wYXBlcmFuYWx5c2lzMicsICJ4Y3JfY2xvbmVzX25vdGVib29rIiA9ICdSbWQveGNyX2Nsb25lc19hbmFseXNpcy5SbWQnLCAiY2xvbmVfcHJldmFsZW5jZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvY2xvbmVfZGF0YS50c3YnLCAibXZjbHVzdF9uY2x1c3QiID0gMywgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJzcGF0aWFsX3Jlc3VsdF9kaXJzIiA9IGxpc3QoImVwaXRoZWxpYWwiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL3NwYXRzaW0vaXRoMy9hYmMnLCAic3Ryb21hbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvc3BhdHNpbS9pdGg1L2FiYycpLCAidGlsc19mb3JfdmFyaWFiaWxpdHkiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknKSwgIm5hbm9zdHJpbmdfZGF0YSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbmFub3N0cmluZ19yZXN1bHRzL2l0aF9mdWxsL3FjL2xpbW1hX3F1YW50aWxlL25vcm1hbGl6ZWRfZXhwcmVzc2lvbl92b2FfbGFiZWxzX2ZpbHRlcmVkLnRzdicsICJiY3JwaHlsb19jb3JyZWxhdGlvbnNfbm90ZWJvb2siID0gJ1JtZC9iY3JfcGh5bG9fY29ycmVsYXRpb25zLlJtZCcsICJkcml2ZXJfYW5hbHlzaXNfbm90ZWJvb2siID0gJ1JtZC9kcml2ZXJfYW5hbHlzaXMuUm1kJywgImloY194Y3JfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgImZpZ3VyZV9nYWxsZXJ5X25vdGVib29rIiA9ICdSbWQvZmlndXJlcy5SbWQnLCAic3VidHlwZV9tYXJrZXJfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9uYW5vc3RyaW5nL3N1YnR5cGVfbWFya2Vycy50c3YnLCAid2FuZ19mYmlfc3RhdHVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9uZy4zODQ5LVMxMi50eHQnLCAieGNybWFwc2NhcGVfbm90ZWJvb2siID0gJ1JtZC94Y3JtYXBzY2FwZS5SbWQnLCAibW1jdG1fb3ZfY29tYmluZWRfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9jb21iaW5lZF9vdl9tbWN0bS9vdXRwdXQnLCAiaW1tdW5lX3ZhcmlhYmlsaXR5X25vdGVib29rIiA9ICdSbWQvaW1tdW5lX3ZhcmlhYmlsaXR5LlJtZCcsICJkZWZhdWx0X3NhbXBsZXIiID0gJ0hNQycsICJub3RlYm9va19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3dlYicsICJtdXRzaWdfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgInNpdGVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL2FuYWx5c2lzL1JtZC9fc2l0ZS55bWwnLCAia25vd25fc3VidHlwZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL2FycmF5L3N1YnR5cGVzL2tub3duX3N1YnR5cGVzLnRzdicsICJjbG9uZV90cmVlX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2l0aC9jb21wbGV0ZS90cmVlX2RhdGEudHN2JywgIm1vbHN1YnR5cGVfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknKSwgImJjcnBoeWxvX2V4YW1wbGVzX25vdGVib29rIiA9ICdSbWQvYmNyX3BoeWxvX2V4YW1wbGVzLlJtZCcsICJ0aWxfY2xhc3NpZmllcl9ub3RlYm9vayIgPSAnUm1kL3RpbF9jbGFzc2lmaWVyLlJtZCcsICJuZW9lZGl0aW5nX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbmVvZWRpdGluZy9ydW40JywgIm1tY3RtX3BhdGllbnRfYWRfc2lncGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudC1hbmNlc3RyeS9wbG90cy9pdGgtYnktcGF0aWVudC1hbmNlc3RyeV9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJ4Y3JfcWNfbm90ZWJvb2siID0gJ1JtZC9yZXBsaWNhdGVzLlJtZCcsICJiY3JfY2xvbm90eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L2Nsb25vdHlwZXMvSUdIX2Nsb25vdHlwZXNfZmlsdGVyZWQudHh0JywgImtub3duX3N1YnR5cGVzX21lcmdlZCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9rbm93bl9zdWJ0eXBlc19tZXJnZWQudHN2JywgIm1vbHN1YnR5cGVfbm90ZWJvb2siID0gJ1JtZC9tb2xlY3VsYXJfc3VidHlwZXMuUm1kJywgIml0aF9zdGF0aXN0aWNzX25vdGVib29rIiA9ICdSbWQvaXRoX3N0YXRpc3RpY3MuUm1kJywgInByZXZhbGVuY2VfdGhyZXNob2xkIiA9IDAuMDEsICJsaWJyYXJ5X3NpemVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvbGlicmFyeV9zaXplcy50c3YnLCAiaWdwYXJ0aXRpb25fb3V0ZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9pZ3BhcnRpdGlvbi9ydW4yMicsICJwYXRpZW50c19mb3JfY2xvbmFsIiA9IGMoMSwgMiwgMywgNCwgNywgOSwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNSwgMTYsIDE3KSwgImpfZGljdGlvbmFyeSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3N1YnByb2plY3RzL2ltbXR5cGVyL21ldGFkYXRhL2ltZ3QvSG9tb19zYXBpZW5zX1RSQkouZmFzdGEnLCAiYmNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL0lHSC9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAibnNjYXR0ZXJzIiA9IDYsICJpbW10eXBlcl9tb2RlbHMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL2ltbXR5cGVyX3Jlc3VsdHMva2xhcmVuYmVlay9hYV92ai9ncmFkYm9vc3QnLCAiaWhjX3J1bjEiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2loYy9jZDhjZDNjZDIwL3ZhbGlkYXRlZF9zdGF0c193ZWlnaHRlZF9uZXcucmRhdGEnLCAiUE5HX1FVQUxJVFkiID0gMzAwLCAiaWNnY19tb2xlY3VsYXJfc3VidHlwZXMiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL2ljZ2NfcHJpbWFyeV90dW1vdXJfc3VidHlwZXMudHN2JywgImNsYXNzaWZpZXJfdHlwZSIgPSAna25uJywgInNhZF9ub3RlYm9vayIgPSAnUm1kL3NwZWNpZXNfYWJ1bmRhbmNlX2Rpc3RyaWJ1dGlvbnMuUm1kJywgImloY194Y3Jfc3RhdHNfbm90ZWJvb2siID0gJ1JtZC9paGNfeGNyX3N0YXRzLlJtZCcsICJpY2djX2V4cHJfbWVsdGVkIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9PVkFVX2V4cHJfbWVsdGVkLnRzdicsICJ4Y3JtYXBzY2FwZV90Y3JfcGF0aWVudF9vcmRlciIgPSBjKDE1LCAxLCAzLCA0LCAyLCAxNywgNywgMTQsIDksIDEwLCAxMiwgMTMsIDExLCAxNiksICJtdmNsdXN0X3RpbHR5cGVzIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJpbnRlcm1lZGlhdGVfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjInLCAiaXRoX3N0YXRfdHlwZXMiID0gYygnZW50cm9weScsICdwb3N0cHJvY2Vzc2VkX2RpdmVyZ2VuY2UnLCAnY29tYmluZWRfaXRoX25vcm1hbGl6ZWQnLCAncHJvcG9ydGlvbl9zdWJjbG9uYWwnKSwgIm1hcHNjYXBlX25vdGVib29rIiA9ICdSbWQvbWFwc2NhcGUuUm1kJywgIm1hc3Rlcl92YXJpYW50X2ZpbGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9zbnZzLnRzdicsICJpdGhfc3RhdHNfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaXRoL2NvbXBsZXRlL2Nsb25hbF9tZWFzdXJlcy50c3YnLCAiZXhhbXBsZV9tc2FfcGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMTMvb2xkL2FsaWdubWVudF9wbG90cy9tc2EvaXRoMl8yL2NsdXN0OS9pbmRlbF9yZXZlcnNlZC5odG1sJywgImJlbmNobWFya2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9iZW5jaG1hcmtzL3BhcGVyYW5hbHlzaXMyJywgImV4YW1wbGVfYW5ub3RhdGlvbnMiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2lncGFydGl0aW9uL3J1bjEzL2ZpbmFsX3BhcnRpdGlvbnMvaXRoMl8yL2NsdXN0OS9hbm5vdGF0aW9uc19mbGFnZ2VkLnRzdicsICJpY2djX25vcm1hbGl6ZWRfcmVhZHNfbWF0cml4IiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9PVkFVX2V4cHJfbWF0cml4LnRzdicsICJpbmRleF9ub3RlYm9vayIgPSAnUm1kL2luZGV4LlJtZCcsICJ0Y2dhX292X2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvVENHQS90Y2dhX292X2Fubm90YXRpb25fc3VwMTMudHh0JywgIm1tY3RtX3NhbXBsZV9zaWdwbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1zYW1wbGUvcGxvdHMvaXRoLWJ5LXNhbXBsZV9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJuZW9hbnRpZ2VuX2VkaXRpbmdfbm90ZWJvb2siID0gJ1JtZC9pbW11bm9lZGl0aW5nLlJtZCcsICJ0YWJsZV9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yJywgInByb3BvcnRpb25fc3ViY2xvbmFsX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2l0aC9jb21wbGV0ZS9vbGRfcHJvcG9ydGlvbl9zdWJjbG9uYWwudHN2JywgInNwYXRpYWxfbm90ZWJvb2siID0gJ1JtZC9zcGF0aWFsX2FuYWx5c2lzLlJtZCcsICJ4Y3JfbWFwcGluZ19ub3RlYm9vayIgPSAnUm1kL3hjcl9tYXBwaW5nLlJtZCcsICJ0Y3JfY2xvbm90eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L2Nsb25vdHlwZXMvVFJCX2Nsb25vdHlwZXNfZmlsdGVyZWQudHh0JyksCiAgICBydWxlID0gJ3hjcl90cmFja2luZycKKQojIyMjIyMjIyBPcmlnaW5hbCBzY3JpcHQgIyMjIyMjIyMjCgogICAgICAgICAgICAgICAgICAgICAgICBgYGAKCgpgYGB7ciBnbG9iYWxfY2h1bmtfb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB0aWR5PVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGl0aGkudXRpbHMpCmxvYWRfYmFzZV9saWJzKCkKCmxpYnJhcnkoaXRoaS5tZXRhKQpsaWJyYXJ5KGl0aGkueGNyKQpsaWJyYXJ5KGl0aGkuY2xvbmVzKQpgYGAKCiMjIENvbG91ciBwYWxldHRlcwoKYGBge3J9CnBhbF9wYXRpZW50IDwtIHNlbGVjdF9wYWxldHRlKCJwYXRpZW50IikKYGBgCgojIyBQYXJhbWV0ZXJzCgpgYGB7cn0KZGJfcGF0aCA8LSBzbmFrZW1ha2VAcGFyYW1zJGRiCgp4Y3JfdGFibGVfcGF0aCA8LSBzbmFrZW1ha2VAaW5wdXQkeGNyX3RhYmxlCnByZXZhbGVuY2Vfb3B0aW9uIDwtIHNuYWtlbWFrZUBwYXJhbXMkcHJldmFsZW5jZV9vcHRpb24KZGlzdGFuY2VfbWV0aG9kIDwtIHNuYWtlbWFrZUBwYXJhbXMkeGNyX2Rpc3RhbmNlX21ldGhvZAoKY2xvbmVfdHJlZV9maWxlIDwtIHNuYWtlbWFrZUBpbnB1dCRjbG9uZV90cmVlX2ZpbGUKY2xvbmVfcHJldmFsZW5jZV9maWxlIDwtIHNuYWtlbWFrZUBpbnB1dCRjbG9uZV9wcmV2YWxlbmNlX2ZpbGUKY2xvbmVfYnJhbmNoX2xlbmd0aF9maWxlIDwtIHNuYWtlbWFrZUBpbnB1dCRjbG9uZV9icmFuY2hfbGVuZ3RoX2ZpbGUKYGBgCgojIyBNZXRhZGF0YQoKYGBge3J9CmRiIDwtIHNyY19zcWxpdGUoZGJfcGF0aCwgY3JlYXRlPUZBTFNFKQoKZHVwbGljYXRlcyA8LSBjb2xsZWN0KHRibChkYiwgImR1cGxpY2F0ZXMiKSkKYGBgCgojIyBBbmFseXNpcwoKIyMjIFhDUiByZXBlcnRvaXJlIHNpbWlsYXJpdHkKCmBgYHtyfQp4Y3JfdGFibGUgPC0gcmVhZF9jbG9ub3R5cGVzKHhjcl90YWJsZV9wYXRoLCBkdXBsaWNhdGVzID0gRkFMU0UsIGRiX3BhdGgsIHZlcmJvc2U9MSkKYGBgCgpgYGB7cn0KdGNyX3NlZ21lbnRfdHlwZSA8LSAiVFJCIgpiY3Jfc2VnbWVudF90eXBlIDwtICJJR0giCgppZF90eXBlIDwtICJjb25kZW5zZWRfaWQiCmBgYAoKYGBge3J9CnBhdGllbnRzIDwtIHVuaXF1ZSh4Y3JfdGFibGUkcGF0aWVudF9pZCkKCmRpc3RzIDwtIGxhcHBseShwYXRpZW50cywgZnVuY3Rpb24ocGF0aWVudCkgewogIHRjcl9jbG9ub3R5cGVzIDwtIHN1YnNldCh4Y3JfdGFibGUsIHR5cGUgPT0gdGNyX3NlZ21lbnRfdHlwZSAmIHBhdGllbnRfaWQgPT0gcGF0aWVudCkKICBiY3JfY2xvbm90eXBlcyA8LSBzdWJzZXQoeGNyX3RhYmxlLCB0eXBlID09IGJjcl9zZWdtZW50X3R5cGUgJiBwYXRpZW50X2lkID09IHBhdGllbnQpCiAgdGNyX2Nyb3NzX3RhYmxlIDwtIGNyb3NzX3RhYnVsYXRlKHRjcl9jbG9ub3R5cGVzLCBpZF90eXBlID0gaWRfdHlwZSkKICBiY3JfY3Jvc3NfdGFibGUgPC0gY3Jvc3NfdGFidWxhdGUoYmNyX2Nsb25vdHlwZXMsIGlkX3R5cGUgPSBpZF90eXBlKQogIAogIGNyb3NzX3RhYmxlcyA8LSBsaXN0KHRjcj10Y3JfY3Jvc3NfdGFibGUsIGJjcj1iY3JfY3Jvc3NfdGFibGUpCiAgCiAgZGlzdGFuY2VfbWF0cmljZXMgPC0gbGFwcGx5KGNyb3NzX3RhYmxlcywgZnVuY3Rpb24oY3Jvc3NfdGFibGUpIHsKICAgIGRpc3RtYXQgPC0gY29tcHV0ZV9pbW11bmVfZGlzdGFuY2VfbWF0cml4KGNyb3NzX3RhYmxlLCBtZXRob2QgPSBkaXN0YW5jZV9tZXRob2QpCiAgICBtYXQgPC0gYXMubWF0cml4KGRpc3RtYXQpCiAgICByZXR1cm4obWF0KQogIH0pCiAgcmV0dXJuKGRpc3RhbmNlX21hdHJpY2VzKQp9KQp0Y3JfZGlzdHMgPC0gbGFwcGx5KGRpc3RzLCBmdW5jdGlvbih4KSB4JHRjcikKYmNyX2Rpc3RzIDwtIGxhcHBseShkaXN0cywgZnVuY3Rpb24oeCkgeCRiY3IpCgp4Y3JfZGlzdHMgPC0gdGliYmxlKHBhdGllbnRfaWQgPSBwYXRpZW50cywgdGNyPXRjcl9kaXN0cywgYmNyPWJjcl9kaXN0cykKeGNyX2Rpc3RzJHBhdGllbnRfaWQgPC0gZmFjdG9yKHhjcl9kaXN0cyRwYXRpZW50X2lkKQp4Y3JfZGlzdHMgPC0geGNyX2Rpc3RzW29yZGVyKHhjcl9kaXN0cyRwYXRpZW50X2lkKSxdCmBgYAoKVGhlIGRpc3RhbmNlIG1ldHJpYyBiZWluZyB1c2VkIGlzIGByIGRpc3RhbmNlX21ldGhvZGAuIAoKCiMjIyBUdW1vdXIgY2xvbmVzCgpgYGB7cn0KdHJlZV9icmFuY2hfZGF0YSA8LSByZWFkX2Nsb25lX3RyZWVfZGF0YShjbG9uZV90cmVlX2ZpbGUsIGNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZSwgY2xvbmVfcHJldmFsZW5jZV9maWxlLCBkYl9wYXRoKQp0cmVlcyA8LSBsYXBwbHkodHJlZV9icmFuY2hfZGF0YSwgZnVuY3Rpb24oeCkgeCR0cmVlKQpwcmV2YWxlbmNlcyA8LSByYmluZC5maWxsKGxhcHBseSh0cmVlX2JyYW5jaF9kYXRhLCBmdW5jdGlvbih4KSB4JHByZXZhbGVuY2VfZGF0KSkKYnJhbmNoX2xlbmd0aHMgPC0gcmJpbmQuZmlsbChsYXBwbHkodHJlZV9icmFuY2hfZGF0YSwgZnVuY3Rpb24oeCkgeCRicmFuY2hfZGF0KSkKCmNjZnMgPC0gY29tcHV0ZV9jY2YocHJldmFsZW5jZXMsIHRyZWVzLCBpZF90eXBlID0gaWRfdHlwZSkKY2Nmc19sYWJlbGVkIDwtIG1lcmdlKGNjZnMsIGJyYW5jaF9sZW5ndGhzLCBieT1jKCJsYWJlbCIsICJub2RlIiwgInBhdGllbnRfaWQiKSkKCiMjIE5lZWQgbm9uLW5vcm1hbGl6ZWQgZGlzdGFuY2VzCmNsb25lX2Rpc3RzIDwtIGNsb25lX2Rpc3RhbmNlcyhjY2ZzX2xhYmVsZWQsIG5vcm1hbGl6ZSA9IEZBTFNFLCBpZF90eXBlID0gImNvbmRlbnNlZF9pZCIpCmBgYAoKIyMjIENvbWJpbmF0aW9uCgoKYGBge3J9CmNsb25lX2Rpc3RzJHBhdGllbnRfaWQgPC0gZmFjdG9yKGNsb25lX2Rpc3RzJHBhdGllbnRfaWQpCgp0b3RhbF9kaXN0cyA8LSBpbm5lcl9qb2luKGNsb25lX2Rpc3RzLCB4Y3JfZGlzdHMpCmBgYAoKYGBge3J9CmNvbXB1dGVfb3ZlcmxhcF9zaW1pbGFyaXRpZXMgPC0gZnVuY3Rpb24odmFscykgewogIGNvbW1vbl9zYW1wbGVzIDwtIGxhcHBseSh2YWxzLCBmdW5jdGlvbih4KSB7CiAgICBjb2xuYW1lcyh4KQogIH0pCiAgY29tbW9uX3NhbXBsZXMgPC0gUmVkdWNlKGludGVyc2VjdCwgY29tbW9uX3NhbXBsZXMpCiAgCiAgc2ltX2RmcyA8LSBsYXBwbHkobmFtZXModmFscyksIGZ1bmN0aW9uKGNhdGVnb3J5KSB7CiAgICBtYXQgPC0gdmFsc1tbY2F0ZWdvcnldXQogICAgbWF0IDwtIG1hdFtjb21tb25fc2FtcGxlcyxjb21tb25fc2FtcGxlc10KICAgIAogICAgcmVzIDwtIHNldE5hbWVzKG1lbHQoYXMubWF0cml4KG1hdCkpLCBjKCJzYW1wbGUxIiwgInNhbXBsZTIiLCBjYXRlZ29yeSkpCiAgICByZXR1cm4ocmVzKQogIH0pCiAgc2ltaWxhcml0aWVzIDwtIFJlZHVjZShtZXJnZSwgc2ltX2RmcykKICByZXN1bHQgPC0gc3Vic2V0KHNpbWlsYXJpdGllcywgYXMubnVtZXJpYyhzYW1wbGUxKSA8IGFzLm51bWVyaWMoc2FtcGxlMikpCiAgcmV0dXJuKHJlc3VsdCkKfQpgYGAKCmBgYHtyfQpwYWlyd2lzZV9zaW1pbGFyaXRpZXMgPC0gcmJpbmQuZmlsbChsYXBwbHkoMTpucm93KHRvdGFsX2Rpc3RzKSwgZnVuY3Rpb24oaSkgewogIGNsb25lX2Rpc3RtYXQgPC0gdG90YWxfZGlzdHNbaSxdJGRpc3RfY2xvbmVzX3dlaWdodGVkW1sxXV0KICB0Y3JfZGlzdG1hdCA8LSB0b3RhbF9kaXN0c1tpLF0kdGNyW1sxXV0KICBiY3JfZGlzdG1hdCA8LSB0b3RhbF9kaXN0c1tpLF0kYmNyW1sxXV0KICAKICBpbnB1dHMgPC0gbGlzdChjbG9uZV9kaXN0bWF0LCB0Y3JfZGlzdG1hdCwgYmNyX2Rpc3RtYXQpCiAgbmFtZXMoaW5wdXRzKSA8LSBjKCJjbG9uZXMiLCAidGNyIiwgImJjciIpCiAgCiAgcGF0aWVudF9pZCA8LSB0b3RhbF9kaXN0c1tpLF0kcGF0aWVudF9pZAogIAogIHBhaXJ3aXNlX3NpbXMgPC0gY2JpbmQocGF0aWVudF9pZD1wYXRpZW50X2lkLCBjb21wdXRlX292ZXJsYXBfc2ltaWxhcml0aWVzKGlucHV0cykpCiAgcmV0dXJuKHBhaXJ3aXNlX3NpbXMpCn0pKQpwYWlyd2lzZV9zaW1pbGFyaXRpZXMkcGF0aWVudF9pZCA8LSBmYWN0b3IocGFpcndpc2Vfc2ltaWxhcml0aWVzJHBhdGllbnRfaWQpCgpwYXRpZW50X2NvdW50cyA8LSBwYWlyd2lzZV9zaW1pbGFyaXRpZXMgJT4lIGdyb3VwX2J5KHBhdGllbnRfaWQpICU+JSBzdW1tYXJpc2Uobj1uKCkpCnNpbmdsZXRvbnMgPC0gc3Vic2V0KHBhdGllbnRfY291bnRzLCBuPT0xKSRwYXRpZW50X2lkCnBhaXJ3aXNlX3NpbWlsYXJpdGllcyA8LSBzdWJzZXQocGFpcndpc2Vfc2ltaWxhcml0aWVzLCAhcGF0aWVudF9pZCAlaW4lIHNpbmdsZXRvbnMpCmBgYAoKCiMjIyBUQ1ItY2xvbmVzCgpgYGB7cn0Kc3RhdHMgPC0gc2V0TmFtZXMoZGRwbHkocGFpcndpc2Vfc2ltaWxhcml0aWVzLCAuKHBhdGllbnRfaWQpLCBmdW5jdGlvbih4KSB7CiAgcmVzIDwtIHdpdGgoeCwgY29yLnRlc3QoY2xvbmVzLCB0Y3IsIG1ldGhvZD0icGVhcnNvbiIpKQogIHB2YWx1ZSA8LSByZXMkcC52YWx1ZQogIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKFApPT1wLCBsaXN0KHA9Zm9ybWF0KHB2YWx1ZSwgZGlnaXRzPTMpKSkKICByZXR1cm4oYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpKSkKfSksIGMoInBhdGllbnRfaWQiLCAicC52YWx1ZSIpKQoKc3VtbWFyeShsbWVyKHRjciB+IGNsb25lcyArICgxfHBhdGllbnRfaWQpLCBkYXRhID0gcGFpcndpc2Vfc2ltaWxhcml0aWVzKSkKYGBgCgoKYGBge3J9CmdncGxvdChwYWlyd2lzZV9zaW1pbGFyaXRpZXMsIGFlcyh4PWNsb25lcywgeT10Y3IpKSArIGdlb21fcG9pbnQoYWVzKGNvbG91cj1wYXRpZW50X2lkKSkgKyB0aGVtZV9idygpICsgdGhlbWVfUHVibGljYXRpb24oKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBwYWxfcGF0aWVudCkgKyB4bGFiKCJDbG9uZSBkaXN0YW5jZSIpICsgeWxhYigiVENSIGRpc3RhbmNlIikgKyBmYWNldF93cmFwKH4gcGF0aWVudF9pZCwgc2NhbGVzPSJmcmVlIikgKyBnZW9tX3RleHQoZGF0YT1zdGF0cywgYWVzKHg9SW5mLCB5PUluZiwgbGFiZWw9cC52YWx1ZSksIGhqdXN0PTEuMSwgdmp1c3Q9MS41LCBzaXplPTMsIHBhcnNlPVRSVUUpCmBgYAoKIyMjIEJDUi1jbG9uZXMKCmBgYHtyfQpzdGF0cyA8LSBzZXROYW1lcyhkZHBseShwYWlyd2lzZV9zaW1pbGFyaXRpZXMsIC4ocGF0aWVudF9pZCksIGZ1bmN0aW9uKHgpIHsKICByZXMgPC0gd2l0aCh4LCBjb3IudGVzdChjbG9uZXMsIGJjciwgbWV0aG9kPSJwZWFyc29uIikpCiAgcHZhbHVlIDwtIHJlcyRwLnZhbHVlCiAgZXEgPC0gc3Vic3RpdHV0ZShpdGFsaWMoUCk9PXAsIGxpc3QocD1mb3JtYXQocHZhbHVlLCBkaWdpdHM9MykpKQogIHJldHVybihhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpKQp9KSwgYygicGF0aWVudF9pZCIsICJwLnZhbHVlIikpCgpzdW1tYXJ5KGxtZXIoYmNyIH4gY2xvbmVzICsgKDF8cGF0aWVudF9pZCksIGRhdGEgPSBwYWlyd2lzZV9zaW1pbGFyaXRpZXMpKQpgYGAKCgpgYGB7cn0KZ2dwbG90KHBhaXJ3aXNlX3NpbWlsYXJpdGllcywgYWVzKHg9Y2xvbmVzLCB5PWJjcikpICsgZ2VvbV9wb2ludChhZXMoY29sb3VyPXBhdGllbnRfaWQpKSArIHRoZW1lX2J3KCkgKyB0aGVtZV9QdWJsaWNhdGlvbigpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbF9wYXRpZW50KSArIHhsYWIoIkNsb25lIGRpc3RhbmNlIikgKyB5bGFiKCJCQ1IgZGlzdGFuY2UiKSArIGZhY2V0X3dyYXAofiBwYXRpZW50X2lkLCBzY2FsZXM9ImZyZWUiKSArIGdlb21fdGV4dChkYXRhPXN0YXRzLCBhZXMoeD1JbmYsIHk9SW5mLCBsYWJlbD1wLnZhbHVlKSwgaGp1c3Q9MS4xLCB2anVzdD0xLjUsIHNpemU9MywgcGFyc2U9VFJVRSkKYGBgCgoKVENSLWNsb25lIGNvcnJlbGF0aW9ucyBhcmUgZ29vZCBmb3IgbW9zdCBwYXRpZW50cywgd2hpbGUgQkNSLWNsb25lIGNvcnJlbGF0aW9ucyBhcmUgcG9vciBmb3IgbW9zdCBwYXRpZW50cy4gUGF0aWVudCAxIGhhcyBnb29kIGNvcnJlbGF0aW9ucyBmb3IgYm90aCAtLSBub3QgZXhhY3RseSBzdXJwcmlzaW5nIGFzIHBhdGllbnQgMSBpcyB2ZXJ5IGltbXVub3JlYWN0aXZlIChoaWdoZXN0IG91dCBvZiB0aGUgSVRIMiBjb2hvcnQpLiBQYXRpZW50IDQgaXMgYSBjbGVhciBvcHBvc2l0ZSB0byB0aGlzIHRyZW5kLiBJcyBpdCBwb3NzaWJsZSB0aGF0IHBhdGllbnQgNCBoYXJib3JzIGEgQi1jZWxsIGRyaXZlbiByZXNwb25zZSwgcmF0aGVyIHRoYW4gYSBULWNlbGwgZHJpdmVuIG9uZT8KCkRvIHdlIGhhdmUgY29ycm9ib3JhdGluZyBldmlkZW5jZSBmb3IgdGhpcz8gCgpTdXBwb3J0czoKCiogUGF0aWVudCA0IGhhcyB0aGUgaGlnaGVzdCBpbnRyYXBhdGllbnQgQkNSIHNpbWlsYXJpdHkgYWNyb3NzIHRoZSBlbnRpcmUgY29ob3J0IChpbW11bmUgcmVzcG9uc2VzIGhpZ2hseSBzaW1pbGFyIGZyb20gc2l0ZS10by1zaXRlIGNvdWxkIGltcGx5IHRoYXQgdGhlcmUncyBhIHdpZGVzcHJlYWQgYW50aWdlbiwgYW5kIHRlbmRzIHRvIGJlIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgQ0QyMCsgVElMKQoqIFBhdGllbnQgNCBoYXMgcmVsYXRpdmVseSBoaWdoIENEMjArIFRJTCBkZW5zaXR5IChzZWUgdGhlIEltbXVuZSBWYXJpYWJpbGl0eSBwYWdlKSAtLSB0aWVkIGZvciAzcmQvMjEKCkRvZXMgbm90IHN1cHBvcnQ6CgoqIFBhdGllbnQgMyBhbHNvIGhhcyBoaWdoIENEMjArIFRJTCBkZW5zaXR5ICh0aWVkIGZvciAzcmQvMjEpLCBidXQgZG9lcyBub3QgZXhoaWJpdCB0aGlzIHBhdHRlcm4=