1. load libraries

2. Load Data into Seurat


library(Seurat)
library(dplyr)

# Set directory paths
ss_dir <- "data/SS_Patients/"
MF_dir <- "data/MF_Patients/"

ss_dirs <- sort(list.dirs(ss_dir, full.names = TRUE, recursive = FALSE))
mf_dirs <- sort(list.dirs(MF_dir, full.names = TRUE, recursive = FALSE))

ss_names <- paste0("SS_P", 1:4)
mf_names <- paste0("MF_P", 1:3)

# Initialize list for Seurat objects
seurat_objects <- list()

# Load SS samples
for (i in seq_along(ss_dirs)) {
  dat <- Read10X(data.dir = ss_dirs[i])
  seu <- CreateSeuratObject(counts = dat, project = ss_names[i], min.cells = 3, min.features = 200)
  seu$sample <- ss_names[i]
  seu <- RenameCells(seu, add.cell.id = ss_names[i])
  seu$Disease_state <- "Sézary"
  seu$Patient_ID <- gsub("^SS_P", "P", ss_names[i])
  seurat_objects[[ss_names[i]]] <- seu
}

# Load MF samples
for (i in seq_along(mf_dirs)) {
  dat <- Read10X(data.dir = mf_dirs[i])
  seu <- CreateSeuratObject(counts = dat, project = mf_names[i], min.cells = 3, min.features = 200)
  seu$sample <- mf_names[i]
  seu <- RenameCells(seu, add.cell.id = mf_names[i])
  seu$Disease_state <- "MF"
  seu$Patient_ID <- gsub("^MF_P", "P", mf_names[i])
  seurat_objects[[mf_names[i]]] <- seu
}

# Merge all Seurat objects
all_seurat <- Reduce(function(x, y) merge(x, y), seurat_objects)

# Basic QC: Filter low-quality cells and high mitochondrial content
all_seurat[["percent.mt"]] <- PercentageFeatureSet(all_seurat, pattern = "^MT-")
all_seurat <- subset(all_seurat, subset = nFeature_RNA > 200 & percent.mt < 10)

# Store main object
ss_Harro <- all_seurat

3. QC


VlnPlot(ss_Harro, features = c("nFeature_RNA", 
                                    "nCount_RNA", 
                                    "percent.mt"), 
                                      ncol = 3)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.Warning: The `slot` argument of `FetchData()` is deprecated as of SeuratObject 5.0.0.
Please use the `layer` argument instead.Warning: `PackageCheck()` was deprecated in SeuratObject 5.0.0.
Please use `rlang::check_installed()` instead.Rasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`
Rasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`
Rasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`

VlnPlot(ss_Harro, features = c("nFeature_RNA", 
                                         "nCount_RNA", 
                                         "percent.mt",
                                         "percent.rb"), 
                            ncol = 4, pt.size = 0.1) & 
              theme(plot.title = element_text(size=10))
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.Warning: The following requested variables were not found: percent.rbRasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`
Rasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`
Rasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`

FeatureScatter(ss_Harro, 
               feature1 = "nCount_RNA", 
               feature2 = "nFeature_RNA") +
  geom_smooth(method = 'lm')
Rasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`

##FeatureScatter is typically used to visualize feature-feature relationships ##for anything calculated by the object, ##i.e. columns in object metadata, PC scores etc.


FeatureScatter(ss_Harro, 
               feature1 = "nCount_RNA", 
               feature2 = "percent.mt")+
  geom_smooth(method = 'lm')
Rasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`

FeatureScatter(ss_Harro, 
               feature1 = "nCount_RNA", 
               feature2 = "nFeature_RNA")+
  geom_smooth(method = 'lm')
Rasterizing points since number of points exceeds 100,000.
To disable this behavior set `raster=FALSE`

##Read Seurat object with load as you save it with save() function


All_samples_Merged <- readRDS("../0-Seurat_RDS_OBJECT_FINAL/All_samples_Merged_Harmony_integrated_Cell_line_renamed_03-07-2025.rds")

Save the Seurat object as an RDS



saveRDS(ss_Harro, file = "data/ss_Harro_SS_4_MF_3_QC_object.rds")

4. Log-normalization (scale factor = 10,000) and Integration



library(Seurat)

# Normalize (log-normalization), identify top 5000 variable genes
ss_list <- SplitObject(ss_Harro, split.by = "orig.ident")
ss_list <- lapply(ss_list, function(x) {
  x <- NormalizeData(x, normalization.method = "LogNormalize", scale.factor = 10000)
  x <- FindVariableFeatures(x, selection.method = "vst", nfeatures = 5000)
  x <- CellCycleScoring(x, s.features = cc.genes$s.genes, g2m.features = cc.genes$g2m.genes)
  return(x)
})

# Remove TCR/Ig genes from variable features
tcr_genes <- grep("^TR[ABGD]|^IG[HKL]", rownames(ss_list[[1]]), value = TRUE)
ss_list <- lapply(ss_list, function(x) {
  vgs <- VariableFeatures(x)
  vgs <- setdiff(vgs, tcr_genes)
  VariableFeatures(x) <- vgs
  return(x)
})


# Integration using 8000 anchors and CCA (dims = 40)
features <- SelectIntegrationFeatures(object.list = ss_list, nfeatures = 8000)
anchors <- FindIntegrationAnchors(object.list = ss_list, anchor.features = features, reduction = "cca", dims = 1:40)
ss_integrated <- IntegrateData(anchorset = anchors, dims = 1:40)

# Set integrated assay as default
DefaultAssay(ss_integrated) <- "integrated"


# ScaleData with regressions
ss_integrated <- ScaleData(ss_integrated, vars.to.regress = c("nCount_RNA", "percent.mt", "S.Score", "G2M.Score"))

5. PCA + UMAP


ss_Harro <- ss_integrated

