1 Introduction

Sézary syndrome (SS) is an aggressive leukemic variant of cutaneous T-cell lymphoma (CTCL) characterized by metabolic reprogramming. Recent studies show that malignant Sézary cells upregulate oxidative phosphorylation (OXPHOS), unlike most cancers that rely on aerobic glycolysis [web:104][web:105]. This analysis uses scMetabolism to characterize metabolic heterogeneity at single-cell resolution.

Key metabolic features in Sézary syndrome: - Elevated OXPHOS in malignant clones [web:104] - Altered glycolysis and glutaminolysis [web:104] - Fatty acid metabolism dysregulation [web:110][web:113] - Oxidative stress and ROS production [web:110][web:113]

Tool: scMetabolism GitHub

2 load libraries

# Data Processing
library(dplyr)
library(Seurat)
library(tibble)
library(tidyr)
library(stringr)

# Visualization
library(ggplot2)
library(ComplexHeatmap)
library(patchwork)
library(circlize)
library(viridis)

# Metabolic Analysis
library(scMetabolism)
library(rsvd)

# Set theme
theme_set(theme_classic())

3 Load Seurat Object


# Load your integrated Sézary syndrome object
SS <- readRDS("../../1-Seurat_RDS_OBJECT_FINAL/All_samples_Merged_with_Renamed_Clusters_Cell_state-03-12-2025.rds.rds")

# Set identity to clusters
Idents(SS) <- "seurat_clusters"

# Summary
cat("Total cells:", ncol(SS), "\n")
Total cells: 49305 
cat("Total features:", nrow(SS), "\n")
Total features: 36601 
cat("Clusters:", length(unique(SS$seurat_clusters)), "\n")
Clusters: 14 
cat("Samples:", length(unique(SS$orig.ident)), "\n")
Samples: 9 

4 Prepare Seurat Object for scMetabolism


# 1. Create v3 assay from RNA counts
rna_counts <- GetAssayData(SS, assay = "RNA", layer = "counts")
RNA_v3 <- CreateAssayObject(counts = rna_counts)

# 2. Add the v3 assay with a temporary name
SS[["RNA_v3"]] <- RNA_v3

# 3. Switch default assay away from RNA
DefaultAssay(SS) <- "RNA_v3"

# 4. Delete the old RNA Assay5
SS[["RNA"]] <- NULL

# 5. Create RNA from RNA_v3
SS[["RNA"]] <- SS[["RNA_v3"]]

# 6. Switch default to RNA FIRST (before deleting RNA_v3!)
DefaultAssay(SS) <- "RNA"

# 7. Now delete RNA_v3
SS[["RNA_v3"]] <- NULL

# Verify the setup
Assays(SS)                    # Should show RNA (v3 version)
[1] "ADT"                          "prediction.score.celltype.l1" "prediction.score.celltype.l2" "prediction.score.celltype.l3" "SCT"                         
[6] "RNA"                         
class(SS[["RNA"]])            # Should be "Assay" not "Assay5"
[1] "Assay"
attr(,"package")
[1] "SeuratObject"
DefaultAssay(SS)              # Should be "RNA"
[1] "RNA"
# Run scMetabolism
SS <- sc.metabolism.Seurat(obj = SS,
                           method = "AUCell",
                           imputation = FALSE,
                           ncores = 4,
                           metabolism.type = "KEGG")
Your choice is: KEGG
Start quantify the metabolism activity...

Please Cite: 
Yingcheng Wu, Qiang Gao, et al. Cancer Discovery. 2021. 
https://pubmed.ncbi.nlm.nih.gov/34417225/   
# Check results
dim(SS@assays$METABOLISM$score)
[1]    85 49305
head(rownames(SS@assays$METABOLISM$score), 10)
 [1] "Glycolysis / Gluconeogenesis"                "Citrate cycle (TCA cycle)"                   "Pentose phosphate pathway"                  
 [4] "Pentose and glucuronate interconversions"    "Fructose and mannose metabolism"             "Galactose metabolism"                       
 [7] "Ascorbate and aldarate metabolism"           "Starch and sucrose metabolism"               "Amino sugar and nucleotide sugar metabolism"
[10] "Pyruvate metabolism"                        

5 Run scMetabolism Analysis check

# Check results
cat("\nMetabolism assay dimensions:", dim(SS@assays$METABOLISM$score), "\n")

Metabolism assay dimensions: 85 49305 
cat("Pathways quantified:", nrow(SS@assays$METABOLISM$score), "\n")
Pathways quantified: 85 
cat("\nFirst 10 pathways:\n")

First 10 pathways:
print(head(rownames(SS@assays$METABOLISM$score), 10))
 [1] "Glycolysis / Gluconeogenesis"                "Citrate cycle (TCA cycle)"                   "Pentose phosphate pathway"                  
 [4] "Pentose and glucuronate interconversions"    "Fructose and mannose metabolism"             "Galactose metabolism"                       
 [7] "Ascorbate and aldarate metabolism"           "Starch and sucrose metabolism"               "Amino sugar and nucleotide sugar metabolism"
[10] "Pyruvate metabolism"                        

6 Extract Metabolism Scores


# Extract metabolism matrix (official method from GitHub)
metabolism.matrix <- SS@assays$METABOLISM$score

cat("Pathways:", nrow(metabolism.matrix), "| Cells:", ncol(metabolism.matrix), "\n")
Pathways: 85 | Cells: 49305 
print(head(rownames(metabolism.matrix), 10))
 [1] "Glycolysis / Gluconeogenesis"                "Citrate cycle (TCA cycle)"                   "Pentose phosphate pathway"                  
 [4] "Pentose and glucuronate interconversions"    "Fructose and mannose metabolism"             "Galactose metabolism"                       
 [7] "Ascorbate and aldarate metabolism"           "Starch and sucrose metabolism"               "Amino sugar and nucleotide sugar metabolism"
[10] "Pyruvate metabolism"                        

7 Top Scoring Pathways Analysis


# Get metabolism scores
DefaultAssay(SS) <- "METABOLISM"
met_mat <- SS@assays$METABOLISM$score
pathway_means <- rowMeans(met_mat)

