library(DESeq2)
library(ggplot2)
#loading my dataset
counts_D3 <- read.delim("counts_D3", header = TRUE, sep = "\t", row.names = 1)
#calling in the metadata
metadata_D3 <- read.csv("metadata_D3.csv", header = TRUE)

#checking the distribution of counts in my dataset
total_counts_per_gene_D3 <- rowSums(counts_D3)
hist(total_counts_per_gene_D3, 
     breaks=100, 
     main="Distribution of Total Counts per Gene", 
     xlab="Total counts across all samples",
     ylab="Number of genes")
summary(total_counts_per_gene_D3)
#ignoring low expressed gene to remove noise & get better results
counts_D3 <- counts_D3[which(rowSums(counts_D3) > 50), ]
#round counts for DESeq2 compatibility
counts_D3 <- round(counts_D3)
#loading DESeq2 for differential expression analysis
library(DESeq2)

#creating DESeq2 object with additive design
dds_D3 <- DESeqDataSetFromMatrix(countData = counts_D3,
                             colData = metadata_D3,        
                             design = ~ CellLine + Treatment)
dds_D3

#running the main DESeq2 analysis
dds_D3 <- DESeq(dds_D3)
dds_D3

res_D3 <- results(dds_D3, contrast = c("Treatment", "Apatinib", "Control"))
summary(res_D3)
plotDispEsts(dds_D3)

pdf("DispersionPlot_D3.pdf", width = 6, height = 5)
plotDispEsts(dds_D3)
dev.off()

png("DispersionPlot_D3.png", width = 2000, height = 1600, res = 300)
plotDispEsts(dds_D3)
dev.off()
#creating variance stabilized data for visualization
vsdata_D3 <- vst(dds_D3, blind = TRUE)

vst_matrix_D3 <- assay(vsdata_D3)

head(vst_matrix_D3[1:5, 1:3])

library(reshape2)

vst_df_D3 <- as.data.frame(vst_matrix_D3)
vst_df_D3$gene_id <- rownames(vst_df_D3)

vst_final_D3 <- melt(vst_df_D3, 
                 id.vars = "gene_id", 
                 variable.name = "sample_id", 
                 value.name = "expression_value")

# Check the result - should have exactly 3 columns
head(vst_final_D3)

#loading ggplot2 for enhanced plotting
library(ggplot2)
pca_plot_D3 <- plotPCA(vsdata_D3, intgroup = c("CellLine", "Treatment"))

ggsave(("D3_PCA.pdf"), pca_plot_D3, width = 6, height = 5)
ggsave(("D3_PCA.png"), pca_plot_D3, width = 6, height = 5, dpi = 300)

Strong Baseline Resistance:

The 90% variance dominated by cell line differences suggests PC9GR cells have undergone major transcriptional reprogramming. This indicates constitutive resistance mechanisms - the resistant cells are fundamentally different

Modest Treatment Response:

Only 6% variance from treatment suggests apatinib causes relatively subtle transcriptional changes compared to the baseline resistance.Both cell lines respond to treatment, but the response is small compared to their inherent differences.

resultsNames(dds_D3)
#clean LFC shrinkage
res_treatment_D3 <- lfcShrink(dds_D3, 
                                 coef = "Treatment_Control_vs_Apatinib", 
                                 type = "apeglm")

res_cellline_D3 <- lfcShrink(dds_D3, 
                                coef = "CellLine_PC9GR_vs_PC9", 
                                type = "apeglm")

summary(res_treatment_D3, alpha = 0.05)
summary(res_cellline_D3, alpha = 0.05)
library(AnnotationDbi)
library(org.Hs.eg.db)

# I'm converting ENSEMBL IDs to gene symbols
gene_symbols_D3 <- mapIds(org.Hs.eg.db,
                         keys = rownames(dds_D3),
                         column = "SYMBOL",
                         keytype = "ENSEMBL",
                         multiVals = "first")
res_annotated_D3 <- res_D3
res_annotated_D3$gene_symbol <- gene_symbols_D3
as.data.frame(res_annotated_D3)

#adding annotations to both main results
res_cellline_annotated_D3 <- res_cellline_D3
res_cellline_annotated_D3$gene_symbol <- gene_symbols_D3

res_treatment_annotated_D3 <- res_treatment_D3
res_treatment_annotated_D3$gene_symbol <- gene_symbols_D3
sig_treatment_D3 <- res_treatment_annotated_D3[which(res_treatment_annotated_D3$padj < 0.05 & abs(res_treatment_annotated_D3$log2FoldChange) > 1), ]
sig_cellline_D3 <- res_cellline_annotated_D3[which(res_cellline_annotated_D3$padj < 0.05 & abs(res_cellline_annotated_D3$log2FoldChange) > 1), ]

nrow(sig_treatment_D3)
[1] 489
nrow(sig_cellline_D3)
[1] 4818
# Get the top genes from each comparison
top20_treatment_D3 <- head(sig_treatment_D3[order(sig_treatment_D3$padj), ], 20)
top20_cellline_D3 <- head(sig_cellline_D3[order(sig_cellline_D3$padj), ], 20)

# Find overlapping genes
overlap_D3 <- intersect(rownames(sig_treatment_D3), rownames(sig_cellline_D3))
length(overlap_D3)
[1] 276

Visualization Plots

#MA Plots
plotMA(res_treatment_D3, ylim=c(-5,5), main="Treatment: Control vs Apatinib")
plotMA(res_cellline_D3, ylim=c(-5,5), main="Cell Line: PC9 vs PC9-GR")

pdf(("MA_res_treatment_D3.pdf"), width = 6, height = 5)
plotMA(res_treatment_D3, ylim=c(-5,5), main="Treatment: Control vs Apatinib")
dev.off()

png(("MA_res_treatment_D3.png"), width = 2000, height = 1600, res = 300)
plotMA(res_treatment_D3, ylim=c(-5,5), main="Treatment: Control vs Apatinib")
dev.off()

pdf(("MA_res_cellline_D3.pdf"), width = 6, height = 5)
plotMA(res_cellline_D3, ylim=c(-5,5), main="Cell Line: PC9 vs PC9-GR")
dev.off()

png(("MA_res_cellline_D3.png"), width = 2000, height = 1600, res = 300)
plotMA(res_cellline_D3, ylim=c(-5,5), main="Cell Line: PC9 vs PC9-GR")
dev.off()

# Volcano plots
library(EnhancedVolcano)
volcano_cellline_D3 <- EnhancedVolcano(res_cellline_annotated_D3, lab = res_cellline_annotated_D3$gene_symbol, 
                x = 'log2FoldChange', y = 'padj',
                title = 'PC9 cells vs PC9-GR cells')

ggsave(("D3_CelllineVolcano.pdf"), volcano_cellline_D3, width = 6, height = 5)
ggsave(("D3_CelllineVolcano.png"), volcano_cellline_D3, width = 6, height = 5, dpi = 300)

volcano_treatment_D3 <- EnhancedVolcano(res_treatment_annotated_D3, lab = res_treatment_annotated_D3$gene_symbol, 
                x = 'log2FoldChange', y = 'padj',
                title = 'Control vs Apatinib')

ggsave(("D3_TreatmentVolcano.pdf"), volcano_treatment_D3, width = 6, height = 5)
ggsave(("D3_TreatmentVolcano.png"), volcano_treatment_D3, width = 6, height = 5, dpi = 300)

# Heatmap of top differentially expressed genes
library(pheatmap)
top_overlap_D3 <- head(order(sig_treatment_D3[overlap_D3,]$padj), 50)
pheatmap::pheatmap(assay(vsdata_D3)[top_overlap_D3,], 
         annotation_col = as.data.frame(colData(dds_D3)[,c("CellLine", "Treatment")]), 
         scale = "row", 
         show_rownames = FALSE,
         main = "Top 50 Differentially Expressed Genes which overlapped",
         filename = "DEGs_D3.png")

In Volcano plots: The resistance genes (red dots in plot 1) are potential targets to overcome resistance The treatment genes (red dots in plot 2) reveal apatinib’s mechanism of action.

#creating enhanced heatmap with gene symbols and values
library(dplyr)
library(ComplexHeatmap)
library(RColorBrewer)
library(circlize)

#preparing top genes for enhanced heatmap 
top_cellline_heatmap_D3 <- res_cellline_annotated_D3[!is.na(res_cellline_annotated_D3$padj) & 
                                                    !is.na(res_cellline_annotated_D3$baseMean) & 
                                                    !is.na(res_cellline_annotated_D3$log2FoldChange) &
                                                    (res_cellline_annotated_D3$padj < 0.05) & 
                                                    (res_cellline_annotated_D3$baseMean > 50) & 
                                                    (abs(res_cellline_annotated_D3$log2FoldChange) > 2),]

top_cellline_heatmap_D3 <- top_cellline_heatmap_D3 %>%
  as.data.frame() %>%
  head(50)  

top_cellline_heatmap_D3 <- top_cellline_heatmap_D3[order(top_cellline_heatmap_D3$log2FoldChange, decreasing = TRUE),]

#getting normalized count data 
mat_D3 <- assay(vsdata_D3)[rownames(top_cellline_heatmap_D3), metadata_D3$Run]
colnames(mat_D3) <- metadata_D3$Run
base_mean_D3 <- rowMeans(mat_D3)
mat_scaled_D3 <- t(apply(mat_D3, 1, scale)) # Z-score normalization
colnames(mat_scaled_D3) <- colnames(mat_D3)

#selecting top and bottom genes
num_keep <- 25
rows_keep_D3 <- c(seq(1:num_keep), seq((nrow(mat_scaled_D3)-num_keep), nrow(mat_scaled_D3)))

# I'm preparing annotation matrices
l2_val_D3 <- as.matrix(top_cellline_heatmap_D3[rows_keep_D3,]$log2FoldChange)
colnames(l2_val_D3) <- "logFC"

mean_D3 <- as.matrix(top_cellline_heatmap_D3[rows_keep_D3,]$baseMean)
colnames(mean_D3) <- "AveExpr"

# I'm setting up color schemes (same as Dataset 2)
col_logFC_D3 <- colorRamp2(c(min(l2_val_D3), 0, max(l2_val_D3)), c("blue", "white", "red")) 
col_AveExpr_D3 <- colorRamp2(c(quantile(mean_D3)[1], quantile(mean_D3)[4]), c("white", "red"))
col_zscore_D3 <- colorRamp2(c(-2, 0, 2), c("#4575b4", "white", "#d73027"))

