Functions
scAssign_db <- function(tissue) {
lapply(c("dplyr","Seurat","HGNChelper"), library, character.only = T)
source("https://raw.githubusercontent.com/IanevskiAleksandr/sc-type/master/R/gene_sets_prepare.R"); source("https://raw.githubusercontent.com/IanevskiAleksandr/sc-type/master/R/sctype_score_.R")
db_ = "https://raw.githubusercontent.com/IanevskiAleksandr/sc-type/master/ScTypeDB_full.xlsx";
tissue = tissue # e.g. Immune system,Pancreas,Liver,Eye,Kidney,Brain,Lung,Adrenal,Heart,Intestine,Muscle,Placenta,Spleen,Stomach,Thymus
# prepare gene sets
gs_list = gene_sets_prepare(db_, tissue)
return(gs_list)
}
scAssign <- function(seuratObj,gs_list) {
es.max = sctype_score(scRNAseqData = seuratObj[["RNA"]]@scale.data, scaled = TRUE,
gs = gs_list$gs_positive, gs2 = gs_list$gs_negative)
# merge by cluster
cL_resutls = do.call("rbind", lapply(unique(seuratObj@meta.data$seurat_clusters), function(cl){
es.max.cl = sort(rowSums(es.max[ ,rownames(seuratObj@meta.data[seuratObj@meta.data$seurat_clusters==cl, ])]), decreasing = !0)
head(data.frame(cluster = cl, type = names(es.max.cl), scores = es.max.cl, ncells = sum(seuratObj@meta.data$seurat_clusters==cl)), 10)
}))
sctype_scores = cL_resutls %>% group_by(cluster) %>% top_n(n = 1, wt = scores)
# set low-confident (low ScType score) clusters to "unknown"
sctype_scores$type[as.numeric(as.character(sctype_scores$scores)) < sctype_scores$ncells/4] = "Unknown"
print(sctype_scores[,1:3])
seuratObj@meta.data$cell_identity = ""
for(j in unique(sctype_scores$cluster)){
cl_type = sctype_scores[sctype_scores$cluster==j,];
seuratObj@meta.data$cell_identity[seuratObj@meta.data$seurat_clusters == j] = as.character(cl_type$type[1])
}
return(seuratObj)
}
Data
acc_immune = LoadH5Seurat(file = "./Data/acc_immune_5KvarGenes.h5seurat")
Clustering
acc_immune <- FindClusters(acc_immune, resolution = 5,verbose = F, algorithm = 1)
DimPlot(acc_immune,label = T)

Cell
type assignment
cluster scores
gs_list = scAssign_db(tissue = "Immune system")
Warning in checkGeneSymbols(markers_all) : Human gene symbols should
be all upper-case except for the ‘orf’ in open reading frames. The case
of some letters was corrected. Warning in checkGeneSymbols(markers_all)
: x contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols Warning in checkGeneSymbols(markers_all) : x
contains non-approved gene symbols Warning in
checkGeneSymbols(markers_all) : x contains non-approved gene symbols
Warning in checkGeneSymbols(markers_all) : x contains non-approved gene
symbols Warning in checkGeneSymbols(markers_all) : x contains
non-approved gene symbols
acc_immune %<>% scAssign(gs_list = gs_list)
acc_immune %<>% SetIdent(value = "cell_identity")
print_tab(DimPlot(acc_immune,group.by = "cell_identity"),title = "UMAP")
UMAP

print_tab(plt = acc_immune$cell_identity %>% table() %>% as.data.frame(), title = "cell count")
cell count

NA
Markers
FeaturePlot(acc_immune, features = c("CD8A","MS4A1", "CD4","CD14","MS4A2"))

Markers
heatmaps
print_tab(plt =
DoHeatmap(acc_immune, features =c("CD8A","MS4A1", "CD4","CD14","MS4A2"), size = 3,slot = "data")
,title = "markers")
markers