# PCA
ss_Harro <- RunPCA(ss_Harro, npcs = 50)




# Optional: Visualize elbow plot
ElbowPlot(ss_Harro, ndims = 50)

# # Run JackStraw analysis properly
# ss_Harro <- JackStraw(ss_Harro, num.replicate = 100)
# ss_Harro <- ScoreJackStraw(ss_Harro, dims = 1:20)
# 
# # Visualize JackStraw scores
# JackStrawPlot(ss_Harro, dims = 1:20)

6. PCA Visualization




# TEST-1
# given that the output of RunPCA is "pca"
# replace "so" by the name of your seurat object

pct <- ss_Harro[["pca"]]@stdev / sum(ss_Harro[["pca"]]@stdev) * 100
cumu <- cumsum(pct) # Calculate cumulative percents for each PC
# Determine the difference between variation of PC and subsequent PC
co2 <- sort(which((pct[-length(pct)] - pct[-1]) > 0.1), decreasing = T)[1] + 1
# last point where change of % of variation is more than 0.1%. -> co2
co2

# TEST-2
# get significant PCs
stdv <- ss_Harro[["pca"]]@stdev
sum.stdv <- sum(ss_Harro[["pca"]]@stdev)
percent.stdv <- (stdv / sum.stdv) * 100
cumulative <- cumsum(percent.stdv)
co1 <- which(cumulative > 90 & percent.stdv < 5)[1]
co2 <- sort(which((percent.stdv[1:length(percent.stdv) - 1] - 
                       percent.stdv[2:length(percent.stdv)]) > 0.1), 
              decreasing = T)[1] + 1
min.pc <- min(co1, co2)
min.pc

# Create a dataframe with values
plot_df <- data.frame(pct = percent.stdv, 
           cumu = cumulative, 
           rank = 1:length(percent.stdv))

# Elbow plot to visualize 
  ggplot(plot_df, aes(cumulative, percent.stdv, label = rank, color = rank > min.pc)) + 
  geom_text() + 
  geom_vline(xintercept = 90, color = "grey") + 
  geom_hline(yintercept = min(percent.stdv[percent.stdv > 5]), color = "grey") +
  theme_bw()

  

7. Clustering (resolution = 1.2)

# Then find neighbors & clusters
ss_Harro <- FindNeighbors(ss_Harro, dims = 1:40)
ss_Harro <- FindClusters(ss_Harro, resolution = 1.0)

# run UMAP
ss_Harro <- RunUMAP(ss_Harro, dims = 1:40)

ss_Harro <-RunTSNE(ss_Harro, dims.use = 1:40)

8. Visualize UMAP with Clusters


DimPlot(ss_Harro, reduction = "umap",group.by = "orig.ident", label = TRUE,repel = T, pt.size = 0.6) +
  ggtitle("UMAP of Sézary Syndrome CD4+ T Cells")


DimPlot(ss_Harro, reduction = "umap", label = TRUE,repel = T, pt.size = 0.6) +
  ggtitle("UMAP of Sézary Syndrome CD4+ T Cells")


DimPlot(ss_Harro, reduction = "tsne", label = TRUE, pt.size = 0.6) +
  ggtitle("TSNE of Sézary Syndrome CD4+ T Cells")

9. FeaturePlots for Top50 UP

top_50_up <- read.csv("../Data_ss_Harro_2019/top_50_upregulated.csv")        # or read.delim("top_50_up.tsv")
top_50_down <- read.csv("../Data_ss_Harro_2019/top_50_downregulated.csv")

Idents(ss_Harro) <- "seurat_clusters"


FeaturePlot(ss_Harro, 
             features = top_50_up$gene[1:10], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)


FeaturePlot(ss_Harro, 
             features = top_50_up$gene[11:20], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)

FeaturePlot(ss_Harro, 
             features = top_50_up$gene[21:30], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
FeaturePlot(ss_Harro, 
             features = top_50_up$gene[31:40], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
FeaturePlot(ss_Harro, 
             features = top_50_up$gene[41:50], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)

10. FeaturePlots for Top50 DOWN


FeaturePlot(ss_Harro, 
             features = top_50_down$gene[1:10], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)


FeaturePlot(ss_Harro, 
             features = top_50_down$gene[11:20], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)

FeaturePlot(ss_Harro, 
             features = top_50_down$gene[21:30], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
FeaturePlot(ss_Harro, 
             features = top_50_down$gene[31:40], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
FeaturePlot(ss_Harro, 
             features = top_50_down$gene[41:50], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)

Visualization



DimPlot(ss_Harro, group.by = "seurat_clusters", label = T, label.box = T, repel = T, reduction = "umap")

Visualization of Potential biomarkers-Upregulated


DefaultAssay(ss_Harro) <- "RNA"
Idents(ss_Harro) <- "Disease_state"

# Vector of genes to plot
up_genes <- c("CLIC1", "COX5A","GTSF1", "MAD2L1","MYBL2","MYL6B","NME1","PLK1", "PYCR1", "SLC25A5", "SRI", "TUBA1C", "UBE2T", "YWHAH")

# DotPlot with custom firebrick-red gradient
DotPlot(ss_Harro, features = up_genes) +
  RotatedAxis() +
  scale_color_gradient2(low = "lightyellow", mid = "red", high = "firebrick", midpoint = 1) +
  ggtitle("Expression of Upregulated Genes in Sézary Syndrome") +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
    axis.text.y = element_text(size = 12),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14)
  )

Idents(ss_Harro) <- "orig.ident"

# Vector of genes to plot
up_genes <- c("CLIC1", "COX5A","GTSF1", "MAD2L1","MYBL2","MYL6B","NME1","PLK1", "PYCR1", "SLC25A5", "SRI", "TUBA1C", "UBE2T", "YWHAH")

# DotPlot with custom firebrick-red gradient
DotPlot(ss_Harro, features = up_genes) +
  RotatedAxis() +
  scale_color_gradient2(low = "lightyellow", mid = "red", high = "firebrick", midpoint = 1) +
  ggtitle("Expression of Upregulated Genes in Sézary Syndrome") +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
    axis.text.y = element_text(size = 12),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14)
  )

