Parameters
suffix = ""
data_to_read = "./Data/acc_tpm_nCount_mito_no146_15k_cancercells.rds"
functions
library(stringi)
source_from_github(repositoy = "DEG_functions",version = "0.2.24")
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
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_'
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

NA
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
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
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
UMAP clusters
acc <- FindNeighbors(acc, dims = 1:10,reduction = "PCA_pathway_scores")
Computing nearest neighbor graph
Computing SNN
acc <- FindClusters(acc, resolution = 0.1,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.9052
Number of communities: 2
Elapsed time: 0 seconds
DimPlot(acc,reduction = "pathway_scores_umap")

pathways DEG
print_tab(plt = datatable(pathway_markers_deg),title = "all deg")
all deg
print_tab(plt = datatable(pathway_markers_deg %>% dplyr::filter(abs(avg_log2FC)>1)),title = "all deg FC>1")
genes
DEG
acc = SetIdent(object = acc,value = "pathway_scores_snn_res.0.1")
genes_markers = FindMarkers(object = acc,ident.1 = "0",ident.2 = "1",assay = "RNA",min.cells.feature = 10,logfc.threshold = 0,densify = T)
acc_deg = genes_markers %>% mutate(fdr = p.adjust(p_val,method = "fdr"))%>% #add fdr
dplyr::filter((avg_log2FC>1 & fdr<0.05) | (avg_log2FC< (-1) & fdr<0.05)) #filter significant
# enrichment_analysis(Differential_expression_genes = genes_markers,background = rownames(acc),fdr_Cutoff = 0.05,ident.1 = "0",ident.2 = "1")
cp_genes = msigdbr(species = "Homo sapiens", category = "C2") %>% dplyr::filter(gs_subcat != "CGP") %>% dplyr::distinct(gs_name, gene_symbol) %>% as.data.frame()
down = acc_deg %>%
dplyr::filter((avg_log2FC>1.5 & fdr<0.05)) %>%
rownames()
genes_vec_enrichment(genes = down,background = rownames(acc),homer = T,title = "test",custom_pathways = cp_genes)
up = acc_deg %>%
dplyr::filter((avg_log2FC<1.5 & fdr<0.05)) %>%
rownames()
genes_vec_enrichment(genes = up,background = rownames(acc),homer = T,title = "test",custom_pathways = cp_genes)
# genes = msigdbr(species = "Homo sapiens", category = "C2") %>% dplyr::filter(gs_subcat != "CGP" & grepl('REACTOME_RHO_GTPASE_CYCLE', gs_name)) %>% pull("gene_symbol") %>% unique()
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")
all DEG
print_tab(plt = acc_deg[rownames(acc_deg) %in% rho_genes,]%>% datatable(class = 'cell-border stripe') ,title = "Rho genes in DEG")
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")
NOTCH genes in DEG
NA
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")
NOTCH2 UMAP

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

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

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

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

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

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

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")

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")
UMAP

NA
for (i in 0:4) {
print_tab(plt = deg_markers %>% dplyr::filter(cluster == i) %>% datatable(),title = paste("cluster",i))
}
Genes
in DEG
print_tab(plt = acc_deg %>% dplyr::filter(gene %in% rho_genes),title = "Rho genes",subtitle_num = 3)
Rho genes
print_tab(plt = acc_deg %>% dplyr::filter(gene %in% notch_genes),title = "Notch genes",subtitle_num = 3)
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBkZl9wcmludDogIWV4cHIgcHJpbnQubWUgPC0gRFQ6OmRhdGF0YWJsZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKIyBQYXJhbWV0ZXJzCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpzdWZmaXggPSAiIgpkYXRhX3RvX3JlYWQgPSAiLi9EYXRhL2FjY190cG1fbkNvdW50X21pdG9fbm8xNDZfMTVrX2NhbmNlcmNlbGxzLnJkcyIKYGBgCgoKIyBmdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoc3RyaW5naSkKc291cmNlX2Zyb21fZ2l0aHViKHJlcG9zaXRveSA9ICJERUdfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMi4yNCIpCmBgYAoKIyBEYXRhCgpgYGB7cn0KYWNjID0gcmVhZFJEUyhmaWxlID0gZGF0YV90b19yZWFkKQphY2NfcHJpbWFyeSA9IHJlYWRSRFMoZmlsZSA9ICIuL0RhdGEvYWNjX2NhbmNlcl9ubzE0Nl9wcmltYXJ5b25seTE1a19jYW5jZXJjZWxscy5yZHMiKQoKKG1lc3NhZ2UoInJlYWRpbmcgJyIgJT4lIHBhc3RlMChkYXRhX3RvX3JlYWQgJT4lIGJhc2VuYW1lKCkpICU+JSBwYXN0ZTAoIiciKSkpCnBhdGh3YXlzX3Njb3JlcyA9IGZyZWFkKGZpbGUgPSAiLi9EYXRhL0FDQ19DYW5vbmljYWxfUGF0aHdheV9TY29yZXMudHh0IixzZXAgPSAiLCIpICU+JSBhcy5tYXRyaXgocm93bmFtZXM9MSkgJT4lIHQoKSAlPiUgIGFzLmRhdGEuZnJhbWUoKQpoYWxsbWFya19zY29yZXMgPSBmcmVhZChmaWxlID0gIi4vRGF0YS9BQ0NfSGFsbG1hcmtfUGF0aHdheV9TY29yZXMudHh0IixzZXAgPSAiLCIpICU+JSBhcy5tYXRyaXgocm93bmFtZXM9MSkgJT4lIHQoKSAlPiUgIGFzLmRhdGEuZnJhbWUoKQpgYGAKCmBgYHtyfQpsbl9saXN0ID0gYygiQUNDMjIuTE4uUDExIiwgIkFDQzIyLlAxMi5MTiIsIkFDQzcuUDEzIikKbG5fcGxhdGVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYyx2YXJzID0gIm9yaWcuaWRlbnQiKSAlPiUgbXV0YXRlKAogIHR1bW9yX3R5cGUgPSBpZl9lbHNlKGNvbmRpdGlvbiA9IG9yaWcuaWRlbnQgJWluJSBsbl9saXN0CiAgICAgICAgICAgICAgICAgICAgICAgLHRydWUgPSAiTE4iCiAgICAgICAgICAgICAgICAgICAgICAgLGZhbHNlID0gInByaW1hcnkiKSkKCmxuX3BsYXRlc1sib3JpZy5pZGVudCJdIDwtTlVMTAphY2M9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYyxtZXRhZGF0YSA9IGxuX3BsYXRlcykKYGBgCgoKYGBge3J9CnBhdGh3YXlzX3Njb3JlcyA9IGNiaW5kKHBhdGh3YXlzX3Njb3JlcyxoYWxsbWFya19zY29yZXMpCnBhdGh3YXlzX3Njb3JlcyA9IHBhdGh3YXlzX3Njb3Jlc1sgLCBjb2xTdW1zKGlzLm5hKHBhdGh3YXlzX3Njb3JlcykpPT0wXSAjcmVtb3ZlIGNvbHMgd2l0aCBOQQpwYXRod2F5c19zY29yZXMgPSBwYXRod2F5c19zY29yZXMgW3Jvd25hbWVzKHBhdGh3YXlzX3Njb3JlcykgJWluJSBjb2xuYW1lcyhhY2MpLF0gI3JlbW92ZSBjZWxscyBub3QgaW4gZGF0YXNldApwYXRod2F5c19zY29yZXMgPSAgcGF0aHdheXNfc2NvcmVzW29yZGVyKHJvdy5uYW1lcyhwYXRod2F5c19zY29yZXMpKSxdICNvcmRlciBjZWxscyBsaWtlIGRhdGFzZXQKYGBgCgojIERpbSByZWR1Y3Rpb24KYGBge3Igd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naGlkZScsZWNobz1UUlVFfQojIHJ1bi1kaW0tcmVkdWN0aW9uIG9uIGdlbmVzOgphY2MgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoYWNjLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCmFjYyA8LSBTY2FsZURhdGEoYWNjKQphY2MgPC0gUnVuUENBKGFjYyx2ZXJib3NlID0gRikKRWxib3dQbG90KGFjYykKYGBgCgoKYGBge3IgaW5jbHVkZT1GQUxTRX0KYWNjIDwtIFJ1blVNQVAoYWNjLCBkaW1zID0gMTo1KQpgYGAKCgoKYGBge3J9CnBhdGh3YXlfc2NvcmVzX2Fzc2F5IDwtIENyZWF0ZUFzc2F5T2JqZWN0KGNvdW50cyA9IHBhdGh3YXlzX3Njb3JlcyAlPiUgdCgpKSAjY3JlYXRlIGFuIGFzc2F5CmFjY1tbInBhdGh3YXlfc2NvcmVzIl1dID0gcGF0aHdheV9zY29yZXNfYXNzYXkKYGBgCmBgYHtyIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLGVjaG89VFJVRX0KIyBydW4tZGltLXJlZHVjdGlvbjoKYWNjIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKGFjYywgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwLGFzc2F5ID0gInBhdGh3YXlfc2NvcmVzIikKYWNjIDwtIFNjYWxlRGF0YShhY2MsYXNzYXkgPSAicGF0aHdheV9zY29yZXMiLGZlYXR1cmVzID0gcm93bmFtZXMoYWNjW1sicGF0aHdheV9zY29yZXMiXV0pKQphY2MgPC0gUnVuUENBKGFjYywgZmVhdHVyZXMgPSByb3duYW1lcyhhY2NbWyJwYXRod2F5X3Njb3JlcyJdXSksYXNzYXkgPSAicGF0aHdheV9zY29yZXMiLHJlZHVjdGlvbi5uYW1lID0gIlBDQV9wYXRod2F5X3Njb3JlcyIsdmVyYm9zZSA9IEYpCkVsYm93UGxvdChhY2MscmVkdWN0aW9uID0gICJQQ0FfcGF0aHdheV9zY29yZXMiKQpgYGAKCgpgYGB7cn0KYWNjIDwtIFJ1blVNQVAoYWNjLCBkaW1zID0gMTo1LHJlZHVjdGlvbiA9IlBDQV9wYXRod2F5X3Njb3JlcyIscmVkdWN0aW9uLm5hbWUgPSAicGF0aHdheV9zY29yZXNfdW1hcCIsdmVyYm9zZSA9IEYpCmBgYAoKCiMgYWNjIHVtYXBzIHsudGFic2V0fQoKYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsdCA9IERpbVBsb3QoYWNjLGdyb3VwLmJ5ID0gInBhdGllbnQuaWRlbnQiKSx0aXRsZSA9ICJnZW5lIGV4cHJlc3Npb24iKQpwcmludF90YWIocGx0ID0gRGltUGxvdChhY2MscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiLGdyb3VwLmJ5ID0gInBhdGllbnQuaWRlbnQiKSx0aXRsZSA9ICJwYXRod2F5cyBzY29yZXMiKQoKYGBgCmBgYHtyfQpncz1hY2NAYXNzYXlzJFJOQUB2YXIuZmVhdHVyZXMKCm15b3Njb3JlPWFwcGx5KGFjY0Bhc3NheXMkUk5BQHNjYWxlLmRhdGFbaW50ZXJzZWN0KGMoIlRQNjMiLCJUUDczIiwiQ0FWMSIsIkNESDMiLCJLUlQ1IiwiS1JUMTQiLCJBQ1RBMiIsIlRBR0xOIiwiTVlMSyIsIkRLSzMiKSxncyksXSwyLG1lYW4pCgpsZXNjb3JlPWFwcGx5KGFjY0Bhc3NheXMkUk5BQHNjYWxlLmRhdGFbaW50ZXJzZWN0KGMoIktJVCIsIkVIRiIsIkVMRjUiLCJLUlQ3IiwiQ0xETjMiLCJDTERONCIsIkNEMjQiLCJMR0FMUzMiLCJMQ04yIiwiU0xQSSIpLGdzKSxdLDIsbWVhbikKYWNjPUFkZE1ldGFEYXRhKGFjYyxsZXNjb3JlLW15b3Njb3JlLCJsdW1pbmFsX292ZXJfbXlvIikKYGBgCgpgYGB7cn0KI3NldCBsdW1fb3JfbXlvIG1ldGFkYXRhCmx1bWluYWxfb3Zlcl9teW8gPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjLHZhcnMgPSAibHVtaW5hbF9vdmVyX215byIpCmx1bWluYWxfb3Zlcl9teW8kbHVtX29yX215byAgPSBjYXNlX3doZW4obHVtaW5hbF9vdmVyX215byRsdW1pbmFsX292ZXJfbXlvID4xfiJsdW0iLGx1bWluYWxfb3Zlcl9teW8kbHVtaW5hbF9vdmVyX215byA8KC0xKX4ibXlvIixUUlVFfiJOQSIpCmx1bWluYWxfb3Zlcl9teW8kbHVtaW5hbF9vdmVyX215byA8LU5VTEwKYWNjPUFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYyxtZXRhZGF0YSA9IGx1bWluYWxfb3Zlcl9teW8sY29sLm5hbWUgPSAibHVtX29yX215byIpCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRSxyZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsdCA9IEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9ICJsdW1pbmFsX292ZXJfbXlvIixyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpLHRpdGxlID0gImx1bWluYWxfb3Zlcl9teW8iKQpwcmludF90YWIocGx0ID0gRGltUGxvdChhY2MsZ3JvdXAuYnkgPSAibHVtX29yX215byIsY29scyA9IGMoInJlZCIsImdyZWVuIiwiZ3JleSIpLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIiksdGl0bGUgPSAiY2VsbCB0eXBlIikKYGBgCiMgR2VuZXMgey50YWJzZXR9CgpgYGB7ciAgcmVzdWx0cz0nYXNpcyd9CnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gYygiRkdGMSIsIkZHRjIiLCJGR0YxMSIsIkZHRjEyIikscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKQogICAgICAgICAgLHRpdGxlID0gIkZHRiIpCgpwcmludF90YWIocGx0ID0gCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9IGMoIkZHRjE4IiwiRkdGMjAiLCJGR0YxNSIsIkZHRjIzIikscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKQogICAgICAgICAgLHRpdGxlID0gIkZHRiIpCgpwcmludF90YWIocGx0ID0gCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9IGMoIkVHRiIpLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICAgICAgICAgICx0aXRsZSA9ICJFR0YiKQoKcHJpbnRfdGFiKHBsdCA9IApGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSBjKCJOT1RDSDEiLCJOT1RDSDIiLCJOT1RDSDMiLCJOT1RDSDQiKSxyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpCiAgICAgICAgICAsdGl0bGUgPSAiTk9UQ0ggZ2VuZXMiKQoKcHJpbnRfdGFiKHBsdCA9IApGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSBjKCJIRVM0IiwiSEVZMSIsIkhFWTIiLCJOUkFSUCIpLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICAgICAgICAgICx0aXRsZSA9ICJOT1RDSCB0YXJnZXRzIikKCgpgYGAKCiMgQWxsIFBDJ3Mgey50YWJzZXR9CgpgYGB7ciBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTE0LCByZXN1bHRzPSdhc2lzJ30KZm9yIChpIGluIDE6OCkgewpwcmludF90YWIocGx0ID0gVml6RGltTG9hZGluZ3MoYWNjLCBkaW1zID0gaSwgcmVkdWN0aW9uID0gIlBDQV9wYXRod2F5X3Njb3JlcyIpLHRpdGxlID0gcGFzdGUoIlBDIiwgaSkpCn0KYGBgCgoKCiMgY3ljbGluZyBjZWxscyBjbHVzdHJpbmcgey50YWJzZXR9CmBgYHtyIHdhcm5pbmc9RkFMU0UscmVzdWx0cz0nYXNpcyd9CmhhbGxtYXJrX25hbWUgPSAiSEFMTE1BUktfRzJNX0NIRUNLUE9JTlQiCmdlbmVzZXRzICA9R1NFQUJhc2U6OmdldEdtdCgiLi9EYXRhL2guYWxsLnY3LjAuc3ltYm9scy5wbHVzY2MuZ210IikKdmFyX2ZlYXR1cmVzPWFjY0Bhc3NheXMkUk5BQHZhci5mZWF0dXJlcwpnZW5lSWRzPSBnZW5lc2V0c1tbaGFsbG1hcmtfbmFtZV1dQGdlbmVJZHMKc2NvcmUgPC0gYXBwbHkoYWNjQGFzc2F5cyRSTkFAZGF0YVtpbnRlcnNlY3QoZ2VuZUlkcyx2YXJfZmVhdHVyZXMpLF0sMixtZWFuKQphY2M9QWRkTWV0YURhdGEoYWNjLHNjb3JlLGhhbGxtYXJrX25hbWUpCgpwcmludF90YWIocGx0ID0gRmVhdHVyZVBsb3QoYWNjLCByZWR1Y3Rpb24gPSAidW1hcCIsZmVhdHVyZXMgPSAiSEFMTE1BUktfRzJNX0NIRUNLUE9JTlQiKSx0aXRsZSA9ICJieSBnZW5lcyIpCnByaW50X3RhYihwbHQgPSBGZWF0dXJlUGxvdChhY2MsIHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIixmZWF0dXJlcyA9ICJIQUxMTUFSS19HMk1fQ0hFQ0tQT0lOVCIpLHRpdGxlID0gImJ5IGdlbmVzIikKCmBgYAoKIyBVTUFQIGNsdXN0ZXJzCmBgYHtyfQphY2MgPC0gRmluZE5laWdoYm9ycyhhY2MsIGRpbXMgPSAxOjEwLHJlZHVjdGlvbiA9ICJQQ0FfcGF0aHdheV9zY29yZXMiKQphY2MgPC0gRmluZENsdXN0ZXJzKGFjYywgcmVzb2x1dGlvbiA9IDAuMSxncmFwaC5uYW1lID0gInBhdGh3YXlfc2NvcmVzX3NubiIpCmBgYAoKYGBge3J9CkRpbVBsb3QoYWNjLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKYGBgCiMgcGF0aHdheXMgREVHICB7LnRhYnNldH0KCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQpwYXRod2F5X21hcmtlcnMgPSBGaW5kTWFya2VycyhvYmplY3QgPSBhY2MsaWRlbnQuMSA9ICIwIixpZGVudC4yID0gIjEiLGFzc2F5ID0gInBhdGh3YXlfc2NvcmVzIixtaW4uY2VsbHMuZmVhdHVyZSA9IDEwLGxvZ2ZjLnRocmVzaG9sZCA9IDAsZGVuc2lmeSA9IFQpCnBhdGh3YXlfbWFya2Vyc19kZWcgPSBwYXRod2F5X21hcmtlcnMgJT4lCiAgbXV0YXRlKGZkciA9IHAuYWRqdXN0KHBfdmFsLG1ldGhvZCA9ICJmZHIiKSklPiUgICNhZGQgZmRyIAogIGRwbHlyOjpmaWx0ZXIoZmRyPDAuMDUpCgpgYGAKPGRpdiBzdHlsZT0nd2lkdGg6MTMwMHB4O21hcmdpbjogMCBhdXRvOyc+CgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KCnByaW50X3RhYihwbHQgPSBkYXRhdGFibGUocGF0aHdheV9tYXJrZXJzX2RlZyksdGl0bGUgPSAiYWxsIGRlZyIpCnByaW50X3RhYihwbHQgPSBkYXRhdGFibGUocGF0aHdheV9tYXJrZXJzX2RlZyAlPiUgZHBseXI6OmZpbHRlcihhYnMoYXZnX2xvZzJGQyk+MSkpLHRpdGxlID0gImFsbCBkZWcgRkM+MSIpCgpgYGAKPC9kaXY+CgoKIyBnZW5lcyBERUcgey50YWJzZXR9CgoKCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQphY2MgPSBTZXRJZGVudChvYmplY3QgPSBhY2MsdmFsdWUgPSAicGF0aHdheV9zY29yZXNfc25uX3Jlcy4wLjEiKQpnZW5lc19tYXJrZXJzID0gRmluZE1hcmtlcnMob2JqZWN0ID0gYWNjLGlkZW50LjEgPSAiMCIsaWRlbnQuMiA9ICIxIixhc3NheSA9ICJSTkEiLG1pbi5jZWxscy5mZWF0dXJlID0gMTAsbG9nZmMudGhyZXNob2xkID0gMCxkZW5zaWZ5ID0gVCkKYWNjX2RlZyAgPSBnZW5lc19tYXJrZXJzICU+JSBtdXRhdGUoZmRyID0gcC5hZGp1c3QocF92YWwsbWV0aG9kID0gImZkciIpKSU+JSAjYWRkIGZkcgogICAgZHBseXI6OmZpbHRlcigoYXZnX2xvZzJGQz4xICYgZmRyPDAuMDUpIHwgKGF2Z19sb2cyRkM8ICgtMSkgJiBmZHI8MC4wNSkpICAjZmlsdGVyIHNpZ25pZmljYW50CgpgYGAKCmBgYHtyfQojIGVucmljaG1lbnRfYW5hbHlzaXMoRGlmZmVyZW50aWFsX2V4cHJlc3Npb25fZ2VuZXMgPSBnZW5lc19tYXJrZXJzLGJhY2tncm91bmQgPSByb3duYW1lcyhhY2MpLGZkcl9DdXRvZmYgPSAwLjA1LGlkZW50LjEgPSAiMCIsaWRlbnQuMiA9ICIxIikKCgpjcF9nZW5lcyA9IG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiLCBjYXRlZ29yeSA9ICJDMiIpICU+JSBkcGx5cjo6ZmlsdGVyKGdzX3N1YmNhdCAhPSAiQ0dQIikgJT4lIGRwbHlyOjpkaXN0aW5jdChnc19uYW1lLCBnZW5lX3N5bWJvbCkgJT4lIGFzLmRhdGEuZnJhbWUoKQoKCmRvd24gPSAgYWNjX2RlZyAlPiUgCiAgICBkcGx5cjo6ZmlsdGVyKChhdmdfbG9nMkZDPjEuNSAmIGZkcjwwLjA1KSkgJT4lIAogICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKCkKCmdlbmVzX3ZlY19lbnJpY2htZW50KGdlbmVzID0gZG93bixiYWNrZ3JvdW5kID0gcm93bmFtZXMoYWNjKSxob21lciA9IFQsdGl0bGUgPSAidGVzdCIsY3VzdG9tX3BhdGh3YXlzID0gY3BfZ2VuZXMpCgp1cCA9ICBhY2NfZGVnICU+JSAKICAgIGRwbHlyOjpmaWx0ZXIoKGF2Z19sb2cyRkM8MS41ICYgZmRyPDAuMDUpKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoKQoKZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB1cCxiYWNrZ3JvdW5kID0gcm93bmFtZXMoYWNjKSxob21lciA9IFQsdGl0bGUgPSAidGVzdCIsY3VzdG9tX3BhdGh3YXlzID0gY3BfZ2VuZXMpCmBgYAoKCgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KIyBnZW5lcyA9IG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiLCBjYXRlZ29yeSA9ICJDMiIpICU+JSBkcGx5cjo6ZmlsdGVyKGdzX3N1YmNhdCAhPSAiQ0dQIiAmIGdyZXBsKCdSRUFDVE9NRV9SSE9fR1RQQVNFX0NZQ0xFJywgZ3NfbmFtZSkpICU+JSBwdWxsKCJnZW5lX3N5bWJvbCIpICU+JSB1bmlxdWUoKQoKCnJob19nZW5lcyA9IGMoIkNEQzQyIiwKIlJIT1EiLAoiUkhPSiIsCiJSSE9VViIsCidSSE9VJywKIlJIT1YiLAoiUkFDMSIsCiJSQUMyIiwKIlJBQzMiLAoiUkhPRyIsCiJSSE9CVEIxIiwKJ1JIT0JUQjInLAonUkhPQlRCMycsCidSSE9IJywKJ1JIT0EnLAonUkhPQicsCidSSE9DJywKJ1JORDEnLAonUk5EMicsCidSTkQzJywKJ1JIT0YnLAonUkhPRCcsCidSSE9GJykKCm5vdGNoX2dlbmVzID0gYygiSkFHMSIsIkpBRzIiLCJOT1RDSDMiLCJOT1RDSDIiLCJOT1RDSDEiLCJETEwxIiwiTVlCIiwiSEVTNCIsIkhFWTEiLCJIRVkyIiwiTlJBUlAiKQoKcHJpbnRfdGFiKHBsdCA9IGFjY19kZWcgJT4lIGRhdGF0YWJsZShjbGFzcyA9ICdjZWxsLWJvcmRlciBzdHJpcGUnKSAsdGl0bGUgPSAiYWxsIERFRyIpCnByaW50X3RhYihwbHQgPSBhY2NfZGVnW3Jvd25hbWVzKGFjY19kZWcpICVpbiUgIHJob19nZW5lcyxdJT4lIGRhdGF0YWJsZShjbGFzcyA9ICdjZWxsLWJvcmRlciBzdHJpcGUnKSAgICx0aXRsZSA9ICJSaG8gZ2VuZXMgaW4gREVHIikKcHJpbnRfdGFiKHBsdCA9IGFjY19kZWdbcm93bmFtZXMoYWNjX2RlZykgJWluJSAgbm90Y2hfZ2VuZXMsXSAlPiUgZGF0YXRhYmxlKGNsYXNzID0gJ2NlbGwtYm9yZGVyIHN0cmlwZScpICx0aXRsZSA9ICJOT1RDSCBnZW5lcyBpbiBERUciKQoKYGBgCgoKYGBge3J9CkRlZmF1bHRBc3NheShvYmplY3QgPSBhY2MpPC0gInBhdGh3YXlfc2NvcmVzIgpnZW5lc19leHByZXNzaW9uID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYyx2YXJzID0gYygiUkVBQ1RPTUUtUkhPLUdUUEFTRS1DWUNMRSIsIldQLUhFQUQtQU5ELU5FQ0stU1FVQU1PVVMtQ0VMTC1DQVJDSU5PTUEiKSkKY29yKGdlbmVzX2V4cHJlc3Npb24pCgp0b3BfY29ycmVsYXRlZCA8LSBmdW5jdGlvbihkYXRhc2V0LCBnZW5lcywgdGhyZXNob2xkLGFudGlfY29yID0gRikgewogIG1hcmtlcnNfZXhwcmVzc2lvbiA9IEZldGNoRGF0YShvYmplY3QgPSBkYXRhc2V0LHZhcnMgPSBnZW5lcyxzbG90ID0gImRhdGEiKSAjZ2V0IGdlbmVzIGV4cHJlc3Npb24KICBtYXJrZXJzX2F2ZXJhZ2UgPSByb3dNZWFucyhtYXJrZXJzX2V4cHJlc3Npb24pICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJlbmFtZSgiYXZlcmFnZSIgPSAxKSAjYXZlcmFnZSB0aGVtCiAgY29yX21hdCA9IGNvcihleHByZXNzaW9uICU+JSB0KCksIG1hcmtlcnNfYXZlcmFnZSklPiUgYXMuZGF0YS5mcmFtZSgpICNjb3Igd2l0aCBhbGwgZ2VuZXMKICBjb3JfbWF0ID0gY29yX21hdFtjb21wbGV0ZS5jYXNlcyhjb3JfbWF0KSwsZHJvcD1GXSAgJT4lIGFzLmRhdGEuZnJhbWUgJT4lICByZW5hbWUoImNvcnIiID0gMSkgI3JlbW92ZSByb3dzIHdpdGggTkEgaW4gYXQgbGVhc3Qgb25lIGNvbAogIGlmICh0aHJlc2hvbGQ8MSl7ICNpZiB0aHJlc2hvbGQgaXMgYmFzZWQgb24gcGVhcnNvbiBjb3JyZWxhdGlvbiAKICAgICAgaWYoYW50aV9jb3IgPT0gVCl7dG9wX2dlbmVzID0gICBjb3JfbWF0ICU+JSBhcy5kYXRhLmZyYW1lICU+JSBzZWxlY3QoMSkgJT4lIGRwbHlyOjpmaWx0ZXIoLjwgdGhyZXNob2xkKSAlPiUgcm93bmFtZXMoKX1lbHNlewogICAgICAgICAgdG9wX2dlbmVzID0gICBjb3JfbWF0ICU+JSBhcy5kYXRhLmZyYW1lICU+JSBzZWxlY3QoMSkgJT4lIGRwbHlyOjpmaWx0ZXIoLj4gdGhyZXNob2xkKSAlPiUgcm93bmFtZXMoKQogICAgICB9CiAgfWVsc2V7ICNpZiB0aHJlc2hvbGQgaXMgYmFzZWQgb24gdG9wIGNvcnJlbGF0ZWQgZ2VuZXMgCiAgICAgIGlmKGFudGlfY29yID09IFQpe3RocmVzaG9sZCAgPSB0aHJlc2hvbGQqKC0xKX0KICAgICAgdG9wX2dlbmVzID0gICBjb3JfbWF0ICU+JSAgdG9wX24odGhyZXNob2xkLGNvcnIpICU+JSByb3duYW1lcygpCiAgICAgIH0KICByZXR1cm4odG9wX2dlbmVzKQp9CmV4cHJlc3Npb24gPSBHZXRBc3NheURhdGEob2JqZWN0ID0gYWNjLGFzc2F5ID0gIlJOQSIsc2xvdCA9ICJkYXRhIikgJT4lIGFzLmRhdGEuZnJhbWUoKQoKdG9wX2NvcnJlbGF0ZWQoZGF0YXNldCA9IGFjYyxnZW5lcyA9ICJSTkQzIix0aHJlc2hvbGQgPSAyMCkKYGBgCgojVU1BUFMKYGBge3IgcmVzdWx0cz0nYXNpcyd9CnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIk5PVENIMiIscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKQogLHRpdGxlID0gIk5PVENIMiBVTUFQIikKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIlJORDMiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICx0aXRsZSA9ICJSTkQzIFVNQVAiKQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSAiSkFHMSIscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKQogLHRpdGxlID0gIkpBRzEgVU1BUCIpCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9ICJKQUcyIixyZWR1Y3Rpb24gPSAicGF0aHdheV9zY29yZXNfdW1hcCIpCiAsdGl0bGUgPSAiSkFHMiBVTUFQIikKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIkRMTDEiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKICx0aXRsZSA9ICJETEwxIFVNQVAiKQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSAiSEVTNCIscmVkdWN0aW9uID0gInBhdGh3YXlfc2NvcmVzX3VtYXAiKQogLHRpdGxlID0gIkhFUzQgVU1BUCIpCmBgYAoKCgojIEhFQUQtQU5ELU5FQ0stU1FVQU1PVVMKYGBge3Igd2FybmluZz1GQUxTRX0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gIldQLUhFQUQtQU5ELU5FQ0stU1FVQU1PVVMtQ0VMTC1DQVJDSU5PTUEiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKYGBgCgoKCiMgQUNDMS8yCmBgYHtyfQpBQ0MxX2dlbmVzID0gYygiTVlDIiwgIlNPWDYiLCAiU09YOCIsICJDVE5ORDIiLCAiTk9UQ0gzIiwiQkNMMiIpCkFDQzJfZ2VuZXMgPSBjKCJUUDYzIiwiQ09MMTdBMSIsIlBER0ZBIiwgIkRLSzMiLCJFR0ZSIiwgIkFYTCIsIlBER0ZSQSIpCgpncz1hY2NAYXNzYXlzJFJOQUB2YXIuZmVhdHVyZXMKCmFjYzFfc2NvcmU9YXBwbHkoYWNjQGFzc2F5cyRSTkFAZGF0YVtBQ0MxX2dlbmVzLF0sMixtZWFuKQoKYWNjMl9zY29yZT1hcHBseShhY2NAYXNzYXlzJFJOQUBkYXRhW0FDQzJfZ2VuZXMsXSwyLG1lYW4pCmFjYz1BZGRNZXRhRGF0YShhY2MsYWNjMV9zY29yZS1hY2MyX3Njb3JlLCJhY2MxX292ZXJfYWNjMiIpCgpGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSAiYWNjMV9vdmVyX2FjYzIiLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIikKYGBgCgojIE1vcmUgY2x1c3RlcnMgIHsudGFic2V0fQoKCgpgYGB7cn0KYWNjIDwtIEZpbmROZWlnaGJvcnMoYWNjLCBkaW1zID0gMToxMCxyZWR1Y3Rpb24gPSAiUENBX3BhdGh3YXlfc2NvcmVzIikKYWNjIDwtIEZpbmRDbHVzdGVycyhhY2MsIHJlc29sdXRpb24gPSAwLjUsZ3JhcGgubmFtZSA9ICJwYXRod2F5X3Njb3Jlc19zbm4iKQpgYGAKCmBgYHtyICByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsdCA9IERpbVBsb3QoYWNjLHJlZHVjdGlvbiA9ICJwYXRod2F5X3Njb3Jlc191bWFwIiksdGl0bGUgPSAiVU1BUCIpCmBgYApgYGB7ciByZXN1bHRzPSdoaWRlJ30KYWxsX21hcmtlcnMgPSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSBhY2MsbG9nZmMudGhyZXNob2xkID0gMCxkZW5zaWZ5ID0gVCxhc3NheSA9ICJwYXRod2F5X3Njb3JlcyIpCmRlZ19tYXJrZXJzPWFsbF9tYXJrZXJzICU+JSAKICBtdXRhdGUoZmRyID0gcC5hZGp1c3QocF92YWwsbWV0aG9kID0gImZkciIpKSU+JSAgI2FkZCBmZHIgCiAgZHBseXI6OmZpbHRlcihmZHI8MC4wNSkgJT4lICAgZHBseXI6OmZpbHRlcihhYnMoYXZnX2xvZzJGQyk+MSkKYGBgCgpgYGB7ciAgcmVzdWx0cz0nYXNpcyd9CmZvciAoaSBpbiAwOjQpIHsKcHJpbnRfdGFiKHBsdCA9IGRlZ19tYXJrZXJzICU+JSBkcGx5cjo6ZmlsdGVyKGNsdXN0ZXIgPT0gaSkgJT4lIGRhdGF0YWJsZSgpLHRpdGxlID0gcGFzdGUoImNsdXN0ZXIiLGkpKQogIH0KYGBgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQphY2MgPSBTZXRJZGVudChvYmplY3QgPSBhY2MsdmFsdWUgPSAicGF0aHdheV9zY29yZXNfc25uX3Jlcy4wLjUiKQpnZW5lc19tYXJrZXJzID0gRmluZEFsbE1hcmtlcnMob2JqZWN0ID0gYWNjLGFzc2F5ID0gIlJOQSIsbWluLmNlbGxzLmZlYXR1cmUgPSAxMCxsb2dmYy50aHJlc2hvbGQgPSAwLGRlbnNpZnkgPSBUKQphY2NfZGVnICA9IGdlbmVzX21hcmtlcnMgJT4lIG11dGF0ZShmZHIgPSBwLmFkanVzdChwX3ZhbCxtZXRob2QgPSAiZmRyIikpJT4lICNhZGQgZmRyCiAgICBkcGx5cjo6ZmlsdGVyKChhYnMoYXZnX2xvZzJGQyk+MSAmIGZkcjwwLjA1KSkgICNmaWx0ZXIgc2lnbmlmaWNhbnQKYGBgCgojIHstfQoKIyMgR2VuZXMgaW4gREVHIHsudGFic2V0fQpgYGB7ciAgcmVzdWx0cz0nYXNpcyd9CnByaW50X3RhYihwbHQgPSBhY2NfZGVnICU+JSBkcGx5cjo6ZmlsdGVyKGdlbmUgJWluJSByaG9fZ2VuZXMpLHRpdGxlID0gIlJobyBnZW5lcyIsc3VidGl0bGVfbnVtID0gMykKcHJpbnRfdGFiKHBsdCA9IGFjY19kZWcgJT4lIGRwbHlyOjpmaWx0ZXIoZ2VuZSAlaW4lIG5vdGNoX2dlbmVzKSx0aXRsZSA9ICJOb3RjaCBnZW5lcyIsc3VidGl0bGVfbnVtID0gMykKCgpgYGAK