This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

First, install the package dependencies required for this analysis. Required package libraries will be loaded in their respective steps.

#Install Package Dependencies 
install.packages(c("readr", "survival", "ranger", "dplyr", "ggplot2", "ggfortify", "survminer","ggrepel", "tidyr", "tibble", "pheatmap", "stringr"))
BiocManager::install(c("edgeR", "EnhancedVolcano", "DESeq2", "limma"))
#Load Libraries
library(readr)
library(survival)
library(ranger)
library(ggplot2)
library(dplyr)
library(ggfortify)
library(survminer)
library(ggrepel)
library(tidyr)
library(tibble)
library(limma)
library(edgeR)
library(stringr)

Download the Input datasets onto your desktop directory to load into R (available in Supplementary Information).

For the first analysis (Univariate Cox-Proportional Hazards Model and Kaplain-Meier analysis of genes) we will use “GSEsurvgenes.csv” and “TCGAsurvgenes.csv”. These are survival data for Overall Survival and Progression Free Survival from the respective cohorts: GSE107943 and TCGA-CHOL, appended with gene expression information of the 3017 genes from the Immune Gene Signature (Table S1)

#Data Loading
setwd("~/Desktop/Datasets/")
GSEsurvgenes <- read_csv("~/Desktop/Datasets/GSEsurvgenes.csv")
TCGAsurvgenes <- read_csv("~/Desktop/Datasets/TCGAsurvgenes.csv")
colnames(GSEsurvgenes) <- gsub(x = colnames(GSEsurvgenes), pattern = "\\-", replacement = "")
colnames(TCGAsurvgenes) <- gsub(x = colnames(TCGAsurvgenes), pattern = "\\-", replacement = "")
#Preparing the function
covariatesGSE <- colnames(GSEsurvgenes[,6:2598])
covariatesTCGA <- colnames(TCGAsurvgenes[,6:2659])
univ_formulas1 <- sapply(covariatesGSE, function(x) as.formula(paste('Surv(OS,Death)~', x)))
univ_formulas2 <- sapply(covariatesTCGA, function(x) as.formula(paste('Surv(OS,Death)~', x)))
univ_models1 <- lapply(univ_formulas1, function(x){coxph(x, data = GSEsurvgenes)})
univ_models2 <- lapply(univ_formulas2, function(x){coxph(x, data = TCGAsurvgenes)})
# Applying the function and extracting the results
univ_GSEresults <- lapply(univ_models1,
                       function(x){ 
                         x <- summary(x)
                         p.value<-signif(x$wald["pvalue"], digits=2)
                         wald.test<-signif(x$wald["test"], digits=2)
                         beta<-signif(x$coef[1], digits=2);#coeficient beta
                         HR <-signif(x$coef[2], digits=2);#exp(beta)
                         HR.confint.lower <- signif(x$conf.int[,"lower .95"], 2)
                         HR.confint.upper <- signif(x$conf.int[,"upper .95"],2)
                         HR <- paste0(HR, " (", 
                                      HR.confint.lower, "-", HR.confint.upper, ")")
                         res<-c(beta, HR, wald.test, p.value)
                         names(res)<-c("beta", "HR (95% CI for HR)", "wald.test", 
                                       "p.value")
                         return(res)
                         #return(exp(cbind(coef(x),confint(x))))
                       })
resGSE <- t(as.data.frame(univ_GSEresults, check.names = FALSE))
resGSE <- as.data.frame(resGSE)

univ_TCGAresults <- lapply(univ_models2,
                          function(x){ 
                            x <- summary(x)
                            p.value<-signif(x$wald["pvalue"], digits=2)
                            wald.test<-signif(x$wald["test"], digits=2)
                            beta<-signif(x$coef[1], digits=2);#coeficient beta
                            HR <-signif(x$coef[2], digits=2);#exp(beta)
                            HR.confint.lower <- signif(x$conf.int[,"lower .95"], 2)
                            HR.confint.upper <- signif(x$conf.int[,"upper .95"],2)
                            HR <- paste0(HR, " (", 
                                         HR.confint.lower, "-", HR.confint.upper, ")")
                            res<-c(beta, HR, wald.test, p.value)
                            names(res)<-c("beta", "HR (95% CI for HR)", "wald.test", 
                                          "p.value")
                            return(res)
                            #return(exp(cbind(coef(x),confint(x))))
                          })
resTCGA <- t(as.data.frame(univ_TCGAresults, check.names = FALSE))
resTCGA <- as.data.frame(resTCGA)

#Write the output files
write.csv(resGSE, "~/Desktop/Datasets/TableS2.csv")
write.csv(resTCGA, "~/Desktop/Datasets/TableS3.csv")
#Draw a scatter plot depicting significant and insignificant genes
resTCGA$color <- "Insignificant"
resGSE$color <- "Insignificant"
resGSE <- separate(resGSE, `HR (95% CI for HR)`, into = c("HR", "CI"), sep = " (?=[^ ]+$)")
resTCGA <- separate(resTCGA, `HR (95% CI for HR)`, into = c("HR", "CI"), sep = " (?=[^ ]+$)")
resGSE[,c(1,2,4,5)] <- sapply(resGSE[,c(1,2,4,5)], as.numeric)
resTCGA[,c(1,2,4,5)] <- sapply(resTCGA[,c(1,2,4,5)], as.numeric)
resTCGA$color[resTCGA$HR > 1 & resTCGA$p.value < 0.05] <- "Significant"
resGSE$color[resGSE$HR > 1 & resGSE$p.value < 0.05] <- "Significant"
#GSE Scatter Plot
ggplot(data=resGSE, aes(x=HR, y=-log10(p.value), col = color, label= rownames(resGSE))) +
geom_point() +
theme_minimal() +
geom_text_repel() +
scale_color_manual(values=c("black", "blue"))+xlim(0, 5) +  geom_vline(xintercept= 1, col="red") + geom_hline(yintercept = 1.3, col = "red")
Warning: Removed 80 rows containing missing values (geom_point).
Warning: Removed 80 rows containing missing values (geom_text_repel).
Warning: ggrepel: 2482 unlabeled data points (too many overlaps). Consider increasing max.overlaps

#TCGA Scatter Plot
ggplot(data=resTCGA, aes(x=HR, y=-log10(p.value), col = color, label= rownames(resTCGA))) +
geom_point() +
theme_minimal() +
geom_text_repel() +
scale_color_manual(values=c("black", "blue"))+xlim(0, 3) +  geom_vline(xintercept= 1, col="red") + geom_hline(yintercept = 1.3, col = "red")
Warning: Removed 5 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_text_repel).
Warning: ggrepel: 2641 unlabeled data points (too many overlaps). Consider increasing max.overlaps

NA

Now that we have identified the clinically relevant genes in each cohort, we have enlisted the mutual significant entities in Table S4. We will now use this gene list as the CCA Immune Signature to stratify samples. We will first load the gene expression datasets: “GSEds.csv” and “data_RNA_Seq_v2_expression_median.txt”

#Load Libraries
library(dplyr)
library(pheatmap)
library(tidyr)
library(tibble)

#Load Data
Microarrayds <- read_csv("~/Desktop/Datasets/Microarrayds.csv")
GSEds <- read_csv("~/Desktop/Datasets/GSEds.csv")
GSEds <- GSEds[,-1]
TCGAds <- read_tsv("~/Desktop/Datasets/data_RNA_Seq_v2_expression_median.txt")
TCGAds <- TCGAds[30:20531,-2]
TCGAds <- TCGAds %>% group_by(Hugo_Symbol) %>% summarize_all(mean)

# 26 mortality-associated immune-related genes
genelist <- c("GGH", "ANXA1", "GLIPR1", "PDK1", "TPM2", "SNPH", "DMBT1", "SIGLEC1", "KRT6B", "PFKFB4", "CENPW", "RACGAP1", "CDCA4", "BCAT1", "QPCT", "VTA1", "TTK", "PLOD2", "MRC1", "GCNT1", "SERPINB7", "TP63", "AURKA", "CEACAM3", "NRIP3", "DEPDC1")

#Filter datasets for CCA Immune Signature
GSEimmune <- filter(GSEds, GSEds$Genes %in% genelist)
GSEimmune <- column_to_rownames(GSEimmune, "Genes")
#GSEimmune <- GSEimmune[,-1]
TCGAimmune <- filter(TCGAds, TCGAds$Hugo_Symbol %in% genelist)
TCGAimmune <- column_to_rownames(TCGAimmune, "Hugo_Symbol")
Microarrayimmune <- filter(Microarrayds, Microarrayds$GeneID %in% genelist)
Microarrayimmune <- column_to_rownames(Microarrayimmune, "GeneID")

#Hierarchical Clustering
x= pheatmap(GSEimmune, scale = "row", border_color = NA, 
         breaks = seq(-1.5, 1.5, length.out = 101), 
         clustering_method = "complete", 
         clustering_distance_cols = "canberra", 
         cutree_cols = 2)
y = pheatmap(TCGAimmune, scale = "row", border_color = NA, 
         breaks = seq(-1.5, 1.5, length.out = 101), 
         clustering_method = "complete", 
         clustering_distance_cols = "canberra", 
         cutree_cols = 4)
z = pheatmap(Microarrayimmune, scale = "row", clustering_method = "complete", clustering_distance_cols = "canberra", breaks = seq(-1, 1, length.out = 101), show_colnames = F, cutree_cols = 4)

#Identify Cluster IDs
indGSE <- cutree(x$tree_col, k = 2)
indTCGA <- cutree(y$tree_col, k = 4)
indMA <- cutree(z$tree_col, k = 4)
indGSE <- as.data.frame(indGSE)
indTCGA <- as.data.frame(indTCGA)
indMA <- as.data.frame(indMA)
indGSE$indGSE <- sapply(indGSE$indGSE, as.factor)
indTCGA$indTCGA <- sapply(indTCGA$indTCGA, as.factor)
indMA$indMA <- sapply(indMA$indMA, as.factor)
indMA$anno <- "High"
indMA$anno[indMA$indMA == 1] <- "Intermediate"
indMA$anno[indMA$indMA == 4] <- "Low"
write.csv(indGSE, "~/Desktop/Datasets/GSEhclustidentifiers.csv")
write.csv(indTCGA, "~/Desktop/Datasets/TCGAhclustidentifiers.csv")
write.csv(indMA, "~/Desktop/Datasets/MAhclustidentifiers.csv")
#Draw Heatmap for GSEimmune
pheatmap(GSEimmune, scale = "row", border_color = NA, 
             breaks = seq(-1.5, 1.5, length.out = 101), 
             clustering_method = "complete", 
             clustering_distance_cols = "canberra", 
             cutree_cols = 2, annotation = indGSE, main ="GSE107943")

#Draw Heatmap for TCGAimmune
pheatmap(TCGAimmune, scale = "row", border_color = NA, 
             breaks = seq(-1.5, 1.5, length.out = 101), 
             clustering_method = "complete", 
             clustering_distance_cols = "canberra", 
             clustering_distance_rows = "manhattan",
             cutree_cols = 4, annotation = indTCGA, main = "TCGA-CHOL")

