1 Introduction

This document is intended to provide an overview of TMRC3 samples which have been sequenced. It includes some plots and analyses showing the relationships among the samples as well as some differential analyses when possible.

2 Annotation

We take the annotation data from ensembl’s biomart instance. The genome which was used to map the data was hg38 revision 100. My default when using biomart is to load the data from 1 year before the current date.

hs_annot <- sm(load_biomart_annotations(year = "2020"))
hs_annot <- hs_annot[["annotation"]]
hs_annot[["transcript"]] <- paste0(rownames(hs_annot), ".", hs_annot[["version"]])
rownames(hs_annot) <- make.names(hs_annot[["ensembl_gene_id"]], unique = TRUE)
tx_gene_map <- hs_annot[, c("transcript", "ensembl_gene_id")]

summary(hs_annot)
##  ensembl_transcript_id ensembl_gene_id       version     transcript_version
##  Length:227921         Length:227921      Min.   : 1.0   Min.   : 1.00     
##  Class :character      Class :character   1st Qu.: 6.0   1st Qu.: 1.00     
##  Mode  :character      Mode  :character   Median :12.0   Median : 1.00     
##                                           Mean   :10.7   Mean   : 3.08     
##                                           3rd Qu.:16.0   3rd Qu.: 5.00     
##                                           Max.   :29.0   Max.   :17.00     
##                                                                            
##  hgnc_symbol        description        gene_biotype         cds_length    
##  Length:227921      Length:227921      Length:227921      Min.   :     3  
##  Class :character   Class :character   Class :character   1st Qu.:   357  
##  Mode  :character   Mode  :character   Mode  :character   Median :   694  
##                                                           Mean   :  1139  
##                                                           3rd Qu.:  1446  
##                                                           Max.   :107976  
##                                                           NA's   :127343  
##  chromosome_name       strand          start_position      end_position     
##  Length:227921      Length:227921      Min.   :5.77e+02   Min.   :6.47e+02  
##  Class :character   Class :character   1st Qu.:3.11e+07   1st Qu.:3.12e+07  
##  Mode  :character   Mode  :character   Median :6.04e+07   Median :6.06e+07  
##                                        Mean   :7.41e+07   Mean   :7.42e+07  
##                                        3rd Qu.:1.09e+08   3rd Qu.:1.09e+08  
##                                        Max.   :2.49e+08   Max.   :2.49e+08  
##                                                                             
##   transcript       
##  Length:227921     
##  Class :character  
##  Mode  :character  
##                    
##                    
##                    
## 
hs_go <- sm(load_biomart_go()[["go"]])
hs_length <- hs_annot[, c("ensembl_gene_id", "cds_length")]
colnames(hs_length) <- c("ID", "length")

3 Sample Estimation

3.1 Generate expressionsets

The sample sheet is copied from our shared online sheet and updated with each release of sequencing data.

samplesheet <- "sample_sheets/tmrc3_samples_202103.xlsx"

3.1.1 Hisat2 expressionsets

The first thing to note is the large range in coverage. There are multiple samples with coverage which is too low to use. These will be removed shortly.

In the following block I immediately exclude any non-coding reads as well.

## Create the expressionset and immediately pass it to a filter
## removing the non protein coding genes.
hs_expt <- sm(create_expt(samplesheet,
                          file_column = "hg38100hisatfile",
                          savefile = glue::glue("rda/hs_expt_all-v{ver}.rda"),
                          gene_info = hs_annot)) %>%
  exclude_genes_expt(column = "gene_biotype", method = "keep", pattern = "protein_coding")
## Before removal, there were 21481 genes, now there are 19941.
## There are 11 samples which kept less than 90 percent counts.
## TMRC30015 TMRC30017 TMRC30019 TMRC30044 TMRC30045 TMRC30097 TMRC30075 TMRC30087 
##     79.24     85.72     89.75     80.34     73.33     89.90     86.97     83.63 
## TMRC30101 TMRC30104 TMRC30073 
##     88.41     80.29     89.26

3.1.1.1 Initial metrics

Once the data was loaded, there are a couple of metrics which may be plotted immediately.

nonzero <- plot_nonzero(hs_expt)
nonzero$plot
## Warning: ggrepel: 80 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

3.2 Minimum coverage sample filtering

I arbitrarily chose 11,000 non-zero genes as a minimum. We may want this to be higher.

hs_valid <- subset_expt(hs_expt, nonzero = 11000)
## The samples (and read coverage) removed when filtering 11000 non-zero genes are:
## TMRC30010 TMRC30050 TMRC30052 
##     52471    808149   3087347
## There were 108, now there are 105 samples.
## valid_write <- write_expt(hs_valid, excel = glue("excel/hs_valid-v{ver}.xlsx"))

4 Project Aims

The project seeks to determine the relationship of the innate immune response and inflammatory signaling to the clinical outcome of antileishmanial drug treatment. We will test the hypothesis that the profile of innate immune cell activation and their dynamics through the course of treatment differ between CL patients with prospectively determined therapeutic cure or failure.

This will be achieved through the characterization of the in vivo dynamics of blood-derived monocyte, neutrophil and eosinophil transcriptome before, during and at the end of treatment in CL patients. Cell-type specific transcriptomes, composite signatures and time-response expression profiles will be contrasted among patients with therapeutic cure or failure.

4.1 Preparation

To address these, I added to the end of the sample sheet columns named ‘condition’, ‘batch’, ‘donor’, and ‘time’. These are filled in with shorthand values according to the above.

4.2 Global view

Before addressing the questions explicitly by subsetting the data, I want to get a look at the samples as they are.

hs_valid <- hs_valid %>%
  set_expt_batches(fact = "cellssource") %>%
  set_expt_conditions(fact = "typeofcells") %>%
  set_expt_samplenames(newnames = pData(hs_valid)[["samplename"]])

all_norm <- sm(normalize_expt(hs_valid, transform = "log2", norm = "quant",
                              convert = "cpm", filter = TRUE))

all_pca <- plot_pca(all_norm, plot_labels = FALSE, plot_title = "PCA - Cell type")
pp(file = glue("images/tmrc3_pca_nolabels-v{ver}.png"), image = all_pca$plot)

write.csv(all_pca$table, file = "coords/hs_donor_pca_coords.csv")
plot_corheat(all_norm, plot_title = "Heirarchical clustering - cell types")$plot

4.3 Examine samples relevant to clinical outcome

Now let us consider only the samples for which we have a clinical outcome. These fall primarily into either ‘cured’ or ‘failed’, but some people have not yet returned to the clinic after the first or second visit. These are deemed ‘lost’.

chosen_colors <- c("#D95F02", "#7570B3", "#1B9E77", "#FF0000")
names(chosen_colors) <- c("cure", "failure", "lost", "null")
newnames <- pData(hs_valid)[["samplename"]]

hs_clinical <- hs_valid %>%
  set_expt_conditions(fact = "clinicaloutcome") %>%
  set_expt_batches(fact = "typeofcells") %>%
  set_expt_colors(colors = chosen_colors) %>%
  set_expt_samplenames(newnames = newnames) %>%
  subset_expt(subset = "typeofcells!='PBMCs'&typeofcells!='Macrophages'")
## There were 105, now there are 87 samples.
hs_clinical_norm <- sm(normalize_expt(hs_clinical, filter = TRUE, transform = "log2",
                                      convert = "cpm", norm = "quant"))
clinical_pca <- plot_pca(hs_clinical_norm, plot_labels = FALSE, cis = NULL,
                         plot_title = "PCA - clinical samples")
pp(file = glue("images/all_clinical_nobatch_pca-v{ver}.png"), image = clinical_pca$plot,
   height = 8, width = 20)

4.3.1 Repeat without the biopsy samples

hs_clinical_nobiop <- hs_clinical %>%
  subset_expt(subset = "typeofcells!='Biopsy'")
## There were 87, now there are 55 samples.
hs_clinical_nobiop_norm <- sm(normalize_expt(hs_clinical_nobiop, filter = TRUE, transform = "log2",
                                             convert = "cpm", norm = "quant"))
clinical_nobiop_pca <- plot_pca(hs_clinical_nobiop_norm, plot_labels = FALSE, cis = NULL,
                                plot_title = "PCA - clinical samples without biopsies")
pp(file = glue("images/all_clinical_nobiop_nobatch_pca-v{ver}.png"),
   image = clinical_nobiop_pca$plot)

4.3.2 Attempt to correct for the surrogate variables

At this time we have two primary data structures of interest: hs_clinical and hs_clinical_nobiop

hs_clinical_nb <- normalize_expt(hs_clinical, filter = TRUE, batch = "svaseq",
                                 transform = "log2", convert = "cpm")
## Removing 5457 low-count genes (14484 remaining).
## batch_counts: Before batch/surrogate estimation, 72813 entries are x==0: 6%.
## batch_counts: Before batch/surrogate estimation, 220887 entries are 0<x<1: 18%.
## Setting 14890 low elements to zero.
## transform_counts: Found 14890 values equal to 0, adding 1 to the matrix.
clinical_batch_pca <- plot_pca(hs_clinical_nb, plot_labels = FALSE, cis = NULL,
                               plot_title = "PCA - clinical samples")
clinical_batch_pca$plot

hs_clinical_nobiop_nb <- sm(normalize_expt(hs_clinical_nobiop, filter = TRUE, batch = "svaseq",
                                           transform = "log2", convert = "cpm"))
clinical_nobiop_batch_pca <- plot_pca(hs_clinical_nobiop_nb,
                                      plot_title = "PCA - clinical samples without biopsies",
                                      plot_labels = FALSE)
pp(file = "images/clinical_batch.png", image = clinical_nobiop_batch_pca$plot)

clinical_nobiop_batch_tsne <- plot_tsne(hs_clinical_nobiop_nb,
                                        plot_title = "tSNE - clinical samples without biopsies",
                                        plot_labels = FALSE)
clinical_nobiop_batch_tsne$plot

test <- simple_varpart(hs_clinical_nobiop)
## Loading required package: Matrix
## 
## Total:109 s
test$partition_plot

4.4 Perform DE of the clinical samples cure vs. fail

individual_celltypes <- subset_expt(hs_clinical_nobiop, subset="condition!='lost'")
## There were 55, now there are 40 samples.
hs_clinic_de <- sm(all_pairwise(individual_celltypes, model_batch = "svaseq", filter = TRUE))
hs_clinic_table <- sm(combine_de_tables(
    hs_clinic_de,
    excel = glue::glue("excel/individual_celltypes_table-v{ver}.xlsx")))
hs_clinic_sig <- sm(extract_significant_genes(
    hs_clinic_table,
    excel = glue::glue("excel/individual_celltypes_sig-v{ver}.xlsx")))

hs_clinic_sig[["summary_df"]]
##                 limma_change_counts_up limma_change_counts_down
## failure_vs_cure                    230                      369
##                 edger_change_counts_up edger_change_counts_down
## failure_vs_cure                    347                      322
##                 deseq_change_counts_up deseq_change_counts_down
## failure_vs_cure                    290                      371
##                 ebseq_change_counts_up ebseq_change_counts_down
## failure_vs_cure                     84                      268
##                 basic_change_counts_up basic_change_counts_down
## failure_vs_cure                     55                       69

4.4.1 Look at only the differential genes

A good suggestion from Theresa was to examine only the most variant genes from failure vs. cure and see how they change the clustering/etc results. This is my attempt to address this query.

hs_clinic_topn <- sm(extract_significant_genes(hs_clinic_table, n = 100))
table <- "failure_vs_cure"
wanted <- rbind(hs_clinic_topn[["deseq"]][["ups"]][[table]],
                hs_clinic_topn[["deseq"]][["downs"]][[table]])

small_expt <- exclude_genes_expt(hs_clinical_nobiop, ids = rownames(wanted), method = "keep")
## Before removal, there were 19941 genes, now there are 200.
## There are 55 samples which kept less than 90 percent counts.
##  1017n1  1017m1  1034n1  1034n2  1034m2 1034m2-  2052e1  2052m2  2052n2  2052m3 
##  0.1412  0.2526  1.1251  1.3798  0.8174  0.8127  0.4081  0.4147  0.3047  0.5205 
##  2052n3  2065m1  2065n1  2066m1  2066n1  2065m2  2065n2  2066m2  2068m1  2068n1 
##  0.3258  0.8297  1.1489  0.3545  0.2052  0.6134  0.5544  0.5485  0.5715  0.5106 
##  2068e1  2072m1  2072n1  2072e1  2073m1  2073n1  2073e1  2068m2  2068n2  2068e2 
##  1.0353  0.5206  0.3950  0.6709  0.5844  0.7572  0.5837  0.2638  0.2737  0.3495 
##  2072m2  2072n2  2072e2  2073m2  2073n2  2073e2  2068m3  2068n3  2068e3  2072m3 
##  0.2881  0.2474  0.3760  0.7659  1.3507  0.4852  0.3715  0.3559  0.4352  0.5425 
##  2072n3  2072e3  2073m3  2073n3  2073e3  2162m1  2162n1  2162e1  2168e1  2168m2 
##  0.8864  0.5136  0.4433  0.3778  0.3168  0.4533  0.3589  0.6662  0.7565  0.7862 
##  2168n2  2168e2  2168m3  2168n3  2168e3 
##  1.2432  0.6534  0.8916  1.4272  0.7247
small_norm <- sm(normalize_expt(small_expt, transform = "log2", convert = "cpm",
                                norm = "quant", filter = TRUE))
plot_pca(small_norm)$plot

small_nb <- normalize_expt(small_expt, transform = "log2", convert = "cpm",
                           batch = "svaseq", norm = "quant", filter = TRUE)