# Top 10 pathways
N <- 20
top_paths_global <- names(sort(pathway_means, decreasing = TRUE))[1:N]
cat("Top 20 pathways:\n")
Top 20 pathways:
print(top_paths_global)
 [1] "Oxidative phosphorylation"               "Pyruvate metabolism"                     "Glycolysis / Gluconeogenesis"           
 [4] "One carbon pool by folate"               "Cysteine and methionine metabolism"      "Citrate cycle (TCA cycle)"              
 [7] "Pentose phosphate pathway"               "Propanoate metabolism"                   "Pyrimidine metabolism"                  
[10] "Glyoxylate and dicarboxylate metabolism" "Glutathione metabolism"                  "Purine metabolism"                      
[13] "Fatty acid elongation"                   "Drug metabolism - other enzymes"         "Fructose and mannose metabolism"        
[16] "Vitamin B6 metabolism"                   "Riboflavin metabolism"                   "Biosynthesis of unsaturated fatty acids"
[19] "Phenylalanine metabolism"                "N-Glycan biosynthesis"                  

8 Visualization


# ============================================================================
# ADD ALL PATHWAYS TO METADATA (FIXED)
# ============================================================================
for (pathway in rownames(metabolism.matrix)) {
  SS@meta.data[[pathway]] <- as.numeric(metabolism.matrix[pathway, ])
}

cat("✓ Added", nrow(metabolism.matrix), "pathways to metadata\n")
✓ Added 85 pathways to metadata
# ============================================================================
# UMAP PLOTS - Top 4 Pathways
# ============================================================================
library(patchwork)
library(viridis)

p1 <- FeaturePlot(SS, features = top_paths_global[1], reduction = "umap", 
                  pt.size = 0.5, cols = viridis(100)) +
  ggtitle(top_paths_global[1]) +
  theme(plot.title = element_text(face = "bold"))

p2 <- FeaturePlot(SS, features = top_paths_global[2], reduction = "umap",
                  pt.size = 0.5, cols = viridis(100)) +
  ggtitle(top_paths_global[2]) +
  theme(plot.title = element_text(face = "bold"))

p3 <- FeaturePlot(SS, features = top_paths_global[3], reduction = "umap",
                  pt.size = 0.5, cols = viridis(100)) +
  ggtitle(top_paths_global[3]) +
  theme(plot.title = element_text(face = "bold"))

p4 <- FeaturePlot(SS, features = top_paths_global[4], reduction = "umap",
                  pt.size = 0.5, cols = viridis(100)) +
  ggtitle(top_paths_global[4]) +
  theme(plot.title = element_text(face = "bold"))

(p1 | p2) / (p3 | p4)


# All top 10
all_plots <- list()
for (i in 1:10) {
  all_plots[[i]] <- FeaturePlot(
    SS, 
    features = top_paths_global[i], 
    reduction = "umap",
    pt.size = 0.3,
    cols = c("lightgrey", "red")
  ) + 
    ggtitle(top_paths_global[i]) +
    NoLegend() +
    theme(plot.title = element_text(size = 9, face = "bold"))
}

wrap_plots(all_plots, ncol = 3)


# Key pathways
p_oxphos <- FeaturePlot(SS, "Oxidative phosphorylation", 
                        reduction = "umap", pt.size = 0.5,
                        cols = viridis(100)) +
  ggtitle("Oxidative Phosphorylation (#1)")

p_glyc <- FeaturePlot(SS, "Glycolysis / Gluconeogenesis",
                      reduction = "umap", pt.size = 0.5,
                      cols = viridis(100)) +
  ggtitle("Glycolysis / Gluconeogenesis")

p_oxphos | p_glyc


# DotPlot
DotPlot.metabolism(
  obj = SS,
  pathway = top_paths_global,
  phenotype = "seurat_clusters",
  norm = "y"
) +
  ggtitle("Top 10 Pathways") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Please Cite: 
Yingcheng Wu, Qiang Gao, et al. Cancer Discovery. 2021. 
https://pubmed.ncbi.nlm.nih.gov/34417225/   

# BoxPlot
BoxPlot.metabolism(
  obj = SS,
  pathway = top_paths_global[1:3],
  phenotype = "seurat_clusters",
  ncol = 1
)

Please Cite: 
Yingcheng Wu, Qiang Gao, et al. Cancer Discovery. 2021. 
https://pubmed.ncbi.nlm.nih.gov/34417225/   

# Heatmap
library(ComplexHeatmap)
library(circlize)

clusters <- SS$seurat_clusters
avg_by_cluster <- sapply(levels(factor(clusters)), function(cl) {
  cells <- which(clusters == cl)
  rowMeans(metabolism.matrix[, cells, drop = FALSE])
})
colnames(avg_by_cluster) <- levels(factor(clusters))

avg_top10 <- avg_by_cluster[top_paths_global, ]
avg_top10_scaled <- t(scale(t(avg_top10)))

Heatmap(
  avg_top10_scaled,
  name = "Z-score",
  cluster_rows = TRUE,
  cluster_columns = TRUE,
  col = colorRamp2(c(-2, 0, 2), c("#2166AC", "white", "#B2182B")),
  column_title = "Top 10 Pathways by Cluster"
)

NA
NA

9 UMAP PLOTS - Top 4 Pathways


# ============================================================================
# UMAP PLOTS - Top 4 Pathways
# ============================================================================
library(patchwork)
library(viridis)

p1 <- FeaturePlot(SS, features = top_paths_global[1], reduction = "umap", 
                  pt.size = 0.5, cols = viridis(100)) +
  ggtitle(top_paths_global[1]) +
  theme(plot.title = element_text(face = "bold"))

p2 <- FeaturePlot(SS, features = top_paths_global[2], reduction = "umap",
                  pt.size = 0.5, cols = viridis(100)) +
  ggtitle(top_paths_global[2]) +
  theme(plot.title = element_text(face = "bold"))

p3 <- FeaturePlot(SS, features = top_paths_global[3], reduction = "umap",
                  pt.size = 0.5, cols = viridis(100)) +
  ggtitle(top_paths_global[3]) +
  theme(plot.title = element_text(face = "bold"))

p4 <- FeaturePlot(SS, features = top_paths_global[4], reduction = "umap",
                  pt.size = 0.5, cols = viridis(100)) +
  ggtitle(top_paths_global[4]) +
  theme(plot.title = element_text(face = "bold"))

(p1 | p2) / (p3 | p4)


# All top 10
all_plots <- list()
for (i in 1:10) {
  all_plots[[i]] <- FeaturePlot(
    SS, 
    features = top_paths_global[i], 
    reduction = "umap",
    pt.size = 0.3,
    cols = c("lightgrey", "red")
  ) + 
    ggtitle(top_paths_global[i]) +
    NoLegend() +
    theme(plot.title = element_text(size = 9, face = "bold"))
}

wrap_plots(all_plots, ncol = 3)

10 UMAP PLOTS - Top 20 Pathways


# All top 10
all_plots <- list()
for (i in 1:20) {
  all_plots[[i]] <- FeaturePlot(
    SS, 
    features = top_paths_global[i], 
    reduction = "umap",
    pt.size = 0.3,
    cols = c("lightgrey", "red")
  ) + 
    ggtitle(top_paths_global[i]) +
    NoLegend() +
    theme(plot.title = element_text(size = 9, face = "bold"))
}

wrap_plots(all_plots, ncol = 3)

11 FeaturePlots - Top 20 Pathways


# Key pathways
p_oxphos <- FeaturePlot(SS, "Oxidative phosphorylation", 
                        reduction = "umap", pt.size = 0.5,
                        cols = viridis(100)) +
  ggtitle("Oxidative Phosphorylation (#1)")

p_glyc <- FeaturePlot(SS, "Glycolysis / Gluconeogenesis",
                      reduction = "umap", pt.size = 0.5,
                      cols = viridis(100)) +
  ggtitle("Glycolysis / Gluconeogenesis")

p_oxphos | p_glyc

12 Dot PLOTS


# DotPlot
DotPlot.metabolism(
  obj = SS,
  pathway = top_paths_global,
  phenotype = "orig.ident",
  norm = "y"
) +
  ggtitle("Top 10 Pathways") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Please Cite: 
Yingcheng Wu, Qiang Gao, et al. Cancer Discovery. 2021. 
https://pubmed.ncbi.nlm.nih.gov/34417225/   

# DotPlot
DotPlot.metabolism(
  obj = SS,
  pathway = top_paths_global,
  phenotype = "seurat_clusters",
  norm = "y"
) +
  ggtitle("Top 10 Pathways") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Please Cite: 
Yingcheng Wu, Qiang Gao, et al. Cancer Discovery. 2021. 
https://pubmed.ncbi.nlm.nih.gov/34417225/   

13 Box PLOTS


# BoxPlot
BoxPlot.metabolism(
  obj = SS,
  pathway = top_paths_global[1:3],
  phenotype = "orig.ident",
  ncol = 1
)

Please Cite: 
Yingcheng Wu, Qiang Gao, et al. Cancer Discovery. 2021. 
https://pubmed.ncbi.nlm.nih.gov/34417225/   

# BoxPlot
BoxPlot.metabolism(
  obj = SS,
  pathway = top_paths_global[1:3],
  phenotype = "seurat_clusters",
  ncol = 1
)

Please Cite: 
Yingcheng Wu, Qiang Gao, et al. Cancer Discovery. 2021. 
https://pubmed.ncbi.nlm.nih.gov/34417225/   

14 Heatmap


# Heatmap
library(ComplexHeatmap)
library(circlize)

clusters <- SS$orig.ident
avg_by_cluster <- sapply(levels(factor(clusters)), function(cl) {
  cells <- which(clusters == cl)
  rowMeans(metabolism.matrix[, cells, drop = FALSE])
})
colnames(avg_by_cluster) <- levels(factor(clusters))

avg_top10 <- avg_by_cluster[top_paths_global, ]
avg_top10_scaled <- t(scale(t(avg_top10)))

Heatmap(
  avg_top10_scaled,
  name = "Z-score",
  cluster_rows = TRUE,
  cluster_columns = TRUE,
  col = colorRamp2(c(-2, 0, 2), c("#2166AC", "white", "#B2182B")),
  column_title = "Top 10 Pathways by Cluster"
)







# Heatmap
library(ComplexHeatmap)
library(circlize)

clusters <- SS$seurat_clusters
avg_by_cluster <- sapply(levels(factor(clusters)), function(cl) {
  cells <- which(clusters == cl)
  rowMeans(metabolism.matrix[, cells, drop = FALSE])
})
colnames(avg_by_cluster) <- levels(factor(clusters))

avg_top10 <- avg_by_cluster[top_paths_global, ]
avg_top10_scaled <- t(scale(t(avg_top10)))

Heatmap(
  avg_top10_scaled,
  name = "Z-score",
  cluster_rows = TRUE,
  cluster_columns = TRUE,
  col = colorRamp2(c(-2, 0, 2), c("#2166AC", "white", "#B2182B")),
  column_title = "Top 10 Pathways by Cluster"
)

NA
NA
NA

15 Heatmap


# Heatmap
library(ComplexHeatmap)
library(circlize)

clusters <- SS$orig.ident
avg_by_cluster <- sapply(levels(factor(clusters)), function(cl) {
  cells <- which(clusters == cl)
  rowMeans(metabolism.matrix[, cells, drop = FALSE])
})
colnames(avg_by_cluster) <- levels(factor(clusters))

avg_top10 <- avg_by_cluster[top_paths_global, ]
avg_top10_scaled <- t(scale(t(avg_top10)))

Heatmap(
  avg_top10_scaled,
  name = "Z-score",
  cluster_rows = TRUE,
  cluster_columns = TRUE,
  col = colorRamp2(c(-2, 0, 2), c("#2166AC", "white", "#B2182B")),
  column_title = "Top 10 Pathways by Cluster"
)







# Heatmap
library(ComplexHeatmap)
library(circlize)

clusters <- SS$seurat_clusters
avg_by_cluster <- sapply(levels(factor(clusters)), function(cl) {
  cells <- which(clusters == cl)
  rowMeans(metabolism.matrix[, cells, drop = FALSE])
})
colnames(avg_by_cluster) <- levels(factor(clusters))

avg_top10 <- avg_by_cluster[top_paths_global, ]
avg_top10_scaled <- t(scale(t(avg_top10)))

Heatmap(
  avg_top10_scaled,
  name = "Z-score",
  cluster_rows = TRUE,
  cluster_columns = TRUE,
  col = colorRamp2(c(-2, 0, 2), c("#2166AC", "white", "#B2182B")),
  column_title = "Top 10 Pathways by Cluster"
)

