1 Main libraries and configuration

library(dplyr)
library(ExperimentHub)
library(GenomicRanges)
library(coMethDMR)
library(ggplot2)
library(LOLA)
library(qvalue)
dir.data <- "./DATASETS/"
dir.result <- "../meta_analysis_region_results/"
dir.result.meta.analysis <- file.path(dir.result, "step1_meta_analysis/")
dir.result.comp <- file.path(dir.result, "step3_comp/")
dir.result.lola <- file.path("bacon/lola/")
dir.result.pathway <- file.path("bacon/results_pathway/")
for(p in grep("dir",ls(),value = T)) dir.create(get(p),recursive = TRUE,showWarnings = FALSE)

2 Enrichment analysis of FDR significant CpGs, after inflation correction by bacon method

2.1 For single cpgs

2.1.1 Get results

### Foreground
single.cpg.results <- readr::read_csv(
  paste0(dir.data,"meta_analysis_single_cpg_bacon_df.csv"),
  col_types = readr::cols()
)
single.cpg.sig.results <- readr::read_csv(                                                        
  paste0(dir.data,"meta_analysis_single_cpg_sig_no_crossHyb_smoking_df_bacon.csv"),
  col_types = readr::cols()
)                                                                                                 

foreground.probes <- single.cpg.sig.results %>% pull(cpg) %>% as.character
foreground.probes.neg.est <- single.cpg.sig.results %>% 
  filter(estimate.bacon < 0) %>% 
  pull(cpg) %>% 
  as.character
foreground.probes.pos.est <- single.cpg.sig.results  %>% 
  filter(estimate.bacon > 0) %>% 
  pull(cpg) %>% 
  as.character
length(foreground.probes)
## [1] 2767
### Background
background.probes <- single.cpg.results  %>% pull(cpg) %>% as.character 
length(background.probes)
## [1] 450793

2.1.2 Annotation

l.probes <- list(
    background.probes,
    foreground.probes.neg.est,
    foreground.probes.pos.est
)

names(l.probes) <- c(
    paste0("Evaluated probes (n = ",length(background.probes),")"),
    paste0("Significant w/ Negative estimate (n = ",length(foreground.probes.neg.est),")"),
    paste0("Significant w/ Positive estimate (n = ",length(foreground.probes.pos.est),")")
)

all.plot <- cpGsGenomicFeatures(l.probes)
plot.single.cpg <- all.plot$plot + ggtitle("Single cpg meta-analysis probes") 
plot.single.cpg

ggsave(
  plot = plot.single.cpg,
  width = 9,
  filename = "bacon/plots_enrichment_analysis//meta_analysis_single_cpg_enrichment.pdf"
)
## Saving 9 x 10 in image

2.1.3 ChroMHMM

file <- paste0("https://egg2.wustl.edu/roadmap/data/byFileType/chromhmmSegmentations",
               "/ChmmModels/coreMarks/jointModel/final/E073_15_coreMarks_segments.bed")
if(!file.exists( basename(file))) downloader::download(file, destfile = basename(file))


ChmmModels <- readr::read_tsv(
  basename(file),
  col_names = FALSE,
  col_types = readr::cols()
)
colnames(ChmmModels) <- c("chr","start","end","state")
states <- readr::read_csv(
  "../../../DNAm_RNA/data/chromHMM_labels.csv",
  col_names = FALSE,
  col_types = readr::cols()
)
states$X1 <- paste0("E",states$X1)
ChmmModels$state <- states$X3[match(ChmmModels$state,states$X1)]
ChmmModels.gr <- makeGRangesFromDataFrame(ChmmModels,keep.extra.columns = TRUE)
l.probes <- list(
    background.probes,
    foreground.probes.neg.est,
    foreground.probes.pos.est
)

names(l.probes) <- c(
    paste0("Evaluated probes (n = ",length(background.probes),")"),
    paste0("Significant w/ Negative estimate (n = ",length(foreground.probes.neg.est),")"),
    paste0("Significant w/ Positive estimate (n = ",length(foreground.probes.pos.est),")")
)

single.cpg.plot <- cpGsGenomicFeatures(
  l.probes,
  annotation.gr = ChmmModels.gr,
  plot.width = 12,
  plot.title = "Single cpg meta-analysis probes\nChroMHMM: E073 - 15 coreMarks segments",
  enrichment.type = "customized",
  plot.filename = "bacon/plots_enrichment_analysis//meta_analysis_single_cpg_chromHMM_states.pdf",
)
single.cpg.plot$plot

tab.chrm <- cbind(
  data.frame(
    "Meta-Analysis" = c(
      rep("Single CpG",nrow(plot.chrm.hyper$table) + nrow(plot.chrm.hypo$table))
    ),
    "Foreground probes" = c(
      rep("Significant probes w/ Positive estimate",nrow(plot.chrm.hyper$table)),
      rep("Significant probes w/ Negative estimate",nrow(plot.chrm.hypo$table))
    ),
    "Enrichment analysis" = c(
      rep("ChroMHMM: E073",nrow(plot.chrm.hyper$table) + nrow(plot.chrm.hypo$table))
    )
  ),
  rbind(plot.chrm.hyper$table[,c(1,6,7)],
        plot.chrm.hypo$table[,c(1,6,7)])
)
tab.chrm  %>% 
  DT::datatable(
    filter = 'top',
    style = "bootstrap",
    extensions = 'Buttons',
    options = list(scrollX = TRUE, 
                   dom = 'Bfrtip',
                   buttons = I('colvis'),
                   keys = TRUE, 
                   pageLength = 10)
  )

3 Pathway analysis of FDR significant CpGs after inflation correction

3.1 For regions + single cpgs

3.1.1 Get probes

3.1.2 Get probes from regions

### Call in datasets
meta_sig <- read.csv(dir(dir.result.comp,pattern = "no.*csv",full.names = TRUE))

meta_all <- read.csv(
  paste0(dir.result.meta.analysis, "meta_analysis_ALL_df.csv")
) #dim: 40010 41
probes.cluster.all <- coMethDMR::getPredefinedCluster(
  arrayType = "450k",
  clusterType = "regions"
)

### get all cps in meta_sig input regions
idx <- gsub(
  "450k_Gene_3_200.|450k_InterGene_3_200.","",names(probes.cluster.all)
) %in% meta_sig$inputRegion

meta_sig_probes <- probes.cluster.all[idx] %>%
  unlist %>%
  as.character() %>%
  unique
length(meta_sig_probes)
## [1] 742
### get all cps in meta_all input regions
idx <- gsub(
  "450k_Gene_3_200.|450k_InterGene_3_200.","",names(probes.cluster.all)
) %in% meta_all$inputRegion

meta_all_probes <- probes.cluster.all[idx] %>%
  unlist %>%
  as.character() %>%
  unique

length(meta_all_probes)
## [1] 203198
all.foreground.probes <- c(meta_sig_probes, foreground.probes) %>% unique  
all.background.probes <- c(meta_all_probes, background.probes) %>% unique

3.1.3 Pathway analysis (gene ontology analysis)

library(missMethyl)
library(IlluminaHumanMethylation450kanno.ilmn12.hg19)
### collection = "GO"
all_go <- gometh(
  sig.cpg = all.foreground.probes,
  all.cpg = all.background.probes,
  collection = "GO",
  fract.counts = TRUE
)
# topGSA(all_go)

go <- missMethyl:::.getGO()
out <- getMappedEntrezIDs(
  sig.cpg = foreground.probes,
  all.cpg = background.probes,
  array.type = "450K"
)
sorted.eg.sig <-  out$sig.eg
gene.info <- TCGAbiolinks::get.GRCh.bioMart(genome = "hg19")
all_go$de_genes <- plyr::aaply(rownames(all_go),1,.fun = function(idx){
  gene.info$external_gene_name[gene.info$entrezgene_id %in% intersect(go$idList[[idx]],sorted.eg.sig)] %>%
    sort %>% unique %>% paste(collapse = ",")
})

all_go_ordered <- all_go[
  order(all_go$P.DE),
  ]
write.csv(
  all_go_ordered,
  paste0(dir.result.pathway, "pathway_regions_and_cpgs_GO_results_all.csv"),
  row.names = TRUE
)
all_go_ordered.bp <- all_go_ordered %>%
  tibble::rownames_to_column("GO") %>%  # keep row names
  dplyr::filter(ONTOLOGY == "BP") %>%
  tibble::column_to_rownames("GO")   # keep row names
all_go_ordered.bp$FDR <- p.adjust(all_go_ordered.bp$P.DE,"fdr")
write.csv(
  all_go_ordered.bp,
  paste0(dir.result.pathway, "pathway_regions_and_cpgs_GO_results_BP_N_range_5_200_fdr_recalc.csv"),
  row.names = TRUE
)
all_go_ordered.bp  %>% 
  dplyr::filter(FDR < 0.05) %>%
  DT::datatable(filter = 'top',
                style = "bootstrap",
                extensions = 'Buttons',
                options = list(scrollX = TRUE, 
                               dom = 'Bfrtip',
                               buttons = I('colvis'),
                               keys = TRUE, 
                               pageLength = 10), 
                rownames = FALSE,
                caption = "GO results BP (FDR < 0.05)")
### collection = "KEGG"
all_kegg <- gometh(
  sig.cpg = all.foreground.probes,
  all.cpg = all.background.probes,
  collection = "KEGG",
  fract.counts = TRUE
)
# topGSA(all_kegg)

kegg <- missMethyl:::.getKEGG()
out <- getMappedEntrezIDs(
  sig.cpg = foreground.probes,
  all.cpg = background.probes,
  array.type = "450K"
)
sorted.eg.sig <- out$sig.eg
gene.info <- TCGAbiolinks::get.GRCh.bioMart(genome = "hg19")
all_kegg$de_genes <- plyr::aaply(rownames(all_kegg),1,.fun = function(idx){
  gene.info$external_gene_name[gene.info$entrezgene_id %in% intersect(kegg$idList[[idx]],sorted.eg.sig)] %>%
    sort %>% unique %>% paste(collapse = ",")
})

all_kegg_ordered <- all_kegg[
  order(all_kegg$P.DE),
  ]
write.csv(
  all_kegg_ordered,
  paste0(dir.result.pathway, "pathway_regions_and_cpgs_KEGG_results_all.csv"),
  row.names = TRUE
)
all_kegg_ordered <- all_kegg_ordered %>%
  tibble::rownames_to_column("KEGG") %>%  # keep row names
  tibble::column_to_rownames("KEGG")      # keep row names
all_kegg_ordered$FDR <- p.adjust(all_kegg_ordered$P.DE,"fdr")
write.csv(
  all_kegg_ordered,
  paste0(dir.result.pathway, "pathway_regions_and_cpgs_KEGG_results_N_range_5_200_fdr_recalc.csv"),
  row.names = TRUE
)
all_kegg_ordered  %>% 
  dplyr::filter(P.DE < 0.05) %>%
  DT::datatable(filter = 'top',
                style = "bootstrap",
                extensions = 'Buttons',
                options = list(scrollX = TRUE, 
                               dom = 'Bfrtip',
                               buttons = I('colvis'),
                               keys = TRUE, 
                               pageLength = 10), 
                rownames = FALSE,
                caption = "kegg results (P.DE < 0.05)")                                   

4 Locus overlap analysis (LOLA) of FDR significant CpGs after inflation correction by bacon method

4.1 For single cpg

### Call in datasets
cpg_sig_noCrossHyb_noSmoke <- read.csv(
  paste0(dir.data,"/meta_analysis_single_cpg_sig_no_crossHyb_smoking_df_bacon.csv")
) #dim: 3751 24

cpg_all <- read.csv(
  paste0(dir.data,"/meta_analysis_single_cpg_bacon_df.csv")
) #dim: 450793 24

cpg_sig_hyper_noCrossHyb_noSmoke <- cpg_sig_noCrossHyb_noSmoke %>%
  filter(estimate.bacon > 0)
cpg_sig_hypo_noCrossHyb_noSmoke <- cpg_sig_noCrossHyb_noSmoke %>%
  filter(estimate.bacon < 0)

### Turn input regions into GRanges
library(GenomicRanges)
cpg_sig_noCrossHyb_noSmoke_gr <- makeGRangesFromDataFrame(
  cpg_sig_noCrossHyb_noSmoke
)
cpg_sig_hyper_noCrossHyb_noSmoke_gr <- makeGRangesFromDataFrame(
  cpg_sig_hyper_noCrossHyb_noSmoke
)
cpg_sig_hypo_noCrossHyb_noSmoke_gr <- makeGRangesFromDataFrame(
  cpg_sig_hypo_noCrossHyb_noSmoke
)
cpg_all_gr <- makeGRangesFromDataFrame(cpg_all)
regionDB_hg19 <- loadRegionDB("../LOLACore/hg19")

### All sig. cpgs
locResults <- runLOLA(
  userSets = cpg_sig_noCrossHyb_noSmoke_gr,
  userUniverse = cpg_all_gr,
  regionDB = regionDB_hg19,
  cores = 1
)

locResults$pValue <- 10^(-locResults$pValueLog)
locResults_ordered <- locResults[,c(1:3, 24, 4:23)]
write.csv(
  locResults_ordered,
  paste0(dir.result.lola, "cpgs_all_LOLA_results.csv"),
  row.names = FALSE
)
locResults   %>%
  dplyr::filter(qValue < 0.05 & collection == "encode_tfbs") %>%
  DT::datatable(filter = 'top',
                style = "bootstrap",
                extensions = 'Buttons',
                options = list(scrollX = TRUE,
                               dom = 'Bfrtip',
                               buttons = I('colvis'),
                               keys = TRUE,
                               pageLength = 10),
                rownames = FALSE,
                caption = "single cpg all LOLA results")
locResults_ordered <- locResults[,c(1:3, 24, 4:23)]

write.csv(
  locResults_ordered,
  paste0(dir.result.lola, "cpgs_hyper_LOLA_results.csv"),
  row.names = FALSE
)
locResults_ordered <- locResults[,c(1:3, 24, 4:23)]

write.csv(
  locResults_ordered,
  paste0(dir.result.lola, "cpgs_hypo_LOLA_results.csv"),
  row.names = FALSE
)

5 Enrichment analysis of genome-wide significant CpGs (p < 2.4E-7) after inflation correction by Bacon method

dir.result.lola <- file.path("bacon_2_4_minus_7/lola/")
dir.result.pathway <- file.path("bacon_2_4_minus_7/results_pathway/")

5.1 For single cpgs

5.1.1 Get results

### Foreground
single.cpg.results <- readr::read_csv(
  paste0(dir.data,"meta_analysis_single_cpg_bacon_df.csv"),
  col_types = readr::cols()
)
single.cpg.sig.results <- readr::read_csv(                                                        
  paste0(dir.data,"meta_analysis_single_cpg_sig_no_crossHyb_smoking_df_bacon_2_4_minus_7.csv"),
  col_types = readr::cols()
)                                                                                                 

foreground.probes <- single.cpg.sig.results %>% pull(cpg) %>% as.character
foreground.probes.neg.est <- single.cpg.sig.results %>% filter(estimate.bacon < 0) %>% pull(cpg) %>% as.character
foreground.probes.pos.est <- single.cpg.sig.results  %>% filter(estimate.bacon > 0) %>% pull(cpg) %>% as.character
length(foreground.probes)
## [1] 339
### Background
background.probes <- single.cpg.results  %>% pull(cpg) %>% as.character 
length(background.probes)
## [1] 450793

