1. load libraries

2. Load Data into Seurat


library(Seurat)

# Load 10x-format data
data_dir <- "data/GSM3478791/"
ss.data <- Read10X(data.dir = data_dir)

# Create Seurat object
ss_Borcherding <- CreateSeuratObject(counts = ss.data, project = "SS_Patient1", min.cells = 3, min.features = 200)
Warning: Feature names cannot have underscores ('_'), replacing with dashes ('-')
# Basic QC and filtering
ss_Borcherding[["percent.mt"]] <- PercentageFeatureSet(ss_Borcherding, pattern = "^MT-")
ss_Borcherding <- subset(ss_Borcherding, subset = nFeature_RNA > 200 & nFeature_RNA < 3500 & percent.mt < 9)

3. QC


VlnPlot(ss_Borcherding, 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.

VlnPlot(ss_Borcherding, 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.rb

FeatureScatter(ss_Borcherding, 
               feature1 = "nCount_RNA", 
               feature2 = "nFeature_RNA") +
  geom_smooth(method = 'lm')

##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_Borcherding, 
               feature1 = "nCount_RNA", 
               feature2 = "percent.mt")+
  geom_smooth(method = 'lm')


FeatureScatter(ss_Borcherding, 
               feature1 = "nCount_RNA", 
               feature2 = "nFeature_RNA")+
  geom_smooth(method = 'lm')

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



ss_Borcherding <- NormalizeData(ss_Borcherding, normalization.method = "LogNormalize", scale.factor = 10000)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

5. Variable features & scaling



ss_Borcherding <- FindVariableFeatures(ss_Borcherding, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
ss_Borcherding <- ScaleData(ss_Borcherding, features = VariableFeatures(ss_Borcherding))
Centering and scaling data matrix

  |                                                                                                                      
  |                                                                                                                |   0%
  |                                                                                                                      
  |========================================================                                                        |  50%
  |                                                                                                                      
  |================================================================================================================| 100%

6. PCA + UMAP

# Optional: Visualize elbow plot
ElbowPlot(ss_Borcherding, ndims = 20)

# Run JackStraw analysis properly
ss_Borcherding <- JackStraw(ss_Borcherding, num.replicate = 100)

  |                                                  | 0 % ~calculating  
  |+                                                 | 1 % ~01m 46s      
  |+                                                 | 2 % ~01m 47s      
  |++                                                | 3 % ~01m 46s      
  |++                                                | 4 % ~01m 45s      
  |+++                                               | 5 % ~01m 45s      
  |+++                                               | 6 % ~01m 44s      
  |++++                                              | 7 % ~01m 42s      
  |++++                                              | 8 % ~01m 41s      
  |+++++                                             | 9 % ~01m 40s      
  |+++++                                             | 10% ~01m 39s      
  |++++++                                            | 11% ~01m 38s      
  |++++++                                            | 12% ~01m 36s      
  |+++++++                                           | 13% ~01m 35s      
  |+++++++                                           | 14% ~01m 34s      
  |++++++++                                          | 15% ~01m 33s      
  |++++++++                                          | 16% ~01m 32s      
  |+++++++++                                         | 17% ~01m 31s      
  |+++++++++                                         | 18% ~01m 31s      
  |++++++++++                                        | 19% ~01m 29s      
  |++++++++++                                        | 20% ~01m 28s      
  |+++++++++++                                       | 21% ~01m 27s      
  |+++++++++++                                       | 22% ~01m 26s      
  |++++++++++++                                      | 23% ~01m 25s      
  |++++++++++++                                      | 24% ~01m 24s      
  |+++++++++++++                                     | 25% ~01m 23s      
  |+++++++++++++                                     | 26% ~01m 24s      
  |++++++++++++++                                    | 27% ~01m 22s      
  |++++++++++++++                                    | 28% ~01m 21s      
  |+++++++++++++++                                   | 29% ~01m 20s      
  |+++++++++++++++                                   | 30% ~01m 19s      
  |++++++++++++++++                                  | 31% ~01m 18s      
  |++++++++++++++++                                  | 32% ~01m 16s      
  |+++++++++++++++++                                 | 33% ~01m 15s      
  |+++++++++++++++++                                 | 34% ~01m 14s      
  |++++++++++++++++++                                | 35% ~01m 13s      
  |++++++++++++++++++                                | 36% ~01m 12s      
  |+++++++++++++++++++                               | 37% ~01m 11s      
  |+++++++++++++++++++                               | 38% ~01m 10s      
  |++++++++++++++++++++                              | 39% ~01m 08s      
  |++++++++++++++++++++                              | 40% ~01m 07s      
  |+++++++++++++++++++++                             | 41% ~01m 06s      
  |+++++++++++++++++++++                             | 42% ~01m 05s      
  |++++++++++++++++++++++                            | 43% ~01m 04s      
  |++++++++++++++++++++++                            | 44% ~01m 03s      
  |+++++++++++++++++++++++                           | 45% ~01m 01s      
  |+++++++++++++++++++++++                           | 46% ~01m 00s      
  |++++++++++++++++++++++++                          | 47% ~59s          
  |++++++++++++++++++++++++                          | 48% ~58s          
  |+++++++++++++++++++++++++                         | 49% ~57s          
  |+++++++++++++++++++++++++                         | 50% ~56s          
  |++++++++++++++++++++++++++                        | 51% ~55s          
  |++++++++++++++++++++++++++                        | 52% ~54s          
  |+++++++++++++++++++++++++++                       | 53% ~52s          
  |+++++++++++++++++++++++++++                       | 54% ~51s          
  |++++++++++++++++++++++++++++                      | 55% ~50s          
  |++++++++++++++++++++++++++++                      | 56% ~49s          
  |+++++++++++++++++++++++++++++                     | 57% ~48s          
  |+++++++++++++++++++++++++++++                     | 58% ~47s          
  |++++++++++++++++++++++++++++++                    | 59% ~46s          
  |++++++++++++++++++++++++++++++                    | 60% ~45s          
  |+++++++++++++++++++++++++++++++                   | 61% ~44s          
  |+++++++++++++++++++++++++++++++                   | 62% ~42s          
  |++++++++++++++++++++++++++++++++                  | 63% ~41s          
  |++++++++++++++++++++++++++++++++                  | 64% ~40s          
  |+++++++++++++++++++++++++++++++++                 | 65% ~39s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~38s          
  |++++++++++++++++++++++++++++++++++                | 67% ~37s          
  |++++++++++++++++++++++++++++++++++                | 68% ~36s          
  |+++++++++++++++++++++++++++++++++++               | 69% ~35s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~34s          
  |++++++++++++++++++++++++++++++++++++              | 71% ~33s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~31s          
  |+++++++++++++++++++++++++++++++++++++             | 73% ~30s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~29s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~28s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~27s          
  |+++++++++++++++++++++++++++++++++++++++           | 77% ~26s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~25s          
  |++++++++++++++++++++++++++++++++++++++++          | 79% ~24s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~22s          
  |+++++++++++++++++++++++++++++++++++++++++         | 81% ~21s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~20s          
  |++++++++++++++++++++++++++++++++++++++++++        | 83% ~19s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~18s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~17s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~16s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~15s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~13s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~12s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~11s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~10s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~09s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~08s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~07s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~06s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~04s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~03s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~02s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01m 52s

  |                                                  | 0 % ~calculating  
  |+++                                               | 5 % ~00s          
  |+++++                                             | 10% ~00s          
  |++++++++                                          | 15% ~00s          
  |++++++++++                                        | 20% ~00s          
  |+++++++++++++                                     | 25% ~00s          
  |+++++++++++++++                                   | 30% ~00s          
  |++++++++++++++++++                                | 35% ~00s          
  |++++++++++++++++++++                              | 40% ~00s          
  |+++++++++++++++++++++++                           | 45% ~00s          
  |+++++++++++++++++++++++++                         | 50% ~00s          
  |++++++++++++++++++++++++++++                      | 55% ~00s          
  |++++++++++++++++++++++++++++++                    | 60% ~00s          
  |+++++++++++++++++++++++++++++++++                 | 65% ~00s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~00s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~00s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=00s  
ss_Borcherding <- ScoreJackStraw(ss_Borcherding, dims = 1:20)

# Visualize JackStraw scores
JackStrawPlot(ss_Borcherding, dims = 1:20)

7. PCA Visualization




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

pct <- ss_Borcherding[["pca"]]@stdev / sum(ss_Borcherding[["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
[1] 14
# TEST-2
# get significant PCs
stdv <- ss_Borcherding[["pca"]]@stdev
sum.stdv <- sum(ss_Borcherding[["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
[1] 14
# 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()

NA
NA
NA

8. Clustering (resolution = 1.2)



ss_Borcherding <- FindNeighbors(ss_Borcherding, dims = 1:10)
Computing nearest neighbor graph
Computing SNN
ss_Borcherding <- FindClusters(ss_Borcherding, resolution = 1.2)
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 3443
Number of edges: 109727

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.7143
Number of communities: 13
Elapsed time: 0 seconds

9. Visualize UMAP with Clusters



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

10. FeaturePlots for Top50 UP

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



FeaturePlot(ss_Borcherding, 
             features = top_50_up$gene[1:10], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
Warning: The following requested variables were not found: PCLAF

FeaturePlot(ss_Borcherding, 
             features = top_50_up$gene[11:20], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
Warning: The following requested variables were not found: PKMYT1

FeaturePlot(ss_Borcherding, 
             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_Borcherding, 
             features = top_50_up$gene[31:40], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
Warning: The following requested variables were not found: CDC20

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

11. FeaturePlots for Top50 DOWN


FeaturePlot(ss_Borcherding, 
             features = top_50_down$gene[1:10], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
Warning: The following requested variables were not found: PCED1B-AS1, SNHG5

FeaturePlot(ss_Borcherding, 
             features = top_50_down$gene[11:20], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
Warning: The following requested variables were not found: RIPOR2

FeaturePlot(ss_Borcherding, 
             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_Borcherding, 
             features = top_50_down$gene[31:40], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
Warning: The following requested variables were not found: LINC01578

FeaturePlot(ss_Borcherding, 
             features = top_50_down$gene[41:50], 
             reduction = "umap", 
             cols = c("lightblue", "red"),  # Custom color gradient from light blue to red
             label = TRUE)
Warning: The following requested variables were not found: AL138963.4

Visualization



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

NA
NA

Visualization of Potential biomarkers-Upregulated



# 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_Borcherding, 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)
  )
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.

Visualization of Potential biomarkers-Downregulated



# 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_Borcherding, 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)
  )
Warning: The following requested variables were not found: RIPOR2Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.

Save the Seurat object as an RDS



saveRDS(ss_Borcherding, file = "data/ss_Borcherding.rds")
LS0tCnRpdGxlOiAiUG90ZW50aWFsIGJpb21hcmtlcnMgVmFsaWRhdGlvbiBvbiBQdWJsaWMgUGF0aWVudCBkYXRhX0JvcmNoZXJkaW5nXzFfTWFsaWduYW50X1BhdGllbnRfU2FtcGxlIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0RGF0YSkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoQXppbXV0aCkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShybWFya2Rvd24pCmxpYnJhcnkodGlueXRleCkKCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGRpdHRvU2VxKQpsaWJyYXJ5KGdncmVwZWwpCiNsaWJyYXJ5KGdndHJlZSkKbGlicmFyeShwYXJhbGxlbCkKbGlicmFyeShwbG90bHkpICAjIDNEIHBsb3QKbGlicmFyeShTZXVyYXQpICAjIElkZW50cygpCmxpYnJhcnkoU2V1cmF0RGlzaykgICMgU2F2ZUg1U2V1cmF0KCkKbGlicmFyeSh0aWJibGUpICAjIHJvd25uYW1lc190b19jb2x1bW4KbGlicmFyeShoYXJtb255KSAjIFJ1bkhhcm1vbnkoKQojb3B0aW9ucyhtYy5jb3JlcyA9IGRldGVjdENvcmVzKCkgLSAxKQoKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZGJwbHlyKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeShrbml0cikKbGlicmFyeSh0aW55dGV4KQojQXppbXV0aCBBbm5vdGF0aW9uIGxpYnJhcmllcwpsaWJyYXJ5KEF6aW11dGgpCiNQcm9qZWNUaWxzIEFubm90YXRpb24gbGlicmFyaWVzCmxpYnJhcnkoU1RBQ0FTKQpsaWJyYXJ5KFByb2plY1RJTHMpCiNzaW5nbGVSIEFubm90YXRpb24gbGlicmFyaWVzCgpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQoKYGBgCgoKIyAyLiBMb2FkIERhdGEgaW50byBTZXVyYXQKYGBge3IgbG9hZF9zZXVyYXR9CgpsaWJyYXJ5KFNldXJhdCkKCiMgTG9hZCAxMHgtZm9ybWF0IGRhdGEKZGF0YV9kaXIgPC0gImRhdGEvR1NNMzQ3ODc5MS8iCnNzLmRhdGEgPC0gUmVhZDEwWChkYXRhLmRpciA9IGRhdGFfZGlyKQoKIyBDcmVhdGUgU2V1cmF0IG9iamVjdApzc19Cb3JjaGVyZGluZyA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gc3MuZGF0YSwgcHJvamVjdCA9ICJTU19QYXRpZW50MSIsIG1pbi5jZWxscyA9IDMsIG1pbi5mZWF0dXJlcyA9IDIwMCkKCiMgQmFzaWMgUUMgYW5kIGZpbHRlcmluZwpzc19Cb3JjaGVyZGluZ1tbInBlcmNlbnQubXQiXV0gPC0gUGVyY2VudGFnZUZlYXR1cmVTZXQoc3NfQm9yY2hlcmRpbmcsIHBhdHRlcm4gPSAiXk1ULSIpCnNzX0JvcmNoZXJkaW5nIDwtIHN1YnNldChzc19Cb3JjaGVyZGluZywgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gMjAwICYgbkZlYXR1cmVfUk5BIDwgMzUwMCAmIHBlcmNlbnQubXQgPCA5KQoKYGBgCiMgMy4gUUMKYGBge3IgUUMsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKVmxuUGxvdChzc19Cb3JjaGVyZGluZywgZmVhdHVyZXMgPSBjKCJuRmVhdHVyZV9STkEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5Db3VudF9STkEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnQubXQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMpCgpWbG5QbG90KHNzX0JvcmNoZXJkaW5nLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnQubXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjZW50LnJiIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDQsIHB0LnNpemUgPSAwLjEpICYgCiAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSkKCkZlYXR1cmVTY2F0dGVyKHNzX0JvcmNoZXJkaW5nLCAKICAgICAgICAgICAgICAgZmVhdHVyZTEgPSAibkNvdW50X1JOQSIsIAogICAgICAgICAgICAgICBmZWF0dXJlMiA9ICJuRmVhdHVyZV9STkEiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJykKCmBgYAoKIyNGZWF0dXJlU2NhdHRlciBpcyB0eXBpY2FsbHkgdXNlZCB0byB2aXN1YWxpemUgZmVhdHVyZS1mZWF0dXJlIHJlbGF0aW9uc2hpcHMKIyNmb3IgYW55dGhpbmcgY2FsY3VsYXRlZCBieSB0aGUgb2JqZWN0LCAKIyNpLmUuIGNvbHVtbnMgaW4gb2JqZWN0IG1ldGFkYXRhLCBQQyBzY29yZXMgZXRjLgoKYGBge3IgRkMsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKRmVhdHVyZVNjYXR0ZXIoc3NfQm9yY2hlcmRpbmcsIAogICAgICAgICAgICAgICBmZWF0dXJlMSA9ICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgIGZlYXR1cmUyID0gInBlcmNlbnQubXQiKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKQoKRmVhdHVyZVNjYXR0ZXIoc3NfQm9yY2hlcmRpbmcsIAogICAgICAgICAgICAgICBmZWF0dXJlMSA9ICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgIGZlYXR1cmUyID0gIm5GZWF0dXJlX1JOQSIpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpCgpgYGAKIyA0LiBMb2ctbm9ybWFsaXphdGlvbiAoc2NhbGUgZmFjdG9yID0gMTAsMDAwKQpgYGB7ciBQQ0EsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKCnNzX0JvcmNoZXJkaW5nIDwtIE5vcm1hbGl6ZURhdGEoc3NfQm9yY2hlcmRpbmcsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIHNjYWxlLmZhY3RvciA9IDEwMDAwKQoKCgpgYGAKCgojIDUuIFZhcmlhYmxlIGZlYXR1cmVzICYgc2NhbGluZwpgYGB7ciAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKCnNzX0JvcmNoZXJkaW5nIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKHNzX0JvcmNoZXJkaW5nLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCnNzX0JvcmNoZXJkaW5nIDwtIFNjYWxlRGF0YShzc19Cb3JjaGVyZGluZywgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKHNzX0JvcmNoZXJkaW5nKSkKCgoKYGBgCgojIDYuIFBDQSArIFVNQVAKYGBge3IgLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgojIFBDQQpzc19Cb3JjaGVyZGluZyA8LSBSdW5QQ0Eoc3NfQm9yY2hlcmRpbmcsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhzc19Cb3JjaGVyZGluZykpCgojIEFmdGVyIFBDQSBhbmQgRmluZE5laWdoYm9ycwpzc19Cb3JjaGVyZGluZyA8LSBSdW5VTUFQKHNzX0JvcmNoZXJkaW5nLCBkaW1zID0gMToxMCkKCiMgT3B0aW9uYWw6IFZpc3VhbGl6ZSBlbGJvdyBwbG90CkVsYm93UGxvdChzc19Cb3JjaGVyZGluZywgbmRpbXMgPSAyMCkKCiMgUnVuIEphY2tTdHJhdyBhbmFseXNpcyBwcm9wZXJseQpzc19Cb3JjaGVyZGluZyA8LSBKYWNrU3RyYXcoc3NfQm9yY2hlcmRpbmcsIG51bS5yZXBsaWNhdGUgPSAxMDApCnNzX0JvcmNoZXJkaW5nIDwtIFNjb3JlSmFja1N0cmF3KHNzX0JvcmNoZXJkaW5nLCBkaW1zID0gMToyMCkKCiMgVmlzdWFsaXplIEphY2tTdHJhdyBzY29yZXMKSmFja1N0cmF3UGxvdChzc19Cb3JjaGVyZGluZywgZGltcyA9IDE6MjApCgpgYGAKCiMgNy4gUENBIFZpc3VhbGl6YXRpb24KYGBge3IgUENBLVRFU1QyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgoKIyBURVNULTEKIyBnaXZlbiB0aGF0IHRoZSBvdXRwdXQgb2YgUnVuUENBIGlzICJwY2EiCiMgcmVwbGFjZSAic28iIGJ5IHRoZSBuYW1lIG9mIHlvdXIgc2V1cmF0IG9iamVjdAoKcGN0IDwtIHNzX0JvcmNoZXJkaW5nW1sicGNhIl1dQHN0ZGV2IC8gc3VtKHNzX0JvcmNoZXJkaW5nW1sicGNhIl1dQHN0ZGV2KSAqIDEwMApjdW11IDwtIGN1bXN1bShwY3QpICMgQ2FsY3VsYXRlIGN1bXVsYXRpdmUgcGVyY2VudHMgZm9yIGVhY2ggUEMKIyBEZXRlcm1pbmUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB2YXJpYXRpb24gb2YgUEMgYW5kIHN1YnNlcXVlbnQgUEMKY28yIDwtIHNvcnQod2hpY2goKHBjdFstbGVuZ3RoKHBjdCldIC0gcGN0Wy0xXSkgPiAwLjEpLCBkZWNyZWFzaW5nID0gVClbMV0gKyAxCiMgbGFzdCBwb2ludCB3aGVyZSBjaGFuZ2Ugb2YgJSBvZiB2YXJpYXRpb24gaXMgbW9yZSB0aGFuIDAuMSUuIC0+IGNvMgpjbzIKCiMgVEVTVC0yCiMgZ2V0IHNpZ25pZmljYW50IFBDcwpzdGR2IDwtIHNzX0JvcmNoZXJkaW5nW1sicGNhIl1dQHN0ZGV2CnN1bS5zdGR2IDwtIHN1bShzc19Cb3JjaGVyZGluZ1tbInBjYSJdXUBzdGRldikKcGVyY2VudC5zdGR2IDwtIChzdGR2IC8gc3VtLnN0ZHYpICogMTAwCmN1bXVsYXRpdmUgPC0gY3Vtc3VtKHBlcmNlbnQuc3RkdikKY28xIDwtIHdoaWNoKGN1bXVsYXRpdmUgPiA5MCAmIHBlcmNlbnQuc3RkdiA8IDUpWzFdCmNvMiA8LSBzb3J0KHdoaWNoKChwZXJjZW50LnN0ZHZbMTpsZW5ndGgocGVyY2VudC5zdGR2KSAtIDFdIC0gCiAgICAgICAgICAgICAgICAgICAgICAgcGVyY2VudC5zdGR2WzI6bGVuZ3RoKHBlcmNlbnQuc3RkdildKSA+IDAuMSksIAogICAgICAgICAgICAgIGRlY3JlYXNpbmcgPSBUKVsxXSArIDEKbWluLnBjIDwtIG1pbihjbzEsIGNvMikKbWluLnBjCgojIENyZWF0ZSBhIGRhdGFmcmFtZSB3aXRoIHZhbHVlcwpwbG90X2RmIDwtIGRhdGEuZnJhbWUocGN0ID0gcGVyY2VudC5zdGR2LCAKICAgICAgICAgICBjdW11ID0gY3VtdWxhdGl2ZSwgCiAgICAgICAgICAgcmFuayA9IDE6bGVuZ3RoKHBlcmNlbnQuc3RkdikpCgojIEVsYm93IHBsb3QgdG8gdmlzdWFsaXplIAogIGdncGxvdChwbG90X2RmLCBhZXMoY3VtdWxhdGl2ZSwgcGVyY2VudC5zdGR2LCBsYWJlbCA9IHJhbmssIGNvbG9yID0gcmFuayA+IG1pbi5wYykpICsgCiAgZ2VvbV90ZXh0KCkgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSA5MCwgY29sb3IgPSAiZ3JleSIpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWluKHBlcmNlbnQuc3RkdltwZXJjZW50LnN0ZHYgPiA1XSksIGNvbG9yID0gImdyZXkiKSArCiAgdGhlbWVfYncoKQoKICAKCmBgYAoKIyA4LiBDbHVzdGVyaW5nIChyZXNvbHV0aW9uID0gMS4yKQpgYGB7ciAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKCnNzX0JvcmNoZXJkaW5nIDwtIEZpbmROZWlnaGJvcnMoc3NfQm9yY2hlcmRpbmcsIGRpbXMgPSAxOjEwKQpzc19Cb3JjaGVyZGluZyA8LSBGaW5kQ2x1c3RlcnMoc3NfQm9yY2hlcmRpbmcsIHJlc29sdXRpb24gPSAxLjIpCgoKYGBgCiMgOS4gVmlzdWFsaXplIFVNQVAgd2l0aCBDbHVzdGVycwpgYGB7ciAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKCkRpbVBsb3Qoc3NfQm9yY2hlcmRpbmcsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBUUlVFLCBwdC5zaXplID0gMC42KSArCiAgZ2d0aXRsZSgiVU1BUCBvZiBTw6l6YXJ5IFN5bmRyb21lIENENCsgVCBDZWxscyIpCgpgYGAKCiMgMTAuICBGZWF0dXJlUGxvdHMgZm9yIFRvcDUwIFVQCmBgYHtyICwgZmlnLmhlaWdodD0xNiwgZmlnLndpZHRoPTIwfQp0b3BfNTBfdXAgPC0gcmVhZC5jc3YoInRvcF81MF91cHJlZ3VsYXRlZC5jc3YiKSAgICAgICAgIyBvciByZWFkLmRlbGltKCJ0b3BfNTBfdXAudHN2IikKdG9wXzUwX2Rvd24gPC0gcmVhZC5jc3YoInRvcF81MF9kb3ducmVndWxhdGVkLmNzdiIpCgoKCkZlYXR1cmVQbG90KHNzX0JvcmNoZXJkaW5nLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX3VwJGdlbmVbMToxMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgoKRmVhdHVyZVBsb3Qoc3NfQm9yY2hlcmRpbmcsIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfdXAkZ2VuZVsxMToyMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgpGZWF0dXJlUGxvdChzc19Cb3JjaGVyZGluZywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF91cCRnZW5lWzIxOjMwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKRmVhdHVyZVBsb3Qoc3NfQm9yY2hlcmRpbmcsIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfdXAkZ2VuZVszMTo0MF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCkZlYXR1cmVQbG90KHNzX0JvcmNoZXJkaW5nLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX3VwJGdlbmVbNDE6NTBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQoKYGBgCgoKCiMgMTEuICBGZWF0dXJlUGxvdHMgZm9yIFRvcDUwIERPV04KYGBge3IgLCBmaWcuaGVpZ2h0PTE2LCBmaWcud2lkdGg9MjB9CgpGZWF0dXJlUGxvdChzc19Cb3JjaGVyZGluZywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF9kb3duJGdlbmVbMToxMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgoKRmVhdHVyZVBsb3Qoc3NfQm9yY2hlcmRpbmcsIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfZG93biRnZW5lWzExOjIwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKCkZlYXR1cmVQbG90KHNzX0JvcmNoZXJkaW5nLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX2Rvd24kZ2VuZVsyMTozMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCkZlYXR1cmVQbG90KHNzX0JvcmNoZXJkaW5nLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX2Rvd24kZ2VuZVszMTo0MF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCkZlYXR1cmVQbG90KHNzX0JvcmNoZXJkaW5nLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX2Rvd24kZ2VuZVs0MTo1MF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCmBgYAoKIyMgVmlzdWFsaXphdGlvbgpgYGB7ciAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKCkRpbVBsb3Qoc3NfQm9yY2hlcmRpbmcsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCwgcmVwZWwgPSBULCByZWR1Y3Rpb24gPSAidW1hcCIpCgoKYGBgCgojIyBWaXN1YWxpemF0aW9uIG9mIFBvdGVudGlhbCBiaW9tYXJrZXJzLVVwcmVndWxhdGVkCmBgYHtyICwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgoKIyBWZWN0b3Igb2YgZ2VuZXMgdG8gcGxvdAp1cF9nZW5lcyA8LSBjKCJDTElDMSIsICJDT1g1QSIsIkdUU0YxIiwgIk1BRDJMMSIsIk1ZQkwyIiwiTVlMNkIiLCJOTUUxIiwiUExLMSIsICJQWUNSMSIsICJTTEMyNUE1IiwgIlNSSSIsICJUVUJBMUMiLCAiVUJFMlQiLCAiWVdIQUgiKQoKIyBEb3RQbG90IHdpdGggY3VzdG9tIGZpcmVicmljay1yZWQgZ3JhZGllbnQKRG90UGxvdChzc19Cb3JjaGVyZGluZywgZmVhdHVyZXMgPSB1cF9nZW5lcykgKwogIFJvdGF0ZWRBeGlzKCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAibGlnaHR5ZWxsb3ciLCBtaWQgPSAicmVkIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDEpICsKICBnZ3RpdGxlKCJFeHByZXNzaW9uIG9mIFVwcmVndWxhdGVkIEdlbmVzIGluIFPDqXphcnkgU3luZHJvbWUiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KQogICkKCgoKYGBgCgoKCiMjIFZpc3VhbGl6YXRpb24gb2YgUG90ZW50aWFsIGJpb21hcmtlcnMtRG93bnJlZ3VsYXRlZApgYGB7ciBDMiwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgoKIyBEb3ducmVndWxhdGVkIGdlbmVzCmRvd25fZ2VuZXMgPC0gYygiVFhOSVAiLCAiUkFTQTMiLCAiUklQT1IyIiwgCiAgICAgICAgICAgICAgICAiWkZQMzYiLCAiWkZQMzZMMSIsICJaRlAzNkwyIiwKICAgICAgICAgICAgICAgICJQUk1UMiIsICJNQVgiLCAiUElLM0lQMSIsIAogICAgICAgICAgICAgICAgIkJURzEiLCAiQ0RLTjFCIikKCiMgRG90UGxvdCB3aXRoIGZpcmVicmljayBjb2xvciBmb3IgaGlnaCBleHByZXNzaW9uCkRvdFBsb3Qoc3NfQm9yY2hlcmRpbmcsIGZlYXR1cmVzID0gZG93bl9nZW5lcykgKwogIFJvdGF0ZWRBeGlzKCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAibGlnaHR5ZWxsb3ciLCBtaWQgPSAicmVkIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDEpICsKICBnZ3RpdGxlKCJFeHByZXNzaW9uIG9mIERvd25yZWd1bGF0ZWQgR2VuZXMgaW4gU8OpemFyeSBTeW5kcm9tZSIpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpCiAgKQoKCgpgYGAKCiMgU2F2ZSB0aGUgU2V1cmF0IG9iamVjdCBhcyBhbiBSRFMKYGBge3Igc2F2ZVJEU30KCgpzYXZlUkRTKHNzX0JvcmNoZXJkaW5nLCBmaWxlID0gImRhdGEvc3NfQm9yY2hlcmRpbmcucmRzIikKCgpgYGAKCgoK