index.html 01_annotation.html 02_estimation_infection.html

1 PBMC Infection Differential Expression, Infection: 20170820

This document turns to the infection of PBMC cells with L.panamensis. This data is particularly strangely affected by the different strains used to infect the cells, and as a result is both useful and troubling.

Given the observations above, we have some ideas of ways to pass the data for differential expression analyses which may or may not be ‘better’. Lets try some and see what happens.

1.1 Create data sets to compare differential expression analyses

Given the above ways to massage the data, lets use a few of them for limma/deseq/edger. The main caveat in this is that those tools really do expect specific distributions of data which we horribly violate if we use log2() data, which is why in the previous blocks I named them l2blahblah, thus we can do the same sets of normalization but without that and forcibly push the resulting data into limma/edger/deseq.

2 The negative control

Everything I did in 02_estimation_infection.html suggests that there are no significant differences visible if one looks just at chronic/self-healing in this data. Further testing has seemingly proven this statement, as a result most of the following analyses will look at chronic/uninfected and self-healing/uninfected followed by attempts to reconcile those results.

2.1 Filter the data

To save some time and annoyance with sva, lets filter the data now. In addition, write down a small function used to extract the sets of significant genes across different contrasts (notably self/uninfected vs. chronic/uninfected).

hs_inf_filt <- sm(normalize_expt(hs_inf, filter=TRUE))
hs_uninf_filt <- sm(normalize_expt(hs_uninf, filter=TRUE))
keepers <- list("sh_nil" = c("sh", "uninf"),
                "ch_nil" = c("chr", "uninf"),
                "ch_sh" = c("chr", "sh"))

subset_significants <- function(hs_sig) {
    sh_nil_up_genes <- rownames(hs_sig[["deseq"]][["ups"]][["sh_vs_uninf"]])
    ch_nil_up_genes <- rownames(hs_sig[["deseq"]][["ups"]][["chr_vs_uninf"]])
    sh_nil_down_genes <- rownames(hs_sig[["deseq"]][["downs"]][["sh_vs_uninf"]])
    ch_nil_down_genes <- rownames(hs_sig[["deseq"]][["downs"]][["chr_vs_uninf"]])

    sh_solo_up_idx <- ! sh_nil_up_genes %in% ch_nil_up_genes
    sh_solo_up <- sh_nil_up_genes[sh_solo_up_idx]
    sh_shared_ch_idx <- sh_nil_up_genes %in% ch_nil_up_genes
    sh_shared_ch_up <- sh_nil_up_genes[sh_shared_ch_idx]
    ch_solo_up_idx <- ! ch_nil_up_genes %in% sh_nil_up_genes
    ch_solo_up <- ch_nil_up_genes[ch_solo_up_idx]

    sh_solo_down_idx <- ! sh_nil_down_genes %in% ch_nil_down_genes
    sh_solo_down <- sh_nil_down_genes[sh_solo_down_idx]
    sh_shared_ch_idx <- sh_nil_down_genes %in% ch_nil_down_genes
    sh_shared_ch_down <- sh_nil_down_genes[sh_shared_ch_idx]
    ch_solo_down_idx <- ! ch_nil_down_genes %in% sh_nil_down_genes
    ch_solo_down <- ch_nil_down_genes[ch_solo_down_idx]

    retlist <- list(
        "sh_solo_up" = hs_sig[["deseq"]][["ups"]][["sh_vs_uninf"]][sh_solo_up, ],
        "ch_solo_up" = hs_sig[["deseq"]][["ups"]][["chr_vs_uninf"]][ch_solo_up, ],
        "sh_shared_ch_up" = hs_sig[["deseq"]][["ups"]][["sh_vs_uninf"]][sh_shared_ch_up, ],
        "sh_solo_down" = hs_sig[["deseq"]][["downs"]][["sh_vs_uninf"]][sh_solo_down, ],
        "ch_solo_down" = hs_sig[["deseq"]][["downs"]][["chr_vs_uninf"]][ch_solo_down, ],
        "sh_shared_ch_down" = hs_sig[["deseq"]][["downs"]][["sh_vs_uninf"]][sh_shared_ch_down, ])
    retlist[["up_weights"]] <- c(0, nrow(retlist[["sh_solo_up"]]),
                                 nrow(retlist[["ch_solo_up"]]), nrow(retlist[["sh_shared_ch_up"]]))
    retlist[["down_weights"]] <- c(0, nrow(retlist[["sh_solo_down"]]),
                                 nrow(retlist[["ch_solo_down"]]), nrow(retlist[["sh_shared_ch_down"]]))
    retlist[["up_venn"]] <- Vennerable::Venn(SetNames = c("sh", "chr"),
                                             Weight = retlist[["up_weights"]])
    retlist[["down_venn"]] <- Vennerable::Venn(SetNames = c("sh", "chr"),
                                               Weight = retlist[["down_weights"]])
    return(retlist)
}

2.2 Do a completely normal limma invocation.

The following probably should not be used.

counts <- exprs(hs_uninf_filt)
design <- pData(hs_uninf_filt)
model <- model.matrix(~ 0 + condition + donor + pathogenstrain, data=design)
voom_weight_result <- limma::voomWithQualityWeights(counts=counts, design=model,
                                                    normalize.method="quantile", plot=TRUE)
voom_result <- limma::voom(counts=counts, design=model, normalize.method="quantile", plot=TRUE)
fitting_weight <- limma::lmFit(object=voom_weight_result, design=model, method="ls")
fitting <- limma::lmFit(object=voom_result, design=model, method="ls")
contrast <- limma::makeContrasts(sh_ch=conditionpbmc_sh-conditionpbmc_ch, levels=model)
contrast_weight <- limma::contrasts.fit(fit=fitting_weight, contrasts=contrast)
contrast <- limma::contrasts.fit(fit=fitting, contrasts=contrast)
ebayes_weighted <- limma::eBayes(contrast_weight)
ebayes <- limma::eBayes(contrast)
toptable_weighted <- limma::topTable(ebayes_weighted)
toptable <- limma::topTable(ebayes)
toptable

limma_test <- limma_pairwise(input=hs_uninf_filt,
                             alt_model="~ 0 + condition + donor + donor:pathogenstrain")
limma_top <- limma::topTable(limma_test$pairwise_comparisons,
                             number=nrow(limma_test$pairwise_comparisons),
                             sort.by="P",
                             coef="pbmc_ch_vs_pbmc_sh")
head(limma_top, n=10)

limma_test2 <- limma_pairwise(input=hs_uninf_filt,
                              alt_model="~ 0 + condition + donor")
limma_top2 <- limma::topTable(limma_test2$pairwise_comparisons,
                              coef="pbmc_ch_vs_pbmc_sh",
                              number=nrow(limma_test2$pairwise_comparisons),
                              sort.by="P")
head(limma_top2)
hs_pairwise_nobatch <- sm(all_pairwise(hs_uninf_filt, model_batch=FALSE))
hs_combined_nobatch <- sm(combine_de_tables(hs_pairwise_nobatch,
                                            excel=paste0("excel/hs_infect_nobatch-v", ver, ".xlsx"),
                                            keepers=keepers))
hs_sig_nobatch <- sm(extract_significant_genes(hs_combined_nobatch,
                                               excel=paste0("excel/hs_infect_nobatch_sig-v", ver, ".xlsx")))
hs_sig_nobatch$deseq$counts
##              change_counts_up change_counts_down
## sh_vs_uninf              1050                193
## chr_vs_uninf             1052                171
## chr_vs_sh                   0                  0
common_solos_nobatch <- subset_significants(hs_sig_nobatch)
summary(common_solos_nobatch)
##                   Length Class      Mode   
## sh_solo_up        38     data.frame list   
## ch_solo_up        38     data.frame list   
## sh_shared_ch_up   38     data.frame list   
## sh_solo_down      38     data.frame list   
## ch_solo_down      38     data.frame list   
## sh_shared_ch_down 38     data.frame list   
## up_weights         4     -none-     numeric
## down_weights       4     -none-     numeric
## up_venn            1     Venn       S4     
## down_venn          1     Venn       S4
nobatch_up_venn <- Vennerable::plot(common_solos_nobatch$up_venn, doWeights=FALSE)

nobatch_down_venn <- Vennerable::plot(common_solos_nobatch$down_venn, doWeights=FALSE)

3 Add patient to the model

Repeat the previous set of analyses with d107/108/110 in the model.

hs_pairwise_batch <- sm(all_pairwise(hs_uninf_filt, model_batch=TRUE))
hs_combined_batch <- sm(combine_de_tables(hs_pairwise_batch,
                                          excel=paste0("excel/hs_infect_patbatch-v", ver, ".xlsx"),
                                          keepers=keepers))
hs_sig_batch <- sm(extract_significant_genes(hs_combined_batch,
                                             excel=paste0("excel/hs_infect_patbatch_sig-v", ver, ".xlsx")))
hs_sig_batch[["deseq"]][["counts"]]
##              change_counts_up change_counts_down
## sh_vs_uninf              1035                330
## chr_vs_uninf             1060                294
## chr_vs_sh                   0                  0
common_solos_batch <- subset_significants(hs_sig_batch)
summary(common_solos_batch)
##                   Length Class      Mode   
## sh_solo_up        38     data.frame list   
## ch_solo_up        38     data.frame list   
## sh_shared_ch_up   38     data.frame list   
## sh_solo_down      38     data.frame list   
## ch_solo_down      38     data.frame list   
## sh_shared_ch_down 38     data.frame list   
## up_weights         4     -none-     numeric
## down_weights       4     -none-     numeric
## up_venn            1     Venn       S4     
## down_venn          1     Venn       S4
similar <- sm(compare_de_results(hs_combined_nobatch, hs_combined_batch, cor_method="spearman"))
similar[["deseq"]]
## $sh_vs_uninf
## $sh_vs_uninf$logfc
## [1] 0.992
## 
## $sh_vs_uninf$p
## [1] 0.9339
## 
## $sh_vs_uninf$adjp
## [1] 0.9339
## 
## 
## $chr_vs_uninf
## $chr_vs_uninf$logfc
## [1] 0.9926
## 
## $chr_vs_uninf$p
## [1] 0.9361
## 
## $chr_vs_uninf$adjp
## [1] 0.9361
## 
## 
## $chr_vs_sh
## $chr_vs_sh$logfc
## [1] 0.9854
## 
## $chr_vs_sh$p
## [1] 0.9266
## 
## $chr_vs_sh$adjp
## [1] 0.0953
batch_up_venn <- Vennerable::plot(common_solos_batch[["up_venn"]], doWeights=FALSE)

batch_down_venn <- Vennerable::plot(common_solos_batch[["down_venn"]], doWeights=FALSE)

kept_columns <- c("transcriptid", "geneid", "description", "deseq_logfc", "deseq_adjp")
xls_result <- write_xls(data=common_solos_batch[["sh_solo_up"]][, kept_columns], sheet="sh_up_solo")
xls_result <- write_xls(data=common_solos_batch[["ch_solo_up"]][, kept_columns], sheet="chr_up_solo",
                        wb=xls_result[["workbook"]])
xls_result <- write_xls(data=common_solos_batch[["sh_shared_ch_up"]][, kept_columns],
                        sheet="shchr_shared_up", wb=xls_result[["workbook"]])
xls_result <- write_xls(data=common_solos_batch[["sh_solo_down"]][, kept_columns],
                        sheet="sh_down_solo", wb=xls_result[["workbook"]])
xls_result <- write_xls(data=common_solos_batch[["ch_solo_down"]][, kept_columns],
                        sheet="chr_down_solo", wb=xls_result[["workbook"]])
xls_result <- write_xls(data=common_solos_batch[["sh_shared_ch_down"]][, kept_columns],
                        sheet="shchr_shared_down", wb=xls_result[["workbook"]],
                        excel=paste0("excel/figure_5a_stuff-v", ver, ".xlsx"))
## Saving to: excel/figure_5a_stuff-v20170820.xlsx

4 Add sva into the mix

Repeat, this time attmepting to tamp down the variance by person.

hs_pairwise_ssva <- sm(all_pairwise(hs_uninf_filt, model_batch="ssva"))
hs_combined_ssva <- sm(combine_de_tables(hs_pairwise_ssva,
                                         excel=paste0("excel/hs_infect_ssva-v", ver, ".xlsx"),
                                         keepers=keepers))
hs_sig_ssva <- sm(extract_significant_genes(hs_combined_ssva,
                                            excel=paste0("excel/hs_infect_ssva_sig-v", ver, ".xlsx")))
hs_sig_ssva$deseq$counts
##              change_counts_up change_counts_down
## sh_vs_uninf              1151                768
## chr_vs_uninf             1312                822
## chr_vs_sh                   0                  0
common_solos_ssva <- subset_significants(hs_sig_ssva)
similar <- sm(compare_de_results(hs_combined_nobatch, hs_combined_ssva, cor_method="spearman"))
similar$limma
## $sh_vs_uninf
## $sh_vs_uninf$logfc
## [1] 0.3367
## 
## $sh_vs_uninf$p
## [1] 0.04093
## 
## $sh_vs_uninf$adjp
## [1] 0.04093
## 
## 
## $chr_vs_uninf
## $chr_vs_uninf$logfc
## [1] 0.4321
## 
## $chr_vs_uninf$p
## [1] 0.08029
## 
## $chr_vs_uninf$adjp
## [1] 0.08029
## 
## 
## $chr_vs_sh
## $chr_vs_sh$logfc
## [1] 0.9379
## 
## $chr_vs_sh$p
## [1] 0.8481
## 
## $chr_vs_sh$adjp
## [1] 0.07285
similar <- sm(compare_de_results(hs_combined_batch, hs_combined_ssva, cor_method="spearman"))
similar$limma
## $sh_vs_uninf
## $sh_vs_uninf$logfc
## [1] 0.3504
## 
## $sh_vs_uninf$p
## [1] 0.1662
## 
## $sh_vs_uninf$adjp
## [1] 0.1662
## 
## 
## $chr_vs_uninf
## $chr_vs_uninf$logfc
## [1] 0.4144
## 
## $chr_vs_uninf$p
## [1] 0.1923
## 
## $chr_vs_uninf$adjp
## [1] 0.1923
## 
## 
## $chr_vs_sh
## $chr_vs_sh$logfc
## [1] 0.9808
## 
## $chr_vs_sh$p
## [1] 0.9256
## 
## $chr_vs_sh$adjp
## [1] 0.9255
ssva_up_venn <- Vennerable::plot(common_solos_ssva$up_venn, doWeights=FALSE)

ssva_down_venn <- Vennerable::plot(common_solos_ssva$down_venn, doWeights=FALSE)

hs_pairwise_fsva <- sm(all_pairwise(hs_uninf_filt, model_batch="fsva"))
hs_combined_fsva <- sm(combine_de_tables(hs_pairwise_fsva,
                                         excel=paste0("excel/hs_infect_fsva-v", ver, ".xlsx"),
                                         keepers=keepers))
hs_sig_fsva <- sm(extract_significant_genes(hs_combined_fsva,
                                            excel=paste0("excel/hs_infect_fsva_sig-v", ver, ".xlsx")))
hs_sig_fsva$deseq$counts
##              change_counts_up change_counts_down
## sh_vs_uninf              1068                328
## chr_vs_uninf             1103                290
## chr_vs_sh                   0                  0
common_solos_fsva <- sm(subset_significants(hs_sig_fsva))
length(common_solos_fsva)
## [1] 10
summary(common_solos_fsva)
##                   Length Class      Mode   
## sh_solo_up        38     data.frame list   
## ch_solo_up        38     data.frame list   
## sh_shared_ch_up   38     data.frame list   
## sh_solo_down      38     data.frame list   
## ch_solo_down      38     data.frame list   
## sh_shared_ch_down 38     data.frame list   
## up_weights         4     -none-     numeric
## down_weights       4     -none-     numeric
## up_venn            1     Venn       S4     
## down_venn          1     Venn       S4
similar <- sm(compare_de_results(hs_combined_nobatch, hs_combined_fsva, cor_method="spearman"))
similar$limma
## $sh_vs_uninf
## $sh_vs_uninf$logfc
## [1] 0.9922
## 
## $sh_vs_uninf$p
## [1] 0.9105
## 
## $sh_vs_uninf$adjp
## [1] 0.9105
## 
## 
## $chr_vs_uninf
## $chr_vs_uninf$logfc
## [1] 0.9865
## 
## $chr_vs_uninf$p
## [1] 0.904
## 
## $chr_vs_uninf$adjp
## [1] 0.904
## 
## 
## $chr_vs_sh
## $chr_vs_sh$logfc
## [1] 0.9401
## 
## $chr_vs_sh$p
## [1] 0.8631
## 
## $chr_vs_sh$adjp
## [1] 0.07755
similar <- sm(compare_de_results(hs_combined_ssva, hs_combined_fsva, cor_method="spearman"))
similar$limma
## $sh_vs_uninf
## $sh_vs_uninf$logfc
## [1] 0.3141
## 
## $sh_vs_uninf$p
## [1] 0.1535
## 
## $sh_vs_uninf$adjp
## [1] 0.1535
## 
## 
## $chr_vs_uninf
## $chr_vs_uninf$logfc
## [1] 0.3568
## 
## $chr_vs_uninf$p
## [1] 0.1718
## 
## $chr_vs_uninf$adjp
## [1] 0.1718
## 
## 
## $chr_vs_sh
## $chr_vs_sh$logfc
## [1] 0.9893
## 
## $chr_vs_sh$p
## [1] 0.9666
## 
## $chr_vs_sh$adjp
## [1] 0.9664
fsva_up_venn <- Vennerable::plot(common_solos_fsva$up_venn, doWeights=FALSE)

fsva_down_venn <- Vennerable::plot(common_solos_fsva$down_venn, doWeights=FALSE)

5 Try with the combat modified data

old_condition <- hs_uninf$design$condition
names(old_condition) <- hs_uninf$design$sampleid
new_condition <- paste0(hs_uninf$design$state, '_', hs_uninf$design$donor)
combat_input <- set_expt_factors(hs_uninf_filt, batch="pathogenstrain", condition=new_condition)
combat_input <- sm(normalize_expt(combat_input, batch="combat_scale"))
combat_input <- set_expt_condition(combat_input, fact=old_condition)

hs_pairwise_combatpath <- sm(all_pairwise(combat_input, model_batch=FALSE, force=TRUE))
hs_combined_combatpath <- sm(combine_de_tables(hs_pairwise_combatpath,
                                               excel=paste0("excel/hs_infect_combatpath-v", ver, ".xlsx"),
                                               keepers=keepers))
hs_sig_combatpath <- sm(extract_significant_genes(hs_combined_combatpath,
                                                  excel=paste0("excel/hs_infect_combatpath_sig-v", ver, ".xlsx")))
