1 Functions

library(stringi)
source_from_github(repositoy = "DEG_functions",version = "0.2.45")
ℹ SHA-1 hash of file is 645c7d8e9571eb9caed4b7baf4b058f6a2c051cc
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

2 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)
New names:
• `` -> `...1`
• `` -> `...2`
• `` -> `...3`
• `` -> `...4`
• `` -> `...5`
• `` -> `...6`
• `` -> `...7`
• `` -> `...8`
• `` -> `...9`
• `` -> `...10`
• `` -> `...11`
• `` -> `...12`
• `` -> `...13`
• `` -> `...14`
• `` -> `...15`
• `` -> `...16`
• `` -> `...17`
• `` -> `...18`
• `` -> `...19`
• `` -> `...20`
• `` -> `...21`
• `` -> `...22`
• `` -> `...23`
• `` -> `...24`
• `` -> `...25`
• `` -> `...26`
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)
New names:
• `` -> `...1`
• `` -> `...2`
• `` -> `...3`
• `` -> `...4`
• `` -> `...5`
• `` -> `...6`
• `` -> `...7`
• `` -> `...8`
• `` -> `...9`
• `` -> `...10`
• `` -> `...11`
• `` -> `...12`
• `` -> `...13`
• `` -> `...14`
• `` -> `...15`
• `` -> `...16`
• `` -> `...17`
• `` -> `...18`
• `` -> `...19`
• `` -> `...20`
• `` -> `...21`
• `` -> `...22`
• `` -> `...23`
• `` -> `...24`
• `` -> `...25`
• `` -> `...26`
• `` -> `...27`
• `` -> `...28`
• `` -> `...29`
• `` -> `...30`
• `` -> `...31`
• `` -> `...32`
• `` -> `...33`
• `` -> `...34`
• `` -> `...35`
• `` -> `...36`
• `` -> `...37`
• `` -> `...38`
• `` -> `...39`
• `` -> `...40`
• `` -> `...41`
• `` -> `...42`
• `` -> `...43`
• `` -> `...44`
• `` -> `...45`
• `` -> `...46`
• `` -> `...47`
• `` -> `...48`
• `` -> `...49`
• `` -> `...50`
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)

3 ACC all cells UMAP

DimPlot(acc_all)
Warning in grSoftVersion() :
  unable to load shared object '/usr/local/lib/R/modules//R_X11.so':
  libXt.so.6: cannot open shared object file: No such file or directory

4 Neuronal signatures

for (neural_name in colnames(neuronal_signatures)) {
  genes = neuronal_signatures[,neural_name,drop=T]
  pathways_scores = getPathwayScores(acc_all@assays$RNA@data,pathwayGenes = genes)
  acc_all  %<>% AddMetaData(metadata = pathways_scores$pathwayScores,col.name = neural_name)
}
FeaturePlot(object = acc_all,features = colnames(neuronal_signatures))

5 Neuronal signatures cor genes

for (neural_name in colnames(neuronal_signatures)) {
  genes = neuronal_signatures[,neural_name,drop=T]
  anontation = plot_genes_cor(dataset = acc_all,geneIds = genes,num_of_clusters = 3,show_rownames =T,title = neural_name)
  correlated_genes = anontation %>% filter(cluster == 1) %>% rownames()
  pathways_scores = getPathwayScores(acc_all@assays$RNA@data,pathwayGenes = correlated_genes)
  acc_all  %<>% AddMetaData(metadata = pathways_scores$pathwayScores,col.name = paste0(neural_name,"_cor"))
}

Sympathetic_cholinergic_neuron

Sympathetic_noradrenergic_neuron

Peripheral_nervous_system_neuron_

Autonomic_neuron

Peripheral_neuron

Sensory_neuron

Adrenergic_neuron_tabula_sapiens

Peripheral_sensory_neuron

Parasympathetic_neuron

NA

6 Correlated genes UMAP

FeaturePlot(object = acc_all,features = paste0(colnames(neuronal_signatures),"_cor"))

8 Neuronal pathways in ACC

8.1 dim reduction

DimPlot(acc_cancer)

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
Warning: The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
This message will be shown once per session
DimPlot(acc_cancer,group.by = "patient.ident")

for (pathway_name in names(neuronal_pathways)) {
  genes = neuronal_pathways[[pathway_name]]
  pathways_scores = getPathwayScores(acc_cancer@assays$RNA@data,pathwayGenes = genes)
  acc_cancer  %<>% AddMetaData(metadata = pathways_scores$pathwayScores,col.name = pathway_name)
}
names(neuronal_pathways)
[1] "GOBP_NOREPINEPHRINE_SECRETION"                   "GOBP_NOREPINEPHRINE_TRANSPORT"                  
[3] "GOBP_NORADRENERGIC_NEURON_DEVELOPMENT"           "GOBP_NORADRENERGIC_NEURON_DIFFERENTIATION"      
[5] "GOBP_AUTONOMIC_NERVOUS_SYSTEM_DEVELOPMENT"       "GOBP_PARASYMPATHETIC_NERVOUS_SYSTEM_DEVELOPMENT"
[7] "GOBP_ADRENERGIC_RECEPTOR_SIGNALING_PATHWAY"      "GOMF_BETA_2_ADRENERGIC_RECEPTOR_BINDING"        

8.2 Scores UMAP

FeaturePlot(object = acc_cancer,features = names(neuronal_pathways))

8.3 Scores violin