print_tab(plt =
DoHeatmap(subset(acc_immune,subset = cell_identity == "Macrophages"), features
=gs_list$gs_positive$Macrophages, size = 3,slot = "data")
,title = "Macrophages markers")
Macrophages markers
Warning in DoHeatmap(subset(acc_immune, subset = cell_identity ==
“Macrophages”), : The following features were omitted as they were not
found in the data slot for the RNA assay: PF4

NA
Cell type
correlation
acc_immune = SetIdent(object = acc_immune,value = "cell_identity")
correlation = cor(AverageExpression(object = acc_immune) %>% as.data.frame())
colnames(correlation) <- gsub(pattern = "RNA.",replacement = "",x = colnames(correlation))
rownames(correlation) <- gsub(pattern = "RNA.",replacement = "",x = rownames(correlation))
pheatmap(mat = correlation,main = "Expression correlation")

Antigen
presenting machinery
apm_genes = c("HLA-A","HLA-B","HLA-C","B2M","TAP1","TAP2", "TAPBP")
apm_score = FetchData(acc_immune,vars = apm_genes,slot = "data") %>% rowMeans()
acc_immune = AddMetaData(object = acc_immune,metadata = apm_score,col.name = "APM_score")
print_tab(plt = FeaturePlot(acc_immune,features = apm_genes),title = "genes")
print_tab(plt = FeaturePlot(acc_immune,features = "APM_score"),title = "score")
Exhaustion markers
exhausted_genes = c("PDCD1","CD244","CD160","CTLA4","HAVCR2")
FeaturePlot(acc_immune,features = exhausted_genes)
Immune receptors
receptors = c("CCR3", "CCR4", "CCR10","CXCR2", "CXCR3", "CXCR4", "IL17A")
FeaturePlot(acc_immune,features = receptors)
CellphoneDB
acc_cancer_cells_pri = readRDS("/sci/labs/yotamd/lab_share/avishai.wizel/R_projects/ACC_microenv/Data/acc_cancer_no146_primaryonly15k_cancercells.rds")
acc_caf = readRDS("/sci/labs/yotamd/lab_share/ACC/ACC_sc/analysis/acc_tpm_nCount_mito_no146_cafs.rds")
acc_immune_pri = subset(acc_immune, subset = origin == "Primary")
# merge cancer and immune
common_genes = intersect(rownames(acc_cancer_cells_pri),rownames(acc_immune_pri)) %>% intersect(rownames(acc_caf_cells))
acc_cancer_and_cd45 = merge(acc_cancer_cells_pri[common_genes,],acc_immune_pri[common_genes,])
overlapping_cells = colnames(acc_cancer_cells_pri) %>% intersect(colnames(acc_caf))
acc_cancer_cd45_caf = merge(acc_cancer_and_cd45[common_genes,],acc_caf_cells[common_genes,!colnames(acc_caf_cells) %in% overlapping_cells] )
#write metadata
#create lum or myo
lum_over_myo = FetchData(object = acc_cancer_cells_pri,vars = "luminal_over_myo")
lum_over_myo$lum_or_myo = "Unknown"
lum_over_myo$lum_or_myo [lum_over_myo$luminal_over_myo>1] = "Luminal"
lum_over_myo$lum_or_myo [lum_over_myo$luminal_over_myo<(-1)] = "Myo"
lum_or_myo = lum_over_myo[,"lum_or_myo",drop = F]
names(lum_or_myo)[1] = "cell_identity"
lum_or_myo = lum_or_myo %>% filter(cell_identity != "Unknown") #remove unknown cells
# combine
immune_identity =FetchData(object = acc_immune_pri,vars = "cell_identity")
caf_identity =FetchData(object = acc_caf_cells,vars = "cell.type")
names(caf_identity)[1] = "cell_identity"
all_identity = do.call("rbind", list(lum_or_myo, immune_identity, caf_identity))
#rename and sort columns
all_identity$barcode_sample = rownames(all_identity)
all_identity = all_identity %>% rename(cell_type = cell_identity)
all_identity = all_identity[,c(2,1)]
write.table(x = all_identity,file = "./Data/CellphoneDB/metadata_primary.tsv",row.names =F,sep = "\t")
#write normalized counts
acc_cancer_cd45_caf = acc_cancer_cd45_caf[,rownames(all_identity)]
count_matrix = as.data.frame(acc_cancer_cd45_caf@assays[["RNA"]]@data)
fwrite(count_matrix, file = "./Data/CellphoneDB/counts_primary.txt",sep = "\t",row.names = T)
library(ktplots)
library(reticulate)
acc_cancer_cd45_caf$cell_type = all_identity[,2,drop = F] # add cells identities to Seurat
#read data:
pvals = py$pvalues
means = py$means
#or:
pvals = read.delim("./Data/CellphoneDB/output_primary/statistical_analysis_pvalues_08_01_2023_16:13:32.txt",check.names = F)
means = read.delim("./Data/CellphoneDB/output_primary/statistical_analysis_means_08_01_2023_16:13:32.txt",check.names = F)
significant
interactions heatmap
plot_cpdb_heatmap(scdata = acc_cancer_cd45_caf, idents = 'cell_type',pvals = pvals,main = "Number of significant interactions",alpha = 0.05,treeheight_row = 50)
trace(plot_cpdb,edit = T)
untrace(plot_cpdb)
plot_cpdb_with_col_clustering = plot_cpdb
to_insert =quote(
if (ncol(means_mat) > 2) {
d <- dist(as.data.frame(t(means_mat)))
h <- hclust(d)
means_mat <- means_mat[, h$order, drop = FALSE]
pvals_mat <- pvals_mat[, h$order, drop = FALSE]
plot(h, main = cell_type2)
}
)
body(plot_cpdb_with_col_clustering) <- body(plot_cpdb_with_col_clustering) %>% as.list %>% append(to_insert,after = 41) %>% as.call
trace(plot_cpdb_with_col_clustering,edit = T)
uniq_interactions <- function(cell_type1, cell_type2_a ,cell_type2_b, gene.family = NULL,genes = NULL) {
require(purrr)
a = plot_cpdb(cell_type1 = cell_type1, cell_type2 =cell_type2_a, scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
gene.family = gene.family,return_table = T, p.adjust.method = "fdr",keep_significant_only = T, genes = genes)
b = plot_cpdb(cell_type1 = cell_type1, cell_type2 = cell_type2_b, scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
gene.family = gene.family,return_table = T,p.adjust.method = "fdr",keep_significant_only = T, genes = genes)
all = list()
i=0
nelements = a$Var2 %>% unique() %>% length()
a_couples = a$Var2 %>% unique()%>% as.vector()
b_couples = b$Var2 %>% unique()%>% as.vector()
for (i in 1:nelements) {
sig_couples_a = a %>% filter(Var2 == a_couples[i]) %>% filter(pvals_adj <= 0.05) %>% pull(Var1) %>% as.vector()
sig_couples_b = b %>% filter(Var2 == b_couples[i]) %>% filter(pvals_adj <= 0.05) %>% pull(Var1) %>% as.vector()
only_in_a = sig_couples_a[! sig_couples_a %in% sig_couples_b]
all[[a_couples[i]]] = only_in_a
i = i+1
}
all = t(map_dfr(all, ~as_tibble(t(.)))) %>% as.data.frame() %>% set_names(a_couples)
return(all)
}
All
interactions



acc_immune <- StashIdent(object = acc_immune, save.name = "cell_identity")
With Seurat 3.X, stashing identity classes can be accomplished with the following:
acc_immune[["cell_identity"]] <- Idents(object = acc_immune)
SeuratDisk::SaveH5Seurat(object = acc_immune,filename = "./Data/acc_immune_5KvarGenes_V2_cellIdentity.h5seurat")
Creating h5Seurat file for version 3.1.5.9900
Adding counts for RNA
Adding data for RNA
Adding scale.data for RNA
Adding variable features for RNA
Adding feature-level metadata for RNA
Adding cell embeddings for pca
Adding loadings for pca
No projected loadings for pca
Adding standard deviations for pca
No JackStraw data for pca
Adding cell embeddings for umap
No loadings for umap
No projected loadings for umap
No standard deviations for umap
No JackStraw data for umap
Coinhibitory interactions
print_tab(plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Luminal', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
gene.family = 'coinhibitory',return_table = F,max_size = 4,p.adjust.method = "fdr",keep_significant_only = F,cluster_rows = F)+
ggtitle("coinhibitory Luminal"),title = "Luminal")
print_tab(plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Myo', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
gene.family = 'coinhibitory',return_table = F,max_size = 4,p.adjust.method = "fdr",keep_significant_only = F,cluster_rows = F)+
ggtitle("coinhibitory Myo"),title = "Myo")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'Luminal',cell_type2_b = "Myo",gene.family = "coinhibitory")
,title = "unique in luminal")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'Myo',cell_type2_b = "Luminal",gene.family = "coinhibitory")
,title = "unique in myo")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'CAF',cell_type2_b = "Myo|Luminal",gene.family = "coinhibitory")
,title = "unique in CAF")
Chemokines interactions
print_tab(
plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Luminal', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
gene.family = 'chemokines',return_table = F,max_size = 4,p.adjust.method = "fdr",keep_significant_only = F,cluster_rows = F)+
ggtitle("chemokines Luminal"),title = "Luminal")
print_tab(
plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Myo', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
gene.family = 'chemokines',return_table = F,max_size = 4,p.adjust.method = "fdr",keep_significant_only = F,cluster_rows = F)+
ggtitle("chemokines Myo"),title = "Myo")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'Luminal',cell_type2_b = "Myo",gene.family = "chemokines")
,title = "unique in luminal")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'Myo',cell_type2_b = "Luminal",gene.family = "chemokines")
,title = "unique in myo")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'CAF',cell_type2_b = "Myo|Luminal",gene.family = "chemokines")
,title = "unique in CAF")
Chemokine ligands
genes = c("CXCL1\\D", "CXCL2\\D","CXCL3\\D","CXCL17","C3","CXCL14")
print_tab(plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Myo', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
genes = genes,return_table = F,max_size = 4,p.adjust.method = "fdr" ,keep_significant_only = F)
,title = "Myo")
print_tab(plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Luminal', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
genes = genes,return_table = F,max_size = 4,p.adjust.method = "fdr" ,keep_significant_only = F)
,title = "Luminal")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'Luminal',cell_type2_b = "Myo", genes = genes)
,title = "unique in luminal")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'Myo',cell_type2_b = "Luminal", genes = genes)
,title = "unique in myo")
print_tab(plt =
uniq_interactions(cell_type1 = 'CD|B|FC',cell_type2_a = 'CAF',cell_type2_b = "Myo|Luminal", genes = genes)
,title = "unique in CAF")
CCL22
and CCL28
print_tab(plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Myo', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
genes = c("CCL22", "CCL28" ),return_table = F,max_size = 4,p.adjust.method = "fdr" ,keep_significant_only = F),title = "Myo")
print_tab(plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Luminal', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
genes = c("CCL22", "CCL28" ),return_table = F,max_size = 6,p.adjust.method = "fdr" ,keep_significant_only = F),title = "Luminal")
plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Myo', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
genes = c("JAG", "MYB" ),return_table = F,max_size = 4,p.adjust.method = "fdr" ,keep_significant_only = F)
plot_cpdb(cell_type1 = 'CD|B|FC', cell_type2 = 'Luminal', scdata = acc_cancer_cd45_caf,
idents = 'cell_type', means = means, pvals = pvals,
genes = c("JAG", "MYB" , "NOTCH","HES1","HEY"),return_table = F,max_size = 4,p.adjust.method = "fdr" ,keep_significant_only = F)
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCgoKIyBGdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CgpzY0Fzc2lnbl9kYiA8LSBmdW5jdGlvbih0aXNzdWUpIHsKICBsYXBwbHkoYygiZHBseXIiLCJTZXVyYXQiLCJIR05DaGVscGVyIiksIGxpYnJhcnksIGNoYXJhY3Rlci5vbmx5ID0gVCkKICBzb3VyY2UoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9JYW5ldnNraUFsZWtzYW5kci9zYy10eXBlL21hc3Rlci9SL2dlbmVfc2V0c19wcmVwYXJlLlIiKTsgc291cmNlKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vSWFuZXZza2lBbGVrc2FuZHIvc2MtdHlwZS9tYXN0ZXIvUi9zY3R5cGVfc2NvcmVfLlIiKQogIAogIGRiXyA9ICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vSWFuZXZza2lBbGVrc2FuZHIvc2MtdHlwZS9tYXN0ZXIvU2NUeXBlREJfZnVsbC54bHN4IjsKICB0aXNzdWUgPSB0aXNzdWUgIyBlLmcuIEltbXVuZSBzeXN0ZW0sUGFuY3JlYXMsTGl2ZXIsRXllLEtpZG5leSxCcmFpbixMdW5nLEFkcmVuYWwsSGVhcnQsSW50ZXN0aW5lLE11c2NsZSxQbGFjZW50YSxTcGxlZW4sU3RvbWFjaCxUaHltdXMgCiAgCiAgIyBwcmVwYXJlIGdlbmUgc2V0cwogIGdzX2xpc3QgPSBnZW5lX3NldHNfcHJlcGFyZShkYl8sIHRpc3N1ZSkKICByZXR1cm4oZ3NfbGlzdCkKfQoKc2NBc3NpZ24gPC0gZnVuY3Rpb24oc2V1cmF0T2JqLGdzX2xpc3QpIHsKICBlcy5tYXggPSBzY3R5cGVfc2NvcmUoc2NSTkFzZXFEYXRhID0gc2V1cmF0T2JqW1siUk5BIl1dQHNjYWxlLmRhdGEsIHNjYWxlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgZ3MgPSBnc19saXN0JGdzX3Bvc2l0aXZlLCBnczIgPSBnc19saXN0JGdzX25lZ2F0aXZlKSAKICAjIG1lcmdlIGJ5IGNsdXN0ZXIKICBjTF9yZXN1dGxzID0gZG8uY2FsbCgicmJpbmQiLCBsYXBwbHkodW5pcXVlKHNldXJhdE9iakBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzKSwgZnVuY3Rpb24oY2wpewogICAgICBlcy5tYXguY2wgPSBzb3J0KHJvd1N1bXMoZXMubWF4WyAscm93bmFtZXMoc2V1cmF0T2JqQG1ldGEuZGF0YVtzZXVyYXRPYmpAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycz09Y2wsIF0pXSksIGRlY3JlYXNpbmcgPSAhMCkKICAgICAgaGVhZChkYXRhLmZyYW1lKGNsdXN0ZXIgPSBjbCwgdHlwZSA9IG5hbWVzKGVzLm1heC5jbCksIHNjb3JlcyA9IGVzLm1heC5jbCwgbmNlbGxzID0gc3VtKHNldXJhdE9iakBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzPT1jbCkpLCAxMCkKICB9KSkKICBzY3R5cGVfc2NvcmVzID0gY0xfcmVzdXRscyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSAxLCB3dCA9IHNjb3JlcykgIAogIAogICMgc2V0IGxvdy1jb25maWRlbnQgKGxvdyBTY1R5cGUgc2NvcmUpIGNsdXN0ZXJzIHRvICJ1bmtub3duIgogIHNjdHlwZV9zY29yZXMkdHlwZVthcy5udW1lcmljKGFzLmNoYXJhY3RlcihzY3R5cGVfc2NvcmVzJHNjb3JlcykpIDwgc2N0eXBlX3Njb3JlcyRuY2VsbHMvNF0gPSAiVW5rbm93biIKICBwcmludChzY3R5cGVfc2NvcmVzWywxOjNdKQogIAogIHNldXJhdE9iakBtZXRhLmRhdGEkY2VsbF9pZGVudGl0eSA9ICIiCiAgZm9yKGogaW4gdW5pcXVlKHNjdHlwZV9zY29yZXMkY2x1c3RlcikpewogICAgY2xfdHlwZSA9IHNjdHlwZV9zY29yZXNbc2N0eXBlX3Njb3JlcyRjbHVzdGVyPT1qLF07IAogICAgc2V1cmF0T2JqQG1ldGEuZGF0YSRjZWxsX2lkZW50aXR5W3NldXJhdE9iakBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzID09IGpdID0gYXMuY2hhcmFjdGVyKGNsX3R5cGUkdHlwZVsxXSkKICB9CiAgcmV0dXJuKHNldXJhdE9iaikKfQoKYGBgCgojIERhdGEKCmBgYHtyfQphY2NfaW1tdW5lID0gTG9hZEg1U2V1cmF0KGZpbGUgPSAiLi9EYXRhL2FjY19pbW11bmVfNUt2YXJHZW5lcy5oNXNldXJhdCIpCmBgYAoKIyBDbHVzdGVyaW5nCmBgYHtyfQphY2NfaW1tdW5lIDwtIEZpbmRDbHVzdGVycyhhY2NfaW1tdW5lLCByZXNvbHV0aW9uID0gNSx2ZXJib3NlID0gRiwgYWxnb3JpdGhtID0gMSkKRGltUGxvdChhY2NfaW1tdW5lLGxhYmVsID0gVCkKYGBgCgoKCiMgQ2VsbCB0eXBlIGFzc2lnbm1lbnQgIHsudGFic2V0fQoKIyMgY2x1c3RlciBzY29yZXMKYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KZ3NfbGlzdCA9IHNjQXNzaWduX2RiKHRpc3N1ZSA9ICJJbW11bmUgc3lzdGVtIikKYWNjX2ltbXVuZSAlPD4lIHNjQXNzaWduKGdzX2xpc3QgPSBnc19saXN0KQpgYGAKCgoKYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KYWNjX2ltbXVuZSAlPD4lICBTZXRJZGVudCh2YWx1ZSA9ICJjZWxsX2lkZW50aXR5IikKcHJpbnRfdGFiKERpbVBsb3QoYWNjX2ltbXVuZSxncm91cC5ieSA9ICJjZWxsX2lkZW50aXR5IiksdGl0bGUgPSAiVU1BUCIpCnByaW50X3RhYihwbHQgPSBhY2NfaW1tdW5lJGNlbGxfaWRlbnRpdHkgJT4lIHRhYmxlKCkgJT4lIGFzLmRhdGEuZnJhbWUoKSwgdGl0bGUgPSAiY2VsbCBjb3VudCIpCmBgYAojIE1hcmtlcnMKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CkZlYXR1cmVQbG90KGFjY19pbW11bmUsIGZlYXR1cmVzID0gYygiQ0Q4QSIsIk1TNEExIiwgIkNENCIsIkNEMTQiLCJNUzRBMiIpKQpgYGAKCgoKIyBNYXJrZXJzIGhlYXRtYXBzIHsudGFic2V0fQpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMiwgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBEb0hlYXRtYXAoYWNjX2ltbXVuZSwgZmVhdHVyZXMgPWMoIkNEOEEiLCJNUzRBMSIsICJDRDQiLCJDRDE0IiwiTVM0QTIiKSwgc2l6ZSA9IDMsc2xvdCA9ICJkYXRhIikKICAgICAgICAgICx0aXRsZSA9ICJtYXJrZXJzIikKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRG9IZWF0bWFwKHN1YnNldChhY2NfaW1tdW5lLHN1YnNldCA9IGNlbGxfaWRlbnRpdHkgPT0gIk1hY3JvcGhhZ2VzIiksIGZlYXR1cmVzCiAgICAgICAgICAgICAgICAgICAgICA9Z3NfbGlzdCRnc19wb3NpdGl2ZSRNYWNyb3BoYWdlcywgc2l6ZSA9IDMsc2xvdCA9ICJkYXRhIikKICAgICAgICAgICx0aXRsZSA9ICJNYWNyb3BoYWdlcyBtYXJrZXJzIikKCmBgYAoKIyBDZWxsIHR5cGUgY29ycmVsYXRpb24KYGBge3J9CmFjY19pbW11bmUgPSBTZXRJZGVudChvYmplY3QgPSBhY2NfaW1tdW5lLHZhbHVlID0gImNlbGxfaWRlbnRpdHkiKQpjb3JyZWxhdGlvbiA9IGNvcihBdmVyYWdlRXhwcmVzc2lvbihvYmplY3QgPSBhY2NfaW1tdW5lKSAlPiUgYXMuZGF0YS5mcmFtZSgpKQpjb2xuYW1lcyhjb3JyZWxhdGlvbikgPC0gZ3N1YihwYXR0ZXJuID0gIlJOQS4iLHJlcGxhY2VtZW50ID0gIiIseCA9IGNvbG5hbWVzKGNvcnJlbGF0aW9uKSkKcm93bmFtZXMoY29ycmVsYXRpb24pIDwtIGdzdWIocGF0dGVybiA9ICJSTkEuIixyZXBsYWNlbWVudCA9ICIiLHggPSByb3duYW1lcyhjb3JyZWxhdGlvbikpCgpwaGVhdG1hcChtYXQgPSBjb3JyZWxhdGlvbixtYWluID0gIkV4cHJlc3Npb24gY29ycmVsYXRpb24iKQpgYGAKCiMgQW50aWdlbiBwcmVzZW50aW5nIG1hY2hpbmVyeSB7LnRhYnNldH0KYGBge3J9CmFwbV9nZW5lcyA9IGMoIkhMQS1BIiwiSExBLUIiLCJITEEtQyIsIkIyTSIsIlRBUDEiLCJUQVAyIiwgIlRBUEJQIikKYXBtX3Njb3JlID0gRmV0Y2hEYXRhKGFjY19pbW11bmUsdmFycyA9IGFwbV9nZW5lcyxzbG90ID0gImRhdGEiKSAlPiUgcm93TWVhbnMoKQphY2NfaW1tdW5lID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjX2ltbXVuZSxtZXRhZGF0YSA9IGFwbV9zY29yZSxjb2wubmFtZSA9ICJBUE1fc2NvcmUiKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwLCByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsdCA9IEZlYXR1cmVQbG90KGFjY19pbW11bmUsZmVhdHVyZXMgPSBhcG1fZ2VuZXMpLHRpdGxlID0gImdlbmVzIikKcHJpbnRfdGFiKHBsdCA9IEZlYXR1cmVQbG90KGFjY19pbW11bmUsZmVhdHVyZXMgPSAiQVBNX3Njb3JlIiksdGl0bGUgPSAic2NvcmUiKQpgYGAKCiMgRXhoYXVzdGlvbiBtYXJrZXJzCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQpleGhhdXN0ZWRfZ2VuZXMgPSBjKCJQRENEMSIsIkNEMjQ0IiwiQ0QxNjAiLCJDVExBNCIsIkhBVkNSMiIpCkZlYXR1cmVQbG90KGFjY19pbW11bmUsZmVhdHVyZXMgPSBleGhhdXN0ZWRfZ2VuZXMpCmBgYAojIEltbXVuZSByZWNlcHRvcnMKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CnJlY2VwdG9ycyA9IGMoIkNDUjMiLCAiQ0NSNCIsICJDQ1IxMCIsIkNYQ1IyIiwgIkNYQ1IzIiwgIkNYQ1I0IiwgIklMMTdBIikKRmVhdHVyZVBsb3QoYWNjX2ltbXVuZSxmZWF0dXJlcyA9IHJlY2VwdG9ycykKYGBgCgojIENlbGxwaG9uZURCCmBgYHtyfQphY2NfY2FuY2VyX2NlbGxzX3ByaSA9IHJlYWRSRFMoIi9zY2kvbGFicy95b3RhbWQvbGFiX3NoYXJlL2F2aXNoYWkud2l6ZWwvUl9wcm9qZWN0cy9BQ0NfbWljcm9lbnYvRGF0YS9hY2NfY2FuY2VyX25vMTQ2X3ByaW1hcnlvbmx5MTVrX2NhbmNlcmNlbGxzLnJkcyIpCmFjY19jYWYgPSByZWFkUkRTKCIvc2NpL2xhYnMveW90YW1kL2xhYl9zaGFyZS9BQ0MvQUNDX3NjL2FuYWx5c2lzL2FjY190cG1fbkNvdW50X21pdG9fbm8xNDZfY2Fmcy5yZHMiKQphY2NfaW1tdW5lX3ByaSA9IHN1YnNldChhY2NfaW1tdW5lLCBzdWJzZXQgPSBvcmlnaW4gPT0gIlByaW1hcnkiKQpgYGAKCgpgYGB7cn0KIyBtZXJnZSBjYW5jZXIgYW5kIGltbXVuZQpjb21tb25fZ2VuZXMgPSBpbnRlcnNlY3Qocm93bmFtZXMoYWNjX2NhbmNlcl9jZWxsc19wcmkpLHJvd25hbWVzKGFjY19pbW11bmVfcHJpKSkgJT4lIGludGVyc2VjdChyb3duYW1lcyhhY2NfY2FmX2NlbGxzKSkKYWNjX2NhbmNlcl9hbmRfY2Q0NSA9IG1lcmdlKGFjY19jYW5jZXJfY2VsbHNfcHJpW2NvbW1vbl9nZW5lcyxdLGFjY19pbW11bmVfcHJpW2NvbW1vbl9nZW5lcyxdKQpvdmVybGFwcGluZ19jZWxscyA9IGNvbG5hbWVzKGFjY19jYW5jZXJfY2VsbHNfcHJpKSAlPiUgaW50ZXJzZWN0KGNvbG5hbWVzKGFjY19jYWYpKSAKYWNjX2NhbmNlcl9jZDQ1X2NhZiA9IG1lcmdlKGFjY19jYW5jZXJfYW5kX2NkNDVbY29tbW9uX2dlbmVzLF0sYWNjX2NhZl9jZWxsc1tjb21tb25fZ2VuZXMsIWNvbG5hbWVzKGFjY19jYWZfY2VsbHMpICVpbiUgb3ZlcmxhcHBpbmdfY2VsbHNdICkKCmBgYAoKYGBge3J9CiAgI3dyaXRlIG1ldGFkYXRhCgojY3JlYXRlIGx1bSBvciBteW8KbHVtX292ZXJfbXlvID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjY19jYW5jZXJfY2VsbHNfcHJpLHZhcnMgPSAibHVtaW5hbF9vdmVyX215byIpCmx1bV9vdmVyX215byRsdW1fb3JfbXlvID0gIlVua25vd24iCmx1bV9vdmVyX215byRsdW1fb3JfbXlvIFtsdW1fb3Zlcl9teW8kbHVtaW5hbF9vdmVyX215bz4xXSAgPSAiTHVtaW5hbCIKbHVtX292ZXJfbXlvJGx1bV9vcl9teW8gW2x1bV9vdmVyX215byRsdW1pbmFsX292ZXJfbXlvPCgtMSldICA9ICJNeW8iCmx1bV9vcl9teW8gPSBsdW1fb3Zlcl9teW9bLCJsdW1fb3JfbXlvIixkcm9wID0gRl0KbmFtZXMobHVtX29yX215bylbMV0gPSAiY2VsbF9pZGVudGl0eSIKbHVtX29yX215byA9IGx1bV9vcl9teW8gJT4lIGZpbHRlcihjZWxsX2lkZW50aXR5ICE9ICJVbmtub3duIikgI3JlbW92ZSB1bmtub3duIGNlbGxzCiAgCiMgY29tYmluZQppbW11bmVfaWRlbnRpdHkgPUZldGNoRGF0YShvYmplY3QgPSBhY2NfaW1tdW5lX3ByaSx2YXJzID0gImNlbGxfaWRlbnRpdHkiKQpjYWZfaWRlbnRpdHkgPUZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FmX2NlbGxzLHZhcnMgPSAiY2VsbC50eXBlIikKbmFtZXMoY2FmX2lkZW50aXR5KVsxXSA9ICJjZWxsX2lkZW50aXR5IgphbGxfaWRlbnRpdHkgPSBkby5jYWxsKCJyYmluZCIsIGxpc3QobHVtX29yX215bywgaW1tdW5lX2lkZW50aXR5LCBjYWZfaWRlbnRpdHkpKQoKI3JlbmFtZSBhbmQgc29ydCBjb2x1bW5zCmFsbF9pZGVudGl0eSRiYXJjb2RlX3NhbXBsZSA9IHJvd25hbWVzKGFsbF9pZGVudGl0eSkKYWxsX2lkZW50aXR5ID0gYWxsX2lkZW50aXR5ICU+JSByZW5hbWUoY2VsbF90eXBlID0gY2VsbF9pZGVudGl0eSkKYWxsX2lkZW50aXR5ID0gYWxsX2lkZW50aXR5WyxjKDIsMSldCgoKYGBgCgpgYGB7cn0Kd3JpdGUudGFibGUoeCA9IGFsbF9pZGVudGl0eSxmaWxlID0gIi4vRGF0YS9DZWxscGhvbmVEQi9tZXRhZGF0YV9wcmltYXJ5LnRzdiIscm93Lm5hbWVzID1GLHNlcCA9ICJcdCIpCmBgYAoKYGBge3J9CiN3cml0ZSBub3JtYWxpemVkIGNvdW50cwphY2NfY2FuY2VyX2NkNDVfY2FmID0gYWNjX2NhbmNlcl9jZDQ1X2NhZlsscm93bmFtZXMoYWxsX2lkZW50aXR5KV0KY291bnRfbWF0cml4ID0gYXMuZGF0YS5mcmFtZShhY2NfY2FuY2VyX2NkNDVfY2FmQGFzc2F5c1tbIlJOQSJdXUBkYXRhKQpmd3JpdGUoY291bnRfbWF0cml4LCBmaWxlID0gIi4vRGF0YS9DZWxscGhvbmVEQi9jb3VudHNfcHJpbWFyeS50eHQiLHNlcCA9ICJcdCIscm93Lm5hbWVzID0gVCkKYGBgCgoKCgpgYGB7cHl0aG9uIGluY2x1ZGU9RkFMU0V9CiNkb3dubG9hZCBkYXRhYmFzZQppbXBvcnQgcGFuZGFzIGFzIHBkCmltcG9ydCBnbG9iCmltcG9ydCBvcwojIC0tIFZlcnNpb24gb2YgdGhlIGRhdGFic2UKY3BkYl92ZXJzaW9uID0gJ3Y0LjEuMCcKCiMgLS0gUGF0aCB3aGVyZSB0aGUgaW5wdXQgZmlsZXMgdG8gZ2VuZXJhdGUgdGhlIGRhdGFiYXNlIGFyZSBsb2NhdGVkCmNwZGJfdGFyZ2V0X2RpciA9IG9zLnBhdGguam9pbignLi9EYXRhL0NlbGxwaG9uZURCLycsIGNwZGJfdmVyc2lvbikKCiMgRG93bmxvYWQgZGF0YWJhc2UKZnJvbSBjZWxscGhvbmVkYi51dGlscyBpbXBvcnQgZGJfdXRpbHMKZGJfdXRpbHMuZG93bmxvYWRfZGF0YWJhc2UoY3BkYl90YXJnZXRfZGlyLCBjcGRiX3ZlcnNpb24pCmBgYAoKYGBge3B5dGhvbiBpbmNsdWRlPUZBTFNFfQpmcm9tIGNlbGxwaG9uZWRiLnNyYy5jb3JlLm1ldGhvZHMgaW1wb3J0IGNwZGJfc3RhdGlzdGljYWxfYW5hbHlzaXNfbWV0aG9kCgpkZWNvbnZvbHV0ZWQsIG1lYW5zLCBwdmFsdWVzLCBzaWduaWZpY2FudF9tZWFucyA9IGNwZGJfc3RhdGlzdGljYWxfYW5hbHlzaXNfbWV0aG9kLmNhbGwoCiAgICBjcGRiX2ZpbGVfcGF0aCA9ICIuL0RhdGEvQ2VsbHBob25lREIvdjQuMS4wL2NlbGxwaG9uZWRiLnppcCIsICAgICAgICAgICAgICAgICAjIG1hbmRhdG9yeTogQ2VsbFBob25lREIgZGF0YWJhc2UgemlwIGZpbGUuCiAgICBtZXRhX2ZpbGVfcGF0aCA9ICIuL0RhdGEvQ2VsbHBob25lREIvbWV0YWRhdGFfcHJpbWFyeS50c3YiLCAgICAgICAgICAgICAgICAgIyBtYW5kYXRvcnk6IHRzdiBmaWxlIGRlZmluaW5nIGJhcmNvZGVzIHRvIGNlbGwgbGFiZWwuCiAgICBjb3VudHNfZmlsZV9wYXRoID0gIi4vRGF0YS9DZWxscGhvbmVEQi9jb3VudHNfcHJpbWFyeS50eHQiLCAgICAgICAgICAgICAjIG1hbmRhdG9yeTogbm9ybWFsaXplZCBjb3VudCBtYXRyaXguCiAgICBjb3VudHNfZGF0YSA9ICdoZ25jX3N5bWJvbCcsICAgICAgICAgICAgICAgICAgICAgIyBkZWZpbmVzIHRoZSBnZW5lIGFubm90YXRpb24gaW4gY291bnRzIG1hdHJpeC4KICAgIG91dHB1dF9wYXRoID0gIi4vRGF0YS9DZWxscGhvbmVEQi9vdXRwdXRfcHJpbWFyeSIsICAgICAgICAgICAgICAgICAgICAgICAgICAjIFBhdGggdG8gc2F2ZSByZXN1bHRzLgopCmBgYCAgIAoKCmBgYHtyfQpsaWJyYXJ5KGt0cGxvdHMpCmxpYnJhcnkocmV0aWN1bGF0ZSkKYWNjX2NhbmNlcl9jZDQ1X2NhZiRjZWxsX3R5cGUgPSBhbGxfaWRlbnRpdHlbLDIsZHJvcCA9IEZdICMgYWRkIGNlbGxzIGlkZW50aXRpZXMgdG8gU2V1cmF0CgojcmVhZCBkYXRhOgpwdmFscyA9ICBweSRwdmFsdWVzCm1lYW5zID0gcHkkbWVhbnMKCiNvcjoKcHZhbHMgPSByZWFkLmRlbGltKCIuL0RhdGEvQ2VsbHBob25lREIvb3V0cHV0X3ByaW1hcnkvc3RhdGlzdGljYWxfYW5hbHlzaXNfcHZhbHVlc18wOF8wMV8yMDIzXzE2OjEzOjMyLnR4dCIsY2hlY2submFtZXMgPSBGKQptZWFucyA9IHJlYWQuZGVsaW0oIi4vRGF0YS9DZWxscGhvbmVEQi9vdXRwdXRfcHJpbWFyeS9zdGF0aXN0aWNhbF9hbmFseXNpc19tZWFuc18wOF8wMV8yMDIzXzE2OjEzOjMyLnR4dCIsY2hlY2submFtZXMgPSBGKQoKYGBgCgojIHNpZ25pZmljYW50IGludGVyYWN0aW9ucyBoZWF0bWFwCmBgYHtyfQpwbG90X2NwZGJfaGVhdG1hcChzY2RhdGEgPSBhY2NfY2FuY2VyX2NkNDVfY2FmLCBpZGVudHMgPSAnY2VsbF90eXBlJyxwdmFscyA9ICBwdmFscyxtYWluID0gIk51bWJlciBvZiBzaWduaWZpY2FudCBpbnRlcmFjdGlvbnMiLGFscGhhID0gMC4wNSx0cmVlaGVpZ2h0X3JvdyA9IDUwKQpgYGAKCgoKYGBge3J9Cgp0cmFjZShwbG90X2NwZGIsZWRpdCA9IFQpCnVudHJhY2UocGxvdF9jcGRiKQpwbG90X2NwZGJfd2l0aF9jb2xfY2x1c3RlcmluZyA9IHBsb3RfY3BkYgp0b19pbnNlcnQgPXF1b3RlKAogICBpZiAobmNvbChtZWFuc19tYXQpID4gMikgewogICAgICAgICAgICAgIGQgPC0gZGlzdChhcy5kYXRhLmZyYW1lKHQobWVhbnNfbWF0KSkpCiAgICAgICAgICAgICAgaCA8LSBoY2x1c3QoZCkKICAgICAgICAgICAgICBtZWFuc19tYXQgPC0gbWVhbnNfbWF0WywgaCRvcmRlciwgZHJvcCA9IEZBTFNFXQogICAgICAgICAgICAgIHB2YWxzX21hdCA8LSBwdmFsc19tYXRbLCBoJG9yZGVyLCBkcm9wID0gRkFMU0VdCiAgICAgICAgICAgICAgcGxvdChoLCBtYWluID0gY2VsbF90eXBlMikKICB9CikKCgpib2R5KHBsb3RfY3BkYl93aXRoX2NvbF9jbHVzdGVyaW5nKSA8LSBib2R5KHBsb3RfY3BkYl93aXRoX2NvbF9jbHVzdGVyaW5nKSAlPiUgYXMubGlzdCAlPiUgYXBwZW5kKHRvX2luc2VydCxhZnRlciA9ICA0MSkgJT4lIGFzLmNhbGwKdHJhY2UocGxvdF9jcGRiX3dpdGhfY29sX2NsdXN0ZXJpbmcsZWRpdCA9IFQpCmBgYAoKCgpgYGB7cn0KdW5pcV9pbnRlcmFjdGlvbnMgPC0gZnVuY3Rpb24oY2VsbF90eXBlMSwgY2VsbF90eXBlMl9hICxjZWxsX3R5cGUyX2IsIGdlbmUuZmFtaWx5ID0gTlVMTCxnZW5lcyA9IE5VTEwpIHsKICByZXF1aXJlKHB1cnJyKQogIGEgPSBwbG90X2NwZGIoY2VsbF90eXBlMSA9IGNlbGxfdHlwZTEsIGNlbGxfdHlwZTIgPWNlbGxfdHlwZTJfYSwgc2NkYXRhID0gYWNjX2NhbmNlcl9jZDQ1X2NhZiwKICAgICAgICAgICAgICAgICAgICAgIGlkZW50cyA9ICdjZWxsX3R5cGUnLCBtZWFucyA9IG1lYW5zLCBwdmFscyA9IHB2YWxzLAogICAgICAgICAgICAgICAgICAgICAgZ2VuZS5mYW1pbHkgPSBnZW5lLmZhbWlseSxyZXR1cm5fdGFibGUgPSBULCBwLmFkanVzdC5tZXRob2QgPSAiZmRyIixrZWVwX3NpZ25pZmljYW50X29ubHkgPSBULCBnZW5lcyA9IGdlbmVzKQogIAogIGIgPSBwbG90X2NwZGIoY2VsbF90eXBlMSA9IGNlbGxfdHlwZTEsIGNlbGxfdHlwZTIgPSBjZWxsX3R5cGUyX2IsIHNjZGF0YSA9IGFjY19jYW5jZXJfY2Q0NV9jYWYsCiAgICAgICAgICAgICAgICAgICAgICBpZGVudHMgPSAnY2VsbF90eXBlJywgbWVhbnMgPSBtZWFucywgcHZhbHMgPSBwdmFscywKICAgICAgICAgICAgICAgICAgICAgIGdlbmUuZmFtaWx5ID0gZ2VuZS5mYW1pbHkscmV0dXJuX3RhYmxlID0gVCxwLmFkanVzdC5tZXRob2QgPSAiZmRyIixrZWVwX3NpZ25pZmljYW50X29ubHkgPSBULCBnZW5lcyA9IGdlbmVzKQogIAogIAogIGFsbCA9IGxpc3QoKQogIGk9MAogIG5lbGVtZW50cyA9IGEkVmFyMiAlPiUgdW5pcXVlKCkgJT4lIGxlbmd0aCgpCiAgYV9jb3VwbGVzID0gYSRWYXIyICU+JSB1bmlxdWUoKSU+JSBhcy52ZWN0b3IoKSAgCiAgYl9jb3VwbGVzID0gYiRWYXIyICU+JSB1bmlxdWUoKSU+JSBhcy52ZWN0b3IoKSAgCiAgZm9yIChpIGluIDE6bmVsZW1lbnRzKSB7CiAgICBzaWdfY291cGxlc19hID0gYSAlPiUgZmlsdGVyKFZhcjIgPT0gYV9jb3VwbGVzW2ldKSAlPiUgZmlsdGVyKHB2YWxzX2FkaiA8PSAwLjA1KSAlPiUgIHB1bGwoVmFyMSkgJT4lIGFzLnZlY3RvcigpICAKICAgIHNpZ19jb3VwbGVzX2IgPSBiICU+JSBmaWx0ZXIoVmFyMiA9PSBiX2NvdXBsZXNbaV0pICU+JSBmaWx0ZXIocHZhbHNfYWRqIDw9IDAuMDUpICU+JSAgcHVsbChWYXIxKSAlPiUgYXMudmVjdG9yKCkgIAogICAgb25seV9pbl9hID0gc2lnX2NvdXBsZXNfYVshIHNpZ19jb3VwbGVzX2EgJWluJSBzaWdfY291cGxlc19iXQogICAgYWxsW1thX2NvdXBsZXNbaV1dXSA9IG9ubHlfaW5fYSAKICAgIGkgPSBpKzEKICB9CiAgYWxsID0gdChtYXBfZGZyKGFsbCwgfmFzX3RpYmJsZSh0KC4pKSkpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lICBzZXRfbmFtZXMoYV9jb3VwbGVzKQogIHJldHVybihhbGwpCn0KCmBgYCAgIAoKIyBBbGwgaW50ZXJhY3Rpb25zIHsudGFic2V0fQpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MjAsIHJlc3VsdHM9J2FzaXMnfQpwbG90X2NwZGJfd2l0aF9jb2xfY2x1c3RlcmluZyhjZWxsX3R5cGUxID0gJ0NEfEJ8TmF0dXJhbHxtb25vfE1hY3JvJywgY2VsbF90eXBlMiA9ICdMdW1pbmFsJywgc2NkYXRhID0gYWNjX2NhbmNlcl9jZDQ1X2NhZiwKICAgICAgICAgICAgICAgICAgICAgIGlkZW50cyA9ICdjZWxsX3R5cGUnLCBtZWFucyA9IG1lYW5zLCBwdmFscyA9IHB2YWxzLAogICAgICAgICAgICAgICAgICAgICAgZ2VuZS5mYW1pbHkgPSBOVUxMLHJldHVybl90YWJsZSA9IEYsbWF4X3NpemUgPSAzLHAuYWRqdXN0Lm1ldGhvZCA9ICJmZHIiLGtlZXBfc2lnbmlmaWNhbnRfb25seSA9IFQsY2x1c3Rlcl9yb3dzID0gVCkrCiAgICAgICAgICAgIGdndGl0bGUoImFsbCBMdW1pbmFsIikrCnRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkrCiAgcGxvdF9jcGRiX3dpdGhfY29sX2NsdXN0ZXJpbmcoY2VsbF90eXBlMSA9ICdDRHxCfE5hdHVyYWx8bW9ub3xNYWNybycsIGNlbGxfdHlwZTIgPSAnTXlvJywgc2NkYXRhID0gYWNjX2NhbmNlcl9jZDQ1X2NhZiwKICAgICAgICAgICAgICAgICAgICAgIGlkZW50cyA9ICdjZWxsX3R5cGUnLCBtZWFucyA9IG1lYW5zLCBwdmFscyA9IHB2YWxzLAogICAgICAgICAgICAgICAgICAgICAgZ2VuZS5mYW1pbHkgPSBOVUxMLHJldHVybl90YWJsZSA9IEYsbWF4X3NpemUgPSAzLHAuYWRqdXN0Lm1ldGhvZCA9ICJmZHIiLGtlZXBfc2lnbmlmaWNhbnRfb25seSA9IFQsY2x1c3Rlcl9yb3dzID0gVCkrCiAgICAgICAgICAgIGdndGl0bGUoImFsbCBNeW8iKSsKdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQogICAgICAKICAgICAgCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgcGxvdF9jcGRiKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsIGNlbGxfdHlwZTIgPSAnTHVtaW5hbCcsIHNjZGF0YSA9IGFjY19jYW5jZXJfY2Q0NV9jYWYsCiAgICAgICAgICAgICAgICAgICAgICBpZGVudHMgPSAnY2VsbF90eXBlJywgbWVhbnMgPSBtZWFucywgcHZhbHMgPSBwdmFscywKICAgICAgICAgICAgICAgICAgICAgIGdlbmUuZmFtaWx5ID0gTlVMTCxyZXR1cm5fdGFibGUgPSBGLG1heF9zaXplID0gMyxwLmFkanVzdC5tZXRob2QgPSAiZmRyIixrZWVwX3NpZ25pZmljYW50X29ubHkgPSBULGNsdXN0ZXJfcm93cyA9IFQpKwogICAgICAgICAgICBnZ3RpdGxlKCJhbGwgTHVtaW5hbCIpKwp0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpCiAgLHRpdGxlID0gIkx1bWluYWwiKQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBwbG90X2NwZGIoY2VsbF90eXBlMSA9ICdDRHxCfEZDJywgY2VsbF90eXBlMiA9ICdNeW8nLCBzY2RhdGEgPSBhY2NfY2FuY2VyX2NkNDVfY2FmLAogICAgICAgICAgICAgICAgICAgICAgaWRlbnRzID0gJ2NlbGxfdHlwZScsIG1lYW5zID0gbWVhbnMsIHB2YWxzID0gcHZhbHMsCiAgICAgICAgICAgICAgICAgICAgICBnZW5lLmZhbWlseSA9IE5VTEwscmV0dXJuX3RhYmxlID0gRixtYXhfc2l6ZSA9IDMscC5hZGp1c3QubWV0aG9kID0gImZkciIsa2VlcF9zaWduaWZpY2FudF9vbmx5ID0gVCxjbHVzdGVyX3Jvd3MgPSBUKSsKICAgICAgICAgICAgZ2d0aXRsZSgiYWxsIE15byIpKwp0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpCiAgLHRpdGxlID0gIkx1bWluYWwiKQoKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgcGxvdF9jcGRiKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsIGNlbGxfdHlwZTIgPSAnTXlvJywgc2NkYXRhID0gYWNjX2NhbmNlcl9jZDQ1X2NhZiwKICAgICAgICAgICAgICAgICAgICAgIGlkZW50cyA9ICdjZWxsX3R5cGUnLCBtZWFucyA9IG1lYW5zLCBwdmFscyA9IHB2YWxzLAogICAgICAgICAgICAgICAgICAgICAgZ2VuZS5mYW1pbHkgPSAnY29zdGltdWxhdG9yeScscmV0dXJuX3RhYmxlID0gRixtYXhfc2l6ZSA9IDMscC5hZGp1c3QubWV0aG9kID0gImZkciIsa2VlcF9zaWduaWZpY2FudF9vbmx5ID0gVCxjbHVzdGVyX3Jvd3MgPSBGKSsKICAgICAgICAgICAgZ2d0aXRsZSgiQ29zdGltdWxhdG9yeSBNeW8iKQogICx0aXRsZSA9ICJNeW8iKQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBwbG90X2NwZGIoY2VsbF90eXBlMSA9ICdDRHxCfEZDJywgY2VsbF90eXBlMiA9ICdDQUYnLCBzY2RhdGEgPSBhY2NfY2FuY2VyX2NkNDVfY2FmLAogICAgICAgICAgICAgICAgICAgICAgaWRlbnRzID0gJ2NlbGxfdHlwZScsIG1lYW5zID0gbWVhbnMsIHB2YWxzID0gcHZhbHMsCiAgICAgICAgICAgICAgICAgICAgICBnZW5lLmZhbWlseSA9ICdjb3N0aW11bGF0b3J5JyxyZXR1cm5fdGFibGUgPSBGLG1heF9zaXplID0gMyxwLmFkanVzdC5tZXRob2QgPSAiZmRyIixrZWVwX3NpZ25pZmljYW50X29ubHkgPSBULGNsdXN0ZXJfcm93cyA9IEYpKwogICAgICAgICAgICBnZ3RpdGxlKCJDb3N0aW11bGF0b3J5IENBRiIpCiAgLHRpdGxlID0gIkNBRiIpCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIHVuaXFfaW50ZXJhY3Rpb25zKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsY2VsbF90eXBlMl9hICA9ICdMdW1pbmFsJyxjZWxsX3R5cGUyX2IgPSAiTXlvIixnZW5lLmZhbWlseSA9ICJDb3N0aW11bGF0b3J5IikKLHRpdGxlID0gInVuaXF1ZSBpbiBsdW1pbmFsIikKCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIHVuaXFfaW50ZXJhY3Rpb25zKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsY2VsbF90eXBlMl9hICA9ICdNeW8nLGNlbGxfdHlwZTJfYiA9ICJMdW1pbmFsIixnZW5lLmZhbWlseSA9ICJDb3N0aW11bGF0b3J5IikKLHRpdGxlID0gInVuaXF1ZSBpbiBteW8iKQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICB1bmlxX2ludGVyYWN0aW9ucyhjZWxsX3R5cGUxID0gJ0NEfEJ8RkMnLGNlbGxfdHlwZTJfYSAgPSAnQ0FGJyxjZWxsX3R5cGUyX2IgPSAiTXlvfEx1bWluYWwiLGdlbmUuZmFtaWx5ID0gIkNvc3RpbXVsYXRvcnkiKQosdGl0bGUgPSAidW5pcXVlIGluIENBRiIpCmBgYAoKYGBge3J9CmFjY19pbW11bmUkc3BlY2lmaWNfaWRlbnRpdHkgPSBhY2NfaW1tdW5lJGNlbGxfaWRlbnRpdHkKYWNjX2ltbXVuZSAlPD4lIFNldElkZW50KHZhbHVlID0gInNwZWNpZmljX2lkZW50aXR5IikKYWNjX2ltbXVuZSA8LSBSZW5hbWVJZGVudHMoYWNjX2ltbXVuZSwgJ05haXZlIENENCsgVCBjZWxscycgPSAnQ0Q0KycsICdFZmZlY3RvciBDRDgrIFQgY2VsbHMnID0gJ0NEOCsnLCdDRDgrIE5LVC1saWtlIGNlbGxzJyA9ICJDRDgrIiwgJ05haXZlIENEOCsgVCBjZWxscycgPSAiQ0Q4KyIsICdFZmZlY3RvciBDRDQrIFQgY2VsbHMnID0gIkNENCsiKQphY2NfaW1tdW5lW1siY2VsbF9pZGVudGl0eSJdXSA8LSBJZGVudHMob2JqZWN0ID0gYWNjX2ltbXVuZSkKYGBgCgpgYGB7cn0KU2V1cmF0RGlzazo6U2F2ZUg1U2V1cmF0KG9iamVjdCA9IGFjY19pbW11bmUsZmlsZW5hbWUgPSAiLi9EYXRhL2FjY19pbW11bmVfNUt2YXJHZW5lc19WMl9jZWxsSWRlbnRpdHkuaDVzZXVyYXQiKQpgYGAKCiMgQ29pbmhpYml0b3J5IGludGVyYWN0aW9ucyB7LnRhYnNldH0KCmBgYHtyIGZpZy5oZWlnaHQ9NSxyZXN1bHRzPSdhc2lzJ30KCnByaW50X3RhYihwbG90X2NwZGIoY2VsbF90eXBlMSA9ICdDRHxCfEZDJywgY2VsbF90eXBlMiA9ICdMdW1pbmFsJywgc2NkYXRhID0gYWNjX2NhbmNlcl9jZDQ1X2NhZiwKICAgICAgICAgIGlkZW50cyA9ICdjZWxsX3R5cGUnLCBtZWFucyA9IG1lYW5zLCBwdmFscyA9IHB2YWxzLAogICAgICAgICAgZ2VuZS5mYW1pbHkgPSAnY29pbmhpYml0b3J5JyxyZXR1cm5fdGFibGUgPSBGLG1heF9zaXplID0gNCxwLmFkanVzdC5tZXRob2QgPSAiZmRyIixrZWVwX3NpZ25pZmljYW50X29ubHkgPSBGLGNsdXN0ZXJfcm93cyA9IEYpKwogIGdndGl0bGUoImNvaW5oaWJpdG9yeSBMdW1pbmFsIiksdGl0bGUgPSAiTHVtaW5hbCIpCgpwcmludF90YWIocGxvdF9jcGRiKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsIGNlbGxfdHlwZTIgPSAnTXlvJywgc2NkYXRhID0gYWNjX2NhbmNlcl9jZDQ1X2NhZiwKICAgICAgICAgIGlkZW50cyA9ICdjZWxsX3R5cGUnLCBtZWFucyA9IG1lYW5zLCBwdmFscyA9IHB2YWxzLAogICAgICAgICAgZ2VuZS5mYW1pbHkgPSAnY29pbmhpYml0b3J5JyxyZXR1cm5fdGFibGUgPSBGLG1heF9zaXplID0gNCxwLmFkanVzdC5tZXRob2QgPSAiZmRyIixrZWVwX3NpZ25pZmljYW50X29ubHkgPSBGLGNsdXN0ZXJfcm93cyA9IEYpKwogIGdndGl0bGUoImNvaW5oaWJpdG9yeSBNeW8iKSx0aXRsZSA9ICJNeW8iKQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICB1bmlxX2ludGVyYWN0aW9ucyhjZWxsX3R5cGUxID0gJ0NEfEJ8RkMnLGNlbGxfdHlwZTJfYSAgPSAnTHVtaW5hbCcsY2VsbF90eXBlMl9iID0gIk15byIsZ2VuZS5mYW1pbHkgPSAiY29pbmhpYml0b3J5IikKLHRpdGxlID0gInVuaXF1ZSBpbiBsdW1pbmFsIikKCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIHVuaXFfaW50ZXJhY3Rpb25zKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsY2VsbF90eXBlMl9hICA9ICdNeW8nLGNlbGxfdHlwZTJfYiA9ICJMdW1pbmFsIixnZW5lLmZhbWlseSA9ICJjb2luaGliaXRvcnkiKQosdGl0bGUgPSAidW5pcXVlIGluIG15byIpCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIHVuaXFfaW50ZXJhY3Rpb25zKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsY2VsbF90eXBlMl9hICA9ICdDQUYnLGNlbGxfdHlwZTJfYiA9ICJNeW98THVtaW5hbCIsZ2VuZS5mYW1pbHkgPSAiY29pbmhpYml0b3J5IikKLHRpdGxlID0gInVuaXF1ZSBpbiBDQUYiKQoKYGBgCgojIENoZW1va2luZXMgaW50ZXJhY3Rpb25zIHsudGFic2V0fQpgYGB7ciBmaWcuaGVpZ2h0PTYsIHJlc3VsdHM9J2FzaXMnfQpwcmludF90YWIoCiAgcGxvdF9jcGRiKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsIGNlbGxfdHlwZTIgPSAnTHVtaW5hbCcsIHNjZGF0YSA9IGFjY19jYW5jZXJfY2Q0NV9jYWYsCiAgICAgICAgICBpZGVudHMgPSAnY2VsbF90eXBlJywgbWVhbnMgPSBtZWFucywgcHZhbHMgPSBwdmFscywKICAgICAgICAgIGdlbmUuZmFtaWx5ID0gJ2NoZW1va2luZXMnLHJldHVybl90YWJsZSA9IEYsbWF4X3NpemUgPSA0LHAuYWRqdXN0Lm1ldGhvZCA9ICJmZHIiLGtlZXBfc2lnbmlmaWNhbnRfb25seSA9IEYsY2x1c3Rlcl9yb3dzID0gRikrCiAgZ2d0aXRsZSgiY2hlbW9raW5lcyBMdW1pbmFsIiksdGl0bGUgPSAiTHVtaW5hbCIpCgpwcmludF90YWIoCiAgcGxvdF9jcGRiKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsIGNlbGxfdHlwZTIgPSAnTXlvJywgc2NkYXRhID0gYWNjX2NhbmNlcl9jZDQ1X2NhZiwKICAgICAgICAgIGlkZW50cyA9ICdjZWxsX3R5cGUnLCBtZWFucyA9IG1lYW5zLCBwdmFscyA9IHB2YWxzLAogICAgICAgICAgZ2VuZS5mYW1pbHkgPSAnY2hlbW9raW5lcycscmV0dXJuX3RhYmxlID0gRixtYXhfc2l6ZSA9IDQscC5hZGp1c3QubWV0aG9kID0gImZkciIsa2VlcF9zaWduaWZpY2FudF9vbmx5ID0gRixjbHVzdGVyX3Jvd3MgPSBGKSsKICBnZ3RpdGxlKCJjaGVtb2tpbmVzIE15byIpLHRpdGxlID0gIk15byIpCgoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICB1bmlxX2ludGVyYWN0aW9ucyhjZWxsX3R5cGUxID0gJ0NEfEJ8RkMnLGNlbGxfdHlwZTJfYSAgPSAnTHVtaW5hbCcsY2VsbF90eXBlMl9iID0gIk15byIsZ2VuZS5mYW1pbHkgPSAiY2hlbW9raW5lcyIpCix0aXRsZSA9ICJ1bmlxdWUgaW4gbHVtaW5hbCIpCgoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICB1bmlxX2ludGVyYWN0aW9ucyhjZWxsX3R5cGUxID0gJ0NEfEJ8RkMnLGNlbGxfdHlwZTJfYSAgPSAnTXlvJyxjZWxsX3R5cGUyX2IgPSAiTHVtaW5hbCIsZ2VuZS5mYW1pbHkgPSAiY2hlbW9raW5lcyIpCix0aXRsZSA9ICJ1bmlxdWUgaW4gbXlvIikKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgdW5pcV9pbnRlcmFjdGlvbnMoY2VsbF90eXBlMSA9ICdDRHxCfEZDJyxjZWxsX3R5cGUyX2EgID0gJ0NBRicsY2VsbF90eXBlMl9iID0gIk15b3xMdW1pbmFsIixnZW5lLmZhbWlseSA9ICJjaGVtb2tpbmVzIikKLHRpdGxlID0gInVuaXF1ZSBpbiBDQUYiKQpgYGAKIyBDaGVtb2tpbmUgbGlnYW5kcyB7LnRhYnNldH0KYGBge3IgcmVzdWx0cz0nYXNpcyd9CmdlbmVzID0gYygiQ1hDTDFcXEQiLCAiQ1hDTDJcXEQiLCJDWENMM1xcRCIsIkNYQ0wxNyIsIkMzIiwiQ1hDTDE0IikKcHJpbnRfdGFiKHBsb3RfY3BkYihjZWxsX3R5cGUxID0gJ0NEfEJ8RkMnLCBjZWxsX3R5cGUyID0gJ015bycsIHNjZGF0YSA9IGFjY19jYW5jZXJfY2Q0NV9jYWYsCiAgICBpZGVudHMgPSAnY2VsbF90eXBlJywgbWVhbnMgPSBtZWFucywgcHZhbHMgPSBwdmFscywKIGdlbmVzID0gZ2VuZXMscmV0dXJuX3RhYmxlID0gRixtYXhfc2l6ZSA9IDQscC5hZGp1c3QubWV0aG9kID0gImZkciIgLGtlZXBfc2lnbmlmaWNhbnRfb25seSA9IEYpIAogLHRpdGxlID0gIk15byIpCgpwcmludF90YWIocGxvdF9jcGRiKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsIGNlbGxfdHlwZTIgPSAnTHVtaW5hbCcsIHNjZGF0YSA9IGFjY19jYW5jZXJfY2Q0NV9jYWYsCiAgICBpZGVudHMgPSAnY2VsbF90eXBlJywgbWVhbnMgPSBtZWFucywgcHZhbHMgPSBwdmFscywKICBnZW5lcyA9IGdlbmVzLHJldHVybl90YWJsZSA9IEYsbWF4X3NpemUgPSA0LHAuYWRqdXN0Lm1ldGhvZCA9ICJmZHIiICxrZWVwX3NpZ25pZmljYW50X29ubHkgPSBGKSAKLHRpdGxlID0gIkx1bWluYWwiKQoKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgdW5pcV9pbnRlcmFjdGlvbnMoY2VsbF90eXBlMSA9ICdDRHxCfEZDJyxjZWxsX3R5cGUyX2EgID0gJ0x1bWluYWwnLGNlbGxfdHlwZTJfYiA9ICJNeW8iLCBnZW5lcyA9IGdlbmVzKQosdGl0bGUgPSAidW5pcXVlIGluIGx1bWluYWwiKQoKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgdW5pcV9pbnRlcmFjdGlvbnMoY2VsbF90eXBlMSA9ICdDRHxCfEZDJyxjZWxsX3R5cGUyX2EgID0gJ015bycsY2VsbF90eXBlMl9iID0gIkx1bWluYWwiLCBnZW5lcyA9IGdlbmVzKQosdGl0bGUgPSAidW5pcXVlIGluIG15byIpCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIHVuaXFfaW50ZXJhY3Rpb25zKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsY2VsbF90eXBlMl9hICA9ICdDQUYnLGNlbGxfdHlwZTJfYiA9ICJNeW98THVtaW5hbCIsIGdlbmVzID0gZ2VuZXMpCix0aXRsZSA9ICJ1bmlxdWUgaW4gQ0FGIikKYGBgCiMgQ0NMMjIgYW5kIENDTDI4IHsudGFic2V0fQpgYGB7ciByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsb3RfY3BkYihjZWxsX3R5cGUxID0gJ0NEfEJ8RkMnLCBjZWxsX3R5cGUyID0gJ015bycsIHNjZGF0YSA9IGFjY19jYW5jZXJfY2Q0NV9jYWYsCiAgICBpZGVudHMgPSAnY2VsbF90eXBlJywgbWVhbnMgPSBtZWFucywgcHZhbHMgPSBwdmFscywKIGdlbmVzID0gYygiQ0NMMjIiLCAiQ0NMMjgiICkscmV0dXJuX3RhYmxlID0gRixtYXhfc2l6ZSA9IDQscC5hZGp1c3QubWV0aG9kID0gImZkciIgLGtlZXBfc2lnbmlmaWNhbnRfb25seSA9IEYpLHRpdGxlID0gIk15byIpCgpwcmludF90YWIocGxvdF9jcGRiKGNlbGxfdHlwZTEgPSAnQ0R8QnxGQycsIGNlbGxfdHlwZTIgPSAnTHVtaW5hbCcsIHNjZGF0YSA9IGFjY19jYW5jZXJfY2Q0NV9jYWYsCiAgICBpZGVudHMgPSAnY2VsbF90eXBlJywgbWVhbnMgPSBtZWFucywgcHZhbHMgPSBwdmFscywKICBnZW5lcyA9IGMoIkNDTDIyIiwgIkNDTDI4IiApLHJldHVybl90YWJsZSA9IEYsbWF4X3NpemUgPSA2LHAuYWRqdXN0Lm1ldGhvZCA9ICJmZHIiICxrZWVwX3NpZ25pZmljYW50X29ubHkgPSBGKSx0aXRsZSA9ICJMdW1pbmFsIikKCgoKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTZ9CnBsb3RfY3BkYihjZWxsX3R5cGUxID0gJ0NEfEJ8RkMnLCBjZWxsX3R5cGUyID0gJ015bycsIHNjZGF0YSA9IGFjY19jYW5jZXJfY2Q0NV9jYWYsCiAgICBpZGVudHMgPSAnY2VsbF90eXBlJywgbWVhbnMgPSBtZWFucywgcHZhbHMgPSBwdmFscywKIGdlbmVzID0gYygiSkFHIiwgIk1ZQiIgKSxyZXR1cm5fdGFibGUgPSBGLG1heF9zaXplID0gNCxwLmFkanVzdC5tZXRob2QgPSAiZmRyIiAsa2VlcF9zaWduaWZpY2FudF9vbmx5ID0gRikgCgpwbG90X2NwZGIoY2VsbF90eXBlMSA9ICdDRHxCfEZDJywgY2VsbF90eXBlMiA9ICdMdW1pbmFsJywgc2NkYXRhID0gYWNjX2NhbmNlcl9jZDQ1X2NhZiwKICAgIGlkZW50cyA9ICdjZWxsX3R5cGUnLCBtZWFucyA9IG1lYW5zLCBwdmFscyA9IHB2YWxzLAogIGdlbmVzID0gYygiSkFHIiwgIk1ZQiIgLCAiTk9UQ0giLCJIRVMxIiwiSEVZIikscmV0dXJuX3RhYmxlID0gRixtYXhfc2l6ZSA9IDQscC5hZGp1c3QubWV0aG9kID0gImZkciIgLGtlZXBfc2lnbmlmaWNhbnRfb25seSA9IEYpIAoKCmBgYAoKPHNjcmlwdCBzcmM9Imh0dHBzOi8vaHlwb3RoZXMuaXMvZW1iZWQuanMiIGFzeW5jPjwvc2NyaXB0PgoK