# I'm creating the main expression heatmap
h1_D3 <- Heatmap(mat_scaled_D3[rows_keep_D3,], 
              cluster_rows = TRUE,
              column_labels = colnames(mat_scaled_D3), 
              name="Z-score",
              col = col_zscore_D3,
              cluster_columns = TRUE,
              show_row_names = FALSE,
              column_names_gp = gpar(fontsize = 9),
              heatmap_legend_param = list(title_gp = gpar(fontsize = 10)))

# I'm creating the log2FC annotation heatmap
h2_D3 <- Heatmap(l2_val_D3, 
              row_labels = top_cellline_heatmap_D3$gene_symbol[rows_keep_D3],
              cluster_rows = FALSE, 
              name="logFC", 
              col = col_logFC_D3,
              width = unit(15, "mm"),
              show_column_names = TRUE,
              row_names_gp = gpar(fontsize = 8),
              column_names_gp = gpar(fontsize = 9),
              cell_fun = function(j, i, x, y, w, h, col) { 
                grid.text(round(l2_val_D3[i, j], 1), x, y, gp = gpar(fontsize = 7))
              })

# I'm creating the average expression annotation heatmap
h3_D3 <- Heatmap(mean_D3, 
              row_labels = top_cellline_heatmap_D3$gene_symbol[rows_keep_D3],
              cluster_rows = FALSE, 
              name = "AveExpr", 
              col = col_AveExpr_D3,
              width = unit(15, "mm"),
              show_row_names = TRUE,
              show_column_names = TRUE,
              column_names_gp = gpar(fontsize = 9),
              row_names_gp = gpar(fontsize = 7),
              cell_fun = function(j, i, x, y, w, h, col) { 
                grid.text(round(mean_D3[i, j], 0), x, y, gp = gpar(fontsize = 7))
              })

# I'm combining all heatmaps (same as Dataset 2)
h_D3 <- h1_D3 + h2_D3 + h3_D3
h_D3

pdf("AnnotatedHeatmap_D3.pdf", width = 10, height = 6)
draw(h_D3)
dev.off()

png("AnnotatedHeatmap_D3.png", width = 3000, height = 2000, res = 300)
draw(h_D3)
dev.off()
# Loading pathway analysis packages
  library(DOSE)
  library(enrichplot)
  library(clusterProfiler)
  
  # separating upregulated and downregulated genes
  sig_genes_up_cellline_D3 <- rownames(sig_cellline_D3)[sig_cellline_D3$log2FoldChange > 1]
  sig_genes_down_cellline_D3 <- rownames(sig_cellline_D3)[sig_cellline_D3$log2FoldChange < -1]
  
  # converting ENSEMBL to ENTREZ for KEGG analysis
  entrez_genes_up_cellline_D3 <- mapIds(org.Hs.eg.db, sig_genes_up_cellline_D3, "ENTREZID", "ENSEMBL")
  entrez_genes_down_cellline_D3 <- mapIds(org.Hs.eg.db, sig_genes_down_cellline_D3, "ENTREZID", "ENSEMBL")
  entrez_genes_up_cellline_D3 <- entrez_genes_up_cellline_D3[!is.na(entrez_genes_up_cellline_D3)]
  entrez_genes_down_cellline_D3 <- entrez_genes_down_cellline_D3[!is.na(entrez_genes_down_cellline_D3)]
  
  # running GO Analysis
  go_up_cellline_D3 <- enrichGO(gene = sig_genes_up_cellline_D3,
                                OrgDb = org.Hs.eg.db,
                                keyType = "ENSEMBL",
                                ont = "ALL",  # BP, CC, MF
                                pAdjustMethod = "BH",
                                pvalueCutoff = 0.05)
  as.data.frame(go_up_cellline_D3)

  go_up_D3 <-plot(barplot(go_up_cellline_D3, showCategory = 15)+labs(title = "Upregulated GO Terms (PC9GR vs PC9)"))
  ggsave("GO_cellline_Upreg_D3.pdf", go_up_D3, width = 7, height = 6)
  ggsave("GO_cellline_Upreg_D3.png", go_up_D3, width = 7, height = 6, dpi = 300)
  
  go_down_cellline_D3 <- enrichGO(gene = sig_genes_down_cellline_D3,
                                  OrgDb = org.Hs.eg.db,
                                  keyType = "ENSEMBL",
                                  ont = "ALL",
                                  pAdjustMethod = "BH",
                                  pvalueCutoff = 0.05)
  as.data.frame(go_down_cellline_D3)
  go_down_D3 <- plot(barplot(go_down_cellline_D3, showCategory = 15)+labs(title = "Downregulated GO Terms (PC9GR vs PC9)"))
  ggsave("GO_cellline_down_D3.pdf", go_down_D3, width = 7, height = 6)
  ggsave("GO_cellline_down_D3.png", go_down_D3, width = 7, height = 6, dpi = 300)
  
  # Running KEGG Pathway Analysis
  kegg_up_cellline_D3 <- enrichKEGG(gene = entrez_genes_up_cellline_D3,
                                    organism = 'hsa',
                                    pvalueCutoff = 0.05,
                                    pAdjustMethod = "BH")
  as.data.frame(kegg_up_cellline_D3)
  kegg_up_D3 <- plot(barplot(kegg_up_cellline_D3, showCategory = 15)+labs(title = "Upregulated KEGG Pathways (PC9GR vs PC9)"))
  ggsave("KEGG_cellline_up_D3.pdf", kegg_up_D3, width = 7, height = 6)
  ggsave("KEGG_cellline_up_D3.png", kegg_up_D3, width = 7, height = 6, dpi = 300)
  
  kegg_down_cellline_D3 <- enrichKEGG(gene = entrez_genes_down_cellline_D3,
                                      organism = 'hsa',
                                      pvalueCutoff = 0.1,
                                      pAdjustMethod = "BH")
  as.data.frame(kegg_down_cellline_D3)
  kegg_down_D3 <- plot(barplot(kegg_down_cellline_D3, showCategory = 15)+labs(title = "Downregulated KEGG Pathways (PC9GR vs PC9)"))
  ggsave("KEGG_cellline_down_D3.pdf", kegg_down_D3, width = 7, height = 6)
  ggsave("KEGG_cellline_down_D3.png", kegg_down_D3, width = 7, height = 6, dpi = 300)
  
# separating upregulated and downregulated genes
  sig_genes_up_treatment_D3 <- rownames(sig_treatment_D3)[sig_treatment_D3$log2FoldChange > 1]
length(sig_genes_up_treatment_D3)
  sig_genes_down_treatment_D3 <- rownames(sig_treatment_D3)[sig_treatment_D3$log2FoldChange < -1]
  
  print(paste("Upregulated:", length(sig_genes_up_treatment_D3)))
print(paste("Downregulated:", length(sig_genes_down_treatment_D3)))
  
  # converting ENSEMBL to ENTREZ for KEGG analysis
  entrez_genes_up_treatment_D3 <- mapIds(org.Hs.eg.db, sig_genes_up_treatment_D3, "ENTREZID", "ENSEMBL")
  entrez_genes_down_treatment_D3 <- mapIds(org.Hs.eg.db, sig_genes_down_treatment_D3, "ENTREZID", "ENSEMBL")
  entrez_genes_up_treatment_D3 <- entrez_genes_up_treatment_D3[!is.na(entrez_genes_up_treatment_D3)]
  entrez_genes_down_treatment_D3 <- entrez_genes_down_treatment_D3[!is.na(entrez_genes_down_treatment_D3)]
  
  # running GO Analysis
  go_up_treatment_D3 <- enrichGO(gene = sig_genes_up_treatment_D3,
                                OrgDb = org.Hs.eg.db,
                                keyType = "ENSEMBL",
                                ont = "ALL",  # BP, CC, MF
                                pAdjustMethod = "BH",
                                pvalueCutoff = 0.1)
  as.data.frame(go_up_treatment_D3)

  go_up_D3 <-plot(barplot(go_up_treatment_D3, showCategory = 15)+labs(title = "Upregulated GO Terms (Control vs Apatinib)"))
  ggsave("GO_treatment_Upreg_D3.pdf", go_uptreatment_D3, width = 7, height = 6)
  ggsave("GO_treatment_Upreg_D3.png", go_uptreatment_D3, width = 7, height = 6, dpi = 300)
  
  go_down_treatment_D3 <- enrichGO(gene = sig_genes_down_treatment_D3,
                                  OrgDb = org.Hs.eg.db,
                                  keyType = "ENSEMBL",
                                  ont = "ALL",
                                  pAdjustMethod = "BH",
                                  pvalueCutoff = 0.05)
  as.data.frame(go_down_treatment_D3)
  top_go_down_treatment_D3 <- go_down_treatment_D3@result[1:10, ]
as.data.frame(top_go_down_treatment_D3)
  
  go_down_D3 <- plot(barplot(go_down_treatment_D3, showCategory = 15)+labs(title = "Downregulated GO Terms (Control vs Apatinib)"))
  ggsave("GO_treatment_down_D3.pdf", go_downtreatment_D3, width = 7, height = 6)
  ggsave("GO_treatment_down_D3.png", go_downtreatment_D3, width = 7, height = 6, dpi = 300)
  
  # Running KEGG Pathway Analysis
  kegg_up_treatment_D3 <- enrichKEGG(gene = entrez_genes_up_treatment_D3,
                                    organism = 'hsa',
                                    pvalueCutoff = 0.1,
                                    pAdjustMethod = "BH")
  as.data.frame(kegg_up_treatment_D3)
  kegg_up_D3 <- plot(barplot(kegg_up_treatment_D3, showCategory = 15)+labs(title = "Upregulated KEGG Pathways (Control vs Apatinib)"))
  ggsave("KEGG_cellline_up_D3.pdf", kegg_up_D3, width = 7, height = 6)
  ggsave("KEGG_cellline_up_D3.png", kegg_up_D3, width = 7, height = 6, dpi = 300)
  
  kegg_down_treatment_D3 <- enrichKEGG(gene = entrez_genes_down_treatment_D3,
                                      organism = 'hsa',
                                      pvalueCutoff = 0.05,
                                      pAdjustMethod = "BH")
  as.data.frame(kegg_down_treatment_D3)
  kegg_down_D3 <- plot(barplot(kegg_down_cellline_D3, showCategory = 15)+labs(title = "Downregulated KEGG Pathways (PC9GR vs PC9)"))
  ggsave("KEGG_cellline_down_D3.pdf", kegg_down_D3, width = 7, height = 6)
  ggsave("KEGG_cellline_down_D3.png", kegg_down_D3, width = 7, height = 6, dpi = 300)
  
library(fgsea)
library(msigdbr)