hs_sig_combatpath$deseq$counts
##              change_counts_up change_counts_down
## sh_vs_uninf              2055                  4
## chr_vs_uninf             3017               2389
## chr_vs_sh                 672               1129
common_solos_combatpath <- subset_significants(hs_sig_combatpath)
summary(common_solos_combatpath)
##                   Length Class      Mode   
## sh_solo_up        38     data.frame list   
## ch_solo_up        38     data.frame list   
## sh_shared_ch_up   38     data.frame list   
## sh_solo_down      38     data.frame list   
## ch_solo_down      38     data.frame list   
## sh_shared_ch_down 38     data.frame list   
## up_weights         4     -none-     numeric
## down_weights       4     -none-     numeric
## up_venn            1     Venn       S4     
## down_venn          1     Venn       S4
similar <- sm(compare_de_results(hs_combined_nobatch, hs_combined_combatpath, cor_method="spearman"))
similar$limma
## $sh_vs_uninf
## $sh_vs_uninf$logfc
## [1] -0.03092
## 
## $sh_vs_uninf$p
## [1] -0.09456
## 
## $sh_vs_uninf$adjp
## [1] -0.09457
## 
## 
## $chr_vs_uninf
## $chr_vs_uninf$logfc
## [1] -0.1478
## 
## $chr_vs_uninf$p
## [1] -0.04167
## 
## $chr_vs_uninf$adjp
## [1] -0.04167
## 
## 
## $chr_vs_sh
## $chr_vs_sh$logfc
## [1] -0.1485
## 
## $chr_vs_sh$p
## [1] -0.177
## 
## $chr_vs_sh$adjp
## [1] -0.01484
similar <- sm(compare_de_results(hs_combined_fsva, hs_combined_combatpath, cor_method="spearman"))
similar$limma
## $sh_vs_uninf
## $sh_vs_uninf$logfc
## [1] -0.07044
## 
## $sh_vs_uninf$p
## [1] 0.03195
## 
## $sh_vs_uninf$adjp
## [1] 0.03195
## 
## 
## $chr_vs_uninf
## $chr_vs_uninf$logfc
## [1] -0.1593
## 
## $chr_vs_uninf$p
## [1] 0.1013
## 
## $chr_vs_uninf$adjp
## [1] 0.1013
## 
## 
## $chr_vs_sh
## $chr_vs_sh$logfc
## [1] -0.07519
## 
## $chr_vs_sh$p
## [1] -0.02281
## 
## $chr_vs_sh$adjp
## [1] -0.02287
## OUCH!
combat_up_venn <- Vennerable::plot(common_solos_combatpath$up_venn, doWeights=FALSE)

combat_down_venn <- Vennerable::plot(common_solos_combatpath$down_venn, doWeights=FALSE)

## inf_hsstr is the data set that provided the relatively 'pretty' PCA plots in infection_estimation
hs_inf_strbatch$notes
## [1] "New experimental design factors by snp added 2016-09-20Subsetted with experimentname=='infection' on Thu Aug 31 10:46:18 2017.\nSubsetted with condition!='uninf' on Thu Aug 31 10:46:19 2017.\n"

5.1 Compare DE results

For each of the following, perform a simple DE and see what happens: 1. no uninfected strain as batch, try to compare each of the 3 patients chronic/self 2. no uninfected strain as batch, try to compare chronic/self for all 3. and 4. Repeat with uninfected

5.1.1 DE: include uninfected, use strain as batch

The data used in the following is the quantile(cpm(filter())) where the condition was set to a concatenation of patient and healing state, combat was also performed, so we no longer want batch in the experimental model and also we need to pass ‘force=TRUE’ because deseq/edger will need to be coerced into accepting these modified data.

hs_inf$condition
## chr_5430_d108 chr_5397_d108 chr_2504_d108  sh_2272_d108  sh_1022_d108  sh_2189_d108 
##         "chr"         "chr"         "chr"          "sh"          "sh"          "sh" 
## chr_5430_d110 chr_5397_d110 chr_2504_d110  sh_2272_d110  sh_1022_d110  sh_2189_d110 
##         "chr"         "chr"         "chr"          "sh"          "sh"          "sh" 
## chr_5430_d107 chr_5397_d107 chr_2504_d107  sh_2272_d107  sh_1022_d107  sh_2189_d107 
##         "chr"         "chr"         "chr"          "sh"          "sh"          "sh"
## Start by leaving the data relatively alone, especially noting that we do not have a usable batch
## by default.
hs_uninf_filtv2 <- hs_uninf_filt
donor_state <- paste0(hs_uninf_filtv2$design$state, "_", hs_uninf_filtv2$design$donor)
hs_uninf_filtv2 <- set_expt_factors(hs_uninf_filtv2, condition=donor_state)

uninf_patient_keepers <- list(
    "d107_chun" = c("chronic_d107", "uninfected_d107"),
    "d107_shun" = c("self_heal_d107", "uninfected_d107"),
    "d107_chsh" = c("chronic_d107", "self_heal_d107"),
    "d108_chun" = c("chronic_d108", "uninfected_d108"),
    "d108_shun" = c("self_heal_d108", "uninfected_d108"),
    "d108_chsh" = c("chronic_d108", "self_heal_d108"),
    "d110_chun" = c("chronic_d110", "uninfected_d110"),
    "d110_shun" = c("self_heal_d110", "uninfected_d110"),
    "d110_chsh" = c("chronic_d110", "self_heal_d110"))

hs_uninf_filtv2_pairwise <- sm(all_pairwise(hs_uninf_filtv2, model_batch=FALSE))
hs_uninf_filtv2_combined <- sm(combine_de_tables(hs_uninf_filtv2_pairwise,
                                                 keepers=uninf_patient_keepers,
                                                 excel=paste0("excel/hs_infect_patient_nobatch-v", ver, ".xlsx")))
hs_uninf_filtv2_sig <- sm(extract_significant_genes(hs_uninf_filtv2_combined,
                                                    excel=paste0("excel/hs_infect_patient_nobatch_sig-v", ver, ".xlsx")))

##hs_uninf_filtv3_pairwise <- all_pairwise(hs_uninf_filtv2, model_batch="svaseq", surrogates=1)
##hs_uninf_filtv3_combined <- sm(combine_de_tables(hs_uninf_filtv3_pairwise,
##                                                 keepers=uninf_patient_keepers,
##                                                 excel=paste0("excel/hs_infect_patient_fsva-v", ver, ".xlsx")))
##hs_uninf_filtv3_sig <- sm(extract_significant_genes(hs_uninf_filtv3_combined,
##                                                    excel=paste0("excel/hs_infect_patient_fsva_sig-v", ver, ".xlsx")))

5.2 Make some Venns

They want venns, I’ll given them venns…

comp_people <- function(f, s, t) {
    ddf <- f
    ddf[["rn"]] <- rownames(ddf)
    ddf <- ddf[, c("rn", "deseq_logfc")]
    colnames(ddf) <- c("rn", "first")
    ddf <- merge(ddf, s, by="row.names", all=TRUE)
    rownames(ddf) <- ddf[["Row.names"]]
    ddf <- ddf[, -1]
    ddf <- ddf[, c("first", "deseq_logfc")]
    colnames(ddf) <- c("first", "second")
    ddf <- merge(ddf, t, by="row.names", all=TRUE)
    rownames(ddf) <- ddf[["Row.names"]]
    ddf <- ddf[, -1]
    ddf <- ddf[, c("first", "second", "deseq_logfc")]
    colnames(ddf) <- c("first", "second", "third")
    return(ddf)
}
up_sig <- hs_uninf_filtv2_sig$deseq$ups
sh_un_sig <- comp_people(f=up_sig[["self_heal_d107_vs_uninfected_d107"]],
                         s=up_sig[["self_heal_d108_vs_uninfected_d108"]],
                         t=up_sig[["self_heal_d110_vs_uninfected_d110"]])
upa <- sum(!is.na(sh_un_sig[["first"]]) & is.na(sh_un_sig[["second"]]) & is.na(sh_un_sig[["third"]]))
upb <- sum(is.na(sh_un_sig[["first"]]) & !is.na(sh_un_sig[["second"]]) & is.na(sh_un_sig[["third"]]))
upc <- sum(is.na(sh_un_sig[["first"]]) & is.na(sh_un_sig[["second"]]) & !is.na(sh_un_sig[["third"]]))
upab <- sum(!is.na(sh_un_sig[["first"]]) & !is.na(sh_un_sig[["second"]]) & is.na(sh_un_sig[["third"]]))
upbc <- sum(is.na(sh_un_sig[["first"]]) & !is.na(sh_un_sig[["second"]]) & !is.na(sh_un_sig[["third"]]))
upac <- sum(!is.na(sh_un_sig[["first"]]) & is.na(sh_un_sig[["second"]]) & !is.na(sh_un_sig[["third"]]))
upabc <- sum(!is.na(sh_un_sig[["first"]]) & !is.na(sh_un_sig[["second"]]) & !is.na(sh_un_sig[["third"]]))
up_ones <- c("a" = upa, "b" = upb, "c" = upc)
up_twos <- c("a&b" = upab, "b&c" = upbc, "a&c" = upac)
up_threes <- c("a&b&c" <- upabc)
sh_up_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                               Weight = c(0, upa, upb, upc,
                                          upab, upbc, upac,
                                          upabc))
up_res <- Vennerable::plot(sh_up_venn, doWeights=FALSE)

shared_up_sh <- complete.cases(sh_un_sig)
shared_up_sh <- rownames(sh_un_sig[shared_up_sh, ])

de_table_shared_up_sh_first <- hs_uninf_filtv2_combined[["data"]][["self_heal_d107_vs_uninfected_d107"]][shared_up_sh, ]
de_table_shared_up_sh_second <- hs_uninf_filtv2_combined[["data"]][["self_heal_d108_vs_uninfected_d108"]][shared_up_sh, ]
de_table_shared_up_sh_third <- hs_uninf_filtv2_combined[["data"]][["self_heal_d110_vs_uninfected_d110"]][shared_up_sh, ]
de_table_shared_up_sh_all <- merge(de_table_shared_up_sh_first[, c("description", "deseq_logfc", "deseq_adjp")],
                                   de_table_shared_up_sh_second[, c("deseq_logfc", "deseq_adjp")],
                                   by="row.names")
de_table_shared_up_sh_all <- merge(de_table_shared_up_sh_all,
                                   de_table_shared_up_sh_third[, c("deseq_logfc", "deseq_adjp")],
                                   by.x="Row.names", by.y="row.names")
rownames(de_table_shared_up_sh_all) <- de_table_shared_up_sh_all[["Row.names"]]
de_table_shared_up_sh_all <- de_table_shared_up_sh_all[, -1]
colnames(de_table_shared_up_sh_all) <- c("description", "logfc_107", "adjp_107", "logfc_108", "adjp_108", "logfc_110", "adjp_110")
write.csv(de_table_shared_up_sh_all, file="images/de_table_shared_up_sh_all.csv")
up_sig <- hs_uninf_filtv2_sig$deseq$ups
ch_un_sig <- comp_people(f=up_sig[["chronic_d107_vs_uninfected_d107"]],
                         s=up_sig[["chronic_d108_vs_uninfected_d108"]],
                         t=up_sig[["chronic_d110_vs_uninfected_d110"]])
upa <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upb <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upc <- sum(is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upab <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upbc <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upac <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upabc <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
up_ones <- c("a" = upa, "b" = upb, "c" = upc)
up_twos <- c("a&b" = upab, "b&c" = upbc, "a&c" = upac)
up_threes <- c("a&b&c" <- upabc)
chr_up_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, upa, upb, upc,
                                           upab, upbc, upac,
                                           upabc))
up_res <- Vennerable::plot(chr_up_venn, doWeights=FALSE)

shared_up_ch <- complete.cases(ch_un_sig)
shared_up_ch <- rownames(ch_un_sig[shared_up_ch, ])

de_table_shared_up_ch_first <- hs_uninf_filtv2_combined[["data"]][["chronic_d107_vs_uninfected_d107"]][shared_up_ch, ]
de_table_shared_up_ch_second <- hs_uninf_filtv2_combined[["data"]][["chronic_d108_vs_uninfected_d108"]][shared_up_ch, ]
de_table_shared_up_ch_third <- hs_uninf_filtv2_combined[["data"]][["chronic_d110_vs_uninfected_d110"]][shared_up_ch, ]
de_table_shared_up_ch_all <- merge(de_table_shared_up_ch_first[, c("description", "deseq_logfc", "deseq_adjp")],
                                   de_table_shared_up_ch_second[, c("deseq_logfc", "deseq_adjp")],
                                   by="row.names")
de_table_shared_up_ch_all <- merge(de_table_shared_up_ch_all,
                                   de_table_shared_up_ch_third[, c("deseq_logfc", "deseq_adjp")],
                                   by.x="Row.names", by.y="row.names")
rownames(de_table_shared_up_ch_all) <- de_table_shared_up_ch_all[["Row.names"]]
de_table_shared_up_ch_all <- de_table_shared_up_ch_all[, -1]
colnames(de_table_shared_up_ch_all) <- c("logfc_107", "adjp_107", "logfc_108", "adjp_108", "logfc_110", "adjp_110")
write.csv(de_table_shared_up_ch_all, file="images/de_table_shared_up_ch_all.csv")
down_sig <- hs_uninf_filtv2_sig$deseq$downs
sh_un_sig <- comp_people(f=down_sig[["self_heal_d107_vs_uninfected_d107"]],
                         s=down_sig[["self_heal_d108_vs_uninfected_d108"]],
                         t=down_sig[["self_heal_d110_vs_uninfected_d110"]])
downa <- sum(!is.na(sh_un_sig[["first"]]) & is.na(sh_un_sig[["second"]]) & is.na(sh_un_sig[["third"]]))
downb <- sum(is.na(sh_un_sig[["first"]]) & !is.na(sh_un_sig[["second"]]) & is.na(sh_un_sig[["third"]]))
downc <- sum(is.na(sh_un_sig[["first"]]) & is.na(sh_un_sig[["second"]]) & !is.na(sh_un_sig[["third"]]))
downab <- sum(!is.na(sh_un_sig[["first"]]) & !is.na(sh_un_sig[["second"]]) & is.na(sh_un_sig[["third"]]))
downbc <- sum(is.na(sh_un_sig[["first"]]) & !is.na(sh_un_sig[["second"]]) & !is.na(sh_un_sig[["third"]]))
downac <- sum(!is.na(sh_un_sig[["first"]]) & is.na(sh_un_sig[["second"]]) & !is.na(sh_un_sig[["third"]]))
downabc <- sum(!is.na(sh_un_sig[["first"]]) & !is.na(sh_un_sig[["second"]]) & !is.na(sh_un_sig[["third"]]))
down_ones <- c("a" = downa, "b" = downb, "c" = downc)
down_twos <- c("a&b" = downab, "b&c" = downbc, "a&c" = downac)
down_threes <- c("a&b&c" <- downabc)
sh_down_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, downa, downb, downc,
                                           downab, downbc, downac,
                                           downabc))
sh_down_res <- Vennerable::plot(sh_down_venn, doWeights=FALSE)

shared_down_sh <- complete.cases(sh_un_sig)
shared_down_sh <- rownames(sh_un_sig[shared_down_sh, ])

de_table_shared_down_sh_first <- hs_uninf_filtv2_combined[["data"]][["self_heal_d107_vs_uninfected_d107"]][shared_down_sh, ]
de_table_shared_down_sh_second <- hs_uninf_filtv2_combined[["data"]][["self_heal_d108_vs_uninfected_d108"]][shared_down_sh, ]
de_table_shared_down_sh_third <- hs_uninf_filtv2_combined[["data"]][["self_heal_d110_vs_uninfected_d110"]][shared_down_sh, ]
de_table_shared_down_sh_all <- merge(de_table_shared_down_sh_first[, c("description", "deseq_logfc", "deseq_adjp")],
                                   de_table_shared_down_sh_second[, c("deseq_logfc", "deseq_adjp")],
                                   by="row.names")
de_table_shared_down_sh_all <- merge(de_table_shared_down_sh_all,
                                   de_table_shared_down_sh_third[, c("deseq_logfc", "deseq_adjp")],
                                   by.x="Row.names", by.y="row.names")
rownames(de_table_shared_down_sh_all) <- de_table_shared_down_sh_all[["Row.names"]]
de_table_shared_down_sh_all <- de_table_shared_down_sh_all[, -1]
colnames(de_table_shared_down_sh_all) <- c("description", "logfc_107", "adjp_107", "logfc_108", "adjp_108", "logfc_110", "adjp_110")
write.csv(de_table_shared_down_sh_all, file="images/de_table_shared_down_sh_all.csv")
down_sig <- hs_uninf_filtv2_sig$deseq$downs
ch_un_sig <- comp_people(f=down_sig[["chronic_d107_vs_uninfected_d107"]],
                         s=down_sig[["chronic_d108_vs_uninfected_d108"]],
                         t=down_sig[["chronic_d110_vs_uninfected_d110"]])
downa <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downb <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downc <- sum(is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downab <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downbc <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downac <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downabc <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
down_ones <- c("a" = downa, "b" = downb, "c" = downc)
down_twos <- c("a&b" = downab, "b&c" = downbc, "a&c" = downac)
down_threes <- c("a&b&c" <- downabc)
chr_down_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, downa, downb, downc,
                                           downab, downbc, downac,
                                           downabc))
chr_down_res <- Vennerable::plot(chr_down_venn, doWeights=FALSE)

shared_down_ch <- complete.cases(ch_un_sig)
shared_down_ch <- rownames(ch_un_sig[shared_down_ch, ])

de_table_shared_down_ch_first <- hs_uninf_filtv2_combined[["data"]][["chronic_d107_vs_uninfected_d107"]][shared_down_ch, ]
de_table_shared_down_ch_second <- hs_uninf_filtv2_combined[["data"]][["chronic_d108_vs_uninfected_d108"]][shared_down_ch, ]
de_table_shared_down_ch_third <- hs_uninf_filtv2_combined[["data"]][["chronic_d110_vs_uninfected_d110"]][shared_down_ch, ]
de_table_shared_down_ch_all <- merge(de_table_shared_down_ch_first[, c("description", "deseq_logfc", "deseq_adjp")],
                                   de_table_shared_down_ch_second[, c("deseq_logfc", "deseq_adjp")],
                                   by="row.names")
de_table_shared_down_ch_all <- merge(de_table_shared_down_ch_all,
                                   de_table_shared_down_ch_third[, c("deseq_logfc", "deseq_adjp")],
                                   by.x="Row.names", by.y="row.names")
rownames(de_table_shared_down_ch_all) <- de_table_shared_down_ch_all[["Row.names"]]
de_table_shared_down_ch_all <- de_table_shared_down_ch_all[, -1]
colnames(de_table_shared_down_ch_all) <- c("logfc_107", "adjp_107", "logfc_108", "adjp_108", "logfc_110", "adjp_110")
write.csv(de_table_shared_down_ch_all, file="images/de_table_shared_down_ch_all.csv")
upupgenes <- intersect(shared_up_sh, shared_up_ch)
upup <- length(upupgenes)
upsh_notch <- !shared_up_sh %in% shared_up_ch
upsh_notch <- shared_up_sh[upsh_notch]
upch_notsh <- !shared_up_ch %in% shared_up_sh
upch_notsh <- shared_up_ch[upch_notsh]
## upnot and length(upsh_notch) should be equivalent.
upnot <- sum(! shared_up_sh %in% shared_up_ch)
notup <- sum(! shared_up_ch %in% shared_up_sh)
shared_up <- Vennerable::Venn(SetNames=c("up_sh", "up_ch"),
                              Weight=c(0, upnot, notup, upup))
Vennerable::plot(shared_up, doWeights=FALSE)