#Draw Heatmap for Microarrayimmune
pheatmap(Microarrayimmune, scale = "row", 
         clustering_method = "complete", 
         clustering_distance_cols = "canberra", 
         breaks = seq(-1, 1, length.out = 101), 
         show_colnames = F, cutree_cols = 4, annotation = indMA, main = "Microarray Datasets")

Then, we applied Kaplan-Meier curve to elucidate the prognostic value of 26 immune gene signature classification in the pooled cohort of CCA patients (GSE107943 and TCGA-CHOL)

#Annotate Samples with Cluster Group name
indGSE$samples <- rownames(indGSE)
indGSE$anno <- "High"
indGSE$anno[indGSE$indGSE == 1] <- "Low"

indTCGA$samples <- rownames(indTCGA)
indTCGA$anno <- "High"
indTCGA$anno[indTCGA$indTCGA == 2] <- "Low"
annotation <- rbind(indGSE[,2:3], indTCGA[,2:3])
#Plot Kaplain-Meier Curve using the Cluster annotation as a factor
GSETCGA <- rbind(GSEsurvgenes[,1:5], TCGAsurvgenes[,1:5])
GSETCGA <- merge(GSETCGA, annotation, by.x = "Sample", by.y = "samples", all.y = TRUE)
km_fit <- survfit(Surv(OS, Death) ~ anno, data=GSETCGA)
ggsurv <- ggsurvplot(km_fit, data = GSETCGA,  risk.table = TRUE, cumevents = TRUE, pval = TRUE, pval.method = TRUE, risk.table.col = "strata", 
                    legend.labs=c("High", "Low"), palette = c("tomato", "cornflowerblue"))
ggsurv

We have identified low expressing and high expressing samples in each cohort. We would now like to assess the transcriptomic differences between these two groups, hence we will conduct Differential Gene Expression Analysis.

#Load Libraries and Pre-process Data
library(DESeq2)
library(EnhancedVolcano)
library(pheatmap)
library(dplyr)
library(tibble)

#Data Preprocessing
GSEds <- column_to_rownames(GSEds, "Genes")
counts.m <- as.matrix(GSEds)
LHgroup <- indGSE
dds <- DESeqDataSetFromMatrix(countData = round(counts.m),
                              colData = LHgroup,
                             design = ~ anno) 
keep <- rowSums(counts(dds)) >= 10
summary(keep)
dds <- dds[keep,]
#Differential Gene Expression Analysis
dds <- DESeq(dds)
res <- results(dds)
res
resOrdered <- res[order(res$pvalue),]
summary(res)
sum(res$padj < 0.1, na.rm=TRUE)
res1 <- as.data.frame(res)
res1 <- filter(res1, res1$padj < 0.05, na.rm=TRUE)
write.csv(as.data.frame(resOrdered), 
          file="~/Desktop/Datasets/GSEimmune2DESeq2_HighLow.csv")
resSig <- subset(resOrdered, padj < 0.05)
resSig
write.csv(as.data.frame(resSig), file = "~/Desktop/Datasets/TableS5.csv")
#Plot PCA - GSE107943
rld <- rlog(dds, blind=TRUE)
rlog() may take a few minutes with 30 or more samples,
vst() is a much faster transformation
p <- plotPCA(rld, intgroup="anno")
p + scale_colour_manual(values = c("Low" = "cornflowerblue", "High" = "tomato"))

#Plot Volcano of Differentially Expressed Genes - GSE107943
EnhancedVolcano(res,
                lab = rownames(res),
                x = "log2FoldChange",
                y = "padj",
                ylim = c(0,4),
                title = "GSE107943",
                FCcutoff = log2(2),
                pCutoff = 0.05,
                legendPosition = "none",
                xlim = c(-5,5))

#Plot Heatmap of Differentially Expressed Genes - GSE107943
hmapx = subset(counts.m, rownames(counts.m) %in% rownames(resSig))
anno = LHgroup[,2:3]
rownames(anno) = NULL
anno = column_to_rownames(anno, "samples")
hmapx = hmapx[,-1]
pheatmap(hmapx, breaks = seq(-1.5, 1.5, length.out = 101), scale = "row",
         clustering_method = "complete", fontsize_row = 7, annotation_col = anno, annotation_colors = list(anno = c(Low = "cornflowerblue", High = "tomato")),
         main = "GSE107943", border_color = NA, clustering_distance_cols = "canberra", annotation_names_col = F)

Now we will repeat this analysis for the TCGA-CHOL cohort

library(dplyr)
library(tibble)
library(tidyr)
#Repeat analysis in TCGA-CHOL cohort
#Data Pre-Processing
TCGAds = column_to_rownames(TCGAds, "Hugo_Symbol")
counts.m = as.matrix(TCGAds)
LHgroup = indTCGA
dds <- DESeqDataSetFromMatrix(countData = round(counts.m),
                              colData = LHgroup,
                              design = ~ anno)
keep <- rowSums(counts(dds)) >= 10
summary(keep)
dds <- dds[keep,]
#Differential Gene Expression Analysis
dds <- DESeq(dds)
res <- results(dds)
res
resOrdered <- res[order(res$pvalue),]
summary(res)
sum(res$padj < 0.1, na.rm=TRUE)
res1 = as.data.frame(res)
res1 = filter(res1, res1$padj < 0.05, na.rm=TRUE)
write.csv(as.data.frame(resOrdered), 
          file="~/Desktop/Datasets/TCGAimmune2DESeq2_HighLow.csv")
resSig <- subset(resOrdered, padj < 0.05)
resSig
write.csv(as.data.frame(resSig), file = "~/Desktop/Datasets/TableS6.csv")
#Plot PCA - TCGA-CHOL
rld <- rlog(dds, blind=TRUE)
rlog() may take a few minutes with 30 or more samples,
vst() is a much faster transformation
p = plotPCA(rld, intgroup="anno")
p + scale_colour_manual(values = c("Low" = "cornflowerblue", "High" = "tomato"))

#Plot Volcano of Differentially Expressed Genes
EnhancedVolcano(res,
                lab = rownames(res),
                x = "log2FoldChange",
                y = "padj",
                ylim = c(0,4),
                title = "TCGA-CHOL",
                FCcutoff = log2(2),
                pCutoff = 0.05,
                legendPosition = "none",
                xlim = c(-5,5))

#Plot Heatmap of Differentially expressed genes
hmapx = subset(counts.m, rownames(counts.m) %in% rownames(resSig))
anno = LHgroup[,2:3]
rownames(anno) = NULL
anno = column_to_rownames(anno, "samples")
pheatmap(hmapx, breaks = seq(-1.5, 1.5, length.out = 101), show_colnames = T, scale = "row",
         clustering_method = "complete", fontsize_row = 7, annotation_col = anno, annotation_colors = list(anno = c(Low = "cornflowerblue", High = "tomato")), clustering_distance_cols = "correlation",
         main = "TCGA-CHOL", border_color = NA, annotation_names_col = F) 

# Microarray DGE Validation
df <- as.data.frame(Microarrayds)
df = column_to_rownames(df, "GeneID")
counts <- as.matrix(df)
View(counts)

sample_id <- read_csv("~/Desktop/Datasets/MAhclustidentifiers.csv")
New names:
* `` -> ...1
Rows: 704 Columns: 3
── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): ...1, anno
dbl (1): indMA

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
View(sample_id)
sample_id = filter(sample_id, sample_id$anno == "Low"| sample_id$anno == "High")
colnames(sample_id)[1] = "samples"
sample_id = column_to_rownames(sample_id, "samples")
counts = t(counts)
counts = subset(counts, rownames(counts) %in% rownames(sample_id))
counts = t(counts)
genelist <- rownames(counts)
genes = genelist
group <- sample_id$anno
counts.m<-as.matrix(counts)
is.numeric(counts.m)
[1] TRUE
#Remove genes that are 0 
n <- which(is.na(counts.m))
counts.m[n]<-0

#Transformation from raw  scale -->log2
counts.L = log2(counts.m + 1)
x <- DGEList(counts= counts.L, genes = genes, group = group, samples = sample_id$X1)
group <- as.factor(group)
x$samples$group <- group
x$genes <- genes
x <- calcNormFactors(x, method = "TMM")

#plotMDS for unsupervised clustering
par(mfrow=c(1,2))
group <- as.factor(group)
col.group <- group
levels(col.group) <-  c("tomato", "cornflowerblue")
col.group <- as.character(col.group)
plotMDS(x, labels=group, col=col.group)

#title(main="Sample groups")

The differentially expressed gene list has been used as an input in iLINCS and EnrichR to obtain pathway enrichments and positively correlated connected perturbagens. These are presented in Table S6, S8, S10, S11 and S12. They have been visualized using the following script.

#Pathway Enrichment Plot
library(ggplot2)
Enrichment_GSE <- read_csv("~/Desktop/Datasets/Enrichment_GSE.csv")
Rows: 692 Columns: 10
── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Term, Overlap, Database
dbl (7): P-value, Adjusted P-value, Old P-value, Old Adjusted P-value, Odds Ratio, C...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Enrichment_TCGA <- read_csv("~/Desktop/Datasets/Enrichment_TCGA.csv")
Rows: 488 Columns: 10
── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Term, Overlap, Database
dbl (7): P-value, Adjusted P-value, Old P-value, Old Adjusted P-value, Odds Ratio, C...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Enrichment_MA <- read_csv("~/Desktop/Datasets/Enrichment_MA.csv")
Rows: 453 Columns: 10
── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Term, Overlap, Database
dbl (7): P-value, Adjusted P-value, Old P-value, Old Adjusted P-value, Odds Ratio, C...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
ds <- data.frame(cbind(Enrichment_GSE$`Term`, Enrichment_GSE$`DEGs`, Enrichment_GSE$`Combined Score`, Enrichment_GSE$`Adjusted P-value`, Enrichment_GSE$Database))
colnames(ds) <- c("Pathways", "DEGs", "Combined Score", "Adjusted P.val", "Database")
Enrichment_GSE <- as.data.frame(Enrichment_GSE)
ds[,c(2:4)] <- sapply(ds[,c(2:4)], as.numeric)
pathway_GSE = ggplot(ds ,aes(x= `Combined Score`, 
                  y= Pathways, size = DEGs))+geom_point(aes(col= `Adjusted P.val`), alpha=0.8)+scale_colour_gradient(low = "red", high = "blue")+scale_y_discrete(labels = function(x) str_wrap(x, width = 10))+facet_grid(~Database)+xlim(0, 500)
pathway_GSE 
Warning: Removed 2 rows containing missing values (geom_point).

ds <- data.frame(cbind(Enrichment_TCGA$`Term`, Enrichment_TCGA$`DEGs`, Enrichment_TCGA$`Combined Score`, Enrichment_TCGA$`Adjusted P-value`, Enrichment_TCGA$Database))
colnames(ds) <- c("Pathways", "DEGs", "Combined Score", "Adjusted P.val", "Database")
Enrichment_TCGA <- as.data.frame(Enrichment_TCGA)
ds[,c(2:4)] <- sapply(ds[,c(2:4)], as.numeric)

pathway_TCGA <- ggplot(ds ,aes(x= `Combined Score`, 
                   y= Pathways, size = DEGs))+geom_point(aes(col= `Adjusted P.val`), alpha=0.8)+scale_colour_gradient(low = "red", high = "blue")+scale_y_discrete(labels = function(x) str_wrap(x, width = 10))+facet_grid(~Database)+xlim(0, 500)
pathway_TCGA
Warning: Removed 1 rows containing missing values (geom_point).

ds = data.frame(cbind(Enrichment_MA$`Term`, Enrichment_MA$`DEGs`, Enrichment_MA$`Combined Score`, Enrichment_MA$`Adjusted P-value`, Enrichment_MA$Database))
colnames(ds) <- c("Pathways", "DEGs", "Combined Score", "Adjusted P.val", "Database")
Enrichment_MA <- as.data.frame(Enrichment_MA)
ds[,c(2:4)] <- sapply(ds[,c(2:4)], as.numeric)
pathway_MA <- ggplot(ds ,aes(x= `Combined Score`, 
                  y= Pathways, size = DEGs))+geom_point(aes(col= `Adjusted P.val`), alpha=0.8)+scale_colour_gradient(low = "red", high = "blue")+scale_y_discrete(labels = function(x) str_wrap(x, width = 10))+facet_grid(~Database)+xlim(0, 500)
pathway_MA

#Connected Perturbagens Plot
GSEdrugs <- read_tsv("~/Desktop/Datasets/GSEdrugs.txt")
Rows: 312 Columns: 7
── Column specification ────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (4): PerturbagenId, Perturbagen, GeneTargets, Correlation
dbl (3): NoOfSignatures, pValue, zScore

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
TCGAdrugs <- read_tsv("~/Desktop/Datasets/TCGAdrugs.txt")
Rows: 1604 Columns: 7
── Column specification ────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (4): PerturbagenId, Perturbagen, GeneTargets, Correlation
dbl (3): NoOfSignatures, pValue, zScore

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
MAdrugs <- read_tsv("~/Desktop/Datasets/MAdrugs.txt")
Rows: 1780 Columns: 7
── Column specification ────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (4): PerturbagenId, Perturbagen, GeneTargets, Correlation
dbl (3): NoOfSignatures, pValue, zScore

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
GSEdrugs %>% arrange(desc(zScore)) %>% head(25) %>%ggplot(aes(reorder(Perturbagen, zScore), zScore))+ 
  geom_col(aes(fill = pValue)) + 
  scale_fill_gradient(low = "darkgoldenrod1", 
                      high = "darkgoldenrod4") +
  scale_x_discrete(labels = function(x) str_wrap(x, width = 10))+
  coord_flip() + 
  labs(x = "Connected Perturbagens", y = "Z score")

TCGAdrugs %>% arrange(desc(zScore)) %>% head(25) %>%ggplot(aes(reorder(Perturbagen, zScore), zScore))+ 
  geom_col(aes(fill = pValue)) + 
  scale_fill_gradient(low = "darkolivegreen2", 
                      high = "darkolivegreen4") + 
  coord_flip() + 
  labs(x = "Connected Perturbagens", y = "Z score")

MAdrugs %>% arrange(desc(zScore)) %>% head(25) %>%ggplot(aes(reorder(Perturbagen, zScore), zScore))+
  geom_col(aes(fill = pValue)) + 
  scale_fill_gradient(low = "deepskyblue", 
                      high = "deepskyblue4") + 
  coord_flip() + 
  labs(x = "Connected Perturbagens", y = "Z score")

