4. Use FindAllMarkers() for DE on RNA assay
# Load necessary libraries
library(Seurat)
DefaultAssay(All_samples_Merged) <- "RNA"
All_samples_Merged <- NormalizeData(
All_samples_Merged,
assay = "RNA",
normalization.method = "LogNormalize",
scale.factor = 10000
)
Normalizing layer: counts
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
# Subset only malignant Sézary syndrome cell lines
malignant_lines <- c("L1", "L2", "L3", "L4", "L5", "L6", "L7")
Malignant_obj <- subset(All_samples_Merged, subset = cell_line %in% malignant_lines)
# Set cell_line as the active identity
Idents(Malignant_obj) <- "cell_line"
# Ensure RNA slot is normalized (if not already done)
if (!"RNA" %in% names(Malignant_obj@assays)) {
Malignant_obj <- NormalizeData(Malignant_obj)
}
# Run FindAllMarkers to compare each cell_line against all other malignant cell lines
all_markers<- FindAllMarkers(Malignant_obj,
assay = "RNA",
only.pos = FALSE,
logfc.threshold = 0,
min.pct = 0,
test.use = "wilcox") # can also use "MAST", "t", etc.
Calculating cluster L1
Avis : The `slot` argument of `GetAssayData()` is deprecated as of SeuratObject 5.0.0.
Please use the `layer` argument instead.Avis : `PackageCheck()` was deprecated in SeuratObject 5.0.0.
Please use `rlang::check_installed()` instead.Calculating cluster L2
Calculating cluster L3
Calculating cluster L4
Calculating cluster L5
Calculating cluster L6
Calculating cluster L7
# Save all marker results
write.csv(all_markers, "AllMarkers_CellLines_MalignantOnly.csv", row.names = FALSE)
4. Run GSEA per Cluster using DE Files
# 3. Prepare output list for storing FGSEA results
gsea_all <- list()
# 4. Get unique clusters from all_markers
clusters <- unique(all_markers$cluster)
# 5. Loop over each cluster and run FGSEA
for (cluster_id in clusters) {
cat("Processing cluster:", cluster_id, "\n")
# Subset DE genes for cluster vs rest
de_df <- all_markers %>%
filter(cluster == cluster_id) %>%
filter(!is.na(avg_log2FC))
# Create named vector ranked by avg_log2FC (descending)
ranked_genes <- deframe(de_df %>% select(gene, avg_log2FC))
ranked_genes <- sort(ranked_genes, decreasing = TRUE)
# Run FGSEA on each MSigDB collection
for (db_name in names(msigdb_sets)) {
fgsea_res <- fgsea(
pathways = msigdb_sets[[db_name]],
stats = ranked_genes,
minSize = 10,
maxSize = 300,
nperm = 10000
)
if (nrow(fgsea_res) > 0) {
fgsea_res$cluster <- cluster_id
fgsea_res$database <- db_name
# Save in list with unique name
gsea_all[[paste0("Cluster_", cluster_id, "_", db_name)]] <- fgsea_res
}
}
}
Processing cluster: L1
Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : There were 1 pathways for which P-values were not calculated properly due to unbalanced gene-level statistic valuesAvis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : There were 1 pathways for which P-values were not calculated properly due to unbalanced gene-level statistic values
Processing cluster: L2
Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.
Processing cluster: L3
Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.
Processing cluster: L4
Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.
Processing cluster: L5
Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.
Processing cluster: L6
Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : There are ties in the preranked stats (0.11% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : There are ties in the preranked stats (0.11% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : There are ties in the preranked stats (0.11% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : There are ties in the preranked stats (0.11% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : There are ties in the preranked stats (0.11% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.
Processing cluster: L7
Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.
Combine and Save All GSEA Results
# 6. Combine all GSEA results into one dataframe
gsea_df <- bind_rows(gsea_all)
# 7. Flatten leadingEdge list column into a semicolon-separated string
gsea_df <- gsea_df %>%
mutate(leadingEdge = map_chr(leadingEdge, ~ paste(.x, collapse = ";")))
# 8. Save combined results (optional)
write.csv(gsea_df, "GSEA_MSigDB_Results_Clusterwise_findAllMarkers_used.csv", row.names = FALSE)
# 9. Create folders and save cluster-wise results separately
gsea_by_cluster <- split(gsea_df, gsea_df$cluster)
for (cluster_id in names(gsea_by_cluster)) {
folder_name <- paste0("Cluster_", cluster_id)
if (!dir.exists(folder_name)) {
dir.create(folder_name)
}
file_path <- file.path(folder_name, paste0("GSEA_Cluster_", cluster_id, ".csv"))
write.csv(gsea_by_cluster[[cluster_id]], file = file_path, row.names = FALSE)
}
Combine and Save All GSEA Results
# 10. Plot top GSEA pathways per cluster & collection (top 3 per cluster/db, padj<0.05)
top_terms <- gsea_df %>%
filter(padj < 0.05) %>%
group_by(cluster, database) %>%
slice_max(NES, n = 10, with_ties = FALSE) %>%
ungroup()
# Clean pathway names
top_terms$pathway <- gsub("GO_|REACTOME_|KEGG_", "", top_terms$pathway)
top_terms$pathway <- gsub("_", " ", top_terms$pathway)
top_terms$pathway <- str_to_title(top_terms$pathway)
top_terms$pathway <- str_trunc(top_terms$pathway, width = 60)
# Plot using ggplot2
p1 <- ggplot(top_terms, aes(x = fct_reorder(pathway, NES), y = NES, fill = database)) +
geom_col(width = 0.9) +
coord_flip() +
facet_grid(database ~ cluster, scales = "free_y", space = "free") +
geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") +
labs(
x = "Pathway",
y = "Normalized Enrichment Score (NES)",
title = "Top GSEA Pathways per Cluster",
fill = "Database"
) +
scale_fill_brewer(palette = "Set2") +
theme_minimal(base_size = 16) +
theme(
strip.text = element_text(face = "bold", size = 16),
strip.background = element_rect(fill = "gray90", color = "black"),
strip.placement = "outside",
legend.position = "bottom",
axis.text.y = element_text(face = "bold", size = 13),
axis.text.x = element_text(size = 14),
panel.spacing = unit(1, "lines"),
panel.border = element_rect(color = "black", fill = NA, size = 1.5)
)
ggsave("Top_GSEA_Pathways_Per_Cluster1.pdf", p1, width = 30, height = 58, limitsize = FALSE)
p1

Combine and Save All GSEA Results
library(ggplot2)
library(ggforce)
library(forcats)
library(dplyr)
library(stringr)
# Force cluster order
top_terms$cluster <- factor(top_terms$cluster, levels = as.character(0:13))
# Clean and shorten pathway names
top_terms <- top_terms %>%
mutate(
pathway = gsub("GO_|REACTOME_|KEGG_", "", pathway),
pathway = gsub("_", " ", pathway),
pathway = str_to_title(pathway),
pathway = str_trunc(pathway, width = 60)
)
# Add direction column
top_terms <- top_terms %>%
mutate(direction = ifelse(NES > 0, "Upregulated", "Downregulated"))
# Use direction and database together for color
top_terms$direction_db <- interaction(top_terms$direction, top_terms$database, sep = "_")
# Define custom colors for each direction+db combo (optional: customize as you like)
n_colors <- length(unique(top_terms$direction_db))
palette <- scales::hue_pal()(n_colors)
names(palette) <- unique(top_terms$direction_db)
# Plot
p2 <- ggplot(top_terms, aes(x = fct_reorder(pathway, NES), y = NES, fill = direction_db)) +
geom_col(width = 0.9) +
coord_flip() +
facet_grid(database ~ cluster, scales = "free_y", space = "free") +
geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") +
labs(
x = "Pathway",
y = "Normalized Enrichment Score (NES)",
title = "Top GSEA Pathways per Cluster",
fill = "Direction + DB"
) +
scale_fill_manual(values = palette) +
theme_minimal(base_size = 16) +
theme(
strip.text = element_text(face = "bold", size = 16),
strip.background = element_rect(fill = "gray90", color = "black"),
strip.placement = "outside",
legend.position = "bottom",
axis.text.y = element_text(face = "bold", size = 13),
axis.text.x = element_text(size = 14),
panel.spacing = unit(1, "lines"),
panel.border = element_rect(color = "black", fill = NA, size = 1.5)
)
# Save with correct size override
ggsave("Top_GSEA_Pathways_Per_Cluster2.pdf", p2, width = 30, height = 58, limitsize = FALSE)
p2

Combine and Save All GSEA Results

Combine and Save All GSEA Results
# Required packages
library(msigdbr)
library(fgsea)
library(dplyr)
library(tibble)
library(forcats)
library(ggplot2)
library(pheatmap)
library(stringr)
# 1. Curated Sézary syndrome–relevant MSigDB pathways
curated_pathways <- c(
# Hallmark
"HALLMARK_JAK_STAT3_SIGNALING", "HALLMARK_TNFA_SIGNALING_VIA_NFKB", "HALLMARK_APOPTOSIS",
# KEGG
"KEGG_T_CELL_RECEPTOR_SIGNALING_PATHWAY", "KEGG_JAK_STAT_SIGNALING_PATHWAY",
"KEGG_PI3K_AKT_SIGNALING_PATHWAY", "KEGG_MAPK_SIGNALING_PATHWAY",
"KEGG_TGF_BETA_SIGNALING_PATHWAY", "KEGG_CELL_CYCLE", "KEGG_APOPTOSIS",
# Reactome
"REACTOME_SIGNALING_BY_TCR", "REACTOME_SIGNALING_BY_JAK_STAT",
"REACTOME_PI3K_AKT_ACTIVATION", "REACTOME_NFKB_ACTIVATION",
# GO (Biological Process)
"GOBP_CYTOKINE_MEDIATED_SIGNALING_PATHWAY", "GOBP_T_CELL_ACTIVATION",
"GOBP_CELL_CYCLE_PROCESS", "GOBP_APOPTOTIC_PROCESS",
"GOBP_MAPK_CASCADE", "GOBP_NF_KAPPA_B_TRANSCRIPTION_FACTOR_ACTIVITY",
"GOBP_JAK_STAT_CASCADE", "GOBP_EPIGENETIC_REGULATION"
)
# 2. Load MSigDB genes
msig_df <- msigdbr(species = "Homo sapiens") %>%
filter(gs_name %in% curated_pathways)
pathways_list <- split(msig_df$gene_symbol, msig_df$gs_name)
# 3. Split FindAllMarkers data frame by cluster
cluster_stats <- split(all_markers, all_markers$cluster)
# 4. Run fgsea using avg_log2FC as ranking metric
fgsea_results <- lapply(cluster_stats, function(stats_df) {
# Ensure avg_log2FC exists and gene names are present
stats_df <- stats_df %>%
filter(!is.na(avg_log2FC)) %>%
distinct(gene, .keep_all = TRUE)
# Check if gene column exists
if (!"gene" %in% colnames(stats_df)) {
warning("No 'gene' column found in stats_df")
return(NULL)
}
# Create rank vector
ranks <- stats_df$avg_log2FC
names(ranks) <- stats_df$gene
ranks <- sort(ranks, decreasing = TRUE)
# Optional: skip small rank vectors
if (length(ranks) < 100) return(NULL)
fgsea(
pathways = pathways_list,
stats = sort(ranks, decreasing = TRUE),
minSize = 10,
maxSize = 300,
nperm = 10000
)
})
Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.Avis : There are ties in the preranked stats (0.11% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Avis : You are trying to run fgseaSimple. It is recommended to use fgseaMultilevel. To run fgseaMultilevel, you need to remove the nperm argument in the fgsea function call.
# 5. Combine and annotate results
gsea_df <- bind_rows(lapply(names(fgsea_results), function(cluster) {
res <- fgsea_results[[cluster]]
res$cluster <- cluster
res
}))
# 6. Ensure all pathways appear across clusters
all_combos <- expand.grid(
cluster = names(cluster_stats),
pathway = curated_pathways,
stringsAsFactors = FALSE
)
gsea_complete <- all_combos %>%
left_join(gsea_df, by = c("cluster", "pathway")) %>%
mutate(
NES = ifelse(is.na(NES), 0, NES),
padj = ifelse(is.na(padj), 1, padj),
database = case_when(
str_detect(pathway, "^HALLMARK") ~ "Hallmark",
str_detect(pathway, "^KEGG") ~ "KEGG",
str_detect(pathway, "^REACTOME") ~ "Reactome",
str_detect(pathway, "^GOBP") ~ "GO",
TRUE ~ "Other"
),
direction_db = ifelse(NES > 0, paste0("+ ", database), paste0("- ", database)),
sig = ifelse(padj < 0.05, "*", "")
)
# 7. Color palette
palette <- c(
`+ Hallmark` = "#d62728", `- Hallmark` = "#fcbba1",
`+ KEGG` = "#2ca02c", `- KEGG` = "#b9f6ca",
`+ Reactome` = "#1f77b4", `- Reactome` = "#aec7e8",
`+ GO` = "#9467bd", `- GO` = "#d5bde3"
)
# 8. Plot
p4 <- ggplot(gsea_complete, aes(x = fct_reorder(pathway, NES), y = NES, fill = direction_db)) +
geom_col(width = 0.9) +
geom_text(aes(label = sig), hjust = -0.3, size = 5, fontface = "bold", color = "black") +
coord_flip() +
facet_grid(database ~ cluster, scales = "free_y", space = "free") +
geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") +
labs(
x = "Pathway",
y = "Normalized Enrichment Score (NES)",
title = "GSEA (avg_log2FC only) — Curated Pathways per Cluster",
fill = "Enrichment"
) +
scale_fill_manual(values = palette, na.value = "gray80") +
theme_minimal(base_size = 16) +
theme(
strip.text = element_text(face = "bold", size = 16),
strip.background = element_rect(fill = "gray90", color = "black"),
legend.position = "bottom",
axis.text.y = element_text(face = "bold", size = 13),
axis.text.x = element_text(size = 14),
panel.spacing = unit(1, "lines"),
panel.border = element_rect(color = "black", fill = NA, size = 1.5)
)
# 9. Save to PDF
ggsave("Curated_GSEA_avgLogFC_Only.pdf", p4, width = 30, height = 58, limitsize = FALSE)
p4

LS0tCnRpdGxlOiAiZmluZEFsbE1hcmtlcnMtTmV3VU1BUCBmZ3NlYSBBbmFseXNpcyBvbiBtYWxpZ25hbnQgY2VsbCBsaW5lcyIKYXV0aG9yOiAiTmFzaXIgTWFobW9vZCBBYmJhc2kiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19jb2xsYXBzZWQ6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCi0tLQoKIyAxLiBMb2FkIExpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShkcGx5cikKbGlicmFyeShFbmhhbmNlZFZvbGNhbm8pCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwaGVhdG1hcCkKbGlicmFyeSh0aWJibGUpCmBgYAoKCiMgMi4gbG9hZCBzZXVyYXQgb2JqZWN0CmBgYHtyIGxvYWRfc2V1cmF0fQojTG9hZCBTZXVyYXQgT2JqZWN0CkFsbF9zYW1wbGVzX01lcmdlZCA8LSByZWFkUkRTKCIvaG9tZS9uYWJiYXNpL2lzaWxvbi9QSERfM3JkX1lFQVJfQW5hbHlzaXMvMC1TZXVyYXRfUkRTX09CSkVDVF9GSU5BTC9BbGxfc2FtcGxlc19NZXJnZWRfSGFybW9ueV9pbnRlZ3JhdGVkX0NlbGxfbGluZV9yZW5hbWVkXzAzLTA3LTIwMjUucmRzIikKCgpBbGxfc2FtcGxlc19NZXJnZWQKYGBgCgojIDMuIFNldCBVcCBJZGVudGlmaWVycyBmb3IgQ2x1c3RlcmluZwpgYGB7cn0KIyBBc3NpZ24gY2x1c3RlciBpZGVudGl0aWVzIHRvIHRoZSBTZXVyYXQgb2JqZWN0CklkZW50cyhBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJzZXVyYXRfY2x1c3RlcnMiCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCgpgYGAKCiMgNC4gVXNlIEZpbmRBbGxNYXJrZXJzKCkgZm9yIERFIG9uIFJOQSBhc3NheQpgYGB7cn0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMKbGlicmFyeShTZXVyYXQpCgpEZWZhdWx0QXNzYXkoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiUk5BIgoKCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBOb3JtYWxpemVEYXRhKAogIEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgYXNzYXkgPSAiUk5BIiwgCiAgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgCiAgc2NhbGUuZmFjdG9yID0gMTAwMDAKKQoKCiMgU3Vic2V0IG9ubHkgbWFsaWduYW50IFPDqXphcnkgc3luZHJvbWUgY2VsbCBsaW5lcwptYWxpZ25hbnRfbGluZXMgPC0gYygiTDEiLCAiTDIiLCAiTDMiLCAiTDQiLCAiTDUiLCAiTDYiLCAiTDciKQpNYWxpZ25hbnRfb2JqIDwtIHN1YnNldChBbGxfc2FtcGxlc19NZXJnZWQsIHN1YnNldCA9IGNlbGxfbGluZSAlaW4lIG1hbGlnbmFudF9saW5lcykKCiMgU2V0IGNlbGxfbGluZSBhcyB0aGUgYWN0aXZlIGlkZW50aXR5CklkZW50cyhNYWxpZ25hbnRfb2JqKSA8LSAiY2VsbF9saW5lIgoKIyBFbnN1cmUgUk5BIHNsb3QgaXMgbm9ybWFsaXplZCAoaWYgbm90IGFscmVhZHkgZG9uZSkKaWYgKCEiUk5BIiAlaW4lIG5hbWVzKE1hbGlnbmFudF9vYmpAYXNzYXlzKSkgewogIE1hbGlnbmFudF9vYmogPC0gTm9ybWFsaXplRGF0YShNYWxpZ25hbnRfb2JqKQp9CgojIFJ1biBGaW5kQWxsTWFya2VycyB0byBjb21wYXJlIGVhY2ggY2VsbF9saW5lIGFnYWluc3QgYWxsIG90aGVyIG1hbGlnbmFudCBjZWxsIGxpbmVzCmFsbF9tYXJrZXJzPC0gRmluZEFsbE1hcmtlcnMoTWFsaWduYW50X29iaiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gIlJOQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmx5LnBvcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZmMudGhyZXNob2xkID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5wY3QgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdC51c2UgPSAid2lsY294IikgICMgY2FuIGFsc28gdXNlICJNQVNUIiwgInQiLCBldGMuCgojIFNhdmUgYWxsIG1hcmtlciByZXN1bHRzCndyaXRlLmNzdihhbGxfbWFya2VycywgIkFsbE1hcmtlcnNfQ2VsbExpbmVzX01hbGlnbmFudE9ubHkuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgpgYGAKCiMgNS4gICBMb2FkIEdlbmUgU2V0cyBmcm9tIE1TaWdEQgpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShkcGx5cikKbGlicmFyeShwdXJycikKbGlicmFyeShmZ3NlYSkKbGlicmFyeShtc2lnZGJyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShmb3JjYXRzKQoKIyAyLiBMb2FkIEdlbmUgU2V0cyBmcm9tIE1TaWdEQiAoeW91ciBleGFjdCBjb2RlKQoKIyBIYWxsbWFyayAobm8gc3ViY29sbGVjdGlvbiBuZWVkZWQpCmhhbGxtYXJrX3NldHMgPC0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIsIGNhdGVnb3J5ID0gIkgiKSAlPiUKICBzcGxpdCh4ID0gLiRnZW5lX3N5bWJvbCwgZiA9IC4kZ3NfbmFtZSkKCiMgS0VHRyBsZWdhY3kgcGF0aHdheXMKa2VnZ19zZXRzIDwtIG1zaWdkYnIoCiAgICBzcGVjaWVzICAgICAgPSAiSG9tbyBzYXBpZW5zIiwKICAgIGNhdGVnb3J5ICAgICA9ICJDMiIsCiAgICBzdWJjb2xsZWN0aW9uID0gIkNQOktFR0dfTEVHQUNZIgogICkgJT4lCiAgc3BsaXQoeCA9IC4kZ2VuZV9zeW1ib2wsIGYgPSAuJGdzX25hbWUpCgojIFJlYWN0b21lIHBhdGh3YXlzCnJlYWN0b21lX3NldHMgPC0gbXNpZ2RicigKICAgIHNwZWNpZXMgICAgICA9ICJIb21vIHNhcGllbnMiLAogICAgY2F0ZWdvcnkgICAgID0gIkMyIiwKICAgIHN1YmNvbGxlY3Rpb24gPSAiQ1A6UkVBQ1RPTUUiCiAgKSAlPiUKICBzcGxpdCh4ID0gLiRnZW5lX3N5bWJvbCwgZiA9IC4kZ3NfbmFtZSkKCiMgSW1tdW5vbG9naWMgc2lnbmF0dXJlcwpjN19zZXRzIDwtIG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiLCBjYXRlZ29yeSA9ICJDNyIpICU+JQogIHNwbGl0KHggPSAuJGdlbmVfc3ltYm9sLCBmID0gLiRnc19uYW1lKQoKIyBHTyBCaW9sb2dpY2FsIFByb2Nlc3MsIENDLCBNRgpjNV9icCA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiQzUiLCBzdWJjb2xsZWN0aW9uID0gIkJQIikgJT4lCiAgc3BsaXQoeCA9IC4kZ2VuZV9zeW1ib2wsIGYgPSAuJGdzX25hbWUpCgoKIyBDb21iaW5lIGFsbCBzZXRzCm1zaWdkYl9zZXRzIDwtIGxpc3QoCiAgSGFsbG1hcmsgPSBoYWxsbWFya19zZXRzLAogIEtFR0cgICAgID0ga2VnZ19zZXRzLAogIFJlYWN0b21lID0gcmVhY3RvbWVfc2V0cywKICBDNyAgICAgICA9IGM3X3NldHMsCiAgR09fQlAgICAgPSBjNV9icAopCgpgYGAKCgoKIyA0LiAgUnVuIEdTRUEgcGVyIENsdXN0ZXIgdXNpbmcgREUgRmlsZXMKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgMy4gUHJlcGFyZSBvdXRwdXQgbGlzdCBmb3Igc3RvcmluZyBGR1NFQSByZXN1bHRzCmdzZWFfYWxsIDwtIGxpc3QoKQoKIyA0LiBHZXQgdW5pcXVlIGNsdXN0ZXJzIGZyb20gYWxsX21hcmtlcnMKY2x1c3RlcnMgPC0gdW5pcXVlKGFsbF9tYXJrZXJzJGNsdXN0ZXIpCgojIDUuIExvb3Agb3ZlciBlYWNoIGNsdXN0ZXIgYW5kIHJ1biBGR1NFQQpmb3IgKGNsdXN0ZXJfaWQgaW4gY2x1c3RlcnMpIHsKICAKICBjYXQoIlByb2Nlc3NpbmcgY2x1c3RlcjoiLCBjbHVzdGVyX2lkLCAiXG4iKQogIAogICMgU3Vic2V0IERFIGdlbmVzIGZvciBjbHVzdGVyIHZzIHJlc3QKICBkZV9kZiA8LSBhbGxfbWFya2VycyAlPiUKICAgIGZpbHRlcihjbHVzdGVyID09IGNsdXN0ZXJfaWQpICU+JQogICAgZmlsdGVyKCFpcy5uYShhdmdfbG9nMkZDKSkKICAKICAjIENyZWF0ZSBuYW1lZCB2ZWN0b3IgcmFua2VkIGJ5IGF2Z19sb2cyRkMgKGRlc2NlbmRpbmcpCiAgcmFua2VkX2dlbmVzIDwtIGRlZnJhbWUoZGVfZGYgJT4lIHNlbGVjdChnZW5lLCBhdmdfbG9nMkZDKSkKICByYW5rZWRfZ2VuZXMgPC0gc29ydChyYW5rZWRfZ2VuZXMsIGRlY3JlYXNpbmcgPSBUUlVFKQogIAogICMgUnVuIEZHU0VBIG9uIGVhY2ggTVNpZ0RCIGNvbGxlY3Rpb24KICBmb3IgKGRiX25hbWUgaW4gbmFtZXMobXNpZ2RiX3NldHMpKSB7CiAgICBmZ3NlYV9yZXMgPC0gZmdzZWEoCiAgICAgIHBhdGh3YXlzID0gbXNpZ2RiX3NldHNbW2RiX25hbWVdXSwKICAgICAgc3RhdHMgPSByYW5rZWRfZ2VuZXMsCiAgICAgIG1pblNpemUgPSAxMCwKICAgICAgbWF4U2l6ZSA9IDMwMCwKICAgICAgbnBlcm0gPSAxMDAwMAogICAgKQogICAgCiAgICBpZiAobnJvdyhmZ3NlYV9yZXMpID4gMCkgewogICAgICBmZ3NlYV9yZXMkY2x1c3RlciA8LSBjbHVzdGVyX2lkCiAgICAgIGZnc2VhX3JlcyRkYXRhYmFzZSA8LSBkYl9uYW1lCiAgICAgIAogICAgICAjIFNhdmUgaW4gbGlzdCB3aXRoIHVuaXF1ZSBuYW1lCiAgICAgIGdzZWFfYWxsW1twYXN0ZTAoIkNsdXN0ZXJfIiwgY2x1c3Rlcl9pZCwgIl8iLCBkYl9uYW1lKV1dIDwtIGZnc2VhX3JlcwogICAgfQogIH0KfQoKCmBgYAoKIyMgQ29tYmluZSBhbmQgU2F2ZSBBbGwgR1NFQSBSZXN1bHRzCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgNi4gQ29tYmluZSBhbGwgR1NFQSByZXN1bHRzIGludG8gb25lIGRhdGFmcmFtZQpnc2VhX2RmIDwtIGJpbmRfcm93cyhnc2VhX2FsbCkKCiMgNy4gRmxhdHRlbiBsZWFkaW5nRWRnZSBsaXN0IGNvbHVtbiBpbnRvIGEgc2VtaWNvbG9uLXNlcGFyYXRlZCBzdHJpbmcKZ3NlYV9kZiA8LSBnc2VhX2RmICU+JQogIG11dGF0ZShsZWFkaW5nRWRnZSA9IG1hcF9jaHIobGVhZGluZ0VkZ2UsIH4gcGFzdGUoLngsIGNvbGxhcHNlID0gIjsiKSkpCgojIDguIFNhdmUgY29tYmluZWQgcmVzdWx0cyAob3B0aW9uYWwpCndyaXRlLmNzdihnc2VhX2RmLCAiR1NFQV9NU2lnREJfUmVzdWx0c19DbHVzdGVyd2lzZV9maW5kQWxsTWFya2Vyc191c2VkLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKIyA5LiBDcmVhdGUgZm9sZGVycyBhbmQgc2F2ZSBjbHVzdGVyLXdpc2UgcmVzdWx0cyBzZXBhcmF0ZWx5CmdzZWFfYnlfY2x1c3RlciA8LSBzcGxpdChnc2VhX2RmLCBnc2VhX2RmJGNsdXN0ZXIpCgpmb3IgKGNsdXN0ZXJfaWQgaW4gbmFtZXMoZ3NlYV9ieV9jbHVzdGVyKSkgewogIGZvbGRlcl9uYW1lIDwtIHBhc3RlMCgiQ2x1c3Rlcl8iLCBjbHVzdGVyX2lkKQogIAogIGlmICghZGlyLmV4aXN0cyhmb2xkZXJfbmFtZSkpIHsKICAgIGRpci5jcmVhdGUoZm9sZGVyX25hbWUpCiAgfQogIAogIGZpbGVfcGF0aCA8LSBmaWxlLnBhdGgoZm9sZGVyX25hbWUsIHBhc3RlMCgiR1NFQV9DbHVzdGVyXyIsIGNsdXN0ZXJfaWQsICIuY3N2IikpCiAgd3JpdGUuY3N2KGdzZWFfYnlfY2x1c3RlcltbY2x1c3Rlcl9pZF1dLCBmaWxlID0gZmlsZV9wYXRoLCByb3cubmFtZXMgPSBGQUxTRSkKfQoKYGBgCgoKIyMgQ29tYmluZSBhbmQgU2F2ZSBBbGwgR1NFQSBSZXN1bHRzCmBgYHtyICwgZmlnLmhlaWdodD00MCwgZmlnLndpZHRoPTU4fQojIDEwLiBQbG90IHRvcCBHU0VBIHBhdGh3YXlzIHBlciBjbHVzdGVyICYgY29sbGVjdGlvbiAodG9wIDMgcGVyIGNsdXN0ZXIvZGIsIHBhZGo8MC4wNSkKdG9wX3Rlcm1zIDwtIGdzZWFfZGYgJT4lCiAgZmlsdGVyKHBhZGogPCAwLjA1KSAlPiUKICBncm91cF9ieShjbHVzdGVyLCBkYXRhYmFzZSkgJT4lCiAgc2xpY2VfbWF4KE5FUywgbiA9IDEwLCB3aXRoX3RpZXMgPSBGQUxTRSkgJT4lCiAgdW5ncm91cCgpCgojIENsZWFuIHBhdGh3YXkgbmFtZXMKdG9wX3Rlcm1zJHBhdGh3YXkgPC0gZ3N1YigiR09ffFJFQUNUT01FX3xLRUdHXyIsICIiLCB0b3BfdGVybXMkcGF0aHdheSkKdG9wX3Rlcm1zJHBhdGh3YXkgPC0gZ3N1YigiXyIsICIgIiwgdG9wX3Rlcm1zJHBhdGh3YXkpCnRvcF90ZXJtcyRwYXRod2F5IDwtIHN0cl90b190aXRsZSh0b3BfdGVybXMkcGF0aHdheSkKdG9wX3Rlcm1zJHBhdGh3YXkgPC0gc3RyX3RydW5jKHRvcF90ZXJtcyRwYXRod2F5LCB3aWR0aCA9IDYwKQoKIyBQbG90IHVzaW5nIGdncGxvdDIKcDEgPC0gZ2dwbG90KHRvcF90ZXJtcywgYWVzKHggPSBmY3RfcmVvcmRlcihwYXRod2F5LCBORVMpLCB5ID0gTkVTLCBmaWxsID0gZGF0YWJhc2UpKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjkpICsKICBjb29yZF9mbGlwKCkgKwogIGZhY2V0X2dyaWQoZGF0YWJhc2UgfiBjbHVzdGVyLCBzY2FsZXMgPSAiZnJlZV95Iiwgc3BhY2UgPSAiZnJlZSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NTAiKSArCiAgbGFicygKICAgIHggPSAiUGF0aHdheSIsCiAgICB5ID0gIk5vcm1hbGl6ZWQgRW5yaWNobWVudCBTY29yZSAoTkVTKSIsCiAgICB0aXRsZSA9ICJUb3AgR1NFQSBQYXRod2F5cyBwZXIgQ2x1c3RlciIsCiAgICBmaWxsID0gIkRhdGFiYXNlIgogICkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE2KSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTkwIiwgY29sb3IgPSAiYmxhY2siKSwKICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEzKSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgxLCAibGluZXMiKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgc2l6ZSA9IDEuNSkKICApCgogZ2dzYXZlKCJUb3BfR1NFQV9QYXRod2F5c19QZXJfQ2x1c3RlcjEucGRmIiwgcDEsIHdpZHRoID0gMzAsIGhlaWdodCA9IDU4LCBsaW1pdHNpemUgPSBGQUxTRSkKCnAxCgpgYGAKCgojIyBDb21iaW5lIGFuZCBTYXZlIEFsbCBHU0VBIFJlc3VsdHMKYGBge3IgLCBmaWcuaGVpZ2h0PTMwLCBmaWcud2lkdGg9NTh9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ2ZvcmNlKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKCiMgRm9yY2UgY2x1c3RlciBvcmRlcgp0b3BfdGVybXMkY2x1c3RlciA8LSBmYWN0b3IodG9wX3Rlcm1zJGNsdXN0ZXIsIGxldmVscyA9IGFzLmNoYXJhY3RlcigwOjEzKSkKCiMgQ2xlYW4gYW5kIHNob3J0ZW4gcGF0aHdheSBuYW1lcwp0b3BfdGVybXMgPC0gdG9wX3Rlcm1zICU+JQogIG11dGF0ZSgKICAgIHBhdGh3YXkgPSBnc3ViKCJHT198UkVBQ1RPTUVffEtFR0dfIiwgIiIsIHBhdGh3YXkpLAogICAgcGF0aHdheSA9IGdzdWIoIl8iLCAiICIsIHBhdGh3YXkpLAogICAgcGF0aHdheSA9IHN0cl90b190aXRsZShwYXRod2F5KSwKICAgIHBhdGh3YXkgPSBzdHJfdHJ1bmMocGF0aHdheSwgd2lkdGggPSA2MCkKICApCgojIEFkZCBkaXJlY3Rpb24gY29sdW1uCnRvcF90ZXJtcyA8LSB0b3BfdGVybXMgJT4lCiAgbXV0YXRlKGRpcmVjdGlvbiA9IGlmZWxzZShORVMgPiAwLCAiVXByZWd1bGF0ZWQiLCAiRG93bnJlZ3VsYXRlZCIpKQoKIyBVc2UgZGlyZWN0aW9uIGFuZCBkYXRhYmFzZSB0b2dldGhlciBmb3IgY29sb3IKdG9wX3Rlcm1zJGRpcmVjdGlvbl9kYiA8LSBpbnRlcmFjdGlvbih0b3BfdGVybXMkZGlyZWN0aW9uLCB0b3BfdGVybXMkZGF0YWJhc2UsIHNlcCA9ICJfIikKCiMgRGVmaW5lIGN1c3RvbSBjb2xvcnMgZm9yIGVhY2ggZGlyZWN0aW9uK2RiIGNvbWJvIChvcHRpb25hbDogY3VzdG9taXplIGFzIHlvdSBsaWtlKQpuX2NvbG9ycyA8LSBsZW5ndGgodW5pcXVlKHRvcF90ZXJtcyRkaXJlY3Rpb25fZGIpKQpwYWxldHRlIDwtIHNjYWxlczo6aHVlX3BhbCgpKG5fY29sb3JzKQpuYW1lcyhwYWxldHRlKSA8LSB1bmlxdWUodG9wX3Rlcm1zJGRpcmVjdGlvbl9kYikKCiMgUGxvdApwMiA8LSBnZ3Bsb3QodG9wX3Rlcm1zLCBhZXMoeCA9IGZjdF9yZW9yZGVyKHBhdGh3YXksIE5FUyksIHkgPSBORVMsIGZpbGwgPSBkaXJlY3Rpb25fZGIpKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjkpICsKICBjb29yZF9mbGlwKCkgKwogIGZhY2V0X2dyaWQoZGF0YWJhc2UgfiBjbHVzdGVyLCBzY2FsZXMgPSAiZnJlZV95Iiwgc3BhY2UgPSAiZnJlZSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NTAiKSArCiAgbGFicygKICAgIHggPSAiUGF0aHdheSIsCiAgICB5ID0gIk5vcm1hbGl6ZWQgRW5yaWNobWVudCBTY29yZSAoTkVTKSIsCiAgICB0aXRsZSA9ICJUb3AgR1NFQSBQYXRod2F5cyBwZXIgQ2x1c3RlciIsCiAgICBmaWxsID0gIkRpcmVjdGlvbiArIERCIgogICkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE2KSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTkwIiwgY29sb3IgPSAiYmxhY2siKSwKICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEzKSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgxLCAibGluZXMiKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgc2l6ZSA9IDEuNSkKICApCgojIFNhdmUgd2l0aCBjb3JyZWN0IHNpemUgb3ZlcnJpZGUKIGdnc2F2ZSgiVG9wX0dTRUFfUGF0aHdheXNfUGVyX0NsdXN0ZXIyLnBkZiIsIHAyLCB3aWR0aCA9IDMwLCBoZWlnaHQgPSA1OCwgbGltaXRzaXplID0gRkFMU0UpCnAyCmBgYAoKIyMgQ29tYmluZSBhbmQgU2F2ZSBBbGwgR1NFQSBSZXN1bHRzCmBgYHtyICwgZmlnLmhlaWdodD0xOCwgZmlnLndpZHRoPTIwfQojIFJlcXVpcmVkIHBhY2thZ2VzCmxpYnJhcnkobXNpZ2RicikKbGlicmFyeShmZ3NlYSkKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KHN0cmluZ3IpCgojIFNwbGl0IHRoZSBhbGxtYXJrZXJzIChmcm9tIEZpbmRBbGxNYXJrZXJzKSBpbnRvIGEgbmFtZWQgbGlzdCBwZXIgY2x1c3RlcgpjbHVzdGVyX3N0YXRzIDwtIHNwbGl0KGFsbF9tYXJrZXJzLCBhbGxfbWFya2VycyRjbHVzdGVyKQoKCiMgMS4gQ3VyYXRlZCBTw6l6YXJ5IHN5bmRyb21l4oCTcmVsZXZhbnQgcGF0aHdheXMgKHVzZSB0aGVpciBleGFjdCBNU2lnREIgbmFtZXMpCmN1cmF0ZWRfcGF0aHdheXMgPC0gYygKICAjIEhhbGxtYXJrCiAgIkhBTExNQVJLX0pBS19TVEFUM19TSUdOQUxJTkciLCAiSEFMTE1BUktfVE5GQV9TSUdOQUxJTkdfVklBX05GS0IiLCAiSEFMTE1BUktfQVBPUFRPU0lTIiwKICAjIEtFR0cKICAiS0VHR19UX0NFTExfUkVDRVBUT1JfU0lHTkFMSU5HX1BBVEhXQVkiLCAiS0VHR19KQUtfU1RBVF9TSUdOQUxJTkdfUEFUSFdBWSIsCiAgIktFR0dfUEkzS19BS1RfU0lHTkFMSU5HX1BBVEhXQVkiLCAiS0VHR19NQVBLX1NJR05BTElOR19QQVRIV0FZIiwKICAiS0VHR19UR0ZfQkVUQV9TSUdOQUxJTkdfUEFUSFdBWSIsICJLRUdHX0NFTExfQ1lDTEUiLCAiS0VHR19BUE9QVE9TSVMiLAogICMgUmVhY3RvbWUKICAiUkVBQ1RPTUVfU0lHTkFMSU5HX0JZX1RDUiIsICJSRUFDVE9NRV9TSUdOQUxJTkdfQllfSkFLX1NUQVQiLAogICJSRUFDVE9NRV9QSTNLX0FLVF9BQ1RJVkFUSU9OIiwgIlJFQUNUT01FX05GS0JfQUNUSVZBVElPTiIsCiAgIyBHTyAoQmlvbG9naWNhbCBQcm9jZXNzKQogICJHT0JQX0NZVE9LSU5FX01FRElBVEVEX1NJR05BTElOR19QQVRIV0FZIiwgIkdPQlBfVF9DRUxMX0FDVElWQVRJT04iLAogICJHT0JQX0NFTExfQ1lDTEVfUFJPQ0VTUyIsICJHT0JQX0FQT1BUT1RJQ19QUk9DRVNTIiwKICAiR09CUF9NQVBLX0NBU0NBREUiLCAiR09CUF9ORl9LQVBQQV9CX1RSQU5TQ1JJUFRJT05fRkFDVE9SX0FDVElWSVRZIiwKICAiR09CUF9KQUtfU1RBVF9DQVNDQURFIiwgIkdPQlBfRVBJR0VORVRJQ19SRUdVTEFUSU9OIgopCgojIDIuIExvYWQgcGF0aHdheXMgZnJvbSBtc2lnZGJyCm1zaWdfZGYgPC0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIpICU+JQogIGZpbHRlcihnc19uYW1lICVpbiUgY3VyYXRlZF9wYXRod2F5cykKCnBhdGh3YXlzX2xpc3QgPC0gc3BsaXQobXNpZ19kZiRnZW5lX3N5bWJvbCwgbXNpZ19kZiRnc19uYW1lKQoKIyAzLiBZb3VyIGlucHV0OiBhIGxpc3Qgb2YgcmFua2VkIGdlbmUgc3RhdHMgKGUuZy4sIGZyb20gU2V1cmF0OjpGaW5kTWFya2VycykgZm9yIGVhY2ggY2x1c3RlcgojIEV4YW1wbGU6IGNsdXN0ZXJfc3RhdHMgaXMgYSBuYW1lZCBsaXN0IG9mIGRhdGEuZnJhbWVzLCBlYWNoIGNvbnRhaW5pbmcgZ2VuZSwgYXZnX2xvZzJGQywgcF92YWxfYWRqCiMgRXhhbXBsZSBvZiBtYWtpbmcgcmFuayB2ZWN0b3I6IHN0YXRzJGF2Z19sb2cyRkMgKiAtbG9nMTAoc3RhdHMkcF92YWxfYWRqICsgMWUtMzAwKQoKIyBSZXBsYWNlIHdpdGggeW91ciByZWFsIGNsdXN0ZXItbGV2ZWwgc3RhdHMgbGlzdAojIGNsdXN0ZXJfc3RhdHMgPC0gbGlzdChjbHVzdGVyQSA9IGRmX0EsIGNsdXN0ZXJCID0gZGZfQiwgLi4uKQoKIyA0LiBSdW4gZmdzZWEgZm9yIGVhY2ggY2x1c3RlcgpmZ3NlYV9yZXN1bHRzIDwtIGxhcHBseShjbHVzdGVyX3N0YXRzLCBmdW5jdGlvbihzdGF0c19kZikgewogIHN0YXRzX2RmIDwtIHN0YXRzX2RmICU+JSBmaWx0ZXIoIWlzLm5hKHBfdmFsX2FkaiksICFpcy5uYShhdmdfbG9nMkZDKSkKICByYW5rcyA8LSBzdGF0c19kZiRhdmdfbG9nMkZDICogLWxvZzEwKHN0YXRzX2RmJHBfdmFsX2FkaiArIDFlLTMwMCkKICBuYW1lcyhyYW5rcykgPC0gcm93bmFtZXMoc3RhdHNfZGYpCiAgZmdzZWEocGF0aHdheXMgPSBwYXRod2F5c19saXN0LCBzdGF0cyA9IHNvcnQocmFua3MsIGRlY3JlYXNpbmcgPSBUUlVFKSwgbnBlcm0gPSA1MDAwKQp9KQoKIyA1LiBDb21iaW5lIGFuZCBhbm5vdGF0ZQpnc2VhX2RmIDwtIGJpbmRfcm93cyhsYXBwbHkobmFtZXMoZmdzZWFfcmVzdWx0cyksIGZ1bmN0aW9uKGNsdXN0ZXIpIHsKICByZXMgPC0gZmdzZWFfcmVzdWx0c1tbY2x1c3Rlcl1dCiAgcmVzJGNsdXN0ZXIgPC0gY2x1c3RlcgogIHJlcwp9KSkKCiMgRmlsdGVyIHRvIGN1cmF0ZWQgcGF0aHdheXMgKGFscmVhZHkgZG9uZSBidXQgZ29vZCB0byBkb3VibGUgY2hlY2spCmdzZWFfZGYgPC0gZ3NlYV9kZiAlPiUgZmlsdGVyKHBhdGh3YXkgJWluJSBjdXJhdGVkX3BhdGh3YXlzKQoKIyBBZGQgcGF0aHdheSBzb3VyY2UgbGFiZWwKZ3NlYV9kZiA8LSBnc2VhX2RmICU+JQogIG11dGF0ZShkYXRhYmFzZSA9IGNhc2Vfd2hlbigKICAgIHN0cl9kZXRlY3QocGF0aHdheSwgIl5IQUxMTUFSSyIpIH4gIkhhbGxtYXJrIiwKICAgIHN0cl9kZXRlY3QocGF0aHdheSwgIl5LRUdHIikgfiAiS0VHRyIsCiAgICBzdHJfZGV0ZWN0KHBhdGh3YXksICJeUkVBQ1RPTUUiKSB+ICJSZWFjdG9tZSIsCiAgICBzdHJfZGV0ZWN0KHBhdGh3YXksICJeR09CUCIpIH4gIkdPIiwKICAgIFRSVUUgfiAiT3RoZXIiCiAgKSkgJT4lCiAgbXV0YXRlKGRpcmVjdGlvbl9kYiA9IGlmZWxzZShORVMgPiAwLCBwYXN0ZTAoIisgIiwgZGF0YWJhc2UpLCBwYXN0ZTAoIi0gIiwgZGF0YWJhc2UpKSkKCiMgNi4gT3B0aW9uYWxseSBmaWx0ZXIgdG8gdG9wIE4gcGF0aHdheXMgcGVyIGNsdXN0ZXIKdG9wX3Rlcm1zIDwtIGdzZWFfZGYgJT4lCiAgZ3JvdXBfYnkoY2x1c3RlciwgZGF0YWJhc2UpICU+JQogIHRvcF9uKDUsIHd0ID0gYWJzKE5FUykpICU+JQogIHVuZ3JvdXAoKQoKIyA3LiBTZXQgZmlsbCBwYWxldHRlIGZvciB1cC9kb3duLXJlZ3VsYXRpb24KcGFsZXR0ZSA8LSBjKAogICJIYWxsbWFyayIgPSAiI2Q2MjcyOCIsICJLRUdHIiA9ICIjMmNhMDJjIiwKICAiUmVhY3RvbWUiID0gIiMxZjc3YjQiLCAiR08iID0gIiM5NDY3YmQiCikKcGFsZXR0ZSA8LSBjKAogIGArIEhhbGxtYXJrYCA9ICIjZDYyNzI4IiwgYC0gSGFsbG1hcmtgID0gIiNmY2JiYTEiLAogIGArIEtFR0dgID0gIiMyY2EwMmMiLCBgLSBLRUdHYCA9ICIjYjlmNmNhIiwKICBgKyBSZWFjdG9tZWAgPSAiIzFmNzdiNCIsIGAtIFJlYWN0b21lYCA9ICIjYWVjN2U4IiwKICBgKyBHT2AgPSAiIzk0NjdiZCIsIGAtIEdPYCA9ICIjZDViZGUzIgopCgojIDguIFBsb3QKcDMgPC0gZ2dwbG90KHRvcF90ZXJtcywgYWVzKHggPSBmY3RfcmVvcmRlcihwYXRod2F5LCBORVMpLCB5ID0gTkVTLCBmaWxsID0gZGlyZWN0aW9uX2RiKSkgKwogIGdlb21fY29sKHdpZHRoID0gMC45KSArCiAgY29vcmRfZmxpcCgpICsKICBmYWNldF9ncmlkKGRhdGFiYXNlIH4gY2x1c3Rlciwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlID0gImZyZWUiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JheTUwIikgKwogIGxhYnMoCiAgICB4ID0gIlBhdGh3YXkiLAogICAgeSA9ICJOb3JtYWxpemVkIEVucmljaG1lbnQgU2NvcmUgKE5FUykiLAogICAgdGl0bGUgPSAiVG9wIEdTRUEgUGF0aHdheXMgcGVyIENsdXN0ZXIiLAogICAgZmlsbCA9ICJEaXJlY3Rpb24gKyBEQiIKICApICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNikgKwogIHRoZW1lKAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXk5MCIsIGNvbG9yID0gImJsYWNrIiksCiAgICBzdHJpcC5wbGFjZW1lbnQgPSAib3V0c2lkZSIsCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMyksCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIHNpemUgPSAxLjUpCiAgKQoKIyA5LiBTYXZlIHRoZSBwbG90Cmdnc2F2ZSgiVG9wX0dTRUFfUGF0aHdheXNfUGVyX0NsdXN0ZXIzLnBkZiIsIHAzLCB3aWR0aCA9IDMwLCBoZWlnaHQgPSA1OCwgbGltaXRzaXplID0gRkFMU0UpCgpwMwpgYGAKCgojIyBDb21iaW5lIGFuZCBTYXZlIEFsbCBHU0VBIFJlc3VsdHMKYGBge3IgLCBmaWcuaGVpZ2h0PTE4LCBmaWcud2lkdGg9MjB9CiMgUmVxdWlyZWQgcGFja2FnZXMKbGlicmFyeShtc2lnZGJyKQpsaWJyYXJ5KGZnc2VhKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpYmJsZSkKbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkoc3RyaW5ncikKCiMgMS4gQ3VyYXRlZCBTw6l6YXJ5IHN5bmRyb21l4oCTcmVsZXZhbnQgTVNpZ0RCIHBhdGh3YXlzCmN1cmF0ZWRfcGF0aHdheXMgPC0gYygKICAjIEhhbGxtYXJrCiAgIkhBTExNQVJLX0pBS19TVEFUM19TSUdOQUxJTkciLCAiSEFMTE1BUktfVE5GQV9TSUdOQUxJTkdfVklBX05GS0IiLCAiSEFMTE1BUktfQVBPUFRPU0lTIiwKICAjIEtFR0cKICAiS0VHR19UX0NFTExfUkVDRVBUT1JfU0lHTkFMSU5HX1BBVEhXQVkiLCAiS0VHR19KQUtfU1RBVF9TSUdOQUxJTkdfUEFUSFdBWSIsCiAgIktFR0dfUEkzS19BS1RfU0lHTkFMSU5HX1BBVEhXQVkiLCAiS0VHR19NQVBLX1NJR05BTElOR19QQVRIV0FZIiwKICAiS0VHR19UR0ZfQkVUQV9TSUdOQUxJTkdfUEFUSFdBWSIsICJLRUdHX0NFTExfQ1lDTEUiLCAiS0VHR19BUE9QVE9TSVMiLAogICMgUmVhY3RvbWUKICAiUkVBQ1RPTUVfU0lHTkFMSU5HX0JZX1RDUiIsICJSRUFDVE9NRV9TSUdOQUxJTkdfQllfSkFLX1NUQVQiLAogICJSRUFDVE9NRV9QSTNLX0FLVF9BQ1RJVkFUSU9OIiwgIlJFQUNUT01FX05GS0JfQUNUSVZBVElPTiIsCiAgIyBHTyAoQmlvbG9naWNhbCBQcm9jZXNzKQogICJHT0JQX0NZVE9LSU5FX01FRElBVEVEX1NJR05BTElOR19QQVRIV0FZIiwgIkdPQlBfVF9DRUxMX0FDVElWQVRJT04iLAogICJHT0JQX0NFTExfQ1lDTEVfUFJPQ0VTUyIsICJHT0JQX0FQT1BUT1RJQ19QUk9DRVNTIiwKICAiR09CUF9NQVBLX0NBU0NBREUiLCAiR09CUF9ORl9LQVBQQV9CX1RSQU5TQ1JJUFRJT05fRkFDVE9SX0FDVElWSVRZIiwKICAiR09CUF9KQUtfU1RBVF9DQVNDQURFIiwgIkdPQlBfRVBJR0VORVRJQ19SRUdVTEFUSU9OIgopCgojIDIuIExvYWQgTVNpZ0RCIGdlbmVzCm1zaWdfZGYgPC0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIpICU+JQogIGZpbHRlcihnc19uYW1lICVpbiUgY3VyYXRlZF9wYXRod2F5cykKCnBhdGh3YXlzX2xpc3QgPC0gc3BsaXQobXNpZ19kZiRnZW5lX3N5bWJvbCwgbXNpZ19kZiRnc19uYW1lKQoKIyAzLiBTcGxpdCBGaW5kQWxsTWFya2VycyBkYXRhIGZyYW1lIGJ5IGNsdXN0ZXIKY2x1c3Rlcl9zdGF0cyA8LSBzcGxpdChhbGxfbWFya2VycywgYWxsX21hcmtlcnMkY2x1c3RlcikKCiMgNC4gUnVuIGZnc2VhIHVzaW5nIGF2Z19sb2cyRkMgYXMgcmFua2luZyBtZXRyaWMKZmdzZWFfcmVzdWx0cyA8LSBsYXBwbHkoY2x1c3Rlcl9zdGF0cywgZnVuY3Rpb24oc3RhdHNfZGYpIHsKICAjIEVuc3VyZSBhdmdfbG9nMkZDIGV4aXN0cyBhbmQgZ2VuZSBuYW1lcyBhcmUgcHJlc2VudAogIHN0YXRzX2RmIDwtIHN0YXRzX2RmICU+JQogICAgZmlsdGVyKCFpcy5uYShhdmdfbG9nMkZDKSkgJT4lCiAgICBkaXN0aW5jdChnZW5lLCAua2VlcF9hbGwgPSBUUlVFKQoKICAjIENoZWNrIGlmIGdlbmUgY29sdW1uIGV4aXN0cwogIGlmICghImdlbmUiICVpbiUgY29sbmFtZXMoc3RhdHNfZGYpKSB7CiAgICB3YXJuaW5nKCJObyAnZ2VuZScgY29sdW1uIGZvdW5kIGluIHN0YXRzX2RmIikKICAgIHJldHVybihOVUxMKQogIH0KCiAgIyBDcmVhdGUgcmFuayB2ZWN0b3IKICByYW5rcyA8LSBzdGF0c19kZiRhdmdfbG9nMkZDCiAgbmFtZXMocmFua3MpIDwtIHN0YXRzX2RmJGdlbmUKICByYW5rcyA8LSBzb3J0KHJhbmtzLCBkZWNyZWFzaW5nID0gVFJVRSkKCiAgIyBPcHRpb25hbDogc2tpcCBzbWFsbCByYW5rIHZlY3RvcnMKICBpZiAobGVuZ3RoKHJhbmtzKSA8IDEwMCkgcmV0dXJuKE5VTEwpCgogICBmZ3NlYSgKICAgIHBhdGh3YXlzID0gcGF0aHdheXNfbGlzdCwKICAgIHN0YXRzID0gc29ydChyYW5rcywgZGVjcmVhc2luZyA9IFRSVUUpLAogICAgbWluU2l6ZSA9IDEwLAogICAgbWF4U2l6ZSA9IDMwMCwKICAgIG5wZXJtID0gMTAwMDAKICApCn0pCgoKIyA1LiBDb21iaW5lIGFuZCBhbm5vdGF0ZSByZXN1bHRzCmdzZWFfZGYgPC0gYmluZF9yb3dzKGxhcHBseShuYW1lcyhmZ3NlYV9yZXN1bHRzKSwgZnVuY3Rpb24oY2x1c3RlcikgewogIHJlcyA8LSBmZ3NlYV9yZXN1bHRzW1tjbHVzdGVyXV0KICByZXMkY2x1c3RlciA8LSBjbHVzdGVyCiAgcmVzCn0pKQoKIyA2LiBFbnN1cmUgYWxsIHBhdGh3YXlzIGFwcGVhciBhY3Jvc3MgY2x1c3RlcnMKYWxsX2NvbWJvcyA8LSBleHBhbmQuZ3JpZCgKICBjbHVzdGVyID0gbmFtZXMoY2x1c3Rlcl9zdGF0cyksCiAgcGF0aHdheSA9IGN1cmF0ZWRfcGF0aHdheXMsCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCikKCmdzZWFfY29tcGxldGUgPC0gYWxsX2NvbWJvcyAlPiUKICBsZWZ0X2pvaW4oZ3NlYV9kZiwgYnkgPSBjKCJjbHVzdGVyIiwgInBhdGh3YXkiKSkgJT4lCiAgbXV0YXRlKAogICAgTkVTID0gaWZlbHNlKGlzLm5hKE5FUyksIDAsIE5FUyksCiAgICBwYWRqID0gaWZlbHNlKGlzLm5hKHBhZGopLCAxLCBwYWRqKSwKICAgIGRhdGFiYXNlID0gY2FzZV93aGVuKAogICAgICBzdHJfZGV0ZWN0KHBhdGh3YXksICJeSEFMTE1BUksiKSB+ICJIYWxsbWFyayIsCiAgICAgIHN0cl9kZXRlY3QocGF0aHdheSwgIl5LRUdHIikgfiAiS0VHRyIsCiAgICAgIHN0cl9kZXRlY3QocGF0aHdheSwgIl5SRUFDVE9NRSIpIH4gIlJlYWN0b21lIiwKICAgICAgc3RyX2RldGVjdChwYXRod2F5LCAiXkdPQlAiKSB+ICJHTyIsCiAgICAgIFRSVUUgfiAiT3RoZXIiCiAgICApLAogICAgZGlyZWN0aW9uX2RiID0gaWZlbHNlKE5FUyA+IDAsIHBhc3RlMCgiKyAiLCBkYXRhYmFzZSksIHBhc3RlMCgiLSAiLCBkYXRhYmFzZSkpLAogICAgc2lnID0gaWZlbHNlKHBhZGogPCAwLjA1LCAiKiIsICIiKQogICkKCiMgNy4gQ29sb3IgcGFsZXR0ZQpwYWxldHRlIDwtIGMoCiAgYCsgSGFsbG1hcmtgID0gIiNkNjI3MjgiLCBgLSBIYWxsbWFya2AgPSAiI2ZjYmJhMSIsCiAgYCsgS0VHR2AgPSAiIzJjYTAyYyIsIGAtIEtFR0dgID0gIiNiOWY2Y2EiLAogIGArIFJlYWN0b21lYCA9ICIjMWY3N2I0IiwgYC0gUmVhY3RvbWVgID0gIiNhZWM3ZTgiLAogIGArIEdPYCA9ICIjOTQ2N2JkIiwgYC0gR09gID0gIiNkNWJkZTMiCikKCiMgOC4gUGxvdApwNCA8LSBnZ3Bsb3QoZ3NlYV9jb21wbGV0ZSwgYWVzKHggPSBmY3RfcmVvcmRlcihwYXRod2F5LCBORVMpLCB5ID0gTkVTLCBmaWxsID0gZGlyZWN0aW9uX2RiKSkgKwogIGdlb21fY29sKHdpZHRoID0gMC45KSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNpZyksIGhqdXN0ID0gLTAuMywgc2l6ZSA9IDUsIGZvbnRmYWNlID0gImJvbGQiLCBjb2xvciA9ICJibGFjayIpICsKICBjb29yZF9mbGlwKCkgKwogIGZhY2V0X2dyaWQoZGF0YWJhc2UgfiBjbHVzdGVyLCBzY2FsZXMgPSAiZnJlZV95Iiwgc3BhY2UgPSAiZnJlZSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NTAiKSArCiAgbGFicygKICAgIHggPSAiUGF0aHdheSIsCiAgICB5ID0gIk5vcm1hbGl6ZWQgRW5yaWNobWVudCBTY29yZSAoTkVTKSIsCiAgICB0aXRsZSA9ICJHU0VBIChhdmdfbG9nMkZDIG9ubHkpIOKAlCBDdXJhdGVkIFBhdGh3YXlzIHBlciBDbHVzdGVyIiwKICAgIGZpbGwgPSAiRW5yaWNobWVudCIKICApICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlLCBuYS52YWx1ZSA9ICJncmF5ODAiKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNikgKwogIHRoZW1lKAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXk5MCIsIGNvbG9yID0gImJsYWNrIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMyksCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIHNpemUgPSAxLjUpCiAgKQoKIyA5LiBTYXZlIHRvIFBERgpnZ3NhdmUoIkN1cmF0ZWRfR1NFQV9hdmdMb2dGQ19Pbmx5LnBkZiIsIHA0LCB3aWR0aCA9IDMwLCBoZWlnaHQgPSA1OCwgbGltaXRzaXplID0gRkFMU0UpCgpwNApgYGAKCgo=