1. load libraries

#Differential Expression Analysis

2. load seurat object

All_samples_Merged
An object of class Seurat 
62900 features across 49305 samples within 6 assays 
Active assay: SCT (26176 features, 3000 variable features)
 3 layers present: counts, data, scale.data
 5 other assays present: RNA, ADT, prediction.score.celltype.l1, prediction.score.celltype.l2, prediction.score.celltype.l3
 5 dimensional reductions calculated: integrated_dr, ref.umap, pca, umap, harmony
DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T)

#Differential Expression Analysis

3. P1 vs P2


DefaultAssay(All_samples_Merged) <- "SCT"
Idents(All_samples_Merged) <- "seurat_clusters"

# Patient 1 vs Patient 2
p1_vs_p2 <- FindMarkers(All_samples_Merged, 
                        ident.1 = c(5, 1, 9),  # P1 clusters
                        ident.2 = c(2, 6, 8),      # P2 clusters
                        assay = "SCT")
write.csv(p1_vs_p2, "comparison_P1_vs_P2.csv")

# Create volcano plot for P1 vs P2
volcano_p1_vs_p2 <- EnhancedVolcano(p1_vs_p2, 
                                    lab = rownames(p1_vs_p2),
                                    x = 'avg_log2FC',
                                    y = 'p_val_adj',
                                    title = 'P1 vs P2',
                                    xlab = bquote(~Log[2]~ 'fold change'),
                                    pCutoff = 0.05,
                                    FCcutoff = 1.5, 
                                    pointSize = 3.0,
                                    labSize = 5.0,
                                    boxedLabels = TRUE,
                                    colAlpha = 0.5,
                                    legendPosition = 'right',
                                    legendLabSize = 10,
                                    legendIconSize = 4.0,
                                    drawConnectors = TRUE,
                                    widthConnectors = 0.5,
                                    colConnectors = 'grey50',
                                    arrowheads = FALSE,
                                    max.overlaps = 30)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...
print(volcano_p1_vs_p2)
png("volcano_P1_vs_P2.png", width = 12, height = 10, units = "in", res = 300)
print(volcano_p1_vs_p2)
dev.off()
png 
  2 

volcano2_p1_vs_p2 <- EnhancedVolcano(p1_vs_p2, 
                lab = rownames(p1_vs_p2),
                x = "avg_log2FC", 
                y = "p_val_adj",
                selectLab = c('EPCAM', 'KIR3DL2', 'FOXM1', 'TWIST1', 'TNFSF9', 
                              'CD80', 'FOS','PTPN6','NCR1','NCR2',
                              'PCLAF', 'KIR3DL1', 'IL4','ITGA6','CCL5',
                              'IL7R', 'TCF7', 'PTTG1', 'RRM2', 'MKI67', 'CD70', 
                              'IL2RA', 'FCGR3A', 'GNLY', 'FOXP3', 'SELL',  'LEF1',
                              'CCL17', 'THY1', 'CD27', 'CD28', 'CD7',
                              # Key Sézary syndrome genes
                              'PRF1', 'GZMB', 'NCR1', 'NFATC3', 
                              'KLRK1', 'LCK', 'KLRC1', 'KLRC2', 'TNF', 
                              'KIR3DL1','KIR3DL3','KIR3DL4', 'IFNG', 'IFNGR1', 'CD244', 'FASLG'),
                title = "P1 vs P2",
                subtitle = "Sézary Syndrome Cell Lines",
                xlab = bquote(~Log[2]~ 'fold change'),
                pCutoff = 0.05,
                FCcutoff = log2(1.5), 
                pointSize = 3.0,
                labSize = 4.0,
                labFace = 'bold',
                boxedLabels = TRUE,
                colAlpha = 0.5,
                legendPosition = 'right',
                legendLabSize = 10,
                legendIconSize = 4.0,
                drawConnectors = TRUE,
                widthConnectors = 0.5,
                colConnectors = 'grey50',
                arrowheads = FALSE,
                max.overlaps = 30)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...
print(volcano2_p1_vs_p2)
png("volcano2_P1_vs_P2.png", width = 12, height = 10, units = "in", res = 300)
print(volcano2_p1_vs_p2)
dev.off()
png 
  2 

# Display top differentially expressed genes for each comparison
head(p1_vs_p2)
NA
NA

4. P1 vs P3


DefaultAssay(All_samples_Merged) <- "SCT"
Idents(All_samples_Merged) <- "seurat_clusters"


# Patient 1 vs Patient 3
p1_vs_p3 <- FindMarkers(All_samples_Merged, 
                        ident.1 = c(5, 1, 9),  # P1 clusters
                        ident.2 = c(4, 0, 7, 11, 12, 13),  # P3 clusters
                        assay = "SCT")
write.csv(p1_vs_p3, "comparison_P1_vs_P3.csv")

# Create volcano plot for P1 vs P3
volcano_p1_vs_p3 <- EnhancedVolcano(p1_vs_p3, 
                                    lab = rownames(p1_vs_p3),
                                    x = 'avg_log2FC',
                                    y = 'p_val_adj',
                                    title = 'P1 vs P3',
                                    pCutoff = 0.05,
                                    FCcutoff = 1,
                                    pointSize = 1.5,
                                    labSize = 4.0,
                                    col = c('grey', 'darkgreen', 'blue', 'red'),
                                    colAlpha = 0.5,
                                    legendPosition = 'right',
                                    legendLabSize = 10,
                                    legendIconSize = 4.0,
                                    drawConnectors = TRUE,
                                    widthConnectors = 0.5)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...
print(volcano_p1_vs_p3)
png("volcano_P1_vs_P3.png", width = 12, height = 10, units = "in", res = 300)
print(volcano_p1_vs_p3)
dev.off()
png 
  2 