downdowngenes <- intersect(shared_down_sh, shared_down_ch)
downdown <- length(downdowngenes)
downsh_notch <- !shared_down_sh %in% shared_down_ch
downsh_notch <- shared_down_sh[downsh_notch]
downch_notsh <- !shared_down_ch %in% shared_down_sh
downch_notsh <- shared_down_ch[downch_notsh]
## downnot and length(downsh_notch) should be equivalent.
downnot <- sum(! shared_down_sh %in% shared_down_ch)
notdown <- sum(! shared_down_ch %in% shared_down_sh)
shared_down <- Vennerable::Venn(SetNames=c("down_sh", "down_ch"),
                              Weight=c(0, downnot, notdown, downdown))
Vennerable::plot(shared_down, doWeights=FALSE)

kept_columns <- c("transcriptid", "geneid", "description", "deseq_logfc", "deseq_adjp")
xls_result <- write_xls(data=up_sig[["self_heal_d107_vs_uninfected_d107"]][upupgenes, kept_columns],
                        sheet="upsh_upch")
xls_result <- write_xls(data=up_sig[["self_heal_d107_vs_uninfected_d107"]][upsh_notch, kept_columns],
                        sheet="upsh_noch",
                        wb=xls_result[["workbook"]])
xls_result <- write_xls(data=up_sig[["chronic_d107_vs_uninfected_d107"]][upch_notsh, kept_columns],
                        sheet="upch_nosh", wb=xls_result[["workbook"]])
xls_result <- write_xls(data=down_sig[["self_heal_d107_vs_uninfected_d107"]][downdowngenes, kept_columns],
                        sheet="downsh_downch", wb=xls_result[["workbook"]])
xls_result <- write_xls(data=down_sig[["self_heal_d107_vs_uninfected_d107"]][downsh_notch, kept_columns],
                        sheet="downsh_noch", wb=xls_result[["workbook"]])
xls_result <- write_xls(data=down_sig[["chronic_d107_vs_uninfected_d107"]][downch_notsh, kept_columns],
                        sheet="downch_nosh", wb=xls_result[["workbook"]],
                        excel=paste0("excel/figure_5c_stuff-v", ver, ".xlsx"))
## Saving to: excel/figure_5c_stuff-v20170820.xlsx
up_sig <- hs_uninf_filtv2_sig$deseq$ups
ch_un_sig <- comp_people(f=up_sig[["self_heal_d107_vs_uninfected_d107"]],
                         s=up_sig[["self_heal_d108_vs_uninfected_d108"]],
                         t=up_sig[["self_heal_d110_vs_uninfected_d110"]])
upa <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upb <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upc <- sum(is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upab <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upbc <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upac <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upabc <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
up_ones <- c("a" = upa, "b" = upb, "c" = upc)
up_twos <- c("a&b" = upab, "b&c" = upbc, "a&c" = upac)
up_threes <- c("a&b&c" <- upabc)
up_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, upa, upb, upc,
                                           upab, upbc, upac,
                                           upabc))
up_res <- Vennerable::plot(up_venn, doWeights=FALSE)

down_sig <- hs_uninf_filtv2_sig$deseq$downs
ch_un_sig <- comp_people(f=down_sig[["self_heal_d107_vs_uninfected_d107"]],
                         s=down_sig[["self_heal_d108_vs_uninfected_d108"]],
                         t=down_sig[["self_heal_d110_vs_uninfected_d110"]])
downa <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downb <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downc <- sum(is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downab <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downbc <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downac <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downabc <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
down_ones <- c("a" = downa, "b" = downb, "c" = downc)
down_twos <- c("a&b" = downab, "b&c" = downbc, "a&c" = downac)
down_threes <- c("a&b&c" <- downabc)
down_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, downa, downb, downc,
                                           downab, downbc, downac,
                                           downabc))
down_res <- Vennerable::plot(down_venn, doWeights=FALSE)

up_sig <- hs_uninf_filtv2_sig$deseq$ups
ch_un_sig <- comp_people(f=up_sig[["chronic_d107_vs_self_heal_d107"]],
                         s=up_sig[["chronic_d108_vs_self_heal_d108"]],
                         t=up_sig[["chronic_d110_vs_self_heal_d110"]])
upa <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upb <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upc <- sum(is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upab <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upbc <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upac <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upabc <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
up_ones <- c("a" = upa, "b" = upb, "c" = upc)
up_twos <- c("a&b" = upab, "b&c" = upbc, "a&c" = upac)
up_threes <- c("a&b&c" <- upabc)
up_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, upa, upb, upc,
                                           upab, upbc, upac,
                                           upabc))
up_res <- Vennerable::plot(up_venn, doWeights=FALSE)

down_sig <- hs_uninf_filtv2_sig$deseq$downs
ch_un_sig <- comp_people(f=down_sig[["chronic_d107_vs_self_heal_d107"]],
                         s=down_sig[["chronic_d108_vs_self_heal_d108"]],
                         t=down_sig[["chronic_d110_vs_self_heal_d110"]])
downa <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downb <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downc <- sum(is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downab <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downbc <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downac <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downabc <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
down_ones <- c("a" = downa, "b" = downb, "c" = downc)
down_twos <- c("a&b" = downab, "b&c" = downbc, "a&c" = downac)
down_threes <- c("a&b&c" <- downabc)
down_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, downa, downb, downc,
                                           downab, downbc, downac,
                                           downabc))
down_res <- Vennerable::plot(down_venn, doWeights=FALSE)

up_sig <- hs_uninf_filtv3_sig$deseq$ups
ch_un_sig <- comp_people(f=up_sig[["chronic_d107_vs_uninfected_d107"]],
                         s=up_sig[["chronic_d108_vs_uninfected_d108"]],
                         t=up_sig[["chronic_d110_vs_uninfected_d110"]])
upa <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upb <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upc <- sum(is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upab <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
upbc <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upac <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
upabc <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
up_ones <- c("a" = upa, "b" = upb, "c" = upc)
up_twos <- c("a&b" = upab, "b&c" = upbc, "a&c" = upac)
up_threes <- c("a&b&c" <- upabc)
up_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, upa, upb, upc,
                                           upab, upbc, upac,
                                           upabc))
up_res <- Vennerable::plot(up_venn, doWeights=FALSE)

down_sig <- hs_uninf_filtv3_sig$deseq$downs
ch_un_sig <- comp_people(f=down_sig[["chronic_d107_vs_uninfected_d107"]],
                         s=down_sig[["chronic_d108_vs_uninfected_d108"]],
                         t=down_sig[["chronic_d110_vs_uninfected_d110"]])