5.1.2 Annotation

l.probes <- list(
    background.probes,
    foreground.probes.neg.est,
    foreground.probes.pos.est
)

names(l.probes) <- c(
    paste0("Evaluated probes (n = ",length(background.probes),")"),
    paste0("Significant w/ Negative estimate (n = ",length(foreground.probes.neg.est),")"),
    paste0("Significant w/ Positive estimate (n = ",length(foreground.probes.pos.est),")")
)

all.plot <- cpGsGenomicFeatures(l.probes)
plot.single.cpg <- all.plot$plot + ggtitle("Single cpg meta-analysis probes") 
plot.single.cpg

ggsave(
    plot = plot.single.cpg,
    width = 9, 
    filename = "bacon_2_4_minus_7/plots_enrichment_analysis/meta_analysis_single_cpg_enrichment.pdf"
)
## Saving 9 x 10 in image

5.1.3 ChroMHMM

file <- paste0("https://egg2.wustl.edu/roadmap/data/byFileType/chromhmmSegmentations",
               "/ChmmModels/coreMarks/jointModel/final/E073_15_coreMarks_segments.bed")
if(!file.exists( basename(file))) downloader::download(file, destfile = basename(file))
ChmmModels <- readr::read_tsv(
  basename(file),
  col_names = FALSE,
  col_types = readr::cols()
)
colnames(ChmmModels) <- c("chr","start","end","state")
states <- readr::read_csv(
  "../../../DNAm_RNA/data/chromHMM_labels.csv",
  col_names = FALSE,
  col_types = readr::cols()
)
states$X1 <- paste0("E",states$X1)
ChmmModels$state <- states$X3[match(ChmmModels$state,states$X1)]
ChmmModels.gr <- makeGRangesFromDataFrame(ChmmModels,keep.extra.columns = TRUE)
l.probes <- list(
    background.probes,
    foreground.probes.neg.est,
    foreground.probes.pos.est
)

names(l.probes) <- c(
    paste0("Evaluated probes (n = ",length(background.probes),")"),
    paste0("Significant w/ Negative estimate (n = ",length(foreground.probes.neg.est),")"),
    paste0("Significant w/ Positive estimate (n = ",length(foreground.probes.pos.est),")")
)

single.cpg.plot <- cpGsGenomicFeatures(
  l.probes,
  annotation.gr = ChmmModels.gr,
  plot.width = 12,
  plot.title = "Single cpg meta-analysis probes\nChroMHMM: E073 - 15 coreMarks segments",
  enrichment.type = "customized",
  plot.filename = "bacon_2_4_minus_7/plots_enrichment_analysis/meta_analysis_single_cpg_chromHMM_states.pdf",
)
single.cpg.plot$plot

tab.chrm <- cbind(
  data.frame(
    "Meta-Analysis" = c(
      rep("Single CpG",nrow(plot.chrm.hyper$table) + nrow(plot.chrm.hypo$table))
    ),
    "Foreground probes" = c(
      rep("Significant probes w/ Positive estimate",nrow(plot.chrm.hyper$table)),
      rep("Significant probes w/ Negative estimate",nrow(plot.chrm.hypo$table))
    ),
    "Enrichment analysis" = c(
      rep("ChroMHMM: E073",nrow(plot.chrm.hyper$table) + nrow(plot.chrm.hypo$table))
    )
  ),
  rbind(plot.chrm.hyper$table[,c(1,6,7)],
        plot.chrm.hypo$table[,c(1,6,7)])
)
tab.chrm %>% 
  DT::datatable(
    filter = 'top',
    style = "bootstrap",
    extensions = 'Buttons',
    options = list(scrollX = TRUE, 
                   dom = 'Bfrtip',
                   buttons = I('colvis'),
                   keys = TRUE, 
                   pageLength = 10)
  )

6 Pathway analysis of genome-wide significant CpGs (p < 2.4E-7) after inflation correction by Bacon method

6.1 For regions + single cpgs

6.1.1 Get probes

6.1.2 Get probes from regions

### Call in datasets
meta_sig <- read.csv(dir(dir.result.comp,pattern = "no.*csv",full.names = TRUE))

meta_all <- read.csv(
  paste0(dir.result.meta.analysis, "meta_analysis_ALL_df.csv")
) #dim: 40010 41
probes.cluster.all <- coMethDMR::getPredefinedCluster(
  arrayType = "450k",
  clusterType = "regions"
)

### get all cps in meta_sig input regions
idx <- gsub(
  "450k_Gene_3_200.|450k_InterGene_3_200.","",names(probes.cluster.all)
) %in% meta_sig$inputRegion

meta_sig_probes <- probes.cluster.all[idx] %>%
  unlist %>%
  as.character() %>%
  unique
length(meta_sig_probes)
## [1] 742
### get all cps in meta_all input regions
idx <- gsub(
  "450k_Gene_3_200.|450k_InterGene_3_200.","",names(probes.cluster.all)
) %in% meta_all$inputRegion

meta_all_probes <- probes.cluster.all[idx] %>%
  unlist %>%
  as.character() %>%
  unique

length(meta_all_probes)
## [1] 203198
all.foreground.probes <- c(meta_sig_probes, foreground.probes) %>% unique  
all.background.probes <- c(meta_all_probes, background.probes) %>% unique

6.1.3 Pathway analysis (gene ontology analysis)

library(missMethyl)
library(IlluminaHumanMethylation450kanno.ilmn12.hg19)
### collection = "GO"
all_go <- gometh(
  sig.cpg = all.foreground.probes,
  all.cpg = all.background.probes,
  collection = "GO",
  fract.counts = TRUE
)
# topGSA(all_go)

go <- missMethyl:::.getGO()
out <- getMappedEntrezIDs(sig.cpg = foreground.probes,
                          all.cpg = background.probes,
                          array.type = "450K")
sorted.eg.sig <-  out$sig.eg
gene.info <- TCGAbiolinks::get.GRCh.bioMart(genome = "hg19")
all_go$de_genes <- plyr::aaply(rownames(all_go),1,.fun = function(idx){
  gene.info$external_gene_name[gene.info$entrezgene_id %in% intersect(go$idList[[idx]],sorted.eg.sig)] %>%
    sort %>% unique %>% paste(collapse = ",")
})

all_go_ordered <- all_go[
  order(all_go$P.DE),
  ]

write.csv(
  all_go_ordered,
  paste0(dir.result.pathway, "pathway_regions_and_cpgs_GO_results_all.csv"),
  row.names = TRUE
)

all_go_ordered.bp <- all_go_ordered %>%
  tibble::rownames_to_column("GO") %>%  # keep row names
  dplyr::filter(ONTOLOGY == "BP") %>%
  tibble::column_to_rownames("GO")   # keep row names
all_go_ordered.bp$FDR <- p.adjust(all_go_ordered.bp$P.DE,"fdr")
write.csv(
  all_go_ordered.bp,
  paste0(dir.result.pathway, "pathway_regions_and_cpgs_GO_results_BP_N_range_5_200_fdr_recalc.csv"),
  row.names = TRUE
)
all_go_ordered.bp  %>% 
  dplyr::filter(FDR < 0.05) %>%
  DT::datatable(filter = 'top',
                style = "bootstrap",
                extensions = 'Buttons',
                options = list(scrollX = TRUE, 
                               dom = 'Bfrtip',
                               buttons = I('colvis'),
                               keys = TRUE, 
                               pageLength = 10), 
                rownames = FALSE,
                caption = "GO results BP (FDR < 0.05)")
### collection = "KEGG"
all_kegg <- gometh(
  sig.cpg = all.foreground.probes,
  all.cpg = all.background.probes,
  collection = "KEGG",
  fract.counts = TRUE
)
# topGSA(all_kegg)

kegg <- missMethyl:::.getKEGG()
out <- getMappedEntrezIDs(sig.cpg = foreground.probes,
                          all.cpg = background.probes,
                          array.type = "450K")
sorted.eg.sig <- out$sig.eg
gene.info <- TCGAbiolinks::get.GRCh.bioMart(genome = "hg19")
all_kegg$de_genes <- plyr::aaply(rownames(all_kegg),1,.fun = function(idx){
  gene.info$external_gene_name[gene.info$entrezgene_id %in% intersect(kegg$idList[[idx]],sorted.eg.sig)] %>%
    sort %>% unique %>% paste(collapse = ",")
})

all_kegg_ordered <- all_kegg[
  order(all_kegg$P.DE),
  ]

write.csv(
  all_kegg_ordered,
  paste0(dir.result.pathway, "pathway_regions_and_cpgs_KEGG_results_all.csv"),
  row.names = TRUE
)


all_kegg_ordered <- all_kegg_ordered %>%
  tibble::rownames_to_column("KEGG") %>%  # keep row names
  tibble::column_to_rownames("KEGG")      # keep row names
all_kegg_ordered$FDR <- p.adjust(all_kegg_ordered$P.DE,"fdr")
write.csv(
  all_kegg_ordered,
  paste0(dir.result.pathway, "pathway_regions_and_cpgs_KEGG_results_N_range_5_200_fdr_recalc.csv"),
  row.names = TRUE
)
all_kegg_ordered  %>% 
  dplyr::filter(P.DE < 0.05) %>%
  DT::datatable(filter = 'top',
                style = "bootstrap",
                extensions = 'Buttons',
                options = list(scrollX = TRUE, 
                               dom = 'Bfrtip',
                               buttons = I('colvis'),
                               keys = TRUE, 
                               pageLength = 10), 
                rownames = FALSE,
                caption = "kegg results (P.DE < 0.05)")                                   

7 Session information

