1 Parameters

suffix = ""
data_to_read = "./Data/acc_tpm_nCount_mito_no146_15k_cancercells.rds"

2 functions

library(stringi)
source_from_github(repositoy = "DEG_functions",version = "0.2.24")

3 Data

acc = readRDS(file = data_to_read)
acc_primary = readRDS(file = "./Data/acc_cancer_no146_primaryonly15k_cancercells.rds")

(message("reading '" %>% paste0(data_to_read %>% basename()) %>% paste0("'")))
reading 'acc_tpm_nCount_mito_no146_15k_cancercells.rds'
NULL
pathways_scores = fread(file = "./Data/ACC_Canonical_Pathway_Scores.txt",sep = ",") %>% as.matrix(rownames=1) %>% t() %>%  as.data.frame()
hallmark_scores = fread(file = "./Data/ACC_Hallmark_Pathway_Scores.txt",sep = ",") %>% as.matrix(rownames=1) %>% t() %>%  as.data.frame()
ln_list = c("ACC22.LN.P11", "ACC22.P12.LN","ACC7.P13")
ln_plates = FetchData(object = acc,vars = "orig.ident") %>% mutate(
  tumor_type = if_else(condition = orig.ident %in% ln_list
                       ,true = "LN"
                       ,false = "primary"))

ln_plates["orig.ident"] <-NULL
acc= AddMetaData(object = acc,metadata = ln_plates)
pathways_scores = cbind(pathways_scores,hallmark_scores)
pathways_scores = pathways_scores[ , colSums(is.na(pathways_scores))==0] #remove cols with NA
pathways_scores = pathways_scores [rownames(pathways_scores) %in% colnames(acc),] #remove cells not in dataset
pathways_scores =  pathways_scores[order(row.names(pathways_scores)),] #order cells like dataset

4 Dim reduction

# run-dim-reduction on genes:
acc <- FindVariableFeatures(acc, selection.method = "vst", nfeatures = 2000)
acc <- ScaleData(acc)
acc <- RunPCA(acc,verbose = F)
ElbowPlot(acc)

pathway_scores_assay <- CreateAssayObject(counts = pathways_scores %>% t()) #create an assay
Warning: Feature names cannot have underscores ('_'), replacing with dashes ('-')
acc[["pathway_scores"]] = pathway_scores_assay
Warning: Keys should be one or more alphanumeric characters followed by an underscore, setting key from pathway_scores_ to pathwayscores_
# run-dim-reduction:
acc <- FindVariableFeatures(acc, selection.method = "vst", nfeatures = 2000,assay = "pathway_scores")
acc <- ScaleData(acc,assay = "pathway_scores",features = rownames(acc[["pathway_scores"]]))
acc <- RunPCA(acc, features = rownames(acc[["pathway_scores"]]),assay = "pathway_scores",reduction.name = "PCA_pathway_scores",verbose = F)
ElbowPlot(acc,reduction =  "PCA_pathway_scores")

acc <- RunUMAP(acc, dims = 1:5,reduction ="PCA_pathway_scores",reduction.name = "pathway_scores_umap",verbose = F)
Warning: Cannot add objects with duplicate keys (offending key: UMAP_), setting key to 'pathway_scores_umap_'

5 acc umaps

print_tab(plt = DimPlot(acc,group.by = "patient.ident"),title = "gene expression")

gene expression

print_tab(plt = DimPlot(acc,reduction = "pathway_scores_umap",group.by = "patient.ident"),title = "pathways scores")

pathways scores

NA

gs=acc@assays$RNA@var.features

myoscore=apply(acc@assays$RNA@scale.data[intersect(c("TP63","TP73","CAV1","CDH3","KRT5","KRT14","ACTA2","TAGLN","MYLK","DKK3"),gs),],2,mean)

lescore=apply(acc@assays$RNA@scale.data[intersect(c("KIT","EHF","ELF5","KRT7","CLDN3","CLDN4","CD24","LGALS3","LCN2","SLPI"),gs),],2,mean)
acc=AddMetaData(acc,lescore-myoscore,"luminal_over_myo")
#set lum_or_myo metadata
luminal_over_myo = FetchData(object = acc,vars = "luminal_over_myo")
luminal_over_myo$lum_or_myo  = case_when(luminal_over_myo$luminal_over_myo >1~"lum",luminal_over_myo$luminal_over_myo <(-1)~"myo",TRUE~"NA")
luminal_over_myo$luminal_over_myo <-NULL
acc=AddMetaData(object = acc,metadata = luminal_over_myo,col.name = "lum_or_myo")
print_tab(plt = FeaturePlot(object = acc,features = "luminal_over_myo",reduction = "pathway_scores_umap"),title = "luminal_over_myo")

luminal_over_myo

print_tab(plt = DimPlot(acc,group.by = "lum_or_myo",cols = c("red","green","grey"),reduction = "pathway_scores_umap"),title = "cell type")

cell type

print_tab(plt = FeaturePlot(object = acc,features = "luminal_over_myo"),title = "luminal_over_myo")

luminal_over_myo

print_tab(plt = DimPlot(acc,group.by = "lum_or_myo",cols = c("red","green","grey")),title = "cell type")

cell type

NA

6 Genes

print_tab(plt = 
            FeaturePlot(object = acc,features = c("FGF1","FGF2","FGF11","FGF12"),reduction = "pathway_scores_umap")
          ,title = "FGF")

FGF

print_tab(plt = 
FeaturePlot(object = acc,features = c("FGF18","FGF20","FGF15","FGF23"),reduction = "pathway_scores_umap")
          ,title = "FGF")

FGF