LS0tCnRpdGxlOiAiUiBTY3JpcHQgZm9yIENDQSBJbW11bmUgU2lnbmF0dXJlIEFuYWx5c2lzIgphdXRob3I6ICJTaW1yYW4gVmVua2F0cmFtYW4gYW5kIFNvbWNoYWkgQ2h1dGlwb25ndGFuYXRlIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKRmlyc3QsIGluc3RhbGwgdGhlIHBhY2thZ2UgZGVwZW5kZW5jaWVzIHJlcXVpcmVkIGZvciB0aGlzIGFuYWx5c2lzLiBSZXF1aXJlZCBwYWNrYWdlIGxpYnJhcmllcyB3aWxsIGJlIGxvYWRlZCBpbiB0aGVpciByZXNwZWN0aXZlIHN0ZXBzLgoKYGBge3J9CiNJbnN0YWxsIFBhY2thZ2UgRGVwZW5kZW5jaWVzIAppbnN0YWxsLnBhY2thZ2VzKGMoInJlYWRyIiwgInN1cnZpdmFsIiwgInJhbmdlciIsICJkcGx5ciIsICJnZ3Bsb3QyIiwgImdnZm9ydGlmeSIsICJzdXJ2bWluZXIiLCJnZ3JlcGVsIiwgInRpZHlyIiwgInRpYmJsZSIsICJwaGVhdG1hcCIsICJzdHJpbmdyIikpCkJpb2NNYW5hZ2VyOjppbnN0YWxsKGMoImVkZ2VSIiwgIkVuaGFuY2VkVm9sY2FubyIsICJERVNlcTIiLCAibGltbWEiKSkKYGBgCgpgYGB7cn0KI0xvYWQgTGlicmFyaWVzCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoc3Vydml2YWwpCmxpYnJhcnkocmFuZ2VyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dmb3J0aWZ5KQpsaWJyYXJ5KHN1cnZtaW5lcikKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHRpYmJsZSkKbGlicmFyeShsaW1tYSkKbGlicmFyeShlZGdlUikKbGlicmFyeShzdHJpbmdyKQpgYGAKCkRvd25sb2FkIHRoZSBJbnB1dCBkYXRhc2V0cyBvbnRvIHlvdXIgZGVza3RvcCBkaXJlY3RvcnkgdG8gbG9hZCBpbnRvIFIgKGF2YWlsYWJsZSBpbiBTdXBwbGVtZW50YXJ5IEluZm9ybWF0aW9uKS4gCgpGb3IgdGhlIGZpcnN0IGFuYWx5c2lzIChVbml2YXJpYXRlIENveC1Qcm9wb3J0aW9uYWwgSGF6YXJkcyBNb2RlbCBhbmQgS2FwbGFpbi1NZWllciBhbmFseXNpcyBvZiBnZW5lcykgd2Ugd2lsbCB1c2UgIkdTRXN1cnZnZW5lcy5jc3YiIGFuZCAiVENHQXN1cnZnZW5lcy5jc3YiLiBUaGVzZSBhcmUgc3Vydml2YWwgZGF0YSBmb3IgT3ZlcmFsbCBTdXJ2aXZhbCBhbmQgUHJvZ3Jlc3Npb24gRnJlZSBTdXJ2aXZhbCBmcm9tIHRoZSByZXNwZWN0aXZlIGNvaG9ydHM6IEdTRTEwNzk0MyBhbmQgVENHQS1DSE9MLCBhcHBlbmRlZCB3aXRoIGdlbmUgZXhwcmVzc2lvbiBpbmZvcm1hdGlvbiBvZiB0aGUgMzAxNyBnZW5lcyBmcm9tIHRoZSBJbW11bmUgR2VuZSBTaWduYXR1cmUgKFRhYmxlIFMxKQpgYGB7cn0KI0RhdGEgTG9hZGluZwpzZXR3ZCgifi9EZXNrdG9wL0RhdGFzZXRzLyIpCkdTRXN1cnZnZW5lcyA8LSByZWFkX2Nzdigifi9EZXNrdG9wL0RhdGFzZXRzL0dTRXN1cnZnZW5lcy5jc3YiKQpUQ0dBc3VydmdlbmVzIDwtIHJlYWRfY3N2KCJ+L0Rlc2t0b3AvRGF0YXNldHMvVENHQXN1cnZnZW5lcy5jc3YiKQpjb2xuYW1lcyhHU0VzdXJ2Z2VuZXMpIDwtIGdzdWIoeCA9IGNvbG5hbWVzKEdTRXN1cnZnZW5lcyksIHBhdHRlcm4gPSAiXFwtIiwgcmVwbGFjZW1lbnQgPSAiIikKY29sbmFtZXMoVENHQXN1cnZnZW5lcykgPC0gZ3N1Yih4ID0gY29sbmFtZXMoVENHQXN1cnZnZW5lcyksIHBhdHRlcm4gPSAiXFwtIiwgcmVwbGFjZW1lbnQgPSAiIikKYGBgCgpgYGB7cn0KI1ByZXBhcmluZyB0aGUgZnVuY3Rpb24KY292YXJpYXRlc0dTRSA8LSBjb2xuYW1lcyhHU0VzdXJ2Z2VuZXNbLDY6MjU5OF0pCmNvdmFyaWF0ZXNUQ0dBIDwtIGNvbG5hbWVzKFRDR0FzdXJ2Z2VuZXNbLDY6MjY1OV0pCnVuaXZfZm9ybXVsYXMxIDwtIHNhcHBseShjb3ZhcmlhdGVzR1NFLCBmdW5jdGlvbih4KSBhcy5mb3JtdWxhKHBhc3RlKCdTdXJ2KE9TLERlYXRoKX4nLCB4KSkpCnVuaXZfZm9ybXVsYXMyIDwtIHNhcHBseShjb3ZhcmlhdGVzVENHQSwgZnVuY3Rpb24oeCkgYXMuZm9ybXVsYShwYXN0ZSgnU3VydihPUyxEZWF0aCl+JywgeCkpKQp1bml2X21vZGVsczEgPC0gbGFwcGx5KHVuaXZfZm9ybXVsYXMxLCBmdW5jdGlvbih4KXtjb3hwaCh4LCBkYXRhID0gR1NFc3VydmdlbmVzKX0pCnVuaXZfbW9kZWxzMiA8LSBsYXBwbHkodW5pdl9mb3JtdWxhczIsIGZ1bmN0aW9uKHgpe2NveHBoKHgsIGRhdGEgPSBUQ0dBc3VydmdlbmVzKX0pCiMgQXBwbHlpbmcgdGhlIGZ1bmN0aW9uIGFuZCBleHRyYWN0aW5nIHRoZSByZXN1bHRzCnVuaXZfR1NFcmVzdWx0cyA8LSBsYXBwbHkodW5pdl9tb2RlbHMxLAogICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpeyAKICAgICAgICAgICAgICAgICAgICAgICAgIHggPC0gc3VtbWFyeSh4KQogICAgICAgICAgICAgICAgICAgICAgICAgcC52YWx1ZTwtc2lnbmlmKHgkd2FsZFsicHZhbHVlIl0sIGRpZ2l0cz0yKQogICAgICAgICAgICAgICAgICAgICAgICAgd2FsZC50ZXN0PC1zaWduaWYoeCR3YWxkWyJ0ZXN0Il0sIGRpZ2l0cz0yKQogICAgICAgICAgICAgICAgICAgICAgICAgYmV0YTwtc2lnbmlmKHgkY29lZlsxXSwgZGlnaXRzPTIpOyNjb2VmaWNpZW50IGJldGEKICAgICAgICAgICAgICAgICAgICAgICAgIEhSIDwtc2lnbmlmKHgkY29lZlsyXSwgZGlnaXRzPTIpOyNleHAoYmV0YSkKICAgICAgICAgICAgICAgICAgICAgICAgIEhSLmNvbmZpbnQubG93ZXIgPC0gc2lnbmlmKHgkY29uZi5pbnRbLCJsb3dlciAuOTUiXSwgMikKICAgICAgICAgICAgICAgICAgICAgICAgIEhSLmNvbmZpbnQudXBwZXIgPC0gc2lnbmlmKHgkY29uZi5pbnRbLCJ1cHBlciAuOTUiXSwyKQogICAgICAgICAgICAgICAgICAgICAgICAgSFIgPC0gcGFzdGUwKEhSLCAiICgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBIUi5jb25maW50Lmxvd2VyLCAiLSIsIEhSLmNvbmZpbnQudXBwZXIsICIpIikKICAgICAgICAgICAgICAgICAgICAgICAgIHJlczwtYyhiZXRhLCBIUiwgd2FsZC50ZXN0LCBwLnZhbHVlKQogICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXMocmVzKTwtYygiYmV0YSIsICJIUiAoOTUlIENJIGZvciBIUikiLCAid2FsZC50ZXN0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwLnZhbHVlIikKICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybihyZXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAjcmV0dXJuKGV4cChjYmluZChjb2VmKHgpLGNvbmZpbnQoeCkpKSkKICAgICAgICAgICAgICAgICAgICAgICB9KQpyZXNHU0UgPC0gdChhcy5kYXRhLmZyYW1lKHVuaXZfR1NFcmVzdWx0cywgY2hlY2submFtZXMgPSBGQUxTRSkpCnJlc0dTRSA8LSBhcy5kYXRhLmZyYW1lKHJlc0dTRSkKCnVuaXZfVENHQXJlc3VsdHMgPC0gbGFwcGx5KHVuaXZfbW9kZWxzMiwKICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KXsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4IDwtIHN1bW1hcnkoeCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAudmFsdWU8LXNpZ25pZih4JHdhbGRbInB2YWx1ZSJdLCBkaWdpdHM9MikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhbGQudGVzdDwtc2lnbmlmKHgkd2FsZFsidGVzdCJdLCBkaWdpdHM9MikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJldGE8LXNpZ25pZih4JGNvZWZbMV0sIGRpZ2l0cz0yKTsjY29lZmljaWVudCBiZXRhCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBIUiA8LXNpZ25pZih4JGNvZWZbMl0sIGRpZ2l0cz0yKTsjZXhwKGJldGEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBIUi5jb25maW50Lmxvd2VyIDwtIHNpZ25pZih4JGNvbmYuaW50WywibG93ZXIgLjk1Il0sIDIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBIUi5jb25maW50LnVwcGVyIDwtIHNpZ25pZih4JGNvbmYuaW50WywidXBwZXIgLjk1Il0sMikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhSIDwtIHBhc3RlMChIUiwgIiAoIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSFIuY29uZmludC5sb3dlciwgIi0iLCBIUi5jb25maW50LnVwcGVyLCAiKSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXM8LWMoYmV0YSwgSFIsIHdhbGQudGVzdCwgcC52YWx1ZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzKHJlcyk8LWMoImJldGEiLCAiSFIgKDk1JSBDSSBmb3IgSFIpIiwgIndhbGQudGVzdCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicC52YWx1ZSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ocmVzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgI3JldHVybihleHAoY2JpbmQoY29lZih4KSxjb25maW50KHgpKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgfSkKcmVzVENHQSA8LSB0KGFzLmRhdGEuZnJhbWUodW5pdl9UQ0dBcmVzdWx0cywgY2hlY2submFtZXMgPSBGQUxTRSkpCnJlc1RDR0EgPC0gYXMuZGF0YS5mcmFtZShyZXNUQ0dBKQoKI1dyaXRlIHRoZSBvdXRwdXQgZmlsZXMKd3JpdGUuY3N2KHJlc0dTRSwgIn4vRGVza3RvcC9EYXRhc2V0cy9UYWJsZVMyLmNzdiIpCndyaXRlLmNzdihyZXNUQ0dBLCAifi9EZXNrdG9wL0RhdGFzZXRzL1RhYmxlUzMuY3N2IikKYGBgCgpgYGB7cn0KI0RyYXcgYSBzY2F0dGVyIHBsb3QgZGVwaWN0aW5nIHNpZ25pZmljYW50IGFuZCBpbnNpZ25pZmljYW50IGdlbmVzCnJlc1RDR0EkY29sb3IgPC0gIkluc2lnbmlmaWNhbnQiCnJlc0dTRSRjb2xvciA8LSAiSW5zaWduaWZpY2FudCIKcmVzR1NFIDwtIHNlcGFyYXRlKHJlc0dTRSwgYEhSICg5NSUgQ0kgZm9yIEhSKWAsIGludG8gPSBjKCJIUiIsICJDSSIpLCBzZXAgPSAiICg/PVteIF0rJCkiKQpyZXNUQ0dBIDwtIHNlcGFyYXRlKHJlc1RDR0EsIGBIUiAoOTUlIENJIGZvciBIUilgLCBpbnRvID0gYygiSFIiLCAiQ0kiKSwgc2VwID0gIiAoPz1bXiBdKyQpIikKcmVzR1NFWyxjKDEsMiw0LDUpXSA8LSBzYXBwbHkocmVzR1NFWyxjKDEsMiw0LDUpXSwgYXMubnVtZXJpYykKcmVzVENHQVssYygxLDIsNCw1KV0gPC0gc2FwcGx5KHJlc1RDR0FbLGMoMSwyLDQsNSldLCBhcy5udW1lcmljKQpyZXNUQ0dBJGNvbG9yW3Jlc1RDR0EkSFIgPiAxICYgcmVzVENHQSRwLnZhbHVlIDwgMC4wNV0gPC0gIlNpZ25pZmljYW50IgpyZXNHU0UkY29sb3JbcmVzR1NFJEhSID4gMSAmIHJlc0dTRSRwLnZhbHVlIDwgMC4wNV0gPC0gIlNpZ25pZmljYW50IgpgYGAKCmBgYHtyfQojR1NFIFNjYXR0ZXIgUGxvdApnZ3Bsb3QoZGF0YT1yZXNHU0UsIGFlcyh4PUhSLCB5PS1sb2cxMChwLnZhbHVlKSwgY29sID0gY29sb3IsIGxhYmVsPSByb3duYW1lcyhyZXNHU0UpKSkgKwpnZW9tX3BvaW50KCkgKwp0aGVtZV9taW5pbWFsKCkgKwpnZW9tX3RleHRfcmVwZWwoKSArCnNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiYmxhY2siLCAiYmx1ZSIpKSt4bGltKDAsIDUpICsgIGdlb21fdmxpbmUoeGludGVyY2VwdD0gMSwgY29sPSJyZWQiKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEuMywgY29sID0gInJlZCIpCmBgYAoKYGBge3J9CiNUQ0dBIFNjYXR0ZXIgUGxvdApnZ3Bsb3QoZGF0YT1yZXNUQ0dBLCBhZXMoeD1IUiwgeT0tbG9nMTAocC52YWx1ZSksIGNvbCA9IGNvbG9yLCBsYWJlbD0gcm93bmFtZXMocmVzVENHQSkpKSArCmdlb21fcG9pbnQoKSArCnRoZW1lX21pbmltYWwoKSArCmdlb21fdGV4dF9yZXBlbCgpICsKc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJibGFjayIsICJibHVlIikpK3hsaW0oMCwgMykgKyAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSAxLCBjb2w9InJlZCIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMS4zLCBjb2wgPSAicmVkIikKICAKYGBgCgpOb3cgdGhhdCB3ZSBoYXZlIGlkZW50aWZpZWQgdGhlIGNsaW5pY2FsbHkgcmVsZXZhbnQgZ2VuZXMgaW4gZWFjaCBjb2hvcnQsIHdlIGhhdmUgZW5saXN0ZWQgdGhlIG11dHVhbCBzaWduaWZpY2FudCBlbnRpdGllcyBpbiBUYWJsZSBTNC4gV2Ugd2lsbCBub3cgdXNlIHRoaXMgZ2VuZSBsaXN0IGFzIHRoZSBDQ0EgSW1tdW5lIFNpZ25hdHVyZSB0byBzdHJhdGlmeSBzYW1wbGVzLiBXZSB3aWxsIGZpcnN0IGxvYWQgdGhlIGdlbmUgZXhwcmVzc2lvbiBkYXRhc2V0czogIkdTRWRzLmNzdiIgYW5kICJkYXRhX1JOQV9TZXFfdjJfZXhwcmVzc2lvbl9tZWRpYW4udHh0IgpgYGB7cn0KI0xvYWQgTGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkodGliYmxlKQoKI0xvYWQgRGF0YQpNaWNyb2FycmF5ZHMgPC0gcmVhZF9jc3YoIn4vRGVza3RvcC9EYXRhc2V0cy9NaWNyb2FycmF5ZHMuY3N2IikKR1NFZHMgPC0gcmVhZF9jc3YoIn4vRGVza3RvcC9EYXRhc2V0cy9HU0Vkcy5jc3YiKQpHU0VkcyA8LSBHU0Vkc1ssLTFdClRDR0FkcyA8LSByZWFkX3Rzdigifi9EZXNrdG9wL0RhdGFzZXRzL2RhdGFfUk5BX1NlcV92Ml9leHByZXNzaW9uX21lZGlhbi50eHQiKQpUQ0dBZHMgPC0gVENHQWRzWzMwOjIwNTMxLC0yXQpUQ0dBZHMgPC0gVENHQWRzICU+JSBncm91cF9ieShIdWdvX1N5bWJvbCkgJT4lIHN1bW1hcml6ZV9hbGwobWVhbikKCiMgMjYgbW9ydGFsaXR5LWFzc29jaWF0ZWQgaW1tdW5lLXJlbGF0ZWQgZ2VuZXMKZ2VuZWxpc3QgPC0gYygiR0dIIiwgIkFOWEExIiwgIkdMSVBSMSIsICJQREsxIiwgIlRQTTIiLCAiU05QSCIsICJETUJUMSIsICJTSUdMRUMxIiwgIktSVDZCIiwgIlBGS0ZCNCIsICJDRU5QVyIsICJSQUNHQVAxIiwgIkNEQ0E0IiwgIkJDQVQxIiwgIlFQQ1QiLCAiVlRBMSIsICJUVEsiLCAiUExPRDIiLCAiTVJDMSIsICJHQ05UMSIsICJTRVJQSU5CNyIsICJUUDYzIiwgIkFVUktBIiwgIkNFQUNBTTMiLCAiTlJJUDMiLCAiREVQREMxIikKCiNGaWx0ZXIgZGF0YXNldHMgZm9yIENDQSBJbW11bmUgU2lnbmF0dXJlCkdTRWltbXVuZSA8LSBmaWx0ZXIoR1NFZHMsIEdTRWRzJEdlbmVzICVpbiUgZ2VuZWxpc3QpCkdTRWltbXVuZSA8LSBjb2x1bW5fdG9fcm93bmFtZXMoR1NFaW1tdW5lLCAiR2VuZXMiKQojR1NFaW1tdW5lIDwtIEdTRWltbXVuZVssLTFdClRDR0FpbW11bmUgPC0gZmlsdGVyKFRDR0FkcywgVENHQWRzJEh1Z29fU3ltYm9sICVpbiUgZ2VuZWxpc3QpClRDR0FpbW11bmUgPC0gY29sdW1uX3RvX3Jvd25hbWVzKFRDR0FpbW11bmUsICJIdWdvX1N5bWJvbCIpCk1pY3JvYXJyYXlpbW11bmUgPC0gZmlsdGVyKE1pY3JvYXJyYXlkcywgTWljcm9hcnJheWRzJEdlbmVJRCAlaW4lIGdlbmVsaXN0KQpNaWNyb2FycmF5aW1tdW5lIDwtIGNvbHVtbl90b19yb3duYW1lcyhNaWNyb2FycmF5aW1tdW5lLCAiR2VuZUlEIikKCiNIaWVyYXJjaGljYWwgQ2x1c3RlcmluZwp4PSBwaGVhdG1hcChHU0VpbW11bmUsIHNjYWxlID0gInJvdyIsIGJvcmRlcl9jb2xvciA9IE5BLCAKICAgICAgICAgYnJlYWtzID0gc2VxKC0xLjUsIDEuNSwgbGVuZ3RoLm91dCA9IDEwMSksIAogICAgICAgICBjbHVzdGVyaW5nX21ldGhvZCA9ICJjb21wbGV0ZSIsIAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSAiY2FuYmVycmEiLCAKICAgICAgICAgY3V0cmVlX2NvbHMgPSAyKQp5ID0gcGhlYXRtYXAoVENHQWltbXVuZSwgc2NhbGUgPSAicm93IiwgYm9yZGVyX2NvbG9yID0gTkEsIAogICAgICAgICBicmVha3MgPSBzZXEoLTEuNSwgMS41LCBsZW5ndGgub3V0ID0gMTAxKSwgCiAgICAgICAgIGNsdXN0ZXJpbmdfbWV0aG9kID0gImNvbXBsZXRlIiwgCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2VfY29scyA9ICJjYW5iZXJyYSIsIAogICAgICAgICBjdXRyZWVfY29scyA9IDQpCnogPSBwaGVhdG1hcChNaWNyb2FycmF5aW1tdW5lLCBzY2FsZSA9ICJyb3ciLCBjbHVzdGVyaW5nX21ldGhvZCA9ICJjb21wbGV0ZSIsIGNsdXN0ZXJpbmdfZGlzdGFuY2VfY29scyA9ICJjYW5iZXJyYSIsIGJyZWFrcyA9IHNlcSgtMSwgMSwgbGVuZ3RoLm91dCA9IDEwMSksIHNob3dfY29sbmFtZXMgPSBGLCBjdXRyZWVfY29scyA9IDQpCgojSWRlbnRpZnkgQ2x1c3RlciBJRHMKaW5kR1NFIDwtIGN1dHJlZSh4JHRyZWVfY29sLCBrID0gMikKaW5kVENHQSA8LSBjdXRyZWUoeSR0cmVlX2NvbCwgayA9IDQpCmluZE1BIDwtIGN1dHJlZSh6JHRyZWVfY29sLCBrID0gNCkKaW5kR1NFIDwtIGFzLmRhdGEuZnJhbWUoaW5kR1NFKQppbmRUQ0dBIDwtIGFzLmRhdGEuZnJhbWUoaW5kVENHQSkKaW5kTUEgPC0gYXMuZGF0YS5mcmFtZShpbmRNQSkKaW5kR1NFJGluZEdTRSA8LSBzYXBwbHkoaW5kR1NFJGluZEdTRSwgYXMuZmFjdG9yKQppbmRUQ0dBJGluZFRDR0EgPC0gc2FwcGx5KGluZFRDR0EkaW5kVENHQSwgYXMuZmFjdG9yKQppbmRNQSRpbmRNQSA8LSBzYXBwbHkoaW5kTUEkaW5kTUEsIGFzLmZhY3RvcikKaW5kTUEkYW5ubyA8LSAiSGlnaCIKaW5kTUEkYW5ub1tpbmRNQSRpbmRNQSA9PSAxXSA8LSAiSW50ZXJtZWRpYXRlIgppbmRNQSRhbm5vW2luZE1BJGluZE1BID09IDRdIDwtICJMb3ciCndyaXRlLmNzdihpbmRHU0UsICJ+L0Rlc2t0b3AvRGF0YXNldHMvR1NFaGNsdXN0aWRlbnRpZmllcnMuY3N2IikKd3JpdGUuY3N2KGluZFRDR0EsICJ+L0Rlc2t0b3AvRGF0YXNldHMvVENHQWhjbHVzdGlkZW50aWZpZXJzLmNzdiIpCndyaXRlLmNzdihpbmRNQSwgIn4vRGVza3RvcC9EYXRhc2V0cy9NQWhjbHVzdGlkZW50aWZpZXJzLmNzdiIpCmBgYAoKYGBge3J9CiNEcmF3IEhlYXRtYXAgZm9yIEdTRWltbXVuZQpwaGVhdG1hcChHU0VpbW11bmUsIHNjYWxlID0gInJvdyIsIGJvcmRlcl9jb2xvciA9IE5BLCAKICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgtMS41LCAxLjUsIGxlbmd0aC5vdXQgPSAxMDEpLCAKICAgICAgICAgICAgIGNsdXN0ZXJpbmdfbWV0aG9kID0gImNvbXBsZXRlIiwgCiAgICAgICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSAiY2FuYmVycmEiLCAKICAgICAgICAgICAgIGN1dHJlZV9jb2xzID0gMiwgYW5ub3RhdGlvbiA9IGluZEdTRSwgbWFpbiA9IkdTRTEwNzk0MyIpCmBgYAoKYGBge3J9CiNEcmF3IEhlYXRtYXAgZm9yIFRDR0FpbW11bmUKcGhlYXRtYXAoVENHQWltbXVuZSwgc2NhbGUgPSAicm93IiwgYm9yZGVyX2NvbG9yID0gTkEsIAogICAgICAgICAgICAgYnJlYWtzID0gc2VxKC0xLjUsIDEuNSwgbGVuZ3RoLm91dCA9IDEwMSksIAogICAgICAgICAgICAgY2x1c3RlcmluZ19tZXRob2QgPSAiY29tcGxldGUiLCAKICAgICAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2VfY29scyA9ICJjYW5iZXJyYSIsIAogICAgICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gIm1hbmhhdHRhbiIsCiAgICAgICAgICAgICBjdXRyZWVfY29scyA9IDQsIGFubm90YXRpb24gPSBpbmRUQ0dBLCBtYWluID0gIlRDR0EtQ0hPTCIpCmBgYAoKYGBge3J9CiNEcmF3IEhlYXRtYXAgZm9yIE1pY3JvYXJyYXlpbW11bmUKcGhlYXRtYXAoTWljcm9hcnJheWltbXVuZSwgc2NhbGUgPSAicm93IiwgCiAgICAgICAgIGNsdXN0ZXJpbmdfbWV0aG9kID0gImNvbXBsZXRlIiwgCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2VfY29scyA9ICJjYW5iZXJyYSIsIAogICAgICAgICBicmVha3MgPSBzZXEoLTEsIDEsIGxlbmd0aC5vdXQgPSAxMDEpLCAKICAgICAgICAgc2hvd19jb2xuYW1lcyA9IEYsIGN1dHJlZV9jb2xzID0gNCwgYW5ub3RhdGlvbiA9IGluZE1BLCBtYWluID0gIk1pY3JvYXJyYXkgRGF0YXNldHMiKQpgYGAKClRoZW4sIHdlIGFwcGxpZWQgS2FwbGFuLU1laWVyIGN1cnZlIHRvIGVsdWNpZGF0ZSB0aGUgcHJvZ25vc3RpYyB2YWx1ZSBvZiAyNiBpbW11bmUgZ2VuZSBzaWduYXR1cmUgY2xhc3NpZmljYXRpb24gaW4gdGhlIHBvb2xlZCBjb2hvcnQgb2YgQ0NBIHBhdGllbnRzIChHU0UxMDc5NDMgYW5kIFRDR0EtQ0hPTCkgCmBgYHtyIEtNIHBsb3QsIGVjaG89VFJVRX0KI0Fubm90YXRlIFNhbXBsZXMgd2l0aCBDbHVzdGVyIEdyb3VwIG5hbWUKaW5kR1NFJHNhbXBsZXMgPC0gcm93bmFtZXMoaW5kR1NFKQppbmRHU0UkYW5ubyA8LSAiSGlnaCIKaW5kR1NFJGFubm9baW5kR1NFJGluZEdTRSA9PSAxXSA8LSAiTG93IgoKaW5kVENHQSRzYW1wbGVzIDwtIHJvd25hbWVzKGluZFRDR0EpCmluZFRDR0EkYW5ubyA8LSAiSGlnaCIKaW5kVENHQSRhbm5vW2luZFRDR0EkaW5kVENHQSA9PSAyXSA8LSAiTG93Igphbm5vdGF0aW9uIDwtIHJiaW5kKGluZEdTRVssMjozXSwgaW5kVENHQVssMjozXSkKI1Bsb3QgS2FwbGFpbi1NZWllciBDdXJ2ZSB1c2luZyB0aGUgQ2x1c3RlciBhbm5vdGF0aW9uIGFzIGEgZmFjdG9yCkdTRVRDR0EgPC0gcmJpbmQoR1NFc3VydmdlbmVzWywxOjVdLCBUQ0dBc3VydmdlbmVzWywxOjVdKQpHU0VUQ0dBIDwtIG1lcmdlKEdTRVRDR0EsIGFubm90YXRpb24sIGJ5LnggPSAiU2FtcGxlIiwgYnkueSA9ICJzYW1wbGVzIiwgYWxsLnkgPSBUUlVFKQprbV9maXQgPC0gc3VydmZpdChTdXJ2KE9TLCBEZWF0aCkgfiBhbm5vLCBkYXRhPUdTRVRDR0EpCmdnc3VydiA8LSBnZ3N1cnZwbG90KGttX2ZpdCwgZGF0YSA9IEdTRVRDR0EsICByaXNrLnRhYmxlID0gVFJVRSwgY3VtZXZlbnRzID0gVFJVRSwgcHZhbCA9IFRSVUUsIHB2YWwubWV0aG9kID0gVFJVRSwgcmlzay50YWJsZS5jb2wgPSAic3RyYXRhIiwgCiAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmxhYnM9YygiSGlnaCIsICJMb3ciKSwgcGFsZXR0ZSA9IGMoInRvbWF0byIsICJjb3JuZmxvd2VyYmx1ZSIpKQpnZ3N1cnYKYGBgCgpXZSBoYXZlIGlkZW50aWZpZWQgbG93IGV4cHJlc3NpbmcgYW5kIGhpZ2ggZXhwcmVzc2luZyBzYW1wbGVzIGluIGVhY2ggY29ob3J0LiBXZSB3b3VsZCBub3cgbGlrZSB0byBhc3Nlc3MgdGhlIHRyYW5zY3JpcHRvbWljIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlc2UgdHdvIGdyb3VwcywgaGVuY2Ugd2Ugd2lsbCBjb25kdWN0IERpZmZlcmVudGlhbCBHZW5lIEV4cHJlc3Npb24gQW5hbHlzaXMuCmBgYHtyfQojTG9hZCBMaWJyYXJpZXMgYW5kIFByZS1wcm9jZXNzIERhdGEKbGlicmFyeShERVNlcTIpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpYmJsZSkKCiNEYXRhIFByZXByb2Nlc3NpbmcKR1NFZHMgPC0gY29sdW1uX3RvX3Jvd25hbWVzKEdTRWRzLCAiR2VuZXMiKQpjb3VudHMubSA8LSBhcy5tYXRyaXgoR1NFZHMpCkxIZ3JvdXAgPC0gaW5kR1NFCmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IHJvdW5kKGNvdW50cy5tKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IExIZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiBhbm5vKSAKa2VlcCA8LSByb3dTdW1zKGNvdW50cyhkZHMpKSA+PSAxMApzdW1tYXJ5KGtlZXApCmRkcyA8LSBkZHNba2VlcCxdCiNEaWZmZXJlbnRpYWwgR2VuZSBFeHByZXNzaW9uIEFuYWx5c2lzCmRkcyA8LSBERVNlcShkZHMpCnJlcyA8LSByZXN1bHRzKGRkcykKcmVzCnJlc09yZGVyZWQgPC0gcmVzW29yZGVyKHJlcyRwdmFsdWUpLF0Kc3VtbWFyeShyZXMpCnN1bShyZXMkcGFkaiA8IDAuMSwgbmEucm09VFJVRSkKcmVzMSA8LSBhcy5kYXRhLmZyYW1lKHJlcykKcmVzMSA8LSBmaWx0ZXIocmVzMSwgcmVzMSRwYWRqIDwgMC4wNSwgbmEucm09VFJVRSkKd3JpdGUuY3N2KGFzLmRhdGEuZnJhbWUocmVzT3JkZXJlZCksIAogICAgICAgICAgZmlsZT0ifi9EZXNrdG9wL0RhdGFzZXRzL0dTRWltbXVuZTJERVNlcTJfSGlnaExvdy5jc3YiKQpyZXNTaWcgPC0gc3Vic2V0KHJlc09yZGVyZWQsIHBhZGogPCAwLjA1KQpyZXNTaWcKd3JpdGUuY3N2KGFzLmRhdGEuZnJhbWUocmVzU2lnKSwgZmlsZSA9ICJ+L0Rlc2t0b3AvRGF0YXNldHMvVGFibGVTNS5jc3YiKQpgYGAKCmBgYHtyfQojUGxvdCBQQ0EgLSBHU0UxMDc5NDMKcmxkIDwtIHJsb2coZGRzLCBibGluZD1UUlVFKQpwIDwtIHBsb3RQQ0EocmxkLCBpbnRncm91cD0iYW5ubyIpCnAgKyBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIkxvdyIgPSAiY29ybmZsb3dlcmJsdWUiLCAiSGlnaCIgPSAidG9tYXRvIikpCmBgYAoKYGBge3J9CiNQbG90IFZvbGNhbm8gb2YgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzIC0gR1NFMTA3OTQzCkVuaGFuY2VkVm9sY2FubyhyZXMsCiAgICAgICAgICAgICAgICBsYWIgPSByb3duYW1lcyhyZXMpLAogICAgICAgICAgICAgICAgeCA9ICJsb2cyRm9sZENoYW5nZSIsCiAgICAgICAgICAgICAgICB5ID0gInBhZGoiLAogICAgICAgICAgICAgICAgeWxpbSA9IGMoMCw0KSwKICAgICAgICAgICAgICAgIHRpdGxlID0gIkdTRTEwNzk0MyIsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IGxvZzIoMiksCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgICAgICAgeGxpbSA9IGMoLTUsNSkpCmBgYAoKYGBge3J9CiNQbG90IEhlYXRtYXAgb2YgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzIC0gR1NFMTA3OTQzCmhtYXB4ID0gc3Vic2V0KGNvdW50cy5tLCByb3duYW1lcyhjb3VudHMubSkgJWluJSByb3duYW1lcyhyZXNTaWcpKQphbm5vID0gTEhncm91cFssMjozXQpyb3duYW1lcyhhbm5vKSA9IE5VTEwKYW5ubyA9IGNvbHVtbl90b19yb3duYW1lcyhhbm5vLCAic2FtcGxlcyIpCmhtYXB4ID0gaG1hcHhbLC0xXQpwaGVhdG1hcChobWFweCwgYnJlYWtzID0gc2VxKC0xLjUsIDEuNSwgbGVuZ3RoLm91dCA9IDEwMSksIHNjYWxlID0gInJvdyIsCiAgICAgICAgIGNsdXN0ZXJpbmdfbWV0aG9kID0gImNvbXBsZXRlIiwgZm9udHNpemVfcm93ID0gNywgYW5ub3RhdGlvbl9jb2wgPSBhbm5vLCBhbm5vdGF0aW9uX2NvbG9ycyA9IGxpc3QoYW5ubyA9IGMoTG93ID0gImNvcm5mbG93ZXJibHVlIiwgSGlnaCA9ICJ0b21hdG8iKSksCiAgICAgICAgIG1haW4gPSAiR1NFMTA3OTQzIiwgYm9yZGVyX2NvbG9yID0gTkEsIGNsdXN0ZXJpbmdfZGlzdGFuY2VfY29scyA9ICJjYW5iZXJyYSIsIGFubm90YXRpb25fbmFtZXNfY29sID0gRikKYGBgCgpOb3cgd2Ugd2lsbCByZXBlYXQgdGhpcyBhbmFseXNpcyBmb3IgdGhlIFRDR0EtQ0hPTCBjb2hvcnQKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KHRpZHlyKQojUmVwZWF0IGFuYWx5c2lzIGluIFRDR0EtQ0hPTCBjb2hvcnQKI0RhdGEgUHJlLVByb2Nlc3NpbmcKVENHQWRzID0gY29sdW1uX3RvX3Jvd25hbWVzKFRDR0FkcywgIkh1Z29fU3ltYm9sIikKY291bnRzLm0gPSBhcy5tYXRyaXgoVENHQWRzKQpMSGdyb3VwID0gaW5kVENHQQpkZHMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSByb3VuZChjb3VudHMubSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBMSGdyb3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSB+IGFubm8pCmtlZXAgPC0gcm93U3Vtcyhjb3VudHMoZGRzKSkgPj0gMTAKc3VtbWFyeShrZWVwKQpkZHMgPC0gZGRzW2tlZXAsXQojRGlmZmVyZW50aWFsIEdlbmUgRXhwcmVzc2lvbiBBbmFseXNpcwpkZHMgPC0gREVTZXEoZGRzKQpyZXMgPC0gcmVzdWx0cyhkZHMpCnJlcwpyZXNPcmRlcmVkIDwtIHJlc1tvcmRlcihyZXMkcHZhbHVlKSxdCnN1bW1hcnkocmVzKQpzdW0ocmVzJHBhZGogPCAwLjEsIG5hLnJtPVRSVUUpCnJlczEgPSBhcy5kYXRhLmZyYW1lKHJlcykKcmVzMSA9IGZpbHRlcihyZXMxLCByZXMxJHBhZGogPCAwLjA1LCBuYS5ybT1UUlVFKQp3cml0ZS5jc3YoYXMuZGF0YS5mcmFtZShyZXNPcmRlcmVkKSwgCiAgICAgICAgICBmaWxlPSJ+L0Rlc2t0b3AvRGF0YXNldHMvVENHQWltbXVuZTJERVNlcTJfSGlnaExvdy5jc3YiKQpyZXNTaWcgPC0gc3Vic2V0KHJlc09yZGVyZWQsIHBhZGogPCAwLjA1KQpyZXNTaWcKd3JpdGUuY3N2KGFzLmRhdGEuZnJhbWUocmVzU2lnKSwgZmlsZSA9ICJ+L0Rlc2t0b3AvRGF0YXNldHMvVGFibGVTNi5jc3YiKQpgYGAKCmBgYHtyfQojUGxvdCBQQ0EgLSBUQ0dBLUNIT0wKcmxkIDwtIHJsb2coZGRzLCBibGluZD1UUlVFKQpwID0gcGxvdFBDQShybGQsIGludGdyb3VwPSJhbm5vIikKcCArIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiTG93IiA9ICJjb3JuZmxvd2VyYmx1ZSIsICJIaWdoIiA9ICJ0b21hdG8iKSkKYGBgCgpgYGB7cn0KI1Bsb3QgVm9sY2FubyBvZiBEaWZmZXJlbnRpYWxseSBFeHByZXNzZWQgR2VuZXMKRW5oYW5jZWRWb2xjYW5vKHJlcywKICAgICAgICAgICAgICAgIGxhYiA9IHJvd25hbWVzKHJlcyksCiAgICAgICAgICAgICAgICB4ID0gImxvZzJGb2xkQ2hhbmdlIiwKICAgICAgICAgICAgICAgIHkgPSAicGFkaiIsCiAgICAgICAgICAgICAgICB5bGltID0gYygwLDQpLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiVENHQS1DSE9MIiwKICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gbG9nMigyKSwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICAgICAgICB4bGltID0gYygtNSw1KSkKYGBgCgpgYGB7cn0KI1Bsb3QgSGVhdG1hcCBvZiBEaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMKaG1hcHggPSBzdWJzZXQoY291bnRzLm0sIHJvd25hbWVzKGNvdW50cy5tKSAlaW4lIHJvd25hbWVzKHJlc1NpZykpCmFubm8gPSBMSGdyb3VwWywyOjNdCnJvd25hbWVzKGFubm8pID0gTlVMTAphbm5vID0gY29sdW1uX3RvX3Jvd25hbWVzKGFubm8sICJzYW1wbGVzIikKcGhlYXRtYXAoaG1hcHgsIGJyZWFrcyA9IHNlcSgtMS41LCAxLjUsIGxlbmd0aC5vdXQgPSAxMDEpLCBzaG93X2NvbG5hbWVzID0gVCwgc2NhbGUgPSAicm93IiwKICAgICAgICAgY2x1c3RlcmluZ19tZXRob2QgPSAiY29tcGxldGUiLCBmb250c2l6ZV9yb3cgPSA3LCBhbm5vdGF0aW9uX2NvbCA9IGFubm8sIGFubm90YXRpb25fY29sb3JzID0gbGlzdChhbm5vID0gYyhMb3cgPSAiY29ybmZsb3dlcmJsdWUiLCBIaWdoID0gInRvbWF0byIpKSwgY2x1c3RlcmluZ19kaXN0YW5jZV9jb2xzID0gImNvcnJlbGF0aW9uIiwKICAgICAgICAgbWFpbiA9ICJUQ0dBLUNIT0wiLCBib3JkZXJfY29sb3IgPSBOQSwgYW5ub3RhdGlvbl9uYW1lc19jb2wgPSBGKSAKYGBgCgpgYGB7cn0KIyBNaWNyb2FycmF5IERHRSBWYWxpZGF0aW9uCmRmIDwtIGFzLmRhdGEuZnJhbWUoTWljcm9hcnJheWRzKQpkZiA9IGNvbHVtbl90b19yb3duYW1lcyhkZiwgIkdlbmVJRCIpCmNvdW50cyA8LSBhcy5tYXRyaXgoZGYpCnNhbXBsZV9pZCA8LSByZWFkX2Nzdigifi9EZXNrdG9wL0RhdGFzZXRzL01BaGNsdXN0aWRlbnRpZmllcnMuY3N2IikKc2FtcGxlX2lkID0gZmlsdGVyKHNhbXBsZV9pZCwgc2FtcGxlX2lkJGFubm8gPT0gIkxvdyJ8IHNhbXBsZV9pZCRhbm5vID09ICJIaWdoIikKY29sbmFtZXMoc2FtcGxlX2lkKVsxXSA9ICJzYW1wbGVzIgpzYW1wbGVfaWQgPSBjb2x1bW5fdG9fcm93bmFtZXMoc2FtcGxlX2lkLCAic2FtcGxlcyIpCmNvdW50cyA9IHQoY291bnRzKQpjb3VudHMgPSBzdWJzZXQoY291bnRzLCByb3duYW1lcyhjb3VudHMpICVpbiUgcm93bmFtZXMoc2FtcGxlX2lkKSkKY291bnRzID0gdChjb3VudHMpCmdlbmVsaXN0IDwtIHJvd25hbWVzKGNvdW50cykKZ2VuZXMgPSBnZW5lbGlzdApncm91cCA8LSBzYW1wbGVfaWQkYW5ubwpjb3VudHMubTwtYXMubWF0cml4KGNvdW50cykKaXMubnVtZXJpYyhjb3VudHMubSkKCiNSZW1vdmUgZ2VuZXMgdGhhdCBhcmUgMCAKbiA8LSB3aGljaChpcy5uYShjb3VudHMubSkpCmNvdW50cy5tW25dPC0wCgojVHJhbnNmb3JtYXRpb24gZnJvbSByYXcgIHNjYWxlIC0tPmxvZzIKY291bnRzLkwgPSBsb2cyKGNvdW50cy5tICsgMSkKeCA8LSBER0VMaXN0KGNvdW50cz0gY291bnRzLkwsIGdlbmVzID0gZ2VuZXMsIGdyb3VwID0gZ3JvdXAsIHNhbXBsZXMgPSBzYW1wbGVfaWQkWDEpCmdyb3VwIDwtIGFzLmZhY3Rvcihncm91cCkKeCRzYW1wbGVzJGdyb3VwIDwtIGdyb3VwCngkZ2VuZXMgPC0gZ2VuZXMKeCA8LSBjYWxjTm9ybUZhY3RvcnMoeCwgbWV0aG9kID0gIlRNTSIpCgojcGxvdE1EUyBmb3IgdW5zdXBlcnZpc2VkIGNsdXN0ZXJpbmcKcGFyKG1mcm93PWMoMSwyKSkKZ3JvdXAgPC0gYXMuZmFjdG9yKGdyb3VwKQpjb2wuZ3JvdXAgPC0gZ3JvdXAKbGV2ZWxzKGNvbC5ncm91cCkgPC0gIGMoInRvbWF0byIsICJjb3JuZmxvd2VyYmx1ZSIpCmNvbC5ncm91cCA8LSBhcy5jaGFyYWN0ZXIoY29sLmdyb3VwKQpwbG90TURTKHgsIGxhYmVscz1ncm91cCwgY29sPWNvbC5ncm91cCkKI3RpdGxlKG1haW49IlNhbXBsZSBncm91cHMiKQpgYGAKCmBgYHtyfQojM0QgcGxvdHMgLSBNaWNyb2FycmF5IGRhdGFzZXQKbGlicmFyeShyZ2wpCgojQ29tcHV0ZSBQQ0EKcCA8LSBjb3VudHMuTApwLnQgPC0gdChwKQpwLnRfZGYgPC0gYXMuZGF0YS5mcmFtZShwLnQpCnBjYSA8LSBwcmNvbXAocC50X2RmKQpzY29yZXMgPSBhcy5kYXRhLmZyYW1lKHBjYSR4KQpzdW1tYXJ5KHBjYSkKcGxvdDNkKHNjb3Jlcywgc2l6ZT0xMCwgdHlwZT0ncCcsIGNvbCA9IGNvbC5ncm91cCkKI3RleHQzZChzY29yZXMsIHRleHRzPWMoZ3JvdXApLCBjZXg9IDAuNywgcG9zPTMpCgojVG8gc2F2ZSB0aGUgYW5pbWF0ZWQgUENBIGdyYXBocwpkaXIuY3JlYXRlKCJ+L0Rlc2t0b3AvRGF0YXNldHMvYW5pbWF0aW9uX21lcmdlIikKZm9yIChpIGluIDE6MzYwKSB7CiAgdmlldzNkKHVzZXJNYXRyaXg9cm90YXRpb25NYXRyaXgoMipwaSAqIGkvMzYwLCAwLCAxLCAwKSkKICByZ2wuc25hcHNob3QoZmlsZW5hbWU9cGFzdGUoIn4vRGVza3RvcC9EYXRhc2V0cy9hbmltYXRpb25fbWVyZ2UvZnJhbWUtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaW50ZigiJTAzZCIsIGkpLCAiLnBuZyIsIHNlcD0iIikpfQoKI0Rlc2lnbiBtYXRyaXgKIyBsaW5lYXIgbW9kZWxzIGFyZSBmaXR0ZWQgdG8gdGhlIGRhdGEgd2l0aCB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSB1bmRlcmx5aW5nIGRhdGEgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuCiNhIGRlc2lnbiBtYXRyaXggaXMgc2V0IHVwIHdpdGggYm90aCB0aGUgY2x1c3RlciBncm91cHMgKGdyb3VwKSBhbmQgc3R1ZHkgKGJhdGNoKSBpbmZvcm1hdGlvbi4KZ3JvdXAgPC0gYXMuZmFjdG9yKGdyb3VwKQpkZXNpZ24gPC0gbW9kZWwubWF0cml4KH4wK2dyb3VwKQpjb2xuYW1lcyhkZXNpZ24pIDwtIGMoIkxvdyIsICJIaWdoIikKICAgICAgICAgICAgICAgICAgICAgCmRlc2lnbgoKY29udHIubWF0cml4IDwtIG1ha2VDb250cmFzdHMoKExvdyAtIEhpZ2gpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gY29sbmFtZXMoZGVzaWduKSkKY29udHIubWF0cml4CgojbGltbWEtdHJlbmQKZml0IDwtIGxtRml0KHgkY291bnRzLCBkZXNpZ24sIG1ldGhvZCA9ICJscyIpCmZpdCA8LSBjb250cmFzdHMuZml0KGZpdCwgY29udHJhc3RzID0gY29udHIubWF0cml4KQpmaXQgPC0gZUJheWVzKGZpdCwgdHJlbmQgPSBUUlVFKQp0b3BUYWJsZShmaXQpCgojVk9PTUEKdiA8LSB2b29tYSh4JGNvdW50cywgZGVzaWduLAogICAgICAgICAgIHBsb3Q9VFJVRSkKdiA8LSB2b29tYUJ5R3JvdXAoeCRjb3VudHMsIGdyb3VwLCBkZXNpZ24sIHBsb3QgPSBUUlVFKQp2CnZmaXQgPC0gbG1GaXQodiwgZGVzaWduLCBtZXRob2QgPSAibHMiKQp2Zml0IDwtIGNvbnRyYXN0cy5maXQodmZpdCwgY29udHJhc3RzPWNvbnRyLm1hdHJpeCkKZWZpdCA8LSBlQmF5ZXModmZpdCkKcGxvdFNBKGVmaXQsIG1haW49IkZpbmFsIG1vZGVsOiBNZWFuLXZhcmlhbmNlIHRyZW5kIikKYGBgCgpgYGB7cn0KI0V4YW1pbmluZyB0aGUgbnVtYmVyIG9mIERFIGdlbmVzIC0gTWljcm9hcnJheSBkYXRhc2V0CnN1bW1hcnkoZGVjaWRlVGVzdHMoZWZpdCkpCnRmaXQgPC0gdHJlYXQoZWZpdCwgbGZjPSBsb2cyKDEpKQpkdCA8LSBkZWNpZGVUZXN0cyh0Zml0LCBtZXRob2QgPSAiaGllcmFyY2hpY2FsIiwgCiAgICAgICAgICAgICAgICAgIGFkanVzdC5tZXRob2QgPSAiQkgiLCBsZmMgPSBsb2cyKDIpLCAKICAgICAgICAgICAgICAgICAgcC52YWx1ZSA9IDAuMDEpCnN1bW1hcnkoZHQpCndyaXRlLmZpdCh0Zml0LCByZXN1bHRzID0gZHQsICJ+L0Rlc2t0b3AvRGF0YXNldHMvTUFfREdFLnR4dCIsIGFkanVzdCA9ICJCSCIpCgp0b3BUbiA8LSB0b3BUYWJsZSh0Zml0LCBjb2VmID0gTlVMTCwgbnVtYmVyID0gSW5mLCBnZW5lbGlzdCA9IHRmaXQkZ2VuZXMsIGFkanVzdC5tZXRob2QgPSAiQkgiLCBwLnZhbHVlID0gMSwgbGZjID0gbG9nMigxKSwgc29ydC5ieSA9ICJsb2dGQyIpCnRvcFRuX3NpZyA8LSB0b3BUYWJsZSh0Zml0LCBjb2VmID0gTlVMTCwgbnVtYmVyID0gSW5mLCBnZW5lbGlzdCA9IHRmaXQkZ2VuZXMsIGFkanVzdC5tZXRob2QgPSAiQkgiLCBwLnZhbHVlID0gMC4wMSwgbGZjID0gbG9nMigyKSwgc29ydC5ieSA9ICJsb2dGQyIpCndyaXRlLmNzdih0b3BUbl9zaWcsIGZpbGUgPSAifi9EZXNrdG9wL0RhdGFzZXRzL01BX3RvcFRuX3NpZy5jc3YiKQpFbmhhbmNlZFZvbGNhbm8odG9wVG4sCiAgICAgICAgICAgICAgICBsYWIgPSByb3duYW1lcyh0b3BUbiksCiAgICAgICAgICAgICAgICB4ID0gImxvZ0ZDIiwKICAgICAgICAgICAgICAgIHkgPSAiYWRqLlAuVmFsIiwKICAgICAgICAgICAgICAgIHhsaW0gPSBjKC01LCA1KSwKICAgICAgICAgICAgICAgIHlsaW0gPSBjKC0xLCAzMDApLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiTWljcm9hcnJheSBER0UiLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDEsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IGxvZzIoMiksCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAyLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gMy4wLAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCmBgYHtyfQojaGVhdG1hcCAtIE1pY3JvYXJyYXkgZGF0YXNldApjbHVzdGVyID0gYXMuZGF0YS5mcmFtZShncm91cCkKcm93bmFtZXMoY2x1c3RlcikgPSByb3duYW1lcyhzYW1wbGVfaWQpCmhtYXB4ID0gc3Vic2V0KGNvdW50cy5MLCByb3duYW1lcyhjb3VudHMuTCkgJWluJSByb3duYW1lcyh0b3BUbikpCnBoZWF0bWFwKGhtYXB4LCBicmVha3MgPSBzZXEoLTEuNSwgMS41LCBsZW5ndGgub3V0ID0gMTAxKSwgc2NhbGUgPSAicm93IiwgY2x1c3RlcmluZ19tZXRob2QgPSAiY29tcGxldGUiLCBmb250c2l6ZV9yb3cgPSA3LCBhbm5vdGF0aW9uX2NvbCA9IGNsdXN0ZXIsIGFubm90YXRpb25fY29sb3JzID0gbGlzdChjbHVzdGVyID0gYyhMb3cgPSAiY29ybmZsb3dlcmJsdWUiLCBIaWdoID0gInRvbWF0byIpKSwgY2x1c3RlcmluZ19kaXN0YW5jZV9jb2xzID0gImNvcnJlbGF0aW9uIiwgbWFpbiA9ICJNaWNyb2FycmF5IERHRSIsIGJvcmRlcl9jb2xvciA9IE5BLCBzaG93X2NvbG5hbWVzID0gRiwgYW5ub3RhdGlvbl9uYW1lc19jb2wgPSBGKSAKYGBgCgpUaGUgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmUgbGlzdCBoYXMgYmVlbiB1c2VkIGFzIGFuIGlucHV0IGluIGlMSU5DUyBhbmQgRW5yaWNoUiB0byBvYnRhaW4gcGF0aHdheSBlbnJpY2htZW50cyBhbmQgcG9zaXRpdmVseSBjb3JyZWxhdGVkIGNvbm5lY3RlZCBwZXJ0dXJiYWdlbnMuIFRoZXNlIGFyZSBwcmVzZW50ZWQgaW4gVGFibGUgUzYsIFM4LCBTMTAsIFMxMSBhbmQgUzEyLiBUaGV5IGhhdmUgYmVlbiB2aXN1YWxpemVkIHVzaW5nIHRoZSBmb2xsb3dpbmcgc2NyaXB0LiAKYGBge3J9CiNQYXRod2F5IEVucmljaG1lbnQgUGxvdApsaWJyYXJ5KGdncGxvdDIpCkVucmljaG1lbnRfR1NFIDwtIHJlYWRfY3N2KCJ+L0Rlc2t0b3AvRGF0YXNldHMvRW5yaWNobWVudF9HU0UuY3N2IikKRW5yaWNobWVudF9UQ0dBIDwtIHJlYWRfY3N2KCJ+L0Rlc2t0b3AvRGF0YXNldHMvRW5yaWNobWVudF9UQ0dBLmNzdiIpCkVucmljaG1lbnRfTUEgPC0gcmVhZF9jc3YoIn4vRGVza3RvcC9EYXRhc2V0cy9FbnJpY2htZW50X01BLmNzdiIpCgpkcyA8LSBkYXRhLmZyYW1lKGNiaW5kKEVucmljaG1lbnRfR1NFJGBUZXJtYCwgRW5yaWNobWVudF9HU0UkYERFR3NgLCBFbnJpY2htZW50X0dTRSRgQ29tYmluZWQgU2NvcmVgLCBFbnJpY2htZW50X0dTRSRgQWRqdXN0ZWQgUC12YWx1ZWAsIEVucmljaG1lbnRfR1NFJERhdGFiYXNlKSkKY29sbmFtZXMoZHMpIDwtIGMoIlBhdGh3YXlzIiwgIkRFR3MiLCAiQ29tYmluZWQgU2NvcmUiLCAiQWRqdXN0ZWQgUC52YWwiLCAiRGF0YWJhc2UiKQpFbnJpY2htZW50X0dTRSA8LSBhcy5kYXRhLmZyYW1lKEVucmljaG1lbnRfR1NFKQpkc1ssYygyOjQpXSA8LSBzYXBwbHkoZHNbLGMoMjo0KV0sIGFzLm51bWVyaWMpCnBhdGh3YXlfR1NFID0gZ2dwbG90KGRzICxhZXMoeD0gYENvbWJpbmVkIFNjb3JlYCwgCiAgICAgICAgICAgICAgICAgIHk9IFBhdGh3YXlzLCBzaXplID0gREVHcykpK2dlb21fcG9pbnQoYWVzKGNvbD0gYEFkanVzdGVkIFAudmFsYCksIGFscGhhPTAuOCkrc2NhbGVfY29sb3VyX2dyYWRpZW50KGxvdyA9ICJyZWQiLCBoaWdoID0gImJsdWUiKStzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cl93cmFwKHgsIHdpZHRoID0gMTApKStmYWNldF9ncmlkKH5EYXRhYmFzZSkreGxpbSgwLCA1MDApCnBhdGh3YXlfR1NFIApgYGAKCmBgYHtyfQpkcyA8LSBkYXRhLmZyYW1lKGNiaW5kKEVucmljaG1lbnRfVENHQSRgVGVybWAsIEVucmljaG1lbnRfVENHQSRgREVHc2AsIEVucmljaG1lbnRfVENHQSRgQ29tYmluZWQgU2NvcmVgLCBFbnJpY2htZW50X1RDR0EkYEFkanVzdGVkIFAtdmFsdWVgLCBFbnJpY2htZW50X1RDR0EkRGF0YWJhc2UpKQpjb2xuYW1lcyhkcykgPC0gYygiUGF0aHdheXMiLCAiREVHcyIsICJDb21iaW5lZCBTY29yZSIsICJBZGp1c3RlZCBQLnZhbCIsICJEYXRhYmFzZSIpCkVucmljaG1lbnRfVENHQSA8LSBhcy5kYXRhLmZyYW1lKEVucmljaG1lbnRfVENHQSkKZHNbLGMoMjo0KV0gPC0gc2FwcGx5KGRzWyxjKDI6NCldLCBhcy5udW1lcmljKQoKcGF0aHdheV9UQ0dBIDwtIGdncGxvdChkcyAsYWVzKHg9IGBDb21iaW5lZCBTY29yZWAsIAogICAgICAgICAgICAgICAgICAgeT0gUGF0aHdheXMsIHNpemUgPSBERUdzKSkrZ2VvbV9wb2ludChhZXMoY29sPSBgQWRqdXN0ZWQgUC52YWxgKSwgYWxwaGE9MC44KStzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93ID0gInJlZCIsIGhpZ2ggPSAiYmx1ZSIpK3NjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyX3dyYXAoeCwgd2lkdGggPSAxMCkpK2ZhY2V0X2dyaWQofkRhdGFiYXNlKSt4bGltKDAsIDUwMCkKcGF0aHdheV9UQ0dBCmBgYAoKYGBge3J9CmRzID0gZGF0YS5mcmFtZShjYmluZChFbnJpY2htZW50X01BJGBUZXJtYCwgRW5yaWNobWVudF9NQSRgREVHc2AsIEVucmljaG1lbnRfTUEkYENvbWJpbmVkIFNjb3JlYCwgRW5yaWNobWVudF9NQSRgQWRqdXN0ZWQgUC12YWx1ZWAsIEVucmljaG1lbnRfTUEkRGF0YWJhc2UpKQpjb2xuYW1lcyhkcykgPC0gYygiUGF0aHdheXMiLCAiREVHcyIsICJDb21iaW5lZCBTY29yZSIsICJBZGp1c3RlZCBQLnZhbCIsICJEYXRhYmFzZSIpCkVucmljaG1lbnRfTUEgPC0gYXMuZGF0YS5mcmFtZShFbnJpY2htZW50X01BKQpkc1ssYygyOjQpXSA8LSBzYXBwbHkoZHNbLGMoMjo0KV0sIGFzLm51bWVyaWMpCnBhdGh3YXlfTUEgPC0gZ2dwbG90KGRzICxhZXMoeD0gYENvbWJpbmVkIFNjb3JlYCwgCiAgICAgICAgICAgICAgICAgIHk9IFBhdGh3YXlzLCBzaXplID0gREVHcykpK2dlb21fcG9pbnQoYWVzKGNvbD0gYEFkanVzdGVkIFAudmFsYCksIGFscGhhPTAuOCkrc2NhbGVfY29sb3VyX2dyYWRpZW50KGxvdyA9ICJyZWQiLCBoaWdoID0gImJsdWUiKStzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cl93cmFwKHgsIHdpZHRoID0gMTApKStmYWNldF9ncmlkKH5EYXRhYmFzZSkreGxpbSgwLCA1MDApCnBhdGh3YXlfTUEKYGBgCgpgYGB7cn0KI0Nvbm5lY3RlZCBQZXJ0dXJiYWdlbnMgUGxvdApHU0VkcnVncyA8LSByZWFkX3Rzdigifi9EZXNrdG9wL0RhdGFzZXRzL0dTRWRydWdzLnR4dCIpClRDR0FkcnVncyA8LSByZWFkX3Rzdigifi9EZXNrdG9wL0RhdGFzZXRzL1RDR0FkcnVncy50eHQiKQpNQWRydWdzIDwtIHJlYWRfdHN2KCJ+L0Rlc2t0b3AvRGF0YXNldHMvTUFkcnVncy50eHQiKQoKR1NFZHJ1Z3MgJT4lIGFycmFuZ2UoZGVzYyh6U2NvcmUpKSAlPiUgaGVhZCgyNSkgJT4lZ2dwbG90KGFlcyhyZW9yZGVyKFBlcnR1cmJhZ2VuLCB6U2NvcmUpLCB6U2NvcmUpKSsgCiAgZ2VvbV9jb2woYWVzKGZpbGwgPSBwVmFsdWUpKSArIAogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImRhcmtnb2xkZW5yb2QxIiwgCiAgICAgICAgICAgICAgICAgICAgICBoaWdoID0gImRhcmtnb2xkZW5yb2Q0IikgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyX3dyYXAoeCwgd2lkdGggPSAxMCkpKwogIGNvb3JkX2ZsaXAoKSArIAogIGxhYnMoeCA9ICJDb25uZWN0ZWQgUGVydHVyYmFnZW5zIiwgeSA9ICJaIHNjb3JlIikKYGBgCgpgYGB7cn0KVENHQWRydWdzICU+JSBhcnJhbmdlKGRlc2MoelNjb3JlKSkgJT4lIGhlYWQoMjUpICU+JWdncGxvdChhZXMocmVvcmRlcihQZXJ0dXJiYWdlbiwgelNjb3JlKSwgelNjb3JlKSkrIAogIGdlb21fY29sKGFlcyhmaWxsID0gcFZhbHVlKSkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJkYXJrb2xpdmVncmVlbjIiLCAKICAgICAgICAgICAgICAgICAgICAgIGhpZ2ggPSAiZGFya29saXZlZ3JlZW40IikgKyAKICBjb29yZF9mbGlwKCkgKyAKICBsYWJzKHggPSAiQ29ubmVjdGVkIFBlcnR1cmJhZ2VucyIsIHkgPSAiWiBzY29yZSIpCmBgYAoKYGBge3J9Ck1BZHJ1Z3MgJT4lIGFycmFuZ2UoZGVzYyh6U2NvcmUpKSAlPiUgaGVhZCgyNSkgJT4lZ2dwbG90KGFlcyhyZW9yZGVyKFBlcnR1cmJhZ2VuLCB6U2NvcmUpLCB6U2NvcmUpKSsKICBnZW9tX2NvbChhZXMoZmlsbCA9IHBWYWx1ZSkpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiZGVlcHNreWJsdWUiLCAKICAgICAgICAgICAgICAgICAgICAgIGhpZ2ggPSAiZGVlcHNreWJsdWU0IikgKyAKICBjb29yZF9mbGlwKCkgKyAKICBsYWJzKHggPSAiQ29ubmVjdGVkIFBlcnR1cmJhZ2VucyIsIHkgPSAiWiBzY29yZSIpCmBgYAoK