## Warning in normalize_expt(small_expt, transform = "log2", convert = "cpm", :
## Quantile normalization and sva do not always play well together.
## Removing 0 low-count genes (200 remaining).
## batch_counts: Before batch/surrogate estimation, 0 entries are x==0: 0%.
## batch_counts: Before batch/surrogate estimation, 131 entries are 0<x<1: 1%.
## Setting 8 low elements to zero.
## transform_counts: Found 8 values equal to 0, adding 1 to the matrix.
plot_pca(small_nb)$plot

## DESeq2 MA plot of failure / cure
hs_clinic_table[["plots"]][["failure_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure
hs_clinic_table[["plots"]][["failure_vs_cure"]][["deseq_vol_plots"]]$plot

4.4.2 g:Profiler results using the significant up and down genes

ups <- hs_clinic_sig[["deseq"]][["ups"]][[1]]
downs <- hs_clinic_sig[["deseq"]][["downs"]][[1]]

hs_clinic_gprofiler_ups <- simple_gprofiler(ups)
## Performing gProfiler GO search of 290 genes against hsapiens.
## GO search found 22 hits.
## Performing gProfiler KEGG search of 290 genes against hsapiens.
## KEGG search found 2 hits.
## Performing gProfiler REAC search of 290 genes against hsapiens.
## REAC search found 6 hits.
## Performing gProfiler MI search of 290 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 290 genes against hsapiens.
## TF search found 28 hits.
## Performing gProfiler CORUM search of 290 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 290 genes against hsapiens.
## HP search found 0 hits.
hs_clinic_gprofiler_ups[["pvalue_plots"]][["bpp_plot_over"]]

hs_clinic_gprofiler_ups[["pvalue_plots"]][["mfp_plot_over"]]

hs_clinic_gprofiler_ups[["pvalue_plots"]][["reactome_plot_over"]]

##hs_try2 <- simple_gprofiler2(ups)

hs_clinic_gprofiler_downs <- simple_gprofiler(downs)
## Performing gProfiler GO search of 371 genes against hsapiens.
## GO search found 62 hits.
## Performing gProfiler KEGG search of 371 genes against hsapiens.
## KEGG search found 4 hits.
## Performing gProfiler REAC search of 371 genes against hsapiens.
## REAC search found 4 hits.
## Performing gProfiler MI search of 371 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 371 genes against hsapiens.
## TF search found 21 hits.
## Performing gProfiler CORUM search of 371 genes against hsapiens.
## CORUM search found 3 hits.
## Performing gProfiler HP search of 371 genes against hsapiens.
## HP search found 6 hits.
hs_clinic_gprofiler_downs[["pvalue_plots"]][["bpp_plot_over"]]

hs_clinic_gprofiler_downs[["pvalue_plots"]][["mfp_plot_over"]]

hs_clinic_gprofiler_downs[["pvalue_plots"]][["reactome_plot_over"]]

4.5 Perform GSVA on the clinical samples

hs_celltype_gsva_c2 <- sm(simple_gsva(individual_celltypes))
hs_celltype_gsva_c2_sig <- sm(get_sig_gsva_categories(
    hs_celltype_gsva_c2,
    excel = "excel/individual_celltypes_gsva_c2.xlsx"))
broad_c7 <- GSEABase::getGmt("reference/msigdb/c7.all.v7.2.entrez.gmt",
                             collectionType = GSEABase::BroadCollection(category = "c7"),
                             geneIdType = GSEABase::EntrezIdentifier())
hs_celltype_gsva_c7 <- sm(simple_gsva(individual_celltypes, signatures = broad_c7,
                                      msig_xml = "reference/msigdb_v7.2.xml", cores = 10))
hs_celltype_gsva_c7_sig <- sm(get_sig_gsva_categories(
    hs_celltype_gsva_c7,
    excel = "excel/individual_celltypes_gsva_c7.xlsx"))

5 Individual Cell types

The following blocks split the samples into a few groups by sample type and look at the distributions between them.

5.1 Implementation details

Get top/bottom n genes for each cell type, using clinical outcome as the factor of interest. For the moment, use sva for the DE analysis. Provide cpms for the top/bottom n genes.

Start with top/bottom 200. Perform default logFC and p-value as well.

5.1.1 Shared contrasts

Here is the contrast we will use throughput, I am leaving open the option to add more.

keepers <- list(
  "fail_vs_cure" = c("failure", "cure"))

5.2 Monocytes

5.2.1 Evaluate Monocyte samples

mono <- subset_expt(hs_valid, subset = "typeofcells=='Monocytes'") %>%
  set_expt_conditions(fact = "clinicaloutcome") %>%
  set_expt_batches(fact = "donor") %>%
  set_expt_colors(colors = chosen_colors)
## There were 105, now there are 21 samples.
## FIXME set_expt_colors should speak up if there are mismatches here!!!

save_result <- save(mono, file = "rda/monocyte_expt.rda")
mono_norm <- normalize_expt(mono, convert = "cpm", filter = TRUE,
                            transform = "log2", norm = "quant")
## Removing 8968 low-count genes (10973 remaining).
## transform_counts: Found 9 values equal to 0, adding 1 to the matrix.
plt <- plot_pca(mono_norm, plot_labels = FALSE)$plot
pp(file = glue("images/mono_pca_normalized-v{ver}.pdf"), image = plt)

mono_nb <- normalize_expt(mono, convert = "cpm", filter = TRUE,
                          transform = "log2", batch = "svaseq")
## Removing 8968 low-count genes (10973 remaining).
## batch_counts: Before batch/surrogate estimation, 1144 entries are x==0: 0%.
## batch_counts: Before batch/surrogate estimation, 12729 entries are 0<x<1: 6%.
## Setting 368 low elements to zero.
## transform_counts: Found 368 values equal to 0, adding 1 to the matrix.
plt <- plot_pca(mono_nb, plot_labels = FALSE)$plot
pp(file = glue("images/mono_pca_normalized_batch-v{ver}.pdf"), image = plt)

5.2.2 DE of Monocyte samples

5.2.2.1 Without sva

mono_de <- sm(all_pairwise(mono, model_batch = FALSE, filter = TRUE))
mono_tables <- sm(combine_de_tables(
    mono_de, keepers = keepers,
    excel = glue::glue("excel/monocyte_clinical_all_tables-v{ver}.xlsx")))
written <- write_xlsx(data = mono_tables[["data"]][[1]],
                      excel = glue::glue("excel/monocyte_clinical_table-v{ver}.xlsx"))
mono_sig <- sm(extract_significant_genes(mono_tables, according_to = "deseq"))
written <- write_xlsx(data = mono_sig[["deseq"]][["ups"]][[1]],
                      excel = glue::glue("excel/monocyte_clinical_sigup-v{ver}.xlsx"))
written <- write_xlsx(data = mono_sig[["deseq"]][["downs"]][[1]],
                      excel = glue::glue("excel/monocyte_clinical_sigdown-v{ver}.xlsx"))

mono_pct_sig <- sm(extract_significant_genes(mono_tables, n = 200,
                                             lfc = NULL, p = NULL, according_to = "deseq"))
written <- write_xlsx(data = mono_pct_sig[["deseq"]][["ups"]][[1]],
                      excel = glue::glue("excel/monocyte_clinical_sigup_pct-v{ver}.xlsx"))
written <- write_xlsx(data = mono_pct_sig[["deseq"]][["downs"]][[1]],
                      excel = glue::glue("excel/monocyte_clinical_sigdown_pct-v{ver}.xlsx"))
mono_sig$summary_df
## data frame with 0 columns and 1 row
## Print out a table of the cpm values for other explorations.
mono_cpm <- sm(normalize_expt(mono, convert = "cpm"))
written <- write_xlsx(data = exprs(mono_cpm),
                      excel = glue::glue("excel/monocyte_cpm_before_batch-v{ver}.xlsx"))
mono_bcpm <- sm(normalize_expt(mono, filter = TRUE, convert = "cpm", batch = "svaseq"))
written <- write_xlsx(data = exprs(mono_bcpm),
                      excel = glue::glue("excel/monocyte_cpm_after_batch-v{ver}.xlsx"))

5.2.2.2 With sva

mono_de_sva <- sm(all_pairwise(mono, model_batch = "svaseq", filter = TRUE))
mono_tables_sva <- sm(combine_de_tables(
    mono_de_sva, keepers = keepers,
    excel = glue::glue("excel/monocyte_clinical_all_tables_sva-v{ver}.xlsx")))
mono_sig_sva <- sm(extract_significant_genes(
    mono_tables_sva,
    excel = glue::glue("excel/monocyte_clinical_sig_tables_sva-v{ver}.xlsx"),
    according_to = "deseq"))

5.2.2.3 Monocyte DE plots

First print out the DE plots without and then with sva estimates.

## DESeq2 MA plot of failure / cure
mono_tables[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure
mono_tables[["plots"]][["fail_vs_cure"]][["deseq_vol_plots"]]$plot

## DESeq2 MA plot of failure / cure with svaseq
mono_tables_sva[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure with svaseq
mono_tables_sva[["plots"]][["fail_vs_cure"]][["deseq_vol_plots"]]$plot

5.2.2.5 Monocyte MSigDB query

broad_c7 <- GSEABase::getGmt("reference/msigdb/c7.all.v7.2.entrez.gmt",
                             collectionType = GSEABase::BroadCollection(category = "c7"),
                             geneIdType = GSEABase::EntrezIdentifier())

mono_up_goseq_msig <- goseq_msigdb(sig_genes = ups, signatures = broad_c7,
                                   signature_category = "c7", length_db = hs_length)
## Before conversion: 149, after conversion: 147.
## Before conversion: 227921, after conversion: 35341.
## Found 132 go_db genes and 147 length_db genes out of 147.
mono_down_goseq_msig <- goseq_msigdb(sig_genes = downs, signatures = broad_c7,
                                     signature_category = "c7", length_db = hs_length)
## Before conversion: 262, after conversion: 258.
## Before conversion: 227921, after conversion: 35341.
## Found 249 go_db genes and 258 length_db genes out of 258.

5.2.2.6 Plot of similar experiments

## Monocyte genes with increased expression in the failed samples
## share genes with the following experiments
mono_up_goseq_msig[["pvalue_plots"]][["mfp_plot_over"]]

## Monocyte genes with increased expression in the cured samples
## share genes with the following experiments
mono_down_goseq_msig[["pvalue_plots"]][["mfp_plot_over"]]

5.2.3 Evaluate Neutrophil samples

neut <- subset_expt(hs_valid, subset = "typeofcells=='Neutrophils'") %>%
  set_expt_conditions(fact = "clinicaloutcome") %>%
  set_expt_batches(fact = "donor") %>%
  set_expt_colors(colors = chosen_colors)
## There were 105, now there are 20 samples.
save_result <- save(neut, file = "rda/neutrophil_expt.rda")
neut_norm <- sm(normalize_expt(neut, convert = "cpm", filter = TRUE, transform = "log2"))
plt <- plot_pca(neut_norm, plot_labels = FALSE)$plot
pp(file = glue("images/neut_pca_normalized-v{ver}.pdf"), image = plt)

neut_nb <- sm(normalize_expt(neut, convert = "cpm", filter = TRUE,
                             transform = "log2", batch = "svaseq"))
plt <- plot_pca(neut_nb, plot_labels = FALSE)$plot
pp(file = glue("images/neut_pca_normalized_svaseq-v{ver}.pdf"), image = plt)

5.2.4 DE of Netrophil samples

5.2.4.1 Without sva

neut_de <- sm(all_pairwise(neut, model_batch = FALSE, filter = TRUE))
neut_tables <- sm(combine_de_tables(
    neut_de, keepers = keepers,
    excel = glue::glue("excel/neutrophil_clinical_all_tables-v{ver}.xlsx")))
written <- write_xlsx(data = neut_tables[["data"]][[1]],
                      excel = glue::glue("excel/neutrophil_clinical_table-v{ver}.xlsx"))
neut_sig <- sm(extract_significant_genes(neut_tables, according_to = "deseq"))
written <- write_xlsx(data = neut_sig[["deseq"]][["ups"]][[1]],
                      excel = glue::glue("excel/neutrophil_clinical_sigup-v{ver}.xlsx"))
written <- write_xlsx(data = neut_sig[["deseq"]][["downs"]][[1]],
                      excel = glue::glue("excel/neutrophil_clinical_sigdown-v{ver}.xlsx"))

neut_pct_sig <- sm(extract_significant_genes(neut_tables, n = 200, lfc = NULL,
                                             p = NULL, according_to = "deseq"))
written <- write_xlsx(data = neut_sig[["deseq"]][["ups"]][[1]],
                      excel = glue::glue("excel/neutrophil_clinical_sigup_pct-v{ver}.xlsx"))
written <- write_xlsx(data = neut_sig[["deseq"]][["downs"]][[1]],
                      excel = glue::glue("excel/neutrophil_clinical_sigdown_pct-v{ver}.xlsx"))
neut_cpm <- sm(normalize_expt(neut, convert = "cpm"))
written <- write_xlsx(data = exprs(neut_cpm),
                      excel = glue::glue("excel/neutrophil_cpm_before_batch-v{ver}.xlsx"))
neut_bcpm <- sm(normalize_expt(neut, filter = TRUE, batch = "svaseq", convert = "cpm"))
written <- write_xlsx(data = exprs(neut_bcpm),
                      excel = glue::glue("excel/neutrophil_cpm_after_batch-v{ver}.xlsx"))

5.2.4.2 With sva

neut_de_sva <- sm(all_pairwise(neut, model_batch = "svaseq", filter = TRUE))
neut_tables_sva <- sm(combine_de_tables(
    neut_de_sva, keepers = keepers,
    excel = glue::glue("excel/neutrophil_clinical_all_tables_sva-v{ver}.xlsx")))
neut_sig_sva <- sm(extract_significant_genes(
    neut_tables_sva,
    excel = glue::glue("excel/neutrophil_clinical_sig_tables_sva-v{ver}.xlsx"),
    according_to = "deseq"))

5.2.4.3 Neutrophil DE plots

## DESeq2 MA plot of failure / cure
neut_tables[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure
neut_tables[["plots"]][["fail_vs_cure"]][["deseq_vol_plots"]]$plot

## DESeq2 MA plot of failure / cure with sva
neut_tables_sva[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure with sva
neut_tables_sva[["plots"]][["fail_vs_cure"]][["deseq_vol_plots"]]$plot

5.2.4.5 Neutrophil GSVA query

neut_up_goseq_msig <- goseq_msigdb(sig_genes = ups, signatures = broad_c7,
                                   signature_category = "c7", length_db = hs_length)
## Before conversion: 271, after conversion: 267.
## Before conversion: 227921, after conversion: 35341.
## Found 251 go_db genes and 267 length_db genes out of 267.
neut_down_goseq_msig <- goseq_msigdb(sig_genes = downs, signatures = broad_c7,
                                     signature_category = "c7", length_db = hs_length)
## Before conversion: 260, after conversion: 255.
## Before conversion: 227921, after conversion: 35341.
## Found 247 go_db genes and 255 length_db genes out of 255.

5.2.4.6 Plot of similar experiments

## Neutrophil genes with increased expression in the failed samples
## share genes with the following experiments
neut_up_goseq_msig[["pvalue_plots"]][["mfp_plot_over"]]

## Neutrophil genes with increased expression in the cured samples
## share genes with the following experiments
neut_down_goseq_msig[["pvalue_plots"]][["mfp_plot_over"]]

5.3 Eosinophils

5.3.1 Evaluate Eosinophil samples

eo <- subset_expt(hs_valid, subset = "typeofcells=='Eosinophils'") %>%
  set_expt_conditions(fact = "clinicaloutcome") %>%
  set_expt_batches(fact = "donor") %>%
  set_expt_colors(colors = chosen_colors)
## There were 105, now there are 14 samples.
save_result <- save(eo, file = "rda/eosinophil_expt.rda")
eo_norm <- sm(normalize_expt(eo, convert = "cpm", transform = "log2",
                             norm = "quant", filter = TRUE))
plt <- plot_pca(eo_norm, plot_labels = FALSE)$plot
pp(file = glue("images/eo_pca_normalized-v{ver}.pdf"), image = plt)

eo_nb <- sm(normalize_expt(eo, convert = "cpm", transform = "log2",
                           filter = TRUE, batch = "svaseq"))
plot_pca(eo_nb)$plot

5.3.2 DE of Eosinophil samples

5.3.2.1 Withouth sva

eo_de <- sm(all_pairwise(eo, model_batch = FALSE, filter = TRUE))
eo_tables <- sm(combine_de_tables(
    eo_de, keepers = keepers,
    excel = glue::glue("excel/eosinophil_clinical_all_tables-v{ver}.xlsx")))
written <- write_xlsx(data = eo_tables[["data"]][[1]],
                      excel = glue::glue("excel/eosinophil_clinical_table-v{ver}.xlsx"))
eo_sig <- sm(extract_significant_genes(eo_tables, according_to = "deseq"))
written <- write_xlsx(data = eo_sig[["deseq"]][["ups"]][[1]],
                      excel = glue::glue("excel/eosinophil_clinical_sigup-v{ver}.xlsx"))
written <- write_xlsx(data = eo_sig[["deseq"]][["downs"]][[1]],
                      excel = glue::glue("excel/eosinophil_clinical_sigdown-v{ver}.xlsx"))

eo_pct_sig <- sm(extract_significant_genes(eo_tables, n = 200,
                                           lfc = NULL, p = NULL, according_to = "deseq"))
written <- write_xlsx(data = eo_pct_sig[["deseq"]][["ups"]][[1]],
                      excel = glue::glue("excel/eosinophil_clinical_sigup_pct-v{ver}.xlsx"))
written <- write_xlsx(data = eo_pct_sig[["deseq"]][["downs"]][[1]],
                      excel = glue::glue("excel/eosinophil_clinical_sigdown_pct-v{ver}.xlsx"))

eo_cpm <- sm(normalize_expt(eo, convert = "cpm"))
written <- write_xlsx(data = exprs(eo_cpm),
                      excel = glue::glue("excel/eosinophil_cpm_before_batch-v{ver}.xlsx"))
eo_bcpm <- sm(normalize_expt(eo, filter = TRUE, batch = "svaseq", convert = "cpm"))
written <- write_xlsx(data = exprs(eo_bcpm),
                      excel = glue::glue("excel/eosinophil_cpm_after_batch-v{ver}.xlsx"))

5.3.2.2 With sva

eo_de_sva <- sm(all_pairwise(eo, model_batch = "svaseq", filter = TRUE))
eo_tables_sva <- sm(combine_de_tables(
    eo_de_sva, keepers = keepers,
    excel = glue::glue("excel/eosinophil_clinical_all_tables_sva-v{ver}.xlsx")))
eo_sig_sva <- sm(extract_significant_genes(
    eo_tables_sva,
    excel = glue::glue("excel/eosinophil_clinical_sig_tables_sva-v{ver}.xlsx"),
    according_to = "deseq"))

5.3.2.3 Eosinophil DE plots

## DESeq2 MA plot of failure / cure
eo_tables[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure
eo_tables[["plots"]][["fail_vs_cure"]][["deseq_vol_plots"]]$plot

## DESeq2 MA plot of failure / cure with sva
eo_tables_sva[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure with sva
eo_tables_sva[["plots"]][["fail_vs_cure"]][["deseq_vol_plots"]]$plot

5.3.2.5 Eosinophil MSigDB query

eo_up_goseq_msig <- goseq_msigdb(sig_genes = ups, signatures = broad_c7,
                                 signature_category = "c7", length_db = hs_length)
## Before conversion: 212, after conversion: 211.
## Before conversion: 227921, after conversion: 35341.
## Found 183 go_db genes and 211 length_db genes out of 211.
eo_down_goseq_msig <- goseq_msigdb(sig_genes = downs, signatures = broad_c7,
                                   signature_category = "c7", length_db = hs_length)
## Before conversion: 154, after conversion: 152.
## Before conversion: 227921, after conversion: 35341.
## Found 139 go_db genes and 152 length_db genes out of 152.

5.3.2.6 Plot of similar experiments

## Eosinophil genes with increased expression in the failed samples
## share genes with the following experiments
eo_up_goseq_msig[["pvalue_plots"]][["mfp_plot_over"]]

## Eosinophil genes with increased expression in the cured samples
## share genes with the following experiments
eo_down_goseq_msig[["pvalue_plots"]][["mfp_plot_over"]]

5.4 Biopsies

5.4.1 Evaluate Biopsy samples

biop <- subset_expt(hs_valid, subset = "typeofcells=='Biopsy'") %>%
  set_expt_conditions(fact = "clinicaloutcome") %>%
  set_expt_batches(fact = "donor") %>%
  set_expt_colors(colors = chosen_colors)
## There were 105, now there are 32 samples.
save_result <- save(biop, file = "rda/biopsy_expt.rda")
biop_norm <- normalize_expt(biop, filter = TRUE, convert = "cpm",
                            transform = "log2", norm = "quant")
## Removing 5950 low-count genes (13991 remaining).
## transform_counts: Found 5 values equal to 0, adding 1 to the matrix.
plt <- plot_pca(biop_norm, plot_labels = FALSE)$plot
pp(file = glue("images/biop_pca_normalized-v{ver}.pdf"), image = plt)

biop_nb <- sm(normalize_expt(biop, convert = "cpm", filter = TRUE,
                             transform = "log2", batch = "svaseq"))
plt <- plot_pca(biop_nb, plot_labels = FALSE)$plot
pp(file = glue("images/biop_pca_normalized_svaseq-v{ver}.pdf"), image = plt)

5.4.2 DE of Biopsy samples

5.4.2.1 Without sva

biop_de <- sm(all_pairwise(biop, model_batch = FALSE, filter = TRUE))
biop_tables <- combine_de_tables(biop_de, keepers = keepers,
                                 excel = glue::glue("excel/biopsy_clinical_all_tables-v{ver}.xlsx"))
## Deleting the file excel/biopsy_clinical_all_tables-v202104.xlsx before writing the tables.
written <- write_xlsx(data = biop_tables[["data"]][[1]],
                      excel = glue::glue("excel/biopsy_clinical_table-v{ver}.xlsx"))
biop_sig <- extract_significant_genes(biop_tables, according_to = "deseq")
##written <- write_xlsx(data = biop_sig[["deseq"]][["ups"]][[1]],
##                      excel = glue::glue("excel/biopsy_clinical_sigup-v{ver}.xlsx"))
written <- write_xlsx(data = biop_sig[["deseq"]][["downs"]][[1]],
                      excel = glue::glue("excel/biopsy_clinical_sigdown-v{ver}.xlsx"))
biop_pct_sig <- extract_significant_genes(biop_tables, n = 200, lfc = NULL, p = NULL, according_to = "deseq")
## Getting the top and bottom 200 genes.
written <- write_xlsx(data = biop_pct_sig[["deseq"]][["ups"]][[1]],
                      excel = glue::glue("excel/biopsy_clinical_sigup_pct-v{ver}.xlsx"))
written <- write_xlsx(data = biop_pct_sig[["deseq"]][["downs"]][[1]],
                      excel = glue::glue("excel/biopsy_clinical_sigdown_pct-v{ver}.xlsx"))

biop_cpm <- sm(normalize_expt(biop, convert = "cpm"))
written <- write_xlsx(data = exprs(biop_cpm),
                      excel = glue::glue("excel/biopsy_cpm_before_batch-v{ver}.xlsx"))
biop_bcpm <- sm(normalize_expt(biop, filter = TRUE, batch = "svaseq", convert = "cpm"))
written <- write_xlsx(data = exprs(biop_bcpm),
                      excel = glue::glue("excel/biopsy_cpm_after_batch-v{ver}.xlsx"))

5.4.2.2 with sva

biop_de_sva <- sm(all_pairwise(biop, model_batch = "svaseq", filter = TRUE))
biop_tables_sva <- sm(combine_de_tables(
    biop_de_sva, keepers = keepers,
    excel = glue::glue("excel/biopsy_clinical_all_tables_sva-v{ver}.xlsx")))
biop_sig_sva <- sm(extract_significant_genes(
    biop_tables_sva,
    excel = glue::glue("excel/biopsy_clinical_sig_tables_sva-v{ver}.xlsx"),
    according_to = "deseq"))

5.4.2.3 Biopsy DE plots

## DESeq2 MA plot of failure / cure
biop_tables[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure
biop_tables[["plots"]][["fail_vs_cure"]][["deseq_vol_plots"]]$plot

## DESeq2 MA plot of failure / cure
biop_tables_sva[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]$plot

## DESeq2 Volcano plot of failure / cure
biop_tables_sva[["plots"]][["fail_vs_cure"]][["deseq_vol_plots"]]$plot

if (!isTRUE(get0("skip_load"))) {
  pander::pander(sessionInfo())
  message(paste0("This is hpgltools commit: ", get_git_commit()))
  message(paste0("Saving to ", savefile))
  tmp <- sm(saveme(filename = savefile))
}
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 75c439759cfc03b66dda979814171e43e69506ca
## This is hpgltools commit: Thu Apr 22 12:37:06 2021 -0400: 75c439759cfc03b66dda979814171e43e69506ca
## Saving to tmrc3_02sample_estimation_v202104.rda.xz
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiVE1SQzMgQ29tcHJlaGVuc2l2ZSBEYXRhIEFuYWx5c2lzOiAyMDIxMDQiCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICBjb2xsYXBzZWQ6IGZhbHNlCiAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4OwogIH0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGUgPSBGQUxTRX0KbGlicmFyeShocGdsdG9vbHMpCnR0IDwtIHNtKGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKSkKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3MgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICB2ZXJib3NlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAxMjAsCiAgICAgICAgICAgICAgICAgICAgIGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoZXJyb3IgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoID0gMTIsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0ID0gMTIsCiAgICAgICAgICAgICAgICAgICAgICBkcGkgPSA5NikKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWwgPSAiYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpKQp2ZXIgPC0gIjIwMjEwNCIKcnVuZGF0ZSA8LSBmb3JtYXQoU3lzLkRhdGUoKSwgZm9ybWF0ID0gIiVZJW0lZCIpCgpybWRfZmlsZSA8LSBnbHVlOjpnbHVlKCJ0bXJjM18wMnNhbXBsZV9lc3RpbWF0aW9uX3Z7dmVyfS5SbWQiKQpzYXZlZmlsZSA8LSBnc3ViKHBhdHRlcm4gPSAiXFwuUm1kIiwgcmVwbGFjZSA9ICJcXC5yZGFcXC54eiIsIHggPSBybWRfZmlsZSkKYGBgCgojIEludHJvZHVjdGlvbgoKVGhpcyBkb2N1bWVudCBpcyBpbnRlbmRlZCB0byBwcm92aWRlIGFuIG92ZXJ2aWV3IG9mIFRNUkMzIHNhbXBsZXMgd2hpY2ggaGF2ZQpiZWVuIHNlcXVlbmNlZC4gIEl0IGluY2x1ZGVzIHNvbWUgcGxvdHMgYW5kIGFuYWx5c2VzIHNob3dpbmcgdGhlIHJlbGF0aW9uc2hpcHMKYW1vbmcgdGhlIHNhbXBsZXMgYXMgd2VsbCBhcyBzb21lIGRpZmZlcmVudGlhbCBhbmFseXNlcyB3aGVuIHBvc3NpYmxlLgoKIyBBbm5vdGF0aW9uCgpXZSB0YWtlIHRoZSBhbm5vdGF0aW9uIGRhdGEgZnJvbSBlbnNlbWJsJ3MgYmlvbWFydCBpbnN0YW5jZS4gIFRoZSBnZW5vbWUgd2hpY2gKd2FzIHVzZWQgdG8gbWFwIHRoZSBkYXRhIHdhcyBoZzM4IHJldmlzaW9uIDEwMC4gIE15IGRlZmF1bHQgd2hlbiB1c2luZyBiaW9tYXJ0IGlzCnRvIGxvYWQgdGhlIGRhdGEgZnJvbSAxIHllYXIgYmVmb3JlIHRoZSBjdXJyZW50IGRhdGUuCgpgYGB7ciBoc19hbm5vdH0KaHNfYW5ub3QgPC0gc20obG9hZF9iaW9tYXJ0X2Fubm90YXRpb25zKHllYXIgPSAiMjAyMCIpKQpoc19hbm5vdCA8LSBoc19hbm5vdFtbImFubm90YXRpb24iXV0KaHNfYW5ub3RbWyJ0cmFuc2NyaXB0Il1dIDwtIHBhc3RlMChyb3duYW1lcyhoc19hbm5vdCksICIuIiwgaHNfYW5ub3RbWyJ2ZXJzaW9uIl1dKQpyb3duYW1lcyhoc19hbm5vdCkgPC0gbWFrZS5uYW1lcyhoc19hbm5vdFtbImVuc2VtYmxfZ2VuZV9pZCJdXSwgdW5pcXVlID0gVFJVRSkKdHhfZ2VuZV9tYXAgPC0gaHNfYW5ub3RbLCBjKCJ0cmFuc2NyaXB0IiwgImVuc2VtYmxfZ2VuZV9pZCIpXQoKc3VtbWFyeShoc19hbm5vdCkKYGBgCgpgYGB7ciBoc19nb30KaHNfZ28gPC0gc20obG9hZF9iaW9tYXJ0X2dvKClbWyJnbyJdXSkKaHNfbGVuZ3RoIDwtIGhzX2Fubm90WywgYygiZW5zZW1ibF9nZW5lX2lkIiwgImNkc19sZW5ndGgiKV0KY29sbmFtZXMoaHNfbGVuZ3RoKSA8LSBjKCJJRCIsICJsZW5ndGgiKQpgYGAKCiMgU2FtcGxlIEVzdGltYXRpb24KCiMjIEdlbmVyYXRlIGV4cHJlc3Npb25zZXRzCgpUaGUgc2FtcGxlIHNoZWV0IGlzIGNvcGllZCBmcm9tIG91ciBzaGFyZWQgb25saW5lIHNoZWV0IGFuZCB1cGRhdGVkIHdpdGggZWFjaCByZWxlYXNlCm9mIHNlcXVlbmNpbmcgZGF0YS4KCmBgYHtyIHNhbXBsZXNoZWV0fQpzYW1wbGVzaGVldCA8LSAic2FtcGxlX3NoZWV0cy90bXJjM19zYW1wbGVzXzIwMjEwMy54bHN4IgpgYGAKCiMjIyBIaXNhdDIgZXhwcmVzc2lvbnNldHMKClRoZSBmaXJzdCB0aGluZyB0byBub3RlIGlzIHRoZSBsYXJnZSByYW5nZSBpbiBjb3ZlcmFnZS4gIFRoZXJlIGFyZSBtdWx0aXBsZQpzYW1wbGVzIHdpdGggY292ZXJhZ2Ugd2hpY2ggaXMgdG9vIGxvdyB0byB1c2UuICBUaGVzZSB3aWxsIGJlIHJlbW92ZWQgc2hvcnRseS4KCkluIHRoZSBmb2xsb3dpbmcgYmxvY2sgSSBpbW1lZGlhdGVseSBleGNsdWRlIGFueSBub24tY29kaW5nIHJlYWRzIGFzIHdlbGwuCgpgYGB7ciBhbGxfbmV3X2hpc2F0Mn0KIyMgQ3JlYXRlIHRoZSBleHByZXNzaW9uc2V0IGFuZCBpbW1lZGlhdGVseSBwYXNzIGl0IHRvIGEgZmlsdGVyCiMjIHJlbW92aW5nIHRoZSBub24gcHJvdGVpbiBjb2RpbmcgZ2VuZXMuCmhzX2V4cHQgPC0gc20oY3JlYXRlX2V4cHQoc2FtcGxlc2hlZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW4gPSAiaGczODEwMGhpc2F0ZmlsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZWZpbGUgPSBnbHVlOjpnbHVlKCJyZGEvaHNfZXhwdF9hbGwtdnt2ZXJ9LnJkYSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbyA9IGhzX2Fubm90KSkgJT4lCiAgZXhjbHVkZV9nZW5lc19leHB0KGNvbHVtbiA9ICJnZW5lX2Jpb3R5cGUiLCBtZXRob2QgPSAia2VlcCIsIHBhdHRlcm4gPSAicHJvdGVpbl9jb2RpbmciKQpgYGAKCiMjIyMgSW5pdGlhbCBtZXRyaWNzCgpPbmNlIHRoZSBkYXRhIHdhcyBsb2FkZWQsIHRoZXJlIGFyZSBhIGNvdXBsZSBvZiBtZXRyaWNzIHdoaWNoIG1heSBiZSBwbG90dGVkIGltbWVkaWF0ZWx5LgoKYGBge3IgaW5pdGlhbF9tZXRyaWNzfQpub256ZXJvIDwtIHBsb3Rfbm9uemVybyhoc19leHB0KQpub256ZXJvJHBsb3QKYGBgCgojIyBNaW5pbXVtIGNvdmVyYWdlIHNhbXBsZSBmaWx0ZXJpbmcKCkkgYXJiaXRyYXJpbHkgY2hvc2UgMTEsMDAwIG5vbi16ZXJvIGdlbmVzIGFzIGEgbWluaW11bS4gIFdlIG1heQp3YW50IHRoaXMgdG8gYmUgaGlnaGVyLgoKYGBge3IgaGlzYXQyX3dyaXRlLCBmaWcuc2hvdyA9ICJoaWRlIn0KaHNfdmFsaWQgPC0gc3Vic2V0X2V4cHQoaHNfZXhwdCwgbm9uemVybyA9IDExMDAwKQoKIyMgdmFsaWRfd3JpdGUgPC0gd3JpdGVfZXhwdChoc192YWxpZCwgZXhjZWwgPSBnbHVlKCJleGNlbC9oc192YWxpZC12e3Zlcn0ueGxzeCIpKQpgYGAKCiMgUHJvamVjdCBBaW1zCgpUaGUgcHJvamVjdCBzZWVrcyB0byBkZXRlcm1pbmUgdGhlIHJlbGF0aW9uc2hpcCBvZiB0aGUgaW5uYXRlIGltbXVuZSByZXNwb25zZQphbmQgaW5mbGFtbWF0b3J5IHNpZ25hbGluZyB0byB0aGUgY2xpbmljYWwgb3V0Y29tZSBvZiBhbnRpbGVpc2htYW5pYWwgZHJ1Zwp0cmVhdG1lbnQuIFdlIHdpbGwgdGVzdCB0aGUgaHlwb3RoZXNpcyB0aGF0IHRoZSBwcm9maWxlIG9mIGlubmF0ZSBpbW11bmUgY2VsbAphY3RpdmF0aW9uIGFuZCB0aGVpciBkeW5hbWljcyB0aHJvdWdoIHRoZSBjb3Vyc2Ugb2YgdHJlYXRtZW50IGRpZmZlciBiZXR3ZWVuIENMCnBhdGllbnRzIHdpdGggcHJvc3BlY3RpdmVseSBkZXRlcm1pbmVkIHRoZXJhcGV1dGljIGN1cmUgb3IgZmFpbHVyZS4KClRoaXMgd2lsbCBiZSBhY2hpZXZlZCB0aHJvdWdoIHRoZSBjaGFyYWN0ZXJpemF0aW9uIG9mIHRoZSBpbiB2aXZvIGR5bmFtaWNzIG9mCmJsb29kLWRlcml2ZWQgbW9ub2N5dGUsIG5ldXRyb3BoaWwgYW5kIGVvc2lub3BoaWwgdHJhbnNjcmlwdG9tZSBiZWZvcmUsIGR1cmluZwphbmQgYXQgdGhlIGVuZCBvZiB0cmVhdG1lbnQgaW4gQ0wgcGF0aWVudHMuIENlbGwtdHlwZSBzcGVjaWZpYyB0cmFuc2NyaXB0b21lcywKY29tcG9zaXRlIHNpZ25hdHVyZXMgYW5kIHRpbWUtcmVzcG9uc2UgZXhwcmVzc2lvbiBwcm9maWxlcyB3aWxsIGJlIGNvbnRyYXN0ZWQKYW1vbmcgcGF0aWVudHMgd2l0aCB0aGVyYXBldXRpYyBjdXJlIG9yIGZhaWx1cmUuCgojIyBQcmVwYXJhdGlvbgoKVG8gYWRkcmVzcyB0aGVzZSwgSSBhZGRlZCB0byB0aGUgZW5kIG9mIHRoZSBzYW1wbGUgc2hlZXQgY29sdW1ucyBuYW1lZAonY29uZGl0aW9uJywgJ2JhdGNoJywgJ2Rvbm9yJywgYW5kICd0aW1lJy4gIFRoZXNlIGFyZSBmaWxsZWQgaW4gd2l0aCBzaG9ydGhhbmQKdmFsdWVzIGFjY29yZGluZyB0byB0aGUgYWJvdmUuCgojIyBHbG9iYWwgdmlldwoKQmVmb3JlIGFkZHJlc3NpbmcgdGhlIHF1ZXN0aW9ucyBleHBsaWNpdGx5IGJ5IHN1YnNldHRpbmcgdGhlIGRhdGEsIEkgd2FudCB0byBnZXQKYSBsb29rIGF0IHRoZSBzYW1wbGVzIGFzIHRoZXkgYXJlLgoKYGBge3IgcHJlX3F1ZXN0aW9uc30KaHNfdmFsaWQgPC0gaHNfdmFsaWQgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gImNlbGxzc291cmNlIikgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0ID0gInR5cGVvZmNlbGxzIikgJT4lCiAgc2V0X2V4cHRfc2FtcGxlbmFtZXMobmV3bmFtZXMgPSBwRGF0YShoc192YWxpZClbWyJzYW1wbGVuYW1lIl1dKQoKYWxsX25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQoaHNfdmFsaWQsIHRyYW5zZm9ybSA9ICJsb2cyIiwgbm9ybSA9ICJxdWFudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQgPSAiY3BtIiwgZmlsdGVyID0gVFJVRSkpCgphbGxfcGNhIDwtIHBsb3RfcGNhKGFsbF9ub3JtLCBwbG90X2xhYmVscyA9IEZBTFNFLCBwbG90X3RpdGxlID0gIlBDQSAtIENlbGwgdHlwZSIpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvdG1yYzNfcGNhX25vbGFiZWxzLXZ7dmVyfS5wbmciKSwgaW1hZ2UgPSBhbGxfcGNhJHBsb3QpCgp3cml0ZS5jc3YoYWxsX3BjYSR0YWJsZSwgZmlsZSA9ICJjb29yZHMvaHNfZG9ub3JfcGNhX2Nvb3Jkcy5jc3YiKQpwbG90X2NvcmhlYXQoYWxsX25vcm0sIHBsb3RfdGl0bGUgPSAiSGVpcmFyY2hpY2FsIGNsdXN0ZXJpbmcgLSBjZWxsIHR5cGVzIikkcGxvdApgYGAKCiMjIEV4YW1pbmUgc2FtcGxlcyByZWxldmFudCB0byBjbGluaWNhbCBvdXRjb21lCgpOb3cgbGV0IHVzIGNvbnNpZGVyIG9ubHkgdGhlIHNhbXBsZXMgZm9yIHdoaWNoIHdlIGhhdmUgYSBjbGluaWNhbCBvdXRjb21lLgpUaGVzZSBmYWxsIHByaW1hcmlseSBpbnRvIGVpdGhlciAnY3VyZWQnIG9yICdmYWlsZWQnLCBidXQgc29tZSBwZW9wbGUgaGF2ZSBub3QKeWV0IHJldHVybmVkIHRvIHRoZSBjbGluaWMgYWZ0ZXIgdGhlIGZpcnN0IG9yIHNlY29uZCB2aXNpdC4gIFRoZXNlIGFyZSBkZWVtZWQKJ2xvc3QnLgoKYGBge3IgYWxsX2NsaW5pY2FsfQpjaG9zZW5fY29sb3JzIDwtIGMoIiNEOTVGMDIiLCAiIzc1NzBCMyIsICIjMUI5RTc3IiwgIiNGRjAwMDAiKQpuYW1lcyhjaG9zZW5fY29sb3JzKSA8LSBjKCJjdXJlIiwgImZhaWx1cmUiLCAibG9zdCIsICJudWxsIikKbmV3bmFtZXMgPC0gcERhdGEoaHNfdmFsaWQpW1sic2FtcGxlbmFtZSJdXQoKaHNfY2xpbmljYWwgPC0gaHNfdmFsaWQgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0ID0gImNsaW5pY2Fsb3V0Y29tZSIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdCA9ICJ0eXBlb2ZjZWxscyIpICU+JQogIHNldF9leHB0X2NvbG9ycyhjb2xvcnMgPSBjaG9zZW5fY29sb3JzKSAlPiUKICBzZXRfZXhwdF9zYW1wbGVuYW1lcyhuZXduYW1lcyA9IG5ld25hbWVzKSAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQgPSAidHlwZW9mY2VsbHMhPSdQQk1DcycmdHlwZW9mY2VsbHMhPSdNYWNyb3BoYWdlcyciKQoKaHNfY2xpbmljYWxfbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdChoc19jbGluaWNhbCwgZmlsdGVyID0gVFJVRSwgdHJhbnNmb3JtID0gImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQgPSAiY3BtIiwgbm9ybSA9ICJxdWFudCIpKQpjbGluaWNhbF9wY2EgPC0gcGxvdF9wY2EoaHNfY2xpbmljYWxfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSwgY2lzID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RfdGl0bGUgPSAiUENBIC0gY2xpbmljYWwgc2FtcGxlcyIpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvYWxsX2NsaW5pY2FsX25vYmF0Y2hfcGNhLXZ7dmVyfS5wbmciKSwgaW1hZ2UgPSBjbGluaWNhbF9wY2EkcGxvdCwKICAgaGVpZ2h0ID0gOCwgd2lkdGggPSAyMCkKYGBgCgojIyMgUmVwZWF0IHdpdGhvdXQgdGhlIGJpb3BzeSBzYW1wbGVzCgpgYGB7ciBpYmlkX25vYmlvcHN5fQpoc19jbGluaWNhbF9ub2Jpb3AgPC0gaHNfY2xpbmljYWwgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0ID0gInR5cGVvZmNlbGxzIT0nQmlvcHN5JyIpCgpoc19jbGluaWNhbF9ub2Jpb3Bfbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdChoc19jbGluaWNhbF9ub2Jpb3AsIGZpbHRlciA9IFRSVUUsIHRyYW5zZm9ybSA9ICJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydCA9ICJjcG0iLCBub3JtID0gInF1YW50IikpCmNsaW5pY2FsX25vYmlvcF9wY2EgPC0gcGxvdF9wY2EoaHNfY2xpbmljYWxfbm9iaW9wX25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UsIGNpcyA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdF90aXRsZSA9ICJQQ0EgLSBjbGluaWNhbCBzYW1wbGVzIHdpdGhvdXQgYmlvcHNpZXMiKQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL2FsbF9jbGluaWNhbF9ub2Jpb3Bfbm9iYXRjaF9wY2Etdnt2ZXJ9LnBuZyIpLAogICBpbWFnZSA9IGNsaW5pY2FsX25vYmlvcF9wY2EkcGxvdCkKYGBgCgojIyMgQXR0ZW1wdCB0byBjb3JyZWN0IGZvciB0aGUgc3Vycm9nYXRlIHZhcmlhYmxlcwoKQXQgdGhpcyB0aW1lIHdlIGhhdmUgdHdvIHByaW1hcnkgZGF0YSBzdHJ1Y3R1cmVzIG9mIGludGVyZXN0OiBoc19jbGluaWNhbCBhbmQgaHNfY2xpbmljYWxfbm9iaW9wCgpgYGB7ciBjbGluaWNhbF9zdmF9CmhzX2NsaW5pY2FsX25iIDwtIG5vcm1hbGl6ZV9leHB0KGhzX2NsaW5pY2FsLCBmaWx0ZXIgPSBUUlVFLCBiYXRjaCA9ICJzdmFzZXEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIikKY2xpbmljYWxfYmF0Y2hfcGNhIDwtIHBsb3RfcGNhKGhzX2NsaW5pY2FsX25iLCBwbG90X2xhYmVscyA9IEZBTFNFLCBjaXMgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdF90aXRsZSA9ICJQQ0EgLSBjbGluaWNhbCBzYW1wbGVzIikKY2xpbmljYWxfYmF0Y2hfcGNhJHBsb3QKCmhzX2NsaW5pY2FsX25vYmlvcF9uYiA8LSBzbShub3JtYWxpemVfZXhwdChoc19jbGluaWNhbF9ub2Jpb3AsIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIikpCmNsaW5pY2FsX25vYmlvcF9iYXRjaF9wY2EgPC0gcGxvdF9wY2EoaHNfY2xpbmljYWxfbm9iaW9wX25iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RfdGl0bGUgPSAiUENBIC0gY2xpbmljYWwgc2FtcGxlcyB3aXRob3V0IGJpb3BzaWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90X2xhYmVscyA9IEZBTFNFKQpwcChmaWxlID0gImltYWdlcy9jbGluaWNhbF9iYXRjaC5wbmciLCBpbWFnZSA9IGNsaW5pY2FsX25vYmlvcF9iYXRjaF9wY2EkcGxvdCkKCmNsaW5pY2FsX25vYmlvcF9iYXRjaF90c25lIDwtIHBsb3RfdHNuZShoc19jbGluaWNhbF9ub2Jpb3BfbmIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90X3RpdGxlID0gInRTTkUgLSBjbGluaWNhbCBzYW1wbGVzIHdpdGhvdXQgYmlvcHNpZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdF9sYWJlbHMgPSBGQUxTRSkKY2xpbmljYWxfbm9iaW9wX2JhdGNoX3RzbmUkcGxvdAoKdGVzdCA8LSBzaW1wbGVfdmFycGFydChoc19jbGluaWNhbF9ub2Jpb3ApCnRlc3QkcGFydGl0aW9uX3Bsb3QKYGBgCgojIyBQZXJmb3JtIERFIG9mIHRoZSBjbGluaWNhbCBzYW1wbGVzIGN1cmUgdnMuIGZhaWwKCmBgYHtyIGNsaW5pY2FsX2RlLCBmaWcuc2hvdz0iaGlkZSJ9CmluZGl2aWR1YWxfY2VsbHR5cGVzIDwtIHN1YnNldF9leHB0KGhzX2NsaW5pY2FsX25vYmlvcCwgc3Vic2V0PSJjb25kaXRpb24hPSdsb3N0JyIpCmhzX2NsaW5pY19kZSA8LSBzbShhbGxfcGFpcndpc2UoaW5kaXZpZHVhbF9jZWxsdHlwZXMsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpKQpoc19jbGluaWNfdGFibGUgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgICBoc19jbGluaWNfZGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2luZGl2aWR1YWxfY2VsbHR5cGVzX3RhYmxlLXZ7dmVyfS54bHN4IikpKQpoc19jbGluaWNfc2lnIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBoc19jbGluaWNfdGFibGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2luZGl2aWR1YWxfY2VsbHR5cGVzX3NpZy12e3Zlcn0ueGxzeCIpKSkKCmhzX2NsaW5pY19zaWdbWyJzdW1tYXJ5X2RmIl1dCmBgYAoKIyMjIExvb2sgYXQgb25seSB0aGUgZGlmZmVyZW50aWFsIGdlbmVzCgpBIGdvb2Qgc3VnZ2VzdGlvbiBmcm9tIFRoZXJlc2Egd2FzIHRvIGV4YW1pbmUgb25seSB0aGUgbW9zdCB2YXJpYW50CmdlbmVzIGZyb20gZmFpbHVyZSB2cy4gY3VyZSBhbmQgc2VlIGhvdyB0aGV5IGNoYW5nZSB0aGUgY2x1c3RlcmluZy9ldGMKcmVzdWx0cy4gIFRoaXMgaXMgbXkgYXR0ZW1wdCB0byBhZGRyZXNzIHRoaXMgcXVlcnkuCgpgYGB7ciBzbWFsbF9leHBsb3JlfQpoc19jbGluaWNfdG9wbiA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKGhzX2NsaW5pY190YWJsZSwgbiA9IDEwMCkpCnRhYmxlIDwtICJmYWlsdXJlX3ZzX2N1cmUiCndhbnRlZCA8LSByYmluZChoc19jbGluaWNfdG9wbltbImRlc2VxIl1dW1sidXBzIl1dW1t0YWJsZV1dLAogICAgICAgICAgICAgICAgaHNfY2xpbmljX3RvcG5bWyJkZXNlcSJdXVtbImRvd25zIl1dW1t0YWJsZV1dKQoKc21hbGxfZXhwdCA8LSBleGNsdWRlX2dlbmVzX2V4cHQoaHNfY2xpbmljYWxfbm9iaW9wLCBpZHMgPSByb3duYW1lcyh3YW50ZWQpLCBtZXRob2QgPSAia2VlcCIpCnNtYWxsX25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQoc21hbGxfZXhwdCwgdHJhbnNmb3JtID0gImxvZzIiLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybSA9ICJxdWFudCIsIGZpbHRlciA9IFRSVUUpKQpwbG90X3BjYShzbWFsbF9ub3JtKSRwbG90CgpzbWFsbF9uYiA8LSBub3JtYWxpemVfZXhwdChzbWFsbF9leHB0LCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYmF0Y2ggPSAic3Zhc2VxIiwgbm9ybSA9ICJxdWFudCIsIGZpbHRlciA9IFRSVUUpCnBsb3RfcGNhKHNtYWxsX25iKSRwbG90CmBgYAoKYGBge3IgY2xpbmljYWxfcGxvdH0KIyMgREVTZXEyIE1BIHBsb3Qgb2YgZmFpbHVyZSAvIGN1cmUKaHNfY2xpbmljX3RhYmxlW1sicGxvdHMiXV1bWyJmYWlsdXJlX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXSRwbG90CgojIyBERVNlcTIgVm9sY2FubyBwbG90IG9mIGZhaWx1cmUgLyBjdXJlCmhzX2NsaW5pY190YWJsZVtbInBsb3RzIl1dW1siZmFpbHVyZV92c19jdXJlIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dJHBsb3QKYGBgCgojIyMgZzpQcm9maWxlciByZXN1bHRzIHVzaW5nIHRoZSBzaWduaWZpY2FudCB1cCBhbmQgZG93biBnZW5lcwoKYGBge3IgcGVyZm9ybV9ncHJvZmlsZXJ9CnVwcyA8LSBoc19jbGluaWNfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWzFdXQpkb3ducyA8LSBoc19jbGluaWNfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dCgpoc19jbGluaWNfZ3Byb2ZpbGVyX3VwcyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHVwcykKaHNfY2xpbmljX2dwcm9maWxlcl91cHNbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCmhzX2NsaW5pY19ncHJvZmlsZXJfdXBzW1sicHZhbHVlX3Bsb3RzIl1dW1sibWZwX3Bsb3Rfb3ZlciJdXQpoc19jbGluaWNfZ3Byb2ZpbGVyX3Vwc1tbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQoKIyNoc190cnkyIDwtIHNpbXBsZV9ncHJvZmlsZXIyKHVwcykKCmhzX2NsaW5pY19ncHJvZmlsZXJfZG93bnMgPC0gc2ltcGxlX2dwcm9maWxlcihkb3ducykKaHNfY2xpbmljX2dwcm9maWxlcl9kb3duc1tbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KaHNfY2xpbmljX2dwcm9maWxlcl9kb3duc1tbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KaHNfY2xpbmljX2dwcm9maWxlcl9kb3duc1tbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpgYGAKCiMjIFBlcmZvcm0gR1NWQSBvbiB0aGUgY2xpbmljYWwgc2FtcGxlcwoKYGBge3IgZ3N2YSwgZmlnLnNob3cgPSAiaGlkZSJ9CmhzX2NlbGx0eXBlX2dzdmFfYzIgPC0gc20oc2ltcGxlX2dzdmEoaW5kaXZpZHVhbF9jZWxsdHlwZXMpKQpoc19jZWxsdHlwZV9nc3ZhX2MyX3NpZyA8LSBzbShnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcygKICAgIGhzX2NlbGx0eXBlX2dzdmFfYzIsCiAgICBleGNlbCA9ICJleGNlbC9pbmRpdmlkdWFsX2NlbGx0eXBlc19nc3ZhX2MyLnhsc3giKSkKCmJyb2FkX2M3IDwtIEdTRUFCYXNlOjpnZXRHbXQoInJlZmVyZW5jZS9tc2lnZGIvYzcuYWxsLnY3LjIuZW50cmV6LmdtdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGVjdGlvblR5cGUgPSBHU0VBQmFzZTo6QnJvYWRDb2xsZWN0aW9uKGNhdGVnb3J5ID0gImM3IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZUlkVHlwZSA9IEdTRUFCYXNlOjpFbnRyZXpJZGVudGlmaWVyKCkpCmhzX2NlbGx0eXBlX2dzdmFfYzcgPC0gc20oc2ltcGxlX2dzdmEoaW5kaXZpZHVhbF9jZWxsdHlwZXMsIHNpZ25hdHVyZXMgPSBicm9hZF9jNywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtc2lnX3htbCA9ICJyZWZlcmVuY2UvbXNpZ2RiX3Y3LjIueG1sIiwgY29yZXMgPSAxMCkpCmhzX2NlbGx0eXBlX2dzdmFfYzdfc2lnIDwtIHNtKGdldF9zaWdfZ3N2YV9jYXRlZ29yaWVzKAogICAgaHNfY2VsbHR5cGVfZ3N2YV9jNywKICAgIGV4Y2VsID0gImV4Y2VsL2luZGl2aWR1YWxfY2VsbHR5cGVzX2dzdmFfYzcueGxzeCIpKQpgYGAKCiMjIyBQcmludCBzb21lIHBsb3RzIG9mIHRoZSBHU1ZBIG91dHB1dHMKCmBgYHtyIGdzdmFfcGxvdHN9CiMjIFRoZSByYXcgaGVhdG1hcCBvZiB0aGUgQzIgdmFsdWVzCmhzX2NlbGx0eXBlX2dzdmFfYzJfc2lnW1sicmF3X3Bsb3QiXV0KIyMgVGhlICdzaWduaWZpY2FuY2UnIHNjb3JlcyBvZiB0aGUgQzIgdmFsdWVzCmhzX2NlbGx0eXBlX2dzdmFfYzJfc2lnW1sic2NvcmVfcGxvdCJdXQojIyBUaGUgc3Vic2V0IG9mIHNjb3JlcyBmb3IgY2F0ZWdvcmllcyBkZWVtZWQgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQuCmhzX2NlbGx0eXBlX2dzdmFfYzJfc2lnW1sic3Vic2V0X3Bsb3QiXV0KCiMjIFRoZSByYXcgaGVhdG1hcCBvZiB0aGUgQzcgdmFsdWVzCmhzX2NlbGx0eXBlX2dzdmFfYzdfc2lnW1sicmF3X3Bsb3QiXV0KIyMgVGhlICdzaWduaWZpY2FuY2UnIHNjb3JlcyBvZiB0aGUgQzcgdmFsdWVzCmhzX2NlbGx0eXBlX2dzdmFfYzdfc2lnW1sic2NvcmVfcGxvdCJdXQojIyBUaGUgc3Vic2V0IG9mIHNjb3JlcyBmb3IgY2F0ZWdvcmllcyBkZWVtZWQgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQuCmhzX2NlbGx0eXBlX2dzdmFfYzdfc2lnW1sic3Vic2V0X3Bsb3QiXV0KYGBgCgojIEluZGl2aWR1YWwgQ2VsbCB0eXBlcwoKVGhlIGZvbGxvd2luZyBibG9ja3Mgc3BsaXQgdGhlIHNhbXBsZXMgaW50byBhIGZldyBncm91cHMgYnkgc2FtcGxlIHR5cGUgYW5kIGxvb2sKYXQgdGhlIGRpc3RyaWJ1dGlvbnMgYmV0d2VlbiB0aGVtLgoKIyMgSW1wbGVtZW50YXRpb24gZGV0YWlscwoKR2V0IHRvcC9ib3R0b20gbiBnZW5lcyBmb3IgZWFjaCBjZWxsIHR5cGUsIHVzaW5nIGNsaW5pY2FsIG91dGNvbWUgYXMgdGhlIGZhY3RvciBvZiBpbnRlcmVzdC4KRm9yIHRoZSBtb21lbnQsIHVzZSBzdmEgZm9yIHRoZSBERSBhbmFseXNpcy4KUHJvdmlkZSBjcG1zIGZvciB0aGUgdG9wL2JvdHRvbSBuIGdlbmVzLgoKU3RhcnQgd2l0aCB0b3AvYm90dG9tIDIwMC4KUGVyZm9ybSBkZWZhdWx0IGxvZ0ZDIGFuZCBwLXZhbHVlIGFzIHdlbGwuCgojIyMgU2hhcmVkIGNvbnRyYXN0cwoKSGVyZSBpcyB0aGUgY29udHJhc3Qgd2Ugd2lsbCB1c2UgdGhyb3VnaHB1dCwgSSBhbSBsZWF2aW5nIG9wZW4gdGhlIG9wdGlvbiB0byBhZGQgbW9yZS4KCmBgYHtyIGtlZXBlcnN9CmtlZXBlcnMgPC0gbGlzdCgKICAiZmFpbF92c19jdXJlIiA9IGMoImZhaWx1cmUiLCAiY3VyZSIpKQpgYGAKCiMjIE1vbm9jeXRlcwoKIyMjIEV2YWx1YXRlIE1vbm9jeXRlIHNhbXBsZXMKCmBgYHtyIG1vbm9jeXRlc30KbW9ubyA8LSBzdWJzZXRfZXhwdChoc192YWxpZCwgc3Vic2V0ID0gInR5cGVvZmNlbGxzPT0nTW9ub2N5dGVzJyIpICU+JQogIHNldF9leHB0X2NvbmRpdGlvbnMoZmFjdCA9ICJjbGluaWNhbG91dGNvbWUiKSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3QgPSAiZG9ub3IiKSAlPiUKICBzZXRfZXhwdF9jb2xvcnMoY29sb3JzID0gY2hvc2VuX2NvbG9ycykKIyMgRklYTUUgc2V0X2V4cHRfY29sb3JzIHNob3VsZCBzcGVhayB1cCBpZiB0aGVyZSBhcmUgbWlzbWF0Y2hlcyBoZXJlISEhCgpzYXZlX3Jlc3VsdCA8LSBzYXZlKG1vbm8sIGZpbGUgPSAicmRhL21vbm9jeXRlX2V4cHQucmRhIikKbW9ub19ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm8sIGNvbnZlcnQgPSAiY3BtIiwgZmlsdGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgbm9ybSA9ICJxdWFudCIpCnBsdCA8LSBwbG90X3BjYShtb25vX25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UpJHBsb3QKcHAoZmlsZSA9IGdsdWUoImltYWdlcy9tb25vX3BjYV9ub3JtYWxpemVkLXZ7dmVyfS5wZGYiKSwgaW1hZ2UgPSBwbHQpCgptb25vX25iIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm8sIGNvbnZlcnQgPSAiY3BtIiwgZmlsdGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGJhdGNoID0gInN2YXNlcSIpCnBsdCA8LSBwbG90X3BjYShtb25vX25iLCBwbG90X2xhYmVscyA9IEZBTFNFKSRwbG90CnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvbW9ub19wY2Ffbm9ybWFsaXplZF9iYXRjaC12e3Zlcn0ucGRmIiksIGltYWdlID0gcGx0KQpgYGAKCiMjIyBERSBvZiBNb25vY3l0ZSBzYW1wbGVzCgojIyMjIFdpdGhvdXQgc3ZhCgpgYGB7ciBkZV9tb25vY3l0ZSwgZmlnLnNob3cgPSAiaGlkZSJ9Cm1vbm9fZGUgPC0gc20oYWxsX3BhaXJ3aXNlKG1vbm8sIG1vZGVsX2JhdGNoID0gRkFMU0UsIGZpbHRlciA9IFRSVUUpKQptb25vX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICAgIG1vbm9fZGUsIGtlZXBlcnMgPSBrZWVwZXJzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9tb25vY3l0ZV9jbGluaWNhbF9hbGxfdGFibGVzLXZ7dmVyfS54bHN4IikpKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IG1vbm9fdGFibGVzW1siZGF0YSJdXVtbMV1dLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9tb25vY3l0ZV9jbGluaWNhbF90YWJsZS12e3Zlcn0ueGxzeCIpKQptb25vX3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKG1vbm9fdGFibGVzLCBhY2NvcmRpbmdfdG8gPSAiZGVzZXEiKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBtb25vX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL21vbm9jeXRlX2NsaW5pY2FsX3NpZ3VwLXZ7dmVyfS54bHN4IikpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gbW9ub19zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL21vbm9jeXRlX2NsaW5pY2FsX3NpZ2Rvd24tdnt2ZXJ9Lnhsc3giKSkKCm1vbm9fcGN0X3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKG1vbm9fdGFibGVzLCBuID0gMjAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZmMgPSBOVUxMLCBwID0gTlVMTCwgYWNjb3JkaW5nX3RvID0gImRlc2VxIikpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gbW9ub19wY3Rfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWzFdXSwKICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvbW9ub2N5dGVfY2xpbmljYWxfc2lndXBfcGN0LXZ7dmVyfS54bHN4IikpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gbW9ub19wY3Rfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9tb25vY3l0ZV9jbGluaWNhbF9zaWdkb3duX3BjdC12e3Zlcn0ueGxzeCIpKQptb25vX3NpZyRzdW1tYXJ5X2RmCgojIyBQcmludCBvdXQgYSB0YWJsZSBvZiB0aGUgY3BtIHZhbHVlcyBmb3Igb3RoZXIgZXhwbG9yYXRpb25zLgptb25vX2NwbSA8LSBzbShub3JtYWxpemVfZXhwdChtb25vLCBjb252ZXJ0ID0gImNwbSIpKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGV4cHJzKG1vbm9fY3BtKSwKICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvbW9ub2N5dGVfY3BtX2JlZm9yZV9iYXRjaC12e3Zlcn0ueGxzeCIpKQptb25vX2JjcG0gPC0gc20obm9ybWFsaXplX2V4cHQobW9ubywgZmlsdGVyID0gVFJVRSwgY29udmVydCA9ICJjcG0iLCBiYXRjaCA9ICJzdmFzZXEiKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBleHBycyhtb25vX2JjcG0pLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9tb25vY3l0ZV9jcG1fYWZ0ZXJfYmF0Y2gtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMjIFdpdGggc3ZhCgpgYGB7ciBkZV9tb25vX3N2YSwgZmlnLnNob3cgPSAiaGlkZSJ9Cm1vbm9fZGVfc3ZhIDwtIHNtKGFsbF9wYWlyd2lzZShtb25vLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKSkKbW9ub190YWJsZXNfc3ZhIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogICAgbW9ub19kZV9zdmEsIGtlZXBlcnMgPSBrZWVwZXJzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9tb25vY3l0ZV9jbGluaWNhbF9hbGxfdGFibGVzX3N2YS12e3Zlcn0ueGxzeCIpKSkKbW9ub19zaWdfc3ZhIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBtb25vX3RhYmxlc19zdmEsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL21vbm9jeXRlX2NsaW5pY2FsX3NpZ190YWJsZXNfc3ZhLXZ7dmVyfS54bHN4IiksCiAgICBhY2NvcmRpbmdfdG8gPSAiZGVzZXEiKSkKYGBgCgojIyMjIE1vbm9jeXRlIERFIHBsb3RzCgpGaXJzdCBwcmludCBvdXQgdGhlIERFIHBsb3RzIHdpdGhvdXQgYW5kIHRoZW4gd2l0aCBzdmEgZXN0aW1hdGVzLgoKYGBge3IgbW9ub19kZV9wbG90c30KIyMgREVTZXEyIE1BIHBsb3Qgb2YgZmFpbHVyZSAvIGN1cmUKbW9ub190YWJsZXNbWyJwbG90cyJdXVtbImZhaWxfdnNfY3VyZSJdXVtbImRlc2VxX21hX3Bsb3RzIl1dJHBsb3QKCiMjIERFU2VxMiBWb2xjYW5vIHBsb3Qgb2YgZmFpbHVyZSAvIGN1cmUKbW9ub190YWJsZXNbWyJwbG90cyJdXVtbImZhaWxfdnNfY3VyZSJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXSRwbG90CgojIyBERVNlcTIgTUEgcGxvdCBvZiBmYWlsdXJlIC8gY3VyZSB3aXRoIHN2YXNlcQptb25vX3RhYmxlc19zdmFbWyJwbG90cyJdXVtbImZhaWxfdnNfY3VyZSJdXVtbImRlc2VxX21hX3Bsb3RzIl1dJHBsb3QKCiMjIERFU2VxMiBWb2xjYW5vIHBsb3Qgb2YgZmFpbHVyZSAvIGN1cmUgd2l0aCBzdmFzZXEKbW9ub190YWJsZXNfc3ZhW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0kcGxvdApgYGAKCiMjIyMgTW9ub2N5dGUgb250b2xvZ3kgc2VhcmNoCgpgYGB7ciBtb25vX2dwcm9maWxlcn0KdXBzIDwtIG1vbm9fc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV0KZG93bnMgPC0gbW9ub19zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siZmFpbF92c19jdXJlIl1dCgptb25vX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2lnX2dlbmVzID0gdXBzKQptb25vX3VwX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQptb25vX3VwX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sibWZwX3Bsb3Rfb3ZlciJdXQptb25vX3VwX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sicmVhY3RvbWVfcGxvdF9vdmVyIl1dCgptb25vX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaWdfZ2VuZXMgPSBkb3ducykKbW9ub19kb3duX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQptb25vX2Rvd25fZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJtZnBfcGxvdF9vdmVyIl1dCm1vbm9fZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpgYGAKCiMjIyMgTW9ub2N5dGUgTVNpZ0RCIHF1ZXJ5CgpgYGB7ciBtc2lnX21vbm9fZ29zZXEsIGZpZy5zaG93ID0gImhpZGUifQpicm9hZF9jNyA8LSBHU0VBQmFzZTo6Z2V0R210KCJyZWZlcmVuY2UvbXNpZ2RiL2M3LmFsbC52Ny4yLmVudHJlei5nbXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxlY3Rpb25UeXBlID0gR1NFQUJhc2U6OkJyb2FkQ29sbGVjdGlvbihjYXRlZ29yeSA9ICJjNyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVJZFR5cGUgPSBHU0VBQmFzZTo6RW50cmV6SWRlbnRpZmllcigpKQoKbW9ub191cF9nb3NlcV9tc2lnIDwtIGdvc2VxX21zaWdkYihzaWdfZ2VuZXMgPSB1cHMsIHNpZ25hdHVyZXMgPSBicm9hZF9jNywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWduYXR1cmVfY2F0ZWdvcnkgPSAiYzciLCBsZW5ndGhfZGIgPSBoc19sZW5ndGgpCgptb25vX2Rvd25fZ29zZXFfbXNpZyA8LSBnb3NlcV9tc2lnZGIoc2lnX2dlbmVzID0gZG93bnMsIHNpZ25hdHVyZXMgPSBicm9hZF9jNywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJjNyIsIGxlbmd0aF9kYiA9IGhzX2xlbmd0aCkKYGBgCgojIyMjIFBsb3Qgb2Ygc2ltaWxhciBleHBlcmltZW50cwoKYGBge3IgbXNpZ19wbG90c30KIyMgTW9ub2N5dGUgZ2VuZXMgd2l0aCBpbmNyZWFzZWQgZXhwcmVzc2lvbiBpbiB0aGUgZmFpbGVkIHNhbXBsZXMKIyMgc2hhcmUgZ2VuZXMgd2l0aCB0aGUgZm9sbG93aW5nIGV4cGVyaW1lbnRzCm1vbm9fdXBfZ29zZXFfbXNpZ1tbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KCiMjIE1vbm9jeXRlIGdlbmVzIHdpdGggaW5jcmVhc2VkIGV4cHJlc3Npb24gaW4gdGhlIGN1cmVkIHNhbXBsZXMKIyMgc2hhcmUgZ2VuZXMgd2l0aCB0aGUgZm9sbG93aW5nIGV4cGVyaW1lbnRzCm1vbm9fZG93bl9nb3NlcV9tc2lnW1sicHZhbHVlX3Bsb3RzIl1dW1sibWZwX3Bsb3Rfb3ZlciJdXQpgYGAKCiMjIyBFdmFsdWF0ZSBOZXV0cm9waGlsIHNhbXBsZXMKCmBgYHtyIG5ldXRyb3BoaWxzfQpuZXV0IDwtIHN1YnNldF9leHB0KGhzX3ZhbGlkLCBzdWJzZXQgPSAidHlwZW9mY2VsbHM9PSdOZXV0cm9waGlscyciKSAlPiUKICBzZXRfZXhwdF9jb25kaXRpb25zKGZhY3QgPSAiY2xpbmljYWxvdXRjb21lIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gImRvbm9yIikgJT4lCiAgc2V0X2V4cHRfY29sb3JzKGNvbG9ycyA9IGNob3Nlbl9jb2xvcnMpCgpzYXZlX3Jlc3VsdCA8LSBzYXZlKG5ldXQsIGZpbGUgPSAicmRhL25ldXRyb3BoaWxfZXhwdC5yZGEiKQpuZXV0X25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQobmV1dCwgY29udmVydCA9ICJjcG0iLCBmaWx0ZXIgPSBUUlVFLCB0cmFuc2Zvcm0gPSAibG9nMiIpKQpwbHQgPC0gcGxvdF9wY2EobmV1dF9ub3JtLCBwbG90X2xhYmVscyA9IEZBTFNFKSRwbG90CnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvbmV1dF9wY2Ffbm9ybWFsaXplZC12e3Zlcn0ucGRmIiksIGltYWdlID0gcGx0KQoKbmV1dF9uYiA8LSBzbShub3JtYWxpemVfZXhwdChuZXV0LCBjb252ZXJ0ID0gImNwbSIsIGZpbHRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCBiYXRjaCA9ICJzdmFzZXEiKSkKcGx0IDwtIHBsb3RfcGNhKG5ldXRfbmIsIHBsb3RfbGFiZWxzID0gRkFMU0UpJHBsb3QKcHAoZmlsZSA9IGdsdWUoImltYWdlcy9uZXV0X3BjYV9ub3JtYWxpemVkX3N2YXNlcS12e3Zlcn0ucGRmIiksIGltYWdlID0gcGx0KQpgYGAKCiMjIyBERSBvZiBOZXRyb3BoaWwgc2FtcGxlcwoKIyMjIyBXaXRob3V0IHN2YQoKYGBge3IgbmV1dHJvcGhpbF9kZSwgZmlnLnNob3cgPSAiaGlkZSJ9Cm5ldXRfZGUgPC0gc20oYWxsX3BhaXJ3aXNlKG5ldXQsIG1vZGVsX2JhdGNoID0gRkFMU0UsIGZpbHRlciA9IFRSVUUpKQpuZXV0X3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICAgIG5ldXRfZGUsIGtlZXBlcnMgPSBrZWVwZXJzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9uZXV0cm9waGlsX2NsaW5pY2FsX2FsbF90YWJsZXMtdnt2ZXJ9Lnhsc3giKSkpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gbmV1dF90YWJsZXNbWyJkYXRhIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL25ldXRyb3BoaWxfY2xpbmljYWxfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKbmV1dF9zaWcgPC0gc20oZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyhuZXV0X3RhYmxlcywgYWNjb3JkaW5nX3RvID0gImRlc2VxIikpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gbmV1dF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbMV1dLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9uZXV0cm9waGlsX2NsaW5pY2FsX3NpZ3VwLXZ7dmVyfS54bHN4IikpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gbmV1dF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL25ldXRyb3BoaWxfY2xpbmljYWxfc2lnZG93bi12e3Zlcn0ueGxzeCIpKQoKbmV1dF9wY3Rfc2lnIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMobmV1dF90YWJsZXMsIG4gPSAyMDAsIGxmYyA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAgPSBOVUxMLCBhY2NvcmRpbmdfdG8gPSAiZGVzZXEiKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBuZXV0X3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL25ldXRyb3BoaWxfY2xpbmljYWxfc2lndXBfcGN0LXZ7dmVyfS54bHN4IikpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gbmV1dF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL25ldXRyb3BoaWxfY2xpbmljYWxfc2lnZG93bl9wY3Qtdnt2ZXJ9Lnhsc3giKSkKbmV1dF9jcG0gPC0gc20obm9ybWFsaXplX2V4cHQobmV1dCwgY29udmVydCA9ICJjcG0iKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBleHBycyhuZXV0X2NwbSksCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL25ldXRyb3BoaWxfY3BtX2JlZm9yZV9iYXRjaC12e3Zlcn0ueGxzeCIpKQpuZXV0X2JjcG0gPC0gc20obm9ybWFsaXplX2V4cHQobmV1dCwgZmlsdGVyID0gVFJVRSwgYmF0Y2ggPSAic3Zhc2VxIiwgY29udmVydCA9ICJjcG0iKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBleHBycyhuZXV0X2JjcG0pLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9uZXV0cm9waGlsX2NwbV9hZnRlcl9iYXRjaC12e3Zlcn0ueGxzeCIpKQpgYGAKCiMjIyMgV2l0aCBzdmEKCmBgYHtyIGRlX25ldXRfc3ZhLCBmaWcuc2hvdyA9ICJoaWRlIn0KbmV1dF9kZV9zdmEgPC0gc20oYWxsX3BhaXJ3aXNlKG5ldXQsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpKQpuZXV0X3RhYmxlc19zdmEgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgICBuZXV0X2RlX3N2YSwga2VlcGVycyA9IGtlZXBlcnMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL25ldXRyb3BoaWxfY2xpbmljYWxfYWxsX3RhYmxlc19zdmEtdnt2ZXJ9Lnhsc3giKSkpCm5ldXRfc2lnX3N2YSA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgbmV1dF90YWJsZXNfc3ZhLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9uZXV0cm9waGlsX2NsaW5pY2FsX3NpZ190YWJsZXNfc3ZhLXZ7dmVyfS54bHN4IiksCiAgICBhY2NvcmRpbmdfdG8gPSAiZGVzZXEiKSkKYGBgCgojIyMjIE5ldXRyb3BoaWwgREUgcGxvdHMKCmBgYHtyIG5ldXRfZGVfcGxvdHN9CiMjIERFU2VxMiBNQSBwbG90IG9mIGZhaWx1cmUgLyBjdXJlCm5ldXRfdGFibGVzW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXSRwbG90CgojIyBERVNlcTIgVm9sY2FubyBwbG90IG9mIGZhaWx1cmUgLyBjdXJlCm5ldXRfdGFibGVzW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0kcGxvdAoKIyMgREVTZXEyIE1BIHBsb3Qgb2YgZmFpbHVyZSAvIGN1cmUgd2l0aCBzdmEKbmV1dF90YWJsZXNfc3ZhW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXSRwbG90CgojIyBERVNlcTIgVm9sY2FubyBwbG90IG9mIGZhaWx1cmUgLyBjdXJlIHdpdGggc3ZhCm5ldXRfdGFibGVzX3N2YVtbInBsb3RzIl1dW1siZmFpbF92c19jdXJlIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dJHBsb3QKYGBgCgojIyMjIE5ldXRyb3BoaWwgb250b2xvZ3kgc2VhcmNoCgpgYGB7ciBuZXV0X2dwfQp1cHMgPC0gbmV1dF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbImZhaWxfdnNfY3VyZSJdXQpkb3ducyA8LSBuZXV0X3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJmYWlsX3ZzX2N1cmUiXV0KCm5ldXRfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaWdfZ2VuZXMgPSB1cHMpCm5ldXRfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCm5ldXRfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJtZnBfcGxvdF9vdmVyIl1dCm5ldXRfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJyZWFjdG9tZV9wbG90X292ZXIiXV0KCm5ldXRfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGRvd25zKQpuZXV0X2Rvd25fZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCm5ldXRfZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KbmV1dF9kb3duX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sicmVhY3RvbWVfcGxvdF9vdmVyIl1dCmBgYAoKIyMjIyBOZXV0cm9waGlsIEdTVkEgcXVlcnkKCmBgYHtyIG1zaWdfbmV1dF9nb3NlcSwgZmlnLnNob3cgPSAiaGlkZSJ9Cm5ldXRfdXBfZ29zZXFfbXNpZyA8LSBnb3NlcV9tc2lnZGIoc2lnX2dlbmVzID0gdXBzLCBzaWduYXR1cmVzID0gYnJvYWRfYzcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lnbmF0dXJlX2NhdGVnb3J5ID0gImM3IiwgbGVuZ3RoX2RiID0gaHNfbGVuZ3RoKQoKbmV1dF9kb3duX2dvc2VxX21zaWcgPC0gZ29zZXFfbXNpZ2RiKHNpZ19nZW5lcyA9IGRvd25zLCBzaWduYXR1cmVzID0gYnJvYWRfYzcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWduYXR1cmVfY2F0ZWdvcnkgPSAiYzciLCBsZW5ndGhfZGIgPSBoc19sZW5ndGgpCmBgYAoKIyMjIyBQbG90IG9mIHNpbWlsYXIgZXhwZXJpbWVudHMKCmBgYHtyIG1zaWdfcGxvdHNfbmV1dH0KIyMgTmV1dHJvcGhpbCBnZW5lcyB3aXRoIGluY3JlYXNlZCBleHByZXNzaW9uIGluIHRoZSBmYWlsZWQgc2FtcGxlcwojIyBzaGFyZSBnZW5lcyB3aXRoIHRoZSBmb2xsb3dpbmcgZXhwZXJpbWVudHMKbmV1dF91cF9nb3NlcV9tc2lnW1sicHZhbHVlX3Bsb3RzIl1dW1sibWZwX3Bsb3Rfb3ZlciJdXQoKIyMgTmV1dHJvcGhpbCBnZW5lcyB3aXRoIGluY3JlYXNlZCBleHByZXNzaW9uIGluIHRoZSBjdXJlZCBzYW1wbGVzCiMjIHNoYXJlIGdlbmVzIHdpdGggdGhlIGZvbGxvd2luZyBleHBlcmltZW50cwpuZXV0X2Rvd25fZ29zZXFfbXNpZ1tbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KYGBgCgojIyBFb3Npbm9waGlscwoKIyMjIEV2YWx1YXRlIEVvc2lub3BoaWwgc2FtcGxlcwoKYGBge3IgZW9zaW5vcGhpbHN9CmVvIDwtIHN1YnNldF9leHB0KGhzX3ZhbGlkLCBzdWJzZXQgPSAidHlwZW9mY2VsbHM9PSdFb3Npbm9waGlscyciKSAlPiUKICBzZXRfZXhwdF9jb25kaXRpb25zKGZhY3QgPSAiY2xpbmljYWxvdXRjb21lIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gImRvbm9yIikgJT4lCiAgc2V0X2V4cHRfY29sb3JzKGNvbG9ycyA9IGNob3Nlbl9jb2xvcnMpCgpzYXZlX3Jlc3VsdCA8LSBzYXZlKGVvLCBmaWxlID0gInJkYS9lb3Npbm9waGlsX2V4cHQucmRhIikKZW9fbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdChlbywgY29udmVydCA9ICJjcG0iLCB0cmFuc2Zvcm0gPSAibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybSA9ICJxdWFudCIsIGZpbHRlciA9IFRSVUUpKQpwbHQgPC0gcGxvdF9wY2EoZW9fbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkkcGxvdApwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL2VvX3BjYV9ub3JtYWxpemVkLXZ7dmVyfS5wZGYiKSwgaW1hZ2UgPSBwbHQpCgplb19uYiA8LSBzbShub3JtYWxpemVfZXhwdChlbywgY29udmVydCA9ICJjcG0iLCB0cmFuc2Zvcm0gPSAibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpKQpwbG90X3BjYShlb19uYikkcGxvdApgYGAKCiMjIyBERSBvZiBFb3Npbm9waGlsIHNhbXBsZXMKCiMjIyMgV2l0aG91dGggc3ZhCgpgYGB7ciBlb3Npbm9waGlsX2RlLCBmaWcuc2hvdyA9ICJoaWRlIn0KZW9fZGUgPC0gc20oYWxsX3BhaXJ3aXNlKGVvLCBtb2RlbF9iYXRjaCA9IEZBTFNFLCBmaWx0ZXIgPSBUUlVFKSkKZW9fdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogICAgZW9fZGUsIGtlZXBlcnMgPSBrZWVwZXJzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9lb3Npbm9waGlsX2NsaW5pY2FsX2FsbF90YWJsZXMtdnt2ZXJ9Lnhsc3giKSkpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gZW9fdGFibGVzW1siZGF0YSJdXVtbMV1dLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9lb3Npbm9waGlsX2NsaW5pY2FsX3RhYmxlLXZ7dmVyfS54bHN4IikpCmVvX3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKGVvX3RhYmxlcywgYWNjb3JkaW5nX3RvID0gImRlc2VxIikpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gZW9fc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWzFdXSwKICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvZW9zaW5vcGhpbF9jbGluaWNhbF9zaWd1cC12e3Zlcn0ueGxzeCIpKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGVvX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWzFdXSwKICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvZW9zaW5vcGhpbF9jbGluaWNhbF9zaWdkb3duLXZ7dmVyfS54bHN4IikpCgplb19wY3Rfc2lnIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoZW9fdGFibGVzLCBuID0gMjAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGZjID0gTlVMTCwgcCA9IE5VTEwsIGFjY29yZGluZ190byA9ICJkZXNlcSIpKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGVvX3BjdF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbMV1dLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9lb3Npbm9waGlsX2NsaW5pY2FsX3NpZ3VwX3BjdC12e3Zlcn0ueGxzeCIpKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGVvX3BjdF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Vvc2lub3BoaWxfY2xpbmljYWxfc2lnZG93bl9wY3Qtdnt2ZXJ9Lnhsc3giKSkKCmVvX2NwbSA8LSBzbShub3JtYWxpemVfZXhwdChlbywgY29udmVydCA9ICJjcG0iKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBleHBycyhlb19jcG0pLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9lb3Npbm9waGlsX2NwbV9iZWZvcmVfYmF0Y2gtdnt2ZXJ9Lnhsc3giKSkKZW9fYmNwbSA8LSBzbShub3JtYWxpemVfZXhwdChlbywgZmlsdGVyID0gVFJVRSwgYmF0Y2ggPSAic3Zhc2VxIiwgY29udmVydCA9ICJjcG0iKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBleHBycyhlb19iY3BtKSwKICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvZW9zaW5vcGhpbF9jcG1fYWZ0ZXJfYmF0Y2gtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMjIFdpdGggc3ZhCgpgYGB7ciBkZV9lb19zdmEsIGZpZy5zaG93ID0gImhpZGUifQplb19kZV9zdmEgPC0gc20oYWxsX3BhaXJ3aXNlKGVvLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKSkKZW9fdGFibGVzX3N2YSA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICAgIGVvX2RlX3N2YSwga2VlcGVycyA9IGtlZXBlcnMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Vvc2lub3BoaWxfY2xpbmljYWxfYWxsX3RhYmxlc19zdmEtdnt2ZXJ9Lnhsc3giKSkpCmVvX3NpZ19zdmEgPC0gc20oZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGVvX3RhYmxlc19zdmEsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Vvc2lub3BoaWxfY2xpbmljYWxfc2lnX3RhYmxlc19zdmEtdnt2ZXJ9Lnhsc3giKSwKICAgIGFjY29yZGluZ190byA9ICJkZXNlcSIpKQpgYGAKCiMjIyMgRW9zaW5vcGhpbCBERSBwbG90cwoKYGBge3IgZW9fZGVfcGxvdHN9CiMjIERFU2VxMiBNQSBwbG90IG9mIGZhaWx1cmUgLyBjdXJlCmVvX3RhYmxlc1tbInBsb3RzIl1dW1siZmFpbF92c19jdXJlIl1dW1siZGVzZXFfbWFfcGxvdHMiXV0kcGxvdAoKIyMgREVTZXEyIFZvbGNhbm8gcGxvdCBvZiBmYWlsdXJlIC8gY3VyZQplb190YWJsZXNbWyJwbG90cyJdXVtbImZhaWxfdnNfY3VyZSJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXSRwbG90CgojIyBERVNlcTIgTUEgcGxvdCBvZiBmYWlsdXJlIC8gY3VyZSB3aXRoIHN2YQplb190YWJsZXNfc3ZhW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXSRwbG90CgojIyBERVNlcTIgVm9sY2FubyBwbG90IG9mIGZhaWx1cmUgLyBjdXJlIHdpdGggc3ZhCmVvX3RhYmxlc19zdmFbWyJwbG90cyJdXVtbImZhaWxfdnNfY3VyZSJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXSRwbG90CmBgYAoKIyMjIyBFb3Npbm9waGlsIG9udG9sb2d5IHNlYXJjaAoKYGBge3IgZW9fZ3Byb2ZpbGVyfQp1cHMgPC0gZW9fc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV0KZG93bnMgPC0gZW9fc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbImZhaWxfdnNfY3VyZSJdXQoKZW9fdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaWdfZ2VuZXMgPSB1cHMpCmVvX3VwX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQplb191cF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KZW9fdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJyZWFjdG9tZV9wbG90X292ZXIiXV0KCmVvX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihkb3ducykKZW9fZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KZW9fZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KZW9fZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpgYGAKCiMjIyMgRW9zaW5vcGhpbCBNU2lnREIgcXVlcnkKCmBgYHtyIG1zaWdfZW9fZ29zZXEsIGZpZy5zaG93ID0gImhpZGUifQplb191cF9nb3NlcV9tc2lnIDwtIGdvc2VxX21zaWdkYihzaWdfZ2VuZXMgPSB1cHMsIHNpZ25hdHVyZXMgPSBicm9hZF9jNywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lnbmF0dXJlX2NhdGVnb3J5ID0gImM3IiwgbGVuZ3RoX2RiID0gaHNfbGVuZ3RoKQoKZW9fZG93bl9nb3NlcV9tc2lnIDwtIGdvc2VxX21zaWdkYihzaWdfZ2VuZXMgPSBkb3ducywgc2lnbmF0dXJlcyA9IGJyb2FkX2M3LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJjNyIsIGxlbmd0aF9kYiA9IGhzX2xlbmd0aCkKYGBgCgojIyMjIFBsb3Qgb2Ygc2ltaWxhciBleHBlcmltZW50cwoKYGBge3IgbXNpZ19wbG90c19lb30KIyMgRW9zaW5vcGhpbCBnZW5lcyB3aXRoIGluY3JlYXNlZCBleHByZXNzaW9uIGluIHRoZSBmYWlsZWQgc2FtcGxlcwojIyBzaGFyZSBnZW5lcyB3aXRoIHRoZSBmb2xsb3dpbmcgZXhwZXJpbWVudHMKZW9fdXBfZ29zZXFfbXNpZ1tbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KCiMjIEVvc2lub3BoaWwgZ2VuZXMgd2l0aCBpbmNyZWFzZWQgZXhwcmVzc2lvbiBpbiB0aGUgY3VyZWQgc2FtcGxlcwojIyBzaGFyZSBnZW5lcyB3aXRoIHRoZSBmb2xsb3dpbmcgZXhwZXJpbWVudHMKZW9fZG93bl9nb3NlcV9tc2lnW1sicHZhbHVlX3Bsb3RzIl1dW1sibWZwX3Bsb3Rfb3ZlciJdXQpgYGAKCiMjIEJpb3BzaWVzCgojIyMgRXZhbHVhdGUgQmlvcHN5IHNhbXBsZXMKCmBgYHtyIGJpb3BzaWVzfQpiaW9wIDwtIHN1YnNldF9leHB0KGhzX3ZhbGlkLCBzdWJzZXQgPSAidHlwZW9mY2VsbHM9PSdCaW9wc3knIikgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0ID0gImNsaW5pY2Fsb3V0Y29tZSIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdCA9ICJkb25vciIpICU+JQogIHNldF9leHB0X2NvbG9ycyhjb2xvcnMgPSBjaG9zZW5fY29sb3JzKQoKc2F2ZV9yZXN1bHQgPC0gc2F2ZShiaW9wLCBmaWxlID0gInJkYS9iaW9wc3lfZXhwdC5yZGEiKQpiaW9wX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoYmlvcCwgZmlsdGVyID0gVFJVRSwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCBub3JtID0gInF1YW50IikKcGx0IDwtIHBsb3RfcGNhKGJpb3Bfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkkcGxvdApwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL2Jpb3BfcGNhX25vcm1hbGl6ZWQtdnt2ZXJ9LnBkZiIpLCBpbWFnZSA9IHBsdCkKCmJpb3BfbmIgPC0gc20obm9ybWFsaXplX2V4cHQoYmlvcCwgY29udmVydCA9ICJjcG0iLCBmaWx0ZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgYmF0Y2ggPSAic3Zhc2VxIikpCnBsdCA8LSBwbG90X3BjYShiaW9wX25iLCBwbG90X2xhYmVscyA9IEZBTFNFKSRwbG90CnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvYmlvcF9wY2Ffbm9ybWFsaXplZF9zdmFzZXEtdnt2ZXJ9LnBkZiIpLCBpbWFnZSA9IHBsdCkKYGBgCgojIyMgREUgb2YgQmlvcHN5IHNhbXBsZXMKCiMjIyMgV2l0aG91dCBzdmEKCmBgYHtyIGRlX2Jpb3BzeSwgZmlnLnNob3cgPSAiaGlkZSJ9CmJpb3BfZGUgPC0gc20oYWxsX3BhaXJ3aXNlKGJpb3AsIG1vZGVsX2JhdGNoID0gRkFMU0UsIGZpbHRlciA9IFRSVUUpKQpiaW9wX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcyhiaW9wX2RlLCBrZWVwZXJzID0ga2VlcGVycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9iaW9wc3lfY2xpbmljYWxfYWxsX3RhYmxlcy12e3Zlcn0ueGxzeCIpKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGJpb3BfdGFibGVzW1siZGF0YSJdXVtbMV1dLAogICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9iaW9wc3lfY2xpbmljYWxfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKYmlvcF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyhiaW9wX3RhYmxlcywgYWNjb3JkaW5nX3RvID0gImRlc2VxIikKIyN3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGJpb3Bfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWzFdXSwKIyMgICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9iaW9wc3lfY2xpbmljYWxfc2lndXAtdnt2ZXJ9Lnhsc3giKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBiaW9wX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWzFdXSwKICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvYmlvcHN5X2NsaW5pY2FsX3NpZ2Rvd24tdnt2ZXJ9Lnhsc3giKSkKYmlvcF9wY3Rfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoYmlvcF90YWJsZXMsIG4gPSAyMDAsIGxmYyA9IE5VTEwsIHAgPSBOVUxMLCBhY2NvcmRpbmdfdG8gPSAiZGVzZXEiKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGJpb3BfcGN0X3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Jpb3BzeV9jbGluaWNhbF9zaWd1cF9wY3Qtdnt2ZXJ9Lnhsc3giKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBiaW9wX3BjdF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Jpb3BzeV9jbGluaWNhbF9zaWdkb3duX3BjdC12e3Zlcn0ueGxzeCIpKQoKYmlvcF9jcG0gPC0gc20obm9ybWFsaXplX2V4cHQoYmlvcCwgY29udmVydCA9ICJjcG0iKSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBleHBycyhiaW9wX2NwbSksCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Jpb3BzeV9jcG1fYmVmb3JlX2JhdGNoLXZ7dmVyfS54bHN4IikpCmJpb3BfYmNwbSA8LSBzbShub3JtYWxpemVfZXhwdChiaW9wLCBmaWx0ZXIgPSBUUlVFLCBiYXRjaCA9ICJzdmFzZXEiLCBjb252ZXJ0ID0gImNwbSIpKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGV4cHJzKGJpb3BfYmNwbSksCiAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Jpb3BzeV9jcG1fYWZ0ZXJfYmF0Y2gtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMjIHdpdGggc3ZhCgpgYGB7ciBkZV9iaW9wc3lfc3ZhLCBmaWcuc2hvdyA9ICJoaWRlIn0KYmlvcF9kZV9zdmEgPC0gc20oYWxsX3BhaXJ3aXNlKGJpb3AsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpKQpiaW9wX3RhYmxlc19zdmEgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgICBiaW9wX2RlX3N2YSwga2VlcGVycyA9IGtlZXBlcnMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Jpb3BzeV9jbGluaWNhbF9hbGxfdGFibGVzX3N2YS12e3Zlcn0ueGxzeCIpKSkKYmlvcF9zaWdfc3ZhIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBiaW9wX3RhYmxlc19zdmEsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2Jpb3BzeV9jbGluaWNhbF9zaWdfdGFibGVzX3N2YS12e3Zlcn0ueGxzeCIpLAogICAgYWNjb3JkaW5nX3RvID0gImRlc2VxIikpCmBgYAoKIyMjIyBCaW9wc3kgREUgcGxvdHMKCmBgYHtyIGJpb3BfZGVfcGxvdHN9CiMjIERFU2VxMiBNQSBwbG90IG9mIGZhaWx1cmUgLyBjdXJlCmJpb3BfdGFibGVzW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXSRwbG90CgojIyBERVNlcTIgVm9sY2FubyBwbG90IG9mIGZhaWx1cmUgLyBjdXJlCmJpb3BfdGFibGVzW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0kcGxvdAoKIyMgREVTZXEyIE1BIHBsb3Qgb2YgZmFpbHVyZSAvIGN1cmUKYmlvcF90YWJsZXNfc3ZhW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXSRwbG90CgojIyBERVNlcTIgVm9sY2FubyBwbG90IG9mIGZhaWx1cmUgLyBjdXJlCmJpb3BfdGFibGVzX3N2YVtbInBsb3RzIl1dW1siZmFpbF92c19jdXJlIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dJHBsb3QKYGBgCgpgYGB7ciBzYXZlbWV9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIHBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCiAgbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCiAgbWVzc2FnZShwYXN0ZTAoIlNhdmluZyB0byAiLCBzYXZlZmlsZSkpCiAgdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZSA9IHNhdmVmaWxlKSkKfQpgYGAKCmBgYHtyIGxvYWRtZV9hZnRlciwgZXZhbCA9IEZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYAo=