3. Volcano Plot 1
library(ggplot2)
library(dplyr)
library(ggrepel)
# Filter significant genes
de_genes_sig <- de_genes %>%
filter(!is.na(p_val_adj)) %>%
mutate(direction = case_when(
avg_log2FC >= 1 & p_val_adj < 0.05 ~ "Upregulated",
avg_log2FC <= -1 & p_val_adj < 0.05 ~ "Downregulated",
TRUE ~ "NS"
))
# Select top 50 up and 50 downregulated genes
top_genes <- de_genes_sig %>%
filter(direction %in% c("Upregulated", "Downregulated")) %>%
group_by(direction) %>%
slice_min(order_by = p_val_adj, n = 50) %>%
ungroup()
# Volcano plot
volcano <- ggplot(de_genes_sig, aes(x = avg_log2FC, y = -log10(p_val_adj))) +
geom_point(aes(color = direction), alpha = 0.7, size = 2.5) + # Increased dot size here
scale_color_manual(values = c("Upregulated" = "#D62728", "Downregulated" = "#1F77B4", "NS" = "lightgrey")) +
geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "grey40") +
geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "grey40") +
geom_text_repel(
data = top_genes,
aes(label = gene),
size = 4,
max.overlaps = Inf, # No limit on overlaps
box.padding = 0.5,
segment.size = 0.3
) +
labs(
title = "Volcano Plot: Malignant vs Normal CD4+ T cells",
x = "log2 Fold Change",
y = "-log10 Adjusted p-value",
color = "Regulation"
) +
theme_minimal(base_size = 13) +
theme(
legend.position = "right",
plot.title = element_text(hjust = 0.5)
)
# Display or save
print(volcano)

# ggsave("volcano_plot.pdf", plot = volcano, width = 8, height = 6)
Volcano Plot 2
library(ggplot2)
library(dplyr)
library(ggrepel)
# ---- Step 1: Prepare Data ----
de_genes <- de_genes %>%
mutate(
log10_pval = -log10(p_val_adj),
regulation = case_when(
avg_log2FC >= 1.5 & p_val_adj < 0.05 ~ "Upregulated",
avg_log2FC <= -1 & p_val_adj < 0.05 ~ "Downregulated",
TRUE ~ "NS"
)
)
# ---- Step 2: Top 50 Up and 50 Downregulated Genes ----
top_genes <- de_genes %>%
filter(regulation %in% c("Upregulated", "Downregulated")) %>%
group_by(regulation) %>%
slice_min(order_by = p_val_adj, n = 50) %>%
ungroup()
# ---- Step 3: Plot ----
p3 <- ggplot(de_genes, aes(x = avg_log2FC, y = log10_pval)) +
geom_point(aes(color = regulation), size = 3, alpha = 0.7) +
scale_color_manual(values = c("Upregulated" = "#D62728", "Downregulated" = "#1F77B4", "NS" = "lightgrey")) +
geom_vline(xintercept = c(-1, 1.5), linetype = "dashed", color = "grey50") +
geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "grey50") +
geom_label_repel(
data = top_genes,
mapping = aes(label = gene),
size = 3.5, # text size
max.overlaps = 100,
box.padding = 0.3,
segment.size = 0.3,
min.segment.length = 0
) +
labs(
title = "Volcano Plot: Malignant vs Normal CD4+ T cells",
x = "log2 Fold Change",
y = "-log10 Adjusted p-value",
color = "Regulation"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(hjust = 0.5),
legend.position = "right"
)
# ---- Step 4: Display Plot ----
print(p3)

Volcano Plot 3
# Step 1: Store Your Gene Lists in R
# Upregulated genes
up_genes <- c("MYL6B", "CENPF", "CDT1", "CRNDE", "CHEK1", "TPX2", "UBE2T", "CDCA8", "CDKN3", "PCLAF",
"ASF1B", "MCM2", "MYBL2", "PKMYT1", "SLC25A5", "NUSAP1", "CENPW", "AHCY", "TTF2", "COX5A",
"FH", "CKS1B", "UCK2", "CKS2", "CCNB1", "PYCR1", "MAPKAPK3", "NCAPD2", "TRIP13", "RBBP8",
"TUBA1C", "RNASEH2A", "BRCA1", "KPNA2", "NME1", "NABP2", "GTSF1", "CDC20", "SNX10", "MAD2L1",
"YWHAH", "UBE2C", "TOP2A", "EBP", "CLIC1", "GINS2", "SLC29A1", "SRI", "ORC6", "PLK1")
# Downregulated genes
down_genes <- c("SARAF", "PCED1B-AS1", "SNHG5", "BTG1", "SRSF5", "IKZF1", "PRMT2", "RBL2", "PACS1", "MAX",
"ZBTB20", "PIK3IP1", "RAPGEF6", "IL7R", "N4BP2L2", "SF1", "RPS27", "RIPOR2", "RSRP1", "DAZAP2",
"ZFP36L1", "TXNIP", "HLA-E", "DGKA", "SON", "DDX6", "RASA3", "VAMP2", "PNRC1", "CDKN1B",
"PPP2R5C", "LEPROTL1", "EPC1", "CD247", "FOXP1", "PBXIP1", "LINC01578", "CIRBP", "ABLIM1",
"SUN2", "ZFP36", "ZFP36L2", "AL138963.4", "ETS1", "RNASET2", "HIF1A", "PNISR", "R3HDM4",
"ANKRD44", "DDX24")
#Step 2: Process DE Data and Add Regulation Category
highlight_genes <- c(up_genes, down_genes)
library(dplyr)
de_genes_processed <- de_genes %>%
filter(!is.na(p_val_adj)) %>%
mutate(
log10_pval = -log10(p_val_adj),
regulation = case_when(
avg_log2FC >= 1.5 & p_val_adj < 0.05 ~ "Upregulated",
avg_log2FC <= -1 & p_val_adj < 0.05 ~ "Downregulated",
TRUE ~ "NS"
),
highlight = ifelse(gene %in% highlight_genes, gene, NA)
)
# Step 3: Make Volcano Plot with Highlighted Genes
library(ggplot2)
library(ggrepel)
ggplot(de_genes_processed, aes(x = avg_log2FC, y = log10_pval)) +
geom_point(aes(color = regulation), alpha = 0.7, size = 2.8) +
scale_color_manual(values = c("Upregulated" = "#D62728", "Downregulated" = "#1F77B4", "NS" = "lightgrey")) +
geom_vline(xintercept = c(-1, 1.5), linetype = "dashed", color = "gray50") +
geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "gray50") +
geom_label_repel(
data = filter(de_genes_processed, !is.na(highlight)),
aes(label = highlight),
size = 3.2,
box.padding = 0.3,
max.overlaps = 100,
segment.size = 0.3
) +
labs(
title = "Volcano Plot Highlighting Selected Biomarkers",
x = "log2 Fold Change",
y = "-log10 Adjusted p-value",
color = "Regulation"
) +
theme_minimal(base_size = 14) +
theme(plot.title = element_text(hjust = 0.5))