VlnPlot(object = acc_cancer,features = names(neuronal_pathways),group.by = "patient.ident")

  volcano_plot<- function(de_genes, top_genes_text=0, title = "" ,show_gene_names = NULL, ident1 = "",
                      ident2 = "" , fdr_cutoff = 0.05 , log2fc_cutoff = 0.6, max_names = 10,
                      return_de_genes = F, show_graph = T, show_legend = T) {
  library(ggrepel,quietly = T)
  library(dplyr,quietly = T)
  names_for_label = c(paste(ident2,"down genes"),paste(ident2,"up genes"))
  #color genes if there are over/under/same expressed
  de_genes$diffexpressed <- "Same" 
  de_genes$avg_log2FC[!is.finite(de_genes$avg_log2FC)] <- 1000 #remove infinite values
  
  # #calculate fdr from genes that has logFC > clac_fdr_from_logfc (clac_fdr_from_logfc = 0 -> all genes)
  # filtered_markers = filter(de_genes, abs(avg_log2FC) > clac_fdr_from_logfc) #take genes with logFC > clac_fdr_from_logfc
  # filtered_markers$fdr <-p.adjust(p = filtered_markers$p_val ,method = "fdr") #calc fdr
  # de_genes$fdr = 1 
  # filtered_markers_indexes = which(rownames(de_genes) %in% rownames(filtered_markers))
  # de_genes[filtered_markers_indexes, "fdr"] = filtered_markers$fdr 
  
  de_genes$fdr = p.adjust(p = de_genes$p_val ,method = "fdr")
  # if log2Foldchange > 0.6 and pvalue < 0.05, set as "UP" 
  de_genes$diffexpressed[de_genes$avg_log2FC > log2fc_cutoff & de_genes$fdr < fdr_cutoff] <- names_for_label[1]
  
  # if log2Foldchange < -0.6 and pvalue < 0.05, set as "DOWN"
  de_genes$diffexpressed[de_genes$avg_log2FC < -log2fc_cutoff & de_genes$fdr < fdr_cutoff] <- names_for_label[2]
  
  #set name labels for highest genes
  de_genes$delabel <- NA
  de_genes$delabel[0:top_genes_text] <- rownames(de_genes)[0:top_genes_text]
  
  #set name labels for significant genes
  down_genes = de_genes$diffexpressed == names_for_label[1]
  up_genes = de_genes$diffexpressed == names_for_label[2]
  
  last_gene_to_show_down = which(de_genes$diffexpressed == names_for_label[1])[max_names]
  last_gene_to_show_up = which(de_genes$diffexpressed == names_for_label[2])[max_names]
  
  down_genes[last_gene_to_show_down:length(down_genes)] = F
  up_genes[last_gene_to_show_up:length(up_genes)] = F
  
  de_genes$delabel[up_genes] <- rownames(de_genes)[up_genes]
  de_genes$delabel[down_genes] <- rownames(de_genes)[down_genes]
  
  
  #Show genes that specify in show_gene_names
  if (!is.null(show_gene_names)){
    de_genes_index = match(show_gene_names,rownames(de_genes)) #indexes of de_genes that in show_gene_names
    de_genes_index <- de_genes_index[!is.na(de_genes_index)] #remove NA
  
    show_gene_names_index = show_gene_names %in% rownames(de_genes) #indexes of show_gene_names that in de_genes
    de_genes$delabel[de_genes_index] = show_gene_names [show_gene_names_index]
  }
  
  #colors for diff exp genes
  cols <- structure(c("green4", "red", "grey"), .Names = c(names_for_label[2],names_for_label[1], "Same"))
  
  title = paste(title,"Volcano plot- ", ident1,"vs", ident2)
  p = ggplot(data=de_genes, aes(x=avg_log2FC, y=-log10(p_val), col=diffexpressed, label=delabel)) + 
    geom_point() + 
    theme_minimal() +
    scale_color_manual(values=cols) +
    geom_text_repel(na.rm = T,box.padding = 1,max.overlaps = Inf,color = "blue") +
    xlab(paste("avg_log2FC (Positive = up in", ident1,")"))+ 
    ylab("Significance")+ 
    scale_y_continuous(labels = function(x) {parse(text = paste0("10^-",x))})+
    guides(col=guide_legend(title=paste0("Significant DEG\n(FDR<",fdr_cutoff," ,abs(log2fc) >", log2fc_cutoff,")")))+
    {if(show_legend == F) theme(legend.position="none")}+
    {if(show_legend) ggtitle(title) }+
    theme(axis.text  = element_text( color="black", size=12),axis.title = element_text( color="black", size=12))
  
  if(show_graph == T){print(p)}
  
  if (return_de_genes == T){ return(de_genes)}
  else {return (p)}
  
  }

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

  |                                                  | 0 % ~calculating  
  |+                                                 | 1 % ~08s          
  |++                                                | 2 % ~08s          
  |++                                                | 3 % ~08s          
  |+++                                               | 4 % ~08s          
  |+++                                               | 5 % ~07s          
  |++++                                              | 6 % ~07s          
  |++++                                              | 7 % ~07s          
  |+++++                                             | 8 % ~07s          
  |+++++                                             | 9 % ~07s          
  |++++++                                            | 10% ~07s          
  |++++++                                            | 11% ~07s          
  |+++++++                                           | 12% ~07s          
  |+++++++                                           | 13% ~06s          
  |++++++++                                          | 14% ~06s          
  |++++++++                                          | 15% ~06s          
  |+++++++++                                         | 16% ~06s          
  |+++++++++                                         | 17% ~06s          
  |++++++++++                                        | 18% ~06s          
  |++++++++++                                        | 19% ~06s          
  |+++++++++++                                       | 20% ~06s          
  |+++++++++++                                       | 21% ~06s          
  |++++++++++++                                      | 22% ~05s          
  |++++++++++++                                      | 23% ~05s          
  |+++++++++++++                                     | 24% ~05s          
  |+++++++++++++                                     | 25% ~05s          
  |++++++++++++++                                    | 26% ~05s          
  |++++++++++++++                                    | 27% ~05s          
  |+++++++++++++++                                   | 28% ~05s          
  |+++++++++++++++                                   | 29% ~05s          
  |++++++++++++++++                                  | 30% ~05s          
  |++++++++++++++++                                  | 31% ~05s          
  |+++++++++++++++++                                 | 32% ~05s          
  |+++++++++++++++++                                 | 33% ~04s          
  |++++++++++++++++++                                | 34% ~04s          
  |++++++++++++++++++                                | 35% ~04s          
  |+++++++++++++++++++                               | 36% ~04s          
  |+++++++++++++++++++                               | 37% ~04s          
  |++++++++++++++++++++                              | 38% ~04s          
  |++++++++++++++++++++                              | 39% ~04s          
  |+++++++++++++++++++++                             | 40% ~04s          
  |+++++++++++++++++++++                             | 41% ~04s          
  |++++++++++++++++++++++                            | 42% ~04s          
  |++++++++++++++++++++++                            | 43% ~04s          
  |+++++++++++++++++++++++                           | 44% ~04s          
  |+++++++++++++++++++++++                           | 45% ~04s          
  |++++++++++++++++++++++++                          | 46% ~04s          
  |++++++++++++++++++++++++                          | 47% ~04s          
  |+++++++++++++++++++++++++                         | 48% ~03s          
  |+++++++++++++++++++++++++                         | 49% ~03s          
  |++++++++++++++++++++++++++                        | 51% ~03s          
  |++++++++++++++++++++++++++                        | 52% ~03s          
  |+++++++++++++++++++++++++++                       | 53% ~03s          
  |+++++++++++++++++++++++++++                       | 54% ~03s          
  |++++++++++++++++++++++++++++                      | 55% ~03s          
  |++++++++++++++++++++++++++++                      | 56% ~03s          
  |+++++++++++++++++++++++++++++                     | 57% ~03s          
  |+++++++++++++++++++++++++++++                     | 58% ~03s          
  |++++++++++++++++++++++++++++++                    | 59% ~03s          
  |++++++++++++++++++++++++++++++                    | 60% ~03s          
  |+++++++++++++++++++++++++++++++                   | 61% ~03s          
  |+++++++++++++++++++++++++++++++                   | 62% ~03s          
  |++++++++++++++++++++++++++++++++                  | 63% ~02s          
  |++++++++++++++++++++++++++++++++                  | 64% ~02s          
  |+++++++++++++++++++++++++++++++++                 | 65% ~02s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~02s          
  |++++++++++++++++++++++++++++++++++                | 67% ~02s          
  |++++++++++++++++++++++++++++++++++                | 68% ~02s          
  |+++++++++++++++++++++++++++++++++++               | 69% ~02s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~02s          
  |++++++++++++++++++++++++++++++++++++              | 71% ~02s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~02s          
  |+++++++++++++++++++++++++++++++++++++             | 73% ~02s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~02s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~02s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~02s          
  |+++++++++++++++++++++++++++++++++++++++           | 77% ~02s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 79% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 81% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 83% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=06s  
