1. load libraries

2. Enrichment Analysis_part1

# Load necessary libraries ------------------------------------


# Read the TSV file into R
Significant_Genes <- read_csv("/home/bioinfo/18-Enrichment_Analysis_final_Results/NewFiles/All_Results_Together_for_Enrichment/Cell_lines_vs_control/filtered_data_Cell_lines_vs_CD4Tcells.csv")
Rows: 746 Columns: 9── Column specification ────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): gene
dbl (8): mean_All_cell_lines_cells, mean_PBMC_CD4T_cells, Relative_variance_All_cell_lines_cells, Relative_varia...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
SS_up  <- subset(Significant_Genes,
                    Significant_Genes$log2FC > 3
                      & Significant_Genes$pValueBH <  0.05)
SS_up_genes <- SS_up$gene


SS_down  <- subset(Significant_Genes,
                    Significant_Genes$log2FC < -1 
                      & Significant_Genes$pValueBH <  0.05)
SS_down_genes <- SS_down$gene


SS_vs_norm_go <- clusterProfiler::enrichGO(SS_up_genes,
                                            "org.Hs.eg.db",
                                            keyType = "SYMBOL",
                                            ont = "BP",
                                            minGSSize = 50)

print(SS_vs_norm_go@result)

enr_go <- clusterProfiler::simplify(SS_vs_norm_go)

print(enr_go@result)

enrichplot::emapplot(enrichplot::pairwise_termsim(enr_go),
                     showCategory = 50)



SS_vs_norm_go <- clusterProfiler::enrichGO(SS_down_genes,
                                            "org.Hs.eg.db",
                                            keyType = "SYMBOL",
                                            ont = "BP",
                                            minGSSize = 50)

print(SS_vs_norm_go@result)

enr_go <- clusterProfiler::simplify(SS_vs_norm_go)

print(enr_go@result)

enrichplot::emapplot(enrichplot::pairwise_termsim(enr_go),
                     showCategory = 50)

NA
NA

3. Enrichment Analysis_part2

gmt <- msigdbr::msigdbr(species = "human", category = "H")

SS_vs_norm_enrich_up <- clusterProfiler::enricher(gene = SS_up_genes,
                                                pAdjustMethod = "BH",
                                                pvalueCutoff  = 0.05,
                                                qvalueCutoff  = 0.05,
                                                TERM2GENE = gmt[,c("gs_name", "gene_symbol")])


print(SS_vs_norm_enrich_up@result[SS_vs_norm_enrich_up@result$p.adjust < 0.05,])


SS_vs_norm_enrich_down <- clusterProfiler::enricher(gene = SS_down_genes,
                                                pAdjustMethod = "BH",
                                                pvalueCutoff  = 0.05,
                                                qvalueCutoff  = 0.05,
                                                TERM2GENE = gmt[,c("gs_name", "gene_symbol")])


print(SS_vs_norm_enrich_down@result[SS_vs_norm_enrich_down@result$p.adjust < 0.05,])
NA

4. Enrichment Analysis_part3

# We use the function `barplot` from package `enrichplot`
graphics::barplot(
  # We provide the variable pointing to enrichment results
  height = SS_vs_norm_enrich_up,
  # We display the best 15 results
  showCategory=15
)



enrichplot::dotplot(
  # We provide the variable pointing to enrichment results
  object = SS_vs_norm_enrich_up,
  # We display the best 15 results
  showCategory=15
)

# We use the function `barplot` from package `enrichplot`
graphics::barplot(
  # We provide the variable pointing to enrichment results
  height = SS_vs_norm_enrich_down,
  # We display the best 15 results
  showCategory=15
)



enrichplot::dotplot(
  # We provide the variable pointing to enrichment results
  object = SS_vs_norm_enrich_down,
  # We display the best 15 results
  showCategory=15
)

5. Enrichment Analysis_part5


# We use the function `heatplot` from `enrichplot` package
# We use the function `upsetplot` from `enrichplot` package
enrichplot::upsetplot(
  # We probide the variable pointing to GSEA results
  x = SS_vs_norm_enrich_up,
  # We show the 10 best results
  n = 10
)


enrichplot::upsetplot(
  # We probide the variable pointing to GSEA results
  x = SS_vs_norm_enrich_down,
  # We show the 10 best results
  n = 10
)

6. Enrichment Analysis_part6


# Load the packages
library(clusterProfiler)
clusterProfiler v4.14.4 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(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
library(org.Hs.eg.db)
Loading required package: AnnotationDbi
Loading required package: stats4
Loading required package: BiocGenerics

Attaching package: ‘BiocGenerics’

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(pathview)
##############################################################################
Pathview is an open source software package distributed under GNU General
Public License version 3 (GPLv3). Details of GPLv3 is available at
http://www.gnu.org/licenses/gpl-3.0.html. Particullary, users are required to
formally cite the original Pathview paper (not just mention it) in publications
or products. For details, do citation("pathview") within R.

The pathview downloads and uses KEGG data. Non-academic uses may require a KEGG
license agreement (details at http://www.kegg.jp/kegg/legal.html).
##############################################################################
# Extract the gene symbols and log2FC values for SS_up
gene_list_up <- as.character(SS_up$gene)
log2fc_values_up <- SS_up$log2FC

# Get a list of valid gene symbols from org.Hs.eg.db
valid_symbols <- keys(org.Hs.eg.db, keytype = "SYMBOL")

# Check which gene symbols are not valid
invalid_symbols_up <- setdiff(gene_list_up, valid_symbols)

# Print invalid gene symbols
if (length(invalid_symbols_up) > 0) {
    cat("The following gene symbols are not valid and will be excluded from SS_up:\n")
    print(invalid_symbols_up)
}
The following gene symbols are not valid and will be excluded from SS_up:
 [1] "C19orf48"    "H2AFX"       "WARS"        "VARS"        "WDR34"       "HLA.DMA"     "PALM2.AKAP2" "FAM126A"    
 [9] "AC016747.1"  "CD3EAP"      "AL441992.1"  "C3orf14"     "HLA.DMB"     "ARNTL2"      "AC006064.4"  "AC011603.2" 
[17] "BHLHE40.AS1" "AC093865.1"  "HLA.DPB1"    "HIST1H2AL"   "MSC.AS1"     "HLA.DRB5"    "HLA.DQB1"    "AL590550.1" 
[25] "HIST1H3B"    "AC010967.1"  "HLA.DPA1"    "HIST1H1A"    "HLA.DRA"     "TRBV23.1"    "HLA.DQA1"    "HLA.DRB1"   
[33] "HIST1H1B"    "SLC7A11.AS1" "HLA.DQA2"    "TRAV38.2DV8"
# Filter out invalid gene symbols
gene_list_up <- intersect(gene_list_up, valid_symbols)

# Convert gene symbols to Entrez IDs
entrez_ids_up <- bitr(gene_list_up, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
# Check for successful conversion
if (nrow(entrez_ids_up) == 0) {
    stop("No gene symbols were converted to Entrez IDs for SS_up.")
}

# Merge Entrez IDs with log2FC values
entrez_ids_up <- merge(entrez_ids_up, SS_up, by.x = "SYMBOL", by.y = "gene")

# Create a named vector of log2FC values with Entrez IDs as names
gene_data_up <- setNames(entrez_ids_up$log2FC, entrez_ids_up$ENTREZID)

7. Enrichment Analysis_part7


# Perform GO enrichment analysis
ego <- enrichGO(gene = entrez_ids_up$ENTREZID,
                OrgDb = org.Hs.eg.db,
                keyType = "ENTREZID",
                ont = "BP",  # "BP" for Biological Process
                pAdjustMethod = "BH",
                pvalueCutoff = 0.05,
                qvalueCutoff = 0.2)

# Perform KEGG pathway enrichment analysis
ekegg <- enrichKEGG(gene = entrez_ids_up$ENTREZID,
                    organism = "hsa",
                    pvalueCutoff = 0.001)


# Perform Reactome pathway enrichment analysis
reactome <- enrichPathway(gene = entrez_ids_up$ENTREZID,
                          organism = "human",
                          pvalueCutoff = 0.05)


# Visualize GO enrichment results
barplot(ego, showCategory = 10)

dotplot(ego, showCategory = 10)


# Visualize KEGG pathway enrichment results
barplot(ekegg, showCategory = 30)

dotplot(ekegg, showCategory = 30)


# Visualize Reactome pathway enrichment results
barplot(reactome, showCategory = 10)

dotplot(reactome, showCategory = 10)


# Pathway visualization with pathview
# Example: Visualize KEGG pathway hsa04010 (replace with your pathway of interest)
pathway_up <- pathview(gene.data = as.numeric(entrez_ids_up$ENTREZID),
         pathway.id = "hsa05200", # Example KEGG pathway ID
         species = "hsa")
Warning: None of the genes or compounds mapped to the pathway!
Argument gene.idtype or cpd.idtype may be wrong.
'select()' returned 1:1 mapping between keys and columns
Info: Working in directory /home/bioinfo/17-SingleCellFCscanner
Info: Writing image file hsa05200.pathview.png
pathway_up
$plot.data.gene

$plot.data.cpd
NA

8. Enrichment Analysis_part8

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

# Extract the gene symbols and log2FC values for SS_down
gene_list_down <- as.character(SS_down$gene)
log2fc_values_down <- SS_down$log2FC

# Check which gene symbols are not valid
invalid_symbols_down <- setdiff(gene_list_down, valid_symbols)

# Print invalid gene symbols
if (length(invalid_symbols_down) > 0) {
    cat("The following gene symbols are not valid and will be excluded from SS_down:\n")
    print(invalid_symbols_down)
}
The following gene symbols are not valid and will be excluded from SS_down:
[1] "TMEM8A"     "PCED1B.AS1" "AC243960.1" "AC139720.1" "AC119396.1"
# Filter out invalid gene symbols
gene_list_down <- intersect(gene_list_down, valid_symbols)

# Convert gene symbols to Entrez IDs
entrez_ids_down <- bitr(gene_list_down, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:1 mapping between keys and columns
# Check for successful conversion
if (nrow(entrez_ids_down) == 0) {
    stop("No gene symbols were converted to Entrez IDs for SS_down.")
}

# Merge Entrez IDs with log2FC values
entrez_ids_down <- merge(entrez_ids_down, SS_down, by.x = "SYMBOL", by.y = "gene")

# Create a named vector of log2FC values with Entrez IDs as names
gene_data_down <- setNames(entrez_ids_down$log2FC, entrez_ids_down$ENTREZID)

9. Enrichment Analysis_part9

# Install necessary packages if they are not already installed
if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager")
BiocManager::install(c("pathview", "IRdisplay"))
'getOption("repos")' replaces Bioconductor standard repositories, see 'help("repositories", package =
"BiocManager")' for details.
Replacement repositories:
    CRAN: https://cloud.r-project.org
Bioconductor version 3.20 (BiocManager 1.30.25), R 4.4.2 (2024-10-31)
Warning: package(s) not installed when version(s) same as or greater than current; use `force = TRUE` to re-install:
  'pathview'Installing package(s) 'IRdisplay'
also installing the dependency ‘repr’

trying URL 'https://cloud.r-project.org/src/contrib/repr_1.1.7.tar.gz'
Content type 'application/x-gzip' length 32736 bytes (31 KB)
==================================================
downloaded 31 KB

trying URL 'https://cloud.r-project.org/src/contrib/IRdisplay_1.1.tar.gz'
Content type 'application/x-gzip' length 8286 bytes
==================================================
downloaded 8286 bytes

* installing *source* package ‘repr’ ...
** package ‘repr’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (repr)
* installing *source* package ‘IRdisplay’ ...
** package ‘IRdisplay’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (IRdisplay)

The downloaded source packages are in
    ‘/tmp/RtmpzBOl8G/downloaded_packages’
Installation paths not writeable, unable to update packages
  path: /usr/local/lib/R/site-library
  packages:
    BiocVersion
Old packages: 'argparse'
Update all/some/none? [a/s/n]: 
a
trying URL 'https://cloud.r-project.org/src/contrib/argparse_2.2.5.tar.gz'
Content type 'application/x-gzip' length 36066 bytes (35 KB)
==================================================
downloaded 35 KB

* installing *source* package ‘argparse’ ...
** package ‘argparse’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** exec
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
*** copying figures
** building package indices
** installing vignettes
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (argparse)

The downloaded source packages are in
    ‘/tmp/RtmpzBOl8G/downloaded_packages’
# Load the required packages
library(pathview)
library(IRdisplay)


# Perform GO enrichment analysis
ego_down <- enrichGO(gene = entrez_ids_down$ENTREZID,
                     OrgDb = org.Hs.eg.db,
                     keyType = "ENTREZID",
                     ont = "BP",  # "BP" for Biological Process
                     pAdjustMethod = "BH",
                     pvalueCutoff = 0.05,
                     qvalueCutoff = 0.2)

ekegg_down <- enrichKEGG(
  gene         = entrez_ids_down$ENTREZID,  # Your list of gene IDs
  organism     = "hsa",                # Human pathways
  pvalueCutoff = 0.05,                 # Adjust if needed
  qvalueCutoff = 0.2
)

# Perform Reactome pathway enrichment analysis
reactome_down <- enrichPathway(gene = entrez_ids_down$ENTREZID,
                               organism = "human",
                               pvalueCutoff = 0.05)

# Visualize GO enrichment results
barplot(ego_down, showCategory = 10)

dotplot(ego_down, showCategory = 10)


# Plot if the object is valid
if (!is.null(ekegg_down) && nrow(as.data.frame(ekegg_down)) > 0) {
  barplot(ekegg_down, showCategory = 30)
} else {
  print("No enriched categories found.")
}


dotplot(ekegg_down, showCategory = 30)


if (!is.null(reactome_down) && nrow(as.data.frame(reactome_down)) > 0) {
  barplot(reactome_down, showCategory = 30)
} else {
  print("No enriched categories found.")
}


dotplot(reactome_down, showCategory = 10)




# Pathway visualization with pathview for downregulated genes
pathway_down <- pathview(gene.data = gene_data_down,
         pathway.id = "hsa05200", # Example KEGG pathway ID
         species = "hsa",
         kegg.native = TRUE) # Use KEGG's native pathway diagram
'select()' returned 1:1 mapping between keys and columns
Info: Working in directory /home/bioinfo/17-SingleCellFCscanner
Info: Writing image file hsa05200.pathview.png
pathway_down
$plot.data.gene

$plot.data.cpd
NA
LS0tCnRpdGxlOiAiRW5yaWNobWVudCBhZnRlciBGQyBTY2FubmVyIEFuYWx5c2lzIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICMgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgIyB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgIyBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGZvcmVhY2gpCmxpYnJhcnkoZG9QYXJhbGxlbCkKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVhZHIpICAjICdyZWFkcicgcGFja2FnZSBpcyByZWNvbW1lbmRlZCBmb3IgcmVhZGluZyAuY3N2IGFuZCAudHN2IGZpbGVzIGVmZmljaWVudGx5CmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQoKCmBgYAoKCiMgMi4gRW5yaWNobWVudCBBbmFseXNpc19wYXJ0MQpgYGB7ciBFbnJpY2htZW50MSwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTE4fQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgojIFJlYWQgdGhlIFRTViBmaWxlIGludG8gUgpTaWduaWZpY2FudF9HZW5lcyA8LSByZWFkX2NzdigiL2hvbWUvYmlvaW5mby8xOC1FbnJpY2htZW50X0FuYWx5c2lzX2ZpbmFsX1Jlc3VsdHMvTmV3RmlsZXMvQWxsX1Jlc3VsdHNfVG9nZXRoZXJfZm9yX0VucmljaG1lbnQvQ2VsbF9saW5lc192c19jb250cm9sL2ZpbHRlcmVkX2RhdGFfQ2VsbF9saW5lc192c19DRDRUY2VsbHMuY3N2IikKClNTX3VwICA8LSBzdWJzZXQoU2lnbmlmaWNhbnRfR2VuZXMsCiAgICAgICAgICAgICAgICAgICAgU2lnbmlmaWNhbnRfR2VuZXMkbG9nMkZDID4gMwogICAgICAgICAgICAgICAgICAgICAgJiBTaWduaWZpY2FudF9HZW5lcyRwVmFsdWVCSCA8ICAwLjA1KQpTU191cF9nZW5lcyA8LSBTU191cCRnZW5lCgoKU1NfZG93biAgPC0gc3Vic2V0KFNpZ25pZmljYW50X0dlbmVzLAogICAgICAgICAgICAgICAgICAgIFNpZ25pZmljYW50X0dlbmVzJGxvZzJGQyA8IC0xIAogICAgICAgICAgICAgICAgICAgICAgJiBTaWduaWZpY2FudF9HZW5lcyRwVmFsdWVCSCA8ICAwLjA1KQpTU19kb3duX2dlbmVzIDwtIFNTX2Rvd24kZ2VuZQoKClNTX3ZzX25vcm1fZ28gPC0gY2x1c3RlclByb2ZpbGVyOjplbnJpY2hHTyhTU191cF9nZW5lcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAib3JnLkhzLmVnLmRiIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIlNZTUJPTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkJQIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5HU1NpemUgPSA1MCkKCnByaW50KFNTX3ZzX25vcm1fZ29AcmVzdWx0KQoKZW5yX2dvIDwtIGNsdXN0ZXJQcm9maWxlcjo6c2ltcGxpZnkoU1NfdnNfbm9ybV9nbykKCnByaW50KGVucl9nb0ByZXN1bHQpCgplbnJpY2hwbG90OjplbWFwcGxvdChlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKGVucl9nbyksCiAgICAgICAgICAgICAgICAgICAgIHNob3dDYXRlZ29yeSA9IDUwKQoKClNTX3ZzX25vcm1fZ28gPC0gY2x1c3RlclByb2ZpbGVyOjplbnJpY2hHTyhTU19kb3duX2dlbmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvcmcuSHMuZWcuZGIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleVR5cGUgPSAiU1lNQk9MIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbkdTU2l6ZSA9IDUwKQoKcHJpbnQoU1NfdnNfbm9ybV9nb0ByZXN1bHQpCgplbnJfZ28gPC0gY2x1c3RlclByb2ZpbGVyOjpzaW1wbGlmeShTU192c19ub3JtX2dvKQoKcHJpbnQoZW5yX2dvQHJlc3VsdCkKCmVucmljaHBsb3Q6OmVtYXBwbG90KGVucmljaHBsb3Q6OnBhaXJ3aXNlX3Rlcm1zaW0oZW5yX2dvKSwKICAgICAgICAgICAgICAgICAgICAgc2hvd0NhdGVnb3J5ID0gNTApCgoKYGBgCgojIDMuIEVucmljaG1lbnQgQW5hbHlzaXNfcGFydDIKYGBge3IgRW5yaWNobWVudDIsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KZ210IDwtIG1zaWdkYnI6Om1zaWdkYnIoc3BlY2llcyA9ICJodW1hbiIsIGNhdGVnb3J5ID0gIkgiKQoKU1NfdnNfbm9ybV9lbnJpY2hfdXAgPC0gY2x1c3RlclByb2ZpbGVyOjplbnJpY2hlcihnZW5lID0gU1NfdXBfZ2VuZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgID0gMC4wNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmICA9IDAuMDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRFUk0yR0VORSA9IGdtdFssYygiZ3NfbmFtZSIsICJnZW5lX3N5bWJvbCIpXSkKCgpwcmludChTU192c19ub3JtX2VucmljaF91cEByZXN1bHRbU1NfdnNfbm9ybV9lbnJpY2hfdXBAcmVzdWx0JHAuYWRqdXN0IDwgMC4wNSxdKQoKClNTX3ZzX25vcm1fZW5yaWNoX2Rvd24gPC0gY2x1c3RlclByb2ZpbGVyOjplbnJpY2hlcihnZW5lID0gU1NfZG93bl9nZW5lcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiAgPSAwLjA1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgID0gMC4wNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVEVSTTJHRU5FID0gZ210WyxjKCJnc19uYW1lIiwgImdlbmVfc3ltYm9sIildKQoKCnByaW50KFNTX3ZzX25vcm1fZW5yaWNoX2Rvd25AcmVzdWx0W1NTX3ZzX25vcm1fZW5yaWNoX2Rvd25AcmVzdWx0JHAuYWRqdXN0IDwgMC4wNSxdKQoKYGBgCiMgNC4gRW5yaWNobWVudCBBbmFseXNpc19wYXJ0MwpgYGB7ciBFbnJpY2htZW50NCwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgV2UgdXNlIHRoZSBmdW5jdGlvbiBgYmFycGxvdGAgZnJvbSBwYWNrYWdlIGBlbnJpY2hwbG90YApncmFwaGljczo6YmFycGxvdCgKICAjIFdlIHByb3ZpZGUgdGhlIHZhcmlhYmxlIHBvaW50aW5nIHRvIGVucmljaG1lbnQgcmVzdWx0cwogIGhlaWdodCA9IFNTX3ZzX25vcm1fZW5yaWNoX3VwLAogICMgV2UgZGlzcGxheSB0aGUgYmVzdCAxNSByZXN1bHRzCiAgc2hvd0NhdGVnb3J5PTE1CikKCgplbnJpY2hwbG90Ojpkb3RwbG90KAogICMgV2UgcHJvdmlkZSB0aGUgdmFyaWFibGUgcG9pbnRpbmcgdG8gZW5yaWNobWVudCByZXN1bHRzCiAgb2JqZWN0ID0gU1NfdnNfbm9ybV9lbnJpY2hfdXAsCiAgIyBXZSBkaXNwbGF5IHRoZSBiZXN0IDE1IHJlc3VsdHMKICBzaG93Q2F0ZWdvcnk9MTUKKQojIFdlIHVzZSB0aGUgZnVuY3Rpb24gYGJhcnBsb3RgIGZyb20gcGFja2FnZSBgZW5yaWNocGxvdGAKZ3JhcGhpY3M6OmJhcnBsb3QoCiAgIyBXZSBwcm92aWRlIHRoZSB2YXJpYWJsZSBwb2ludGluZyB0byBlbnJpY2htZW50IHJlc3VsdHMKICBoZWlnaHQgPSBTU192c19ub3JtX2VucmljaF9kb3duLAogICMgV2UgZGlzcGxheSB0aGUgYmVzdCAxNSByZXN1bHRzCiAgc2hvd0NhdGVnb3J5PTE1CikKCgplbnJpY2hwbG90Ojpkb3RwbG90KAogICMgV2UgcHJvdmlkZSB0aGUgdmFyaWFibGUgcG9pbnRpbmcgdG8gZW5yaWNobWVudCByZXN1bHRzCiAgb2JqZWN0ID0gU1NfdnNfbm9ybV9lbnJpY2hfZG93biwKICAjIFdlIGRpc3BsYXkgdGhlIGJlc3QgMTUgcmVzdWx0cwogIHNob3dDYXRlZ29yeT0xNQopCgpgYGAKCiMgNS4gRW5yaWNobWVudCBBbmFseXNpc19wYXJ0NQpgYGB7ciBFbnJpY2htZW50NSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIFdlIHVzZSB0aGUgZnVuY3Rpb24gYGhlYXRwbG90YCBmcm9tIGBlbnJpY2hwbG90YCBwYWNrYWdlCiMgV2UgdXNlIHRoZSBmdW5jdGlvbiBgdXBzZXRwbG90YCBmcm9tIGBlbnJpY2hwbG90YCBwYWNrYWdlCmVucmljaHBsb3Q6OnVwc2V0cGxvdCgKICAjIFdlIHByb2JpZGUgdGhlIHZhcmlhYmxlIHBvaW50aW5nIHRvIEdTRUEgcmVzdWx0cwogIHggPSBTU192c19ub3JtX2VucmljaF91cCwKICAjIFdlIHNob3cgdGhlIDEwIGJlc3QgcmVzdWx0cwogIG4gPSAxMAopCgplbnJpY2hwbG90Ojp1cHNldHBsb3QoCiAgIyBXZSBwcm9iaWRlIHRoZSB2YXJpYWJsZSBwb2ludGluZyB0byBHU0VBIHJlc3VsdHMKICB4ID0gU1NfdnNfbm9ybV9lbnJpY2hfZG93biwKICAjIFdlIHNob3cgdGhlIDEwIGJlc3QgcmVzdWx0cwogIG4gPSAxMAopCgpgYGAKCiMgNi4gRW5yaWNobWVudCBBbmFseXNpc19wYXJ0NgpgYGB7ciBFbnJpY2htZW50NiwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIExvYWQgdGhlIHBhY2thZ2VzCmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KFJlYWN0b21lUEEpCmxpYnJhcnkob3JnLkhzLmVnLmRiKQpsaWJyYXJ5KHBhdGh2aWV3KQoKIyBFeHRyYWN0IHRoZSBnZW5lIHN5bWJvbHMgYW5kIGxvZzJGQyB2YWx1ZXMgZm9yIFNTX3VwCmdlbmVfbGlzdF91cCA8LSBhcy5jaGFyYWN0ZXIoU1NfdXAkZ2VuZSkKbG9nMmZjX3ZhbHVlc191cCA8LSBTU191cCRsb2cyRkMKCiMgR2V0IGEgbGlzdCBvZiB2YWxpZCBnZW5lIHN5bWJvbHMgZnJvbSBvcmcuSHMuZWcuZGIKdmFsaWRfc3ltYm9scyA8LSBrZXlzKG9yZy5Icy5lZy5kYiwga2V5dHlwZSA9ICJTWU1CT0wiKQoKIyBDaGVjayB3aGljaCBnZW5lIHN5bWJvbHMgYXJlIG5vdCB2YWxpZAppbnZhbGlkX3N5bWJvbHNfdXAgPC0gc2V0ZGlmZihnZW5lX2xpc3RfdXAsIHZhbGlkX3N5bWJvbHMpCgojIFByaW50IGludmFsaWQgZ2VuZSBzeW1ib2xzCmlmIChsZW5ndGgoaW52YWxpZF9zeW1ib2xzX3VwKSA+IDApIHsKICAgIGNhdCgiVGhlIGZvbGxvd2luZyBnZW5lIHN5bWJvbHMgYXJlIG5vdCB2YWxpZCBhbmQgd2lsbCBiZSBleGNsdWRlZCBmcm9tIFNTX3VwOlxuIikKICAgIHByaW50KGludmFsaWRfc3ltYm9sc191cCkKfQoKIyBGaWx0ZXIgb3V0IGludmFsaWQgZ2VuZSBzeW1ib2xzCmdlbmVfbGlzdF91cCA8LSBpbnRlcnNlY3QoZ2VuZV9saXN0X3VwLCB2YWxpZF9zeW1ib2xzKQoKIyBDb252ZXJ0IGdlbmUgc3ltYm9scyB0byBFbnRyZXogSURzCmVudHJlel9pZHNfdXAgPC0gYml0cihnZW5lX2xpc3RfdXAsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQoKIyBDaGVjayBmb3Igc3VjY2Vzc2Z1bCBjb252ZXJzaW9uCmlmIChucm93KGVudHJlel9pZHNfdXApID09IDApIHsKICAgIHN0b3AoIk5vIGdlbmUgc3ltYm9scyB3ZXJlIGNvbnZlcnRlZCB0byBFbnRyZXogSURzIGZvciBTU191cC4iKQp9CgojIE1lcmdlIEVudHJleiBJRHMgd2l0aCBsb2cyRkMgdmFsdWVzCmVudHJlel9pZHNfdXAgPC0gbWVyZ2UoZW50cmV6X2lkc191cCwgU1NfdXAsIGJ5LnggPSAiU1lNQk9MIiwgYnkueSA9ICJnZW5lIikKCiMgQ3JlYXRlIGEgbmFtZWQgdmVjdG9yIG9mIGxvZzJGQyB2YWx1ZXMgd2l0aCBFbnRyZXogSURzIGFzIG5hbWVzCmdlbmVfZGF0YV91cCA8LSBzZXROYW1lcyhlbnRyZXpfaWRzX3VwJGxvZzJGQywgZW50cmV6X2lkc191cCRFTlRSRVpJRCkKCgpgYGAKCiMgNy4gRW5yaWNobWVudCBBbmFseXNpc19wYXJ0NwpgYGB7ciBFbnJpY2htZW50NywgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIFBlcmZvcm0gR08gZW5yaWNobWVudCBhbmFseXNpcwplZ28gPC0gZW5yaWNoR08oZ2VuZSA9IGVudHJlel9pZHNfdXAkRU5UUkVaSUQsCiAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwKICAgICAgICAgICAgICAgIGtleVR5cGUgPSAiRU5UUkVaSUQiLAogICAgICAgICAgICAgICAgb250ID0gIkJQIiwgICMgIkJQIiBmb3IgQmlvbG9naWNhbCBQcm9jZXNzCiAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwKICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIpCgojIFBlcmZvcm0gS0VHRyBwYXRod2F5IGVucmljaG1lbnQgYW5hbHlzaXMKZWtlZ2cgPC0gZW5yaWNoS0VHRyhnZW5lID0gZW50cmV6X2lkc191cCRFTlRSRVpJRCwKICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2EiLAogICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDAxKQoKCiMgUGVyZm9ybSBSZWFjdG9tZSBwYXRod2F5IGVucmljaG1lbnQgYW5hbHlzaXMKcmVhY3RvbWUgPC0gZW5yaWNoUGF0aHdheShnZW5lID0gZW50cmV6X2lkc191cCRFTlRSRVpJRCwKICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJodW1hbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCgojIFZpc3VhbGl6ZSBHTyBlbnJpY2htZW50IHJlc3VsdHMKYmFycGxvdChlZ28sIHNob3dDYXRlZ29yeSA9IDEwKQpkb3RwbG90KGVnbywgc2hvd0NhdGVnb3J5ID0gMTApCgojIFZpc3VhbGl6ZSBLRUdHIHBhdGh3YXkgZW5yaWNobWVudCByZXN1bHRzCmJhcnBsb3QoZWtlZ2csIHNob3dDYXRlZ29yeSA9IDMwKQpkb3RwbG90KGVrZWdnLCBzaG93Q2F0ZWdvcnkgPSAzMCkKCiMgVmlzdWFsaXplIFJlYWN0b21lIHBhdGh3YXkgZW5yaWNobWVudCByZXN1bHRzCmJhcnBsb3QocmVhY3RvbWUsIHNob3dDYXRlZ29yeSA9IDEwKQpkb3RwbG90KHJlYWN0b21lLCBzaG93Q2F0ZWdvcnkgPSAxMCkKCiMgUGF0aHdheSB2aXN1YWxpemF0aW9uIHdpdGggcGF0aHZpZXcKIyBFeGFtcGxlOiBWaXN1YWxpemUgS0VHRyBwYXRod2F5IGhzYTA0MDEwIChyZXBsYWNlIHdpdGggeW91ciBwYXRod2F5IG9mIGludGVyZXN0KQpwYXRod2F5X3VwIDwtIHBhdGh2aWV3KGdlbmUuZGF0YSA9IGFzLm51bWVyaWMoZW50cmV6X2lkc191cCRFTlRSRVpJRCksCiAgICAgICAgIHBhdGh3YXkuaWQgPSAiaHNhMDUyMDAiLCAjIEV4YW1wbGUgS0VHRyBwYXRod2F5IElECiAgICAgICAgIHNwZWNpZXMgPSAiaHNhIikKCnBhdGh3YXlfdXAKCgojIEFzc3VtaW5nIHRoZSBpbWFnZSBpcyBzYXZlZCB3aXRoIHRoZSBuYW1lICdoc2EwNTIwMC5wYXRodmlldy5wbmcnCmltYWdlX3BhdGggPC0gImhzYTA1MjAwLmhzYTA1MjAwLnBuZyIKCiMgQ2hlY2sgaWYgdGhlIGltYWdlIGZpbGUgZXhpc3RzIGFuZCBkaXNwbGF5IGl0CmlmIChmaWxlLmV4aXN0cyhpbWFnZV9wYXRoKSkgewogICAgZGlzcGxheV9wbmcoZmlsZSA9IGltYWdlX3BhdGgpCn0gZWxzZSB7CiAgICBjYXQoIkltYWdlIGZpbGUiLCBpbWFnZV9wYXRoLCAibm90IGZvdW5kLiIpCn0KCmBgYAoKCgojIDguIEVucmljaG1lbnQgQW5hbHlzaXNfcGFydDgKYGBge3IgRW5yaWNobWVudDgsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIExvYWQgdGhlIHBhY2thZ2VzCmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KFJlYWN0b21lUEEpCmxpYnJhcnkob3JnLkhzLmVnLmRiKQpsaWJyYXJ5KHBhdGh2aWV3KQoKIyBFeHRyYWN0IHRoZSBnZW5lIHN5bWJvbHMgYW5kIGxvZzJGQyB2YWx1ZXMgZm9yIFNTX2Rvd24KZ2VuZV9saXN0X2Rvd24gPC0gYXMuY2hhcmFjdGVyKFNTX2Rvd24kZ2VuZSkKbG9nMmZjX3ZhbHVlc19kb3duIDwtIFNTX2Rvd24kbG9nMkZDCgojIENoZWNrIHdoaWNoIGdlbmUgc3ltYm9scyBhcmUgbm90IHZhbGlkCmludmFsaWRfc3ltYm9sc19kb3duIDwtIHNldGRpZmYoZ2VuZV9saXN0X2Rvd24sIHZhbGlkX3N5bWJvbHMpCgojIFByaW50IGludmFsaWQgZ2VuZSBzeW1ib2xzCmlmIChsZW5ndGgoaW52YWxpZF9zeW1ib2xzX2Rvd24pID4gMCkgewogICAgY2F0KCJUaGUgZm9sbG93aW5nIGdlbmUgc3ltYm9scyBhcmUgbm90IHZhbGlkIGFuZCB3aWxsIGJlIGV4Y2x1ZGVkIGZyb20gU1NfZG93bjpcbiIpCiAgICBwcmludChpbnZhbGlkX3N5bWJvbHNfZG93bikKfQoKIyBGaWx0ZXIgb3V0IGludmFsaWQgZ2VuZSBzeW1ib2xzCmdlbmVfbGlzdF9kb3duIDwtIGludGVyc2VjdChnZW5lX2xpc3RfZG93biwgdmFsaWRfc3ltYm9scykKCiMgQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gRW50cmV6IElEcwplbnRyZXpfaWRzX2Rvd24gPC0gYml0cihnZW5lX2xpc3RfZG93biwgZnJvbVR5cGUgPSAiU1lNQk9MIiwgdG9UeXBlID0gIkVOVFJFWklEIiwgT3JnRGIgPSBvcmcuSHMuZWcuZGIpCgojIENoZWNrIGZvciBzdWNjZXNzZnVsIGNvbnZlcnNpb24KaWYgKG5yb3coZW50cmV6X2lkc19kb3duKSA9PSAwKSB7CiAgICBzdG9wKCJObyBnZW5lIHN5bWJvbHMgd2VyZSBjb252ZXJ0ZWQgdG8gRW50cmV6IElEcyBmb3IgU1NfZG93bi4iKQp9CgojIE1lcmdlIEVudHJleiBJRHMgd2l0aCBsb2cyRkMgdmFsdWVzCmVudHJlel9pZHNfZG93biA8LSBtZXJnZShlbnRyZXpfaWRzX2Rvd24sIFNTX2Rvd24sIGJ5LnggPSAiU1lNQk9MIiwgYnkueSA9ICJnZW5lIikKCiMgQ3JlYXRlIGEgbmFtZWQgdmVjdG9yIG9mIGxvZzJGQyB2YWx1ZXMgd2l0aCBFbnRyZXogSURzIGFzIG5hbWVzCmdlbmVfZGF0YV9kb3duIDwtIHNldE5hbWVzKGVudHJlel9pZHNfZG93biRsb2cyRkMsIGVudHJlel9pZHNfZG93biRFTlRSRVpJRCkKCgpgYGAKCiMgOS4gRW5yaWNobWVudCBBbmFseXNpc19wYXJ0OQpgYGB7ciBFbnJpY2htZW50OSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgSW5zdGFsbCBuZWNlc3NhcnkgcGFja2FnZXMgaWYgdGhleSBhcmUgbm90IGFscmVhZHkgaW5zdGFsbGVkCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKQmlvY01hbmFnZXI6Omluc3RhbGwoYygicGF0aHZpZXciLCAiSVJkaXNwbGF5IikpCgojIExvYWQgdGhlIHJlcXVpcmVkIHBhY2thZ2VzCmxpYnJhcnkocGF0aHZpZXcpCmxpYnJhcnkoSVJkaXNwbGF5KQoKCiMgUGVyZm9ybSBHTyBlbnJpY2htZW50IGFuYWx5c2lzCmVnb19kb3duIDwtIGVucmljaEdPKGdlbmUgPSBlbnRyZXpfaWRzX2Rvd24kRU5UUkVaSUQsCiAgICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLAogICAgICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIkVOVFJFWklEIiwKICAgICAgICAgICAgICAgICAgICAgb250ID0gIkJQIiwgICMgIkJQIiBmb3IgQmlvbG9naWNhbCBQcm9jZXNzCiAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLAogICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjIpCgpla2VnZ19kb3duIDwtIGVucmljaEtFR0coCiAgZ2VuZSAgICAgICAgID0gZW50cmV6X2lkc19kb3duJEVOVFJFWklELCAgIyBZb3VyIGxpc3Qgb2YgZ2VuZSBJRHMKICBvcmdhbmlzbSAgICAgPSAiaHNhIiwgICAgICAgICAgICAgICAgIyBIdW1hbiBwYXRod2F5cwogIHB2YWx1ZUN1dG9mZiA9IDAuMDUsICAgICAgICAgICAgICAgICAjIEFkanVzdCBpZiBuZWVkZWQKICBxdmFsdWVDdXRvZmYgPSAwLjIKKQoKIyBQZXJmb3JtIFJlYWN0b21lIHBhdGh3YXkgZW5yaWNobWVudCBhbmFseXNpcwpyZWFjdG9tZV9kb3duIDwtIGVucmljaFBhdGh3YXkoZ2VuZSA9IGVudHJlel9pZHNfZG93biRFTlRSRVpJRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImh1bWFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpc3VhbGl6ZSBHTyBlbnJpY2htZW50IHJlc3VsdHMKYmFycGxvdChlZ29fZG93biwgc2hvd0NhdGVnb3J5ID0gMTApCmRvdHBsb3QoZWdvX2Rvd24sIHNob3dDYXRlZ29yeSA9IDEwKQoKIyBQbG90IGlmIHRoZSBvYmplY3QgaXMgdmFsaWQKaWYgKCFpcy5udWxsKGVrZWdnX2Rvd24pICYmIG5yb3coYXMuZGF0YS5mcmFtZShla2VnZ19kb3duKSkgPiAwKSB7CiAgYmFycGxvdChla2VnZ19kb3duLCBzaG93Q2F0ZWdvcnkgPSAzMCkKfSBlbHNlIHsKICBwcmludCgiTm8gZW5yaWNoZWQgY2F0ZWdvcmllcyBmb3VuZC4iKQp9Cgpkb3RwbG90KGVrZWdnX2Rvd24sIHNob3dDYXRlZ29yeSA9IDMwKQoKaWYgKCFpcy5udWxsKHJlYWN0b21lX2Rvd24pICYmIG5yb3coYXMuZGF0YS5mcmFtZShyZWFjdG9tZV9kb3duKSkgPiAwKSB7CiAgYmFycGxvdChyZWFjdG9tZV9kb3duLCBzaG93Q2F0ZWdvcnkgPSAzMCkKfSBlbHNlIHsKICBwcmludCgiTm8gZW5yaWNoZWQgY2F0ZWdvcmllcyBmb3VuZC4iKQp9Cgpkb3RwbG90KHJlYWN0b21lX2Rvd24sIHNob3dDYXRlZ29yeSA9IDEwKQoKCgojIFBhdGh3YXkgdmlzdWFsaXphdGlvbiB3aXRoIHBhdGh2aWV3IGZvciBkb3ducmVndWxhdGVkIGdlbmVzCnBhdGh3YXlfZG93biA8LSBwYXRodmlldyhnZW5lLmRhdGEgPSBnZW5lX2RhdGFfZG93biwKICAgICAgICAgcGF0aHdheS5pZCA9ICJoc2EwNTIwMCIsICMgRXhhbXBsZSBLRUdHIHBhdGh3YXkgSUQKICAgICAgICAgc3BlY2llcyA9ICJoc2EiLAogICAgICAgICBrZWdnLm5hdGl2ZSA9IFRSVUUpICMgVXNlIEtFR0cncyBuYXRpdmUgcGF0aHdheSBkaWFncmFtCgpwYXRod2F5X2Rvd24KYGBg