Volcano Plot 4
# Step 1: Store Your Gene Lists in R
# Upregulated genes
up_genes <- c("MYL6B", "CENPF", "CDT1", "CRNDE", "CHEK1", "TPX2", "UBE2T", "CDCA8", "CDKN3", "PCLAF",
"ASF1B", "MCM2", "MYBL2", "PKMYT1", "SLC25A5", "NUSAP1", "CENPW", "AHCY", "TTF2", "COX5A",
"FH", "CKS1B", "UCK2", "CKS2", "CCNB1", "PYCR1", "MAPKAPK3", "NCAPD2", "TRIP13", "RBBP8",
"TUBA1C", "RNASEH2A", "BRCA1", "KPNA2", "NME1", "NABP2", "GTSF1", "CDC20", "SNX10", "MAD2L1",
"YWHAH", "UBE2C", "TOP2A", "EBP", "CLIC1", "GINS2", "SLC29A1", "SRI", "ORC6", "PLK1")
# Downregulated genes
down_genes <- c("SARAF", "PCED1B-AS1", "SNHG5", "BTG1", "SRSF5", "IKZF1", "PRMT2", "RBL2", "PACS1", "MAX",
"ZBTB20", "PIK3IP1", "RAPGEF6", "IL7R", "N4BP2L2", "SF1", "RPS27", "RIPOR2", "RSRP1", "DAZAP2",
"ZFP36L1", "TXNIP", "HLA-E", "DGKA", "SON", "DDX6", "RASA3", "VAMP2", "PNRC1", "CDKN1B",
"PPP2R5C", "LEPROTL1", "EPC1", "CD247", "FOXP1", "PBXIP1", "LINC01578", "CIRBP", "ABLIM1",
"SUN2", "ZFP36", "ZFP36L2", "AL138963.4", "ETS1", "RNASET2", "HIF1A", "PNISR", "R3HDM4",
"ANKRD44", "DDX24")
# Custom theme for Nature-style plots
nature_theme <- function(base_size = 12, base_family = "sans") {
theme_minimal(base_size = base_size, base_family = base_family) +
theme(
text = element_text(color = "black"),
plot.title = element_text(hjust = 0.5, face = "bold", size = rel(1.2)),
axis.title = element_text(face = "bold", size = rel(1)),
axis.text = element_text(size = rel(0.9)),
legend.position = c(0.85, 0.85),
legend.background = element_rect(fill = "white", color = NA),
panel.grid.major = element_line(linewidth = 0.25, color = "grey90"),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
axis.line = element_line(linewidth = 0.5, color = "black")
)
}
# Enhanced volcano plot with bold text and 1 point bigger size
ggplot(de_genes_processed, aes(x = avg_log2FC, y = log10_pval)) +
geom_point(
aes(color = regulation, alpha = regulation, size = regulation),
shape = 16
) +
scale_color_manual(
values = c(
"Upregulated" = "#D32F2F", # Nature-style red
"Downregulated" = "#1976D2", # Nature-style blue
"NS" = "grey60"
),
breaks = c("Upregulated", "Downregulated")
) +
scale_alpha_manual(
values = c(
"Upregulated" = 0.8, # Slightly reduced opacity for better contrast
"Downregulated" = 0.8,
"NS" = 0.5
),
guide = "none"
) +
scale_size_manual(
values = c(
"Upregulated" = 3.5, # Slightly larger size for upregulated
"Downregulated" = 3.5,
"NS" = 2
),
guide = "none"
) +
geom_vline(
xintercept = c(-1.5, 1.5), # Adjust threshold for more specific markers
linetype = "dashed",
color = "grey40",
linewidth = 0.6
) +
geom_hline(
yintercept = -log10(0.05),
linetype = "dashed",
color = "grey40",
linewidth = 0.6
) +
geom_text_repel(
data = filter(de_genes_processed, !is.na(highlight)),
aes(label = highlight),
size = 4.5, # Increase text size by 1 point
fontface = "bold", # Make text bold
box.padding = 0.45,
point.padding = 0.3,
segment.color = "grey30",
segment.size = 0.4,
max.overlaps = 25,
min.segment.length = 0.1,
force = 2,
color = "black",
bg.color = "white",
bg.r = 0.15
) +
annotate(
"text",
x = c(-2.8, 2.8),
y = rep(max(de_genes_processed$log10_pval) * 0.95, 2),
label = c("Downregulated", "Upregulated"),
color = c("#1976D2", "#D32F2F"),
size = 5, # Increase text size by 1 point
fontface = "bold"
) +
labs(
title = "Volcano Plot of Differentially Expressed Genes",
x = expression(Log[2]~fold~change),
y = expression(-Log[10]~adjusted~italic(p)),
color = "Gene Regulation"
) +
nature_theme() +
guides(
color = guide_legend(override.aes = list(size = 4, alpha = 1))
) +
coord_cartesian(clip = "off") +
scale_x_continuous(expand = expansion(mult = 0.1)) +
scale_y_continuous(expand = expansion(mult = 0.05))

NA
NA
Heatmap-1

Heatmap-2
library(Seurat)
library(ComplexHeatmap)
library(circlize)
library(viridis)
# 1. Prepare gene lists with error checking
all_genes <- unique(c(up_genes, down_genes))
all_genes <- intersect(all_genes, rownames(GetAssayData(sample, assay = "RNA"))) # Corrected line
if(length(all_genes) == 0) stop("No genes from the lists found in the Seurat object")
# 2. Set default assay to "RNA" and scale the data
DefaultAssay(sample) <- "RNA" # Set the default assay to RNA
#sample <- ScaleData(sample) # Scale the RNA data
# 3. Extract scaled data
expr_matrix <- GetAssayData(sample, assay = "RNA", slot = "scale.data")[all_genes, ]
# 4. Create metadata annotations
gene_annotation <- data.frame(
Gene = all_genes,
Regulation = ifelse(all_genes %in% up_genes, "Up", "Down"),
row.names = all_genes
)
# Order by clusters
cluster_order <- order(sample$seurat_clusters)
expr_matrix <- expr_matrix[, cluster_order]
# 5. Create annotations
column_ha <- HeatmapAnnotation(
Cluster = sample$seurat_clusters[cluster_order],
col = list(Cluster = setNames(
viridis(length(unique(sample$seurat_clusters))),
unique(sample$seurat_clusters)
)),
annotation_name_side = "left",
show_legend = TRUE
)
row_ha <- rowAnnotation(
Regulation = gene_annotation[all_genes, "Regulation"],
col = list(Regulation = c("Up" = "#D32F2F", "Down" = "#1976D2")),
show_annotation_name = FALSE
)
# 6. Create heatmap with additional improvements
ht <- Heatmap(expr_matrix,
name = "Z-score",
col = colorRamp2(c(-2, 0, 2), c("#1E88E5", "white", "#D81B60")), # Adjust color scheme for better contrast
cluster_rows = TRUE, # Cluster rows (genes)
cluster_columns = TRUE, # Cluster columns (samples)
show_row_names = TRUE,
show_column_names = FALSE,
row_names_gp = gpar(fontsize = 8), # Smaller row name font
column_title_gp = gpar(fontsize = 12, fontface = "bold"), # Larger column title font
top_annotation = column_ha,
left_annotation = row_ha,
heatmap_legend_param = list(
title_gp = gpar(fontsize = 10, fontface = "bold"),
labels_gp = gpar(fontsize = 8),
direction = "horizontal" # Place legend horizontally for more room
),
row_title = "Genes", # Add a row title
column_split = sample$seurat_clusters, # Split columns by clusters
row_dend_width = unit(4, "cm"),
column_dend_height = unit(4, "cm"), # Adjust column dendrogram height
show_row_dend = TRUE, # Show row dendrogram
show_column_dend = TRUE, # Show column dendrogram
border = TRUE, # Add borders around the cells
row_names_side = "left", # Place row names on the left
column_names_gp = gpar(fontsize = 8, fontface = "italic"), # Italicize column names
use_raster = TRUE # Use rasterization for better performance
)
# 7. Display in notebook with improved padding and legend side
draw(ht, padding = unit(c(4, 4, 4, 4), "mm"),
heatmap_legend_side = "right",
annotation_legend_side = "right")
# 8. Save outputs
# PDF for publication
pdf("publication_heatmap_improved2.pdf", width = 8.7/2.54, height = 11/2.54) # Convert cm to inches
draw(ht)
dev.off()
png
2
# PNG for preview
png("heatmap_preview_improved2.png", width = 2500, height = 3000, res = 300)
draw(ht)
dev.off()
png
2