Idents(ss_Harro) <- "seurat_clusters"

# Vector of genes to plot
up_genes <- c("CLIC1", "COX5A","GTSF1", "MAD2L1","MYBL2","MYL6B","NME1","PLK1", "PYCR1", "SLC25A5", "SRI", "TUBA1C", "UBE2T", "YWHAH")

# DotPlot with custom firebrick-red gradient
DotPlot(ss_Harro, features = up_genes) +
  RotatedAxis() +
  scale_color_gradient2(low = "lightyellow", mid = "red", high = "firebrick", midpoint = 1) +
  ggtitle("Expression of Upregulated Genes in Sézary Syndrome") +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
    axis.text.y = element_text(size = 12),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14)
  )

Visualization of Potential biomarkers-Downregulated


Idents(ss_Harro) <- "Disease_state"
# Downregulated genes
down_genes <- c("TXNIP", "RASA3", "RIPOR2", 
                "ZFP36", "ZFP36L1", "ZFP36L2",
                "PRMT2", "MAX", "PIK3IP1", 
                "BTG1", "CDKN1B")

# DotPlot with firebrick color for high expression
DotPlot(ss_Harro, features = down_genes) +
  RotatedAxis() +
  scale_color_gradient2(low = "lightyellow", mid = "red", high = "firebrick", midpoint = 1) +
  ggtitle("Expression of Downregulated Genes in Sézary Syndrome") +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
    axis.text.y = element_text(size = 12),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14)
  )


Idents(ss_Harro) <- "orig.ident"
# Downregulated genes
down_genes <- c("TXNIP", "RASA3", "RIPOR2", 
                "ZFP36", "ZFP36L1", "ZFP36L2",
                "PRMT2", "MAX", "PIK3IP1", 
                "BTG1", "CDKN1B")

# DotPlot with firebrick color for high expression
DotPlot(ss_Harro, features = down_genes) +
  RotatedAxis() +
  scale_color_gradient2(low = "lightyellow", mid = "red", high = "firebrick", midpoint = 1) +
  ggtitle("Expression of Downregulated Genes in Sézary Syndrome") +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
    axis.text.y = element_text(size = 12),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14)
  )
Idents(ss_Harro) <- "seurat_clusters"

# DotPlot with firebrick color for high expression
DotPlot(ss_Harro, features = down_genes) +
  RotatedAxis() +
  scale_color_gradient2(low = "lightyellow", mid = "red", high = "firebrick", midpoint = 1) +
  ggtitle("Expression of Downregulated Genes in Sézary Syndrome") +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
    axis.text.y = element_text(size = 12),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14)
  )

Save the Seurat object as an RDS