#preparing ranked gene list for GSEA (cell line comparison)
gene_ranks_cellline_D3 <- res_cellline_D3$log2FoldChange
names(gene_ranks_cellline_D3) <- rownames(res_cellline_D3)
gene_ranks_cellline_D3 <- gene_ranks_cellline_D3[!is.na(gene_ranks_cellline_D3)]
gene_ranks_cellline_D3 <- sort(gene_ranks_cellline_D3, decreasing = TRUE)

#getting Hallmark pathways for GSEA 
hallmark_sets_D3 <- msigdbr(species = "Homo sapiens", category = "H")
hallmark_list_D3 <- split(hallmark_sets_D3$ensembl_gene, hallmark_sets_D3$gs_name)

#running GSEA analysis 
fgsea_results_cellline_D3 <- fgsea(pathways = hallmark_list_D3,
                                  stats = gene_ranks_cellline_D3,
                                  minSize = 15,
                                  maxSize = 500)

#viewing top results (same format as previous datasets)
print("Top GSEA Results (PC9GR vs PC9):")
print(head(fgsea_results_cellline_D3[order(pval), ], 10))

# I'm plotting top 3 most significant pathways from my GSEA results
print("Top 3 GSEA pathways:")
top_pathways_D3 <- head(fgsea_results_cellline_D3[order(pval), ], 3)
print(top_pathways_D3[, c("pathway", "pval", "NES")])

for(i in 1:3) {
  pathway_name <- top_pathways_D3$pathway[i]
  pathways_D3 <- plotEnrichment(hallmark_list_D3[[pathway_name]], gene_ranks_cellline_D3) + 
    labs(title = paste("Pathway", i, ":", pathway_name))
  print(pathways_D3)
  ggsave("Top3_GSEA_D3.pdf", pathways_D3, width = 7, height = 6)
  ggsave("Top3_GSEA_D3.png", pathways_D3, width = 7, height = 6, dpi = 300)
}
# Summary statistics table for D3
summary_stats_D3 <- data.frame(
  Metric = c("Total Samples", "Genes Analyzed", "Significant DEGs - PC9 vs PC9-GR", "Upregulated - PC9 vs PC9-GR", "Downregulated - PC9 vs PC9-GR"),
  Value = c(ncol(counts_D3), 
            nrow(res_D3),
            nrow(sig_cellline_D3),
            length(sig_genes_up_cellline_D3),
            length(sig_genes_down_cellline_D3))
)

summary_stats_D3

# Top genes table
top_genes_table_D3 <- data.frame(
  Gene_Symbol = gene_symbols_D3[rownames(head(sig_cellline_D3[order(sig_cellline_D3$padj),], 20))],
  ENSEMBL_ID = rownames(head(sig_cellline_D3[order(sig_cellline_D3$padj),], 20)),
  Log2FC = round(head(sig_cellline_D3[order(sig_cellline_D3$padj),], 20)$log2FoldChange, 3),
  Padj = format(head(sig_cellline_D3[order(sig_cellline_D3$padj),], 20)$padj, scientific = TRUE, digits = 3),
  Direction = ifelse(head(sig_cellline_D3[order(sig_cellline_D3$padj),], 20)$log2FoldChange > 0, "Up", "Down")
)

print("Top 20 Significant Genes: PC9 vs PC9-GR")
print(top_genes_table_D3)
# Export main results
write.csv(as.data.frame(res_cellline_annotated_D3), "D3_cellline_annotated_results.csv", row.names = TRUE)
write.csv(sig_cellline_D3, "D3_sig_cellline_genes.csv", row.names = TRUE)
write.csv(summary_stats_D3, "D3_summary_statistics.csv", row.names = FALSE)
write.csv(top_genes_table_D3, "D3_top20_genes.csv", row.names = FALSE)

# Export normalized data
write.csv(counts(dds_D3, normalized=TRUE), "D3_normalized_counts.csv", row.names = TRUE)
write.csv(assay(vsdata_D3), "D3_vst_data.csv", row.names = TRUE)

# Export pathway results
if(nrow(go_up_cellline_D3@result) > 0) {
  write.csv(go_up_cellline_D3@result, "D3_GO_upregulated.csv", row.names = FALSE)
}
if(nrow(go_down_cellline_D3@result) > 0) {
  write.csv(go_down_cellline_D3@result, "D3_GO_downregulated.csv", row.names = FALSE)
}
if(nrow(kegg_up_cellline_D3@result) > 0) {
  write.csv(kegg_up_cellline_D3@result, "D3_KEGG_upregulated.csv", row.names = FALSE)
}
if(nrow(kegg_down_cellline_D3@result) > 0) {
  write.csv(kegg_down_cellline_D3@result, "D3_KEGG_downregulated.csv", row.names = FALSE)
}

# Remove the leadingEdge column (which contains lists)
fgsea_results_clean_D3 <- fgsea_results_cellline_D3 %>%
  select(-leadingEdge)

