1. load libraries
2. Load Seurat Object
#Load Seurat Object merged from cell lines and a control(PBMC) after filtration
load("0-imp_Robj/SS_CD4_Tcells_Azimuth_Annotated_PBMC10x_excluding_nonCD4_cells_from_Control_Bcells_from_L4_and_ILC_NK_just_oneCell_CD14Mono.robj")
All_samples_Merged <- filtered_seurat
Summarizing Seurat Object
# Load necessary libraries
library(Seurat)
# Display basic metadata summary
head(All_samples_Merged@meta.data)
# Check if columns such as `orig.ident`, `nCount_RNA`, `nFeature_RNA`, `nUMI`, `ngene`, and any other necessary columns exist
required_columns <- c("orig.ident", "nCount_RNA", "nFeature_RNA", "nUMI", "ngene")
missing_columns <- setdiff(required_columns, colnames(All_samples_Merged@meta.data))
if (length(missing_columns) > 0) {
cat("Missing columns:", paste(missing_columns, collapse = ", "), "\n")
} else {
cat("All required columns are present.\n")
}
# Check cell counts and features
cat("Number of cells:", ncol(All_samples_Merged), "\n")
cat("Number of features:", nrow(All_samples_Merged), "\n")
# Verify that each `orig.ident` label has the correct number of cells
cat("Cell counts per group:\n")
print(table(All_samples_Merged$orig.ident))
# Check that the cell IDs are unique (which ensures no issues from merging)
if (any(duplicated(colnames(All_samples_Merged)))) {
cat("Warning: There are duplicated cell IDs.\n")
} else {
cat("Cell IDs are unique.\n")
}
# Check the assay consistency for RNA
DefaultAssay(All_samples_Merged) <- "RNA"
# Check dimensions of the RNA counts layer using the new method
cat("Dimensions of the RNA counts layer:", dim(GetAssayData(All_samples_Merged, layer = "counts")), "\n")
cat("Dimensions of the RNA data layer:", dim(GetAssayData(All_samples_Merged, layer = "data")), "\n")
# Check the ADT assay (optional)
if ("ADT" %in% names(All_samples_Merged@assays)) {
cat("ADT assay is present.\n")
cat("Dimensions of the ADT counts layer:", dim(GetAssayData(All_samples_Merged, assay = "ADT", layer = "counts")), "\n")
} else {
cat("ADT assay is not present.\n")
}
Azimuth Annotation
# InstallData("pbmcref")
#
# # The RunAzimuth function can take a Seurat object as input
# All_samples_Merged <- RunAzimuth(All_samples_Merged, reference = "pbmcref")
3. QC
# Remove the percent.mito column
All_samples_Merged$percent.mito <- NULL
# Set identity classes to an existing column in meta data
Idents(object = All_samples_Merged) <- "cell_line"
All_samples_Merged[["percent.rb"]] <- PercentageFeatureSet(All_samples_Merged,
pattern = "^RP[SL]")
# Convert 'percent.mt' to numeric, replacing "NaN" with 0
All_samples_Merged$percent.rb <- replace(as.numeric(All_samples_Merged$percent.rb), is.na(All_samples_Merged$percent.rb), 0)
# The [[ operator can add columns to object metadata. This is a great place to stash QC stats
All_samples_Merged[["percent.mt"]] <- PercentageFeatureSet(All_samples_Merged, pattern = "^MT-")
# Convert 'percent.mt' to numeric, replacing "NaN" with 0
All_samples_Merged$percent.mt <- replace(as.numeric(All_samples_Merged$percent.mt), is.na(All_samples_Merged$percent.mt), 0)
VlnPlot(All_samples_Merged, features = c("nFeature_RNA",
"nCount_RNA",
"percent.mt",
"percent.rb"),
ncol = 4, pt.size = 0.1) &
theme(plot.title = element_text(size=10))
FeatureScatter(All_samples_Merged, feature1 = "percent.mt",
feature2 = "percent.rb")
VlnPlot(All_samples_Merged, features = c("nFeature_RNA",
"nCount_RNA",
"percent.mt"),
ncol = 3)
FeatureScatter(All_samples_Merged,
feature1 = "percent.mt",
feature2 = "percent.rb") +
geom_smooth(method = 'lm')
FeatureScatter(All_samples_Merged,
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(All_samples_Merged,
feature1 = "nCount_RNA",
feature2 = "percent.mt")+
geom_smooth(method = 'lm')
FeatureScatter(All_samples_Merged,
feature1 = "nCount_RNA",
feature2 = "nFeature_RNA")+
geom_smooth(method = 'lm')
Assign Cell-Cycle Scores
4. Normalize data
# Apply SCTransform
All_samples_Merged <- SCTransform(All_samples_Merged,
vars.to.regress = c("percent.rb","percent.mt", "CC.Difference"),
do.scale=TRUE,
do.center=TRUE,
verbose = TRUE)
7. Clustering
# Set the seed for clustering steps
set.seed(123)
All_samples_Merged <- FindNeighbors(All_samples_Merged,
dims = 1:16,
verbose = FALSE)
# understanding resolution
All_samples_Merged <- FindClusters(All_samples_Merged,
resolution = c(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7,0.8, 0.9, 1,1.2,1.5,2))
UMAP Visualization
# Set the seed for clustering steps
set.seed(123)
# non-linear dimensionality reduction --------------
All_samples_Merged <- RunUMAP(All_samples_Merged,
dims = 1:16,
verbose = FALSE)
# note that you can set `label = TRUE` or use the Label Clusters function to help label
# individual clusters
DimPlot(All_samples_Merged,group.by = "cell_line",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,group.by = "predicted.celltype.l2",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.1",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.2",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.3",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.4",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.5",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.6",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.7",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.8",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.0.9",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.1",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.1.2",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.1.5",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged,
group.by = "SCT_snn_res.2",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
# Set identity classes to an existing column in meta data
Idents(object = All_samples_Merged) <- "SCT_snn_res.0.9"
cluster_table <- table(Idents(All_samples_Merged))
barplot(cluster_table, main = "Number of Cells in Each Cluster",
xlab = "Cluster",
ylab = "Number of Cells",
col = rainbow(length(cluster_table)))
print(cluster_table)
table(All_samples_Merged$predicted.celltype.l2, All_samples_Merged$SCT_snn_res.0.1)
8. clusTree
clustree(All_samples_Merged, prefix = "SCT_snn_res.")
9. Azimuth Annotation
# InstallData("pbmcref")
#
# # The RunAzimuth function can take a Seurat object as input
# All_samples_Merged <- RunAzimuth(All_samples_Merged, reference = "pbmcref")
10. Azimuth Visualization
DimPlot(All_samples_Merged, group.by = "predicted.celltype.l1",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged, group.by = "predicted.celltype.l1",
reduction = "umap",
label.size = 3,
repel = T,
label = F)
DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2",
reduction = "umap",
label.size = 3,
repel = T,
label = F)
DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2",
reduction = "umap",
label.size = 3,
repel = T,
label = T, label.box = T)
table(All_samples_Merged$predicted.celltype.l2, All_samples_Merged$SCT_snn_res.0.2)
Save the Seurat object as an Robj file
save(All_samples_Merged, file = "0-imp_Robj/All_Samples_Merged_with_10x_Azitmuth_Annotated_SCT_HPC_without_harmony_integration_removed_nonCD4cells_from_control_and_Bcells_from_L4_ILC_NK_CD14Mono_no_nCount_nFeatureRegress_ready_for_Harmony_final.robj")
11. Harmony Integration
# Load required libraries
library(Seurat)
library(harmony)
library(ggplot2)
# Run Harmony, adjusting for batch effect using "cell_line" or another grouping variable
All_samples_Merged <- RunHarmony(
All_samples_Merged,
group.by.vars = "cell_line", # Replace with the metadata column specifying batch or cell line
assay.use="SCT")
# Check results in harmony embeddings
harmony_embeddings <- Embeddings(All_samples_Merged, reduction = "harmony")
head(harmony_embeddings)
# Set the seed for clustering steps
set.seed(123)
# Run UMAP on Harmony embeddings
All_samples_Merged <- RunUMAP(All_samples_Merged, reduction = "harmony", dims = 1:16)
# Set the seed for clustering steps
set.seed(123)
# Optionally, find neighbors and clusters (if you plan to do clustering analysis)
All_samples_Merged <- FindNeighbors(All_samples_Merged, reduction = "harmony", dims = 1:16)
All_samples_Merged <- FindClusters(All_samples_Merged, resolution = 0.5) # Adjust resolution as needed
# Visualize UMAP
DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line", label = TRUE, pt.size = 0.5) +
ggtitle("UMAP of Harmony-Integrated Data")
# Visualize UMAP with batch/cell line information
DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line", label = TRUE, pt.size = 0.5) +
ggtitle("UMAP - Colored by Cell Line (After Harmony Integration)")
# Visualize UMAP with clusters
DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters", label = TRUE, pt.size = 0.5) +
ggtitle("UMAP - Clustered Data (After Harmony Integration)")
# Visualize specific cell types or other metadata
DimPlot(All_samples_Merged, reduction = "umap", group.by = "predicted.celltype.l2", label = TRUE, pt.size = 0.5) +
ggtitle("UMAP - Cell Types After Harmony Integration")
12.Save the Seurat object as an Robj file
#save(All_samples_Merged, file = "../../../0-IMP-OBJECTS/All_Samples_Merged_with_10x_Azitmuth_Annotated_SCT_HPC_without_harmony_integration.robj")
LS0tCnRpdGxlOiAiTWVyZ2VkIEFsbCBzYW1wbGVzIHdpdGggUEJNQ18xMHggYW5kIHJlbW92ZWQgbm9uIENENCBUIGNlbGxzIGZyb20gQ29udHJvbCBhbmQgQiBjZWxscyBmcm9tIEw0IGFuZCBJTEMsIE5LLCBDRDE0IE1vbm8gZGlkbnQgcmVncmVzcyBuQ291bnQgYW5kIG5GZWF0dXJlIGFuZCBhcHBseSBTQ1QiCmF1dGhvcjogTmFzaXIgTWFobW9vZCBBYmJhc2kKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgZWNobz1GQUxTRX0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGRicGx5cikKbGlicmFyeShybWFya2Rvd24pCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkodGlueXRleCkKI0F6aW11dGggQW5ub3RhdGlvbiBsaWJyYXJpZXMKbGlicmFyeShBemltdXRoKQoKbGlicmFyeShjbHVzdHJlZSkKCgpgYGAKCgojIDIuIExvYWQgU2V1cmF0IE9iamVjdCAKYGBge3IgbG9hZF9zZXVyYXR9CgojTG9hZCBTZXVyYXQgT2JqZWN0IG1lcmdlZCBmcm9tIGNlbGwgbGluZXMgYW5kIGEgY29udHJvbChQQk1DKSBhZnRlciBmaWx0cmF0aW9uCmxvYWQoIjAtaW1wX1JvYmovU1NfQ0Q0X1RjZWxsc19BemltdXRoX0Fubm90YXRlZF9QQk1DMTB4X2V4Y2x1ZGluZ19ub25DRDRfY2VsbHNfZnJvbV9Db250cm9sX0JjZWxsc19mcm9tX0w0X2FuZF9JTENfTktfanVzdF9vbmVDZWxsX0NEMTRNb25vLnJvYmoiKQoKQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIGZpbHRlcmVkX3NldXJhdAogCmBgYAoKIyMgU3VtbWFyaXppbmcgU2V1cmF0IE9iamVjdApgYGB7ciBzdW1tYXJ5LCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzCmxpYnJhcnkoU2V1cmF0KQoKIyBEaXNwbGF5IGJhc2ljIG1ldGFkYXRhIHN1bW1hcnkKaGVhZChBbGxfc2FtcGxlc19NZXJnZWRAbWV0YS5kYXRhKQoKIyBDaGVjayBpZiBjb2x1bW5zIHN1Y2ggYXMgYG9yaWcuaWRlbnRgLCBgbkNvdW50X1JOQWAsIGBuRmVhdHVyZV9STkFgLCBgblVNSWAsIGBuZ2VuZWAsIGFuZCBhbnkgb3RoZXIgbmVjZXNzYXJ5IGNvbHVtbnMgZXhpc3QKcmVxdWlyZWRfY29sdW1ucyA8LSBjKCJvcmlnLmlkZW50IiwgIm5Db3VudF9STkEiLCAibkZlYXR1cmVfUk5BIiwgIm5VTUkiLCAibmdlbmUiKQptaXNzaW5nX2NvbHVtbnMgPC0gc2V0ZGlmZihyZXF1aXJlZF9jb2x1bW5zLCBjb2xuYW1lcyhBbGxfc2FtcGxlc19NZXJnZWRAbWV0YS5kYXRhKSkKCmlmIChsZW5ndGgobWlzc2luZ19jb2x1bW5zKSA+IDApIHsKICAgIGNhdCgiTWlzc2luZyBjb2x1bW5zOiIsIHBhc3RlKG1pc3NpbmdfY29sdW1ucywgY29sbGFwc2UgPSAiLCAiKSwgIlxuIikKfSBlbHNlIHsKICAgIGNhdCgiQWxsIHJlcXVpcmVkIGNvbHVtbnMgYXJlIHByZXNlbnQuXG4iKQp9CgojIENoZWNrIGNlbGwgY291bnRzIGFuZCBmZWF0dXJlcwpjYXQoIk51bWJlciBvZiBjZWxsczoiLCBuY29sKEFsbF9zYW1wbGVzX01lcmdlZCksICJcbiIpCmNhdCgiTnVtYmVyIG9mIGZlYXR1cmVzOiIsIG5yb3coQWxsX3NhbXBsZXNfTWVyZ2VkKSwgIlxuIikKCiMgVmVyaWZ5IHRoYXQgZWFjaCBgb3JpZy5pZGVudGAgbGFiZWwgaGFzIHRoZSBjb3JyZWN0IG51bWJlciBvZiBjZWxscwpjYXQoIkNlbGwgY291bnRzIHBlciBncm91cDpcbiIpCnByaW50KHRhYmxlKEFsbF9zYW1wbGVzX01lcmdlZCRvcmlnLmlkZW50KSkKCiMgQ2hlY2sgdGhhdCB0aGUgY2VsbCBJRHMgYXJlIHVuaXF1ZSAod2hpY2ggZW5zdXJlcyBubyBpc3N1ZXMgZnJvbSBtZXJnaW5nKQppZiAoYW55KGR1cGxpY2F0ZWQoY29sbmFtZXMoQWxsX3NhbXBsZXNfTWVyZ2VkKSkpKSB7CiAgICBjYXQoIldhcm5pbmc6IFRoZXJlIGFyZSBkdXBsaWNhdGVkIGNlbGwgSURzLlxuIikKfSBlbHNlIHsKICAgIGNhdCgiQ2VsbCBJRHMgYXJlIHVuaXF1ZS5cbiIpCn0KCiMgQ2hlY2sgdGhlIGFzc2F5IGNvbnNpc3RlbmN5IGZvciBSTkEKRGVmYXVsdEFzc2F5KEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlJOQSIKCiMgQ2hlY2sgZGltZW5zaW9ucyBvZiB0aGUgUk5BIGNvdW50cyBsYXllciB1c2luZyB0aGUgbmV3IG1ldGhvZApjYXQoIkRpbWVuc2lvbnMgb2YgdGhlIFJOQSBjb3VudHMgbGF5ZXI6IiwgZGltKEdldEFzc2F5RGF0YShBbGxfc2FtcGxlc19NZXJnZWQsIGxheWVyID0gImNvdW50cyIpKSwgIlxuIikKY2F0KCJEaW1lbnNpb25zIG9mIHRoZSBSTkEgZGF0YSBsYXllcjoiLCBkaW0oR2V0QXNzYXlEYXRhKEFsbF9zYW1wbGVzX01lcmdlZCwgbGF5ZXIgPSAiZGF0YSIpKSwgIlxuIikKCiMgQ2hlY2sgdGhlIEFEVCBhc3NheSAob3B0aW9uYWwpCmlmICgiQURUIiAlaW4lIG5hbWVzKEFsbF9zYW1wbGVzX01lcmdlZEBhc3NheXMpKSB7CiAgICBjYXQoIkFEVCBhc3NheSBpcyBwcmVzZW50LlxuIikKICAgIGNhdCgiRGltZW5zaW9ucyBvZiB0aGUgQURUIGNvdW50cyBsYXllcjoiLCBkaW0oR2V0QXNzYXlEYXRhKEFsbF9zYW1wbGVzX01lcmdlZCwgYXNzYXkgPSAiQURUIiwgbGF5ZXIgPSAiY291bnRzIikpLCAiXG4iKQp9IGVsc2UgewogICAgY2F0KCJBRFQgYXNzYXkgaXMgbm90IHByZXNlbnQuXG4iKQp9CgoKYGBgCgojIyBBemltdXRoIEFubm90YXRpb24KYGBge3IgYXppbXV0aF9Bbm5vdGF0aW9uMSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CiMgSW5zdGFsbERhdGEoInBibWNyZWYiKQojIAojICMgVGhlIFJ1bkF6aW11dGggZnVuY3Rpb24gY2FuIHRha2UgYSBTZXVyYXQgb2JqZWN0IGFzIGlucHV0CiMgQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIFJ1bkF6aW11dGgoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWZlcmVuY2UgPSAicGJtY3JlZiIpCgpgYGAKCiMgMy4gUUMKYGBge3IgUUMsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKIyBSZW1vdmUgdGhlIHBlcmNlbnQubWl0byBjb2x1bW4KQWxsX3NhbXBsZXNfTWVyZ2VkJHBlcmNlbnQubWl0byA8LSBOVUxMCgoKIyBTZXQgaWRlbnRpdHkgY2xhc3NlcyB0byBhbiBleGlzdGluZyBjb2x1bW4gaW4gbWV0YSBkYXRhCklkZW50cyhvYmplY3QgPSBBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJjZWxsX2xpbmUiCgpBbGxfc2FtcGxlc19NZXJnZWRbWyJwZXJjZW50LnJiIl1dIDwtIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJeUlBbU0xdIikKIyBDb252ZXJ0ICdwZXJjZW50Lm10JyB0byBudW1lcmljLCByZXBsYWNpbmcgIk5hTiIgd2l0aCAwCkFsbF9zYW1wbGVzX01lcmdlZCRwZXJjZW50LnJiIDwtIHJlcGxhY2UoYXMubnVtZXJpYyhBbGxfc2FtcGxlc19NZXJnZWQkcGVyY2VudC5yYiksIGlzLm5hKEFsbF9zYW1wbGVzX01lcmdlZCRwZXJjZW50LnJiKSwgMCkKCgoKIyBUaGUgW1sgb3BlcmF0b3IgY2FuIGFkZCBjb2x1bW5zIHRvIG9iamVjdCBtZXRhZGF0YS4gVGhpcyBpcyBhIGdyZWF0IHBsYWNlIHRvIHN0YXNoIFFDIHN0YXRzCkFsbF9zYW1wbGVzX01lcmdlZFtbInBlcmNlbnQubXQiXV0gPC0gUGVyY2VudGFnZUZlYXR1cmVTZXQoQWxsX3NhbXBsZXNfTWVyZ2VkLCBwYXR0ZXJuID0gIl5NVC0iKQoKIyBDb252ZXJ0ICdwZXJjZW50Lm10JyB0byBudW1lcmljLCByZXBsYWNpbmcgIk5hTiIgd2l0aCAwCkFsbF9zYW1wbGVzX01lcmdlZCRwZXJjZW50Lm10IDwtIHJlcGxhY2UoYXMubnVtZXJpYyhBbGxfc2FtcGxlc19NZXJnZWQkcGVyY2VudC5tdCksIGlzLm5hKEFsbF9zYW1wbGVzX01lcmdlZCRwZXJjZW50Lm10KSwgMCkKCgoKCgpWbG5QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgZmVhdHVyZXMgPSBjKCJuRmVhdHVyZV9STkEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibkNvdW50X1JOQSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjZW50Lm10IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGVyY2VudC5yYiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSA0LCBwdC5zaXplID0gMC4xKSAmIAogICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCkpCgpGZWF0dXJlU2NhdHRlcihBbGxfc2FtcGxlc19NZXJnZWQsIGZlYXR1cmUxID0gInBlcmNlbnQubXQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmUyID0gInBlcmNlbnQucmIiKQoKVmxuUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjZW50Lm10IiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzKQoKRmVhdHVyZVNjYXR0ZXIoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICAgICAgICAgZmVhdHVyZTEgPSAicGVyY2VudC5tdCIsIAogICAgICAgICAgICAgICBmZWF0dXJlMiA9ICJwZXJjZW50LnJiIikgKwogICAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpCgpGZWF0dXJlU2NhdHRlcihBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICBmZWF0dXJlMSA9ICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgIGZlYXR1cmUyID0gIm5GZWF0dXJlX1JOQSIpICsKICAgICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKQoKYGBgCgojI0ZlYXR1cmVTY2F0dGVyIGlzIHR5cGljYWxseSB1c2VkIHRvIHZpc3VhbGl6ZSBmZWF0dXJlLWZlYXR1cmUgcmVsYXRpb25zaGlwcwojI2ZvciBhbnl0aGluZyBjYWxjdWxhdGVkIGJ5IHRoZSBvYmplY3QsIAojI2kuZS4gY29sdW1ucyBpbiBvYmplY3QgbWV0YWRhdGEsIFBDIHNjb3JlcyBldGMuCgpgYGB7ciBGQywgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgpGZWF0dXJlU2NhdHRlcihBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICBmZWF0dXJlMSA9ICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgIGZlYXR1cmUyID0gInBlcmNlbnQubXQiKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKQoKRmVhdHVyZVNjYXR0ZXIoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICAgICAgICAgZmVhdHVyZTEgPSAibkNvdW50X1JOQSIsIAogICAgICAgICAgICAgICBmZWF0dXJlMiA9ICJuRmVhdHVyZV9STkEiKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKQoKYGBgCgoKIyMgIEFzc2lnbiBDZWxsLUN5Y2xlIFNjb3JlcwpgYGB7ciBSZWdyZXNzLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0Kb3B0aW9ucyhmdXR1cmUuZ2xvYmFscy5tYXhTaXplID0gODAwMCAqIDEwMjReMikgICMgU2V0IHRvIDgwMDAgTWlCIChhYm91dCA4IEdCKQoKCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBTQ1RyYW5zZm9ybShBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvLnNjYWxlID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvLmNlbnRlciA9IEZBTFNFKSAgIyBSZWR1Y2UgdG8gMTAwMCB2YXJpYWJsZSBmZWF0dXJlcwoKCiMgQSBsaXN0IG9mIGNlbGwgY3ljbGUgbWFya2VycywgZnJvbSBUaXJvc2ggZXQgYWwsIDIwMTUsIGlzIGxvYWRlZCB3aXRoIFNldXJhdC4gIFdlIGNhbgojIHNlZ3JlZ2F0ZSB0aGlzIGxpc3QgaW50byBtYXJrZXJzIG9mIEcyL00gcGhhc2UgYW5kIG1hcmtlcnMgb2YgUyBwaGFzZQpzLmdlbmVzIDwtIGNjLmdlbmVzJHMuZ2VuZXMKZzJtLmdlbmVzIDwtIGNjLmdlbmVzJGcybS5nZW5lcwoKCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBDZWxsQ3ljbGVTY29yaW5nKEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMuZmVhdHVyZXMgPSBzLmdlbmVzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZzJtLmZlYXR1cmVzID0gZzJtLmdlbmVzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0LmlkZW50ID0gVFJVRSkKCkRlZmF1bHRBc3NheShBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJSTkEiCkFsbF9zYW1wbGVzX01lcmdlZCRDQy5EaWZmZXJlbmNlIDwtIEFsbF9zYW1wbGVzX01lcmdlZCRTLlNjb3JlIC0gQWxsX3NhbXBsZXNfTWVyZ2VkJEcyTS5TY29yZQoKYGBgCgoKIyA0LiBOb3JtYWxpemUgZGF0YQpgYGB7ciBOb3JtYWxpemUsIGluY2x1ZGU9VFJVRX0KCgojIEFwcGx5IFNDVHJhbnNmb3JtCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBTQ1RyYW5zZm9ybShBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFycy50by5yZWdyZXNzID0gYygicGVyY2VudC5yYiIsInBlcmNlbnQubXQiLCAiQ0MuRGlmZmVyZW5jZSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvLnNjYWxlPVRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG8uY2VudGVyPVRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IFRSVUUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCmBgYAoKCiMgNS4gUGVyZm9ybSBQQ0EKYGBge3IgUENBLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KClZhcmlhYmxlc19nZW5lcyA8LSBBbGxfc2FtcGxlc19NZXJnZWRAYXNzYXlzJFNDVEB2YXIuZmVhdHVyZXMKCiMgRXhjbHVkZSBnZW5lcyBzdGFydGluZyB3aXRoICJITEEtIiBBTkQgIlhpc3QiIEFORCAiVFJCViwgVFJBViIKVmFyaWFibGVzX2dlbmVzX2FmdGVyX2V4Y2x1c2lvbiA8LSBWYXJpYWJsZXNfZ2VuZXNbIWdyZXBsKCJeSExBLXxeWElTVHxeVFJCVnxeVFJBViIsIFZhcmlhYmxlc19nZW5lcyldCgojIFNldCB0aGUgc2VlZCBmb3IgY2x1c3RlcmluZyBzdGVwcwpzZXQuc2VlZCgxMjMpCgojIFRoZXNlIGFyZSBub3cgc3RhbmRhcmQgc3RlcHMgaW4gdGhlIFNldXJhdCB3b3JrZmxvdyBmb3IgdmlzdWFsaXphdGlvbiBhbmQgY2x1c3RlcmluZwpBbGxfc2FtcGxlc19NZXJnZWQgPC0gUnVuUENBKEFsbF9zYW1wbGVzX01lcmdlZCwKICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBWYXJpYWJsZXNfZ2VuZXNfYWZ0ZXJfZXhjbHVzaW9uLAogICAgICAgICAgICAgICAgICAgICAgICBkby5wcmludCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICBwY3MucHJpbnQgPSAxOjUsIAogICAgICAgICAgICAgICAgICAgICAgICBnZW5lcy5wcmludCA9IDE1LAogICAgICAgICAgICAgICAgICAgICAgICBucGNzID0gNTApCgojIGRldGVybWluZSBkaW1lbnNpb25hbGl0eSBvZiB0aGUgZGF0YQpFbGJvd1Bsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBuZGltcyA9IDUwKQoKCmBgYAoKIyA2LiBQZXJmb3JtIFBDQSBURVNUCmBgYHtyIFBDQS1URVNULCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKSAgCgojIEFzc3VtaW5nIHlvdSBoYXZlIDEwIGRpZmZlcmVudCBjZWxsIGxpbmVzLCBnZW5lcmF0aW5nIGEgY29sb3IgcGFsZXR0ZSB3aXRoIDEwIGNvbG9ycwpjZWxsX2xpbmVfY29sb3JzIDwtIGJyZXdlci5wYWwoMTAsICJTZXQzIikKCiMgQXNzdW1pbmcgQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZSBpcyBhIGZhY3RvciBvciBjaGFyYWN0ZXIgdmVjdG9yIGNvbnRhaW5pbmcgY2VsbCBsaW5lIG5hbWVzCmRhdGEgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSkKY29sbmFtZXMoZGF0YSkgPC0gYygiY2VsbF9saW5lIiwgIm5VTUkiKSAgIyBDaGFuZ2UgY29sdW1uIG5hbWUgdG8gblVNSQoKbmNlbGxzIDwtIGdncGxvdChkYXRhLCBhZXMoeCA9IGNlbGxfbGluZSwgeSA9IG5VTUksIGZpbGwgPSBjZWxsX2xpbmUpKSArIAogIGdlb21fY29sKCkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG5VTUkpLCAKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIAogICAgICAgICAgICB2anVzdCA9IC0wLjI1KSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2VsbF9saW5lX2NvbG9ycykgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArICAjIEFkanVzdCB0aGUgdGl0bGUgcG9zaXRpb24KICBnZ3RpdGxlKCJGaWx0ZXJlZCBjZWxscyBwZXIgc2FtcGxlIikgKwogIHhsYWIoIkNlbGwgbGluZXMiKSArICAjIEFkanVzdCB4LWF4aXMgbGFiZWwKICB5bGFiKCJGcmVxdWVuY3kiKSAgICAjIEFkanVzdCB5LWF4aXMgbGFiZWwKCnByaW50KG5jZWxscykKCgoKIyBURVNULTEKIyBnaXZlbiB0aGF0IHRoZSBvdXRwdXQgb2YgUnVuUENBIGlzICJwY2EiCiMgcmVwbGFjZSAic28iIGJ5IHRoZSBuYW1lIG9mIHlvdXIgc2V1cmF0IG9iamVjdAoKcGN0IDwtIEFsbF9zYW1wbGVzX01lcmdlZFtbInBjYSJdXUBzdGRldiAvIHN1bShBbGxfc2FtcGxlc19NZXJnZWRbWyJwY2EiXV1Ac3RkZXYpICogMTAwCmN1bXUgPC0gY3Vtc3VtKHBjdCkgIyBDYWxjdWxhdGUgY3VtdWxhdGl2ZSBwZXJjZW50cyBmb3IgZWFjaCBQQwojIERldGVybWluZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHZhcmlhdGlvbiBvZiBQQyBhbmQgc3Vic2VxdWVudCBQQwpjbzIgPC0gc29ydCh3aGljaCgocGN0Wy1sZW5ndGgocGN0KV0gLSBwY3RbLTFdKSA+IDAuMSksIGRlY3JlYXNpbmcgPSBUKVsxXSArIDEKIyBsYXN0IHBvaW50IHdoZXJlIGNoYW5nZSBvZiAlIG9mIHZhcmlhdGlvbiBpcyBtb3JlIHRoYW4gMC4xJS4gLT4gY28yCmNvMgoKIyBURVNULTIKIyBnZXQgc2lnbmlmaWNhbnQgUENzCnN0ZHYgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkW1sicGNhIl1dQHN0ZGV2CnN1bS5zdGR2IDwtIHN1bShBbGxfc2FtcGxlc19NZXJnZWRbWyJwY2EiXV1Ac3RkZXYpCnBlcmNlbnQuc3RkdiA8LSAoc3RkdiAvIHN1bS5zdGR2KSAqIDEwMApjdW11bGF0aXZlIDwtIGN1bXN1bShwZXJjZW50LnN0ZHYpCmNvMSA8LSB3aGljaChjdW11bGF0aXZlID4gOTAgJiBwZXJjZW50LnN0ZHYgPCA1KVsxXQpjbzIgPC0gc29ydCh3aGljaCgocGVyY2VudC5zdGR2WzE6bGVuZ3RoKHBlcmNlbnQuc3RkdikgLSAxXSAtIAogICAgICAgICAgICAgICAgICAgICAgIHBlcmNlbnQuc3RkdlsyOmxlbmd0aChwZXJjZW50LnN0ZHYpXSkgPiAwLjEpLCAKICAgICAgICAgICAgICBkZWNyZWFzaW5nID0gVClbMV0gKyAxCm1pbi5wYyA8LSBtaW4oY28xLCBjbzIpCm1pbi5wYwoKIyBDcmVhdGUgYSBkYXRhZnJhbWUgd2l0aCB2YWx1ZXMKcGxvdF9kZiA8LSBkYXRhLmZyYW1lKHBjdCA9IHBlcmNlbnQuc3RkdiwgCiAgICAgICAgICAgY3VtdSA9IGN1bXVsYXRpdmUsIAogICAgICAgICAgIHJhbmsgPSAxOmxlbmd0aChwZXJjZW50LnN0ZHYpKQoKIyBFbGJvdyBwbG90IHRvIHZpc3VhbGl6ZSAKICBnZ3Bsb3QocGxvdF9kZiwgYWVzKGN1bXVsYXRpdmUsIHBlcmNlbnQuc3RkdiwgbGFiZWwgPSByYW5rLCBjb2xvciA9IHJhbmsgPiBtaW4ucGMpKSArIAogIGdlb21fdGV4dCgpICsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gOTAsIGNvbG9yID0gImdyZXkiKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IG1pbihwZXJjZW50LnN0ZHZbcGVyY2VudC5zdGR2ID4gNV0pLCBjb2xvciA9ICJncmV5IikgKwogIHRoZW1lX2J3KCkKCiAgCgpgYGAKCiMgNy4gQ2x1c3RlcmluZwpgYGB7ciBDMSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgojIFNldCB0aGUgc2VlZCBmb3IgY2x1c3RlcmluZyBzdGVwcwpzZXQuc2VlZCgxMjMpCgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gRmluZE5laWdoYm9ycyhBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSAxOjE2LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlID0gRkFMU0UpCgojIHVuZGVyc3RhbmRpbmcgcmVzb2x1dGlvbgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gRmluZENsdXN0ZXJzKEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdXRpb24gPSBjKDAuMSwgMC4yLCAwLjMsIDAuNCwgMC41LCAwLjYsIDAuNywwLjgsIDAuOSwgMSwxLjIsMS41LDIpKQoKCmBgYAoKIyMgVU1BUCBWaXN1YWxpemF0aW9uCmBgYHtyIEMyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KIyBTZXQgdGhlIHNlZWQgZm9yIGNsdXN0ZXJpbmcgc3RlcHMKc2V0LnNlZWQoMTIzKQoKIyBub24tbGluZWFyIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiAtLS0tLS0tLS0tLS0tLQpBbGxfc2FtcGxlc19NZXJnZWQgPC0gUnVuVU1BUChBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSAxOjE2LAogICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBGQUxTRSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKIyBub3RlIHRoYXQgeW91IGNhbiBzZXQgYGxhYmVsID0gVFJVRWAgb3IgdXNlIHRoZSBMYWJlbCBDbHVzdGVycyBmdW5jdGlvbiB0byBoZWxwIGxhYmVsCiMgaW5kaXZpZHVhbCBjbHVzdGVycwpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCxncm91cC5ieSA9ICJjZWxsX2xpbmUiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMiIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwKICAgICAgICBncm91cC5ieSA9ICJTQ1Rfc25uX3Jlcy4wLjEiLAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsIAogICAgICAgIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsCiAgICAgICAgZ3JvdXAuYnkgPSAiU0NUX3Nubl9yZXMuMC4yIiwKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULCAKICAgICAgICBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLAogICAgICAgIGdyb3VwLmJ5ID0gIlNDVF9zbm5fcmVzLjAuMyIsCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwgCiAgICAgICAgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLAogICAgICAgIGdyb3VwLmJ5ID0gIlNDVF9zbm5fcmVzLjAuNCIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLAogICAgICAgIGdyb3VwLmJ5ID0gIlNDVF9zbm5fcmVzLjAuNSIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsCiAgICAgICAgZ3JvdXAuYnkgPSAiU0NUX3Nubl9yZXMuMC42IiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwKICAgICAgICBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwKICAgICAgICBncm91cC5ieSA9ICJTQ1Rfc25uX3Jlcy4wLjciLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLAogICAgICAgIGdyb3VwLmJ5ID0gIlNDVF9zbm5fcmVzLjAuOCIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwKICAgICAgICBncm91cC5ieSA9ICJTQ1Rfc25uX3Jlcy4wLjkiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsCiAgICAgICAgZ3JvdXAuYnkgPSAiU0NUX3Nubl9yZXMuMSIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwKICAgICAgICBncm91cC5ieSA9ICJTQ1Rfc25uX3Jlcy4xLjIiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsCiAgICAgICAgZ3JvdXAuYnkgPSAiU0NUX3Nubl9yZXMuMS41IiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwKICAgICAgICBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwKICAgICAgICBncm91cC5ieSA9ICJTQ1Rfc25uX3Jlcy4yIiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwKICAgICAgICBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCgojIFNldCBpZGVudGl0eSBjbGFzc2VzIHRvIGFuIGV4aXN0aW5nIGNvbHVtbiBpbiBtZXRhIGRhdGEKSWRlbnRzKG9iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlNDVF9zbm5fcmVzLjAuOSIKCmNsdXN0ZXJfdGFibGUgPC0gdGFibGUoSWRlbnRzKEFsbF9zYW1wbGVzX01lcmdlZCkpCgoKYmFycGxvdChjbHVzdGVyX3RhYmxlLCBtYWluID0gIk51bWJlciBvZiBDZWxscyBpbiBFYWNoIENsdXN0ZXIiLCAKICAgICAgICAgICAgICAgICAgICAgIHhsYWIgPSAiQ2x1c3RlciIsIAogICAgICAgICAgICAgICAgICAgICAgeWxhYiA9ICJOdW1iZXIgb2YgQ2VsbHMiLCAKICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IHJhaW5ib3cobGVuZ3RoKGNsdXN0ZXJfdGFibGUpKSkKCnByaW50KGNsdXN0ZXJfdGFibGUpCgp0YWJsZShBbGxfc2FtcGxlc19NZXJnZWQkcHJlZGljdGVkLmNlbGx0eXBlLmwyLCBBbGxfc2FtcGxlc19NZXJnZWQkU0NUX3Nubl9yZXMuMC4xKQpgYGAKCiMgOC4gY2x1c1RyZWUKYGBge3IgY2x1c1RyZWUsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xMH0KY2x1c3RyZWUoQWxsX3NhbXBsZXNfTWVyZ2VkLCBwcmVmaXggPSAiU0NUX3Nubl9yZXMuIikKYGBgCgojIDkuIEF6aW11dGggQW5ub3RhdGlvbgpgYGB7ciBhemltdXRoX0Fubm90YXRpb24yLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KIyBJbnN0YWxsRGF0YSgicGJtY3JlZiIpCiMgCiMgIyBUaGUgUnVuQXppbXV0aCBmdW5jdGlvbiBjYW4gdGFrZSBhIFNldXJhdCBvYmplY3QgYXMgaW5wdXQKIyBBbGxfc2FtcGxlc19NZXJnZWQgPC0gUnVuQXppbXV0aChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZmVyZW5jZSA9ICJwYm1jcmVmIikKCmBgYAoKIyAxMC4gQXppbXV0aCBWaXN1YWxpemF0aW9uCmBgYHtyIGF6aW11dGhfVmlzdWFsaXphdGlvbiwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDEiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDEiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gRikKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gRikKCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgZ3JvdXAuYnkgPSAicHJlZGljdGVkLmNlbGx0eXBlLmwyIiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwKICAgICAgICBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCgoKCnRhYmxlKEFsbF9zYW1wbGVzX01lcmdlZCRwcmVkaWN0ZWQuY2VsbHR5cGUubDIsIEFsbF9zYW1wbGVzX01lcmdlZCRTQ1Rfc25uX3Jlcy4wLjIpCmBgYAoKIyMgU2F2ZSB0aGUgU2V1cmF0IG9iamVjdCBhcyBhbiBSb2JqIGZpbGUKYGBge3Igc2F2ZVJPQkoxLCBlY2hvPVRSVUV9CgpzYXZlKEFsbF9zYW1wbGVzX01lcmdlZCwgZmlsZSA9ICIwLWltcF9Sb2JqL0FsbF9TYW1wbGVzX01lcmdlZF93aXRoXzEweF9Beml0bXV0aF9Bbm5vdGF0ZWRfU0NUX0hQQ193aXRob3V0X2hhcm1vbnlfaW50ZWdyYXRpb25fcmVtb3ZlZF9ub25DRDRjZWxsc19mcm9tX2NvbnRyb2xfYW5kX0JjZWxsc19mcm9tX0w0X0lMQ19OS19DRDE0TW9ub19ub19uQ291bnRfbkZlYXR1cmVSZWdyZXNzX3JlYWR5X2Zvcl9IYXJtb255X2ZpbmFsLnJvYmoiKQoKCmBgYAoKCiMgMTEuIEhhcm1vbnkgSW50ZWdyYXRpb24KYGBge3IgaGFybW9ueSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgoKIyBMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdncGxvdDIpCgojIFJ1biBIYXJtb255LCBhZGp1c3RpbmcgZm9yIGJhdGNoIGVmZmVjdCB1c2luZyAiY2VsbF9saW5lIiBvciBhbm90aGVyIGdyb3VwaW5nIHZhcmlhYmxlCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBSdW5IYXJtb255KAogIEFsbF9zYW1wbGVzX01lcmdlZCwKICBncm91cC5ieS52YXJzID0gImNlbGxfbGluZSIsICAjIFJlcGxhY2Ugd2l0aCB0aGUgbWV0YWRhdGEgY29sdW1uIHNwZWNpZnlpbmcgYmF0Y2ggb3IgY2VsbCBsaW5lCiAgYXNzYXkudXNlPSJTQ1QiKQoKIyBDaGVjayByZXN1bHRzIGluIGhhcm1vbnkgZW1iZWRkaW5ncwpoYXJtb255X2VtYmVkZGluZ3MgPC0gRW1iZWRkaW5ncyhBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJoYXJtb255IikKaGVhZChoYXJtb255X2VtYmVkZGluZ3MpCgojIFNldCB0aGUgc2VlZCBmb3IgY2x1c3RlcmluZyBzdGVwcwpzZXQuc2VlZCgxMjMpCgojIFJ1biBVTUFQIG9uIEhhcm1vbnkgZW1iZWRkaW5ncwpBbGxfc2FtcGxlc19NZXJnZWQgPC0gUnVuVU1BUChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJoYXJtb255IiwgZGltcyA9IDE6MTYpCgojIFNldCB0aGUgc2VlZCBmb3IgY2x1c3RlcmluZyBzdGVwcwpzZXQuc2VlZCgxMjMpCgojIE9wdGlvbmFsbHksIGZpbmQgbmVpZ2hib3JzIGFuZCBjbHVzdGVycyAoaWYgeW91IHBsYW4gdG8gZG8gY2x1c3RlcmluZyBhbmFseXNpcykKQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIEZpbmROZWlnaGJvcnMoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAiaGFybW9ueSIsIGRpbXMgPSAxOjE2KQpBbGxfc2FtcGxlc19NZXJnZWQgPC0gRmluZENsdXN0ZXJzKEFsbF9zYW1wbGVzX01lcmdlZCwgcmVzb2x1dGlvbiA9IDAuNSkgICMgQWRqdXN0IHJlc29sdXRpb24gYXMgbmVlZGVkCgojIFZpc3VhbGl6ZSBVTUFQCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsIGxhYmVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuNSkgKwogICAgZ2d0aXRsZSgiVU1BUCBvZiBIYXJtb255LUludGVncmF0ZWQgRGF0YSIpCgoKIyBWaXN1YWxpemUgVU1BUCB3aXRoIGJhdGNoL2NlbGwgbGluZSBpbmZvcm1hdGlvbgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLCBsYWJlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjUpICsKICAgIGdndGl0bGUoIlVNQVAgLSBDb2xvcmVkIGJ5IENlbGwgTGluZSAoQWZ0ZXIgSGFybW9ueSBJbnRlZ3JhdGlvbikiKQoKCiMgVmlzdWFsaXplIFVNQVAgd2l0aCBjbHVzdGVycwpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBsYWJlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjUpICsKICAgIGdndGl0bGUoIlVNQVAgLSBDbHVzdGVyZWQgRGF0YSAoQWZ0ZXIgSGFybW9ueSBJbnRlZ3JhdGlvbikiKQoKIyBWaXN1YWxpemUgc3BlY2lmaWMgY2VsbCB0eXBlcyBvciBvdGhlciBtZXRhZGF0YQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCBsYWJlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjUpICsKICAgIGdndGl0bGUoIlVNQVAgLSBDZWxsIFR5cGVzIEFmdGVyIEhhcm1vbnkgSW50ZWdyYXRpb24iKQoKCgpgYGAKCgojIDEyLlNhdmUgdGhlIFNldXJhdCBvYmplY3QgYXMgYW4gUm9iaiBmaWxlCmBgYHtyIHNhdmVST0JKMiwgZWNobz1UUlVFfQoKI3NhdmUoQWxsX3NhbXBsZXNfTWVyZ2VkLCBmaWxlID0gIi4uLy4uLy4uLzAtSU1QLU9CSkVDVFMvQWxsX1NhbXBsZXNfTWVyZ2VkX3dpdGhfMTB4X0F6aXRtdXRoX0Fubm90YXRlZF9TQ1RfSFBDX3dpdGhvdXRfaGFybW9ueV9pbnRlZ3JhdGlvbi5yb2JqIikKCgpgYGAKCgoKCgo=