Functions
library(stringi)
source_from_github(repositoy = "DEG_functions",version = "0.2.47")
ℹ SHA-1 hash of file is f5bb1cd741d13bded83fe3b6fd43169e29731216
Welcome to enrichR
Checking connection ...
Enrichr ... Connection is Live!
FlyEnrichr ... Connection is available!
WormEnrichr ... Connection is available!
YeastEnrichr ... Connection is available!
FishEnrichr ... Connection is available!
source_from_github(repositoy = "cNMF_functions",version = "0.4.0",script_name = "cnmf_functions_V3.R")
ℹ SHA-1 hash of file is 7b39dfd215cf7e1d29ee976ecc6bfa0e3f1532f6
Loading required package: reticulate
source_from_github(repositoy = "sc_general_functions",version = "0.1.28",script_name = "functions.R")
ℹ SHA-1 hash of file is 737683e4e0a82ffa22769bbd4a0842a271fe63fc
Loading required package: RColorBrewer
Data
library("readxl")
acc_all = readRDS(file = "./Data/acc_tpm_nCount_mito_no146_15k_alldata.rds")
acc_cancer_pri = readRDS(file = "./Data/acc_cancer_no146_primaryonly15k_cancercells.rds")
acc_cancer = readRDS(file = "./Data/acc_tpm_nCount_mito_no146_15k_cancercells.rds")
neuronal_signatures <- read_excel("./Data/Neuronal Signatures.xlsx",col_names =F)
neuronal_signatures %<>% t() %>% as.data.frame() %>% janitor::row_to_names(1) %>% filter(!row_number() == 1)
rownames(neuronal_signatures) <- NULL
colnames(neuronal_signatures) %<>% gsub(replacement = "", pattern = "_\\d.*") #remove any _numbers
colnames(neuronal_signatures) %<>% gsub(replacement = "", pattern = "\\(.*") #rename "(" to the end
colnames(neuronal_signatures) %<>% gsub(replacement = "_", pattern = " ") #rename all spaces
neuronal_pathways <- read_excel("./Data/Pathway analysis Gene sets.xlsx",col_names =F)
neuronal_pathways %<>% t() %>% as.data.frame() %>% janitor::row_to_names(1) %>% filter(!row_number() == 1) %>% as.list()
neuronal_pathways = lapply(neuronal_pathways, na.omit)
neuronal_pathways = lapply(neuronal_pathways, as.character)
ACC all cells UMAP
DimPlot(acc_all)

Neuronal
signatures
for (neural_name in colnames(neuronal_signatures)) {
genes = neuronal_signatures[,neural_name,drop=T]
# Assuming df is your data frame
pathways_scores = FetchData(object = acc_all,vars = genes,slot = "data") %>%
mutate_all(~ 2^.)%>% mutate_all(~ .-1) %>% #covert log(TPM+1) to TPM
rowwise() %>% mutate(score = mean(c_across(everything()))) #mean
acc_all %<>% AddMetaData(metadata = pathways_scores$score,col.name = neural_name)
}
Warning in FetchData.Seurat(object = acc_all, vars = genes, slot =
“data”) : The following requested variables were not found: SNHG29,
NOP53 Warning in FetchData.Seurat(object = acc_all, vars = genes, slot =
“data”) : The following requested variables were not found: NOP53
Warning in FetchData.Seurat(object = acc_all, vars = genes, slot =
“data”) : The following requested variables were not found: NOP53
plt = VlnPlot(object = acc_all,features = colnames(neuronal_signatures))
plt[[1]] = plt[[1]]+ ylab("TPM")
plt[[4]] = plt[[4]]+ ylab("TPM")
plt[[7]] = plt[[7]]+ ylab("TPM")
plt

Neuronal signatures NO
RP genes
neuronal_signatures_no_RP = lapply(neuronal_signatures %>% as.list(), function(x) {x[!startsWith(x = x,prefix = "RP")]})
names(neuronal_signatures_no_RP) = paste0(names(neuronal_signatures_no_RP),"_noRP")
for (neural_name in names(neuronal_signatures_no_RP)) {
genes = neuronal_signatures_no_RP[[neural_name]]
# Assuming df is your data frame
pathways_scores = FetchData(object = acc_all,vars = genes,slot = "data") %>%
mutate_all(~ 2^.)%>% mutate_all(~ .-1) %>% #covert log(TPM+1) to TPM
rowwise() %>% mutate(score = mean(c_across(everything()))) #mean
acc_all %<>% AddMetaData(metadata = pathways_scores$score,col.name = neural_name)
}
Warning in FetchData.Seurat(object = acc_all, vars = genes, slot = "data") :
The following requested variables were not found: SNHG29, NOP53
Warning in FetchData.Seurat(object = acc_all, vars = genes, slot = "data") :
The following requested variables were not found: NOP53
Warning in FetchData.Seurat(object = acc_all, vars = genes, slot = "data") :
The following requested variables were not found: NOP53
plt = VlnPlot(object = acc_all,features = names(neuronal_signatures_no_RP))
plt[[1]] = plt[[1]]+ ylab("TPM")
plt[[4]] = plt[[4]]+ ylab("TPM")
plt[[7]] = plt[[7]]+ ylab("TPM")
plt

Neuronal signatures expression
count.data <- GetAssayData(object = acc_all[["RNA"]], slot = "data")
count.data <- as.matrix(x = (2**count.data) - 1)
acc_tpm <- SetAssayData(
object = acc_all,
slot = "counts",
new.data = count.data,
assay = "RNA"
)
for (neural_name in colnames(neuronal_signatures)) {
genes = neuronal_signatures[,neural_name,drop=T]
# Assuming df is your data frame
print_tab(
DoHeatmap(object = acc_tpm,features = genes,slot = "counts",combine = T,disp.max = 5000)+ labs(fill = "TPM")
,title = neural_name,subtitle_num = 3)
}
Sympathetic_cholinergic_neuron

Sympathetic_noradrenergic_neuron