write.csv(fgsea_results_clean_D3, "D3_GSEA_hallmarks.csv", row.names = FALSE)
LS0tDQp0aXRsZTogIkRhdGFzZXQgMyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShERVNlcTIpDQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KYGBge3J9DQojbG9hZGluZyBteSBkYXRhc2V0DQpjb3VudHNfRDMgPC0gcmVhZC5kZWxpbSgiY291bnRzX0QzIiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gMSkNCiNjYWxsaW5nIGluIHRoZSBtZXRhZGF0YQ0KbWV0YWRhdGFfRDMgPC0gcmVhZC5jc3YoIm1ldGFkYXRhX0QzLmNzdiIsIGhlYWRlciA9IFRSVUUpDQoNCiNjaGVja2luZyB0aGUgZGlzdHJpYnV0aW9uIG9mIGNvdW50cyBpbiBteSBkYXRhc2V0DQp0b3RhbF9jb3VudHNfcGVyX2dlbmVfRDMgPC0gcm93U3Vtcyhjb3VudHNfRDMpDQpoaXN0KHRvdGFsX2NvdW50c19wZXJfZ2VuZV9EMywgDQogICAgIGJyZWFrcz0xMDAsIA0KICAgICBtYWluPSJEaXN0cmlidXRpb24gb2YgVG90YWwgQ291bnRzIHBlciBHZW5lIiwgDQogICAgIHhsYWI9IlRvdGFsIGNvdW50cyBhY3Jvc3MgYWxsIHNhbXBsZXMiLA0KICAgICB5bGFiPSJOdW1iZXIgb2YgZ2VuZXMiKQ0Kc3VtbWFyeSh0b3RhbF9jb3VudHNfcGVyX2dlbmVfRDMpDQpgYGANCg0KYGBge3J9DQojaWdub3JpbmcgbG93IGV4cHJlc3NlZCBnZW5lIHRvIHJlbW92ZSBub2lzZSAmIGdldCBiZXR0ZXIgcmVzdWx0cw0KY291bnRzX0QzIDwtIGNvdW50c19EM1t3aGljaChyb3dTdW1zKGNvdW50c19EMykgPiA1MCksIF0NCmBgYA0KDQpgYGB7cn0NCiNyb3VuZCBjb3VudHMgZm9yIERFU2VxMiBjb21wYXRpYmlsaXR5DQpjb3VudHNfRDMgPC0gcm91bmQoY291bnRzX0QzKQ0KI2xvYWRpbmcgREVTZXEyIGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcw0KbGlicmFyeShERVNlcTIpDQoNCiNjcmVhdGluZyBERVNlcTIgb2JqZWN0IHdpdGggYWRkaXRpdmUgZGVzaWduDQpkZHNfRDMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSBjb3VudHNfRDMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBtZXRhZGF0YV9EMywgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSB+IENlbGxMaW5lICsgVHJlYXRtZW50KQ0KZGRzX0QzDQoNCiNydW5uaW5nIHRoZSBtYWluIERFU2VxMiBhbmFseXNpcw0KZGRzX0QzIDwtIERFU2VxKGRkc19EMykNCmRkc19EMw0KDQpyZXNfRDMgPC0gcmVzdWx0cyhkZHNfRDMsIGNvbnRyYXN0ID0gYygiVHJlYXRtZW50IiwgIkFwYXRpbmliIiwgIkNvbnRyb2wiKSkNCnN1bW1hcnkocmVzX0QzKQ0KYGBgDQoNCmBgYHtyfQ0KcGxvdERpc3BFc3RzKGRkc19EMykNCg0KcGRmKCJEaXNwZXJzaW9uUGxvdF9EMy5wZGYiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUpDQpwbG90RGlzcEVzdHMoZGRzX0QzKQ0KZGV2Lm9mZigpDQoNCnBuZygiRGlzcGVyc2lvblBsb3RfRDMucG5nIiwgd2lkdGggPSAyMDAwLCBoZWlnaHQgPSAxNjAwLCByZXMgPSAzMDApDQpwbG90RGlzcEVzdHMoZGRzX0QzKQ0KZGV2Lm9mZigpDQpgYGANCg0KYGBge3J9DQojY3JlYXRpbmcgdmFyaWFuY2Ugc3RhYmlsaXplZCBkYXRhIGZvciB2aXN1YWxpemF0aW9uDQp2c2RhdGFfRDMgPC0gdnN0KGRkc19EMywgYmxpbmQgPSBUUlVFKQ0KDQp2c3RfbWF0cml4X0QzIDwtIGFzc2F5KHZzZGF0YV9EMykNCg0KaGVhZCh2c3RfbWF0cml4X0QzWzE6NSwgMTozXSkNCg0KbGlicmFyeShyZXNoYXBlMikNCg0KdnN0X2RmX0QzIDwtIGFzLmRhdGEuZnJhbWUodnN0X21hdHJpeF9EMykNCnZzdF9kZl9EMyRnZW5lX2lkIDwtIHJvd25hbWVzKHZzdF9kZl9EMykNCg0KdnN0X2ZpbmFsX0QzIDwtIG1lbHQodnN0X2RmX0QzLCANCiAgICAgICAgICAgICAgICAgaWQudmFycyA9ICJnZW5lX2lkIiwgDQogICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAic2FtcGxlX2lkIiwgDQogICAgICAgICAgICAgICAgIHZhbHVlLm5hbWUgPSAiZXhwcmVzc2lvbl92YWx1ZSIpDQoNCiMgQ2hlY2sgdGhlIHJlc3VsdCAtIHNob3VsZCBoYXZlIGV4YWN0bHkgMyBjb2x1bW5zDQpoZWFkKHZzdF9maW5hbF9EMykNCg0KI2xvYWRpbmcgZ2dwbG90MiBmb3IgZW5oYW5jZWQgcGxvdHRpbmcNCmxpYnJhcnkoZ2dwbG90MikNCnBjYV9wbG90X0QzIDwtIHBsb3RQQ0EodnNkYXRhX0QzLCBpbnRncm91cCA9IGMoIkNlbGxMaW5lIiwgIlRyZWF0bWVudCIpKQ0KDQpnZ3NhdmUoKCJEM19QQ0EucGRmIiksIHBjYV9wbG90X0QzLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUpDQpnZ3NhdmUoKCJEM19QQ0EucG5nIiksIHBjYV9wbG90X0QzLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUsIGRwaSA9IDMwMCkNCmBgYA0KU3Ryb25nIEJhc2VsaW5lIFJlc2lzdGFuY2U6DQoNClRoZSA5MCUgdmFyaWFuY2UgZG9taW5hdGVkIGJ5IGNlbGwgbGluZSBkaWZmZXJlbmNlcyBzdWdnZXN0cyBQQzlHUiBjZWxscyBoYXZlIHVuZGVyZ29uZSBtYWpvciB0cmFuc2NyaXB0aW9uYWwgcmVwcm9ncmFtbWluZy4gVGhpcyBpbmRpY2F0ZXMgY29uc3RpdHV0aXZlIHJlc2lzdGFuY2UgbWVjaGFuaXNtcyAtIHRoZSByZXNpc3RhbnQgY2VsbHMgYXJlIGZ1bmRhbWVudGFsbHkgZGlmZmVyZW50DQoNCk1vZGVzdCBUcmVhdG1lbnQgUmVzcG9uc2U6DQoNCk9ubHkgNiUgdmFyaWFuY2UgZnJvbSB0cmVhdG1lbnQgc3VnZ2VzdHMgYXBhdGluaWIgY2F1c2VzIHJlbGF0aXZlbHkgc3VidGxlIHRyYW5zY3JpcHRpb25hbCBjaGFuZ2VzIGNvbXBhcmVkIHRvIHRoZSBiYXNlbGluZSByZXNpc3RhbmNlLkJvdGggY2VsbCBsaW5lcyByZXNwb25kIHRvIHRyZWF0bWVudCwgYnV0IHRoZSByZXNwb25zZSBpcyBzbWFsbCBjb21wYXJlZCB0byB0aGVpciBpbmhlcmVudCBkaWZmZXJlbmNlcy4NCg0KYGBge3J9DQpyZXN1bHRzTmFtZXMoZGRzX0QzKQ0KYGBgDQpgYGB7cn0NCiNjbGVhbiBMRkMgc2hyaW5rYWdlDQpyZXNfdHJlYXRtZW50X0QzIDwtIGxmY1NocmluayhkZHNfRDMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZiA9ICJUcmVhdG1lbnRfQ29udHJvbF92c19BcGF0aW5pYiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJhcGVnbG0iKQ0KDQpyZXNfY2VsbGxpbmVfRDMgPC0gbGZjU2hyaW5rKGRkc19EMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWYgPSAiQ2VsbExpbmVfUEM5R1JfdnNfUEM5IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAiYXBlZ2xtIikNCg0Kc3VtbWFyeShyZXNfdHJlYXRtZW50X0QzLCBhbHBoYSA9IDAuMDUpDQpzdW1tYXJ5KHJlc19jZWxsbGluZV9EMywgYWxwaGEgPSAwLjA1KQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShBbm5vdGF0aW9uRGJpKQ0KbGlicmFyeShvcmcuSHMuZWcuZGIpDQoNCiMgSSdtIGNvbnZlcnRpbmcgRU5TRU1CTCBJRHMgdG8gZ2VuZSBzeW1ib2xzDQpnZW5lX3N5bWJvbHNfRDMgPC0gbWFwSWRzKG9yZy5Icy5lZy5kYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzID0gcm93bmFtZXMoZGRzX0QzKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW4gPSAiU1lNQk9MIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICBrZXl0eXBlID0gIkVOU0VNQkwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpVmFscyA9ICJmaXJzdCIpDQpyZXNfYW5ub3RhdGVkX0QzIDwtIHJlc19EMw0KcmVzX2Fubm90YXRlZF9EMyRnZW5lX3N5bWJvbCA8LSBnZW5lX3N5bWJvbHNfRDMNCmFzLmRhdGEuZnJhbWUocmVzX2Fubm90YXRlZF9EMykNCg0KI2FkZGluZyBhbm5vdGF0aW9ucyB0byBib3RoIG1haW4gcmVzdWx0cw0KcmVzX2NlbGxsaW5lX2Fubm90YXRlZF9EMyA8LSByZXNfY2VsbGxpbmVfRDMNCnJlc19jZWxsbGluZV9hbm5vdGF0ZWRfRDMkZ2VuZV9zeW1ib2wgPC0gZ2VuZV9zeW1ib2xzX0QzDQoNCnJlc190cmVhdG1lbnRfYW5ub3RhdGVkX0QzIDwtIHJlc190cmVhdG1lbnRfRDMNCnJlc190cmVhdG1lbnRfYW5ub3RhdGVkX0QzJGdlbmVfc3ltYm9sIDwtIGdlbmVfc3ltYm9sc19EMw0KDQpgYGANCg0KYGBge3J9DQpzaWdfdHJlYXRtZW50X0QzIDwtIHJlc190cmVhdG1lbnRfYW5ub3RhdGVkX0QzW3doaWNoKHJlc190cmVhdG1lbnRfYW5ub3RhdGVkX0QzJHBhZGogPCAwLjA1ICYgYWJzKHJlc190cmVhdG1lbnRfYW5ub3RhdGVkX0QzJGxvZzJGb2xkQ2hhbmdlKSA+IDEpLCBdDQpzaWdfY2VsbGxpbmVfRDMgPC0gcmVzX2NlbGxsaW5lX2Fubm90YXRlZF9EM1t3aGljaChyZXNfY2VsbGxpbmVfYW5ub3RhdGVkX0QzJHBhZGogPCAwLjA1ICYgYWJzKHJlc19jZWxsbGluZV9hbm5vdGF0ZWRfRDMkbG9nMkZvbGRDaGFuZ2UpID4gMSksIF0NCg0KbnJvdyhzaWdfdHJlYXRtZW50X0QzKQ0KbnJvdyhzaWdfY2VsbGxpbmVfRDMpDQpgYGANCg0KYGBge3J9DQojIEdldCB0aGUgdG9wIGdlbmVzIGZyb20gZWFjaCBjb21wYXJpc29uDQp0b3AyMF90cmVhdG1lbnRfRDMgPC0gaGVhZChzaWdfdHJlYXRtZW50X0QzW29yZGVyKHNpZ190cmVhdG1lbnRfRDMkcGFkaiksIF0sIDIwKQ0KdG9wMjBfY2VsbGxpbmVfRDMgPC0gaGVhZChzaWdfY2VsbGxpbmVfRDNbb3JkZXIoc2lnX2NlbGxsaW5lX0QzJHBhZGopLCBdLCAyMCkNCg0KIyBGaW5kIG92ZXJsYXBwaW5nIGdlbmVzDQpvdmVybGFwX0QzIDwtIGludGVyc2VjdChyb3duYW1lcyhzaWdfdHJlYXRtZW50X0QzKSwgcm93bmFtZXMoc2lnX2NlbGxsaW5lX0QzKSkNCmxlbmd0aChvdmVybGFwX0QzKQ0KYGBgDQotIFRoZXNlIGdlbmVzIGFyZSBib3RoIHN0cm9uZ2x5IGR5c3JlZ3VsYXRlZCBpbiByZXNpc3RhbmNlIChQQzlHUiB2cyBQQzkpDQotIEFORCBzdHJvbmdseSByZXNwb25kIHRvIGFwYXRpbmliIHRyZWF0bWVudA0KLSBUaGlzIHJlcHJlc2VudHMgNTYlIG9mIHRyZWF0bWVudC1yZXNwb25zaXZlIGdlbmVzICgyNzYvNDg5KQ0KDQoNCg0KDQpWaXN1YWxpemF0aW9uIFBsb3RzDQpgYGB7cn0NCiNNQSBQbG90cw0KcGxvdE1BKHJlc190cmVhdG1lbnRfRDMsIHlsaW09YygtNSw1KSwgbWFpbj0iVHJlYXRtZW50OiBDb250cm9sIHZzIEFwYXRpbmliIikNCnBsb3RNQShyZXNfY2VsbGxpbmVfRDMsIHlsaW09YygtNSw1KSwgbWFpbj0iQ2VsbCBMaW5lOiBQQzkgdnMgUEM5LUdSIikNCg0KcGRmKCgiTUFfcmVzX3RyZWF0bWVudF9EMy5wZGYiKSwgd2lkdGggPSA2LCBoZWlnaHQgPSA1KQ0KcGxvdE1BKHJlc190cmVhdG1lbnRfRDMsIHlsaW09YygtNSw1KSwgbWFpbj0iVHJlYXRtZW50OiBDb250cm9sIHZzIEFwYXRpbmliIikNCmRldi5vZmYoKQ0KDQpwbmcoKCJNQV9yZXNfdHJlYXRtZW50X0QzLnBuZyIpLCB3aWR0aCA9IDIwMDAsIGhlaWdodCA9IDE2MDAsIHJlcyA9IDMwMCkNCnBsb3RNQShyZXNfdHJlYXRtZW50X0QzLCB5bGltPWMoLTUsNSksIG1haW49IlRyZWF0bWVudDogQ29udHJvbCB2cyBBcGF0aW5pYiIpDQpkZXYub2ZmKCkNCg0KcGRmKCgiTUFfcmVzX2NlbGxsaW5lX0QzLnBkZiIpLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUpDQpwbG90TUEocmVzX2NlbGxsaW5lX0QzLCB5bGltPWMoLTUsNSksIG1haW49IkNlbGwgTGluZTogUEM5IHZzIFBDOS1HUiIpDQpkZXYub2ZmKCkNCg0KcG5nKCgiTUFfcmVzX2NlbGxsaW5lX0QzLnBuZyIpLCB3aWR0aCA9IDIwMDAsIGhlaWdodCA9IDE2MDAsIHJlcyA9IDMwMCkNCnBsb3RNQShyZXNfY2VsbGxpbmVfRDMsIHlsaW09YygtNSw1KSwgbWFpbj0iQ2VsbCBMaW5lOiBQQzkgdnMgUEM5LUdSIikNCmRldi5vZmYoKQ0KDQojIFZvbGNhbm8gcGxvdHMNCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQ0Kdm9sY2Fub19jZWxsbGluZV9EMyA8LSBFbmhhbmNlZFZvbGNhbm8ocmVzX2NlbGxsaW5lX2Fubm90YXRlZF9EMywgbGFiID0gcmVzX2NlbGxsaW5lX2Fubm90YXRlZF9EMyRnZW5lX3N5bWJvbCwgDQogICAgICAgICAgICAgICAgeCA9ICdsb2cyRm9sZENoYW5nZScsIHkgPSAncGFkaicsDQogICAgICAgICAgICAgICAgdGl0bGUgPSAnUEM5IGNlbGxzIHZzIFBDOS1HUiBjZWxscycpDQoNCmdnc2F2ZSgoIkQzX0NlbGxsaW5lVm9sY2Fuby5wZGYiKSwgdm9sY2Fub19jZWxsbGluZV9EMywgd2lkdGggPSA2LCBoZWlnaHQgPSA1KQ0KZ2dzYXZlKCgiRDNfQ2VsbGxpbmVWb2xjYW5vLnBuZyIpLCB2b2xjYW5vX2NlbGxsaW5lX0QzLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUsIGRwaSA9IDMwMCkNCg0Kdm9sY2Fub190cmVhdG1lbnRfRDMgPC0gRW5oYW5jZWRWb2xjYW5vKHJlc190cmVhdG1lbnRfYW5ub3RhdGVkX0QzLCBsYWIgPSByZXNfdHJlYXRtZW50X2Fubm90YXRlZF9EMyRnZW5lX3N5bWJvbCwgDQogICAgICAgICAgICAgICAgeCA9ICdsb2cyRm9sZENoYW5nZScsIHkgPSAncGFkaicsDQogICAgICAgICAgICAgICAgdGl0bGUgPSAnQ29udHJvbCB2cyBBcGF0aW5pYicpDQoNCmdnc2F2ZSgoIkQzX1RyZWF0bWVudFZvbGNhbm8ucGRmIiksIHZvbGNhbm9fdHJlYXRtZW50X0QzLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUpDQpnZ3NhdmUoKCJEM19UcmVhdG1lbnRWb2xjYW5vLnBuZyIpLCB2b2xjYW5vX3RyZWF0bWVudF9EMywgd2lkdGggPSA2LCBoZWlnaHQgPSA1LCBkcGkgPSAzMDApDQoNCiMgSGVhdG1hcCBvZiB0b3AgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzDQpsaWJyYXJ5KHBoZWF0bWFwKQ0KdG9wX292ZXJsYXBfRDMgPC0gaGVhZChvcmRlcihzaWdfdHJlYXRtZW50X0QzW292ZXJsYXBfRDMsXSRwYWRqKSwgNTApDQpwaGVhdG1hcDo6cGhlYXRtYXAoYXNzYXkodnNkYXRhX0QzKVt0b3Bfb3ZlcmxhcF9EMyxdLCANCiAgICAgICAgIGFubm90YXRpb25fY29sID0gYXMuZGF0YS5mcmFtZShjb2xEYXRhKGRkc19EMylbLGMoIkNlbGxMaW5lIiwgIlRyZWF0bWVudCIpXSksIA0KICAgICAgICAgc2NhbGUgPSAicm93IiwgDQogICAgICAgICBzaG93X3Jvd25hbWVzID0gRkFMU0UsDQogICAgICAgICBtYWluID0gIlRvcCA1MCBEaWZmZXJlbnRpYWxseSBFeHByZXNzZWQgR2VuZXMgd2hpY2ggb3ZlcmxhcHBlZCIsDQogICAgICAgICBmaWxlbmFtZSA9ICJERUdzX0QzLnBuZyIpDQoNCmBgYA0KSW4gVm9sY2FubyBwbG90czogVGhlIHJlc2lzdGFuY2UgZ2VuZXMgKHJlZCBkb3RzIGluIHBsb3QgMSkgYXJlIHBvdGVudGlhbCB0YXJnZXRzIHRvIG92ZXJjb21lIHJlc2lzdGFuY2UNClRoZSB0cmVhdG1lbnQgZ2VuZXMgKHJlZCBkb3RzIGluIHBsb3QgMikgcmV2ZWFsIGFwYXRpbmliJ3MgbWVjaGFuaXNtIG9mIGFjdGlvbi4NCg0KYGBge3J9DQojY3JlYXRpbmcgZW5oYW5jZWQgaGVhdG1hcCB3aXRoIGdlbmUgc3ltYm9scyBhbmQgdmFsdWVzDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShDb21wbGV4SGVhdG1hcCkNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShjaXJjbGl6ZSkNCg0KI3ByZXBhcmluZyB0b3AgZ2VuZXMgZm9yIGVuaGFuY2VkIGhlYXRtYXAgDQp0b3BfY2VsbGxpbmVfaGVhdG1hcF9EMyA8LSByZXNfY2VsbGxpbmVfYW5ub3RhdGVkX0QzWyFpcy5uYShyZXNfY2VsbGxpbmVfYW5ub3RhdGVkX0QzJHBhZGopICYgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKHJlc19jZWxsbGluZV9hbm5vdGF0ZWRfRDMkYmFzZU1lYW4pICYgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKHJlc19jZWxsbGluZV9hbm5vdGF0ZWRfRDMkbG9nMkZvbGRDaGFuZ2UpICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVzX2NlbGxsaW5lX2Fubm90YXRlZF9EMyRwYWRqIDwgMC4wNSkgJiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVzX2NlbGxsaW5lX2Fubm90YXRlZF9EMyRiYXNlTWVhbiA+IDUwKSAmIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChhYnMocmVzX2NlbGxsaW5lX2Fubm90YXRlZF9EMyRsb2cyRm9sZENoYW5nZSkgPiAyKSxdDQoNCnRvcF9jZWxsbGluZV9oZWF0bWFwX0QzIDwtIHRvcF9jZWxsbGluZV9oZWF0bWFwX0QzICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkgJT4lDQogIGhlYWQoNTApICANCg0KdG9wX2NlbGxsaW5lX2hlYXRtYXBfRDMgPC0gdG9wX2NlbGxsaW5lX2hlYXRtYXBfRDNbb3JkZXIodG9wX2NlbGxsaW5lX2hlYXRtYXBfRDMkbG9nMkZvbGRDaGFuZ2UsIGRlY3JlYXNpbmcgPSBUUlVFKSxdDQoNCiNnZXR0aW5nIG5vcm1hbGl6ZWQgY291bnQgZGF0YSANCm1hdF9EMyA8LSBhc3NheSh2c2RhdGFfRDMpW3Jvd25hbWVzKHRvcF9jZWxsbGluZV9oZWF0bWFwX0QzKSwgbWV0YWRhdGFfRDMkUnVuXQ0KY29sbmFtZXMobWF0X0QzKSA8LSBtZXRhZGF0YV9EMyRSdW4NCmJhc2VfbWVhbl9EMyA8LSByb3dNZWFucyhtYXRfRDMpDQptYXRfc2NhbGVkX0QzIDwtIHQoYXBwbHkobWF0X0QzLCAxLCBzY2FsZSkpICMgWi1zY29yZSBub3JtYWxpemF0aW9uDQpjb2xuYW1lcyhtYXRfc2NhbGVkX0QzKSA8LSBjb2xuYW1lcyhtYXRfRDMpDQoNCiNzZWxlY3RpbmcgdG9wIGFuZCBib3R0b20gZ2VuZXMNCm51bV9rZWVwIDwtIDI1DQpyb3dzX2tlZXBfRDMgPC0gYyhzZXEoMTpudW1fa2VlcCksIHNlcSgobnJvdyhtYXRfc2NhbGVkX0QzKS1udW1fa2VlcCksIG5yb3cobWF0X3NjYWxlZF9EMykpKQ0KDQojIEknbSBwcmVwYXJpbmcgYW5ub3RhdGlvbiBtYXRyaWNlcw0KbDJfdmFsX0QzIDwtIGFzLm1hdHJpeCh0b3BfY2VsbGxpbmVfaGVhdG1hcF9EM1tyb3dzX2tlZXBfRDMsXSRsb2cyRm9sZENoYW5nZSkNCmNvbG5hbWVzKGwyX3ZhbF9EMykgPC0gImxvZ0ZDIg0KDQptZWFuX0QzIDwtIGFzLm1hdHJpeCh0b3BfY2VsbGxpbmVfaGVhdG1hcF9EM1tyb3dzX2tlZXBfRDMsXSRiYXNlTWVhbikNCmNvbG5hbWVzKG1lYW5fRDMpIDwtICJBdmVFeHByIg0KDQojIEknbSBzZXR0aW5nIHVwIGNvbG9yIHNjaGVtZXMgKHNhbWUgYXMgRGF0YXNldCAyKQ0KY29sX2xvZ0ZDX0QzIDwtIGNvbG9yUmFtcDIoYyhtaW4obDJfdmFsX0QzKSwgMCwgbWF4KGwyX3ZhbF9EMykpLCBjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKSANCmNvbF9BdmVFeHByX0QzIDwtIGNvbG9yUmFtcDIoYyhxdWFudGlsZShtZWFuX0QzKVsxXSwgcXVhbnRpbGUobWVhbl9EMylbNF0pLCBjKCJ3aGl0ZSIsICJyZWQiKSkNCmNvbF96c2NvcmVfRDMgPC0gY29sb3JSYW1wMihjKC0yLCAwLCAyKSwgYygiIzQ1NzViNCIsICJ3aGl0ZSIsICIjZDczMDI3IikpDQoNCiMgSSdtIGNyZWF0aW5nIHRoZSBtYWluIGV4cHJlc3Npb24gaGVhdG1hcA0KaDFfRDMgPC0gSGVhdG1hcChtYXRfc2NhbGVkX0QzW3Jvd3Nfa2VlcF9EMyxdLCANCiAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwNCiAgICAgICAgICAgICAgY29sdW1uX2xhYmVscyA9IGNvbG5hbWVzKG1hdF9zY2FsZWRfRDMpLCANCiAgICAgICAgICAgICAgbmFtZT0iWi1zY29yZSIsDQogICAgICAgICAgICAgIGNvbCA9IGNvbF96c2NvcmVfRDMsDQogICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucyA9IFRSVUUsDQogICAgICAgICAgICAgIHNob3dfcm93X25hbWVzID0gRkFMU0UsDQogICAgICAgICAgICAgIGNvbHVtbl9uYW1lc19ncCA9IGdwYXIoZm9udHNpemUgPSA5KSwNCiAgICAgICAgICAgICAgaGVhdG1hcF9sZWdlbmRfcGFyYW0gPSBsaXN0KHRpdGxlX2dwID0gZ3Bhcihmb250c2l6ZSA9IDEwKSkpDQoNCiMgSSdtIGNyZWF0aW5nIHRoZSBsb2cyRkMgYW5ub3RhdGlvbiBoZWF0bWFwDQpoMl9EMyA8LSBIZWF0bWFwKGwyX3ZhbF9EMywgDQogICAgICAgICAgICAgIHJvd19sYWJlbHMgPSB0b3BfY2VsbGxpbmVfaGVhdG1hcF9EMyRnZW5lX3N5bWJvbFtyb3dzX2tlZXBfRDNdLA0KICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgDQogICAgICAgICAgICAgIG5hbWU9ImxvZ0ZDIiwgDQogICAgICAgICAgICAgIGNvbCA9IGNvbF9sb2dGQ19EMywNCiAgICAgICAgICAgICAgd2lkdGggPSB1bml0KDE1LCAibW0iKSwNCiAgICAgICAgICAgICAgc2hvd19jb2x1bW5fbmFtZXMgPSBUUlVFLA0KICAgICAgICAgICAgICByb3dfbmFtZXNfZ3AgPSBncGFyKGZvbnRzaXplID0gOCksDQogICAgICAgICAgICAgIGNvbHVtbl9uYW1lc19ncCA9IGdwYXIoZm9udHNpemUgPSA5KSwNCiAgICAgICAgICAgICAgY2VsbF9mdW4gPSBmdW5jdGlvbihqLCBpLCB4LCB5LCB3LCBoLCBjb2wpIHsgDQogICAgICAgICAgICAgICAgZ3JpZC50ZXh0KHJvdW5kKGwyX3ZhbF9EM1tpLCBqXSwgMSksIHgsIHksIGdwID0gZ3Bhcihmb250c2l6ZSA9IDcpKQ0KICAgICAgICAgICAgICB9KQ0KDQojIEknbSBjcmVhdGluZyB0aGUgYXZlcmFnZSBleHByZXNzaW9uIGFubm90YXRpb24gaGVhdG1hcA0KaDNfRDMgPC0gSGVhdG1hcChtZWFuX0QzLCANCiAgICAgICAgICAgICAgcm93X2xhYmVscyA9IHRvcF9jZWxsbGluZV9oZWF0bWFwX0QzJGdlbmVfc3ltYm9sW3Jvd3Nfa2VlcF9EM10sDQogICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCANCiAgICAgICAgICAgICAgbmFtZSA9ICJBdmVFeHByIiwgDQogICAgICAgICAgICAgIGNvbCA9IGNvbF9BdmVFeHByX0QzLA0KICAgICAgICAgICAgICB3aWR0aCA9IHVuaXQoMTUsICJtbSIpLA0KICAgICAgICAgICAgICBzaG93X3Jvd19uYW1lcyA9IFRSVUUsDQogICAgICAgICAgICAgIHNob3dfY29sdW1uX25hbWVzID0gVFJVRSwNCiAgICAgICAgICAgICAgY29sdW1uX25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDkpLA0KICAgICAgICAgICAgICByb3dfbmFtZXNfZ3AgPSBncGFyKGZvbnRzaXplID0gNyksDQogICAgICAgICAgICAgIGNlbGxfZnVuID0gZnVuY3Rpb24oaiwgaSwgeCwgeSwgdywgaCwgY29sKSB7IA0KICAgICAgICAgICAgICAgIGdyaWQudGV4dChyb3VuZChtZWFuX0QzW2ksIGpdLCAwKSwgeCwgeSwgZ3AgPSBncGFyKGZvbnRzaXplID0gNykpDQogICAgICAgICAgICAgIH0pDQoNCiMgSSdtIGNvbWJpbmluZyBhbGwgaGVhdG1hcHMgKHNhbWUgYXMgRGF0YXNldCAyKQ0KaF9EMyA8LSBoMV9EMyArIGgyX0QzICsgaDNfRDMNCmhfRDMNCg0KcGRmKCJBbm5vdGF0ZWRIZWF0bWFwX0QzLnBkZiIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDYpDQpkcmF3KGhfRDMpDQpkZXYub2ZmKCkNCg0KcG5nKCJBbm5vdGF0ZWRIZWF0bWFwX0QzLnBuZyIsIHdpZHRoID0gMzAwMCwgaGVpZ2h0ID0gMjAwMCwgcmVzID0gMzAwKQ0KZHJhdyhoX0QzKQ0KZGV2Lm9mZigpDQoNCmBgYA0KDQpgYGB7cn0NCiMgTG9hZGluZyBwYXRod2F5IGFuYWx5c2lzIHBhY2thZ2VzDQogIGxpYnJhcnkoRE9TRSkNCiAgbGlicmFyeShlbnJpY2hwbG90KQ0KICBsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikNCiAgDQogICMgc2VwYXJhdGluZyB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcw0KICBzaWdfZ2VuZXNfdXBfY2VsbGxpbmVfRDMgPC0gcm93bmFtZXMoc2lnX2NlbGxsaW5lX0QzKVtzaWdfY2VsbGxpbmVfRDMkbG9nMkZvbGRDaGFuZ2UgPiAxXQ0KICBzaWdfZ2VuZXNfZG93bl9jZWxsbGluZV9EMyA8LSByb3duYW1lcyhzaWdfY2VsbGxpbmVfRDMpW3NpZ19jZWxsbGluZV9EMyRsb2cyRm9sZENoYW5nZSA8IC0xXQ0KICANCiAgIyBjb252ZXJ0aW5nIEVOU0VNQkwgdG8gRU5UUkVaIGZvciBLRUdHIGFuYWx5c2lzDQogIGVudHJlel9nZW5lc191cF9jZWxsbGluZV9EMyA8LSBtYXBJZHMob3JnLkhzLmVnLmRiLCBzaWdfZ2VuZXNfdXBfY2VsbGxpbmVfRDMsICJFTlRSRVpJRCIsICJFTlNFTUJMIikNCiAgZW50cmV6X2dlbmVzX2Rvd25fY2VsbGxpbmVfRDMgPC0gbWFwSWRzKG9yZy5Icy5lZy5kYiwgc2lnX2dlbmVzX2Rvd25fY2VsbGxpbmVfRDMsICJFTlRSRVpJRCIsICJFTlNFTUJMIikNCiAgZW50cmV6X2dlbmVzX3VwX2NlbGxsaW5lX0QzIDwtIGVudHJlel9nZW5lc191cF9jZWxsbGluZV9EM1shaXMubmEoZW50cmV6X2dlbmVzX3VwX2NlbGxsaW5lX0QzKV0NCiAgZW50cmV6X2dlbmVzX2Rvd25fY2VsbGxpbmVfRDMgPC0gZW50cmV6X2dlbmVzX2Rvd25fY2VsbGxpbmVfRDNbIWlzLm5hKGVudHJlel9nZW5lc19kb3duX2NlbGxsaW5lX0QzKV0NCiAgDQogICMgcnVubmluZyBHTyBBbmFseXNpcw0KICBnb191cF9jZWxsbGluZV9EMyA8LSBlbnJpY2hHTyhnZW5lID0gc2lnX2dlbmVzX3VwX2NlbGxsaW5lX0QzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJFTlNFTUJMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkFMTCIsICAjIEJQLCBDQywgTUYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpDQogIGFzLmRhdGEuZnJhbWUoZ29fdXBfY2VsbGxpbmVfRDMpDQoNCiAgZ29fdXBfRDMgPC1wbG90KGJhcnBsb3QoZ29fdXBfY2VsbGxpbmVfRDMsIHNob3dDYXRlZ29yeSA9IDE1KStsYWJzKHRpdGxlID0gIlVwcmVndWxhdGVkIEdPIFRlcm1zIChQQzlHUiB2cyBQQzkpIikpDQogIGdnc2F2ZSgiR09fY2VsbGxpbmVfVXByZWdfRDMucGRmIiwgZ29fdXBfRDMsIHdpZHRoID0gNywgaGVpZ2h0ID0gNikNCiAgZ2dzYXZlKCJHT19jZWxsbGluZV9VcHJlZ19EMy5wbmciLCBnb191cF9EMywgd2lkdGggPSA3LCBoZWlnaHQgPSA2LCBkcGkgPSAzMDApDQogIA0KICBnb19kb3duX2NlbGxsaW5lX0QzIDwtIGVucmljaEdPKGdlbmUgPSBzaWdfZ2VuZXNfZG93bl9jZWxsbGluZV9EMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIkVOU0VNQkwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJBTEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpDQogIGFzLmRhdGEuZnJhbWUoZ29fZG93bl9jZWxsbGluZV9EMykNCiAgZ29fZG93bl9EMyA8LSBwbG90KGJhcnBsb3QoZ29fZG93bl9jZWxsbGluZV9EMywgc2hvd0NhdGVnb3J5ID0gMTUpK2xhYnModGl0bGUgPSAiRG93bnJlZ3VsYXRlZCBHTyBUZXJtcyAoUEM5R1IgdnMgUEM5KSIpKQ0KICBnZ3NhdmUoIkdPX2NlbGxsaW5lX2Rvd25fRDMucGRmIiwgZ29fZG93bl9EMywgd2lkdGggPSA3LCBoZWlnaHQgPSA2KQ0KICBnZ3NhdmUoIkdPX2NlbGxsaW5lX2Rvd25fRDMucG5nIiwgZ29fZG93bl9EMywgd2lkdGggPSA3LCBoZWlnaHQgPSA2LCBkcGkgPSAzMDApDQogIA0KICAjIFJ1bm5pbmcgS0VHRyBQYXRod2F5IEFuYWx5c2lzDQogIGtlZ2dfdXBfY2VsbGxpbmVfRDMgPC0gZW5yaWNoS0VHRyhnZW5lID0gZW50cmV6X2dlbmVzX3VwX2NlbGxsaW5lX0QzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAnaHNhJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIikNCiAgYXMuZGF0YS5mcmFtZShrZWdnX3VwX2NlbGxsaW5lX0QzKQ0KICBrZWdnX3VwX0QzIDwtIHBsb3QoYmFycGxvdChrZWdnX3VwX2NlbGxsaW5lX0QzLCBzaG93Q2F0ZWdvcnkgPSAxNSkrbGFicyh0aXRsZSA9ICJVcHJlZ3VsYXRlZCBLRUdHIFBhdGh3YXlzIChQQzlHUiB2cyBQQzkpIikpDQogIGdnc2F2ZSgiS0VHR19jZWxsbGluZV91cF9EMy5wZGYiLCBrZWdnX3VwX0QzLCB3aWR0aCA9IDcsIGhlaWdodCA9IDYpDQogIGdnc2F2ZSgiS0VHR19jZWxsbGluZV91cF9EMy5wbmciLCBrZWdnX3VwX0QzLCB3aWR0aCA9IDcsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCiAgDQogIGtlZ2dfZG93bl9jZWxsbGluZV9EMyA8LSBlbnJpY2hLRUdHKGdlbmUgPSBlbnRyZXpfZ2VuZXNfZG93bl9jZWxsbGluZV9EMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAnaHNhJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIikNCiAgYXMuZGF0YS5mcmFtZShrZWdnX2Rvd25fY2VsbGxpbmVfRDMpDQogIGtlZ2dfZG93bl9EMyA8LSBwbG90KGJhcnBsb3Qoa2VnZ19kb3duX2NlbGxsaW5lX0QzLCBzaG93Q2F0ZWdvcnkgPSAxNSkrbGFicyh0aXRsZSA9ICJEb3ducmVndWxhdGVkIEtFR0cgUGF0aHdheXMgKFBDOUdSIHZzIFBDOSkiKSkNCiAgZ2dzYXZlKCJLRUdHX2NlbGxsaW5lX2Rvd25fRDMucGRmIiwga2VnZ19kb3duX0QzLCB3aWR0aCA9IDcsIGhlaWdodCA9IDYpDQogIGdnc2F2ZSgiS0VHR19jZWxsbGluZV9kb3duX0QzLnBuZyIsIGtlZ2dfZG93bl9EMywgd2lkdGggPSA3LCBoZWlnaHQgPSA2LCBkcGkgPSAzMDApDQogIA0KYGBgDQoNCmBgYHtyfQ0KIyBzZXBhcmF0aW5nIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzDQogIHNpZ19nZW5lc191cF90cmVhdG1lbnRfRDMgPC0gcm93bmFtZXMoc2lnX3RyZWF0bWVudF9EMylbc2lnX3RyZWF0bWVudF9EMyRsb2cyRm9sZENoYW5nZSA+IDFdDQpsZW5ndGgoc2lnX2dlbmVzX3VwX3RyZWF0bWVudF9EMykNCiAgc2lnX2dlbmVzX2Rvd25fdHJlYXRtZW50X0QzIDwtIHJvd25hbWVzKHNpZ190cmVhdG1lbnRfRDMpW3NpZ190cmVhdG1lbnRfRDMkbG9nMkZvbGRDaGFuZ2UgPCAtMV0NCiAgDQogIHByaW50KHBhc3RlKCJVcHJlZ3VsYXRlZDoiLCBsZW5ndGgoc2lnX2dlbmVzX3VwX3RyZWF0bWVudF9EMykpKQ0KcHJpbnQocGFzdGUoIkRvd25yZWd1bGF0ZWQ6IiwgbGVuZ3RoKHNpZ19nZW5lc19kb3duX3RyZWF0bWVudF9EMykpKQ0KICANCiAgIyBjb252ZXJ0aW5nIEVOU0VNQkwgdG8gRU5UUkVaIGZvciBLRUdHIGFuYWx5c2lzDQogIGVudHJlel9nZW5lc191cF90cmVhdG1lbnRfRDMgPC0gbWFwSWRzKG9yZy5Icy5lZy5kYiwgc2lnX2dlbmVzX3VwX3RyZWF0bWVudF9EMywgIkVOVFJFWklEIiwgIkVOU0VNQkwiKQ0KICBlbnRyZXpfZ2VuZXNfZG93bl90cmVhdG1lbnRfRDMgPC0gbWFwSWRzKG9yZy5Icy5lZy5kYiwgc2lnX2dlbmVzX2Rvd25fdHJlYXRtZW50X0QzLCAiRU5UUkVaSUQiLCAiRU5TRU1CTCIpDQogIGVudHJlel9nZW5lc191cF90cmVhdG1lbnRfRDMgPC0gZW50cmV6X2dlbmVzX3VwX3RyZWF0bWVudF9EM1shaXMubmEoZW50cmV6X2dlbmVzX3VwX3RyZWF0bWVudF9EMyldDQogIGVudHJlel9nZW5lc19kb3duX3RyZWF0bWVudF9EMyA8LSBlbnRyZXpfZ2VuZXNfZG93bl90cmVhdG1lbnRfRDNbIWlzLm5hKGVudHJlel9nZW5lc19kb3duX3RyZWF0bWVudF9EMyldDQogIA0KICAjIHJ1bm5pbmcgR08gQW5hbHlzaXMNCiAgZ29fdXBfdHJlYXRtZW50X0QzIDwtIGVucmljaEdPKGdlbmUgPSBzaWdfZ2VuZXNfdXBfdHJlYXRtZW50X0QzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJFTlNFTUJMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkFMTCIsICAjIEJQLCBDQywgTUYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMSkNCiAgYXMuZGF0YS5mcmFtZShnb191cF90cmVhdG1lbnRfRDMpDQoNCiAgZ29fdXBfRDMgPC1wbG90KGJhcnBsb3QoZ29fdXBfdHJlYXRtZW50X0QzLCBzaG93Q2F0ZWdvcnkgPSAxNSkrbGFicyh0aXRsZSA9ICJVcHJlZ3VsYXRlZCBHTyBUZXJtcyAoQ29udHJvbCB2cyBBcGF0aW5pYikiKSkNCiAgZ2dzYXZlKCJHT190cmVhdG1lbnRfVXByZWdfRDMucGRmIiwgZ29fdXB0cmVhdG1lbnRfRDMsIHdpZHRoID0gNywgaGVpZ2h0ID0gNikNCiAgZ2dzYXZlKCJHT190cmVhdG1lbnRfVXByZWdfRDMucG5nIiwgZ29fdXB0cmVhdG1lbnRfRDMsIHdpZHRoID0gNywgaGVpZ2h0ID0gNiwgZHBpID0gMzAwKQ0KICANCiAgZ29fZG93bl90cmVhdG1lbnRfRDMgPC0gZW5yaWNoR08oZ2VuZSA9IHNpZ19nZW5lc19kb3duX3RyZWF0bWVudF9EMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIkVOU0VNQkwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJBTEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpDQogIGFzLmRhdGEuZnJhbWUoZ29fZG93bl90cmVhdG1lbnRfRDMpDQogIHRvcF9nb19kb3duX3RyZWF0bWVudF9EMyA8LSBnb19kb3duX3RyZWF0bWVudF9EM0ByZXN1bHRbMToxMCwgXQ0KYXMuZGF0YS5mcmFtZSh0b3BfZ29fZG93bl90cmVhdG1lbnRfRDMpDQogIA0KICBnb19kb3duX0QzIDwtIHBsb3QoYmFycGxvdChnb19kb3duX3RyZWF0bWVudF9EMywgc2hvd0NhdGVnb3J5ID0gMTUpK2xhYnModGl0bGUgPSAiRG93bnJlZ3VsYXRlZCBHTyBUZXJtcyAoQ29udHJvbCB2cyBBcGF0aW5pYikiKSkNCiAgZ2dzYXZlKCJHT190cmVhdG1lbnRfZG93bl9EMy5wZGYiLCBnb19kb3dudHJlYXRtZW50X0QzLCB3aWR0aCA9IDcsIGhlaWdodCA9IDYpDQogIGdnc2F2ZSgiR09fdHJlYXRtZW50X2Rvd25fRDMucG5nIiwgZ29fZG93bnRyZWF0bWVudF9EMywgd2lkdGggPSA3LCBoZWlnaHQgPSA2LCBkcGkgPSAzMDApDQogIA0KICAjIFJ1bm5pbmcgS0VHRyBQYXRod2F5IEFuYWx5c2lzDQogIGtlZ2dfdXBfdHJlYXRtZW50X0QzIDwtIGVucmljaEtFR0coZ2VuZSA9IGVudHJlel9nZW5lc191cF90cmVhdG1lbnRfRDMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICdoc2EnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIpDQogIGFzLmRhdGEuZnJhbWUoa2VnZ191cF90cmVhdG1lbnRfRDMpDQogIGtlZ2dfdXBfRDMgPC0gcGxvdChiYXJwbG90KGtlZ2dfdXBfdHJlYXRtZW50X0QzLCBzaG93Q2F0ZWdvcnkgPSAxNSkrbGFicyh0aXRsZSA9ICJVcHJlZ3VsYXRlZCBLRUdHIFBhdGh3YXlzIChDb250cm9sIHZzIEFwYXRpbmliKSIpKQ0KICBnZ3NhdmUoIktFR0dfY2VsbGxpbmVfdXBfRDMucGRmIiwga2VnZ191cF9EMywgd2lkdGggPSA3LCBoZWlnaHQgPSA2KQ0KICBnZ3NhdmUoIktFR0dfY2VsbGxpbmVfdXBfRDMucG5nIiwga2VnZ191cF9EMywgd2lkdGggPSA3LCBoZWlnaHQgPSA2LCBkcGkgPSAzMDApDQogIA0KICBrZWdnX2Rvd25fdHJlYXRtZW50X0QzIDwtIGVucmljaEtFR0coZ2VuZSA9IGVudHJlel9nZW5lc19kb3duX3RyZWF0bWVudF9EMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAnaHNhJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIpDQogIGFzLmRhdGEuZnJhbWUoa2VnZ19kb3duX3RyZWF0bWVudF9EMykNCiAga2VnZ19kb3duX0QzIDwtIHBsb3QoYmFycGxvdChrZWdnX2Rvd25fY2VsbGxpbmVfRDMsIHNob3dDYXRlZ29yeSA9IDE1KStsYWJzKHRpdGxlID0gIkRvd25yZWd1bGF0ZWQgS0VHRyBQYXRod2F5cyAoUEM5R1IgdnMgUEM5KSIpKQ0KICBnZ3NhdmUoIktFR0dfY2VsbGxpbmVfZG93bl9EMy5wZGYiLCBrZWdnX2Rvd25fRDMsIHdpZHRoID0gNywgaGVpZ2h0ID0gNikNCiAgZ2dzYXZlKCJLRUdHX2NlbGxsaW5lX2Rvd25fRDMucG5nIiwga2VnZ19kb3duX0QzLCB3aWR0aCA9IDcsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCiAgDQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkoZmdzZWEpDQpsaWJyYXJ5KG1zaWdkYnIpDQoNCiNwcmVwYXJpbmcgcmFua2VkIGdlbmUgbGlzdCBmb3IgR1NFQSAoY2VsbCBsaW5lIGNvbXBhcmlzb24pDQpnZW5lX3JhbmtzX2NlbGxsaW5lX0QzIDwtIHJlc19jZWxsbGluZV9EMyRsb2cyRm9sZENoYW5nZQ0KbmFtZXMoZ2VuZV9yYW5rc19jZWxsbGluZV9EMykgPC0gcm93bmFtZXMocmVzX2NlbGxsaW5lX0QzKQ0KZ2VuZV9yYW5rc19jZWxsbGluZV9EMyA8LSBnZW5lX3JhbmtzX2NlbGxsaW5lX0QzWyFpcy5uYShnZW5lX3JhbmtzX2NlbGxsaW5lX0QzKV0NCmdlbmVfcmFua3NfY2VsbGxpbmVfRDMgPC0gc29ydChnZW5lX3JhbmtzX2NlbGxsaW5lX0QzLCBkZWNyZWFzaW5nID0gVFJVRSkNCg0KI2dldHRpbmcgSGFsbG1hcmsgcGF0aHdheXMgZm9yIEdTRUEgDQpoYWxsbWFya19zZXRzX0QzIDwtIG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiLCBjYXRlZ29yeSA9ICJIIikNCmhhbGxtYXJrX2xpc3RfRDMgPC0gc3BsaXQoaGFsbG1hcmtfc2V0c19EMyRlbnNlbWJsX2dlbmUsIGhhbGxtYXJrX3NldHNfRDMkZ3NfbmFtZSkNCg0KI3J1bm5pbmcgR1NFQSBhbmFseXNpcyANCmZnc2VhX3Jlc3VsdHNfY2VsbGxpbmVfRDMgPC0gZmdzZWEocGF0aHdheXMgPSBoYWxsbWFya19saXN0X0QzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRzID0gZ2VuZV9yYW5rc19jZWxsbGluZV9EMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5TaXplID0gMTUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4U2l6ZSA9IDUwMCkNCg0KI3ZpZXdpbmcgdG9wIHJlc3VsdHMgKHNhbWUgZm9ybWF0IGFzIHByZXZpb3VzIGRhdGFzZXRzKQ0KcHJpbnQoIlRvcCBHU0VBIFJlc3VsdHMgKFBDOUdSIHZzIFBDOSk6IikNCnByaW50KGhlYWQoZmdzZWFfcmVzdWx0c19jZWxsbGluZV9EM1tvcmRlcihwdmFsKSwgXSwgMTApKQ0KDQojIEknbSBwbG90dGluZyB0b3AgMyBtb3N0IHNpZ25pZmljYW50IHBhdGh3YXlzIGZyb20gbXkgR1NFQSByZXN1bHRzDQpwcmludCgiVG9wIDMgR1NFQSBwYXRod2F5czoiKQ0KdG9wX3BhdGh3YXlzX0QzIDwtIGhlYWQoZmdzZWFfcmVzdWx0c19jZWxsbGluZV9EM1tvcmRlcihwdmFsKSwgXSwgMykNCnByaW50KHRvcF9wYXRod2F5c19EM1ssIGMoInBhdGh3YXkiLCAicHZhbCIsICJORVMiKV0pDQoNCmZvcihpIGluIDE6Mykgew0KICBwYXRod2F5X25hbWUgPC0gdG9wX3BhdGh3YXlzX0QzJHBhdGh3YXlbaV0NCiAgcGF0aHdheXNfRDMgPC0gcGxvdEVucmljaG1lbnQoaGFsbG1hcmtfbGlzdF9EM1tbcGF0aHdheV9uYW1lXV0sIGdlbmVfcmFua3NfY2VsbGxpbmVfRDMpICsgDQogICAgbGFicyh0aXRsZSA9IHBhc3RlKCJQYXRod2F5IiwgaSwgIjoiLCBwYXRod2F5X25hbWUpKQ0KICBwcmludChwYXRod2F5c19EMykNCiAgZ2dzYXZlKCJUb3AzX0dTRUFfRDMucGRmIiwgcGF0aHdheXNfRDMsIHdpZHRoID0gNywgaGVpZ2h0ID0gNikNCiAgZ2dzYXZlKCJUb3AzX0dTRUFfRDMucG5nIiwgcGF0aHdheXNfRDMsIHdpZHRoID0gNywgaGVpZ2h0ID0gNiwgZHBpID0gMzAwKQ0KfQ0KYGBgDQoNCg0KYGBge3J9DQojIFN1bW1hcnkgc3RhdGlzdGljcyB0YWJsZSBmb3IgRDMNCnN1bW1hcnlfc3RhdHNfRDMgPC0gZGF0YS5mcmFtZSgNCiAgTWV0cmljID0gYygiVG90YWwgU2FtcGxlcyIsICJHZW5lcyBBbmFseXplZCIsICJTaWduaWZpY2FudCBERUdzIC0gUEM5IHZzIFBDOS1HUiIsICJVcHJlZ3VsYXRlZCAtIFBDOSB2cyBQQzktR1IiLCAiRG93bnJlZ3VsYXRlZCAtIFBDOSB2cyBQQzktR1IiKSwNCiAgVmFsdWUgPSBjKG5jb2woY291bnRzX0QzKSwgDQogICAgICAgICAgICBucm93KHJlc19EMyksDQogICAgICAgICAgICBucm93KHNpZ19jZWxsbGluZV9EMyksDQogICAgICAgICAgICBsZW5ndGgoc2lnX2dlbmVzX3VwX2NlbGxsaW5lX0QzKSwNCiAgICAgICAgICAgIGxlbmd0aChzaWdfZ2VuZXNfZG93bl9jZWxsbGluZV9EMykpDQopDQoNCnN1bW1hcnlfc3RhdHNfRDMNCg0KIyBUb3AgZ2VuZXMgdGFibGUNCnRvcF9nZW5lc190YWJsZV9EMyA8LSBkYXRhLmZyYW1lKA0KICBHZW5lX1N5bWJvbCA9IGdlbmVfc3ltYm9sc19EM1tyb3duYW1lcyhoZWFkKHNpZ19jZWxsbGluZV9EM1tvcmRlcihzaWdfY2VsbGxpbmVfRDMkcGFkaiksXSwgMjApKV0sDQogIEVOU0VNQkxfSUQgPSByb3duYW1lcyhoZWFkKHNpZ19jZWxsbGluZV9EM1tvcmRlcihzaWdfY2VsbGxpbmVfRDMkcGFkaiksXSwgMjApKSwNCiAgTG9nMkZDID0gcm91bmQoaGVhZChzaWdfY2VsbGxpbmVfRDNbb3JkZXIoc2lnX2NlbGxsaW5lX0QzJHBhZGopLF0sIDIwKSRsb2cyRm9sZENoYW5nZSwgMyksDQogIFBhZGogPSBmb3JtYXQoaGVhZChzaWdfY2VsbGxpbmVfRDNbb3JkZXIoc2lnX2NlbGxsaW5lX0QzJHBhZGopLF0sIDIwKSRwYWRqLCBzY2llbnRpZmljID0gVFJVRSwgZGlnaXRzID0gMyksDQogIERpcmVjdGlvbiA9IGlmZWxzZShoZWFkKHNpZ19jZWxsbGluZV9EM1tvcmRlcihzaWdfY2VsbGxpbmVfRDMkcGFkaiksXSwgMjApJGxvZzJGb2xkQ2hhbmdlID4gMCwgIlVwIiwgIkRvd24iKQ0KKQ0KDQpwcmludCgiVG9wIDIwIFNpZ25pZmljYW50IEdlbmVzOiBQQzkgdnMgUEM5LUdSIikNCnByaW50KHRvcF9nZW5lc190YWJsZV9EMykNCg0KYGBgDQoNCmBgYHtyfQ0KIyBFeHBvcnQgbWFpbiByZXN1bHRzDQp3cml0ZS5jc3YoYXMuZGF0YS5mcmFtZShyZXNfY2VsbGxpbmVfYW5ub3RhdGVkX0QzKSwgIkQzX2NlbGxsaW5lX2Fubm90YXRlZF9yZXN1bHRzLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp3cml0ZS5jc3Yoc2lnX2NlbGxsaW5lX0QzLCAiRDNfc2lnX2NlbGxsaW5lX2dlbmVzLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp3cml0ZS5jc3Yoc3VtbWFyeV9zdGF0c19EMywgIkQzX3N1bW1hcnlfc3RhdGlzdGljcy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCndyaXRlLmNzdih0b3BfZ2VuZXNfdGFibGVfRDMsICJEM190b3AyMF9nZW5lcy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCg0KIyBFeHBvcnQgbm9ybWFsaXplZCBkYXRhDQp3cml0ZS5jc3YocmVzX2Fubm90YXRlZF9EMywgIkQzX3Jlc3VsdHMuY3N2IikNCndyaXRlLmNzdihjb3VudHMoZGRzX0QzLCBub3JtYWxpemVkPVRSVUUpLCAiRDNfbm9ybWFsaXplZF9jb3VudHMuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCndyaXRlLmNzdih2c3RfZmluYWxfRDMsICJEM192c3RfZGF0YS5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KDQojIEV4cG9ydCBwYXRod2F5IHJlc3VsdHMNCmlmKG5yb3coZ29fdXBfY2VsbGxpbmVfRDNAcmVzdWx0KSA+IDApIHsNCiAgd3JpdGUuY3N2KGdvX3VwX2NlbGxsaW5lX0QzQHJlc3VsdCwgIkQzX0dPX3VwcmVndWxhdGVkLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KfQ0KaWYobnJvdyhnb19kb3duX2NlbGxsaW5lX0QzQHJlc3VsdCkgPiAwKSB7DQogIHdyaXRlLmNzdihnb19kb3duX2NlbGxsaW5lX0QzQHJlc3VsdCwgIkQzX0dPX2Rvd25yZWd1bGF0ZWQuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQp9DQppZihucm93KGtlZ2dfdXBfY2VsbGxpbmVfRDNAcmVzdWx0KSA+IDApIHsNCiAgd3JpdGUuY3N2KGtlZ2dfdXBfY2VsbGxpbmVfRDNAcmVzdWx0LCAiRDNfS0VHR191cHJlZ3VsYXRlZC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCn0NCmlmKG5yb3coa2VnZ19kb3duX2NlbGxsaW5lX0QzQHJlc3VsdCkgPiAwKSB7DQogIHdyaXRlLmNzdihrZWdnX2Rvd25fY2VsbGxpbmVfRDNAcmVzdWx0LCAiRDNfS0VHR19kb3ducmVndWxhdGVkLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KfQ0KDQojIFJlbW92ZSB0aGUgbGVhZGluZ0VkZ2UgY29sdW1uICh3aGljaCBjb250YWlucyBsaXN0cykNCmZnc2VhX3Jlc3VsdHNfY2xlYW5fRDMgPC0gZmdzZWFfcmVzdWx0c19jZWxsbGluZV9EMyAlPiUNCiAgc2VsZWN0KC1sZWFkaW5nRWRnZSkNCg0Kd3JpdGUuY3N2KGZnc2VhX3Jlc3VsdHNfY2xlYW5fRDMsICJEM19HU0VBX2hhbGxtYXJrcy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCg0KYGBgDQoNCg==