HMSC vs ACC
UMAP
DimPlot(all_acc_cancer_cells,group.by = "patient.ident",label = T)

FeaturePlot(object = all_acc_cancer_cells,features = c("MYB"),pt.size = 2)

FeaturePlot(object = all_acc_cancer_cells,features = c("kaye_acc_score"),pt.size = 1)

pdf("./Figures/kaye_acc_score_AllCancerCells.pdf")
FeaturePlot(object = all_acc_cancer_cells,features = c("kaye_acc_score"),pt.size = 1)
dev.off()
null device
1
enrichment
analysis
enrichment_analysis(acc_deg,background = VariableFeatures(all_acc_cancer_cells),fdr_Cutoff = 0.01,ident.1 = "HMSC",ident.2 = "ACC",show_by = 1)

Cell
cycle score
hallmark_name = "GO_MITOTIC_CELL_CYCLE"
genesets =getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
acc_cancerCells_noACC1 = ScaleData(object = acc_cancerCells_noACC1,features = VariableFeatures(acc_cancerCells_noACC1,assay = "integrated"))
geneIds= genesets[[hallmark_name]]@geneIds %>% intersect(VariableFeatures(acc_cancerCells_noACC1,assay = "integrated"))
score <- apply(acc_cancerCells_noACC1@assays$integrated@scale.data[geneIds,],2,mean)
acc_cancerCells_noACC1=AddMetaData(acc_cancerCells_noACC1,score,hallmark_name)
acc1_cancer_cells = FindVariableFeatures(object = acc1_cancer_cells,nfeatures = 15000)
acc1_cancer_cells = ScaleData(object = acc1_cancer_cells,features = VariableFeatures(acc1_cancer_cells))
geneIds= genesets[[hallmark_name]]@geneIds %>% intersect(VariableFeatures(acc1_cancer_cells))
score <- apply(acc1_cancer_cells@assays$integrated@scale.data[geneIds,],2,mean)
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,score,hallmark_name)
acc_cc_scores = FetchData(object = acc_cancerCells_noACC1,vars = "GO_MITOTIC_CELL_CYCLE")
hmsc_cc_scores = FetchData(object = acc1_cancer_cells,vars = "GO_MITOTIC_CELL_CYCLE")
distributions_plt = ggplot() +
geom_density(aes(GO_MITOTIC_CELL_CYCLE, fill = "ACC"), alpha = .2, data = acc_cc_scores) +
geom_density(aes(GO_MITOTIC_CELL_CYCLE, fill = "HMSC"), alpha = .2, data = hmsc_cc_scores) +
scale_fill_manual(name = "Dataset", values = c(ACC = "red", HMSC = "green"))+ geom_vline(aes(xintercept=0.3),
color="blue", linetype="dashed", size=1) +ggtitle("'GO_MITOTIC_CELL_CYCLE' score distribution")
print_tab(plt = distributions_plt,title = "score distribution",subtitle_num = 3)
score distribution

NA
hmsc_cc_cells = (sum(acc1_cancer_cells@meta.data[[hallmark_name]]> 0.3) /ncol(acc1_cancer_cells)) %>% round(digits = 3)*100
acc_cc_cells = (sum(acc_cancerCells_noACC1@meta.data[[hallmark_name]]> 0.3)/ncol(acc_cancerCells_noACC1)) %>% round(digits = 3)*100
df = data.frame(Dataset = c("HMSC","ACC"), cycling_cells_percentage = c(hmsc_cc_cells,acc_cc_cells))
cycling_cells_plt = ggplot(data=df, aes(x=Dataset, y=cycling_cells_percentage)) +
geom_text(aes(label=cycling_cells_percentage), vjust=0, color="black", size=3.5)+
geom_bar(stat="identity")+ylab(" % cycling cells")+
geom_bar(stat="identity", fill="steelblue")+
theme_minimal() + ggtitle("Cycling cells count")
print_tab(plt = cycling_cells_plt,title = "# cycling cells",subtitle_num = 3)
# cycling cells

NA
pdf(file = "./Figures/CC_distributions.pdf")
distributions_plt
dev.off()
null device
1
pdf(file = "./Figures/cycling_cells.pdf")
cycling_cells_plt
dev.off()
null device
1
print_tab(plt =
FeaturePlot(all_acc_cancer_cells,features = c("MKI67","CDK1","MCM2","CDC20"))
,title = "CC genes",subtitle_num = 3)
CC genes

NA
Cycling cells filtering
#add score to all acc cancer cells
# geneIds= genesets[[hallmark_name]]@geneIds %>% intersect(VariableFeatures(all_acc_cancer_cells,assay = "integrated"))
# score <- apply(all_acc_cancer_cells@assays$integrated@scale.data[geneIds,],2,mean)
#add score to all acc cancer cells
cc_all = c(acc_cancerCells_noACC1$GO_MITOTIC_CELL_CYCLE, acc1_cancer_cells$GO_MITOTIC_CELL_CYCLE) %>% as.data.frame()
all_acc_cancer_cells=AddMetaData(all_acc_cancer_cells,cc_all,hallmark_name)
#filter:
all_acc_cancer_cells_ccFiltered=all_acc_cancer_cells[,all_acc_cancer_cells@meta.data[[hallmark_name]]< 0.3]
min_threshold = min(all_acc_cancer_cells$GO_MITOTIC_CELL_CYCLE)
max_threshold = max(all_acc_cancer_cells$GO_MITOTIC_CELL_CYCLE)
library(viridis)
Loading required package: viridisLite
print_tab(plt = FeaturePlot(object = all_acc_cancer_cells,features = hallmark_name) + ggtitle("Before cc filtering") &
scale_color_gradientn(colours = plasma(n = 10, direction = -1), limits = c(min_threshold, max_threshold))
,title = "Before CC filtering",subtitle_num = 3)
Before CC filtering
Scale for ‘colour’ is already present. Adding another scale for
‘colour’, which will replace the existing scale.

print_tab(plt =
FeaturePlot(object = all_acc_cancer_cells_ccFiltered,features = hallmark_name) + ggtitle("After cc filtering") &
scale_color_gradientn(colours = plasma(n = 10, direction = -1), limits = c(min_threshold, max_threshold))
,title = "After CC filtering" ,subtitle_num = 3)
After CC filtering
Scale for ‘colour’ is already present. Adding another scale for
‘colour’, which will replace the existing scale.

NA
DEG
all_acc_cancer_cells_ccFiltered = SetIdent(all_acc_cancer_cells_ccFiltered, value ="patient.ident")
acc_deg <-
FindMarkers(
all_acc_cancer_cells_ccFiltered,
ident.1 = "HMSC",
features = VariableFeatures(all_acc_cancer_cells_ccFiltered),
densify = T,
verbose = T,
slot = "data",
mean.fxn = function(x) {
return(log(rowMeans(x) + 1,base = 2)) # change func to calculate logFC in log space data (default to exponent data)
},
assay = "RNA"
)
| | 0 % ~calculating
|+ | 1 % ~12s
|+ | 2 % ~12s
|++ | 3 % ~12s
|++ | 4 % ~12s
|+++ | 5 % ~12s
|+++ | 6 % ~11s
|++++ | 7 % ~11s
|++++ | 8 % ~11s
|+++++ | 9 % ~11s
|+++++ | 10% ~10s
|++++++ | 11% ~10s
|++++++ | 12% ~10s
|+++++++ | 13% ~10s
|+++++++ | 14% ~10s
|++++++++ | 15% ~10s
|++++++++ | 16% ~09s
|+++++++++ | 17% ~09s
|+++++++++ | 18% ~09s
|++++++++++ | 19% ~09s
|++++++++++ | 20% ~09s
|+++++++++++ | 21% ~09s
|+++++++++++ | 22% ~09s
|++++++++++++ | 23% ~09s
|++++++++++++ | 24% ~09s
|+++++++++++++ | 25% ~08s
|+++++++++++++ | 26% ~08s
|++++++++++++++ | 27% ~08s
|++++++++++++++ | 28% ~08s
|+++++++++++++++ | 29% ~08s
|+++++++++++++++ | 30% ~08s
|++++++++++++++++ | 31% ~08s
|++++++++++++++++ | 32% ~08s
|+++++++++++++++++ | 33% ~07s
|+++++++++++++++++ | 34% ~08s
|++++++++++++++++++ | 35% ~08s
|++++++++++++++++++ | 36% ~07s
|+++++++++++++++++++ | 37% ~07s
|+++++++++++++++++++ | 38% ~07s
|++++++++++++++++++++ | 39% ~07s
|++++++++++++++++++++ | 40% ~07s
|+++++++++++++++++++++ | 41% ~07s
|+++++++++++++++++++++ | 42% ~07s
|++++++++++++++++++++++ | 43% ~07s
|++++++++++++++++++++++ | 44% ~06s
|+++++++++++++++++++++++ | 45% ~06s
|+++++++++++++++++++++++ | 46% ~06s
|++++++++++++++++++++++++ | 47% ~06s
|++++++++++++++++++++++++ | 48% ~06s
|+++++++++++++++++++++++++ | 49% ~06s
|+++++++++++++++++++++++++ | 50% ~06s
|++++++++++++++++++++++++++ | 51% ~06s
|++++++++++++++++++++++++++ | 52% ~05s
|+++++++++++++++++++++++++++ | 53% ~05s
|+++++++++++++++++++++++++++ | 54% ~05s
|++++++++++++++++++++++++++++ | 55% ~05s
|++++++++++++++++++++++++++++ | 56% ~05s
|+++++++++++++++++++++++++++++ | 57% ~05s
|+++++++++++++++++++++++++++++ | 58% ~05s
|++++++++++++++++++++++++++++++ | 59% ~05s
|++++++++++++++++++++++++++++++ | 60% ~04s
|+++++++++++++++++++++++++++++++ | 61% ~04s
|+++++++++++++++++++++++++++++++ | 62% ~04s
|++++++++++++++++++++++++++++++++ | 63% ~04s
|++++++++++++++++++++++++++++++++ | 64% ~04s
|+++++++++++++++++++++++++++++++++ | 65% ~04s
|+++++++++++++++++++++++++++++++++ | 66% ~04s
|++++++++++++++++++++++++++++++++++ | 67% ~04s
|++++++++++++++++++++++++++++++++++ | 68% ~04s
|+++++++++++++++++++++++++++++++++++ | 69% ~03s
|+++++++++++++++++++++++++++++++++++ | 70% ~03s
|++++++++++++++++++++++++++++++++++++ | 71% ~03s
|++++++++++++++++++++++++++++++++++++ | 72% ~03s
|+++++++++++++++++++++++++++++++++++++ | 73% ~03s
|+++++++++++++++++++++++++++++++++++++ | 74% ~03s
|++++++++++++++++++++++++++++++++++++++ | 75% ~03s
|++++++++++++++++++++++++++++++++++++++ | 76% ~03s
|+++++++++++++++++++++++++++++++++++++++ | 77% ~03s
|+++++++++++++++++++++++++++++++++++++++ | 78% ~02s
|++++++++++++++++++++++++++++++++++++++++ | 79% ~02s
|++++++++++++++++++++++++++++++++++++++++ | 80% ~02s
|+++++++++++++++++++++++++++++++++++++++++ | 81% ~02s
|+++++++++++++++++++++++++++++++++++++++++ | 82% ~02s
|++++++++++++++++++++++++++++++++++++++++++ | 83% ~02s
|++++++++++++++++++++++++++++++++++++++++++ | 84% ~02s
|+++++++++++++++++++++++++++++++++++++++++++ | 85% ~02s
|+++++++++++++++++++++++++++++++++++++++++++ | 86% ~02s
|++++++++++++++++++++++++++++++++++++++++++++ | 87% ~01s
|++++++++++++++++++++++++++++++++++++++++++++ | 88% ~01s
|+++++++++++++++++++++++++++++++++++++++++++++ | 89% ~01s
|+++++++++++++++++++++++++++++++++++++++++++++ | 90% ~01s
|++++++++++++++++++++++++++++++++++++++++++++++ | 91% ~01s
|++++++++++++++++++++++++++++++++++++++++++++++ | 92% ~01s
|+++++++++++++++++++++++++++++++++++++++++++++++ | 93% ~01s
|+++++++++++++++++++++++++++++++++++++++++++++++ | 94% ~01s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 95% ~01s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 96% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100%
elapsed=12s
print_tab(plt = enrichment_analysis(acc_deg,background = VariableFeatures(all_acc_cancer_cells_ccFiltered),fdr_Cutoff = 0.01,ident.1 =
"HMSC",ident.2 = "ACC",show_by = 1)
,title = "Enrichment after filtering",subtitle_num = 3)
### Enrichment after filtering {.unnumbered }

NA
library(hypeR)
genesets <- msigdb_download("Homo sapiens",category="H") %>% append( msigdb_download("Homo sapiens",category="C2",subcategory = "CP:KEGG"))
ranked_vec = acc_deg[,"avg_log2FC"]%>% setNames(rownames(acc_deg)) %>% na.omit() # make named vector
hyp_obj <-hypeR_fgsea(signature = ranked_vec,genesets = genesets,up_only = F)
plt = hyp_dots(hyp_obj,merge = F)
plt1 = plt$up+ aes(size=nes)+ggtitle("up in HMSC")
plt2 = plt$dn+ aes(size=abs(nes))+ggtitle("up in ACC")
plt3 = plt1+plt2
plt3

pdf(file = "./Figures/ACC_vs_HMSC_GSEA.pdf",width = 13,height = 6)
plt3
dev.off()
null device
1
volcano_plot(de_genes = acc_deg,fdr_cutoff = 0.05,fc_cutoff = 2, ident1 = "HMSC",ident2 = "ACC",top_genes_text = 4)

all_acc_cancer_cells_ccFiltered = SetIdent(all_acc_cancer_cells_ccFiltered, value ="patient.ident")
acc_deg <-
FindMarkers(
all_acc_cancer_cells_ccFiltered,
ident.1 = "HMSC",
features = VariableFeatures(all_acc_cancer_cells_ccFiltered),
densify = T,
verbose = T,
slot = "data",
mean.fxn = function(x) {
return(rowMeans(x) + 1) # change func to calculate logFC in log space data (default to exponent data)
},
assay = "RNA"
)
volcano_plot(de_genes = acc_deg,fdr_cutoff = 0.05,fc_cutoff = 2, ident1 = "HMSC",ident2 = "ACC",top_genes_text = 4)+xlab("avg diff")

pdf("./Figures/volcano_plot_ACC_VS_HMSC.pdf")
volcano_plot(de_genes = acc_deg,fdr_cutoff = 0.05,fc_cutoff = 2, ident1 = "HMSC",ident2 = "ACC",top_genes_text = 4)
dev.off()
null device
1
pdf("./Figures/Enrichment_analysis_ACC_VS_HMSC.pdf")
enrichment_analysis(acc_deg,background = VariableFeatures(all_acc_cancer_cells_ccFiltered),fdr_Cutoff = 0.01,ident.1 =
"HMSC",ident.2 = "ACC",show_by = 1)
dev.off()
null device
1
top_hmsc_genes = acc_deg %>% dplyr::filter(avg_log2FC > 0) %>% slice_min(n = 10,order_by = p_val_adj) %>% rownames()
top_acc_genes = acc_deg %>% dplyr::filter(avg_log2FC < 0) %>% slice_min(n = 10,order_by = p_val_adj) %>% rownames()
all_top_deg = c(top_hmsc_genes,top_acc_genes)
all_acc_cancer_cells_ccFiltered$cancer_type = all_acc_cancer_cells_ccFiltered$patient.ident %>% gsub(pattern = "ACC.*",replacement = "ACC")
cancer_type = FetchData(object = all_acc_cancer_cells_ccFiltered, vars = "cancer_type")
# col_list = list(circlize::colorRamp2(c(0, 1), c("white", "red"))); names(col_list) = colnames(all_metagenes)[i]
column_ha = HeatmapAnnotation(df = cancer_type)
data = FetchData(object = all_acc_cancer_cells_ccFiltered,vars = all_top_deg,slot = "scale.data") %>% t()
print(ComplexHeatmap::Heatmap(data,show_column_names = F,row_names_gp = grid::gpar(fontsize = 7),cluster_rows = F, ,name = "Z-score expression",cluster_columns = F,top_annotation = column_ha))