Warning in FetchData.Seurat(object = object, vars = c(dims, “ident”, features), : The following requested variables were not found: FGF15

print_tab(plt = 
FeaturePlot(object = acc,features = c("EGF"),reduction = "pathway_scores_umap")
          ,title = "EGF")

EGF

print_tab(plt = 
FeaturePlot(object = acc,features = c("NOTCH1","NOTCH2","NOTCH3","NOTCH4"),reduction = "pathway_scores_umap")
          ,title = "NOTCH genes")

NOTCH genes

print_tab(plt = 
FeaturePlot(object = acc,features = c("HES4","HEY1","HEY2","NRARP"),reduction = "pathway_scores_umap")
          ,title = "NOTCH targets")

NOTCH targets

NA

7 All PC’s

for (i in 1:8) {
print_tab(plt = VizDimLoadings(acc, dims = i, reduction = "PCA_pathway_scores"),title = paste("PC", i))
}

PC 1

PC 2

PC 3

PC 4

PC 5

PC 6

PC 7

PC 8

NA

8 cycling cells clustring

hallmark_name = "HALLMARK_G2M_CHECKPOINT"
genesets  =GSEABase::getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
var_features=acc@assays$RNA@var.features
geneIds= genesets[[hallmark_name]]@geneIds
score <- apply(acc@assays$RNA@data[intersect(geneIds,var_features),],2,mean)
acc=AddMetaData(acc,score,hallmark_name)

print_tab(plt = FeaturePlot(acc, reduction = "umap",features = "HALLMARK_G2M_CHECKPOINT"),title = "by genes")

by genes

print_tab(plt = FeaturePlot(acc, reduction = "pathway_scores_umap",features = "HALLMARK_G2M_CHECKPOINT"),title = "by genes")

by genes

NA

9 UMAP clusters

acc <- FindNeighbors(acc, dims = 1:10,reduction = "PCA_pathway_scores")
Computing nearest neighbor graph
Computing SNN
acc <- FindClusters(acc, resolution = 0.15,graph.name = "pathway_scores_snn")
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 951
Number of edges: 33164

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.8799
Number of communities: 2
Elapsed time: 0 seconds
DimPlot(acc,reduction = "pathway_scores_umap")

FeaturePlot(object = acc,features = "nFeature_RNA",reduction = "pathway_scores_umap")

VlnPlot(acc, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)

10 pathways DEG


print_tab(plt = datatable(pathway_markers_deg),title = "all deg")
print_tab(plt = datatable(pathway_markers_deg %>% dplyr::filter(abs(avg_log2FC)>1)),title = "all deg FC>1")

11 genes DEG

rho_genes = c("CDC42",
"RHOQ",
"RHOJ",
"RHOUV",
'RHOU',
"RHOV",
"RAC1",
"RAC2",
"RAC3",
"RHOG",
"RHOBTB1",
'RHOBTB2',
'RHOBTB3',
'RHOH',
'RHOA',
'RHOB',
'RHOC',
'RND1',
'RND2',
'RND3',
'RHOF',
'RHOD',
'RHOF')

notch_genes = c("JAG1","JAG2","NOTCH3","NOTCH2","NOTCH1","DLL1","MYB","HES4","HEY1","HEY2","NRARP")

print_tab(plt = acc_deg %>% datatable(class = 'cell-border stripe') ,title = "all DEG")
print_tab(plt = acc_deg[rownames(acc_deg) %in%  rho_genes,]%>% datatable(class = 'cell-border stripe')   ,title = "Rho genes in DEG")
print_tab(plt = acc_deg[rownames(acc_deg) %in%  notch_genes,] %>% datatable(class = 'cell-border stripe') ,title = "NOTCH genes in DEG")
DefaultAssay(object = acc)<- "pathway_scores"
genes_expression = FetchData(object = acc,vars = c("REACTOME-RHO-GTPASE-CYCLE","WP-HEAD-AND-NECK-SQUAMOUS-CELL-CARCINOMA"))
cor(genes_expression)

top_correlated <- function(dataset, genes, threshold,anti_cor = F) {
  markers_expression = FetchData(object = dataset,vars = genes,slot = "data") #get genes expression
  markers_average = rowMeans(markers_expression) %>% as.data.frame() %>% rename("average" = 1) #average them
  cor_mat = cor(expression %>% t(), markers_average)%>% as.data.frame() #cor with all genes
  cor_mat = cor_mat[complete.cases(cor_mat),,drop=F]  %>% as.data.frame %>%  rename("corr" = 1) #remove rows with NA in at least one col
  if (threshold<1){ #if threshold is based on pearson correlation 
      if(anti_cor == T){top_genes =   cor_mat %>% as.data.frame %>% select(1) %>% dplyr::filter(.< threshold) %>% rownames()}else{
          top_genes =   cor_mat %>% as.data.frame %>% select(1) %>% dplyr::filter(.> threshold) %>% rownames()
      }
  }else{ #if threshold is based on top correlated genes 
      if(anti_cor == T){threshold  = threshold*(-1)}
      top_genes =   cor_mat %>%  top_n(threshold,corr) %>% rownames()
      }
  return(top_genes)
}
expression = GetAssayData(object = acc,assay = "RNA",slot = "data") %>% as.data.frame()

top_correlated(dataset = acc,genes = "RND3",threshold = 20)

#UMAPS

print_tab(plt = 
            FeaturePlot(object = acc,features = "NOTCH2",reduction = "pathway_scores_umap")
 ,title = "NOTCH2 UMAP")

print_tab(plt = 
            FeaturePlot(object = acc,features = "RND3",reduction = "pathway_scores_umap")
 ,title = "RND3 UMAP")

print_tab(plt = 
            FeaturePlot(object = acc,features = "JAG1",reduction = "pathway_scores_umap")
 ,title = "JAG1 UMAP")

print_tab(plt = 
            FeaturePlot(object = acc,features = "JAG2",reduction = "pathway_scores_umap")
 ,title = "JAG2 UMAP")

print_tab(plt = 
            FeaturePlot(object = acc,features = "DLL1",reduction = "pathway_scores_umap")
 ,title = "DLL1 UMAP")

print_tab(plt = 
            FeaturePlot(object = acc,features = "HES4",reduction = "pathway_scores_umap")
 ,title = "HES4 UMAP")

12 HEAD-AND-NECK-SQUAMOUS

FeaturePlot(object = acc,features = "WP-HEAD-AND-NECK-SQUAMOUS-CELL-CARCINOMA",reduction = "pathway_scores_umap")

13 ACC1/2

ACC1_genes = c("MYC", "SOX6", "SOX8", "CTNND2", "NOTCH3","BCL2")
ACC2_genes = c("TP63","COL17A1","PDGFA", "DKK3","EGFR", "AXL","PDGFRA")

gs=acc@assays$RNA@var.features

acc1_score=apply(acc@assays$RNA@data[ACC1_genes,],2,mean)

acc2_score=apply(acc@assays$RNA@data[ACC2_genes,],2,mean)
acc=AddMetaData(acc,acc1_score-acc2_score,"acc1_over_acc2")

FeaturePlot(object = acc,features = "acc1_over_acc2",reduction = "pathway_scores_umap")

14 More clusters

acc <- FindNeighbors(acc, dims = 1:10,reduction = "PCA_pathway_scores")
acc <- FindClusters(acc, resolution = 0.5,graph.name = "pathway_scores_snn")
print_tab(plt = DimPlot(acc,reduction = "pathway_scores_umap"),title = "UMAP")
DimPlot(acc,group.by = "lum_or_myo",cols = c("red","green","grey"),reduction = "pathway_scores_umap")
FeaturePlot(object = acc,features = "nFeature_RNA",reduction = "pathway_scores_umap")
acc <- FindNeighbors(acc, dims = 1:10)
acc <- FindClusters(acc, resolution = 0.5)
print_tab(plt = DimPlot(acc),title = "UMAP")
DimPlot(acc,group.by = "lum_or_myo",cols = c("red","green","grey"))
for (i in 0:4) {
print_tab(plt = deg_markers %>% dplyr::filter(cluster == i) %>% datatable(),title = paste("cluster",i))
  }

14.1 Genes in DEG

print_tab(plt = acc_deg %>% dplyr::filter(gene %in% rho_genes),title = "Rho genes",subtitle_num = 3)
print_tab(plt = acc_deg %>% dplyr::filter(gene %in% notch_genes),title = "Notch genes",subtitle_num = 3)

15 MET pathway score

FeaturePlot(object = acc,features = "BIOCARTA-MET-PATHWAY",reduction = "pathway_scores_umap",max.cutoff = 0.3)
Warning: Could not find BIOCARTA-MET-PATHWAY in the default search locations, found in pathway_scores assay instead

16 MET pathway score based on gene expression

met_genes = msigdbr(species = "Homo sapiens",category = "C2") %>% dplyr::filter(gs_subcat != "CGP") %>%dplyr::filter(gs_name == "BIOCARTA_MET_PATHWAY") %>%  dplyr::distinct(gs_name, gene_symbol) %>% as.data.frame() %>% pull(gene_symbol)

geneIds= met_genes
score <- apply(acc@assays$RNA@data[geneIds,],2,mean)
acc=AddMetaData(acc,score,"BIOCARTA_MET_PATHWAY")
FeaturePlot(object = acc,features = "BIOCARTA_MET_PATHWAY" ,reduction =  "pathway_scores_umap")

pathways_scores[,"BIOCARTA_MET_PATHWAY"]
pathways_scores[,"BIOCARTA_MET_PATHWAY"] %>% sort()

17 nFeatures of met genes

acc <- subset(acc, subset = nFeature_RNA > 2000 & percent.mt < 20)
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKLS0tCgojIFBhcmFtZXRlcnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CnN1ZmZpeCA9ICIiCmRhdGFfdG9fcmVhZCA9ICIuL0RhdGEvYWNjX3RwbV9uQ291bnRfbWl0b19ubzE0Nl8xNWtfY2FuY2VyY2VsbHMucmRzIgpgYGAKCgojIGZ1bmN0aW9ucwoKYGBge3Igd2FybmluZz1GQUxTRX0KbGlicmFyeShzdHJpbmdpKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gIkRFR19mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC4yLjI0IikKYGBgCgojIERhdGEKCmBgYHtyfQphY2MgPSByZWFkUkRTKGZpbGUgPSBkYXRhX3RvX3JlYWQpCmFjY19wcmltYXJ5ID0gcmVhZFJEUyhmaWxlID0gIi4vRGF0YS9hY2NfY2FuY2VyX25vMTQ2X3ByaW1hcnlvbmx5MTVrX2NhbmNlcmNlbGxzLnJkcyIpCgoobWVzc2FnZSgicmVhZGluZyAnIiAlPiUgcGFzdGUwKGRhdGFfdG9fcmVhZCAlPiUgYmFzZW5hbWUoKSkgJT4lIHBhc3RlMCgiJyIpKSkKcGF0aHdheXNfc2NvcmVzID0gZnJlYWQoZmlsZSA9ICIuL0RhdGEvQUNDX0Nhbm9uaWNhbF9QYXRod2F5X1Njb3Jlcy50eHQiLHNlcCA9ICIsIikgJT4lIGFzLm1hdHJpeChyb3duYW1lcz0xKSAlPiUgdCgpICU+JSAgYXMuZGF0YS5mcmFtZSgpCmhhbGxtYXJrX3Njb3JlcyA9IGZyZWFkKGZpbGUgPSAiLi9EYXRhL0FDQ19IYWxsbWFya19QYXRod2F5X1Njb3Jlcy50eHQiLHNlcCA9ICIsIikgJT4lIGFzLm1hdHJpeChyb3duYW1lcz0xKSAlPiUgdCgpICU+JSAgYXMuZGF0YS5mcmFtZSgpCmBgYAoKYGBge3J9CmxuX2xpc3QgPSBjKCJBQ0MyMi5MTi5QMTEiLCAiQUNDMjIuUDEyLkxOIiwiQUNDNy5QMTMiKQpsbl9wbGF0ZXMgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjLHZhcnMgPSAib3JpZy5pZGVudCIpICU+JSBtdXRhdGUoCiAgdHVtb3JfdHlwZSA9IGlmX2Vsc2UoY29uZGl0aW9uID0gb3JpZy5pZGVudCAlaW4lIGxuX2xpc3QKICAgICAgICAgICAgICAgICAgICAgICAsdHJ1ZSA9ICJMTiIKICAgICAgICAgICAgICAgICAgICAgICAsZmFsc2UgPSAicHJpbWFyeSIpKQoKbG5fcGxhdGVzWyJvcmlnLmlkZW50Il0gPC1OVUxMCmFjYz0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjLG1ldGFkYXRhID0gbG5fcGxhdGVzKQpgYGAKCgoKYGBge3J9CnBhdGh3YXlzX3Njb3JlcyA9IGNiaW5kKHBhdGh3YXlzX3Njb3JlcyxoYWxsbWFya19zY29yZXMpCnBhdGh3YXlzX3Njb3JlcyA9IHBhdGh3YXlzX3Njb3Jlc1sgLCBjb2xTdW1zKGlzLm5hKHBhdGh3YXlzX3Njb3JlcykpPT0wXSAjcmVtb3ZlIGNvbHMgd2l0aCBOQQpwYXRod2F5c19zY29yZXMgPSBwYXRod2F5c19zY29yZXMgW3Jvd25hbWVzKHBhdGh3YXlzX3Njb3JlcykgJWluJSBjb2xuYW1lcyhhY2MpLF0gI3JlbW92ZSBjZWxscyBub3QgaW4gZGF0YXNldApwYXRod2F5c19zY29yZXMgPSAgcGF0aHdheXNfc2NvcmVzW29yZGVyKHJvdy5uYW1lcyhwYXRod2F5c19zY29yZXMpKSxdICNvcmRlciBjZWxscyBsaWtlIGRhdGFzZXQKYGBgCgoKIyBEaW0gcmVkdWN0aW9uCmBgYHtyIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLGVjaG89VFJVRX0KIyBydW4tZGltLXJlZHVjdGlvbiBvbiBnZW5lczoKYWNjIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKGFjYywgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQphY2MgPC0gU2NhbGVEYXRhKGFjYykKYWNjIDwtIFJ1blBDQShhY2MsdmVyYm9zZSA9IEYpCkVsYm93UGxvdChhY2MpCmBgYAoKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmFjYyA8LSBSdW5VTUFQKGFjYywgZGltcyA9IDE6NSkKYGBgCgoKCmBgYHtyfQpwYXRod2F5X3Njb3Jlc19hc3NheSA8LSBDcmVhdGVBc3NheU9iamVjdChjb3VudHMgPSBwYXRod2F5c19zY29yZXMgJT4lIHQoKSkgI2NyZWF0ZSBhbiBhc3NheQphY2NbWyJwYXRod2F5X3Njb3JlcyJdXSA9IHBhdGh3YXlfc2NvcmVzX2Fzc2F5CmBgYApgYGB7ciB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJyxlY2hvPVRSVUV9CiMgcnVuLWRpbS1yZWR1Y3Rpb246CmFjYyA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhhY2MsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCxhc3NheSA9ICJwYXRod2F5X3Njb3JlcyIpCmFjYyA8LSBTY2FsZURhdGEoYWNjLGFzc2F5ID0gInBhdGh3YXlfc2NvcmVzIixmZWF0dXJlcyA9IHJvd25hbWVzKGFjY1tbInBhdGh3YXlfc2NvcmVzIl1dKSkKYWNjIDwtIFJ1blBDQShhY2MsIGZlYXR1cmVzID0gcm93bmFtZXMoYWNjW1sicGF0aHdheV9zY29yZXMiXV0pLGFzc2F5ID0gInBhdGh3YXlfc2NvcmVzIixyZWR1Y3Rpb24ubmFtZSA9ICJQQ0FfcGF0aHdheV9zY29yZXMiLHZlcmJvc2UgPSBGKQpFbGJvd1Bsb3QoYWNjLHJlZHVjdGlvbiA9ICAiUENBX3BhdGh3YXlfc2NvcmVzIikKYGBgCgoKYGBge3J9CmFjYyA8LSBSdW5VTUFQKGFjYywgZGltcyA9IDE6NSxyZWR1Y3Rpb24gPSJQQ0FfcGF0aHdheV9zY29yZXMiLHJlZHVjdGlvbi5uYW1lID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiLHZlcmJvc2UgPSBGKQpgYGAKCgojIGFjYyB1bWFwcyB7LnRhYnNldH0KCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CnByaW50X3RhYihwbHQgPSBEaW1QbG90KGFjYyxncm91cC5ieSA9ICJwYXRpZW50LmlkZW50IiksdGl0bGUgPSAiZ2VuZSBleHByZXNzaW9uIikKcHJpbnRfdGFiKHBsdCA9IERpbVBsb3QoYWNjLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIixncm91cC5ieSA9ICJwYXRpZW50LmlkZW50IiksdGl0bGUgPSAicGF0aHdheXMgc2NvcmVzIikKCmBgYApgYGB7cn0KZ3M9YWNjQGFzc2F5cyRSTkFAdmFyLmZlYXR1cmVzCgpteW9zY29yZT1hcHBseShhY2NAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW2ludGVyc2VjdChjKCJUUDYzIiwiVFA3MyIsIkNBVjEiLCJDREgzIiwiS1JUNSIsIktSVDE0IiwiQUNUQTIiLCJUQUdMTiIsIk1ZTEsiLCJES0szIiksZ3MpLF0sMixtZWFuKQoKbGVzY29yZT1hcHBseShhY2NAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW2ludGVyc2VjdChjKCJLSVQiLCJFSEYiLCJFTEY1IiwiS1JUNyIsIkNMRE4zIiwiQ0xETjQiLCJDRDI0IiwiTEdBTFMzIiwiTENOMiIsIlNMUEkiKSxncyksXSwyLG1lYW4pCmFjYz1BZGRNZXRhRGF0YShhY2MsbGVzY29yZS1teW9zY29yZSwibHVtaW5hbF9vdmVyX215byIpCmBgYAoKYGBge3J9CiNzZXQgbHVtX29yX215byBtZXRhZGF0YQpsdW1pbmFsX292ZXJfbXlvID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYyx2YXJzID0gImx1bWluYWxfb3Zlcl9teW8iKQpsdW1pbmFsX292ZXJfbXlvJGx1bV9vcl9teW8gID0gY2FzZV93aGVuKGx1bWluYWxfb3Zlcl9teW8kbHVtaW5hbF9vdmVyX215byA+MX4ibHVtIixsdW1pbmFsX292ZXJfbXlvJGx1bWluYWxfb3Zlcl9teW8gPCgtMSl+Im15byIsVFJVRX4iTkEiKQpsdW1pbmFsX292ZXJfbXlvJGx1bWluYWxfb3Zlcl9teW8gPC1OVUxMCmFjYz1BZGRNZXRhRGF0YShvYmplY3QgPSBhY2MsbWV0YWRhdGEgPSBsdW1pbmFsX292ZXJfbXlvLGNvbC5uYW1lID0gImx1bV9vcl9teW8iKQpgYGAKCmBgYHtyIHdhcm5pbmc9RkFMU0UscmVzdWx0cz0nYXNpcyd9CnByaW50X3RhYihwbHQgPSBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSAibHVtaW5hbF9vdmVyX215byIscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKSx0aXRsZSA9ICJsdW1pbmFsX292ZXJfbXlvIikKcHJpbnRfdGFiKHBsdCA9IERpbVBsb3QoYWNjLGdyb3VwLmJ5ID0gImx1bV9vcl9teW8iLGNvbHMgPSBjKCJyZWQiLCJncmVlbiIsImdyZXkiKSxyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpLHRpdGxlID0gImNlbGwgdHlwZSIpCgpwcmludF90YWIocGx0ID0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gImx1bWluYWxfb3Zlcl9teW8iKSx0aXRsZSA9ICJsdW1pbmFsX292ZXJfbXlvIikKcHJpbnRfdGFiKHBsdCA9IERpbVBsb3QoYWNjLGdyb3VwLmJ5ID0gImx1bV9vcl9teW8iLGNvbHMgPSBjKCJyZWQiLCJncmVlbiIsImdyZXkiKSksdGl0bGUgPSAiY2VsbCB0eXBlIikKYGBgCiMgR2VuZXMgey50YWJzZXR9CgpgYGB7ciAgcmVzdWx0cz0nYXNpcyd9CnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gYygiRkdGMSIsIkZHRjIiLCJGR0YxMSIsIkZHRjEyIikscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKQogICAgICAgICAgLHRpdGxlID0gIkZHRiIpCgpwcmludF90YWIocGx0ID0gCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9IGMoIkZHRjE4IiwiRkdGMjAiLCJGR0YxNSIsIkZHRjIzIikscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKQogICAgICAgICAgLHRpdGxlID0gIkZHRiIpCgpwcmludF90YWIocGx0ID0gCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9IGMoIkVHRiIpLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICAgICAgICAgICx0aXRsZSA9ICJFR0YiKQoKcHJpbnRfdGFiKHBsdCA9IApGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSBjKCJOT1RDSDEiLCJOT1RDSDIiLCJOT1RDSDMiLCJOT1RDSDQiKSxyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpCiAgICAgICAgICAsdGl0bGUgPSAiTk9UQ0ggZ2VuZXMiKQoKcHJpbnRfdGFiKHBsdCA9IApGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSBjKCJIRVM0IiwiSEVZMSIsIkhFWTIiLCJOUkFSUCIpLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICAgICAgICAgICx0aXRsZSA9ICJOT1RDSCB0YXJnZXRzIikKCgpgYGAKCiMgQWxsIFBDJ3Mgey50YWJzZXR9CgpgYGB7ciBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTE0LCByZXN1bHRzPSdhc2lzJ30KZm9yIChpIGluIDE6OCkgewpwcmludF90YWIocGx0ID0gVml6RGltTG9hZGluZ3MoYWNjLCBkaW1zID0gaSwgcmVkdWN0aW9uID0gIlBDQV9wYXRod2F5X3Njb3JlcyIpLHRpdGxlID0gcGFzdGUoIlBDIiwgaSkpCn0KYGBgCgoKCiMgY3ljbGluZyBjZWxscyBjbHVzdHJpbmcgey50YWJzZXR9CmBgYHtyIHdhcm5pbmc9RkFMU0UscmVzdWx0cz0nYXNpcyd9CmhhbGxtYXJrX25hbWUgPSAiSEFMTE1BUktfRzJNX0NIRUNLUE9JTlQiCmdlbmVzZXRzICA9R1NFQUJhc2U6OmdldEdtdCgiLi9EYXRhL2guYWxsLnY3LjAuc3ltYm9scy5wbHVzY2MuZ210IikKdmFyX2ZlYXR1cmVzPWFjY0Bhc3NheXMkUk5BQHZhci5mZWF0dXJlcwpnZW5lSWRzPSBnZW5lc2V0c1tbaGFsbG1hcmtfbmFtZV1dQGdlbmVJZHMKc2NvcmUgPC0gYXBwbHkoYWNjQGFzc2F5cyRSTkFAZGF0YVtpbnRlcnNlY3QoZ2VuZUlkcyx2YXJfZmVhdHVyZXMpLF0sMixtZWFuKQphY2M9QWRkTWV0YURhdGEoYWNjLHNjb3JlLGhhbGxtYXJrX25hbWUpCgpwcmludF90YWIocGx0ID0gRmVhdHVyZVBsb3QoYWNjLCByZWR1Y3Rpb24gPSAidW1hcCIsZmVhdHVyZXMgPSAiSEFMTE1BUktfRzJNX0NIRUNLUE9JTlQiKSx0aXRsZSA9ICJieSBnZW5lcyIpCnByaW50X3RhYihwbHQgPSBGZWF0dXJlUGxvdChhY2MsIHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIixmZWF0dXJlcyA9ICJIQUxMTUFSS19HMk1fQ0hFQ0tQT0lOVCIpLHRpdGxlID0gImJ5IGdlbmVzIikKCmBgYAoKIyBVTUFQIGNsdXN0ZXJzCmBgYHtyfQphY2MgPC0gRmluZE5laWdoYm9ycyhhY2MsIGRpbXMgPSAxOjEwLHJlZHVjdGlvbiA9ICJQQ0FfcGF0aHdheV9zY29yZXMiKQphY2MgPC0gRmluZENsdXN0ZXJzKGFjYywgcmVzb2x1dGlvbiA9IDAuMTUsZ3JhcGgubmFtZSA9ICJwYXRod2F5X3Njb3Jlc19zbm4iKQpgYGAKCmBgYHtyfQpEaW1QbG90KGFjYyxyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpCmBgYAoKYGBge3J9CkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9ICJuRmVhdHVyZV9STkEiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKVmxuUGxvdChhY2MsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgIm5Db3VudF9STkEiLCAicGVyY2VudC5tdCIpLCBuY29sID0gMykKCmBgYAoKIyBwYXRod2F5cyBERUcgIHsudGFic2V0fQoKYGBge3IgcmVzdWx0cz0naGlkZSd9CnBhdGh3YXlfbWFya2VycyA9IEZpbmRNYXJrZXJzKG9iamVjdCA9IGFjYyxpZGVudC4xID0gIjAiLGlkZW50LjIgPSAiMSIsYXNzYXkgPSAicGF0aHdheV9zY29yZXMiLG1pbi5jZWxscy5mZWF0dXJlID0gMTAsbG9nZmMudGhyZXNob2xkID0gMCxkZW5zaWZ5ID0gVCkKcGF0aHdheV9tYXJrZXJzX2RlZyA9IHBhdGh3YXlfbWFya2VycyAlPiUKICBtdXRhdGUoZmRyID0gcC5hZGp1c3QocF92YWwsbWV0aG9kID0gImZkciIpKSU+JSAgI2FkZCBmZHIgCiAgZHBseXI6OmZpbHRlcihmZHI8MC4wNSkKCmBgYAo8ZGl2IHN0eWxlPSd3aWR0aDoxMzAwcHg7bWFyZ2luOiAwIGF1dG87Jz4KCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQoKcHJpbnRfdGFiKHBsdCA9IGRhdGF0YWJsZShwYXRod2F5X21hcmtlcnNfZGVnKSx0aXRsZSA9ICJhbGwgZGVnIikKcHJpbnRfdGFiKHBsdCA9IGRhdGF0YWJsZShwYXRod2F5X21hcmtlcnNfZGVnICU+JSBkcGx5cjo6ZmlsdGVyKGFicyhhdmdfbG9nMkZDKT4xKSksdGl0bGUgPSAiYWxsIGRlZyBGQz4xIikKCmBgYAo8L2Rpdj4KCgojIGdlbmVzIERFRyB7LnRhYnNldH0KCgoKYGBge3IgcmVzdWx0cz0naGlkZSd9CmFjYyA9IFNldElkZW50KG9iamVjdCA9IGFjYyx2YWx1ZSA9ICJwYXRod2F5X3Njb3Jlc19zbm5fcmVzLjAuMSIpCmdlbmVzX21hcmtlcnMgPSBGaW5kTWFya2VycyhvYmplY3QgPSBhY2MsaWRlbnQuMSA9ICIwIixpZGVudC4yID0gIjEiLGFzc2F5ID0gIlJOQSIsbWluLmNlbGxzLmZlYXR1cmUgPSAxMCxsb2dmYy50aHJlc2hvbGQgPSAwLGRlbnNpZnkgPSBUKQphY2NfZGVnICA9IGdlbmVzX21hcmtlcnMgJT4lIG11dGF0ZShmZHIgPSBwLmFkanVzdChwX3ZhbCxtZXRob2QgPSAiZmRyIikpJT4lICNhZGQgZmRyCiAgICBkcGx5cjo6ZmlsdGVyKChhdmdfbG9nMkZDPjEgJiBmZHI8MC4wNSkgfCAoYXZnX2xvZzJGQzwgKC0xKSAmIGZkcjwwLjA1KSkgICNmaWx0ZXIgc2lnbmlmaWNhbnQKCmBgYAoKCgoKCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpyaG9fZ2VuZXMgPSBjKCJDREM0MiIsCiJSSE9RIiwKIlJIT0oiLAoiUkhPVVYiLAonUkhPVScsCiJSSE9WIiwKIlJBQzEiLAoiUkFDMiIsCiJSQUMzIiwKIlJIT0ciLAoiUkhPQlRCMSIsCidSSE9CVEIyJywKJ1JIT0JUQjMnLAonUkhPSCcsCidSSE9BJywKJ1JIT0InLAonUkhPQycsCidSTkQxJywKJ1JORDInLAonUk5EMycsCidSSE9GJywKJ1JIT0QnLAonUkhPRicpCgpub3RjaF9nZW5lcyA9IGMoIkpBRzEiLCJKQUcyIiwiTk9UQ0gzIiwiTk9UQ0gyIiwiTk9UQ0gxIiwiRExMMSIsIk1ZQiIsIkhFUzQiLCJIRVkxIiwiSEVZMiIsIk5SQVJQIikKCnByaW50X3RhYihwbHQgPSBhY2NfZGVnICU+JSBkYXRhdGFibGUoY2xhc3MgPSAnY2VsbC1ib3JkZXIgc3RyaXBlJykgLHRpdGxlID0gImFsbCBERUciKQpwcmludF90YWIocGx0ID0gYWNjX2RlZ1tyb3duYW1lcyhhY2NfZGVnKSAlaW4lICByaG9fZ2VuZXMsXSU+JSBkYXRhdGFibGUoY2xhc3MgPSAnY2VsbC1ib3JkZXIgc3RyaXBlJykgICAsdGl0bGUgPSAiUmhvIGdlbmVzIGluIERFRyIpCnByaW50X3RhYihwbHQgPSBhY2NfZGVnW3Jvd25hbWVzKGFjY19kZWcpICVpbiUgIG5vdGNoX2dlbmVzLF0gJT4lIGRhdGF0YWJsZShjbGFzcyA9ICdjZWxsLWJvcmRlciBzdHJpcGUnKSAsdGl0bGUgPSAiTk9UQ0ggZ2VuZXMgaW4gREVHIikKCmBgYAoKCmBgYHtyfQpEZWZhdWx0QXNzYXkob2JqZWN0ID0gYWNjKTwtICJwYXRod2F5X3Njb3JlcyIKZ2VuZXNfZXhwcmVzc2lvbiA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MsdmFycyA9IGMoIlJFQUNUT01FLVJITy1HVFBBU0UtQ1lDTEUiLCJXUC1IRUFELUFORC1ORUNLLVNRVUFNT1VTLUNFTEwtQ0FSQ0lOT01BIikpCmNvcihnZW5lc19leHByZXNzaW9uKQoKdG9wX2NvcnJlbGF0ZWQgPC0gZnVuY3Rpb24oZGF0YXNldCwgZ2VuZXMsIHRocmVzaG9sZCxhbnRpX2NvciA9IEYpIHsKICBtYXJrZXJzX2V4cHJlc3Npb24gPSBGZXRjaERhdGEob2JqZWN0ID0gZGF0YXNldCx2YXJzID0gZ2VuZXMsc2xvdCA9ICJkYXRhIikgI2dldCBnZW5lcyBleHByZXNzaW9uCiAgbWFya2Vyc19hdmVyYWdlID0gcm93TWVhbnMobWFya2Vyc19leHByZXNzaW9uKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSByZW5hbWUoImF2ZXJhZ2UiID0gMSkgI2F2ZXJhZ2UgdGhlbQogIGNvcl9tYXQgPSBjb3IoZXhwcmVzc2lvbiAlPiUgdCgpLCBtYXJrZXJzX2F2ZXJhZ2UpJT4lIGFzLmRhdGEuZnJhbWUoKSAjY29yIHdpdGggYWxsIGdlbmVzCiAgY29yX21hdCA9IGNvcl9tYXRbY29tcGxldGUuY2FzZXMoY29yX21hdCksLGRyb3A9Rl0gICU+JSBhcy5kYXRhLmZyYW1lICU+JSAgcmVuYW1lKCJjb3JyIiA9IDEpICNyZW1vdmUgcm93cyB3aXRoIE5BIGluIGF0IGxlYXN0IG9uZSBjb2wKICBpZiAodGhyZXNob2xkPDEpeyAjaWYgdGhyZXNob2xkIGlzIGJhc2VkIG9uIHBlYXJzb24gY29ycmVsYXRpb24gCiAgICAgIGlmKGFudGlfY29yID09IFQpe3RvcF9nZW5lcyA9ICAgY29yX21hdCAlPiUgYXMuZGF0YS5mcmFtZSAlPiUgc2VsZWN0KDEpICU+JSBkcGx5cjo6ZmlsdGVyKC48IHRocmVzaG9sZCkgJT4lIHJvd25hbWVzKCl9ZWxzZXsKICAgICAgICAgIHRvcF9nZW5lcyA9ICAgY29yX21hdCAlPiUgYXMuZGF0YS5mcmFtZSAlPiUgc2VsZWN0KDEpICU+JSBkcGx5cjo6ZmlsdGVyKC4+IHRocmVzaG9sZCkgJT4lIHJvd25hbWVzKCkKICAgICAgfQogIH1lbHNleyAjaWYgdGhyZXNob2xkIGlzIGJhc2VkIG9uIHRvcCBjb3JyZWxhdGVkIGdlbmVzIAogICAgICBpZihhbnRpX2NvciA9PSBUKXt0aHJlc2hvbGQgID0gdGhyZXNob2xkKigtMSl9CiAgICAgIHRvcF9nZW5lcyA9ICAgY29yX21hdCAlPiUgIHRvcF9uKHRocmVzaG9sZCxjb3JyKSAlPiUgcm93bmFtZXMoKQogICAgICB9CiAgcmV0dXJuKHRvcF9nZW5lcykKfQpleHByZXNzaW9uID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IGFjYyxhc3NheSA9ICJSTkEiLHNsb3QgPSAiZGF0YSIpICU+JSBhcy5kYXRhLmZyYW1lKCkKCnRvcF9jb3JyZWxhdGVkKGRhdGFzZXQgPSBhY2MsZ2VuZXMgPSAiUk5EMyIsdGhyZXNob2xkID0gMjApCmBgYAoKI1VNQVBTCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9ICJOT1RDSDIiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICx0aXRsZSA9ICJOT1RDSDIgVU1BUCIpCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9ICJSTkQzIixyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpCiAsdGl0bGUgPSAiUk5EMyBVTUFQIikKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIkpBRzEiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICx0aXRsZSA9ICJKQUcxIFVNQVAiKQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSAiSkFHMiIscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKQogLHRpdGxlID0gIkpBRzIgVU1BUCIpCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9ICJETEwxIixyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpCiAsdGl0bGUgPSAiRExMMSBVTUFQIikKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIkhFUzQiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICx0aXRsZSA9ICJIRVM0IFVNQVAiKQpgYGAKCgojIEhFQUQtQU5ELU5FQ0stU1FVQU1PVVMKYGBge3Igd2FybmluZz1GQUxTRX0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIldQLUhFQUQtQU5ELU5FQ0stU1FVQU1PVVMtQ0VMTC1DQVJDSU5PTUEiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKYGBgCgoKCiMgQUNDMS8yCmBgYHtyfQpBQ0MxX2dlbmVzID0gYygiTVlDIiwgIlNPWDYiLCAiU09YOCIsICJDVE5ORDIiLCAiTk9UQ0gzIiwiQkNMMiIpCkFDQzJfZ2VuZXMgPSBjKCJUUDYzIiwiQ09MMTdBMSIsIlBER0ZBIiwgIkRLSzMiLCJFR0ZSIiwgIkFYTCIsIlBER0ZSQSIpCgpncz1hY2NAYXNzYXlzJFJOQUB2YXIuZmVhdHVyZXMKCmFjYzFfc2NvcmU9YXBwbHkoYWNjQGFzc2F5cyRSTkFAZGF0YVtBQ0MxX2dlbmVzLF0sMixtZWFuKQoKYWNjMl9zY29yZT1hcHBseShhY2NAYXNzYXlzJFJOQUBkYXRhW0FDQzJfZ2VuZXMsXSwyLG1lYW4pCmFjYz1BZGRNZXRhRGF0YShhY2MsYWNjMV9zY29yZS1hY2MyX3Njb3JlLCJhY2MxX292ZXJfYWNjMiIpCgpGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSAiYWNjMV9vdmVyX2FjYzIiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKYGBgCgojIE1vcmUgY2x1c3RlcnMgIHsudGFic2V0fQoKCgpgYGB7cn0KYWNjIDwtIEZpbmROZWlnaGJvcnMoYWNjLCBkaW1zID0gMToxMCxyZWR1Y3Rpb24gPSAiUENBX3BhdGh3YXlfc2NvcmVzIikKYWNjIDwtIEZpbmRDbHVzdGVycyhhY2MsIHJlc29sdXRpb24gPSAwLjUsZ3JhcGgubmFtZSA9ICJwYXRod2F5X3Njb3Jlc19zbm4iKQpgYGAKCmBgYHtyICByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsdCA9IERpbVBsb3QoYWNjLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIiksdGl0bGUgPSAiVU1BUCIpCkRpbVBsb3QoYWNjLGdyb3VwLmJ5ID0gImx1bV9vcl9teW8iLGNvbHMgPSBjKCJyZWQiLCJncmVlbiIsImdyZXkiKSxyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9ICJuRmVhdHVyZV9STkEiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKYGBgCgoKYGBge3J9CmFjYyA8LSBGaW5kTmVpZ2hib3JzKGFjYywgZGltcyA9IDE6MTApCmFjYyA8LSBGaW5kQ2x1c3RlcnMoYWNjLCByZXNvbHV0aW9uID0gMC41KQpgYGAKCmBgYHtyICByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsdCA9IERpbVBsb3QoYWNjKSx0aXRsZSA9ICJVTUFQIikKRGltUGxvdChhY2MsZ3JvdXAuYnkgPSAibHVtX29yX215byIsY29scyA9IGMoInJlZCIsImdyZWVuIiwiZ3JleSIpKQoKYGBgCgoKYGBge3IgcmVzdWx0cz0naGlkZSd9CmFsbF9tYXJrZXJzID0gRmluZEFsbE1hcmtlcnMob2JqZWN0ID0gYWNjLGxvZ2ZjLnRocmVzaG9sZCA9IDAsZGVuc2lmeSA9IFQsYXNzYXkgPSAicGF0aHdheV9zY29yZXMiKQpkZWdfbWFya2Vycz1hbGxfbWFya2VycyAlPiUgCiAgbXV0YXRlKGZkciA9IHAuYWRqdXN0KHBfdmFsLG1ldGhvZCA9ICJmZHIiKSklPiUgICNhZGQgZmRyIAogIGRwbHlyOjpmaWx0ZXIoZmRyPDAuMDUpICU+JSAgIGRwbHlyOjpmaWx0ZXIoYWJzKGF2Z19sb2cyRkMpPjEpCmBgYAoKYGBge3IgIHJlc3VsdHM9J2FzaXMnfQpmb3IgKGkgaW4gMDo0KSB7CnByaW50X3RhYihwbHQgPSBkZWdfbWFya2VycyAlPiUgZHBseXI6OmZpbHRlcihjbHVzdGVyID09IGkpICU+JSBkYXRhdGFibGUoKSx0aXRsZSA9IHBhc3RlKCJjbHVzdGVyIixpKSkKICB9CmBgYAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KYWNjID0gU2V0SWRlbnQob2JqZWN0ID0gYWNjLHZhbHVlID0gInBhdGh3YXlfc2NvcmVzX3Nubl9yZXMuMC41IikKZ2VuZXNfbWFya2VycyA9IEZpbmRBbGxNYXJrZXJzKG9iamVjdCA9IGFjYyxhc3NheSA9ICJSTkEiLG1pbi5jZWxscy5mZWF0dXJlID0gMTAsbG9nZmMudGhyZXNob2xkID0gMCxkZW5zaWZ5ID0gVCkKYWNjX2RlZyAgPSBnZW5lc19tYXJrZXJzICU+JSBtdXRhdGUoZmRyID0gcC5hZGp1c3QocF92YWwsbWV0aG9kID0gImZkciIpKSU+JSAjYWRkIGZkcgogICAgZHBseXI6OmZpbHRlcigoYWJzKGF2Z19sb2cyRkMpPjEgJiBmZHI8MC4wNSkpICAjZmlsdGVyIHNpZ25pZmljYW50CmBgYAoKIyB7LX0KCiMjIEdlbmVzIGluIERFRyB7LnRhYnNldH0KYGBge3IgIHJlc3VsdHM9J2FzaXMnfQpwcmludF90YWIocGx0ID0gYWNjX2RlZyAlPiUgZHBseXI6OmZpbHRlcihnZW5lICVpbiUgcmhvX2dlbmVzKSx0aXRsZSA9ICJSaG8gZ2VuZXMiLHN1YnRpdGxlX251bSA9IDMpCnByaW50X3RhYihwbHQgPSBhY2NfZGVnICU+JSBkcGx5cjo6ZmlsdGVyKGdlbmUgJWluJSBub3RjaF9nZW5lcyksdGl0bGUgPSAiTm90Y2ggZ2VuZXMiLHN1YnRpdGxlX251bSA9IDMpCgoKYGBgCgoKIyBNRVQgcGF0aHdheSBzY29yZQpgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIkJJT0NBUlRBLU1FVC1QQVRIV0FZIixyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIsbWF4LmN1dG9mZiA9IDAuMykKCmBgYAojIE1FVCBwYXRod2F5IHNjb3JlIGJhc2VkIG9uIGdlbmUgZXhwcmVzc2lvbgpgYGB7cn0KbWV0X2dlbmVzID0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIsY2F0ZWdvcnkgPSAiQzIiKSAlPiUgZHBseXI6OmZpbHRlcihnc19zdWJjYXQgIT0gIkNHUCIpICU+JWRwbHlyOjpmaWx0ZXIoZ3NfbmFtZSA9PSAiQklPQ0FSVEFfTUVUX1BBVEhXQVkiKSAlPiUgIGRwbHlyOjpkaXN0aW5jdChnc19uYW1lLCBnZW5lX3N5bWJvbCkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcHVsbChnZW5lX3N5bWJvbCkKCmdlbmVJZHM9IG1ldF9nZW5lcwpzY29yZSA8LSBhcHBseShhY2NAYXNzYXlzJFJOQUBkYXRhW2dlbmVJZHMsXSwyLG1lYW4pCmFjYz1BZGRNZXRhRGF0YShhY2Msc2NvcmUsIkJJT0NBUlRBX01FVF9QQVRIV0FZIikKRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIkJJT0NBUlRBX01FVF9QQVRIV0FZIiAscmVkdWN0aW9uID0gICJwYXRod2F5X3Njb3Jlc191bWFwIikKYGBgCgpgYGB7cn0KcGF0aHdheXNfc2NvcmVzWywiQklPQ0FSVEFfTUVUX1BBVEhXQVkiXQpwYXRod2F5c19zY29yZXNbLCJCSU9DQVJUQV9NRVRfUEFUSFdBWSJdICU+JSBzb3J0KCkKCmBgYAoKIyBuRmVhdHVyZXMgb2YgbWV0IGdlbmVzCmBgYHtyfQphc3NheSA9IEdldEFzc2F5KG9iamVjdCA9IGFjYykKbWV0X2Fzc2F5ID0gYXNzYXlbbWV0X2dlbmVzLF0KbWV0X3NldXJhdCA9IENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBtZXRfYXNzYXkpCmFjYzI9IGFjYwphY2MyJG5GZWF0dXJlX1JOQSA9IG1ldF9zZXVyYXQkbkZlYXR1cmVfUk5BCgpWbG5QbG90KGFjYzIsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgIm5Db3VudF9STkEiLCAicGVyY2VudC5tdCIpLCBuY29sID0gMykKCmBgYApgYGB7cn0KYWNjIDwtIHN1YnNldChhY2MsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDIwMDAgJiBwZXJjZW50Lm10IDwgMjApCmBgYAo=