volcano_plot(de_genes = markers,max_names = 10,title = "markers",ident1 = "ACC2",ident2 = "PNI patients",show_graph = F)

9.1 GSEA

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

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

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 ~ "unknowkn"))
for (pathway_name in names(neuronal_pathways)) {
  genes = neuronal_pathways[[pathway_name]]
  pathways_scores = getPathwayScores(acc_cancer_pri@assays$RNA@data,pathwayGenes = genes)
  acc_cancer_pri  %<>% AddMetaData(metadata = pathways_scores$pathwayScores,col.name = pathway_name)
}
FeaturePlot(object = acc_cancer_pri,features =  names(neuronal_pathways))

10 Lum vs Myo

library(ggpubr)
for (pathway in names(neuronal_pathways)) {
  data = FetchData(object = acc_cancer_pri,vars = c("lum_or_myo",pathway)) 
  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("score")+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

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCiMgRnVuY3Rpb25zCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHN0cmluZ2kpCnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiREVHX2Z1bmN0aW9ucyIsdmVyc2lvbiA9ICIwLjIuNDUiKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gImNOTUZfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuNC4wIixzY3JpcHRfbmFtZSA9ICJjbm1mX2Z1bmN0aW9uc19WMy5SIikKc291cmNlX2Zyb21fZ2l0aHViKHJlcG9zaXRveSA9ICJzY19nZW5lcmFsX2Z1bmN0aW9ucyIsdmVyc2lvbiA9ICIwLjEuMjgiLHNjcmlwdF9uYW1lID0gImZ1bmN0aW9ucy5SIikKYGBgCgojIERhdGEKCmBgYHtyfQpsaWJyYXJ5KCJyZWFkeGwiKQphY2NfYWxsID0gcmVhZFJEUyhmaWxlID0gIi4vRGF0YS9hY2NfdHBtX25Db3VudF9taXRvX25vMTQ2XzE1a19hbGxkYXRhLnJkcyIpCmFjY19jYW5jZXJfcHJpID0gcmVhZFJEUyhmaWxlID0gIi4vRGF0YS9hY2NfY2FuY2VyX25vMTQ2X3ByaW1hcnlvbmx5MTVrX2NhbmNlcmNlbGxzLnJkcyIpCmFjY19jYW5jZXIgPSByZWFkUkRTKGZpbGUgPSAiLi9EYXRhL2FjY190cG1fbkNvdW50X21pdG9fbm8xNDZfMTVrX2NhbmNlcmNlbGxzLnJkcyIpCgoKbmV1cm9uYWxfc2lnbmF0dXJlcyA8LSByZWFkX2V4Y2VsKCIuL0RhdGEvTmV1cm9uYWwgU2lnbmF0dXJlcy54bHN4Iixjb2xfbmFtZXMgPUYpCm5ldXJvbmFsX3NpZ25hdHVyZXMgICU8PiUgIHQoKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSBqYW5pdG9yOjpyb3dfdG9fbmFtZXMoMSkgJT4lICBmaWx0ZXIoIXJvd19udW1iZXIoKSA9PSAxKQpyb3duYW1lcyhuZXVyb25hbF9zaWduYXR1cmVzKSA8LSBOVUxMCmNvbG5hbWVzKG5ldXJvbmFsX3NpZ25hdHVyZXMpICAgJTw+JSAgZ3N1YihyZXBsYWNlbWVudCA9ICIiLCBwYXR0ZXJuID0gIl9cXGQuKiIpICNyZW1vdmUgYW55IF9udW1iZXJzCmNvbG5hbWVzKG5ldXJvbmFsX3NpZ25hdHVyZXMpICAgJTw+JSAgZ3N1YihyZXBsYWNlbWVudCA9ICIiLCBwYXR0ZXJuID0gIlxcKC4qIikgI3JlbmFtZSAiKCIgdG8gdGhlIGVuZApjb2xuYW1lcyhuZXVyb25hbF9zaWduYXR1cmVzKSAgICU8PiUgIGdzdWIocmVwbGFjZW1lbnQgPSAiXyIsIHBhdHRlcm4gPSAiICIpICNyZW5hbWUgYWxsIHNwYWNlcwoKbmV1cm9uYWxfcGF0aHdheXMgPC0gcmVhZF9leGNlbCgiLi9EYXRhL1BhdGh3YXkgYW5hbHlzaXMgR2VuZSBzZXRzLnhsc3giLGNvbF9uYW1lcyA9RikKbmV1cm9uYWxfcGF0aHdheXMgICU8PiUgIHQoKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSBqYW5pdG9yOjpyb3dfdG9fbmFtZXMoMSkgJT4lICBmaWx0ZXIoIXJvd19udW1iZXIoKSA9PSAxKSAgJT4lICBhcy5saXN0KCkgCm5ldXJvbmFsX3BhdGh3YXlzID0gbGFwcGx5KG5ldXJvbmFsX3BhdGh3YXlzLCBuYS5vbWl0KQpuZXVyb25hbF9wYXRod2F5cyA9IGxhcHBseShuZXVyb25hbF9wYXRod2F5cywgYXMuY2hhcmFjdGVyKQoKYGBgCgojIEFDQyBhbGwgY2VsbHMgVU1BUAoKYGBge3J9CkRpbVBsb3QoYWNjX2FsbCkKYGBgCgojIE5ldXJvbmFsIHNpZ25hdHVyZXMKCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpmb3IgKG5ldXJhbF9uYW1lIGluIGNvbG5hbWVzKG5ldXJvbmFsX3NpZ25hdHVyZXMpKSB7CiAgZ2VuZXMgPSBuZXVyb25hbF9zaWduYXR1cmVzWyxuZXVyYWxfbmFtZSxkcm9wPVRdCiAgcGF0aHdheXNfc2NvcmVzID0gZ2V0UGF0aHdheVNjb3JlcyhhY2NfYWxsQGFzc2F5cyRSTkFAZGF0YSxwYXRod2F5R2VuZXMgPSBnZW5lcykKICBhY2NfYWxsICAlPD4lIEFkZE1ldGFEYXRhKG1ldGFkYXRhID0gcGF0aHdheXNfc2NvcmVzJHBhdGh3YXlTY29yZXMsY29sLm5hbWUgPSBuZXVyYWxfbmFtZSkKfQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xMn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjX2FsbCxmZWF0dXJlcyA9IGNvbG5hbWVzKG5ldXJvbmFsX3NpZ25hdHVyZXMpKQpgYGAKCiMgTmV1cm9uYWwgc2lnbmF0dXJlcyBjb3IgZ2VuZXMgey50YWJzZXR9CgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KZm9yIChuZXVyYWxfbmFtZSBpbiBjb2xuYW1lcyhuZXVyb25hbF9zaWduYXR1cmVzKSkgewogIGdlbmVzID0gbmV1cm9uYWxfc2lnbmF0dXJlc1ssbmV1cmFsX25hbWUsZHJvcD1UXQogIGFub250YXRpb24gPSBwbG90X2dlbmVzX2NvcihkYXRhc2V0ID0gYWNjX2FsbCxnZW5lSWRzID0gZ2VuZXMsbnVtX29mX2NsdXN0ZXJzID0gMyxzaG93X3Jvd25hbWVzID1ULHRpdGxlID0gbmV1cmFsX25hbWUpCiAgY29ycmVsYXRlZF9nZW5lcyA9IGFub250YXRpb24gJT4lIGZpbHRlcihjbHVzdGVyID09IDEpICU+JSByb3duYW1lcygpCiAgcGF0aHdheXNfc2NvcmVzID0gZ2V0UGF0aHdheVNjb3JlcyhhY2NfYWxsQGFzc2F5cyRSTkFAZGF0YSxwYXRod2F5R2VuZXMgPSBjb3JyZWxhdGVkX2dlbmVzKQogIGFjY19hbGwgICU8PiUgQWRkTWV0YURhdGEobWV0YWRhdGEgPSBwYXRod2F5c19zY29yZXMkcGF0aHdheVNjb3Jlcyxjb2wubmFtZSA9IHBhc3RlMChuZXVyYWxfbmFtZSwiX2NvciIpKQp9CgpgYGAKCiMgQ29ycmVsYXRlZCBnZW5lcyBVTUFQCgpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CkZlYXR1cmVQbG90KG9iamVjdCA9IGFjY19hbGwsZmVhdHVyZXMgPSBwYXN0ZTAoY29sbmFtZXMobmV1cm9uYWxfc2lnbmF0dXJlcyksIl9jb3IiKSkKYGBgCgojIENTRjMKCltTaW5nbGUtY2VsbCBSTkEgc2VxdWVuY2luZyByZXZlYWxzIGludHJhdHVtb3JhbCBoZXRlcm9nZW5laXR5IGFuZCBwb3RlbnRpYWwgbWVjaGFuaXNtcyBvZiBtYWxpZ25hbnQgcHJvZ3Jlc3Npb24gaW4gcHJvc3RhdGUgY2FuY2VyIHdpdGggcGVyaW5ldXJhbCBpbnZhc2lvbl0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DOTg3NTc5OS8pCgpgYGB7cn0KVmxuUGxvdChvYmplY3QgPSBhY2NfYWxsLGZlYXR1cmVzID0gIkNTRjMiLGdyb3VwLmJ5ID0gInBhdGllbnQuaWRlbnQiKQpgYGAKCiMgTmV1cm9uYWwgcGF0aHdheXMgaW4gQUNDCgojIyBkaW0gcmVkdWN0aW9uCgpgYGB7cn0KRGltUGxvdChhY2NfY2FuY2VyKQphY2NfY2FuY2VyIDwtIFJ1blBDQShhY2NfY2FuY2VyLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gYWNjX2NhbmNlciksdmVyYm9zZSA9IEYpCkVsYm93UGxvdChhY2NfY2FuY2VyKQphY2NfY2FuY2VyIDwtIEZpbmROZWlnaGJvcnMoYWNjX2NhbmNlciwgZGltcyA9IDE6MTAsdmVyYm9zZSA9IEYpICU+JSAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjUpICU+JSAgUnVuVU1BUChkaW1zID0gMToxMCx2ZXJib3NlID0gRikKYGBgCgpgYGB7cn0KRGltUGxvdChhY2NfY2FuY2VyLGdyb3VwLmJ5ID0gInBhdGllbnQuaWRlbnQiKQpgYGAKCmBgYHtyfQpmb3IgKHBhdGh3YXlfbmFtZSBpbiBuYW1lcyhuZXVyb25hbF9wYXRod2F5cykpIHsKICBnZW5lcyA9IG5ldXJvbmFsX3BhdGh3YXlzW1twYXRod2F5X25hbWVdXQogIHBhdGh3YXlzX3Njb3JlcyA9IGdldFBhdGh3YXlTY29yZXMoYWNjX2NhbmNlckBhc3NheXMkUk5BQGRhdGEscGF0aHdheUdlbmVzID0gZ2VuZXMpCiAgYWNjX2NhbmNlciAgJTw+JSBBZGRNZXRhRGF0YShtZXRhZGF0YSA9IHBhdGh3YXlzX3Njb3JlcyRwYXRod2F5U2NvcmVzLGNvbC5uYW1lID0gcGF0aHdheV9uYW1lKQp9CmBgYAoKYGBge3J9Cm5hbWVzKG5ldXJvbmFsX3BhdGh3YXlzKQpgYGAKCiMjIFNjb3JlcyBVTUFQCgpgYGB7ciBmaWcuaGVpZ2h0PTEzLCBmaWcud2lkdGg9MTN9CkZlYXR1cmVQbG90KG9iamVjdCA9IGFjY19jYW5jZXIsZmVhdHVyZXMgPSBuYW1lcyhuZXVyb25hbF9wYXRod2F5cykpCmBgYAoKIyMgU2NvcmVzIHZpb2xpbgoKYGBge3IgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTEyfQpWbG5QbG90KG9iamVjdCA9IGFjY19jYW5jZXIsZmVhdHVyZXMgPSBuYW1lcyhuZXVyb25hbF9wYXRod2F5cyksZ3JvdXAuYnkgPSAicGF0aWVudC5pZGVudCIpCmBgYAoKYGBge3J9CiAgdm9sY2Fub19wbG90PC0gZnVuY3Rpb24oZGVfZ2VuZXMsIHRvcF9nZW5lc190ZXh0PTAsIHRpdGxlID0gIiIgLHNob3dfZ2VuZV9uYW1lcyA9IE5VTEwsIGlkZW50MSA9ICIiLAogICAgICAgICAgICAgICAgICAgICAgaWRlbnQyID0gIiIgLCBmZHJfY3V0b2ZmID0gMC4wNSAsIGxvZzJmY19jdXRvZmYgPSAwLjYsIG1heF9uYW1lcyA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgcmV0dXJuX2RlX2dlbmVzID0gRiwgc2hvd19ncmFwaCA9IFQsIHNob3dfbGVnZW5kID0gVCkgewogIGxpYnJhcnkoZ2dyZXBlbCxxdWlldGx5ID0gVCkKICBsaWJyYXJ5KGRwbHlyLHF1aWV0bHkgPSBUKQogIG5hbWVzX2Zvcl9sYWJlbCA9IGMocGFzdGUoaWRlbnQyLCJkb3duIGdlbmVzIikscGFzdGUoaWRlbnQyLCJ1cCBnZW5lcyIpKQogICNjb2xvciBnZW5lcyBpZiB0aGVyZSBhcmUgb3Zlci91bmRlci9zYW1lIGV4cHJlc3NlZAogIGRlX2dlbmVzJGRpZmZleHByZXNzZWQgPC0gIlNhbWUiIAogIGRlX2dlbmVzJGF2Z19sb2cyRkNbIWlzLmZpbml0ZShkZV9nZW5lcyRhdmdfbG9nMkZDKV0gPC0gMTAwMCAjcmVtb3ZlIGluZmluaXRlIHZhbHVlcwogIAogICMgI2NhbGN1bGF0ZSBmZHIgZnJvbSBnZW5lcyB0aGF0IGhhcyBsb2dGQyA+IGNsYWNfZmRyX2Zyb21fbG9nZmMgKGNsYWNfZmRyX2Zyb21fbG9nZmMgPSAwIC0+IGFsbCBnZW5lcykKICAjIGZpbHRlcmVkX21hcmtlcnMgPSBmaWx0ZXIoZGVfZ2VuZXMsIGFicyhhdmdfbG9nMkZDKSA+IGNsYWNfZmRyX2Zyb21fbG9nZmMpICN0YWtlIGdlbmVzIHdpdGggbG9nRkMgPiBjbGFjX2Zkcl9mcm9tX2xvZ2ZjCiAgIyBmaWx0ZXJlZF9tYXJrZXJzJGZkciA8LXAuYWRqdXN0KHAgPSBmaWx0ZXJlZF9tYXJrZXJzJHBfdmFsICxtZXRob2QgPSAiZmRyIikgI2NhbGMgZmRyCiAgIyBkZV9nZW5lcyRmZHIgPSAxIAogICMgZmlsdGVyZWRfbWFya2Vyc19pbmRleGVzID0gd2hpY2gocm93bmFtZXMoZGVfZ2VuZXMpICVpbiUgcm93bmFtZXMoZmlsdGVyZWRfbWFya2VycykpCiAgIyBkZV9nZW5lc1tmaWx0ZXJlZF9tYXJrZXJzX2luZGV4ZXMsICJmZHIiXSA9IGZpbHRlcmVkX21hcmtlcnMkZmRyIAogIAogIGRlX2dlbmVzJGZkciA9IHAuYWRqdXN0KHAgPSBkZV9nZW5lcyRwX3ZhbCAsbWV0aG9kID0gImZkciIpCiAgIyBpZiBsb2cyRm9sZGNoYW5nZSA+IDAuNiBhbmQgcHZhbHVlIDwgMC4wNSwgc2V0IGFzICJVUCIgCiAgZGVfZ2VuZXMkZGlmZmV4cHJlc3NlZFtkZV9nZW5lcyRhdmdfbG9nMkZDID4gbG9nMmZjX2N1dG9mZiAmIGRlX2dlbmVzJGZkciA8IGZkcl9jdXRvZmZdIDwtIG5hbWVzX2Zvcl9sYWJlbFsxXQogIAogICMgaWYgbG9nMkZvbGRjaGFuZ2UgPCAtMC42IGFuZCBwdmFsdWUgPCAwLjA1LCBzZXQgYXMgIkRPV04iCiAgZGVfZ2VuZXMkZGlmZmV4cHJlc3NlZFtkZV9nZW5lcyRhdmdfbG9nMkZDIDwgLWxvZzJmY19jdXRvZmYgJiBkZV9nZW5lcyRmZHIgPCBmZHJfY3V0b2ZmXSA8LSBuYW1lc19mb3JfbGFiZWxbMl0KICAKICAjc2V0IG5hbWUgbGFiZWxzIGZvciBoaWdoZXN0IGdlbmVzCiAgZGVfZ2VuZXMkZGVsYWJlbCA8LSBOQQogIGRlX2dlbmVzJGRlbGFiZWxbMDp0b3BfZ2VuZXNfdGV4dF0gPC0gcm93bmFtZXMoZGVfZ2VuZXMpWzA6dG9wX2dlbmVzX3RleHRdCiAgCiAgI3NldCBuYW1lIGxhYmVscyBmb3Igc2lnbmlmaWNhbnQgZ2VuZXMKICBkb3duX2dlbmVzID0gZGVfZ2VuZXMkZGlmZmV4cHJlc3NlZCA9PSBuYW1lc19mb3JfbGFiZWxbMV0KICB1cF9nZW5lcyA9IGRlX2dlbmVzJGRpZmZleHByZXNzZWQgPT0gbmFtZXNfZm9yX2xhYmVsWzJdCiAgCiAgbGFzdF9nZW5lX3RvX3Nob3dfZG93biA9IHdoaWNoKGRlX2dlbmVzJGRpZmZleHByZXNzZWQgPT0gbmFtZXNfZm9yX2xhYmVsWzFdKVttYXhfbmFtZXNdCiAgbGFzdF9nZW5lX3RvX3Nob3dfdXAgPSB3aGljaChkZV9nZW5lcyRkaWZmZXhwcmVzc2VkID09IG5hbWVzX2Zvcl9sYWJlbFsyXSlbbWF4X25hbWVzXQogIAogIGRvd25fZ2VuZXNbbGFzdF9nZW5lX3RvX3Nob3dfZG93bjpsZW5ndGgoZG93bl9nZW5lcyldID0gRgogIHVwX2dlbmVzW2xhc3RfZ2VuZV90b19zaG93X3VwOmxlbmd0aCh1cF9nZW5lcyldID0gRgogIAogIGRlX2dlbmVzJGRlbGFiZWxbdXBfZ2VuZXNdIDwtIHJvd25hbWVzKGRlX2dlbmVzKVt1cF9nZW5lc10KICBkZV9nZW5lcyRkZWxhYmVsW2Rvd25fZ2VuZXNdIDwtIHJvd25hbWVzKGRlX2dlbmVzKVtkb3duX2dlbmVzXQogIAogIAogICNTaG93IGdlbmVzIHRoYXQgc3BlY2lmeSBpbiBzaG93X2dlbmVfbmFtZXMKICBpZiAoIWlzLm51bGwoc2hvd19nZW5lX25hbWVzKSl7CiAgICBkZV9nZW5lc19pbmRleCA9IG1hdGNoKHNob3dfZ2VuZV9uYW1lcyxyb3duYW1lcyhkZV9nZW5lcykpICNpbmRleGVzIG9mIGRlX2dlbmVzIHRoYXQgaW4gc2hvd19nZW5lX25hbWVzCiAgICBkZV9nZW5lc19pbmRleCA8LSBkZV9nZW5lc19pbmRleFshaXMubmEoZGVfZ2VuZXNfaW5kZXgpXSAjcmVtb3ZlIE5BCiAgCiAgICBzaG93X2dlbmVfbmFtZXNfaW5kZXggPSBzaG93X2dlbmVfbmFtZXMgJWluJSByb3duYW1lcyhkZV9nZW5lcykgI2luZGV4ZXMgb2Ygc2hvd19nZW5lX25hbWVzIHRoYXQgaW4gZGVfZ2VuZXMKICAgIGRlX2dlbmVzJGRlbGFiZWxbZGVfZ2VuZXNfaW5kZXhdID0gc2hvd19nZW5lX25hbWVzIFtzaG93X2dlbmVfbmFtZXNfaW5kZXhdCiAgfQogIAogICNjb2xvcnMgZm9yIGRpZmYgZXhwIGdlbmVzCiAgY29scyA8LSBzdHJ1Y3R1cmUoYygiZ3JlZW40IiwgInJlZCIsICJncmV5IiksIC5OYW1lcyA9IGMobmFtZXNfZm9yX2xhYmVsWzJdLG5hbWVzX2Zvcl9sYWJlbFsxXSwgIlNhbWUiKSkKICAKICB0aXRsZSA9IHBhc3RlKHRpdGxlLCJWb2xjYW5vIHBsb3QtICIsIGlkZW50MSwidnMiLCBpZGVudDIpCiAgcCA9IGdncGxvdChkYXRhPWRlX2dlbmVzLCBhZXMoeD1hdmdfbG9nMkZDLCB5PS1sb2cxMChwX3ZhbCksIGNvbD1kaWZmZXhwcmVzc2VkLCBsYWJlbD1kZWxhYmVsKSkgKyAKICAgIGdlb21fcG9pbnQoKSArIAogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29scykgKwogICAgZ2VvbV90ZXh0X3JlcGVsKG5hLnJtID0gVCxib3gucGFkZGluZyA9IDEsbWF4Lm92ZXJsYXBzID0gSW5mLGNvbG9yID0gImJsdWUiKSArCiAgICB4bGFiKHBhc3RlKCJhdmdfbG9nMkZDIChQb3NpdGl2ZSA9IHVwIGluIiwgaWRlbnQxLCIpIikpKyAKICAgIHlsYWIoIlNpZ25pZmljYW5jZSIpKyAKICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBmdW5jdGlvbih4KSB7cGFyc2UodGV4dCA9IHBhc3RlMCgiMTBeLSIseCkpfSkrCiAgICBndWlkZXMoY29sPWd1aWRlX2xlZ2VuZCh0aXRsZT1wYXN0ZTAoIlNpZ25pZmljYW50IERFR1xuKEZEUjwiLGZkcl9jdXRvZmYsIiAsYWJzKGxvZzJmYykgPiIsIGxvZzJmY19jdXRvZmYsIikiKSkpKwogICAge2lmKHNob3dfbGVnZW5kID09IEYpIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpfSsKICAgIHtpZihzaG93X2xlZ2VuZCkgZ2d0aXRsZSh0aXRsZSkgfSsKICAgIHRoZW1lKGF4aXMudGV4dCAgPSBlbGVtZW50X3RleHQoIGNvbG9yPSJibGFjayIsIHNpemU9MTIpLGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoIGNvbG9yPSJibGFjayIsIHNpemU9MTIpKQogIAogIGlmKHNob3dfZ3JhcGggPT0gVCl7cHJpbnQocCl9CiAgCiAgaWYgKHJldHVybl9kZV9nZW5lcyA9PSBUKXsgcmV0dXJuKGRlX2dlbmVzKX0KICBlbHNlIHtyZXR1cm4gKHApfQogIAogIH0KYGBgCgojIEFDQzIgREVHCgpgYGB7cn0KYWNjX2NhbmNlcl9wcmkgPSBTZXRJZGVudChvYmplY3QgPSBhY2NfY2FuY2VyX3ByaSx2YWx1ZSA9ICJwYXRpZW50LmlkZW50IikKbWFya2VycyA9IEZpbmRNYXJrZXJzKG9iamVjdCA9IGFjY19jYW5jZXJfcHJpLGlkZW50LjEgPSAiQUNDMiIsZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKGFjY19jYW5jZXJfcHJpKSxkZW5zaWZ5ID0gVCkKdm9sY2Fub19wbG90KGRlX2dlbmVzID0gbWFya2VycyxtYXhfbmFtZXMgPSAxMCx0aXRsZSA9ICJtYXJrZXJzIixpZGVudDEgPSAiQUNDMiIsaWRlbnQyID0gIlBOSSBwYXRpZW50cyIsc2hvd19ncmFwaCA9IEYpCmBgYAoKIyMgR1NFQQoKdXAgPSB1cCBpbiBBQ0MyCgpgYGB7cn0KbGlicmFyeShoeXBlUikKZ2VuZXNldHMgPC0gbXNpZ2RiX2Rvd25sb2FkKCJIb21vIHNhcGllbnMiLGNhdGVnb3J5PSJIIikgJT4lIGFwcGVuZCggbXNpZ2RiX2Rvd25sb2FkKCJIb21vIHNhcGllbnMiLGNhdGVnb3J5PSJDMiIsc3ViY2F0ZWdvcnkgPSAiQ1AiKSkKYWxsX2dlbmVzID0gbWFya2VycyAgJT4lICBhcnJhbmdlKGRlc2MoYXZnX2xvZzJGQykpICU+JSBzZWxlY3QoImF2Z19sb2cyRkMiKSAKcmFua2VkX2xpc3QgICA8LSBzZXROYW1lcyhhbGxfZ2VuZXMkYXZnX2xvZzJGQywgcm93bmFtZXMoYWxsX2dlbmVzKSkKaHlwX29iaiA8LSBoeXBlUl9mZ3NlYShzaWduYXR1cmUgPSByYW5rZWRfbGlzdCxnZW5lc2V0cyA9ICBnZW5lc2V0cyx1cF9vbmx5ID0gRikKaHlwX2RvdHMoaHlwX29iaikKYGBgCgpgYGB7cn0KZ2VuZXNldHMgPC0gbXNpZ2RiX2Rvd25sb2FkKCJIb21vIHNhcGllbnMiLGNhdGVnb3J5PSJIIikgJT4lIGFwcGVuZCggbXNpZ2RiX2Rvd25sb2FkKCJIb21vIHNhcGllbnMiLGNhdGVnb3J5PSJDNSIsc3ViY2F0ZWdvcnkgPSAiR086QlAiKSkKYWxsX2dlbmVzID0gbWFya2VycyAgJT4lICBhcnJhbmdlKGRlc2MoYXZnX2xvZzJGQykpICU+JSBzZWxlY3QoImF2Z19sb2cyRkMiKSAKcmFua2VkX2xpc3QgICA8LSBzZXROYW1lcyhhbGxfZ2VuZXMkYXZnX2xvZzJGQywgcm93bmFtZXMoYWxsX2dlbmVzKSkKaHlwX29iaiA8LSBoeXBlUl9mZ3NlYShzaWduYXR1cmUgPSByYW5rZWRfbGlzdCxnZW5lc2V0cyA9ICBnZW5lc2V0cyx1cF9vbmx5ID0gRikKaHlwX2RvdHMoaHlwX29iaikKYGBgCgpgYGB7PWh0bWx9CjxzY3JpcHQgc3JjPSJodHRwczovL2h5cG90aGVzLmlzL2VtYmVkLmpzIiBhc3luYz48L3NjcmlwdD4KYGBgCmBgYHtyfQpsdW1fc2NvcmUgPSBGZXRjaERhdGEoYWNjX2NhbmNlcl9wcmksImx1bWluYWxfb3Zlcl9teW8iKQpsdW1fc2NvcmUgICU8PiUgbXV0YXRlIChsdW1fb3JfbXlvID0gY2FzZV93aGVuKAogICAgICAgICBsdW1pbmFsX292ZXJfbXlvID4gMSB+ICJsdW1pbmFsIiwKICAgICAgICAgbHVtaW5hbF9vdmVyX215byA8ICgtMSkgfiAibXlvIiwKICAgICAgICAgVFJVRSB+ICJ1bmtub3duIikpCmFjY19jYW5jZXJfcHJpICAlPD4lIEFkZE1ldGFEYXRhKG1ldGFkYXRhID0gbHVtX3Njb3JlJGx1bV9vcl9teW8sY29sLm5hbWUgPSAibHVtX29yX215byIpCmBgYAoKYGBge3J9CmZvciAocGF0aHdheV9uYW1lIGluIG5hbWVzKG5ldXJvbmFsX3BhdGh3YXlzKSkgewogIGdlbmVzID0gbmV1cm9uYWxfcGF0aHdheXNbW3BhdGh3YXlfbmFtZV1dCiAgcGF0aHdheXNfc2NvcmVzID0gZ2V0UGF0aHdheVNjb3JlcyhhY2NfY2FuY2VyX3ByaUBhc3NheXMkUk5BQGRhdGEscGF0aHdheUdlbmVzID0gZ2VuZXMpCiAgYWNjX2NhbmNlcl9wcmkgICU8PiUgQWRkTWV0YURhdGEobWV0YWRhdGEgPSBwYXRod2F5c19zY29yZXMkcGF0aHdheVNjb3Jlcyxjb2wubmFtZSA9IHBhdGh3YXlfbmFtZSkKfQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTMsIGZpZy53aWR0aD0xM30KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjX2NhbmNlcl9wcmksZmVhdHVyZXMgPSAgbmFtZXMobmV1cm9uYWxfcGF0aHdheXMpKQpgYGAKCiMgTHVtIHZzIE15byB7LnRhYnNldH0KCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpsaWJyYXJ5KGdncHVicikKZm9yIChwYXRod2F5IGluIG5hbWVzKG5ldXJvbmFsX3BhdGh3YXlzKSkgewogIGRhdGEgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2NhbmNlcl9wcmksdmFycyA9IGMoImx1bV9vcl9teW8iLHBhdGh3YXkpKSAKICBwID0gZ2dib3hwbG90KGRhdGEsIHggPSAibHVtX29yX215byIsIHkgPXBhdGh3YXksCiAgICAgICAgICAgICAgICBwYWxldHRlID0gImpjbyIsCiAgICAgICAgICAgICAgICBhZGQgPSAiaml0dGVyIikrIAogICAgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsY29tcGFyaXNvbnMgPSBsaXN0KGMoImx1bWluYWwiLCJteW8iKSkpKyBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBmdW5jdGlvbih4KSBkYXRhLmZyYW1lKHk9bWF4KHgpKjEuMiwgbGFiZWwgPSBwYXN0ZSgiTWVhbj0iLHJvdW5kKG1lYW4oeCksZGlnaXRzID0gMikpKSwgZ2VvbT0idGV4dCIpICt5bGFiKCJzY29yZSIpK2dndGl0bGUocGF0aHdheSkKICBwcmludF90YWIocCx0aXRsZSA9IHBhdGh3YXkpCn0KCmBgYAo=