NA
NA
CNV
plot
# create expression matrix of acc + normal cells + HMSC seurat integrated
# acc_all_cells_noAcc1 = subset(acc_all_cells, subset = patient.ident != "ACC1")
# acc_expr = acc_all_cells_noAcc1@assays$RNA@data %>% as.data.frame()
# hmsc_expr = acc.combined@assays$integrated@data %>% as.data.frame()
# acc_expr = acc_expr [ rownames(hmsc_expr),]
# all_expr = cbind(acc_expr,hmsc_expr)
#
# # create annotation
# acc_annotation_integrated = as.data.frame(acc_all_cells@meta.data[,"cell.type",drop = F])
# acc_annotation_integrated = acc_annotation_integrated[colnames(all_expr),,drop = F]
# acc_annotation_integrated = acc_annotation_integrated %>% rownames_to_column("orig.ident")
# #write expression and annotation
# write.table(acc_annotation_integrated, "./Data/inferCNV/acc_annotation_integrated.txt", append = FALSE,
# sep = "\t", dec = ".",row.names = FALSE, col.names = F)
#
#
# write.table(all_expr, "./Data/inferCNV/all.4icnv_integrated.txt", append = FALSE,
# sep = "\t", dec = ".",row.names = T, col.names = T)
trace(infercnv::run,edit = T) # to skip normalization, change to skip_past = 4 (https://github.com/broadinstitute/infercnv/issues/346)
Tracing function "run" in package "infercnv"
[1] "run"
infercnv_obj = CreateInfercnvObject(raw_counts_matrix="./Data/inferCNV/all.4icnv_integrated.txt",
annotations_file="./Data/inferCNV/acc_annotation_integrated.txt",
delim="\t",gene_order_file="./Data/inferCNV/gencode_v19_gene_pos.txt"
,ref_group_names=c("CAF", "Endothelial", "WBC")) #groups of normal cells
infercnv_obj_default = infercnv::run(infercnv_obj, cutoff=1, out_dir='./Data/inferCNV/infercnv_intergrated_output',
cluster_by_groups=T, plot_steps=FALSE,
denoise=TRUE, HMM=FALSE, no_prelim_plot=TRUE,
png_res=300)
untrace(infercnv::run)
trace(infercnv:::get_group_color_palette ,edit = T) # change "Set3" to "Set1" for more distinguishable colors
plot_cnv(infercnv_obj_default, output_format = "png", write_expr_matrix = FALSE,out_dir = "./Data/inferCNV/infercnv_intergrated_output",png_res =800,obs_title = "Malignant cells",ref_title = "Normal cells",contig_cex = 2, title = "Copy number variation")
untrace(infercnv:::get_group_color_palette)
print_tab(plt = knitr::include_graphics("./Data/inferCNV/infercnv_intergrated_output/infercnv.png")
,title = "CNV plot",subtitle_num = 3)
CNV plot

NA
library(limma)
smoothed=apply(infercnv_obj_default@expr.data,2,tricubeMovingAverage, span=0.01)
cnsig=sqrt(apply((smoothed-1)^2,2,mean))
acc_all_cells <- AddMetaData(object = acc_all_cells, metadata = cnsig, col.name = "copynumber")
acc_all_cells = SetIdent(object = acc_all_cells,value = "cell.type")
print_tab(plt = FeaturePlot(acc_all_cells, "copynumber",pt.size = 1,label = T,repel = T)+
scale_colour_gradientn(colours=c("white","lightblue","orange","red","darkred"))
,title = "CNV UMAP",subtitle_num = 3)
CNV UMAP
Scale for ‘colour’ is already present. Adding another scale for
‘colour’, which will replace the existing scale.

NA
HMSC analysis
UMAP
acc1_cancer_cells = FindClusters(object = acc1_cancer_cells,verbose = F,resolution = 0.5)
DimPlot(object = acc1_cancer_cells,pt.size = 2)

Scores
FeaturePlot(object = acc1_cancer_cells,features = c("MYB","JAG1"),pt.size = 2)+
DimPlot(object = acc1_cancer_cells,group.by = c("hpv33_positive"),pt.size = 2)

DEG
SetIdent(object = acc1_cancer_cells,value = "seurat_clusters")
An object of class Seurat 80474 features across 134 samples within 2
assays Active assay: integrated (40237 features, 15000 variable
features) 1 other assay present: RNA 2 dimensional reductions
calculated: pca, umap
deg = FindAllMarkers(object = acc1_cancer_cells,features = VariableFeatures(acc1_cancer_cells),densify = T,verbose = F)
for (cluster in unique(deg$cluster)) {
print_tab(plt = deg[deg$cluster == cluster,],title = "DEG" ,subtitle_num = toc_tabs_level)
}
DEG
NA
for (cluster in unique(deg$cluster)) {
deg_of_cluster = deg[deg$cluster == cluster,]
# print(deg_of_cluster %in% original_myo_genes %>% which())
# print(deg_of_cluster %in% original_lum_genes %>% which())
print_tab(plt =
enrichment_analysis(deg_of_cluster,background =VariableFeatures(acc1_cancer_cells),fdr_Cutoff = 0.01,ident.1 =
paste("Cluster",cluster),ident.2 = paste("Cluster",cluster),show_by = 1)
,title = cluster,subtitle_num = toc_tabs_level)
}
0

1

NA
NMF
reticulate::repl_python()
from cnmf import cNMF
import pickle
nfeatures = "2K"
f = open('./Data/cNMF/HMSC_cNMF_harmony_2Kvargenes/cnmf_obj.pckl', 'rb')
cnmf_obj = pickle.load(f)
f.close()
quit
knitr::include_graphics("./Data/cNMF/HMSC_cNMF_harmony_2Kvargenes/HMSC_cNMF_harmony_2Kvargenes.k_selection.png")

reticulate::repl_python()
selected_k = 3
density_threshold = 0.1
cnmf_obj.consensus(k=selected_k, density_threshold=density_threshold,show_clustering=True)
usage_norm, gep_scores, gep_tpm, topgenes = cnmf_obj.load_results(K=selected_k, density_threshold=density_threshold)
quit
gep_scores = py$gep_scores
gep_tpm = py$gep_tpm
all_metagenes= py$usage_norm
Harmony results
# Make metagene names
for (i in 1:ncol(all_metagenes)) {
colnames(all_metagenes)[i] = "metagene." %>% paste0(i)
}
#add each metagene to metadata
for (i in 1:ncol(all_metagenes)) {
metage_metadata = all_metagenes %>% select(i)
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = metage_metadata)
}
Note: Using an external vector in selections is ambiguous. ℹ Use
all_of(i) instead of i to silence this
message. ℹ See https://tidyselect.r-lib.org/reference/faq-external-vector.html.
This message is displayed once per session.
print_tab(plt =
FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes),combine = T),
title = "metagenes expression",subtitle_num = toc_tabs_level)
Enrichment analysis
by top 200 genes of each program
canonical_pathways = msigdbr(species = "Homo sapiens", category = "C2") %>% dplyr::filter(gs_subcat != "CGP") %>% dplyr::distinct(gs_name, gene_symbol)
plt_list = list()
for (i in 1:ncol(gep_scores)) {
top_genes = gep_scores %>% arrange(desc(gep_scores[i])) #sort by score a
top = head(rownames(top_genes),200) #take top top_genes_num
res = genes_vec_enrichment(genes = top,background = rownames(gep_scores),homer = T,title =
i,silent = T,return_all = T,custom_pathways = canonical_pathways)
plt_list[[i]] = res$plt
}
gridExtra::grid.arrange(grobs = plt_list)

for (i in 1:ncol(gep_scores)) {
ranked_vec = gep_scores %>% pull(i) %>% setNames(rownames(gep_scores))
hyp_obj <-hypeR_fgsea(signature = ranked_vec,genesets = genesets,up_only = T)
plt = hyp_dots(hyp_obj,merge = F)+ aes(size=abs(nes))
print(plt)
}



library(ComplexHeatmap)
acc1_cancer_cells = SetIdent(object = acc1_cancer_cells,value = "seurat_clusters")
for (i in 1:ncol(gep_scores)) {
top_genes = gep_scores %>% arrange(desc(gep_scores[i])) #sort by score a
top = head(rownames(top_genes),50) #take top top_genes_num
data = FetchData(object = acc1_cancer_cells,vars = top)%>% scale() %>% t()
metagene_data = FetchData(object = acc1_cancer_cells,vars = colnames(all_metagenes)[i])
col_list = list(circlize::colorRamp2(c(0, 1), c("white", "red"))); names(col_list) = colnames(all_metagenes)[i]
column_ha = HeatmapAnnotation(df = metagene_data,col = col_list)
print(ComplexHeatmap::Heatmap(data,show_column_names = F,row_names_gp = grid::gpar(fontsize = 7),cluster_rows = F, top_annotation =
column_ha,name = "Z-score expression"))
pdf(paste0("./Figures/NMF_top_genes_program",i,".pdf"))
print(ComplexHeatmap::Heatmap(data,show_column_names = F,row_names_gp = grid::gpar(fontsize = 7),cluster_rows = F, top_annotation =
column_ha,name = "Z-score expression"))
dev.off()
}



Lum Myo score
original_myo_genes = c( "TP63", "TP73", "CAV1", "CDH3", "KRT5", "KRT14", "ACTA2", "TAGLN", "MYLK", "DKK3")
original_lum_genes = c("KIT", "EHF", "ELF5", "KRT7", "CLDN3", "CLDN4", "CD24", "LGALS3", "LCN2", "SLPI" )
FeaturePlot(acc1_cancer_cells,features = original_myo_genes)

FeaturePlot(acc1_cancer_cells,features = original_lum_genes)

acc_cancerCells_noACC1 = SetIdent(acc_cancerCells_noACC1,value = "patient.ident")
calculate_score(dataset = acc_cancerCells_noACC1,myo_genes = original_myo_genes,lum_genes = original_lum_genes)
correlation of lum score and myo score: -0.51
correlation of lum score and original lum score: 1
correlation of myo score and original myo score: 1



Original score of
ACC1
calculate_score(dataset = acc1_cancer_cells,myo_genes = original_myo_genes,lum_genes = original_lum_genes,lum_threshold = 0,myo_threshold = 0)
correlation of lum score and myo score: -0.08
correlation of lum score and original lum score: 1
correlation of myo score and original myo score: 1



Myo genes
myo_protein_markers = c("CNN1", "TP63","ACTA2")
top_myo = top_correlated(dataset = acc1_cancer_cells, genes = myo_protein_markers,threshold = 0.35)
print("Number of genes = " %>% paste(length(top_myo)))
message("Names of genes:")
top_myo %>% head(30)
message("Genes that also apeared in the original score:")
base::intersect(top_myo,original_myo_genes)
myo_enrich_res = genes_vec_enrichment(genes = top_myo,background = rownames(acc1_cancer_cells),homer = T,title = "myo top enrichment",custom_pathways = luminal_gs)
myo_enrich_res
Lum genes
lum_protein_markers = c("KIT")
top_lum = top_correlated(dataset = acc1_cancer_cells, genes = lum_protein_markers,threshold = 0.30,n_vargenes = 5000)
print("Number of genes = " %>% paste(length(top_lum)))
message("Names of genes:")
top_lum %>% head(30)
message("Genes that also apeared in the original score:")
base::intersect(top_lum,original_lum_genes)
lum_enrich_res = genes_vec_enrichment(genes = top_lum,background = rownames(acc1_cancer_cells),homer = T,title = "lum top enrichment",custom_pathways = luminal_gs)
lum_enrich_res
rownames(myo_enrich_res) = myo_enrich_res$pathway_name
myo_enriched_genes = myo_enrich_res[1,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,myo_protein_markers) #add original markers
myoscore=FetchData(object =acc1_cancer_cells,vars = myo_enriched_genes,slot = "data") %>% rowMeans()
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,myoscore,"myo_score")
myoscore=FetchData(object =acc1_cancer_cells,vars = top_myo,slot = "data") %>% rowMeans()
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,myoscore,"myo_score")
HPV
HPV UMAP
HPV33_P3 = fread("./Data/HPV33_P3.txt",col.names = c("plate","reads")) %>% as.data.frame()
HPV33_P3.df = HPV33_P3 %>% mutate(
plate = gsub(x =HPV33_P3$plate, replacement = "",pattern = "_.*$")
%>% gsub(pattern = "-P",replacement = ".P")
%>% gsub(pattern = "-",replacement = "_",)
)
HPV33_P3.df = HPV33_P3.df %>% dplyr::filter(HPV33_P3.df$plate %in% colnames(acc1_cancer_cells))
rownames(HPV33_P3.df) <- HPV33_P3.df$plate
HPV33_P3.df$plate = NULL
HPV33_P2 = fread("./Data/HPV33_P2.txt",col.names = c("plate","reads")) %>% as.data.frame()
HPV33_P2.df = HPV33_P2 %>% mutate(
plate = gsub(x =HPV33_P2$plate, replacement = "",pattern = "_.*$")
%>% gsub(pattern = "plate2-",replacement = "plate2_",)
%>% gsub(pattern = "-",replacement = "\\.",)
)
HPV33_P2.df = HPV33_P2.df %>% dplyr::filter(HPV33_P2.df$plate %in% colnames(acc1_cancer_cells))
rownames(HPV33_P2.df) <- HPV33_P2.df$plate
HPV33_P2.df$plate = NULL
HPV33 = rbind(HPV33_P3.df,HPV33_P2.df)
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = HPV33,col.name = "HPV33.reads")
FeaturePlot(acc1_cancer_cells,features = "HPV33.reads",max.cutoff = 10)
data = FetchData(object = acc1_cancer_cells,vars = "HPV33.reads")
data = data %>% mutate("0 reads" = if_else(condition = HPV33.reads == 0,true = 1,false = 0))
data = data %>% mutate("1 reads" = if_else(condition = HPV33.reads == 1,true = 1,false = 0))
data = data %>% mutate("2 reads" = if_else(condition = HPV33.reads == 2,true = 1,false = 0))
data = data %>% mutate("3-23 reads" = if_else(condition = HPV33.reads >=3 &HPV33.reads <24,true = 1,false = 0))
data = data %>% mutate("24+ reads" = if_else(condition = HPV33.reads >=24,true = 1,false = 0))
data = colSums(data[,2:ncol(data)]) %>% as.data.frame()
names(data)[1] = "count"
data = rownames_to_column(data,var = "bin")
data
ggplot(data=data, aes(x=factor(bin,levels = c("0 reads","1 reads","2 reads","3-23 reads","24+ reads")), y=count)) +
geom_bar(stat="identity", fill="steelblue") + xlab("HPV Reads")+ theme_minimal()+
geom_text(aes(label=count), vjust=-0.5, color="black", size=3.5)
hpv33_positive = HPV33 %>% dplyr::mutate(hpv33_positive = case_when(reads >= 10 ~ "positive",
reads < 10 ~ "negative")
)
hpv33_positive$reads = NULL
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = hpv33_positive)
DimPlot(object = acc1_cancer_cells,group.by = c("hpv33_positive"),pt.size = 2)