downa <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downb <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downc <- sum(is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downab <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & is.na(ch_un_sig[["third"]]))
downbc <- sum(is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downac <- sum(!is.na(ch_un_sig[["first"]]) & is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
downabc <- sum(!is.na(ch_un_sig[["first"]]) & !is.na(ch_un_sig[["second"]]) & !is.na(ch_un_sig[["third"]]))
down_ones <- c("a" = downa, "b" = downb, "c" = downc)
down_twos <- c("a&b" = downab, "b&c" = downbc, "a&c" = downac)
down_threes <- c("a&b&c" <- downabc)
down_venn <- Vennerable::Venn(SetNames = c("a", "b", "c"),
                                Weight = c(0, downa, downb, downc,
                                           downab, downbc, downac,
                                           downabc))
down_res <- Vennerable::plot(down_venn, doWeights=FALSE)

5.2.1 DE: include uninfected, repeat with condition simplified to chronic/self

Do I think the exact same thing as in the previous comparison, but now simplify the ‘condition’ factor to just self-healing vs. chronic and see what happens.

uninf_strainbatch_qcf <- set_expt_batch(expt=uninf_cqf, fact="pathogenstrain")
uninf_strainbatch_qcf <- set_expt_condition(expt=uninf_strainbatch_qcf, fact="state")
withuninf_strainbatch_pairs_chsh <- all_pairwise(uninf_strainbatch_qcf,
                                                 model_batch=FALSE, force=TRUE)
chsh_keepers <- list(
    "ch_sh" = c("chronic", "self_heal"),
    "ch_nil" = c("chronic", "uninfected"),
    "sh_nil" = c("self_heal", "uninfected"))
withuninf_strainbatch_tables_chsh <- sm(combine_de_tables(withuninf_strainbatch_pairs_chsh,
                                                          keepers=chsh_keepers,
                                                          excel=paste0("excel/withuninf_strainbatch_chsh_pairwise-v", ver, ".xlsx")))
withuninf_strainbatch_sig_chsh <- extract_significant_genes(withuninf_strainbatch_tables_chsh,
                                                            excel=paste0("excel/withuninf_strainbatch_chsh_sig-v", ver, ".xlsx"))
##withuninf_strainbatch_tables_chsh$limma_plots
##withuninf_strainbatch_tables_chsh$edger_plots
##withuninf_strainbatch_tables_chsh$deseq_plots

6 Figure 5

Generate DE lists of each donor for all contrasts for PBMCs.

  1. Venn sh/uninf vs chr/uninf 2 venn diagram up. (donor in model)
  2. Venn sh/uninf vs chr/uninf 2 venn diagram down.
  3. Venn Sh/uninf up genes 3 venn diagram.
  4. Venn Sh/uninf down genes 3 venn.
  5. Venn Chr/uninf up genes 3 venn.
  6. Venn Chr/uninf down genes 3 venn.
  7. 2 way venn of (common up in 3 venn sh/uninf) vs. (common up in 3 venn chr/uninf)
  8. 2 way venn of (common down in 3 venn sh/uninf) vs. (common down in 3 venn chr/uninf)
pp(file="images/fig_05a-sh_uninf_vs_chr_uninf_up.pdf")
## NULL
Vennerable::plot(common_solos_batch$up_venn, doWeights=FALSE)
dev.off()
## png 
##   2
pp(file="images/fig_05b-sh_uninf_vs_chr_uninf_down.pdf")
## NULL
Vennerable::plot(common_solos_batch$down_venn, doWeights=FALSE)
dev.off()
## png 
##   2
pp(file="images/fig_05c-sh_uninf_donors_up.pdf")
## NULL
Vennerable::plot(sh_up_venn, doWeights=FALSE)
dev.off()
## png 
##   2
pp(file="images/fig_05d-sh_uninf_donors_down.pdf")
## NULL
Vennerable::plot(sh_down_venn, doWeights=FALSE)
dev.off()
## png 
##   2
pp(file="images/fig_05e-chr_uninf_donors_up.pdf")
## NULL
Vennerable::plot(chr_up_venn, doWeights=FALSE)
dev.off()
## png 
##   2
pp(file="images/fig_05f-chr_uninf_donors_down.pdf")
## NULL
Vennerable::plot(chr_down_venn, doWeights=FALSE)
dev.off()
## png 
##   2
pp(file="images/fig_05g-up_common.pdf")
## NULL
Vennerable::plot(shared_up, doWeights=FALSE)
dev.off()
## png 
##   2
pp(file="images/fig_05h-down_common.pdf")
## NULL
Vennerable::plot(shared_down, doWeights=FALSE)
dev.off()
## png 
##   2

7 Table Szzz

Tables of the stuff in figure 5

funkytown <- hpgltools:::compare_logfc_plots(withuninf_strainbatch_tables_chsh)
funkytown$ch_nil$le
funkytown$ch_nil$ld
funkytown$ch_nil$de

8 Try again on the parasite data

8.1 Remember our data set

lp_inf_filt <- sm(normalize_expt(lp_inf, filter=TRUE))
lp_pairwise_nobatch <- sm(all_pairwise(lp_inf_filt, model_batch=FALSE))
lp_combined_nobatch <- sm(combine_de_tables(lp_pairwise_nobatch,
                                            excel=paste0("excel/lp_infect_nobatch-v", ver, ".xlsx")))

lp_sig_nobatch <- sm(extract_significant_genes(lp_combined_nobatch,
                                               excel=paste0("excel/lp_infect_nobatch_sig-v", ver, ".xlsx")))
lp_pairwise_batch <- sm(all_pairwise(lp_inf_filt, model_batch=TRUE))
lp_combined_batch <- sm(combine_de_tables(lp_pairwise_batch,
                                          excel=paste0("excel/lp_infect_batch-v", ver, ".xlsx")))

lp_sig_batch <- sm(extract_significant_genes(lp_combined_batch,
                                             excel=paste0("excel/lp_infect_batch_sig-v", ver, ".xlsx")))
lp_pairwise_ssva <- sm(all_pairwise(lp_inf_filt, model_batch="ssva"))
lp_combined_ssva <- sm(combine_de_tables(lp_pairwise_ssva,
                                         excel=paste0("excel/lp_infect_ssva-v", ver, ".xlsx")))

lp_sig_ssva <- sm(extract_significant_genes(lp_combined_ssva,
                                             excel=paste0("excel/lp_infect_ssva_sig-v", ver, ".xlsx")))
lp_pairwise_fsva <- sm(all_pairwise(lp_inf_filt, model_batch="fsva"))
lp_combined_fsva <- sm(combine_de_tables(lp_pairwise_fsva,
                                         excel=paste0("excel/lp_infect_fsva-v", ver, ".xlsx")))

lp_sig_fsva <- sm(extract_significant_genes(lp_combined_fsva,
                                             excel=paste0("excel/lp_infect_fsva_sig-v", ver, ".xlsx")))

index.html 02_infection_estimation.html

pander::pander(sessionInfo())

R version 3.4.1 (2017-06-30)

**Platform:** x86_64-pc-linux-gnu (64-bit)

locale: LC_CTYPE=en_US.utf8, LC_NUMERIC=C, LC_TIME=en_US.utf8, LC_COLLATE=en_US.utf8, LC_MONETARY=en_US.utf8, LC_MESSAGES=en_US.utf8, LC_PAPER=en_US.utf8, LC_NAME=C, LC_ADDRESS=C, LC_TELEPHONE=C, LC_MEASUREMENT=en_US.utf8 and LC_IDENTIFICATION=C

attached base packages: stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: ruv(v.0.9.6), Vennerable(v.3.1.0.9000) and hpgltools(v.2017.01)

loaded via a namespace (and not attached): minqa(v.1.2.4), colorspace(v.1.3-2), colorRamps(v.2.3), rprojroot(v.1.2), htmlTable(v.1.9), corpcor(v.1.6.9), XVector(v.0.16.0), GenomicRanges(v.1.28.4), base64enc(v.0.1-3), roxygen2(v.6.0.1), ggrepel(v.0.6.5), bit64(v.0.9-7), AnnotationDbi(v.1.38.2), xml2(v.1.1.1), codetools(v.0.2-15), splines(v.3.4.1), doParallel(v.1.0.10), geneplotter(v.1.54.0), knitr(v.1.17), Formula(v.1.2-2), nloptr(v.1.0.4), Rsamtools(v.1.28.0), pbkrtest(v.0.4-7), annotate(v.1.54.0), cluster(v.2.0.6), graph(v.1.54.0), compiler(v.3.4.1), backports(v.1.1.0), Matrix(v.1.2-11), lazyeval(v.0.2.0), limma(v.3.32.5), acepack(v.1.4.1), htmltools(v.0.3.6), tools(v.3.4.1), gtable(v.0.2.0), GenomeInfoDbData(v.0.99.0), reshape2(v.1.4.2), Rcpp(v.0.12.12), Biobase(v.2.36.2), Biostrings(v.2.44.2), gdata(v.2.18.0), preprocessCore(v.1.38.1), nlme(v.3.1-131), rtracklayer(v.1.36.4), iterators(v.1.0.8), stringr(v.1.2.0), openxlsx(v.4.0.17), testthat(v.1.0.2), lme4(v.1.1-13), gtools(v.3.5.0), devtools(v.1.13.3), XML(v.3.98-1.9), edgeR(v.3.18.1), directlabels(v.2017.03.31), zlibbioc(v.1.22.0), MASS(v.7.3-47), scales(v.0.5.0), BiocInstaller(v.1.26.0), parallel(v.3.4.1), SummarizedExperiment(v.1.6.3), RBGL(v.1.52.0), RColorBrewer(v.1.1-2), yaml(v.2.1.14), memoise(v.1.1.0), gridExtra(v.2.2.1), pander(v.0.6.1), ggplot2(v.2.2.1), biomaRt(v.2.32.1), rpart(v.4.1-11), latticeExtra(v.0.6-28), stringi(v.1.1.5), RSQLite(v.2.0), genefilter(v.1.58.1), S4Vectors(v.0.14.3), foreach(v.1.4.3), checkmate(v.1.8.3), GenomicFeatures(v.1.28.4), caTools(v.1.17.1), BiocGenerics(v.0.22.0), BiocParallel(v.1.10.1), GenomeInfoDb(v.1.12.2), rlang(v.0.1.2), commonmark(v.1.2), matrixStats(v.0.52.2), bitops(v.1.0-6), evaluate(v.0.10.1), lattice(v.0.20-35), GenomicAlignments(v.1.12.2), htmlwidgets(v.0.9), labeling(v.0.3), bit(v.1.1-12), plyr(v.1.8.4), magrittr(v.1.5), variancePartition(v.1.6.0), DESeq2(v.1.16.1), R6(v.2.2.2), IRanges(v.2.10.2), gplots(v.3.0.1), Hmisc(v.4.0-3), DelayedArray(v.0.2.7), DBI(v.0.7), mgcv(v.1.8-19), foreign(v.0.8-69), withr(v.2.0.0), survival(v.2.41-3), RCurl(v.1.95-4.8), nnet(v.7.3-12), tibble(v.1.3.4), crayon(v.1.3.2), KernSmooth(v.2.23-15), OrganismDbi(v.1.18.0), rmarkdown(v.1.6), locfit(v.1.5-9.1), grid(v.3.4.1), sva(v.3.24.4), data.table(v.1.10.4), blob(v.1.1.0), digest(v.0.6.12), xtable(v.1.8-2), stats4(v.3.4.1), munsell(v.0.4.3) and quadprog(v.1.5-5)

message(paste0("This is hpgltools commit: ", get_git_commit()))
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 739e4a10345a89efb17b37e7de07c5811491ccea
## R> packrat::restore()
## This is hpgltools commit: Thu Aug 31 11:24:06 2017 -0400: 739e4a10345a89efb17b37e7de07c5811491ccea
this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
message(paste0("Saving to ", this_save))
## Saving to 03_expression_infection-v20170820.rda.xz
tmp <- sm(saveme(filename=this_save))
LS0tCnRpdGxlOiAiUk5Bc2VxIG9mIEwucGFuYW1lbnNpczogUEJNQyBJbmZlY3Rpb24gRGlmZmVyZW50aWFsIEV4cHJlc3Npb24uIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiBodG1sX2RvY3VtZW50OgogIGNvZGVfZG93bmxvYWQ6IHRydWUKICBjb2RlX2ZvbGRpbmc6IHNob3cKICBmaWdfY2FwdGlvbjogdHJ1ZQogIGZpZ19oZWlnaHQ6IDcKICBmaWdfd2lkdGg6IDcKICBoaWdobGlnaHQ6IGRlZmF1bHQKICBrZWVwX21kOiBmYWxzZQogIG1vZGU6IHNlbGZjb250YWluZWQKICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogIHRoZW1lOiByZWFkYWJsZQogIHRvYzogdHJ1ZQogIHRvY19mbG9hdDoKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4Owp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KCJocGdsdG9vbHMiKQp0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICB3aWR0aD05MCwKICAgICAgICAgICAgICAgICAgICAgZWNobz1UUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoZXJyb3I9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aD04LAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodD04LAogICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQpvcHRpb25zKGRpZ2l0cz00LAogICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsPSJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpzZXQuc2VlZCgxKQpwcmV2aW91c19maWxlIDwtICIwMl9lc3RpbWF0aW9uX2luZmVjdGlvbi5SbWQiCnZlciA8LSAiMjAxNzA4MjAiCgp0bXAgPC0gc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpCgpybWRfZmlsZSA8LSAiMDNfZXhwcmVzc2lvbl9pbmZlY3Rpb24uUm1kIgpgYGAKCmBgYHtyIHJlbmRlciwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kcm1hcmtkb3duOjpyZW5kZXIocm1kX2ZpbGUpCgpybWFya2Rvd246OnJlbmRlcihybWRfZmlsZSwgb3V0cHV0X2Zvcm1hdD0icGRmX2RvY3VtZW50IikKYGBgCgpbaW5kZXguaHRtbF0oaW5kZXguaHRtbCkKWzAxX2Fubm90YXRpb24uaHRtbF0oMDFfYW5ub3RhdGlvbi5odG1sKQpbMDJfZXN0aW1hdGlvbl9pbmZlY3Rpb24uaHRtbF0oMDJfZXN0aW1hdGlvbl9pbmZlY3Rpb24uaHRtbCkKCiMgUEJNQyBJbmZlY3Rpb24gRGlmZmVyZW50aWFsIEV4cHJlc3Npb24sIEluZmVjdGlvbjogYHIgdmVyYAoKVGhpcyBkb2N1bWVudCB0dXJucyB0byB0aGUgaW5mZWN0aW9uIG9mIFBCTUMgY2VsbHMgd2l0aCBMLnBhbmFtZW5zaXMuICBUaGlzIGRhdGEKaXMgcGFydGljdWxhcmx5IHN0cmFuZ2VseSBhZmZlY3RlZCBieSB0aGUgZGlmZmVyZW50IHN0cmFpbnMgdXNlZCB0byBpbmZlY3QgdGhlCmNlbGxzLCBhbmQgYXMgYSByZXN1bHQgaXMgYm90aCB1c2VmdWwgYW5kIHRyb3VibGluZy4KCkdpdmVuIHRoZSBvYnNlcnZhdGlvbnMgYWJvdmUsIHdlIGhhdmUgc29tZSBpZGVhcyBvZiB3YXlzIHRvIHBhc3MgdGhlIGRhdGEgZm9yCmRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2VzIHdoaWNoIG1heSBvciBtYXkgbm90IGJlICdiZXR0ZXInLiAgTGV0cyB0cnkKc29tZSBhbmQgc2VlIHdoYXQgaGFwcGVucy4KCiMjIENyZWF0ZSBkYXRhIHNldHMgdG8gY29tcGFyZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNlcwoKR2l2ZW4gdGhlIGFib3ZlIHdheXMgdG8gbWFzc2FnZSB0aGUgZGF0YSwgbGV0cyB1c2UgYSBmZXcgb2YgdGhlbSBmb3IKbGltbWEvZGVzZXEvZWRnZXIuIFRoZSBtYWluIGNhdmVhdCBpbiB0aGlzIGlzIHRoYXQgdGhvc2UgdG9vbHMgcmVhbGx5IGRvIGV4cGVjdApzcGVjaWZpYyBkaXN0cmlidXRpb25zIG9mIGRhdGEgd2hpY2ggd2UgaG9ycmlibHkgdmlvbGF0ZSBpZiB3ZSB1c2UgbG9nMigpIGRhdGEsCndoaWNoIGlzIHdoeSBpbiB0aGUgcHJldmlvdXMgYmxvY2tzIEkgbmFtZWQgdGhlbSBsMmJsYWhibGFoLCB0aHVzIHdlIGNhbiBkbyB0aGUKc2FtZSBzZXRzIG9mIG5vcm1hbGl6YXRpb24gYnV0IHdpdGhvdXQgdGhhdCBhbmQgZm9yY2libHkgcHVzaCB0aGUgcmVzdWx0aW5nIGRhdGEKaW50byBsaW1tYS9lZGdlci9kZXNlcS4KCiMgVGhlIG5lZ2F0aXZlIGNvbnRyb2wKCkV2ZXJ5dGhpbmcgSSBkaWQgaW4gMDJfZXN0aW1hdGlvbl9pbmZlY3Rpb24uaHRtbCBzdWdnZXN0cyB0aGF0IHRoZXJlIGFyZSBubwpzaWduaWZpY2FudCBkaWZmZXJlbmNlcyB2aXNpYmxlIGlmIG9uZSBsb29rcyBqdXN0IGF0IGNocm9uaWMvc2VsZi1oZWFsaW5nIGluCnRoaXMgZGF0YS4gIEZ1cnRoZXIgdGVzdGluZyBoYXMgc2VlbWluZ2x5IHByb3ZlbiB0aGlzIHN0YXRlbWVudCwgYXMgYSByZXN1bHQKbW9zdCBvZiB0aGUgZm9sbG93aW5nIGFuYWx5c2VzIHdpbGwgbG9vayBhdCBjaHJvbmljL3VuaW5mZWN0ZWQgYW5kIApzZWxmLWhlYWxpbmcvdW5pbmZlY3RlZCBmb2xsb3dlZCBieSBhdHRlbXB0cyB0byByZWNvbmNpbGUgdGhvc2UgcmVzdWx0cy4KCiMjIEZpbHRlciB0aGUgZGF0YQoKVG8gc2F2ZSBzb21lIHRpbWUgYW5kIGFubm95YW5jZSB3aXRoIHN2YSwgbGV0cyBmaWx0ZXIgdGhlIGRhdGEgbm93LiAgSW4gYWRkaXRpb24sIHdyaXRlCmRvd24gYSBzbWFsbCBmdW5jdGlvbiB1c2VkIHRvIGV4dHJhY3QgdGhlIHNldHMgb2Ygc2lnbmlmaWNhbnQgZ2VuZXMgYWNyb3NzIGRpZmZlcmVudApjb250cmFzdHMgKG5vdGFibHkgc2VsZi91bmluZmVjdGVkIHZzLiBjaHJvbmljL3VuaW5mZWN0ZWQpLgoKYGBge3IgZmlsdGVyfQpoc19pbmZfZmlsdCA8LSBzbShub3JtYWxpemVfZXhwdChoc19pbmYsIGZpbHRlcj1UUlVFKSkKaHNfdW5pbmZfZmlsdCA8LSBzbShub3JtYWxpemVfZXhwdChoc191bmluZiwgZmlsdGVyPVRSVUUpKQprZWVwZXJzIDwtIGxpc3QoInNoX25pbCIgPSBjKCJzaCIsICJ1bmluZiIpLAogICAgICAgICAgICAgICAgImNoX25pbCIgPSBjKCJjaHIiLCAidW5pbmYiKSwKICAgICAgICAgICAgICAgICJjaF9zaCIgPSBjKCJjaHIiLCAic2giKSkKCnN1YnNldF9zaWduaWZpY2FudHMgPC0gZnVuY3Rpb24oaHNfc2lnKSB7CiAgICBzaF9uaWxfdXBfZ2VuZXMgPC0gcm93bmFtZXMoaHNfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJzaF92c191bmluZiJdXSkKICAgIGNoX25pbF91cF9nZW5lcyA8LSByb3duYW1lcyhoc19zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbImNocl92c191bmluZiJdXSkKICAgIHNoX25pbF9kb3duX2dlbmVzIDwtIHJvd25hbWVzKGhzX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJzaF92c191bmluZiJdXSkKICAgIGNoX25pbF9kb3duX2dlbmVzIDwtIHJvd25hbWVzKGhzX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJjaHJfdnNfdW5pbmYiXV0pCgogICAgc2hfc29sb191cF9pZHggPC0gISBzaF9uaWxfdXBfZ2VuZXMgJWluJSBjaF9uaWxfdXBfZ2VuZXMKICAgIHNoX3NvbG9fdXAgPC0gc2hfbmlsX3VwX2dlbmVzW3NoX3NvbG9fdXBfaWR4XQogICAgc2hfc2hhcmVkX2NoX2lkeCA8LSBzaF9uaWxfdXBfZ2VuZXMgJWluJSBjaF9uaWxfdXBfZ2VuZXMKICAgIHNoX3NoYXJlZF9jaF91cCA8LSBzaF9uaWxfdXBfZ2VuZXNbc2hfc2hhcmVkX2NoX2lkeF0KICAgIGNoX3NvbG9fdXBfaWR4IDwtICEgY2hfbmlsX3VwX2dlbmVzICVpbiUgc2hfbmlsX3VwX2dlbmVzCiAgICBjaF9zb2xvX3VwIDwtIGNoX25pbF91cF9nZW5lc1tjaF9zb2xvX3VwX2lkeF0KCiAgICBzaF9zb2xvX2Rvd25faWR4IDwtICEgc2hfbmlsX2Rvd25fZ2VuZXMgJWluJSBjaF9uaWxfZG93bl9nZW5lcwogICAgc2hfc29sb19kb3duIDwtIHNoX25pbF9kb3duX2dlbmVzW3NoX3NvbG9fZG93bl9pZHhdCiAgICBzaF9zaGFyZWRfY2hfaWR4IDwtIHNoX25pbF9kb3duX2dlbmVzICVpbiUgY2hfbmlsX2Rvd25fZ2VuZXMKICAgIHNoX3NoYXJlZF9jaF9kb3duIDwtIHNoX25pbF9kb3duX2dlbmVzW3NoX3NoYXJlZF9jaF9pZHhdCiAgICBjaF9zb2xvX2Rvd25faWR4IDwtICEgY2hfbmlsX2Rvd25fZ2VuZXMgJWluJSBzaF9uaWxfZG93bl9nZW5lcwogICAgY2hfc29sb19kb3duIDwtIGNoX25pbF9kb3duX2dlbmVzW2NoX3NvbG9fZG93bl9pZHhdCgogICAgcmV0bGlzdCA8LSBsaXN0KAogICAgICAgICJzaF9zb2xvX3VwIiA9IGhzX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sic2hfdnNfdW5pbmYiXV1bc2hfc29sb191cCwgXSwKICAgICAgICAiY2hfc29sb191cCIgPSBoc19zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbImNocl92c191bmluZiJdXVtjaF9zb2xvX3VwLCBdLAogICAgICAgICJzaF9zaGFyZWRfY2hfdXAiID0gaHNfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJzaF92c191bmluZiJdXVtzaF9zaGFyZWRfY2hfdXAsIF0sCiAgICAgICAgInNoX3NvbG9fZG93biIgPSBoc19zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sic2hfdnNfdW5pbmYiXV1bc2hfc29sb19kb3duLCBdLAogICAgICAgICJjaF9zb2xvX2Rvd24iID0gaHNfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbImNocl92c191bmluZiJdXVtjaF9zb2xvX2Rvd24sIF0sCiAgICAgICAgInNoX3NoYXJlZF9jaF9kb3duIiA9IGhzX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJzaF92c191bmluZiJdXVtzaF9zaGFyZWRfY2hfZG93biwgXSkKICAgIHJldGxpc3RbWyJ1cF93ZWlnaHRzIl1dIDwtIGMoMCwgbnJvdyhyZXRsaXN0W1sic2hfc29sb191cCJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5yb3cocmV0bGlzdFtbImNoX3NvbG9fdXAiXV0pLCBucm93KHJldGxpc3RbWyJzaF9zaGFyZWRfY2hfdXAiXV0pKQogICAgcmV0bGlzdFtbImRvd25fd2VpZ2h0cyJdXSA8LSBjKDAsIG5yb3cocmV0bGlzdFtbInNoX3NvbG9fZG93biJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5yb3cocmV0bGlzdFtbImNoX3NvbG9fZG93biJdXSksIG5yb3cocmV0bGlzdFtbInNoX3NoYXJlZF9jaF9kb3duIl1dKSkKICAgIHJldGxpc3RbWyJ1cF92ZW5uIl1dIDwtIFZlbm5lcmFibGU6OlZlbm4oU2V0TmFtZXMgPSBjKCJzaCIsICJjaHIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV2VpZ2h0ID0gcmV0bGlzdFtbInVwX3dlaWdodHMiXV0pCiAgICByZXRsaXN0W1siZG93bl92ZW5uIl1dIDwtIFZlbm5lcmFibGU6OlZlbm4oU2V0TmFtZXMgPSBjKCJzaCIsICJjaHIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXZWlnaHQgPSByZXRsaXN0W1siZG93bl93ZWlnaHRzIl1dKQogICAgcmV0dXJuKHJldGxpc3QpCn0KYGBgCgojIyBEbyBhIGNvbXBsZXRlbHkgbm9ybWFsIGxpbW1hIGludm9jYXRpb24uCgpUaGUgZm9sbG93aW5nIHByb2JhYmx5IHNob3VsZCBub3QgYmUgdXNlZC4KCmBgYHtyIG5vcm1hbF9saW1tYSwgZXZhbD1GQUxTRX0KY291bnRzIDwtIGV4cHJzKGhzX3VuaW5mX2ZpbHQpCmRlc2lnbiA8LSBwRGF0YShoc191bmluZl9maWx0KQptb2RlbCA8LSBtb2RlbC5tYXRyaXgofiAwICsgY29uZGl0aW9uICsgZG9ub3IgKyBwYXRob2dlbnN0cmFpbiwgZGF0YT1kZXNpZ24pCnZvb21fd2VpZ2h0X3Jlc3VsdCA8LSBsaW1tYTo6dm9vbVdpdGhRdWFsaXR5V2VpZ2h0cyhjb3VudHM9Y291bnRzLCBkZXNpZ249bW9kZWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemUubWV0aG9kPSJxdWFudGlsZSIsIHBsb3Q9VFJVRSkKdm9vbV9yZXN1bHQgPC0gbGltbWE6OnZvb20oY291bnRzPWNvdW50cywgZGVzaWduPW1vZGVsLCBub3JtYWxpemUubWV0aG9kPSJxdWFudGlsZSIsIHBsb3Q9VFJVRSkKZml0dGluZ193ZWlnaHQgPC0gbGltbWE6OmxtRml0KG9iamVjdD12b29tX3dlaWdodF9yZXN1bHQsIGRlc2lnbj1tb2RlbCwgbWV0aG9kPSJscyIpCmZpdHRpbmcgPC0gbGltbWE6OmxtRml0KG9iamVjdD12b29tX3Jlc3VsdCwgZGVzaWduPW1vZGVsLCBtZXRob2Q9ImxzIikKY29udHJhc3QgPC0gbGltbWE6Om1ha2VDb250cmFzdHMoc2hfY2g9Y29uZGl0aW9ucGJtY19zaC1jb25kaXRpb25wYm1jX2NoLCBsZXZlbHM9bW9kZWwpCmNvbnRyYXN0X3dlaWdodCA8LSBsaW1tYTo6Y29udHJhc3RzLmZpdChmaXQ9Zml0dGluZ193ZWlnaHQsIGNvbnRyYXN0cz1jb250cmFzdCkKY29udHJhc3QgPC0gbGltbWE6OmNvbnRyYXN0cy5maXQoZml0PWZpdHRpbmcsIGNvbnRyYXN0cz1jb250cmFzdCkKZWJheWVzX3dlaWdodGVkIDwtIGxpbW1hOjplQmF5ZXMoY29udHJhc3Rfd2VpZ2h0KQplYmF5ZXMgPC0gbGltbWE6OmVCYXllcyhjb250cmFzdCkKdG9wdGFibGVfd2VpZ2h0ZWQgPC0gbGltbWE6OnRvcFRhYmxlKGViYXllc193ZWlnaHRlZCkKdG9wdGFibGUgPC0gbGltbWE6OnRvcFRhYmxlKGViYXllcykKdG9wdGFibGUKCmxpbW1hX3Rlc3QgPC0gbGltbWFfcGFpcndpc2UoaW5wdXQ9aHNfdW5pbmZfZmlsdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRfbW9kZWw9In4gMCArIGNvbmRpdGlvbiArIGRvbm9yICsgZG9ub3I6cGF0aG9nZW5zdHJhaW4iKQpsaW1tYV90b3AgPC0gbGltbWE6OnRvcFRhYmxlKGxpbW1hX3Rlc3QkcGFpcndpc2VfY29tcGFyaXNvbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyPW5yb3cobGltbWFfdGVzdCRwYWlyd2lzZV9jb21wYXJpc29ucyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc29ydC5ieT0iUCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0icGJtY19jaF92c19wYm1jX3NoIikKaGVhZChsaW1tYV90b3AsIG49MTApCgpsaW1tYV90ZXN0MiA8LSBsaW1tYV9wYWlyd2lzZShpbnB1dD1oc191bmluZl9maWx0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRfbW9kZWw9In4gMCArIGNvbmRpdGlvbiArIGRvbm9yIikKbGltbWFfdG9wMiA8LSBsaW1tYTo6dG9wVGFibGUobGltbWFfdGVzdDIkcGFpcndpc2VfY29tcGFyaXNvbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWY9InBibWNfY2hfdnNfcGJtY19zaCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bWJlcj1ucm93KGxpbW1hX3Rlc3QyJHBhaXJ3aXNlX2NvbXBhcmlzb25zKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc29ydC5ieT0iUCIpCmhlYWQobGltbWFfdG9wMikKYGBgCgpgYGB7ciB0ZXN0X2Nocl9zaDAxLCBmaWcuc2hvdz0iaGlkZSJ9CmhzX3BhaXJ3aXNlX25vYmF0Y2ggPC0gc20oYWxsX3BhaXJ3aXNlKGhzX3VuaW5mX2ZpbHQsIG1vZGVsX2JhdGNoPUZBTFNFKSkKaHNfY29tYmluZWRfbm9iYXRjaCA8LSBzbShjb21iaW5lX2RlX3RhYmxlcyhoc19wYWlyd2lzZV9ub2JhdGNoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfaW5mZWN0X25vYmF0Y2gtdiIsIHZlciwgIi54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcGVycz1rZWVwZXJzKSkKaHNfc2lnX25vYmF0Y2ggPC0gc20oZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyhoc19jb21iaW5lZF9ub2JhdGNoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfaW5mZWN0X25vYmF0Y2hfc2lnLXYiLCB2ZXIsICIueGxzeCIpKSkKaHNfc2lnX25vYmF0Y2gkZGVzZXEkY291bnRzCmNvbW1vbl9zb2xvc19ub2JhdGNoIDwtIHN1YnNldF9zaWduaWZpY2FudHMoaHNfc2lnX25vYmF0Y2gpCnN1bW1hcnkoY29tbW9uX3NvbG9zX25vYmF0Y2gpCmBgYAoKYGBge3IgY2hzaF92ZW5uMDF9Cm5vYmF0Y2hfdXBfdmVubiA8LSBWZW5uZXJhYmxlOjpwbG90KGNvbW1vbl9zb2xvc19ub2JhdGNoJHVwX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKbm9iYXRjaF9kb3duX3Zlbm4gPC0gVmVubmVyYWJsZTo6cGxvdChjb21tb25fc29sb3Nfbm9iYXRjaCRkb3duX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKYGBgCgojIEFkZCBwYXRpZW50IHRvIHRoZSBtb2RlbAoKUmVwZWF0IHRoZSBwcmV2aW91cyBzZXQgb2YgYW5hbHlzZXMgd2l0aCBkMTA3LzEwOC8xMTAgaW4gdGhlIG1vZGVsLgoKYGBge3IgdGVzdF9jaHJfc2gwMiwgZmlnLnNob3c9ImhpZGUifQpoc19wYWlyd2lzZV9iYXRjaCA8LSBzbShhbGxfcGFpcndpc2UoaHNfdW5pbmZfZmlsdCwgbW9kZWxfYmF0Y2g9VFJVRSkpCmhzX2NvbWJpbmVkX2JhdGNoIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKGhzX3BhaXJ3aXNlX2JhdGNoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL2hzX2luZmVjdF9wYXRiYXRjaC12IiwgdmVyLCAiLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcGVycz1rZWVwZXJzKSkKaHNfc2lnX2JhdGNoIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoaHNfY29tYmluZWRfYmF0Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfaW5mZWN0X3BhdGJhdGNoX3NpZy12IiwgdmVyLCAiLnhsc3giKSkpCmhzX3NpZ19iYXRjaFtbImRlc2VxIl1dW1siY291bnRzIl1dCmNvbW1vbl9zb2xvc19iYXRjaCA8LSBzdWJzZXRfc2lnbmlmaWNhbnRzKGhzX3NpZ19iYXRjaCkKc3VtbWFyeShjb21tb25fc29sb3NfYmF0Y2gpCgpzaW1pbGFyIDwtIHNtKGNvbXBhcmVfZGVfcmVzdWx0cyhoc19jb21iaW5lZF9ub2JhdGNoLCBoc19jb21iaW5lZF9iYXRjaCwgY29yX21ldGhvZD0ic3BlYXJtYW4iKSkKc2ltaWxhcltbImRlc2VxIl1dCmBgYAoKYGBge3IgY2hzaF92ZW5uMDJ9CmJhdGNoX3VwX3Zlbm4gPC0gVmVubmVyYWJsZTo6cGxvdChjb21tb25fc29sb3NfYmF0Y2hbWyJ1cF92ZW5uIl1dLCBkb1dlaWdodHM9RkFMU0UpCmJhdGNoX2Rvd25fdmVubiA8LSBWZW5uZXJhYmxlOjpwbG90KGNvbW1vbl9zb2xvc19iYXRjaFtbImRvd25fdmVubiJdXSwgZG9XZWlnaHRzPUZBTFNFKQoKa2VwdF9jb2x1bW5zIDwtIGMoInRyYW5zY3JpcHRpZCIsICJnZW5laWQiLCAiZGVzY3JpcHRpb24iLCAiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIpCnhsc19yZXN1bHQgPC0gd3JpdGVfeGxzKGRhdGE9Y29tbW9uX3NvbG9zX2JhdGNoW1sic2hfc29sb191cCJdXVssIGtlcHRfY29sdW1uc10sIHNoZWV0PSJzaF91cF9zb2xvIikKeGxzX3Jlc3VsdCA8LSB3cml0ZV94bHMoZGF0YT1jb21tb25fc29sb3NfYmF0Y2hbWyJjaF9zb2xvX3VwIl1dWywga2VwdF9jb2x1bW5zXSwgc2hlZXQ9ImNocl91cF9zb2xvIiwKICAgICAgICAgICAgICAgICAgICAgICAgd2I9eGxzX3Jlc3VsdFtbIndvcmtib29rIl1dKQp4bHNfcmVzdWx0IDwtIHdyaXRlX3hscyhkYXRhPWNvbW1vbl9zb2xvc19iYXRjaFtbInNoX3NoYXJlZF9jaF91cCJdXVssIGtlcHRfY29sdW1uc10sCiAgICAgICAgICAgICAgICAgICAgICAgIHNoZWV0PSJzaGNocl9zaGFyZWRfdXAiLCB3Yj14bHNfcmVzdWx0W1sid29ya2Jvb2siXV0pCnhsc19yZXN1bHQgPC0gd3JpdGVfeGxzKGRhdGE9Y29tbW9uX3NvbG9zX2JhdGNoW1sic2hfc29sb19kb3duIl1dWywga2VwdF9jb2x1bW5zXSwKICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQ9InNoX2Rvd25fc29sbyIsIHdiPXhsc19yZXN1bHRbWyJ3b3JrYm9vayJdXSkKeGxzX3Jlc3VsdCA8LSB3cml0ZV94bHMoZGF0YT1jb21tb25fc29sb3NfYmF0Y2hbWyJjaF9zb2xvX2Rvd24iXV1bLCBrZXB0X2NvbHVtbnNdLAogICAgICAgICAgICAgICAgICAgICAgICBzaGVldD0iY2hyX2Rvd25fc29sbyIsIHdiPXhsc19yZXN1bHRbWyJ3b3JrYm9vayJdXSkKeGxzX3Jlc3VsdCA8LSB3cml0ZV94bHMoZGF0YT1jb21tb25fc29sb3NfYmF0Y2hbWyJzaF9zaGFyZWRfY2hfZG93biJdXVssIGtlcHRfY29sdW1uc10sCiAgICAgICAgICAgICAgICAgICAgICAgIHNoZWV0PSJzaGNocl9zaGFyZWRfZG93biIsIHdiPXhsc19yZXN1bHRbWyJ3b3JrYm9vayJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9maWd1cmVfNWFfc3R1ZmYtdiIsIHZlciwgIi54bHN4IikpCmBgYAoKIyBBZGQgc3ZhIGludG8gdGhlIG1peAoKUmVwZWF0LCB0aGlzIHRpbWUgYXR0bWVwdGluZyB0byB0YW1wIGRvd24gdGhlIHZhcmlhbmNlIGJ5IHBlcnNvbi4KCmBgYHtyIHRlc3RfY2hyX3NoMDUsIGZpZy5zaG93PSJoaWRlIn0KaHNfcGFpcndpc2Vfc3N2YSA8LSBzbShhbGxfcGFpcndpc2UoaHNfdW5pbmZfZmlsdCwgbW9kZWxfYmF0Y2g9InNzdmEiKSkKaHNfY29tYmluZWRfc3N2YSA8LSBzbShjb21iaW5lX2RlX3RhYmxlcyhoc19wYWlyd2lzZV9zc3ZhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfaW5mZWN0X3NzdmEtdiIsIHZlciwgIi54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcGVycz1rZWVwZXJzKSkKaHNfc2lnX3NzdmEgPC0gc20oZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyhoc19jb21iaW5lZF9zc3ZhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfaW5mZWN0X3NzdmFfc2lnLXYiLCB2ZXIsICIueGxzeCIpKSkKaHNfc2lnX3NzdmEkZGVzZXEkY291bnRzCmNvbW1vbl9zb2xvc19zc3ZhIDwtIHN1YnNldF9zaWduaWZpY2FudHMoaHNfc2lnX3NzdmEpCnNpbWlsYXIgPC0gc20oY29tcGFyZV9kZV9yZXN1bHRzKGhzX2NvbWJpbmVkX25vYmF0Y2gsIGhzX2NvbWJpbmVkX3NzdmEsIGNvcl9tZXRob2Q9InNwZWFybWFuIikpCnNpbWlsYXIkbGltbWEKc2ltaWxhciA8LSBzbShjb21wYXJlX2RlX3Jlc3VsdHMoaHNfY29tYmluZWRfYmF0Y2gsIGhzX2NvbWJpbmVkX3NzdmEsIGNvcl9tZXRob2Q9InNwZWFybWFuIikpCnNpbWlsYXIkbGltbWEKYGBgCgpgYGB7ciBjaHNoX3Zlbm4wM30Kc3N2YV91cF92ZW5uIDwtIFZlbm5lcmFibGU6OnBsb3QoY29tbW9uX3NvbG9zX3NzdmEkdXBfdmVubiwgZG9XZWlnaHRzPUZBTFNFKQpzc3ZhX2Rvd25fdmVubiA8LSBWZW5uZXJhYmxlOjpwbG90KGNvbW1vbl9zb2xvc19zc3ZhJGRvd25fdmVubiwgZG9XZWlnaHRzPUZBTFNFKQpgYGAKCmBgYHtyIHRlc3RfY2hyX3NoMDMsIGZpZy5zaG93PSJoaWRlIn0KaHNfcGFpcndpc2VfZnN2YSA8LSBzbShhbGxfcGFpcndpc2UoaHNfdW5pbmZfZmlsdCwgbW9kZWxfYmF0Y2g9ImZzdmEiKSkKaHNfY29tYmluZWRfZnN2YSA8LSBzbShjb21iaW5lX2RlX3RhYmxlcyhoc19wYWlyd2lzZV9mc3ZhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfaW5mZWN0X2ZzdmEtdiIsIHZlciwgIi54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcGVycz1rZWVwZXJzKSkKaHNfc2lnX2ZzdmEgPC0gc20oZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyhoc19jb21iaW5lZF9mc3ZhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfaW5mZWN0X2ZzdmFfc2lnLXYiLCB2ZXIsICIueGxzeCIpKSkKaHNfc2lnX2ZzdmEkZGVzZXEkY291bnRzCmNvbW1vbl9zb2xvc19mc3ZhIDwtIHNtKHN1YnNldF9zaWduaWZpY2FudHMoaHNfc2lnX2ZzdmEpKQpsZW5ndGgoY29tbW9uX3NvbG9zX2ZzdmEpCnN1bW1hcnkoY29tbW9uX3NvbG9zX2ZzdmEpCnNpbWlsYXIgPC0gc20oY29tcGFyZV9kZV9yZXN1bHRzKGhzX2NvbWJpbmVkX25vYmF0Y2gsIGhzX2NvbWJpbmVkX2ZzdmEsIGNvcl9tZXRob2Q9InNwZWFybWFuIikpCnNpbWlsYXIkbGltbWEKc2ltaWxhciA8LSBzbShjb21wYXJlX2RlX3Jlc3VsdHMoaHNfY29tYmluZWRfc3N2YSwgaHNfY29tYmluZWRfZnN2YSwgY29yX21ldGhvZD0ic3BlYXJtYW4iKSkKc2ltaWxhciRsaW1tYQpgYGAKCmBgYHtyIGNoc2hfdmVubjAzfQpmc3ZhX3VwX3Zlbm4gPC0gVmVubmVyYWJsZTo6cGxvdChjb21tb25fc29sb3NfZnN2YSR1cF92ZW5uLCBkb1dlaWdodHM9RkFMU0UpCmZzdmFfZG93bl92ZW5uIDwtIFZlbm5lcmFibGU6OnBsb3QoY29tbW9uX3NvbG9zX2ZzdmEkZG93bl92ZW5uLCBkb1dlaWdodHM9RkFMU0UpCmBgYAoKIyBUcnkgd2l0aCB0aGUgY29tYmF0IG1vZGlmaWVkIGRhdGEKCmBgYHtyIHRlc3RfY2hyX3NoMDQsIGZpZy5zaG93PSJoaWRlIn0Kb2xkX2NvbmRpdGlvbiA8LSBoc191bmluZiRkZXNpZ24kY29uZGl0aW9uCm5hbWVzKG9sZF9jb25kaXRpb24pIDwtIGhzX3VuaW5mJGRlc2lnbiRzYW1wbGVpZApuZXdfY29uZGl0aW9uIDwtIHBhc3RlMChoc191bmluZiRkZXNpZ24kc3RhdGUsICdfJywgaHNfdW5pbmYkZGVzaWduJGRvbm9yKQpjb21iYXRfaW5wdXQgPC0gc2V0X2V4cHRfZmFjdG9ycyhoc191bmluZl9maWx0LCBiYXRjaD0icGF0aG9nZW5zdHJhaW4iLCBjb25kaXRpb249bmV3X2NvbmRpdGlvbikKY29tYmF0X2lucHV0IDwtIHNtKG5vcm1hbGl6ZV9leHB0KGNvbWJhdF9pbnB1dCwgYmF0Y2g9ImNvbWJhdF9zY2FsZSIpKQpjb21iYXRfaW5wdXQgPC0gc2V0X2V4cHRfY29uZGl0aW9uKGNvbWJhdF9pbnB1dCwgZmFjdD1vbGRfY29uZGl0aW9uKQoKaHNfcGFpcndpc2VfY29tYmF0cGF0aCA8LSBzbShhbGxfcGFpcndpc2UoY29tYmF0X2lucHV0LCBtb2RlbF9iYXRjaD1GQUxTRSwgZm9yY2U9VFJVRSkpCgpoc19jb21iaW5lZF9jb21iYXRwYXRoIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKGhzX3BhaXJ3aXNlX2NvbWJhdHBhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9oc19pbmZlY3RfY29tYmF0cGF0aC12IiwgdmVyLCAiLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwZXJzPWtlZXBlcnMpKQpoc19zaWdfY29tYmF0cGF0aCA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKGhzX2NvbWJpbmVkX2NvbWJhdHBhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9oc19pbmZlY3RfY29tYmF0cGF0aF9zaWctdiIsIHZlciwgIi54bHN4IikpKQpoc19zaWdfY29tYmF0cGF0aCRkZXNlcSRjb3VudHMKY29tbW9uX3NvbG9zX2NvbWJhdHBhdGggPC0gc3Vic2V0X3NpZ25pZmljYW50cyhoc19zaWdfY29tYmF0cGF0aCkKc3VtbWFyeShjb21tb25fc29sb3NfY29tYmF0cGF0aCkKCnNpbWlsYXIgPC0gc20oY29tcGFyZV9kZV9yZXN1bHRzKGhzX2NvbWJpbmVkX25vYmF0Y2gsIGhzX2NvbWJpbmVkX2NvbWJhdHBhdGgsIGNvcl9tZXRob2Q9InNwZWFybWFuIikpCnNpbWlsYXIkbGltbWEKc2ltaWxhciA8LSBzbShjb21wYXJlX2RlX3Jlc3VsdHMoaHNfY29tYmluZWRfZnN2YSwgaHNfY29tYmluZWRfY29tYmF0cGF0aCwgY29yX21ldGhvZD0ic3BlYXJtYW4iKSkKc2ltaWxhciRsaW1tYQojIyBPVUNIIQpgYGAKCmBgYHtyIGNoc2hfdmVubjA1fQpjb21iYXRfdXBfdmVubiA8LSBWZW5uZXJhYmxlOjpwbG90KGNvbW1vbl9zb2xvc19jb21iYXRwYXRoJHVwX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKY29tYmF0X2Rvd25fdmVubiA8LSBWZW5uZXJhYmxlOjpwbG90KGNvbW1vbl9zb2xvc19jb21iYXRwYXRoJGRvd25fdmVubiwgZG9XZWlnaHRzPUZBTFNFKQpgYGAKCmBgYHtyIGNyZWF0ZV9kZV9kYXRhc2V0cywgZmlnLnNob3c9ImhpZGUifQojIyBpbmZfaHNzdHIgaXMgdGhlIGRhdGEgc2V0IHRoYXQgcHJvdmlkZWQgdGhlIHJlbGF0aXZlbHkgJ3ByZXR0eScgUENBIHBsb3RzIGluIGluZmVjdGlvbl9lc3RpbWF0aW9uCmhzX2luZl9zdHJiYXRjaCRub3RlcwpgYGAKCiMjIENvbXBhcmUgREUgcmVzdWx0cwoKRm9yIGVhY2ggb2YgdGhlIGZvbGxvd2luZywgcGVyZm9ybSBhIHNpbXBsZSBERSBhbmQgc2VlIHdoYXQgaGFwcGVuczoKMS4gIG5vIHVuaW5mZWN0ZWQgc3RyYWluIGFzIGJhdGNoLCB0cnkgdG8gY29tcGFyZSBlYWNoIG9mIHRoZSAzIHBhdGllbnRzIGNocm9uaWMvc2VsZgoyLiAgbm8gdW5pbmZlY3RlZCBzdHJhaW4gYXMgYmF0Y2gsIHRyeSB0byBjb21wYXJlIGNocm9uaWMvc2VsZiBmb3IgYWxsCjMuIGFuZCA0LiBSZXBlYXQgd2l0aCB1bmluZmVjdGVkCgojIyMgREU6IGluY2x1ZGUgdW5pbmZlY3RlZCwgdXNlIHN0cmFpbiBhcyBiYXRjaAoKVGhlIGRhdGEgdXNlZCBpbiB0aGUgZm9sbG93aW5nIGlzIHRoZSBxdWFudGlsZShjcG0oZmlsdGVyKCkpKSB3aGVyZSB0aGUgY29uZGl0aW9uIHdhcyBzZXQgdG8gYQpjb25jYXRlbmF0aW9uIG9mIHBhdGllbnQgYW5kIGhlYWxpbmcgc3RhdGUsIGNvbWJhdCB3YXMgYWxzbyBwZXJmb3JtZWQsIHNvIHdlIG5vIGxvbmdlciB3YW50IGJhdGNoIGluCnRoZSBleHBlcmltZW50YWwgbW9kZWwgYW5kIGFsc28gd2UgbmVlZCB0byBwYXNzICdmb3JjZT1UUlVFJyBiZWNhdXNlIGRlc2VxL2VkZ2VyIHdpbGwgbmVlZCB0byBiZQpjb2VyY2VkIGludG8gYWNjZXB0aW5nIHRoZXNlIG1vZGlmaWVkIGRhdGEuCgpgYGB7ciBkZV9jb21wYXJpc29ucywgZmlnLnNob3c9ImhpZGUifQpoc19pbmYkY29uZGl0aW9uCiMjIFN0YXJ0IGJ5IGxlYXZpbmcgdGhlIGRhdGEgcmVsYXRpdmVseSBhbG9uZSwgZXNwZWNpYWxseSBub3RpbmcgdGhhdCB3ZSBkbyBub3QgaGF2ZSBhIHVzYWJsZSBiYXRjaAojIyBieSBkZWZhdWx0Lgpoc191bmluZl9maWx0djIgPC0gaHNfdW5pbmZfZmlsdApkb25vcl9zdGF0ZSA8LSBwYXN0ZTAoaHNfdW5pbmZfZmlsdHYyJGRlc2lnbiRzdGF0ZSwgIl8iLCBoc191bmluZl9maWx0djIkZGVzaWduJGRvbm9yKQpoc191bmluZl9maWx0djIgPC0gc2V0X2V4cHRfZmFjdG9ycyhoc191bmluZl9maWx0djIsIGNvbmRpdGlvbj1kb25vcl9zdGF0ZSkKCnVuaW5mX3BhdGllbnRfa2VlcGVycyA8LSBsaXN0KAogICAgImQxMDdfY2h1biIgPSBjKCJjaHJvbmljX2QxMDciLCAidW5pbmZlY3RlZF9kMTA3IiksCiAgICAiZDEwN19zaHVuIiA9IGMoInNlbGZfaGVhbF9kMTA3IiwgInVuaW5mZWN0ZWRfZDEwNyIpLAogICAgImQxMDdfY2hzaCIgPSBjKCJjaHJvbmljX2QxMDciLCAic2VsZl9oZWFsX2QxMDciKSwKICAgICJkMTA4X2NodW4iID0gYygiY2hyb25pY19kMTA4IiwgInVuaW5mZWN0ZWRfZDEwOCIpLAogICAgImQxMDhfc2h1biIgPSBjKCJzZWxmX2hlYWxfZDEwOCIsICJ1bmluZmVjdGVkX2QxMDgiKSwKICAgICJkMTA4X2Noc2giID0gYygiY2hyb25pY19kMTA4IiwgInNlbGZfaGVhbF9kMTA4IiksCiAgICAiZDExMF9jaHVuIiA9IGMoImNocm9uaWNfZDExMCIsICJ1bmluZmVjdGVkX2QxMTAiKSwKICAgICJkMTEwX3NodW4iID0gYygic2VsZl9oZWFsX2QxMTAiLCAidW5pbmZlY3RlZF9kMTEwIiksCiAgICAiZDExMF9jaHNoIiA9IGMoImNocm9uaWNfZDExMCIsICJzZWxmX2hlYWxfZDExMCIpKQoKaHNfdW5pbmZfZmlsdHYyX3BhaXJ3aXNlIDwtIHNtKGFsbF9wYWlyd2lzZShoc191bmluZl9maWx0djIsIG1vZGVsX2JhdGNoPUZBTFNFKSkKaHNfdW5pbmZfZmlsdHYyX2NvbWJpbmVkIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKGhzX3VuaW5mX2ZpbHR2Ml9wYWlyd2lzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBlcnM9dW5pbmZfcGF0aWVudF9rZWVwZXJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9oc19pbmZlY3RfcGF0aWVudF9ub2JhdGNoLXYiLCB2ZXIsICIueGxzeCIpKSkKaHNfdW5pbmZfZmlsdHYyX3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKGhzX3VuaW5mX2ZpbHR2Ml9jb21iaW5lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfaW5mZWN0X3BhdGllbnRfbm9iYXRjaF9zaWctdiIsIHZlciwgIi54bHN4IikpKQoKIyNoc191bmluZl9maWx0djNfcGFpcndpc2UgPC0gYWxsX3BhaXJ3aXNlKGhzX3VuaW5mX2ZpbHR2MiwgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIHN1cnJvZ2F0ZXM9MSkKIyNoc191bmluZl9maWx0djNfY29tYmluZWQgPC0gc20oY29tYmluZV9kZV90YWJsZXMoaHNfdW5pbmZfZmlsdHYzX3BhaXJ3aXNlLAojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwZXJzPXVuaW5mX3BhdGllbnRfa2VlcGVycywKIyMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9oc19pbmZlY3RfcGF0aWVudF9mc3ZhLXYiLCB2ZXIsICIueGxzeCIpKSkKIyNoc191bmluZl9maWx0djNfc2lnIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoaHNfdW5pbmZfZmlsdHYzX2NvbWJpbmVkLAojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL2hzX2luZmVjdF9wYXRpZW50X2ZzdmFfc2lnLXYiLCB2ZXIsICIueGxzeCIpKSkKYGBgCgojIyBNYWtlIHNvbWUgVmVubnMKClRoZXkgd2FudCB2ZW5ucywgSSdsbCBnaXZlbiB0aGVtIHZlbm5zLi4uCgpgYGB7ciB2ZW5uc2FwbGVudHl9CmNvbXBfcGVvcGxlIDwtIGZ1bmN0aW9uKGYsIHMsIHQpIHsKICAgIGRkZiA8LSBmCiAgICBkZGZbWyJybiJdXSA8LSByb3duYW1lcyhkZGYpCiAgICBkZGYgPC0gZGRmWywgYygicm4iLCAiZGVzZXFfbG9nZmMiKV0KICAgIGNvbG5hbWVzKGRkZikgPC0gYygicm4iLCAiZmlyc3QiKQogICAgZGRmIDwtIG1lcmdlKGRkZiwgcywgYnk9InJvdy5uYW1lcyIsIGFsbD1UUlVFKQogICAgcm93bmFtZXMoZGRmKSA8LSBkZGZbWyJSb3cubmFtZXMiXV0KICAgIGRkZiA8LSBkZGZbLCAtMV0KICAgIGRkZiA8LSBkZGZbLCBjKCJmaXJzdCIsICJkZXNlcV9sb2dmYyIpXQogICAgY29sbmFtZXMoZGRmKSA8LSBjKCJmaXJzdCIsICJzZWNvbmQiKQogICAgZGRmIDwtIG1lcmdlKGRkZiwgdCwgYnk9InJvdy5uYW1lcyIsIGFsbD1UUlVFKQogICAgcm93bmFtZXMoZGRmKSA8LSBkZGZbWyJSb3cubmFtZXMiXV0KICAgIGRkZiA8LSBkZGZbLCAtMV0KICAgIGRkZiA8LSBkZGZbLCBjKCJmaXJzdCIsICJzZWNvbmQiLCAiZGVzZXFfbG9nZmMiKV0KICAgIGNvbG5hbWVzKGRkZikgPC0gYygiZmlyc3QiLCAic2Vjb25kIiwgInRoaXJkIikKICAgIHJldHVybihkZGYpCn0KYGBgCgpgYGB7ciB2ZW5uX3VwX2Rlc2VxX3NofQp1cF9zaWcgPC0gaHNfdW5pbmZfZmlsdHYyX3NpZyRkZXNlcSR1cHMKc2hfdW5fc2lnIDwtIGNvbXBfcGVvcGxlKGY9dXBfc2lnW1sic2VsZl9oZWFsX2QxMDdfdnNfdW5pbmZlY3RlZF9kMTA3Il1dLAogICAgICAgICAgICAgICAgICAgICAgICAgcz11cF9zaWdbWyJzZWxmX2hlYWxfZDEwOF92c191bmluZmVjdGVkX2QxMDgiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICB0PXVwX3NpZ1tbInNlbGZfaGVhbF9kMTEwX3ZzX3VuaW5mZWN0ZWRfZDExMCJdXSkKdXBhIDwtIHN1bSghaXMubmEoc2hfdW5fc2lnW1siZmlyc3QiXV0pICYgaXMubmEoc2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmIGlzLm5hKHNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBiIDwtIHN1bShpcy5uYShzaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoc2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmIGlzLm5hKHNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBjIDwtIHN1bShpcy5uYShzaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShzaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKHNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBhYiA8LSBzdW0oIWlzLm5hKHNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShzaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgaXMubmEoc2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGJjIDwtIHN1bShpcy5uYShzaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoc2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmICFpcy5uYShzaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYWMgPC0gc3VtKCFpcy5uYShzaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShzaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKHNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBhYmMgPC0gc3VtKCFpcy5uYShzaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoc2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmICFpcy5uYShzaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwX29uZXMgPC0gYygiYSIgPSB1cGEsICJiIiA9IHVwYiwgImMiID0gdXBjKQp1cF90d29zIDwtIGMoImEmYiIgPSB1cGFiLCAiYiZjIiA9IHVwYmMsICJhJmMiID0gdXBhYykKdXBfdGhyZWVzIDwtIGMoImEmYiZjIiA8LSB1cGFiYykKc2hfdXBfdmVubiA8LSBWZW5uZXJhYmxlOjpWZW5uKFNldE5hbWVzID0gYygiYSIsICJiIiwgImMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdlaWdodCA9IGMoMCwgdXBhLCB1cGIsIHVwYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBhYiwgdXBiYywgdXBhYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBhYmMpKQp1cF9yZXMgPC0gVmVubmVyYWJsZTo6cGxvdChzaF91cF92ZW5uLCBkb1dlaWdodHM9RkFMU0UpCnNoYXJlZF91cF9zaCA8LSBjb21wbGV0ZS5jYXNlcyhzaF91bl9zaWcpCnNoYXJlZF91cF9zaCA8LSByb3duYW1lcyhzaF91bl9zaWdbc2hhcmVkX3VwX3NoLCBdKQoKZGVfdGFibGVfc2hhcmVkX3VwX3NoX2ZpcnN0IDwtIGhzX3VuaW5mX2ZpbHR2Ml9jb21iaW5lZFtbImRhdGEiXV1bWyJzZWxmX2hlYWxfZDEwN192c191bmluZmVjdGVkX2QxMDciXV1bc2hhcmVkX3VwX3NoLCBdCmRlX3RhYmxlX3NoYXJlZF91cF9zaF9zZWNvbmQgPC0gaHNfdW5pbmZfZmlsdHYyX2NvbWJpbmVkW1siZGF0YSJdXVtbInNlbGZfaGVhbF9kMTA4X3ZzX3VuaW5mZWN0ZWRfZDEwOCJdXVtzaGFyZWRfdXBfc2gsIF0KZGVfdGFibGVfc2hhcmVkX3VwX3NoX3RoaXJkIDwtIGhzX3VuaW5mX2ZpbHR2Ml9jb21iaW5lZFtbImRhdGEiXV1bWyJzZWxmX2hlYWxfZDExMF92c191bmluZmVjdGVkX2QxMTAiXV1bc2hhcmVkX3VwX3NoLCBdCmRlX3RhYmxlX3NoYXJlZF91cF9zaF9hbGwgPC0gbWVyZ2UoZGVfdGFibGVfc2hhcmVkX3VwX3NoX2ZpcnN0WywgYygiZGVzY3JpcHRpb24iLCAiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZV90YWJsZV9zaGFyZWRfdXBfc2hfc2Vjb25kWywgYygiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZGVfdGFibGVfc2hhcmVkX3VwX3NoX2FsbCA8LSBtZXJnZShkZV90YWJsZV9zaGFyZWRfdXBfc2hfYWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlX3RhYmxlX3NoYXJlZF91cF9zaF90aGlyZFssIGMoImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2FkanAiKV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkueD0iUm93Lm5hbWVzIiwgYnkueT0icm93Lm5hbWVzIikKcm93bmFtZXMoZGVfdGFibGVfc2hhcmVkX3VwX3NoX2FsbCkgPC0gZGVfdGFibGVfc2hhcmVkX3VwX3NoX2FsbFtbIlJvdy5uYW1lcyJdXQpkZV90YWJsZV9zaGFyZWRfdXBfc2hfYWxsIDwtIGRlX3RhYmxlX3NoYXJlZF91cF9zaF9hbGxbLCAtMV0KY29sbmFtZXMoZGVfdGFibGVfc2hhcmVkX3VwX3NoX2FsbCkgPC0gYygiZGVzY3JpcHRpb24iLCAibG9nZmNfMTA3IiwgImFkanBfMTA3IiwgImxvZ2ZjXzEwOCIsICJhZGpwXzEwOCIsICJsb2dmY18xMTAiLCAiYWRqcF8xMTAiKQp3cml0ZS5jc3YoZGVfdGFibGVfc2hhcmVkX3VwX3NoX2FsbCwgZmlsZT0iaW1hZ2VzL2RlX3RhYmxlX3NoYXJlZF91cF9zaF9hbGwuY3N2IikKYGBgCgpgYGB7ciB2ZW5uX3VwX2Rlc2VxX2Nocn0KdXBfc2lnIDwtIGhzX3VuaW5mX2ZpbHR2Ml9zaWckZGVzZXEkdXBzCmNoX3VuX3NpZyA8LSBjb21wX3Blb3BsZShmPXVwX3NpZ1tbImNocm9uaWNfZDEwN192c191bmluZmVjdGVkX2QxMDciXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICBzPXVwX3NpZ1tbImNocm9uaWNfZDEwOF92c191bmluZmVjdGVkX2QxMDgiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICB0PXVwX3NpZ1tbImNocm9uaWNfZDExMF92c191bmluZmVjdGVkX2QxMTAiXV0pCnVwYSA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYiA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYyA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYWIgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBiYyA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGFjIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYWJjIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cF9vbmVzIDwtIGMoImEiID0gdXBhLCAiYiIgPSB1cGIsICJjIiA9IHVwYykKdXBfdHdvcyA8LSBjKCJhJmIiID0gdXBhYiwgImImYyIgPSB1cGJjLCAiYSZjIiA9IHVwYWMpCnVwX3RocmVlcyA8LSBjKCJhJmImYyIgPC0gdXBhYmMpCmNocl91cF92ZW5uIDwtIFZlbm5lcmFibGU6OlZlbm4oU2V0TmFtZXMgPSBjKCJhIiwgImIiLCAiYyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdlaWdodCA9IGMoMCwgdXBhLCB1cGIsIHVwYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwYWIsIHVwYmMsIHVwYWMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGFiYykpCnVwX3JlcyA8LSBWZW5uZXJhYmxlOjpwbG90KGNocl91cF92ZW5uLCBkb1dlaWdodHM9RkFMU0UpCnNoYXJlZF91cF9jaCA8LSBjb21wbGV0ZS5jYXNlcyhjaF91bl9zaWcpCnNoYXJlZF91cF9jaCA8LSByb3duYW1lcyhjaF91bl9zaWdbc2hhcmVkX3VwX2NoLCBdKQoKZGVfdGFibGVfc2hhcmVkX3VwX2NoX2ZpcnN0IDwtIGhzX3VuaW5mX2ZpbHR2Ml9jb21iaW5lZFtbImRhdGEiXV1bWyJjaHJvbmljX2QxMDdfdnNfdW5pbmZlY3RlZF9kMTA3Il1dW3NoYXJlZF91cF9jaCwgXQpkZV90YWJsZV9zaGFyZWRfdXBfY2hfc2Vjb25kIDwtIGhzX3VuaW5mX2ZpbHR2Ml9jb21iaW5lZFtbImRhdGEiXV1bWyJjaHJvbmljX2QxMDhfdnNfdW5pbmZlY3RlZF9kMTA4Il1dW3NoYXJlZF91cF9jaCwgXQpkZV90YWJsZV9zaGFyZWRfdXBfY2hfdGhpcmQgPC0gaHNfdW5pbmZfZmlsdHYyX2NvbWJpbmVkW1siZGF0YSJdXVtbImNocm9uaWNfZDExMF92c191bmluZmVjdGVkX2QxMTAiXV1bc2hhcmVkX3VwX2NoLCBdCmRlX3RhYmxlX3NoYXJlZF91cF9jaF9hbGwgPC0gbWVyZ2UoZGVfdGFibGVfc2hhcmVkX3VwX2NoX2ZpcnN0WywgYygiZGVzY3JpcHRpb24iLCAiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZV90YWJsZV9zaGFyZWRfdXBfY2hfc2Vjb25kWywgYygiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZGVfdGFibGVfc2hhcmVkX3VwX2NoX2FsbCA8LSBtZXJnZShkZV90YWJsZV9zaGFyZWRfdXBfY2hfYWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlX3RhYmxlX3NoYXJlZF91cF9jaF90aGlyZFssIGMoImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2FkanAiKV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkueD0iUm93Lm5hbWVzIiwgYnkueT0icm93Lm5hbWVzIikKcm93bmFtZXMoZGVfdGFibGVfc2hhcmVkX3VwX2NoX2FsbCkgPC0gZGVfdGFibGVfc2hhcmVkX3VwX2NoX2FsbFtbIlJvdy5uYW1lcyJdXQpkZV90YWJsZV9zaGFyZWRfdXBfY2hfYWxsIDwtIGRlX3RhYmxlX3NoYXJlZF91cF9jaF9hbGxbLCAtMV0KY29sbmFtZXMoZGVfdGFibGVfc2hhcmVkX3VwX2NoX2FsbCkgPC0gYygibG9nZmNfMTA3IiwgImFkanBfMTA3IiwgImxvZ2ZjXzEwOCIsICJhZGpwXzEwOCIsICJsb2dmY18xMTAiLCAiYWRqcF8xMTAiKQp3cml0ZS5jc3YoZGVfdGFibGVfc2hhcmVkX3VwX2NoX2FsbCwgZmlsZT0iaW1hZ2VzL2RlX3RhYmxlX3NoYXJlZF91cF9jaF9hbGwuY3N2IikKYGBgCgpgYGB7ciB2ZW5uX2Rvd25fZGVzZXF9CmRvd25fc2lnIDwtIGhzX3VuaW5mX2ZpbHR2Ml9zaWckZGVzZXEkZG93bnMKc2hfdW5fc2lnIDwtIGNvbXBfcGVvcGxlKGY9ZG93bl9zaWdbWyJzZWxmX2hlYWxfZDEwN192c191bmluZmVjdGVkX2QxMDciXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICBzPWRvd25fc2lnW1sic2VsZl9oZWFsX2QxMDhfdnNfdW5pbmZlY3RlZF9kMTA4Il1dLAogICAgICAgICAgICAgICAgICAgICAgICAgdD1kb3duX3NpZ1tbInNlbGZfaGVhbF9kMTEwX3ZzX3VuaW5mZWN0ZWRfZDExMCJdXSkKZG93bmEgPC0gc3VtKCFpcy5uYShzaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShzaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgaXMubmEoc2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYiA8LSBzdW0oaXMubmEoc2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKHNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShzaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25jIDwtIHN1bShpcy5uYShzaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShzaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKHNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmFiIDwtIHN1bSghaXMubmEoc2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKHNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShzaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25iYyA8LSBzdW0oaXMubmEoc2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKHNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoc2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYWMgPC0gc3VtKCFpcy5uYShzaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShzaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKHNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmFiYyA8LSBzdW0oIWlzLm5hKHNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShzaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKHNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bl9vbmVzIDwtIGMoImEiID0gZG93bmEsICJiIiA9IGRvd25iLCAiYyIgPSBkb3duYykKZG93bl90d29zIDwtIGMoImEmYiIgPSBkb3duYWIsICJiJmMiID0gZG93bmJjLCAiYSZjIiA9IGRvd25hYykKZG93bl90aHJlZXMgPC0gYygiYSZiJmMiIDwtIGRvd25hYmMpCnNoX2Rvd25fdmVubiA8LSBWZW5uZXJhYmxlOjpWZW5uKFNldE5hbWVzID0gYygiYSIsICJiIiwgImMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXZWlnaHQgPSBjKDAsIGRvd25hLCBkb3duYiwgZG93bmMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3duYWIsIGRvd25iYywgZG93bmFjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG93bmFiYykpCnNoX2Rvd25fcmVzIDwtIFZlbm5lcmFibGU6OnBsb3Qoc2hfZG93bl92ZW5uLCBkb1dlaWdodHM9RkFMU0UpCnNoYXJlZF9kb3duX3NoIDwtIGNvbXBsZXRlLmNhc2VzKHNoX3VuX3NpZykKc2hhcmVkX2Rvd25fc2ggPC0gcm93bmFtZXMoc2hfdW5fc2lnW3NoYXJlZF9kb3duX3NoLCBdKQoKZGVfdGFibGVfc2hhcmVkX2Rvd25fc2hfZmlyc3QgPC0gaHNfdW5pbmZfZmlsdHYyX2NvbWJpbmVkW1siZGF0YSJdXVtbInNlbGZfaGVhbF9kMTA3X3ZzX3VuaW5mZWN0ZWRfZDEwNyJdXVtzaGFyZWRfZG93bl9zaCwgXQpkZV90YWJsZV9zaGFyZWRfZG93bl9zaF9zZWNvbmQgPC0gaHNfdW5pbmZfZmlsdHYyX2NvbWJpbmVkW1siZGF0YSJdXVtbInNlbGZfaGVhbF9kMTA4X3ZzX3VuaW5mZWN0ZWRfZDEwOCJdXVtzaGFyZWRfZG93bl9zaCwgXQpkZV90YWJsZV9zaGFyZWRfZG93bl9zaF90aGlyZCA8LSBoc191bmluZl9maWx0djJfY29tYmluZWRbWyJkYXRhIl1dW1sic2VsZl9oZWFsX2QxMTBfdnNfdW5pbmZlY3RlZF9kMTEwIl1dW3NoYXJlZF9kb3duX3NoLCBdCmRlX3RhYmxlX3NoYXJlZF9kb3duX3NoX2FsbCA8LSBtZXJnZShkZV90YWJsZV9zaGFyZWRfZG93bl9zaF9maXJzdFssIGMoImRlc2NyaXB0aW9uIiwgImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2FkanAiKV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVfdGFibGVfc2hhcmVkX2Rvd25fc2hfc2Vjb25kWywgYygiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZGVfdGFibGVfc2hhcmVkX2Rvd25fc2hfYWxsIDwtIG1lcmdlKGRlX3RhYmxlX3NoYXJlZF9kb3duX3NoX2FsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZV90YWJsZV9zaGFyZWRfZG93bl9zaF90aGlyZFssIGMoImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2FkanAiKV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkueD0iUm93Lm5hbWVzIiwgYnkueT0icm93Lm5hbWVzIikKcm93bmFtZXMoZGVfdGFibGVfc2hhcmVkX2Rvd25fc2hfYWxsKSA8LSBkZV90YWJsZV9zaGFyZWRfZG93bl9zaF9hbGxbWyJSb3cubmFtZXMiXV0KZGVfdGFibGVfc2hhcmVkX2Rvd25fc2hfYWxsIDwtIGRlX3RhYmxlX3NoYXJlZF9kb3duX3NoX2FsbFssIC0xXQpjb2xuYW1lcyhkZV90YWJsZV9zaGFyZWRfZG93bl9zaF9hbGwpIDwtIGMoImRlc2NyaXB0aW9uIiwgImxvZ2ZjXzEwNyIsICJhZGpwXzEwNyIsICJsb2dmY18xMDgiLCAiYWRqcF8xMDgiLCAibG9nZmNfMTEwIiwgImFkanBfMTEwIikKd3JpdGUuY3N2KGRlX3RhYmxlX3NoYXJlZF9kb3duX3NoX2FsbCwgZmlsZT0iaW1hZ2VzL2RlX3RhYmxlX3NoYXJlZF9kb3duX3NoX2FsbC5jc3YiKQpgYGAKCmBgYHtyIHZlbm5fZG93bl9kZXNlcX0KZG93bl9zaWcgPC0gaHNfdW5pbmZfZmlsdHYyX3NpZyRkZXNlcSRkb3ducwpjaF91bl9zaWcgPC0gY29tcF9wZW9wbGUoZj1kb3duX3NpZ1tbImNocm9uaWNfZDEwN192c191bmluZmVjdGVkX2QxMDciXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICBzPWRvd25fc2lnW1siY2hyb25pY19kMTA4X3ZzX3VuaW5mZWN0ZWRfZDEwOCJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgIHQ9ZG93bl9zaWdbWyJjaHJvbmljX2QxMTBfdnNfdW5pbmZlY3RlZF9kMTEwIl1dKQpkb3duYSA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25iIDwtIHN1bShpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmMgPC0gc3VtKGlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYWIgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmJjIDwtIHN1bShpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25hYyA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYWJjIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duX29uZXMgPC0gYygiYSIgPSBkb3duYSwgImIiID0gZG93bmIsICJjIiA9IGRvd25jKQpkb3duX3R3b3MgPC0gYygiYSZiIiA9IGRvd25hYiwgImImYyIgPSBkb3duYmMsICJhJmMiID0gZG93bmFjKQpkb3duX3RocmVlcyA8LSBjKCJhJmImYyIgPC0gZG93bmFiYykKY2hyX2Rvd25fdmVubiA8LSBWZW5uZXJhYmxlOjpWZW5uKFNldE5hbWVzID0gYygiYSIsICJiIiwgImMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXZWlnaHQgPSBjKDAsIGRvd25hLCBkb3duYiwgZG93bmMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3duYWIsIGRvd25iYywgZG93bmFjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG93bmFiYykpCmNocl9kb3duX3JlcyA8LSBWZW5uZXJhYmxlOjpwbG90KGNocl9kb3duX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKc2hhcmVkX2Rvd25fY2ggPC0gY29tcGxldGUuY2FzZXMoY2hfdW5fc2lnKQpzaGFyZWRfZG93bl9jaCA8LSByb3duYW1lcyhjaF91bl9zaWdbc2hhcmVkX2Rvd25fY2gsIF0pCgpkZV90YWJsZV9zaGFyZWRfZG93bl9jaF9maXJzdCA8LSBoc191bmluZl9maWx0djJfY29tYmluZWRbWyJkYXRhIl1dW1siY2hyb25pY19kMTA3X3ZzX3VuaW5mZWN0ZWRfZDEwNyJdXVtzaGFyZWRfZG93bl9jaCwgXQpkZV90YWJsZV9zaGFyZWRfZG93bl9jaF9zZWNvbmQgPC0gaHNfdW5pbmZfZmlsdHYyX2NvbWJpbmVkW1siZGF0YSJdXVtbImNocm9uaWNfZDEwOF92c191bmluZmVjdGVkX2QxMDgiXV1bc2hhcmVkX2Rvd25fY2gsIF0KZGVfdGFibGVfc2hhcmVkX2Rvd25fY2hfdGhpcmQgPC0gaHNfdW5pbmZfZmlsdHYyX2NvbWJpbmVkW1siZGF0YSJdXVtbImNocm9uaWNfZDExMF92c191bmluZmVjdGVkX2QxMTAiXV1bc2hhcmVkX2Rvd25fY2gsIF0KZGVfdGFibGVfc2hhcmVkX2Rvd25fY2hfYWxsIDwtIG1lcmdlKGRlX3RhYmxlX3NoYXJlZF9kb3duX2NoX2ZpcnN0WywgYygiZGVzY3JpcHRpb24iLCAiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZV90YWJsZV9zaGFyZWRfZG93bl9jaF9zZWNvbmRbLCBjKCJkZXNlcV9sb2dmYyIsICJkZXNlcV9hZGpwIildLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSJyb3cubmFtZXMiKQpkZV90YWJsZV9zaGFyZWRfZG93bl9jaF9hbGwgPC0gbWVyZ2UoZGVfdGFibGVfc2hhcmVkX2Rvd25fY2hfYWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlX3RhYmxlX3NoYXJlZF9kb3duX2NoX3RoaXJkWywgYygiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieS54PSJSb3cubmFtZXMiLCBieS55PSJyb3cubmFtZXMiKQpyb3duYW1lcyhkZV90YWJsZV9zaGFyZWRfZG93bl9jaF9hbGwpIDwtIGRlX3RhYmxlX3NoYXJlZF9kb3duX2NoX2FsbFtbIlJvdy5uYW1lcyJdXQpkZV90YWJsZV9zaGFyZWRfZG93bl9jaF9hbGwgPC0gZGVfdGFibGVfc2hhcmVkX2Rvd25fY2hfYWxsWywgLTFdCmNvbG5hbWVzKGRlX3RhYmxlX3NoYXJlZF9kb3duX2NoX2FsbCkgPC0gYygibG9nZmNfMTA3IiwgImFkanBfMTA3IiwgImxvZ2ZjXzEwOCIsICJhZGpwXzEwOCIsICJsb2dmY18xMTAiLCAiYWRqcF8xMTAiKQp3cml0ZS5jc3YoZGVfdGFibGVfc2hhcmVkX2Rvd25fY2hfYWxsLCBmaWxlPSJpbWFnZXMvZGVfdGFibGVfc2hhcmVkX2Rvd25fY2hfYWxsLmNzdiIpCmBgYAoKYGBge3Igc2hhcmVkX2ludGVyc2VjdGlvbnN9CnVwdXBnZW5lcyA8LSBpbnRlcnNlY3Qoc2hhcmVkX3VwX3NoLCBzaGFyZWRfdXBfY2gpCnVwdXAgPC0gbGVuZ3RoKHVwdXBnZW5lcykKdXBzaF9ub3RjaCA8LSAhc2hhcmVkX3VwX3NoICVpbiUgc2hhcmVkX3VwX2NoCnVwc2hfbm90Y2ggPC0gc2hhcmVkX3VwX3NoW3Vwc2hfbm90Y2hdCnVwY2hfbm90c2ggPC0gIXNoYXJlZF91cF9jaCAlaW4lIHNoYXJlZF91cF9zaAp1cGNoX25vdHNoIDwtIHNoYXJlZF91cF9jaFt1cGNoX25vdHNoXQojIyB1cG5vdCBhbmQgbGVuZ3RoKHVwc2hfbm90Y2gpIHNob3VsZCBiZSBlcXVpdmFsZW50Lgp1cG5vdCA8LSBzdW0oISBzaGFyZWRfdXBfc2ggJWluJSBzaGFyZWRfdXBfY2gpCm5vdHVwIDwtIHN1bSghIHNoYXJlZF91cF9jaCAlaW4lIHNoYXJlZF91cF9zaCkKc2hhcmVkX3VwIDwtIFZlbm5lcmFibGU6OlZlbm4oU2V0TmFtZXM9YygidXBfc2giLCAidXBfY2giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV2VpZ2h0PWMoMCwgdXBub3QsIG5vdHVwLCB1cHVwKSkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWRfdXAsIGRvV2VpZ2h0cz1GQUxTRSkKCmRvd25kb3duZ2VuZXMgPC0gaW50ZXJzZWN0KHNoYXJlZF9kb3duX3NoLCBzaGFyZWRfZG93bl9jaCkKZG93bmRvd24gPC0gbGVuZ3RoKGRvd25kb3duZ2VuZXMpCmRvd25zaF9ub3RjaCA8LSAhc2hhcmVkX2Rvd25fc2ggJWluJSBzaGFyZWRfZG93bl9jaApkb3duc2hfbm90Y2ggPC0gc2hhcmVkX2Rvd25fc2hbZG93bnNoX25vdGNoXQpkb3duY2hfbm90c2ggPC0gIXNoYXJlZF9kb3duX2NoICVpbiUgc2hhcmVkX2Rvd25fc2gKZG93bmNoX25vdHNoIDwtIHNoYXJlZF9kb3duX2NoW2Rvd25jaF9ub3RzaF0KIyMgZG93bm5vdCBhbmQgbGVuZ3RoKGRvd25zaF9ub3RjaCkgc2hvdWxkIGJlIGVxdWl2YWxlbnQuCmRvd25ub3QgPC0gc3VtKCEgc2hhcmVkX2Rvd25fc2ggJWluJSBzaGFyZWRfZG93bl9jaCkKbm90ZG93biA8LSBzdW0oISBzaGFyZWRfZG93bl9jaCAlaW4lIHNoYXJlZF9kb3duX3NoKQpzaGFyZWRfZG93biA8LSBWZW5uZXJhYmxlOjpWZW5uKFNldE5hbWVzPWMoImRvd25fc2giLCAiZG93bl9jaCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXZWlnaHQ9YygwLCBkb3dubm90LCBub3Rkb3duLCBkb3duZG93bikpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkX2Rvd24sIGRvV2VpZ2h0cz1GQUxTRSkKCmtlcHRfY29sdW1ucyA8LSBjKCJ0cmFuc2NyaXB0aWQiLCAiZ2VuZWlkIiwgImRlc2NyaXB0aW9uIiwgImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2FkanAiKQp4bHNfcmVzdWx0IDwtIHdyaXRlX3hscyhkYXRhPXVwX3NpZ1tbInNlbGZfaGVhbF9kMTA3X3ZzX3VuaW5mZWN0ZWRfZDEwNyJdXVt1cHVwZ2VuZXMsIGtlcHRfY29sdW1uc10sCiAgICAgICAgICAgICAgICAgICAgICAgIHNoZWV0PSJ1cHNoX3VwY2giKQp4bHNfcmVzdWx0IDwtIHdyaXRlX3hscyhkYXRhPXVwX3NpZ1tbInNlbGZfaGVhbF9kMTA3X3ZzX3VuaW5mZWN0ZWRfZDEwNyJdXVt1cHNoX25vdGNoLCBrZXB0X2NvbHVtbnNdLAogICAgICAgICAgICAgICAgICAgICAgICBzaGVldD0idXBzaF9ub2NoIiwKICAgICAgICAgICAgICAgICAgICAgICAgd2I9eGxzX3Jlc3VsdFtbIndvcmtib29rIl1dKQp4bHNfcmVzdWx0IDwtIHdyaXRlX3hscyhkYXRhPXVwX3NpZ1tbImNocm9uaWNfZDEwN192c191bmluZmVjdGVkX2QxMDciXV1bdXBjaF9ub3RzaCwga2VwdF9jb2x1bW5zXSwKICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQ9InVwY2hfbm9zaCIsIHdiPXhsc19yZXN1bHRbWyJ3b3JrYm9vayJdXSkKeGxzX3Jlc3VsdCA8LSB3cml0ZV94bHMoZGF0YT1kb3duX3NpZ1tbInNlbGZfaGVhbF9kMTA3X3ZzX3VuaW5mZWN0ZWRfZDEwNyJdXVtkb3duZG93bmdlbmVzLCBrZXB0X2NvbHVtbnNdLAogICAgICAgICAgICAgICAgICAgICAgICBzaGVldD0iZG93bnNoX2Rvd25jaCIsIHdiPXhsc19yZXN1bHRbWyJ3b3JrYm9vayJdXSkKeGxzX3Jlc3VsdCA8LSB3cml0ZV94bHMoZGF0YT1kb3duX3NpZ1tbInNlbGZfaGVhbF9kMTA3X3ZzX3VuaW5mZWN0ZWRfZDEwNyJdXVtkb3duc2hfbm90Y2gsIGtlcHRfY29sdW1uc10sCiAgICAgICAgICAgICAgICAgICAgICAgIHNoZWV0PSJkb3duc2hfbm9jaCIsIHdiPXhsc19yZXN1bHRbWyJ3b3JrYm9vayJdXSkKeGxzX3Jlc3VsdCA8LSB3cml0ZV94bHMoZGF0YT1kb3duX3NpZ1tbImNocm9uaWNfZDEwN192c191bmluZmVjdGVkX2QxMDciXV1bZG93bmNoX25vdHNoLCBrZXB0X2NvbHVtbnNdLAogICAgICAgICAgICAgICAgICAgICAgICBzaGVldD0iZG93bmNoX25vc2giLCB3Yj14bHNfcmVzdWx0W1sid29ya2Jvb2siXV0sCiAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvZmlndXJlXzVjX3N0dWZmLXYiLCB2ZXIsICIueGxzeCIpKQpgYGAKCgpgYGB7ciBvdGhlcl9zdHVmZn0KdXBfc2lnIDwtIGhzX3VuaW5mX2ZpbHR2Ml9zaWckZGVzZXEkdXBzCmNoX3VuX3NpZyA8LSBjb21wX3Blb3BsZShmPXVwX3NpZ1tbInNlbGZfaGVhbF9kMTA3X3ZzX3VuaW5mZWN0ZWRfZDEwNyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgIHM9dXBfc2lnW1sic2VsZl9oZWFsX2QxMDhfdnNfdW5pbmZlY3RlZF9kMTA4Il1dLAogICAgICAgICAgICAgICAgICAgICAgICAgdD11cF9zaWdbWyJzZWxmX2hlYWxfZDExMF92c191bmluZmVjdGVkX2QxMTAiXV0pCnVwYSA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYiA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYyA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYWIgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBiYyA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGFjIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYWJjIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cF9vbmVzIDwtIGMoImEiID0gdXBhLCAiYiIgPSB1cGIsICJjIiA9IHVwYykKdXBfdHdvcyA8LSBjKCJhJmIiID0gdXBhYiwgImImYyIgPSB1cGJjLCAiYSZjIiA9IHVwYWMpCnVwX3RocmVlcyA8LSBjKCJhJmImYyIgPC0gdXBhYmMpCnVwX3Zlbm4gPC0gVmVubmVyYWJsZTo6VmVubihTZXROYW1lcyA9IGMoImEiLCAiYiIsICJjIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV2VpZ2h0ID0gYygwLCB1cGEsIHVwYiwgdXBjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBhYiwgdXBiYywgdXBhYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwYWJjKSkKdXBfcmVzIDwtIFZlbm5lcmFibGU6OnBsb3QodXBfdmVubiwgZG9XZWlnaHRzPUZBTFNFKQoKZG93bl9zaWcgPC0gaHNfdW5pbmZfZmlsdHYyX3NpZyRkZXNlcSRkb3ducwpjaF91bl9zaWcgPC0gY29tcF9wZW9wbGUoZj1kb3duX3NpZ1tbInNlbGZfaGVhbF9kMTA3X3ZzX3VuaW5mZWN0ZWRfZDEwNyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgIHM9ZG93bl9zaWdbWyJzZWxmX2hlYWxfZDEwOF92c191bmluZmVjdGVkX2QxMDgiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICB0PWRvd25fc2lnW1sic2VsZl9oZWFsX2QxMTBfdnNfdW5pbmZlY3RlZF9kMTEwIl1dKQpkb3duYSA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25iIDwtIHN1bShpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmMgPC0gc3VtKGlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYWIgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmJjIDwtIHN1bShpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sic2Vjb25kIl1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25hYyA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYWJjIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duX29uZXMgPC0gYygiYSIgPSBkb3duYSwgImIiID0gZG93bmIsICJjIiA9IGRvd25jKQpkb3duX3R3b3MgPC0gYygiYSZiIiA9IGRvd25hYiwgImImYyIgPSBkb3duYmMsICJhJmMiID0gZG93bmFjKQpkb3duX3RocmVlcyA8LSBjKCJhJmImYyIgPC0gZG93bmFiYykKZG93bl92ZW5uIDwtIFZlbm5lcmFibGU6OlZlbm4oU2V0TmFtZXMgPSBjKCJhIiwgImIiLCAiYyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdlaWdodCA9IGMoMCwgZG93bmEsIGRvd25iLCBkb3duYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvd25hYiwgZG93bmJjLCBkb3duYWMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3duYWJjKSkKZG93bl9yZXMgPC0gVmVubmVyYWJsZTo6cGxvdChkb3duX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKCnVwX3NpZyA8LSBoc191bmluZl9maWx0djJfc2lnJGRlc2VxJHVwcwpjaF91bl9zaWcgPC0gY29tcF9wZW9wbGUoZj11cF9zaWdbWyJjaHJvbmljX2QxMDdfdnNfc2VsZl9oZWFsX2QxMDciXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICBzPXVwX3NpZ1tbImNocm9uaWNfZDEwOF92c19zZWxmX2hlYWxfZDEwOCJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgIHQ9dXBfc2lnW1siY2hyb25pY19kMTEwX3ZzX3NlbGZfaGVhbF9kMTEwIl1dKQp1cGEgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGIgPC0gc3VtKGlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGMgPC0gc3VtKGlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGFiIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYmMgPC0gc3VtKGlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBhYyA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGFiYyA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBfb25lcyA8LSBjKCJhIiA9IHVwYSwgImIiID0gdXBiLCAiYyIgPSB1cGMpCnVwX3R3b3MgPC0gYygiYSZiIiA9IHVwYWIsICJiJmMiID0gdXBiYywgImEmYyIgPSB1cGFjKQp1cF90aHJlZXMgPC0gYygiYSZiJmMiIDwtIHVwYWJjKQp1cF92ZW5uIDwtIFZlbm5lcmFibGU6OlZlbm4oU2V0TmFtZXMgPSBjKCJhIiwgImIiLCAiYyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdlaWdodCA9IGMoMCwgdXBhLCB1cGIsIHVwYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwYWIsIHVwYmMsIHVwYWMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGFiYykpCnVwX3JlcyA8LSBWZW5uZXJhYmxlOjpwbG90KHVwX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKCmRvd25fc2lnIDwtIGhzX3VuaW5mX2ZpbHR2Ml9zaWckZGVzZXEkZG93bnMKY2hfdW5fc2lnIDwtIGNvbXBfcGVvcGxlKGY9ZG93bl9zaWdbWyJjaHJvbmljX2QxMDdfdnNfc2VsZl9oZWFsX2QxMDciXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICBzPWRvd25fc2lnW1siY2hyb25pY19kMTA4X3ZzX3NlbGZfaGVhbF9kMTA4Il1dLAogICAgICAgICAgICAgICAgICAgICAgICAgdD1kb3duX3NpZ1tbImNocm9uaWNfZDExMF92c19zZWxmX2hlYWxfZDExMCJdXSkKZG93bmEgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYiA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25jIDwtIHN1bShpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmFiIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25iYyA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYWMgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmFiYyA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bl9vbmVzIDwtIGMoImEiID0gZG93bmEsICJiIiA9IGRvd25iLCAiYyIgPSBkb3duYykKZG93bl90d29zIDwtIGMoImEmYiIgPSBkb3duYWIsICJiJmMiID0gZG93bmJjLCAiYSZjIiA9IGRvd25hYykKZG93bl90aHJlZXMgPC0gYygiYSZiJmMiIDwtIGRvd25hYmMpCmRvd25fdmVubiA8LSBWZW5uZXJhYmxlOjpWZW5uKFNldE5hbWVzID0gYygiYSIsICJiIiwgImMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXZWlnaHQgPSBjKDAsIGRvd25hLCBkb3duYiwgZG93bmMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3duYWIsIGRvd25iYywgZG93bmFjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG93bmFiYykpCmRvd25fcmVzIDwtIFZlbm5lcmFibGU6OnBsb3QoZG93bl92ZW5uLCBkb1dlaWdodHM9RkFMU0UpCmBgYAoKYGBge3Igc3ZhX3Zlbm4sIGV2YWw9RkFMU0V9CnVwX3NpZyA8LSBoc191bmluZl9maWx0djNfc2lnJGRlc2VxJHVwcwpjaF91bl9zaWcgPC0gY29tcF9wZW9wbGUoZj11cF9zaWdbWyJjaHJvbmljX2QxMDdfdnNfdW5pbmZlY3RlZF9kMTA3Il1dLAogICAgICAgICAgICAgICAgICAgICAgICAgcz11cF9zaWdbWyJjaHJvbmljX2QxMDhfdnNfdW5pbmZlY3RlZF9kMTA4Il1dLAogICAgICAgICAgICAgICAgICAgICAgICAgdD11cF9zaWdbWyJjaHJvbmljX2QxMTBfdnNfdW5pbmZlY3RlZF9kMTEwIl1dKQp1cGEgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGIgPC0gc3VtKGlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGMgPC0gc3VtKGlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGFiIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCnVwYmMgPC0gc3VtKGlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBhYyA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmIGlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQp1cGFiYyA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKdXBfb25lcyA8LSBjKCJhIiA9IHVwYSwgImIiID0gdXBiLCAiYyIgPSB1cGMpCnVwX3R3b3MgPC0gYygiYSZiIiA9IHVwYWIsICJiJmMiID0gdXBiYywgImEmYyIgPSB1cGFjKQp1cF90aHJlZXMgPC0gYygiYSZiJmMiIDwtIHVwYWJjKQp1cF92ZW5uIDwtIFZlbm5lcmFibGU6OlZlbm4oU2V0TmFtZXMgPSBjKCJhIiwgImIiLCAiYyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdlaWdodCA9IGMoMCwgdXBhLCB1cGIsIHVwYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwYWIsIHVwYmMsIHVwYWMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGFiYykpCnVwX3JlcyA8LSBWZW5uZXJhYmxlOjpwbG90KHVwX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKCmRvd25fc2lnIDwtIGhzX3VuaW5mX2ZpbHR2M19zaWckZGVzZXEkZG93bnMKY2hfdW5fc2lnIDwtIGNvbXBfcGVvcGxlKGY9ZG93bl9zaWdbWyJjaHJvbmljX2QxMDdfdnNfdW5pbmZlY3RlZF9kMTA3Il1dLAogICAgICAgICAgICAgICAgICAgICAgICAgcz1kb3duX3NpZ1tbImNocm9uaWNfZDEwOF92c191bmluZmVjdGVkX2QxMDgiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICB0PWRvd25fc2lnW1siY2hyb25pY19kMTEwX3ZzX3VuaW5mZWN0ZWRfZDExMCJdXSkKZG93bmEgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYiA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25jIDwtIHN1bShpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmFiIDwtIHN1bSghaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJ0aGlyZCJdXSkpCmRvd25iYyA8LSBzdW0oaXMubmEoY2hfdW5fc2lnW1siZmlyc3QiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInNlY29uZCJdXSkgJiAhaXMubmEoY2hfdW5fc2lnW1sidGhpcmQiXV0pKQpkb3duYWMgPC0gc3VtKCFpcy5uYShjaF91bl9zaWdbWyJmaXJzdCJdXSkgJiBpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bmFiYyA8LSBzdW0oIWlzLm5hKGNoX3VuX3NpZ1tbImZpcnN0Il1dKSAmICFpcy5uYShjaF91bl9zaWdbWyJzZWNvbmQiXV0pICYgIWlzLm5hKGNoX3VuX3NpZ1tbInRoaXJkIl1dKSkKZG93bl9vbmVzIDwtIGMoImEiID0gZG93bmEsICJiIiA9IGRvd25iLCAiYyIgPSBkb3duYykKZG93bl90d29zIDwtIGMoImEmYiIgPSBkb3duYWIsICJiJmMiID0gZG93bmJjLCAiYSZjIiA9IGRvd25hYykKZG93bl90aHJlZXMgPC0gYygiYSZiJmMiIDwtIGRvd25hYmMpCmRvd25fdmVubiA8LSBWZW5uZXJhYmxlOjpWZW5uKFNldE5hbWVzID0gYygiYSIsICJiIiwgImMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXZWlnaHQgPSBjKDAsIGRvd25hLCBkb3duYiwgZG93bmMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3duYWIsIGRvd25iYywgZG93bmFjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG93bmFiYykpCmRvd25fcmVzIDwtIFZlbm5lcmFibGU6OnBsb3QoZG93bl92ZW5uLCBkb1dlaWdodHM9RkFMU0UpCmBgYAoKIyMjIERFOiBpbmNsdWRlIHVuaW5mZWN0ZWQsIHJlcGVhdCB3aXRoIGNvbmRpdGlvbiBzaW1wbGlmaWVkIHRvIGNocm9uaWMvc2VsZgoKRG8gSSB0aGluayB0aGUgZXhhY3Qgc2FtZSB0aGluZyBhcyBpbiB0aGUgcHJldmlvdXMgY29tcGFyaXNvbiwgYnV0IG5vdyBzaW1wbGlmeSB0aGUgJ2NvbmRpdGlvbicKZmFjdG9yIHRvIGp1c3Qgc2VsZi1oZWFsaW5nIHZzLiBjaHJvbmljIGFuZCBzZWUgd2hhdCBoYXBwZW5zLgoKYGBge3IgZGVfY2hyb25pY3NoX3N0cmFpbmJhdGNoLCBldmFsPUZBTFNFfQp1bmluZl9zdHJhaW5iYXRjaF9xY2YgPC0gc2V0X2V4cHRfYmF0Y2goZXhwdD11bmluZl9jcWYsIGZhY3Q9InBhdGhvZ2Vuc3RyYWluIikKdW5pbmZfc3RyYWluYmF0Y2hfcWNmIDwtIHNldF9leHB0X2NvbmRpdGlvbihleHB0PXVuaW5mX3N0cmFpbmJhdGNoX3FjZiwgZmFjdD0ic3RhdGUiKQp3aXRodW5pbmZfc3RyYWluYmF0Y2hfcGFpcnNfY2hzaCA8LSBhbGxfcGFpcndpc2UodW5pbmZfc3RyYWluYmF0Y2hfcWNmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfYmF0Y2g9RkFMU0UsIGZvcmNlPVRSVUUpCmNoc2hfa2VlcGVycyA8LSBsaXN0KAogICAgImNoX3NoIiA9IGMoImNocm9uaWMiLCAic2VsZl9oZWFsIiksCiAgICAiY2hfbmlsIiA9IGMoImNocm9uaWMiLCAidW5pbmZlY3RlZCIpLAogICAgInNoX25pbCIgPSBjKCJzZWxmX2hlYWwiLCAidW5pbmZlY3RlZCIpKQp3aXRodW5pbmZfc3RyYWluYmF0Y2hfdGFibGVzX2Noc2ggPC0gc20oY29tYmluZV9kZV90YWJsZXMod2l0aHVuaW5mX3N0cmFpbmJhdGNoX3BhaXJzX2Noc2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwZXJzPWNoc2hfa2VlcGVycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvd2l0aHVuaW5mX3N0cmFpbmJhdGNoX2Noc2hfcGFpcndpc2UtdiIsIHZlciwgIi54bHN4IikpKQp3aXRodW5pbmZfc3RyYWluYmF0Y2hfc2lnX2Noc2ggPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyh3aXRodW5pbmZfc3RyYWluYmF0Y2hfdGFibGVzX2Noc2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvd2l0aHVuaW5mX3N0cmFpbmJhdGNoX2Noc2hfc2lnLXYiLCB2ZXIsICIueGxzeCIpKQojI3dpdGh1bmluZl9zdHJhaW5iYXRjaF90YWJsZXNfY2hzaCRsaW1tYV9wbG90cwojI3dpdGh1bmluZl9zdHJhaW5iYXRjaF90YWJsZXNfY2hzaCRlZGdlcl9wbG90cwojI3dpdGh1bmluZl9zdHJhaW5iYXRjaF90YWJsZXNfY2hzaCRkZXNlcV9wbG90cwpgYGAKCiMgRmlndXJlIDUKCkdlbmVyYXRlIERFIGxpc3RzIG9mIGVhY2ggZG9ub3IgZm9yIGFsbCBjb250cmFzdHMgZm9yIFBCTUNzLgoKICBhLiAgVmVubiBzaC91bmluZiB2cyBjaHIvdW5pbmYgMiB2ZW5uIGRpYWdyYW0gdXAuIChkb25vciBpbiBtb2RlbCkKICBiLiAgVmVubiBzaC91bmluZiB2cyBjaHIvdW5pbmYgMiB2ZW5uIGRpYWdyYW0gZG93bi4KICBjLiAgVmVubiBTaC91bmluZiB1cCBnZW5lcyAzIHZlbm4gZGlhZ3JhbS4KICBkLiAgVmVubiBTaC91bmluZiBkb3duIGdlbmVzIDMgdmVubi4KICBlLiAgVmVubiBDaHIvdW5pbmYgdXAgZ2VuZXMgMyB2ZW5uLgogIGYuICBWZW5uIENoci91bmluZiBkb3duIGdlbmVzIDMgdmVubi4KICBnLiAgMiB3YXkgdmVubiBvZiAoY29tbW9uIHVwIGluIDMgdmVubiBzaC91bmluZikgdnMuIChjb21tb24gdXAgaW4gMyB2ZW5uIGNoci91bmluZikKICBoLiAgMiB3YXkgdmVubiBvZiAoY29tbW9uIGRvd24gaW4gMyB2ZW5uIHNoL3VuaW5mKSB2cy4gKGNvbW1vbiBkb3duIGluIDMgdmVubiBjaHIvdW5pbmYpCgpgYGB7ciBmaWd1cmVfNX0KcHAoZmlsZT0iaW1hZ2VzL2ZpZ18wNWEtc2hfdW5pbmZfdnNfY2hyX3VuaW5mX3VwLnBkZiIpClZlbm5lcmFibGU6OnBsb3QoY29tbW9uX3NvbG9zX2JhdGNoJHVwX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKZGV2Lm9mZigpCnBwKGZpbGU9ImltYWdlcy9maWdfMDViLXNoX3VuaW5mX3ZzX2Nocl91bmluZl9kb3duLnBkZiIpClZlbm5lcmFibGU6OnBsb3QoY29tbW9uX3NvbG9zX2JhdGNoJGRvd25fdmVubiwgZG9XZWlnaHRzPUZBTFNFKQpkZXYub2ZmKCkKcHAoZmlsZT0iaW1hZ2VzL2ZpZ18wNWMtc2hfdW5pbmZfZG9ub3JzX3VwLnBkZiIpClZlbm5lcmFibGU6OnBsb3Qoc2hfdXBfdmVubiwgZG9XZWlnaHRzPUZBTFNFKQpkZXYub2ZmKCkKcHAoZmlsZT0iaW1hZ2VzL2ZpZ18wNWQtc2hfdW5pbmZfZG9ub3JzX2Rvd24ucGRmIikKVmVubmVyYWJsZTo6cGxvdChzaF9kb3duX3Zlbm4sIGRvV2VpZ2h0cz1GQUxTRSkKZGV2Lm9mZigpCnBwKGZpbGU9ImltYWdlcy9maWdfMDVlLWNocl91bmluZl9kb25vcnNfdXAucGRmIikKVmVubmVyYWJsZTo6cGxvdChjaHJfdXBfdmVubiwgZG9XZWlnaHRzPUZBTFNFKQpkZXYub2ZmKCkKcHAoZmlsZT0iaW1hZ2VzL2ZpZ18wNWYtY2hyX3VuaW5mX2Rvbm9yc19kb3duLnBkZiIpClZlbm5lcmFibGU6OnBsb3QoY2hyX2Rvd25fdmVubiwgZG9XZWlnaHRzPUZBTFNFKQpkZXYub2ZmKCkKcHAoZmlsZT0iaW1hZ2VzL2ZpZ18wNWctdXBfY29tbW9uLnBkZiIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkX3VwLCBkb1dlaWdodHM9RkFMU0UpCmRldi5vZmYoKQpwcChmaWxlPSJpbWFnZXMvZmlnXzA1aC1kb3duX2NvbW1vbi5wZGYiKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZF9kb3duLCBkb1dlaWdodHM9RkFMU0UpCmRldi5vZmYoKQpgYGAKCiMgVGFibGUgU3p6egoKVGFibGVzIG9mIHRoZSBzdHVmZiBpbiBmaWd1cmUgNQoKYGBge3IgdGFibGVfenp6fQoKYGBgCgpgYGB7ciBleHRyYWN0X3NpZywgZXZhbD1GQUxTRX0KZnVua3l0b3duIDwtIGhwZ2x0b29sczo6OmNvbXBhcmVfbG9nZmNfcGxvdHMod2l0aHVuaW5mX3N0cmFpbmJhdGNoX3RhYmxlc19jaHNoKQpmdW5reXRvd24kY2hfbmlsJGxlCmZ1bmt5dG93biRjaF9uaWwkbGQKZnVua3l0b3duJGNoX25pbCRkZQpgYGAKCiMgVHJ5IGFnYWluIG9uIHRoZSBwYXJhc2l0ZSBkYXRhCgojIyBSZW1lbWJlciBvdXIgZGF0YSBzZXQKCmBgYHtyIGxwX2V4cHJlc3Npb24wMX0KbHBfaW5mX2ZpbHQgPC0gc20obm9ybWFsaXplX2V4cHQobHBfaW5mLCBmaWx0ZXI9VFJVRSkpCmBgYAoKYGBge3IgbHBfbm9iYXRjaCwgc2hvdy5maWc9ImhpZGUifQpscF9wYWlyd2lzZV9ub2JhdGNoIDwtIHNtKGFsbF9wYWlyd2lzZShscF9pbmZfZmlsdCwgbW9kZWxfYmF0Y2g9RkFMU0UpKQpscF9jb21iaW5lZF9ub2JhdGNoIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKGxwX3BhaXJ3aXNlX25vYmF0Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9scF9pbmZlY3Rfbm9iYXRjaC12IiwgdmVyLCAiLnhsc3giKSkpCmxwX3NpZ19ub2JhdGNoIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMobHBfY29tYmluZWRfbm9iYXRjaCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL2xwX2luZmVjdF9ub2JhdGNoX3NpZy12IiwgdmVyLCAiLnhsc3giKSkpCmBgYAoKYGBge3IgbHBfYmF0Y2gsIHNob3cuZmlnPSJoaWRlIn0KbHBfcGFpcndpc2VfYmF0Y2ggPC0gc20oYWxsX3BhaXJ3aXNlKGxwX2luZl9maWx0LCBtb2RlbF9iYXRjaD1UUlVFKSkKbHBfY29tYmluZWRfYmF0Y2ggPC0gc20oY29tYmluZV9kZV90YWJsZXMobHBfcGFpcndpc2VfYmF0Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfaW5mZWN0X2JhdGNoLXYiLCB2ZXIsICIueGxzeCIpKSkKbHBfc2lnX2JhdGNoIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMobHBfY29tYmluZWRfYmF0Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfaW5mZWN0X2JhdGNoX3NpZy12IiwgdmVyLCAiLnhsc3giKSkpCmBgYAoKYGBge3IgbHBfc3N2YSwgc2hvdy5maWc9ImhpZGUifQpscF9wYWlyd2lzZV9zc3ZhIDwtIHNtKGFsbF9wYWlyd2lzZShscF9pbmZfZmlsdCwgbW9kZWxfYmF0Y2g9InNzdmEiKSkKbHBfY29tYmluZWRfc3N2YSA8LSBzbShjb21iaW5lX2RlX3RhYmxlcyhscF9wYWlyd2lzZV9zc3ZhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfaW5mZWN0X3NzdmEtdiIsIHZlciwgIi54bHN4IikpKQpscF9zaWdfc3N2YSA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKGxwX2NvbWJpbmVkX3NzdmEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfaW5mZWN0X3NzdmFfc2lnLXYiLCB2ZXIsICIueGxzeCIpKSkKYGBgCgoKYGBge3IgbHBfZnN2YSwgc2hvdy5maWc9ImhpZGUifQpscF9wYWlyd2lzZV9mc3ZhIDwtIHNtKGFsbF9wYWlyd2lzZShscF9pbmZfZmlsdCwgbW9kZWxfYmF0Y2g9ImZzdmEiKSkKbHBfY29tYmluZWRfZnN2YSA8LSBzbShjb21iaW5lX2RlX3RhYmxlcyhscF9wYWlyd2lzZV9mc3ZhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfaW5mZWN0X2ZzdmEtdiIsIHZlciwgIi54bHN4IikpKQpscF9zaWdfZnN2YSA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKGxwX2NvbWJpbmVkX2ZzdmEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfaW5mZWN0X2ZzdmFfc2lnLXYiLCB2ZXIsICIueGxzeCIpKSkKYGBgCgoKCltpbmRleC5odG1sXShpbmRleC5odG1sKSBbMDJfaW5mZWN0aW9uX2VzdGltYXRpb24uaHRtbF0oMDJfaW5mZWN0aW9uX2VzdGltYXRpb24uaHRtbCkKCmBgYHtyIHNhdmVtZX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCnRoaXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXJtZF9maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgdGhpc19zYXZlKSkKdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQpgYGAK