1. load libraries

2. Load Seurat Object


load ("/home/bioinfo/0-imp_Robj/Harmony_integrated_All_samples_Merged_with_PBMC10x_with_harmony_clustering.Robj")
 

2. Initial Visualization



All_samples_Merged <- SetIdent(All_samples_Merged, value = "Harmony_snn_res.0.9")
  
DimPlot(All_samples_Merged,group.by = "cell_line", 
        reduction = "umap.harmony",
        label.size = 3,
        repel = T,
        label = T)


DimPlot(All_samples_Merged,
        group.by = "Harmony_snn_res.0.9", 
        reduction = "umap.harmony",
        label.size = 3,
        repel = T,
        label = T)


DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2", 
        reduction = "umap.harmony",
        label.size = 3,
        repel = T,
        label = T)

3. Perform DE analysis using the FindMarkers



All_samples_Merged <- SetIdent(All_samples_Merged, value = "Harmony_snn_res.0.9")

Patient_cell_lines_vs_PBMC_Tcells <- FindMarkers(All_samples_Merged, 
                           ident.1 = c("3", "8", "10", "18", "1", "2", "13", "6", "16", "19", "4", "7", "9"),
                           ident.2 = c("0", "5", "14", "24", "20")
                           )



# Convert to data frame and add gene names as a new column
Patient_cell_lines_vs_PBMC_Tcells <- as.data.frame(Patient_cell_lines_vs_PBMC_Tcells)
Patient_cell_lines_vs_PBMC_Tcells$gene <- rownames(Patient_cell_lines_vs_PBMC_Tcells)

# Rearranging the columns for better readability (optional)
Patient_cell_lines_vs_PBMC_Tcells <- Patient_cell_lines_vs_PBMC_Tcells[, c("gene", "p_val", "avg_log2FC", "pct.1", "pct.2", "p_val_adj")]

#write.csv(Patient_cell_lines_vs_PBMC_Tcells, "Patient_cell_lines_vs_PBMC_Tcells.csv", row.names = FALSE)
Warning messages:
1: ggrepel: 25 unlabeled data points (too many overlaps). Consider increasing max.overlaps 
2: ggrepel: 25 unlabeled data points (too many overlaps). Consider increasing max.overlaps 
3: ggrepel: 15 unlabeled data points (too many overlaps). Consider increasing max.overlaps 
4: ggrepel: 13 unlabeled data points (too many overlaps). Consider increasing max.overlaps 
5: ggrepel: 8 unlabeled data points (too many overlaps). Consider increasing max.overlaps 
6: ggrepel: 7 unlabeled data points (too many overlaps). Consider increasing max.overlaps 
7: ggrepel: 7 unlabeled data points (too many overlaps). Consider increasing max.overlaps 
EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells , 
                lab=rownames(Patient_cell_lines_vs_PBMC_Tcells),
                x ="avg_log2FC", 
                y ="p_val_adj",
                title = "Sézary Cell Lines vs PBMC T cells",
                pCutoff = 0.05,
                FCcutoff = 1.5, 
                legendPosition = 'right', 
                labCol = 'black',
                labFace = 'bold',
                boxedLabels = TRUE,
                pointSize = 3.0,
                labSize = 5.0, 
                drawConnectors = TRUE,
                widthConnectors = 0.25)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells, 
                lab = ifelse((Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5 | Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5) & 
                             Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05, 
                             rownames(Patient_cell_lines_vs_PBMC_Tcells), 
                             ""),  # Label only significant genes
                x = "avg_log2FC", 
                y = "p_val_adj",
                title = "Sézary Cell Lines vs PBMC T cells",
                pCutoff = 0.05,
                FCcutoff = 1.5, 
                legendPosition = 'right', 
                labCol = 'black',
                labFace = 'bold',
                boxedLabels = TRUE,
                pointSize = 3.0,
                labSize = 5.0, 
                drawConnectors = TRUE,
                widthConnectors = 0.25)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells, 
                lab = Patient_cell_lines_vs_PBMC_Tcells$gene,
                x = "avg_log2FC", 
                y = "p_val_adj",
                selectLab = c('EPCAM', 'BCAT1', 'KIR3DL2', 'FOXM1', 'TWIST1', 'TNFSF9', 
                              'CD80',  'IL1B', 'TRBV7.6', 'TRBV5.4', 'TRBV12.4',
                              'UBE2C', 'PCLAF', 'TYMS', 'CDC20', 'RPS4Y1', 
                              'IL7R', 'TCF7', 'PTTG1', 'RRM2', 'MKI67', 'CD70', 
                              'IL2RA','TRBV6-2', 'TRBV10-3', 'TRBV4-2', 'TRBV9', 'TRBV7-9', 
                              'TRAV12-1', 'CD8B', 'FCGR3A', 'GNLY', 'FOXP3', 'SELL', 
                              'GIMAP1', 'RIPOR2', 'LEF1', 'HOXC9', 'SP5',
                              'CCL17', 'ETV4', 'THY1', 'FOXA2', 'ITGAD', 'S100P', 'TBX4', 
                              'ID1', 'XCL1', 'SOX2', 'CD27', 'CD28','PLS3','CD70','RAB25' , 'TRBV27', 'TRBV2'),
                title = "Sézary Cell Lines vs PBMC T cells",
                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...

4. Enrichment Analysis


#Step-by-Step Guide for Gene Set Enrichment Analysis (GSEA) or Over-Representation Analysis (ORA)

# Load the packages
library(clusterProfiler)
clusterProfiler v4.14.0 Learn more at https://yulab-smu.top/contribution-knowledge-mining/

Please cite:

T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu.
clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. The Innovation. 2021,
2(3):100141

Attaching package: 'clusterProfiler'

The following object is masked from 'package:stats':

    filter
library(org.Hs.eg.db)
Loading required package: AnnotationDbi
Loading required package: stats4
Loading required package: BiocGenerics

Attaching package: 'BiocGenerics'

The following object is masked from 'package:gridExtra':

    combine

The following objects are masked from 'package:dplyr':

    combine, intersect, setdiff, union

The following object is masked from 'package:SeuratObject':

    intersect

The following objects are masked from 'package:stats':

    IQR, mad, sd, var, xtabs

The following objects are masked from 'package:base':

    anyDuplicated, aperm, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated,
    eval, evalq, Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget,
    order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce, rownames, sapply, saveRDS,
    setdiff, table, tapply, union, unique, unsplit, which.max, which.min

Loading required package: Biobase
Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see
    'citation("Biobase")', and for packages 'citation("pkgname")'.

Loading required package: IRanges
Loading required package: S4Vectors

Attaching package: 'S4Vectors'

The following object is masked from 'package:clusterProfiler':

    rename

The following objects are masked from 'package:dplyr':

    first, rename

The following object is masked from 'package:utils':

    findMatches

The following objects are masked from 'package:base':

    expand.grid, I, unname


Attaching package: 'IRanges'

The following object is masked from 'package:clusterProfiler':

    slice

The following objects are masked from 'package:dplyr':

    collapse, desc, slice

The following object is masked from 'package:sp':

    %over%


Attaching package: 'AnnotationDbi'

The following object is masked from 'package:clusterProfiler':

    select

The following object is masked from 'package:dplyr':

    select
library(enrichplot)
enrichplot v1.26.0 Learn more at https://yulab-smu.top/contribution-knowledge-mining/

Please cite:

Guangchuang Yu, Li-Gen Wang, and Qing-Yu He. ChIPseeker: an R/Bioconductor package for ChIP peak annotation,
comparison and visualization. Bioinformatics. 2015, 31(14):2382-2383
library(ReactomePA)
ReactomePA v1.50.0 Learn more at https://yulab-smu.top/contribution-knowledge-mining/

Please cite:

Guangchuang Yu, Qing-Yu He. ReactomePA: an R/Bioconductor package for reactome pathway analysis and
visualization. Molecular BioSystems. 2016, 12(2):477-479
# Get upregulated genes
upregulated_genes <- rownames(Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5 & Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05, ])

# Get downregulated genes
downregulated_genes <- rownames(Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5 & Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05, ])

#Gene Ontology (GO) Enrichment Analysis
# GO enrichment for upregulated genes
go_up <- enrichGO(gene = upregulated_genes, 
                  OrgDb = org.Hs.eg.db, 
                  keyType = "SYMBOL", 
                  ont = "BP",   # "BP" for Biological Processes, "MF" for Molecular Function, "CC" for Cellular Component
                  pAdjustMethod = "BH", 
                  pvalueCutoff = 0.05)

# GO enrichment for downregulated genes
go_down <- enrichGO(gene = downregulated_genes, 
                    OrgDb = org.Hs.eg.db, 
                    keyType = "SYMBOL", 
                    ont = "BP", 
                    pAdjustMethod = "BH", 
                    pvalueCutoff = 0.05)

# Visualize the top enriched GO terms
dotplot(go_up, showCategory = 20, title = "GO Enrichment for Upregulated Genes")

dotplot(go_down, showCategory = 20, title = "GO Enrichment for Downregulated Genes")


#KEGG Pathway Enrichment
# Convert gene symbols to Entrez IDs for KEGG analysis
upregulated_entrez <- bitr(upregulated_genes, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:many mapping between keys and columns
Warning: 10.4% of input gene IDs are fail to map...
downregulated_entrez <- bitr(downregulated_genes, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:1 mapping between keys and columns
Warning: 16.3% of input gene IDs are fail to map...
# KEGG pathway enrichment for upregulated genes
kegg_up <- enrichKEGG(gene = upregulated_entrez, 
                      organism = "hsa", 
                      pvalueCutoff = 0.05)
Reading KEGG annotation online: "https://rest.kegg.jp/link/hsa/pathway"...
Reading KEGG annotation online: "https://rest.kegg.jp/list/pathway/hsa"...
# KEGG pathway enrichment for downregulated genes
kegg_down <- enrichKEGG(gene = downregulated_entrez, 
                        organism = "hsa", 
                        pvalueCutoff = 0.05)

# Visualize KEGG pathway results
dotplot(kegg_up, showCategory = 20, title = "KEGG Pathway Enrichment for Upregulated Genes")

dotplot(kegg_down, showCategory = 20, title = "KEGG Pathway Enrichment for Downregulated Genes")


#Reactome Pathway Enrichment

# Reactome pathway enrichment for upregulated genes
reactome_up <- enrichPathway(gene = upregulated_entrez, 
                             organism = "human", 
                             pvalueCutoff = 0.05)

# Reactome pathway enrichment for downregulated genes
reactome_down <- enrichPathway(gene = downregulated_entrez, 
                               organism = "human", 
                               pvalueCutoff = 0.05)

# Visualize Reactome pathways
dotplot(reactome_up, showCategory = 20, title = "Reactome Pathway Enrichment for Upregulated Genes")

dotplot(reactome_down, showCategory = 20, title = "Reactome Pathway Enrichment for Downregulated Genes")



# Gene Set Enrichment Analysis (GSEA) (Optional)
# Create a ranked list of genes
gene_list <- Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC
names(gene_list) <- rownames(Patient_cell_lines_vs_PBMC_Tcells)
gene_list <- sort(gene_list, decreasing = TRUE)

# Convert gene symbols to Entrez IDs
gene_df <- bitr(names(gene_list), fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:many mapping between keys and columns
Warning: 11.19% of input gene IDs are fail to map...
# Ensure the gene list matches the Entrez IDs
gene_list <- gene_list[names(gene_list) %in% gene_df$SYMBOL]

# Replace gene symbols with Entrez IDs
names(gene_list) <- gene_df$ENTREZID[match(names(gene_list), gene_df$SYMBOL)]


# Run GSEA using KEGG
gsea_kegg <- gseKEGG(geneList = gene_list, 
                     organism = "hsa", 
                     pvalueCutoff = 0.05)
using 'fgsea' for GSEA analysis, please cite Korotkevich et al (2019).

preparing geneSet collections...
GSEA analysis...
Warning: There are ties in the preranked stats (0.27% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Warning: There were 1 pathways for which P-values were not calculated properly due to unbalanced (positive and negative) gene-level statistic values. For such pathways pval, padj, NES, log2err are set to NA. You can try to increase the value of the argument nPermSimple (for example set it nPermSimple = 10000)Warning: For some of the pathways the P-values were likely overestimated. For such pathways log2err is set to NA.Warning: For some pathways, in reality P-values are less than 1e-10. You can set the `eps` argument to zero for better estimation.leading edge analysis...
done...
# Plot the GSEA results
gseaplot(gsea_kegg, geneSetID = 1, title = "Top KEGG Pathway")


# Extract the name of the top KEGG pathway
top_pathway <- gsea_kegg@result[1, "Description"]

# Plot GSEA with the top pathway's name as the title
gseaplot(gsea_kegg, geneSetID = 1, title = top_pathway)

NA
NA

5. Bar PLOT

# Filter for significant pathways
top_kegg_up <- kegg_up@result[kegg_up@result$p.adjust < 0.05, ]
top_kegg_down <- kegg_down@result[kegg_down@result$p.adjust < 0.05, ]

# If there are not enough pathways, consider relaxing the threshold or checking the output
top_kegg_up <- top_kegg_up[order(-top_kegg_up$p.adjust), ][1:10, ]
top_kegg_down <- top_kegg_down[order(top_kegg_down$p.adjust), ][1:10, ]

# Combine into one data frame
top_pathways <- rbind(
  data.frame(Pathway = top_kegg_up$Description, p.adjust = top_kegg_up$p.adjust, Direction = "Upregulated"),
  data.frame(Pathway = top_kegg_down$Description, p.adjust = top_kegg_down$p.adjust, Direction = "Downregulated")
)

# Convert p.adjust to -log10(p.adjust) for visualization
top_pathways$neg_log10_p <- -log10(top_pathways$p.adjust)

# Create the barplot
ggplot(top_pathways, aes(x = reorder(Pathway, neg_log10_p), y = neg_log10_p, fill = Direction)) +
  geom_bar(stat = "identity", position = position_dodge()) +
  scale_fill_manual(values = c("Upregulated" = "red", "Downregulated" = "blue")) +
  coord_flip() +  # Flip the coordinates for better readability
  labs(title = "Top Significant Pathways",
       x = "Pathways",
       y = "-Log10 Adjusted P-Value") +
  theme_minimal() +
  theme(legend.title = element_blank())


# Load necessary library
library(ggplot2)

# Create the barplot
ggplot(top_pathways, aes(x = Pathway, y = neg_log10_p, fill = Direction)) +
  geom_bar(stat = "identity", position = "identity") +  # Use position = "identity"
  scale_fill_manual(values = c("Upregulated" = "red", "Downregulated" = "blue")) +
  coord_flip() +  # Flip the coordinates for better readability
  labs(title = "Top Significant Pathways",
       x = "Pathways",
       y = "-Log10 Adjusted P-Value") +
  theme_minimal() +
  theme(legend.title = element_blank())

NA
NA
NA

5. perform gene enrichment analysis and identify pathways

# Load the packages
library(clusterProfiler)
library(org.Hs.eg.db)

# Assuming `significant_genes` is your list of significant gene symbols
significant_genes <- rownames(Patient_cell_lines_vs_PBMC_Tcells[
    (Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5 | 
     Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5) & 
    Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05, ])

entrez_ids <- bitr(significant_genes, fromType = "SYMBOL", 
                   toType = "ENTREZID", 
                   OrgDb = org.Hs.eg.db)
'select()' returned 1:many mapping between keys and columns
Warning: 10.94% of input gene IDs are fail to map...
kegg_results <- enrichKEGG(gene = entrez_ids$ENTREZID,
                           organism = 'hsa',
                           pvalueCutoff = 0.05)

# View results
head(kegg_results)


go_results <- enrichGO(gene = entrez_ids$ENTREZID,
                       OrgDb = org.Hs.eg.db,
                       ont = "BP", # Biological Process
                       pvalueCutoff = 0.05)

# View results
head(go_results)

# Dot plot for KEGG results
dotplot(kegg_results, showCategory=10) + ggtitle("KEGG Pathway Enrichment")


# Dot plot for GO results
dotplot(go_results, showCategory=10) + ggtitle("GO Biological Process Enrichment")

NA
NA

5. ggplot2 for Volcano

library(ggplot2)
library(ggrepel)

# Identify top and bottom genes
top_genes <- Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05 & Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5, ]
bottom_genes <- Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05 & Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5, ]

# Create a new column for color based on significance
Patient_cell_lines_vs_PBMC_Tcells$color <- ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5, "Upregulated genes",
                                                   ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5, "Downregulated genes", "Nonsignificant"))

# Create a volcano plot
ggplot(Patient_cell_lines_vs_PBMC_Tcells, aes(x = avg_log2FC, y = -log10(p_val_adj))) +
  geom_point(aes(color = color), alpha = 0.7, size = 2) +
  
  # Add labels for top and bottom genes
  geom_text_repel(data = top_genes, aes(label = gene), color = "black", vjust = 1, fontface = "bold") +
  geom_text_repel(data = bottom_genes, aes(label = gene), color = "black", vjust = -1, fontface = "bold") +
  
  # Customize labels and title
  labs(title = "Volcano Plot",
       x = "log2 Fold Change",
       y = "-log10(p-value)") +
  
  # Add significance threshold lines
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black") +
  geom_vline(xintercept = c(-1.5, 2), linetype = "dashed", color = "black") +
  
  # Set colors for top and bottom genes
  scale_color_manual(values = c("Upregulated genes" = "red", "Downregulated genes" = "blue", "Nonsignificant" = "darkgrey")) +
  
  # Customize theme if needed
  theme_minimal()

NA
NA
NA
NA
NA
LS0tCnRpdGxlOiAiRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMgb2YgU1MgdnMgUEJNQzEwWCtQQk1DIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KEF6aW11dGgpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQpgYGAKCiMgMi4gTG9hZCBTZXVyYXQgT2JqZWN0IApgYGB7ciBsb2FkX3NldXJhdCwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9Cgpsb2FkICgiL2hvbWUvYmlvaW5mby8wLWltcF9Sb2JqL0hhcm1vbnlfaW50ZWdyYXRlZF9BbGxfc2FtcGxlc19NZXJnZWRfd2l0aF9QQk1DMTB4X3dpdGhfaGFybW9ueV9jbHVzdGVyaW5nLlJvYmoiKQogCgpgYGAKCgojIDIuIEluaXRpYWwgVmlzdWFsaXphdGlvbgpgYGB7ciBWLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gU2V0SWRlbnQoQWxsX3NhbXBsZXNfTWVyZ2VkLCB2YWx1ZSA9ICJIYXJtb255X3Nubl9yZXMuMC45IikKICAKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLAogICAgICAgIGdyb3VwLmJ5ID0gIkhhcm1vbnlfc25uX3Jlcy4wLjkiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBUKQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMiIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwKICAgICAgICBsYWJlbCA9IFQpCgpgYGAKCiMgMy4gUGVyZm9ybSBERSBhbmFseXNpcyB1c2luZyB0aGUgRmluZE1hcmtlcnMgCmBgYHtyIGRhdGExLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gU2V0SWRlbnQoQWxsX3NhbXBsZXNfTWVyZ2VkLCB2YWx1ZSA9ICJIYXJtb255X3Nubl9yZXMuMC45IikKClBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyA8LSBGaW5kTWFya2VycyhBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4xID0gYygiMyIsICI4IiwgIjEwIiwgIjE4IiwgIjEiLCAiMiIsICIxMyIsICI2IiwgIjE2IiwgIjE5IiwgIjQiLCAiNyIsICI5IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50LjIgPSBjKCIwIiwgIjUiLCAiMTQiLCAiMjQiLCAiMjAiKQogICAgICAgICAgICAgICAgICAgICAgICAgICApCgoKCiMgQ29udmVydCB0byBkYXRhIGZyYW1lIGFuZCBhZGQgZ2VuZSBuYW1lcyBhcyBhIG5ldyBjb2x1bW4KUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzIDwtIGFzLmRhdGEuZnJhbWUoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKQpQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkZ2VuZSA8LSByb3duYW1lcyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMpCgojIFJlYXJyYW5naW5nIHRoZSBjb2x1bW5zIGZvciBiZXR0ZXIgcmVhZGFiaWxpdHkgKG9wdGlvbmFsKQpQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMgPC0gUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzWywgYygiZ2VuZSIsICJwX3ZhbCIsICJhdmdfbG9nMkZDIiwgInBjdC4xIiwgInBjdC4yIiwgInBfdmFsX2FkaiIpXQoKI3dyaXRlLmNzdihQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMsICJQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgoKYGBgCgpgYGB7ciBlbmhhbmNlZFYsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNn0KCkVuaGFuY2VkVm9sY2FubyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMgLCAKICAgICAgICAgICAgICAgIGxhYj1yb3duYW1lcyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMpLAogICAgICAgICAgICAgICAgeCA9ImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSJwX3ZhbF9hZGoiLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiU8OpemFyeSBDZWxsIExpbmVzIHZzIFBCTUMgVCBjZWxscyIsCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gMS41LCAKICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ3JpZ2h0JywgCiAgICAgICAgICAgICAgICBsYWJDb2wgPSAnYmxhY2snLAogICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDMuMCwKICAgICAgICAgICAgICAgIGxhYlNpemUgPSA1LjAsIAogICAgICAgICAgICAgICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgd2lkdGhDb25uZWN0b3JzID0gMC4yNSkKCgoKCkVuaGFuY2VkVm9sY2FubyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMsIAogICAgICAgICAgICAgICAgbGFiID0gaWZlbHNlKChQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA+IDEuNSB8IFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDIDwgLTEuNSkgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkcF92YWxfYWRqIDwgMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiIpLCAgIyBMYWJlbCBvbmx5IHNpZ25pZmljYW50IGdlbmVzCiAgICAgICAgICAgICAgICB4ID0gImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHRpdGxlID0gIlPDqXphcnkgQ2VsbCBMaW5lcyB2cyBQQk1DIFQgY2VsbHMiLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEuNSwgCiAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsIAogICAgICAgICAgICAgICAgbGFiQ29sID0gJ2JsYWNrJywKICAgICAgICAgICAgICAgIGxhYkZhY2UgPSAnYm9sZCcsCiAgICAgICAgICAgICAgICBib3hlZExhYmVscyA9IFRSVUUsCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gNS4wLCAKICAgICAgICAgICAgICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgICAgICAgICAgICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuMjUpCgoKCkVuaGFuY2VkVm9sY2FubyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMsIAogICAgICAgICAgICAgICAgbGFiID0gUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGdlbmUsCiAgICAgICAgICAgICAgICB4ID0gImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHNlbGVjdExhYiA9IGMoJ0VQQ0FNJywgJ0JDQVQxJywgJ0tJUjNETDInLCAnRk9YTTEnLCAnVFdJU1QxJywgJ1RORlNGOScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQ0Q4MCcsICAnSUwxQicsICdUUkJWNy42JywgJ1RSQlY1LjQnLCAnVFJCVjEyLjQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVUJFMkMnLCAnUENMQUYnLCAnVFlNUycsICdDREMyMCcsICdSUFM0WTEnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0lMN1InLCAnVENGNycsICdQVFRHMScsICdSUk0yJywgJ01LSTY3JywgJ0NENzAnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0lMMlJBJywnVFJCVjYtMicsICdUUkJWMTAtMycsICdUUkJWNC0yJywgJ1RSQlY5JywgJ1RSQlY3LTknLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RSQVYxMi0xJywgJ0NEOEInLCAnRkNHUjNBJywgJ0dOTFknLCAnRk9YUDMnLCAnU0VMTCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnR0lNQVAxJywgJ1JJUE9SMicsICdMRUYxJywgJ0hPWEM5JywgJ1NQNScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDQ0wxNycsICdFVFY0JywgJ1RIWTEnLCAnRk9YQTInLCAnSVRHQUQnLCAnUzEwMFAnLCAnVEJYNCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUQxJywgJ1hDTDEnLCAnU09YMicsICdDRDI3JywgJ0NEMjgnLCdQTFMzJywnQ0Q3MCcsJ1JBQjI1JyAsICdUUkJWMjcnLCAnVFJCVjInKSwKICAgICAgICAgICAgICAgIHRpdGxlID0gIlPDqXphcnkgQ2VsbCBMaW5lcyB2cyBQQk1DIFQgY2VsbHMiLAogICAgICAgICAgICAgICAgeGxhYiA9IGJxdW90ZSh+TG9nWzJdfiAnZm9sZCBjaGFuZ2UnKSwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLjUsIAogICAgICAgICAgICAgICAgcG9pbnRTaXplID0gMy4wLAogICAgICAgICAgICAgICAgbGFiU2l6ZSA9IDUuMCwKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIGNvbEFscGhhID0gMC41LAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAncmlnaHQnLAogICAgICAgICAgICAgICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjUsCiAgICAgICAgICAgICAgICBjb2xDb25uZWN0b3JzID0gJ2dyZXk1MCcsCiAgICAgICAgICAgICAgICBhcnJvd2hlYWRzID0gRkFMU0UsCiAgICAgICAgICAgICAgICBtYXgub3ZlcmxhcHMgPSAzMCkKCmBgYAoKIyA0LiBFbnJpY2htZW50IEFuYWx5c2lzCmBgYHtyIGRhdGEyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTZ9CgojU3RlcC1ieS1TdGVwIEd1aWRlIGZvciBHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKSBvciBPdmVyLVJlcHJlc2VudGF0aW9uIEFuYWx5c2lzIChPUkEpCgojIExvYWQgdGhlIHBhY2thZ2VzCmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KG9yZy5Icy5lZy5kYikKbGlicmFyeShlbnJpY2hwbG90KQpsaWJyYXJ5KFJlYWN0b21lUEEpCgoKIyBHZXQgdXByZWd1bGF0ZWQgZ2VuZXMKdXByZWd1bGF0ZWRfZ2VuZXMgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzW1BhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDID4gMS41ICYgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUsIF0pCgojIEdldCBkb3ducmVndWxhdGVkIGdlbmVzCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzW1BhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDIDwgLTEuNSAmIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdKQoKI0dlbmUgT250b2xvZ3kgKEdPKSBFbnJpY2htZW50IEFuYWx5c2lzCiMgR08gZW5yaWNobWVudCBmb3IgdXByZWd1bGF0ZWQgZ2VuZXMKZ29fdXAgPC0gZW5yaWNoR08oZ2VuZSA9IHVwcmVndWxhdGVkX2dlbmVzLCAKICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIlNZTUJPTCIsIAogICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAgICMgIkJQIiBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMsICJNRiIgZm9yIE1vbGVjdWxhciBGdW5jdGlvbiwgIkNDIiBmb3IgQ2VsbHVsYXIgQ29tcG9uZW50CiAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgR08gZW5yaWNobWVudCBmb3IgZG93bnJlZ3VsYXRlZCBnZW5lcwpnb19kb3duIDwtIGVucmljaEdPKGdlbmUgPSBkb3ducmVndWxhdGVkX2dlbmVzLCAKICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJTWU1CT0wiLCAKICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAKICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgVmlzdWFsaXplIHRoZSB0b3AgZW5yaWNoZWQgR08gdGVybXMKZG90cGxvdChnb191cCwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIkdPIEVucmljaG1lbnQgZm9yIFVwcmVndWxhdGVkIEdlbmVzIikKZG90cGxvdChnb19kb3duLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiR08gRW5yaWNobWVudCBmb3IgRG93bnJlZ3VsYXRlZCBHZW5lcyIpCgojS0VHRyBQYXRod2F5IEVucmljaG1lbnQKIyBDb252ZXJ0IGdlbmUgc3ltYm9scyB0byBFbnRyZXogSURzIGZvciBLRUdHIGFuYWx5c2lzCnVwcmVndWxhdGVkX2VudHJleiA8LSBiaXRyKHVwcmVndWxhdGVkX2dlbmVzLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikkRU5UUkVaSUQKZG93bnJlZ3VsYXRlZF9lbnRyZXogPC0gYml0cihkb3ducmVndWxhdGVkX2dlbmVzLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikkRU5UUkVaSUQKCiMgS0VHRyBwYXRod2F5IGVucmljaG1lbnQgZm9yIHVwcmVndWxhdGVkIGdlbmVzCmtlZ2dfdXAgPC0gZW5yaWNoS0VHRyhnZW5lID0gdXByZWd1bGF0ZWRfZW50cmV6LCAKICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYSIsIAogICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgS0VHRyBwYXRod2F5IGVucmljaG1lbnQgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMKa2VnZ19kb3duIDwtIGVucmljaEtFR0coZ2VuZSA9IGRvd25yZWd1bGF0ZWRfZW50cmV6LCAKICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpc3VhbGl6ZSBLRUdHIHBhdGh3YXkgcmVzdWx0cwpkb3RwbG90KGtlZ2dfdXAsIHNob3dDYXRlZ29yeSA9IDIwLCB0aXRsZSA9ICJLRUdHIFBhdGh3YXkgRW5yaWNobWVudCBmb3IgVXByZWd1bGF0ZWQgR2VuZXMiKQpkb3RwbG90KGtlZ2dfZG93biwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIktFR0cgUGF0aHdheSBFbnJpY2htZW50IGZvciBEb3ducmVndWxhdGVkIEdlbmVzIikKCiNSZWFjdG9tZSBQYXRod2F5IEVucmljaG1lbnQKCiMgUmVhY3RvbWUgcGF0aHdheSBlbnJpY2htZW50IGZvciB1cHJlZ3VsYXRlZCBnZW5lcwpyZWFjdG9tZV91cCA8LSBlbnJpY2hQYXRod2F5KGdlbmUgPSB1cHJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImh1bWFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgUmVhY3RvbWUgcGF0aHdheSBlbnJpY2htZW50IGZvciBkb3ducmVndWxhdGVkIGdlbmVzCnJlYWN0b21lX2Rvd24gPC0gZW5yaWNoUGF0aHdheShnZW5lID0gZG93bnJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHVtYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpc3VhbGl6ZSBSZWFjdG9tZSBwYXRod2F5cwpkb3RwbG90KHJlYWN0b21lX3VwLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiUmVhY3RvbWUgUGF0aHdheSBFbnJpY2htZW50IGZvciBVcHJlZ3VsYXRlZCBHZW5lcyIpCmRvdHBsb3QocmVhY3RvbWVfZG93biwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIlJlYWN0b21lIFBhdGh3YXkgRW5yaWNobWVudCBmb3IgRG93bnJlZ3VsYXRlZCBHZW5lcyIpCgoKIyBHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKSAoT3B0aW9uYWwpCiMgQ3JlYXRlIGEgcmFua2VkIGxpc3Qgb2YgZ2VuZXMKZ2VuZV9saXN0IDwtIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDCm5hbWVzKGdlbmVfbGlzdCkgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKQpnZW5lX2xpc3QgPC0gc29ydChnZW5lX2xpc3QsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBDb252ZXJ0IGdlbmUgc3ltYm9scyB0byBFbnRyZXogSURzCmdlbmVfZGYgPC0gYml0cihuYW1lcyhnZW5lX2xpc3QpLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikKCiMgRW5zdXJlIHRoZSBnZW5lIGxpc3QgbWF0Y2hlcyB0aGUgRW50cmV6IElEcwpnZW5lX2xpc3QgPC0gZ2VuZV9saXN0W25hbWVzKGdlbmVfbGlzdCkgJWluJSBnZW5lX2RmJFNZTUJPTF0KCiMgUmVwbGFjZSBnZW5lIHN5bWJvbHMgd2l0aCBFbnRyZXogSURzCm5hbWVzKGdlbmVfbGlzdCkgPC0gZ2VuZV9kZiRFTlRSRVpJRFttYXRjaChuYW1lcyhnZW5lX2xpc3QpLCBnZW5lX2RmJFNZTUJPTCldCgoKIyBSdW4gR1NFQSB1c2luZyBLRUdHCmdzZWFfa2VnZyA8LSBnc2VLRUdHKGdlbmVMaXN0ID0gZ2VuZV9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhIiwgCiAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFBsb3QgdGhlIEdTRUEgcmVzdWx0cwpnc2VhcGxvdChnc2VhX2tlZ2csIGdlbmVTZXRJRCA9IDEsIHRpdGxlID0gIlRvcCBLRUdHIFBhdGh3YXkiKQoKIyBFeHRyYWN0IHRoZSBuYW1lIG9mIHRoZSB0b3AgS0VHRyBwYXRod2F5CnRvcF9wYXRod2F5IDwtIGdzZWFfa2VnZ0ByZXN1bHRbMSwgIkRlc2NyaXB0aW9uIl0KCiMgUGxvdCBHU0VBIHdpdGggdGhlIHRvcCBwYXRod2F5J3MgbmFtZSBhcyB0aGUgdGl0bGUKZ3NlYXBsb3QoZ3NlYV9rZWdnLCBnZW5lU2V0SUQgPSAxLCB0aXRsZSA9IHRvcF9wYXRod2F5KQoKCmBgYAoKIyA1LiBCYXIgUExPVApgYGB7ciBkYXRhMywgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgRmlsdGVyIGZvciBzaWduaWZpY2FudCBwYXRod2F5cwp0b3Bfa2VnZ191cCA8LSBrZWdnX3VwQHJlc3VsdFtrZWdnX3VwQHJlc3VsdCRwLmFkanVzdCA8IDAuMDUsIF0KdG9wX2tlZ2dfZG93biA8LSBrZWdnX2Rvd25AcmVzdWx0W2tlZ2dfZG93bkByZXN1bHQkcC5hZGp1c3QgPCAwLjA1LCBdCgojIElmIHRoZXJlIGFyZSBub3QgZW5vdWdoIHBhdGh3YXlzLCBjb25zaWRlciByZWxheGluZyB0aGUgdGhyZXNob2xkIG9yIGNoZWNraW5nIHRoZSBvdXRwdXQKdG9wX2tlZ2dfdXAgPC0gdG9wX2tlZ2dfdXBbb3JkZXIoLXRvcF9rZWdnX3VwJHAuYWRqdXN0KSwgXVsxOjEwLCBdCnRvcF9rZWdnX2Rvd24gPC0gdG9wX2tlZ2dfZG93bltvcmRlcih0b3Bfa2VnZ19kb3duJHAuYWRqdXN0KSwgXVsxOjEwLCBdCgojIENvbWJpbmUgaW50byBvbmUgZGF0YSBmcmFtZQp0b3BfcGF0aHdheXMgPC0gcmJpbmQoCiAgZGF0YS5mcmFtZShQYXRod2F5ID0gdG9wX2tlZ2dfdXAkRGVzY3JpcHRpb24sIHAuYWRqdXN0ID0gdG9wX2tlZ2dfdXAkcC5hZGp1c3QsIERpcmVjdGlvbiA9ICJVcHJlZ3VsYXRlZCIpLAogIGRhdGEuZnJhbWUoUGF0aHdheSA9IHRvcF9rZWdnX2Rvd24kRGVzY3JpcHRpb24sIHAuYWRqdXN0ID0gdG9wX2tlZ2dfZG93biRwLmFkanVzdCwgRGlyZWN0aW9uID0gIkRvd25yZWd1bGF0ZWQiKQopCgojIENvbnZlcnQgcC5hZGp1c3QgdG8gLWxvZzEwKHAuYWRqdXN0KSBmb3IgdmlzdWFsaXphdGlvbgp0b3BfcGF0aHdheXMkbmVnX2xvZzEwX3AgPC0gLWxvZzEwKHRvcF9wYXRod2F5cyRwLmFkanVzdCkKCiMgQ3JlYXRlIHRoZSBiYXJwbG90CmdncGxvdCh0b3BfcGF0aHdheXMsIGFlcyh4ID0gcmVvcmRlcihQYXRod2F5LCBuZWdfbG9nMTBfcCksIHkgPSBuZWdfbG9nMTBfcCwgZmlsbCA9IERpcmVjdGlvbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVXByZWd1bGF0ZWQiID0gInJlZCIsICJEb3ducmVndWxhdGVkIiA9ICJibHVlIikpICsKICBjb29yZF9mbGlwKCkgKyAgIyBGbGlwIHRoZSBjb29yZGluYXRlcyBmb3IgYmV0dGVyIHJlYWRhYmlsaXR5CiAgbGFicyh0aXRsZSA9ICJUb3AgU2lnbmlmaWNhbnQgUGF0aHdheXMiLAogICAgICAgeCA9ICJQYXRod2F5cyIsCiAgICAgICB5ID0gIi1Mb2cxMCBBZGp1c3RlZCBQLVZhbHVlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQoKIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJ5CmxpYnJhcnkoZ2dwbG90MikKCiMgQ3JlYXRlIHRoZSBiYXJwbG90CmdncGxvdCh0b3BfcGF0aHdheXMsIGFlcyh4ID0gUGF0aHdheSwgeSA9IG5lZ19sb2cxMF9wLCBmaWxsID0gRGlyZWN0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsgICMgVXNlIHBvc2l0aW9uID0gImlkZW50aXR5IgogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIlVwcmVndWxhdGVkIiA9ICJyZWQiLCAiRG93bnJlZ3VsYXRlZCIgPSAiYmx1ZSIpKSArCiAgY29vcmRfZmxpcCgpICsgICMgRmxpcCB0aGUgY29vcmRpbmF0ZXMgZm9yIGJldHRlciByZWFkYWJpbGl0eQogIGxhYnModGl0bGUgPSAiVG9wIFNpZ25pZmljYW50IFBhdGh3YXlzIiwKICAgICAgIHggPSAiUGF0aHdheXMiLAogICAgICAgeSA9ICItTG9nMTAgQWRqdXN0ZWQgUC1WYWx1ZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCgoKYGBgCgojIDUuIHBlcmZvcm0gZ2VuZSBlbnJpY2htZW50IGFuYWx5c2lzIGFuZCBpZGVudGlmeSBwYXRod2F5cwpgYGB7ciBkYXRhNCwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgTG9hZCB0aGUgcGFja2FnZXMKbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpCmxpYnJhcnkob3JnLkhzLmVnLmRiKQoKIyBBc3N1bWluZyBgc2lnbmlmaWNhbnRfZ2VuZXNgIGlzIHlvdXIgbGlzdCBvZiBzaWduaWZpY2FudCBnZW5lIHN5bWJvbHMKc2lnbmlmaWNhbnRfZ2VuZXMgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzWwogICAgKFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDID4gMS41IHwgCiAgICAgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPCAtMS41KSAmIAogICAgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUsIF0pCgplbnRyZXpfaWRzIDwtIGJpdHIoc2lnbmlmaWNhbnRfZ2VuZXMsIGZyb21UeXBlID0gIlNZTUJPTCIsIAogICAgICAgICAgICAgICAgICAgdG9UeXBlID0gIkVOVFJFWklEIiwgCiAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYikKCmtlZ2dfcmVzdWx0cyA8LSBlbnJpY2hLRUdHKGdlbmUgPSBlbnRyZXpfaWRzJEVOVFJFWklELAogICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICdoc2EnLAogICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1KQoKIyBWaWV3IHJlc3VsdHMKaGVhZChrZWdnX3Jlc3VsdHMpCgoKZ29fcmVzdWx0cyA8LSBlbnJpY2hHTyhnZW5lID0gZW50cmV6X2lkcyRFTlRSRVpJRCwKICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwKICAgICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAjIEJpb2xvZ2ljYWwgUHJvY2VzcwogICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpZXcgcmVzdWx0cwpoZWFkKGdvX3Jlc3VsdHMpCgojIERvdCBwbG90IGZvciBLRUdHIHJlc3VsdHMKZG90cGxvdChrZWdnX3Jlc3VsdHMsIHNob3dDYXRlZ29yeT0xMCkgKyBnZ3RpdGxlKCJLRUdHIFBhdGh3YXkgRW5yaWNobWVudCIpCgojIERvdCBwbG90IGZvciBHTyByZXN1bHRzCmRvdHBsb3QoZ29fcmVzdWx0cywgc2hvd0NhdGVnb3J5PTEwKSArIGdndGl0bGUoIkdPIEJpb2xvZ2ljYWwgUHJvY2VzcyBFbnJpY2htZW50IikKCgpgYGAKCgojIDUuIGdncGxvdDIgZm9yIFZvbGNhbm8KYGBge3IgZGF0YTUsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyZXBlbCkKCiMgSWRlbnRpZnkgdG9wIGFuZCBib3R0b20gZ2VuZXMKdG9wX2dlbmVzIDwtIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxsc1tQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkcF92YWxfYWRqIDwgMC4wNSAmIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDID4gMS41LCBdCmJvdHRvbV9nZW5lcyA8LSBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHNbUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUgJiBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsIF0KCiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBmb3IgY29sb3IgYmFzZWQgb24gc2lnbmlmaWNhbmNlClBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRjb2xvciA8LSBpZmVsc2UoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPiAxLjUsICJVcHJlZ3VsYXRlZCBnZW5lcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsICJEb3ducmVndWxhdGVkIGdlbmVzIiwgIk5vbnNpZ25pZmljYW50IikpCgojIENyZWF0ZSBhIHZvbGNhbm8gcGxvdApnZ3Bsb3QoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzLCBhZXMoeCA9IGF2Z19sb2cyRkMsIHkgPSAtbG9nMTAocF92YWxfYWRqKSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGNvbG9yKSwgYWxwaGEgPSAwLjcsIHNpemUgPSAyKSArCiAgCiAgIyBBZGQgbGFiZWxzIGZvciB0b3AgYW5kIGJvdHRvbSBnZW5lcwogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gdG9wX2dlbmVzLCBhZXMobGFiZWwgPSBnZW5lKSwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IDEsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSBib3R0b21fZ2VuZXMsIGFlcyhsYWJlbCA9IGdlbmUpLCBjb2xvciA9ICJibGFjayIsIHZqdXN0ID0gLTEsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgCiAgIyBDdXN0b21pemUgbGFiZWxzIGFuZCB0aXRsZQogIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90IiwKICAgICAgIHggPSAibG9nMiBGb2xkIENoYW5nZSIsCiAgICAgICB5ID0gIi1sb2cxMChwLXZhbHVlKSIpICsKICAKICAjIEFkZCBzaWduaWZpY2FuY2UgdGhyZXNob2xkIGxpbmVzCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0xLjUsIDIpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsKICAKICAjIFNldCBjb2xvcnMgZm9yIHRvcCBhbmQgYm90dG9tIGdlbmVzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlVwcmVndWxhdGVkIGdlbmVzIiA9ICJyZWQiLCAiRG93bnJlZ3VsYXRlZCBnZW5lcyIgPSAiYmx1ZSIsICJOb25zaWduaWZpY2FudCIgPSAiZGFya2dyZXkiKSkgKwogIAogICMgQ3VzdG9taXplIHRoZW1lIGlmIG5lZWRlZAogIHRoZW1lX21pbmltYWwoKQoKCgoKCmBgYAoKCgoK