3. Log-normalization (scale factor = 10,000) and Integration
# 1. Split Seurat object by sample
ss_list <- SplitObject(ss_Harro, split.by = "orig.ident")
# 2. Log-normalization + variable feature selection + cell cycle scoring
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)
})
Normalizing layer: counts.SS_P1.SeuratProject.SeuratProject.SeuratProject.SeuratProject.SeuratProject
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Finding variable features for layer counts.SS_P1.SeuratProject.SeuratProject.SeuratProject.SeuratProject.SeuratProject
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%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Avis : The `slot` argument of `GetAssayData()` is deprecated as of SeuratObject 5.0.0.
Please use the `layer` argument instead.Avis : The following features are not present in the object: MLF1IP, E2F8, not searching for symbol synonymsAvis : The following features are not present in the object: FAM64A, HN1, CDC25C, GAS2L3, not searching for symbol synonymsNormalizing layer: counts.SS_P2.SeuratProject.SeuratProject.SeuratProject.SeuratProject.SeuratProject
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Finding variable features for layer counts.SS_P2.SeuratProject.SeuratProject.SeuratProject.SeuratProject.SeuratProject
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%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Avis : The following features are not present in the object: MLF1IP, not searching for symbol synonymsAvis : The following features are not present in the object: FAM64A, HN1, GAS2L3, not searching for symbol synonymsNormalizing layer: counts.SS_P3.SeuratProject.SeuratProject.SeuratProject.SeuratProject
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Finding variable features for layer counts.SS_P3.SeuratProject.SeuratProject.SeuratProject.SeuratProject
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%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Avis : The following features are not present in the object: MLF1IP, not searching for symbol synonymsAvis : The following features are not present in the object: FAM64A, HN1, not searching for symbol synonymsNormalizing layer: counts.SS_P4.SeuratProject.SeuratProject.SeuratProject
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Finding variable features for layer counts.SS_P4.SeuratProject.SeuratProject.SeuratProject
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%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Avis : The following features are not present in the object: MLF1IP, not searching for symbol synonymsAvis : The following features are not present in the object: FAM64A, HN1, CDC25C, NEK2, GAS2L3, not searching for symbol synonymsNormalizing layer: counts.MF_P1.SeuratProject.SeuratProject
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Finding variable features for layer counts.MF_P1.SeuratProject.SeuratProject
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%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Avis : The following features are not present in the object: MLF1IP, not searching for symbol synonymsAvis : The following features are not present in the object: FAM64A, HN1, not searching for symbol synonymsNormalizing layer: counts.MF_P2.SeuratProject
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Finding variable features for layer counts.MF_P2.SeuratProject
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%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Avis : The following features are not present in the object: MLF1IP, not searching for symbol synonymsAvis : The following features are not present in the object: FAM64A, HN1, GAS2L3, not searching for symbol synonymsNormalizing layer: counts.MF_P3
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Finding variable features for layer counts.MF_P3
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%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Avis : The following features are not present in the object: MLF1IP, not searching for symbol synonymsAvis : The following features are not present in the object: FAM64A, HN1, not searching for symbol synonyms
# 3. Intersect genes across all objects to ensure consistency
common_genes <- Reduce(intersect, lapply(ss_list, rownames))
ss_list <- lapply(ss_list, function(x) {
x <- subset(x, features = common_genes)
return(x)
})
# 4. Remove TCR/Ig genes from variable features
tcr_genes <- grep("^TR[ABGD]|^IG[HKL]", common_genes, value = TRUE)
ss_list <- lapply(ss_list, function(x) {
vgs <- VariableFeatures(x)
vgs <- setdiff(vgs, tcr_genes)
VariableFeatures(x) <- vgs
return(x)
})
# 5. Run PCA on each object (required for RPCA)
ss_list <- lapply(ss_list, function(x) {
x <- ScaleData(x, features = VariableFeatures(x), verbose = FALSE)
x <- RunPCA(x, features = VariableFeatures(x), verbose = FALSE)
return(x)
})
# 6. Select integration features
features <- SelectIntegrationFeatures(object.list = ss_list, nfeatures = 8000)
# 7. Find integration anchors using RPCA
anchors <- FindIntegrationAnchors(
object.list = ss_list,
anchor.features = features,
reduction = "rpca",
dims = 1:40
)
Scaling features for provided objects
| | 0 % ~calculating
Avis : Different features in new layer data than already exists for scale.data
|++++++++ | 14% ~32s
Avis : Different features in new layer data than already exists for scale.data
|+++++++++++++++ | 29% ~21s
Avis : Different features in new layer data than already exists for scale.data
|++++++++++++++++++++++ | 43% ~22s
Avis : Different features in new layer data than already exists for scale.data
|+++++++++++++++++++++++++++++ | 57% ~14s
Avis : Different features in new layer data than already exists for scale.data
|++++++++++++++++++++++++++++++++++++ | 71% ~14s
Avis : Different features in new layer data than already exists for scale.data
|+++++++++++++++++++++++++++++++++++++++++++ | 86% ~07s
Avis : Different features in new layer data than already exists for scale.data
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=47s
Computing within dataset neighborhoods
| | 0 % ~calculating
|++++++++ | 14% ~43s
|+++++++++++++++ | 29% ~26s
|++++++++++++++++++++++ | 43% ~28s
|+++++++++++++++++++++++++++++ | 57% ~19s
|++++++++++++++++++++++++++++++++++++ | 71% ~19s
|+++++++++++++++++++++++++++++++++++++++++++ | 86% ~09s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01m 02s
Finding all pairwise anchors
| | 0 % ~calculating
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 884 anchors
|+++ | 5 % ~13m 19s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 1521 anchors
|+++++ | 10% ~15m 36s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 944 anchors
|++++++++ | 14% ~14m 48s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 1093 anchors
|++++++++++ | 19% ~13m 09s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 743 anchors
|++++++++++++ | 24% ~11m 20s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 1118 anchors
|+++++++++++++++ | 29% ~10m 43s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 984 anchors
|+++++++++++++++++ | 33% ~11m 53s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 735 anchors
|++++++++++++++++++++ | 38% ~12m 01s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 1102 anchors
|++++++++++++++++++++++ | 43% ~12m 24s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 898 anchors
|++++++++++++++++++++++++ | 48% ~11m 50s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 907 anchors
|+++++++++++++++++++++++++++ | 52% ~10m 44s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 707 anchors
|+++++++++++++++++++++++++++++ | 57% ~09m 28s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 906 anchors
|+++++++++++++++++++++++++++++++ | 62% ~08m 27s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 828 anchors
|++++++++++++++++++++++++++++++++++ | 67% ~07m 16s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 4606 anchors
|++++++++++++++++++++++++++++++++++++ | 71% ~06m 32s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 891 anchors
|+++++++++++++++++++++++++++++++++++++++ | 76% ~05m 22s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 566 anchors
|+++++++++++++++++++++++++++++++++++++++++ | 81% ~04m 11s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 773 anchors
|+++++++++++++++++++++++++++++++++++++++++++ | 86% ~03m 07s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 720 anchors
|++++++++++++++++++++++++++++++++++++++++++++++ | 90% ~02m 01s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 1315 anchors
|++++++++++++++++++++++++++++++++++++++++++++++++ | 95% ~01m 03s
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
Found 1375 anchors
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=21m 48s
# 8. Integrate data
ss_integrated <- IntegrateData(anchorset = anchors, dims = 1:40)
Merging dataset 6 into 5
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Avis : Layer counts isn't present in the assay object; returning NULLMerging dataset 4 into 3
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Avis : Layer counts isn't present in the assay object; returning NULLMerging dataset 2 into 1
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Avis : Layer counts isn't present in the assay object; returning NULLMerging dataset 7 into 5 6
Extracting anchors for merged samples
Finding integration vectors
Avis : Different cells in new layer data than already exists for scale.dataFinding integration vector weights
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Avis : Layer counts isn't present in the assay object; returning NULLMerging dataset 1 2 into 3 4
Extracting anchors for merged samples
Finding integration vectors
Avis : The `slot` argument of `SetAssayData()` is deprecated as of SeuratObject 5.0.0.
Please use the `layer` argument instead.Finding integration vector weights
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Avis : Layer counts isn't present in the assay object; returning NULLMerging dataset 3 4 1 2 into 5 6 7
Extracting anchors for merged samples
Finding integration vectors
9. 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 = "ss_Harro_SS_4_MF_3_Integrated_object_after_featureplot_final.rds")
LS0tCnRpdGxlOiAiUG90ZW50aWFsIGJpb21hcmtlcnMgVmFsaWRhdGlvbiAoSGFycm9fNF9TU19hbmRfM19NRl9QYXRpZW50X1NhbXBsZXMpLUludGVncmF0aW9uIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0RGF0YSkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoQXppbXV0aCkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShybWFya2Rvd24pCmxpYnJhcnkodGlueXRleCkKCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGRpdHRvU2VxKQpsaWJyYXJ5KGdncmVwZWwpCiNsaWJyYXJ5KGdndHJlZSkKbGlicmFyeShwYXJhbGxlbCkKbGlicmFyeShwbG90bHkpICAjIDNEIHBsb3QKbGlicmFyeShTZXVyYXQpICAjIElkZW50cygpCmxpYnJhcnkoU2V1cmF0RGlzaykgICMgU2F2ZUg1U2V1cmF0KCkKbGlicmFyeSh0aWJibGUpICAjIHJvd25uYW1lc190b19jb2x1bW4KbGlicmFyeShoYXJtb255KSAjIFJ1bkhhcm1vbnkoKQojb3B0aW9ucyhtYy5jb3JlcyA9IGRldGVjdENvcmVzKCkgLSAxKQoKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZGJwbHlyKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeShrbml0cikKbGlicmFyeSh0aW55dGV4KQojQXppbXV0aCBBbm5vdGF0aW9uIGxpYnJhcmllcwpsaWJyYXJ5KEF6aW11dGgpCiNQcm9qZWNUaWxzIEFubm90YXRpb24gbGlicmFyaWVzCmxpYnJhcnkoU1RBQ0FTKQpsaWJyYXJ5KFByb2plY1RJTHMpCiNzaW5nbGVSIEFubm90YXRpb24gbGlicmFyaWVzCgpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQoKYGBgCgoKIyAyLiBMb2FkIFFDIHNldXJhdCBPYmplY3QKYGBge3IgbG9hZFNldXJhdH0KCnNzX0hhcnJvIDwtIHJlYWRSRFMoInNzX0hhcnJvX1NTXzRfTUZfM19RQ19vYmplY3QucmRzIikKCmBgYAoKCiMgMy4gTG9nLW5vcm1hbGl6YXRpb24gKHNjYWxlIGZhY3RvciA9IDEwLDAwMCkgYW5kIEludGVncmF0aW9uCmBgYHtyIFBDQSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgoKIyAxLiBTcGxpdCBTZXVyYXQgb2JqZWN0IGJ5IHNhbXBsZQpzc19saXN0IDwtIFNwbGl0T2JqZWN0KHNzX0hhcnJvLCBzcGxpdC5ieSA9ICJvcmlnLmlkZW50IikKCiMgMi4gSW50ZXJzZWN0IGdlbmVzIGFjcm9zcyBhbGwgb2JqZWN0cyB0byBlbnN1cmUgY29uc2lzdGVuY3kKY29tbW9uX2dlbmVzIDwtIFJlZHVjZShpbnRlcnNlY3QsIGxhcHBseShzc19saXN0LCByb3duYW1lcykpCnNzX2xpc3QgPC0gbGFwcGx5KHNzX2xpc3QsIGZ1bmN0aW9uKHgpIHsKICB4IDwtIHN1YnNldCh4LCBmZWF0dXJlcyA9IGNvbW1vbl9nZW5lcykKICByZXR1cm4oeCkKfSkKCiMgMy4gTG9nLW5vcm1hbGl6YXRpb24gKyB2YXJpYWJsZSBmZWF0dXJlIHNlbGVjdGlvbiArIGNlbGwgY3ljbGUgc2NvcmluZwpzc19saXN0IDwtIGxhcHBseShzc19saXN0LCBmdW5jdGlvbih4KSB7CiAgeCA8LSBOb3JtYWxpemVEYXRhKHgsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIHNjYWxlLmZhY3RvciA9IDEwMDAwKQogIHggPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoeCwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSA1MDAwKQogIHggPC0gQ2VsbEN5Y2xlU2NvcmluZyh4LCBzLmZlYXR1cmVzID0gY2MuZ2VuZXMkcy5nZW5lcywgZzJtLmZlYXR1cmVzID0gY2MuZ2VuZXMkZzJtLmdlbmVzKQogIHJldHVybih4KQp9KQoKIyA0LiBSZW1vdmUgY2Fub25pY2FsIFRDUi9JZyBnZW5lcyBmcm9tIHZhcmlhYmxlIGZlYXR1cmVzIChzYWZlIGFuZCBzcGVjaWZpYyByZWdleCkKdGNyX2lnX2dlbmVzIDwtIGdyZXAoCiAgIl5UUkFbVkpEXXxeVFJCW1ZKRF18XlRSRFtWSkRdfF5UUkdbVkpEXXxeSUdIW1ZESl18XklHS1tWREpdfF5JR0xbVkRKXSIsCiAgY29tbW9uX2dlbmVzLAogIHZhbHVlID0gVFJVRQopCnNzX2xpc3QgPC0gbGFwcGx5KHNzX2xpc3QsIGZ1bmN0aW9uKHgpIHsKICB2Z3MgPC0gVmFyaWFibGVGZWF0dXJlcyh4KQogIHZncyA8LSBzZXRkaWZmKHZncywgdGNyX2lnX2dlbmVzKQogIFZhcmlhYmxlRmVhdHVyZXMoeCkgPC0gdmdzCiAgcmV0dXJuKHgpCn0pCgojIDUuIFJ1biBQQ0Egb24gZWFjaCBvYmplY3QgKHJlcXVpcmVkIGZvciBSUENBKQpzc19saXN0IDwtIGxhcHBseShzc19saXN0LCBmdW5jdGlvbih4KSB7CiAgeCA8LSBTY2FsZURhdGEoeCwgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKHgpLCB2ZXJib3NlID0gRkFMU0UpCiAgeCA8LSBSdW5QQ0EoeCwgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKHgpLCB2ZXJib3NlID0gRkFMU0UpCiAgcmV0dXJuKHgpCn0pCgojIDYuIFNlbGVjdCBpbnRlZ3JhdGlvbiBmZWF0dXJlcwpmZWF0dXJlcyA8LSBTZWxlY3RJbnRlZ3JhdGlvbkZlYXR1cmVzKG9iamVjdC5saXN0ID0gc3NfbGlzdCwgbmZlYXR1cmVzID0gODAwMCkKCiMgNy4gRmluZCBpbnRlZ3JhdGlvbiBhbmNob3JzIHVzaW5nIFJQQ0EKYW5jaG9ycyA8LSBGaW5kSW50ZWdyYXRpb25BbmNob3JzKAogIG9iamVjdC5saXN0ID0gc3NfbGlzdCwKICBhbmNob3IuZmVhdHVyZXMgPSBmZWF0dXJlcywKICByZWR1Y3Rpb24gPSAicnBjYSIsCiAgZGltcyA9IDE6NDAKKQoKIyA4LiBJbnRlZ3JhdGUgZGF0YQpzc19pbnRlZ3JhdGVkIDwtIEludGVncmF0ZURhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgZGltcyA9IDE6NDApCgojIDkuIFNldCB0aGUgZGVmYXVsdCBhc3NheSB0byAiaW50ZWdyYXRlZCIKRGVmYXVsdEFzc2F5KHNzX2ludGVncmF0ZWQpIDwtICJpbnRlZ3JhdGVkIgoKIyAxMC4gU2NhbGUgaW50ZWdyYXRlZCBkYXRhIGFuZCByZWdyZXNzIG91dCB1bndhbnRlZCB2YXJpYXRpb24Kc3NfaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEoCiAgc3NfaW50ZWdyYXRlZCwKICB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJuQ291bnRfUk5BIiwgInBlcmNlbnQubXQiLCAiUy5TY29yZSIsICJHMk0uU2NvcmUiKQopCgpgYGAKCgojIDQuIFBDQSArIFVNQVAKYGBge3IgRWxib3csIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKc3NfSGFycm8gPC0gc3NfaW50ZWdyYXRlZAoKIyBQQ0EKc3NfSGFycm8gPC0gUnVuUENBKHNzX0hhcnJvLCBucGNzID0gNTApCgojIE9wdGlvbmFsOiBWaXN1YWxpemUgZWxib3cgcGxvdApFbGJvd1Bsb3Qoc3NfSGFycm8sIG5kaW1zID0gNTApCgpgYGAKCiMgNS4gUENBIFZpc3VhbGl6YXRpb24KYGBge3IgUENBLVRFU1QsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKCgojIFRFU1QtMQojIGdpdmVuIHRoYXQgdGhlIG91dHB1dCBvZiBSdW5QQ0EgaXMgInBjYSIKIyByZXBsYWNlICJzbyIgYnkgdGhlIG5hbWUgb2YgeW91ciBzZXVyYXQgb2JqZWN0CgpwY3QgPC0gc3NfSGFycm9bWyJwY2EiXV1Ac3RkZXYgLyBzdW0oc3NfSGFycm9bWyJwY2EiXV1Ac3RkZXYpICogMTAwCmN1bXUgPC0gY3Vtc3VtKHBjdCkgIyBDYWxjdWxhdGUgY3VtdWxhdGl2ZSBwZXJjZW50cyBmb3IgZWFjaCBQQwojIERldGVybWluZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHZhcmlhdGlvbiBvZiBQQyBhbmQgc3Vic2VxdWVudCBQQwpjbzIgPC0gc29ydCh3aGljaCgocGN0Wy1sZW5ndGgocGN0KV0gLSBwY3RbLTFdKSA+IDAuMSksIGRlY3JlYXNpbmcgPSBUKVsxXSArIDEKIyBsYXN0IHBvaW50IHdoZXJlIGNoYW5nZSBvZiAlIG9mIHZhcmlhdGlvbiBpcyBtb3JlIHRoYW4gMC4xJS4gLT4gY28yCmNvMgoKIyBURVNULTIKIyBnZXQgc2lnbmlmaWNhbnQgUENzCnN0ZHYgPC0gc3NfSGFycm9bWyJwY2EiXV1Ac3RkZXYKc3VtLnN0ZHYgPC0gc3VtKHNzX0hhcnJvW1sicGNhIl1dQHN0ZGV2KQpwZXJjZW50LnN0ZHYgPC0gKHN0ZHYgLyBzdW0uc3RkdikgKiAxMDAKY3VtdWxhdGl2ZSA8LSBjdW1zdW0ocGVyY2VudC5zdGR2KQpjbzEgPC0gd2hpY2goY3VtdWxhdGl2ZSA+IDkwICYgcGVyY2VudC5zdGR2IDwgNSlbMV0KY28yIDwtIHNvcnQod2hpY2goKHBlcmNlbnQuc3RkdlsxOmxlbmd0aChwZXJjZW50LnN0ZHYpIC0gMV0gLSAKICAgICAgICAgICAgICAgICAgICAgICBwZXJjZW50LnN0ZHZbMjpsZW5ndGgocGVyY2VudC5zdGR2KV0pID4gMC4xKSwgCiAgICAgICAgICAgICAgZGVjcmVhc2luZyA9IFQpWzFdICsgMQptaW4ucGMgPC0gbWluKGNvMSwgY28yKQptaW4ucGMKCiMgQ3JlYXRlIGEgZGF0YWZyYW1lIHdpdGggdmFsdWVzCnBsb3RfZGYgPC0gZGF0YS5mcmFtZShwY3QgPSBwZXJjZW50LnN0ZHYsIAogICAgICAgICAgIGN1bXUgPSBjdW11bGF0aXZlLCAKICAgICAgICAgICByYW5rID0gMTpsZW5ndGgocGVyY2VudC5zdGR2KSkKCiMgRWxib3cgcGxvdCB0byB2aXN1YWxpemUgCiAgZ2dwbG90KHBsb3RfZGYsIGFlcyhjdW11bGF0aXZlLCBwZXJjZW50LnN0ZHYsIGxhYmVsID0gcmFuaywgY29sb3IgPSByYW5rID4gbWluLnBjKSkgKyAKICBnZW9tX3RleHQoKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDkwLCBjb2xvciA9ICJncmV5IikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtaW4ocGVyY2VudC5zdGR2W3BlcmNlbnQuc3RkdiA+IDVdKSwgY29sb3IgPSAiZ3JleSIpICsKICB0aGVtZV9idygpCgogIAoKYGBgCgojIDYuIENsdXN0ZXJpbmcgKHJlc29sdXRpb24gPSAxLjApCmBgYHtyIENsdXN0ZXJpbmcsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQojIFRoZW4gZmluZCBuZWlnaGJvcnMgJiBjbHVzdGVycwpzc19IYXJybyA8LSBGaW5kTmVpZ2hib3JzKHNzX0hhcnJvLCBkaW1zID0gMTo0MCkKc3NfSGFycm8gPC0gRmluZENsdXN0ZXJzKHNzX0hhcnJvLCByZXNvbHV0aW9uID0gMS4wKQoKIyBydW4gVU1BUApzc19IYXJybyA8LSBSdW5VTUFQKHNzX0hhcnJvLCBkaW1zID0gMTo0MCkKCnNzX0hhcnJvIDwtUnVuVFNORShzc19IYXJybywgZGltcy51c2UgPSAxOjQwKQoKYGBgCgoKIyA3LiBWaXN1YWxpemUgVU1BUCB3aXRoIENsdXN0ZXJzCmBgYHtyIFVNQVAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKRGltUGxvdChzc19IYXJybywgcmVkdWN0aW9uID0gInVtYXAiLGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiLCBsYWJlbCA9IFRSVUUscmVwZWwgPSBULCBwdC5zaXplID0gMC42KSArCiAgZ2d0aXRsZSgiVU1BUCBvZiBTw6l6YXJ5IFN5bmRyb21lIENENCsgVCBDZWxscyIpCgoKRGltUGxvdChzc19IYXJybywgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUscmVwZWwgPSBULCBwdC5zaXplID0gMC42KSArCiAgZ2d0aXRsZSgiVU1BUCBvZiBTw6l6YXJ5IFN5bmRyb21lIENENCsgVCBDZWxscyIpCgoKRGltUGxvdChzc19IYXJybywgcmVkdWN0aW9uID0gInRzbmUiLCBsYWJlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjYpICsKICBnZ3RpdGxlKCJUU05FIG9mIFPDqXphcnkgU3luZHJvbWUgQ0Q0KyBUIENlbGxzIikKCmBgYAoKIyMgU2F2ZSB0aGUgU2V1cmF0IG9iamVjdCBhcyBhbiBSRFMKYGBge3Igc2F2ZTF9CgoKc2F2ZVJEUyhzc19IYXJybywgZmlsZSA9ICJzc19IYXJyb19TU180X01GXzNfSW50ZWdyYXRlZF9vYmplY3RfYmVmb3JlX2ZlYXR1cmVwbG90LnJkcyIpCgoKYGBgCgoKCiMgOC4gIEZlYXR1cmVQbG90cyBmb3IgVG9wNTAgVVAKYGBge3IgRmVhdHVyZVBsb3QxLCBmaWcuaGVpZ2h0PTE2LCBmaWcud2lkdGg9MjB9CnRvcF81MF91cCA8LSByZWFkLmNzdigidG9wXzUwX3VwcmVndWxhdGVkLmNzdiIpICAgICAgICAjIG9yIHJlYWQuZGVsaW0oInRvcF81MF91cC50c3YiKQp0b3BfNTBfZG93biA8LSByZWFkLmNzdigidG9wXzUwX2Rvd25yZWd1bGF0ZWQuY3N2IikKCgoKSWRlbnRzKHNzX0hhcnJvKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgoKCkZlYXR1cmVQbG90KHNzX0hhcnJvLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX3VwJGdlbmVbMToxMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgoKRmVhdHVyZVBsb3Qoc3NfSGFycm8sIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfdXAkZ2VuZVsxMToyMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgpGZWF0dXJlUGxvdChzc19IYXJybywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF91cCRnZW5lWzIxOjMwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKRmVhdHVyZVBsb3Qoc3NfSGFycm8sIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfdXAkZ2VuZVszMTo0MF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCkZlYXR1cmVQbG90KHNzX0hhcnJvLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX3VwJGdlbmVbNDE6NTBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQoKYGBgCgoKCiMgOS4gIEZlYXR1cmVQbG90cyBmb3IgVG9wNTAgRE9XTgpgYGB7ciBGZWF0dXJlUGxvdDIsIGZpZy5oZWlnaHQ9MTYsIGZpZy53aWR0aD0yMH0KCkZlYXR1cmVQbG90KHNzX0hhcnJvLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzUwX2Rvd24kZ2VuZVsxOjEwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKCgpGZWF0dXJlUGxvdChzc19IYXJybywgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF81MF9kb3duJGdlbmVbMTE6MjBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQoKRmVhdHVyZVBsb3Qoc3NfSGFycm8sIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfZG93biRnZW5lWzIxOjMwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKRmVhdHVyZVBsb3Qoc3NfSGFycm8sIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfZG93biRnZW5lWzMxOjQwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKRmVhdHVyZVBsb3Qoc3NfSGFycm8sIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfNTBfZG93biRnZW5lWzQxOjUwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKYGBgCgojIyBWaXN1YWxpemF0aW9uCmBgYHtyIHVtYXB2aXMsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKCkRpbVBsb3Qoc3NfSGFycm8sIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCwgcmVwZWwgPSBULCByZWR1Y3Rpb24gPSAidW1hcCIpCgoKYGBgCgojIyBWaXN1YWxpemF0aW9uIG9mIFBvdGVudGlhbCBiaW9tYXJrZXJzLVVwcmVndWxhdGVkCmBgYHtyIGJpb21hcmtlcnN2aXMsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKRGVmYXVsdEFzc2F5KHNzX0hhcnJvKSA8LSAiUk5BIgpJZGVudHMoc3NfSGFycm8pIDwtICJEaXNlYXNlX3N0YXRlIgoKIyBWZWN0b3Igb2YgZ2VuZXMgdG8gcGxvdAp1cF9nZW5lcyA8LSBjKCJDTElDMSIsICJDT1g1QSIsIkdUU0YxIiwgIk1BRDJMMSIsIk1ZQkwyIiwiTVlMNkIiLCJOTUUxIiwiUExLMSIsICJQWUNSMSIsICJTTEMyNUE1IiwgIlNSSSIsICJUVUJBMUMiLCAiVUJFMlQiLCAiWVdIQUgiKQoKIyBEb3RQbG90IHdpdGggY3VzdG9tIGZpcmVicmljay1yZWQgZ3JhZGllbnQKRG90UGxvdChzc19IYXJybywgZmVhdHVyZXMgPSB1cF9nZW5lcykgKwogIFJvdGF0ZWRBeGlzKCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAibGlnaHR5ZWxsb3ciLCBtaWQgPSAicmVkIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDEpICsKICBnZ3RpdGxlKCJFeHByZXNzaW9uIG9mIFVwcmVndWxhdGVkIEdlbmVzIGluIFPDqXphcnkgU3luZHJvbWUiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KQogICkKCklkZW50cyhzc19IYXJybykgPC0gIm9yaWcuaWRlbnQiCgojIFZlY3RvciBvZiBnZW5lcyB0byBwbG90CnVwX2dlbmVzIDwtIGMoIkNMSUMxIiwgIkNPWDVBIiwiR1RTRjEiLCAiTUFEMkwxIiwiTVlCTDIiLCJNWUw2QiIsIk5NRTEiLCJQTEsxIiwgIlBZQ1IxIiwgIlNMQzI1QTUiLCAiU1JJIiwgIlRVQkExQyIsICJVQkUyVCIsICJZV0hBSCIpCgojIERvdFBsb3Qgd2l0aCBjdXN0b20gZmlyZWJyaWNrLXJlZCBncmFkaWVudApEb3RQbG90KHNzX0hhcnJvLCBmZWF0dXJlcyA9IHVwX2dlbmVzKSArCiAgUm90YXRlZEF4aXMoKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJsaWdodHllbGxvdyIsIG1pZCA9ICJyZWQiLCBoaWdoID0gImZpcmVicmljayIsIG1pZHBvaW50ID0gMSkgKwogIGdndGl0bGUoIkV4cHJlc3Npb24gb2YgVXByZWd1bGF0ZWQgR2VuZXMgaW4gU8OpemFyeSBTeW5kcm9tZSIpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpCiAgKQoKSWRlbnRzKHNzX0hhcnJvKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgoKIyBWZWN0b3Igb2YgZ2VuZXMgdG8gcGxvdAp1cF9nZW5lcyA8LSBjKCJDTElDMSIsICJDT1g1QSIsIkdUU0YxIiwgIk1BRDJMMSIsIk1ZQkwyIiwiTVlMNkIiLCJOTUUxIiwiUExLMSIsICJQWUNSMSIsICJTTEMyNUE1IiwgIlNSSSIsICJUVUJBMUMiLCAiVUJFMlQiLCAiWVdIQUgiKQoKIyBEb3RQbG90IHdpdGggY3VzdG9tIGZpcmVicmljay1yZWQgZ3JhZGllbnQKRG90UGxvdChzc19IYXJybywgZmVhdHVyZXMgPSB1cF9nZW5lcykgKwogIFJvdGF0ZWRBeGlzKCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAibGlnaHR5ZWxsb3ciLCBtaWQgPSAicmVkIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDEpICsKICBnZ3RpdGxlKCJFeHByZXNzaW9uIG9mIFVwcmVndWxhdGVkIEdlbmVzIGluIFPDqXphcnkgU3luZHJvbWUiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KQogICkKCgpgYGAKCgoKIyMgVmlzdWFsaXphdGlvbiBvZiBQb3RlbnRpYWwgYmlvbWFya2Vycy1Eb3ducmVndWxhdGVkCmBgYHtyIHZpczIsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKSWRlbnRzKHNzX0hhcnJvKSA8LSAiRGlzZWFzZV9zdGF0ZSIKIyBEb3ducmVndWxhdGVkIGdlbmVzCmRvd25fZ2VuZXMgPC0gYygiVFhOSVAiLCAiUkFTQTMiLCAiUklQT1IyIiwgCiAgICAgICAgICAgICAgICAiWkZQMzYiLCAiWkZQMzZMMSIsICJaRlAzNkwyIiwKICAgICAgICAgICAgICAgICJQUk1UMiIsICJNQVgiLCAiUElLM0lQMSIsIAogICAgICAgICAgICAgICAgIkJURzEiLCAiQ0RLTjFCIikKCiMgRG90UGxvdCB3aXRoIGZpcmVicmljayBjb2xvciBmb3IgaGlnaCBleHByZXNzaW9uCkRvdFBsb3Qoc3NfSGFycm8sIGZlYXR1cmVzID0gZG93bl9nZW5lcykgKwogIFJvdGF0ZWRBeGlzKCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAibGlnaHR5ZWxsb3ciLCBtaWQgPSAicmVkIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBtaWRwb2ludCA9IDEpICsKICBnZ3RpdGxlKCJFeHByZXNzaW9uIG9mIERvd25yZWd1bGF0ZWQgR2VuZXMgaW4gU8OpemFyeSBTeW5kcm9tZSIpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpCiAgKQoKCklkZW50cyhzc19IYXJybykgPC0gIm9yaWcuaWRlbnQiCiMgRG93bnJlZ3VsYXRlZCBnZW5lcwpkb3duX2dlbmVzIDwtIGMoIlRYTklQIiwgIlJBU0EzIiwgIlJJUE9SMiIsIAogICAgICAgICAgICAgICAgIlpGUDM2IiwgIlpGUDM2TDEiLCAiWkZQMzZMMiIsCiAgICAgICAgICAgICAgICAiUFJNVDIiLCAiTUFYIiwgIlBJSzNJUDEiLCAKICAgICAgICAgICAgICAgICJCVEcxIiwgIkNES04xQiIpCgojIERvdFBsb3Qgd2l0aCBmaXJlYnJpY2sgY29sb3IgZm9yIGhpZ2ggZXhwcmVzc2lvbgpEb3RQbG90KHNzX0hhcnJvLCBmZWF0dXJlcyA9IGRvd25fZ2VuZXMpICsKICBSb3RhdGVkQXhpcygpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudDIobG93ID0gImxpZ2h0eWVsbG93IiwgbWlkID0gInJlZCIsIGhpZ2ggPSAiZmlyZWJyaWNrIiwgbWlkcG9pbnQgPSAxKSArCiAgZ2d0aXRsZSgiRXhwcmVzc2lvbiBvZiBEb3ducmVndWxhdGVkIEdlbmVzIGluIFPDqXphcnkgU3luZHJvbWUiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KQogICkKSWRlbnRzKHNzX0hhcnJvKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgoKIyBEb3RQbG90IHdpdGggZmlyZWJyaWNrIGNvbG9yIGZvciBoaWdoIGV4cHJlc3Npb24KRG90UGxvdChzc19IYXJybywgZmVhdHVyZXMgPSBkb3duX2dlbmVzKSArCiAgUm90YXRlZEF4aXMoKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJsaWdodHllbGxvdyIsIG1pZCA9ICJyZWQiLCBoaWdoID0gImZpcmVicmljayIsIG1pZHBvaW50ID0gMSkgKwogIGdndGl0bGUoIkV4cHJlc3Npb24gb2YgRG93bnJlZ3VsYXRlZCBHZW5lcyBpbiBTw6l6YXJ5IFN5bmRyb21lIikgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gMTIpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCkKICApCmBgYAoKIyMgU2F2ZSB0aGUgU2V1cmF0IG9iamVjdCBhcyBhbiBSRFMKYGBge3Igc2F2ZVJEU0ZpbmFsfQoKCnNhdmVSRFMoc3NfSGFycm8sIGZpbGUgPSAic3NfSGFycm9fU1NfNF9NRl8zX0ludGVncmF0ZWRfb2JqZWN0X2FmdGVyX2ZlYXR1cmVwbG90X2ZpbmFsLnJkcyIpCgoKYGBgCgo=