devtools::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value                       
##  version  R version 4.0.2 (2020-06-22)
##  os       macOS Catalina 10.15.6      
##  system   x86_64, darwin17.0          
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  ctype    en_US.UTF-8                 
##  tz       America/New_York            
##  date     2020-08-11                  
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package                                       * version    date       lib
##  abind                                           1.4-5      2016-07-21 [1]
##  annotate                                        1.66.0     2020-04-28 [1]
##  AnnotationDbi                                   1.50.3     2020-07-25 [1]
##  AnnotationHub                                 * 2.20.0     2020-04-27 [1]
##  askpass                                         1.1        2019-01-13 [1]
##  assertthat                                      0.2.1      2019-03-21 [1]
##  backports                                       1.1.8      2020-06-17 [1]
##  base64                                          2.0        2016-05-10 [1]
##  base64enc                                       0.1-3      2015-07-28 [1]
##  beanplot                                        1.2        2014-09-19 [1]
##  BiasedUrn                                       1.07       2015-12-28 [1]
##  Biobase                                       * 2.48.0     2020-04-27 [1]
##  BiocFileCache                                 * 1.12.0     2020-04-27 [1]
##  BiocGenerics                                  * 0.34.0     2020-04-27 [1]
##  BiocManager                                     1.30.10    2019-11-16 [1]
##  BiocParallel                                    1.22.0     2020-04-27 [1]
##  BiocVersion                                     3.11.1     2020-04-07 [1]
##  biomaRt                                         2.44.1     2020-06-17 [1]
##  Biostrings                                    * 2.56.0     2020-04-27 [1]
##  bit                                             4.0.3      2020-07-30 [1]
##  bit64                                           4.0.2      2020-07-30 [1]
##  bitops                                          1.0-6      2013-08-17 [1]
##  blob                                            1.2.1      2020-01-20 [1]
##  boot                                            1.3-25     2020-04-26 [1]
##  broom                                           0.7.0      2020-07-09 [1]
##  bumphunter                                    * 1.30.0     2020-04-27 [1]
##  callr                                           3.4.3      2020-03-28 [1]
##  car                                             3.0-8      2020-05-21 [1]
##  carData                                         3.0-4      2020-05-22 [1]
##  cellranger                                      1.1.0      2016-07-27 [1]
##  cli                                             2.0.2      2020-02-28 [1]
##  codetools                                       0.2-16     2018-12-24 [1]
##  colorspace                                      1.4-1      2019-03-18 [1]
##  coMethDMR                                     * 0.0.0.9001 2020-07-23 [1]
##  crayon                                          1.3.4      2017-09-16 [1]
##  crosstalk                                       1.1.0.1    2020-03-13 [1]
##  curl                                            4.3        2019-12-02 [1]
##  data.table                                      1.13.0     2020-07-24 [1]
##  DBI                                             1.1.0      2019-12-15 [1]
##  dbplyr                                        * 1.4.4      2020-05-27 [1]
##  DelayedArray                                  * 0.14.1     2020-07-14 [1]
##  DelayedMatrixStats                              1.10.1     2020-07-03 [1]
##  desc                                            1.2.0      2018-05-01 [1]
##  devtools                                        2.3.1      2020-07-21 [1]
##  digest                                          0.6.25     2020-02-23 [1]
##  doRNG                                           1.8.2      2020-01-27 [1]
##  downloader                                      0.4        2015-07-09 [1]
##  dplyr                                         * 1.0.1      2020-07-31 [1]
##  DT                                              0.14       2020-06-24 [1]
##  ellipsis                                        0.3.1      2020-05-15 [1]
##  evaluate                                        0.14       2019-05-28 [1]
##  ExperimentHub                                 * 1.14.0     2020-04-27 [1]
##  fansi                                           0.4.1      2020-01-08 [1]
##  farver                                          2.0.3      2020-01-16 [1]
##  fastmap                                         1.0.1      2019-10-08 [1]
##  forcats                                         0.5.0      2020-03-01 [1]
##  foreach                                       * 1.5.0      2020-03-30 [1]
##  foreign                                         0.8-80     2020-05-24 [1]
##  fs                                              1.5.0      2020-07-31 [1]
##  genefilter                                      1.70.0     2020-04-27 [1]
##  generics                                        0.0.2      2018-11-29 [1]
##  GenomeInfoDb                                  * 1.24.2     2020-06-15 [1]
##  GenomeInfoDbData                                1.2.3      2020-07-23 [1]
##  GenomicAlignments                               1.24.0     2020-04-27 [1]
##  GenomicFeatures                                 1.40.1     2020-07-14 [1]
##  GenomicRanges                                 * 1.40.0     2020-04-27 [1]
##  GEOquery                                        2.56.0     2020-04-27 [1]
##  ggplot2                                       * 3.3.2      2020-06-19 [1]
##  ggpubr                                          0.4.0      2020-06-27 [1]
##  ggsignif                                        0.6.0      2019-08-08 [1]
##  glue                                            1.4.1      2020-05-13 [1]
##  GO.db                                           3.11.4     2020-07-23 [1]
##  gtable                                          0.3.0      2019-03-25 [1]
##  haven                                           2.3.1      2020-06-01 [1]
##  HDF5Array                                       1.16.1     2020-06-16 [1]
##  hms                                             0.5.3      2020-01-08 [1]
##  htmltools                                       0.5.0      2020-06-16 [1]
##  htmlwidgets                                     1.5.1      2019-10-08 [1]
##  httpuv                                          1.5.4      2020-06-06 [1]
##  httr                                            1.4.2      2020-07-20 [1]
##  IlluminaHumanMethylation450kanno.ilmn12.hg19  * 0.6.0      2020-07-23 [1]
##  IlluminaHumanMethylationEPICanno.ilm10b2.hg19   0.6.0      2020-07-23 [1]
##  IlluminaHumanMethylationEPICanno.ilm10b4.hg19 * 0.6.0      2020-07-23 [1]
##  illuminaio                                      0.30.0     2020-04-27 [1]
##  interactiveDisplayBase                          1.26.3     2020-06-02 [1]
##  IRanges                                       * 2.22.2     2020-05-21 [1]
##  iterators                                     * 1.0.12     2019-07-26 [1]
##  jsonlite                                        1.7.0      2020-06-25 [1]
##  knitr                                           1.29       2020-06-23 [1]
##  labeling                                        0.3        2014-08-23 [1]
##  later                                           1.1.0.1    2020-06-05 [1]
##  lattice                                         0.20-41    2020-04-02 [1]
##  lifecycle                                       0.2.0      2020-03-06 [1]
##  limma                                           3.44.3     2020-06-12 [1]
##  lme4                                            1.1-23     2020-04-07 [1]
##  lmerTest                                        3.1-2      2020-04-08 [1]
##  locfit                                        * 1.5-9.4    2020-03-25 [1]
##  LOLA                                          * 1.18.0     2020-04-27 [1]
##  magrittr                                        1.5        2014-11-22 [1]
##  MASS                                            7.3-51.6   2020-04-26 [1]
##  Matrix                                          1.2-18     2019-11-27 [1]
##  matrixStats                                   * 0.56.0     2020-03-13 [1]
##  mclust                                          5.4.6      2020-04-11 [1]
##  memoise                                         1.1.0      2017-04-21 [1]
##  mime                                            0.9        2020-02-04 [1]
##  minfi                                         * 1.34.0     2020-04-27 [1]
##  minqa                                           1.2.4      2014-10-09 [1]
##  missMethyl                                    * 1.22.0     2020-04-27 [1]
##  multtest                                        2.44.0     2020-04-27 [1]
##  munsell                                         0.5.0      2018-06-12 [1]
##  nlme                                            3.1-148    2020-05-24 [1]
##  nloptr                                          1.2.2.2    2020-07-02 [1]
##  nor1mix                                         1.3-0      2019-06-13 [1]
##  numDeriv                                        2016.8-1.1 2019-06-06 [1]
##  openssl                                         1.4.2      2020-06-27 [1]
##  openxlsx                                        4.1.5      2020-05-06 [1]
##  org.Hs.eg.db                                    3.11.4     2020-07-23 [1]
##  pillar                                          1.4.6      2020-07-10 [1]
##  pkgbuild                                        1.1.0      2020-07-13 [1]
##  pkgconfig                                       2.0.3      2019-09-22 [1]
##  pkgload                                         1.1.0      2020-05-29 [1]
##  plyr                                            1.8.6      2020-03-03 [1]
##  preprocessCore                                  1.50.0     2020-04-27 [1]
##  prettyunits                                     1.1.1      2020-01-24 [1]
##  processx                                        3.4.3      2020-07-05 [1]
##  progress                                        1.2.2      2019-05-16 [1]
##  promises                                        1.1.1      2020-06-09 [1]
##  ps                                              1.3.3      2020-05-08 [1]
##  purrr                                           0.3.4      2020-04-17 [1]
##  quadprog                                        1.5-8      2019-11-20 [1]
##  qvalue                                        * 2.20.0     2020-04-27 [1]
##  R.methodsS3                                     1.8.0      2020-02-14 [1]
##  R.oo                                            1.23.0     2019-11-03 [1]
##  R.utils                                         2.9.2      2019-12-08 [1]
##  R6                                              2.4.1      2019-11-12 [1]
##  rappdirs                                        0.3.1      2016-03-28 [1]
##  RColorBrewer                                    1.1-2      2014-12-07 [1]
##  Rcpp                                            1.0.5      2020-07-06 [1]
##  RCurl                                           1.98-1.2   2020-04-18 [1]
##  readr                                           1.3.1      2018-12-21 [1]
##  readxl                                          1.3.1      2019-03-13 [1]
##  remotes                                         2.2.0      2020-07-21 [1]
##  reshape                                         0.8.8      2018-10-23 [1]
##  reshape2                                        1.4.4      2020-04-09 [1]
##  rhdf5                                           2.32.2     2020-07-03 [1]
##  Rhdf5lib                                        1.10.1     2020-07-09 [1]
##  rio                                             0.5.16     2018-11-26 [1]
##  rlang                                           0.4.7      2020-07-09 [1]
##  rmarkdown                                       2.3        2020-06-18 [1]
##  rngtools                                        1.5        2020-01-23 [1]
##  rprojroot                                       1.3-2      2018-01-03 [1]
##  Rsamtools                                       2.4.0      2020-04-27 [1]
##  RSQLite                                         2.2.0      2020-01-07 [1]
##  rstatix                                         0.6.0      2020-06-18 [1]
##  rtracklayer                                     1.48.0     2020-07-14 [1]
##  rvest                                           0.3.6      2020-07-25 [1]
##  S4Vectors                                     * 0.26.1     2020-05-16 [1]
##  scales                                          1.1.1      2020-05-11 [1]
##  scrime                                          1.3.5      2018-12-01 [1]
##  sessioninfo                                     1.1.1      2018-11-05 [1]
##  shiny                                           1.5.0      2020-06-23 [1]
##  siggenes                                        1.62.0     2020-04-27 [1]
##  simpleCache                                     0.4.1      2019-02-26 [1]
##  statmod                                         1.4.34     2020-02-17 [1]
##  stringi                                         1.4.6      2020-02-17 [1]
##  stringr                                         1.4.0      2019-02-10 [1]
##  SummarizedExperiment                          * 1.18.2     2020-07-14 [1]
##  survival                                        3.2-3      2020-06-13 [1]
##  TCGAbiolinks                                    2.16.3     2020-07-15 [1]
##  testthat                                        2.3.2      2020-03-02 [1]
##  tibble                                          3.0.3      2020-07-10 [1]
##  tidyr                                           1.1.1      2020-07-31 [1]
##  tidyselect                                      1.1.0      2020-05-11 [1]
##  usethis                                         1.6.1      2020-04-29 [1]
##  vctrs                                           0.3.2      2020-07-15 [1]
##  withr                                           2.2.0      2020-04-20 [1]
##  xfun                                            0.16       2020-07-24 [1]
##  XML                                             3.99-0.5   2020-07-23 [1]
##  xml2                                            1.3.2      2020-04-23 [1]
##  xtable                                          1.8-4      2019-04-21 [1]
##  XVector                                       * 0.28.0     2020-04-27 [1]
##  yaml                                            2.2.1      2020-02-01 [1]
##  zip                                             2.0.4      2019-09-01 [1]
##  zlibbioc                                        1.34.0     2020-04-27 [1]
##  source        
##  CRAN (R 4.0.2)
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  CRAN (R 4.0.2)
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.1)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.1)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.1)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  Bioconductor  
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.1)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
##  CRAN (R 4.0.2)
##  CRAN (R 4.0.2)
##  Bioconductor  
## 
## [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library
LS0tCnRpdGxlOiAiRW5yaWNobWVudCBhbmFseXNpcyBvZiBzaWduaWZpY2FudCBDcEdzIGFmdGVyIGluZmxhdGlvbiBjb3JyZWN0aW9uIGJ5IGJhY29uIG1ldGhvZCIKYXV0aG9yOiAiIFRpYWdvIEMuIFNpbHZhLCBMYW55dSBaaGFuZywgTGlseSBXYW5nIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBybWFya2Rvd246Omh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogbHVtZW4KICAgIHRvYzogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBkZl9wcmludDogcGFnZWQKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB5ZXMKICAgIHRvY19kZXB0aDogMwplZGl0b3Jfb3B0aW9uczoKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lICAgIAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSxmaWcud2lkdGggPSAxMCxmaWcuaGVpZ2h0ID0gMTApCmBgYAoKCiMgTWFpbiBsaWJyYXJpZXMgYW5kIGNvbmZpZ3VyYXRpb24KCmBgYHtSIGxpYnMsIG1lc3NhZ2UgPSBGQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30KbGlicmFyeShkcGx5cikKbGlicmFyeShFeHBlcmltZW50SHViKQpsaWJyYXJ5KEdlbm9taWNSYW5nZXMpCmxpYnJhcnkoY29NZXRoRE1SKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoTE9MQSkKbGlicmFyeShxdmFsdWUpCmBgYAoKYGBge1IsIGluY2x1ZGUgPSBGQUxTRX0KZ2VuZS5pbmZvIDwtIFRDR0FiaW9saW5rczo6Z2V0LkdSQ2guYmlvTWFydChnZW5vbWUgPSAiaGcxOSIpCmBgYAoKYGBge1IgcGF0aHN9CmRpci5kYXRhIDwtICIuL0RBVEFTRVRTLyIKZGlyLnJlc3VsdCA8LSAiLi4vbWV0YV9hbmFseXNpc19yZWdpb25fcmVzdWx0cy8iCmRpci5yZXN1bHQubWV0YS5hbmFseXNpcyA8LSBmaWxlLnBhdGgoZGlyLnJlc3VsdCwgInN0ZXAxX21ldGFfYW5hbHlzaXMvIikKZGlyLnJlc3VsdC5jb21wIDwtIGZpbGUucGF0aChkaXIucmVzdWx0LCAic3RlcDNfY29tcC8iKQpkaXIucmVzdWx0LmxvbGEgPC0gZmlsZS5wYXRoKCJiYWNvbi9sb2xhLyIpCmRpci5yZXN1bHQucGF0aHdheSA8LSBmaWxlLnBhdGgoImJhY29uL3Jlc3VsdHNfcGF0aHdheS8iKQpmb3IocCBpbiBncmVwKCJkaXIiLGxzKCksdmFsdWUgPSBUKSkgZGlyLmNyZWF0ZShnZXQocCkscmVjdXJzaXZlID0gVFJVRSxzaG93V2FybmluZ3MgPSBGQUxTRSkKYGBgCgoKIyBFbnJpY2htZW50IGFuYWx5c2lzIG9mIEZEUiBzaWduaWZpY2FudCBDcEdzLCBhZnRlciBpbmZsYXRpb24gY29ycmVjdGlvbiBieSBiYWNvbiBtZXRob2QKCiMjIEZvciBzaW5nbGUgY3BncwoKIyMjICBHZXQgcmVzdWx0cwoKYGBge1J9CiMjIyBGb3JlZ3JvdW5kCnNpbmdsZS5jcGcucmVzdWx0cyA8LSByZWFkcjo6cmVhZF9jc3YoCiAgcGFzdGUwKGRpci5kYXRhLCJtZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfYmFjb25fZGYuY3N2IiksCiAgY29sX3R5cGVzID0gcmVhZHI6OmNvbHMoKQopCnNpbmdsZS5jcGcuc2lnLnJlc3VsdHMgPC0gcmVhZHI6OnJlYWRfY3N2KCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgcGFzdGUwKGRpci5kYXRhLCJtZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfc2lnX25vX2Nyb3NzSHliX3Ntb2tpbmdfZGZfYmFjb24uY3N2IiksCiAgY29sX3R5cGVzID0gcmVhZHI6OmNvbHMoKQopICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKZm9yZWdyb3VuZC5wcm9iZXMgPC0gc2luZ2xlLmNwZy5zaWcucmVzdWx0cyAlPiUgcHVsbChjcGcpICU+JSBhcy5jaGFyYWN0ZXIKZm9yZWdyb3VuZC5wcm9iZXMubmVnLmVzdCA8LSBzaW5nbGUuY3BnLnNpZy5yZXN1bHRzICU+JSAKICBmaWx0ZXIoZXN0aW1hdGUuYmFjb24gPCAwKSAlPiUgCiAgcHVsbChjcGcpICU+JSAKICBhcy5jaGFyYWN0ZXIKZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdCA8LSBzaW5nbGUuY3BnLnNpZy5yZXN1bHRzICAlPiUgCiAgZmlsdGVyKGVzdGltYXRlLmJhY29uID4gMCkgJT4lIAogIHB1bGwoY3BnKSAlPiUgCiAgYXMuY2hhcmFjdGVyCmxlbmd0aChmb3JlZ3JvdW5kLnByb2JlcykKCiMjIyBCYWNrZ3JvdW5kCmJhY2tncm91bmQucHJvYmVzIDwtIHNpbmdsZS5jcGcucmVzdWx0cyAgJT4lIHB1bGwoY3BnKSAlPiUgYXMuY2hhcmFjdGVyIApsZW5ndGgoYmFja2dyb3VuZC5wcm9iZXMpCmBgYAoKCiMjIyBBbm5vdGF0aW9uCmBgYHtSfQpsLnByb2JlcyA8LSBsaXN0KAogICAgYmFja2dyb3VuZC5wcm9iZXMsCiAgICBmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0LAogICAgZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdAopCgpuYW1lcyhsLnByb2JlcykgPC0gYygKICAgIHBhc3RlMCgiRXZhbHVhdGVkIHByb2JlcyAobiA9ICIsbGVuZ3RoKGJhY2tncm91bmQucHJvYmVzKSwiKSIpLAogICAgcGFzdGUwKCJTaWduaWZpY2FudCB3LyBOZWdhdGl2ZSBlc3RpbWF0ZSAobiA9ICIsbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QpLCIpIiksCiAgICBwYXN0ZTAoIlNpZ25pZmljYW50IHcvIFBvc2l0aXZlIGVzdGltYXRlIChuID0gIixsZW5ndGgoZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdCksIikiKQopCgphbGwucGxvdCA8LSBjcEdzR2Vub21pY0ZlYXR1cmVzKGwucHJvYmVzKQpwbG90LnNpbmdsZS5jcGcgPC0gYWxsLnBsb3QkcGxvdCArIGdndGl0bGUoIlNpbmdsZSBjcGcgbWV0YS1hbmFseXNpcyBwcm9iZXMiKSAKcGxvdC5zaW5nbGUuY3BnCmdnc2F2ZSgKICBwbG90ID0gcGxvdC5zaW5nbGUuY3BnLAogIHdpZHRoID0gOSwKICBmaWxlbmFtZSA9ICJiYWNvbi9wbG90c19lbnJpY2htZW50X2FuYWx5c2lzLy9tZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfZW5yaWNobWVudC5wZGYiCikKYGBgCgoKYGBge1IsIG1lc3NhZ2UgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQpwbG90LmNocm0uaHlwbyA8LSBjcEdzRW5yaWNobWVudCgKICBmZy5wcm9iZXMgPSBmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0LAogIGJnLnByb2JlcyA9IGJhY2tncm91bmQucHJvYmVzLAogIGVucmljaG1lbnQudHlwZSA9ICJpc2xhbmQiLAogIGZnLmxhYmVsID0gcGFzdGUwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gTmVnYXRpdmUgZXN0aW1hdGUgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0KSksCiAgYmcubGFiZWwgPSBwYXN0ZTAoIkV2YWx1YXRlZCBwcm9iZXMgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChiYWNrZ3JvdW5kLnByb2JlcykpCiAgKQojcGxvdC5jaHJtLmh5cG8kcGxvdApwbG90LmNocm0uaHlwZXIgPC0gY3BHc0VucmljaG1lbnQoCiAgZmcucHJvYmVzID0gZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdCwKICBiZy5wcm9iZXMgPSBiYWNrZ3JvdW5kLnByb2JlcywKICBlbnJpY2htZW50LnR5cGUgPSAiaXNsYW5kIiwKICBmZy5sYWJlbCA9IHBhc3RlMCgiU2lnbmlmaWNhbnQgcHJvYmVzIHcvIFBvc2l0aXZlIGVzdGltYXRlIChuID0gIiwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgoZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdCkpLAogIGJnLmxhYmVsID0gcGFzdGUwKCJFdmFsdWF0ZWQgcHJvYmVzIChuID0gIiwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgoYmFja2dyb3VuZC5wcm9iZXMpKQogICkKI3Bsb3QuY2hybS5oeXBlciRwbG90CnRhYi5pc2xhbmQgPC0gY2JpbmQoCiAgIGRhdGEuZnJhbWUoCiAgICAiTWV0YS1BbmFseXNpcyIgPSBjKAogICAgICByZXAoIlNpbmdsZSBDcEciLG5yb3cocGxvdC5jaHJtLmh5cGVyJHRhYmxlKSArIG5yb3cocGxvdC5jaHJtLmh5cG8kdGFibGUpKQogICAgKSwKICAgICJGb3JlZ3JvdW5kIHByb2JlcyIgPSBjKAogICAgICByZXAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBQb3NpdGl2ZSBlc3RpbWF0ZSIsbnJvdyhwbG90LmNocm0uaHlwZXIkdGFibGUpKSwKICAgICAgcmVwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gTmVnYXRpdmUgZXN0aW1hdGUiLG5yb3cocGxvdC5jaHJtLmh5cG8kdGFibGUpKQogICAgKSwKICAgICJFbnJpY2htZW50IGFuYWx5c2lzIiA9IGMoCiAgICAgIHJlcCgiUmVsYXRpb25fdG9fSXNsYW5kIixucm93KHBsb3QuY2hybS5oeXBlciR0YWJsZSkgKyBucm93KHBsb3QuY2hybS5oeXBvJHRhYmxlKSkKICAgICkKICApLAogIHJiaW5kKHBsb3QuY2hybS5oeXBlciR0YWJsZVssYygxLDYsNyldLAogICAgICAgIHBsb3QuY2hybS5oeXBvJHRhYmxlWyxjKDEsNiw3KV0pCikKdGFiLmlzbGFuZCAgJT4lIAogIERUOjpkYXRhdGFibGUoCiAgICBmaWx0ZXIgPSAndG9wJywKICAgIHN0eWxlID0gImJvb3RzdHJhcCIsCiAgICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLAogICAgb3B0aW9ucyA9IGxpc3Qoc2Nyb2xsWCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICBidXR0b25zID0gSSgnY29sdmlzJyksCiAgICAgICAgICAgICAgICAgICBrZXlzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gMTApCiAgKQpgYGAKCgpgYGB7UiwgbWVzc2FnZSA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CnBsb3QuY2hybS5oeXBvIDwtIGNwR3NFbnJpY2htZW50KAogIGZnLnByb2JlcyA9IGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QsCiAgYmcucHJvYmVzID0gYmFja2dyb3VuZC5wcm9iZXMsCiAgZW5yaWNobWVudC50eXBlID0gImdlbmUiLAogIGZnLmxhYmVsID0gcGFzdGUwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gTmVnYXRpdmUgZXN0aW1hdGUgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0KSksCiAgYmcubGFiZWwgPSBwYXN0ZTAoIkV2YWx1YXRlZCBwcm9iZXMgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChiYWNrZ3JvdW5kLnByb2JlcykpKQoKI3Bsb3QuY2hybS5oeXBvJHBsb3QKcGxvdC5jaHJtLmh5cGVyIDwtIGNwR3NFbnJpY2htZW50KAogIGZnLnByb2JlcyA9IGZvcmVncm91bmQucHJvYmVzLnBvcy5lc3QsCiAgYmcucHJvYmVzID0gYmFja2dyb3VuZC5wcm9iZXMsCiAgZW5yaWNobWVudC50eXBlID0gImdlbmUiLAogIGZnLmxhYmVsID0gcGFzdGUwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gUG9zaXRpdmUgZXN0aW1hdGUgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChmb3JlZ3JvdW5kLnByb2Jlcy5wb3MuZXN0KSksCiAgYmcubGFiZWwgPSBwYXN0ZTAoIkV2YWx1YXRlZCBwcm9iZXMgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChiYWNrZ3JvdW5kLnByb2JlcykpKQoKdGFiLmdlbmUgPC0gY2JpbmQoCiBkYXRhLmZyYW1lKAogICAgIk1ldGEtQW5hbHlzaXMiID0gYygKICAgICAgcmVwKCJTaW5nbGUgQ3BHIixucm93KHBsb3QuY2hybS5oeXBlciR0YWJsZSkgKyBucm93KHBsb3QuY2hybS5oeXBvJHRhYmxlKSkKICAgICksCiAgICAiRm9yZWdyb3VuZCBwcm9iZXMiID0gYygKICAgICAgcmVwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gUG9zaXRpdmUgZXN0aW1hdGUiLG5yb3cocGxvdC5jaHJtLmh5cGVyJHRhYmxlKSksCiAgICAgIHJlcCgiU2lnbmlmaWNhbnQgcHJvYmVzIHcvIE5lZ2F0aXZlIGVzdGltYXRlIixucm93KHBsb3QuY2hybS5oeXBvJHRhYmxlKSkKICAgICksCiAgICAiRW5yaWNobWVudCBhbmFseXNpcyIgPSBjKAogICAgICByZXAoIlVDU0NfUmVmR2VuZV9Hcm91cF9oaWVyYXJjaHkiLG5yb3cocGxvdC5jaHJtLmh5cGVyJHRhYmxlKSArIG5yb3cocGxvdC5jaHJtLmh5cG8kdGFibGUpKQogICAgKQogICksCiAgcmJpbmQocGxvdC5jaHJtLmh5cGVyJHRhYmxlWyxjKDEsNiw3KV0sCiAgICAgICAgcGxvdC5jaHJtLmh5cG8kdGFibGVbLGMoMSw2LDcpXSkKKQojcGxvdC5jaHJtLmh5cGVyJHBsb3QKdGFiLmdlbmUgICU+JSAKICBEVDo6ZGF0YXRhYmxlKAogICAgZmlsdGVyID0gJ3RvcCcsCiAgICBzdHlsZSA9ICJib290c3RyYXAiLAogICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgIGRvbSA9ICdCZnJ0aXAnLAogICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IEkoJ2NvbHZpcycpLAogICAgICAgICAgICAgICAgICAga2V5cyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKQogICkKYGBgCgoKIyMjIENocm9NSE1NCmBgYHtSfQpmaWxlIDwtIHBhc3RlMCgiaHR0cHM6Ly9lZ2cyLnd1c3RsLmVkdS9yb2FkbWFwL2RhdGEvYnlGaWxlVHlwZS9jaHJvbWhtbVNlZ21lbnRhdGlvbnMiLAogICAgICAgICAgICAgICAiL0NobW1Nb2RlbHMvY29yZU1hcmtzL2pvaW50TW9kZWwvZmluYWwvRTA3M18xNV9jb3JlTWFya3Nfc2VnbWVudHMuYmVkIikKaWYoIWZpbGUuZXhpc3RzKCBiYXNlbmFtZShmaWxlKSkpIGRvd25sb2FkZXI6OmRvd25sb2FkKGZpbGUsIGRlc3RmaWxlID0gYmFzZW5hbWUoZmlsZSkpCgoKQ2htbU1vZGVscyA8LSByZWFkcjo6cmVhZF90c3YoCiAgYmFzZW5hbWUoZmlsZSksCiAgY29sX25hbWVzID0gRkFMU0UsCiAgY29sX3R5cGVzID0gcmVhZHI6OmNvbHMoKQopCmNvbG5hbWVzKENobW1Nb2RlbHMpIDwtIGMoImNociIsInN0YXJ0IiwiZW5kIiwic3RhdGUiKQpzdGF0ZXMgPC0gcmVhZHI6OnJlYWRfY3N2KAogICIuLi8uLi8uLi9ETkFtX1JOQS9kYXRhL2Nocm9tSE1NX2xhYmVscy5jc3YiLAogIGNvbF9uYW1lcyA9IEZBTFNFLAogIGNvbF90eXBlcyA9IHJlYWRyOjpjb2xzKCkKKQpzdGF0ZXMkWDEgPC0gcGFzdGUwKCJFIixzdGF0ZXMkWDEpCkNobW1Nb2RlbHMkc3RhdGUgPC0gc3RhdGVzJFgzW21hdGNoKENobW1Nb2RlbHMkc3RhdGUsc3RhdGVzJFgxKV0KQ2htbU1vZGVscy5nciA8LSBtYWtlR1Jhbmdlc0Zyb21EYXRhRnJhbWUoQ2htbU1vZGVscyxrZWVwLmV4dHJhLmNvbHVtbnMgPSBUUlVFKQpgYGAKCmBgYHtSLCBpbmNsdWRlID0gRkFMU0V9CnBsb3QuY2hybS5oeXBvIDwtIGNwR3NFbnJpY2htZW50KAogIGZnLnByb2JlcyA9IGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QsCiAgYmcucHJvYmVzID0gYmFja2dyb3VuZC5wcm9iZXMsCiAgYW5ub3RhdGlvbi5nciA9IENobW1Nb2RlbHMuZ3IsCiAgZmcubGFiZWwgPSBwYXN0ZTAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBOZWdhdGl2ZSBlc3RpbWF0ZSAobiA9ICIsCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QpLCIpIiksCiAgYmcubGFiZWwgPSBwYXN0ZTAoIkV2YWx1YXRlZCBwcm9iZXMgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChiYWNrZ3JvdW5kLnByb2JlcyksIikiKSwKICBlbnJpY2htZW50LnR5cGUgPSAiY3VzdG9taXplZCIsCiAgcGxvdC5maWxlbmFtZSA9ICJiYWNvbi9wbG90c19lbnJpY2htZW50X2FuYWx5c2lzLy9tZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfbmVnX2VzdGltYXRlX2Nocm9tSE1NX3N0YXRlcy5wbmciCikKCiMjcGxvdC5jaHJtLmh5cG8kcGxvdAoKcGxvdC5jaHJtLmh5cGVyIDwtIGNwR3NFbnJpY2htZW50KAogIGZnLnByb2JlcyA9IGZvcmVncm91bmQucHJvYmVzLnBvcy5lc3QsCiAgYmcucHJvYmVzID0gYmFja2dyb3VuZC5wcm9iZXMsCiAgYW5ub3RhdGlvbi5nciA9IENobW1Nb2RlbHMuZ3IsCiAgZmcubGFiZWwgPSBwYXN0ZTAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBQb3NpdGl2ZSBlc3RpbWF0ZSAobiA9ICIsCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzLnBvcy5lc3QpLCIpIiksCiAgYmcubGFiZWwgPSBwYXN0ZTAoIkV2YWx1YXRlZCBwcm9iZXMgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChiYWNrZ3JvdW5kLnByb2JlcyksIikiKSwKICBlbnJpY2htZW50LnR5cGUgPSAiY3VzdG9taXplZCIsCiAgcGxvdC5maWxlbmFtZSA9ICJiYWNvbi9wbG90c19lbnJpY2htZW50X2FuYWx5c2lzLy9tZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfcG9zX2VzdF9jaHJvbUhNTV9zdGF0ZXMucG5nIikKIyNwbG90LmNocm0uaHlwZXIkcGxvdApgYGAKCmBgYHtSfQpsLnByb2JlcyA8LSBsaXN0KAogICAgYmFja2dyb3VuZC5wcm9iZXMsCiAgICBmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0LAogICAgZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdAopCgpuYW1lcyhsLnByb2JlcykgPC0gYygKICAgIHBhc3RlMCgiRXZhbHVhdGVkIHByb2JlcyAobiA9ICIsbGVuZ3RoKGJhY2tncm91bmQucHJvYmVzKSwiKSIpLAogICAgcGFzdGUwKCJTaWduaWZpY2FudCB3LyBOZWdhdGl2ZSBlc3RpbWF0ZSAobiA9ICIsbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QpLCIpIiksCiAgICBwYXN0ZTAoIlNpZ25pZmljYW50IHcvIFBvc2l0aXZlIGVzdGltYXRlIChuID0gIixsZW5ndGgoZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdCksIikiKQopCgpzaW5nbGUuY3BnLnBsb3QgPC0gY3BHc0dlbm9taWNGZWF0dXJlcygKICBsLnByb2JlcywKICBhbm5vdGF0aW9uLmdyID0gQ2htbU1vZGVscy5nciwKICBwbG90LndpZHRoID0gMTIsCiAgcGxvdC50aXRsZSA9ICJTaW5nbGUgY3BnIG1ldGEtYW5hbHlzaXMgcHJvYmVzXG5DaHJvTUhNTTogRTA3MyAtIDE1IGNvcmVNYXJrcyBzZWdtZW50cyIsCiAgZW5yaWNobWVudC50eXBlID0gImN1c3RvbWl6ZWQiLAogIHBsb3QuZmlsZW5hbWUgPSAiYmFjb24vcGxvdHNfZW5yaWNobWVudF9hbmFseXNpcy8vbWV0YV9hbmFseXNpc19zaW5nbGVfY3BnX2Nocm9tSE1NX3N0YXRlcy5wZGYiLAopCnNpbmdsZS5jcGcucGxvdCRwbG90CmBgYAoKCmBgYHtSfQoKdGFiLmNocm0gPC0gY2JpbmQoCiAgZGF0YS5mcmFtZSgKICAgICJNZXRhLUFuYWx5c2lzIiA9IGMoCiAgICAgIHJlcCgiU2luZ2xlIENwRyIsbnJvdyhwbG90LmNocm0uaHlwZXIkdGFibGUpICsgbnJvdyhwbG90LmNocm0uaHlwbyR0YWJsZSkpCiAgICApLAogICAgIkZvcmVncm91bmQgcHJvYmVzIiA9IGMoCiAgICAgIHJlcCgiU2lnbmlmaWNhbnQgcHJvYmVzIHcvIFBvc2l0aXZlIGVzdGltYXRlIixucm93KHBsb3QuY2hybS5oeXBlciR0YWJsZSkpLAogICAgICByZXAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBOZWdhdGl2ZSBlc3RpbWF0ZSIsbnJvdyhwbG90LmNocm0uaHlwbyR0YWJsZSkpCiAgICApLAogICAgIkVucmljaG1lbnQgYW5hbHlzaXMiID0gYygKICAgICAgcmVwKCJDaHJvTUhNTTogRTA3MyIsbnJvdyhwbG90LmNocm0uaHlwZXIkdGFibGUpICsgbnJvdyhwbG90LmNocm0uaHlwbyR0YWJsZSkpCiAgICApCiAgKSwKICByYmluZChwbG90LmNocm0uaHlwZXIkdGFibGVbLGMoMSw2LDcpXSwKICAgICAgICBwbG90LmNocm0uaHlwbyR0YWJsZVssYygxLDYsNyldKQopCnRhYi5jaHJtICAlPiUgCiAgRFQ6OmRhdGF0YWJsZSgKICAgIGZpbHRlciA9ICd0b3AnLAogICAgc3R5bGUgPSAiYm9vdHN0cmFwIiwKICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsCiAgICBvcHRpb25zID0gbGlzdChzY3JvbGxYID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICBkb20gPSAnQmZydGlwJywKICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBJKCdjb2x2aXMnKSwKICAgICAgICAgICAgICAgICAgIGtleXMgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCkKICApCmBgYAoKIyBQYXRod2F5IGFuYWx5c2lzIG9mIEZEUiBzaWduaWZpY2FudCBDcEdzIGFmdGVyIGluZmxhdGlvbiBjb3JyZWN0aW9uIAoKIyMgRm9yIHJlZ2lvbnMgKyBzaW5nbGUgY3BncwoKIyMjIEdldCBwcm9iZXMKCiMjIyBHZXQgcHJvYmVzIGZyb20gcmVnaW9ucwpgYGB7Un0KIyMjIENhbGwgaW4gZGF0YXNldHMKbWV0YV9zaWcgPC0gcmVhZC5jc3YoZGlyKGRpci5yZXN1bHQuY29tcCxwYXR0ZXJuID0gIm5vLipjc3YiLGZ1bGwubmFtZXMgPSBUUlVFKSkKCm1ldGFfYWxsIDwtIHJlYWQuY3N2KAogIHBhc3RlMChkaXIucmVzdWx0Lm1ldGEuYW5hbHlzaXMsICJtZXRhX2FuYWx5c2lzX0FMTF9kZi5jc3YiKQopICNkaW06IDQwMDEwIDQxCmBgYAoKYGBge1J9CnByb2Jlcy5jbHVzdGVyLmFsbCA8LSBjb01ldGhETVI6OmdldFByZWRlZmluZWRDbHVzdGVyKAogIGFycmF5VHlwZSA9ICI0NTBrIiwKICBjbHVzdGVyVHlwZSA9ICJyZWdpb25zIgopCgojIyMgZ2V0IGFsbCBjcHMgaW4gbWV0YV9zaWcgaW5wdXQgcmVnaW9ucwppZHggPC0gZ3N1YigKICAiNDUwa19HZW5lXzNfMjAwLnw0NTBrX0ludGVyR2VuZV8zXzIwMC4iLCIiLG5hbWVzKHByb2Jlcy5jbHVzdGVyLmFsbCkKKSAlaW4lIG1ldGFfc2lnJGlucHV0UmVnaW9uCgptZXRhX3NpZ19wcm9iZXMgPC0gcHJvYmVzLmNsdXN0ZXIuYWxsW2lkeF0gJT4lCiAgdW5saXN0ICU+JQogIGFzLmNoYXJhY3RlcigpICU+JQogIHVuaXF1ZQpsZW5ndGgobWV0YV9zaWdfcHJvYmVzKQoKIyMjIGdldCBhbGwgY3BzIGluIG1ldGFfYWxsIGlucHV0IHJlZ2lvbnMKaWR4IDwtIGdzdWIoCiAgIjQ1MGtfR2VuZV8zXzIwMC58NDUwa19JbnRlckdlbmVfM18yMDAuIiwiIixuYW1lcyhwcm9iZXMuY2x1c3Rlci5hbGwpCikgJWluJSBtZXRhX2FsbCRpbnB1dFJlZ2lvbgoKbWV0YV9hbGxfcHJvYmVzIDwtIHByb2Jlcy5jbHVzdGVyLmFsbFtpZHhdICU+JQogIHVubGlzdCAlPiUKICBhcy5jaGFyYWN0ZXIoKSAlPiUKICB1bmlxdWUKCmxlbmd0aChtZXRhX2FsbF9wcm9iZXMpCmBgYAoKYGBge1J9CmFsbC5mb3JlZ3JvdW5kLnByb2JlcyA8LSBjKG1ldGFfc2lnX3Byb2JlcywgZm9yZWdyb3VuZC5wcm9iZXMpICU+JSB1bmlxdWUgIAphbGwuYmFja2dyb3VuZC5wcm9iZXMgPC0gYyhtZXRhX2FsbF9wcm9iZXMsIGJhY2tncm91bmQucHJvYmVzKSAlPiUgdW5pcXVlCmBgYAoKIyMjIFBhdGh3YXkgYW5hbHlzaXMgKGdlbmUgb250b2xvZ3kgYW5hbHlzaXMpCgpgYGB7UiBwYXRod2F5X2xpYnNfcmVnaW9uc19jcGdzX2JhY29uLG1lc3NhZ2UgPSBGQUxTRSwgcmVzdWx0cyA9ICJoaWRlIn0KbGlicmFyeShtaXNzTWV0aHlsKQpsaWJyYXJ5KElsbHVtaW5hSHVtYW5NZXRoeWxhdGlvbjQ1MGthbm5vLmlsbW4xMi5oZzE5KQpgYGAKCmBgYHtSIHBhdGh3YXlfcmVnaW9uc19jcGdzX2JhY29ufQojIyMgY29sbGVjdGlvbiA9ICJHTyIKYWxsX2dvIDwtIGdvbWV0aCgKICBzaWcuY3BnID0gYWxsLmZvcmVncm91bmQucHJvYmVzLAogIGFsbC5jcGcgPSBhbGwuYmFja2dyb3VuZC5wcm9iZXMsCiAgY29sbGVjdGlvbiA9ICJHTyIsCiAgZnJhY3QuY291bnRzID0gVFJVRQopCiMgdG9wR1NBKGFsbF9nbykKCmdvIDwtIG1pc3NNZXRoeWw6OjouZ2V0R08oKQpvdXQgPC0gZ2V0TWFwcGVkRW50cmV6SURzKAogIHNpZy5jcGcgPSBmb3JlZ3JvdW5kLnByb2JlcywKICBhbGwuY3BnID0gYmFja2dyb3VuZC5wcm9iZXMsCiAgYXJyYXkudHlwZSA9ICI0NTBLIgopCnNvcnRlZC5lZy5zaWcgPC0gIG91dCRzaWcuZWcKYGBgCgpgYGB7UiwgZXZhbCA9IEZBTFNFfQpnZW5lLmluZm8gPC0gVENHQWJpb2xpbmtzOjpnZXQuR1JDaC5iaW9NYXJ0KGdlbm9tZSA9ICJoZzE5IikKYGBgCgpgYGB7Un0KYWxsX2dvJGRlX2dlbmVzIDwtIHBseXI6OmFhcGx5KHJvd25hbWVzKGFsbF9nbyksMSwuZnVuID0gZnVuY3Rpb24oaWR4KXsKICBnZW5lLmluZm8kZXh0ZXJuYWxfZ2VuZV9uYW1lW2dlbmUuaW5mbyRlbnRyZXpnZW5lX2lkICVpbiUgaW50ZXJzZWN0KGdvJGlkTGlzdFtbaWR4XV0sc29ydGVkLmVnLnNpZyldICU+JQogICAgc29ydCAlPiUgdW5pcXVlICU+JSBwYXN0ZShjb2xsYXBzZSA9ICIsIikKfSkKCmFsbF9nb19vcmRlcmVkIDwtIGFsbF9nb1sKICBvcmRlcihhbGxfZ28kUC5ERSksCiAgXQpgYGAKCmBgYHtSLGV2YWwgPSBGQUxTRX0Kd3JpdGUuY3N2KAogIGFsbF9nb19vcmRlcmVkLAogIHBhc3RlMChkaXIucmVzdWx0LnBhdGh3YXksICJwYXRod2F5X3JlZ2lvbnNfYW5kX2NwZ3NfR09fcmVzdWx0c19hbGwuY3N2IiksCiAgcm93Lm5hbWVzID0gVFJVRQopCmBgYAoKYGBge1IsZXZhbCA9IFRSVUV9CmFsbF9nb19vcmRlcmVkLmJwIDwtIGFsbF9nb19vcmRlcmVkICU+JQogIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKCJHTyIpICU+JSAgIyBrZWVwIHJvdyBuYW1lcwogIGRwbHlyOjpmaWx0ZXIoT05UT0xPR1kgPT0gIkJQIikgJT4lCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXMoIkdPIikgICAjIGtlZXAgcm93IG5hbWVzCmFsbF9nb19vcmRlcmVkLmJwJEZEUiA8LSBwLmFkanVzdChhbGxfZ29fb3JkZXJlZC5icCRQLkRFLCJmZHIiKQpgYGAKCmBgYHtSLGV2YWwgPSBGQUxTRX0Kd3JpdGUuY3N2KAogIGFsbF9nb19vcmRlcmVkLmJwLAogIHBhc3RlMChkaXIucmVzdWx0LnBhdGh3YXksICJwYXRod2F5X3JlZ2lvbnNfYW5kX2NwZ3NfR09fcmVzdWx0c19CUF9OX3JhbmdlXzVfMjAwX2Zkcl9yZWNhbGMuY3N2IiksCiAgcm93Lm5hbWVzID0gVFJVRQopCmBgYAoKYGBge1J9CmFsbF9nb19vcmRlcmVkLmJwICAlPiUgCiAgZHBseXI6OmZpbHRlcihGRFIgPCAwLjA1KSAlPiUKICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9ICd0b3AnLAogICAgICAgICAgICAgICAgc3R5bGUgPSAiYm9vdHN0cmFwIiwKICAgICAgICAgICAgICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsCiAgICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdChzY3JvbGxYID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb20gPSAnQmZydGlwJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBJKCdjb2x2aXMnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleXMgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCksIAogICAgICAgICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgICAgICAgIGNhcHRpb24gPSAiR08gcmVzdWx0cyBCUCAoRkRSIDwgMC4wNSkiKQpgYGAKCmBgYHtSIGtlZ2dfcmVnaW9uc19jcGdzX2JhY29ufQojIyMgY29sbGVjdGlvbiA9ICJLRUdHIgphbGxfa2VnZyA8LSBnb21ldGgoCiAgc2lnLmNwZyA9IGFsbC5mb3JlZ3JvdW5kLnByb2JlcywKICBhbGwuY3BnID0gYWxsLmJhY2tncm91bmQucHJvYmVzLAogIGNvbGxlY3Rpb24gPSAiS0VHRyIsCiAgZnJhY3QuY291bnRzID0gVFJVRQopCiMgdG9wR1NBKGFsbF9rZWdnKQoKa2VnZyA8LSBtaXNzTWV0aHlsOjo6LmdldEtFR0coKQpvdXQgPC0gZ2V0TWFwcGVkRW50cmV6SURzKAogIHNpZy5jcGcgPSBmb3JlZ3JvdW5kLnByb2JlcywKICBhbGwuY3BnID0gYmFja2dyb3VuZC5wcm9iZXMsCiAgYXJyYXkudHlwZSA9ICI0NTBLIgopCnNvcnRlZC5lZy5zaWcgPC0gb3V0JHNpZy5lZwpgYGAKCmBgYHtSLCBldmFsID0gRkFMU0V9CmdlbmUuaW5mbyA8LSBUQ0dBYmlvbGlua3M6OmdldC5HUkNoLmJpb01hcnQoZ2Vub21lID0gImhnMTkiKQpgYGAKCmBgYHtSfQphbGxfa2VnZyRkZV9nZW5lcyA8LSBwbHlyOjphYXBseShyb3duYW1lcyhhbGxfa2VnZyksMSwuZnVuID0gZnVuY3Rpb24oaWR4KXsKICBnZW5lLmluZm8kZXh0ZXJuYWxfZ2VuZV9uYW1lW2dlbmUuaW5mbyRlbnRyZXpnZW5lX2lkICVpbiUgaW50ZXJzZWN0KGtlZ2ckaWRMaXN0W1tpZHhdXSxzb3J0ZWQuZWcuc2lnKV0gJT4lCiAgICBzb3J0ICU+JSB1bmlxdWUgJT4lIHBhc3RlKGNvbGxhcHNlID0gIiwiKQp9KQoKYWxsX2tlZ2dfb3JkZXJlZCA8LSBhbGxfa2VnZ1sKICBvcmRlcihhbGxfa2VnZyRQLkRFKSwKICBdCmBgYAoKYGBge1IsIGV2YWwgPSBGQUxTRX0Kd3JpdGUuY3N2KAogIGFsbF9rZWdnX29yZGVyZWQsCiAgcGFzdGUwKGRpci5yZXN1bHQucGF0aHdheSwgInBhdGh3YXlfcmVnaW9uc19hbmRfY3Bnc19LRUdHX3Jlc3VsdHNfYWxsLmNzdiIpLAogIHJvdy5uYW1lcyA9IFRSVUUKKQpgYGAKCmBgYHtSfQphbGxfa2VnZ19vcmRlcmVkIDwtIGFsbF9rZWdnX29yZGVyZWQgJT4lCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIktFR0ciKSAlPiUgICMga2VlcCByb3cgbmFtZXMKICB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcygiS0VHRyIpICAgICAgIyBrZWVwIHJvdyBuYW1lcwphbGxfa2VnZ19vcmRlcmVkJEZEUiA8LSBwLmFkanVzdChhbGxfa2VnZ19vcmRlcmVkJFAuREUsImZkciIpCmBgYAoKCmBgYHtSLCBldmFsID0gRkFMU0V9CndyaXRlLmNzdigKICBhbGxfa2VnZ19vcmRlcmVkLAogIHBhc3RlMChkaXIucmVzdWx0LnBhdGh3YXksICJwYXRod2F5X3JlZ2lvbnNfYW5kX2NwZ3NfS0VHR19yZXN1bHRzX05fcmFuZ2VfNV8yMDBfZmRyX3JlY2FsYy5jc3YiKSwKICByb3cubmFtZXMgPSBUUlVFCikKYGBgCgpgYGB7Un0KYWxsX2tlZ2dfb3JkZXJlZCAgJT4lIAogIGRwbHlyOjpmaWx0ZXIoUC5ERSA8IDAuMDUpICU+JQogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gJ3RvcCcsCiAgICAgICAgICAgICAgICBzdHlsZSA9ICJib290c3RyYXAiLAogICAgICAgICAgICAgICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbSA9ICdCZnJ0aXAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IEkoJ2NvbHZpcycpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKSwgCiAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJrZWdnIHJlc3VsdHMgKFAuREUgPCAwLjA1KSIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKYGBgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKCiMgTG9jdXMgb3ZlcmxhcCBhbmFseXNpcyAoTE9MQSkgb2YgRkRSIHNpZ25pZmljYW50IENwR3MgYWZ0ZXIgaW5mbGF0aW9uIGNvcnJlY3Rpb24gYnkgYmFjb24gbWV0aG9kCgojIyBGb3Igc2luZ2xlIGNwZyAKCmBgYHtSIExPTEFfc2luZ2xlX2JhY29uLCByZXN1bHRzID0gImhpZGUiLCBtZXNzYWdlID0gRkFMU0V9CiMjIyBDYWxsIGluIGRhdGFzZXRzCmNwZ19zaWdfbm9Dcm9zc0h5Yl9ub1Ntb2tlIDwtIHJlYWQuY3N2KAogIHBhc3RlMChkaXIuZGF0YSwiL21ldGFfYW5hbHlzaXNfc2luZ2xlX2NwZ19zaWdfbm9fY3Jvc3NIeWJfc21va2luZ19kZl9iYWNvbi5jc3YiKQopICNkaW06IDM3NTEgMjQKCmNwZ19hbGwgPC0gcmVhZC5jc3YoCiAgcGFzdGUwKGRpci5kYXRhLCIvbWV0YV9hbmFseXNpc19zaW5nbGVfY3BnX2JhY29uX2RmLmNzdiIpCikgI2RpbTogNDUwNzkzIDI0CgpjcGdfc2lnX2h5cGVyX25vQ3Jvc3NIeWJfbm9TbW9rZSA8LSBjcGdfc2lnX25vQ3Jvc3NIeWJfbm9TbW9rZSAlPiUKICBmaWx0ZXIoZXN0aW1hdGUuYmFjb24gPiAwKQpjcGdfc2lnX2h5cG9fbm9Dcm9zc0h5Yl9ub1Ntb2tlIDwtIGNwZ19zaWdfbm9Dcm9zc0h5Yl9ub1Ntb2tlICU+JQogIGZpbHRlcihlc3RpbWF0ZS5iYWNvbiA8IDApCgojIyMgVHVybiBpbnB1dCByZWdpb25zIGludG8gR1JhbmdlcwpsaWJyYXJ5KEdlbm9taWNSYW5nZXMpCmNwZ19zaWdfbm9Dcm9zc0h5Yl9ub1Ntb2tlX2dyIDwtIG1ha2VHUmFuZ2VzRnJvbURhdGFGcmFtZSgKICBjcGdfc2lnX25vQ3Jvc3NIeWJfbm9TbW9rZQopCmNwZ19zaWdfaHlwZXJfbm9Dcm9zc0h5Yl9ub1Ntb2tlX2dyIDwtIG1ha2VHUmFuZ2VzRnJvbURhdGFGcmFtZSgKICBjcGdfc2lnX2h5cGVyX25vQ3Jvc3NIeWJfbm9TbW9rZQopCmNwZ19zaWdfaHlwb19ub0Nyb3NzSHliX25vU21va2VfZ3IgPC0gbWFrZUdSYW5nZXNGcm9tRGF0YUZyYW1lKAogIGNwZ19zaWdfaHlwb19ub0Nyb3NzSHliX25vU21va2UKKQpjcGdfYWxsX2dyIDwtIG1ha2VHUmFuZ2VzRnJvbURhdGFGcmFtZShjcGdfYWxsKQpgYGAKCmBgYHtSIExPTEFfc2luZ2xlX2luaXRfYmFjb24sIHJlc3VsdHMgPSAiaGlkZSIsIG1lc3NhZ2UgPSBGQUxTRX0KcmVnaW9uREJfaGcxOSA8LSBsb2FkUmVnaW9uREIoIi4uL0xPTEFDb3JlL2hnMTkiKQoKIyMjIEFsbCBzaWcuIGNwZ3MKbG9jUmVzdWx0cyA8LSBydW5MT0xBKAogIHVzZXJTZXRzID0gY3BnX3NpZ19ub0Nyb3NzSHliX25vU21va2VfZ3IsCiAgdXNlclVuaXZlcnNlID0gY3BnX2FsbF9nciwKICByZWdpb25EQiA9IHJlZ2lvbkRCX2hnMTksCiAgY29yZXMgPSAxCikKCmxvY1Jlc3VsdHMkcFZhbHVlIDwtIDEwXigtbG9jUmVzdWx0cyRwVmFsdWVMb2cpCmBgYAoKYGBge1IsIGV2YWwgPSBGQUxTRX0KbG9jUmVzdWx0c19vcmRlcmVkIDwtIGxvY1Jlc3VsdHNbLGMoMTozLCAyNCwgNDoyMyldCndyaXRlLmNzdigKICBsb2NSZXN1bHRzX29yZGVyZWQsCiAgcGFzdGUwKGRpci5yZXN1bHQubG9sYSwgImNwZ3NfYWxsX0xPTEFfcmVzdWx0cy5jc3YiKSwKICByb3cubmFtZXMgPSBGQUxTRQopCmBgYAoKYGBge1J9CmxvY1Jlc3VsdHMgICAlPiUKICBkcGx5cjo6ZmlsdGVyKHFWYWx1ZSA8IDAuMDUgJiBjb2xsZWN0aW9uID09ICJlbmNvZGVfdGZicyIpICU+JQogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gJ3RvcCcsCiAgICAgICAgICAgICAgICBzdHlsZSA9ICJib290c3RyYXAiLAogICAgICAgICAgICAgICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gSSgnY29sdmlzJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCksCiAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJzaW5nbGUgY3BnIGFsbCBMT0xBIHJlc3VsdHMiKQpgYGAKCmBgYHtSIExPTEFfc2luZ2xlX3J1bl9iYWNvbiwgcmVzdWx0cyA9ICJoaWRlIiwgbWVzc2FnZSA9IEZBTFNFLCBpbmNsdWRlID0gRkFMU0UsIGV2YWwgPSBGQUxTRX0KCiMjIyBBbGwgaHlwZXIgY3Bncwpsb2NSZXN1bHRzIDwtIHJ1bkxPTEEoCiAgdXNlclNldHMgPSBjcGdfc2lnX2h5cGVyX25vQ3Jvc3NIeWJfbm9TbW9rZV9nciwKICB1c2VyVW5pdmVyc2UgPSBjcGdfYWxsX2dyLAogIHJlZ2lvbkRCID0gcmVnaW9uREJfaGcxOSwKICBjb3JlcyA9IDEKKQoKbG9jUmVzdWx0cyRwVmFsdWUgPC0gMTBeKC1sb2NSZXN1bHRzJHBWYWx1ZUxvZykKYGBgCgpgYGB7UiwgZXZhbCA9IEZBTFNFfQpsb2NSZXN1bHRzX29yZGVyZWQgPC0gbG9jUmVzdWx0c1ssYygxOjMsIDI0LCA0OjIzKV0KCndyaXRlLmNzdigKICBsb2NSZXN1bHRzX29yZGVyZWQsCiAgcGFzdGUwKGRpci5yZXN1bHQubG9sYSwgImNwZ3NfaHlwZXJfTE9MQV9yZXN1bHRzLmNzdiIpLAogIHJvdy5uYW1lcyA9IEZBTFNFCikKYGBgCgpgYGB7UiwgaW5jbHVkZSA9IEZBTFNFLCBldmFsID0gRkFMU0V9CmxvY1Jlc3VsdHMgICAlPiUKICBkcGx5cjo6ZmlsdGVyKHFWYWx1ZSA8IDAuMDUpICU+JQogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gJ3RvcCcsCiAgICAgICAgICAgICAgICBzdHlsZSA9ICJib290c3RyYXAiLAogICAgICAgICAgICAgICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gSSgnY29sdmlzJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCksCiAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJzaW5nbGUgY3BnIGh5cGVyIExPTEEgcmVzdWx0cyIpCmBgYAoKYGBge1IgTE9MQV9zaW5nbGVfcmVzX2JhY29uLCByZXN1bHRzID0gImhpZGUiLCBtZXNzYWdlID0gRkFMU0UsIGluY2x1ZGUgPSBGQUxTRSwgZXZhbCA9IEZBTFNFfQoKIyMjIEFsbCBoeXBvIGNwZ3MKbG9jUmVzdWx0cyA8LSBydW5MT0xBKAogIHVzZXJTZXRzID0gY3BnX3NpZ19oeXBvX25vQ3Jvc3NIeWJfbm9TbW9rZV9nciwKICB1c2VyVW5pdmVyc2UgPSBjcGdfYWxsX2dyLAogIHJlZ2lvbkRCID0gcmVnaW9uREJfaGcxOSwKICBjb3JlcyA9IDEKKQoKbG9jUmVzdWx0cyRwVmFsdWUgPC0gMTBeKC1sb2NSZXN1bHRzJHBWYWx1ZUxvZykKCmBgYAoKYGBge1IsIGV2YWwgPSBGQUxTRX0KbG9jUmVzdWx0c19vcmRlcmVkIDwtIGxvY1Jlc3VsdHNbLGMoMTozLCAyNCwgNDoyMyldCgp3cml0ZS5jc3YoCiAgbG9jUmVzdWx0c19vcmRlcmVkLAogIHBhc3RlMChkaXIucmVzdWx0LmxvbGEsICJjcGdzX2h5cG9fTE9MQV9yZXN1bHRzLmNzdiIpLAogIHJvdy5uYW1lcyA9IEZBTFNFCikKYGBgCgpgYGB7UiwgaW5jbHVkZSA9IEZBTFNFLCBldmFsID0gRkFMU0V9CmxvY1Jlc3VsdHMgICAlPiUKICBkcGx5cjo6ZmlsdGVyKHFWYWx1ZSA8IDAuMDUpICU+JQogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gJ3RvcCcsCiAgICAgICAgICAgICAgICBzdHlsZSA9ICJib290c3RyYXAiLAogICAgICAgICAgICAgICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gSSgnY29sdmlzJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCksCiAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJzaW5nbGUgY3BnIGh5cG8gTE9MQSByZXN1bHRzIikKYGBgCgoKIyBFbnJpY2htZW50IGFuYWx5c2lzIG9mIGdlbm9tZS13aWRlIHNpZ25pZmljYW50IENwR3MgKHAgPCAyLjRFLTcpIGFmdGVyIGluZmxhdGlvbiBjb3JyZWN0aW9uIGJ5IEJhY29uIG1ldGhvZAoKYGBge1J9CmRpci5yZXN1bHQubG9sYSA8LSBmaWxlLnBhdGgoImJhY29uXzJfNF9taW51c183L2xvbGEvIikKZGlyLnJlc3VsdC5wYXRod2F5IDwtIGZpbGUucGF0aCgiYmFjb25fMl80X21pbnVzXzcvcmVzdWx0c19wYXRod2F5LyIpCmBgYAoKIyMgRm9yIHNpbmdsZSBjcGdzCgojIyMgIEdldCByZXN1bHRzCgpgYGB7Un0KIyMjIEZvcmVncm91bmQKc2luZ2xlLmNwZy5yZXN1bHRzIDwtIHJlYWRyOjpyZWFkX2NzdigKICBwYXN0ZTAoZGlyLmRhdGEsIm1ldGFfYW5hbHlzaXNfc2luZ2xlX2NwZ19iYWNvbl9kZi5jc3YiKSwKICBjb2xfdHlwZXMgPSByZWFkcjo6Y29scygpCikKc2luZ2xlLmNwZy5zaWcucmVzdWx0cyA8LSByZWFkcjo6cmVhZF9jc3YoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICBwYXN0ZTAoZGlyLmRhdGEsIm1ldGFfYW5hbHlzaXNfc2luZ2xlX2NwZ19zaWdfbm9fY3Jvc3NIeWJfc21va2luZ19kZl9iYWNvbl8yXzRfbWludXNfNy5jc3YiKSwKICBjb2xfdHlwZXMgPSByZWFkcjo6Y29scygpCikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgpmb3JlZ3JvdW5kLnByb2JlcyA8LSBzaW5nbGUuY3BnLnNpZy5yZXN1bHRzICU+JSBwdWxsKGNwZykgJT4lIGFzLmNoYXJhY3Rlcgpmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0IDwtIHNpbmdsZS5jcGcuc2lnLnJlc3VsdHMgJT4lIGZpbHRlcihlc3RpbWF0ZS5iYWNvbiA8IDApICU+JSBwdWxsKGNwZykgJT4lIGFzLmNoYXJhY3Rlcgpmb3JlZ3JvdW5kLnByb2Jlcy5wb3MuZXN0IDwtIHNpbmdsZS5jcGcuc2lnLnJlc3VsdHMgICU+JSBmaWx0ZXIoZXN0aW1hdGUuYmFjb24gPiAwKSAlPiUgcHVsbChjcGcpICU+JSBhcy5jaGFyYWN0ZXIKbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzKQoKIyMjIEJhY2tncm91bmQKYmFja2dyb3VuZC5wcm9iZXMgPC0gc2luZ2xlLmNwZy5yZXN1bHRzICAlPiUgcHVsbChjcGcpICU+JSBhcy5jaGFyYWN0ZXIgCmxlbmd0aChiYWNrZ3JvdW5kLnByb2JlcykKYGBgCgoKIyMjIEFubm90YXRpb24KYGBge1J9CmwucHJvYmVzIDwtIGxpc3QoCiAgICBiYWNrZ3JvdW5kLnByb2JlcywKICAgIGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QsCiAgICBmb3JlZ3JvdW5kLnByb2Jlcy5wb3MuZXN0CikKCm5hbWVzKGwucHJvYmVzKSA8LSBjKAogICAgcGFzdGUwKCJFdmFsdWF0ZWQgcHJvYmVzIChuID0gIixsZW5ndGgoYmFja2dyb3VuZC5wcm9iZXMpLCIpIiksCiAgICBwYXN0ZTAoIlNpZ25pZmljYW50IHcvIE5lZ2F0aXZlIGVzdGltYXRlIChuID0gIixsZW5ndGgoZm9yZWdyb3VuZC5wcm9iZXMubmVnLmVzdCksIikiKSwKICAgIHBhc3RlMCgiU2lnbmlmaWNhbnQgdy8gUG9zaXRpdmUgZXN0aW1hdGUgKG4gPSAiLGxlbmd0aChmb3JlZ3JvdW5kLnByb2Jlcy5wb3MuZXN0KSwiKSIpCikKCmFsbC5wbG90IDwtIGNwR3NHZW5vbWljRmVhdHVyZXMobC5wcm9iZXMpCnBsb3Quc2luZ2xlLmNwZyA8LSBhbGwucGxvdCRwbG90ICsgZ2d0aXRsZSgiU2luZ2xlIGNwZyBtZXRhLWFuYWx5c2lzIHByb2JlcyIpIApwbG90LnNpbmdsZS5jcGcKZ2dzYXZlKAogICAgcGxvdCA9IHBsb3Quc2luZ2xlLmNwZywKICAgIHdpZHRoID0gOSwgCiAgICBmaWxlbmFtZSA9ICJiYWNvbl8yXzRfbWludXNfNy9wbG90c19lbnJpY2htZW50X2FuYWx5c2lzL21ldGFfYW5hbHlzaXNfc2luZ2xlX2NwZ19lbnJpY2htZW50LnBkZiIKKQpgYGAKCgpgYGB7UiwgbWVzc2FnZSA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CnBsb3QuY2hybS5oeXBvIDwtIGNwR3NFbnJpY2htZW50KAogIGZnLnByb2JlcyA9IGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QsCiAgYmcucHJvYmVzID0gYmFja2dyb3VuZC5wcm9iZXMsCiAgZW5yaWNobWVudC50eXBlID0gImlzbGFuZCIsCiAgZmcubGFiZWwgPSBwYXN0ZTAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBOZWdhdGl2ZSBlc3RpbWF0ZSAobiA9ICIsCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QpKSwKICBiZy5sYWJlbCA9IHBhc3RlMCgiRXZhbHVhdGVkIHByb2JlcyAobiA9ICIsCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKGJhY2tncm91bmQucHJvYmVzKSkKICApCgpwbG90LmNocm0uaHlwZXIgPC0gY3BHc0VucmljaG1lbnQoCiAgZmcucHJvYmVzID0gZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdCwKICBiZy5wcm9iZXMgPSBiYWNrZ3JvdW5kLnByb2JlcywKICBlbnJpY2htZW50LnR5cGUgPSAiaXNsYW5kIiwKICBmZy5sYWJlbCA9IHBhc3RlMCgiU2lnbmlmaWNhbnQgcHJvYmVzIHcvIFBvc2l0aXZlIGVzdGltYXRlIChuID0gIiwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgoZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdCkpLAogIGJnLmxhYmVsID0gcGFzdGUwKCJFdmFsdWF0ZWQgcHJvYmVzIChuID0gIiwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgoYmFja2dyb3VuZC5wcm9iZXMpKQogICkKCnRhYi5pc2xhbmQgPC0gY2JpbmQoCiAgIGRhdGEuZnJhbWUoCiAgICAiTWV0YS1BbmFseXNpcyIgPSBjKAogICAgICByZXAoIlNpbmdsZSBDcEciLG5yb3cocGxvdC5jaHJtLmh5cGVyJHRhYmxlKSArIG5yb3cocGxvdC5jaHJtLmh5cG8kdGFibGUpKQogICAgKSwKICAgICJGb3JlZ3JvdW5kIHByb2JlcyIgPSBjKAogICAgICByZXAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBQb3NpdGl2ZSBlc3RpbWF0ZSIsbnJvdyhwbG90LmNocm0uaHlwZXIkdGFibGUpKSwKICAgICAgcmVwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gTmVnYXRpdmUgZXN0aW1hdGUiLG5yb3cocGxvdC5jaHJtLmh5cG8kdGFibGUpKQogICAgKSwKICAgICJFbnJpY2htZW50IGFuYWx5c2lzIiA9IGMoCiAgICAgIHJlcCgiUmVsYXRpb25fdG9fSXNsYW5kIixucm93KHBsb3QuY2hybS5oeXBlciR0YWJsZSkgKyBucm93KHBsb3QuY2hybS5oeXBvJHRhYmxlKSkKICAgICkKICApLAogIHJiaW5kKHBsb3QuY2hybS5oeXBlciR0YWJsZVssYygxLDYsNyldLAogICAgICAgIHBsb3QuY2hybS5oeXBvJHRhYmxlWyxjKDEsNiw3KV0pCikKdGFiLmlzbGFuZCAlPiUgCiAgRFQ6OmRhdGF0YWJsZSgKICAgIGZpbHRlciA9ICd0b3AnLAogICAgc3R5bGUgPSAiYm9vdHN0cmFwIiwKICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsCiAgICBvcHRpb25zID0gbGlzdChzY3JvbGxYID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICBkb20gPSAnQmZydGlwJywKICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBJKCdjb2x2aXMnKSwKICAgICAgICAgICAgICAgICAgIGtleXMgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCkKICApCmBgYAoKCmBgYHtSLCBtZXNzYWdlID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KcGxvdC5jaHJtLmh5cG8gPC0gY3BHc0VucmljaG1lbnQoCiAgZmcucHJvYmVzID0gZm9yZWdyb3VuZC5wcm9iZXMubmVnLmVzdCwKICBiZy5wcm9iZXMgPSBiYWNrZ3JvdW5kLnByb2JlcywKICBlbnJpY2htZW50LnR5cGUgPSAiZ2VuZSIsCiAgZmcubGFiZWwgPSBwYXN0ZTAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBOZWdhdGl2ZSBlc3RpbWF0ZSAobiA9ICIsCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzLm5lZy5lc3QpKSwKICBiZy5sYWJlbCA9IHBhc3RlMCgiRXZhbHVhdGVkIHByb2JlcyAobiA9ICIsCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKGJhY2tncm91bmQucHJvYmVzKSkpCgpwbG90LmNocm0uaHlwZXIgPC0gY3BHc0VucmljaG1lbnQoCiAgZmcucHJvYmVzID0gZm9yZWdyb3VuZC5wcm9iZXMucG9zLmVzdCwKICBiZy5wcm9iZXMgPSBiYWNrZ3JvdW5kLnByb2JlcywKICBlbnJpY2htZW50LnR5cGUgPSAiZ2VuZSIsCiAgZmcubGFiZWwgPSBwYXN0ZTAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBQb3NpdGl2ZSBlc3RpbWF0ZSAobiA9ICIsCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzLnBvcy5lc3QpKSwKICBiZy5sYWJlbCA9IHBhc3RlMCgiRXZhbHVhdGVkIHByb2JlcyAobiA9ICIsCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKGJhY2tncm91bmQucHJvYmVzKSkpCgp0YWIuZ2VuZSA8LSBjYmluZCgKIGRhdGEuZnJhbWUoCiAgICAiTWV0YS1BbmFseXNpcyIgPSBjKAogICAgICByZXAoIlNpbmdsZSBDcEciLG5yb3cocGxvdC5jaHJtLmh5cGVyJHRhYmxlKSArIG5yb3cocGxvdC5jaHJtLmh5cG8kdGFibGUpKQogICAgKSwKICAgICJGb3JlZ3JvdW5kIHByb2JlcyIgPSBjKAogICAgICByZXAoIlNpZ25pZmljYW50IHByb2JlcyB3LyBQb3NpdGl2ZSBlc3RpbWF0ZSIsbnJvdyhwbG90LmNocm0uaHlwZXIkdGFibGUpKSwKICAgICAgcmVwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gTmVnYXRpdmUgZXN0aW1hdGUiLG5yb3cocGxvdC5jaHJtLmh5cG8kdGFibGUpKQogICAgKSwKICAgICJFbnJpY2htZW50IGFuYWx5c2lzIiA9IGMoCiAgICAgIHJlcCgiVUNTQ19SZWZHZW5lX0dyb3VwX2hpZXJhcmNoeSIsbnJvdyhwbG90LmNocm0uaHlwZXIkdGFibGUpICsgbnJvdyhwbG90LmNocm0uaHlwbyR0YWJsZSkpCiAgICApCiAgKSwKICByYmluZChwbG90LmNocm0uaHlwZXIkdGFibGVbLGMoMSw2LDcpXSwKICAgICAgICBwbG90LmNocm0uaHlwbyR0YWJsZVssYygxLDYsNyldKQopCnRhYi5nZW5lICU+JSAKICBEVDo6ZGF0YXRhYmxlKAogICAgZmlsdGVyID0gJ3RvcCcsCiAgICBzdHlsZSA9ICJib290c3RyYXAiLAogICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgIGRvbSA9ICdCZnJ0aXAnLAogICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IEkoJ2NvbHZpcycpLAogICAgICAgICAgICAgICAgICAga2V5cyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKQogICkKYGBgCgoKIyMjIENocm9NSE1NCmBgYHtSfQpmaWxlIDwtIHBhc3RlMCgiaHR0cHM6Ly9lZ2cyLnd1c3RsLmVkdS9yb2FkbWFwL2RhdGEvYnlGaWxlVHlwZS9jaHJvbWhtbVNlZ21lbnRhdGlvbnMiLAogICAgICAgICAgICAgICAiL0NobW1Nb2RlbHMvY29yZU1hcmtzL2pvaW50TW9kZWwvZmluYWwvRTA3M18xNV9jb3JlTWFya3Nfc2VnbWVudHMuYmVkIikKaWYoIWZpbGUuZXhpc3RzKCBiYXNlbmFtZShmaWxlKSkpIGRvd25sb2FkZXI6OmRvd25sb2FkKGZpbGUsIGRlc3RmaWxlID0gYmFzZW5hbWUoZmlsZSkpCkNobW1Nb2RlbHMgPC0gcmVhZHI6OnJlYWRfdHN2KAogIGJhc2VuYW1lKGZpbGUpLAogIGNvbF9uYW1lcyA9IEZBTFNFLAogIGNvbF90eXBlcyA9IHJlYWRyOjpjb2xzKCkKKQpjb2xuYW1lcyhDaG1tTW9kZWxzKSA8LSBjKCJjaHIiLCJzdGFydCIsImVuZCIsInN0YXRlIikKc3RhdGVzIDwtIHJlYWRyOjpyZWFkX2NzdigKICAiLi4vLi4vLi4vRE5BbV9STkEvZGF0YS9jaHJvbUhNTV9sYWJlbHMuY3N2IiwKICBjb2xfbmFtZXMgPSBGQUxTRSwKICBjb2xfdHlwZXMgPSByZWFkcjo6Y29scygpCikKc3RhdGVzJFgxIDwtIHBhc3RlMCgiRSIsc3RhdGVzJFgxKQpDaG1tTW9kZWxzJHN0YXRlIDwtIHN0YXRlcyRYM1ttYXRjaChDaG1tTW9kZWxzJHN0YXRlLHN0YXRlcyRYMSldCkNobW1Nb2RlbHMuZ3IgPC0gbWFrZUdSYW5nZXNGcm9tRGF0YUZyYW1lKENobW1Nb2RlbHMsa2VlcC5leHRyYS5jb2x1bW5zID0gVFJVRSkKYGBgCgpgYGB7UiwgaW5jbHVkZSA9IEZBTFNFfQpwbG90LmNocm0uaHlwbyA8LSBjcEdzRW5yaWNobWVudCgKICBmZy5wcm9iZXMgPSBmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0LAogIGJnLnByb2JlcyA9IGJhY2tncm91bmQucHJvYmVzLAogIGFubm90YXRpb24uZ3IgPSBDaG1tTW9kZWxzLmdyLAogIGZnLmxhYmVsID0gcGFzdGUwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gTmVnYXRpdmUgZXN0aW1hdGUgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0KSwiKSIpLAogIGJnLmxhYmVsID0gcGFzdGUwKCJFdmFsdWF0ZWQgcHJvYmVzIChuID0gIiwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgoYmFja2dyb3VuZC5wcm9iZXMpLCIpIiksCiAgZW5yaWNobWVudC50eXBlID0gImN1c3RvbWl6ZWQiLAogIHBsb3QuZmlsZW5hbWUgPSAiYmFjb25fMl80X21pbnVzXzcvcGxvdHNfZW5yaWNobWVudF9hbmFseXNpcy9tZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfbmVnX2VzdGltYXRlX2Nocm9tSE1NX3N0YXRlcy5wbmciCikKCnBsb3QuY2hybS5oeXBvJHBsb3QKCnBsb3QuY2hybS5oeXBlciA8LSBjcEdzRW5yaWNobWVudCgKICBmZy5wcm9iZXMgPSBmb3JlZ3JvdW5kLnByb2Jlcy5wb3MuZXN0LAogIGJnLnByb2JlcyA9IGJhY2tncm91bmQucHJvYmVzLAogIGFubm90YXRpb24uZ3IgPSBDaG1tTW9kZWxzLmdyLAogIGZnLmxhYmVsID0gcGFzdGUwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gUG9zaXRpdmUgZXN0aW1hdGUgKG4gPSAiLAogICAgICAgICAgICAgICAgICAgIGxlbmd0aChmb3JlZ3JvdW5kLnByb2Jlcy5wb3MuZXN0KSwiKSIpLAogIGJnLmxhYmVsID0gcGFzdGUwKCJFdmFsdWF0ZWQgcHJvYmVzIChuID0gIiwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgoYmFja2dyb3VuZC5wcm9iZXMpLCIpIiksCiAgZW5yaWNobWVudC50eXBlID0gImN1c3RvbWl6ZWQiLAogIHBsb3QuZmlsZW5hbWUgPSAiYmFjb25fMl80X21pbnVzXzcvcGxvdHNfZW5yaWNobWVudF9hbmFseXNpcy9tZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfcG9zX2VzdF9jaHJvbUhNTV9zdGF0ZXMucG5nIikKcGxvdC5jaHJtLmh5cGVyJHBsb3QKYGBgCgpgYGB7Un0KbC5wcm9iZXMgPC0gbGlzdCgKICAgIGJhY2tncm91bmQucHJvYmVzLAogICAgZm9yZWdyb3VuZC5wcm9iZXMubmVnLmVzdCwKICAgIGZvcmVncm91bmQucHJvYmVzLnBvcy5lc3QKKQoKbmFtZXMobC5wcm9iZXMpIDwtIGMoCiAgICBwYXN0ZTAoIkV2YWx1YXRlZCBwcm9iZXMgKG4gPSAiLGxlbmd0aChiYWNrZ3JvdW5kLnByb2JlcyksIikiKSwKICAgIHBhc3RlMCgiU2lnbmlmaWNhbnQgdy8gTmVnYXRpdmUgZXN0aW1hdGUgKG4gPSAiLGxlbmd0aChmb3JlZ3JvdW5kLnByb2Jlcy5uZWcuZXN0KSwiKSIpLAogICAgcGFzdGUwKCJTaWduaWZpY2FudCB3LyBQb3NpdGl2ZSBlc3RpbWF0ZSAobiA9ICIsbGVuZ3RoKGZvcmVncm91bmQucHJvYmVzLnBvcy5lc3QpLCIpIikKKQoKc2luZ2xlLmNwZy5wbG90IDwtIGNwR3NHZW5vbWljRmVhdHVyZXMoCiAgbC5wcm9iZXMsCiAgYW5ub3RhdGlvbi5nciA9IENobW1Nb2RlbHMuZ3IsCiAgcGxvdC53aWR0aCA9IDEyLAogIHBsb3QudGl0bGUgPSAiU2luZ2xlIGNwZyBtZXRhLWFuYWx5c2lzIHByb2Jlc1xuQ2hyb01ITU06IEUwNzMgLSAxNSBjb3JlTWFya3Mgc2VnbWVudHMiLAogIGVucmljaG1lbnQudHlwZSA9ICJjdXN0b21pemVkIiwKICBwbG90LmZpbGVuYW1lID0gImJhY29uXzJfNF9taW51c183L3Bsb3RzX2VucmljaG1lbnRfYW5hbHlzaXMvbWV0YV9hbmFseXNpc19zaW5nbGVfY3BnX2Nocm9tSE1NX3N0YXRlcy5wZGYiLAopCnNpbmdsZS5jcGcucGxvdCRwbG90CmBgYAoKCmBgYHtSfQp0YWIuY2hybSA8LSBjYmluZCgKICBkYXRhLmZyYW1lKAogICAgIk1ldGEtQW5hbHlzaXMiID0gYygKICAgICAgcmVwKCJTaW5nbGUgQ3BHIixucm93KHBsb3QuY2hybS5oeXBlciR0YWJsZSkgKyBucm93KHBsb3QuY2hybS5oeXBvJHRhYmxlKSkKICAgICksCiAgICAiRm9yZWdyb3VuZCBwcm9iZXMiID0gYygKICAgICAgcmVwKCJTaWduaWZpY2FudCBwcm9iZXMgdy8gUG9zaXRpdmUgZXN0aW1hdGUiLG5yb3cocGxvdC5jaHJtLmh5cGVyJHRhYmxlKSksCiAgICAgIHJlcCgiU2lnbmlmaWNhbnQgcHJvYmVzIHcvIE5lZ2F0aXZlIGVzdGltYXRlIixucm93KHBsb3QuY2hybS5oeXBvJHRhYmxlKSkKICAgICksCiAgICAiRW5yaWNobWVudCBhbmFseXNpcyIgPSBjKAogICAgICByZXAoIkNocm9NSE1NOiBFMDczIixucm93KHBsb3QuY2hybS5oeXBlciR0YWJsZSkgKyBucm93KHBsb3QuY2hybS5oeXBvJHRhYmxlKSkKICAgICkKICApLAogIHJiaW5kKHBsb3QuY2hybS5oeXBlciR0YWJsZVssYygxLDYsNyldLAogICAgICAgIHBsb3QuY2hybS5oeXBvJHRhYmxlWyxjKDEsNiw3KV0pCikKdGFiLmNocm0gJT4lIAogIERUOjpkYXRhdGFibGUoCiAgICBmaWx0ZXIgPSAndG9wJywKICAgIHN0eWxlID0gImJvb3RzdHJhcCIsCiAgICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLAogICAgb3B0aW9ucyA9IGxpc3Qoc2Nyb2xsWCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICBidXR0b25zID0gSSgnY29sdmlzJyksCiAgICAgICAgICAgICAgICAgICBrZXlzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gMTApCiAgKQpgYGAKCgojIFBhdGh3YXkgYW5hbHlzaXMgb2YgZ2Vub21lLXdpZGUgc2lnbmlmaWNhbnQgQ3BHcyAocCA8IDIuNEUtNykgYWZ0ZXIgaW5mbGF0aW9uIGNvcnJlY3Rpb24gYnkgQmFjb24gbWV0aG9kCgojIyBGb3IgcmVnaW9ucyArIHNpbmdsZSBjcGdzCgojIyMgR2V0IHByb2JlcwoKIyMjIEdldCBwcm9iZXMgZnJvbSByZWdpb25zCmBgYHtSfQojIyMgQ2FsbCBpbiBkYXRhc2V0cwptZXRhX3NpZyA8LSByZWFkLmNzdihkaXIoZGlyLnJlc3VsdC5jb21wLHBhdHRlcm4gPSAibm8uKmNzdiIsZnVsbC5uYW1lcyA9IFRSVUUpKQoKbWV0YV9hbGwgPC0gcmVhZC5jc3YoCiAgcGFzdGUwKGRpci5yZXN1bHQubWV0YS5hbmFseXNpcywgIm1ldGFfYW5hbHlzaXNfQUxMX2RmLmNzdiIpCikgI2RpbTogNDAwMTAgNDEKYGBgCgpgYGB7Un0KcHJvYmVzLmNsdXN0ZXIuYWxsIDwtIGNvTWV0aERNUjo6Z2V0UHJlZGVmaW5lZENsdXN0ZXIoCiAgYXJyYXlUeXBlID0gIjQ1MGsiLAogIGNsdXN0ZXJUeXBlID0gInJlZ2lvbnMiCikKCiMjIyBnZXQgYWxsIGNwcyBpbiBtZXRhX3NpZyBpbnB1dCByZWdpb25zCmlkeCA8LSBnc3ViKAogICI0NTBrX0dlbmVfM18yMDAufDQ1MGtfSW50ZXJHZW5lXzNfMjAwLiIsIiIsbmFtZXMocHJvYmVzLmNsdXN0ZXIuYWxsKQopICVpbiUgbWV0YV9zaWckaW5wdXRSZWdpb24KCm1ldGFfc2lnX3Byb2JlcyA8LSBwcm9iZXMuY2x1c3Rlci5hbGxbaWR4XSAlPiUKICB1bmxpc3QgJT4lCiAgYXMuY2hhcmFjdGVyKCkgJT4lCiAgdW5pcXVlCmxlbmd0aChtZXRhX3NpZ19wcm9iZXMpCgojIyMgZ2V0IGFsbCBjcHMgaW4gbWV0YV9hbGwgaW5wdXQgcmVnaW9ucwppZHggPC0gZ3N1YigKICAiNDUwa19HZW5lXzNfMjAwLnw0NTBrX0ludGVyR2VuZV8zXzIwMC4iLCIiLG5hbWVzKHByb2Jlcy5jbHVzdGVyLmFsbCkKKSAlaW4lIG1ldGFfYWxsJGlucHV0UmVnaW9uCgptZXRhX2FsbF9wcm9iZXMgPC0gcHJvYmVzLmNsdXN0ZXIuYWxsW2lkeF0gJT4lCiAgdW5saXN0ICU+JQogIGFzLmNoYXJhY3RlcigpICU+JQogIHVuaXF1ZQoKbGVuZ3RoKG1ldGFfYWxsX3Byb2JlcykKYGBgCgpgYGB7Un0KYWxsLmZvcmVncm91bmQucHJvYmVzIDwtIGMobWV0YV9zaWdfcHJvYmVzLCBmb3JlZ3JvdW5kLnByb2JlcykgJT4lIHVuaXF1ZSAgCmFsbC5iYWNrZ3JvdW5kLnByb2JlcyA8LSBjKG1ldGFfYWxsX3Byb2JlcywgYmFja2dyb3VuZC5wcm9iZXMpICU+JSB1bmlxdWUKYGBgCgojIyMgUGF0aHdheSBhbmFseXNpcyAoZ2VuZSBvbnRvbG9neSBhbmFseXNpcykKCmBgYHtSIHBhdGh3YXlfbGlic19yZWdpb25zX2NwZ3MsbWVzc2FnZSA9IEZBTFNFLCByZXN1bHRzID0gImhpZGUifQpsaWJyYXJ5KG1pc3NNZXRoeWwpCmxpYnJhcnkoSWxsdW1pbmFIdW1hbk1ldGh5bGF0aW9uNDUwa2Fubm8uaWxtbjEyLmhnMTkpCmBgYAoKYGBge1IgcGF0aHdheV9yZWdpb25zX2NwZ3N9CiMjIyBjb2xsZWN0aW9uID0gIkdPIgphbGxfZ28gPC0gZ29tZXRoKAogIHNpZy5jcGcgPSBhbGwuZm9yZWdyb3VuZC5wcm9iZXMsCiAgYWxsLmNwZyA9IGFsbC5iYWNrZ3JvdW5kLnByb2JlcywKICBjb2xsZWN0aW9uID0gIkdPIiwKICBmcmFjdC5jb3VudHMgPSBUUlVFCikKIyB0b3BHU0EoYWxsX2dvKQoKZ28gPC0gbWlzc01ldGh5bDo6Oi5nZXRHTygpCm91dCA8LSBnZXRNYXBwZWRFbnRyZXpJRHMoc2lnLmNwZyA9IGZvcmVncm91bmQucHJvYmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGFsbC5jcGcgPSBiYWNrZ3JvdW5kLnByb2JlcywKICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheS50eXBlID0gIjQ1MEsiKQpzb3J0ZWQuZWcuc2lnIDwtICBvdXQkc2lnLmVnCmBgYAoKYGBge1IsIGV2YWwgPSBGQUxTRX0KZ2VuZS5pbmZvIDwtIFRDR0FiaW9saW5rczo6Z2V0LkdSQ2guYmlvTWFydChnZW5vbWUgPSAiaGcxOSIpCmBgYAoKYGBge1J9CmFsbF9nbyRkZV9nZW5lcyA8LSBwbHlyOjphYXBseShyb3duYW1lcyhhbGxfZ28pLDEsLmZ1biA9IGZ1bmN0aW9uKGlkeCl7CiAgZ2VuZS5pbmZvJGV4dGVybmFsX2dlbmVfbmFtZVtnZW5lLmluZm8kZW50cmV6Z2VuZV9pZCAlaW4lIGludGVyc2VjdChnbyRpZExpc3RbW2lkeF1dLHNvcnRlZC5lZy5zaWcpXSAlPiUKICAgIHNvcnQgJT4lIHVuaXF1ZSAlPiUgcGFzdGUoY29sbGFwc2UgPSAiLCIpCn0pCgphbGxfZ29fb3JkZXJlZCA8LSBhbGxfZ29bCiAgb3JkZXIoYWxsX2dvJFAuREUpLAogIF0KCndyaXRlLmNzdigKICBhbGxfZ29fb3JkZXJlZCwKICBwYXN0ZTAoZGlyLnJlc3VsdC5wYXRod2F5LCAicGF0aHdheV9yZWdpb25zX2FuZF9jcGdzX0dPX3Jlc3VsdHNfYWxsLmNzdiIpLAogIHJvdy5uYW1lcyA9IFRSVUUKKQoKYWxsX2dvX29yZGVyZWQuYnAgPC0gYWxsX2dvX29yZGVyZWQgJT4lCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIkdPIikgJT4lICAjIGtlZXAgcm93IG5hbWVzCiAgZHBseXI6OmZpbHRlcihPTlRPTE9HWSA9PSAiQlAiKSAlPiUKICB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcygiR08iKSAgICMga2VlcCByb3cgbmFtZXMKYWxsX2dvX29yZGVyZWQuYnAkRkRSIDwtIHAuYWRqdXN0KGFsbF9nb19vcmRlcmVkLmJwJFAuREUsImZkciIpCmBgYAoKYGBge1IsZXZhbCA9IEZBTFNFfQp3cml0ZS5jc3YoCiAgYWxsX2dvX29yZGVyZWQuYnAsCiAgcGFzdGUwKGRpci5yZXN1bHQucGF0aHdheSwgInBhdGh3YXlfcmVnaW9uc19hbmRfY3Bnc19HT19yZXN1bHRzX0JQX05fcmFuZ2VfNV8yMDBfZmRyX3JlY2FsYy5jc3YiKSwKICByb3cubmFtZXMgPSBUUlVFCikKYGBgCgpgYGB7Un0KYWxsX2dvX29yZGVyZWQuYnAgICU+JSAKICBkcGx5cjo6ZmlsdGVyKEZEUiA8IDAuMDUpICU+JQogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gJ3RvcCcsCiAgICAgICAgICAgICAgICBzdHlsZSA9ICJib290c3RyYXAiLAogICAgICAgICAgICAgICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbSA9ICdCZnJ0aXAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IEkoJ2NvbHZpcycpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKSwgCiAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJHTyByZXN1bHRzIEJQIChGRFIgPCAwLjA1KSIpCmBgYAoKYGBge1Iga2VnZ19yZWdpb25zX2NwZ3N9CiMjIyBjb2xsZWN0aW9uID0gIktFR0ciCmFsbF9rZWdnIDwtIGdvbWV0aCgKICBzaWcuY3BnID0gYWxsLmZvcmVncm91bmQucHJvYmVzLAogIGFsbC5jcGcgPSBhbGwuYmFja2dyb3VuZC5wcm9iZXMsCiAgY29sbGVjdGlvbiA9ICJLRUdHIiwKICBmcmFjdC5jb3VudHMgPSBUUlVFCikKIyB0b3BHU0EoYWxsX2tlZ2cpCgprZWdnIDwtIG1pc3NNZXRoeWw6OjouZ2V0S0VHRygpCm91dCA8LSBnZXRNYXBwZWRFbnRyZXpJRHMoc2lnLmNwZyA9IGZvcmVncm91bmQucHJvYmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGFsbC5jcGcgPSBiYWNrZ3JvdW5kLnByb2JlcywKICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheS50eXBlID0gIjQ1MEsiKQpzb3J0ZWQuZWcuc2lnIDwtIG91dCRzaWcuZWcKYGBgCgpgYGB7UiwgZXZhbCA9IEZBTFNFfQpnZW5lLmluZm8gPC0gVENHQWJpb2xpbmtzOjpnZXQuR1JDaC5iaW9NYXJ0KGdlbm9tZSA9ICJoZzE5IikKYGBgCgpgYGB7Un0KYWxsX2tlZ2ckZGVfZ2VuZXMgPC0gcGx5cjo6YWFwbHkocm93bmFtZXMoYWxsX2tlZ2cpLDEsLmZ1biA9IGZ1bmN0aW9uKGlkeCl7CiAgZ2VuZS5pbmZvJGV4dGVybmFsX2dlbmVfbmFtZVtnZW5lLmluZm8kZW50cmV6Z2VuZV9pZCAlaW4lIGludGVyc2VjdChrZWdnJGlkTGlzdFtbaWR4XV0sc29ydGVkLmVnLnNpZyldICU+JQogICAgc29ydCAlPiUgdW5pcXVlICU+JSBwYXN0ZShjb2xsYXBzZSA9ICIsIikKfSkKCmFsbF9rZWdnX29yZGVyZWQgPC0gYWxsX2tlZ2dbCiAgb3JkZXIoYWxsX2tlZ2ckUC5ERSksCiAgXQoKd3JpdGUuY3N2KAogIGFsbF9rZWdnX29yZGVyZWQsCiAgcGFzdGUwKGRpci5yZXN1bHQucGF0aHdheSwgInBhdGh3YXlfcmVnaW9uc19hbmRfY3Bnc19LRUdHX3Jlc3VsdHNfYWxsLmNzdiIpLAogIHJvdy5uYW1lcyA9IFRSVUUKKQoKCmFsbF9rZWdnX29yZGVyZWQgPC0gYWxsX2tlZ2dfb3JkZXJlZCAlPiUKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiS0VHRyIpICU+JSAgIyBrZWVwIHJvdyBuYW1lcwogIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKCJLRUdHIikgICAgICAjIGtlZXAgcm93IG5hbWVzCmFsbF9rZWdnX29yZGVyZWQkRkRSIDwtIHAuYWRqdXN0KGFsbF9rZWdnX29yZGVyZWQkUC5ERSwiZmRyIikKYGBgCgoKYGBge1IsIGV2YWwgPSBGQUxTRX0Kd3JpdGUuY3N2KAogIGFsbF9rZWdnX29yZGVyZWQsCiAgcGFzdGUwKGRpci5yZXN1bHQucGF0aHdheSwgInBhdGh3YXlfcmVnaW9uc19hbmRfY3Bnc19LRUdHX3Jlc3VsdHNfTl9yYW5nZV81XzIwMF9mZHJfcmVjYWxjLmNzdiIpLAogIHJvdy5uYW1lcyA9IFRSVUUKKQpgYGAKCmBgYHtSfQphbGxfa2VnZ19vcmRlcmVkICAlPiUgCiAgZHBseXI6OmZpbHRlcihQLkRFIDwgMC4wNSkgJT4lCiAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSAndG9wJywKICAgICAgICAgICAgICAgIHN0eWxlID0gImJvb3RzdHJhcCIsCiAgICAgICAgICAgICAgICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLAogICAgICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2Nyb2xsWCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gSSgnY29sdmlzJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gMTApLCAKICAgICAgICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICBjYXB0aW9uID0gImtlZ2cgcmVzdWx0cyAoUC5ERSA8IDAuMDUpIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIApgYGAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgojIFNlc3Npb24gaW5mb3JtYXRpb24KYGBge1J9CmRldnRvb2xzOjpzZXNzaW9uX2luZm8oKQpgYGAKCgo=