Peripheral_nervous_system_neuron_
Warning in DoHeatmap(object = acc_tpm, features = genes, slot =
“counts”, : The following features were omitted as they were not found
in the counts slot for the RNA assay: NOP53, SNHG29

Autonomic_neuron

Peripheral_neuron

Sensory_neuron
Warning in DoHeatmap(object = acc_tpm, features = genes, slot =
“counts”, : The following features were omitted as they were not found
in the counts slot for the RNA assay: NOP53

Adrenergic_neuron_tabula_sapiens
Warning in DoHeatmap(object = acc_tpm, features = genes, slot =
“counts”, : The following features were omitted as they were not found
in the counts slot for the RNA assay: NOP53

Peripheral_sensory_neuron

Parasympathetic_neuron

NA
WBC
wbc_cells = subset(acc_all, subset = cell.type == "WBC")
wbc_cells <- FindNeighbors(wbc_cells, dims = 1:10,verbose = F) %>% FindClusters(resolution = 0.5) %>% RunUMAP(dims = 1:10,verbose = F)
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
Number of nodes: 33
Number of edges: 528
Running Louvain algorithm...
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.5572
Number of communities: 2
Elapsed time: 0 seconds
DimPlot(wbc_cells)

WBC devided into 2 clusters:
VlnPlot(object = wbc_cells,features = c("CD79A","PTPRC"))

WBC Neuronal
signatures
acc_all$cluster_idents = acc_all@active.ident
data = FetchData(object = acc_all,vars = c("cluster_idents")) %>% mutate(cluster_idents = as.character(cluster_idents))
cluster_0_cells = subset(wbc_cells, subset = seurat_clusters == 0) %>% colnames()
cluster_1_cells = subset(wbc_cells, subset = seurat_clusters == 1) %>% colnames()
data[rownames(data) %in% cluster_0_cells,] ="WBC_cluster_0"
data[rownames(data) %in% cluster_1_cells,] ="WBC_cluster_1"
acc_all$cluster_idents = data
plt = VlnPlot(object = acc_all,features = colnames(neuronal_signatures),group.by = "cluster_idents")
plt[[1]] = plt[[1]]+ ylab("TPM")
plt[[4]] = plt[[4]]+ ylab("TPM")
plt[[7]] = plt[[7]]+ ylab("TPM")
plt

CD79A
neuronal_signatures correlation
library(ggpubr)
for (neural_name in colnames(neuronal_signatures)) {
wbc_cells = subset(acc_all, subset = cell.type == "WBC")
data = FetchData(object = wbc_cells,vars = c(neural_name,"CD79A"))
p = ggplot(data, aes_string(x=neural_name, y="CD79A")) +
geom_point()+
geom_smooth(method=lm) +
stat_cor()
print_tab(p,title = neural_name,subtitle_num = 3)
}
Sympathetic_cholinergic_neuron
geom_smooth() using formula ‘y ~ x’

Sympathetic_noradrenergic_neuron
geom_smooth() using formula ‘y ~ x’

Peripheral_nervous_system_neuron_
geom_smooth() using formula ‘y ~ x’

Autonomic_neuron
geom_smooth() using formula ‘y ~ x’

Peripheral_neuron
geom_smooth() using formula ‘y ~ x’

Sensory_neuron
geom_smooth() using formula ‘y ~ x’

Adrenergic_neuron_tabula_sapiens
geom_smooth() using formula ‘y ~ x’

Peripheral_sensory_neuron
geom_smooth() using formula ‘y ~ x’

Parasympathetic_neuron
geom_smooth() using formula ‘y ~ x’

NA
PTPRC
neuronal_signatures correlation
library(ggpubr)
for (neural_name in colnames(neuronal_signatures)) {
wbc_cells = subset(acc_all, subset = cell.type == "WBC")
data = FetchData(object = wbc_cells,vars = c(neural_name,"PTPRC"))
p = ggplot(data, aes_string(x=neural_name, y="PTPRC")) +
geom_point()+
geom_smooth(method=lm) +
stat_cor()
print_tab(p,title = neural_name,subtitle_num = 3)
}
Sympathetic_cholinergic_neuron
geom_smooth() using formula ‘y ~ x’

Sympathetic_noradrenergic_neuron
geom_smooth() using formula ‘y ~ x’

Peripheral_nervous_system_neuron_
geom_smooth() using formula ‘y ~ x’

Autonomic_neuron
geom_smooth() using formula ‘y ~ x’

Peripheral_neuron
geom_smooth() using formula ‘y ~ x’

Sensory_neuron
geom_smooth() using formula ‘y ~ x’

Adrenergic_neuron_tabula_sapiens
geom_smooth() using formula ‘y ~ x’

Peripheral_sensory_neuron
geom_smooth() using formula ‘y ~ x’

Parasympathetic_neuron
geom_smooth() using formula ‘y ~ x’

NA
PTPRC
neuronal_signatures correlation no RP
library(ggpubr)
for (neural_name in names(neuronal_signatures_no_RP)) {
wbc_cells = subset(acc_all, subset = cell.type == "WBC")
data = FetchData(object = wbc_cells,vars = c(neural_name,"PTPRC"))
p = ggplot(data, aes_string(x=neural_name, y="PTPRC")) +
geom_point()+
geom_smooth(method=lm) +
stat_cor()
print_tab(p,title = neural_name,subtitle_num = 3)
}
Sympathetic_cholinergic_neuron_noRP
geom_smooth() using formula ‘y ~ x’

Sympathetic_noradrenergic_neuron_noRP
geom_smooth() using formula ‘y ~ x’

Peripheral_nervous_system_neuron__noRP {.unnumbered }
geom_smooth() using formula ‘y ~ x’

Autonomic_neuron_noRP
geom_smooth() using formula ‘y ~ x’

Peripheral_neuron_noRP
geom_smooth() using formula ‘y ~ x’

Sensory_neuron_noRP
geom_smooth() using formula ‘y ~ x’

Adrenergic_neuron_tabula_sapiens_noRP
geom_smooth() using formula ‘y ~ x’

Peripheral_sensory_neuron_noRP
geom_smooth() using formula ‘y ~ x’

Parasympathetic_neuron_noRP
geom_smooth() using formula ‘y ~ x’

NA
FeaturePlot(object = wbc_cells,features = c("PTPRC", colnames(neuronal_signatures)[1:5]))

FeaturePlot(object = wbc_cells,features = c("PTPRC", colnames(neuronal_signatures)[6:9]))

Neuronal pathways in
ACC cancer cells
dim reduction
acc_cancer <- RunPCA(acc_cancer, features = VariableFeatures(object = acc_cancer),verbose = F)
ElbowPlot(acc_cancer)

acc_cancer <- FindNeighbors(acc_cancer, dims = 1:10,verbose = F) %>% FindClusters(resolution = 0.5) %>% RunUMAP(dims = 1:10,verbose = F)
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
Number of nodes: 951
Number of edges: 28888
Running Louvain algorithm...
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.8456
Number of communities: 7
Elapsed time: 0 seconds
DimPlot(acc_cancer,group.by = "patient.ident")

for (pathway_name in names(neuronal_pathways)) {
genes = neuronal_pathways[[pathway_name]]
pathways_scores = FetchData(object = acc_cancer,vars = genes,slot = "data") %>%
mutate_all(~ 2^.)%>% mutate_all(~ .-1) %>% #covert log(TPM+1) to TPM
rowwise() %>% mutate(score = mean(c_across(everything()))) #mean
acc_cancer %<>% AddMetaData(metadata = pathways_scores$score,col.name = pathway_name)
}
Warning in FetchData.Seurat(object = acc_cancer, vars = genes, slot = "data") :
The following requested variables were not found: ADORA3
Warning in FetchData.Seurat(object = acc_cancer, vars = genes, slot = "data") :
The following requested variables were not found: ADORA3
Warning in FetchData.Seurat(object = acc_cancer, vars = genes, slot = "data") :
The following requested variables were not found: ASCL1, PHOX2B
Warning in FetchData.Seurat(object = acc_cancer, vars = genes, slot = "data") :
The following requested variables were not found: ASCL1, PHOX2B
Warning in FetchData.Seurat(object = acc_cancer, vars = genes, slot = "data") :
The following requested variables were not found: ARX, HOXB1, ASCL1, PRLH, PHOX2B, ISX
Warning in FetchData.Seurat(object = acc_cancer, vars = genes, slot = "data") :
The following requested variables were not found: HOXB1, PHOX2B
Warning in FetchData.Seurat(object = acc_cancer, vars = genes, slot = "data") :
The following requested variables were not found: DRD3, MIR1-1, MIR133A1
Scores
UMAP
plt = FeaturePlot(object = acc_cancer,features = names(neuronal_pathways))
for (i in 1:(length(plt$patches$plots)+1)) {
plt[[i]] = plt[[i]] + theme(plot.title = element_text(size=10.5))+ labs(color='TPM')
}
print_tab(plt,title = "UMAP" ,subtitle_num = 3)
UMAP

plt = FeaturePlot(object = acc_cancer,features = names(neuronal_pathways),max.cutoff = 50)
for (i in 1:(length(plt$patches$plots)+1)) {
plt[[i]] = plt[[i]] + theme(plot.title = element_text(size=10.5))+ labs(color='TPM')
}
print_tab(plt,title = "UMAP max=50" ,subtitle_num = 3)
UMAP max=50

plt = FeaturePlot(object = acc_cancer,features = names(neuronal_pathways),max.cutoff = 250)
for (i in 1:(length(plt$patches$plots)+1)) {
plt[[i]] = plt[[i]] + theme(plot.title = element_text(size=10.5))+ labs(color='TPM')
}
print_tab(plt,title = "UMAP max=250" ,subtitle_num = 3)
UMAP max=250

plt = FeaturePlot(object = acc_cancer,features = names(neuronal_pathways))
for (i in 1:(length(plt$patches$plots)+1)) {
plt[[i]] = plt[[i]] + theme(plot.title = element_text(size=10.5))+ labs(color='TPM') + scale_color_gradientn(colours = rainbow(5))
}
Scale for ‘colour’ is already present. Adding another scale for
‘colour’, which will replace the existing scale. Scale for ‘colour’ is
already present. Adding another scale for ‘colour’, which will replace
the existing scale. Scale for ‘colour’ is already present. Adding
another scale for ‘colour’, which will replace the existing scale. Scale
for ‘colour’ is already present. Adding another scale for ‘colour’,
which will replace the existing scale. Scale for ‘colour’ is already
present. Adding another scale for ‘colour’, which will replace the
existing scale. Scale for ‘colour’ is already present. Adding another
scale for ‘colour’, which will replace the existing scale. Scale for
‘colour’ is already present. Adding another scale for ‘colour’, which
will replace the existing scale. Scale for ‘colour’ is already present.
Adding another scale for ‘colour’, which will replace the existing
scale.
print_tab(plt,title = "UMAP rainbow" ,subtitle_num = 3)
UMAP rainbow

NA
Scores violin
plt = VlnPlot(object = acc_cancer,features = names(neuronal_pathways),group.by = "patient.ident")+theme(plot.title = element_text(size = 3))
for (i in 1:(length(plt$patches$plots)+1)) {
plt[[i]] = plt[[i]] + theme(plot.title = element_text(size=9.5))
if (i %in% c(1,4,7)) {
plt[[i]] = plt[[i]]+ylab("TPM")
}
}
print(plt)

ACC2 DEG
acc_cancer_pri = SetIdent(object = acc_cancer_pri,value = "patient.ident")
markers = FindMarkers(object = acc_cancer_pri,ident.1 = "ACC2",features = VariableFeatures(acc_cancer_pri),densify = T)
volcano_plot(de_genes = markers,max_names = 10,title = "",ident1 = "ACC2",ident2 = "PNI patients",show_graph = F,log2fc_cutoff = 1)

GSEA- canonical
pathways
up = up in ACC2
library(hypeR)
genesets <- msigdb_download("Homo sapiens",category="H") %>% append( msigdb_download("Homo sapiens",category="C2",subcategory = "CP"))
all_genes = markers %>% arrange(desc(avg_log2FC)) %>% select("avg_log2FC")
ranked_list <- setNames(all_genes$avg_log2FC, rownames(all_genes))
hyp_obj <- hypeR_fgsea(signature = ranked_list,genesets = genesets,up_only = F)
hyp_dots(hyp_obj)
$up
$dn


GSEA- GO BP
genesets <- msigdb_download("Homo sapiens",category="H") %>% append( msigdb_download("Homo sapiens",category="C5",subcategory = "GO:BP"))
all_genes = markers %>% arrange(desc(avg_log2FC)) %>% select("avg_log2FC")
ranked_list <- setNames(all_genes$avg_log2FC, rownames(all_genes))
hyp_obj <- hypeR_fgsea(signature = ranked_list,genesets = genesets,up_only = F)
Warning in fgsea::fgseaMultilevel(stats = signature, pathways = gsets.obj$genesets, :
For some of the pathways the P-values were likely overestimated. For such pathways log2err is set to NA.
hyp_dots(hyp_obj)
$up
$dn


Neuronal pathways in
ACC primary cancer cells
lum_score = FetchData(acc_cancer_pri,"luminal_over_myo")
lum_score %<>% mutate (lum_or_myo = case_when(
luminal_over_myo > 1 ~ "luminal",
luminal_over_myo < (-1) ~ "myo",
TRUE ~ "unknown"))
acc_cancer_pri %<>% AddMetaData(metadata = lum_score$lum_or_myo,col.name = "lum_or_myo")
for (pathway_name in names(neuronal_pathways)) {
genes = neuronal_pathways[[pathway_name]]
pathways_scores = FetchData(object = acc_cancer_pri,vars = genes,slot = "data") %>%
mutate_all(~ 2^.)%>% mutate_all(~ .-1) %>% #covert log(TPM+1) to TPM
rowwise() %>% mutate(score = mean(c_across(everything()))) #mean
acc_cancer_pri %<>% AddMetaData(metadata = pathways_scores$score,col.name = pathway_name)
}
Warning in FetchData.Seurat(object = acc_cancer_pri, vars = genes, slot = "data") :
The following requested variables were not found: ADORA3
Warning in FetchData.Seurat(object = acc_cancer_pri, vars = genes, slot = "data") :
The following requested variables were not found: ADORA3
Warning in FetchData.Seurat(object = acc_cancer_pri, vars = genes, slot = "data") :
The following requested variables were not found: ASCL1, PHOX2B
Warning in FetchData.Seurat(object = acc_cancer_pri, vars = genes, slot = "data") :
The following requested variables were not found: ASCL1, PHOX2B
Warning in FetchData.Seurat(object = acc_cancer_pri, vars = genes, slot = "data") :
The following requested variables were not found: ARX, HOXB1, ASCL1, PRLH, PHOX2B, ISX
Warning in FetchData.Seurat(object = acc_cancer_pri, vars = genes, slot = "data") :
The following requested variables were not found: HOXB1, PHOX2B
Warning in FetchData.Seurat(object = acc_cancer_pri, vars = genes, slot = "data") :
The following requested variables were not found: DRD3, MIR1-1, MIR133A1
plt = FeaturePlot(object = acc_cancer_pri,features = names(neuronal_pathways))
for (i in 1:(length(plt$patches$plots)+1)) {
plt[[i]] = plt[[i]] + theme(plot.title = element_text(size=10.5))+ labs(color='TPM')
}
print(plt)

Lum vs
Myo
library(ggpubr)
for (pathway in names(neuronal_pathways)) {
data = FetchData(object = acc_cancer_pri,vars = c("lum_or_myo",pathway)) %>% filter(lum_or_myo != "unknown")
p = ggboxplot(data, x = "lum_or_myo", y =pathway,
palette = "jco",
add = "jitter")+
stat_compare_means(method = "wilcox.test",comparisons = list(c("luminal","myo")))+ stat_summary(fun.data = function(x) data.frame(y=max(x)*1.2, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("TPM")+ggtitle(pathway)
print_tab(p,title = pathway)
}
GOBP_NOREPINEPHRINE_SECRETION

GOBP_NOREPINEPHRINE_TRANSPORT

GOBP_NORADRENERGIC_NEURON_DEVELOPMENT

GOBP_NORADRENERGIC_NEURON_DIFFERENTIATION

GOBP_AUTONOMIC_NERVOUS_SYSTEM_DEVELOPMENT

GOBP_PARASYMPATHETIC_NERVOUS_SYSTEM_DEVELOPMENT

GOBP_ADRENERGIC_RECEPTOR_SIGNALING_PATHWAY

GOMF_BETA_2_ADRENERGIC_RECEPTOR_BINDING

NA
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKIyBGdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoc3RyaW5naSkKc291cmNlX2Zyb21fZ2l0aHViKHJlcG9zaXRveSA9ICJERUdfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMi40NyIpCnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiY05NRl9mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC40LjAiLHNjcmlwdF9uYW1lID0gImNubWZfZnVuY3Rpb25zX1YzLlIiKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gInNjX2dlbmVyYWxfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMS4yOCIsc2NyaXB0X25hbWUgPSAiZnVuY3Rpb25zLlIiKQpgYGAKCiMgRGF0YQoKYGBge3J9CmxpYnJhcnkoInJlYWR4bCIpCmFjY19hbGwgPSByZWFkUkRTKGZpbGUgPSAiLi9EYXRhL2FjY190cG1fbkNvdW50X21pdG9fbm8xNDZfMTVrX2FsbGRhdGEucmRzIikKYWNjX2NhbmNlcl9wcmkgPSByZWFkUkRTKGZpbGUgPSAiLi9EYXRhL2FjY19jYW5jZXJfbm8xNDZfcHJpbWFyeW9ubHkxNWtfY2FuY2VyY2VsbHMucmRzIikKYWNjX2NhbmNlciA9IHJlYWRSRFMoZmlsZSA9ICIuL0RhdGEvYWNjX3RwbV9uQ291bnRfbWl0b19ubzE0Nl8xNWtfY2FuY2VyY2VsbHMucmRzIikKCgpuZXVyb25hbF9zaWduYXR1cmVzIDwtIHJlYWRfZXhjZWwoIi4vRGF0YS9OZXVyb25hbCBTaWduYXR1cmVzLnhsc3giLGNvbF9uYW1lcyA9RikKbmV1cm9uYWxfc2lnbmF0dXJlcyAgJTw+JSAgdCgpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIGphbml0b3I6OnJvd190b19uYW1lcygxKSAlPiUgIGZpbHRlcighcm93X251bWJlcigpID09IDEpCnJvd25hbWVzKG5ldXJvbmFsX3NpZ25hdHVyZXMpIDwtIE5VTEwKY29sbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlcykgICAlPD4lICBnc3ViKHJlcGxhY2VtZW50ID0gIiIsIHBhdHRlcm4gPSAiX1xcZC4qIikgI3JlbW92ZSBhbnkgX251bWJlcnMKY29sbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlcykgICAlPD4lICBnc3ViKHJlcGxhY2VtZW50ID0gIiIsIHBhdHRlcm4gPSAiXFwoLioiKSAjcmVuYW1lICIoIiB0byB0aGUgZW5kCmNvbG5hbWVzKG5ldXJvbmFsX3NpZ25hdHVyZXMpICAgJTw+JSAgZ3N1YihyZXBsYWNlbWVudCA9ICJfIiwgcGF0dGVybiA9ICIgIikgI3JlbmFtZSBhbGwgc3BhY2VzCgpuZXVyb25hbF9wYXRod2F5cyA8LSByZWFkX2V4Y2VsKCIuL0RhdGEvUGF0aHdheSBhbmFseXNpcyBHZW5lIHNldHMueGxzeCIsY29sX25hbWVzID1GKQpuZXVyb25hbF9wYXRod2F5cyAgJTw+JSAgdCgpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIGphbml0b3I6OnJvd190b19uYW1lcygxKSAlPiUgIGZpbHRlcighcm93X251bWJlcigpID09IDEpICAlPiUgIGFzLmxpc3QoKSAKbmV1cm9uYWxfcGF0aHdheXMgPSBsYXBwbHkobmV1cm9uYWxfcGF0aHdheXMsIG5hLm9taXQpCm5ldXJvbmFsX3BhdGh3YXlzID0gbGFwcGx5KG5ldXJvbmFsX3BhdGh3YXlzLCBhcy5jaGFyYWN0ZXIpCgpgYGAKCiMgQUNDIGFsbCBjZWxscyBVTUFQCgpgYGB7cn0KRGltUGxvdChhY2NfYWxsKQpgYGAKCiMgTmV1cm9uYWwgc2lnbmF0dXJlcwoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CmZvciAobmV1cmFsX25hbWUgaW4gY29sbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlcykpIHsKICBnZW5lcyA9IG5ldXJvbmFsX3NpZ25hdHVyZXNbLG5ldXJhbF9uYW1lLGRyb3A9VF0KICAjIEFzc3VtaW5nIGRmIGlzIHlvdXIgZGF0YSBmcmFtZQoKICAKICBwYXRod2F5c19zY29yZXMgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2FsbCx2YXJzID0gZ2VuZXMsc2xvdCA9ICJkYXRhIikgJT4lIAogICAgbXV0YXRlX2FsbCh+IDJeLiklPiUgbXV0YXRlX2FsbCh+IC4tMSkgJT4lICAjY292ZXJ0IGxvZyhUUE0rMSkgdG8gVFBNCiAgICByb3d3aXNlKCkgJT4lIG11dGF0ZShzY29yZSA9IG1lYW4oY19hY3Jvc3MoZXZlcnl0aGluZygpKSkpICNtZWFuCiAgYWNjX2FsbCAgJTw+JSBBZGRNZXRhRGF0YShtZXRhZGF0YSA9IHBhdGh3YXlzX3Njb3JlcyRzY29yZSxjb2wubmFtZSA9IG5ldXJhbF9uYW1lKQp9CmBgYAoKYGBge3IgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTEyfQpwbHQgPSBWbG5QbG90KG9iamVjdCA9IGFjY19hbGwsZmVhdHVyZXMgPSBjb2xuYW1lcyhuZXVyb25hbF9zaWduYXR1cmVzKSkKcGx0W1sxXV0gPSBwbHRbWzFdXSsgeWxhYigiVFBNIikKcGx0W1s0XV0gPSBwbHRbWzRdXSsgeWxhYigiVFBNIikKcGx0W1s3XV0gPSBwbHRbWzddXSsgeWxhYigiVFBNIikKcGx0CmBgYAoKIyBOZXVyb25hbCBzaWduYXR1cmVzIE5PIFJQIGdlbmVzCgpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9Cm5ldXJvbmFsX3NpZ25hdHVyZXNfbm9fUlAgPSBsYXBwbHkobmV1cm9uYWxfc2lnbmF0dXJlcyAlPiUgYXMubGlzdCgpLCAgZnVuY3Rpb24oeCkge3hbIXN0YXJ0c1dpdGgoeCA9IHgscHJlZml4ID0gIlJQIildfSkKbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlc19ub19SUCkgPSAgcGFzdGUwKG5hbWVzKG5ldXJvbmFsX3NpZ25hdHVyZXNfbm9fUlApLCJfbm9SUCIpCmZvciAobmV1cmFsX25hbWUgaW4gbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlc19ub19SUCkpIHsKICBnZW5lcyA9IG5ldXJvbmFsX3NpZ25hdHVyZXNfbm9fUlBbW25ldXJhbF9uYW1lXV0KICAjIEFzc3VtaW5nIGRmIGlzIHlvdXIgZGF0YSBmcmFtZQoKICBwYXRod2F5c19zY29yZXMgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2FsbCx2YXJzID0gZ2VuZXMsc2xvdCA9ICJkYXRhIikgJT4lIAogICAgbXV0YXRlX2FsbCh+IDJeLiklPiUgbXV0YXRlX2FsbCh+IC4tMSkgJT4lICAjY292ZXJ0IGxvZyhUUE0rMSkgdG8gVFBNCiAgICByb3d3aXNlKCkgJT4lIG11dGF0ZShzY29yZSA9IG1lYW4oY19hY3Jvc3MoZXZlcnl0aGluZygpKSkpICNtZWFuCiAgYWNjX2FsbCAgJTw+JSBBZGRNZXRhRGF0YShtZXRhZGF0YSA9IHBhdGh3YXlzX3Njb3JlcyRzY29yZSxjb2wubmFtZSA9IG5ldXJhbF9uYW1lKQp9CgpwbHQgPSBWbG5QbG90KG9iamVjdCA9IGFjY19hbGwsZmVhdHVyZXMgPSBuYW1lcyhuZXVyb25hbF9zaWduYXR1cmVzX25vX1JQKSkKcGx0W1sxXV0gPSBwbHRbWzFdXSsgeWxhYigiVFBNIikKcGx0W1s0XV0gPSBwbHRbWzRdXSsgeWxhYigiVFBNIikKcGx0W1s3XV0gPSBwbHRbWzddXSsgeWxhYigiVFBNIikKcGx0CmBgYAoKIyMgTmV1cm9uYWwgc2lnbmF0dXJlcyBleHByZXNzaW9uIHsudGFic2V0fQoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OCwgcmVzdWx0cz0nYXNpcyd9CmNvdW50LmRhdGEgPC0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IGFjY19hbGxbWyJSTkEiXV0sIHNsb3QgPSAiZGF0YSIpCmNvdW50LmRhdGEgPC0gYXMubWF0cml4KHggPSAoMioqY291bnQuZGF0YSkgLSAxKQphY2NfdHBtIDwtIFNldEFzc2F5RGF0YSgKICAgIG9iamVjdCA9IGFjY19hbGwsCiAgICBzbG90ID0gImNvdW50cyIsCiAgICBuZXcuZGF0YSA9IGNvdW50LmRhdGEsCiAgICBhc3NheSA9ICJSTkEiCikKCmZvciAobmV1cmFsX25hbWUgaW4gY29sbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlcykpIHsKICBnZW5lcyA9IG5ldXJvbmFsX3NpZ25hdHVyZXNbLG5ldXJhbF9uYW1lLGRyb3A9VF0KICAjIEFzc3VtaW5nIGRmIGlzIHlvdXIgZGF0YSBmcmFtZQogIHByaW50X3RhYigKICAgIERvSGVhdG1hcChvYmplY3QgPSBhY2NfdHBtLGZlYXR1cmVzID0gZ2VuZXMsc2xvdCA9ICJjb3VudHMiLGNvbWJpbmUgPSBULGRpc3AubWF4ID0gNTAwMCkrIGxhYnMoZmlsbCA9ICJUUE0iKSAKICAsdGl0bGUgPSBuZXVyYWxfbmFtZSxzdWJ0aXRsZV9udW0gPSAzKQp9CmBgYAoKIyMgV0JDCgpgYGB7cn0Kd2JjX2NlbGxzID0gc3Vic2V0KGFjY19hbGwsIHN1YnNldCA9IGNlbGwudHlwZSA9PSAiV0JDIikKd2JjX2NlbGxzIDwtIEZpbmROZWlnaGJvcnMod2JjX2NlbGxzLCBkaW1zID0gMToxMCx2ZXJib3NlID0gRikgJT4lICBGaW5kQ2x1c3RlcnMocmVzb2x1dGlvbiA9IDAuNSkgJT4lICBSdW5VTUFQKGRpbXMgPSAxOjEwLHZlcmJvc2UgPSBGKQoKRGltUGxvdCh3YmNfY2VsbHMpCmBgYAoKV0JDIGRldmlkZWQgaW50byAyIGNsdXN0ZXJzOgoKYGBge3J9ClZsblBsb3Qob2JqZWN0ID0gd2JjX2NlbGxzLGZlYXR1cmVzID0gYygiQ0Q3OUEiLCJQVFBSQyIpKQpgYGAKCiMjIFdCQyBOZXVyb25hbCBzaWduYXR1cmVzCgpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTN9CmFjY19hbGwkY2x1c3Rlcl9pZGVudHMgPSBhY2NfYWxsQGFjdGl2ZS5pZGVudApkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjY19hbGwsdmFycyA9IGMoImNsdXN0ZXJfaWRlbnRzIikpICU+JSBtdXRhdGUoY2x1c3Rlcl9pZGVudHMgPSBhcy5jaGFyYWN0ZXIoY2x1c3Rlcl9pZGVudHMpKQpjbHVzdGVyXzBfY2VsbHMgPSBzdWJzZXQod2JjX2NlbGxzLCBzdWJzZXQgPSBzZXVyYXRfY2x1c3RlcnMgPT0gMCkgJT4lIGNvbG5hbWVzKCkKY2x1c3Rlcl8xX2NlbGxzID0gc3Vic2V0KHdiY19jZWxscywgc3Vic2V0ID0gc2V1cmF0X2NsdXN0ZXJzID09IDEpICU+JSBjb2xuYW1lcygpCgpkYXRhW3Jvd25hbWVzKGRhdGEpICVpbiUgY2x1c3Rlcl8wX2NlbGxzLF0gPSJXQkNfY2x1c3Rlcl8wIgpkYXRhW3Jvd25hbWVzKGRhdGEpICVpbiUgY2x1c3Rlcl8xX2NlbGxzLF0gPSJXQkNfY2x1c3Rlcl8xIgphY2NfYWxsJGNsdXN0ZXJfaWRlbnRzID0gZGF0YQoKcGx0ID0gVmxuUGxvdChvYmplY3QgPSBhY2NfYWxsLGZlYXR1cmVzID0gY29sbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlcyksZ3JvdXAuYnkgPSAiY2x1c3Rlcl9pZGVudHMiKQpwbHRbWzFdXSA9IHBsdFtbMV1dKyB5bGFiKCJUUE0iKQpwbHRbWzRdXSA9IHBsdFtbNF1dKyB5bGFiKCJUUE0iKQpwbHRbWzddXSA9IHBsdFtbN11dKyB5bGFiKCJUUE0iKQpwbHQKYGBgCgojIyBDRDc5QSBuZXVyb25hbF9zaWduYXR1cmVzIGNvcnJlbGF0aW9uIHsudGFic2V0fQoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CmxpYnJhcnkoZ2dwdWJyKQpmb3IgKG5ldXJhbF9uYW1lIGluIGNvbG5hbWVzKG5ldXJvbmFsX3NpZ25hdHVyZXMpKSB7CiAgd2JjX2NlbGxzID0gc3Vic2V0KGFjY19hbGwsIHN1YnNldCA9IGNlbGwudHlwZSA9PSAiV0JDIikKICBkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IHdiY19jZWxscyx2YXJzID0gYyhuZXVyYWxfbmFtZSwiQ0Q3OUEiKSkKICBwID0gZ2dwbG90KGRhdGEsIGFlc19zdHJpbmcoeD1uZXVyYWxfbmFtZSwgeT0iQ0Q3OUEiKSkgKyAKICAgICAgICAgICBnZW9tX3BvaW50KCkrCiAgICAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtKSArCiAgICAgICAgICAgc3RhdF9jb3IoKQogIHByaW50X3RhYihwLHRpdGxlICA9IG5ldXJhbF9uYW1lLHN1YnRpdGxlX251bSA9IDMpCn0KCmBgYAoKIyMgUFRQUkMgbmV1cm9uYWxfc2lnbmF0dXJlcyBjb3JyZWxhdGlvbiB7LnRhYnNldH0KCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpsaWJyYXJ5KGdncHVicikKZm9yIChuZXVyYWxfbmFtZSBpbiBjb2xuYW1lcyhuZXVyb25hbF9zaWduYXR1cmVzKSkgewogIHdiY19jZWxscyA9IHN1YnNldChhY2NfYWxsLCBzdWJzZXQgPSBjZWxsLnR5cGUgPT0gIldCQyIpCiAgZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSB3YmNfY2VsbHMsdmFycyA9IGMobmV1cmFsX25hbWUsIlBUUFJDIikpCiAgcCA9IGdncGxvdChkYXRhLCBhZXNfc3RyaW5nKHg9bmV1cmFsX25hbWUsIHk9IlBUUFJDIikpICsgCiAgICBnZW9tX3BvaW50KCkrCiAgICBnZW9tX3Ntb290aChtZXRob2Q9bG0pICsKICAgIHN0YXRfY29yKCkKICBwcmludF90YWIocCx0aXRsZSAgPSBuZXVyYWxfbmFtZSxzdWJ0aXRsZV9udW0gPSAzKQp9CgpgYGAKCiMjIFBUUFJDIG5ldXJvbmFsX3NpZ25hdHVyZXMgY29ycmVsYXRpb24gbm8gUlAgey50YWJzZXR9CgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KbGlicmFyeShnZ3B1YnIpCmZvciAobmV1cmFsX25hbWUgaW4gbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlc19ub19SUCkpIHsKICB3YmNfY2VsbHMgPSBzdWJzZXQoYWNjX2FsbCwgc3Vic2V0ID0gY2VsbC50eXBlID09ICJXQkMiKQogIGRhdGEgPSBGZXRjaERhdGEob2JqZWN0ID0gd2JjX2NlbGxzLHZhcnMgPSBjKG5ldXJhbF9uYW1lLCJQVFBSQyIpKQogIHAgPSBnZ3Bsb3QoZGF0YSwgYWVzX3N0cmluZyh4PW5ldXJhbF9uYW1lLCB5PSJQVFBSQyIpKSArIAogICAgICAgICAgIGdlb21fcG9pbnQoKSsKICAgICAgICAgICBnZW9tX3Ntb290aChtZXRob2Q9bG0pICsKICAgICAgICAgICBzdGF0X2NvcigpCiAgcHJpbnRfdGFiKHAsdGl0bGUgID0gbmV1cmFsX25hbWUsc3VidGl0bGVfbnVtID0gMykKfQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xMn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gd2JjX2NlbGxzLGZlYXR1cmVzID0gYygiUFRQUkMiLCBjb2xuYW1lcyhuZXVyb25hbF9zaWduYXR1cmVzKVsxOjVdKSkKRmVhdHVyZVBsb3Qob2JqZWN0ID0gd2JjX2NlbGxzLGZlYXR1cmVzID0gYygiUFRQUkMiLCBjb2xuYW1lcyhuZXVyb25hbF9zaWduYXR1cmVzKVs2OjldKSkKYGBgCgojIENTRjMKCltTaW5nbGUtY2VsbCBSTkEgc2VxdWVuY2luZyByZXZlYWxzIGludHJhdHVtb3JhbCBoZXRlcm9nZW5laXR5IGFuZCBwb3RlbnRpYWwgbWVjaGFuaXNtcyBvZiBtYWxpZ25hbnQgcHJvZ3Jlc3Npb24gaW4gcHJvc3RhdGUgY2FuY2VyIHdpdGggcGVyaW5ldXJhbCBpbnZhc2lvbl0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DOTg3NTc5OS8pCgpgYGB7cn0KVmxuUGxvdChvYmplY3QgPSBhY2NfYWxsLGZlYXR1cmVzID0gIkNTRjMiLGdyb3VwLmJ5ID0gInBhdGllbnQuaWRlbnQiKSsgeWxhYigibG9nMiAoVFBNKzEpIikKYGBgCgojIE5ldXJvbmFsIHBhdGh3YXlzIGluIEFDQyBjYW5jZXIgY2VsbHMKCiMjIGRpbSByZWR1Y3Rpb24KCmBgYHtyfQphY2NfY2FuY2VyIDwtIFJ1blBDQShhY2NfY2FuY2VyLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gYWNjX2NhbmNlciksdmVyYm9zZSA9IEYpCkVsYm93UGxvdChhY2NfY2FuY2VyKQphY2NfY2FuY2VyIDwtIEZpbmROZWlnaGJvcnMoYWNjX2NhbmNlciwgZGltcyA9IDE6MTAsdmVyYm9zZSA9IEYpICU+JSAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjUpICU+JSAgUnVuVU1BUChkaW1zID0gMToxMCx2ZXJib3NlID0gRikKYGBgCgpgYGB7cn0KRGltUGxvdChhY2NfY2FuY2VyLGdyb3VwLmJ5ID0gInBhdGllbnQuaWRlbnQiKQpgYGAKCmBgYHtyfQpmb3IgKHBhdGh3YXlfbmFtZSBpbiBuYW1lcyhuZXVyb25hbF9wYXRod2F5cykpIHsKICBnZW5lcyA9IG5ldXJvbmFsX3BhdGh3YXlzW1twYXRod2F5X25hbWVdXQogIHBhdGh3YXlzX3Njb3JlcyA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyLHZhcnMgPSBnZW5lcyxzbG90ID0gImRhdGEiKSAlPiUgCiAgICBtdXRhdGVfYWxsKH4gMl4uKSU+JSBtdXRhdGVfYWxsKH4gLi0xKSAlPiUgICNjb3ZlcnQgbG9nKFRQTSsxKSB0byBUUE0KICAgIHJvd3dpc2UoKSAlPiUgbXV0YXRlKHNjb3JlID0gbWVhbihjX2Fjcm9zcyhldmVyeXRoaW5nKCkpKSkgI21lYW4KICBhY2NfY2FuY2VyICAlPD4lIEFkZE1ldGFEYXRhKG1ldGFkYXRhID0gcGF0aHdheXNfc2NvcmVzJHNjb3JlLGNvbC5uYW1lID0gcGF0aHdheV9uYW1lKQp9CmBgYAoKIyMgU2NvcmVzIFVNQVAgey50YWJzZXR9CgpgYGB7ciBmaWcuaGVpZ2h0PTEzLCBmaWcud2lkdGg9MTMsIHJlc3VsdHM9J2FzaXMnfQoKcGx0ID0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjX2NhbmNlcixmZWF0dXJlcyA9IG5hbWVzKG5ldXJvbmFsX3BhdGh3YXlzKSkKZm9yIChpIGluIDE6KGxlbmd0aChwbHQkcGF0Y2hlcyRwbG90cykrMSkpIHsKICBwbHRbW2ldXSA9IHBsdFtbaV1dICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwLjUpKSsgbGFicyhjb2xvcj0nVFBNJykKfQpwcmludF90YWIocGx0LHRpdGxlID0gIlVNQVAiICxzdWJ0aXRsZV9udW0gPSAzKQoKcGx0ID0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjX2NhbmNlcixmZWF0dXJlcyA9IG5hbWVzKG5ldXJvbmFsX3BhdGh3YXlzKSxtYXguY3V0b2ZmID0gNTApCmZvciAoaSBpbiAxOihsZW5ndGgocGx0JHBhdGNoZXMkcGxvdHMpKzEpKSB7CiAgcGx0W1tpXV0gPSBwbHRbW2ldXSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMC41KSkrIGxhYnMoY29sb3I9J1RQTScpCn0KcHJpbnRfdGFiKHBsdCx0aXRsZSA9ICJVTUFQIG1heD01MCIgLHN1YnRpdGxlX251bSA9IDMpCgpwbHQgPSBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2NfY2FuY2VyLGZlYXR1cmVzID0gbmFtZXMobmV1cm9uYWxfcGF0aHdheXMpLG1heC5jdXRvZmYgPSAyNTApCmZvciAoaSBpbiAxOihsZW5ndGgocGx0JHBhdGNoZXMkcGxvdHMpKzEpKSB7CiAgcGx0W1tpXV0gPSBwbHRbW2ldXSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMC41KSkrIGxhYnMoY29sb3I9J1RQTScpCn0KcHJpbnRfdGFiKHBsdCx0aXRsZSA9ICJVTUFQIG1heD0yNTAiICxzdWJ0aXRsZV9udW0gPSAzKQoKcGx0ID0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjX2NhbmNlcixmZWF0dXJlcyA9IG5hbWVzKG5ldXJvbmFsX3BhdGh3YXlzKSkKZm9yIChpIGluIDE6KGxlbmd0aChwbHQkcGF0Y2hlcyRwbG90cykrMSkpIHsKICBwbHRbW2ldXSA9IHBsdFtbaV1dICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwLjUpKSsgbGFicyhjb2xvcj0nVFBNJykgKyBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IHJhaW5ib3coNSkpCn0KcHJpbnRfdGFiKHBsdCx0aXRsZSA9ICJVTUFQIHJhaW5ib3ciICxzdWJ0aXRsZV9udW0gPSAzKQoKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTEzLCBmaWcud2lkdGg9MTMsIHJlc3VsdHM9J2FzaXMnfQoKYGBgCgojIyBTY29yZXMgdmlvbGluCgpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CiBwbHQgPSBWbG5QbG90KG9iamVjdCA9IGFjY19jYW5jZXIsZmVhdHVyZXMgPSBuYW1lcyhuZXVyb25hbF9wYXRod2F5cyksZ3JvdXAuYnkgPSAicGF0aWVudC5pZGVudCIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDMpKQogCmZvciAoaSBpbiAxOihsZW5ndGgocGx0JHBhdGNoZXMkcGxvdHMpKzEpKSB7CiAgcGx0W1tpXV0gPSBwbHRbW2ldXSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT05LjUpKQogIGlmIChpICVpbiUgYygxLDQsNykpIHsKICAgIHBsdFtbaV1dID0gcGx0W1tpXV0reWxhYigiVFBNIikKICB9Cn0KcHJpbnQocGx0KQpgYGAKCiMgQUNDMiBERUcKCmBgYHtyfQphY2NfY2FuY2VyX3ByaSA9IFNldElkZW50KG9iamVjdCA9IGFjY19jYW5jZXJfcHJpLHZhbHVlID0gInBhdGllbnQuaWRlbnQiKQptYXJrZXJzID0gRmluZE1hcmtlcnMob2JqZWN0ID0gYWNjX2NhbmNlcl9wcmksaWRlbnQuMSA9ICJBQ0MyIixmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoYWNjX2NhbmNlcl9wcmkpLGRlbnNpZnkgPSBUKQoKYGBgCgpgYGB7cn0Kdm9sY2Fub19wbG90KGRlX2dlbmVzID0gbWFya2VycyxtYXhfbmFtZXMgPSAxMCx0aXRsZSA9ICIiLGlkZW50MSA9ICJBQ0MyIixpZGVudDIgPSAiUE5JIHBhdGllbnRzIixzaG93X2dyYXBoID0gRixsb2cyZmNfY3V0b2ZmID0gMSkKYGBgCgojIyBHU0VBLSBjYW5vbmljYWwgcGF0aHdheXMKCnVwID0gdXAgaW4gQUNDMgoKYGBge3J9CmxpYnJhcnkoaHlwZVIpCmdlbmVzZXRzIDwtIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iSCIpICU+JSBhcHBlbmQoIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iQzIiLHN1YmNhdGVnb3J5ID0gIkNQIikpCmFsbF9nZW5lcyA9IG1hcmtlcnMgICU+JSAgYXJyYW5nZShkZXNjKGF2Z19sb2cyRkMpKSAlPiUgc2VsZWN0KCJhdmdfbG9nMkZDIikgCnJhbmtlZF9saXN0ICAgPC0gc2V0TmFtZXMoYWxsX2dlbmVzJGF2Z19sb2cyRkMsIHJvd25hbWVzKGFsbF9nZW5lcykpCmh5cF9vYmogPC0gaHlwZVJfZmdzZWEoc2lnbmF0dXJlID0gcmFua2VkX2xpc3QsZ2VuZXNldHMgPSAgZ2VuZXNldHMsdXBfb25seSA9IEYpCmh5cF9kb3RzKGh5cF9vYmopCmBgYAoKIyMgR1NFQS0gR08gQlAKCmBgYHtyfQpnZW5lc2V0cyA8LSBtc2lnZGJfZG93bmxvYWQoIkhvbW8gc2FwaWVucyIsY2F0ZWdvcnk9IkgiKSAlPiUgYXBwZW5kKCBtc2lnZGJfZG93bmxvYWQoIkhvbW8gc2FwaWVucyIsY2F0ZWdvcnk9IkM1IixzdWJjYXRlZ29yeSA9ICJHTzpCUCIpKQphbGxfZ2VuZXMgPSBtYXJrZXJzICAlPiUgIGFycmFuZ2UoZGVzYyhhdmdfbG9nMkZDKSkgJT4lIHNlbGVjdCgiYXZnX2xvZzJGQyIpIApyYW5rZWRfbGlzdCAgIDwtIHNldE5hbWVzKGFsbF9nZW5lcyRhdmdfbG9nMkZDLCByb3duYW1lcyhhbGxfZ2VuZXMpKQpoeXBfb2JqIDwtIGh5cGVSX2Znc2VhKHNpZ25hdHVyZSA9IHJhbmtlZF9saXN0LGdlbmVzZXRzID0gIGdlbmVzZXRzLHVwX29ubHkgPSBGKQpoeXBfZG90cyhoeXBfb2JqKQpgYGAKCmBgYHs9aHRtbH0KPHNjcmlwdCBzcmM9Imh0dHBzOi8vaHlwb3RoZXMuaXMvZW1iZWQuanMiIGFzeW5jPjwvc2NyaXB0PgpgYGAKIyBOZXVyb25hbCBwYXRod2F5cyBpbiBBQ0MgcHJpbWFyeSBjYW5jZXIgY2VsbHMKCmBgYHtyfQpsdW1fc2NvcmUgPSBGZXRjaERhdGEoYWNjX2NhbmNlcl9wcmksImx1bWluYWxfb3Zlcl9teW8iKQpsdW1fc2NvcmUgICU8PiUgbXV0YXRlIChsdW1fb3JfbXlvID0gY2FzZV93aGVuKAogICAgICAgICBsdW1pbmFsX292ZXJfbXlvID4gMSB+ICJsdW1pbmFsIiwKICAgICAgICAgbHVtaW5hbF9vdmVyX215byA8ICgtMSkgfiAibXlvIiwKICAgICAgICAgVFJVRSB+ICJ1bmtub3duIikpCmFjY19jYW5jZXJfcHJpICAlPD4lIEFkZE1ldGFEYXRhKG1ldGFkYXRhID0gbHVtX3Njb3JlJGx1bV9vcl9teW8sY29sLm5hbWUgPSAibHVtX29yX215byIpCmBgYAoKYGBge3J9CmZvciAocGF0aHdheV9uYW1lIGluIG5hbWVzKG5ldXJvbmFsX3BhdGh3YXlzKSkgewogIGdlbmVzID0gbmV1cm9uYWxfcGF0aHdheXNbW3BhdGh3YXlfbmFtZV1dCiBwYXRod2F5c19zY29yZXMgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2NhbmNlcl9wcmksdmFycyA9IGdlbmVzLHNsb3QgPSAiZGF0YSIpICU+JSAKICAgIG11dGF0ZV9hbGwofiAyXi4pJT4lIG11dGF0ZV9hbGwofiAuLTEpICU+JSAgI2NvdmVydCBsb2coVFBNKzEpIHRvIFRQTQogICAgcm93d2lzZSgpICU+JSBtdXRhdGUoc2NvcmUgPSBtZWFuKGNfYWNyb3NzKGV2ZXJ5dGhpbmcoKSkpKSAjbWVhbgogIGFjY19jYW5jZXJfcHJpICAlPD4lIEFkZE1ldGFEYXRhKG1ldGFkYXRhID0gcGF0aHdheXNfc2NvcmVzJHNjb3JlLGNvbC5uYW1lID0gcGF0aHdheV9uYW1lKQp9CmBgYAoKYGBge3IgZmlnLmhlaWdodD0xMywgZmlnLndpZHRoPTEzfQpwbHQgPSBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2NfY2FuY2VyX3ByaSxmZWF0dXJlcyA9ICBuYW1lcyhuZXVyb25hbF9wYXRod2F5cykpCgpmb3IgKGkgaW4gMToobGVuZ3RoKHBsdCRwYXRjaGVzJHBsb3RzKSsxKSkgewogIHBsdFtbaV1dID0gcGx0W1tpXV0gKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTAuNSkpKyBsYWJzKGNvbG9yPSdUUE0nKSAKfQpwcmludChwbHQpCmBgYAoKIyBMdW0gdnMgTXlvIHsudGFic2V0fQoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CmxpYnJhcnkoZ2dwdWJyKQpmb3IgKHBhdGh3YXkgaW4gbmFtZXMobmV1cm9uYWxfcGF0aHdheXMpKSB7CiAgZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyX3ByaSx2YXJzID0gYygibHVtX29yX215byIscGF0aHdheSkpICU+JSBmaWx0ZXIobHVtX29yX215byAhPSAidW5rbm93biIpCiAgcCA9IGdnYm94cGxvdChkYXRhLCB4ID0gImx1bV9vcl9teW8iLCB5ID1wYXRod2F5LAogICAgICAgICAgICAgICAgcGFsZXR0ZSA9ICJqY28iLAogICAgICAgICAgICAgICAgYWRkID0gImppdHRlciIpKyAKICAgIHN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAid2lsY294LnRlc3QiLGNvbXBhcmlzb25zID0gbGlzdChjKCJsdW1pbmFsIiwibXlvIikpKSsgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PW1heCh4KSoxLjIsIGxhYmVsID0gcGFzdGUoIk1lYW49Iixyb3VuZChtZWFuKHgpLGRpZ2l0cyA9IDIpKSksIGdlb209InRleHQiKSAreWxhYigiVFBNIikrZ2d0aXRsZShwYXRod2F5KQogIHByaW50X3RhYihwLHRpdGxlID0gcGF0aHdheSkKfQoKYGBgCg==