volcano2_p1_vs_p3 <- EnhancedVolcano(p1_vs_p3, 
                lab = rownames(p1_vs_p3),
                x = "avg_log2FC", 
                y = "p_val_adj",
                selectLab = c('KIR3DL2','KIR3DL1','KIR3DL3','KIR3DL4',  'TWIST1', 'TNFSF9', 
                               'FOS', 'TCF7','LEF1',
                               'CD86', 'VCAM1','CCL5',
                              'CD40',  'CD70', 
                              'IL2RA', 'FCGR3A', 'GNLY', 'FOXP3',  'LEF1',
                              'CCL17', 'THY1', 'CD27', 'CD28', 'CD7','EPCAM','TOX','IL16','IL21',
                              # Key Sézary syndrome genes
                              'PRF1', 'GZMB',  
                              'KLRK1', 'LCK', 'KLRC1', 'KLRC2',  
                               'IFNG', 'IFNGR1', 'FASLG'),
                title = "P1 vs P3",
                subtitle = "Sézary Syndrome Cell Lines",
                xlab = bquote(~Log[2]~ 'fold change'),
                pCutoff = 0.05,
                FCcutoff = 1.5, 
                pointSize = 3.0,
                labSize = 4.0,
                labFace = 'bold',
                boxedLabels = TRUE,
                colAlpha = 0.5,
                legendPosition = 'right',
                legendLabSize = 10,
                legendIconSize = 4.0,
                drawConnectors = TRUE,
                widthConnectors = 0.5,
                colConnectors = 'grey50',
                arrowheads = FALSE,
                max.overlaps = 30)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...
print(volcano2_p1_vs_p3)
png("volcano2_P1_vs_P3.png", width = 12, height = 10, units = "in", res = 300)
print(volcano2_p1_vs_p3)
dev.off()
png 
  2 

# Display top differentially expressed genes for each comparison

head(p1_vs_p3)
NA
NA

5. P2 vs P3


DefaultAssay(All_samples_Merged) <- "SCT"
Idents(All_samples_Merged) <- "seurat_clusters"

# Patient 2 vs Patient 3
p2_vs_p3 <- FindMarkers(All_samples_Merged, 
                        ident.1 = c(2, 6, 8),     # P2 clusters
                        ident.2 = c(4, 0, 7, 11, 12, 13),  # P3 clusters
                        assay = "SCT")
write.csv(p2_vs_p3, "comparison_P2_vs_P3.csv")

# Create volcano plot for P2 vs P3
volcano_p2_vs_p3 <- EnhancedVolcano(p2_vs_p3, 
                                    lab = rownames(p2_vs_p3),
                                    x = 'avg_log2FC',
                                    y = 'p_val_adj',
                                    title = 'P2 vs P3',
                                    pCutoff = 0.05,
                                    FCcutoff = 1,
                                    pointSize = 1.5,
                                    labSize = 4.0,
                                    col = c('grey', 'darkgreen', 'blue', 'red'),
                                    colAlpha = 0.5,
                                    legendPosition = 'right',
                                    legendLabSize = 10,
                                    legendIconSize = 4.0,
                                    drawConnectors = TRUE,
                                    widthConnectors = 0.5)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...
print(volcano_p2_vs_p3)
png("volcano_P2_vs_P3.png", width = 12, height = 10, units = "in", res = 300)
print(volcano_p2_vs_p3)
dev.off()
png 
  2 

volcano2_p2_vs_p3 <- EnhancedVolcano(p2_vs_p3, 
                lab = rownames(p2_vs_p3),
                x = "avg_log2FC", 
                y = "p_val_adj",
                selectLab = c('KIR3DL2','KIR3DL1','KIR3DL3','KIR3DL4',  'TWIST1', 'TNFSF9', 
                               
                               'VCAM1','CCL5','CCL23','IL13','IL19', 'TIGIT','JUN','TP53','CD40','CCR10',
                              'CD40',   'KIT','CD52','CD44','RORC','TIFA',
                              'FOXP3',  
                              'CCL17', 'THY1', 'CD28', 'CD7','EPCAM','IL16',
                              # Key Sézary syndrome genes
                                
                              'KLRK1', 'KLRC1', 'KLRC2',  
                               'IFNG', 'IFNGR1', 'FASLG'),
                title = "P2 vs P3",
                subtitle = "Sézary Syndrome Cell Lines",
                xlab = bquote(~Log[2]~ 'fold change'),
                pCutoff = 0.05,
                FCcutoff = 1.5, 
                pointSize = 3.0,
                labSize = 4.0,
                labFace = 'bold',
                boxedLabels = TRUE,
                colAlpha = 0.5,
                legendPosition = 'right',
                legendLabSize = 10,
                legendIconSize = 4.0,
                drawConnectors = TRUE,
                widthConnectors = 0.5,
                colConnectors = 'grey50',
                arrowheads = FALSE,
                max.overlaps = 30)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...
print(volcano2_p2_vs_p3)
png("volcano2_P2_vs_P3.png", width = 12, height = 10, units = "in", res = 300)
print(volcano2_p2_vs_p3)
dev.off()
png 
  2 

print(volcano_p1_vs_p2)

print(volcano_p1_vs_p3)

print(volcano_p2_vs_p3)

print(volcano2_p1_vs_p2)

print(volcano2_p1_vs_p3)

print(volcano2_p2_vs_p3)


# Display top differentially expressed genes for each comparison
head(p1_vs_p2)
head(p1_vs_p3)
head(p2_vs_p3)
NA
NA

6. Enrichment Analysis

library(clusterProfiler)
library(org.Hs.eg.db)
library(enrichplot)

perform_go_enrichment <- function(gene_list, gene_universe, title) {
  ego <- enrichGO(gene = gene_list,
                  universe = gene_universe,
                  OrgDb = org.Hs.eg.db,
                  keyType = "SYMBOL",
                  ont = "BP",
                  pAdjustMethod = "BH",
                  qvalueCutoff = 0.05,
                  readable = TRUE)
  
  if (nrow(ego@result) == 0) {
    warning(paste("No enriched GO terms found for", title))
    return(NULL)
  }
  
  p <- dotplot(ego, showCategory = 20, title = paste("GO -", title)) +
    theme(axis.text.y = element_text(size = 8))
  
  print(p)
  png(paste0("GO_enrichment_", gsub(" ", "_", title), ".png"), width = 12, height = 8, units = "in", res = 300)
  print(p)
  dev.off()
  
  return(ego)
}