NA
NA
NA
LS0tCnRpdGxlOiAiU2luZ2xlLUNlbGwgTWV0YWJvbGljIEFuYWx5c2lzIG9mIFPDqXphcnkgU3luZHJvbWUgSGV0ZXJvZ2VuZWl0eSIKYXV0aG9yOiAiTmFzaXIgTWFobW9vZCBBYmJhc2kiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgIHRoZW1lOiBqb3VybmFsCi0tLQojIEludHJvZHVjdGlvbgoKU8OpemFyeSBzeW5kcm9tZSAoU1MpIGlzIGFuIGFnZ3Jlc3NpdmUgbGV1a2VtaWMgdmFyaWFudCBvZiBjdXRhbmVvdXMgVC1jZWxsIGx5bXBob21hIChDVENMKSBjaGFyYWN0ZXJpemVkIGJ5IG1ldGFib2xpYyByZXByb2dyYW1taW5nLiBSZWNlbnQgc3R1ZGllcyBzaG93IHRoYXQgbWFsaWduYW50IFPDqXphcnkgY2VsbHMgdXByZWd1bGF0ZSAqKm94aWRhdGl2ZSBwaG9zcGhvcnlsYXRpb24gKE9YUEhPUykqKiwgdW5saWtlIG1vc3QgY2FuY2VycyB0aGF0IHJlbHkgb24gYWVyb2JpYyBnbHljb2x5c2lzIFt3ZWI6MTA0XVt3ZWI6MTA1XS4gVGhpcyBhbmFseXNpcyB1c2VzICoqc2NNZXRhYm9saXNtKiogdG8gY2hhcmFjdGVyaXplIG1ldGFib2xpYyBoZXRlcm9nZW5laXR5IGF0IHNpbmdsZS1jZWxsIHJlc29sdXRpb24uCgoqKktleSBtZXRhYm9saWMgZmVhdHVyZXMgaW4gU8OpemFyeSBzeW5kcm9tZToqKgotIEVsZXZhdGVkIE9YUEhPUyBpbiBtYWxpZ25hbnQgY2xvbmVzIFt3ZWI6MTA0XQotIEFsdGVyZWQgZ2x5Y29seXNpcyBhbmQgZ2x1dGFtaW5vbHlzaXMgW3dlYjoxMDRdCi0gRmF0dHkgYWNpZCBtZXRhYm9saXNtIGR5c3JlZ3VsYXRpb24gW3dlYjoxMTBdW3dlYjoxMTNdCi0gT3hpZGF0aXZlIHN0cmVzcyBhbmQgUk9TIHByb2R1Y3Rpb24gW3dlYjoxMTBdW3dlYjoxMTNdCgoqKlRvb2w6KiogW3NjTWV0YWJvbGlzbSBHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS93dS15Yy9zY01ldGFib2xpc20pCgoKIyBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1UUlVFfQojIERhdGEgUHJvY2Vzc2luZwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoc3RyaW5ncikKCiMgVmlzdWFsaXphdGlvbgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoQ29tcGxleEhlYXRtYXApCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KGNpcmNsaXplKQpsaWJyYXJ5KHZpcmlkaXMpCgojIE1ldGFib2xpYyBBbmFseXNpcwpsaWJyYXJ5KHNjTWV0YWJvbGlzbSkKbGlicmFyeShyc3ZkKQoKIyBTZXQgdGhlbWUKdGhlbWVfc2V0KHRoZW1lX2NsYXNzaWMoKSkKYGBgCgojIExvYWQgU2V1cmF0IE9iamVjdCAKYGBge3J9CgojIExvYWQgeW91ciBpbnRlZ3JhdGVkIFPDqXphcnkgc3luZHJvbWUgb2JqZWN0ClNTIDwtIHJlYWRSRFMoIi4uLy4uLzEtU2V1cmF0X1JEU19PQkpFQ1RfRklOQUwvQWxsX3NhbXBsZXNfTWVyZ2VkX3dpdGhfUmVuYW1lZF9DbHVzdGVyc19DZWxsX3N0YXRlLTAzLTEyLTIwMjUucmRzLnJkcyIpCgojIFNldCBpZGVudGl0eSB0byBjbHVzdGVycwpJZGVudHMoU1MpIDwtICJzZXVyYXRfY2x1c3RlcnMiCgojIFN1bW1hcnkKY2F0KCJUb3RhbCBjZWxsczoiLCBuY29sKFNTKSwgIlxuIikKY2F0KCJUb3RhbCBmZWF0dXJlczoiLCBucm93KFNTKSwgIlxuIikKY2F0KCJDbHVzdGVyczoiLCBsZW5ndGgodW5pcXVlKFNTJHNldXJhdF9jbHVzdGVycykpLCAiXG4iKQpjYXQoIlNhbXBsZXM6IiwgbGVuZ3RoKHVuaXF1ZShTUyRvcmlnLmlkZW50KSksICJcbiIpCmBgYAoKCgojIFByZXBhcmUgU2V1cmF0IE9iamVjdCBmb3Igc2NNZXRhYm9saXNtCmBgYHtyICwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTI1fQoKIyAxLiBDcmVhdGUgdjMgYXNzYXkgZnJvbSBSTkEgY291bnRzCnJuYV9jb3VudHMgPC0gR2V0QXNzYXlEYXRhKFNTLCBhc3NheSA9ICJSTkEiLCBsYXllciA9ICJjb3VudHMiKQpSTkFfdjMgPC0gQ3JlYXRlQXNzYXlPYmplY3QoY291bnRzID0gcm5hX2NvdW50cykKCiMgMi4gQWRkIHRoZSB2MyBhc3NheSB3aXRoIGEgdGVtcG9yYXJ5IG5hbWUKU1NbWyJSTkFfdjMiXV0gPC0gUk5BX3YzCgojIDMuIFN3aXRjaCBkZWZhdWx0IGFzc2F5IGF3YXkgZnJvbSBSTkEKRGVmYXVsdEFzc2F5KFNTKSA8LSAiUk5BX3YzIgoKIyA0LiBEZWxldGUgdGhlIG9sZCBSTkEgQXNzYXk1ClNTW1siUk5BIl1dIDwtIE5VTEwKCiMgNS4gQ3JlYXRlIFJOQSBmcm9tIFJOQV92MwpTU1tbIlJOQSJdXSA8LSBTU1tbIlJOQV92MyJdXQoKIyA2LiBTd2l0Y2ggZGVmYXVsdCB0byBSTkEgRklSU1QgKGJlZm9yZSBkZWxldGluZyBSTkFfdjMhKQpEZWZhdWx0QXNzYXkoU1MpIDwtICJSTkEiCgojIDcuIE5vdyBkZWxldGUgUk5BX3YzClNTW1siUk5BX3YzIl1dIDwtIE5VTEwKCiMgVmVyaWZ5IHRoZSBzZXR1cApBc3NheXMoU1MpICAgICAgICAgICAgICAgICAgICAjIFNob3VsZCBzaG93IFJOQSAodjMgdmVyc2lvbikKY2xhc3MoU1NbWyJSTkEiXV0pICAgICAgICAgICAgIyBTaG91bGQgYmUgIkFzc2F5IiBub3QgIkFzc2F5NSIKRGVmYXVsdEFzc2F5KFNTKSAgICAgICAgICAgICAgIyBTaG91bGQgYmUgIlJOQSIKCiMgUnVuIHNjTWV0YWJvbGlzbQpTUyA8LSBzYy5tZXRhYm9saXNtLlNldXJhdChvYmogPSBTUywKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkFVQ2VsbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGltcHV0YXRpb24gPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvcmVzID0gNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWJvbGlzbS50eXBlID0gIktFR0ciKQoKIyBDaGVjayByZXN1bHRzCmRpbShTU0Bhc3NheXMkTUVUQUJPTElTTSRzY29yZSkKaGVhZChyb3duYW1lcyhTU0Bhc3NheXMkTUVUQUJPTElTTSRzY29yZSksIDEwKQpgYGAKCgojIFJ1biBzY01ldGFib2xpc20gQW5hbHlzaXMgY2hlY2sKYGBge3IgLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MjV9CiMgQ2hlY2sgcmVzdWx0cwpjYXQoIlxuTWV0YWJvbGlzbSBhc3NheSBkaW1lbnNpb25zOiIsIGRpbShTU0Bhc3NheXMkTUVUQUJPTElTTSRzY29yZSksICJcbiIpCmNhdCgiUGF0aHdheXMgcXVhbnRpZmllZDoiLCBucm93KFNTQGFzc2F5cyRNRVRBQk9MSVNNJHNjb3JlKSwgIlxuIikKY2F0KCJcbkZpcnN0IDEwIHBhdGh3YXlzOlxuIikKcHJpbnQoaGVhZChyb3duYW1lcyhTU0Bhc3NheXMkTUVUQUJPTElTTSRzY29yZSksIDEwKSkKYGBgCiMgRXh0cmFjdCBNZXRhYm9saXNtIFNjb3JlcwpgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0yNX0KCiMgRXh0cmFjdCBtZXRhYm9saXNtIG1hdHJpeCAob2ZmaWNpYWwgbWV0aG9kIGZyb20gR2l0SHViKQptZXRhYm9saXNtLm1hdHJpeCA8LSBTU0Bhc3NheXMkTUVUQUJPTElTTSRzY29yZQoKY2F0KCJQYXRod2F5czoiLCBucm93KG1ldGFib2xpc20ubWF0cml4KSwgInwgQ2VsbHM6IiwgbmNvbChtZXRhYm9saXNtLm1hdHJpeCksICJcbiIpCnByaW50KGhlYWQocm93bmFtZXMobWV0YWJvbGlzbS5tYXRyaXgpLCAxMCkpCmBgYAojIFRvcCBTY29yaW5nIFBhdGh3YXlzIEFuYWx5c2lzCmBgYHtyICwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTI1fQoKIyBHZXQgbWV0YWJvbGlzbSBzY29yZXMKRGVmYXVsdEFzc2F5KFNTKSA8LSAiTUVUQUJPTElTTSIKbWV0X21hdCA8LSBTU0Bhc3NheXMkTUVUQUJPTElTTSRzY29yZQpwYXRod2F5X21lYW5zIDwtIHJvd01lYW5zKG1ldF9tYXQpCgojIFRvcCAxMCBwYXRod2F5cwpOIDwtIDIwCnRvcF9wYXRoc19nbG9iYWwgPC0gbmFtZXMoc29ydChwYXRod2F5X21lYW5zLCBkZWNyZWFzaW5nID0gVFJVRSkpWzE6Tl0KY2F0KCJUb3AgMjAgcGF0aHdheXM6XG4iKQpwcmludCh0b3BfcGF0aHNfZ2xvYmFsKQpgYGAKCiMgVmlzdWFsaXphdGlvbgpgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0yNX0KCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIEFERCBBTEwgUEFUSFdBWVMgVE8gTUVUQURBVEEgKEZJWEVEKQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KZm9yIChwYXRod2F5IGluIHJvd25hbWVzKG1ldGFib2xpc20ubWF0cml4KSkgewogIFNTQG1ldGEuZGF0YVtbcGF0aHdheV1dIDwtIGFzLm51bWVyaWMobWV0YWJvbGlzbS5tYXRyaXhbcGF0aHdheSwgXSkKfQoKY2F0KCLinJMgQWRkZWQiLCBucm93KG1ldGFib2xpc20ubWF0cml4KSwgInBhdGh3YXlzIHRvIG1ldGFkYXRhXG4iKQoKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgVU1BUCBQTE9UUyAtIFRvcCA0IFBhdGh3YXlzCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeSh2aXJpZGlzKQoKcDEgPC0gRmVhdHVyZVBsb3QoU1MsIGZlYXR1cmVzID0gdG9wX3BhdGhzX2dsb2JhbFsxXSwgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgY29scyA9IHZpcmlkaXMoMTAwKSkgKwogIGdndGl0bGUodG9wX3BhdGhzX2dsb2JhbFsxXSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpCgpwMiA8LSBGZWF0dXJlUGxvdChTUywgZmVhdHVyZXMgPSB0b3BfcGF0aHNfZ2xvYmFsWzJdLCByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIGNvbHMgPSB2aXJpZGlzKDEwMCkpICsKICBnZ3RpdGxlKHRvcF9wYXRoc19nbG9iYWxbMl0pICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKQoKcDMgPC0gRmVhdHVyZVBsb3QoU1MsIGZlYXR1cmVzID0gdG9wX3BhdGhzX2dsb2JhbFszXSwgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCBjb2xzID0gdmlyaWRpcygxMDApKSArCiAgZ2d0aXRsZSh0b3BfcGF0aHNfZ2xvYmFsWzNdKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkKCnA0IDwtIEZlYXR1cmVQbG90KFNTLCBmZWF0dXJlcyA9IHRvcF9wYXRoc19nbG9iYWxbNF0sIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgY29scyA9IHZpcmlkaXMoMTAwKSkgKwogIGdndGl0bGUodG9wX3BhdGhzX2dsb2JhbFs0XSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpCgoocDEgfCBwMikgLyAocDMgfCBwNCkKCiMgQWxsIHRvcCAxMAphbGxfcGxvdHMgPC0gbGlzdCgpCmZvciAoaSBpbiAxOjEwKSB7CiAgYWxsX3Bsb3RzW1tpXV0gPC0gRmVhdHVyZVBsb3QoCiAgICBTUywgCiAgICBmZWF0dXJlcyA9IHRvcF9wYXRoc19nbG9iYWxbaV0sIAogICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgcHQuc2l6ZSA9IDAuMywKICAgIGNvbHMgPSBjKCJsaWdodGdyZXkiLCAicmVkIikKICApICsgCiAgICBnZ3RpdGxlKHRvcF9wYXRoc19nbG9iYWxbaV0pICsKICAgIE5vTGVnZW5kKCkgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgZmFjZSA9ICJib2xkIikpCn0KCndyYXBfcGxvdHMoYWxsX3Bsb3RzLCBuY29sID0gMykKCiMgS2V5IHBhdGh3YXlzCnBfb3hwaG9zIDwtIEZlYXR1cmVQbG90KFNTLCAiT3hpZGF0aXZlIHBob3NwaG9yeWxhdGlvbiIsIAogICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHMgPSB2aXJpZGlzKDEwMCkpICsKICBnZ3RpdGxlKCJPeGlkYXRpdmUgUGhvc3Bob3J5bGF0aW9uICgjMSkiKQoKcF9nbHljIDwtIEZlYXR1cmVQbG90KFNTLCAiR2x5Y29seXNpcyAvIEdsdWNvbmVvZ2VuZXNpcyIsCiAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICBjb2xzID0gdmlyaWRpcygxMDApKSArCiAgZ2d0aXRsZSgiR2x5Y29seXNpcyAvIEdsdWNvbmVvZ2VuZXNpcyIpCgpwX294cGhvcyB8IHBfZ2x5YwoKIyBEb3RQbG90CkRvdFBsb3QubWV0YWJvbGlzbSgKICBvYmogPSBTUywKICBwYXRod2F5ID0gdG9wX3BhdGhzX2dsb2JhbCwKICBwaGVub3R5cGUgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICBub3JtID0gInkiCikgKwogIGdndGl0bGUoIlRvcCAxMCBQYXRod2F5cyIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQoKIyBCb3hQbG90CkJveFBsb3QubWV0YWJvbGlzbSgKICBvYmogPSBTUywKICBwYXRod2F5ID0gdG9wX3BhdGhzX2dsb2JhbFsxOjNdLAogIHBoZW5vdHlwZSA9ICJzZXVyYXRfY2x1c3RlcnMiLAogIG5jb2wgPSAxCikKCiMgSGVhdG1hcApsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQpsaWJyYXJ5KGNpcmNsaXplKQoKY2x1c3RlcnMgPC0gU1Mkc2V1cmF0X2NsdXN0ZXJzCmF2Z19ieV9jbHVzdGVyIDwtIHNhcHBseShsZXZlbHMoZmFjdG9yKGNsdXN0ZXJzKSksIGZ1bmN0aW9uKGNsKSB7CiAgY2VsbHMgPC0gd2hpY2goY2x1c3RlcnMgPT0gY2wpCiAgcm93TWVhbnMobWV0YWJvbGlzbS5tYXRyaXhbLCBjZWxscywgZHJvcCA9IEZBTFNFXSkKfSkKY29sbmFtZXMoYXZnX2J5X2NsdXN0ZXIpIDwtIGxldmVscyhmYWN0b3IoY2x1c3RlcnMpKQoKYXZnX3RvcDEwIDwtIGF2Z19ieV9jbHVzdGVyW3RvcF9wYXRoc19nbG9iYWwsIF0KYXZnX3RvcDEwX3NjYWxlZCA8LSB0KHNjYWxlKHQoYXZnX3RvcDEwKSkpCgpIZWF0bWFwKAogIGF2Z190b3AxMF9zY2FsZWQsCiAgbmFtZSA9ICJaLXNjb3JlIiwKICBjbHVzdGVyX3Jvd3MgPSBUUlVFLAogIGNsdXN0ZXJfY29sdW1ucyA9IFRSVUUsCiAgY29sID0gY29sb3JSYW1wMihjKC0yLCAwLCAyKSwgYygiIzIxNjZBQyIsICJ3aGl0ZSIsICIjQjIxODJCIikpLAogIGNvbHVtbl90aXRsZSA9ICJUb3AgMTAgUGF0aHdheXMgYnkgQ2x1c3RlciIKKQoKCmBgYAoKIyAgVU1BUCBQTE9UUyAtIFRvcCA0IFBhdGh3YXlzCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyBVTUFQIFBMT1RTIC0gVG9wIDQgUGF0aHdheXMKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHZpcmlkaXMpCgpwMSA8LSBGZWF0dXJlUGxvdChTUywgZmVhdHVyZXMgPSB0b3BfcGF0aHNfZ2xvYmFsWzFdLCByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCBjb2xzID0gdmlyaWRpcygxMDApKSArCiAgZ2d0aXRsZSh0b3BfcGF0aHNfZ2xvYmFsWzFdKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkKCnAyIDwtIEZlYXR1cmVQbG90KFNTLCBmZWF0dXJlcyA9IHRvcF9wYXRoc19nbG9iYWxbMl0sIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgY29scyA9IHZpcmlkaXMoMTAwKSkgKwogIGdndGl0bGUodG9wX3BhdGhzX2dsb2JhbFsyXSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpCgpwMyA8LSBGZWF0dXJlUGxvdChTUywgZmVhdHVyZXMgPSB0b3BfcGF0aHNfZ2xvYmFsWzNdLCByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIGNvbHMgPSB2aXJpZGlzKDEwMCkpICsKICBnZ3RpdGxlKHRvcF9wYXRoc19nbG9iYWxbM10pICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKQoKcDQgPC0gRmVhdHVyZVBsb3QoU1MsIGZlYXR1cmVzID0gdG9wX3BhdGhzX2dsb2JhbFs0XSwgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCBjb2xzID0gdmlyaWRpcygxMDApKSArCiAgZ2d0aXRsZSh0b3BfcGF0aHNfZ2xvYmFsWzRdKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkKCihwMSB8IHAyKSAvIChwMyB8IHA0KQoKIyBBbGwgdG9wIDEwCmFsbF9wbG90cyA8LSBsaXN0KCkKZm9yIChpIGluIDE6MTApIHsKICBhbGxfcGxvdHNbW2ldXSA8LSBGZWF0dXJlUGxvdCgKICAgIFNTLCAKICAgIGZlYXR1cmVzID0gdG9wX3BhdGhzX2dsb2JhbFtpXSwgCiAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICBwdC5zaXplID0gMC4zLAogICAgY29scyA9IGMoImxpZ2h0Z3JleSIsICJyZWQiKQogICkgKyAKICAgIGdndGl0bGUodG9wX3BhdGhzX2dsb2JhbFtpXSkgKwogICAgTm9MZWdlbmQoKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gImJvbGQiKSkKfQoKd3JhcF9wbG90cyhhbGxfcGxvdHMsIG5jb2wgPSAzKQoKYGBgCgoKIyAgVU1BUCBQTE9UUyAtIFRvcCAyMCBQYXRod2F5cwpgYGB7ciAsIGZpZy5oZWlnaHQ9MTgsIGZpZy53aWR0aD0xMn0KCiMgQWxsIHRvcCAxMAphbGxfcGxvdHMgPC0gbGlzdCgpCmZvciAoaSBpbiAxOjIwKSB7CiAgYWxsX3Bsb3RzW1tpXV0gPC0gRmVhdHVyZVBsb3QoCiAgICBTUywgCiAgICBmZWF0dXJlcyA9IHRvcF9wYXRoc19nbG9iYWxbaV0sIAogICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgcHQuc2l6ZSA9IDAuMywKICAgIGNvbHMgPSBjKCJsaWdodGdyZXkiLCAicmVkIikKICApICsgCiAgICBnZ3RpdGxlKHRvcF9wYXRoc19nbG9iYWxbaV0pICsKICAgIE5vTGVnZW5kKCkgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgZmFjZSA9ICJib2xkIikpCn0KCndyYXBfcGxvdHMoYWxsX3Bsb3RzLCBuY29sID0gMykKCmBgYAoKIyAgRmVhdHVyZVBsb3RzIC0gVG9wIDIwIFBhdGh3YXlzCmBgYHtyICwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTB9CgojIEtleSBwYXRod2F5cwpwX294cGhvcyA8LSBGZWF0dXJlUGxvdChTUywgIk94aWRhdGl2ZSBwaG9zcGhvcnlsYXRpb24iLCAKICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICBjb2xzID0gdmlyaWRpcygxMDApKSArCiAgZ2d0aXRsZSgiT3hpZGF0aXZlIFBob3NwaG9yeWxhdGlvbiAoIzEpIikKCnBfZ2x5YyA8LSBGZWF0dXJlUGxvdChTUywgIkdseWNvbHlzaXMgLyBHbHVjb25lb2dlbmVzaXMiLAogICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgY29scyA9IHZpcmlkaXMoMTAwKSkgKwogIGdndGl0bGUoIkdseWNvbHlzaXMgLyBHbHVjb25lb2dlbmVzaXMiKQoKcF9veHBob3MgfCBwX2dseWMKCmBgYAoKIyAgRG90IFBMT1RTIApgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQoKIyBEb3RQbG90CkRvdFBsb3QubWV0YWJvbGlzbSgKICBvYmogPSBTUywKICBwYXRod2F5ID0gdG9wX3BhdGhzX2dsb2JhbCwKICBwaGVub3R5cGUgPSAib3JpZy5pZGVudCIsCiAgbm9ybSA9ICJ5IgopICsKICBnZ3RpdGxlKCJUb3AgMTAgUGF0aHdheXMiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKCgojIERvdFBsb3QKRG90UGxvdC5tZXRhYm9saXNtKAogIG9iaiA9IFNTLAogIHBhdGh3YXkgPSB0b3BfcGF0aHNfZ2xvYmFsLAogIHBoZW5vdHlwZSA9ICJzZXVyYXRfY2x1c3RlcnMiLAogIG5vcm0gPSAieSIKKSArCiAgZ2d0aXRsZSgiVG9wIDEwIFBhdGh3YXlzIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCgoKYGBgCgoKIyAgQm94IFBMT1RTIApgYGB7ciAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTd9CgojIEJveFBsb3QKQm94UGxvdC5tZXRhYm9saXNtKAogIG9iaiA9IFNTLAogIHBhdGh3YXkgPSB0b3BfcGF0aHNfZ2xvYmFsWzE6M10sCiAgcGhlbm90eXBlID0gIm9yaWcuaWRlbnQiLAogIG5jb2wgPSAxCikKCiMgQm94UGxvdApCb3hQbG90Lm1ldGFib2xpc20oCiAgb2JqID0gU1MsCiAgcGF0aHdheSA9IHRvcF9wYXRoc19nbG9iYWxbMTozXSwKICBwaGVub3R5cGUgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICBuY29sID0gMQopCgoKYGBgCgojICBIZWF0bWFwCmBgYHtyICwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgojIEhlYXRtYXAKbGlicmFyeShDb21wbGV4SGVhdG1hcCkKbGlicmFyeShjaXJjbGl6ZSkKCmNsdXN0ZXJzIDwtIFNTJG9yaWcuaWRlbnQKYXZnX2J5X2NsdXN0ZXIgPC0gc2FwcGx5KGxldmVscyhmYWN0b3IoY2x1c3RlcnMpKSwgZnVuY3Rpb24oY2wpIHsKICBjZWxscyA8LSB3aGljaChjbHVzdGVycyA9PSBjbCkKICByb3dNZWFucyhtZXRhYm9saXNtLm1hdHJpeFssIGNlbGxzLCBkcm9wID0gRkFMU0VdKQp9KQpjb2xuYW1lcyhhdmdfYnlfY2x1c3RlcikgPC0gbGV2ZWxzKGZhY3RvcihjbHVzdGVycykpCgphdmdfdG9wMTAgPC0gYXZnX2J5X2NsdXN0ZXJbdG9wX3BhdGhzX2dsb2JhbCwgXQphdmdfdG9wMTBfc2NhbGVkIDwtIHQoc2NhbGUodChhdmdfdG9wMTApKSkKCkhlYXRtYXAoCiAgYXZnX3RvcDEwX3NjYWxlZCwKICBuYW1lID0gIlotc2NvcmUiLAogIGNsdXN0ZXJfcm93cyA9IFRSVUUsCiAgY2x1c3Rlcl9jb2x1bW5zID0gVFJVRSwKICBjb2wgPSBjb2xvclJhbXAyKGMoLTIsIDAsIDIpLCBjKCIjMjE2NkFDIiwgIndoaXRlIiwgIiNCMjE4MkIiKSksCiAgY29sdW1uX3RpdGxlID0gIlRvcCAxMCBQYXRod2F5cyBieSBDbHVzdGVyIgopCgoKCgoKCiMgSGVhdG1hcApsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQpsaWJyYXJ5KGNpcmNsaXplKQoKY2x1c3RlcnMgPC0gU1Mkc2V1cmF0X2NsdXN0ZXJzCmF2Z19ieV9jbHVzdGVyIDwtIHNhcHBseShsZXZlbHMoZmFjdG9yKGNsdXN0ZXJzKSksIGZ1bmN0aW9uKGNsKSB7CiAgY2VsbHMgPC0gd2hpY2goY2x1c3RlcnMgPT0gY2wpCiAgcm93TWVhbnMobWV0YWJvbGlzbS5tYXRyaXhbLCBjZWxscywgZHJvcCA9IEZBTFNFXSkKfSkKY29sbmFtZXMoYXZnX2J5X2NsdXN0ZXIpIDwtIGxldmVscyhmYWN0b3IoY2x1c3RlcnMpKQoKYXZnX3RvcDEwIDwtIGF2Z19ieV9jbHVzdGVyW3RvcF9wYXRoc19nbG9iYWwsIF0KYXZnX3RvcDEwX3NjYWxlZCA8LSB0KHNjYWxlKHQoYXZnX3RvcDEwKSkpCgpIZWF0bWFwKAogIGF2Z190b3AxMF9zY2FsZWQsCiAgbmFtZSA9ICJaLXNjb3JlIiwKICBjbHVzdGVyX3Jvd3MgPSBUUlVFLAogIGNsdXN0ZXJfY29sdW1ucyA9IFRSVUUsCiAgY29sID0gY29sb3JSYW1wMihjKC0yLCAwLCAyKSwgYygiIzIxNjZBQyIsICJ3aGl0ZSIsICIjQjIxODJCIikpLAogIGNvbHVtbl90aXRsZSA9ICJUb3AgMTAgUGF0aHdheXMgYnkgQ2x1c3RlciIKKQoKCgpgYGAKCiMgIEhlYXRtYXAKYGBge3IgLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTR9CgojIEhlYXRtYXAKbGlicmFyeShDb21wbGV4SGVhdG1hcCkKbGlicmFyeShjaXJjbGl6ZSkKCmNsdXN0ZXJzIDwtIFNTJG9yaWcuaWRlbnQKYXZnX2J5X2NsdXN0ZXIgPC0gc2FwcGx5KGxldmVscyhmYWN0b3IoY2x1c3RlcnMpKSwgZnVuY3Rpb24oY2wpIHsKICBjZWxscyA8LSB3aGljaChjbHVzdGVycyA9PSBjbCkKICByb3dNZWFucyhtZXRhYm9saXNtLm1hdHJpeFssIGNlbGxzLCBkcm9wID0gRkFMU0VdKQp9KQpjb2xuYW1lcyhhdmdfYnlfY2x1c3RlcikgPC0gbGV2ZWxzKGZhY3RvcihjbHVzdGVycykpCgphdmdfdG9wMTAgPC0gYXZnX2J5X2NsdXN0ZXJbdG9wX3BhdGhzX2dsb2JhbCwgXQphdmdfdG9wMTBfc2NhbGVkIDwtIHQoc2NhbGUodChhdmdfdG9wMTApKSkKCkhlYXRtYXAoCiAgYXZnX3RvcDEwX3NjYWxlZCwKICBuYW1lID0gIlotc2NvcmUiLAogIGNsdXN0ZXJfcm93cyA9IFRSVUUsCiAgY2x1c3Rlcl9jb2x1bW5zID0gVFJVRSwKICBjb2wgPSBjb2xvclJhbXAyKGMoLTIsIDAsIDIpLCBjKCIjMjE2NkFDIiwgIndoaXRlIiwgIiNCMjE4MkIiKSksCiAgY29sdW1uX3RpdGxlID0gIlRvcCAxMCBQYXRod2F5cyBieSBDbHVzdGVyIgopCgoKCgoKCiMgSGVhdG1hcApsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQpsaWJyYXJ5KGNpcmNsaXplKQoKY2x1c3RlcnMgPC0gU1Mkc2V1cmF0X2NsdXN0ZXJzCmF2Z19ieV9jbHVzdGVyIDwtIHNhcHBseShsZXZlbHMoZmFjdG9yKGNsdXN0ZXJzKSksIGZ1bmN0aW9uKGNsKSB7CiAgY2VsbHMgPC0gd2hpY2goY2x1c3RlcnMgPT0gY2wpCiAgcm93TWVhbnMobWV0YWJvbGlzbS5tYXRyaXhbLCBjZWxscywgZHJvcCA9IEZBTFNFXSkKfSkKY29sbmFtZXMoYXZnX2J5X2NsdXN0ZXIpIDwtIGxldmVscyhmYWN0b3IoY2x1c3RlcnMpKQoKYXZnX3RvcDEwIDwtIGF2Z19ieV9jbHVzdGVyW3RvcF9wYXRoc19nbG9iYWwsIF0KYXZnX3RvcDEwX3NjYWxlZCA8LSB0KHNjYWxlKHQoYXZnX3RvcDEwKSkpCgpIZWF0bWFwKAogIGF2Z190b3AxMF9zY2FsZWQsCiAgbmFtZSA9ICJaLXNjb3JlIiwKICBjbHVzdGVyX3Jvd3MgPSBUUlVFLAogIGNsdXN0ZXJfY29sdW1ucyA9IFRSVUUsCiAgY29sID0gY29sb3JSYW1wMihjKC0yLCAwLCAyKSwgYygiIzIxNjZBQyIsICJ3aGl0ZSIsICIjQjIxODJCIikpLAogIGNvbHVtbl90aXRsZSA9ICJUb3AgMTAgUGF0aHdheXMgYnkgQ2x1c3RlciIKKQoKCgpgYGAK