saveRDS(ss_Harro, file = "data/ss_Harro_SS_4_MF_3_Integrated_object.rds")
LS0tCnRpdGxlOiAiUG90ZW50aWFsIGJpb21hcmtlcnMgVmFsaWRhdGlvbiAoSGFycm9fNF9TU19hbmRfM19NRl9QYXRpZW50X1NhbXBsZXMpIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0RGF0YSkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoQXppbXV0aCkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShybWFya2Rvd24pCmxpYnJhcnkodGlueXRleCkKCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGRpdHRvU2VxKQpsaWJyYXJ5KGdncmVwZWwpCiNsaWJyYXJ5KGdndHJlZSkKbGlicmFyeShwYXJhbGxlbCkKbGlicmFyeShwbG90bHkpICAjIDNEIHBsb3QKbGlicmFyeShTZXVyYXQpICAjIElkZW50cygpCmxpYnJhcnkoU2V1cmF0RGlzaykgICMgU2F2ZUg1U2V1cmF0KCkKbGlicmFyeSh0aWJibGUpICAjIHJvd25uYW1lc190b19jb2x1bW4KbGlicmFyeShoYXJtb255KSAjIFJ1bkhhcm1vbnkoKQojb3B0aW9ucyhtYy5jb3JlcyA9IGRldGVjdENvcmVzKCkgLSAxKQoKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZGJwbHlyKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeShrbml0cikKbGlicmFyeSh0aW55dGV4KQojQXppbXV0aCBBbm5vdGF0aW9uIGxpYnJhcmllcwpsaWJyYXJ5KEF6aW11dGgpCiNQcm9qZWNUaWxzIEFubm90YXRpb24gbGlicmFyaWVzCmxpYnJhcnkoU1RBQ0FTKQpsaWJyYXJ5KFByb2plY1RJTHMpCiNzaW5nbGVSIEFubm90YXRpb24gbGlicmFyaWVzCgpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQoKYGBgCgoKIyAyLiBMb2FkIERhdGEgaW50byBTZXVyYXQKYGBge3IgbG9hZF9zZXVyYXR9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShkcGx5cikKCiMgU2V0IGRpcmVjdG9yeSBwYXRocwpzc19kaXIgPC0gImRhdGEvU1NfUGF0aWVudHMvIgpNRl9kaXIgPC0gImRhdGEvTUZfUGF0aWVudHMvIgoKc3NfZGlycyA8LSBzb3J0KGxpc3QuZGlycyhzc19kaXIsIGZ1bGwubmFtZXMgPSBUUlVFLCByZWN1cnNpdmUgPSBGQUxTRSkpCm1mX2RpcnMgPC0gc29ydChsaXN0LmRpcnMoTUZfZGlyLCBmdWxsLm5hbWVzID0gVFJVRSwgcmVjdXJzaXZlID0gRkFMU0UpKQoKc3NfbmFtZXMgPC0gcGFzdGUwKCJTU19QIiwgMTo0KQptZl9uYW1lcyA8LSBwYXN0ZTAoIk1GX1AiLCAxOjMpCgojIEluaXRpYWxpemUgbGlzdCBmb3IgU2V1cmF0IG9iamVjdHMKc2V1cmF0X29iamVjdHMgPC0gbGlzdCgpCgojIExvYWQgU1Mgc2FtcGxlcwpmb3IgKGkgaW4gc2VxX2Fsb25nKHNzX2RpcnMpKSB7CiAgZGF0IDwtIFJlYWQxMFgoZGF0YS5kaXIgPSBzc19kaXJzW2ldKQogIHNldSA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gZGF0LCBwcm9qZWN0ID0gc3NfbmFtZXNbaV0sIG1pbi5jZWxscyA9IDMsIG1pbi5mZWF0dXJlcyA9IDIwMCkKICBzZXUkc2FtcGxlIDwtIHNzX25hbWVzW2ldCiAgc2V1IDwtIFJlbmFtZUNlbGxzKHNldSwgYWRkLmNlbGwuaWQgPSBzc19uYW1lc1tpXSkKICBzZXUkRGlzZWFzZV9zdGF0ZSA8LSAiU8OpemFyeSIKICBzZXUkUGF0aWVudF9JRCA8LSBnc3ViKCJeU1NfUCIsICJQIiwgc3NfbmFtZXNbaV0pCiAgc2V1cmF0X29iamVjdHNbW3NzX25hbWVzW2ldXV0gPC0gc2V1Cn0KCiMgTG9hZCBNRiBzYW1wbGVzCmZvciAoaSBpbiBzZXFfYWxvbmcobWZfZGlycykpIHsKICBkYXQgPC0gUmVhZDEwWChkYXRhLmRpciA9IG1mX2RpcnNbaV0pCiAgc2V1IDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBkYXQsIHByb2plY3QgPSBtZl9uYW1lc1tpXSwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwKQogIHNldSRzYW1wbGUgPC0gbWZfbmFtZXNbaV0KICBzZXUgPC0gUmVuYW1lQ2VsbHMoc2V1LCBhZGQuY2VsbC5pZCA9IG1mX25hbWVzW2ldKQogIHNldSREaXNlYXNlX3N0YXRlIDwtICJNRiIKICBzZXUkUGF0aWVudF9JRCA8LSBnc3ViKCJeTUZfUCIsICJQIiwgbWZfbmFtZXNbaV0pCiAgc2V1cmF0X29iamVjdHNbW21mX25hbWVzW2ldXV0gPC0gc2V1Cn0KCiMgTWVyZ2UgYWxsIFNldXJhdCBvYmplY3RzCmFsbF9zZXVyYXQgPC0gUmVkdWNlKGZ1bmN0aW9uKHgsIHkpIG1lcmdlKHgsIHkpLCBzZXVyYXRfb2JqZWN0cykKCiMgQmFzaWMgUUM6IEZpbHRlciBsb3ctcXVhbGl0eSBjZWxscyBhbmQgaGlnaCBtaXRvY2hvbmRyaWFsIGNvbnRlbnQKYWxsX3NldXJhdFtbInBlcmNlbnQubXQiXV0gPC0gUGVyY2VudGFnZUZlYXR1cmVTZXQoYWxsX3NldXJhdCwgcGF0dGVybiA9ICJeTVQtIikKYWxsX3NldXJhdCA8LSBzdWJzZXQoYWxsX3NldXJhdCwgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gMjAwICYgcGVyY2VudC5tdCA8IDEwKQoKIyBTdG9yZSBtYWluIG9iamVjdApzc19IYXJybyA8LSBhbGxfc2V1cmF0CgpgYGAKCiMgMy4gUUMKYGBge3IgUUMsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKVmxuUGxvdChzc19IYXJybywgZmVhdHVyZXMgPSBjKCJuRmVhdHVyZV9STkEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5Db3VudF9STkEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnQubXQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMpCgpWbG5QbG90KHNzX0hhcnJvLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnQubXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjZW50LnJiIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDQsIHB0LnNpemUgPSAwLjEpICYgCiAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSkKCkZlYXR1cmVTY2F0dGVyKHNzX0hhcnJvLCAKICAgICAgICAgICAgICAgZmVhdHVyZTEgPSAibkNvdW50X1JOQSIsIAogICAgICAgICAgICAgICBmZWF0dXJlMiA9ICJuRmVhdHVyZV9STkEiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJykKCmBgYAoKCiMjRmVhdHVyZVNjYXR0ZXIgaXMgdHlwaWNhbGx5IHVzZWQgdG8gdmlzdWFsaXplIGZlYXR1cmUtZmVhdHVyZSByZWxhdGlvbnNoaXBzCiMjZm9yIGFueXRoaW5nIGNhbGN1bGF0ZWQgYnkgdGhlIG9iamVjdCwgCiMjaS5lLiBjb2x1bW5zIGluIG9iamVjdCBtZXRhZGF0YSwgUEMgc2NvcmVzIGV0Yy4KCmBgYHtyIEZDLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCkZlYXR1cmVTY2F0dGVyKHNzX0hhcnJvLCAKICAgICAgICAgICAgICAgZmVhdHVyZTEgPSAibkNvdW50X1JOQSIsIAogICAgICAgICAgICAgICBmZWF0dXJlMiA9ICJwZXJjZW50Lm10IikrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJykKCkZlYXR1cmVTY2F0dGVyKHNzX0hhcnJvLCAKICAgICAgICAgICAgICAgZmVhdHVyZTEgPSAibkNvdW50X1JOQSIsIAogICAgICAgICAgICAgICBmZWF0dXJlMiA9ICJuRmVhdHVyZV9STkEiKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKQoKYGBgCgojI1JlYWQgU2V1cmF0IG9iamVjdCB3aXRoIGxvYWQgYXMgeW91IHNhdmUgaXQgd2l0aCBzYXZlKCkgZnVuY3Rpb24KCmBgYHtyIGxvYWRTZXVyYXR9CgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gcmVhZFJEUygiLi4vMC1TZXVyYXRfUkRTX09CSkVDVF9GSU5BTC9BbGxfc2FtcGxlc19NZXJnZWRfSGFybW9ueV9pbnRlZ3JhdGVkX0NlbGxfbGluZV9yZW5hbWVkXzAzLTA3LTIwMjUucmRzIikKCmBgYAoKCiMjIFNhdmUgdGhlIFNldXJhdCBvYmplY3QgYXMgYW4gUkRTCmBgYHtyIHNhdmVSRFN9CgoKc2F2ZVJEUyhzc19IYXJybywgZmlsZSA9ICJkYXRhL3NzX0hhcnJvX1NTXzRfTUZfM19RQ19vYmplY3QucmRzIikKCgpgYGAKCgoKIyA0LiBMb2ctbm9ybWFsaXphdGlvbiAoc2NhbGUgZmFjdG9yID0gMTAsMDAwKSBhbmQgSW50ZWdyYXRpb24KYGBge3IgUENBLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgpsaWJyYXJ5KFNldXJhdCkKCiMgTm9ybWFsaXplIChsb2ctbm9ybWFsaXphdGlvbiksIGlkZW50aWZ5IHRvcCA1MDAwIHZhcmlhYmxlIGdlbmVzCnNzX2xpc3QgPC0gU3BsaXRPYmplY3Qoc3NfSGFycm8sIHNwbGl0LmJ5ID0gIm9yaWcuaWRlbnQiKQpzc19saXN0IDwtIGxhcHBseShzc19saXN0LCBmdW5jdGlvbih4KSB7CiAgeCA8LSBOb3JtYWxpemVEYXRhKHgsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIHNjYWxlLmZhY3RvciA9IDEwMDAwKQogIHggPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoeCwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSA1MDAwKQogIHggPC0gQ2VsbEN5Y2xlU2NvcmluZyh4LCBzLmZlYXR1cmVzID0gY2MuZ2VuZXMkcy5nZW5lcywgZzJtLmZlYXR1cmVzID0gY2MuZ2VuZXMkZzJtLmdlbmVzKQogIHJldHVybih4KQp9KQoKIyBSZW1vdmUgVENSL0lnIGdlbmVzIGZyb20gdmFyaWFibGUgZmVhdHVyZXMKdGNyX2dlbmVzIDwtIGdyZXAoIl5UUltBQkdEXXxeSUdbSEtMXSIsIHJvd25hbWVzKHNzX2xpc3RbWzFdXSksIHZhbHVlID0gVFJVRSkKc3NfbGlzdCA8LSBsYXBwbHkoc3NfbGlzdCwgZnVuY3Rpb24oeCkgewogIHZncyA8LSBWYXJpYWJsZUZlYXR1cmVzKHgpCiAgdmdzIDwtIHNldGRpZmYodmdzLCB0Y3JfZ2VuZXMpCiAgVmFyaWFibGVGZWF0dXJlcyh4KSA8LSB2Z3MKICByZXR1cm4oeCkKfSkKCgojIEludGVncmF0aW9uIHVzaW5nIDgwMDAgYW5jaG9ycyBhbmQgQ0NBIChkaW1zID0gNDApCmZlYXR1cmVzIDwtIFNlbGVjdEludGVncmF0aW9uRmVhdHVyZXMob2JqZWN0Lmxpc3QgPSBzc19saXN0LCBuZmVhdHVyZXMgPSA4MDAwKQphbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSBzc19saXN0LCBhbmNob3IuZmVhdHVyZXMgPSBmZWF0dXJlcywgcmVkdWN0aW9uID0gImNjYSIsIGRpbXMgPSAxOjQwKQpzc19pbnRlZ3JhdGVkIDwtIEludGVncmF0ZURhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgZGltcyA9IDE6NDApCgojIFNldCBpbnRlZ3JhdGVkIGFzc2F5IGFzIGRlZmF1bHQKRGVmYXVsdEFzc2F5KHNzX2ludGVncmF0ZWQpIDwtICJpbnRlZ3JhdGVkIgoKCiMgU2NhbGVEYXRhIHdpdGggcmVncmVzc2lvbnMKc3NfaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEoc3NfaW50ZWdyYXRlZCwgdmFycy50by5yZWdyZXNzID0gYygibkNvdW50X1JOQSIsICJwZXJjZW50Lm10IiwgIlMuU2NvcmUiLCAiRzJNLlNjb3JlIikpCgoKYGBgCgoKIyA1LiBQQ0EgKyBVTUFQCmBgYHtyICwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9Cgpzc19IYXJybyA8LSBzc19pbnRlZ3JhdGVkCgojIFBDQQpzc19IYXJybyA8LSBSdW5QQ0Eoc3NfSGFycm8sIG5wY3MgPSA1MCkKCgoKCiMgT3B0aW9uYWw6IFZpc3VhbGl6ZSBlbGJvdyBwbG90CkVsYm93UGxvdChzc19IYXJybywgbmRpbXMgPSA1MCkKCiMgIyBSdW4gSmFja1N0cmF3IGFuYWx5c2lzIHByb3Blcmx5CiMgc3NfSGFycm8gPC0gSmFja1N0cmF3KHNzX0hhcnJvLCBudW0ucmVwbGljYXRlID0gMTAwKQojIHNzX0hhcnJvIDwtIFNjb3JlSmFja1N0cmF3KHNzX0hhcnJvLCBkaW1zID0gMToyMCkKIyAKIyAjIFZpc3VhbGl6ZSBKYWNrU3RyYXcgc2NvcmVzCiMgSmFja1N0cmF3UGxvdChzc19IYXJybywgZGltcyA9IDE6MjApCgpgYGAKCiMgNi4gUENBIFZpc3VhbGl6YXRpb24KYGBge3IgUENBLVRFU1QyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgoKIyBURVNULTEKIyBnaXZlbiB0aGF0IHRoZSBvdXRwdXQgb2YgUnVuUENBIGlzICJwY2EiCiMgcmVwbGFjZSAic28iIGJ5IHRoZSBuYW1lIG9mIHlvdXIgc2V1cmF0IG9iamVjdAoKcGN0IDwtIHNzX0hhcnJvW1sicGNhIl1dQHN0ZGV2IC8gc3VtKHNzX0hhcnJvW1sicGNhIl1dQHN0ZGV2KSAqIDEwMApjdW11IDwtIGN1bXN1bShwY3QpICMgQ2FsY3VsYXRlIGN1bXVsYXRpdmUgcGVyY2VudHMgZm9yIGVhY2ggUEMKIyBEZXRlcm1pbmUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB2YXJpYXRpb24gb2YgUEMgYW5kIHN1YnNlcXVlbnQgUEMKY28yIDwtIHNvcnQod2hpY2goKHBjdFstbGVuZ3RoKHBjdCldIC0gcGN0Wy0xXSkgPiAwLjEpLCBkZWNyZWFzaW5nID0gVClbMV0gKyAxCiMgbGFzdCBwb2ludCB3aGVyZSBjaGFuZ2Ugb2YgJSBvZiB2YXJpYXRpb24gaXMgbW9yZSB0aGFuIDAuMSUuIC0+IGNvMgpjbzIKCiMgVEVTVC0yCiMgZ2V0IHNpZ25pZmljYW50IFBDcwpzdGR2IDwtIHNzX0hhcnJvW1sicGNhIl1dQHN0ZGV2CnN1bS5zdGR2IDwtIHN1bShzc19IYXJyb1tbInBjYSJdXUBzdGRldikKcGVyY2VudC5zdGR2IDwtIChzdGR2IC8gc3VtLnN0ZHYpICogMTAwCmN1bXVsYXRpdmUgPC0gY3Vtc3VtKHBlcmNlbnQuc3RkdikKY28xIDwtIHdoaWNoKGN1bXVsYXRpdmUgPiA5MCAmIHBlcmNlbnQuc3RkdiA8IDUpWzFdCmNvMiA8LSBzb3J0KHdoaWNoKChwZXJjZW50LnN0ZHZbMTpsZW5ndGgocGVyY2VudC5zdGR2KSAtIDFdIC0gCiAgICAgICAgICAgICAgICAgICAgICAgcGVyY2VudC5zdGR2WzI6bGVuZ3RoKHBlcmNlbnQuc3RkdildKSA+IDAuMSksIAogICAgICAgICAgICAgIGRlY3JlYXNpbmcgPSBUKVsxXSArIDEKbWluLnBjIDwtIG1pbihjbzEsIGNvMikKbWluLnBjCgojIENyZWF0ZSBhIGRhdGFmcmFtZSB3aXRoIHZhbHVlcwpwbG90X2RmIDwtIGRhdGEuZnJhbWUocGN0ID0gcGVyY2VudC5zdGR2LCAKICAgICAgICAgICBjdW11ID0gY3VtdWxhdGl2ZSwgCiAgICAgICAgICAgcmFuayA9IDE6bGVuZ3RoKHBlcmNlbnQuc3RkdikpCgojIEVsYm93IHBsb3QgdG8gdmlzdWFsaXplIAogIGdncGxvdChwbG90X2RmLCBhZXMoY3VtdWxhdGl2ZSwgcGVyY2VudC5zdGR2LCBsYWJlbCA9IHJhbmssIGNvbG9yID0gcmFuayA+IG1pbi5wYykpICsgCiAgZ2VvbV90ZXh0KCkgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSA5MCwgY29sb3IgPSAiZ3JleSIpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWluKHBlcmNlbnQuc3RkdltwZXJjZW50LnN0ZHYgPiA1XSksIGNvbG9yID0gImdyZXkiKSArCiAgdGhlbWVfYncoKQoKICAKCmBgYAoKIyA3LiBDbHVzdGVyaW5nIChyZXNvbHV0aW9uID0gMS4yKQpgYGB7ciAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQojIFRoZW4gZmluZCBuZWlnaGJvcnMgJiBjbHVzdGVycwpzc19IYXJybyA8LSBGaW5kTmVpZ2hib3JzKHNzX0hhcnJvLCBkaW1zID0gMTo0MCkKc3NfSGFycm8gPC0gRmluZENsdXN0ZXJzKHNzX0hhcnJvLCByZXNvbHV0aW9uID0gMS4wKQoKIyBydW4gVU1BUApzc19IYXJybyA8LSBSdW5VTUFQKHNzX0hhcnJvLCBkaW1zID0gMTo0MCkKCnNzX0hhcnJvIDwtUnVuVFNORShzc19IYXJybywgZGltcy51c2UgPSAxOjQwKQoKYGBgCgoKIyA4LiBWaXN1YWxpemUgVU1BUCB3aXRoIENsdXN0ZXJzCmBgYHtyICwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgpEaW1QbG90KHNzX0hhcnJvLCByZWR1Y3Rpb24gPSAidW1hcCIsZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsIGxhYmVsID0gVFJVRSxyZXBlbCA9IFQsIHB0LnNpemUgPSAwLjYpICsKICBnZ3RpdGxlKCJVTUFQIG9mIFPDqXphcnkgU3luZHJvbWUgQ0Q0KyBUIENlbGxzIikKCgpEaW1QbG90KHNzX0hhcnJvLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSxyZXBlbCA9IFQsIHB0LnNpemUgPSAwLjYpICsKICBnZ3RpdGxlKCJVTUFQIG9mIFPDqXphcnkgU3luZHJvbWUgQ0Q0KyBUIENlbGxzIikKCgpEaW1QbG90KHNzX0hhcnJvLCByZWR1Y3Rpb24gPSAidHNuZSIsIGxhYmVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuNikgKwogIGdndGl0bGUoIlRTTkUgb2YgU8OpemFyeSBTeW5kcm9tZSBDRDQrIFQgQ2VsbHMiKQoKYGBgCgojIDkuICBGZWF0dXJlUGxvdHMgZm9yIFRvcDUwIFVQCmBgYHtyICwgZmlnLmhlaWdodD0xNiwgZmlnLndpZHRoPTIwfQp0b3BfNTBfdXAgPC0gcmVhZC5jc3YoIi4uL0RhdGFfc3NfSGFycm9fMjAxOS90b3BfNTBfdXByZWd1bGF0ZWQuY3N2IikgICAgICAgICMgb3IgcmVhZC5kZWxpbSgidG9wXzUwX3VwLnRzdiIpCnRvcF81MF9kb3duIDwtIHJlYWQuY3N2KCIuLi9EYXRhX3NzX0hhcnJvXzIwMTkvdG9wXzUwX2Rvd25yZWd1bGF0ZWQuY3N2IikKCklkZW50cyhzc19IYXJybykgPC0gInNldXJhdF9jbHVzdGVycyIKCgpGZWF0dXJlUGxvdChzc19IYXJybywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF91cCRnZW5lWzE6MTBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQoKCkZlYXR1cmVQbG90KHNzX0hhcnJvLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX3VwJGdlbmVbMTE6MjBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQoKRmVhdHVyZVBsb3Qoc3NfSGFycm8sIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfdXAkZ2VuZVsyMTozMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCkZlYXR1cmVQbG90KHNzX0hhcnJvLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX3VwJGdlbmVbMzE6NDBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQpGZWF0dXJlUGxvdChzc19IYXJybywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF91cCRnZW5lWzQxOjUwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKCmBgYAoKCgojIDEwLiAgRmVhdHVyZVBsb3RzIGZvciBUb3A1MCBET1dOCmBgYHtyICwgZmlnLmhlaWdodD0xNiwgZmlnLndpZHRoPTIwfQoKRmVhdHVyZVBsb3Qoc3NfSGFycm8sIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfZG93biRnZW5lWzE6MTBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQoKCkZlYXR1cmVQbG90KHNzX0hhcnJvLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX2Rvd24kZ2VuZVsxMToyMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgpGZWF0dXJlUGxvdChzc19IYXJybywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF9kb3duJGdlbmVbMjE6MzBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQpGZWF0dXJlUGxvdChzc19IYXJybywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF9kb3duJGdlbmVbMzE6NDBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQpGZWF0dXJlUGxvdChzc19IYXJybywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF9kb3duJGdlbmVbNDE6NTBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQpgYGAKCiMjIFZpc3VhbGl6YXRpb24KYGBge3IgLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgpEaW1QbG90KHNzX0hhcnJvLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcmVkdWN0aW9uID0gInVtYXAiKQoKCmBgYAoKIyMgVmlzdWFsaXphdGlvbiBvZiBQb3RlbnRpYWwgYmlvbWFya2Vycy1VcHJlZ3VsYXRlZApgYGB7ciAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKRGVmYXVsdEFzc2F5KHNzX0hhcnJvKSA8LSAiUk5BIgpJZGVudHMoc3NfSGFycm8pIDwtICJEaXNlYXNlX3N0YXRlIgoKIyBWZWN0b3Igb2YgZ2VuZXMgdG8gcGxvdAp1cF9nZW5lcyA8LSBjKCJDTElDMSIsICJDT1g1QSIsIkdUU0YxIiwgIk1BRDJMMSIsIk1ZQkwyIiwiTVlMNkIiLCJOTUUxIiwiUExLMSIsICJQWUNSMSIsICJTTEMyNUE1IiwgIlNSSSIsICJUVUJBMUMiLCAiVUJFMlQiLCAiWVdIQUgiKQoKIyBEb3RQbG90IHdpdGggY3VzdG9tIGZpcmVicmljay1yZWQgZ3JhZGllbnQKRG90UGxvdChzc19IYXJybywgZmVhdHVyZXMgPSB1cF9nZW5lcykgKwogIFJvdGF0ZWRBeGlzKCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAibGlnaHR5ZWxsb3ciLCBtaWQgPSAicmVkIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDEpICsKICBnZ3RpdGxlKCJFeHByZXNzaW9uIG9mIFVwcmVndWxhdGVkIEdlbmVzIGluIFPDqXphcnkgU3luZHJvbWUiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KQogICkKCklkZW50cyhzc19IYXJybykgPC0gIm9yaWcuaWRlbnQiCgojIFZlY3RvciBvZiBnZW5lcyB0byBwbG90CnVwX2dlbmVzIDwtIGMoIkNMSUMxIiwgIkNPWDVBIiwiR1RTRjEiLCAiTUFEMkwxIiwiTVlCTDIiLCJNWUw2QiIsIk5NRTEiLCJQTEsxIiwgIlBZQ1IxIiwgIlNMQzI1QTUiLCAiU1JJIiwgIlRVQkExQyIsICJVQkUyVCIsICJZV0hBSCIpCgojIERvdFBsb3Qgd2l0aCBjdXN0b20gZmlyZWJyaWNrLXJlZCBncmFkaWVudApEb3RQbG90KHNzX0hhcnJvLCBmZWF0dXJlcyA9IHVwX2dlbmVzKSArCiAgUm90YXRlZEF4aXMoKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJsaWdodHllbGxvdyIsIG1pZCA9ICJyZWQiLCBoaWdoID0gImZpcmVicmljayIsIG1pZHBvaW50ID0gMSkgKwogIGdndGl0bGUoIkV4cHJlc3Npb24gb2YgVXByZWd1bGF0ZWQgR2VuZXMgaW4gU8OpemFyeSBTeW5kcm9tZSIpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpCiAgKQoKSWRlbnRzKHNzX0hhcnJvKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgoKIyBWZWN0b3Igb2YgZ2VuZXMgdG8gcGxvdAp1cF9nZW5lcyA8LSBjKCJDTElDMSIsICJDT1g1QSIsIkdUU0YxIiwgIk1BRDJMMSIsIk1ZQkwyIiwiTVlMNkIiLCJOTUUxIiwiUExLMSIsICJQWUNSMSIsICJTTEMyNUE1IiwgIlNSSSIsICJUVUJBMUMiLCAiVUJFMlQiLCAiWVdIQUgiKQoKIyBEb3RQbG90IHdpdGggY3VzdG9tIGZpcmVicmljay1yZWQgZ3JhZGllbnQKRG90UGxvdChzc19IYXJybywgZmVhdHVyZXMgPSB1cF9nZW5lcykgKwogIFJvdGF0ZWRBeGlzKCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAibGlnaHR5ZWxsb3ciLCBtaWQgPSAicmVkIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDEpICsKICBnZ3RpdGxlKCJFeHByZXNzaW9uIG9mIFVwcmVndWxhdGVkIEdlbmVzIGluIFPDqXphcnkgU3luZHJvbWUiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KQogICkKCgpgYGAKCgoKIyMgVmlzdWFsaXphdGlvbiBvZiBQb3RlbnRpYWwgYmlvbWFya2Vycy1Eb3ducmVndWxhdGVkCmBgYHtyIEMyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCklkZW50cyhzc19IYXJybykgPC0gIkRpc2Vhc2Vfc3RhdGUiCiMgRG93bnJlZ3VsYXRlZCBnZW5lcwpkb3duX2dlbmVzIDwtIGMoIlRYTklQIiwgIlJBU0EzIiwgIlJJUE9SMiIsIAogICAgICAgICAgICAgICAgIlpGUDM2IiwgIlpGUDM2TDEiLCAiWkZQMzZMMiIsCiAgICAgICAgICAgICAgICAiUFJNVDIiLCAiTUFYIiwgIlBJSzNJUDEiLCAKICAgICAgICAgICAgICAgICJCVEcxIiwgIkNES04xQiIpCgojIERvdFBsb3Qgd2l0aCBmaXJlYnJpY2sgY29sb3IgZm9yIGhpZ2ggZXhwcmVzc2lvbgpEb3RQbG90KHNzX0hhcnJvLCBmZWF0dXJlcyA9IGRvd25fZ2VuZXMpICsKICBSb3RhdGVkQXhpcygpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudDIobG93ID0gImxpZ2h0eWVsbG93IiwgbWlkID0gInJlZCIsIGhpZ2ggPSAiZmlyZWJyaWNrIiwgbWlkcG9pbnQgPSAxKSArCiAgZ2d0aXRsZSgiRXhwcmVzc2lvbiBvZiBEb3ducmVndWxhdGVkIEdlbmVzIGluIFPDqXphcnkgU3luZHJvbWUiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KQogICkKCgpJZGVudHMoc3NfSGFycm8pIDwtICJvcmlnLmlkZW50IgojIERvd25yZWd1bGF0ZWQgZ2VuZXMKZG93bl9nZW5lcyA8LSBjKCJUWE5JUCIsICJSQVNBMyIsICJSSVBPUjIiLCAKICAgICAgICAgICAgICAgICJaRlAzNiIsICJaRlAzNkwxIiwgIlpGUDM2TDIiLAogICAgICAgICAgICAgICAgIlBSTVQyIiwgIk1BWCIsICJQSUszSVAxIiwgCiAgICAgICAgICAgICAgICAiQlRHMSIsICJDREtOMUIiKQoKIyBEb3RQbG90IHdpdGggZmlyZWJyaWNrIGNvbG9yIGZvciBoaWdoIGV4cHJlc3Npb24KRG90UGxvdChzc19IYXJybywgZmVhdHVyZXMgPSBkb3duX2dlbmVzKSArCiAgUm90YXRlZEF4aXMoKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJsaWdodHllbGxvdyIsIG1pZCA9ICJyZWQiLCBoaWdoID0gImZpcmVicmljayIsIG1pZHBvaW50ID0gMSkgKwogIGdndGl0bGUoIkV4cHJlc3Npb24gb2YgRG93bnJlZ3VsYXRlZCBHZW5lcyBpbiBTw6l6YXJ5IFN5bmRyb21lIikgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gMTIpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCkKICApCklkZW50cyhzc19IYXJybykgPC0gInNldXJhdF9jbHVzdGVycyIKCiMgRG90UGxvdCB3aXRoIGZpcmVicmljayBjb2xvciBmb3IgaGlnaCBleHByZXNzaW9uCkRvdFBsb3Qoc3NfSGFycm8sIGZlYXR1cmVzID0gZG93bl9nZW5lcykgKwogIFJvdGF0ZWRBeGlzKCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAibGlnaHR5ZWxsb3ciLCBtaWQgPSAicmVkIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDEpICsKICBnZ3RpdGxlKCJFeHByZXNzaW9uIG9mIERvd25yZWd1bGF0ZWQgR2VuZXMgaW4gU8OpemFyeSBTeW5kcm9tZSIpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpCiAgKQpgYGAKCiMjIFNhdmUgdGhlIFNldXJhdCBvYmplY3QgYXMgYW4gUkRTCmBgYHtyIHNhdmV9CgoKc2F2ZVJEUyhzc19IYXJybywgZmlsZSA9ICJkYXRhL3NzX0hhcnJvX1NTXzRfTUZfM19JbnRlZ3JhdGVkX29iamVjdC5yZHMiKQoKCmBgYAoK