LS0tCnRpdGxlOiAiSFNQQyB2cyBDb250cm9sX1ZvbGNhbm9QbG90cyIKYXV0aG9yOiBOYXNpciBNYWhtb29kIEFiYmFzaQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICAjIHBkZl9kb2N1bWVudDogZGVmYXVsdAogICMgd29yZF9kb2N1bWVudDogZGVmYXVsdAogICMgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoU0NwdWJyKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTQ3B1YnIpCgojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcwpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShvcmcuSHMuZWcuZGIpCmxpYnJhcnkoZW5yaWNocGxvdCkKbGlicmFyeShSZWFjdG9tZVBBKQpsaWJyYXJ5KERPU0UpICMgRm9yIEdTRUEgYW5hbHlzaXMKbGlicmFyeShnZ3Bsb3QyKSAjIEVuc3VyZSBnZ3Bsb3QyIGlzIGF2YWlsYWJsZSBmb3IgcGxvdHRpbmcKbGlicmFyeShkcGx5cikKCmBgYAoKIyAyLiBMb2FkIHRoZSBmaWx0ZXJlZCBsaXN0IG9uIG1lYW4gZXhwcmVzc2lvbgpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQoKbG9hZCgiLi4vLi4vVG9fVHJhbnNmZXJfYmV0d2Vlbl9jb21wdXRlcnMvMjMtSGFybW9ueV9JbnRlZ3JhdGlvbi8wLXJvYmovNS1IYXJtb255X0ludGVncmF0ZWRfQWxsX3NhbXBsZXNfTWVyZ2VkX0NENFRjZWxsc19maW5hbF9SZXNvbHV0aW9uX1NlbGVjdGVkXzAuOF9BRFRfTm9ybWFsaXplZF9jbGVhbmVkX210LnJvYmoiKQoKc2FtcGxlIDwtIEFsbF9zYW1wbGVzX01lcmdlZAoKcm0oQWxsX3NhbXBsZXNfTWVyZ2VkKQoKZ2MoKQoKIyBSZWFkIHRoZSBDU1YgZmlsZSBmcm9tIExJQlJBIHBzZXVkb2J1bGsgREUKZGVfZ2VuZXMgPC0gcmVhZF9jc3YoIi4uLy4uL1RvX1RyYW5zZmVyX2JldHdlZW5fY29tcHV0ZXJzLzEtRklOQUxfUHNldWRvYnVsX0FuYWx5c2lzLzItTWFsaWduYW50X3ZzX0NvbnRyb2xfUHNldWRvYnVsa19FbnJpY2htZW50X0FuYWx5c2lzLzItUHNldWRvYnVsa19EZXNlcTJfTFJUX2ZpbHRlcmVkX29uX21lYW4uY3N2IikgICMgVXNlIHJlYWQuY3N2KCkgaWYgbmVlZGVkCgojIFN0ZXAgMjogUmVuYW1lIGNvbHVtbnMgdG8gbWF0Y2ggU0NwdWJyIGV4cGVjdGF0aW9ucwpkZV9nZW5lcyA8LSBkZV9nZW5lcyAlPiUKICByZW5hbWUoCiAgICBhdmdfbG9nMkZDID0gYXZnX2xvZ0ZDLCAgICMgVGhpcyBpcyBjcnVjaWFsCiAgICBwX3ZhbF9hZGogPSBwX3ZhbF9hZGosICAgICMgQWxyZWFkeSBjb3JyZWN0CiAgICBnZW5lID0gZ2VuZSAgICAgICAgICAgICAgICMgQWxyZWFkeSBjb3JyZWN0CiAgKQpkZV9nZW5lc191bmlxdWUgPC0gZGVfZ2VuZXMgJT4lCiAgZmlsdGVyKGFicyhhdmdfbG9nMkZDKSA+IDApICU+JSAgIyBGaWx0ZXIgb3V0IGdlbmVzIHdpdGggZm9sZCBjaGFuZ2UgZXhhY3RseSAwIChpZiBhbnkpCiAgZ3JvdXBfYnkoZ2VuZSkgJT4lCiAgc2xpY2VfbWluKG9yZGVyX2J5ID0gcF92YWxfYWRqLCBuID0gMSwgd2l0aF90aWVzID0gRkFMU0UpICU+JSAgIyBLZWVwIG9ubHkgdGhlIGJlc3QgcmVzdWx0IHBlciBnZW5lCiAgdW5ncm91cCgpCgpwIDwtIFNDcHVicjo6ZG9fVm9sY2Fub1Bsb3QoCiAgc2FtcGxlID0gc2FtcGxlLAogIGRlX2dlbmVzID0gZGVfZ2VuZXMKKQoKCiMgRGlzcGxheSB0aGUgcGxvdApwcmludChwKQoKYGBgCgojIDMuIFZvbGNhbm8gUGxvdCAxCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3JlcGVsKQoKIyBGaWx0ZXIgc2lnbmlmaWNhbnQgZ2VuZXMKZGVfZ2VuZXNfc2lnIDwtIGRlX2dlbmVzICU+JQogIGZpbHRlcighaXMubmEocF92YWxfYWRqKSkgJT4lCiAgbXV0YXRlKGRpcmVjdGlvbiA9IGNhc2Vfd2hlbigKICAgIGF2Z19sb2cyRkMgPj0gMSAmIHBfdmFsX2FkaiA8IDAuMDUgfiAiVXByZWd1bGF0ZWQiLAogICAgYXZnX2xvZzJGQyA8PSAtMSAmIHBfdmFsX2FkaiA8IDAuMDUgfiAiRG93bnJlZ3VsYXRlZCIsCiAgICBUUlVFIH4gIk5TIgogICkpCgojIFNlbGVjdCB0b3AgNTAgdXAgYW5kIDUwIGRvd25yZWd1bGF0ZWQgZ2VuZXMKdG9wX2dlbmVzIDwtIGRlX2dlbmVzX3NpZyAlPiUKICBmaWx0ZXIoZGlyZWN0aW9uICVpbiUgYygiVXByZWd1bGF0ZWQiLCAiRG93bnJlZ3VsYXRlZCIpKSAlPiUKICBncm91cF9ieShkaXJlY3Rpb24pICU+JQogIHNsaWNlX21pbihvcmRlcl9ieSA9IHBfdmFsX2FkaiwgbiA9IDUwKSAlPiUKICB1bmdyb3VwKCkKCiMgVm9sY2FubyBwbG90CnZvbGNhbm8gPC0gZ2dwbG90KGRlX2dlbmVzX3NpZywgYWVzKHggPSBhdmdfbG9nMkZDLCB5ID0gLWxvZzEwKHBfdmFsX2FkaikpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBkaXJlY3Rpb24pLCBhbHBoYSA9IDAuNywgc2l6ZSA9IDIuNSkgKyAgIyBJbmNyZWFzZWQgZG90IHNpemUgaGVyZQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJVcHJlZ3VsYXRlZCIgPSAiI0Q2MjcyOCIsICJEb3ducmVndWxhdGVkIiA9ICIjMUY3N0I0IiwgIk5TIiA9ICJsaWdodGdyZXkiKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoLTEsIDEpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5NDAiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5NDAiKSArCiAgZ2VvbV90ZXh0X3JlcGVsKAogICAgZGF0YSA9IHRvcF9nZW5lcywKICAgIGFlcyhsYWJlbCA9IGdlbmUpLAogICAgc2l6ZSA9IDQsCiAgICBtYXgub3ZlcmxhcHMgPSBJbmYsICAjIE5vIGxpbWl0IG9uIG92ZXJsYXBzCiAgICBib3gucGFkZGluZyA9IDAuNSwKICAgIHNlZ21lbnQuc2l6ZSA9IDAuMwogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWb2xjYW5vIFBsb3Q6IE1hbGlnbmFudCB2cyBOb3JtYWwgQ0Q0KyBUIGNlbGxzIiwKICAgIHggPSAibG9nMiBGb2xkIENoYW5nZSIsCiAgICB5ID0gIi1sb2cxMCBBZGp1c3RlZCBwLXZhbHVlIiwKICAgIGNvbG9yID0gIlJlZ3VsYXRpb24iCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpCiAgKQoKIyBEaXNwbGF5IG9yIHNhdmUKcHJpbnQodm9sY2FubykKIyBnZ3NhdmUoInZvbGNhbm9fcGxvdC5wZGYiLCBwbG90ID0gdm9sY2Fubywgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQoKCmBgYAoKCiMjIFZvbGNhbm8gUGxvdCAyCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3JlcGVsKQoKIyAtLS0tIFN0ZXAgMTogUHJlcGFyZSBEYXRhIC0tLS0KZGVfZ2VuZXMgPC0gZGVfZ2VuZXMgJT4lCiAgbXV0YXRlKAogICAgbG9nMTBfcHZhbCA9IC1sb2cxMChwX3ZhbF9hZGopLAogICAgcmVndWxhdGlvbiA9IGNhc2Vfd2hlbigKICAgICAgYXZnX2xvZzJGQyA+PSAxLjUgJiBwX3ZhbF9hZGogPCAwLjA1IH4gIlVwcmVndWxhdGVkIiwKICAgICAgYXZnX2xvZzJGQyA8PSAtMSAmIHBfdmFsX2FkaiA8IDAuMDUgfiAiRG93bnJlZ3VsYXRlZCIsCiAgICAgIFRSVUUgfiAiTlMiCiAgICApCiAgKQoKIyAtLS0tIFN0ZXAgMjogVG9wIDUwIFVwIGFuZCA1MCBEb3ducmVndWxhdGVkIEdlbmVzIC0tLS0KdG9wX2dlbmVzIDwtIGRlX2dlbmVzICU+JQogIGZpbHRlcihyZWd1bGF0aW9uICVpbiUgYygiVXByZWd1bGF0ZWQiLCAiRG93bnJlZ3VsYXRlZCIpKSAlPiUKICBncm91cF9ieShyZWd1bGF0aW9uKSAlPiUKICBzbGljZV9taW4ob3JkZXJfYnkgPSBwX3ZhbF9hZGosIG4gPSA1MCkgJT4lCiAgdW5ncm91cCgpCgoKIyAtLS0tIFN0ZXAgMzogUGxvdCAtLS0tCnAzIDwtIGdncGxvdChkZV9nZW5lcywgYWVzKHggPSBhdmdfbG9nMkZDLCB5ID0gbG9nMTBfcHZhbCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IHJlZ3VsYXRpb24pLCBzaXplID0gMywgYWxwaGEgPSAwLjcpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiVXByZWd1bGF0ZWQiID0gIiNENjI3MjgiLCAiRG93bnJlZ3VsYXRlZCIgPSAiIzFGNzdCNCIsICJOUyIgPSAibGlnaHRncmV5IikpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0xLCAxLjUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5NTAiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5NTAiKSArCiAgZ2VvbV9sYWJlbF9yZXBlbCgKICAgIGRhdGEgPSB0b3BfZ2VuZXMsCiAgICBtYXBwaW5nID0gYWVzKGxhYmVsID0gZ2VuZSksCiAgICBzaXplID0gMy41LCAgICAgICAgICAgICAgIyB0ZXh0IHNpemUKICAgIG1heC5vdmVybGFwcyA9IDEwMCwKICAgIGJveC5wYWRkaW5nID0gMC4zLAogICAgc2VnbWVudC5zaXplID0gMC4zLAogICAgbWluLnNlZ21lbnQubGVuZ3RoID0gMAogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWb2xjYW5vIFBsb3Q6IE1hbGlnbmFudCB2cyBOb3JtYWwgQ0Q0KyBUIGNlbGxzIiwKICAgIHggPSAibG9nMiBGb2xkIENoYW5nZSIsCiAgICB5ID0gIi1sb2cxMCBBZGp1c3RlZCBwLXZhbHVlIiwKICAgIGNvbG9yID0gIlJlZ3VsYXRpb24iCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiCiAgKQoKIyAtLS0tIFN0ZXAgNDogRGlzcGxheSBQbG90IC0tLS0KcHJpbnQocDMpCgpgYGAKCiMjIFZvbGNhbm8gUGxvdCAzCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CiMgU3RlcCAxOiBTdG9yZSBZb3VyIEdlbmUgTGlzdHMgaW4gUgoKIyBVcHJlZ3VsYXRlZCBnZW5lcwp1cF9nZW5lcyA8LSBjKCJNWUw2QiIsICJDRU5QRiIsICJDRFQxIiwgIkNSTkRFIiwgIkNIRUsxIiwgIlRQWDIiLCAiVUJFMlQiLCAiQ0RDQTgiLCAiQ0RLTjMiLCAiUENMQUYiLCAKICAgICAgICAgICAgICAiQVNGMUIiLCAiTUNNMiIsICJNWUJMMiIsICJQS01ZVDEiLCAiU0xDMjVBNSIsICJOVVNBUDEiLCAiQ0VOUFciLCAiQUhDWSIsICJUVEYyIiwgIkNPWDVBIiwgCiAgICAgICAgICAgICAgIkZIIiwgIkNLUzFCIiwgIlVDSzIiLCAiQ0tTMiIsICJDQ05CMSIsICJQWUNSMSIsICJNQVBLQVBLMyIsICJOQ0FQRDIiLCAiVFJJUDEzIiwgIlJCQlA4IiwgCiAgICAgICAgICAgICAgIlRVQkExQyIsICJSTkFTRUgyQSIsICJCUkNBMSIsICJLUE5BMiIsICJOTUUxIiwgIk5BQlAyIiwgIkdUU0YxIiwgIkNEQzIwIiwgIlNOWDEwIiwgIk1BRDJMMSIsIAogICAgICAgICAgICAgICJZV0hBSCIsICJVQkUyQyIsICJUT1AyQSIsICJFQlAiLCAiQ0xJQzEiLCAiR0lOUzIiLCAiU0xDMjlBMSIsICJTUkkiLCAiT1JDNiIsICJQTEsxIikKCiMgRG93bnJlZ3VsYXRlZCBnZW5lcwpkb3duX2dlbmVzIDwtIGMoIlNBUkFGIiwgIlBDRUQxQi1BUzEiLCAiU05IRzUiLCAiQlRHMSIsICJTUlNGNSIsICJJS1pGMSIsICJQUk1UMiIsICJSQkwyIiwgIlBBQ1MxIiwgIk1BWCIsCiAgICAgICAgICAgICAgICAiWkJUQjIwIiwgIlBJSzNJUDEiLCAiUkFQR0VGNiIsICJJTDdSIiwgIk40QlAyTDIiLCAiU0YxIiwgIlJQUzI3IiwgIlJJUE9SMiIsICJSU1JQMSIsICJEQVpBUDIiLAogICAgICAgICAgICAgICAgIlpGUDM2TDEiLCAiVFhOSVAiLCAiSExBLUUiLCAiREdLQSIsICJTT04iLCAiRERYNiIsICJSQVNBMyIsICJWQU1QMiIsICJQTlJDMSIsICJDREtOMUIiLAogICAgICAgICAgICAgICAgIlBQUDJSNUMiLCAiTEVQUk9UTDEiLCAiRVBDMSIsICJDRDI0NyIsICJGT1hQMSIsICJQQlhJUDEiLCAiTElOQzAxNTc4IiwgIkNJUkJQIiwgIkFCTElNMSIsIAogICAgICAgICAgICAgICAgIlNVTjIiLCAiWkZQMzYiLCAiWkZQMzZMMiIsICJBTDEzODk2My40IiwgIkVUUzEiLCAiUk5BU0VUMiIsICJISUYxQSIsICJQTklTUiIsICJSM0hETTQiLCAKICAgICAgICAgICAgICAgICJBTktSRDQ0IiwgIkREWDI0IikKCiNTdGVwIDI6IFByb2Nlc3MgREUgRGF0YSBhbmQgQWRkIFJlZ3VsYXRpb24gQ2F0ZWdvcnkKaGlnaGxpZ2h0X2dlbmVzIDwtIGModXBfZ2VuZXMsIGRvd25fZ2VuZXMpCgpsaWJyYXJ5KGRwbHlyKQoKZGVfZ2VuZXNfcHJvY2Vzc2VkIDwtIGRlX2dlbmVzICU+JQogIGZpbHRlcighaXMubmEocF92YWxfYWRqKSkgJT4lCiAgbXV0YXRlKAogICAgbG9nMTBfcHZhbCA9IC1sb2cxMChwX3ZhbF9hZGopLAogICAgcmVndWxhdGlvbiA9IGNhc2Vfd2hlbigKICAgICAgYXZnX2xvZzJGQyA+PSAxLjUgJiBwX3ZhbF9hZGogPCAwLjA1IH4gIlVwcmVndWxhdGVkIiwKICAgICAgYXZnX2xvZzJGQyA8PSAtMSAmIHBfdmFsX2FkaiA8IDAuMDUgfiAiRG93bnJlZ3VsYXRlZCIsCiAgICAgIFRSVUUgfiAiTlMiCiAgICApLAogICAgaGlnaGxpZ2h0ID0gaWZlbHNlKGdlbmUgJWluJSBoaWdobGlnaHRfZ2VuZXMsIGdlbmUsIE5BKQogICkKCiMgU3RlcCAzOiBNYWtlIFZvbGNhbm8gUGxvdCB3aXRoIEhpZ2hsaWdodGVkIEdlbmVzCgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyZXBlbCkKCmdncGxvdChkZV9nZW5lc19wcm9jZXNzZWQsIGFlcyh4ID0gYXZnX2xvZzJGQywgeSA9IGxvZzEwX3B2YWwpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSByZWd1bGF0aW9uKSwgYWxwaGEgPSAwLjcsIHNpemUgPSAyLjgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiVXByZWd1bGF0ZWQiID0gIiNENjI3MjgiLCAiRG93bnJlZ3VsYXRlZCIgPSAiIzFGNzdCNCIsICJOUyIgPSAibGlnaHRncmV5IikpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0xLCAxLjUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NTAiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NTAiKSArCiAgZ2VvbV9sYWJlbF9yZXBlbCgKICAgIGRhdGEgPSBmaWx0ZXIoZGVfZ2VuZXNfcHJvY2Vzc2VkLCAhaXMubmEoaGlnaGxpZ2h0KSksCiAgICBhZXMobGFiZWwgPSBoaWdobGlnaHQpLAogICAgc2l6ZSA9IDMuMiwKICAgIGJveC5wYWRkaW5nID0gMC4zLAogICAgbWF4Lm92ZXJsYXBzID0gMTAwLAogICAgc2VnbWVudC5zaXplID0gMC4zCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIlZvbGNhbm8gUGxvdCBIaWdobGlnaHRpbmcgU2VsZWN0ZWQgQmlvbWFya2VycyIsCiAgICB4ID0gImxvZzIgRm9sZCBDaGFuZ2UiLAogICAgeSA9ICItbG9nMTAgQWRqdXN0ZWQgcC12YWx1ZSIsCiAgICBjb2xvciA9ICJSZWd1bGF0aW9uIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAoKCgoKIyMgVm9sY2FubyBQbG90IDQKYGBge3IgLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTZ9CiMgU3RlcCAxOiBTdG9yZSBZb3VyIEdlbmUgTGlzdHMgaW4gUgoKIyBVcHJlZ3VsYXRlZCBnZW5lcwp1cF9nZW5lcyA8LSBjKCJNWUw2QiIsICJDRU5QRiIsICJDRFQxIiwgIkNSTkRFIiwgIkNIRUsxIiwgIlRQWDIiLCAiVUJFMlQiLCAiQ0RDQTgiLCAiQ0RLTjMiLCAiUENMQUYiLCAKICAgICAgICAgICAgICAiQVNGMUIiLCAiTUNNMiIsICJNWUJMMiIsICJQS01ZVDEiLCAiU0xDMjVBNSIsICJOVVNBUDEiLCAiQ0VOUFciLCAiQUhDWSIsICJUVEYyIiwgIkNPWDVBIiwgCiAgICAgICAgICAgICAgIkZIIiwgIkNLUzFCIiwgIlVDSzIiLCAiQ0tTMiIsICJDQ05CMSIsICJQWUNSMSIsICJNQVBLQVBLMyIsICJOQ0FQRDIiLCAiVFJJUDEzIiwgIlJCQlA4IiwgCiAgICAgICAgICAgICAgIlRVQkExQyIsICJSTkFTRUgyQSIsICJCUkNBMSIsICJLUE5BMiIsICJOTUUxIiwgIk5BQlAyIiwgIkdUU0YxIiwgIkNEQzIwIiwgIlNOWDEwIiwgIk1BRDJMMSIsIAogICAgICAgICAgICAgICJZV0hBSCIsICJVQkUyQyIsICJUT1AyQSIsICJFQlAiLCAiQ0xJQzEiLCAiR0lOUzIiLCAiU0xDMjlBMSIsICJTUkkiLCAiT1JDNiIsICJQTEsxIikKCiMgRG93bnJlZ3VsYXRlZCBnZW5lcwpkb3duX2dlbmVzIDwtIGMoIlNBUkFGIiwgIlBDRUQxQi1BUzEiLCAiU05IRzUiLCAiQlRHMSIsICJTUlNGNSIsICJJS1pGMSIsICJQUk1UMiIsICJSQkwyIiwgIlBBQ1MxIiwgIk1BWCIsCiAgICAgICAgICAgICAgICAiWkJUQjIwIiwgIlBJSzNJUDEiLCAiUkFQR0VGNiIsICJJTDdSIiwgIk40QlAyTDIiLCAiU0YxIiwgIlJQUzI3IiwgIlJJUE9SMiIsICJSU1JQMSIsICJEQVpBUDIiLAogICAgICAgICAgICAgICAgIlpGUDM2TDEiLCAiVFhOSVAiLCAiSExBLUUiLCAiREdLQSIsICJTT04iLCAiRERYNiIsICJSQVNBMyIsICJWQU1QMiIsICJQTlJDMSIsICJDREtOMUIiLAogICAgICAgICAgICAgICAgIlBQUDJSNUMiLCAiTEVQUk9UTDEiLCAiRVBDMSIsICJDRDI0NyIsICJGT1hQMSIsICJQQlhJUDEiLCAiTElOQzAxNTc4IiwgIkNJUkJQIiwgIkFCTElNMSIsIAogICAgICAgICAgICAgICAgIlNVTjIiLCAiWkZQMzYiLCAiWkZQMzZMMiIsICJBTDEzODk2My40IiwgIkVUUzEiLCAiUk5BU0VUMiIsICJISUYxQSIsICJQTklTUiIsICJSM0hETTQiLCAKICAgICAgICAgICAgICAgICJBTktSRDQ0IiwgIkREWDI0IikKCiMgQ3VzdG9tIHRoZW1lIGZvciBOYXR1cmUtc3R5bGUgcGxvdHMKbmF0dXJlX3RoZW1lIDwtIGZ1bmN0aW9uKGJhc2Vfc2l6ZSA9IDEyLCBiYXNlX2ZhbWlseSA9ICJzYW5zIikgewogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gYmFzZV9zaXplLCBiYXNlX2ZhbWlseSA9IGJhc2VfZmFtaWx5KSArCiAgICB0aGVtZSgKICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gcmVsKDEuMikpLAogICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSByZWwoMSkpLAogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjkpKSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjg1LCAwLjg1KSwKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gTkEpLAogICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGxpbmV3aWR0aCA9IDAuMjUsIGNvbG9yID0gImdyZXk5MCIpLAogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShsaW5ld2lkdGggPSAwLjUsIGNvbG9yID0gImJsYWNrIikKICAgICkKfQoKIyBFbmhhbmNlZCB2b2xjYW5vIHBsb3Qgd2l0aCBib2xkIHRleHQgYW5kIDEgcG9pbnQgYmlnZ2VyIHNpemUKZ2dwbG90KGRlX2dlbmVzX3Byb2Nlc3NlZCwgYWVzKHggPSBhdmdfbG9nMkZDLCB5ID0gbG9nMTBfcHZhbCkpICsKICBnZW9tX3BvaW50KAogICAgYWVzKGNvbG9yID0gcmVndWxhdGlvbiwgYWxwaGEgPSByZWd1bGF0aW9uLCBzaXplID0gcmVndWxhdGlvbiksCiAgICBzaGFwZSA9IDE2CiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgdmFsdWVzID0gYygKICAgICAgIlVwcmVndWxhdGVkIiA9ICIjRDMyRjJGIiwgICMgTmF0dXJlLXN0eWxlIHJlZAogICAgICAiRG93bnJlZ3VsYXRlZCIgPSAiIzE5NzZEMiIsICAjIE5hdHVyZS1zdHlsZSBibHVlCiAgICAgICJOUyIgPSAiZ3JleTYwIgogICAgKSwKICAgIGJyZWFrcyA9IGMoIlVwcmVndWxhdGVkIiwgIkRvd25yZWd1bGF0ZWQiKQogICkgKwogIHNjYWxlX2FscGhhX21hbnVhbCgKICAgIHZhbHVlcyA9IGMoCiAgICAgICJVcHJlZ3VsYXRlZCIgPSAwLjgsICAjIFNsaWdodGx5IHJlZHVjZWQgb3BhY2l0eSBmb3IgYmV0dGVyIGNvbnRyYXN0CiAgICAgICJEb3ducmVndWxhdGVkIiA9IDAuOCwKICAgICAgIk5TIiA9IDAuNQogICAgKSwKICAgIGd1aWRlID0gIm5vbmUiCiAgKSArCiAgc2NhbGVfc2l6ZV9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKAogICAgICAiVXByZWd1bGF0ZWQiID0gMy41LCAgIyBTbGlnaHRseSBsYXJnZXIgc2l6ZSBmb3IgdXByZWd1bGF0ZWQKICAgICAgIkRvd25yZWd1bGF0ZWQiID0gMy41LAogICAgICAiTlMiID0gMgogICAgKSwKICAgIGd1aWRlID0gIm5vbmUiCiAgKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSBjKC0xLjUsIDEuNSksICAjIEFkanVzdCB0aHJlc2hvbGQgZm9yIG1vcmUgc3BlY2lmaWMgbWFya2VycwogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwKICAgIGNvbG9yID0gImdyZXk0MCIsCiAgICBsaW5ld2lkdGggPSAwLjYKICApICsKICBnZW9tX2hsaW5lKAogICAgeWludGVyY2VwdCA9IC1sb2cxMCgwLjA1KSwKICAgIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICBjb2xvciA9ICJncmV5NDAiLAogICAgbGluZXdpZHRoID0gMC42CiAgKSArCiAgZ2VvbV90ZXh0X3JlcGVsKAogICAgZGF0YSA9IGZpbHRlcihkZV9nZW5lc19wcm9jZXNzZWQsICFpcy5uYShoaWdobGlnaHQpKSwKICAgIGFlcyhsYWJlbCA9IGhpZ2hsaWdodCksCiAgICBzaXplID0gNC41LCAgIyBJbmNyZWFzZSB0ZXh0IHNpemUgYnkgMSBwb2ludAogICAgZm9udGZhY2UgPSAiYm9sZCIsICAjIE1ha2UgdGV4dCBib2xkCiAgICBib3gucGFkZGluZyA9IDAuNDUsCiAgICBwb2ludC5wYWRkaW5nID0gMC4zLAogICAgc2VnbWVudC5jb2xvciA9ICJncmV5MzAiLAogICAgc2VnbWVudC5zaXplID0gMC40LAogICAgbWF4Lm92ZXJsYXBzID0gMjUsCiAgICBtaW4uc2VnbWVudC5sZW5ndGggPSAwLjEsCiAgICBmb3JjZSA9IDIsCiAgICBjb2xvciA9ICJibGFjayIsCiAgICBiZy5jb2xvciA9ICJ3aGl0ZSIsCiAgICBiZy5yID0gMC4xNQogICkgKwogIGFubm90YXRlKAogICAgInRleHQiLAogICAgeCA9IGMoLTIuOCwgMi44KSwKICAgIHkgPSByZXAobWF4KGRlX2dlbmVzX3Byb2Nlc3NlZCRsb2cxMF9wdmFsKSAqIDAuOTUsIDIpLAogICAgbGFiZWwgPSBjKCJEb3ducmVndWxhdGVkIiwgIlVwcmVndWxhdGVkIiksCiAgICBjb2xvciA9IGMoIiMxOTc2RDIiLCAiI0QzMkYyRiIpLAogICAgc2l6ZSA9IDUsICAjIEluY3JlYXNlIHRleHQgc2l6ZSBieSAxIHBvaW50CiAgICBmb250ZmFjZSA9ICJib2xkIgogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWb2xjYW5vIFBsb3Qgb2YgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzIiwKICAgIHggPSBleHByZXNzaW9uKExvZ1syXX5mb2xkfmNoYW5nZSksCiAgICB5ID0gZXhwcmVzc2lvbigtTG9nWzEwXX5hZGp1c3RlZH5pdGFsaWMocCkpLAogICAgY29sb3IgPSAiR2VuZSBSZWd1bGF0aW9uIgogICkgKwogIG5hdHVyZV90aGVtZSgpICsKICBndWlkZXMoCiAgICBjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSA0LCBhbHBoYSA9IDEpKQogICkgKwogIGNvb3JkX2NhcnRlc2lhbihjbGlwID0gIm9mZiIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSAwLjEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gMC4wNSkpCgoKYGBgCgojIyBIZWF0bWFwLTEKYGBge3IgLCBmaWcuaGVpZ2h0PTIyLCBmaWcud2lkdGg9MzZ9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShDb21wbGV4SGVhdG1hcCkKbGlicmFyeShjaXJjbGl6ZSkKbGlicmFyeSh2aXJpZGlzKQoKIyAxLiBQcmVwYXJlIGdlbmUgbGlzdHMgd2l0aCBlcnJvciBjaGVja2luZwphbGxfZ2VuZXMgPC0gdW5pcXVlKGModXBfZ2VuZXMsIGRvd25fZ2VuZXMpKQphbGxfZ2VuZXMgPC0gaW50ZXJzZWN0KGFsbF9nZW5lcywgcm93bmFtZXMoR2V0QXNzYXlEYXRhKHNhbXBsZSwgYXNzYXkgPSAiUk5BIikpKSAjIENvcnJlY3RlZCBsaW5lCgppZihsZW5ndGgoYWxsX2dlbmVzKSA9PSAwKSBzdG9wKCJObyBnZW5lcyBmcm9tIHRoZSBsaXN0cyBmb3VuZCBpbiB0aGUgU2V1cmF0IG9iamVjdCIpCgojIDIuIFNldCBkZWZhdWx0IGFzc2F5IHRvICJSTkEiIGFuZCBzY2FsZSB0aGUgZGF0YQpEZWZhdWx0QXNzYXkoc2FtcGxlKSA8LSAiUk5BIiAgIyBTZXQgdGhlIGRlZmF1bHQgYXNzYXkgdG8gUk5BCnNhbXBsZSA8LSBTY2FsZURhdGEoc2FtcGxlKSAgIyBTY2FsZSB0aGUgUk5BIGRhdGEKCiMgMy4gRXh0cmFjdCBzY2FsZWQgZGF0YQpleHByX21hdHJpeCA8LSBHZXRBc3NheURhdGEoc2FtcGxlLCBhc3NheSA9ICJSTkEiLCBzbG90ID0gInNjYWxlLmRhdGEiKVthbGxfZ2VuZXMsIF0KCiMgNC4gQ3JlYXRlIG1ldGFkYXRhIGFubm90YXRpb25zCmdlbmVfYW5ub3RhdGlvbiA8LSBkYXRhLmZyYW1lKAogIEdlbmUgPSBhbGxfZ2VuZXMsCiAgUmVndWxhdGlvbiA9IGlmZWxzZShhbGxfZ2VuZXMgJWluJSB1cF9nZW5lcywgIlVwIiwgIkRvd24iKSwKICByb3cubmFtZXMgPSBhbGxfZ2VuZXMKKQoKIyBPcmRlciBieSBjbHVzdGVycwpjbHVzdGVyX29yZGVyIDwtIG9yZGVyKHNhbXBsZSRzZXVyYXRfY2x1c3RlcnMpCmV4cHJfbWF0cml4IDwtIGV4cHJfbWF0cml4WywgY2x1c3Rlcl9vcmRlcl0KCiMgNS4gQ3JlYXRlIGFubm90YXRpb25zCmNvbHVtbl9oYSA8LSBIZWF0bWFwQW5ub3RhdGlvbigKICBDbHVzdGVyID0gc2FtcGxlJHNldXJhdF9jbHVzdGVyc1tjbHVzdGVyX29yZGVyXSwKICBjb2wgPSBsaXN0KENsdXN0ZXIgPSBzZXROYW1lcygKICAgIHZpcmlkaXMobGVuZ3RoKHVuaXF1ZShzYW1wbGUkc2V1cmF0X2NsdXN0ZXJzKSkpLAogICAgdW5pcXVlKHNhbXBsZSRzZXVyYXRfY2x1c3RlcnMpCiAgKSksCiAgYW5ub3RhdGlvbl9uYW1lX3NpZGUgPSAibGVmdCIsCiAgc2hvd19sZWdlbmQgPSBUUlVFCikKCnJvd19oYSA8LSByb3dBbm5vdGF0aW9uKAogIFJlZ3VsYXRpb24gPSBnZW5lX2Fubm90YXRpb25bYWxsX2dlbmVzLCAiUmVndWxhdGlvbiJdLAogIGNvbCA9IGxpc3QoUmVndWxhdGlvbiA9IGMoIlVwIiA9ICIjRDMyRjJGIiwgIkRvd24iID0gIiMxOTc2RDIiKSksCiAgc2hvd19hbm5vdGF0aW9uX25hbWUgPSBGQUxTRQopCgojIDYuIENyZWF0ZSBoZWF0bWFwCmh0IDwtIEhlYXRtYXAoZXhwcl9tYXRyaXgsCiAgbmFtZSA9ICJaLXNjb3JlIiwKICBjb2wgPSBjb2xvclJhbXAyKGMoLTIsIDAsIDIpLCBjKCIjMUU4OEU1IiwgIndoaXRlIiwgIiNEODFCNjAiKSksCiAgY2x1c3Rlcl9jb2x1bW5zID0gRkFMU0UsCiAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICBzaG93X3Jvd19uYW1lcyA9IFRSVUUsCiAgc2hvd19jb2x1bW5fbmFtZXMgPSBGQUxTRSwKICByb3dfbmFtZXNfZ3AgPSBncGFyKGZvbnRzaXplID0gOCksCiAgY29sdW1uX3RpdGxlX2dwID0gZ3Bhcihmb250c2l6ZSA9IDEwKSwKICB0b3BfYW5ub3RhdGlvbiA9IGNvbHVtbl9oYSwKICBsZWZ0X2Fubm90YXRpb24gPSByb3dfaGEsCiAgaGVhdG1hcF9sZWdlbmRfcGFyYW0gPSBsaXN0KAogICAgdGl0bGVfZ3AgPSBncGFyKGZvbnRzaXplID0gMTApLAogICAgbGFiZWxzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDgpCiAgKSwKICByb3dfdGl0bGUgPSBOVUxMLAogIGNvbHVtbl9zcGxpdCA9IHNhbXBsZSRzZXVyYXRfY2x1c3RlcnMsICMgQ29ycmVjdGVkIHRoaXMgbGluZQogIHJvd19kZW5kX3dpZHRoID0gdW5pdCg0LCAiY20iKSwKICB1c2VfcmFzdGVyID0gVFJVRQopCgojIDcuIERpc3BsYXkgaW4gbm90ZWJvb2sKZHJhdyhodCwgcGFkZGluZyA9IHVuaXQoYygyLCAyLCAyLCAyKSwgIm1tIiksCiAgICAgaGVhdG1hcF9sZWdlbmRfc2lkZSA9ICJyaWdodCIsCiAgICAgYW5ub3RhdGlvbl9sZWdlbmRfc2lkZSA9ICJyaWdodCIpCgojIDguIFNhdmUgb3V0cHV0cwojIFBERiBmb3IgcHVibGljYXRpb24KcGRmKCJwdWJsaWNhdGlvbl9oZWF0bWFwLnBkZiIsIHdpZHRoID0gOC43LzIuNTQsIGhlaWdodCA9IDExLzIuNTQpICMgQ29udmVydCBjbSB0byBpbmNoZXMKZHJhdyhodCkKZGV2Lm9mZigpCgojIFBORyBmb3IgcHJldmlldwpwbmcoImhlYXRtYXBfcHJldmlldy5wbmciLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDI1MDAsIHJlcyA9IDMwMCkKZHJhdyhodCkKZGV2Lm9mZigpCgoKCmBgYAoKCiMjIEhlYXRtYXAtMgpgYGB7ciAsIGZpZy5oZWlnaHQ9MjIsIGZpZy53aWR0aD0zNn0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQpsaWJyYXJ5KGNpcmNsaXplKQpsaWJyYXJ5KHZpcmlkaXMpCgojIDEuIFByZXBhcmUgZ2VuZSBsaXN0cyB3aXRoIGVycm9yIGNoZWNraW5nCmFsbF9nZW5lcyA8LSB1bmlxdWUoYyh1cF9nZW5lcywgZG93bl9nZW5lcykpCmFsbF9nZW5lcyA8LSBpbnRlcnNlY3QoYWxsX2dlbmVzLCByb3duYW1lcyhHZXRBc3NheURhdGEoc2FtcGxlLCBhc3NheSA9ICJSTkEiKSkpICAjIENvcnJlY3RlZCBsaW5lCgppZihsZW5ndGgoYWxsX2dlbmVzKSA9PSAwKSBzdG9wKCJObyBnZW5lcyBmcm9tIHRoZSBsaXN0cyBmb3VuZCBpbiB0aGUgU2V1cmF0IG9iamVjdCIpCgojIDIuIFNldCBkZWZhdWx0IGFzc2F5IHRvICJSTkEiIGFuZCBzY2FsZSB0aGUgZGF0YQpEZWZhdWx0QXNzYXkoc2FtcGxlKSA8LSAiUk5BIiAgIyBTZXQgdGhlIGRlZmF1bHQgYXNzYXkgdG8gUk5BCiNzYW1wbGUgPC0gU2NhbGVEYXRhKHNhbXBsZSkgICMgU2NhbGUgdGhlIFJOQSBkYXRhCgojIDMuIEV4dHJhY3Qgc2NhbGVkIGRhdGEKZXhwcl9tYXRyaXggPC0gR2V0QXNzYXlEYXRhKHNhbXBsZSwgYXNzYXkgPSAiUk5BIiwgc2xvdCA9ICJzY2FsZS5kYXRhIilbYWxsX2dlbmVzLCBdCgojIDQuIENyZWF0ZSBtZXRhZGF0YSBhbm5vdGF0aW9ucwpnZW5lX2Fubm90YXRpb24gPC0gZGF0YS5mcmFtZSgKICBHZW5lID0gYWxsX2dlbmVzLAogIFJlZ3VsYXRpb24gPSBpZmVsc2UoYWxsX2dlbmVzICVpbiUgdXBfZ2VuZXMsICJVcCIsICJEb3duIiksCiAgcm93Lm5hbWVzID0gYWxsX2dlbmVzCikKCiMgT3JkZXIgYnkgY2x1c3RlcnMKY2x1c3Rlcl9vcmRlciA8LSBvcmRlcihzYW1wbGUkc2V1cmF0X2NsdXN0ZXJzKQpleHByX21hdHJpeCA8LSBleHByX21hdHJpeFssIGNsdXN0ZXJfb3JkZXJdCgojIDUuIENyZWF0ZSBhbm5vdGF0aW9ucwpjb2x1bW5faGEgPC0gSGVhdG1hcEFubm90YXRpb24oCiAgQ2x1c3RlciA9IHNhbXBsZSRzZXVyYXRfY2x1c3RlcnNbY2x1c3Rlcl9vcmRlcl0sCiAgY29sID0gbGlzdChDbHVzdGVyID0gc2V0TmFtZXMoCiAgICB2aXJpZGlzKGxlbmd0aCh1bmlxdWUoc2FtcGxlJHNldXJhdF9jbHVzdGVycykpKSwKICAgIHVuaXF1ZShzYW1wbGUkc2V1cmF0X2NsdXN0ZXJzKQogICkpLAogIGFubm90YXRpb25fbmFtZV9zaWRlID0gImxlZnQiLAogIHNob3dfbGVnZW5kID0gVFJVRQopCgpyb3dfaGEgPC0gcm93QW5ub3RhdGlvbigKICBSZWd1bGF0aW9uID0gZ2VuZV9hbm5vdGF0aW9uW2FsbF9nZW5lcywgIlJlZ3VsYXRpb24iXSwKICBjb2wgPSBsaXN0KFJlZ3VsYXRpb24gPSBjKCJVcCIgPSAiI0QzMkYyRiIsICJEb3duIiA9ICIjMTk3NkQyIikpLAogIHNob3dfYW5ub3RhdGlvbl9uYW1lID0gRkFMU0UKKQoKIyA2LiBDcmVhdGUgaGVhdG1hcCB3aXRoIGFkZGl0aW9uYWwgaW1wcm92ZW1lbnRzCmh0IDwtIEhlYXRtYXAoZXhwcl9tYXRyaXgsCiAgbmFtZSA9ICJaLXNjb3JlIiwKICBjb2wgPSBjb2xvclJhbXAyKGMoLTIsIDAsIDIpLCBjKCIjMUU4OEU1IiwgIndoaXRlIiwgIiNEODFCNjAiKSksICAjIEFkanVzdCBjb2xvciBzY2hlbWUgZm9yIGJldHRlciBjb250cmFzdAogIGNsdXN0ZXJfcm93cyA9IFRSVUUsICAjIENsdXN0ZXIgcm93cyAoZ2VuZXMpCiAgY2x1c3Rlcl9jb2x1bW5zID0gVFJVRSwgICMgQ2x1c3RlciBjb2x1bW5zIChzYW1wbGVzKQogIHNob3dfcm93X25hbWVzID0gVFJVRSwKICBzaG93X2NvbHVtbl9uYW1lcyA9IEZBTFNFLAogIHJvd19uYW1lc19ncCA9IGdwYXIoZm9udHNpemUgPSA4KSwgICMgU21hbGxlciByb3cgbmFtZSBmb250CiAgY29sdW1uX3RpdGxlX2dwID0gZ3Bhcihmb250c2l6ZSA9IDEyLCBmb250ZmFjZSA9ICJib2xkIiksICAjIExhcmdlciBjb2x1bW4gdGl0bGUgZm9udAogIHRvcF9hbm5vdGF0aW9uID0gY29sdW1uX2hhLAogIGxlZnRfYW5ub3RhdGlvbiA9IHJvd19oYSwKICBoZWF0bWFwX2xlZ2VuZF9wYXJhbSA9IGxpc3QoCiAgICB0aXRsZV9ncCA9IGdwYXIoZm9udHNpemUgPSAxMCwgZm9udGZhY2UgPSAiYm9sZCIpLAogICAgbGFiZWxzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDgpLAogICAgZGlyZWN0aW9uID0gImhvcml6b250YWwiICAjIFBsYWNlIGxlZ2VuZCBob3Jpem9udGFsbHkgZm9yIG1vcmUgcm9vbQogICksCiAgcm93X3RpdGxlID0gIkdlbmVzIiwgICMgQWRkIGEgcm93IHRpdGxlCiAgY29sdW1uX3NwbGl0ID0gc2FtcGxlJHNldXJhdF9jbHVzdGVycywgICMgU3BsaXQgY29sdW1ucyBieSBjbHVzdGVycwogIHJvd19kZW5kX3dpZHRoID0gdW5pdCg0LCAiY20iKSwKICBjb2x1bW5fZGVuZF9oZWlnaHQgPSB1bml0KDQsICJjbSIpLCAgIyBBZGp1c3QgY29sdW1uIGRlbmRyb2dyYW0gaGVpZ2h0CiAgc2hvd19yb3dfZGVuZCA9IFRSVUUsICAjIFNob3cgcm93IGRlbmRyb2dyYW0KICBzaG93X2NvbHVtbl9kZW5kID0gVFJVRSwgICMgU2hvdyBjb2x1bW4gZGVuZHJvZ3JhbQogIGJvcmRlciA9IFRSVUUsICAjIEFkZCBib3JkZXJzIGFyb3VuZCB0aGUgY2VsbHMKICByb3dfbmFtZXNfc2lkZSA9ICJsZWZ0IiwgICMgUGxhY2Ugcm93IG5hbWVzIG9uIHRoZSBsZWZ0CiAgY29sdW1uX25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDgsIGZvbnRmYWNlID0gIml0YWxpYyIpLCAgIyBJdGFsaWNpemUgY29sdW1uIG5hbWVzCiAgdXNlX3Jhc3RlciA9IFRSVUUgICMgVXNlIHJhc3Rlcml6YXRpb24gZm9yIGJldHRlciBwZXJmb3JtYW5jZQopCgojIDcuIERpc3BsYXkgaW4gbm90ZWJvb2sgd2l0aCBpbXByb3ZlZCBwYWRkaW5nIGFuZCBsZWdlbmQgc2lkZQpkcmF3KGh0LCBwYWRkaW5nID0gdW5pdChjKDQsIDQsIDQsIDQpLCAibW0iKSwKICAgICBoZWF0bWFwX2xlZ2VuZF9zaWRlID0gInJpZ2h0IiwKICAgICBhbm5vdGF0aW9uX2xlZ2VuZF9zaWRlID0gInJpZ2h0IikKCiMgOC4gU2F2ZSBvdXRwdXRzCiMgUERGIGZvciBwdWJsaWNhdGlvbgpwZGYoInB1YmxpY2F0aW9uX2hlYXRtYXBfaW1wcm92ZWQyLnBkZiIsIHdpZHRoID0gOC43LzIuNTQsIGhlaWdodCA9IDExLzIuNTQpICAjIENvbnZlcnQgY20gdG8gaW5jaGVzCmRyYXcoaHQpCmRldi5vZmYoKQoKIyBQTkcgZm9yIHByZXZpZXcKcG5nKCJoZWF0bWFwX3ByZXZpZXdfaW1wcm92ZWQyLnBuZyIsIHdpZHRoID0gMjUwMCwgaGVpZ2h0ID0gMzAwMCwgcmVzID0gMzAwKQpkcmF3KGh0KQpkZXYub2ZmKCkKCgpgYGAK