perform_kegg_enrichment <- function(gene_list, gene_universe, title) {
  # Convert gene symbols to Entrez IDs
  entrez_ids <- bitr(gene_list, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
  universe_entrez <- bitr(gene_universe, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
  
  print(paste("Number of input genes:", length(gene_list)))
  print(paste("Number of input genes mapped to Entrez IDs:", nrow(entrez_ids)))
  print(paste("Number of universe genes:", length(gene_universe)))
  print(paste("Number of universe genes mapped to Entrez IDs:", nrow(universe_entrez)))
  
  if(nrow(entrez_ids) == 0) {
    warning(paste("No genes could be mapped for", title))
    return(NULL)
  }
  
  tryCatch({
    ekegg <- enrichKEGG(gene = entrez_ids$ENTREZID,
                        universe = universe_entrez$ENTREZID,
                        organism = 'hsa',
                        keyType = "kegg",
                        pvalueCutoff = 0.05,
                        pAdjustMethod = "BH")
    
    if(nrow(ekegg@result) == 0) {
      warning(paste("No enriched KEGG pathways found for", title))
      return(NULL)
    }
    
    p <- dotplot(ekegg, showCategory = 20, title = paste("KEGG -", title)) +
      theme(axis.text.y = element_text(size = 8))
    
    print(p)
    png(paste0("KEGG_enrichment_", gsub(" ", "_", title), ".png"), width = 12, height = 8, units = "in", res = 300)
    print(p)
    dev.off()
    
    return(ekegg)
  }, error = function(e) {
    warning(paste("Error in KEGG enrichment for", title, ":", e$message))
    return(NULL)
  })
}

gene_universe <- rownames(All_samples_Merged)

# P1 vs P2 comparison
upregulated_genes_P1vsP2 <- rownames(p1_vs_p2[p1_vs_p2$avg_log2FC > 1.5 & p1_vs_p2$p_val_adj < 0.001, ])
downregulated_genes_P1vsP2 <- rownames(p1_vs_p2[p1_vs_p2$avg_log2FC < -1.5 & p1_vs_p2$p_val_adj < 0.001, ])

go_up_P1vsP2 <- perform_go_enrichment(upregulated_genes_P1vsP2, gene_universe, "Upregulated Genes in P1 vs P2")

go_down_P1vsP2 <- perform_go_enrichment(downregulated_genes_P1vsP2, gene_universe, "Downregulated Genes in P1 vs P2")

kegg_up_P1vsP2 <- perform_kegg_enrichment(upregulated_genes_P1vsP2, gene_universe, "Upregulated Genes in P1 vs P2")
'select()' returned 1:1 mapping between keys and columns
Warning: 13.39% of input gene IDs are fail to map...'select()' returned 1:many mapping between keys and columns
Warning: 28.25% of input gene IDs are fail to map...
[1] "Number of input genes: 1591"
[1] "Number of input genes mapped to Entrez IDs: 1378"
[1] "Number of universe genes: 26176"
[1] "Number of universe genes mapped to Entrez IDs: 18785"

kegg_down_P1vsP2 <- perform_kegg_enrichment(downregulated_genes_P1vsP2, gene_universe, "Downregulated Genes in P1 vs P2")
'select()' returned 1:many mapping between keys and columns
Warning: 18.52% of input gene IDs are fail to map...'select()' returned 1:many mapping between keys and columns
Warning: 28.25% of input gene IDs are fail to map...
[1] "Number of input genes: 1982"
[1] "Number of input genes mapped to Entrez IDs: 1616"
[1] "Number of universe genes: 26176"
[1] "Number of universe genes mapped to Entrez IDs: 18785"

# P1 vs P3 comparison
upregulated_genes_P1vsP3 <- rownames(p1_vs_p3[p1_vs_p3$avg_log2FC > 1.5 & p1_vs_p3$p_val_adj < 0.001, ])
downregulated_genes_P1vsP3 <- rownames(p1_vs_p3[p1_vs_p3$avg_log2FC < -1.5 & p1_vs_p3$p_val_adj < 0.001, ])

go_up_P1vsP3 <- perform_go_enrichment(upregulated_genes_P1vsP3, gene_universe, "Upregulated Genes in P1 vs P3")

go_down_P1vsP3 <- perform_go_enrichment(downregulated_genes_P1vsP3, gene_universe, "Downregulated Genes in P1 vs P3")

kegg_up_P1vsP3 <- perform_kegg_enrichment(upregulated_genes_P1vsP3, gene_universe, "Upregulated Genes in P1 vs P3")
'select()' returned 1:many mapping between keys and columns
Warning: 12.52% of input gene IDs are fail to map...'select()' returned 1:many mapping between keys and columns
Warning: 28.25% of input gene IDs are fail to map...
[1] "Number of input genes: 1366"
[1] "Number of input genes mapped to Entrez IDs: 1196"
[1] "Number of universe genes: 26176"
[1] "Number of universe genes mapped to Entrez IDs: 18785"

kegg_down_P1vsP3 <- perform_kegg_enrichment(downregulated_genes_P1vsP3, gene_universe, "Downregulated Genes in P1 vs P3")
'select()' returned 1:1 mapping between keys and columns
Warning: 17.83% of input gene IDs are fail to map...'select()' returned 1:many mapping between keys and columns
Warning: 28.25% of input gene IDs are fail to map...
[1] "Number of input genes: 1694"
[1] "Number of input genes mapped to Entrez IDs: 1392"
[1] "Number of universe genes: 26176"
[1] "Number of universe genes mapped to Entrez IDs: 18785"

# P2 vs P3 comparison
upregulated_genes_P2vsP3 <- rownames(p2_vs_p3[p2_vs_p3$avg_log2FC > 1.5 & p2_vs_p3$p_val_adj < 0.001, ])
downregulated_genes_P2vsP3 <- rownames(p2_vs_p3[p2_vs_p3$avg_log2FC < -1.5 & p2_vs_p3$p_val_adj < 0.001, ])

go_up_P2vsP3 <- perform_go_enrichment(upregulated_genes_P2vsP3, gene_universe, "Upregulated Genes in P2 vs P3")

go_down_P2vsP3 <- perform_go_enrichment(downregulated_genes_P2vsP3, gene_universe, "Downregulated Genes in P2 vs P3")

kegg_up_P2vsP3 <- perform_kegg_enrichment(upregulated_genes_P2vsP3, gene_universe, "Upregulated Genes in P2 vs P3")
'select()' returned 1:many mapping between keys and columns
Warning: 17.18% of input gene IDs are fail to map...'select()' returned 1:many mapping between keys and columns
Warning: 28.25% of input gene IDs are fail to map...
[1] "Number of input genes: 1269"
[1] "Number of input genes mapped to Entrez IDs: 1053"
[1] "Number of universe genes: 26176"
[1] "Number of universe genes mapped to Entrez IDs: 18785"

kegg_down_P2vsP3 <- perform_kegg_enrichment(downregulated_genes_P2vsP3, gene_universe, "Downregulated Genes in P2 vs P3")
'select()' returned 1:1 mapping between keys and columns
Warning: 18.13% of input gene IDs are fail to map...'select()' returned 1:many mapping between keys and columns
Warning: 28.25% of input gene IDs are fail to map...
[1] "Number of input genes: 1219"
[1] "Number of input genes mapped to Entrez IDs: 998"
[1] "Number of universe genes: 26176"
[1] "Number of universe genes mapped to Entrez IDs: 18785"

LS0tCnRpdGxlOiAiU8OpemFyeSBTeW5kcm9tZSBDZWxsIExpbmUgZGVyaXZlZCBmcm9tIGVhY2ggcGF0aWVudCBERSBjb21wYXJpc29uIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICMgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgIyB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgIyBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShvcmcuSHMuZWcuZGIpCmxpYnJhcnkoZW5yaWNocGxvdCkKbGlicmFyeShlbnJpY2hwbG90KQpsaWJyYXJ5KEVuaGFuY2VkVm9sY2FubykKCgoKYGBgCiNEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbiBBbmFseXNpcwoKIyAyLiBsb2FkIHNldXJhdCBvYmplY3QKYGBge3IgbG9hZF9zZXVyYXR9CiNMb2FkIFNldXJhdCBPYmplY3QgTDcKbG9hZCgiLi4vMC1yb2JqLzUtSGFybW9ueV9JbnRlZ3JhdGVkX0FsbF9zYW1wbGVzX01lcmdlZF9DRDRUY2VsbHNfZmluYWxfUmVzb2x1dGlvbl9TZWxlY3RlZF8wLjhfQURUX05vcm1hbGl6ZWRfY2xlYW5lZF9tdC5yb2JqIikKCgpBbGxfc2FtcGxlc19NZXJnZWQKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKCmBgYAoKI0RpZmZlcmVudGlhbCBFeHByZXNzaW9uIEFuYWx5c2lzCgojIDMuIFAxIHZzIFAyCmBgYHtyIGZpbmRtYXJrZXJzMSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgpEZWZhdWx0QXNzYXkoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiU0NUIgpJZGVudHMoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgoKIyBQYXRpZW50IDEgdnMgUGF0aWVudCAyCnAxX3ZzX3AyIDwtIEZpbmRNYXJrZXJzKEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50LjEgPSBjKDUsIDEsIDkpLCAgIyBQMSBjbHVzdGVycwogICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4yID0gYygyLCA2LCA4KSwgICAgICAjIFAyIGNsdXN0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gIlNDVCIpCndyaXRlLmNzdihwMV92c19wMiwgImNvbXBhcmlzb25fUDFfdnNfUDIuY3N2IikKCiMgQ3JlYXRlIHZvbGNhbm8gcGxvdCBmb3IgUDEgdnMgUDIKdm9sY2Fub19wMV92c19wMiA8LSBFbmhhbmNlZFZvbGNhbm8ocDFfdnNfcDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWIgPSByb3duYW1lcyhwMV92c19wMiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAnYXZnX2xvZzJGQycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAncF92YWxfYWRqJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAnUDEgdnMgUDInLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bGFiID0gYnF1b3RlKH5Mb2dbMl1+ICdmb2xkIGNoYW5nZScpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYlNpemUgPSA1LjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sQWxwaGEgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ3JpZ2h0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmRJY29uU2l6ZSA9IDQuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbENvbm5lY3RvcnMgPSAnZ3JleTUwJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyb3doZWFkcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgub3ZlcmxhcHMgPSAzMCkKcHJpbnQodm9sY2Fub19wMV92c19wMikKcG5nKCJ2b2xjYW5vX1AxX3ZzX1AyLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCB1bml0cyA9ICJpbiIsIHJlcyA9IDMwMCkKcHJpbnQodm9sY2Fub19wMV92c19wMikKZGV2Lm9mZigpCgoKdm9sY2FubzJfcDFfdnNfcDIgPC0gRW5oYW5jZWRWb2xjYW5vKHAxX3ZzX3AyLCAKICAgICAgICAgICAgICAgIGxhYiA9IHJvd25hbWVzKHAxX3ZzX3AyKSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsIAogICAgICAgICAgICAgICAgeSA9ICJwX3ZhbF9hZGoiLAogICAgICAgICAgICAgICAgc2VsZWN0TGFiID0gYygnRVBDQU0nLCAnS0lSM0RMMicsICdGT1hNMScsICdUV0lTVDEnLCAnVE5GU0Y5JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDRDgwJywgJ0ZPUycsJ1BUUE42JywnTkNSMScsJ05DUjInLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnUENMQUYnLCAnS0lSM0RMMScsICdJTDQnLCdJVEdBNicsJ0NDTDUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUw3UicsICdUQ0Y3JywgJ1BUVEcxJywgJ1JSTTInLCAnTUtJNjcnLCAnQ0Q3MCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUwyUkEnLCAnRkNHUjNBJywgJ0dOTFknLCAnRk9YUDMnLCAnU0VMTCcsICAnTEVGMScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDQ0wxNycsICdUSFkxJywgJ0NEMjcnLCAnQ0QyOCcsICdDRDcnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEtleSBTw6l6YXJ5IHN5bmRyb21lIGdlbmVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdQUkYxJywgJ0daTUInLCAnTkNSMScsICdORkFUQzMnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0tMUksxJywgJ0xDSycsICdLTFJDMScsICdLTFJDMicsICdUTkYnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0tJUjNETDEnLCdLSVIzREwzJywnS0lSM0RMNCcsICdJRk5HJywgJ0lGTkdSMScsICdDRDI0NCcsICdGQVNMRycpLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiUDEgdnMgUDIiLAogICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiU8OpemFyeSBTeW5kcm9tZSBDZWxsIExpbmVzIiwKICAgICAgICAgICAgICAgIHhsYWIgPSBicXVvdGUofkxvZ1syXX4gJ2ZvbGQgY2hhbmdlJyksCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gbG9nMigxLjUpLCAKICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDMuMCwKICAgICAgICAgICAgICAgIGxhYlNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICBsYWJGYWNlID0gJ2JvbGQnLAogICAgICAgICAgICAgICAgYm94ZWRMYWJlbHMgPSBUUlVFLAogICAgICAgICAgICAgICAgY29sQWxwaGEgPSAwLjUsCiAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsCiAgICAgICAgICAgICAgICBsZWdlbmRMYWJTaXplID0gMTAsCiAgICAgICAgICAgICAgICBsZWdlbmRJY29uU2l6ZSA9IDQuMCwKICAgICAgICAgICAgICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgICAgICAgICAgICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuNSwKICAgICAgICAgICAgICAgIGNvbENvbm5lY3RvcnMgPSAnZ3JleTUwJywKICAgICAgICAgICAgICAgIGFycm93aGVhZHMgPSBGQUxTRSwKICAgICAgICAgICAgICAgIG1heC5vdmVybGFwcyA9IDMwKQpwcmludCh2b2xjYW5vMl9wMV92c19wMikKcG5nKCJ2b2xjYW5vMl9QMV92c19QMi5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMCwgdW5pdHMgPSAiaW4iLCByZXMgPSAzMDApCnByaW50KHZvbGNhbm8yX3AxX3ZzX3AyKQpkZXYub2ZmKCkKCiMgRGlzcGxheSB0b3AgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGZvciBlYWNoIGNvbXBhcmlzb24KaGVhZChwMV92c19wMikKCgpgYGAKCgojIDQuIFAxIHZzIFAzCmBgYHtyIGZpbmRtYXJrZXJzMiwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgpEZWZhdWx0QXNzYXkoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiU0NUIgpJZGVudHMoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgoKCiMgUGF0aWVudCAxIHZzIFBhdGllbnQgMwpwMV92c19wMyA8LSBGaW5kTWFya2VycyhBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4xID0gYyg1LCAxLCA5KSwgICMgUDEgY2x1c3RlcnMKICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnQuMiA9IGMoNCwgMCwgNywgMTEsIDEyLCAxMyksICAjIFAzIGNsdXN0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gIlNDVCIpCndyaXRlLmNzdihwMV92c19wMywgImNvbXBhcmlzb25fUDFfdnNfUDMuY3N2IikKCiMgQ3JlYXRlIHZvbGNhbm8gcGxvdCBmb3IgUDEgdnMgUDMKdm9sY2Fub19wMV92c19wMyA8LSBFbmhhbmNlZFZvbGNhbm8ocDFfdnNfcDMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWIgPSByb3duYW1lcyhwMV92c19wMyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAnYXZnX2xvZzJGQycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAncF92YWxfYWRqJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAnUDEgdnMgUDMnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAxLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYlNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IGMoJ2dyZXknLCAnZGFya2dyZWVuJywgJ2JsdWUnLCAncmVkJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbEFscGhhID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZExhYlNpemUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGhDb25uZWN0b3JzID0gMC41KQpwcmludCh2b2xjYW5vX3AxX3ZzX3AzKQpwbmcoInZvbGNhbm9fUDFfdnNfUDMucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTAsIHVuaXRzID0gImluIiwgcmVzID0gMzAwKQpwcmludCh2b2xjYW5vX3AxX3ZzX3AzKQpkZXYub2ZmKCkKCnZvbGNhbm8yX3AxX3ZzX3AzIDwtIEVuaGFuY2VkVm9sY2FubyhwMV92c19wMywgCiAgICAgICAgICAgICAgICBsYWIgPSByb3duYW1lcyhwMV92c19wMyksCiAgICAgICAgICAgICAgICB4ID0gImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHNlbGVjdExhYiA9IGMoJ0tJUjNETDInLCdLSVIzREwxJywnS0lSM0RMMycsJ0tJUjNETDQnLCAgJ1RXSVNUMScsICdUTkZTRjknLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdGT1MnLCAnVENGNycsJ0xFRjEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0NEODYnLCAnVkNBTTEnLCdDQ0w1JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0NENDAnLCAgJ0NENzAnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0lMMlJBJywgJ0ZDR1IzQScsICdHTkxZJywgJ0ZPWFAzJywgICdMRUYxJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0NDTDE3JywgJ1RIWTEnLCAnQ0QyNycsICdDRDI4JywgJ0NENycsJ0VQQ0FNJywnVE9YJywnSUwxNicsJ0lMMjEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEtleSBTw6l6YXJ5IHN5bmRyb21lIGdlbmVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdQUkYxJywgJ0daTUInLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdLTFJLMScsICdMQ0snLCAnS0xSQzEnLCAnS0xSQzInLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUZORycsICdJRk5HUjEnLCAnRkFTTEcnKSwKICAgICAgICAgICAgICAgIHRpdGxlID0gIlAxIHZzIFAzIiwKICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIlPDqXphcnkgU3luZHJvbWUgQ2VsbCBMaW5lcyIsCiAgICAgICAgICAgICAgICB4bGFiID0gYnF1b3RlKH5Mb2dbMl1+ICdmb2xkIGNoYW5nZScpLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEuNSwgCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gNC4wLAogICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIGNvbEFscGhhID0gMC41LAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAncmlnaHQnLAogICAgICAgICAgICAgICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjUsCiAgICAgICAgICAgICAgICBjb2xDb25uZWN0b3JzID0gJ2dyZXk1MCcsCiAgICAgICAgICAgICAgICBhcnJvd2hlYWRzID0gRkFMU0UsCiAgICAgICAgICAgICAgICBtYXgub3ZlcmxhcHMgPSAzMCkKcHJpbnQodm9sY2FubzJfcDFfdnNfcDMpCnBuZygidm9sY2FubzJfUDFfdnNfUDMucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTAsIHVuaXRzID0gImluIiwgcmVzID0gMzAwKQpwcmludCh2b2xjYW5vMl9wMV92c19wMykKZGV2Lm9mZigpCgoKIyBEaXNwbGF5IHRvcCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgZm9yIGVhY2ggY29tcGFyaXNvbgoKaGVhZChwMV92c19wMykKCgpgYGAKCgojIDUuIFAyIHZzIFAzCmBgYHtyIGZpbmRtYXJrZXJzMywgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgpEZWZhdWx0QXNzYXkoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiU0NUIgpJZGVudHMoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgoKIyBQYXRpZW50IDIgdnMgUGF0aWVudCAzCnAyX3ZzX3AzIDwtIEZpbmRNYXJrZXJzKEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50LjEgPSBjKDIsIDYsIDgpLCAgICAgIyBQMiBjbHVzdGVycwogICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4yID0gYyg0LCAwLCA3LCAxMSwgMTIsIDEzKSwgICMgUDMgY2x1c3RlcnMKICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXkgPSAiU0NUIikKd3JpdGUuY3N2KHAyX3ZzX3AzLCAiY29tcGFyaXNvbl9QMl92c19QMy5jc3YiKQoKIyBDcmVhdGUgdm9sY2FubyBwbG90IGZvciBQMiB2cyBQMwp2b2xjYW5vX3AyX3ZzX3AzIDwtIEVuaGFuY2VkVm9sY2FubyhwMl92c19wMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYiA9IHJvd25hbWVzKHAyX3ZzX3AzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICdhdmdfbG9nMkZDJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICdwX3ZhbF9hZGonLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICdQMiB2cyBQMycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiU2l6ZSA9IDQuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sID0gYygnZ3JleScsICdkYXJrZ3JlZW4nLCAnYmx1ZScsICdyZWQnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sQWxwaGEgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ3JpZ2h0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmRJY29uU2l6ZSA9IDQuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjUpCnByaW50KHZvbGNhbm9fcDJfdnNfcDMpCnBuZygidm9sY2Fub19QMl92c19QMy5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMCwgdW5pdHMgPSAiaW4iLCByZXMgPSAzMDApCnByaW50KHZvbGNhbm9fcDJfdnNfcDMpCmRldi5vZmYoKQoKdm9sY2FubzJfcDJfdnNfcDMgPC0gRW5oYW5jZWRWb2xjYW5vKHAyX3ZzX3AzLCAKICAgICAgICAgICAgICAgIGxhYiA9IHJvd25hbWVzKHAyX3ZzX3AzKSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsIAogICAgICAgICAgICAgICAgeSA9ICJwX3ZhbF9hZGoiLAogICAgICAgICAgICAgICAgc2VsZWN0TGFiID0gYygnS0lSM0RMMicsJ0tJUjNETDEnLCdLSVIzREwzJywnS0lSM0RMNCcsICAnVFdJU1QxJywgJ1RORlNGOScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVkNBTTEnLCdDQ0w1JywnQ0NMMjMnLCdJTDEzJywnSUwxOScsICdUSUdJVCcsJ0pVTicsJ1RQNTMnLCdDRDQwJywnQ0NSMTAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQ0Q0MCcsICAgJ0tJVCcsJ0NENTInLCdDRDQ0JywnUk9SQycsJ1RJRkEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnRk9YUDMnLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDQ0wxNycsICdUSFkxJywgJ0NEMjgnLCAnQ0Q3JywnRVBDQU0nLCdJTDE2JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBLZXkgU8OpemFyeSBzeW5kcm9tZSBnZW5lcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnS0xSSzEnLCAnS0xSQzEnLCAnS0xSQzInLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUZORycsICdJRk5HUjEnLCAnRkFTTEcnKSwKICAgICAgICAgICAgICAgIHRpdGxlID0gIlAyIHZzIFAzIiwKICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIlPDqXphcnkgU3luZHJvbWUgQ2VsbCBMaW5lcyIsCiAgICAgICAgICAgICAgICB4bGFiID0gYnF1b3RlKH5Mb2dbMl1+ICdmb2xkIGNoYW5nZScpLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEuNSwgCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gNC4wLAogICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIGNvbEFscGhhID0gMC41LAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAncmlnaHQnLAogICAgICAgICAgICAgICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjUsCiAgICAgICAgICAgICAgICBjb2xDb25uZWN0b3JzID0gJ2dyZXk1MCcsCiAgICAgICAgICAgICAgICBhcnJvd2hlYWRzID0gRkFMU0UsCiAgICAgICAgICAgICAgICBtYXgub3ZlcmxhcHMgPSAzMCkKcHJpbnQodm9sY2FubzJfcDJfdnNfcDMpCnBuZygidm9sY2FubzJfUDJfdnNfUDMucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTAsIHVuaXRzID0gImluIiwgcmVzID0gMzAwKQpwcmludCh2b2xjYW5vMl9wMl92c19wMykKZGV2Lm9mZigpCgpwcmludCh2b2xjYW5vX3AxX3ZzX3AyKQpwcmludCh2b2xjYW5vX3AxX3ZzX3AzKQpwcmludCh2b2xjYW5vX3AyX3ZzX3AzKQpwcmludCh2b2xjYW5vMl9wMV92c19wMikKcHJpbnQodm9sY2FubzJfcDFfdnNfcDMpCnByaW50KHZvbGNhbm8yX3AyX3ZzX3AzKQoKIyBEaXNwbGF5IHRvcCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgZm9yIGVhY2ggY29tcGFyaXNvbgpoZWFkKHAxX3ZzX3AyKQpoZWFkKHAxX3ZzX3AzKQpoZWFkKHAyX3ZzX3AzKQoKCmBgYAoKCiMgNi4gRW5yaWNobWVudCBBbmFseXNpcwpgYGB7ciBlbnJpY2htZW50MiwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KG9yZy5Icy5lZy5kYikKbGlicmFyeShlbnJpY2hwbG90KQoKcGVyZm9ybV9nb19lbnJpY2htZW50IDwtIGZ1bmN0aW9uKGdlbmVfbGlzdCwgZ2VuZV91bml2ZXJzZSwgdGl0bGUpIHsKICBlZ28gPC0gZW5yaWNoR08oZ2VuZSA9IGdlbmVfbGlzdCwKICAgICAgICAgICAgICAgICAgdW5pdmVyc2UgPSBnZW5lX3VuaXZlcnNlLAogICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwKICAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJTWU1CT0wiLAogICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLAogICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwKICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgICAgcmVhZGFibGUgPSBUUlVFKQogIAogIGlmIChucm93KGVnb0ByZXN1bHQpID09IDApIHsKICAgIHdhcm5pbmcocGFzdGUoIk5vIGVucmljaGVkIEdPIHRlcm1zIGZvdW5kIGZvciIsIHRpdGxlKSkKICAgIHJldHVybihOVUxMKQogIH0KICAKICBwIDwtIGRvdHBsb3QoZWdvLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSBwYXN0ZSgiR08gLSIsIHRpdGxlKSkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKQogIAogIHByaW50KHApCiAgcG5nKHBhc3RlMCgiR09fZW5yaWNobWVudF8iLCBnc3ViKCIgIiwgIl8iLCB0aXRsZSksICIucG5nIiksIHdpZHRoID0gMTIsIGhlaWdodCA9IDgsIHVuaXRzID0gImluIiwgcmVzID0gMzAwKQogIHByaW50KHApCiAgZGV2Lm9mZigpCiAgCiAgcmV0dXJuKGVnbykKfQoKcGVyZm9ybV9rZWdnX2VucmljaG1lbnQgPC0gZnVuY3Rpb24oZ2VuZV9saXN0LCBnZW5lX3VuaXZlcnNlLCB0aXRsZSkgewogICMgQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gRW50cmV6IElEcwogIGVudHJlel9pZHMgPC0gYml0cihnZW5lX2xpc3QsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQogIHVuaXZlcnNlX2VudHJleiA8LSBiaXRyKGdlbmVfdW5pdmVyc2UsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQogIAogIHByaW50KHBhc3RlKCJOdW1iZXIgb2YgaW5wdXQgZ2VuZXM6IiwgbGVuZ3RoKGdlbmVfbGlzdCkpKQogIHByaW50KHBhc3RlKCJOdW1iZXIgb2YgaW5wdXQgZ2VuZXMgbWFwcGVkIHRvIEVudHJleiBJRHM6IiwgbnJvdyhlbnRyZXpfaWRzKSkpCiAgcHJpbnQocGFzdGUoIk51bWJlciBvZiB1bml2ZXJzZSBnZW5lczoiLCBsZW5ndGgoZ2VuZV91bml2ZXJzZSkpKQogIHByaW50KHBhc3RlKCJOdW1iZXIgb2YgdW5pdmVyc2UgZ2VuZXMgbWFwcGVkIHRvIEVudHJleiBJRHM6IiwgbnJvdyh1bml2ZXJzZV9lbnRyZXopKSkKICAKICBpZihucm93KGVudHJlel9pZHMpID09IDApIHsKICAgIHdhcm5pbmcocGFzdGUoIk5vIGdlbmVzIGNvdWxkIGJlIG1hcHBlZCBmb3IiLCB0aXRsZSkpCiAgICByZXR1cm4oTlVMTCkKICB9CiAgCiAgdHJ5Q2F0Y2goewogICAgZWtlZ2cgPC0gZW5yaWNoS0VHRyhnZW5lID0gZW50cmV6X2lkcyRFTlRSRVpJRCwKICAgICAgICAgICAgICAgICAgICAgICAgdW5pdmVyc2UgPSB1bml2ZXJzZV9lbnRyZXokRU5UUkVaSUQsCiAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gJ2hzYScsCiAgICAgICAgICAgICAgICAgICAgICAgIGtleVR5cGUgPSAia2VnZyIsCiAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiKQogICAgCiAgICBpZihucm93KGVrZWdnQHJlc3VsdCkgPT0gMCkgewogICAgICB3YXJuaW5nKHBhc3RlKCJObyBlbnJpY2hlZCBLRUdHIHBhdGh3YXlzIGZvdW5kIGZvciIsIHRpdGxlKSkKICAgICAgcmV0dXJuKE5VTEwpCiAgICB9CiAgICAKICAgIHAgPC0gZG90cGxvdChla2VnZywgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gcGFzdGUoIktFR0cgLSIsIHRpdGxlKSkgKwogICAgICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpCiAgICAKICAgIHByaW50KHApCiAgICBwbmcocGFzdGUwKCJLRUdHX2VucmljaG1lbnRfIiwgZ3N1YigiICIsICJfIiwgdGl0bGUpLCAiLnBuZyIpLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCB1bml0cyA9ICJpbiIsIHJlcyA9IDMwMCkKICAgIHByaW50KHApCiAgICBkZXYub2ZmKCkKICAgIAogICAgcmV0dXJuKGVrZWdnKQogIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgewogICAgd2FybmluZyhwYXN0ZSgiRXJyb3IgaW4gS0VHRyBlbnJpY2htZW50IGZvciIsIHRpdGxlLCAiOiIsIGUkbWVzc2FnZSkpCiAgICByZXR1cm4oTlVMTCkKICB9KQp9CgpnZW5lX3VuaXZlcnNlIDwtIHJvd25hbWVzKEFsbF9zYW1wbGVzX01lcmdlZCkKCiMgUDEgdnMgUDIgY29tcGFyaXNvbgp1cHJlZ3VsYXRlZF9nZW5lc19QMXZzUDIgPC0gcm93bmFtZXMocDFfdnNfcDJbcDFfdnNfcDIkYXZnX2xvZzJGQyA+IDEuNSAmIHAxX3ZzX3AyJHBfdmFsX2FkaiA8IDAuMDAxLCBdKQpkb3ducmVndWxhdGVkX2dlbmVzX1AxdnNQMiA8LSByb3duYW1lcyhwMV92c19wMltwMV92c19wMiRhdmdfbG9nMkZDIDwgLTEuNSAmIHAxX3ZzX3AyJHBfdmFsX2FkaiA8IDAuMDAxLCBdKQoKZ29fdXBfUDF2c1AyIDwtIHBlcmZvcm1fZ29fZW5yaWNobWVudCh1cHJlZ3VsYXRlZF9nZW5lc19QMXZzUDIsIGdlbmVfdW5pdmVyc2UsICJVcHJlZ3VsYXRlZCBHZW5lcyBpbiBQMSB2cyBQMiIpCmdvX2Rvd25fUDF2c1AyIDwtIHBlcmZvcm1fZ29fZW5yaWNobWVudChkb3ducmVndWxhdGVkX2dlbmVzX1AxdnNQMiwgZ2VuZV91bml2ZXJzZSwgIkRvd25yZWd1bGF0ZWQgR2VuZXMgaW4gUDEgdnMgUDIiKQprZWdnX3VwX1AxdnNQMiA8LSBwZXJmb3JtX2tlZ2dfZW5yaWNobWVudCh1cHJlZ3VsYXRlZF9nZW5lc19QMXZzUDIsIGdlbmVfdW5pdmVyc2UsICJVcHJlZ3VsYXRlZCBHZW5lcyBpbiBQMSB2cyBQMiIpCmtlZ2dfZG93bl9QMXZzUDIgPC0gcGVyZm9ybV9rZWdnX2VucmljaG1lbnQoZG93bnJlZ3VsYXRlZF9nZW5lc19QMXZzUDIsIGdlbmVfdW5pdmVyc2UsICJEb3ducmVndWxhdGVkIEdlbmVzIGluIFAxIHZzIFAyIikKCiMgUDEgdnMgUDMgY29tcGFyaXNvbgp1cHJlZ3VsYXRlZF9nZW5lc19QMXZzUDMgPC0gcm93bmFtZXMocDFfdnNfcDNbcDFfdnNfcDMkYXZnX2xvZzJGQyA+IDEuNSAmIHAxX3ZzX3AzJHBfdmFsX2FkaiA8IDAuMDAxLCBdKQpkb3ducmVndWxhdGVkX2dlbmVzX1AxdnNQMyA8LSByb3duYW1lcyhwMV92c19wM1twMV92c19wMyRhdmdfbG9nMkZDIDwgLTEuNSAmIHAxX3ZzX3AzJHBfdmFsX2FkaiA8IDAuMDAxLCBdKQoKZ29fdXBfUDF2c1AzIDwtIHBlcmZvcm1fZ29fZW5yaWNobWVudCh1cHJlZ3VsYXRlZF9nZW5lc19QMXZzUDMsIGdlbmVfdW5pdmVyc2UsICJVcHJlZ3VsYXRlZCBHZW5lcyBpbiBQMSB2cyBQMyIpCmdvX2Rvd25fUDF2c1AzIDwtIHBlcmZvcm1fZ29fZW5yaWNobWVudChkb3ducmVndWxhdGVkX2dlbmVzX1AxdnNQMywgZ2VuZV91bml2ZXJzZSwgIkRvd25yZWd1bGF0ZWQgR2VuZXMgaW4gUDEgdnMgUDMiKQprZWdnX3VwX1AxdnNQMyA8LSBwZXJmb3JtX2tlZ2dfZW5yaWNobWVudCh1cHJlZ3VsYXRlZF9nZW5lc19QMXZzUDMsIGdlbmVfdW5pdmVyc2UsICJVcHJlZ3VsYXRlZCBHZW5lcyBpbiBQMSB2cyBQMyIpCmtlZ2dfZG93bl9QMXZzUDMgPC0gcGVyZm9ybV9rZWdnX2VucmljaG1lbnQoZG93bnJlZ3VsYXRlZF9nZW5lc19QMXZzUDMsIGdlbmVfdW5pdmVyc2UsICJEb3ducmVndWxhdGVkIEdlbmVzIGluIFAxIHZzIFAzIikKCiMgUDIgdnMgUDMgY29tcGFyaXNvbgp1cHJlZ3VsYXRlZF9nZW5lc19QMnZzUDMgPC0gcm93bmFtZXMocDJfdnNfcDNbcDJfdnNfcDMkYXZnX2xvZzJGQyA+IDEuNSAmIHAyX3ZzX3AzJHBfdmFsX2FkaiA8IDAuMDAxLCBdKQpkb3ducmVndWxhdGVkX2dlbmVzX1AydnNQMyA8LSByb3duYW1lcyhwMl92c19wM1twMl92c19wMyRhdmdfbG9nMkZDIDwgLTEuNSAmIHAyX3ZzX3AzJHBfdmFsX2FkaiA8IDAuMDAxLCBdKQoKZ29fdXBfUDJ2c1AzIDwtIHBlcmZvcm1fZ29fZW5yaWNobWVudCh1cHJlZ3VsYXRlZF9nZW5lc19QMnZzUDMsIGdlbmVfdW5pdmVyc2UsICJVcHJlZ3VsYXRlZCBHZW5lcyBpbiBQMiB2cyBQMyIpCmdvX2Rvd25fUDJ2c1AzIDwtIHBlcmZvcm1fZ29fZW5yaWNobWVudChkb3ducmVndWxhdGVkX2dlbmVzX1AydnNQMywgZ2VuZV91bml2ZXJzZSwgIkRvd25yZWd1bGF0ZWQgR2VuZXMgaW4gUDIgdnMgUDMiKQprZWdnX3VwX1AydnNQMyA8LSBwZXJmb3JtX2tlZ2dfZW5yaWNobWVudCh1cHJlZ3VsYXRlZF9nZW5lc19QMnZzUDMsIGdlbmVfdW5pdmVyc2UsICJVcHJlZ3VsYXRlZCBHZW5lcyBpbiBQMiB2cyBQMyIpCmtlZ2dfZG93bl9QMnZzUDMgPC0gcGVyZm9ybV9rZWdnX2VucmljaG1lbnQoZG93bnJlZ3VsYXRlZF9nZW5lc19QMnZzUDMsIGdlbmVfdW5pdmVyc2UsICJEb3ducmVndWxhdGVkIEdlbmVzIGluIFAyIHZzIFAzIikKCgpgYGAKCgoKCg==