library(biomaRt)
ensembl = useEnsembl(biomart="ensembl", dataset="hsapiens_gene_ensembl")
DEG integrated
wilcox
acc_deg
acc_deg[c("MYB","JAG1"),]
NA
DEG LR latent vars
plate
acc1_cancer_cells = FindVariableFeatures(acc1_cancer_cells,nfeatures = 15000)
acc1_cancer_cells = SetIdent(acc1_cancer_cells, value ="hpv33_positive")
features = VariableFeatures(acc1_cancer_cells)
acc_deg <-
FindMarkers(
acc1_cancer_cells,
ident.1 = "positive",
ident.2 = "negative",
features = features,
densify = T,
assay = "RNA",
test.use = "LR",
latent.vars = "plate",
logfc.threshold = 0.25,
min.pct = 0.15,
mean.fxn = function(x) {
return(log(rowMeans(x) + 1, base = 2)) # change func to calculate logFC in log space data (default to exponent data)
}
)
acc_deg$fdr<-p.adjust(p = as.vector(acc_deg$p_val) ,method = "fdr" )
ranked_vec = acc_deg[,"avg_log2FC"]%>% setNames(rownames(acc_deg)) %>% na.omit() # make named vector
hyp_obj <-hypeR_fgsea(signature = ranked_vec,genesets = genesets,up_only = F)
hyp_dots(hyp_obj,merge = F)
acc_deg
acc_deg[c("MYB","JAG1"),]
NA
volcano plot log2(mean logTPM HPV+) - log2(mean logTPM HPV-)
volcano_plot(de_genes = acc_deg,fc_cutoff = 1.3, fdr_cutoff = 0.1,show_gene_names = c("MYB","JAG1"),ident1 = "HPV33 positive",ident2 = "HPV33 negative",top_genes_text = 5)

volcano plot log2(mean logTPM HPV+) - log2(mean logTPM HPV-)
# library("biomaRt")
# mart <- useMart(biomart="ensembl", dataset="hsapiens_gene_ensembl")
# all_coding_genes <- getBM(attributes = c( "hgnc_symbol"), filters = c("biotype"), values = list(biotype="protein_coding"), mart = mart)
acc1_cancer_cells = FindVariableFeatures(acc1_cancer_cells,nfeatures = 15000)
acc1_cancer_cells = SetIdent(acc1_cancer_cells, value ="hpv33_positive")
features = VariableFeatures(acc1_cancer_cells)
acc_deg <-
FindMarkers(
acc1_cancer_cells,
ident.1 = "positive",
ident.2 = "negative",
features = features,
densify = T,
assay = "RNA",
test.use = "LR",
latent.vars = "plate",
logfc.threshold = 0.25,
min.pct = 0.15,
mean.fxn = function(x) {
return(rowMeans(x) + 1) # change func to calculate logFC in log space data (default to exponent data)
}
)
acc_deg$fdr<-p.adjust(p = as.vector(acc_deg$p_val) ,method = "fdr" )
acc_deg
acc_deg[c("MYB","JAG1"),]
volcano plot (mean logTPM HPV+) - (mean logTPM HPV-)
volcano_plot(de_genes = acc_deg,fc_cutoff = 1.3, fdr_cutoff = 0.1,show_gene_names = c("MYB","JAG1"),ident1 = "HPV33 positive",ident2 = "HPV33 negative",top_genes_text = 5)+xlab("avg diff")

HPV vs genes

notch_genes = c("JAG1","JAG2","NOTCH3","NOTCH2","NOTCH1","DLL1","MYB","HES4","HEY1","HEY2","NRARP")
for (gene in notch_genes) {
myb_vs_hpv = FetchData(object = acc1_cancer_cells,vars = c("hpv33_positive",gene))
myb_vs_hpv$hpv33_positive = paste("HPV33",myb_vs_hpv$hpv33_positiv)
p = ggboxplot(myb_vs_hpv, x = "hpv33_positive", y = gene,
palette = "jco",
add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("HPV33 positive","HPV33 negative")))+ stat_summary(fun.data = function(x) data.frame(y=max(x)*1.2, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("log2(gene)")+ggtitle(gene)
print_tab(p,title = gene)
}
## JAG1 {.unnumbered }

## JAG2 {.unnumbered }

## NOTCH3 {.unnumbered }

## NOTCH2 {.unnumbered }

## NOTCH1 {.unnumbered }

## DLL1 {.unnumbered }

## MYB {.unnumbered }

## HES4 {.unnumbered }

## HEY1 {.unnumbered }

## HEY2 {.unnumbered }

## NRARP {.unnumbered }

NA
notch_targets = c("NOTCH3","HES4","HEY1","HEY2","NRARP")
notch_ligand = c("JAG1","JAG2","DLL1")
notch_genes = list(notch_targets = notch_targets,notch_ligand = notch_ligand)
for (i in 1:length(notch_genes)) {
genes = notch_genes[[i]]
name = names( notch_genes)[i]
myb_vs_hpv = FetchData(object = acc1_cancer_cells,vars = c(genes)) %>% rowMeans()
myb_vs_hpv = myb_vs_hpv %>% cbind(FetchData(object = acc1_cancer_cells,vars = c("hpv33_positive")))
colnames(myb_vs_hpv)[1] = "gene_set"
myb_vs_hpv$hpv33_positive = paste("HPV33",myb_vs_hpv$hpv33_positiv)
p = ggboxplot(myb_vs_hpv, x = "hpv33_positive", y = "gene_set",
palette = "jco",
add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("HPV33 positive","HPV33 negative")))+ stat_summary(fun.data = function(x) data.frame(y=max(x)*1.2, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("log2(gene)")+ggtitle(name)
print(p)
}
cor_data = FetchData(object = acc1_cancer_cells,vars = c("MYB","myo_score"))
ggplot(cor_data, aes(x=MYB, y=myo_score)) +
stat_cor(method = "pearson")+
geom_smooth(method=lm) +
geom_point()
cor_data = FetchData(object = acc1_cancer_cells,vars = c("JAG1","myo_score"))
ggplot(cor_data, aes(x=JAG1, y=myo_score)) +
stat_cor(method = "pearson")+
geom_smooth(method=lm) +
geom_point()
cor_data = FetchData(object = acc1_cancer_cells,vars = c("JAG2","myo_score"))
ggplot(cor_data, aes(x=JAG2, y=myo_score)) +
stat_cor(method = "pearson")+
geom_smooth(method=lm) +
geom_point()
cor_data = FetchData(object = acc1_cancer_cells,vars = c("DLL1","myo_score"))
ggplot(cor_data, aes(x=DLL1, y=myo_score)) +
stat_cor(method = "pearson")+
geom_smooth(method=lm) +
geom_point()
cor_data = FetchData(object = acc1_cancer_cells,vars = notch_targets) %>% rowMeans()
cor_data = cor_data %>% cbind(FetchData(object = acc1_cancer_cells,vars = c("myo_score")))
colnames(cor_data)[1] = "notch_targets"
ggplot(cor_data, aes(x=notch_targets, y=myo_score)) +
stat_cor(method = "pearson")+
geom_smooth(method=lm) +
geom_point()
cor_data = FetchData(object = acc1_cancer_cells,vars = notch_ligand) %>% rowMeans()
cor_data = cor_data %>% cbind(FetchData(object = acc1_cancer_cells,vars = c("myo_score")))
colnames(cor_data)[1] = "notch_ligand"
ggplot(cor_data, aes(x=notch_ligand, y=myo_score)) +
stat_cor(method = "pearson")+
geom_smooth(method=lm) +
geom_point()
notch_score = FetchData(object = all_acc_cancer_cells,vars = notch_targets) %>% rowMeans()
all_acc_cancer_cells = AddMetaData(object = all_acc_cancer_cells,metadata = notch_score,col.name = "notch_score")
FeaturePlot(object = all_acc_cancer_cells,features = "notch_score" )
myo_markers = c("TP63", "TP73", "KRT14", "CDH3")
score = FetchData(object = acc1_cancer_cells,vars = myo_markers) %>% rowMeans()
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = score,col.name = "myo_markers_score")
FeaturePlot(object = acc1_cancer_cells,features = "myo_markers_score",pt.size = 2 )
markers = c("CLDN3", "ANXA8", "EHF", "KIT")
score = FetchData(object = acc1_cancer_cells,vars = markers) %>% rowMeans()
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = score,col.name = "lum_markers_score")
FeaturePlot(object = acc1_cancer_cells,features = "lum_markers_score" ,pt.size = 2 )
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMgotLS0KCgoKIyBGdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiREVHX2Z1bmN0aW9ucyIsdmVyc2lvbiA9ICIwLjIuNTMiKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gIkhNU0NfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMS4xNCIsc2NyaXB0X25hbWUgPSAiZnVuY3Rpb25zLlIiKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gImNOTUZfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMy45IixzY3JpcHRfbmFtZSA9ICJjbm1mX2Z1bmN0aW9uX0hhcm1vbnkuUiIpCnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAic2NfZ2VuZXJhbF9mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC4xLjM0IixzY3JpcHRfbmFtZSA9ICJmdW5jdGlvbnMuUiIpCgp0b2NfdGFic19sZXZlbCA9MwpgYGAKCiMgRGF0YQoKYGBge3J9CmFjYzFfY2FuY2VyX2NlbGxzID0gcmVhZFJEUygiLi9EYXRhL2FjYzFfY2FuY2VyX2NlbGxzXzI1MDBmZWF0dXJlc19pbnRlZ3JhdGVkX1Y1LlJEUyIpCgphbGxfYWNjX2NhbmNlcl9jZWxscyA9IHJlYWRSRFMoIi4vRGF0YS9hY2NfY2FuY2VyX2NlbGxzX1Y1X2ludGVncmF0ZWRfcHJpbWFyeS5SRFMiKQphbGxfYWNjX2NhbmNlcl9jZWxsc19sbiA9IHJlYWRSRFMoIi4vRGF0YS9hY2NfY2FuY2VyX2NlbGxzX1Y1X2ludGVncmF0ZWQuUkRTIikKCmFjY19hbGxfY2VsbHMgPSByZWFkUkRTKCIuL0RhdGEvYWNjX3RwbV9uQ291bnRfbWl0b19ubzE0Nl8xNWtfd2l0aF9BQ0MxXy5SRFMiKQphY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxID0gc3Vic2V0KGFsbF9hY2NfY2FuY2VyX2NlbGxzLHN1YnNldCA9IHBhdGllbnQuaWRlbnQgIT0gIkhNU0MiKQoKbHVtaW5hbF9wYXRod2F5cyA9IGMoIkNIQVJBRkVfQlJFQVNUX0NBTkNFUl9MVU1JTkFMX1ZTX0JBU0FMX0ROIiwiQ0hBUkFGRV9CUkVBU1RfQ0FOQ0VSX0xVTUlOQUxfVlNfQkFTQUxfVVAiLCJDSEFSQUZFX0JSRUFTVF9DQU5DRVJfTFVNSU5BTF9WU19NRVNFTkNIWU1BTF9ETiIsIkNIQVJBRkVfQlJFQVNUX0NBTkNFUl9MVU1JTkFMX1ZTX01FU0VOQ0hZTUFMX1VQIiwiSFVQRVJfQlJFQVNUX0JBU0FMX1ZTX0xVTUlOQUxfRE4iLCJMSU1fTUFNTUFSWV9MVU1JTkFMX1BST0dFTklUT1JfVVAiLCJTTUlEX0JSRUFTVF9DQU5DRVJfTFVNSU5BTF9CX1VQIiApCgojIGFkZCBsdW1pbmFsIHBhdGh3YXlzeCAKbHVtaW5hbF9ncyA9IG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSBkcGx5cjo6ZmlsdGVyKGdzX25hbWUgJWluJSBsdW1pbmFsX3BhdGh3YXlzKSU+JSBkcGx5cjo6ZGlzdGluY3QoZ3NfbmFtZSwgZ2VuZV9zeW1ib2wpICU+JSBhcy5kYXRhLmZyYW1lKCkKYGBgCgoKCgojIEhNU0MgdnMgQUNDCgojIyBVTUFQCgpgYGB7cn0KRGltUGxvdChhbGxfYWNjX2NhbmNlcl9jZWxscyxncm91cC5ieSA9ICJwYXRpZW50LmlkZW50IixsYWJlbCA9IFQpCmBgYAoKYGBge3J9CkZlYXR1cmVQbG90KG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gYygiTVlCIikscHQuc2l6ZSA9IDIpCmBgYApgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBjKCJrYXllX2FjY19zY29yZSIpLHB0LnNpemUgPSAxKQoKYGBgCmBgYHtyfQpwZGYoIi4vRmlndXJlcy9rYXllX2FjY19zY29yZV9BbGxDYW5jZXJDZWxscy5wZGYiKQpGZWF0dXJlUGxvdChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGMoImtheWVfYWNjX3Njb3JlIikscHQuc2l6ZSA9IDEpCmRldi5vZmYoKQpgYGAKCiMjIGVucmljaG1lbnQgYW5hbHlzaXMgCgpgYGB7ciBmaWcud2lkdGg9OCwgZWNobz1UUlVFLHJlc3VsdHM9J2hpZGUnLGZpZy5rZWVwPSdhbGwnfQphbGxfYWNjX2NhbmNlcl9jZWxscyA9IFNldElkZW50KGFsbF9hY2NfY2FuY2VyX2NlbGxzLCB2YWx1ZSA9InBhdGllbnQuaWRlbnQiKQphY2NfZGVnIDwtCiAgRmluZE1hcmtlcnMoCiAgICBhbGxfYWNjX2NhbmNlcl9jZWxscywKICAgIGlkZW50LjEgPSAiSE1TQyIsCiAgICBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoYWxsX2FjY19jYW5jZXJfY2VsbHMpLAogICAgZGVuc2lmeSA9IFQsCiAgICBhc3NheSA9ICJSTkEiLAogICAgbWVhbi5meG4gPSBmdW5jdGlvbih4KSB7CiAgICAgIHJldHVybihsb2cocm93TWVhbnMoeCkgKyAxLCBiYXNlID0gMikpICMgY2hhbmdlIGZ1bmMgdG8gY2FsY3VsYXRlIGxvZ0ZDIGluIGxvZyBzcGFjZSBkYXRhIChkZWZhdWx0IHRvIGV4cG9uZW50IGRhdGEpCiAgICB9CiAgKQoKYGBgCgpgYGB7cn0KZW5yaWNobWVudF9hbmFseXNpcyhhY2NfZGVnLGJhY2tncm91bmQgPSBWYXJpYWJsZUZlYXR1cmVzKGFsbF9hY2NfY2FuY2VyX2NlbGxzKSxmZHJfQ3V0b2ZmID0gMC4wMSxpZGVudC4xID0gIkhNU0MiLGlkZW50LjIgPSAiQUNDIixzaG93X2J5ID0gMSkKYGBgCgojIyBDZWxsIGN5Y2xlIHNjb3JlICB7LnRhYnNldH0KYGBge3J9CgpoYWxsbWFya19uYW1lID0gIkdPX01JVE9USUNfQ0VMTF9DWUNMRSIKZ2VuZXNldHMgID1nZXRHbXQoIi4vRGF0YS9oLmFsbC52Ny4wLnN5bWJvbHMucGx1c2NjLmdtdCIpCgoKYWNjX2NhbmNlckNlbGxzX25vQUNDMSA9IFNjYWxlRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLGFzc2F5ID0gImludGVncmF0ZWQiKSkKZ2VuZUlkcz0gZ2VuZXNldHNbW2hhbGxtYXJrX25hbWVdXUBnZW5lSWRzICU+JSBpbnRlcnNlY3QoVmFyaWFibGVGZWF0dXJlcyhhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLGFzc2F5ID0gImludGVncmF0ZWQiKSkgCnNjb3JlIDwtIGFwcGx5KGFjY19jYW5jZXJDZWxsc19ub0FDQzFAYXNzYXlzJGludGVncmF0ZWRAc2NhbGUuZGF0YVtnZW5lSWRzLF0sMixtZWFuKQphY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxPUFkZE1ldGFEYXRhKGFjY19jYW5jZXJDZWxsc19ub0FDQzEsc2NvcmUsaGFsbG1hcmtfbmFtZSkKCmFjYzFfY2FuY2VyX2NlbGxzID0gRmluZFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbmZlYXR1cmVzID0gMTUwMDApCmFjYzFfY2FuY2VyX2NlbGxzID0gU2NhbGVEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhhY2MxX2NhbmNlcl9jZWxscykpCmdlbmVJZHM9IGdlbmVzZXRzW1toYWxsbWFya19uYW1lXV1AZ2VuZUlkcyAlPiUgaW50ZXJzZWN0KFZhcmlhYmxlRmVhdHVyZXMoYWNjMV9jYW5jZXJfY2VsbHMpKSAKc2NvcmUgPC0gYXBwbHkoYWNjMV9jYW5jZXJfY2VsbHNAYXNzYXlzJGludGVncmF0ZWRAc2NhbGUuZGF0YVtnZW5lSWRzLF0sMixtZWFuKQphY2MxX2NhbmNlcl9jZWxscz1BZGRNZXRhRGF0YShhY2MxX2NhbmNlcl9jZWxscyxzY29yZSxoYWxsbWFya19uYW1lKQoKCgpgYGAKCgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQphY2NfY2Nfc2NvcmVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjY19jYW5jZXJDZWxsc19ub0FDQzEsdmFycyA9ICJHT19NSVRPVElDX0NFTExfQ1lDTEUiKQpobXNjX2NjX3Njb3JlcyA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gIkdPX01JVE9USUNfQ0VMTF9DWUNMRSIpCgpkaXN0cmlidXRpb25zX3BsdCA9IGdncGxvdCgpICsKICBnZW9tX2RlbnNpdHkoYWVzKEdPX01JVE9USUNfQ0VMTF9DWUNMRSwgZmlsbCA9ICJBQ0MiKSwgYWxwaGEgPSAuMiwgZGF0YSA9IGFjY19jY19zY29yZXMpICsKICBnZW9tX2RlbnNpdHkoYWVzKEdPX01JVE9USUNfQ0VMTF9DWUNMRSwgZmlsbCA9ICJITVNDIiksIGFscGhhID0gLjIsIGRhdGEgPSBobXNjX2NjX3Njb3JlcykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiRGF0YXNldCIsIHZhbHVlcyA9IGMoQUNDID0gInJlZCIsIEhNU0MgPSAiZ3JlZW4iKSkrIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9MC4zKSwKICAgICAgICAgICAgY29sb3I9ImJsdWUiLCBsaW5ldHlwZT0iZGFzaGVkIiwgc2l6ZT0xKSArZ2d0aXRsZSgiJ0dPX01JVE9USUNfQ0VMTF9DWUNMRScgIHNjb3JlIGRpc3RyaWJ1dGlvbiIpCgpwcmludF90YWIocGx0ID0gZGlzdHJpYnV0aW9uc19wbHQsdGl0bGUgPSAic2NvcmUgZGlzdHJpYnV0aW9uIixzdWJ0aXRsZV9udW0gPSAzKQoKYGBgCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9Cmhtc2NfY2NfY2VsbHMgPSAoc3VtKGFjYzFfY2FuY2VyX2NlbGxzQG1ldGEuZGF0YVtbaGFsbG1hcmtfbmFtZV1dPiAwLjMpIC9uY29sKGFjYzFfY2FuY2VyX2NlbGxzKSkgJT4lIHJvdW5kKGRpZ2l0cyA9IDMpKjEwMAphY2NfY2NfY2VsbHMgPSAoc3VtKGFjY19jYW5jZXJDZWxsc19ub0FDQzFAbWV0YS5kYXRhW1toYWxsbWFya19uYW1lXV0+IDAuMykvbmNvbChhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxKSkgJT4lIHJvdW5kKGRpZ2l0cyA9IDMpKjEwMApkZiA9IGRhdGEuZnJhbWUoRGF0YXNldCA9IGMoIkhNU0MiLCJBQ0MiKSwgY3ljbGluZ19jZWxsc19wZXJjZW50YWdlID0gYyhobXNjX2NjX2NlbGxzLGFjY19jY19jZWxscykpCmN5Y2xpbmdfY2VsbHNfcGx0ID0gZ2dwbG90KGRhdGE9ZGYsIGFlcyh4PURhdGFzZXQsIHk9Y3ljbGluZ19jZWxsc19wZXJjZW50YWdlKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWw9Y3ljbGluZ19jZWxsc19wZXJjZW50YWdlKSwgdmp1c3Q9MCwgY29sb3I9ImJsYWNrIiwgc2l6ZT0zLjUpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikreWxhYigiICUgY3ljbGluZyBjZWxscyIpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0ic3RlZWxibHVlIikrCiAgdGhlbWVfbWluaW1hbCgpICsgZ2d0aXRsZSgiQ3ljbGluZyBjZWxscyBjb3VudCIpCgpwcmludF90YWIocGx0ID0gY3ljbGluZ19jZWxsc19wbHQsdGl0bGUgPSAiIyBjeWNsaW5nIGNlbGxzIixzdWJ0aXRsZV9udW0gPSAzKQpgYGAKYGBge3J9CnBkZihmaWxlID0gIi4vRmlndXJlcy9DQ19kaXN0cmlidXRpb25zLnBkZiIpCmRpc3RyaWJ1dGlvbnNfcGx0CmRldi5vZmYoKQoKcGRmKGZpbGUgPSAiLi9GaWd1cmVzL2N5Y2xpbmdfY2VsbHMucGRmIikKY3ljbGluZ19jZWxsc19wbHQKZGV2Lm9mZigpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwLCByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBGZWF0dXJlUGxvdChhbGxfYWNjX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGMoIk1LSTY3IiwiQ0RLMSIsIk1DTTIiLCJDREMyMCIpKQogICAgICAgICAgLHRpdGxlID0gIkNDIGdlbmVzIixzdWJ0aXRsZV9udW0gPSAzKQpgYGAKCiMjIEN5Y2xpbmcgY2VsbHMgZmlsdGVyaW5nIHsudGFic2V0fQpgYGB7ciB3YXJuaW5nPUZBTFNFfQojYWRkIHNjb3JlIHRvIGFsbCBhY2MgY2FuY2VyIGNlbGxzCiMgZ2VuZUlkcz0gZ2VuZXNldHNbW2hhbGxtYXJrX25hbWVdXUBnZW5lSWRzICU+JSBpbnRlcnNlY3QoVmFyaWFibGVGZWF0dXJlcyhhbGxfYWNjX2NhbmNlcl9jZWxscyxhc3NheSA9ICJpbnRlZ3JhdGVkIikpIAojIHNjb3JlIDwtIGFwcGx5KGFsbF9hY2NfY2FuY2VyX2NlbGxzQGFzc2F5cyRpbnRlZ3JhdGVkQHNjYWxlLmRhdGFbZ2VuZUlkcyxdLDIsbWVhbikKCiNhZGQgc2NvcmUgdG8gYWxsIGFjYyBjYW5jZXIgY2VsbHMKY2NfYWxsID0gYyhhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxJEdPX01JVE9USUNfQ0VMTF9DWUNMRSwgYWNjMV9jYW5jZXJfY2VsbHMkR09fTUlUT1RJQ19DRUxMX0NZQ0xFKSAlPiUgYXMuZGF0YS5mcmFtZSgpCmFsbF9hY2NfY2FuY2VyX2NlbGxzPUFkZE1ldGFEYXRhKGFsbF9hY2NfY2FuY2VyX2NlbGxzLGNjX2FsbCxoYWxsbWFya19uYW1lKQoKI2ZpbHRlcjoKYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZD1hbGxfYWNjX2NhbmNlcl9jZWxsc1ssYWxsX2FjY19jYW5jZXJfY2VsbHNAbWV0YS5kYXRhW1toYWxsbWFya19uYW1lXV08IDAuM10KCgptaW5fdGhyZXNob2xkID0gbWluKGFsbF9hY2NfY2FuY2VyX2NlbGxzJEdPX01JVE9USUNfQ0VMTF9DWUNMRSkKbWF4X3RocmVzaG9sZCA9IG1heChhbGxfYWNjX2NhbmNlcl9jZWxscyRHT19NSVRPVElDX0NFTExfQ1lDTEUpCmBgYAoKCmBgYHtyLCByZXN1bHRzPSdhc2lzJ30KbGlicmFyeSh2aXJpZGlzKQoKcHJpbnRfdGFiKHBsdCA9IEZlYXR1cmVQbG90KG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gaGFsbG1hcmtfbmFtZSkgKyBnZ3RpdGxlKCJCZWZvcmUgY2MgZmlsdGVyaW5nIikgJgogICAgICAgICAgICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IHBsYXNtYShuID0gMTAsIGRpcmVjdGlvbiA9IC0xKSwgbGltaXRzID0gYyhtaW5fdGhyZXNob2xkLCBtYXhfdGhyZXNob2xkKSkKICAgICAgICAgICx0aXRsZSA9ICJCZWZvcmUgQ0MgZmlsdGVyaW5nIixzdWJ0aXRsZV9udW0gPSAzKQoKCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCxmZWF0dXJlcyA9IGhhbGxtYXJrX25hbWUpICsgZ2d0aXRsZSgiQWZ0ZXIgY2MgZmlsdGVyaW5nIikgJgogICAgICAgICAgICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IHBsYXNtYShuID0gMTAsIGRpcmVjdGlvbiA9IC0xKSwgbGltaXRzID0gYyhtaW5fdGhyZXNob2xkLCBtYXhfdGhyZXNob2xkKSkKICAgICAgICAgICx0aXRsZSA9ICJBZnRlciBDQyBmaWx0ZXJpbmciICxzdWJ0aXRsZV9udW0gPSAzKQoKYGBgCiMjIERFRwoKYGBge3IgZmlnLndpZHRoPTgsIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcycsZmlnLmtlZXA9J2FsbCd9CmFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQgPSBTZXRJZGVudChhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkLCB2YWx1ZSA9InBhdGllbnQuaWRlbnQiKQphY2NfZGVnIDwtCiAgRmluZE1hcmtlcnMoCiAgICBhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkLAogICAgaWRlbnQuMSA9ICJITVNDIiwKICAgIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkKSwKICAgIGRlbnNpZnkgPSBULAogICAgdmVyYm9zZSA9IFQsCiAgICBzbG90ID0gImRhdGEiLAogICAgbWVhbi5meG4gPSBmdW5jdGlvbih4KSB7CiAgICAgIHJldHVybihsb2cocm93TWVhbnMoeCkgKyAxLGJhc2UgPSAyKSkgIyBjaGFuZ2UgZnVuYyB0byBjYWxjdWxhdGUgbG9nRkMgaW4gbG9nIHNwYWNlIGRhdGEgKGRlZmF1bHQgdG8gZXhwb25lbnQgZGF0YSkKICAgIH0sCiAgICBhc3NheSA9ICJSTkEiCiAgKQpgYGAKCgpgYGB7cn0KcHJpbnRfdGFiKHBsdCA9IGVucmljaG1lbnRfYW5hbHlzaXMoYWNjX2RlZyxiYWNrZ3JvdW5kID0gVmFyaWFibGVGZWF0dXJlcyhhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkKSxmZHJfQ3V0b2ZmID0gMC4wMSxpZGVudC4xID0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSE1TQyIsaWRlbnQuMiA9ICJBQ0MiLHNob3dfYnkgPSAxKQogICAgICAgICAgLHRpdGxlID0gIkVucmljaG1lbnQgYWZ0ZXIgZmlsdGVyaW5nIixzdWJ0aXRsZV9udW0gPSAzKQpgYGAKCgpgYGB7ciBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMywgcmVzdWx0cz0nYXNpcyd9CmxpYnJhcnkoaHlwZVIpCmdlbmVzZXRzIDwtIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iSCIpICU+JSBhcHBlbmQoIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iQzIiLHN1YmNhdGVnb3J5ID0gIkNQOktFR0ciKSkKcmFua2VkX3ZlYyA9IGFjY19kZWdbLCJhdmdfbG9nMkZDIl0lPiUgc2V0TmFtZXMocm93bmFtZXMoYWNjX2RlZykpICU+JSBuYS5vbWl0KCkgIyBtYWtlIG5hbWVkIHZlY3RvcgoKaHlwX29iaiA8LWh5cGVSX2Znc2VhKHNpZ25hdHVyZSA9IHJhbmtlZF92ZWMsZ2VuZXNldHMgPSBnZW5lc2V0cyx1cF9vbmx5ID0gRikKCnBsdCA9IGh5cF9kb3RzKGh5cF9vYmosbWVyZ2UgPSBGKQpwbHQxID0gcGx0JHVwKyBhZXMoc2l6ZT1uZXMpK2dndGl0bGUoInVwIGluIEhNU0MiKQpwbHQyID0gcGx0JGRuKyBhZXMoc2l6ZT1hYnMobmVzKSkrZ2d0aXRsZSgidXAgaW4gQUNDIikKcGx0MyA9IHBsdDErcGx0MgpwbHQzCmBgYAoKCmBgYHtyfQpwZGYoZmlsZSA9ICIuL0ZpZ3VyZXMvQUNDX3ZzX0hNU0NfR1NFQS5wZGYiLHdpZHRoID0gMTMsaGVpZ2h0ID0gNikKcGx0MwpkZXYub2ZmKCkKYGBgCgpgYGB7cn0Kdm9sY2Fub19wbG90KGRlX2dlbmVzID0gYWNjX2RlZyxmZHJfY3V0b2ZmID0gMC4wNSxmY19jdXRvZmYgPSAyLCBpZGVudDEgPSAiSE1TQyIsaWRlbnQyID0gIkFDQyIsdG9wX2dlbmVzX3RleHQgPSA0KQpgYGAKYGBge3IgZmlnLndpZHRoPTgsIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcycsZmlnLmtlZXA9J2FsbCd9CmFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQgPSBTZXRJZGVudChhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkLCB2YWx1ZSA9InBhdGllbnQuaWRlbnQiKQphY2NfZGVnIDwtCiAgRmluZE1hcmtlcnMoCiAgICBhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkLAogICAgaWRlbnQuMSA9ICJITVNDIiwKICAgIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkKSwKICAgIGRlbnNpZnkgPSBULAogICAgdmVyYm9zZSA9IFQsCiAgICBzbG90ID0gImRhdGEiLAogICAgbWVhbi5meG4gPSBmdW5jdGlvbih4KSB7CiAgICAgIHJldHVybihyb3dNZWFucyh4KSArIDEpICMgY2hhbmdlIGZ1bmMgdG8gY2FsY3VsYXRlIGxvZ0ZDIGluIGxvZyBzcGFjZSBkYXRhIChkZWZhdWx0IHRvIGV4cG9uZW50IGRhdGEpCiAgICB9LAogICAgYXNzYXkgPSAiUk5BIgogICkKYGBgCgoKYGBge3J9CnZvbGNhbm9fcGxvdChkZV9nZW5lcyA9IGFjY19kZWcsZmRyX2N1dG9mZiA9IDAuMDUsZmNfY3V0b2ZmID0gMiwgaWRlbnQxID0gIkhNU0MiLGlkZW50MiA9ICJBQ0MiLHRvcF9nZW5lc190ZXh0ID0gNCkreGxhYigiYXZnIGRpZmYiKQpgYGAKCgoKCmBgYHtyfQpwZGYoIi4vRmlndXJlcy92b2xjYW5vX3Bsb3RfQUNDX1ZTX0hNU0MucGRmIikKdm9sY2Fub19wbG90KGRlX2dlbmVzID0gYWNjX2RlZyxmZHJfY3V0b2ZmID0gMC4wNSxmY19jdXRvZmYgPSAyLCBpZGVudDEgPSAiSE1TQyIsaWRlbnQyID0gIkFDQyIsdG9wX2dlbmVzX3RleHQgPSA0KQpkZXYub2ZmKCkKCnBkZigiLi9GaWd1cmVzL0VucmljaG1lbnRfYW5hbHlzaXNfQUNDX1ZTX0hNU0MucGRmIikKZW5yaWNobWVudF9hbmFseXNpcyhhY2NfZGVnLGJhY2tncm91bmQgPSBWYXJpYWJsZUZlYXR1cmVzKGFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQpLGZkcl9DdXRvZmYgPSAwLjAxLGlkZW50LjEgPQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJITVNDIixpZGVudC4yID0gIkFDQyIsc2hvd19ieSA9IDEpCmRldi5vZmYoKQoKYGBgCgoKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTh9CnRvcF9obXNjX2dlbmVzID0gYWNjX2RlZyAlPiUgZHBseXI6OmZpbHRlcihhdmdfbG9nMkZDID4gMCkgJT4lICBzbGljZV9taW4obiA9IDEwLG9yZGVyX2J5ID0gcF92YWxfYWRqKSAlPiUgcm93bmFtZXMoKQp0b3BfYWNjX2dlbmVzID0gYWNjX2RlZyAlPiUgZHBseXI6OmZpbHRlcihhdmdfbG9nMkZDIDwgMCkgJT4lICBzbGljZV9taW4obiA9IDEwLG9yZGVyX2J5ID0gcF92YWxfYWRqKSAlPiUgcm93bmFtZXMoKQphbGxfdG9wX2RlZyA9IGModG9wX2htc2NfZ2VuZXMsdG9wX2FjY19nZW5lcykKCmFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQkY2FuY2VyX3R5cGUgPSBhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkJHBhdGllbnQuaWRlbnQgJT4lIGdzdWIocGF0dGVybiA9ICJBQ0MuKiIscmVwbGFjZW1lbnQgPSAiQUNDIikKY2FuY2VyX3R5cGUgPSBGZXRjaERhdGEob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCwgdmFycyA9ICJjYW5jZXJfdHlwZSIpCiMgY29sX2xpc3QgPSBsaXN0KGNpcmNsaXplOjpjb2xvclJhbXAyKGMoMCwgMSksIGMoIndoaXRlIiwgInJlZCIpKSk7IG5hbWVzKGNvbF9saXN0KSA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpW2ldCmNvbHVtbl9oYSA9IEhlYXRtYXBBbm5vdGF0aW9uKGRmID0gY2FuY2VyX3R5cGUpCgpkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQsdmFycyA9IGFsbF90b3BfZGVnLHNsb3QgPSAic2NhbGUuZGF0YSIpICU+JSB0KCkKCnByaW50KENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKGRhdGEsc2hvd19jb2x1bW5fbmFtZXMgPSBGLHJvd19uYW1lc19ncCA9IGdyaWQ6OmdwYXIoZm9udHNpemUgPSA3KSxjbHVzdGVyX3Jvd3MgPSBGLCAsbmFtZSA9ICJaLXNjb3JlIGV4cHJlc3Npb24iLGNsdXN0ZXJfY29sdW1ucyA9IEYsdG9wX2Fubm90YXRpb24gPSBjb2x1bW5faGEpKQogIAoKYGBgCgoKCgoKCgoKIyMgQ05WIHBsb3Qgey50YWJzZXR9CmBgYHtyfQojIGNyZWF0ZSBleHByZXNzaW9uIG1hdHJpeCBvZiBhY2MgKyBub3JtYWwgY2VsbHMgKyBITVNDIHNldXJhdCBpbnRlZ3JhdGVkCiMgYWNjX2FsbF9jZWxsc19ub0FjYzEgPSBzdWJzZXQoYWNjX2FsbF9jZWxscywgc3Vic2V0ID0gcGF0aWVudC5pZGVudCAhPSAiQUNDMSIpCiMgYWNjX2V4cHIgPSBhY2NfYWxsX2NlbGxzX25vQWNjMUBhc3NheXMkUk5BQGRhdGEgJT4lIGFzLmRhdGEuZnJhbWUoKQojIGhtc2NfZXhwciAgPSBhY2MuY29tYmluZWRAYXNzYXlzJGludGVncmF0ZWRAZGF0YSAlPiUgYXMuZGF0YS5mcmFtZSgpCiMgYWNjX2V4cHIgPSBhY2NfZXhwciBbIHJvd25hbWVzKGhtc2NfZXhwciksXQojIGFsbF9leHByID0gY2JpbmQoYWNjX2V4cHIsaG1zY19leHByKQojIAojICMgY3JlYXRlIGFubm90YXRpb24gCiMgYWNjX2Fubm90YXRpb25faW50ZWdyYXRlZCAgPSBhcy5kYXRhLmZyYW1lKGFjY19hbGxfY2VsbHNAbWV0YS5kYXRhWywiY2VsbC50eXBlIixkcm9wID0gRl0pCiMgYWNjX2Fubm90YXRpb25faW50ZWdyYXRlZCA9IGFjY19hbm5vdGF0aW9uX2ludGVncmF0ZWRbY29sbmFtZXMoYWxsX2V4cHIpLCxkcm9wID0gRl0KIyBhY2NfYW5ub3RhdGlvbl9pbnRlZ3JhdGVkID0gYWNjX2Fubm90YXRpb25faW50ZWdyYXRlZCAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJvcmlnLmlkZW50IikgCgojICN3cml0ZSBleHByZXNzaW9uIGFuZCBhbm5vdGF0aW9uCiMgd3JpdGUudGFibGUoYWNjX2Fubm90YXRpb25faW50ZWdyYXRlZCwgIi4vRGF0YS9pbmZlckNOVi9hY2NfYW5ub3RhdGlvbl9pbnRlZ3JhdGVkLnR4dCIsIGFwcGVuZCA9IEZBTFNFLCAKIyAgICAgICAgICAgICBzZXAgPSAiXHQiLCBkZWMgPSAiLiIscm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEYpCiMgCiMgCiMgd3JpdGUudGFibGUoYWxsX2V4cHIsICIuL0RhdGEvaW5mZXJDTlYvYWxsLjRpY252X2ludGVncmF0ZWQudHh0IiwgYXBwZW5kID0gRkFMU0UsIAojICAgICAgICAgICAgIHNlcCA9ICJcdCIsIGRlYyA9ICIuIixyb3cubmFtZXMgPSBULCBjb2wubmFtZXMgPSBUKQpgYGAKCmBgYHtyfQp0cmFjZShpbmZlcmNudjo6cnVuLGVkaXQgPSBUKSAjIHRvIHNraXAgbm9ybWFsaXphdGlvbiwgY2hhbmdlIHRvIHNraXBfcGFzdCA9IDQgKGh0dHBzOi8vZ2l0aHViLmNvbS9icm9hZGluc3RpdHV0ZS9pbmZlcmNudi9pc3N1ZXMvMzQ2KQpgYGAKCmBgYHtyfQoKaW5mZXJjbnZfb2JqID0gQ3JlYXRlSW5mZXJjbnZPYmplY3QocmF3X2NvdW50c19tYXRyaXg9Ii4vRGF0YS9pbmZlckNOVi9hbGwuNGljbnZfaW50ZWdyYXRlZC50eHQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbnNfZmlsZT0iLi9EYXRhL2luZmVyQ05WL2FjY19hbm5vdGF0aW9uX2ludGVncmF0ZWQudHh0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsaW09Ilx0IixnZW5lX29yZGVyX2ZpbGU9Ii4vRGF0YS9pbmZlckNOVi9nZW5jb2RlX3YxOV9nZW5lX3Bvcy50eHQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxyZWZfZ3JvdXBfbmFtZXM9YygiQ0FGIiwgIkVuZG90aGVsaWFsIiwgIldCQyIpKSAjZ3JvdXBzIG9mIG5vcm1hbCBjZWxscwoKaW5mZXJjbnZfb2JqX2RlZmF1bHQgPSBpbmZlcmNudjo6cnVuKGluZmVyY252X29iaiwgY3V0b2ZmPTEsIG91dF9kaXI9Jy4vRGF0YS9pbmZlckNOVi9pbmZlcmNudl9pbnRlcmdyYXRlZF9vdXRwdXQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9ieV9ncm91cHM9VCwgcGxvdF9zdGVwcz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbm9pc2U9VFJVRSwgSE1NPUZBTFNFLCBub19wcmVsaW1fcGxvdD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG5nX3Jlcz0zMDApCnVudHJhY2UoaW5mZXJjbnY6OnJ1bikKCgpgYGAKCgpgYGB7cn0KdHJhY2UoaW5mZXJjbnY6OjpnZXRfZ3JvdXBfY29sb3JfcGFsZXR0ZSAsZWRpdCA9IFQpICMgY2hhbmdlICJTZXQzIiB0byAiU2V0MSIgZm9yIG1vcmUgZGlzdGluZ3Vpc2hhYmxlIGNvbG9ycwpwbG90X2NudihpbmZlcmNudl9vYmpfZGVmYXVsdCwgb3V0cHV0X2Zvcm1hdCA9ICJwbmciLCAgd3JpdGVfZXhwcl9tYXRyaXggPSBGQUxTRSxvdXRfZGlyID0gIi4vRGF0YS9pbmZlckNOVi9pbmZlcmNudl9pbnRlcmdyYXRlZF9vdXRwdXQiLHBuZ19yZXMJPTgwMCxvYnNfdGl0bGUgPSAiTWFsaWduYW50IGNlbGxzIixyZWZfdGl0bGUgPSAiTm9ybWFsIGNlbGxzIixjb250aWdfY2V4ID0gMiwgdGl0bGUgPSAiQ29weSBudW1iZXIgdmFyaWF0aW9uIikKdW50cmFjZShpbmZlcmNudjo6OmdldF9ncm91cF9jb2xvcl9wYWxldHRlKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTgscmVzdWx0cz0nYXNpcyd9CnByaW50X3RhYihwbHQgPSBrbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9EYXRhL2luZmVyQ05WL2luZmVyY252X2ludGVyZ3JhdGVkX291dHB1dC9pbmZlcmNudi5wbmciKQogICAgICAgICAgLHRpdGxlID0gIkNOViBwbG90IixzdWJ0aXRsZV9udW0gPSAzKQpgYGAKCgpgYGB7cixyZXN1bHRzPSdhc2lzJ30KbGlicmFyeShsaW1tYSkKc21vb3RoZWQ9YXBwbHkoaW5mZXJjbnZfb2JqX2RlZmF1bHRAZXhwci5kYXRhLDIsdHJpY3ViZU1vdmluZ0F2ZXJhZ2UsIHNwYW49MC4wMSkKY25zaWc9c3FydChhcHBseSgoc21vb3RoZWQtMSleMiwyLG1lYW4pKQoKYWNjX2FsbF9jZWxscyA8LSBBZGRNZXRhRGF0YShvYmplY3QgPSBhY2NfYWxsX2NlbGxzLCBtZXRhZGF0YSA9IGNuc2lnLCBjb2wubmFtZSA9ICJjb3B5bnVtYmVyIikKYWNjX2FsbF9jZWxscyA9IFNldElkZW50KG9iamVjdCA9IGFjY19hbGxfY2VsbHMsdmFsdWUgPSAiY2VsbC50eXBlIikKCnByaW50X3RhYihwbHQgPSBGZWF0dXJlUGxvdChhY2NfYWxsX2NlbGxzLCAiY29weW51bWJlciIscHQuc2l6ZSA9IDEsbGFiZWwgPSBULHJlcGVsID0gVCkrCiAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCJ3aGl0ZSIsImxpZ2h0Ymx1ZSIsIm9yYW5nZSIsInJlZCIsImRhcmtyZWQiKSkKICAgICAgICAgICx0aXRsZSA9ICJDTlYgVU1BUCIsc3VidGl0bGVfbnVtID0gMykKCmBgYAoKCgoKIyBITVNDIGFuYWx5c2lzIAojIyBVTUFQIApgYGB7cn0KYWNjMV9jYW5jZXJfY2VsbHMgPSBGaW5kQ2x1c3RlcnMob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmVyYm9zZSA9IEYscmVzb2x1dGlvbiA9IDAuNSkKRGltUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxwdC5zaXplID0gMikKYGBgCgojIyBTY29yZXMgCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGMoIk1ZQiIsIkpBRzEiKSxwdC5zaXplID0gMikrCkRpbVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZ3JvdXAuYnkgID0gYygiaHB2MzNfcG9zaXRpdmUiKSxwdC5zaXplID0gMikKCmBgYAoKIyMgREVHIHsudGFic2V0fQpgYGB7ciByZXN1bHRzPSdhc2lzJ30KU2V0SWRlbnQob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmFsdWUgPSAic2V1cmF0X2NsdXN0ZXJzIikKZGVnID0gRmluZEFsbE1hcmtlcnMob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKGFjYzFfY2FuY2VyX2NlbGxzKSxkZW5zaWZ5ID0gVCx2ZXJib3NlID0gRikKZm9yIChjbHVzdGVyIGluIHVuaXF1ZShkZWckY2x1c3RlcikpIHsKICBwcmludF90YWIocGx0ID0gZGVnW2RlZyRjbHVzdGVyID09IGNsdXN0ZXIsXSx0aXRsZSA9ICJERUciICxzdWJ0aXRsZV9udW0gPSB0b2NfdGFic19sZXZlbCkKfQpgYGAKCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpmb3IgKGNsdXN0ZXIgaW4gdW5pcXVlKGRlZyRjbHVzdGVyKSkgewogIGRlZ19vZl9jbHVzdGVyID0gZGVnW2RlZyRjbHVzdGVyID09IGNsdXN0ZXIsXSAKICAjICBwcmludChkZWdfb2ZfY2x1c3RlciAlaW4lIG9yaWdpbmFsX215b19nZW5lcyAlPiUgd2hpY2goKSkKICAjIHByaW50KGRlZ19vZl9jbHVzdGVyICVpbiUgb3JpZ2luYWxfbHVtX2dlbmVzICU+JSB3aGljaCgpKQogIHByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgICBlbnJpY2htZW50X2FuYWx5c2lzKGRlZ19vZl9jbHVzdGVyLGJhY2tncm91bmQgPVZhcmlhYmxlRmVhdHVyZXMoYWNjMV9jYW5jZXJfY2VsbHMpLGZkcl9DdXRvZmYgPSAwLjAxLGlkZW50LjEgPQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCJDbHVzdGVyIixjbHVzdGVyKSxpZGVudC4yID0gIHBhc3RlKCJDbHVzdGVyIixjbHVzdGVyKSxzaG93X2J5ID0gMSkKICAgICAgICAgICAgLHRpdGxlID0gY2x1c3RlcixzdWJ0aXRsZV9udW0gPSB0b2NfdGFic19sZXZlbCkKfQoKCmBgYAoKCiMjIE5NRiB7LnRhYnNldH0KYGBge3B5dGhvbn0KZnJvbSBjbm1mIGltcG9ydCBjTk1GCmltcG9ydCBwaWNrbGUKbmZlYXR1cmVzID0gIjJLIgpmID0gb3BlbignLi9EYXRhL2NOTUYvSE1TQ19jTk1GX2hhcm1vbnlfMkt2YXJnZW5lcy9jbm1mX29iai5wY2tsJywgJ3JiJykKY25tZl9vYmogPSBwaWNrbGUubG9hZChmKQpmLmNsb3NlKCkKYGBgCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4vRGF0YS9jTk1GL0hNU0NfY05NRl9oYXJtb255XzJLdmFyZ2VuZXMvSE1TQ19jTk1GX2hhcm1vbnlfMkt2YXJnZW5lcy5rX3NlbGVjdGlvbi5wbmciKQpgYGAKCmBgYHtweXRob259CnNlbGVjdGVkX2sgPSAzCmRlbnNpdHlfdGhyZXNob2xkID0gMC4xCmNubWZfb2JqLmNvbnNlbnN1cyhrPXNlbGVjdGVkX2ssIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkLHNob3dfY2x1c3RlcmluZz1UcnVlKQp1c2FnZV9ub3JtLCBnZXBfc2NvcmVzLCBnZXBfdHBtLCB0b3BnZW5lcyA9IGNubWZfb2JqLmxvYWRfcmVzdWx0cyhLPXNlbGVjdGVkX2ssIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkKQpgYGAKCmBgYHtyfQpnZXBfc2NvcmVzID0gcHkkZ2VwX3Njb3JlcwpnZXBfdHBtID0gcHkkZ2VwX3RwbQphbGxfbWV0YWdlbmVzPSBweSR1c2FnZV9ub3JtCmBgYAoKIyMgSGFybW9ueSByZXN1bHRzIHsudGFic2V0fQoKCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTAsIHJlc3VsdHM9J2FzaXMnfQojIE1ha2UgbWV0YWdlbmUgbmFtZXMKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzKSkgewogIGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpW2ldID0gIm1ldGFnZW5lLiIgJT4lIHBhc3RlMChpKQp9CgojYWRkIGVhY2ggbWV0YWdlbmUgdG8gbWV0YWRhdGEKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzKSkgewogIG1ldGFnZV9tZXRhZGF0YSA9IGFsbF9tZXRhZ2VuZXMgJT4lIHNlbGVjdChpKQogIGFjYzFfY2FuY2VyX2NlbGxzID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbWV0YWRhdGEgPSBtZXRhZ2VfbWV0YWRhdGEpCn0KcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpLGNvbWJpbmUgPSBUKSwKICAgICAgICAgIHRpdGxlID0gIm1ldGFnZW5lcyBleHByZXNzaW9uIixzdWJ0aXRsZV9udW0gPSB0b2NfdGFic19sZXZlbCkKCmBgYAoKCiMjIEVucmljaG1lbnQgYW5hbHlzaXMgYnkgdG9wIDIwMCBnZW5lcyBvZiBlYWNoIHByb2dyYW0KYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OCwgcmVzdWx0cz0naGlkZSd9CgpjYW5vbmljYWxfcGF0aHdheXMgPSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiQzIiKSAlPiUgZHBseXI6OmZpbHRlcihnc19zdWJjYXQgIT0gIkNHUCIpICU+JSAgZHBseXI6OmRpc3RpbmN0KGdzX25hbWUsIGdlbmVfc3ltYm9sKQoKcGx0X2xpc3QgPSBsaXN0KCkKZm9yIChpIGluIDE6bmNvbChnZXBfc2NvcmVzKSkgewogIHRvcF9nZW5lcyA9IGdlcF9zY29yZXMgICU+JSAgYXJyYW5nZShkZXNjKGdlcF9zY29yZXNbaV0pKSAjc29ydCBieSBzY29yZSBhCiAgdG9wID0gaGVhZChyb3duYW1lcyh0b3BfZ2VuZXMpLDIwMCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICByZXMgPSBnZW5lc192ZWNfZW5yaWNobWVudChnZW5lcyA9IHRvcCxiYWNrZ3JvdW5kID0gcm93bmFtZXMoZ2VwX3Njb3JlcyksaG9tZXIgPSBULHRpdGxlID0gCiAgICAgICAgICAgICAgICAgICAgaSxzaWxlbnQgPSBULHJldHVybl9hbGwgPSBULGN1c3RvbV9wYXRod2F5cyA9IGNhbm9uaWNhbF9wYXRod2F5cykKICAgCiAgcGx0X2xpc3RbW2ldXSA9IHJlcyRwbHQKfQpncmlkRXh0cmE6OmdyaWQuYXJyYW5nZShncm9icyA9IHBsdF9saXN0KQpgYGAKCmBgYHtyfQpmb3IgKGkgaW4gMTpuY29sKGdlcF9zY29yZXMpKSB7CiAgcmFua2VkX3ZlYyA9IGdlcF9zY29yZXMgJT4lIHB1bGwoaSkgJT4lICBzZXROYW1lcyhyb3duYW1lcyhnZXBfc2NvcmVzKSkKICBoeXBfb2JqIDwtaHlwZVJfZmdzZWEoc2lnbmF0dXJlID0gcmFua2VkX3ZlYyxnZW5lc2V0cyA9IGdlbmVzZXRzLHVwX29ubHkgPSBUKQoKICBwbHQgPSBoeXBfZG90cyhoeXBfb2JqLG1lcmdlID0gRikrIGFlcyhzaXplPWFicyhuZXMpKQogIHByaW50KHBsdCkKfQpgYGAKCgpgYGB7ciBmaWcuaGVpZ2h0PTEwfQpsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQphY2MxX2NhbmNlcl9jZWxscyA9IFNldElkZW50KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhbHVlID0gInNldXJhdF9jbHVzdGVycyIpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSw1MCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICBkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSB0b3ApJT4lIHNjYWxlKCkgJT4lIHQoKSAKICBtZXRhZ2VuZV9kYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzKVtpXSkKICBjb2xfbGlzdCA9IGxpc3QoY2lyY2xpemU6OmNvbG9yUmFtcDIoYygwLCAxKSwgYygid2hpdGUiLCAicmVkIikpKTsgbmFtZXMoY29sX2xpc3QpID0gY29sbmFtZXMoYWxsX21ldGFnZW5lcylbaV0KICBjb2x1bW5faGEgPSBIZWF0bWFwQW5ub3RhdGlvbihkZiA9IG1ldGFnZW5lX2RhdGEsY29sID0gY29sX2xpc3QpCiAgcHJpbnQoQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoZGF0YSxzaG93X2NvbHVtbl9uYW1lcyA9IEYscm93X25hbWVzX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IDcpLGNsdXN0ZXJfcm93cyA9IEYsIHRvcF9hbm5vdGF0aW9uID0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5faGEsbmFtZSA9ICJaLXNjb3JlIGV4cHJlc3Npb24iKSkKICAgIAogIHBkZihwYXN0ZTAoIi4vRmlndXJlcy9OTUZfdG9wX2dlbmVzX3Byb2dyYW0iLGksIi5wZGYiKSkKICBwcmludChDb21wbGV4SGVhdG1hcDo6SGVhdG1hcChkYXRhLHNob3dfY29sdW1uX25hbWVzID0gRixyb3dfbmFtZXNfZ3AgPSBncmlkOjpncGFyKGZvbnRzaXplID0gNyksY2x1c3Rlcl9yb3dzID0gRiwgdG9wX2Fubm90YXRpb24gPSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbl9oYSxuYW1lID0gIlotc2NvcmUgZXhwcmVzc2lvbiIpKQogIGRldi5vZmYoKQp9CgpgYGAKCgoKCgoKIyMgTHVtIE15byBzY29yZQoKYGBge3J9Cm9yaWdpbmFsX215b19nZW5lcyA9IGMoICJUUDYzIiwgIlRQNzMiLCAiQ0FWMSIsICJDREgzIiwgIktSVDUiLCAiS1JUMTQiLCAiQUNUQTIiLCAiVEFHTE4iLCAiTVlMSyIsICJES0szIikKb3JpZ2luYWxfbHVtX2dlbmVzID0gYygiS0lUIiwgIkVIRiIsICJFTEY1IiwgIktSVDciLCAiQ0xETjMiLCAiQ0xETjQiLCAiQ0QyNCIsICJMR0FMUzMiLCAiTENOMiIsICJTTFBJIiApCmBgYAoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CkZlYXR1cmVQbG90KGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gb3JpZ2luYWxfbXlvX2dlbmVzKQpGZWF0dXJlUGxvdChhY2MxX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IG9yaWdpbmFsX2x1bV9nZW5lcykKCmBgYAoKCmBgYHtyfQphY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxID0gU2V0SWRlbnQoYWNjX2NhbmNlckNlbGxzX25vQUNDMSx2YWx1ZSA9ICJwYXRpZW50LmlkZW50IikKY2FsY3VsYXRlX3Njb3JlKGRhdGFzZXQgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLG15b19nZW5lcyA9IG9yaWdpbmFsX215b19nZW5lcyxsdW1fZ2VuZXMgPSBvcmlnaW5hbF9sdW1fZ2VuZXMpCmBgYAoKCgojIyBPcmlnaW5hbCBzY29yZSBvZiBBQ0MxCmBgYHtyfQpjYWxjdWxhdGVfc2NvcmUoZGF0YXNldCA9IGFjYzFfY2FuY2VyX2NlbGxzLG15b19nZW5lcyA9IG9yaWdpbmFsX215b19nZW5lcyxsdW1fZ2VuZXMgPSBvcmlnaW5hbF9sdW1fZ2VuZXMsbHVtX3RocmVzaG9sZCA9IDAsbXlvX3RocmVzaG9sZCA9IDApCmBgYAoKCgojIyMgTXlvIGdlbmVzCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBjb2xsYXBzZT1UfQpteW9fcHJvdGVpbl9tYXJrZXJzID0gYygiQ05OMSIsICJUUDYzIiwiQUNUQTIiKQp0b3BfbXlvICA9IHRvcF9jb3JyZWxhdGVkKGRhdGFzZXQgPSBhY2MxX2NhbmNlcl9jZWxscywgZ2VuZXMgPSBteW9fcHJvdGVpbl9tYXJrZXJzLHRocmVzaG9sZCA9IDAuMzUpCnByaW50KCJOdW1iZXIgb2YgZ2VuZXMgPSAiICU+JSBwYXN0ZShsZW5ndGgodG9wX215bykpKQptZXNzYWdlKCJOYW1lcyBvZiBnZW5lczoiKQp0b3BfbXlvICU+JSBoZWFkKDMwKQptZXNzYWdlKCJHZW5lcyB0aGF0IGFsc28gYXBlYXJlZCBpbiB0aGUgb3JpZ2luYWwgc2NvcmU6IikKYmFzZTo6aW50ZXJzZWN0KHRvcF9teW8sb3JpZ2luYWxfbXlvX2dlbmVzKSAKYGBgCgoKCmBgYHtyfQpteW9fZW5yaWNoX3JlcyA9IGdlbmVzX3ZlY19lbnJpY2htZW50KGdlbmVzID0gdG9wX215byxiYWNrZ3JvdW5kID0gcm93bmFtZXMoYWNjMV9jYW5jZXJfY2VsbHMpLGhvbWVyID0gVCx0aXRsZSA9ICJteW8gdG9wIGVucmljaG1lbnQiLGN1c3RvbV9wYXRod2F5cyA9IGx1bWluYWxfZ3MpCm15b19lbnJpY2hfcmVzCmBgYAojIyMgTHVtIGdlbmVzCmBgYHtyfQpsdW1fcHJvdGVpbl9tYXJrZXJzID0gYygiS0lUIikKdG9wX2x1bSAgPSB0b3BfY29ycmVsYXRlZChkYXRhc2V0ID0gYWNjMV9jYW5jZXJfY2VsbHMsIGdlbmVzID0gbHVtX3Byb3RlaW5fbWFya2Vycyx0aHJlc2hvbGQgPSAwLjMwLG5fdmFyZ2VuZXMgPSA1MDAwKQpwcmludCgiTnVtYmVyIG9mIGdlbmVzID0gIiAlPiUgcGFzdGUobGVuZ3RoKHRvcF9sdW0pKSkKbWVzc2FnZSgiTmFtZXMgb2YgZ2VuZXM6IikKdG9wX2x1bSAlPiUgaGVhZCgzMCkKbWVzc2FnZSgiR2VuZXMgdGhhdCBhbHNvIGFwZWFyZWQgaW4gdGhlIG9yaWdpbmFsIHNjb3JlOiIpCmJhc2U6OmludGVyc2VjdCh0b3BfbHVtLG9yaWdpbmFsX2x1bV9nZW5lcykgCmBgYAoKYGBge3J9Cmx1bV9lbnJpY2hfcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3BfbHVtLGJhY2tncm91bmQgPSByb3duYW1lcyhhY2MxX2NhbmNlcl9jZWxscyksaG9tZXIgPSBULHRpdGxlID0gImx1bSB0b3AgZW5yaWNobWVudCIsY3VzdG9tX3BhdGh3YXlzID0gbHVtaW5hbF9ncykKbHVtX2VucmljaF9yZXMKYGBgCgpgYGB7cn0Kcm93bmFtZXMobXlvX2VucmljaF9yZXMpID0gbXlvX2VucmljaF9yZXMkcGF0aHdheV9uYW1lCm15b19lbnJpY2hlZF9nZW5lcyA9IG15b19lbnJpY2hfcmVzWzEsImdlbmVJRCJdICU+JSBzdHJzcGxpdChzcGxpdCA9ICIvIikgJT4lIC5bWzFdXSAlPiUgYyguLG15b19wcm90ZWluX21hcmtlcnMpICNhZGQgb3JpZ2luYWwgbWFya2VycwpteW9zY29yZT1GZXRjaERhdGEob2JqZWN0ID1hY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gIG15b19lbnJpY2hlZF9nZW5lcyxzbG90ID0gImRhdGEiKSAlPiUgcm93TWVhbnMoKQphY2MxX2NhbmNlcl9jZWxscz1BZGRNZXRhRGF0YShhY2MxX2NhbmNlcl9jZWxscyxteW9zY29yZSwibXlvX3Njb3JlIikKCgpteW9zY29yZT1GZXRjaERhdGEob2JqZWN0ID1hY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gIHRvcF9teW8sc2xvdCA9ICJkYXRhIikgJT4lIHJvd01lYW5zKCkKYWNjMV9jYW5jZXJfY2VsbHM9QWRkTWV0YURhdGEoYWNjMV9jYW5jZXJfY2VsbHMsbXlvc2NvcmUsIm15b19zY29yZSIpCmBgYAoKCiMjIEhQVgojIyMgSFBWIFVNQVAKCmBgYHtyfQpIUFYzM19QMyA9IGZyZWFkKCIuL0RhdGEvSFBWMzNfUDMudHh0Iixjb2wubmFtZXMgPSBjKCJwbGF0ZSIsInJlYWRzIikpICU+JSBhcy5kYXRhLmZyYW1lKCkKSFBWMzNfUDMuZGYgPSBIUFYzM19QMyAlPiUgbXV0YXRlKAogIHBsYXRlID0gZ3N1Yih4ID1IUFYzM19QMyRwbGF0ZSwgcmVwbGFjZW1lbnQgPSAiIixwYXR0ZXJuID0gIl8uKiQiKSAKICAlPiUgZ3N1YihwYXR0ZXJuID0gIi1QIixyZXBsYWNlbWVudCA9ICIuUCIpIAogICU+JSBnc3ViKHBhdHRlcm4gPSAiLSIscmVwbGFjZW1lbnQgPSAiXyIsKQogICkKSFBWMzNfUDMuZGYgPSBIUFYzM19QMy5kZiAlPiUgZHBseXI6OmZpbHRlcihIUFYzM19QMy5kZiRwbGF0ZSAlaW4lIGNvbG5hbWVzKGFjYzFfY2FuY2VyX2NlbGxzKSkKcm93bmFtZXMoSFBWMzNfUDMuZGYpICA8LSBIUFYzM19QMy5kZiRwbGF0ZQpIUFYzM19QMy5kZiRwbGF0ZSA9IE5VTEwKCgpIUFYzM19QMiA9IGZyZWFkKCIuL0RhdGEvSFBWMzNfUDIudHh0Iixjb2wubmFtZXMgPSBjKCJwbGF0ZSIsInJlYWRzIikpICU+JSBhcy5kYXRhLmZyYW1lKCkKSFBWMzNfUDIuZGYgPSBIUFYzM19QMiAlPiUgbXV0YXRlKAogIHBsYXRlID0gZ3N1Yih4ID1IUFYzM19QMiRwbGF0ZSwgcmVwbGFjZW1lbnQgPSAiIixwYXR0ZXJuID0gIl8uKiQiKSAKICAlPiUgZ3N1YihwYXR0ZXJuID0gInBsYXRlMi0iLHJlcGxhY2VtZW50ID0gInBsYXRlMl8iLCkKICAlPiUgZ3N1YihwYXR0ZXJuID0gIi0iLHJlcGxhY2VtZW50ID0gIlxcLiIsKQogICkKSFBWMzNfUDIuZGYgPSBIUFYzM19QMi5kZiAlPiUgZHBseXI6OmZpbHRlcihIUFYzM19QMi5kZiRwbGF0ZSAlaW4lIGNvbG5hbWVzKGFjYzFfY2FuY2VyX2NlbGxzKSkKcm93bmFtZXMoSFBWMzNfUDIuZGYpICA8LSBIUFYzM19QMi5kZiRwbGF0ZQpIUFYzM19QMi5kZiRwbGF0ZSA9IE5VTEwKCkhQVjMzID0gcmJpbmQoSFBWMzNfUDMuZGYsSFBWMzNfUDIuZGYpCmFjYzFfY2FuY2VyX2NlbGxzID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbWV0YWRhdGEgPSBIUFYzMyxjb2wubmFtZSA9ICJIUFYzMy5yZWFkcyIpCkZlYXR1cmVQbG90KGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gIkhQVjMzLnJlYWRzIixtYXguY3V0b2ZmID0gMTApCmBgYAoKCmBgYHtyfQoKZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gIkhQVjMzLnJlYWRzIikKCmRhdGEgPSBkYXRhICU+JSBtdXRhdGUoIjAgcmVhZHMiID0gaWZfZWxzZShjb25kaXRpb24gPSBIUFYzMy5yZWFkcyA9PSAwLHRydWUgPSAxLGZhbHNlID0gMCkpCmRhdGEgPSBkYXRhICU+JSBtdXRhdGUoIjEgcmVhZHMiID0gaWZfZWxzZShjb25kaXRpb24gPSBIUFYzMy5yZWFkcyA9PSAxLHRydWUgPSAxLGZhbHNlID0gMCkpCmRhdGEgPSBkYXRhICU+JSBtdXRhdGUoIjIgcmVhZHMiID0gaWZfZWxzZShjb25kaXRpb24gPSBIUFYzMy5yZWFkcyA9PSAyLHRydWUgPSAxLGZhbHNlID0gMCkpCmRhdGEgPSBkYXRhICU+JSBtdXRhdGUoIjMtMjMgcmVhZHMiID0gaWZfZWxzZShjb25kaXRpb24gPSBIUFYzMy5yZWFkcyA+PTMgJkhQVjMzLnJlYWRzICA8MjQsdHJ1ZSA9IDEsZmFsc2UgPSAwKSkKZGF0YSA9IGRhdGEgJT4lIG11dGF0ZSgiMjQrIHJlYWRzIiA9IGlmX2Vsc2UoY29uZGl0aW9uID0gSFBWMzMucmVhZHMgPj0yNCx0cnVlID0gMSxmYWxzZSA9IDApKQpkYXRhID0gY29sU3VtcyhkYXRhWywyOm5jb2woZGF0YSldKSAlPiUgYXMuZGF0YS5mcmFtZSgpCm5hbWVzKGRhdGEpWzFdID0gImNvdW50IgpkYXRhID0gcm93bmFtZXNfdG9fY29sdW1uKGRhdGEsdmFyID0gImJpbiIpCmRhdGEKZ2dwbG90KGRhdGE9ZGF0YSwgYWVzKHg9ZmFjdG9yKGJpbixsZXZlbHMgPSBjKCIwIHJlYWRzIiwiMSByZWFkcyIsIjIgcmVhZHMiLCIzLTIzIHJlYWRzIiwiMjQrIHJlYWRzIikpLCB5PWNvdW50KSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0ic3RlZWxibHVlIikgKyB4bGFiKCJIUFYgUmVhZHMiKSsgdGhlbWVfbWluaW1hbCgpKwogIGdlb21fdGV4dChhZXMobGFiZWw9Y291bnQpLCB2anVzdD0tMC41LCBjb2xvcj0iYmxhY2siLCBzaXplPTMuNSkKYGBgCgoKYGBge3J9CmhwdjMzX3Bvc2l0aXZlID0gSFBWMzMgJT4lIGRwbHlyOjptdXRhdGUoaHB2MzNfcG9zaXRpdmUgPSBjYXNlX3doZW4ocmVhZHMgPj0gMTAgfiAicG9zaXRpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRzIDwgMTAgfiAibmVnYXRpdmUiKQopCgoKCmhwdjMzX3Bvc2l0aXZlJHJlYWRzID0gTlVMTAphY2MxX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gaHB2MzNfcG9zaXRpdmUpCmBgYAoKYGBge3J9CkRpbVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZ3JvdXAuYnkgID0gYygiaHB2MzNfcG9zaXRpdmUiKSxwdC5zaXplID0gMikKYGBgCgoKYGBge3J9CmxpYnJhcnkoYmlvbWFSdCkKZW5zZW1ibCA9IHVzZUVuc2VtYmwoYmlvbWFydD0iZW5zZW1ibCIsIGRhdGFzZXQ9ImhzYXBpZW5zX2dlbmVfZW5zZW1ibCIpCmBgYAoKIyMjIERFRyBpbnRlZ3JhdGVkIHdpbGNveCAKYGBge3IgZmlnLndpZHRoPTgsIGVjaG89VFJVRSxyZXN1bHRzPSdoaWRlJyxmaWcua2VlcD0nYWxsJ30KCiMgbGlicmFyeSgiYmlvbWFSdCIpCiMgbWFydCA8LSB1c2VNYXJ0KGJpb21hcnQ9ImVuc2VtYmwiLCBkYXRhc2V0PSJoc2FwaWVuc19nZW5lX2Vuc2VtYmwiKQojIGFsbF9jb2RpbmdfZ2VuZXMgPC0gZ2V0Qk0oYXR0cmlidXRlcyA9IGMoICJoZ25jX3N5bWJvbCIpLCBmaWx0ZXJzID0gYygiYmlvdHlwZSIpLCB2YWx1ZXMgPSBsaXN0KGJpb3R5cGU9InByb3RlaW5fY29kaW5nIiksIG1hcnQgPSBtYXJ0KQojICAgIAphY2MxX2NhbmNlcl9jZWxscyA9IEZpbmRWYXJpYWJsZUZlYXR1cmVzKGFjYzFfY2FuY2VyX2NlbGxzLG5mZWF0dXJlcyA9IDE1MDAwKQphY2MxX2NhbmNlcl9jZWxscyA9IFNldElkZW50KGFjYzFfY2FuY2VyX2NlbGxzLCB2YWx1ZSA9ImhwdjMzX3Bvc2l0aXZlIikKZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKGFjYzFfY2FuY2VyX2NlbGxzKSAKYWNjX2RlZyA8LSBGaW5kTWFya2VycyhhY2MxX2NhbmNlcl9jZWxscywgaWRlbnQuMSA9ICJwb3NpdGl2ZSIsaWRlbnQuMiA9ICJuZWdhdGl2ZSIsZmVhdHVyZXMgPSBmZWF0dXJlcyxkZW5zaWZ5ID0gVCxsb2dmYy50aHJlc2hvbGQgPSAwLjI1LG1pbi5wY3QgPSAwLjE1LCAgICBtZWFuLmZ4biA9IGZ1bmN0aW9uKHgpIHsKICAgICAgcmV0dXJuKGxvZyhyb3dNZWFucyh4KSArIDEsIGJhc2UgPSAyKSkgIyBjaGFuZ2UgZnVuYyB0byBjYWxjdWxhdGUgbG9nRkMgaW4gbG9nIHNwYWNlIGRhdGEgKGRlZmF1bHQgdG8gZXhwb25lbnQgZGF0YSkKICAgIH0pCgojIGVucmljaG1lbnRfYW5hbHlzaXMoYWNjX2RlZyxiYWNrZ3JvdW5kID0gVmFyaWFibGVGZWF0dXJlcyhhY2MxX2NhbmNlcl9jZWxscyksZmRyX0N1dG9mZiA9IDAuMDEsaWRlbnQuMSA9ICJITVNDIixpZGVudC4yID0gIkFDQyIsc2hvd19ieSA9IDEpCmFjY19kZWckZmRyPC1wLmFkanVzdChwID0gYXMudmVjdG9yKGFjY19kZWckcF92YWwpICxtZXRob2QgPSAiZmRyIikKIyBhY2NfZGVnW2MoIk1ZQiIsIkpBRzEiKSxdCiMgYWNjX2RlZyAlPiUgaGVhZCgpCiMgZ2VuZWRlc2MgPC0gZ2V0Qk0oYXR0cmlidXRlcz1jKCdleHRlcm5hbF9nZW5lX25hbWUnLCdkZXNjcmlwdGlvbicpLCBmaWx0ZXJzID0gJ2V4dGVybmFsX2dlbmVfbmFtZScsIHZhbHVlcyA9IGFjY19kZWcgJT4lIHJvd25hbWVzKCksIG1hcnQgPWVuc2VtYmwpICAKIyAKIyBhbGxfdXBfZ2VuZXMgPSBtZXJnZShhY2NfZGVnLGdlbmVkZXNjLGJ5Lng9InJvdy5uYW1lcyIsYnkueSA9ICJleHRlcm5hbF9nZW5lX25hbWUiLGFsbC54ID0gVCxzb3J0ID1GKQojIGFsbF91cF9nZW5lcwojIGdlbmVzID0gYWxsX3VwX2dlbmVzICU+JSBkcGx5cjo6ZmlsdGVyKFJvdy5uYW1lcyAlaW4lIGMoIk1ZQiIsIkpBRzEiKSkgJT4lIGRwbHlyOjpmaWx0ZXIocF92YWw8MC4wNSkKIyBnZW5lcwpgYGAKCmBgYHtyfQphY2NfZGVnCmFjY19kZWdbYygiTVlCIiwiSkFHMSIpLF0KCmBgYAoKIyMjIERFRyBMUiBsYXRlbnQgdmFycyBwbGF0ZQoKYGBge3J9CmFjYzFfY2FuY2VyX2NlbGxzID0gRmluZFZhcmlhYmxlRmVhdHVyZXMoYWNjMV9jYW5jZXJfY2VsbHMsbmZlYXR1cmVzID0gMTUwMDApCmFjYzFfY2FuY2VyX2NlbGxzID0gU2V0SWRlbnQoYWNjMV9jYW5jZXJfY2VsbHMsIHZhbHVlID0iaHB2MzNfcG9zaXRpdmUiKQpmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoYWNjMV9jYW5jZXJfY2VsbHMpIAphY2NfZGVnIDwtCiAgRmluZE1hcmtlcnMoCiAgICBhY2MxX2NhbmNlcl9jZWxscywKICAgIGlkZW50LjEgPSAicG9zaXRpdmUiLAogICAgaWRlbnQuMiA9ICJuZWdhdGl2ZSIsCiAgICBmZWF0dXJlcyA9IGZlYXR1cmVzLAogICAgZGVuc2lmeSA9IFQsCiAgICBhc3NheSA9ICJSTkEiLAogICAgdGVzdC51c2UgPSAiTFIiLAogICAgbGF0ZW50LnZhcnMgPSAicGxhdGUiLAogICAgbG9nZmMudGhyZXNob2xkID0gMC4yNSwKICAgIG1pbi5wY3QgPSAwLjE1LAogICAgbWVhbi5meG4gPSBmdW5jdGlvbih4KSB7CiAgICAgIHJldHVybihsb2cocm93TWVhbnMoeCkgKyAxLCBiYXNlID0gMikpICMgY2hhbmdlIGZ1bmMgdG8gY2FsY3VsYXRlIGxvZ0ZDIGluIGxvZyBzcGFjZSBkYXRhIChkZWZhdWx0IHRvIGV4cG9uZW50IGRhdGEpCiAgICB9CiAgKQphY2NfZGVnJGZkcjwtcC5hZGp1c3QocCA9IGFzLnZlY3RvcihhY2NfZGVnJHBfdmFsKSAsbWV0aG9kID0gImZkciIgKQoKYGBgCgoKYGBge3J9CnJhbmtlZF92ZWMgPSBhY2NfZGVnWywiYXZnX2xvZzJGQyJdJT4lIHNldE5hbWVzKHJvd25hbWVzKGFjY19kZWcpKSAlPiUgbmEub21pdCgpICMgbWFrZSBuYW1lZCB2ZWN0b3IKCmh5cF9vYmogPC1oeXBlUl9mZ3NlYShzaWduYXR1cmUgPSByYW5rZWRfdmVjLGdlbmVzZXRzID0gZ2VuZXNldHMsdXBfb25seSA9IEYpCmh5cF9kb3RzKGh5cF9vYmosbWVyZ2UgPSBGKQoKYGBgCgpgYGB7cn0KYWNjX2RlZwphY2NfZGVnW2MoIk1ZQiIsIkpBRzEiKSxdCgpgYGAKCnZvbGNhbm8gcGxvdCBsb2cyKG1lYW4gbG9nVFBNIEhQVispIC0gbG9nMihtZWFuIGxvZ1RQTSBIUFYtKQpgYGB7cn0Kdm9sY2Fub19wbG90KGRlX2dlbmVzID0gYWNjX2RlZyxmY19jdXRvZmYgPSAxLjMsIGZkcl9jdXRvZmYgPSAwLjEsc2hvd19nZW5lX25hbWVzID0gYygiTVlCIiwiSkFHMSIpLGlkZW50MSA9ICJIUFYzMyBwb3NpdGl2ZSIsaWRlbnQyID0gIkhQVjMzIG5lZ2F0aXZlIix0b3BfZ2VuZXNfdGV4dCA9IDUpCmBgYAoKdm9sY2FubyBwbG90IGxvZzIobWVhbiBsb2dUUE0gSFBWKykgLSBsb2cyKG1lYW4gbG9nVFBNIEhQVi0pCgpgYGB7cn0KIyBsaWJyYXJ5KCJiaW9tYVJ0IikKIyBtYXJ0IDwtIHVzZU1hcnQoYmlvbWFydD0iZW5zZW1ibCIsIGRhdGFzZXQ9ImhzYXBpZW5zX2dlbmVfZW5zZW1ibCIpCiMgYWxsX2NvZGluZ19nZW5lcyA8LSBnZXRCTShhdHRyaWJ1dGVzID0gYyggImhnbmNfc3ltYm9sIiksIGZpbHRlcnMgPSBjKCJiaW90eXBlIiksIHZhbHVlcyA9IGxpc3QoYmlvdHlwZT0icHJvdGVpbl9jb2RpbmciKSwgbWFydCA9IG1hcnQpCgphY2MxX2NhbmNlcl9jZWxscyA9IEZpbmRWYXJpYWJsZUZlYXR1cmVzKGFjYzFfY2FuY2VyX2NlbGxzLG5mZWF0dXJlcyA9IDE1MDAwKQphY2MxX2NhbmNlcl9jZWxscyA9IFNldElkZW50KGFjYzFfY2FuY2VyX2NlbGxzLCB2YWx1ZSA9ImhwdjMzX3Bvc2l0aXZlIikKZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKGFjYzFfY2FuY2VyX2NlbGxzKSAKYWNjX2RlZyA8LQogIEZpbmRNYXJrZXJzKAogICAgYWNjMV9jYW5jZXJfY2VsbHMsCiAgICBpZGVudC4xID0gInBvc2l0aXZlIiwKICAgIGlkZW50LjIgPSAibmVnYXRpdmUiLAogICAgZmVhdHVyZXMgPSBmZWF0dXJlcywKICAgIGRlbnNpZnkgPSBULAogICAgYXNzYXkgPSAiUk5BIiwKICAgIHRlc3QudXNlID0gIkxSIiwKICAgIGxhdGVudC52YXJzID0gInBsYXRlIiwKICAgIGxvZ2ZjLnRocmVzaG9sZCA9IDAuMjUsCiAgICBtaW4ucGN0ID0gMC4xNSwKICAgIG1lYW4uZnhuID0gZnVuY3Rpb24oeCkgewogICAgICByZXR1cm4ocm93TWVhbnMoeCkgKyAxKSAjIGNoYW5nZSBmdW5jIHRvIGNhbGN1bGF0ZSBsb2dGQyBpbiBsb2cgc3BhY2UgZGF0YSAoZGVmYXVsdCB0byBleHBvbmVudCBkYXRhKQogICAgfQogICkKYWNjX2RlZyRmZHI8LXAuYWRqdXN0KHAgPSBhcy52ZWN0b3IoYWNjX2RlZyRwX3ZhbCkgLG1ldGhvZCA9ICJmZHIiICkKYGBgCgpgYGB7cn0KYWNjX2RlZwphY2NfZGVnW2MoIk1ZQiIsIkpBRzEiKSxdCmBgYAoKdm9sY2FubyBwbG90IChtZWFuIGxvZ1RQTSBIUFYrKSAtIChtZWFuIGxvZ1RQTSBIUFYtKQoKYGBge3J9CnZvbGNhbm9fcGxvdChkZV9nZW5lcyA9IGFjY19kZWcsZmNfY3V0b2ZmID0gMS4zLCBmZHJfY3V0b2ZmID0gMC4xLHNob3dfZ2VuZV9uYW1lcyA9IGMoIk1ZQiIsIkpBRzEiKSxpZGVudDEgPSAiSFBWMzMgcG9zaXRpdmUiLGlkZW50MiA9ICJIUFYzMyBuZWdhdGl2ZSIsdG9wX2dlbmVzX3RleHQgPSA1KSt4bGFiKCJhdmcgZGlmZiIpCmBgYAoKIyMjIEhQViB2cyBnZW5lcwoKCgpgYGB7ciBmaWcud2lkdGg9OH0KZ2VuZXMgPSBjKCJBSzQiLCAiQU5MTiIsICJDQVBHIiwgIklGVDEyMiIsICJKQUcxIiwgIk1ZQiIsICJQQlJNMSIgKQpteWJfdnNfaHB2ID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKCJocHYzM19wb3NpdGl2ZSIsZ2VuZXMpKQpkZiA9IHJlc2hhcGUyOjptZWx0KG15Yl92c19ocHYsdmFsdWUubmFtZSA9ICJsb2dUUE0iKSAlPiUgZHBseXI6OnJlbmFtZShnZW5lID0gdmFyaWFibGUpCgoKc3RhdC50ZXN0IDwtIGRmICU+JQogICAgZ3JvdXBfYnkoZ2VuZSkgJT4lCiAgd2lsY294X3Rlc3QobG9nVFBNIH4gaHB2MzNfcG9zaXRpdmUpICU+JQogIG11dGF0ZSh5LnBvc2l0aW9uID0gNSkKCnN0YXQudGVzdAoKc3RhdC50ZXN0IDwtIHN0YXQudGVzdCAlPiUgCiAgYWRkX3h5X3Bvc2l0aW9uKHggPSAiZ2VuZSIsIGRvZGdlID0gMC44KQoKZ2dib3hwbG90KAogIGRmLAogIHggPSAiZ2VuZSIsCiAgeSA9ICJsb2dUUE0iLAogIGNvbG9yID0gImhwdjMzX3Bvc2l0aXZlIiwKICBwYWxldHRlID0gImpjbyIsCiAgYWRkID0gImppdHRlciIKKSsgc3RhdF9wdmFsdWVfbWFudWFsKHN0YXQudGVzdCx5LnBvc2l0aW9uID0gMTMsIGxhYmVsID0gInAgPSB7cH0iLHJlbW92ZS5icmFja2V0ID0gVCkKYGBgCgpgYGB7cn0Kbm90Y2hfZ2VuZXMgPSBjKCJKQUcxIiwiSkFHMiIsIk5PVENIMyIsIk5PVENIMiIsIk5PVENIMSIsIkRMTDEiLCJNWUIiLCJIRVM0IiwiSEVZMSIsIkhFWTIiLCJOUkFSUCIpCmZvciAoZ2VuZSAgaW4gbm90Y2hfZ2VuZXMpIHsKICBteWJfdnNfaHB2ID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKCJocHYzM19wb3NpdGl2ZSIsZ2VuZSkpIAogIG15Yl92c19ocHYkaHB2MzNfcG9zaXRpdmUgPSBwYXN0ZSgiSFBWMzMiLG15Yl92c19ocHYkaHB2MzNfcG9zaXRpdikKCiAgcCA9IGdnYm94cGxvdChteWJfdnNfaHB2LCB4ID0gImhwdjMzX3Bvc2l0aXZlIiwgeSA9IGdlbmUsCiAgICAgICAgICAgIHBhbGV0dGUgPSAiamNvIiwKICAgICAgICAgICAgYWRkID0gImppdHRlciIpKyBzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveC50ZXN0Iixjb21wYXJpc29ucyA9IGxpc3QoYygiSFBWMzMgcG9zaXRpdmUiLCJIUFYzMyBuZWdhdGl2ZSIpKSkrIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IGZ1bmN0aW9uKHgpIGRhdGEuZnJhbWUoeT1tYXgoeCkqMS4yLCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIscm91bmQobWVhbih4KSxkaWdpdHMgPSAyKSkpLCBnZW9tPSJ0ZXh0IikgK3lsYWIoImxvZzIoZ2VuZSkiKStnZ3RpdGxlKGdlbmUpCiAgcHJpbnRfdGFiKHAsdGl0bGUgPSBnZW5lKQp9CgpgYGAKCgpgYGB7cn0Kbm90Y2hfdGFyZ2V0cyA9IGMoIk5PVENIMyIsIkhFUzQiLCJIRVkxIiwiSEVZMiIsIk5SQVJQIikgCm5vdGNoX2xpZ2FuZCA9IGMoIkpBRzEiLCJKQUcyIiwiRExMMSIpCm5vdGNoX2dlbmVzID0gbGlzdChub3RjaF90YXJnZXRzID0gbm90Y2hfdGFyZ2V0cyxub3RjaF9saWdhbmQgPSBub3RjaF9saWdhbmQpCmZvciAoaSAgaW4gMTpsZW5ndGgobm90Y2hfZ2VuZXMpKSB7CiAgZ2VuZXMgPSBub3RjaF9nZW5lc1tbaV1dCiAgbmFtZSA9IG5hbWVzKCBub3RjaF9nZW5lcylbaV0KICBteWJfdnNfaHB2ID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKGdlbmVzKSkgJT4lIHJvd01lYW5zKCkKICBteWJfdnNfaHB2ID0gbXliX3ZzX2hwdiAlPiUgY2JpbmQoRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKCJocHYzM19wb3NpdGl2ZSIpKSkKICBjb2xuYW1lcyhteWJfdnNfaHB2KVsxXSA9ICJnZW5lX3NldCIKICBteWJfdnNfaHB2JGhwdjMzX3Bvc2l0aXZlID0gcGFzdGUoIkhQVjMzIixteWJfdnNfaHB2JGhwdjMzX3Bvc2l0aXYpCgogIHAgPSBnZ2JveHBsb3QobXliX3ZzX2hwdiwgeCA9ICJocHYzM19wb3NpdGl2ZSIsIHkgPSAiZ2VuZV9zZXQiLAogICAgICAgICAgICBwYWxldHRlID0gImpjbyIsCiAgICAgICAgICAgIGFkZCA9ICJqaXR0ZXIiKSsgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsY29tcGFyaXNvbnMgPSBsaXN0KGMoIkhQVjMzIHBvc2l0aXZlIiwiSFBWMzMgbmVnYXRpdmUiKSkpKyBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBmdW5jdGlvbih4KSBkYXRhLmZyYW1lKHk9bWF4KHgpKjEuMiwgbGFiZWwgPSBwYXN0ZSgiTWVhbj0iLHJvdW5kKG1lYW4oeCksZGlnaXRzID0gMikpKSwgZ2VvbT0idGV4dCIpICt5bGFiKCJsb2cyKGdlbmUpIikrZ2d0aXRsZShuYW1lKQogcHJpbnQocCkKfQoKYGBgCgpgYGB7cn0KICBjb3JfZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygiTVlCIiwibXlvX3Njb3JlIikpCmdncGxvdChjb3JfZGF0YSwgYWVzKHg9TVlCLCB5PW15b19zY29yZSkpICsgCiAgICBzdGF0X2NvcihtZXRob2QgPSAicGVhcnNvbiIpKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtKSAgKwogIGdlb21fcG9pbnQoKQoKCiAgY29yX2RhdGEgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmFycyA9IGMoIkpBRzEiLCJteW9fc2NvcmUiKSkKZ2dwbG90KGNvcl9kYXRhLCBhZXMoeD1KQUcxLCB5PW15b19zY29yZSkpICsgCiAgICBzdGF0X2NvcihtZXRob2QgPSAicGVhcnNvbiIpKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtKSAgKwogIGdlb21fcG9pbnQoKQoKICBjb3JfZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygiSkFHMiIsIm15b19zY29yZSIpKQpnZ3Bsb3QoY29yX2RhdGEsIGFlcyh4PUpBRzIsIHk9bXlvX3Njb3JlKSkgKyAKICAgIHN0YXRfY29yKG1ldGhvZCA9ICJwZWFyc29uIikrCiAgICBnZW9tX3Ntb290aChtZXRob2Q9bG0pICArCiAgZ2VvbV9wb2ludCgpCgogIGNvcl9kYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBjKCJETEwxIiwibXlvX3Njb3JlIikpCmdncGxvdChjb3JfZGF0YSwgYWVzKHg9RExMMSwgeT1teW9fc2NvcmUpKSArIAogICAgc3RhdF9jb3IobWV0aG9kID0gInBlYXJzb24iKSsKICAgIGdlb21fc21vb3RoKG1ldGhvZD1sbSkgICsKICBnZW9tX3BvaW50KCkKCgogIGNvcl9kYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBub3RjaF90YXJnZXRzKSAlPiUgcm93TWVhbnMoKQogIGNvcl9kYXRhID0gY29yX2RhdGEgJT4lIGNiaW5kKEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygibXlvX3Njb3JlIikpKQogIGNvbG5hbWVzKGNvcl9kYXRhKVsxXSA9ICJub3RjaF90YXJnZXRzIgoKICBnZ3Bsb3QoY29yX2RhdGEsIGFlcyh4PW5vdGNoX3RhcmdldHMsIHk9bXlvX3Njb3JlKSkgKyAKICAgIHN0YXRfY29yKG1ldGhvZCA9ICJwZWFyc29uIikrCiAgICBnZW9tX3Ntb290aChtZXRob2Q9bG0pICArCiAgZ2VvbV9wb2ludCgpCiAgCiAgCiAgICBjb3JfZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gbm90Y2hfbGlnYW5kKSAlPiUgcm93TWVhbnMoKQogIGNvcl9kYXRhID0gY29yX2RhdGEgJT4lIGNiaW5kKEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gYygibXlvX3Njb3JlIikpKQogIGNvbG5hbWVzKGNvcl9kYXRhKVsxXSA9ICJub3RjaF9saWdhbmQiCgogIGdncGxvdChjb3JfZGF0YSwgYWVzKHg9bm90Y2hfbGlnYW5kLCB5PW15b19zY29yZSkpICsgCiAgICBzdGF0X2NvcihtZXRob2QgPSAicGVhcnNvbiIpKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtKSAgKwogIGdlb21fcG9pbnQoKQogIApgYGAKCgpgYGB7cn0Kbm90Y2hfc2NvcmUgPSBGZXRjaERhdGEob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsdmFycyA9IG5vdGNoX3RhcmdldHMpICU+JSByb3dNZWFucygpCmFsbF9hY2NfY2FuY2VyX2NlbGxzICA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gbm90Y2hfc2NvcmUsY29sLm5hbWUgPSAibm90Y2hfc2NvcmUiKQpGZWF0dXJlUGxvdChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9ICJub3RjaF9zY29yZSIgKQpgYGAKCgpgYGB7cn0KbXlvX21hcmtlcnMgPSBjKCJUUDYzIiwgIlRQNzMiLCAiS1JUMTQiLCAiQ0RIMyIpCnNjb3JlID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSBteW9fbWFya2VycykgJT4lIHJvd01lYW5zKCkKYWNjMV9jYW5jZXJfY2VsbHMgID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbWV0YWRhdGEgPSBzY29yZSxjb2wubmFtZSA9ICJteW9fbWFya2Vyc19zY29yZSIpCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gIm15b19tYXJrZXJzX3Njb3JlIixwdC5zaXplID0gMiApCgoKbWFya2VycyA9IGMoIkNMRE4zIiwgIkFOWEE4IiwgIkVIRiIsICJLSVQiKQpzY29yZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gbWFya2VycykgJT4lIHJvd01lYW5zKCkKYWNjMV9jYW5jZXJfY2VsbHMgID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbWV0YWRhdGEgPSBzY29yZSxjb2wubmFtZSA9ICJsdW1fbWFya2Vyc19zY29yZSIpCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gImx1bV9tYXJrZXJzX3Njb3JlIiAscHQuc2l6ZSA9IDIgKQpgYGAKCgo8c2NyaXB0IHNyYz0iaHR0cHM6Ly9oeXBvdGhlcy5pcy9lbWJlZC5qcyIgYXN5bmM+PC9zY3JpcHQ+Cg==